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

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

Basic editable text entry

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