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

Last change on this file since d7f7a4a was d7f7a4a, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 4 years ago

Replace some license headers with SPDX identifier

Headers are replaced using tools/transorm-copyright.sh only
when it can be matched verbatim with the license header used
throughout most of the codebase.

  • Property mode set to 100644
File size: 30.1 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2022 Jiri Svoboda
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/** @addtogroup libui
8 * @{
9 */
10/**
11 * @file Window
12 */
13
14#include <congfx/console.h>
15#include <display.h>
16#include <errno.h>
17#include <gfx/bitmap.h>
18#include <gfx/context.h>
19#include <gfx/cursor.h>
20#include <gfx/render.h>
21#include <io/kbd_event.h>
22#include <io/pos_event.h>
23#include <mem.h>
24#include <memgfx/memgc.h>
25#include <stdlib.h>
26#include <ui/control.h>
27#include <ui/resource.h>
28#include <ui/ui.h>
29#include <ui/wdecor.h>
30#include <ui/window.h>
31#include "../private/control.h"
32#include "../private/dummygc.h"
33#include "../private/resource.h"
34#include "../private/ui.h"
35#include "../private/wdecor.h"
36#include "../private/window.h"
37
38static void dwnd_close_event(void *);
39static void dwnd_focus_event(void *);
40static void dwnd_kbd_event(void *, kbd_event_t *);
41static void dwnd_pos_event(void *, pos_event_t *);
42static void dwnd_resize_event(void *, gfx_rect_t *);
43static void dwnd_unfocus_event(void *);
44
45static display_wnd_cb_t dwnd_cb = {
46 .close_event = dwnd_close_event,
47 .focus_event = dwnd_focus_event,
48 .kbd_event = dwnd_kbd_event,
49 .pos_event = dwnd_pos_event,
50 .resize_event = dwnd_resize_event,
51 .unfocus_event = dwnd_unfocus_event
52};
53
54static void wd_maximize(ui_wdecor_t *, void *);
55static void wd_unmaximize(ui_wdecor_t *, void *);
56static void wd_close(ui_wdecor_t *, void *);
57static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *);
58static void wd_resize(ui_wdecor_t *, void *, ui_wdecor_rsztype_t,
59 gfx_coord2_t *);
60static void wd_set_cursor(ui_wdecor_t *, void *, ui_stock_cursor_t);
61
62static ui_wdecor_cb_t wdecor_cb = {
63 .maximize = wd_maximize,
64 .unmaximize = wd_unmaximize,
65 .close = wd_close,
66 .move = wd_move,
67 .resize = wd_resize,
68 .set_cursor = wd_set_cursor
69};
70
71static void ui_window_invalidate(void *, gfx_rect_t *);
72static void ui_window_update(void *);
73static errno_t ui_window_cursor_get_pos(void *, gfx_coord2_t *);
74static errno_t ui_window_cursor_set_pos(void *, gfx_coord2_t *);
75static errno_t ui_window_cursor_set_visible(void *, bool);
76
77/** Window memory GC callbacks */
78static mem_gc_cb_t ui_window_mem_gc_cb = {
79 .invalidate = ui_window_invalidate,
80 .update = ui_window_update,
81 .cursor_get_pos = ui_window_cursor_get_pos,
82 .cursor_set_pos = ui_window_cursor_set_pos,
83 .cursor_set_visible = ui_window_cursor_set_visible
84};
85
86static void ui_window_app_invalidate(void *, gfx_rect_t *);
87static void ui_window_app_update(void *);
88
89/** Application area memory GC callbacks */
90static mem_gc_cb_t ui_window_app_mem_gc_cb = {
91 .invalidate = ui_window_app_invalidate,
92 .update = ui_window_app_update
93};
94
95static void ui_window_expose_cb(void *);
96
97/** Initialize window parameters structure.
98 *
99 * Window parameters structure must always be initialized using this function
100 * first. By default, the window will be decorated. To get a non-decorated
101 * window, one needs to clear ui_wds_decorated
102 * (e.g. params->style &= ~ui_wds_decorated).
103 *
104 * @param params Window parameters structure
105 */
106void ui_wnd_params_init(ui_wnd_params_t *params)
107{
108 memset(params, 0, sizeof(ui_wnd_params_t));
109
110 /* Make window decorated by default. */
111 params->style = ui_wds_decorated;
112}
113
114/** Compute where window should be placed on the screen.
115 *
116 * This only applies to windows that do not use default placement or
117 * if we are running in full-screen mode.
118 *
119 * @param window Window
120 * @param drect Display rectangle
121 * @param params Window parameters
122 * @param pos Place to store position of top-left corner
123 */
124static void ui_window_place(ui_window_t *window, gfx_rect_t *drect,
125 ui_wnd_params_t *params, gfx_coord2_t *pos)
126{
127 gfx_coord2_t dims;
128
129 assert(params->placement != ui_wnd_place_default ||
130 ui_is_fullscreen(window->ui));
131
132 pos->x = 0;
133 pos->y = 0;
134
135 switch (params->placement) {
136 case ui_wnd_place_default:
137 assert(ui_is_fullscreen(window->ui));
138 /* Center window */
139 gfx_rect_dims(&params->rect, &dims);
140 pos->x = (drect->p0.x + drect->p1.x) / 2 - dims.x / 2;
141 pos->y = (drect->p0.y + drect->p1.y) / 2 - dims.y / 2;
142 break;
143 case ui_wnd_place_top_left:
144 case ui_wnd_place_full_screen:
145 pos->x = drect->p0.x - params->rect.p0.x;
146 pos->y = drect->p0.y - params->rect.p0.y;
147 break;
148 case ui_wnd_place_top_right:
149 pos->x = drect->p1.x - params->rect.p1.x;
150 pos->y = drect->p0.y - params->rect.p0.y;
151 break;
152 case ui_wnd_place_bottom_left:
153 pos->x = drect->p0.x - params->rect.p0.x;
154 pos->y = drect->p1.y - params->rect.p1.y;
155 break;
156 case ui_wnd_place_bottom_right:
157 pos->x = drect->p1.x - params->rect.p1.x;
158 pos->y = drect->p1.y - params->rect.p1.y;
159 break;
160 case ui_wnd_place_popup:
161 /* Place popup window below parent rectangle */
162 pos->x = params->prect.p0.x;
163 pos->y = params->prect.p1.y;
164 break;
165 }
166}
167
168/** Create new window.
169 *
170 * @param ui User interface
171 * @param params Window parameters
172 * @param rwindow Place to store pointer to new window
173 * @return EOK on success or an error code
174 */
175errno_t ui_window_create(ui_t *ui, ui_wnd_params_t *params,
176 ui_window_t **rwindow)
177{
178 ui_window_t *window;
179 display_info_t info;
180 gfx_coord2_t scr_dims;
181 display_wnd_params_t dparams;
182 gfx_context_t *gc = NULL;
183 ui_resource_t *res = NULL;
184 ui_wdecor_t *wdecor = NULL;
185 dummy_gc_t *dgc = NULL;
186 gfx_bitmap_params_t bparams;
187 gfx_bitmap_alloc_t alloc;
188 gfx_bitmap_t *bmp = NULL;
189 gfx_coord2_t off;
190 mem_gc_t *memgc = NULL;
191 xlate_gc_t *xgc = NULL;
192 errno_t rc;
193
194 window = calloc(1, sizeof(ui_window_t));
195 if (window == NULL)
196 return ENOMEM;
197
198 window->ui = ui;
199
200 display_wnd_params_init(&dparams);
201 dparams.rect = params->rect;
202 /* Only allow making the window larger */
203 gfx_rect_dims(&params->rect, &dparams.min_size);
204
205 if ((params->flags & ui_wndf_popup) != 0)
206 dparams.flags |= wndf_popup;
207
208 if (ui->display != NULL) {
209 if (params->placement != ui_wnd_place_default) {
210 rc = display_get_info(ui->display, &info);
211 if (rc != EOK)
212 goto error;
213 }
214
215 if (params->placement == ui_wnd_place_full_screen) {
216 /* Make window the size of the screen */
217 gfx_rect_dims(&info.rect, &scr_dims);
218 gfx_coord2_add(&dparams.rect.p0, &scr_dims,
219 &dparams.rect.p1);
220 }
221
222 if (params->placement != ui_wnd_place_default) {
223 /* Set initial display window position */
224 ui_window_place(window, &info.rect, params,
225 &dparams.pos);
226
227 dparams.flags |= wndf_setpos;
228 }
229
230 rc = display_window_create(ui->display, &dparams, &dwnd_cb,
231 (void *) window, &window->dwindow);
232 if (rc != EOK)
233 goto error;
234
235 rc = display_window_get_gc(window->dwindow, &gc);
236 if (rc != EOK)
237 goto error;
238 } else if (ui->console != NULL) {
239 gc = console_gc_get_ctx(ui->cgc);
240
241 if (params->placement == ui_wnd_place_full_screen) {
242 /* Make window the size of the screen */
243 gfx_rect_dims(&ui->rect, &scr_dims);
244 gfx_coord2_add(&dparams.rect.p0, &scr_dims,
245 &dparams.rect.p1);
246 (void) console_set_caption(ui->console,
247 params->caption);
248 }
249 } else {
250 /* Needed for unit tests */
251 rc = dummygc_create(&dgc);
252 if (rc != EOK)
253 goto error;
254
255 gc = dummygc_get_ctx(dgc);
256 }
257
258#ifdef CONFIG_UI_CS_RENDER
259 /* Create window bitmap */
260 gfx_bitmap_params_init(&bparams);
261#ifndef CONFIG_WIN_DOUBLE_BUF
262 /* Console does not support direct output */
263 if (ui->display != NULL)
264 bparams.flags |= bmpf_direct_output;
265#endif
266
267 /* Move rectangle so that top-left corner is 0,0 */
268 gfx_rect_rtranslate(&dparams.rect.p0, &dparams.rect, &bparams.rect);
269
270 rc = gfx_bitmap_create(gc, &bparams, NULL, &bmp);
271 if (rc != EOK)
272 goto error;
273
274 /* Create memory GC */
275 rc = gfx_bitmap_get_alloc(bmp, &alloc);
276 if (rc != EOK) {
277 gfx_bitmap_destroy(window->app_bmp);
278 return rc;
279 }
280
281 rc = mem_gc_create(&bparams.rect, &alloc, &ui_window_mem_gc_cb,
282 (void *) window, &memgc);
283 if (rc != EOK) {
284 gfx_bitmap_destroy(window->app_bmp);
285 return rc;
286 }
287
288 window->bmp = bmp;
289 window->mgc = memgc;
290 window->gc = mem_gc_get_ctx(memgc);
291 window->realgc = gc;
292 (void) off;
293#else
294 /* Server-side rendering */
295
296 /* Full-screen mode? */
297 if (ui->display == NULL) {
298 /* Create translating GC to translate window contents */
299 off.x = 0;
300 off.y = 0;
301 rc = xlate_gc_create(&off, gc, &xgc);
302 if (rc != EOK)
303 goto error;
304
305 window->xgc = xgc;
306 window->gc = xlate_gc_get_ctx(xgc);
307 window->realgc = gc;
308 } else {
309 window->gc = gc;
310 }
311
312 (void) ui_window_mem_gc_cb;
313 (void) alloc;
314 (void) bparams;
315#endif
316 if (ui->display == NULL) {
317 ui_window_place(window, &ui->rect, params, &window->dpos);
318
319 if (window->xgc != NULL)
320 xlate_gc_set_off(window->xgc, &window->dpos);
321 }
322
323 rc = ui_resource_create(window->gc, ui_is_textmode(ui), &res);
324 if (rc != EOK)
325 goto error;
326
327 rc = ui_wdecor_create(res, params->caption, params->style, &wdecor);
328 if (rc != EOK)
329 goto error;
330
331 ui_wdecor_set_rect(wdecor, &dparams.rect);
332 ui_wdecor_set_cb(wdecor, &wdecor_cb, (void *) window);
333 ui_wdecor_paint(wdecor);
334
335 ui_resource_set_expose_cb(res, ui_window_expose_cb, (void *) window);
336
337 window->rect = dparams.rect;
338 window->res = res;
339 window->wdecor = wdecor;
340 window->cursor = ui_curs_arrow;
341 window->placement = params->placement;
342 *rwindow = window;
343
344 list_append(&window->lwindows, &ui->windows);
345 return EOK;
346error:
347 if (wdecor != NULL)
348 ui_wdecor_destroy(wdecor);
349 if (res != NULL)
350 ui_resource_destroy(res);
351 if (memgc != NULL)
352 mem_gc_delete(memgc);
353 if (xgc != NULL)
354 xlate_gc_delete(xgc);
355 if (bmp != NULL)
356 gfx_bitmap_destroy(bmp);
357 if (dgc != NULL)
358 dummygc_destroy(dgc);
359 free(window);
360 return rc;
361}
362
363/** Destroy window.
364 *
365 * @param window Window or @c NULL
366 */
367void ui_window_destroy(ui_window_t *window)
368{
369 ui_t *ui;
370
371 if (window == NULL)
372 return;
373
374 ui = window->ui;
375
376 list_remove(&window->lwindows);
377 ui_control_destroy(window->control);
378 ui_wdecor_destroy(window->wdecor);
379 ui_resource_destroy(window->res);
380 if (window->app_mgc != NULL)
381 mem_gc_delete(window->app_mgc);
382 if (window->app_bmp != NULL)
383 gfx_bitmap_destroy(window->app_bmp);
384 if (window->mgc != NULL) {
385 mem_gc_delete(window->mgc);
386 window->gc = NULL;
387 }
388 if (window->bmp != NULL)
389 gfx_bitmap_destroy(window->bmp);
390 if (window->dwindow != NULL)
391 display_window_destroy(window->dwindow);
392
393 /* Need to repaint if windows are emulated */
394 if (ui_is_fullscreen(ui)) {
395 ui_paint(ui);
396 }
397
398 if (ui->console != NULL &&
399 window->placement == ui_wnd_place_full_screen) {
400 (void) console_set_caption(ui->console, "");
401 }
402
403 free(window);
404}
405
406/** Add control to window.
407 *
408 * Only one control can be added to a window. If more than one control
409 * is added, the results are undefined.
410 *
411 * @param window Window
412 * @param control Control
413 * @return EOK on success, ENOMEM if out of memory
414 */
415void ui_window_add(ui_window_t *window, ui_control_t *control)
416{
417 assert(window->control == NULL);
418
419 window->control = control;
420 control->elemp = (void *) window;
421}
422
423/** Remove control from window.
424 *
425 * @param window Window
426 * @param control Control
427 */
428void ui_window_remove(ui_window_t *window, ui_control_t *control)
429{
430 assert(window->control == control);
431 assert((ui_window_t *) control->elemp == window);
432
433 window->control = NULL;
434 control->elemp = NULL;
435}
436
437/** Get active window (only valid in fullscreen mode).
438 *
439 * @param ui User interface
440 * @return Active window
441 */
442ui_window_t *ui_window_get_active(ui_t *ui)
443{
444 link_t *link;
445
446 link = list_last(&ui->windows);
447 if (link == NULL)
448 return NULL;
449
450 return list_get_instance(link, ui_window_t, lwindows);
451}
452
453/** Resize or (un)maximize window.
454 *
455 * @param window Window
456 * @param rect Rectangle
457 * @param scop Size change operation
458 *
459 * @return EOK on success or an error code
460 */
461errno_t ui_window_size_change(ui_window_t *window, gfx_rect_t *rect,
462 ui_wnd_sc_op_t scop)
463{
464 gfx_coord2_t offs;
465 gfx_rect_t nrect;
466 gfx_rect_t arect;
467 gfx_bitmap_t *app_bmp = NULL;
468 gfx_bitmap_t *win_bmp = NULL;
469 gfx_bitmap_params_t app_params;
470 gfx_bitmap_params_t win_params;
471 gfx_bitmap_alloc_t app_alloc;
472 gfx_bitmap_alloc_t win_alloc;
473 errno_t rc;
474
475 /*
476 * Move rect so that p0=0,0 - keep window's coordinate system origin
477 * locked to top-left corner of the window.
478 */
479 offs = rect->p0;
480 gfx_rect_rtranslate(&offs, rect, &nrect);
481
482 /* mgc != NULL iff client-side rendering */
483 if (window->mgc != NULL) {
484#ifdef CONFIG_WIN_DOUBLE_BUF
485 /*
486 * Create new window bitmap in advance. If direct mapping,
487 * will need do it after resizing the window.
488 */
489 assert(window->bmp != NULL);
490 gfx_bitmap_params_init(&win_params);
491 win_params.rect = nrect;
492
493 rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
494 &win_bmp);
495 if (rc != EOK)
496 goto error;
497
498 rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
499 if (rc != EOK)
500 goto error;
501#endif
502 }
503
504 /* Application area GC? */
505 if (window->app_gc != NULL) {
506 /* Resize application bitmap */
507 assert(window->app_bmp != NULL);
508
509 gfx_bitmap_params_init(&app_params);
510
511 /*
512 * The bitmap will have the same dimensions as the
513 * application rectangle, but start at 0,0.
514 */
515 ui_wdecor_app_from_rect(window->wdecor->style, &nrect, &arect);
516 gfx_rect_rtranslate(&arect.p0, &arect, &app_params.rect);
517
518 rc = gfx_bitmap_create(window->gc, &app_params, NULL,
519 &app_bmp);
520 if (rc != EOK)
521 goto error;
522
523 rc = gfx_bitmap_get_alloc(app_bmp, &app_alloc);
524 if (rc != EOK)
525 goto error;
526 }
527
528 /* dwindow can be NULL in case of unit tests or fullscreen mode */
529 if (window->dwindow != NULL) {
530 switch (scop) {
531 case ui_wsc_resize:
532 rc = display_window_resize(window->dwindow, &offs,
533 &nrect);
534 if (rc != EOK)
535 goto error;
536 break;
537 case ui_wsc_maximize:
538 rc = display_window_maximize(window->dwindow);
539 if (rc != EOK)
540 goto error;
541 break;
542 case ui_wsc_unmaximize:
543 rc = display_window_unmaximize(window->dwindow);
544 if (rc != EOK)
545 goto error;
546 break;
547 }
548 }
549
550 /* Client side rendering? */
551 if (window->mgc != NULL) {
552#ifndef CONFIG_WIN_DOUBLE_BUF
553 /* Window is resized, now we can map the window bitmap again */
554 gfx_bitmap_params_init(&win_params);
555 win_params.flags |= bmpf_direct_output;
556 win_params.rect = nrect;
557
558 rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
559 &win_bmp);
560 if (rc != EOK)
561 goto error;
562
563 rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
564 if (rc != EOK)
565 goto error;
566#endif
567 mem_gc_retarget(window->mgc, &win_params.rect, &win_alloc);
568
569 gfx_bitmap_destroy(window->bmp);
570 window->bmp = win_bmp;
571 }
572
573 window->rect = nrect;
574 ui_wdecor_set_rect(window->wdecor, &nrect);
575 ui_wdecor_paint(window->wdecor);
576 gfx_update(window->gc);
577
578 /* Application area GC? */
579 if (window->app_gc != NULL) {
580 mem_gc_retarget(window->app_mgc, &app_params.rect, &app_alloc);
581
582 gfx_bitmap_destroy(window->app_bmp);
583 window->app_bmp = app_bmp;
584 }
585
586 return EOK;
587error:
588 if (app_bmp != NULL)
589 gfx_bitmap_destroy(app_bmp);
590 if (win_bmp != NULL)
591 gfx_bitmap_destroy(win_bmp);
592 return rc;
593}
594
595/** Resize/move window.
596 *
597 * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
598 * the top-left corner of the window will move on the screen accordingly.
599 *
600 * @param window Window
601 * @param rect Rectangle
602 *
603 * @return EOK on success or an error code
604 */
605errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
606{
607 return ui_window_size_change(window, rect, ui_wsc_resize);
608}
609
610/** Set window callbacks.
611 *
612 * @param window Window
613 * @param cb Window callbacks
614 * @param arg Callback argument
615 */
616void ui_window_set_cb(ui_window_t *window, ui_window_cb_t *cb, void *arg)
617{
618 window->cb = cb;
619 window->arg = arg;
620}
621
622/** Change window caption.
623 *
624 * @param window Window
625 * @param caption New caption
626 *
627 * @return EOK on success or an error code
628 */
629errno_t ui_window_set_caption(ui_window_t *window, const char *caption)
630{
631 return ui_wdecor_set_caption(window->wdecor, caption);
632}
633
634/** Get window's containing UI.
635 *
636 * @param window Window
637 * @return Containing UI
638 */
639ui_t *ui_window_get_ui(ui_window_t *window)
640{
641 return window->ui;
642}
643
644/** Get UI resource from window.
645 *
646 * @param window Window
647 * @return UI resource
648 */
649ui_resource_t *ui_window_get_res(ui_window_t *window)
650{
651 return window->res;
652}
653
654/** Get window GC.
655 *
656 * @param window Window
657 * @return GC (relative to window)
658 */
659gfx_context_t *ui_window_get_gc(ui_window_t *window)
660{
661 return window->gc;
662}
663
664/** Get window position.
665 *
666 * @param window Window
667 * @param pos Place to store position
668 * @return EOK on success or an error code
669 */
670errno_t ui_window_get_pos(ui_window_t *window, gfx_coord2_t *pos)
671{
672 errno_t rc;
673
674 if (window->dwindow != NULL) {
675 rc = display_window_get_pos(window->dwindow, pos);
676 if (rc != EOK)
677 return rc;
678 } else {
679 *pos = window->dpos;
680 }
681
682 return EOK;
683}
684
685/** Get window application area GC
686 *
687 * @param window Window
688 * @param rgc Place to store GC (relative to application area)
689 * @return EOK on success or an error code
690 */
691errno_t ui_window_get_app_gc(ui_window_t *window, gfx_context_t **rgc)
692{
693 gfx_bitmap_params_t params;
694 gfx_bitmap_alloc_t alloc;
695 gfx_rect_t rect;
696 mem_gc_t *memgc;
697 errno_t rc;
698
699 if (window->app_gc == NULL) {
700 assert(window->app_bmp == NULL);
701
702 gfx_bitmap_params_init(&params);
703
704 /*
705 * The bitmap will have the same dimensions as the
706 * application rectangle, but start at 0,0.
707 */
708 ui_window_get_app_rect(window, &rect);
709 gfx_rect_rtranslate(&rect.p0, &rect, &params.rect);
710
711 rc = gfx_bitmap_create(window->gc, &params, NULL,
712 &window->app_bmp);
713 if (rc != EOK)
714 return rc;
715
716 rc = gfx_bitmap_get_alloc(window->app_bmp, &alloc);
717 if (rc != EOK) {
718 gfx_bitmap_destroy(window->app_bmp);
719 return rc;
720 }
721
722 rc = mem_gc_create(&params.rect, &alloc,
723 &ui_window_app_mem_gc_cb, (void *) window, &memgc);
724 if (rc != EOK) {
725 gfx_bitmap_destroy(window->app_bmp);
726 return rc;
727 }
728
729 window->app_mgc = memgc;
730 window->app_gc = mem_gc_get_ctx(memgc);
731 }
732
733 *rgc = window->app_gc;
734 return EOK;
735}
736
737/** Get window application rectangle
738 *
739 * @param window Window
740 * @param rect Place to store application rectangle
741 */
742void ui_window_get_app_rect(ui_window_t *window, gfx_rect_t *rect)
743{
744 ui_wdecor_geom_t geom;
745
746 ui_wdecor_get_geom(window->wdecor, &geom);
747 *rect = geom.app_area_rect;
748}
749
750/** Set cursor when pointer is hovering over a control.
751 *
752 * @param window Window
753 * @param cursor Cursor
754 */
755void ui_window_set_ctl_cursor(ui_window_t *window, ui_stock_cursor_t cursor)
756{
757 display_stock_cursor_t dcursor;
758
759 dcursor = wnd_dcursor_from_cursor(cursor);
760
761 if (window->dwindow != NULL)
762 (void) display_window_set_cursor(window->dwindow, dcursor);
763}
764
765/** Paint window
766 *
767 * @param window Window
768 * @return EOK on success or an error code
769 */
770errno_t ui_window_paint(ui_window_t *window)
771{
772 return ui_window_send_paint(window);
773}
774
775/** Handle window close event. */
776static void dwnd_close_event(void *arg)
777{
778 ui_window_t *window = (ui_window_t *) arg;
779 ui_t *ui = window->ui;
780
781 ui_lock(ui);
782 ui_window_send_close(window);
783 ui_unlock(ui);
784}
785
786/** Handle window focus event. */
787static void dwnd_focus_event(void *arg)
788{
789 ui_window_t *window = (ui_window_t *) arg;
790 ui_t *ui = window->ui;
791
792 ui_lock(ui);
793
794 if (window->wdecor != NULL) {
795 ui_wdecor_set_active(window->wdecor, true);
796 ui_wdecor_paint(window->wdecor);
797 }
798
799 ui_window_send_focus(window);
800 ui_unlock(ui);
801}
802
803/** Handle window keyboard event */
804static void dwnd_kbd_event(void *arg, kbd_event_t *kbd_event)
805{
806 ui_window_t *window = (ui_window_t *) arg;
807 ui_t *ui = window->ui;
808
809 ui_lock(ui);
810 ui_window_send_kbd(window, kbd_event);
811 ui_unlock(ui);
812}
813
814/** Handle window position event */
815static void dwnd_pos_event(void *arg, pos_event_t *event)
816{
817 ui_window_t *window = (ui_window_t *) arg;
818 ui_t *ui = window->ui;
819 ui_evclaim_t claim;
820
821 /* Make sure we don't process events until fully initialized */
822 if (window->wdecor == NULL)
823 return;
824
825 ui_lock(ui);
826
827 claim = ui_wdecor_pos_event(window->wdecor, event);
828 if (claim == ui_claimed) {
829 ui_unlock(ui);
830 return;
831 }
832
833 ui_window_send_pos(window, event);
834 ui_unlock(ui);
835}
836
837/** Handle window resize event */
838static void dwnd_resize_event(void *arg, gfx_rect_t *rect)
839{
840 ui_window_t *window = (ui_window_t *) arg;
841 ui_t *ui = window->ui;
842
843 /* Make sure we don't process events until fully initialized */
844 if (window->wdecor == NULL)
845 return;
846
847 if ((window->wdecor->style & ui_wds_resizable) == 0)
848 return;
849
850 ui_lock(ui);
851 (void) ui_window_resize(window, rect);
852 (void) ui_window_paint(window);
853 ui_unlock(ui);
854}
855
856/** Handle window unfocus event. */
857static void dwnd_unfocus_event(void *arg)
858{
859 ui_window_t *window = (ui_window_t *) arg;
860 ui_t *ui = window->ui;
861
862 ui_lock(ui);
863
864 if (window->wdecor != NULL) {
865 ui_wdecor_set_active(window->wdecor, false);
866 ui_wdecor_paint(window->wdecor);
867 }
868
869 ui_window_send_unfocus(window);
870 ui_unlock(ui);
871}
872
873/** Window decoration requested window maximization.
874 *
875 * @param wdecor Window decoration
876 * @param arg Argument (window)
877 */
878static void wd_maximize(ui_wdecor_t *wdecor, void *arg)
879{
880 ui_window_t *window = (ui_window_t *) arg;
881
882 ui_window_send_maximize(window);
883}
884
885/** Window decoration requested window unmaximization.
886 *
887 * @param wdecor Window decoration
888 * @param arg Argument (window)
889 */
890static void wd_unmaximize(ui_wdecor_t *wdecor, void *arg)
891{
892 ui_window_t *window = (ui_window_t *) arg;
893
894 ui_window_send_unmaximize(window);
895}
896
897/** Window decoration requested window closure.
898 *
899 * @param wdecor Window decoration
900 * @param arg Argument (window)
901 */
902static void wd_close(ui_wdecor_t *wdecor, void *arg)
903{
904 ui_window_t *window = (ui_window_t *) arg;
905
906 ui_window_send_close(window);
907}
908
909/** Window decoration requested window move.
910 *
911 * @param wdecor Window decoration
912 * @param arg Argument (window)
913 * @param pos Position where the title bar was pressed
914 */
915static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos)
916{
917 ui_window_t *window = (ui_window_t *) arg;
918
919 if (window->dwindow != NULL)
920 (void) display_window_move_req(window->dwindow, pos);
921}
922
923/** Window decoration requested window resize.
924 *
925 * @param wdecor Window decoration
926 * @param arg Argument (window)
927 * @param rsztype Resize type
928 * @param pos Position where the button was pressed
929 */
930static void wd_resize(ui_wdecor_t *wdecor, void *arg,
931 ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos)
932{
933 ui_window_t *window = (ui_window_t *) arg;
934
935 if (window->dwindow != NULL)
936 (void) display_window_resize_req(window->dwindow, rsztype, pos);
937}
938
939/** Get display stock cursor from UI stock cursor.
940 *
941 * @param cursor UI stock cursor
942 * @return Display stock cursor
943 */
944display_stock_cursor_t wnd_dcursor_from_cursor(ui_stock_cursor_t cursor)
945{
946 display_stock_cursor_t dcursor;
947
948 dcursor = dcurs_arrow;
949
950 switch (cursor) {
951 case ui_curs_arrow:
952 dcursor = dcurs_arrow;
953 break;
954 case ui_curs_size_ud:
955 dcursor = dcurs_size_ud;
956 break;
957 case ui_curs_size_lr:
958 dcursor = dcurs_size_lr;
959 break;
960 case ui_curs_size_uldr:
961 dcursor = dcurs_size_uldr;
962 break;
963 case ui_curs_size_urdl:
964 dcursor = dcurs_size_urdl;
965 break;
966 case ui_curs_ibeam:
967 dcursor = dcurs_ibeam;
968 break;
969 }
970
971 return dcursor;
972}
973
974/** Window decoration requested changing cursor.
975 *
976 * @param wdecor Window decoration
977 * @param arg Argument (window)
978 * @param cursor Cursor to set
979 */
980static void wd_set_cursor(ui_wdecor_t *wdecor, void *arg,
981 ui_stock_cursor_t cursor)
982{
983 ui_window_t *window = (ui_window_t *) arg;
984 display_stock_cursor_t dcursor;
985
986 if (cursor == window->cursor)
987 return;
988
989 dcursor = wnd_dcursor_from_cursor(cursor);
990
991 if (window->dwindow != NULL)
992 (void) display_window_set_cursor(window->dwindow, dcursor);
993
994 window->cursor = cursor;
995}
996
997/** Send window maximize event.
998 *
999 * @param window Window
1000 */
1001void ui_window_send_maximize(ui_window_t *window)
1002{
1003 if (window->cb != NULL && window->cb->maximize != NULL)
1004 window->cb->maximize(window, window->arg);
1005 else
1006 ui_window_def_maximize(window);
1007}
1008
1009/** Send window unmaximize event.
1010 *
1011 * @param window Window
1012 */
1013void ui_window_send_unmaximize(ui_window_t *window)
1014{
1015 if (window->cb != NULL && window->cb->unmaximize != NULL)
1016 window->cb->unmaximize(window, window->arg);
1017 else
1018 ui_window_def_unmaximize(window);
1019}
1020
1021/** Send window close event.
1022 *
1023 * @param window Window
1024 */
1025void ui_window_send_close(ui_window_t *window)
1026{
1027 if (window->cb != NULL && window->cb->close != NULL)
1028 window->cb->close(window, window->arg);
1029}
1030
1031/** Send window focus event.
1032 *
1033 * @param window Window
1034 */
1035void ui_window_send_focus(ui_window_t *window)
1036{
1037 if (window->cb != NULL && window->cb->focus != NULL)
1038 window->cb->focus(window, window->arg);
1039}
1040
1041/** Send window keyboard event.
1042 *
1043 * @param window Window
1044 */
1045void ui_window_send_kbd(ui_window_t *window, kbd_event_t *kbd)
1046{
1047 if (window->cb != NULL && window->cb->kbd != NULL)
1048 window->cb->kbd(window, window->arg, kbd);
1049 else
1050 ui_window_def_kbd(window, kbd);
1051}
1052
1053/** Send window paint event.
1054 *
1055 * @param window Window
1056 */
1057errno_t ui_window_send_paint(ui_window_t *window)
1058{
1059 if (window->cb != NULL && window->cb->paint != NULL)
1060 return window->cb->paint(window, window->arg);
1061 else
1062 return ui_window_def_paint(window);
1063}
1064
1065/** Send window position event.
1066 *
1067 * @param window Window
1068 */
1069void ui_window_send_pos(ui_window_t *window, pos_event_t *pos)
1070{
1071 if (window->cb != NULL && window->cb->pos != NULL)
1072 window->cb->pos(window, window->arg, pos);
1073 else
1074 ui_window_def_pos(window, pos);
1075}
1076
1077/** Send window unfocus event.
1078 *
1079 * @param window Window
1080 */
1081void ui_window_send_unfocus(ui_window_t *window)
1082{
1083 if (window->cb != NULL && window->cb->unfocus != NULL)
1084 window->cb->unfocus(window, window->arg);
1085 else
1086 return ui_window_def_unfocus(window);
1087}
1088
1089/** Default window maximize routine.
1090 *
1091 * @param window Window
1092 * @return EOK on success or an error code
1093 */
1094errno_t ui_window_def_maximize(ui_window_t *window)
1095{
1096 errno_t rc;
1097 gfx_rect_t old_rect;
1098 gfx_rect_t rect;
1099
1100 old_rect = window->rect;
1101
1102 if (window->dwindow != NULL) {
1103 rc = display_window_get_max_rect(window->dwindow, &rect);
1104 if (rc != EOK)
1105 return rc;
1106 } else {
1107 rect = window->ui->rect;
1108 }
1109
1110 ui_wdecor_set_maximized(window->wdecor, true);
1111
1112 rc = ui_window_size_change(window, &rect, ui_wsc_maximize);
1113 if (rc != EOK) {
1114 ui_wdecor_set_maximized(window->wdecor, false);
1115 return rc;
1116 }
1117
1118 window->normal_rect = old_rect;
1119 (void) ui_window_paint(window);
1120 return EOK;
1121}
1122
1123/** Default window unmaximize routine.
1124 *
1125 * @param window Window
1126 * @return EOK on success or an error code
1127 */
1128errno_t ui_window_def_unmaximize(ui_window_t *window)
1129{
1130 errno_t rc;
1131
1132 ui_wdecor_set_maximized(window->wdecor, false);
1133
1134 rc = ui_window_size_change(window, &window->normal_rect,
1135 ui_wsc_unmaximize);
1136 if (rc != EOK) {
1137 ui_wdecor_set_maximized(window->wdecor, true);
1138 printf("ui_window_size_change->error\n");
1139 return rc;
1140 }
1141
1142 (void) ui_window_paint(window);
1143 return EOK;
1144}
1145
1146/** Default window keyboard event routine.
1147 *
1148 * @param window Window
1149 * @return ui_claimed iff event was claimed
1150 */
1151ui_evclaim_t ui_window_def_kbd(ui_window_t *window, kbd_event_t *kbd)
1152{
1153 if (window->control != NULL)
1154 return ui_control_kbd_event(window->control, kbd);
1155
1156 return ui_unclaimed;
1157}
1158
1159/** Default window paint routine.
1160 *
1161 * @param window Window
1162 * @return EOK on success or an error code
1163 */
1164errno_t ui_window_def_paint(ui_window_t *window)
1165{
1166 gfx_rect_t app_rect;
1167 errno_t rc;
1168
1169 rc = gfx_set_color(window->gc, window->res->wnd_face_color);
1170 if (rc != EOK)
1171 return rc;
1172
1173 ui_window_get_app_rect(window, &app_rect);
1174
1175 rc = gfx_fill_rect(window->gc, &app_rect);
1176 if (rc != EOK)
1177 return rc;
1178
1179 if (window->control != NULL)
1180 return ui_control_paint(window->control);
1181
1182 rc = gfx_update(window->res->gc);
1183 if (rc != EOK)
1184 return rc;
1185
1186 return EOK;
1187}
1188
1189/** Default window position event routine.
1190 *
1191 * @param window Window
1192 */
1193void ui_window_def_pos(ui_window_t *window, pos_event_t *pos)
1194{
1195 if (window->control != NULL)
1196 ui_control_pos_event(window->control, pos);
1197}
1198
1199/** Default window unfocus routine.
1200 *
1201 * @param window Window
1202 * @return EOK on success or an error code
1203 */
1204void ui_window_def_unfocus(ui_window_t *window)
1205{
1206 if (window->control != NULL)
1207 ui_control_unfocus(window->control);
1208}
1209
1210/** Window invalidate callback
1211 *
1212 * @param arg Argument (ui_window_t *)
1213 * @param rect Rectangle to update
1214 */
1215static void ui_window_invalidate(void *arg, gfx_rect_t *rect)
1216{
1217 ui_window_t *window = (ui_window_t *) arg;
1218 gfx_rect_t env;
1219
1220 gfx_rect_envelope(&window->dirty_rect, rect, &env);
1221 window->dirty_rect = env;
1222}
1223
1224/** Window update callback
1225 *
1226 * @param arg Argument (ui_window_t *)
1227 */
1228static void ui_window_update(void *arg)
1229{
1230 ui_window_t *window = (ui_window_t *) arg;
1231
1232 if (!gfx_rect_is_empty(&window->dirty_rect)) {
1233 (void) gfx_bitmap_render(window->bmp, &window->dirty_rect,
1234 &window->dpos);
1235 }
1236
1237 window->dirty_rect.p0.x = 0;
1238 window->dirty_rect.p0.y = 0;
1239 window->dirty_rect.p1.x = 0;
1240 window->dirty_rect.p1.y = 0;
1241}
1242
1243/** Window cursor get position callback
1244 *
1245 * @param arg Argument (ui_window_t *)
1246 * @param pos Place to store position
1247 */
1248static errno_t ui_window_cursor_get_pos(void *arg, gfx_coord2_t *pos)
1249{
1250 ui_window_t *window = (ui_window_t *) arg;
1251 gfx_coord2_t cpos;
1252 errno_t rc;
1253
1254 rc = gfx_cursor_get_pos(window->realgc, &cpos);
1255 if (rc != EOK)
1256 return rc;
1257
1258 pos->x = cpos.x - window->dpos.x;
1259 pos->y = cpos.y - window->dpos.y;
1260 return EOK;
1261}
1262
1263/** Window cursor set position callback
1264 *
1265 * @param arg Argument (ui_window_t *)
1266 * @param pos New position
1267 */
1268static errno_t ui_window_cursor_set_pos(void *arg, gfx_coord2_t *pos)
1269{
1270 ui_window_t *window = (ui_window_t *) arg;
1271 gfx_coord2_t cpos;
1272
1273 cpos.x = pos->x + window->dpos.x;
1274 cpos.y = pos->y + window->dpos.y;
1275
1276 return gfx_cursor_set_pos(window->realgc, &cpos);
1277}
1278
1279/** Window cursor set visibility callback
1280 *
1281 * @param arg Argument (ui_window_t *)
1282 * @param visible @c true iff cursor is to be made visible
1283 */
1284static errno_t ui_window_cursor_set_visible(void *arg, bool visible)
1285{
1286 ui_window_t *window = (ui_window_t *) arg;
1287
1288 return gfx_cursor_set_visible(window->realgc, visible);
1289}
1290
1291/** Application area invalidate callback
1292 *
1293 * @param arg Argument (ui_window_t *)
1294 * @param rect Rectangle to update
1295 */
1296static void ui_window_app_invalidate(void *arg, gfx_rect_t *rect)
1297{
1298 ui_window_t *window = (ui_window_t *) arg;
1299 gfx_rect_t arect;
1300
1301 ui_window_get_app_rect(window, &arect);
1302
1303 /* Render bitmap rectangle inside the application area */
1304 (void) gfx_bitmap_render(window->app_bmp, rect, &arect.p0);
1305 /*
1306 * TODO Update applications to call gfx_update(), then
1307 * we can defer update to ui_window_app_update().
1308 */
1309 (void) gfx_update(window->res->gc);
1310}
1311
1312/** Application area update callback
1313 *
1314 * @param arg Argument (ui_window_t *)
1315 */
1316static void ui_window_app_update(void *arg)
1317{
1318 ui_window_t *window = (ui_window_t *) arg;
1319
1320 /*
1321 * Not used since display is updated immediately
1322 * in ui_window_app_invalidate
1323 */
1324 (void) window;
1325}
1326
1327/** Window expose callback. */
1328static void ui_window_expose_cb(void *arg)
1329{
1330 ui_window_t *window = (ui_window_t *) arg;
1331
1332 ui_window_paint(window);
1333}
1334
1335/** @}
1336 */
Note: See TracBrowser for help on using the repository browser.