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

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

Minimizing windows

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