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

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

Tab set control

This allows to expand the space available in a dialog window
using stacking, with individual tabs that can be activated
by clicking the handle.

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