source: mainline/uspace/lib/ui/src/window.c@ 6a0b2cc

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6a0b2cc was 8a6ebbb, checked in by Jiri Svoboda <jiri@…>, 22 months ago

Add restore, minimize, maximize entries to system menu

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