Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ui/src/window.c

    r25f26600 rb979ffb  
    11/*
    2  * Copyright (c) 2020 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3434 */
    3535
     36#include <congfx/console.h>
    3637#include <display.h>
    3738#include <errno.h>
    3839#include <gfx/bitmap.h>
    3940#include <gfx/context.h>
     41#include <gfx/cursor.h>
    4042#include <gfx/render.h>
    4143#include <io/kbd_event.h>
     
    4547#include <stdlib.h>
    4648#include <ui/control.h>
     49#include <ui/menubar.h>
     50#include <ui/menu.h>
     51#include <ui/menuentry.h>
    4752#include <ui/resource.h>
     53#include <ui/ui.h>
    4854#include <ui/wdecor.h>
    4955#include <ui/window.h>
     
    5662
    5763static void dwnd_close_event(void *);
    58 static void dwnd_focus_event(void *);
     64static void dwnd_focus_event(void *, unsigned);
    5965static void dwnd_kbd_event(void *, kbd_event_t *);
    6066static void dwnd_pos_event(void *, pos_event_t *);
    6167static void dwnd_resize_event(void *, gfx_rect_t *);
    62 static void dwnd_unfocus_event(void *);
     68static void dwnd_unfocus_event(void *, unsigned);
    6369
    6470static display_wnd_cb_t dwnd_cb = {
     
    7177};
    7278
     79static void wd_sysmenu_open(ui_wdecor_t *, void *, sysarg_t);
     80static void wd_sysmenu_left(ui_wdecor_t *, void *, sysarg_t);
     81static void wd_sysmenu_right(ui_wdecor_t *, void *, sysarg_t);
     82static void wd_sysmenu_accel(ui_wdecor_t *, void *, char32_t, sysarg_t);
     83static void wd_minimize(ui_wdecor_t *, void *);
     84static void wd_maximize(ui_wdecor_t *, void *);
     85static void wd_unmaximize(ui_wdecor_t *, void *);
    7386static void wd_close(ui_wdecor_t *, void *);
    74 static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *);
     87static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *, sysarg_t);
    7588static void wd_resize(ui_wdecor_t *, void *, ui_wdecor_rsztype_t,
    76     gfx_coord2_t *);
     89    gfx_coord2_t *, sysarg_t);
    7790static void wd_set_cursor(ui_wdecor_t *, void *, ui_stock_cursor_t);
    7891
    7992static ui_wdecor_cb_t wdecor_cb = {
     93        .sysmenu_open = wd_sysmenu_open,
     94        .sysmenu_left = wd_sysmenu_left,
     95        .sysmenu_right = wd_sysmenu_right,
     96        .sysmenu_accel = wd_sysmenu_accel,
     97        .minimize = wd_minimize,
     98        .maximize = wd_maximize,
     99        .unmaximize = wd_unmaximize,
    80100        .close = wd_close,
    81101        .move = wd_move,
     
    84104};
    85105
    86 static void ui_window_app_update(void *, gfx_rect_t *);
     106static void wnd_sysmenu_left(ui_menu_t *, void *, sysarg_t);
     107static void wnd_sysmenu_right(ui_menu_t *, void *, sysarg_t);
     108static void wnd_sysmenu_close_req(ui_menu_t *, void *);
     109static void wnd_sysmenu_press_accel(ui_menu_t *, void *, char32_t, sysarg_t);
     110
     111static ui_menu_cb_t wnd_sysmenu_cb = {
     112        .left = wnd_sysmenu_left,
     113        .right = wnd_sysmenu_right,
     114        .close_req = wnd_sysmenu_close_req,
     115        .press_accel = wnd_sysmenu_press_accel
     116};
     117
     118static void wnd_sysmenu_erestore(ui_menu_entry_t *, void *);
     119static void wnd_sysmenu_eminimize(ui_menu_entry_t *, void *);
     120static void wnd_sysmenu_emaximize(ui_menu_entry_t *, void *);
     121static void wnd_sysmenu_eclose(ui_menu_entry_t *, void *);
     122
     123static void ui_window_invalidate(void *, gfx_rect_t *);
     124static void ui_window_update(void *);
     125static errno_t ui_window_cursor_get_pos(void *, gfx_coord2_t *);
     126static errno_t ui_window_cursor_set_pos(void *, gfx_coord2_t *);
     127static errno_t ui_window_cursor_set_visible(void *, bool);
     128
     129/** Window memory GC callbacks */
     130static mem_gc_cb_t ui_window_mem_gc_cb = {
     131        .invalidate = ui_window_invalidate,
     132        .update = ui_window_update,
     133        .cursor_get_pos = ui_window_cursor_get_pos,
     134        .cursor_set_pos = ui_window_cursor_set_pos,
     135        .cursor_set_visible = ui_window_cursor_set_visible
     136};
     137
     138static void ui_window_app_invalidate(void *, gfx_rect_t *);
     139static void ui_window_app_update(void *);
     140
     141/** Application area memory GC callbacks */
     142static mem_gc_cb_t ui_window_app_mem_gc_cb = {
     143        .invalidate = ui_window_app_invalidate,
     144        .update = ui_window_app_update
     145};
     146
     147static void ui_window_expose_cb(void *);
    87148
    88149/** Initialize window parameters structure.
     
    103164}
    104165
     166/** Compute where window should be placed on the screen.
     167 *
     168 * This only applies to windows that do not use default placement or
     169 * if we are running in full-screen mode.
     170 *
     171 * @param window Window
     172 * @param drect Display rectangle
     173 * @param wrect Window rectangle
     174 * @param prect Parent rectangle for popup placement or @c NULL
     175 * @param placement Window placement
     176 * @param params Window parameters
     177 * @param pos Place to store position of top-left corner
     178 */
     179static void ui_window_place(ui_window_t *window, gfx_rect_t *drect,
     180    gfx_rect_t *wrect, gfx_rect_t *prect, ui_wnd_placement_t placement,
     181    gfx_coord2_t *pos)
     182{
     183        gfx_coord2_t dims;
     184        gfx_coord2_t below_pos;
     185        gfx_rect_t below_rect;
     186
     187        assert(placement != ui_wnd_place_default ||
     188            ui_is_fullscreen(window->ui));
     189
     190        pos->x = 0;
     191        pos->y = 0;
     192
     193        switch (placement) {
     194        case ui_wnd_place_default:
     195        case ui_wnd_place_center:
     196                assert(placement != ui_wnd_place_default ||
     197                    ui_is_fullscreen(window->ui));
     198                /* Center window */
     199                gfx_rect_dims(wrect, &dims);
     200                pos->x = (drect->p0.x + drect->p1.x) / 2 - dims.x / 2;
     201                pos->y = (drect->p0.y + drect->p1.y) / 2 - dims.y / 2;
     202                break;
     203        case ui_wnd_place_top_left:
     204        case ui_wnd_place_full_screen:
     205                pos->x = drect->p0.x - wrect->p0.x;
     206                pos->y = drect->p0.y - wrect->p0.y;
     207                break;
     208        case ui_wnd_place_top_right:
     209                pos->x = drect->p1.x - wrect->p1.x;
     210                pos->y = drect->p0.y - wrect->p0.y;
     211                break;
     212        case ui_wnd_place_bottom_left:
     213                pos->x = drect->p0.x - wrect->p0.x;
     214                pos->y = drect->p1.y - wrect->p1.y;
     215                break;
     216        case ui_wnd_place_bottom_right:
     217                pos->x = drect->p1.x - wrect->p1.x;
     218                pos->y = drect->p1.y - wrect->p1.y;
     219                break;
     220        case ui_wnd_place_popup:
     221                /* Compute rectangle when placed below */
     222                below_pos.x = prect->p0.x;
     223                below_pos.y = prect->p1.y;
     224                gfx_rect_translate(&below_pos, wrect, &below_rect);
     225
     226                /* Does below_rect fit within the display? */
     227                if (gfx_rect_is_inside(&below_rect, drect)) {
     228                        /* Place popup window below parent rectangle */
     229                        pos->x = prect->p0.x - wrect->p0.x;
     230                        pos->y = prect->p1.y - wrect->p0.y;
     231                } else {
     232                        /* Place popup window above parent rectangle */
     233                        pos->x = prect->p0.x;
     234                        pos->y = prect->p0.y -
     235                            (wrect->p1.y - wrect->p0.y);
     236                }
     237                break;
     238        }
     239}
     240
     241static void ui_window_set_dpos(ui_window_t *window, gfx_coord2_t *dpos)
     242{
     243        window->dpos = *dpos;
     244        if (window->xgc != NULL)
     245                xlate_gc_set_off(window->xgc, &window->dpos);
     246}
     247
     248/** Create window's system menu.
     249 *
     250 * @param window Window
     251 * @return EOK on success or an error code
     252 */
     253static errno_t ui_window_sysmenu_create(ui_window_t *window)
     254{
     255        errno_t rc;
     256        ui_menu_entry_t *mrestore;
     257        ui_menu_entry_t *mmin;
     258        ui_menu_entry_t *mmax;
     259        ui_menu_entry_t *msep;
     260        ui_menu_entry_t *mclose;
     261
     262        rc = ui_menu_create(window, &window->sysmenu);
     263        if (rc != EOK)
     264                goto error;
     265
     266        ui_menu_set_cb(window->sysmenu, &wnd_sysmenu_cb, (void *)window);
     267
     268        rc = ui_menu_entry_create(window->sysmenu, "~R~estore",
     269            "", &mrestore);
     270        if (rc != EOK)
     271                goto error;
     272
     273        if (!window->wdecor->maximized)
     274                ui_menu_entry_set_disabled(mrestore, true);
     275
     276        ui_menu_entry_set_cb(mrestore, wnd_sysmenu_erestore, (void *)window);
     277
     278        rc = ui_menu_entry_create(window->sysmenu, "Mi~n~imize",
     279            "", &mmin);
     280        if (rc != EOK)
     281                goto error;
     282
     283        if ((window->wdecor->style & ui_wds_minimize_btn) == 0)
     284                ui_menu_entry_set_disabled(mmin, true);
     285
     286        ui_menu_entry_set_cb(mmin, wnd_sysmenu_eminimize, (void *)window);
     287
     288        rc = ui_menu_entry_create(window->sysmenu, "Ma~x~imize",
     289            "", &mmax);
     290        if (rc != EOK)
     291                goto error;
     292
     293        if ((window->wdecor->style & ui_wds_maximize_btn) == 0 ||
     294            window->wdecor->maximized)
     295                ui_menu_entry_set_disabled(mmax, true);
     296
     297        ui_menu_entry_set_cb(mmax, wnd_sysmenu_emaximize, (void *)window);
     298
     299        rc = ui_menu_entry_sep_create(window->sysmenu, &msep);
     300        if (rc != EOK)
     301                goto error;
     302
     303        rc = ui_menu_entry_create(window->sysmenu, "~C~lose", "Alt-F4",
     304            &mclose);
     305        if (rc != EOK)
     306                goto error;
     307
     308        if ((window->wdecor->style & ui_wds_close_btn) == 0)
     309                ui_menu_entry_set_disabled(mclose, true);
     310
     311        ui_menu_entry_set_cb(mclose, wnd_sysmenu_eclose, (void *)window);
     312
     313        window->sysmenu_restore = mrestore;
     314        window->sysmenu_minimize = mmin;
     315        window->sysmenu_maximize = mmax;
     316
     317        return EOK;
     318error:
     319        return rc;
     320}
     321
    105322/** Create new window.
    106323 *
     
    114331{
    115332        ui_window_t *window;
     333        ui_window_t *pwindow = NULL;
    116334        display_info_t info;
    117         gfx_coord2_t pos;
    118335        gfx_coord2_t scr_dims;
    119336        display_wnd_params_t dparams;
    120         display_window_t *dwindow = NULL;
    121337        gfx_context_t *gc = NULL;
    122338        ui_resource_t *res = NULL;
    123339        ui_wdecor_t *wdecor = NULL;
    124340        dummy_gc_t *dgc = NULL;
     341        gfx_bitmap_params_t bparams;
     342        gfx_bitmap_alloc_t alloc;
     343        gfx_bitmap_t *bmp = NULL;
     344        gfx_coord2_t off;
     345        mem_gc_t *memgc = NULL;
     346        xlate_gc_t *xgc = NULL;
     347        gfx_coord2_t dpos;
    125348        errno_t rc;
    126349
     
    129352                return ENOMEM;
    130353
     354        window->ui = ui;
     355
    131356        display_wnd_params_init(&dparams);
    132357        dparams.rect = params->rect;
    133         /* Only allow making the window larger */
    134         gfx_rect_dims(&params->rect, &dparams.min_size);
     358        dparams.caption = params->caption;
     359        dparams.min_size = params->min_size;
     360
     361        /*
     362         * If idev_id is not specified, use the UI default (probably
     363         * obtained from display specification. This creates the
     364         * main window in the seat specified on the command line.
     365         */
     366        if (params->idev_id != 0)
     367                dparams.idev_id = params->idev_id;
     368        else
     369                dparams.idev_id = ui->idev_id;
     370
     371        if ((params->flags & ui_wndf_popup) != 0)
     372                dparams.flags |= wndf_popup;
     373        if ((params->flags & ui_wndf_nofocus) != 0)
     374                dparams.flags |= wndf_nofocus;
     375        if ((params->flags & ui_wndf_topmost) != 0)
     376                dparams.flags |= wndf_topmost;
     377        if ((params->flags & ui_wndf_system) != 0)
     378                dparams.flags |= wndf_system;
     379        if ((params->flags & ui_wndf_avoid) != 0)
     380                dparams.flags |= wndf_avoid;
    135381
    136382        if (ui->display != NULL) {
     
    148394                }
    149395
     396                if (params->placement != ui_wnd_place_default) {
     397                        /* Set initial display window position */
     398                        ui_window_place(window, &info.rect, &params->rect,
     399                            &params->prect, params->placement, &dparams.pos);
     400
     401                        dparams.flags |= wndf_setpos;
     402                }
     403
    150404                rc = display_window_create(ui->display, &dparams, &dwnd_cb,
    151                     (void *) window, &dwindow);
     405                    (void *) window, &window->dwindow);
    152406                if (rc != EOK)
    153407                        goto error;
    154408
    155                 if (params->placement != ui_wnd_place_default) {
    156                         pos.x = 0;
    157                         pos.y = 0;
    158 
    159                         switch (params->placement) {
    160                         case ui_wnd_place_default:
    161                                 assert(false);
    162                         case ui_wnd_place_top_left:
    163                         case ui_wnd_place_full_screen:
    164                                 pos.x = info.rect.p0.x - params->rect.p0.x;
    165                                 pos.y = info.rect.p0.y - params->rect.p0.y;
    166                                 break;
    167                         case ui_wnd_place_top_right:
    168                                 pos.x = info.rect.p1.x - params->rect.p1.x;
    169                                 pos.y = info.rect.p0.y - params->rect.p0.y;
    170                                 break;
    171                         case ui_wnd_place_bottom_left:
    172                                 pos.x = info.rect.p0.x - params->rect.p0.x;
    173                                 pos.y = info.rect.p1.y - params->rect.p1.y;
    174                                 break;
    175                         case ui_wnd_place_bottom_right:
    176                                 pos.x = info.rect.p1.x - params->rect.p1.x;
    177                                 pos.y = info.rect.p1.y - params->rect.p1.y;
    178                                 break;
    179                         }
    180 
    181                         rc = display_window_move(dwindow, &pos);
    182                         if (rc != EOK)
    183                                 goto error;
    184                 }
    185 
    186                 rc = display_window_get_gc(dwindow, &gc);
     409                rc = display_window_get_gc(window->dwindow, &gc);
    187410                if (rc != EOK)
    188411                        goto error;
     412        } else if (ui->console != NULL) {
     413                gc = console_gc_get_ctx(ui->cgc);
     414
     415                if (params->placement == ui_wnd_place_full_screen) {
     416                        /* Make window the size of the screen */
     417                        gfx_rect_dims(&ui->rect, &scr_dims);
     418                        gfx_coord2_add(&dparams.rect.p0, &scr_dims,
     419                            &dparams.rect.p1);
     420                        (void) console_set_caption(ui->console,
     421                            params->caption);
     422                }
    189423        } else {
    190424                /* Needed for unit tests */
     
    196430        }
    197431
    198         rc = ui_resource_create(gc, &res);
     432#ifdef CONFIG_UI_CS_RENDER
     433        /* Create window bitmap */
     434        gfx_bitmap_params_init(&bparams);
     435#ifndef CONFIG_WIN_DOUBLE_BUF
     436        /* Console does not support direct output */
     437        if (ui->display != NULL)
     438                bparams.flags |= bmpf_direct_output;
     439#endif
     440
     441        /* Move rectangle so that top-left corner is 0,0 */
     442        gfx_rect_rtranslate(&dparams.rect.p0, &dparams.rect, &bparams.rect);
     443
     444        rc = gfx_bitmap_create(gc, &bparams, NULL, &bmp);
     445        if (rc != EOK)
     446                goto error;
     447
     448        /* Create memory GC */
     449        rc = gfx_bitmap_get_alloc(bmp, &alloc);
     450        if (rc != EOK) {
     451                gfx_bitmap_destroy(window->app_bmp);
     452                return rc;
     453        }
     454
     455        rc = mem_gc_create(&bparams.rect, &alloc, &ui_window_mem_gc_cb,
     456            (void *) window, &memgc);
     457        if (rc != EOK) {
     458                gfx_bitmap_destroy(window->app_bmp);
     459                return rc;
     460        }
     461
     462        window->bmp = bmp;
     463        window->mgc = memgc;
     464        window->gc = mem_gc_get_ctx(memgc);
     465        window->realgc = gc;
     466        (void) off;
     467#else
     468        /* Server-side rendering */
     469
     470        /* Full-screen mode? */
     471        if (ui->display == NULL) {
     472                /* Create translating GC to translate window contents */
     473                off.x = 0;
     474                off.y = 0;
     475                rc = xlate_gc_create(&off, gc, &xgc);
     476                if (rc != EOK)
     477                        goto error;
     478
     479                window->xgc = xgc;
     480                window->gc = xlate_gc_get_ctx(xgc);
     481                window->realgc = gc;
     482        } else {
     483                window->gc = gc;
     484        }
     485
     486        (void) ui_window_mem_gc_cb;
     487        (void) alloc;
     488        (void) bparams;
     489#endif
     490        if (ui->display == NULL) {
     491                ui_window_place(window, &ui->rect, &params->rect, &params->prect,
     492                    params->placement, &dpos);
     493                ui_window_set_dpos(window, &dpos);
     494        }
     495
     496        rc = ui_resource_create(window->gc, ui_is_textmode(ui), &res);
    199497        if (rc != EOK)
    200498                goto error;
     
    208506        ui_wdecor_paint(wdecor);
    209507
    210         window->ui = ui;
    211         window->dwindow = dwindow;
     508        ui_resource_set_expose_cb(res, ui_window_expose_cb, (void *) window);
     509
    212510        window->rect = dparams.rect;
    213         window->gc = gc;
    214511        window->res = res;
    215512        window->wdecor = wdecor;
    216513        window->cursor = ui_curs_arrow;
     514        window->placement = params->placement;
     515
     516        rc = ui_window_sysmenu_create(window);
     517        if (rc != EOK)
     518                goto error;
     519
    217520        *rwindow = window;
     521
     522        if (ui_is_fullscreen(ui))
     523                pwindow = ui_window_get_active(ui);
     524
     525        list_append(&window->lwindows, &ui->windows);
     526
     527        if (ui_is_fullscreen(ui)) {
     528                /* Send unfocus event to previously active window */
     529                if (pwindow != NULL)
     530                        ui_window_send_unfocus(pwindow, 0);
     531        }
     532
    218533        return EOK;
    219534error:
     
    222537        if (res != NULL)
    223538                ui_resource_destroy(res);
     539        if (memgc != NULL)
     540                mem_gc_delete(memgc);
     541        if (xgc != NULL)
     542                xlate_gc_delete(xgc);
     543        if (bmp != NULL)
     544                gfx_bitmap_destroy(bmp);
    224545        if (dgc != NULL)
    225546                dummygc_destroy(dgc);
    226         if (dwindow != NULL)
    227                 display_window_destroy(dwindow);
    228547        free(window);
    229548        return rc;
    230549}
    231550
     551/** Update window placement after screen resize (only in fullscreen UI).
     552 *
     553 * @param window UI window
     554 */
     555void ui_window_update_placement(ui_window_t *window)
     556{
     557        if (window->placement == ui_wnd_place_full_screen ||
     558            (window->flags & uiwf_maximized) != 0) {
     559                /* Update size of fullscreen or maximized window. */
     560                (void)ui_window_resize(window, &window->ui->rect);
     561                ui_window_send_resize(window);
     562        }
     563}
     564
    232565/** Destroy window.
    233566 *
     
    236569void ui_window_destroy(ui_window_t *window)
    237570{
     571        ui_t *ui;
     572        ui_window_t *nwindow;
     573
    238574        if (window == NULL)
    239575                return;
    240576
     577        ui = window->ui;
     578
     579        list_remove(&window->lwindows);
    241580        ui_control_destroy(window->control);
     581        ui_menu_destroy(window->sysmenu);
    242582        ui_wdecor_destroy(window->wdecor);
    243583        ui_resource_destroy(window->res);
    244         gfx_context_delete(window->gc);
    245         display_window_destroy(window->dwindow);
     584        if (window->app_mgc != NULL)
     585                mem_gc_delete(window->app_mgc);
     586        if (window->app_bmp != NULL)
     587                gfx_bitmap_destroy(window->app_bmp);
     588        if (window->mgc != NULL) {
     589                mem_gc_delete(window->mgc);
     590                window->gc = NULL;
     591        }
     592        if (window->bmp != NULL)
     593                gfx_bitmap_destroy(window->bmp);
     594        if (window->dwindow != NULL)
     595                display_window_destroy(window->dwindow);
     596
     597        /* Need to repaint if windows are emulated */
     598        if (ui_is_fullscreen(ui)) {
     599                (void)ui_paint(ui);
     600                /* Send focus event to newly active window */
     601                nwindow = ui_window_get_active(ui);
     602                if (nwindow != NULL)
     603                        ui_window_send_focus(nwindow, 0);
     604        }
     605
     606        if (ui->console != NULL &&
     607            window->placement == ui_wnd_place_full_screen) {
     608                (void) console_set_caption(ui->console, "");
     609        }
     610
    246611        free(window);
    247612}
     
    252617 * is added, the results are undefined.
    253618 *
    254  * @param fixed Fixed layout
     619 * @param window Window
    255620 * @param control Control
    256  * @return EOK on success, ENOMEM if out of memory
    257621 */
    258622void ui_window_add(ui_window_t *window, ui_control_t *control)
     
    278642}
    279643
    280 /** Resize/move window.
    281  *
    282  * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
    283  * the top-left corner of the window will move on the screen accordingly.
     644/** Get first (lowermost) window (only valid in fullscreen mode).
     645 *
     646 * @param ui User interface
     647 * @return First window
     648 */
     649ui_window_t *ui_window_first(ui_t *ui)
     650{
     651        link_t *link;
     652
     653        link = list_first(&ui->windows);
     654        if (link == NULL)
     655                return NULL;
     656
     657        return list_get_instance(link, ui_window_t, lwindows);
     658}
     659
     660/** Get next window (only valid in fullscreen mode).
     661 *
     662 * @param cur Current window
     663 * @return First window
     664 */
     665ui_window_t *ui_window_next(ui_window_t *cur)
     666{
     667        link_t *link;
     668
     669        link = list_next(&cur->lwindows, &cur->ui->windows);
     670        if (link == NULL)
     671                return NULL;
     672
     673        return list_get_instance(link, ui_window_t, lwindows);
     674}
     675
     676/** Get active window (only valid in fullscreen mode).
     677 *
     678 * @param ui User interface
     679 * @return Active window
     680 */
     681ui_window_t *ui_window_get_active(ui_t *ui)
     682{
     683        link_t *link;
     684
     685        link = list_last(&ui->windows);
     686        if (link == NULL)
     687                return NULL;
     688
     689        return list_get_instance(link, ui_window_t, lwindows);
     690}
     691
     692/** Resize or (un)maximize window.
    284693 *
    285694 * @param window Window
    286695 * @param rect Rectangle
     696 * @param scop Size change operation
    287697 *
    288698 * @return EOK on success or an error code
    289699 */
    290 errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
     700errno_t ui_window_size_change(ui_window_t *window, gfx_rect_t *rect,
     701    ui_wnd_sc_op_t scop)
    291702{
    292703        gfx_coord2_t offs;
     
    294705        gfx_rect_t arect;
    295706        gfx_bitmap_t *app_bmp = NULL;
    296         gfx_bitmap_params_t params;
    297         gfx_bitmap_alloc_t alloc;
     707        gfx_bitmap_t *win_bmp = NULL;
     708        gfx_bitmap_params_t app_params;
     709        gfx_bitmap_params_t win_params;
     710        gfx_bitmap_alloc_t app_alloc;
     711        gfx_bitmap_alloc_t win_alloc;
     712        gfx_coord2_t dpos;
    298713        errno_t rc;
    299714
     
    305720        gfx_rect_rtranslate(&offs, rect, &nrect);
    306721
     722        /* mgc != NULL iff client-side rendering */
     723        if (window->mgc != NULL) {
     724#ifdef CONFIG_WIN_DOUBLE_BUF
     725                /*
     726                 * Create new window bitmap in advance. If direct mapping,
     727                 * will need do it after resizing the window.
     728                 */
     729                assert(window->bmp != NULL);
     730                gfx_bitmap_params_init(&win_params);
     731                win_params.rect = nrect;
     732
     733                rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
     734                    &win_bmp);
     735                if (rc != EOK)
     736                        goto error;
     737
     738                rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
     739                if (rc != EOK)
     740                        goto error;
     741#endif
     742        }
     743
     744        /* Application area GC? */
    307745        if (window->app_gc != NULL) {
     746                /* Resize application bitmap */
    308747                assert(window->app_bmp != NULL);
    309748
    310                 gfx_bitmap_params_init(&params);
     749                gfx_bitmap_params_init(&app_params);
    311750
    312751                /*
     
    315754                 */
    316755                ui_wdecor_app_from_rect(window->wdecor->style, &nrect, &arect);
    317                 gfx_rect_rtranslate(&arect.p0, &arect, &params.rect);
    318 
    319                 rc = gfx_bitmap_create(window->gc, &params, NULL,
     756                gfx_rect_rtranslate(&arect.p0, &arect, &app_params.rect);
     757
     758                rc = gfx_bitmap_create(window->gc, &app_params, NULL,
    320759                    &app_bmp);
    321760                if (rc != EOK)
    322761                        goto error;
    323762
    324                 rc = gfx_bitmap_get_alloc(app_bmp, &alloc);
     763                rc = gfx_bitmap_get_alloc(app_bmp, &app_alloc);
    325764                if (rc != EOK)
    326765                        goto error;
    327766        }
    328767
    329         /* dwindow can be NULL in case of unit tests */
     768        /* dwindow can be NULL in case of unit tests or fullscreen mode */
    330769        if (window->dwindow != NULL) {
    331                 rc = display_window_resize(window->dwindow, &offs, &nrect);
     770                switch (scop) {
     771                case ui_wsc_resize:
     772                        rc = display_window_resize(window->dwindow, &offs,
     773                            &nrect);
     774                        if (rc != EOK)
     775                                goto error;
     776                        break;
     777                case ui_wsc_maximize:
     778                        rc = display_window_maximize(window->dwindow);
     779                        if (rc != EOK)
     780                                goto error;
     781                        break;
     782                case ui_wsc_unmaximize:
     783                        rc = display_window_unmaximize(window->dwindow);
     784                        if (rc != EOK)
     785                                goto error;
     786                        break;
     787                }
     788        } else {
     789                /* fullscreen mode or unit tests */
     790                switch (scop) {
     791                case ui_wsc_resize:
     792                        break;
     793                case ui_wsc_maximize:
     794                        window->normal_dpos = window->dpos;
     795                        dpos.x = 0;
     796                        dpos.y = 0;
     797                        ui_window_set_dpos(window, &dpos);
     798                        break;
     799                case ui_wsc_unmaximize:
     800                        ui_window_set_dpos(window, &window->normal_dpos);
     801                        break;
     802                }
     803        }
     804
     805        /* Client side rendering? */
     806        if (window->mgc != NULL) {
     807#ifndef CONFIG_WIN_DOUBLE_BUF
     808                /* Window is resized, now we can map the window bitmap again */
     809                gfx_bitmap_params_init(&win_params);
     810                if (window->ui->display != NULL)
     811                        win_params.flags |= bmpf_direct_output;
     812                win_params.rect = nrect;
     813
     814                rc = gfx_bitmap_create(window->realgc, &win_params, NULL,
     815                    &win_bmp);
    332816                if (rc != EOK)
    333817                        goto error;
    334         }
    335 
     818
     819                rc = gfx_bitmap_get_alloc(win_bmp, &win_alloc);
     820                if (rc != EOK)
     821                        goto error;
     822#endif
     823                mem_gc_retarget(window->mgc, &win_params.rect, &win_alloc);
     824
     825                gfx_bitmap_destroy(window->bmp);
     826                window->bmp = win_bmp;
     827        }
     828
     829        window->rect = nrect;
    336830        ui_wdecor_set_rect(window->wdecor, &nrect);
    337831        ui_wdecor_paint(window->wdecor);
    338 
     832        gfx_update(window->gc);
     833
     834        /* Application area GC? */
    339835        if (window->app_gc != NULL) {
    340                 mem_gc_retarget(window->app_mgc, &params.rect, &alloc);
     836                mem_gc_retarget(window->app_mgc, &app_params.rect, &app_alloc);
    341837
    342838                gfx_bitmap_destroy(window->app_bmp);
    343839                window->app_bmp = app_bmp;
     840        }
     841
     842        switch (scop) {
     843        case ui_wsc_resize:
     844                break;
     845        case ui_wsc_maximize:
     846                window->flags |= uiwf_maximized;
     847                break;
     848        case ui_wsc_unmaximize:
     849                window->flags &= ~uiwf_maximized;
     850                break;
    344851        }
    345852
     
    348855        if (app_bmp != NULL)
    349856                gfx_bitmap_destroy(app_bmp);
     857        if (win_bmp != NULL)
     858                gfx_bitmap_destroy(win_bmp);
    350859        return rc;
    351860}
    352861
     862/** Resize/move window.
     863 *
     864 * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
     865 * the top-left corner of the window will move on the screen accordingly.
     866 *
     867 * @param window Window
     868 * @param rect Rectangle
     869 *
     870 * @return EOK on success or an error code
     871 */
     872errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
     873{
     874        errno_t rc;
     875
     876        rc = ui_window_size_change(window, rect, ui_wsc_resize);
     877        if (rc != EOK)
     878                return rc;
     879
     880        /* Need to repaint UI if windows are emulated */
     881        if (ui_is_fullscreen(window->ui))
     882                (void)ui_paint(window->ui);
     883
     884        return EOK;
     885}
     886
    353887/** Set window callbacks.
    354888 *
    355889 * @param window Window
    356  * @param cb Window decoration callbacks
     890 * @param cb Window callbacks
    357891 * @param arg Callback argument
    358892 */
     
    363897}
    364898
     899/** Change window caption.
     900 *
     901 * @param window Window
     902 * @param caption New caption
     903 *
     904 * @return EOK on success or an error code
     905 */
     906errno_t ui_window_set_caption(ui_window_t *window, const char *caption)
     907{
     908        errno_t rc;
     909
     910        /* Set console caption if fullscreen window on console */
     911        if (window->ui->console != NULL && window->placement ==
     912            ui_wnd_place_full_screen) {
     913                rc = console_set_caption(window->ui->console, caption);
     914                if (rc != EOK)
     915                        return rc;
     916        }
     917
     918        /* Set display window caption if running on display service */
     919        if (window->dwindow != NULL) {
     920                rc = display_window_set_caption(window->dwindow, caption);
     921                if (rc != EOK)
     922                        return rc;
     923        }
     924
     925        return ui_wdecor_set_caption(window->wdecor, caption);
     926}
     927
     928/** Get window's containing UI.
     929 *
     930 * @param window Window
     931 * @return Containing UI
     932 */
     933ui_t *ui_window_get_ui(ui_window_t *window)
     934{
     935        return window->ui;
     936}
     937
    365938/** Get UI resource from window.
    366939 *
     
    381954{
    382955        return window->gc;
     956}
     957
     958/** Get window position.
     959 *
     960 * @param window Window
     961 * @param pos Place to store position
     962 * @return EOK on success or an error code
     963 */
     964errno_t ui_window_get_pos(ui_window_t *window, gfx_coord2_t *pos)
     965{
     966        errno_t rc;
     967
     968        if (window->dwindow != NULL) {
     969                rc = display_window_get_pos(window->dwindow, pos);
     970                if (rc != EOK)
     971                        return rc;
     972        } else {
     973                *pos = window->dpos;
     974        }
     975
     976        return EOK;
    383977}
    384978
     
    4201014                }
    4211015
    422                 rc = mem_gc_create(&params.rect, &alloc, ui_window_app_update,
    423                     (void *) window, &memgc);
     1016                rc = mem_gc_create(&params.rect, &alloc,
     1017                    &ui_window_app_mem_gc_cb, (void *) window, &memgc);
    4241018                if (rc != EOK) {
    4251019                        gfx_bitmap_destroy(window->app_bmp);
     
    4481042}
    4491043
     1044/** Set cursor when pointer is hovering over a control.
     1045 *
     1046 * @param window Window
     1047 * @param cursor Cursor
     1048 */
     1049void ui_window_set_ctl_cursor(ui_window_t *window, ui_stock_cursor_t cursor)
     1050{
     1051        display_stock_cursor_t dcursor;
     1052
     1053        dcursor = wnd_dcursor_from_cursor(cursor);
     1054
     1055        if (window->dwindow != NULL)
     1056                (void) display_window_set_cursor(window->dwindow, dcursor);
     1057}
     1058
    4501059/** Paint window
    4511060 *
     
    4621071{
    4631072        ui_window_t *window = (ui_window_t *) arg;
    464 
     1073        ui_t *ui = window->ui;
     1074
     1075        fibril_mutex_lock(&ui->lock);
    4651076        ui_window_send_close(window);
     1077        fibril_mutex_unlock(&ui->lock);
    4661078}
    4671079
    4681080/** Handle window focus event. */
    469 static void dwnd_focus_event(void *arg)
    470 {
    471         ui_window_t *window = (ui_window_t *) arg;
     1081static void dwnd_focus_event(void *arg, unsigned nfocus)
     1082{
     1083        ui_window_t *window = (ui_window_t *) arg;
     1084        ui_t *ui = window->ui;
     1085
     1086        fibril_mutex_lock(&ui->lock);
     1087        (void)nfocus;
    4721088
    4731089        if (window->wdecor != NULL) {
     
    4761092        }
    4771093
    478         ui_window_send_focus(window);
     1094        ui_window_send_focus(window, nfocus);
     1095        fibril_mutex_unlock(&ui->lock);
    4791096}
    4801097
     
    4831100{
    4841101        ui_window_t *window = (ui_window_t *) arg;
    485 
    486         (void) window;
     1102        ui_t *ui = window->ui;
     1103
     1104        fibril_mutex_lock(&ui->lock);
    4871105        ui_window_send_kbd(window, kbd_event);
     1106        fibril_mutex_unlock(&ui->lock);
    4881107}
    4891108
     
    4921111{
    4931112        ui_window_t *window = (ui_window_t *) arg;
     1113        ui_t *ui = window->ui;
     1114        ui_evclaim_t claim;
    4941115
    4951116        /* Make sure we don't process events until fully initialized */
     
    4971118                return;
    4981119
    499         ui_wdecor_pos_event(window->wdecor, event);
     1120        fibril_mutex_lock(&ui->lock);
     1121
     1122        claim = ui_wdecor_pos_event(window->wdecor, event);
     1123        if (claim == ui_claimed) {
     1124                fibril_mutex_unlock(&ui->lock);
     1125                return;
     1126        }
     1127
    5001128        ui_window_send_pos(window, event);
     1129        fibril_mutex_unlock(&ui->lock);
    5011130}
    5021131
     
    5051134{
    5061135        ui_window_t *window = (ui_window_t *) arg;
     1136        ui_t *ui = window->ui;
    5071137
    5081138        /* Make sure we don't process events until fully initialized */
     
    5131143                return;
    5141144
     1145        fibril_mutex_lock(&ui->lock);
    5151146        (void) ui_window_resize(window, rect);
    516         (void) ui_window_paint(window);
     1147        ui_window_send_resize(window);
     1148        fibril_mutex_unlock(&ui->lock);
    5171149}
    5181150
    5191151/** Handle window unfocus event. */
    520 static void dwnd_unfocus_event(void *arg)
    521 {
    522         ui_window_t *window = (ui_window_t *) arg;
    523 
    524         if (window->wdecor != NULL) {
     1152static void dwnd_unfocus_event(void *arg, unsigned nfocus)
     1153{
     1154        ui_window_t *window = (ui_window_t *) arg;
     1155        ui_t *ui = window->ui;
     1156
     1157        fibril_mutex_lock(&ui->lock);
     1158
     1159        if (window->wdecor != NULL && nfocus == 0) {
    5251160                ui_wdecor_set_active(window->wdecor, false);
    5261161                ui_wdecor_paint(window->wdecor);
    5271162        }
    5281163
    529         ui_window_send_unfocus(window);
     1164        ui_window_send_unfocus(window, nfocus);
     1165        fibril_mutex_unlock(&ui->lock);
     1166}
     1167
     1168/** Window decoration requested opening of system menu.
     1169 *
     1170 * @param wdecor Window decoration
     1171 * @param arg Argument (window)
     1172 * @param idev_id Input device ID
     1173 */
     1174static void wd_sysmenu_open(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
     1175{
     1176        ui_window_t *window = (ui_window_t *) arg;
     1177
     1178        ui_window_send_sysmenu(window, idev_id);
     1179}
     1180
     1181/** Window decoration requested moving left from system menu handle.
     1182 *
     1183 * @param wdecor Window decoration
     1184 * @param arg Argument (window)
     1185 * @param idev_id Input device ID
     1186 */
     1187static void wd_sysmenu_left(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
     1188{
     1189        ui_window_t *window = (ui_window_t *) arg;
     1190
     1191        if (window->mbar != NULL) {
     1192                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1193                ui_menu_close(window->sysmenu);
     1194                ui_menu_bar_select_last(window->mbar, false, idev_id);
     1195        }
     1196}
     1197
     1198/** Window decoration requested moving right from system menu handle.
     1199 *
     1200 * @param wdecor Window decoration
     1201 * @param arg Argument (window)
     1202 * @param idev_id Input device ID
     1203 */
     1204static void wd_sysmenu_right(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
     1205{
     1206        ui_window_t *window = (ui_window_t *) arg;
     1207
     1208        if (window->mbar != NULL) {
     1209                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1210                ui_menu_close(window->sysmenu);
     1211                ui_menu_bar_select_first(window->mbar, false, idev_id);
     1212        }
     1213}
     1214
     1215/** Window decoration detected accelerator press from system menu handle.
     1216 *
     1217 * @param wdecor Window decoration
     1218 * @param arg Argument (window)
     1219 * @param c Accelerator key
     1220 * @param idev_id Input device ID
     1221 */
     1222static void wd_sysmenu_accel(ui_wdecor_t *wdecor, void *arg, char32_t c,
     1223    sysarg_t idev_id)
     1224{
     1225        ui_window_t *window = (ui_window_t *) arg;
     1226
     1227        if (window->mbar != NULL) {
     1228                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1229                ui_menu_close(window->sysmenu);
     1230                ui_menu_bar_press_accel(window->mbar, c, idev_id);
     1231        }
     1232}
     1233
     1234/** Window decoration requested window minimization.
     1235 *
     1236 * @param wdecor Window decoration
     1237 * @param arg Argument (window)
     1238 */
     1239static void wd_minimize(ui_wdecor_t *wdecor, void *arg)
     1240{
     1241        ui_window_t *window = (ui_window_t *) arg;
     1242
     1243        ui_window_send_minimize(window);
     1244}
     1245
     1246/** Window decoration requested window maximization.
     1247 *
     1248 * @param wdecor Window decoration
     1249 * @param arg Argument (window)
     1250 */
     1251static void wd_maximize(ui_wdecor_t *wdecor, void *arg)
     1252{
     1253        ui_window_t *window = (ui_window_t *) arg;
     1254
     1255        ui_window_send_maximize(window);
     1256}
     1257
     1258/** Window decoration requested window unmaximization.
     1259 *
     1260 * @param wdecor Window decoration
     1261 * @param arg Argument (window)
     1262 */
     1263static void wd_unmaximize(ui_wdecor_t *wdecor, void *arg)
     1264{
     1265        ui_window_t *window = (ui_window_t *) arg;
     1266
     1267        ui_window_send_unmaximize(window);
    5301268}
    5311269
     
    5471285 * @param arg Argument (window)
    5481286 * @param pos Position where the title bar was pressed
    549  */
    550 static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos)
    551 {
    552         ui_window_t *window = (ui_window_t *) arg;
    553 
    554         (void) display_window_move_req(window->dwindow, pos);
     1287 * @param pos_id Positioning device ID
     1288 */
     1289static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos,
     1290    sysarg_t pos_id)
     1291{
     1292        ui_window_t *window = (ui_window_t *) arg;
     1293
     1294        if (window->dwindow != NULL)
     1295                (void) display_window_move_req(window->dwindow, pos, pos_id);
    5551296}
    5561297
     
    5611302 * @param rsztype Resize type
    5621303 * @param pos Position where the button was pressed
     1304 * @param pos_id Positioning device ID
    5631305 */
    5641306static void wd_resize(ui_wdecor_t *wdecor, void *arg,
    565     ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos)
    566 {
    567         ui_window_t *window = (ui_window_t *) arg;
    568 
    569         (void) display_window_resize_req(window->dwindow, rsztype, pos);
    570 }
    571 
    572 /** Window decoration requested changing cursor.
    573  *
    574  * @param wdecor Window decoration
    575  * @param arg Argument (window)
    576  * @param cursor Cursor to set
    577  */
    578 static void wd_set_cursor(ui_wdecor_t *wdecor, void *arg,
    579     ui_stock_cursor_t cursor)
    580 {
    581         ui_window_t *window = (ui_window_t *) arg;
     1307    ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos, sysarg_t pos_id)
     1308{
     1309        ui_window_t *window = (ui_window_t *) arg;
     1310
     1311        if (window->dwindow != NULL) {
     1312                (void) display_window_resize_req(window->dwindow,
     1313                    (display_wnd_rsztype_t) rsztype, // Same constants in the enums
     1314                    pos, pos_id);
     1315        }
     1316}
     1317
     1318/** Get display stock cursor from UI stock cursor.
     1319 *
     1320 * @param cursor UI stock cursor
     1321 * @return Display stock cursor
     1322 */
     1323display_stock_cursor_t wnd_dcursor_from_cursor(ui_stock_cursor_t cursor)
     1324{
    5821325        display_stock_cursor_t dcursor;
    583 
    584         if (cursor == window->cursor)
    585                 return;
    5861326
    5871327        dcursor = dcurs_arrow;
     
    6031343                dcursor = dcurs_size_urdl;
    6041344                break;
    605         }
    606 
    607         (void) display_window_set_cursor(window->dwindow, dcursor);
     1345        case ui_curs_ibeam:
     1346                dcursor = dcurs_ibeam;
     1347                break;
     1348        }
     1349
     1350        return dcursor;
     1351}
     1352
     1353/** Window decoration requested changing cursor.
     1354 *
     1355 * @param wdecor Window decoration
     1356 * @param arg Argument (window)
     1357 * @param cursor Cursor to set
     1358 */
     1359static void wd_set_cursor(ui_wdecor_t *wdecor, void *arg,
     1360    ui_stock_cursor_t cursor)
     1361{
     1362        ui_window_t *window = (ui_window_t *) arg;
     1363        display_stock_cursor_t dcursor;
     1364
     1365        if (cursor == window->cursor)
     1366                return;
     1367
     1368        dcursor = wnd_dcursor_from_cursor(cursor);
     1369
     1370        if (window->dwindow != NULL)
     1371                (void) display_window_set_cursor(window->dwindow, dcursor);
     1372
    6081373        window->cursor = cursor;
     1374}
     1375
     1376/** Send window sysmenu event.
     1377 *
     1378 * @param window Window
     1379 * @parma idev_id Input device ID
     1380 */
     1381void ui_window_send_sysmenu(ui_window_t *window, sysarg_t idev_id)
     1382{
     1383        if (window->cb != NULL && window->cb->sysmenu != NULL)
     1384                window->cb->sysmenu(window, window->arg, idev_id);
     1385        else
     1386                ui_window_def_sysmenu(window, idev_id);
     1387}
     1388
     1389/** Send window minimize event.
     1390 *
     1391 * @param window Window
     1392 */
     1393void ui_window_send_minimize(ui_window_t *window)
     1394{
     1395        if (window->cb != NULL && window->cb->minimize != NULL)
     1396                window->cb->minimize(window, window->arg);
     1397        else
     1398                ui_window_def_minimize(window);
     1399}
     1400
     1401/** Send window maximize event.
     1402 *
     1403 * @param window Window
     1404 */
     1405void ui_window_send_maximize(ui_window_t *window)
     1406{
     1407        if (window->cb != NULL && window->cb->maximize != NULL)
     1408                window->cb->maximize(window, window->arg);
     1409        else
     1410                ui_window_def_maximize(window);
     1411}
     1412
     1413/** Send window unmaximize event.
     1414 *
     1415 * @param window Window
     1416 */
     1417void ui_window_send_unmaximize(ui_window_t *window)
     1418{
     1419        if (window->cb != NULL && window->cb->unmaximize != NULL)
     1420                window->cb->unmaximize(window, window->arg);
     1421        else
     1422                ui_window_def_unmaximize(window);
    6091423}
    6101424
     
    6221436 *
    6231437 * @param window Window
    624  */
    625 void ui_window_send_focus(ui_window_t *window)
     1438 * @param nfocus New number of foci
     1439 */
     1440void ui_window_send_focus(ui_window_t *window, unsigned nfocus)
    6261441{
    6271442        if (window->cb != NULL && window->cb->focus != NULL)
    628                 window->cb->focus(window, window->arg);
     1443                window->cb->focus(window, window->arg, nfocus);
    6291444}
    6301445
     
    6371452        if (window->cb != NULL && window->cb->kbd != NULL)
    6381453                window->cb->kbd(window, window->arg, kbd);
     1454        else
     1455                ui_window_def_kbd(window, kbd);
    6391456}
    6401457
     
    6661483 *
    6671484 * @param window Window
    668  */
    669 void ui_window_send_unfocus(ui_window_t *window)
     1485 * @param nfocus Number of remaining foci
     1486 */
     1487void ui_window_send_unfocus(ui_window_t *window, unsigned nfocus)
    6701488{
    6711489        if (window->cb != NULL && window->cb->unfocus != NULL)
    672                 window->cb->unfocus(window, window->arg);
     1490                window->cb->unfocus(window, window->arg, nfocus);
     1491        else
     1492                return ui_window_def_unfocus(window, nfocus);
     1493}
     1494
     1495/** Send window resize event.
     1496 *
     1497 * @param window Window
     1498 */
     1499void ui_window_send_resize(ui_window_t *window)
     1500{
     1501        if (window->cb != NULL && window->cb->resize != NULL)
     1502                window->cb->resize(window, window->arg);
     1503        else
     1504                return ui_window_def_resize(window);
     1505}
     1506
     1507/** Default window sysmenu routine.
     1508 *
     1509 * @param window Window
     1510 * @param idev_id Input device ID
     1511 * @return EOK on success or an error code
     1512 */
     1513errno_t ui_window_def_sysmenu(ui_window_t *window, sysarg_t idev_id)
     1514{
     1515        errno_t rc;
     1516        ui_wdecor_geom_t geom;
     1517
     1518        if (ui_menu_is_open(window->sysmenu)) {
     1519                ui_menu_close(window->sysmenu);
     1520        } else {
     1521                ui_wdecor_get_geom(window->wdecor, &geom);
     1522
     1523                rc = ui_menu_open(window->sysmenu, &geom.title_bar_rect,
     1524                    idev_id);
     1525                if (rc != EOK)
     1526                        goto error;
     1527        }
     1528
     1529        return EOK;
     1530error:
     1531        return rc;
     1532}
     1533
     1534/** Default window minimize routine.
     1535 *
     1536 * @param window Window
     1537 * @return EOK on success or an error code
     1538 */
     1539errno_t ui_window_def_minimize(ui_window_t *window)
     1540{
     1541        errno_t rc;
     1542
     1543        if (window->dwindow != NULL) {
     1544                rc = display_window_minimize(window->dwindow);
     1545                if (rc != EOK)
     1546                        goto error;
     1547        }
     1548
     1549        return EOK;
     1550error:
     1551        return rc;
     1552}
     1553
     1554/** Default window maximize routine.
     1555 *
     1556 * @param window Window
     1557 * @return EOK on success or an error code
     1558 */
     1559errno_t ui_window_def_maximize(ui_window_t *window)
     1560{
     1561        errno_t rc;
     1562        gfx_rect_t old_rect;
     1563        gfx_rect_t rect;
     1564
     1565        old_rect = window->rect;
     1566
     1567        if (window->dwindow != NULL) {
     1568                rc = display_window_get_max_rect(window->dwindow, &rect);
     1569                if (rc != EOK)
     1570                        return rc;
     1571        } else {
     1572                rect = window->ui->rect;
     1573        }
     1574
     1575        ui_wdecor_set_maximized(window->wdecor, true);
     1576        ui_menu_entry_set_disabled(window->sysmenu_restore, false);
     1577        ui_menu_entry_set_disabled(window->sysmenu_maximize, true);
     1578
     1579        rc = ui_window_size_change(window, &rect, ui_wsc_maximize);
     1580        if (rc != EOK) {
     1581                ui_wdecor_set_maximized(window->wdecor, false);
     1582                return rc;
     1583        }
     1584
     1585        window->normal_rect = old_rect;
     1586        ui_window_send_resize(window);
     1587
     1588        /* Need to repaint UI if windows are emulated */
     1589        if (ui_is_fullscreen(window->ui))
     1590                (void)ui_paint(window->ui);
     1591
     1592        return EOK;
     1593}
     1594
     1595/** Default window unmaximize routine.
     1596 *
     1597 * @param window Window
     1598 * @return EOK on success or an error code
     1599 */
     1600errno_t ui_window_def_unmaximize(ui_window_t *window)
     1601{
     1602        errno_t rc;
     1603
     1604        ui_wdecor_set_maximized(window->wdecor, false);
     1605        ui_menu_entry_set_disabled(window->sysmenu_restore, true);
     1606        ui_menu_entry_set_disabled(window->sysmenu_maximize, false);
     1607
     1608        rc = ui_window_size_change(window, &window->normal_rect,
     1609            ui_wsc_unmaximize);
     1610        if (rc != EOK) {
     1611                ui_wdecor_set_maximized(window->wdecor, true);
     1612                printf("ui_window_size_change->error\n");
     1613                return rc;
     1614        }
     1615
     1616        ui_window_send_resize(window);
     1617
     1618        /* Need to repaint UI if windows are emulated */
     1619        if (ui_is_fullscreen(window->ui))
     1620                (void)ui_paint(window->ui);
     1621
     1622        return EOK;
     1623}
     1624
     1625/** Default window keyboard event routine.
     1626 *
     1627 * @param window Window
     1628 * @return ui_claimed iff event was claimed
     1629 */
     1630ui_evclaim_t ui_window_def_kbd(ui_window_t *window, kbd_event_t *kbd)
     1631{
     1632        ui_evclaim_t claim;
     1633
     1634        if (window->control != NULL)
     1635                claim = ui_control_kbd_event(window->control, kbd);
     1636        else
     1637                claim = ui_unclaimed;
     1638
     1639        if (claim == ui_unclaimed)
     1640                return ui_wdecor_kbd_event(window->wdecor, kbd);
     1641
     1642        return ui_unclaimed;
    6731643}
    6741644
     
    6961666                return ui_control_paint(window->control);
    6971667
     1668        rc = gfx_update(window->res->gc);
     1669        if (rc != EOK)
     1670                return rc;
     1671
    6981672        return EOK;
    6991673}
     
    7021676 *
    7031677 * @param window Window
    704  * @return EOK on success or an error code
    7051678 */
    7061679void ui_window_def_pos(ui_window_t *window, pos_event_t *pos)
     
    7101683}
    7111684
    712 /** Application area update callback
     1685/** Default window unfocus routine.
     1686 *
     1687 * @param window Window
     1688 * @param nfocus Number of remaining foci
     1689 * @return EOK on success or an error code
     1690 */
     1691void ui_window_def_unfocus(ui_window_t *window, unsigned nfocus)
     1692{
     1693        if (window->control != NULL)
     1694                ui_control_unfocus(window->control, nfocus);
     1695}
     1696
     1697/** Default window resize routine.
     1698 *
     1699 * @param window Window
     1700 * @return EOK on success or an error code
     1701 */
     1702void ui_window_def_resize(ui_window_t *window)
     1703{
     1704        ui_window_paint(window);
     1705}
     1706
     1707/** Handle system menu left event.
     1708 *
     1709 * @param sysmenu System menu
     1710 * @param arg Argument (ui_window_t *)
     1711 * @param idev_id Input device ID
     1712 */
     1713static void wnd_sysmenu_left(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
     1714{
     1715        ui_window_t *window = (ui_window_t *)arg;
     1716
     1717        if (window->mbar != NULL) {
     1718                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1719                ui_menu_close(sysmenu);
     1720                ui_menu_bar_select_last(window->mbar, true, idev_id);
     1721        }
     1722}
     1723
     1724/** Handle system menu right event.
     1725 *
     1726 * @param sysmenu System menu
     1727 * @param arg Argument (ui_window_t *)
     1728 * @param idev_id Input device ID
     1729 */
     1730static void wnd_sysmenu_right(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
     1731{
     1732        ui_window_t *window = (ui_window_t *)arg;
     1733
     1734        if (window->mbar != NULL) {
     1735                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1736                ui_menu_close(sysmenu);
     1737                ui_menu_bar_select_first(window->mbar, true, idev_id);
     1738        }
     1739}
     1740
     1741/** Handle system menu close request event.
     1742 *
     1743 * @param sysmenu System menu
     1744 * @param arg Argument (ui_window_t *)
     1745 * @param idev_id Input device ID
     1746 */
     1747static void wnd_sysmenu_close_req(ui_menu_t *sysmenu, void *arg)
     1748{
     1749        ui_window_t *window = (ui_window_t *)arg;
     1750
     1751        ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1752        ui_menu_close(sysmenu);
     1753}
     1754
     1755/** Handle system menu Restore entry activation.
     1756 *
     1757 * @param mentry Menu entry
     1758 * @param arg Argument (ui_window_t *)
     1759 */
     1760static void wnd_sysmenu_erestore(ui_menu_entry_t *mentry, void *arg)
     1761{
     1762        ui_window_t *window = (ui_window_t *)arg;
     1763
     1764        ui_window_send_unmaximize(window);
     1765}
     1766
     1767/** Handle system menu Minimize entry activation.
     1768 *
     1769 * @param mentry Menu entry
     1770 * @param arg Argument (ui_window_t *)
     1771 */
     1772static void wnd_sysmenu_eminimize(ui_menu_entry_t *mentry, void *arg)
     1773{
     1774        ui_window_t *window = (ui_window_t *)arg;
     1775
     1776        ui_window_send_minimize(window);
     1777}
     1778
     1779/** Handle system menu Maximize entry activation.
     1780 *
     1781 * @param mentry Menu entry
     1782 * @param arg Argument (ui_window_t *)
     1783 */
     1784static void wnd_sysmenu_emaximize(ui_menu_entry_t *mentry, void *arg)
     1785{
     1786        ui_window_t *window = (ui_window_t *)arg;
     1787
     1788        ui_window_send_maximize(window);
     1789}
     1790
     1791/** Handle system menu Close entry activation.
     1792 *
     1793 * @param mentry Menu entry
     1794 * @param arg Argument (ui_window_t *)
     1795 */
     1796static void wnd_sysmenu_eclose(ui_menu_entry_t *mentry, void *arg)
     1797{
     1798        ui_window_t *window = (ui_window_t *)arg;
     1799
     1800        ui_window_send_close(window);
     1801}
     1802
     1803/** Handle system menu press accelerator key event.
     1804 *
     1805 * @param sysmenu System menu
     1806 * @param arg Argument (ui_window_t *)
     1807 * @param idev_id Input device ID
     1808 */
     1809static void wnd_sysmenu_press_accel(ui_menu_t *sysmenu, void *arg,
     1810    char32_t c, sysarg_t idev_id)
     1811{
     1812        (void)sysmenu;
     1813        (void)arg;
     1814        (void)c;
     1815        (void)idev_id;
     1816}
     1817
     1818/** Window invalidate callback
    7131819 *
    7141820 * @param arg Argument (ui_window_t *)
    7151821 * @param rect Rectangle to update
    7161822 */
    717 static void ui_window_app_update(void *arg, gfx_rect_t *rect)
     1823static void ui_window_invalidate(void *arg, gfx_rect_t *rect)
     1824{
     1825        ui_window_t *window = (ui_window_t *) arg;
     1826        gfx_rect_t env;
     1827
     1828        gfx_rect_envelope(&window->dirty_rect, rect, &env);
     1829        window->dirty_rect = env;
     1830}
     1831
     1832/** Window update callback
     1833 *
     1834 * @param arg Argument (ui_window_t *)
     1835 */
     1836static void ui_window_update(void *arg)
     1837{
     1838        ui_window_t *window = (ui_window_t *) arg;
     1839
     1840        if (!gfx_rect_is_empty(&window->dirty_rect)) {
     1841                (void) gfx_bitmap_render(window->bmp, &window->dirty_rect,
     1842                    &window->dpos);
     1843        }
     1844
     1845        window->dirty_rect.p0.x = 0;
     1846        window->dirty_rect.p0.y = 0;
     1847        window->dirty_rect.p1.x = 0;
     1848        window->dirty_rect.p1.y = 0;
     1849}
     1850
     1851/** Window cursor get position callback
     1852 *
     1853 * @param arg Argument (ui_window_t *)
     1854 * @param pos Place to store position
     1855 */
     1856static errno_t ui_window_cursor_get_pos(void *arg, gfx_coord2_t *pos)
     1857{
     1858        ui_window_t *window = (ui_window_t *) arg;
     1859        gfx_coord2_t cpos;
     1860        errno_t rc;
     1861
     1862        rc = gfx_cursor_get_pos(window->realgc, &cpos);
     1863        if (rc != EOK)
     1864                return rc;
     1865
     1866        pos->x = cpos.x - window->dpos.x;
     1867        pos->y = cpos.y - window->dpos.y;
     1868        return EOK;
     1869}
     1870
     1871/** Window cursor set position callback
     1872 *
     1873 * @param arg Argument (ui_window_t *)
     1874 * @param pos New position
     1875 */
     1876static errno_t ui_window_cursor_set_pos(void *arg, gfx_coord2_t *pos)
     1877{
     1878        ui_window_t *window = (ui_window_t *) arg;
     1879        gfx_coord2_t cpos;
     1880
     1881        cpos.x = pos->x + window->dpos.x;
     1882        cpos.y = pos->y + window->dpos.y;
     1883
     1884        return gfx_cursor_set_pos(window->realgc, &cpos);
     1885}
     1886
     1887/** Window cursor set visibility callback
     1888 *
     1889 * @param arg Argument (ui_window_t *)
     1890 * @param visible @c true iff cursor is to be made visible
     1891 */
     1892static errno_t ui_window_cursor_set_visible(void *arg, bool visible)
     1893{
     1894        ui_window_t *window = (ui_window_t *) arg;
     1895
     1896        return gfx_cursor_set_visible(window->realgc, visible);
     1897}
     1898
     1899/** Application area invalidate callback
     1900 *
     1901 * @param arg Argument (ui_window_t *)
     1902 * @param rect Rectangle to update
     1903 */
     1904static void ui_window_app_invalidate(void *arg, gfx_rect_t *rect)
    7181905{
    7191906        ui_window_t *window = (ui_window_t *) arg;
     
    7241911        /* Render bitmap rectangle inside the application area */
    7251912        (void) gfx_bitmap_render(window->app_bmp, rect, &arect.p0);
     1913        /*
     1914         * TODO Update applications to call gfx_update(), then
     1915         * we can defer update to ui_window_app_update().
     1916         */
     1917        (void) gfx_update(window->res->gc);
     1918}
     1919
     1920/** Application area update callback
     1921 *
     1922 * @param arg Argument (ui_window_t *)
     1923 */
     1924static void ui_window_app_update(void *arg)
     1925{
     1926        ui_window_t *window = (ui_window_t *) arg;
     1927
     1928        /*
     1929         * Not used since display is updated immediately
     1930         * in ui_window_app_invalidate
     1931         */
     1932        (void) window;
     1933}
     1934
     1935/** Window expose callback. */
     1936static void ui_window_expose_cb(void *arg)
     1937{
     1938        ui_window_t *window = (ui_window_t *) arg;
     1939
     1940        ui_window_paint(window);
    7261941}
    7271942
Note: See TracChangeset for help on using the changeset viewer.