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

Last change on this file since 89bca606 was e1f5fb19, checked in by GitHub <noreply@…>, 3 years ago

add relative bottom left/right taskbar coordinates

the absolute coordinates of the screen and relative to the taskbar have been added both in the lower left and in the lower right.
Absolute coordinates place the window above the taskbar, while non-absolute coordinates place the window above the taskbar.
The taskbar delta calculation is a fixed value that corresponds to the height of the taskbar. It is necessary to create a communication the size of the taskbar.

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