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

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

Handover between system menu and menu bar

We can move between them using Left and Right keys in either closed
or open state. One can now open system menu with F10, Left, Down in
a window with menu bar, or just F10 in a window without menu bar.

  • Property mode set to 100644
File size: 42.1 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_menu_bar_select_last(window->mbar, false, idev_id);
1064 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1065 }
1066}
1067
1068/** Window decoration requested moving right from system menu handle.
1069 *
1070 * @param wdecor Window decoration
1071 * @param arg Argument (window)
1072 * @param idev_id Input device ID
1073 */
1074static void wd_sysmenu_right(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
1075{
1076 ui_window_t *window = (ui_window_t *) arg;
1077
1078 if (window->mbar != NULL) {
1079 ui_menu_bar_select_first(window->mbar, false, idev_id);
1080 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1081 }
1082}
1083
1084/** Window decoration detected accelerator press from system menu handle.
1085 *
1086 * @param wdecor Window decoration
1087 * @param arg Argument (window)
1088 * @param c Accelerator key
1089 * @param idev_id Input device ID
1090 */
1091static void wd_sysmenu_accel(ui_wdecor_t *wdecor, void *arg, char32_t c,
1092 sysarg_t idev_id)
1093{
1094 ui_window_t *window = (ui_window_t *) arg;
1095
1096 if (window->mbar != NULL) {
1097 ui_menu_bar_press_accel(window->mbar, c, idev_id);
1098 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1099 }
1100}
1101
1102/** Window decoration requested window minimization.
1103 *
1104 * @param wdecor Window decoration
1105 * @param arg Argument (window)
1106 */
1107static void wd_minimize(ui_wdecor_t *wdecor, void *arg)
1108{
1109 ui_window_t *window = (ui_window_t *) arg;
1110
1111 ui_window_send_minimize(window);
1112}
1113
1114/** Window decoration requested window maximization.
1115 *
1116 * @param wdecor Window decoration
1117 * @param arg Argument (window)
1118 */
1119static void wd_maximize(ui_wdecor_t *wdecor, void *arg)
1120{
1121 ui_window_t *window = (ui_window_t *) arg;
1122
1123 ui_window_send_maximize(window);
1124}
1125
1126/** Window decoration requested window unmaximization.
1127 *
1128 * @param wdecor Window decoration
1129 * @param arg Argument (window)
1130 */
1131static void wd_unmaximize(ui_wdecor_t *wdecor, void *arg)
1132{
1133 ui_window_t *window = (ui_window_t *) arg;
1134
1135 ui_window_send_unmaximize(window);
1136}
1137
1138/** Window decoration requested window closure.
1139 *
1140 * @param wdecor Window decoration
1141 * @param arg Argument (window)
1142 */
1143static void wd_close(ui_wdecor_t *wdecor, void *arg)
1144{
1145 ui_window_t *window = (ui_window_t *) arg;
1146
1147 ui_window_send_close(window);
1148}
1149
1150/** Window decoration requested window move.
1151 *
1152 * @param wdecor Window decoration
1153 * @param arg Argument (window)
1154 * @param pos Position where the title bar was pressed
1155 * @param pos_id Positioning device ID
1156 */
1157static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos,
1158 sysarg_t pos_id)
1159{
1160 ui_window_t *window = (ui_window_t *) arg;
1161
1162 if (window->dwindow != NULL)
1163 (void) display_window_move_req(window->dwindow, pos, pos_id);
1164}
1165
1166/** Window decoration requested window resize.
1167 *
1168 * @param wdecor Window decoration
1169 * @param arg Argument (window)
1170 * @param rsztype Resize type
1171 * @param pos Position where the button was pressed
1172 * @param pos_id Positioning device ID
1173 */
1174static void wd_resize(ui_wdecor_t *wdecor, void *arg,
1175 ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos, sysarg_t pos_id)
1176{
1177 ui_window_t *window = (ui_window_t *) arg;
1178
1179 if (window->dwindow != NULL) {
1180 (void) display_window_resize_req(window->dwindow, rsztype,
1181 pos, pos_id);
1182 }
1183}
1184
1185/** Get display stock cursor from UI stock cursor.
1186 *
1187 * @param cursor UI stock cursor
1188 * @return Display stock cursor
1189 */
1190display_stock_cursor_t wnd_dcursor_from_cursor(ui_stock_cursor_t cursor)
1191{
1192 display_stock_cursor_t dcursor;
1193
1194 dcursor = dcurs_arrow;
1195
1196 switch (cursor) {
1197 case ui_curs_arrow:
1198 dcursor = dcurs_arrow;
1199 break;
1200 case ui_curs_size_ud:
1201 dcursor = dcurs_size_ud;
1202 break;
1203 case ui_curs_size_lr:
1204 dcursor = dcurs_size_lr;
1205 break;
1206 case ui_curs_size_uldr:
1207 dcursor = dcurs_size_uldr;
1208 break;
1209 case ui_curs_size_urdl:
1210 dcursor = dcurs_size_urdl;
1211 break;
1212 case ui_curs_ibeam:
1213 dcursor = dcurs_ibeam;
1214 break;
1215 }
1216
1217 return dcursor;
1218}
1219
1220/** Window decoration requested changing cursor.
1221 *
1222 * @param wdecor Window decoration
1223 * @param arg Argument (window)
1224 * @param cursor Cursor to set
1225 */
1226static void wd_set_cursor(ui_wdecor_t *wdecor, void *arg,
1227 ui_stock_cursor_t cursor)
1228{
1229 ui_window_t *window = (ui_window_t *) arg;
1230 display_stock_cursor_t dcursor;
1231
1232 if (cursor == window->cursor)
1233 return;
1234
1235 dcursor = wnd_dcursor_from_cursor(cursor);
1236
1237 if (window->dwindow != NULL)
1238 (void) display_window_set_cursor(window->dwindow, dcursor);
1239
1240 window->cursor = cursor;
1241}
1242
1243/** Send window sysmenu event.
1244 *
1245 * @param window Window
1246 * @parma idev_id Input device ID
1247 */
1248void ui_window_send_sysmenu(ui_window_t *window, sysarg_t idev_id)
1249{
1250 if (window->cb != NULL && window->cb->sysmenu != NULL)
1251 window->cb->sysmenu(window, window->arg, idev_id);
1252 else
1253 ui_window_def_sysmenu(window, idev_id);
1254}
1255
1256/** Send window minimize event.
1257 *
1258 * @param window Window
1259 */
1260void ui_window_send_minimize(ui_window_t *window)
1261{
1262 if (window->cb != NULL && window->cb->maximize != NULL)
1263 window->cb->minimize(window, window->arg);
1264 else
1265 ui_window_def_minimize(window);
1266}
1267
1268/** Send window maximize event.
1269 *
1270 * @param window Window
1271 */
1272void ui_window_send_maximize(ui_window_t *window)
1273{
1274 if (window->cb != NULL && window->cb->maximize != NULL)
1275 window->cb->maximize(window, window->arg);
1276 else
1277 ui_window_def_maximize(window);
1278}
1279
1280/** Send window unmaximize event.
1281 *
1282 * @param window Window
1283 */
1284void ui_window_send_unmaximize(ui_window_t *window)
1285{
1286 if (window->cb != NULL && window->cb->unmaximize != NULL)
1287 window->cb->unmaximize(window, window->arg);
1288 else
1289 ui_window_def_unmaximize(window);
1290}
1291
1292/** Send window close event.
1293 *
1294 * @param window Window
1295 */
1296void ui_window_send_close(ui_window_t *window)
1297{
1298 if (window->cb != NULL && window->cb->close != NULL)
1299 window->cb->close(window, window->arg);
1300}
1301
1302/** Send window focus event.
1303 *
1304 * @param window Window
1305 * @param nfocus New number of foci
1306 */
1307void ui_window_send_focus(ui_window_t *window, unsigned nfocus)
1308{
1309 if (window->cb != NULL && window->cb->focus != NULL)
1310 window->cb->focus(window, window->arg, nfocus);
1311}
1312
1313/** Send window keyboard event.
1314 *
1315 * @param window Window
1316 */
1317void ui_window_send_kbd(ui_window_t *window, kbd_event_t *kbd)
1318{
1319 if (window->cb != NULL && window->cb->kbd != NULL)
1320 window->cb->kbd(window, window->arg, kbd);
1321 else
1322 ui_window_def_kbd(window, kbd);
1323}
1324
1325/** Send window paint event.
1326 *
1327 * @param window Window
1328 */
1329errno_t ui_window_send_paint(ui_window_t *window)
1330{
1331 if (window->cb != NULL && window->cb->paint != NULL)
1332 return window->cb->paint(window, window->arg);
1333 else
1334 return ui_window_def_paint(window);
1335}
1336
1337/** Send window position event.
1338 *
1339 * @param window Window
1340 */
1341void ui_window_send_pos(ui_window_t *window, pos_event_t *pos)
1342{
1343 if (window->cb != NULL && window->cb->pos != NULL)
1344 window->cb->pos(window, window->arg, pos);
1345 else
1346 ui_window_def_pos(window, pos);
1347}
1348
1349/** Send window unfocus event.
1350 *
1351 * @param window Window
1352 * @param nfocus Number of remaining foci
1353 */
1354void ui_window_send_unfocus(ui_window_t *window, unsigned nfocus)
1355{
1356 if (window->cb != NULL && window->cb->unfocus != NULL)
1357 window->cb->unfocus(window, window->arg, nfocus);
1358 else
1359 return ui_window_def_unfocus(window, nfocus);
1360}
1361
1362/** Default window sysmenu routine.
1363 *
1364 * @param window Window
1365 * @param idev_id Input device ID
1366 * @return EOK on success or an error code
1367 */
1368errno_t ui_window_def_sysmenu(ui_window_t *window, sysarg_t idev_id)
1369{
1370 errno_t rc;
1371 ui_wdecor_geom_t geom;
1372
1373 if (ui_menu_is_open(window->sysmenu)) {
1374 ui_menu_close(window->sysmenu);
1375 } else {
1376 ui_wdecor_get_geom(window->wdecor, &geom);
1377
1378 rc = ui_menu_open(window->sysmenu, &geom.title_bar_rect,
1379 idev_id);
1380 if (rc != EOK)
1381 goto error;
1382 }
1383
1384 return EOK;
1385error:
1386 return rc;
1387}
1388
1389/** Default window minimize routine.
1390 *
1391 * @param window Window
1392 * @return EOK on success or an error code
1393 */
1394errno_t ui_window_def_minimize(ui_window_t *window)
1395{
1396 errno_t rc;
1397
1398 if (window->dwindow != NULL) {
1399 rc = display_window_minimize(window->dwindow);
1400 if (rc != EOK)
1401 goto error;
1402 }
1403
1404 return EOK;
1405error:
1406 return rc;
1407}
1408
1409/** Default window maximize routine.
1410 *
1411 * @param window Window
1412 * @return EOK on success or an error code
1413 */
1414errno_t ui_window_def_maximize(ui_window_t *window)
1415{
1416 errno_t rc;
1417 gfx_rect_t old_rect;
1418 gfx_rect_t rect;
1419
1420 old_rect = window->rect;
1421
1422 if (window->dwindow != NULL) {
1423 rc = display_window_get_max_rect(window->dwindow, &rect);
1424 if (rc != EOK)
1425 return rc;
1426 } else {
1427 rect = window->ui->rect;
1428 }
1429
1430 ui_wdecor_set_maximized(window->wdecor, true);
1431 ui_menu_entry_set_disabled(window->sysmenu_restore, false);
1432 ui_menu_entry_set_disabled(window->sysmenu_maximize, true);
1433
1434 rc = ui_window_size_change(window, &rect, ui_wsc_maximize);
1435 if (rc != EOK) {
1436 ui_wdecor_set_maximized(window->wdecor, false);
1437 return rc;
1438 }
1439
1440 window->normal_rect = old_rect;
1441 (void) ui_window_paint(window);
1442 return EOK;
1443}
1444
1445/** Default window unmaximize routine.
1446 *
1447 * @param window Window
1448 * @return EOK on success or an error code
1449 */
1450errno_t ui_window_def_unmaximize(ui_window_t *window)
1451{
1452 errno_t rc;
1453
1454 ui_wdecor_set_maximized(window->wdecor, false);
1455 ui_menu_entry_set_disabled(window->sysmenu_restore, true);
1456 ui_menu_entry_set_disabled(window->sysmenu_maximize, false);
1457
1458 rc = ui_window_size_change(window, &window->normal_rect,
1459 ui_wsc_unmaximize);
1460 if (rc != EOK) {
1461 ui_wdecor_set_maximized(window->wdecor, true);
1462 printf("ui_window_size_change->error\n");
1463 return rc;
1464 }
1465
1466 (void) ui_window_paint(window);
1467 return EOK;
1468}
1469
1470/** Default window keyboard event routine.
1471 *
1472 * @param window Window
1473 * @return ui_claimed iff event was claimed
1474 */
1475ui_evclaim_t ui_window_def_kbd(ui_window_t *window, kbd_event_t *kbd)
1476{
1477 ui_evclaim_t claim;
1478
1479 if (window->control != NULL)
1480 claim = ui_control_kbd_event(window->control, kbd);
1481 else
1482 claim = ui_unclaimed;
1483
1484 if (claim == ui_unclaimed)
1485 return ui_wdecor_kbd_event(window->wdecor, kbd);
1486
1487 return ui_unclaimed;
1488}
1489
1490/** Default window paint routine.
1491 *
1492 * @param window Window
1493 * @return EOK on success or an error code
1494 */
1495errno_t ui_window_def_paint(ui_window_t *window)
1496{
1497 gfx_rect_t app_rect;
1498 errno_t rc;
1499
1500 rc = gfx_set_color(window->gc, window->res->wnd_face_color);
1501 if (rc != EOK)
1502 return rc;
1503
1504 ui_window_get_app_rect(window, &app_rect);
1505
1506 rc = gfx_fill_rect(window->gc, &app_rect);
1507 if (rc != EOK)
1508 return rc;
1509
1510 if (window->control != NULL)
1511 return ui_control_paint(window->control);
1512
1513 rc = gfx_update(window->res->gc);
1514 if (rc != EOK)
1515 return rc;
1516
1517 return EOK;
1518}
1519
1520/** Default window position event routine.
1521 *
1522 * @param window Window
1523 */
1524void ui_window_def_pos(ui_window_t *window, pos_event_t *pos)
1525{
1526 if (window->control != NULL)
1527 ui_control_pos_event(window->control, pos);
1528}
1529
1530/** Default window unfocus routine.
1531 *
1532 * @param window Window
1533 * @param nfocus Number of remaining foci
1534 * @return EOK on success or an error code
1535 */
1536void ui_window_def_unfocus(ui_window_t *window, unsigned nfocus)
1537{
1538 if (window->control != NULL)
1539 ui_control_unfocus(window->control, nfocus);
1540}
1541
1542/** Handle system menu left event.
1543 *
1544 * @param sysmenu System menu
1545 * @param arg Argument (ui_window_t *)
1546 * @param idev_id Input device ID
1547 */
1548static void wnd_sysmenu_left(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
1549{
1550 ui_window_t *window = (ui_window_t *)arg;
1551
1552 (void)sysmenu;
1553
1554 if (window->mbar != NULL)
1555 ui_menu_bar_select_last(window->mbar, true, idev_id);
1556}
1557
1558/** Handle system menu right event.
1559 *
1560 * @param sysmenu System menu
1561 * @param arg Argument (ui_window_t *)
1562 * @param idev_id Input device ID
1563 */
1564static void wnd_sysmenu_right(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
1565{
1566 ui_window_t *window = (ui_window_t *)arg;
1567
1568 (void)sysmenu;
1569
1570 if (window->mbar != NULL)
1571 ui_menu_bar_select_first(window->mbar, true, idev_id);
1572}
1573
1574/** Handle system menu close request event.
1575 *
1576 * @param sysmenu System menu
1577 * @param arg Argument (ui_window_t *)
1578 * @param idev_id Input device ID
1579 */
1580static void wnd_sysmenu_close_req(ui_menu_t *sysmenu, void *arg)
1581{
1582 ui_window_t *window = (ui_window_t *)arg;
1583
1584 ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
1585 ui_menu_close(sysmenu);
1586}
1587
1588/** Handle system menu Restore entry activation.
1589 *
1590 * @param mentry Menu entry
1591 * @param arg Argument (ui_window_t *)
1592 */
1593static void wnd_sysmenu_erestore(ui_menu_entry_t *mentry, void *arg)
1594{
1595 ui_window_t *window = (ui_window_t *)arg;
1596
1597 ui_window_send_unmaximize(window);
1598}
1599
1600/** Handle system menu Minimize entry activation.
1601 *
1602 * @param mentry Menu entry
1603 * @param arg Argument (ui_window_t *)
1604 */
1605static void wnd_sysmenu_eminimize(ui_menu_entry_t *mentry, void *arg)
1606{
1607 ui_window_t *window = (ui_window_t *)arg;
1608
1609 ui_window_send_minimize(window);
1610}
1611
1612/** Handle system menu Maximize entry activation.
1613 *
1614 * @param mentry Menu entry
1615 * @param arg Argument (ui_window_t *)
1616 */
1617static void wnd_sysmenu_emaximize(ui_menu_entry_t *mentry, void *arg)
1618{
1619 ui_window_t *window = (ui_window_t *)arg;
1620
1621 ui_window_send_maximize(window);
1622}
1623
1624/** Handle system menu Close entry activation.
1625 *
1626 * @param mentry Menu entry
1627 * @param arg Argument (ui_window_t *)
1628 */
1629static void wnd_sysmenu_eclose(ui_menu_entry_t *mentry, void *arg)
1630{
1631 ui_window_t *window = (ui_window_t *)arg;
1632
1633 ui_window_send_close(window);
1634}
1635
1636/** Handle system menu press accelerator key event.
1637 *
1638 * @param sysmenu System menu
1639 * @param arg Argument (ui_window_t *)
1640 * @param idev_id Input device ID
1641 */
1642static void wnd_sysmenu_press_accel(ui_menu_t *sysmenu, void *arg,
1643 char32_t c, sysarg_t idev_id)
1644{
1645 (void)sysmenu;
1646 (void)arg;
1647 (void)c;
1648 (void)idev_id;
1649}
1650
1651/** Window invalidate callback
1652 *
1653 * @param arg Argument (ui_window_t *)
1654 * @param rect Rectangle to update
1655 */
1656static void ui_window_invalidate(void *arg, gfx_rect_t *rect)
1657{
1658 ui_window_t *window = (ui_window_t *) arg;
1659 gfx_rect_t env;
1660
1661 gfx_rect_envelope(&window->dirty_rect, rect, &env);
1662 window->dirty_rect = env;
1663}
1664
1665/** Window update callback
1666 *
1667 * @param arg Argument (ui_window_t *)
1668 */
1669static void ui_window_update(void *arg)
1670{
1671 ui_window_t *window = (ui_window_t *) arg;
1672
1673 if (!gfx_rect_is_empty(&window->dirty_rect)) {
1674 (void) gfx_bitmap_render(window->bmp, &window->dirty_rect,
1675 &window->dpos);
1676 }
1677
1678 window->dirty_rect.p0.x = 0;
1679 window->dirty_rect.p0.y = 0;
1680 window->dirty_rect.p1.x = 0;
1681 window->dirty_rect.p1.y = 0;
1682}
1683
1684/** Window cursor get position callback
1685 *
1686 * @param arg Argument (ui_window_t *)
1687 * @param pos Place to store position
1688 */
1689static errno_t ui_window_cursor_get_pos(void *arg, gfx_coord2_t *pos)
1690{
1691 ui_window_t *window = (ui_window_t *) arg;
1692 gfx_coord2_t cpos;
1693 errno_t rc;
1694
1695 rc = gfx_cursor_get_pos(window->realgc, &cpos);
1696 if (rc != EOK)
1697 return rc;
1698
1699 pos->x = cpos.x - window->dpos.x;
1700 pos->y = cpos.y - window->dpos.y;
1701 return EOK;
1702}
1703
1704/** Window cursor set position callback
1705 *
1706 * @param arg Argument (ui_window_t *)
1707 * @param pos New position
1708 */
1709static errno_t ui_window_cursor_set_pos(void *arg, gfx_coord2_t *pos)
1710{
1711 ui_window_t *window = (ui_window_t *) arg;
1712 gfx_coord2_t cpos;
1713
1714 cpos.x = pos->x + window->dpos.x;
1715 cpos.y = pos->y + window->dpos.y;
1716
1717 return gfx_cursor_set_pos(window->realgc, &cpos);
1718}
1719
1720/** Window cursor set visibility callback
1721 *
1722 * @param arg Argument (ui_window_t *)
1723 * @param visible @c true iff cursor is to be made visible
1724 */
1725static errno_t ui_window_cursor_set_visible(void *arg, bool visible)
1726{
1727 ui_window_t *window = (ui_window_t *) arg;
1728
1729 return gfx_cursor_set_visible(window->realgc, visible);
1730}
1731
1732/** Application area invalidate callback
1733 *
1734 * @param arg Argument (ui_window_t *)
1735 * @param rect Rectangle to update
1736 */
1737static void ui_window_app_invalidate(void *arg, gfx_rect_t *rect)
1738{
1739 ui_window_t *window = (ui_window_t *) arg;
1740 gfx_rect_t arect;
1741
1742 ui_window_get_app_rect(window, &arect);
1743
1744 /* Render bitmap rectangle inside the application area */
1745 (void) gfx_bitmap_render(window->app_bmp, rect, &arect.p0);
1746 /*
1747 * TODO Update applications to call gfx_update(), then
1748 * we can defer update to ui_window_app_update().
1749 */
1750 (void) gfx_update(window->res->gc);
1751}
1752
1753/** Application area update callback
1754 *
1755 * @param arg Argument (ui_window_t *)
1756 */
1757static void ui_window_app_update(void *arg)
1758{
1759 ui_window_t *window = (ui_window_t *) arg;
1760
1761 /*
1762 * Not used since display is updated immediately
1763 * in ui_window_app_invalidate
1764 */
1765 (void) window;
1766}
1767
1768/** Window expose callback. */
1769static void ui_window_expose_cb(void *arg)
1770{
1771 ui_window_t *window = (ui_window_t *) arg;
1772
1773 ui_window_paint(window);
1774}
1775
1776/** @}
1777 */
Note: See TracBrowser for help on using the repository browser.