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

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

Prevent task bar from being listed in task bar

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