source: mainline/uspace/app/taskbar/wndlist.c@ 1b92d4b

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

Update window buttons based on window added/removed events

  • Property mode set to 100644
File size: 9.0 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);
50
51static wndmgt_cb_t wndlist_wndmgt_cb = {
52 .window_added = wndlist_wm_window_added,
53 .window_removed = wndlist_wm_window_removed
54};
55
56/** Create task bar window list.
57 *
58 * @param window Containing window
59 * @param fixed Fixed layout to which buttons will be added
60 * @param wndmgt Window management service
61 * @param rwndlist Place to store pointer to new window list
62 * @return @c EOK on success or an error code
63 */
64errno_t wndlist_create(ui_window_t *window, ui_fixed_t *fixed,
65 wndlist_t **rwndlist)
66{
67 wndlist_t *wndlist = NULL;
68 errno_t rc;
69
70 wndlist = calloc(1, sizeof(wndlist_t));
71 if (wndlist == NULL) {
72 rc = ENOMEM;
73 goto error;
74 }
75
76 wndlist->window = window;
77 wndlist->fixed = fixed;
78 list_initialize(&wndlist->entries);
79 *rwndlist = wndlist;
80 return EOK;
81error:
82 return rc;
83}
84
85/** Attach window management service to window list.
86 *
87 * @param wndlist Window list
88 * @param wndmgt_svc Window management service name
89 * @return @c EOK on success or an error code
90 */
91errno_t wndlist_open_wm(wndlist_t *wndlist, const char *wndmgt_svc)
92{
93 errno_t rc;
94 wndmgt_window_list_t *wlist = NULL;
95 wndmgt_window_info_t *winfo = NULL;
96 sysarg_t i;
97
98 rc = wndmgt_open(wndmgt_svc, &wndlist_wndmgt_cb, (void *)wndlist,
99 &wndlist->wndmgt);
100 if (rc != EOK)
101 goto error;
102
103 rc = wndmgt_get_window_list(wndlist->wndmgt, &wlist);
104 if (rc != EOK)
105 goto error;
106
107 for (i = 0; i < wlist->nwindows; i++) {
108 rc = wndmgt_get_window_info(wndlist->wndmgt, wlist->windows[i],
109 &winfo);
110 if (rc != EOK)
111 goto error;
112
113 rc = wndlist_append(wndlist, wlist->windows[i], winfo->caption,
114 false);
115 if (rc != EOK) {
116 wndmgt_free_window_info(winfo);
117 goto error;
118 }
119
120 wndmgt_free_window_info(winfo);
121 }
122
123 return EOK;
124error:
125 if (wlist != NULL)
126 wndmgt_free_window_list(wlist);
127 if (wndlist->wndmgt != NULL) {
128 wndmgt_close(wndlist->wndmgt);
129 wndlist->wndmgt = NULL;
130 }
131 return rc;
132}
133
134/** Destroy task bar window list. */
135void wndlist_destroy(wndlist_t *wndlist)
136{
137 wndlist_entry_t *entry;
138
139 /* Close window management service */
140 if (wndlist->wndmgt)
141 wndmgt_close(wndlist->wndmgt);
142
143 /* Destroy entries */
144 entry = wndlist_first(wndlist);
145 while (entry != NULL) {
146 (void)wndlist_remove(wndlist, entry, false);
147 entry = wndlist_first(wndlist);
148 }
149
150 free(wndlist);
151}
152
153/** Append new entry to window list.
154 *
155 * @param wndlist Window list
156 * @param wnd_id Window ID
157 * @param caption Entry caption
158 * @param paint @c true to paint immediately
159 * @return @c EOK on success or an error code
160 */
161errno_t wndlist_append(wndlist_t *wndlist, sysarg_t wnd_id,
162 const char *caption, bool paint)
163{
164 wndlist_entry_t *entry = NULL;
165 ui_resource_t *res;
166 errno_t rc;
167
168 entry = calloc(1, sizeof(wndlist_entry_t));
169 if (entry == NULL) {
170 rc = ENOMEM;
171 goto error;
172 }
173
174 entry->wnd_id = wnd_id;
175 res = ui_window_get_res(wndlist->window);
176
177 rc = ui_pbutton_create(res, caption, &entry->button);
178 if (rc != EOK)
179 goto error;
180
181 entry->wndlist = wndlist;
182 list_append(&entry->lentries, &wndlist->entries);
183
184 /* Set the button rectangle */
185 wndlist_set_entry_rect(wndlist, entry);
186
187 rc = ui_fixed_add(wndlist->fixed, ui_pbutton_ctl(entry->button));
188 if (rc != EOK)
189 goto error;
190
191 if (paint) {
192 rc = ui_pbutton_paint(entry->button);
193 if (rc != EOK)
194 goto error;
195 }
196
197 return EOK;
198error:
199 if (entry != NULL && entry->button != NULL)
200 ui_pbutton_destroy(entry->button);
201 if (entry != NULL)
202 free(entry);
203 return rc;
204
205}
206
207/** Remove entry from window list.
208 *
209 * @param wndlist Window list
210 * @param entry Window list entry
211 * @param paint @c true to repaint window list
212 * @return @c EOK on success or an error code
213 */
214errno_t wndlist_remove(wndlist_t *wndlist, wndlist_entry_t *entry,
215 bool paint)
216{
217 wndlist_entry_t *next;
218 assert(entry->wndlist == wndlist);
219
220 next = wndlist_next(entry);
221
222 ui_fixed_remove(wndlist->fixed, ui_pbutton_ctl(entry->button));
223 ui_pbutton_destroy(entry->button);
224 list_remove(&entry->lentries);
225 free(entry);
226
227 /* Update positions of the remaining entries */
228 while (next != NULL) {
229 wndlist_set_entry_rect(wndlist, next);
230 next = wndlist_next(next);
231 }
232
233 if (!paint)
234 return EOK;
235
236 return wndlist_repaint(wndlist);
237}
238
239/** Compute and set window list entry rectangle.
240 *
241 * Compute rectangle for window list entry and set it.
242 *
243 * @param wndlist Window list
244 * @param entry Window list entry
245 */
246void wndlist_set_entry_rect(wndlist_t *wndlist, wndlist_entry_t *entry)
247{
248 wndlist_entry_t *e;
249 gfx_rect_t rect;
250 ui_resource_t *res;
251 size_t idx;
252
253 /* Determine entry index */
254 idx = 0;
255 e = wndlist_first(wndlist);
256 while (e != entry) {
257 assert(e != NULL);
258 e = wndlist_next(e);
259 ++idx;
260 }
261
262 res = ui_window_get_res(wndlist->window);
263
264 if (ui_resource_is_textmode(res)) {
265 rect.p0.x = 17 * idx + 9;
266 rect.p0.y = 0;
267 rect.p1.x = 17 * idx + 25;
268 rect.p1.y = 1;
269 } else {
270 rect.p0.x = 145 * idx + 90;
271 rect.p0.y = 3;
272 rect.p1.x = 145 * idx + 230;
273 rect.p1.y = 29;
274 }
275
276 ui_pbutton_set_rect(entry->button, &rect);
277}
278
279/** Handle WM window added event.
280 *
281 * @param arg Argument (wndlist_t *)
282 * @param wnd_id Window ID
283 */
284static void wndlist_wm_window_added(void *arg, sysarg_t wnd_id)
285{
286 wndlist_t *wndlist = (wndlist_t *)arg;
287 wndmgt_window_info_t *winfo = NULL;
288 errno_t rc;
289
290 rc = wndmgt_get_window_info(wndlist->wndmgt, wnd_id, &winfo);
291 if (rc != EOK)
292 goto error;
293
294 rc = wndlist_append(wndlist, wnd_id, winfo->caption, true);
295 if (rc != EOK) {
296 wndmgt_free_window_info(winfo);
297 goto error;
298 }
299
300 wndmgt_free_window_info(winfo);
301 return;
302error:
303 if (winfo != NULL)
304 wndmgt_free_window_info(winfo);
305}
306
307/** Handle WM window removed event.
308 *
309 * @param arg Argument (wndlist_t *)
310 * @param wnd_id Window ID
311 */
312static void wndlist_wm_window_removed(void *arg, sysarg_t wnd_id)
313{
314 wndlist_t *wndlist = (wndlist_t *)arg;
315 wndlist_entry_t *entry;
316
317 printf("wm_window_removed: wndlist=%p wnd_id=%zu\n",
318 (void *)wndlist, wnd_id);
319
320 entry = wndlist_entry_by_id(wndlist, wnd_id);
321 if (entry == NULL)
322 return;
323
324 (void) wndlist_remove(wndlist, entry, true);
325}
326
327/** Find window list entry by ID.
328 *
329 * @param wndlist Window list
330 * @param wnd_id Window ID
331 * @return Window list entry on success or @c NULL if not found
332 */
333wndlist_entry_t *wndlist_entry_by_id(wndlist_t *wndlist, sysarg_t wnd_id)
334{
335 wndlist_entry_t *entry;
336
337 entry = wndlist_first(wndlist);
338 while (entry != NULL) {
339 if (entry->wnd_id == wnd_id)
340 return entry;
341
342 entry = wndlist_next(entry);
343 }
344
345 return NULL;
346}
347
348/** Get first window list entry.
349 *
350 * @param wndlist Window list
351 * @return First entry or @c NULL if the list is empty
352 */
353wndlist_entry_t *wndlist_first(wndlist_t *wndlist)
354{
355 link_t *link;
356
357 link = list_first(&wndlist->entries);
358 if (link == NULL)
359 return NULL;
360
361 return list_get_instance(link, wndlist_entry_t, lentries);
362}
363
364/** Get next window list entry.
365 *
366 * @param cur Current entry
367 * @return Next entry or @c NULL if @a cur is the last entry
368 */
369wndlist_entry_t *wndlist_next(wndlist_entry_t *cur)
370{
371 link_t *link;
372
373 link = list_next(&cur->lentries, &cur->wndlist->entries);
374 if (link == NULL)
375 return NULL;
376
377 return list_get_instance(link, wndlist_entry_t, lentries);
378}
379
380/** Repaint window list.
381 *
382 * @param wndlist Window list
383 * @return @c EOK on success or an error code
384 */
385errno_t wndlist_repaint(wndlist_t *wndlist)
386{
387 return ui_window_paint(wndlist->window);
388}
389
390/** @}
391 */
Note: See TracBrowser for help on using the repository browser.