source: mainline/uspace/lib/ui/src/window.c@ 4034954c

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

Do not forget to close system menu. Close first, open second!

When moving out of system menu to menu bar we would forget to
close it. This was only causing noticeable problems in text mode.
Also we first close the current menu, then open the other one,
as juggling multiple popup windows in text mode could cause problems.

  • Property mode set to 100644
File size: 42.3 KB
Line 
1/*
2 * Copyright (c) 2023 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 libui
30 * @{
31 */
32/**
33 * @file Window
34 */
35
36#include <congfx/console.h>
37#include <display.h>
38#include <errno.h>
39#include <gfx/bitmap.h>
40#include <gfx/context.h>
41#include <gfx/cursor.h>
42#include <gfx/render.h>
43#include <io/kbd_event.h>
44#include <io/pos_event.h>
45#include <mem.h>
46#include <memgfx/memgc.h>
47#include <stdlib.h>
48#include <ui/control.h>
49#include <ui/menubar.h>
50#include <ui/menu.h>
51#include <ui/menuentry.h>
52#include <ui/resource.h>
53#include <ui/ui.h>
54#include <ui/wdecor.h>
55#include <ui/window.h>
56#include "../private/control.h"
57#include "../private/dummygc.h"
58#include "../private/resource.h"
59#include "../private/ui.h"
60#include "../private/wdecor.h"
61#include "../private/window.h"
62
63static void dwnd_close_event(void *);
64static void dwnd_focus_event(void *, unsigned);
65static void dwnd_kbd_event(void *, kbd_event_t *);
66static void dwnd_pos_event(void *, pos_event_t *);
67static void dwnd_resize_event(void *, gfx_rect_t *);
68static void dwnd_unfocus_event(void *, unsigned);
69
70static display_wnd_cb_t dwnd_cb = {
71 .close_event = dwnd_close_event,
72 .focus_event = dwnd_focus_event,
73 .kbd_event = dwnd_kbd_event,
74 .pos_event = dwnd_pos_event,
75 .resize_event = dwnd_resize_event,
76 .unfocus_event = dwnd_unfocus_event
77};
78
79static void wd_sysmenu_open(ui_wdecor_t *, void *, sysarg_t);
80static void wd_sysmenu_left(ui_wdecor_t *, void *, sysarg_t);
81static void wd_sysmenu_right(ui_wdecor_t *, void *, sysarg_t);
82static void wd_sysmenu_accel(ui_wdecor_t *, void *, char32_t, sysarg_t);
83static void wd_minimize(ui_wdecor_t *, void *);
84static void wd_maximize(ui_wdecor_t *, void *);
85static void wd_unmaximize(ui_wdecor_t *, void *);
86static void wd_close(ui_wdecor_t *, void *);
87static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *, sysarg_t);
88static void wd_resize(ui_wdecor_t *, void *, ui_wdecor_rsztype_t,
89 gfx_coord2_t *, sysarg_t);
90static void wd_set_cursor(ui_wdecor_t *, void *, ui_stock_cursor_t);
91
92static ui_wdecor_cb_t wdecor_cb = {
93 .sysmenu_open = wd_sysmenu_open,
94 .sysmenu_left = wd_sysmenu_left,
95 .sysmenu_right = wd_sysmenu_right,
96 .sysmenu_accel = wd_sysmenu_accel,
97 .minimize = wd_minimize,
98 .maximize = wd_maximize,
99 .unmaximize = wd_unmaximize,
100 .close = wd_close,
101 .move = wd_move,
102 .resize = wd_resize,
103 .set_cursor = wd_set_cursor
104};
105
106static void wnd_sysmenu_left(ui_menu_t *, void *, sysarg_t);
107static void wnd_sysmenu_right(ui_menu_t *, void *, sysarg_t);
108static void wnd_sysmenu_close_req(ui_menu_t *, void *);
109static void wnd_sysmenu_press_accel(ui_menu_t *, void *, char32_t, sysarg_t);
110
111static ui_menu_cb_t wnd_sysmenu_cb = {
112 .left = wnd_sysmenu_left,
113 .right = wnd_sysmenu_right,
114 .close_req = wnd_sysmenu_close_req,
115 .press_accel = wnd_sysmenu_press_accel
116};
117
118static void wnd_sysmenu_erestore(ui_menu_entry_t *, void *);
119static void wnd_sysmenu_eminimize(ui_menu_entry_t *, void *);
120static void wnd_sysmenu_emaximize(ui_menu_entry_t *, void *);
121static void wnd_sysmenu_eclose(ui_menu_entry_t *, void *);
122
123static void ui_window_invalidate(void *, gfx_rect_t *);
124static void ui_window_update(void *);
125static errno_t ui_window_cursor_get_pos(void *, gfx_coord2_t *);
126static errno_t ui_window_cursor_set_pos(void *, gfx_coord2_t *);
127static errno_t ui_window_cursor_set_visible(void *, bool);
128
129/** Window memory GC callbacks */
130static mem_gc_cb_t ui_window_mem_gc_cb = {
131 .invalidate = ui_window_invalidate,
132 .update = ui_window_update,
133 .cursor_get_pos = ui_window_cursor_get_pos,
134 .cursor_set_pos = ui_window_cursor_set_pos,
135 .cursor_set_visible = ui_window_cursor_set_visible
136};
137
138static void ui_window_app_invalidate(void *, gfx_rect_t *);
139static void ui_window_app_update(void *);
140
141/** Application area memory GC callbacks */
142static mem_gc_cb_t ui_window_app_mem_gc_cb = {
143 .invalidate = ui_window_app_invalidate,
144 .update = ui_window_app_update
145};
146
147static void ui_window_expose_cb(void *);
148
149/** Initialize window parameters structure.
150 *
151 * Window parameters structure must always be initialized using this function
152 * first. By default, the window will be decorated. To get a non-decorated
153 * window, one needs to clear ui_wds_decorated
154 * (e.g. params->style &= ~ui_wds_decorated).
155 *
156 * @param params Window parameters structure
157 */
158void ui_wnd_params_init(ui_wnd_params_t *params)
159{
160 memset(params, 0, sizeof(ui_wnd_params_t));
161
162 /* Make window decorated by default. */
163 params->style = ui_wds_decorated;
164}
165
166/** Compute where window should be placed on the screen.
167 *
168 * This only applies to windows that do not use default placement or
169 * if we are running in full-screen mode.
170 *
171 * @param window Window
172 * @param drect Display rectangle
173 * @param params Window parameters
174 * @param pos Place to store position of top-left corner
175 */
176static void ui_window_place(ui_window_t *window, gfx_rect_t *drect,
177 ui_wnd_params_t *params, gfx_coord2_t *pos)
178{
179 gfx_coord2_t dims;
180
181 assert(params->placement != ui_wnd_place_default ||
182 ui_is_fullscreen(window->ui));
183
184 pos->x = 0;
185 pos->y = 0;
186
187 switch (params->placement) {
188 case ui_wnd_place_default:
189 assert(ui_is_fullscreen(window->ui));
190 /* Center window */
191 gfx_rect_dims(&params->rect, &dims);
192 pos->x = (drect->p0.x + drect->p1.x) / 2 - dims.x / 2;
193 pos->y = (drect->p0.y + drect->p1.y) / 2 - dims.y / 2;
194 break;
195 case ui_wnd_place_top_left:
196 case ui_wnd_place_full_screen:
197 pos->x = drect->p0.x - params->rect.p0.x;
198 pos->y = drect->p0.y - params->rect.p0.y;
199 break;
200 case ui_wnd_place_top_right:
201 pos->x = drect->p1.x - params->rect.p1.x;
202 pos->y = drect->p0.y - params->rect.p0.y;
203 break;
204 case ui_wnd_place_bottom_left:
205 pos->x = drect->p0.x - params->rect.p0.x;
206 pos->y = drect->p1.y - params->rect.p1.y;
207 break;
208 case ui_wnd_place_bottom_right:
209 pos->x = drect->p1.x - params->rect.p1.x;
210 pos->y = drect->p1.y - params->rect.p1.y;
211 break;
212 case ui_wnd_place_popup:
213 /* Place popup window below parent rectangle */
214 pos->x = params->prect.p0.x;
215 pos->y = params->prect.p1.y;
216 break;
217 }
218}
219
220/** Create window's system menu.
221 *
222 * @param window Window
223 * @return EOK on success or an error code
224 */
225static errno_t ui_window_sysmenu_create(ui_window_t *window)
226{
227 errno_t rc;
228 ui_menu_entry_t *mrestore;
229 ui_menu_entry_t *mmin;
230 ui_menu_entry_t *mmax;
231 ui_menu_entry_t *msep;
232 ui_menu_entry_t *mclose;
233
234 rc = ui_menu_create(window, &window->sysmenu);
235 if (rc != EOK)
236 goto error;
237
238 ui_menu_set_cb(window->sysmenu, &wnd_sysmenu_cb, (void *)window);
239
240 rc = ui_menu_entry_create(window->sysmenu, "~R~estore",
241 "", &mrestore);
242 if (rc != EOK)
243 goto error;
244
245 if (!window->wdecor->maximized)
246 ui_menu_entry_set_disabled(mrestore, true);
247
248 ui_menu_entry_set_cb(mrestore, wnd_sysmenu_erestore, (void *)window);
249
250 rc = ui_menu_entry_create(window->sysmenu, "Mi~n~imize",
251 "", &mmin);
252 if (rc != EOK)
253 goto error;
254
255 if ((window->wdecor->style & ui_wds_minimize_btn) == 0)
256 ui_menu_entry_set_disabled(mmin, true);
257
258 ui_menu_entry_set_cb(mmin, wnd_sysmenu_eminimize, (void *)window);
259
260 rc = ui_menu_entry_create(window->sysmenu, "Ma~x~imize",
261 "", &mmax);
262 if (rc != EOK)
263 goto error;
264
265 if ((window->wdecor->style & ui_wds_maximize_btn) == 0 ||
266 window->wdecor->maximized)
267 ui_menu_entry_set_disabled(mmax, true);
268
269 ui_menu_entry_set_cb(mmax, wnd_sysmenu_emaximize, (void *)window);
270
271 rc = ui_menu_entry_sep_create(window->sysmenu, &msep);
272 if (rc != EOK)
273 goto error;
274
275 rc = ui_menu_entry_create(window->sysmenu, "~C~lose", "Alt-F4",
276 &mclose);
277 if (rc != EOK)
278 goto error;
279
280 if ((window->wdecor->style & ui_wds_close_btn) == 0)
281 ui_menu_entry_set_disabled(mclose, true);
282
283 ui_menu_entry_set_cb(mclose, wnd_sysmenu_eclose, (void *)window);
284
285 window->sysmenu_restore = mrestore;
286 window->sysmenu_minimize = mmin;
287 window->sysmenu_maximize = mmax;
288
289 return EOK;
290error:
291 return rc;
292}
293
294/** Create new window.
295 *
296 * @param ui User interface
297 * @param params Window parameters
298 * @param rwindow Place to store pointer to new window
299 * @return EOK on success or an error code
300 */
301errno_t ui_window_create(ui_t *ui, ui_wnd_params_t *params,
302 ui_window_t **rwindow)
303{
304 ui_window_t *window;
305 display_info_t info;
306 gfx_coord2_t scr_dims;
307 display_wnd_params_t dparams;
308 gfx_context_t *gc = NULL;
309 ui_resource_t *res = NULL;
310 ui_wdecor_t *wdecor = NULL;
311 dummy_gc_t *dgc = NULL;
312 gfx_bitmap_params_t bparams;
313 gfx_bitmap_alloc_t alloc;
314 gfx_bitmap_t *bmp = NULL;
315 gfx_coord2_t off;
316 mem_gc_t *memgc = NULL;
317 xlate_gc_t *xgc = NULL;
318 errno_t rc;
319
320 window = calloc(1, sizeof(ui_window_t));
321 if (window == NULL)
322 return ENOMEM;
323
324 window->ui = ui;
325
326 display_wnd_params_init(&dparams);
327 dparams.rect = params->rect;
328 dparams.caption = params->caption;
329 /* Only allow making the window larger */
330 gfx_rect_dims(&params->rect, &dparams.min_size);
331
332 /*
333 * If idev_id is not specified, use the UI default (probably
334 * obtained from display specification. This creates the
335 * main window in the seat specified on the command line.
336 */
337 if (params->idev_id != 0)
338 dparams.idev_id = params->idev_id;
339 else
340 dparams.idev_id = ui->idev_id;
341
342 if ((params->flags & ui_wndf_popup) != 0)
343 dparams.flags |= wndf_popup;
344 if ((params->flags & ui_wndf_topmost) != 0)
345 dparams.flags |= wndf_topmost;
346 if ((params->flags & ui_wndf_system) != 0)
347 dparams.flags |= wndf_system;
348 if ((params->flags & ui_wndf_avoid) != 0)
349 dparams.flags |= wndf_avoid;
350
351 if (ui->display != NULL) {
352 if (params->placement != ui_wnd_place_default) {
353 rc = display_get_info(ui->display, &info);
354 if (rc != EOK)
355 goto error;
356 }
357
358 if (params->placement == ui_wnd_place_full_screen) {
359 /* Make window the size of the screen */
360 gfx_rect_dims(&info.rect, &scr_dims);
361 gfx_coord2_add(&dparams.rect.p0, &scr_dims,
362 &dparams.rect.p1);
363 }
364
365 if (params->placement != ui_wnd_place_default) {
366 /* Set initial display window position */
367 ui_window_place(window, &info.rect, params,
368 &dparams.pos);
369
370 dparams.flags |= wndf_setpos;
371 }
372
373 rc = display_window_create(ui->display, &dparams, &dwnd_cb,
374 (void *) window, &window->dwindow);
375 if (rc != EOK)
376 goto error;
377
378 rc = display_window_get_gc(window->dwindow, &gc);
379 if (rc != EOK)
380 goto error;
381 } else if (ui->console != NULL) {
382 gc = console_gc_get_ctx(ui->cgc);
383
384 if (params->placement == ui_wnd_place_full_screen) {
385 /* Make window the size of the screen */
386 gfx_rect_dims(&ui->rect, &scr_dims);
387 gfx_coord2_add(&dparams.rect.p0, &scr_dims,
388 &dparams.rect.p1);
389 (void) console_set_caption(ui->console,
390 params->caption);
391 }
392 } else {
393 /* Needed for unit tests */
394 rc = dummygc_create(&dgc);
395 if (rc != EOK)
396 goto error;
397
398 gc = dummygc_get_ctx(dgc);
399 }
400
401#ifdef CONFIG_UI_CS_RENDER
402 /* Create window bitmap */
403 gfx_bitmap_params_init(&bparams);
404#ifndef CONFIG_WIN_DOUBLE_BUF
405 /* Console does not support direct output */
406 if (ui->display != NULL)
407 bparams.flags |= bmpf_direct_output;
408#endif
409
410 /* Move rectangle so that top-left corner is 0,0 */
411 gfx_rect_rtranslate(&dparams.rect.p0, &dparams.rect, &bparams.rect);
412
413 rc = gfx_bitmap_create(gc, &bparams, NULL, &bmp);
414 if (rc != EOK)
415 goto error;
416
417 /* Create memory GC */
418 rc = gfx_bitmap_get_alloc(bmp, &alloc);
419 if (rc != EOK) {
420 gfx_bitmap_destroy(window->app_bmp);
421 return rc;
422 }
423
424 rc = mem_gc_create(&bparams.rect, &alloc, &ui_window_mem_gc_cb,
425 (void *) window, &memgc);
426 if (rc != EOK) {
427 gfx_bitmap_destroy(window->app_bmp);
428 return rc;
429 }
430
431 window->bmp = bmp;
432 window->mgc = memgc;
433 window->gc = mem_gc_get_ctx(memgc);
434 window->realgc = gc;
435 (void) off;
436#else
437 /* Server-side rendering */
438
439 /* Full-screen mode? */
440 if (ui->display == NULL) {
441 /* Create translating GC to translate window contents */
442 off.x = 0;
443 off.y = 0;
444 rc = xlate_gc_create(&off, gc, &xgc);
445 if (rc != EOK)
446 goto error;
447
448 window->xgc = xgc;
449 window->gc = xlate_gc_get_ctx(xgc);
450 window->realgc = gc;
451 } else {
452 window->gc = gc;
453 }
454
455 (void) ui_window_mem_gc_cb;
456 (void) alloc;
457 (void) bparams;
458#endif
459 if (ui->display == NULL) {
460 ui_window_place(window, &ui->rect, params, &window->dpos);
461
462 if (window->xgc != NULL)
463 xlate_gc_set_off(window->xgc, &window->dpos);
464 }
465
466 rc = ui_resource_create(window->gc, ui_is_textmode(ui), &res);
467 if (rc != EOK)
468 goto error;
469
470 rc = ui_wdecor_create(res, params->caption, params->style, &wdecor);
471 if (rc != EOK)
472 goto error;
473
474 ui_wdecor_set_rect(wdecor, &dparams.rect);
475 ui_wdecor_set_cb(wdecor, &wdecor_cb, (void *) window);
476 ui_wdecor_paint(wdecor);
477
478 ui_resource_set_expose_cb(res, ui_window_expose_cb, (void *) window);
479
480 window->rect = dparams.rect;
481 window->res = res;
482 window->wdecor = wdecor;
483 window->cursor = ui_curs_arrow;
484 window->placement = params->placement;
485
486 rc = ui_window_sysmenu_create(window);
487 if (rc != EOK)
488 goto error;
489
490 *rwindow = window;
491
492 list_append(&window->lwindows, &ui->windows);
493 return EOK;
494error:
495 if (wdecor != NULL)
496 ui_wdecor_destroy(wdecor);
497 if (res != NULL)
498 ui_resource_destroy(res);
499 if (memgc != NULL)
500 mem_gc_delete(memgc);
501 if (xgc != NULL)
502 xlate_gc_delete(xgc);
503 if (bmp != NULL)
504 gfx_bitmap_destroy(bmp);
505 if (dgc != NULL)
506 dummygc_destroy(dgc);
507 free(window);
508 return rc;
509}
510
511/** Destroy window.
512 *
513 * @param window Window or @c NULL
514 */
515void ui_window_destroy(ui_window_t *window)
516{
517 ui_t *ui;
518
519 if (window == NULL)
520 return;
521
522 ui = window->ui;
523
524 list_remove(&window->lwindows);
525 ui_control_destroy(window->control);
526 ui_menu_destroy(window->sysmenu);
527 ui_wdecor_destroy(window->wdecor);
528 ui_resource_destroy(window->res);
529 if (window->app_mgc != NULL)
530 mem_gc_delete(window->app_mgc);
531 if (window->app_bmp != NULL)
532 gfx_bitmap_destroy(window->app_bmp);
533 if (window->mgc != NULL) {
534 mem_gc_delete(window->mgc);
535 window->gc = NULL;
536 }
537 if (window->bmp != NULL)
538 gfx_bitmap_destroy(window->bmp);
539 if (window->dwindow != NULL)
540 display_window_destroy(window->dwindow);
541
542 /* Need to repaint if windows are emulated */
543 if (ui_is_fullscreen(ui)) {
544 ui_paint(ui);
545 }
546
547 if (ui->console != NULL &&
548 window->placement == ui_wnd_place_full_screen) {
549 (void) console_set_caption(ui->console, "");
550 }
551
552 free(window);
553}
554
555/** Add control to window.
556 *
557 * Only one control can be added to a window. If more than one control
558 * is added, the results are undefined.
559 *
560 * @param window Window
561 * @param control Control
562 */
563void ui_window_add(ui_window_t *window, ui_control_t *control)
564{
565 assert(window->control == NULL);
566
567 window->control = control;
568 control->elemp = (void *) window;
569}
570
571/** Remove control from window.
572 *
573 * @param window Window
574 * @param control Control
575 */
576void ui_window_remove(ui_window_t *window, ui_control_t *control)
577{
578 assert(window->control == control);
579 assert((ui_window_t *) control->elemp == window);
580
581 window->control = NULL;
582 control->elemp = NULL;
583}
584
585/** Get active window (only valid in fullscreen mode).
586 *
587 * @param ui User interface
588 * @return Active window
589 */
590ui_window_t *ui_window_get_active(ui_t *ui)
591{
592 link_t *link;
593
594 link = list_last(&ui->windows);
595 if (link == NULL)
596 return NULL;
597
598 return list_get_instance(link, ui_window_t, lwindows);
599}
600
601/** Resize or (un)maximize window.
602 *
603 * @param window Window
604 * @param rect Rectangle
605 * @param scop Size change operation
606 *
607 * @return EOK on success or an error code
608 */
609errno_t ui_window_size_change(ui_window_t *window, gfx_rect_t *rect,
610 ui_wnd_sc_op_t scop)
611{
612 gfx_coord2_t offs;
613 gfx_rect_t nrect;
614 gfx_rect_t arect;
615 gfx_bitmap_t *app_bmp = NULL;
616 gfx_bitmap_t *win_bmp = NULL;
617 gfx_bitmap_params_t app_params;
618 gfx_bitmap_params_t win_params;
619 gfx_bitmap_alloc_t app_alloc;
620 gfx_bitmap_alloc_t win_alloc;
621 errno_t rc;
622
623 /*
624 * Move rect so that p0=0,0 - keep window's coordinate system origin
625 * locked to top-left corner of the window.
626 */
627 offs = rect->p0;
628 gfx_rect_rtranslate(&offs, rect, &nrect);
629
630 /* mgc != NULL iff client-side rendering */
631 if (window->mgc != NULL) {
632#ifdef CONFIG_WIN_DOUBLE_BUF
633 /*
634 * Create new window bitmap in advance. If direct mapping,
635 * will need do it after resizing the window.
636 */
637 assert(window->bmp != NULL);
638 gfx_bitmap_params_init(&win_params);
639 win_params.rect = nrect;
640
641 rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
642 &win_bmp);
643 if (rc != EOK)
644 goto error;
645
646 rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
647 if (rc != EOK)
648 goto error;
649#endif
650 }
651
652 /* Application area GC? */
653 if (window->app_gc != NULL) {
654 /* Resize application bitmap */
655 assert(window->app_bmp != NULL);
656
657 gfx_bitmap_params_init(&app_params);
658
659 /*
660 * The bitmap will have the same dimensions as the
661 * application rectangle, but start at 0,0.
662 */
663 ui_wdecor_app_from_rect(window->wdecor->style, &nrect, &arect);
664 gfx_rect_rtranslate(&arect.p0, &arect, &app_params.rect);
665
666 rc = gfx_bitmap_create(window->gc, &app_params, NULL,
667 &app_bmp);
668 if (rc != EOK)
669 goto error;
670
671 rc = gfx_bitmap_get_alloc(app_bmp, &app_alloc);
672 if (rc != EOK)
673 goto error;
674 }
675
676 /* dwindow can be NULL in case of unit tests or fullscreen mode */
677 if (window->dwindow != NULL) {
678 switch (scop) {
679 case ui_wsc_resize:
680 rc = display_window_resize(window->dwindow, &offs,
681 &nrect);
682 if (rc != EOK)
683 goto error;
684 break;
685 case ui_wsc_maximize:
686 rc = display_window_maximize(window->dwindow);
687 if (rc != EOK)
688 goto error;
689 break;
690 case ui_wsc_unmaximize:
691 rc = display_window_unmaximize(window->dwindow);
692 if (rc != EOK)
693 goto error;
694 break;
695 }
696 }
697
698 /* Client side rendering? */
699 if (window->mgc != NULL) {
700#ifndef CONFIG_WIN_DOUBLE_BUF
701 /* Window is resized, now we can map the window bitmap again */
702 gfx_bitmap_params_init(&win_params);
703 win_params.flags |= bmpf_direct_output;
704 win_params.rect = nrect;
705
706 rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
707 &win_bmp);
708 if (rc != EOK)
709 goto error;
710
711 rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
712 if (rc != EOK)
713 goto error;
714#endif
715 mem_gc_retarget(window->mgc, &win_params.rect, &win_alloc);
716
717 gfx_bitmap_destroy(window->bmp);
718 window->bmp = win_bmp;
719 }
720
721 window->rect = nrect;
722 ui_wdecor_set_rect(window->wdecor, &nrect);
723 ui_wdecor_paint(window->wdecor);
724 gfx_update(window->gc);
725
726 /* Application area GC? */
727 if (window->app_gc != NULL) {
728 mem_gc_retarget(window->app_mgc, &app_params.rect, &app_alloc);
729
730 gfx_bitmap_destroy(window->app_bmp);
731 window->app_bmp = app_bmp;
732 }
733
734 return EOK;
735error:
736 if (app_bmp != NULL)
737 gfx_bitmap_destroy(app_bmp);
738 if (win_bmp != NULL)
739 gfx_bitmap_destroy(win_bmp);
740 return rc;
741}
742
743/** Resize/move window.
744 *
745 * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
746 * the top-left corner of the window will move on the screen accordingly.
747 *
748 * @param window Window
749 * @param rect Rectangle
750 *
751 * @return EOK on success or an error code
752 */
753errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
754{
755 return ui_window_size_change(window, rect, ui_wsc_resize);
756}
757
758/** Set window callbacks.
759 *
760 * @param window Window
761 * @param cb Window callbacks
762 * @param arg Callback argument
763 */
764void ui_window_set_cb(ui_window_t *window, ui_window_cb_t *cb, void *arg)
765{
766 window->cb = cb;
767 window->arg = arg;
768}
769
770/** Change window caption.
771 *
772 * @param window Window
773 * @param caption New caption
774 *
775 * @return EOK on success or an error code
776 */
777errno_t ui_window_set_caption(ui_window_t *window, const char *caption)
778{
779 errno_t rc;
780
781 /* Set console caption if fullscreen window on console */
782 if (window->ui->console != NULL && window->placement ==
783 ui_wnd_place_full_screen) {
784 rc = console_set_caption(window->ui->console, caption);
785 if (rc != EOK)
786 return rc;
787 }
788
789 /* Set display window caption if running on display service */
790 if (window->dwindow != NULL) {
791 rc = display_window_set_caption(window->dwindow, caption);
792 if (rc != EOK)
793 return rc;
794 }
795
796 return ui_wdecor_set_caption(window->wdecor, caption);
797}
798
799/** Get window's containing UI.
800 *
801 * @param window Window
802 * @return Containing UI
803 */
804ui_t *ui_window_get_ui(ui_window_t *window)
805{
806 return window->ui;
807}
808
809/** Get UI resource from window.
810 *
811 * @param window Window
812 * @return UI resource
813 */
814ui_resource_t *ui_window_get_res(ui_window_t *window)
815{
816 return window->res;
817}
818
819/** Get window GC.
820 *
821 * @param window Window
822 * @return GC (relative to window)
823 */
824gfx_context_t *ui_window_get_gc(ui_window_t *window)
825{
826 return window->gc;
827}
828
829/** Get window position.
830 *
831 * @param window Window
832 * @param pos Place to store position
833 * @return EOK on success or an error code
834 */
835errno_t ui_window_get_pos(ui_window_t *window, gfx_coord2_t *pos)
836{
837 errno_t rc;
838
839 if (window->dwindow != NULL) {
840 rc = display_window_get_pos(window->dwindow, pos);
841 if (rc != EOK)
842 return rc;
843 } else {
844 *pos = window->dpos;
845 }
846
847 return EOK;
848}
849
850/** Get window application area GC
851 *
852 * @param window Window
853 * @param rgc Place to store GC (relative to application area)
854 * @return EOK on success or an error code
855 */
856errno_t ui_window_get_app_gc(ui_window_t *window, gfx_context_t **rgc)
857{
858 gfx_bitmap_params_t params;
859 gfx_bitmap_alloc_t alloc;
860 gfx_rect_t rect;
861 mem_gc_t *memgc;
862 errno_t rc;
863
864 if (window->app_gc == NULL) {
865 assert(window->app_bmp == NULL);
866
867 gfx_bitmap_params_init(&params);
868
869 /*
870 * The bitmap will have the same dimensions as the
871 * application rectangle, but start at 0,0.
872 */
873 ui_window_get_app_rect(window, &rect);
874 gfx_rect_rtranslate(&rect.p0, &rect, &params.rect);
875
876 rc = gfx_bitmap_create(window->gc, &params, NULL,
877 &window->app_bmp);
878 if (rc != EOK)
879 return rc;
880
881 rc = gfx_bitmap_get_alloc(window->app_bmp, &alloc);
882 if (rc != EOK) {
883 gfx_bitmap_destroy(window->app_bmp);
884 return rc;
885 }
886
887 rc = mem_gc_create(&params.rect, &alloc,
888 &ui_window_app_mem_gc_cb, (void *) window, &memgc);
889 if (rc != EOK) {
890 gfx_bitmap_destroy(window->app_bmp);
891 return rc;
892 }
893
894 window->app_mgc = memgc;
895 window->app_gc = mem_gc_get_ctx(memgc);
896 }
897
898 *rgc = window->app_gc;
899 return EOK;
900}
901
902/** Get window application rectangle
903 *
904 * @param window Window
905 * @param rect Place to store application rectangle
906 */
907void ui_window_get_app_rect(ui_window_t *window, gfx_rect_t *rect)
908{
909 ui_wdecor_geom_t geom;
910
911 ui_wdecor_get_geom(window->wdecor, &geom);
912 *rect = geom.app_area_rect;
913}
914
915/** Set cursor when pointer is hovering over a control.
916 *
917 * @param window Window
918 * @param cursor Cursor
919 */
920void ui_window_set_ctl_cursor(ui_window_t *window, ui_stock_cursor_t cursor)
921{
922 display_stock_cursor_t dcursor;
923
924 dcursor = wnd_dcursor_from_cursor(cursor);
925
926 if (window->dwindow != NULL)
927 (void) display_window_set_cursor(window->dwindow, dcursor);
928}
929
930/** Paint window
931 *
932 * @param window Window
933 * @return EOK on success or an error code
934 */
935errno_t ui_window_paint(ui_window_t *window)
936{
937 return ui_window_send_paint(window);
938}
939
940/** Handle window close event. */
941static void dwnd_close_event(void *arg)
942{
943 ui_window_t *window = (ui_window_t *) arg;
944 ui_t *ui = window->ui;
945
946 ui_lock(ui);
947 ui_window_send_close(window);
948 ui_unlock(ui);
949}
950
951/** Handle window focus event. */
952static void dwnd_focus_event(void *arg, unsigned nfocus)
953{
954 ui_window_t *window = (ui_window_t *) arg;
955 ui_t *ui = window->ui;
956
957 ui_lock(ui);
958 (void)nfocus;
959
960 if (window->wdecor != NULL) {
961 ui_wdecor_set_active(window->wdecor, true);
962 ui_wdecor_paint(window->wdecor);
963 }
964
965 ui_window_send_focus(window, nfocus);
966 ui_unlock(ui);
967}
968
969/** Handle window keyboard event */
970static void dwnd_kbd_event(void *arg, kbd_event_t *kbd_event)
971{
972 ui_window_t *window = (ui_window_t *) arg;
973 ui_t *ui = window->ui;
974
975 ui_lock(ui);
976 ui_window_send_kbd(window, kbd_event);
977 ui_unlock(ui);
978}
979
980/** Handle window position event */
981static void dwnd_pos_event(void *arg, pos_event_t *event)
982{
983 ui_window_t *window = (ui_window_t *) arg;
984 ui_t *ui = window->ui;
985 ui_evclaim_t claim;
986
987 /* Make sure we don't process events until fully initialized */
988 if (window->wdecor == NULL)
989 return;
990
991 ui_lock(ui);
992
993 claim = ui_wdecor_pos_event(window->wdecor, event);
994 if (claim == ui_claimed) {
995 ui_unlock(ui);
996 return;
997 }
998
999 ui_window_send_pos(window, event);
1000 ui_unlock(ui);
1001}
1002
1003/** Handle window resize event */
1004static void dwnd_resize_event(void *arg, gfx_rect_t *rect)
1005{
1006 ui_window_t *window = (ui_window_t *) arg;
1007 ui_t *ui = window->ui;
1008
1009 /* Make sure we don't process events until fully initialized */
1010 if (window->wdecor == NULL)
1011 return;
1012
1013 if ((window->wdecor->style & ui_wds_resizable) == 0)
1014 return;
1015
1016 ui_lock(ui);
1017 (void) ui_window_resize(window, rect);
1018 (void) ui_window_paint(window);
1019 ui_unlock(ui);
1020}
1021
1022/** Handle window unfocus event. */
1023static void dwnd_unfocus_event(void *arg, unsigned nfocus)
1024{
1025 ui_window_t *window = (ui_window_t *) arg;
1026 ui_t *ui = window->ui;
1027
1028 ui_lock(ui);
1029
1030 if (window->wdecor != NULL && nfocus == 0) {
1031 ui_wdecor_set_active(window->wdecor, false);
1032 ui_wdecor_paint(window->wdecor);
1033 }
1034
1035 ui_window_send_unfocus(window, nfocus);
1036 ui_unlock(ui);
1037}
1038
1039/** Window decoration requested opening of system menu.
1040 *
1041 * @param wdecor Window decoration
1042 * @param arg Argument (window)
1043 * @param idev_id Input device ID
1044 */
1045static void wd_sysmenu_open(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
1046{
1047 ui_window_t *window = (ui_window_t *) arg;
1048
1049 ui_window_send_sysmenu(window, idev_id);
1050}
1051
1052/** Window decoration requested moving left from system menu handle.
1053 *
1054 * @param wdecor Window decoration
1055 * @param arg Argument (window)
1056 * @param idev_id Input device ID
1057 */
1058static void wd_sysmenu_left(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
1059{
1060 ui_window_t *window = (ui_window_t *) arg;
1061
1062 if (window->mbar != NULL) {
1063 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1064 ui_menu_close(window->sysmenu);
1065 ui_menu_bar_select_last(window->mbar, false, idev_id);
1066 }
1067}
1068
1069/** Window decoration requested moving right from system menu handle.
1070 *
1071 * @param wdecor Window decoration
1072 * @param arg Argument (window)
1073 * @param idev_id Input device ID
1074 */
1075static void wd_sysmenu_right(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
1076{
1077 ui_window_t *window = (ui_window_t *) arg;
1078
1079 if (window->mbar != NULL) {
1080 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1081 ui_menu_close(window->sysmenu);
1082 ui_menu_bar_select_first(window->mbar, false, idev_id);
1083 }
1084}
1085
1086/** Window decoration detected accelerator press from system menu handle.
1087 *
1088 * @param wdecor Window decoration
1089 * @param arg Argument (window)
1090 * @param c Accelerator key
1091 * @param idev_id Input device ID
1092 */
1093static void wd_sysmenu_accel(ui_wdecor_t *wdecor, void *arg, char32_t c,
1094 sysarg_t idev_id)
1095{
1096 ui_window_t *window = (ui_window_t *) arg;
1097
1098 if (window->mbar != NULL) {
1099 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1100 ui_menu_close(window->sysmenu);
1101 ui_menu_bar_press_accel(window->mbar, c, idev_id);
1102 }
1103}
1104
1105/** Window decoration requested window minimization.
1106 *
1107 * @param wdecor Window decoration
1108 * @param arg Argument (window)
1109 */
1110static void wd_minimize(ui_wdecor_t *wdecor, void *arg)
1111{
1112 ui_window_t *window = (ui_window_t *) arg;
1113
1114 ui_window_send_minimize(window);
1115}
1116
1117/** Window decoration requested window maximization.
1118 *
1119 * @param wdecor Window decoration
1120 * @param arg Argument (window)
1121 */
1122static void wd_maximize(ui_wdecor_t *wdecor, void *arg)
1123{
1124 ui_window_t *window = (ui_window_t *) arg;
1125
1126 ui_window_send_maximize(window);
1127}
1128
1129/** Window decoration requested window unmaximization.
1130 *
1131 * @param wdecor Window decoration
1132 * @param arg Argument (window)
1133 */
1134static void wd_unmaximize(ui_wdecor_t *wdecor, void *arg)
1135{
1136 ui_window_t *window = (ui_window_t *) arg;
1137
1138 ui_window_send_unmaximize(window);
1139}
1140
1141/** Window decoration requested window closure.
1142 *
1143 * @param wdecor Window decoration
1144 * @param arg Argument (window)
1145 */
1146static void wd_close(ui_wdecor_t *wdecor, void *arg)
1147{
1148 ui_window_t *window = (ui_window_t *) arg;
1149
1150 ui_window_send_close(window);
1151}
1152
1153/** Window decoration requested window move.
1154 *
1155 * @param wdecor Window decoration
1156 * @param arg Argument (window)
1157 * @param pos Position where the title bar was pressed
1158 * @param pos_id Positioning device ID
1159 */
1160static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos,
1161 sysarg_t pos_id)
1162{
1163 ui_window_t *window = (ui_window_t *) arg;
1164
1165 if (window->dwindow != NULL)
1166 (void) display_window_move_req(window->dwindow, pos, pos_id);
1167}
1168
1169/** Window decoration requested window resize.
1170 *
1171 * @param wdecor Window decoration
1172 * @param arg Argument (window)
1173 * @param rsztype Resize type
1174 * @param pos Position where the button was pressed
1175 * @param pos_id Positioning device ID
1176 */
1177static void wd_resize(ui_wdecor_t *wdecor, void *arg,
1178 ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos, sysarg_t pos_id)
1179{
1180 ui_window_t *window = (ui_window_t *) arg;
1181
1182 if (window->dwindow != NULL) {
1183 (void) display_window_resize_req(window->dwindow, rsztype,
1184 pos, pos_id);
1185 }
1186}
1187
1188/** Get display stock cursor from UI stock cursor.
1189 *
1190 * @param cursor UI stock cursor
1191 * @return Display stock cursor
1192 */
1193display_stock_cursor_t wnd_dcursor_from_cursor(ui_stock_cursor_t cursor)
1194{
1195 display_stock_cursor_t dcursor;
1196
1197 dcursor = dcurs_arrow;
1198
1199 switch (cursor) {
1200 case ui_curs_arrow:
1201 dcursor = dcurs_arrow;
1202 break;
1203 case ui_curs_size_ud:
1204 dcursor = dcurs_size_ud;
1205 break;
1206 case ui_curs_size_lr:
1207 dcursor = dcurs_size_lr;
1208 break;
1209 case ui_curs_size_uldr:
1210 dcursor = dcurs_size_uldr;
1211 break;
1212 case ui_curs_size_urdl:
1213 dcursor = dcurs_size_urdl;
1214 break;
1215 case ui_curs_ibeam:
1216 dcursor = dcurs_ibeam;
1217 break;
1218 }
1219
1220 return dcursor;
1221}
1222
1223/** Window decoration requested changing cursor.
1224 *
1225 * @param wdecor Window decoration
1226 * @param arg Argument (window)
1227 * @param cursor Cursor to set
1228 */
1229static void wd_set_cursor(ui_wdecor_t *wdecor, void *arg,
1230 ui_stock_cursor_t cursor)
1231{
1232 ui_window_t *window = (ui_window_t *) arg;
1233 display_stock_cursor_t dcursor;
1234
1235 if (cursor == window->cursor)
1236 return;
1237
1238 dcursor = wnd_dcursor_from_cursor(cursor);
1239
1240 if (window->dwindow != NULL)
1241 (void) display_window_set_cursor(window->dwindow, dcursor);
1242
1243 window->cursor = cursor;
1244}
1245
1246/** Send window sysmenu event.
1247 *
1248 * @param window Window
1249 * @parma idev_id Input device ID
1250 */
1251void ui_window_send_sysmenu(ui_window_t *window, sysarg_t idev_id)
1252{
1253 if (window->cb != NULL && window->cb->sysmenu != NULL)
1254 window->cb->sysmenu(window, window->arg, idev_id);
1255 else
1256 ui_window_def_sysmenu(window, idev_id);
1257}
1258
1259/** Send window minimize event.
1260 *
1261 * @param window Window
1262 */
1263void ui_window_send_minimize(ui_window_t *window)
1264{
1265 if (window->cb != NULL && window->cb->maximize != NULL)
1266 window->cb->minimize(window, window->arg);
1267 else
1268 ui_window_def_minimize(window);
1269}
1270
1271/** Send window maximize event.
1272 *
1273 * @param window Window
1274 */
1275void ui_window_send_maximize(ui_window_t *window)
1276{
1277 if (window->cb != NULL && window->cb->maximize != NULL)
1278 window->cb->maximize(window, window->arg);
1279 else
1280 ui_window_def_maximize(window);
1281}
1282
1283/** Send window unmaximize event.
1284 *
1285 * @param window Window
1286 */
1287void ui_window_send_unmaximize(ui_window_t *window)
1288{
1289 if (window->cb != NULL && window->cb->unmaximize != NULL)
1290 window->cb->unmaximize(window, window->arg);
1291 else
1292 ui_window_def_unmaximize(window);
1293}
1294
1295/** Send window close event.
1296 *
1297 * @param window Window
1298 */
1299void ui_window_send_close(ui_window_t *window)
1300{
1301 if (window->cb != NULL && window->cb->close != NULL)
1302 window->cb->close(window, window->arg);
1303}
1304
1305/** Send window focus event.
1306 *
1307 * @param window Window
1308 * @param nfocus New number of foci
1309 */
1310void ui_window_send_focus(ui_window_t *window, unsigned nfocus)
1311{
1312 if (window->cb != NULL && window->cb->focus != NULL)
1313 window->cb->focus(window, window->arg, nfocus);
1314}
1315
1316/** Send window keyboard event.
1317 *
1318 * @param window Window
1319 */
1320void ui_window_send_kbd(ui_window_t *window, kbd_event_t *kbd)
1321{
1322 if (window->cb != NULL && window->cb->kbd != NULL)
1323 window->cb->kbd(window, window->arg, kbd);
1324 else
1325 ui_window_def_kbd(window, kbd);
1326}
1327
1328/** Send window paint event.
1329 *
1330 * @param window Window
1331 */
1332errno_t ui_window_send_paint(ui_window_t *window)
1333{
1334 if (window->cb != NULL && window->cb->paint != NULL)
1335 return window->cb->paint(window, window->arg);
1336 else
1337 return ui_window_def_paint(window);
1338}
1339
1340/** Send window position event.
1341 *
1342 * @param window Window
1343 */
1344void ui_window_send_pos(ui_window_t *window, pos_event_t *pos)
1345{
1346 if (window->cb != NULL && window->cb->pos != NULL)
1347 window->cb->pos(window, window->arg, pos);
1348 else
1349 ui_window_def_pos(window, pos);
1350}
1351
1352/** Send window unfocus event.
1353 *
1354 * @param window Window
1355 * @param nfocus Number of remaining foci
1356 */
1357void ui_window_send_unfocus(ui_window_t *window, unsigned nfocus)
1358{
1359 if (window->cb != NULL && window->cb->unfocus != NULL)
1360 window->cb->unfocus(window, window->arg, nfocus);
1361 else
1362 return ui_window_def_unfocus(window, nfocus);
1363}
1364
1365/** Default window sysmenu routine.
1366 *
1367 * @param window Window
1368 * @param idev_id Input device ID
1369 * @return EOK on success or an error code
1370 */
1371errno_t ui_window_def_sysmenu(ui_window_t *window, sysarg_t idev_id)
1372{
1373 errno_t rc;
1374 ui_wdecor_geom_t geom;
1375
1376 if (ui_menu_is_open(window->sysmenu)) {
1377 ui_menu_close(window->sysmenu);
1378 } else {
1379 ui_wdecor_get_geom(window->wdecor, &geom);
1380
1381 rc = ui_menu_open(window->sysmenu, &geom.title_bar_rect,
1382 idev_id);
1383 if (rc != EOK)
1384 goto error;
1385 }
1386
1387 return EOK;
1388error:
1389 return rc;
1390}
1391
1392/** Default window minimize routine.
1393 *
1394 * @param window Window
1395 * @return EOK on success or an error code
1396 */
1397errno_t ui_window_def_minimize(ui_window_t *window)
1398{
1399 errno_t rc;
1400
1401 if (window->dwindow != NULL) {
1402 rc = display_window_minimize(window->dwindow);
1403 if (rc != EOK)
1404 goto error;
1405 }
1406
1407 return EOK;
1408error:
1409 return rc;
1410}
1411
1412/** Default window maximize routine.
1413 *
1414 * @param window Window
1415 * @return EOK on success or an error code
1416 */
1417errno_t ui_window_def_maximize(ui_window_t *window)
1418{
1419 errno_t rc;
1420 gfx_rect_t old_rect;
1421 gfx_rect_t rect;
1422
1423 old_rect = window->rect;
1424
1425 if (window->dwindow != NULL) {
1426 rc = display_window_get_max_rect(window->dwindow, &rect);
1427 if (rc != EOK)
1428 return rc;
1429 } else {
1430 rect = window->ui->rect;
1431 }
1432
1433 ui_wdecor_set_maximized(window->wdecor, true);
1434 ui_menu_entry_set_disabled(window->sysmenu_restore, false);
1435 ui_menu_entry_set_disabled(window->sysmenu_maximize, true);
1436
1437 rc = ui_window_size_change(window, &rect, ui_wsc_maximize);
1438 if (rc != EOK) {
1439 ui_wdecor_set_maximized(window->wdecor, false);
1440 return rc;
1441 }
1442
1443 window->normal_rect = old_rect;
1444 (void) ui_window_paint(window);
1445 return EOK;
1446}
1447
1448/** Default window unmaximize routine.
1449 *
1450 * @param window Window
1451 * @return EOK on success or an error code
1452 */
1453errno_t ui_window_def_unmaximize(ui_window_t *window)
1454{
1455 errno_t rc;
1456
1457 ui_wdecor_set_maximized(window->wdecor, false);
1458 ui_menu_entry_set_disabled(window->sysmenu_restore, true);
1459 ui_menu_entry_set_disabled(window->sysmenu_maximize, false);
1460
1461 rc = ui_window_size_change(window, &window->normal_rect,
1462 ui_wsc_unmaximize);
1463 if (rc != EOK) {
1464 ui_wdecor_set_maximized(window->wdecor, true);
1465 printf("ui_window_size_change->error\n");
1466 return rc;
1467 }
1468
1469 (void) ui_window_paint(window);
1470 return EOK;
1471}
1472
1473/** Default window keyboard event routine.
1474 *
1475 * @param window Window
1476 * @return ui_claimed iff event was claimed
1477 */
1478ui_evclaim_t ui_window_def_kbd(ui_window_t *window, kbd_event_t *kbd)
1479{
1480 ui_evclaim_t claim;
1481
1482 if (window->control != NULL)
1483 claim = ui_control_kbd_event(window->control, kbd);
1484 else
1485 claim = ui_unclaimed;
1486
1487 if (claim == ui_unclaimed)
1488 return ui_wdecor_kbd_event(window->wdecor, kbd);
1489
1490 return ui_unclaimed;
1491}
1492
1493/** Default window paint routine.
1494 *
1495 * @param window Window
1496 * @return EOK on success or an error code
1497 */
1498errno_t ui_window_def_paint(ui_window_t *window)
1499{
1500 gfx_rect_t app_rect;
1501 errno_t rc;
1502
1503 rc = gfx_set_color(window->gc, window->res->wnd_face_color);
1504 if (rc != EOK)
1505 return rc;
1506
1507 ui_window_get_app_rect(window, &app_rect);
1508
1509 rc = gfx_fill_rect(window->gc, &app_rect);
1510 if (rc != EOK)
1511 return rc;
1512
1513 if (window->control != NULL)
1514 return ui_control_paint(window->control);
1515
1516 rc = gfx_update(window->res->gc);
1517 if (rc != EOK)
1518 return rc;
1519
1520 return EOK;
1521}
1522
1523/** Default window position event routine.
1524 *
1525 * @param window Window
1526 */
1527void ui_window_def_pos(ui_window_t *window, pos_event_t *pos)
1528{
1529 if (window->control != NULL)
1530 ui_control_pos_event(window->control, pos);
1531}
1532
1533/** Default window unfocus routine.
1534 *
1535 * @param window Window
1536 * @param nfocus Number of remaining foci
1537 * @return EOK on success or an error code
1538 */
1539void ui_window_def_unfocus(ui_window_t *window, unsigned nfocus)
1540{
1541 if (window->control != NULL)
1542 ui_control_unfocus(window->control, nfocus);
1543}
1544
1545/** Handle system menu left event.
1546 *
1547 * @param sysmenu System menu
1548 * @param arg Argument (ui_window_t *)
1549 * @param idev_id Input device ID
1550 */
1551static void wnd_sysmenu_left(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
1552{
1553 ui_window_t *window = (ui_window_t *)arg;
1554
1555 if (window->mbar != NULL) {
1556 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1557 ui_menu_close(sysmenu);
1558 ui_menu_bar_select_last(window->mbar, true, idev_id);
1559 }
1560}
1561
1562/** Handle system menu right event.
1563 *
1564 * @param sysmenu System menu
1565 * @param arg Argument (ui_window_t *)
1566 * @param idev_id Input device ID
1567 */
1568static void wnd_sysmenu_right(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
1569{
1570 ui_window_t *window = (ui_window_t *)arg;
1571
1572 if (window->mbar != NULL) {
1573 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1574 ui_menu_close(sysmenu);
1575 ui_menu_bar_select_first(window->mbar, true, idev_id);
1576 }
1577}
1578
1579/** Handle system menu close request event.
1580 *
1581 * @param sysmenu System menu
1582 * @param arg Argument (ui_window_t *)
1583 * @param idev_id Input device ID
1584 */
1585static void wnd_sysmenu_close_req(ui_menu_t *sysmenu, void *arg)
1586{
1587 ui_window_t *window = (ui_window_t *)arg;
1588
1589 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1590 ui_menu_close(sysmenu);
1591}
1592
1593/** Handle system menu Restore entry activation.
1594 *
1595 * @param mentry Menu entry
1596 * @param arg Argument (ui_window_t *)
1597 */
1598static void wnd_sysmenu_erestore(ui_menu_entry_t *mentry, void *arg)
1599{
1600 ui_window_t *window = (ui_window_t *)arg;
1601
1602 ui_window_send_unmaximize(window);
1603}
1604
1605/** Handle system menu Minimize entry activation.
1606 *
1607 * @param mentry Menu entry
1608 * @param arg Argument (ui_window_t *)
1609 */
1610static void wnd_sysmenu_eminimize(ui_menu_entry_t *mentry, void *arg)
1611{
1612 ui_window_t *window = (ui_window_t *)arg;
1613
1614 ui_window_send_minimize(window);
1615}
1616
1617/** Handle system menu Maximize entry activation.
1618 *
1619 * @param mentry Menu entry
1620 * @param arg Argument (ui_window_t *)
1621 */
1622static void wnd_sysmenu_emaximize(ui_menu_entry_t *mentry, void *arg)
1623{
1624 ui_window_t *window = (ui_window_t *)arg;
1625
1626 ui_window_send_maximize(window);
1627}
1628
1629/** Handle system menu Close entry activation.
1630 *
1631 * @param mentry Menu entry
1632 * @param arg Argument (ui_window_t *)
1633 */
1634static void wnd_sysmenu_eclose(ui_menu_entry_t *mentry, void *arg)
1635{
1636 ui_window_t *window = (ui_window_t *)arg;
1637
1638 ui_window_send_close(window);
1639}
1640
1641/** Handle system menu press accelerator key event.
1642 *
1643 * @param sysmenu System menu
1644 * @param arg Argument (ui_window_t *)
1645 * @param idev_id Input device ID
1646 */
1647static void wnd_sysmenu_press_accel(ui_menu_t *sysmenu, void *arg,
1648 char32_t c, sysarg_t idev_id)
1649{
1650 (void)sysmenu;
1651 (void)arg;
1652 (void)c;
1653 (void)idev_id;
1654}
1655
1656/** Window invalidate callback
1657 *
1658 * @param arg Argument (ui_window_t *)
1659 * @param rect Rectangle to update
1660 */
1661static void ui_window_invalidate(void *arg, gfx_rect_t *rect)
1662{
1663 ui_window_t *window = (ui_window_t *) arg;
1664 gfx_rect_t env;
1665
1666 gfx_rect_envelope(&window->dirty_rect, rect, &env);
1667 window->dirty_rect = env;
1668}
1669
1670/** Window update callback
1671 *
1672 * @param arg Argument (ui_window_t *)
1673 */
1674static void ui_window_update(void *arg)
1675{
1676 ui_window_t *window = (ui_window_t *) arg;
1677
1678 if (!gfx_rect_is_empty(&window->dirty_rect)) {
1679 (void) gfx_bitmap_render(window->bmp, &window->dirty_rect,
1680 &window->dpos);
1681 }
1682
1683 window->dirty_rect.p0.x = 0;
1684 window->dirty_rect.p0.y = 0;
1685 window->dirty_rect.p1.x = 0;
1686 window->dirty_rect.p1.y = 0;
1687}
1688
1689/** Window cursor get position callback
1690 *
1691 * @param arg Argument (ui_window_t *)
1692 * @param pos Place to store position
1693 */
1694static errno_t ui_window_cursor_get_pos(void *arg, gfx_coord2_t *pos)
1695{
1696 ui_window_t *window = (ui_window_t *) arg;
1697 gfx_coord2_t cpos;
1698 errno_t rc;
1699
1700 rc = gfx_cursor_get_pos(window->realgc, &cpos);
1701 if (rc != EOK)
1702 return rc;
1703
1704 pos->x = cpos.x - window->dpos.x;
1705 pos->y = cpos.y - window->dpos.y;
1706 return EOK;
1707}
1708
1709/** Window cursor set position callback
1710 *
1711 * @param arg Argument (ui_window_t *)
1712 * @param pos New position
1713 */
1714static errno_t ui_window_cursor_set_pos(void *arg, gfx_coord2_t *pos)
1715{
1716 ui_window_t *window = (ui_window_t *) arg;
1717 gfx_coord2_t cpos;
1718
1719 cpos.x = pos->x + window->dpos.x;
1720 cpos.y = pos->y + window->dpos.y;
1721
1722 return gfx_cursor_set_pos(window->realgc, &cpos);
1723}
1724
1725/** Window cursor set visibility callback
1726 *
1727 * @param arg Argument (ui_window_t *)
1728 * @param visible @c true iff cursor is to be made visible
1729 */
1730static errno_t ui_window_cursor_set_visible(void *arg, bool visible)
1731{
1732 ui_window_t *window = (ui_window_t *) arg;
1733
1734 return gfx_cursor_set_visible(window->realgc, visible);
1735}
1736
1737/** Application area invalidate callback
1738 *
1739 * @param arg Argument (ui_window_t *)
1740 * @param rect Rectangle to update
1741 */
1742static void ui_window_app_invalidate(void *arg, gfx_rect_t *rect)
1743{
1744 ui_window_t *window = (ui_window_t *) arg;
1745 gfx_rect_t arect;
1746
1747 ui_window_get_app_rect(window, &arect);
1748
1749 /* Render bitmap rectangle inside the application area */
1750 (void) gfx_bitmap_render(window->app_bmp, rect, &arect.p0);
1751 /*
1752 * TODO Update applications to call gfx_update(), then
1753 * we can defer update to ui_window_app_update().
1754 */
1755 (void) gfx_update(window->res->gc);
1756}
1757
1758/** Application area update callback
1759 *
1760 * @param arg Argument (ui_window_t *)
1761 */
1762static void ui_window_app_update(void *arg)
1763{
1764 ui_window_t *window = (ui_window_t *) arg;
1765
1766 /*
1767 * Not used since display is updated immediately
1768 * in ui_window_app_invalidate
1769 */
1770 (void) window;
1771}
1772
1773/** Window expose callback. */
1774static void ui_window_expose_cb(void *arg)
1775{
1776 ui_window_t *window = (ui_window_t *) arg;
1777
1778 ui_window_paint(window);
1779}
1780
1781/** @}
1782 */
Note: See TracBrowser for help on using the repository browser.