source: mainline/uspace/app/taskbar/wndlist.c@ 3a6d44b7

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

Activate window by pushing window button on taskbar

Note that with multiple seats, one would need to know which seat pushed
the button and set the appropriate focus.

  • Property mode set to 100644
File size: 10.7 KB
RevLine 
[e0e612b]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>
[1b92d4b]36#include <stdbool.h>
[e0e612b]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
[1b92d4b]48static void wndlist_wm_window_added(void *, sysarg_t);
49static void wndlist_wm_window_removed(void *, sysarg_t);
[f1f433d]50static void wndlist_wm_window_changed(void *, sysarg_t);
[1b92d4b]51
[3a6d44b7]52/** Window list WM callbacks */
[1b92d4b]53static wndmgt_cb_t wndlist_wndmgt_cb = {
54 .window_added = wndlist_wm_window_added,
[f1f433d]55 .window_removed = wndlist_wm_window_removed,
56 .window_changed = wndlist_wm_window_changed
[1b92d4b]57};
58
[3a6d44b7]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
[e0e612b]66/** Create task bar window list.
67 *
[1b92d4b]68 * @param window Containing window
[e0e612b]69 * @param fixed Fixed layout to which buttons will be added
[7a05d924]70 * @param wndmgt Window management service
[e0e612b]71 * @param rwndlist Place to store pointer to new window list
72 * @return @c EOK on success or an error code
73 */
[1b92d4b]74errno_t wndlist_create(ui_window_t *window, ui_fixed_t *fixed,
[e0e612b]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
[1b92d4b]86 wndlist->window = window;
[e0e612b]87 wndlist->fixed = fixed;
88 list_initialize(&wndlist->entries);
89 *rwndlist = wndlist;
90 return EOK;
91error:
92 return rc;
[7a05d924]93}
94
95/** Attach window management service to window list.
96 *
97 * @param wndlist Window list
[1b92d4b]98 * @param wndmgt_svc Window management service name
[7a05d924]99 * @return @c EOK on success or an error code
100 */
[1b92d4b]101errno_t wndlist_open_wm(wndlist_t *wndlist, const char *wndmgt_svc)
[7a05d924]102{
103 errno_t rc;
104 wndmgt_window_list_t *wlist = NULL;
105 wndmgt_window_info_t *winfo = NULL;
106 sysarg_t i;
107
[1b92d4b]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);
[7a05d924]114 if (rc != EOK)
115 goto error;
116
117 for (i = 0; i < wlist->nwindows; i++) {
[1b92d4b]118 rc = wndmgt_get_window_info(wndlist->wndmgt, wlist->windows[i],
[7a05d924]119 &winfo);
120 if (rc != EOK)
121 goto error;
122
[1b92d4b]123 rc = wndlist_append(wndlist, wlist->windows[i], winfo->caption,
124 false);
[7a05d924]125 if (rc != EOK) {
126 wndmgt_free_window_info(winfo);
127 goto error;
128 }
129
130 wndmgt_free_window_info(winfo);
131 }
[e0e612b]132
[7a05d924]133 return EOK;
134error:
135 if (wlist != NULL)
136 wndmgt_free_window_list(wlist);
[1b92d4b]137 if (wndlist->wndmgt != NULL) {
138 wndmgt_close(wndlist->wndmgt);
139 wndlist->wndmgt = NULL;
140 }
[7a05d924]141 return rc;
[e0e612b]142}
143
144/** Destroy task bar window list. */
145void wndlist_destroy(wndlist_t *wndlist)
146{
[1b92d4b]147 wndlist_entry_t *entry;
148
149 /* Close window management service */
150 if (wndlist->wndmgt)
151 wndmgt_close(wndlist->wndmgt);
152
153 /* Destroy entries */
154 entry = wndlist_first(wndlist);
155 while (entry != NULL) {
156 (void)wndlist_remove(wndlist, entry, false);
157 entry = wndlist_first(wndlist);
158 }
159
[e0e612b]160 free(wndlist);
161}
162
163/** Append new entry to window list.
164 *
165 * @param wndlist Window list
[1b92d4b]166 * @param wnd_id Window ID
[e0e612b]167 * @param caption Entry caption
[1b92d4b]168 * @param paint @c true to paint immediately
[e0e612b]169 * @return @c EOK on success or an error code
170 */
[1b92d4b]171errno_t wndlist_append(wndlist_t *wndlist, sysarg_t wnd_id,
172 const char *caption, bool paint)
[e0e612b]173{
174 wndlist_entry_t *entry = NULL;
[1b92d4b]175 ui_resource_t *res;
[e0e612b]176 errno_t rc;
177
178 entry = calloc(1, sizeof(wndlist_entry_t));
179 if (entry == NULL) {
180 rc = ENOMEM;
181 goto error;
182 }
183
[1b92d4b]184 entry->wnd_id = wnd_id;
185 res = ui_window_get_res(wndlist->window);
186
187 rc = ui_pbutton_create(res, caption, &entry->button);
[e0e612b]188 if (rc != EOK)
189 goto error;
190
[1b92d4b]191 entry->wndlist = wndlist;
192 list_append(&entry->lentries, &wndlist->entries);
[e0e612b]193
[1b92d4b]194 /* Set the button rectangle */
195 wndlist_set_entry_rect(wndlist, entry);
[e0e612b]196
[3a6d44b7]197 /* Set button callbacks */
198 ui_pbutton_set_cb(entry->button, &wndlist_button_cb, (void *)entry);
199
[e0e612b]200 rc = ui_fixed_add(wndlist->fixed, ui_pbutton_ctl(entry->button));
201 if (rc != EOK)
202 goto error;
203
[1b92d4b]204 if (paint) {
205 rc = ui_pbutton_paint(entry->button);
206 if (rc != EOK)
207 goto error;
208 }
[e0e612b]209
210 return EOK;
211error:
212 if (entry != NULL && entry->button != NULL)
213 ui_pbutton_destroy(entry->button);
214 if (entry != NULL)
215 free(entry);
216 return rc;
217
218}
219
[1b92d4b]220/** Remove entry from window list.
221 *
222 * @param wndlist Window list
223 * @param entry Window list entry
224 * @param paint @c true to repaint window list
225 * @return @c EOK on success or an error code
226 */
227errno_t wndlist_remove(wndlist_t *wndlist, wndlist_entry_t *entry,
228 bool paint)
229{
230 wndlist_entry_t *next;
231 assert(entry->wndlist == wndlist);
232
233 next = wndlist_next(entry);
234
235 ui_fixed_remove(wndlist->fixed, ui_pbutton_ctl(entry->button));
236 ui_pbutton_destroy(entry->button);
237 list_remove(&entry->lentries);
238 free(entry);
239
240 /* Update positions of the remaining entries */
241 while (next != NULL) {
242 wndlist_set_entry_rect(wndlist, next);
243 next = wndlist_next(next);
244 }
245
246 if (!paint)
247 return EOK;
248
249 return wndlist_repaint(wndlist);
250}
251
[f1f433d]252/** Update window list entry.
253 *
254 * @param wndlist Window list
255 * @param entry Window list entry
256 * @return @c EOK on success or an error code
257 */
258errno_t wndlist_update(wndlist_t *wndlist, wndlist_entry_t *entry,
259 const char *caption)
260{
261 errno_t rc;
262 assert(entry->wndlist == wndlist);
263
264 rc = ui_pbutton_set_caption(entry->button, caption);
265 if (rc != EOK)
266 return rc;
267
268 rc = ui_pbutton_paint(entry->button);
269 if (rc != EOK)
270 return rc;
271
272 return wndlist_repaint(wndlist);
273}
274
[1b92d4b]275/** Compute and set window list entry rectangle.
276 *
277 * Compute rectangle for window list entry and set it.
278 *
279 * @param wndlist Window list
280 * @param entry Window list entry
281 */
282void wndlist_set_entry_rect(wndlist_t *wndlist, wndlist_entry_t *entry)
283{
284 wndlist_entry_t *e;
285 gfx_rect_t rect;
286 ui_resource_t *res;
287 size_t idx;
288
289 /* Determine entry index */
290 idx = 0;
291 e = wndlist_first(wndlist);
292 while (e != entry) {
293 assert(e != NULL);
294 e = wndlist_next(e);
295 ++idx;
296 }
297
298 res = ui_window_get_res(wndlist->window);
299
300 if (ui_resource_is_textmode(res)) {
301 rect.p0.x = 17 * idx + 9;
302 rect.p0.y = 0;
303 rect.p1.x = 17 * idx + 25;
304 rect.p1.y = 1;
305 } else {
306 rect.p0.x = 145 * idx + 90;
307 rect.p0.y = 3;
308 rect.p1.x = 145 * idx + 230;
309 rect.p1.y = 29;
310 }
311
312 ui_pbutton_set_rect(entry->button, &rect);
313}
314
315/** Handle WM window added event.
316 *
317 * @param arg Argument (wndlist_t *)
318 * @param wnd_id Window ID
319 */
320static void wndlist_wm_window_added(void *arg, sysarg_t wnd_id)
321{
322 wndlist_t *wndlist = (wndlist_t *)arg;
323 wndmgt_window_info_t *winfo = NULL;
324 errno_t rc;
325
326 rc = wndmgt_get_window_info(wndlist->wndmgt, wnd_id, &winfo);
327 if (rc != EOK)
328 goto error;
329
330 rc = wndlist_append(wndlist, wnd_id, winfo->caption, true);
331 if (rc != EOK) {
332 wndmgt_free_window_info(winfo);
333 goto error;
334 }
335
336 wndmgt_free_window_info(winfo);
337 return;
338error:
339 if (winfo != NULL)
340 wndmgt_free_window_info(winfo);
341}
342
343/** Handle WM window removed event.
344 *
345 * @param arg Argument (wndlist_t *)
346 * @param wnd_id Window ID
347 */
348static void wndlist_wm_window_removed(void *arg, sysarg_t wnd_id)
349{
350 wndlist_t *wndlist = (wndlist_t *)arg;
351 wndlist_entry_t *entry;
352
353 entry = wndlist_entry_by_id(wndlist, wnd_id);
354 if (entry == NULL)
355 return;
356
357 (void) wndlist_remove(wndlist, entry, true);
358}
359
[f1f433d]360/** Handle WM window changed event.
361 *
362 * @param arg Argument (wndlist_t *)
363 * @param wnd_id Window ID
364 */
365static void wndlist_wm_window_changed(void *arg, sysarg_t wnd_id)
366{
367 wndlist_t *wndlist = (wndlist_t *)arg;
368 wndmgt_window_info_t *winfo = NULL;
369 wndlist_entry_t *entry;
370 errno_t rc;
371
372 entry = wndlist_entry_by_id(wndlist, wnd_id);
373 if (entry == NULL)
374 return;
375
376 rc = wndmgt_get_window_info(wndlist->wndmgt, wnd_id, &winfo);
377 if (rc != EOK)
378 return;
379
380 (void) wndlist_update(wndlist, entry, winfo->caption);
381 wndmgt_free_window_info(winfo);
382}
383
[1b92d4b]384/** Find window list entry by ID.
385 *
386 * @param wndlist Window list
387 * @param wnd_id Window ID
388 * @return Window list entry on success or @c NULL if not found
389 */
390wndlist_entry_t *wndlist_entry_by_id(wndlist_t *wndlist, sysarg_t wnd_id)
391{
392 wndlist_entry_t *entry;
393
394 entry = wndlist_first(wndlist);
395 while (entry != NULL) {
396 if (entry->wnd_id == wnd_id)
397 return entry;
398
399 entry = wndlist_next(entry);
400 }
401
402 return NULL;
403}
404
405/** Get first window list entry.
406 *
407 * @param wndlist Window list
408 * @return First entry or @c NULL if the list is empty
409 */
410wndlist_entry_t *wndlist_first(wndlist_t *wndlist)
411{
412 link_t *link;
413
414 link = list_first(&wndlist->entries);
415 if (link == NULL)
416 return NULL;
417
418 return list_get_instance(link, wndlist_entry_t, lentries);
419}
420
421/** Get next window list entry.
422 *
423 * @param cur Current entry
424 * @return Next entry or @c NULL if @a cur is the last entry
425 */
426wndlist_entry_t *wndlist_next(wndlist_entry_t *cur)
427{
428 link_t *link;
429
430 link = list_next(&cur->lentries, &cur->wndlist->entries);
431 if (link == NULL)
432 return NULL;
433
434 return list_get_instance(link, wndlist_entry_t, lentries);
435}
436
437/** Repaint window list.
438 *
439 * @param wndlist Window list
440 * @return @c EOK on success or an error code
441 */
442errno_t wndlist_repaint(wndlist_t *wndlist)
443{
444 return ui_window_paint(wndlist->window);
445}
446
[3a6d44b7]447/** Window button was clicked.
448 *
449 * @param pbutton Push button
450 * @param arg Argument (wdnlist_entry_t *)
451 */
452static void wndlist_button_clicked(ui_pbutton_t *pbutton, void *arg)
453{
454 wndlist_entry_t *entry = (wndlist_entry_t *)arg;
455 sysarg_t seat_id;
456
457 seat_id = 0; // TODO Multi-seat
458
459 (void) wndmgt_activate_window(entry->wndlist->wndmgt,
460 seat_id, entry->wnd_id);
461}
462
[e0e612b]463/** @}
464 */
Note: See TracBrowser for help on using the repository browser.