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

serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 90f1f19 was 90f1f19, checked in by jxsvoboda <5887334+jxsvoboda@…>, 4 years ago

Allow setting initial window position (instead of moving the window)

To reduce display artifacts. We can create the menu popup windows
in the correct place from the start. The same goes for regular
windows with specific placement.

  • Property mode set to 100644
File size: 23.6 KB
RevLine 
[f7a90df]1/*
[2ab8ab3]2 * Copyright (c) 2021 Jiri Svoboda
[f7a90df]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
[77ffa01]36#include <congfx/console.h>
[f7a90df]37#include <display.h>
38#include <errno.h>
[66a2becf]39#include <gfx/bitmap.h>
[f7a90df]40#include <gfx/context.h>
[fa01c05]41#include <gfx/render.h>
[f03d1308]42#include <io/kbd_event.h>
[d284ce9]43#include <io/pos_event.h>
[f7a90df]44#include <mem.h>
[66a2becf]45#include <memgfx/memgc.h>
[f7a90df]46#include <stdlib.h>
[b71c0fc]47#include <ui/control.h>
[f7a90df]48#include <ui/resource.h>
[9c7dc8e]49#include <ui/ui.h>
[f7a90df]50#include <ui/wdecor.h>
51#include <ui/window.h>
[b71c0fc]52#include "../private/control.h"
[f7a90df]53#include "../private/dummygc.h"
[fa01c05]54#include "../private/resource.h"
[f7a90df]55#include "../private/ui.h"
[d284ce9]56#include "../private/wdecor.h"
[f7a90df]57#include "../private/window.h"
58
[d284ce9]59static void dwnd_close_event(void *);
60static void dwnd_focus_event(void *);
61static void dwnd_kbd_event(void *, kbd_event_t *);
62static void dwnd_pos_event(void *, pos_event_t *);
[2d879f7]63static void dwnd_resize_event(void *, gfx_rect_t *);
[d284ce9]64static void dwnd_unfocus_event(void *);
65
66static display_wnd_cb_t dwnd_cb = {
67 .close_event = dwnd_close_event,
68 .focus_event = dwnd_focus_event,
69 .kbd_event = dwnd_kbd_event,
70 .pos_event = dwnd_pos_event,
[2d879f7]71 .resize_event = dwnd_resize_event,
[d284ce9]72 .unfocus_event = dwnd_unfocus_event
73};
74
75static void wd_close(ui_wdecor_t *, void *);
76static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *);
[2d879f7]77static void wd_resize(ui_wdecor_t *, void *, ui_wdecor_rsztype_t,
78 gfx_coord2_t *);
79static void wd_set_cursor(ui_wdecor_t *, void *, ui_stock_cursor_t);
[d284ce9]80
81static ui_wdecor_cb_t wdecor_cb = {
82 .close = wd_close,
[2d879f7]83 .move = wd_move,
84 .resize = wd_resize,
85 .set_cursor = wd_set_cursor
[d284ce9]86};
87
[2ab8ab3]88static void ui_window_invalidate(void *, gfx_rect_t *);
89static void ui_window_update(void *);
90static void ui_window_app_invalidate(void *, gfx_rect_t *);
91static void ui_window_app_update(void *);
[214aefb]92static void ui_window_expose_cb(void *);
[66a2becf]93
[f7a90df]94/** Initialize window parameters structure.
95 *
96 * Window parameters structure must always be initialized using this function
[266ec54]97 * first. By default, the window will be decorated. To get a non-decorated
98 * window, one needs to clear ui_wds_decorated
99 * (e.g. params->style &= ~ui_wds_decorated).
[f7a90df]100 *
101 * @param params Window parameters structure
102 */
[d284ce9]103void ui_wnd_params_init(ui_wnd_params_t *params)
[f7a90df]104{
[d284ce9]105 memset(params, 0, sizeof(ui_wnd_params_t));
[266ec54]106
107 /* Make window decorated by default. */
108 params->style = ui_wds_decorated;
[f7a90df]109}
110
[90f1f19]111/** Compute where window should be placed on the screen.
112 *
113 * This only applies to windows that do not use default placement.
114 *
115 * @param window Window
116 * @param display Display
117 * @param info Display info
118 * @param params Window parameters
119 * @param pos Place to store position of top-left corner
120 */
121static void ui_window_place(ui_window_t *window, display_t *display,
122 display_info_t *info, ui_wnd_params_t *params, gfx_coord2_t *pos)
[c9927c66]123{
124 assert(params->placement != ui_wnd_place_default);
125
[90f1f19]126 pos->x = 0;
127 pos->y = 0;
128
[c9927c66]129 switch (params->placement) {
130 case ui_wnd_place_default:
131 assert(false);
132 case ui_wnd_place_top_left:
133 case ui_wnd_place_full_screen:
[90f1f19]134 pos->x = info->rect.p0.x - params->rect.p0.x;
135 pos->y = info->rect.p0.y - params->rect.p0.y;
[c9927c66]136 break;
137 case ui_wnd_place_top_right:
[90f1f19]138 pos->x = info->rect.p1.x - params->rect.p1.x;
139 pos->y = info->rect.p0.y - params->rect.p0.y;
[c9927c66]140 break;
141 case ui_wnd_place_bottom_left:
[90f1f19]142 pos->x = info->rect.p0.x - params->rect.p0.x;
143 pos->y = info->rect.p1.y - params->rect.p1.y;
[c9927c66]144 break;
145 case ui_wnd_place_bottom_right:
[90f1f19]146 pos->x = info->rect.p1.x - params->rect.p1.x;
147 pos->y = info->rect.p1.y - params->rect.p1.y;
[c9927c66]148 break;
149 case ui_wnd_place_popup:
150 /* Place popup window below parent rectangle */
[90f1f19]151 pos->x = params->prect.p0.x;
152 pos->y = params->prect.p1.y;
[c9927c66]153 break;
154 }
155}
156
[f7a90df]157/** Create new window.
158 *
159 * @param ui User interface
160 * @param params Window parameters
161 * @param rwindow Place to store pointer to new window
162 * @return EOK on success or an error code
163 */
[d284ce9]164errno_t ui_window_create(ui_t *ui, ui_wnd_params_t *params,
[f7a90df]165 ui_window_t **rwindow)
166{
167 ui_window_t *window;
[06d0c81]168 display_info_t info;
[266ec54]169 gfx_coord2_t scr_dims;
[f7a90df]170 display_wnd_params_t dparams;
171 gfx_context_t *gc = NULL;
172 ui_resource_t *res = NULL;
173 ui_wdecor_t *wdecor = NULL;
174 dummy_gc_t *dgc = NULL;
[2ab8ab3]175 gfx_bitmap_params_t bparams;
176 gfx_bitmap_alloc_t alloc;
177 gfx_bitmap_t *bmp = NULL;
178 mem_gc_t *memgc = NULL;
[f7a90df]179 errno_t rc;
180
181 window = calloc(1, sizeof(ui_window_t));
182 if (window == NULL)
183 return ENOMEM;
184
185 display_wnd_params_init(&dparams);
[d284ce9]186 dparams.rect = params->rect;
[2d879f7]187 /* Only allow making the window larger */
188 gfx_rect_dims(&params->rect, &dparams.min_size);
[f7a90df]189
[9e84d2c]190 if ((params->flags & ui_wndf_popup) != 0)
191 dparams.flags |= wndf_popup;
192
[f7a90df]193 if (ui->display != NULL) {
[266ec54]194 if (params->placement != ui_wnd_place_default) {
195 rc = display_get_info(ui->display, &info);
196 if (rc != EOK)
197 goto error;
198 }
199
200 if (params->placement == ui_wnd_place_full_screen) {
201 /* Make window the size of the screen */
202 gfx_rect_dims(&info.rect, &scr_dims);
203 gfx_coord2_add(&dparams.rect.p0, &scr_dims,
204 &dparams.rect.p1);
205 }
206
[90f1f19]207 if (params->placement != ui_wnd_place_default) {
208 /* Set initial display window position */
209 ui_window_place(window, ui->display, &info,
210 params, &dparams.pos);
211
212 dparams.flags |= wndf_setpos;
213 }
214
[d284ce9]215 rc = display_window_create(ui->display, &dparams, &dwnd_cb,
[c9927c66]216 (void *) window, &window->dwindow);
[f7a90df]217 if (rc != EOK)
218 goto error;
219
[c9927c66]220 rc = display_window_get_gc(window->dwindow, &gc);
[f7a90df]221 if (rc != EOK)
222 goto error;
[77ffa01]223 } else if (ui->console != NULL) {
[252d03c]224 gc = console_gc_get_ctx(ui->cgc);
[f7a90df]225 } else {
226 /* Needed for unit tests */
227 rc = dummygc_create(&dgc);
228 if (rc != EOK)
229 goto error;
230
231 gc = dummygc_get_ctx(dgc);
232 }
233
[2ab8ab3]234#ifdef CONFIG_UI_CS_RENDER
235 /* Create window bitmap */
236 gfx_bitmap_params_init(&bparams);
237#ifndef CONFIG_WIN_DOUBLE_BUF
[77ffa01]238 /* Console does not support direct output */
239 if (ui->display != NULL)
240 bparams.flags |= bmpf_direct_output;
[2ab8ab3]241#endif
242
243 /* Move rectangle so that top-left corner is 0,0 */
244 gfx_rect_rtranslate(&params->rect.p0, &params->rect, &bparams.rect);
245
246 rc = gfx_bitmap_create(gc, &bparams, NULL, &bmp);
247 if (rc != EOK)
248 goto error;
249
250 /* Create memory GC */
251 rc = gfx_bitmap_get_alloc(bmp, &alloc);
252 if (rc != EOK) {
253 gfx_bitmap_destroy(window->app_bmp);
254 return rc;
255 }
256
257 rc = mem_gc_create(&bparams.rect, &alloc, ui_window_invalidate,
258 ui_window_update, (void *) window, &memgc);
259 if (rc != EOK) {
260 gfx_bitmap_destroy(window->app_bmp);
261 return rc;
262 }
263
264 window->bmp = bmp;
265 window->mgc = memgc;
266 window->gc = mem_gc_get_ctx(memgc);
267 window->realgc = gc;
268#else
269 (void) ui_window_update;
270 (void) ui_window_invalidate;
271 (void) alloc;
272 (void) bparams;
273 window->gc = gc;
274#endif
[d6c4d40]275
[9c7dc8e]276 rc = ui_resource_create(window->gc, ui_is_textmode(ui), &res);
[f7a90df]277 if (rc != EOK)
278 goto error;
279
[2d879f7]280 rc = ui_wdecor_create(res, params->caption, params->style, &wdecor);
[f7a90df]281 if (rc != EOK)
282 goto error;
283
[266ec54]284 ui_wdecor_set_rect(wdecor, &dparams.rect);
[d284ce9]285 ui_wdecor_set_cb(wdecor, &wdecor_cb, (void *) window);
286 ui_wdecor_paint(wdecor);
287
[214aefb]288 ui_resource_set_expose_cb(res, ui_window_expose_cb, (void *) window);
289
[f7a90df]290 window->ui = ui;
[266ec54]291 window->rect = dparams.rect;
[2ab8ab3]292
[f7a90df]293 window->res = res;
294 window->wdecor = wdecor;
[2d879f7]295 window->cursor = ui_curs_arrow;
[f7a90df]296 *rwindow = window;
[77ffa01]297
[252d03c]298 list_append(&window->lwindows, &ui->windows);
[f7a90df]299 return EOK;
300error:
301 if (wdecor != NULL)
302 ui_wdecor_destroy(wdecor);
303 if (res != NULL)
304 ui_resource_destroy(res);
[2ab8ab3]305 if (memgc != NULL)
306 mem_gc_delete(memgc);
307 if (bmp != NULL)
308 gfx_bitmap_destroy(bmp);
[f7a90df]309 if (dgc != NULL)
310 dummygc_destroy(dgc);
311 free(window);
312 return rc;
313}
314
315/** Destroy window.
316 *
317 * @param window Window or @c NULL
318 */
319void ui_window_destroy(ui_window_t *window)
320{
[252d03c]321 ui_t *ui;
322
[f7a90df]323 if (window == NULL)
324 return;
325
[252d03c]326 ui = window->ui;
327
328 list_remove(&window->lwindows);
[b71c0fc]329 ui_control_destroy(window->control);
[f7a90df]330 ui_wdecor_destroy(window->wdecor);
331 ui_resource_destroy(window->res);
[2ab8ab3]332 if (0 && window->app_mgc != NULL)
333 mem_gc_delete(window->app_mgc);
334 if (0 && window->app_bmp != NULL)
335 gfx_bitmap_destroy(window->app_bmp);
336 if (window->mgc != NULL) {
337 mem_gc_delete(window->mgc);
338 window->gc = NULL;
339 }
340 if (window->bmp != NULL)
341 gfx_bitmap_destroy(window->bmp);
[f7a90df]342 gfx_context_delete(window->gc);
[77ffa01]343 if (window->dwindow != NULL)
344 display_window_destroy(window->dwindow);
[252d03c]345
[f7a90df]346 free(window);
[252d03c]347
348 /* Need to repaint if windows are emulated */
349 if (ui_is_fullscreen(ui)) {
350 ui_paint(ui);
351 }
[f7a90df]352}
353
[b71c0fc]354/** Add control to window.
355 *
356 * Only one control can be added to a window. If more than one control
357 * is added, the results are undefined.
358 *
[3c8c580]359 * @param window Window
[b71c0fc]360 * @param control Control
361 * @return EOK on success, ENOMEM if out of memory
362 */
363void ui_window_add(ui_window_t *window, ui_control_t *control)
364{
365 assert(window->control == NULL);
366
367 window->control = control;
368 control->elemp = (void *) window;
369}
370
371/** Remove control from window.
372 *
373 * @param window Window
374 * @param control Control
375 */
376void ui_window_remove(ui_window_t *window, ui_control_t *control)
377{
378 assert(window->control == control);
379 assert((ui_window_t *) control->elemp == window);
380
381 window->control = NULL;
382 control->elemp = NULL;
383}
384
[252d03c]385/** Get active window (only valid in fullscreen mode).
386 *
387 * @param ui User interface
388 * @return Active window
389 */
390ui_window_t *ui_window_get_active(ui_t *ui)
391{
392 link_t *link;
393
394 link = list_last(&ui->windows);
395 if (link == NULL)
396 return NULL;
397
398 return list_get_instance(link, ui_window_t, lwindows);
399}
400
[0576df9]401/** Resize/move window.
402 *
403 * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
404 * the top-left corner of the window will move on the screen accordingly.
405 *
406 * @param window Window
407 * @param rect Rectangle
408 *
409 * @return EOK on success or an error code
410 */
411errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
412{
413 gfx_coord2_t offs;
414 gfx_rect_t nrect;
[25f26600]415 gfx_rect_t arect;
416 gfx_bitmap_t *app_bmp = NULL;
[2ab8ab3]417 gfx_bitmap_t *win_bmp = NULL;
418 gfx_bitmap_params_t app_params;
419 gfx_bitmap_params_t win_params;
420 gfx_bitmap_alloc_t app_alloc;
421 gfx_bitmap_alloc_t win_alloc;
[0576df9]422 errno_t rc;
423
424 /*
425 * Move rect so that p0=0,0 - keep window's coordinate system origin
426 * locked to top-left corner of the window.
427 */
428 offs = rect->p0;
429 gfx_rect_rtranslate(&offs, rect, &nrect);
430
[2ab8ab3]431 /* mgc != NULL iff client-side rendering */
432 if (window->mgc != NULL) {
[a85d5c6]433#ifdef CONFIG_WIN_DOUBLE_BUF
434 /*
435 * Create new window bitmap in advance. If direct mapping,
436 * will need do it after resizing the window.
437 */
[2ab8ab3]438 assert(window->bmp != NULL);
439 gfx_bitmap_params_init(&win_params);
440 win_params.rect = nrect;
441
442 rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
443 &win_bmp);
444 if (rc != EOK)
445 goto error;
446
447 rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
448 if (rc != EOK)
449 goto error;
[a85d5c6]450#endif
[2ab8ab3]451 }
452
453 /* Application area GC? */
[25f26600]454 if (window->app_gc != NULL) {
[2ab8ab3]455 /* Resize application bitmap */
[25f26600]456 assert(window->app_bmp != NULL);
457
[2ab8ab3]458 gfx_bitmap_params_init(&app_params);
[25f26600]459
460 /*
461 * The bitmap will have the same dimensions as the
462 * application rectangle, but start at 0,0.
463 */
464 ui_wdecor_app_from_rect(window->wdecor->style, &nrect, &arect);
[2ab8ab3]465 gfx_rect_rtranslate(&arect.p0, &arect, &app_params.rect);
[25f26600]466
[2ab8ab3]467 rc = gfx_bitmap_create(window->gc, &app_params, NULL,
[25f26600]468 &app_bmp);
469 if (rc != EOK)
470 goto error;
471
[2ab8ab3]472 rc = gfx_bitmap_get_alloc(app_bmp, &app_alloc);
[25f26600]473 if (rc != EOK)
474 goto error;
475 }
476
[0576df9]477 /* dwindow can be NULL in case of unit tests */
478 if (window->dwindow != NULL) {
479 rc = display_window_resize(window->dwindow, &offs, &nrect);
480 if (rc != EOK)
[25f26600]481 goto error;
[0576df9]482 }
483
[a85d5c6]484 /* Client side rendering? */
[2ab8ab3]485 if (window->mgc != NULL) {
[a85d5c6]486#ifndef CONFIG_WIN_DOUBLE_BUF
487 /* Window is resized, now we can map the window bitmap again */
488 gfx_bitmap_params_init(&win_params);
489 win_params.flags |= bmpf_direct_output;
490 win_params.rect = nrect;
491
492 rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
493 &win_bmp);
494 if (rc != EOK)
495 goto error;
496
497 rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
498 if (rc != EOK)
499 goto error;
500#endif
501
[2ab8ab3]502 mem_gc_retarget(window->mgc, &win_params.rect, &win_alloc);
503
504 gfx_bitmap_destroy(window->bmp);
505 window->bmp = win_bmp;
506 }
507
[0576df9]508 ui_wdecor_set_rect(window->wdecor, &nrect);
509 ui_wdecor_paint(window->wdecor);
[2ab8ab3]510 gfx_update(window->gc);
[25f26600]511
[2ab8ab3]512 /* Application area GC? */
[25f26600]513 if (window->app_gc != NULL) {
[2ab8ab3]514 mem_gc_retarget(window->app_mgc, &app_params.rect, &app_alloc);
[25f26600]515
516 gfx_bitmap_destroy(window->app_bmp);
517 window->app_bmp = app_bmp;
518 }
519
[0576df9]520 return EOK;
[25f26600]521error:
522 if (app_bmp != NULL)
523 gfx_bitmap_destroy(app_bmp);
[2ab8ab3]524 if (win_bmp != NULL)
525 gfx_bitmap_destroy(win_bmp);
[25f26600]526 return rc;
[0576df9]527}
528
[d284ce9]529/** Set window callbacks.
530 *
531 * @param window Window
[3c8c580]532 * @param cb Window callbacks
[d284ce9]533 * @param arg Callback argument
534 */
535void ui_window_set_cb(ui_window_t *window, ui_window_cb_t *cb, void *arg)
536{
537 window->cb = cb;
538 window->arg = arg;
539}
540
[66a2becf]541/** Get UI resource from window.
542 *
543 * @param window Window
544 * @return UI resource
545 */
[3583ffb]546ui_resource_t *ui_window_get_res(ui_window_t *window)
547{
548 return window->res;
549}
550
[66a2becf]551/** Get window GC.
552 *
553 * @param window Window
554 * @return GC (relative to window)
555 */
[d284ce9]556gfx_context_t *ui_window_get_gc(ui_window_t *window)
557{
558 return window->gc;
559}
560
[c9927c66]561/** Get window position.
562 *
563 * @param window Window
564 * @param pos Place to store position
565 * @return EOK on success or an error code
566 */
567errno_t ui_window_get_pos(ui_window_t *window, gfx_coord2_t *pos)
568{
569 errno_t rc;
570
571 if (window->dwindow != NULL) {
572 rc = display_window_get_pos(window->dwindow, pos);
573 if (rc != EOK)
574 return rc;
575 } else {
576 pos->x = 0;
577 pos->y = 0;
578 }
579
580 return EOK;
581}
582
[66a2becf]583/** Get window application area GC
584 *
585 * @param window Window
586 * @param rgc Place to store GC (relative to application area)
587 * @return EOK on success or an error code
588 */
589errno_t ui_window_get_app_gc(ui_window_t *window, gfx_context_t **rgc)
590{
591 gfx_bitmap_params_t params;
592 gfx_bitmap_alloc_t alloc;
593 gfx_rect_t rect;
594 mem_gc_t *memgc;
595 errno_t rc;
596
597 if (window->app_gc == NULL) {
598 assert(window->app_bmp == NULL);
599
600 gfx_bitmap_params_init(&params);
601
602 /*
603 * The bitmap will have the same dimensions as the
604 * application rectangle, but start at 0,0.
605 */
606 ui_window_get_app_rect(window, &rect);
607 gfx_rect_rtranslate(&rect.p0, &rect, &params.rect);
608
609 rc = gfx_bitmap_create(window->gc, &params, NULL,
610 &window->app_bmp);
611 if (rc != EOK)
612 return rc;
613
614 rc = gfx_bitmap_get_alloc(window->app_bmp, &alloc);
615 if (rc != EOK) {
616 gfx_bitmap_destroy(window->app_bmp);
617 return rc;
618 }
619
[2ab8ab3]620 rc = mem_gc_create(&params.rect, &alloc, ui_window_app_invalidate,
621 ui_window_app_update, (void *) window, &memgc);
[66a2becf]622 if (rc != EOK) {
623 gfx_bitmap_destroy(window->app_bmp);
624 return rc;
625 }
626
[25f26600]627 window->app_mgc = memgc;
[66a2becf]628 window->app_gc = mem_gc_get_ctx(memgc);
629 }
630
631 *rgc = window->app_gc;
632 return EOK;
633}
634
635/** Get window application rectangle
636 *
637 * @param window Window
638 * @param rect Place to store application rectangle
639 */
[d284ce9]640void ui_window_get_app_rect(ui_window_t *window, gfx_rect_t *rect)
641{
642 ui_wdecor_geom_t geom;
643
644 ui_wdecor_get_geom(window->wdecor, &geom);
645 *rect = geom.app_area_rect;
646}
647
[66a2becf]648/** Paint window
649 *
650 * @param window Window
651 * @return EOK on success or an error code
652 */
[fa01c05]653errno_t ui_window_paint(ui_window_t *window)
654{
655 return ui_window_send_paint(window);
656}
657
[d284ce9]658/** Handle window close event. */
659static void dwnd_close_event(void *arg)
660{
661 ui_window_t *window = (ui_window_t *) arg;
662
[fa01c05]663 ui_window_send_close(window);
[d284ce9]664}
665
666/** Handle window focus event. */
667static void dwnd_focus_event(void *arg)
668{
669 ui_window_t *window = (ui_window_t *) arg;
670
671 if (window->wdecor != NULL) {
672 ui_wdecor_set_active(window->wdecor, true);
673 ui_wdecor_paint(window->wdecor);
674 }
[f03d1308]675
[fa01c05]676 ui_window_send_focus(window);
[d284ce9]677}
678
679/** Handle window keyboard event */
680static void dwnd_kbd_event(void *arg, kbd_event_t *kbd_event)
681{
682 ui_window_t *window = (ui_window_t *) arg;
683
684 (void) window;
[fa01c05]685 ui_window_send_kbd(window, kbd_event);
[d284ce9]686}
687
688/** Handle window position event */
689static void dwnd_pos_event(void *arg, pos_event_t *event)
690{
691 ui_window_t *window = (ui_window_t *) arg;
692
693 /* Make sure we don't process events until fully initialized */
694 if (window->wdecor == NULL)
695 return;
696
697 ui_wdecor_pos_event(window->wdecor, event);
[fa01c05]698 ui_window_send_pos(window, event);
[d284ce9]699}
700
[2d879f7]701/** Handle window resize event */
702static void dwnd_resize_event(void *arg, gfx_rect_t *rect)
703{
704 ui_window_t *window = (ui_window_t *) arg;
705
706 /* Make sure we don't process events until fully initialized */
707 if (window->wdecor == NULL)
708 return;
709
710 if ((window->wdecor->style & ui_wds_resizable) == 0)
711 return;
712
713 (void) ui_window_resize(window, rect);
714 (void) ui_window_paint(window);
715}
716
[d284ce9]717/** Handle window unfocus event. */
718static void dwnd_unfocus_event(void *arg)
719{
720 ui_window_t *window = (ui_window_t *) arg;
721
722 if (window->wdecor != NULL) {
723 ui_wdecor_set_active(window->wdecor, false);
724 ui_wdecor_paint(window->wdecor);
725 }
[f03d1308]726
[fa01c05]727 ui_window_send_unfocus(window);
[d284ce9]728}
729
730/** Window decoration requested window closure.
731 *
732 * @param wdecor Window decoration
[2d879f7]733 * @param arg Argument (window)
[d284ce9]734 */
735static void wd_close(ui_wdecor_t *wdecor, void *arg)
736{
737 ui_window_t *window = (ui_window_t *) arg;
738
[fa01c05]739 ui_window_send_close(window);
[d284ce9]740}
741
742/** Window decoration requested window move.
743 *
744 * @param wdecor Window decoration
[2d879f7]745 * @param arg Argument (window)
[d284ce9]746 * @param pos Position where the title bar was pressed
747 */
748static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos)
749{
750 ui_window_t *window = (ui_window_t *) arg;
751
[77ffa01]752 if (window->dwindow != NULL)
753 (void) display_window_move_req(window->dwindow, pos);
[d284ce9]754}
755
[2d879f7]756/** Window decoration requested window resize.
757 *
758 * @param wdecor Window decoration
759 * @param arg Argument (window)
760 * @param rsztype Resize type
761 * @param pos Position where the button was pressed
762 */
763static void wd_resize(ui_wdecor_t *wdecor, void *arg,
764 ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos)
765{
766 ui_window_t *window = (ui_window_t *) arg;
767
[77ffa01]768 if (window->dwindow != NULL)
769 (void) display_window_resize_req(window->dwindow, rsztype, pos);
[2d879f7]770}
771
772/** Window decoration requested changing cursor.
773 *
774 * @param wdecor Window decoration
775 * @param arg Argument (window)
776 * @param cursor Cursor to set
777 */
778static void wd_set_cursor(ui_wdecor_t *wdecor, void *arg,
779 ui_stock_cursor_t cursor)
780{
781 ui_window_t *window = (ui_window_t *) arg;
782 display_stock_cursor_t dcursor;
783
784 if (cursor == window->cursor)
785 return;
786
787 dcursor = dcurs_arrow;
788
789 switch (cursor) {
790 case ui_curs_arrow:
791 dcursor = dcurs_arrow;
792 break;
793 case ui_curs_size_ud:
794 dcursor = dcurs_size_ud;
795 break;
796 case ui_curs_size_lr:
797 dcursor = dcurs_size_lr;
798 break;
799 case ui_curs_size_uldr:
800 dcursor = dcurs_size_uldr;
801 break;
802 case ui_curs_size_urdl:
803 dcursor = dcurs_size_urdl;
804 break;
805 }
806
[77ffa01]807 if (window->dwindow != NULL)
808 (void) display_window_set_cursor(window->dwindow, dcursor);
[2d879f7]809 window->cursor = cursor;
810}
811
[d284ce9]812/** Send window close event.
813 *
814 * @param window Window
815 */
[fa01c05]816void ui_window_send_close(ui_window_t *window)
[d284ce9]817{
818 if (window->cb != NULL && window->cb->close != NULL)
819 window->cb->close(window, window->arg);
820}
821
[f03d1308]822/** Send window focus event.
823 *
824 * @param window Window
825 */
[fa01c05]826void ui_window_send_focus(ui_window_t *window)
[f03d1308]827{
828 if (window->cb != NULL && window->cb->focus != NULL)
829 window->cb->focus(window, window->arg);
830}
831
832/** Send window keyboard event.
833 *
834 * @param window Window
835 */
[fa01c05]836void ui_window_send_kbd(ui_window_t *window, kbd_event_t *kbd)
[f03d1308]837{
838 if (window->cb != NULL && window->cb->kbd != NULL)
839 window->cb->kbd(window, window->arg, kbd);
840}
841
[fa01c05]842/** Send window paint event.
843 *
844 * @param window Window
845 */
846errno_t ui_window_send_paint(ui_window_t *window)
847{
848 if (window->cb != NULL && window->cb->paint != NULL)
849 return window->cb->paint(window, window->arg);
850 else
851 return ui_window_def_paint(window);
852}
853
[d284ce9]854/** Send window position event.
855 *
856 * @param window Window
857 */
[fa01c05]858void ui_window_send_pos(ui_window_t *window, pos_event_t *pos)
[d284ce9]859{
860 if (window->cb != NULL && window->cb->pos != NULL)
861 window->cb->pos(window, window->arg, pos);
[b71c0fc]862 else
863 ui_window_def_pos(window, pos);
[d284ce9]864}
865
[f03d1308]866/** Send window unfocus event.
867 *
868 * @param window Window
869 */
[fa01c05]870void ui_window_send_unfocus(ui_window_t *window)
[f03d1308]871{
872 if (window->cb != NULL && window->cb->unfocus != NULL)
873 window->cb->unfocus(window, window->arg);
[62223ec]874 else
875 return ui_window_def_unfocus(window);
[f03d1308]876}
877
[fa01c05]878/** Default window paint routine.
879 *
880 * @param window Window
881 * @return EOK on success or an error code
882 */
883errno_t ui_window_def_paint(ui_window_t *window)
884{
885 gfx_rect_t app_rect;
886 errno_t rc;
887
888 rc = gfx_set_color(window->gc, window->res->wnd_face_color);
889 if (rc != EOK)
890 return rc;
891
892 ui_window_get_app_rect(window, &app_rect);
893
894 rc = gfx_fill_rect(window->gc, &app_rect);
895 if (rc != EOK)
896 return rc;
897
[b71c0fc]898 if (window->control != NULL)
899 return ui_control_paint(window->control);
900
[2ab8ab3]901 rc = gfx_update(window->res->gc);
902 if (rc != EOK)
903 return rc;
904
[fa01c05]905 return EOK;
906}
907
[b71c0fc]908/** Default window position event routine.
909 *
910 * @param window Window
911 */
912void ui_window_def_pos(ui_window_t *window, pos_event_t *pos)
913{
914 if (window->control != NULL)
915 ui_control_pos_event(window->control, pos);
916}
917
[62223ec]918/** Default window unfocus routine.
919 *
920 * @param window Window
921 * @return EOK on success or an error code
922 */
923void ui_window_def_unfocus(ui_window_t *window)
924{
925 if (window->control != NULL)
926 ui_control_unfocus(window->control);
927}
928
[2ab8ab3]929/** Window invalidate callback
[66a2becf]930 *
931 * @param arg Argument (ui_window_t *)
932 * @param rect Rectangle to update
933 */
[2ab8ab3]934static void ui_window_invalidate(void *arg, gfx_rect_t *rect)
935{
936 ui_window_t *window = (ui_window_t *) arg;
937 gfx_rect_t env;
938
939 gfx_rect_envelope(&window->dirty_rect, rect, &env);
940 window->dirty_rect = env;
941}
942
943/** Window update callback
944 *
945 * @param arg Argument (ui_window_t *)
946 */
947static void ui_window_update(void *arg)
948{
949 ui_window_t *window = (ui_window_t *) arg;
950
951 if (!gfx_rect_is_empty(&window->dirty_rect))
952 (void) gfx_bitmap_render(window->bmp, &window->dirty_rect, NULL);
953
954 window->dirty_rect.p0.x = 0;
955 window->dirty_rect.p0.y = 0;
956 window->dirty_rect.p1.x = 0;
957 window->dirty_rect.p1.y = 0;
958}
959
960/** Application area invalidate callback
961 *
962 * @param arg Argument (ui_window_t *)
963 * @param rect Rectangle to update
964 */
965static void ui_window_app_invalidate(void *arg, gfx_rect_t *rect)
[66a2becf]966{
967 ui_window_t *window = (ui_window_t *) arg;
968 gfx_rect_t arect;
969
970 ui_window_get_app_rect(window, &arect);
971
972 /* Render bitmap rectangle inside the application area */
973 (void) gfx_bitmap_render(window->app_bmp, rect, &arect.p0);
[2ab8ab3]974 /*
975 * TODO Update applications to call gfx_update(), then
976 * we can defer update to ui_window_app_update().
977 */
978 (void) gfx_update(window->res->gc);
979}
980
981/** Application area update callback
982 *
983 * @param arg Argument (ui_window_t *)
984 */
985static void ui_window_app_update(void *arg)
986{
987 ui_window_t *window = (ui_window_t *) arg;
988
989 /*
990 * Not used since display is updated immediately
991 * in ui_window_app_invalidate
992 */
993 (void) window;
[66a2becf]994}
995
[214aefb]996/** Window expose callback. */
997static void ui_window_expose_cb(void *arg)
998{
999 ui_window_t *window = (ui_window_t *) arg;
1000
1001 ui_window_paint(window);
1002}
1003
[f7a90df]1004/** @}
1005 */
Note: See TracBrowser for help on using the repository browser.