source: mainline/uspace/app/taskbar/wndlist.c@ 68704ab

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 68704ab was 68704ab, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Do not list popup windows in task bar

  • Property mode set to 100644
File size: 10.8 KB
Line 
1/*
2 * Copyright (c) 2022 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup taskbar
30 * @{
31 */
32/** @file Task bar window list
33 */
34
35#include <gfx/coord.h>
36#include <stdbool.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <str.h>
40#include <ui/fixed.h>
41#include <ui/label.h>
42#include <ui/resource.h>
43#include <ui/ui.h>
44#include <ui/window.h>
45#include "clock.h"
46#include "wndlist.h"
47
48static void wndlist_wm_window_added(void *, sysarg_t);
49static void wndlist_wm_window_removed(void *, sysarg_t);
50static void wndlist_wm_window_changed(void *, sysarg_t);
51
52/** Window list WM callbacks */
53static wndmgt_cb_t wndlist_wndmgt_cb = {
54 .window_added = wndlist_wm_window_added,
55 .window_removed = wndlist_wm_window_removed,
56 .window_changed = wndlist_wm_window_changed
57};
58
59static void wndlist_button_clicked(ui_pbutton_t *, void *);
60
61/** Window list button callbacks */
62static ui_pbutton_cb_t wndlist_button_cb = {
63 .clicked = wndlist_button_clicked
64};
65
66/** Create task bar window list.
67 *
68 * @param window Containing window
69 * @param fixed Fixed layout to which buttons will be added
70 * @param wndmgt Window management service
71 * @param rwndlist Place to store pointer to new window list
72 * @return @c EOK on success or an error code
73 */
74errno_t wndlist_create(ui_window_t *window, ui_fixed_t *fixed,
75 wndlist_t **rwndlist)
76{
77 wndlist_t *wndlist = NULL;
78 errno_t rc;
79
80 wndlist = calloc(1, sizeof(wndlist_t));
81 if (wndlist == NULL) {
82 rc = ENOMEM;
83 goto error;
84 }
85
86 wndlist->window = window;
87 wndlist->fixed = fixed;
88 list_initialize(&wndlist->entries);
89 *rwndlist = wndlist;
90 return EOK;
91error:
92 return rc;
93}
94
95/** Attach window management service to window list.
96 *
97 * @param wndlist Window list
98 * @param wndmgt_svc Window management service name
99 * @return @c EOK on success or an error code
100 */
101errno_t wndlist_open_wm(wndlist_t *wndlist, const char *wndmgt_svc)
102{
103 errno_t rc;
104 wndmgt_window_list_t *wlist = NULL;
105 wndmgt_window_info_t *winfo = NULL;
106 sysarg_t i;
107
108 rc = wndmgt_open(wndmgt_svc, &wndlist_wndmgt_cb, (void *)wndlist,
109 &wndlist->wndmgt);
110 if (rc != EOK)
111 goto error;
112
113 rc = wndmgt_get_window_list(wndlist->wndmgt, &wlist);
114 if (rc != EOK)
115 goto error;
116
117 for (i = 0; i < wlist->nwindows; i++) {
118 rc = wndmgt_get_window_info(wndlist->wndmgt, wlist->windows[i],
119 &winfo);
120 if (rc != EOK)
121 goto error;
122
123 if ((winfo->flags & wndf_popup) == 0) {
124 rc = wndlist_append(wndlist, wlist->windows[i],
125 winfo->caption, false);
126 if (rc != EOK) {
127 wndmgt_free_window_info(winfo);
128 goto error;
129 }
130 }
131
132 wndmgt_free_window_info(winfo);
133 }
134
135 return EOK;
136error:
137 if (wlist != NULL)
138 wndmgt_free_window_list(wlist);
139 if (wndlist->wndmgt != NULL) {
140 wndmgt_close(wndlist->wndmgt);
141 wndlist->wndmgt = NULL;
142 }
143 return rc;
144}
145
146/** Destroy task bar window list. */
147void wndlist_destroy(wndlist_t *wndlist)
148{
149 wndlist_entry_t *entry;
150
151 /* Close window management service */
152 if (wndlist->wndmgt)
153 wndmgt_close(wndlist->wndmgt);
154
155 /* Destroy entries */
156 entry = wndlist_first(wndlist);
157 while (entry != NULL) {
158 (void)wndlist_remove(wndlist, entry, false);
159 entry = wndlist_first(wndlist);
160 }
161
162 free(wndlist);
163}
164
165/** Append new entry to window list.
166 *
167 * @param wndlist Window list
168 * @param wnd_id Window ID
169 * @param caption Entry caption
170 * @param paint @c true to paint immediately
171 * @return @c EOK on success or an error code
172 */
173errno_t wndlist_append(wndlist_t *wndlist, sysarg_t wnd_id,
174 const char *caption, bool paint)
175{
176 wndlist_entry_t *entry = NULL;
177 ui_resource_t *res;
178 errno_t rc;
179
180 entry = calloc(1, sizeof(wndlist_entry_t));
181 if (entry == NULL) {
182 rc = ENOMEM;
183 goto error;
184 }
185
186 entry->wnd_id = wnd_id;
187 res = ui_window_get_res(wndlist->window);
188
189 rc = ui_pbutton_create(res, caption, &entry->button);
190 if (rc != EOK)
191 goto error;
192
193 entry->wndlist = wndlist;
194 list_append(&entry->lentries, &wndlist->entries);
195
196 /* Set the button rectangle */
197 wndlist_set_entry_rect(wndlist, entry);
198
199 /* Set button callbacks */
200 ui_pbutton_set_cb(entry->button, &wndlist_button_cb, (void *)entry);
201
202 rc = ui_fixed_add(wndlist->fixed, ui_pbutton_ctl(entry->button));
203 if (rc != EOK)
204 goto error;
205
206 if (paint) {
207 rc = ui_pbutton_paint(entry->button);
208 if (rc != EOK)
209 goto error;
210 }
211
212 return EOK;
213error:
214 if (entry != NULL && entry->button != NULL)
215 ui_pbutton_destroy(entry->button);
216 if (entry != NULL)
217 free(entry);
218 return rc;
219
220}
221
222/** Remove entry from window list.
223 *
224 * @param wndlist Window list
225 * @param entry Window list entry
226 * @param paint @c true to repaint window list
227 * @return @c EOK on success or an error code
228 */
229errno_t wndlist_remove(wndlist_t *wndlist, wndlist_entry_t *entry,
230 bool paint)
231{
232 wndlist_entry_t *next;
233 assert(entry->wndlist == wndlist);
234
235 next = wndlist_next(entry);
236
237 ui_fixed_remove(wndlist->fixed, ui_pbutton_ctl(entry->button));
238 ui_pbutton_destroy(entry->button);
239 list_remove(&entry->lentries);
240 free(entry);
241
242 /* Update positions of the remaining entries */
243 while (next != NULL) {
244 wndlist_set_entry_rect(wndlist, next);
245 next = wndlist_next(next);
246 }
247
248 if (!paint)
249 return EOK;
250
251 return wndlist_repaint(wndlist);
252}
253
254/** Update window list entry.
255 *
256 * @param wndlist Window list
257 * @param entry Window list entry
258 * @return @c EOK on success or an error code
259 */
260errno_t wndlist_update(wndlist_t *wndlist, wndlist_entry_t *entry,
261 const char *caption)
262{
263 errno_t rc;
264 assert(entry->wndlist == wndlist);
265
266 rc = ui_pbutton_set_caption(entry->button, caption);
267 if (rc != EOK)
268 return rc;
269
270 rc = ui_pbutton_paint(entry->button);
271 if (rc != EOK)
272 return rc;
273
274 return wndlist_repaint(wndlist);
275}
276
277/** Compute and set window list entry rectangle.
278 *
279 * Compute rectangle for window list entry and set it.
280 *
281 * @param wndlist Window list
282 * @param entry Window list entry
283 */
284void wndlist_set_entry_rect(wndlist_t *wndlist, wndlist_entry_t *entry)
285{
286 wndlist_entry_t *e;
287 gfx_rect_t rect;
288 ui_resource_t *res;
289 size_t idx;
290
291 /* Determine entry index */
292 idx = 0;
293 e = wndlist_first(wndlist);
294 while (e != entry) {
295 assert(e != NULL);
296 e = wndlist_next(e);
297 ++idx;
298 }
299
300 res = ui_window_get_res(wndlist->window);
301
302 if (ui_resource_is_textmode(res)) {
303 rect.p0.x = 17 * idx + 9;
304 rect.p0.y = 0;
305 rect.p1.x = 17 * idx + 25;
306 rect.p1.y = 1;
307 } else {
308 rect.p0.x = 145 * idx + 90;
309 rect.p0.y = 4;
310 rect.p1.x = 145 * idx + 230;
311 rect.p1.y = 28;
312 }
313
314 ui_pbutton_set_rect(entry->button, &rect);
315}
316
317/** Handle WM window added event.
318 *
319 * @param arg Argument (wndlist_t *)
320 * @param wnd_id Window ID
321 */
322static void wndlist_wm_window_added(void *arg, sysarg_t wnd_id)
323{
324 wndlist_t *wndlist = (wndlist_t *)arg;
325 wndmgt_window_info_t *winfo = NULL;
326 errno_t rc;
327
328 rc = wndmgt_get_window_info(wndlist->wndmgt, wnd_id, &winfo);
329 if (rc != EOK)
330 goto error;
331
332 if ((winfo->flags & wndf_popup) == 0) {
333 rc = wndlist_append(wndlist, wnd_id, winfo->caption, true);
334 if (rc != EOK) {
335 wndmgt_free_window_info(winfo);
336 goto error;
337 }
338 }
339
340 wndmgt_free_window_info(winfo);
341 return;
342error:
343 if (winfo != NULL)
344 wndmgt_free_window_info(winfo);
345}
346
347/** Handle WM window removed event.
348 *
349 * @param arg Argument (wndlist_t *)
350 * @param wnd_id Window ID
351 */
352static void wndlist_wm_window_removed(void *arg, sysarg_t wnd_id)
353{
354 wndlist_t *wndlist = (wndlist_t *)arg;
355 wndlist_entry_t *entry;
356
357 entry = wndlist_entry_by_id(wndlist, wnd_id);
358 if (entry == NULL)
359 return;
360
361 (void) wndlist_remove(wndlist, entry, true);
362}
363
364/** Handle WM window changed event.
365 *
366 * @param arg Argument (wndlist_t *)
367 * @param wnd_id Window ID
368 */
369static void wndlist_wm_window_changed(void *arg, sysarg_t wnd_id)
370{
371 wndlist_t *wndlist = (wndlist_t *)arg;
372 wndmgt_window_info_t *winfo = NULL;
373 wndlist_entry_t *entry;
374 errno_t rc;
375
376 entry = wndlist_entry_by_id(wndlist, wnd_id);
377 if (entry == NULL)
378 return;
379
380 rc = wndmgt_get_window_info(wndlist->wndmgt, wnd_id, &winfo);
381 if (rc != EOK)
382 return;
383
384 (void) wndlist_update(wndlist, entry, winfo->caption);
385 wndmgt_free_window_info(winfo);
386}
387
388/** Find window list entry by ID.
389 *
390 * @param wndlist Window list
391 * @param wnd_id Window ID
392 * @return Window list entry on success or @c NULL if not found
393 */
394wndlist_entry_t *wndlist_entry_by_id(wndlist_t *wndlist, sysarg_t wnd_id)
395{
396 wndlist_entry_t *entry;
397
398 entry = wndlist_first(wndlist);
399 while (entry != NULL) {
400 if (entry->wnd_id == wnd_id)
401 return entry;
402
403 entry = wndlist_next(entry);
404 }
405
406 return NULL;
407}
408
409/** Get first window list entry.
410 *
411 * @param wndlist Window list
412 * @return First entry or @c NULL if the list is empty
413 */
414wndlist_entry_t *wndlist_first(wndlist_t *wndlist)
415{
416 link_t *link;
417
418 link = list_first(&wndlist->entries);
419 if (link == NULL)
420 return NULL;
421
422 return list_get_instance(link, wndlist_entry_t, lentries);
423}
424
425/** Get next window list entry.
426 *
427 * @param cur Current entry
428 * @return Next entry or @c NULL if @a cur is the last entry
429 */
430wndlist_entry_t *wndlist_next(wndlist_entry_t *cur)
431{
432 link_t *link;
433
434 link = list_next(&cur->lentries, &cur->wndlist->entries);
435 if (link == NULL)
436 return NULL;
437
438 return list_get_instance(link, wndlist_entry_t, lentries);
439}
440
441/** Repaint window list.
442 *
443 * @param wndlist Window list
444 * @return @c EOK on success or an error code
445 */
446errno_t wndlist_repaint(wndlist_t *wndlist)
447{
448 return ui_window_paint(wndlist->window);
449}
450
451/** Window button was clicked.
452 *
453 * @param pbutton Push button
454 * @param arg Argument (wndlist_entry_t *)
455 */
456static void wndlist_button_clicked(ui_pbutton_t *pbutton, void *arg)
457{
458 wndlist_entry_t *entry = (wndlist_entry_t *)arg;
459 sysarg_t dev_id;
460
461 /* ID of device that clicked the button */
462 dev_id = entry->wndlist->ev_pos_id;
463
464 (void) wndmgt_activate_window(entry->wndlist->wndmgt,
465 dev_id, entry->wnd_id);
466}
467
468/** @}
469 */
Note: See TracBrowser for help on using the repository browser.