Ignore:
File:
1 edited

Legend:

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

    rdb3895d r0d00e53  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2024 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939#include <gfx/bitmap.h>
    4040#include <gfx/context.h>
     41#include <gfx/cursor.h>
    4142#include <gfx/render.h>
    4243#include <io/kbd_event.h>
     
    4647#include <stdlib.h>
    4748#include <ui/control.h>
     49#include <ui/menubar.h>
     50#include <ui/menu.h>
     51#include <ui/menuentry.h>
    4852#include <ui/resource.h>
    4953#include <ui/ui.h>
     
    5862
    5963static void dwnd_close_event(void *);
    60 static void dwnd_focus_event(void *);
     64static void dwnd_focus_event(void *, unsigned);
    6165static void dwnd_kbd_event(void *, kbd_event_t *);
    6266static void dwnd_pos_event(void *, pos_event_t *);
    6367static void dwnd_resize_event(void *, gfx_rect_t *);
    64 static void dwnd_unfocus_event(void *);
     68static void dwnd_unfocus_event(void *, unsigned);
    6569
    6670static display_wnd_cb_t dwnd_cb = {
     
    7377};
    7478
     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 *);
    7586static void wd_close(ui_wdecor_t *, void *);
    76 static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *);
     87static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *, sysarg_t);
    7788static void wd_resize(ui_wdecor_t *, void *, ui_wdecor_rsztype_t,
    78     gfx_coord2_t *);
     89    gfx_coord2_t *, sysarg_t);
    7990static void wd_set_cursor(ui_wdecor_t *, void *, ui_stock_cursor_t);
    8091
    8192static 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,
    82100        .close = wd_close,
    83101        .move = wd_move,
     
    86104};
    87105
     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
    88123static void ui_window_invalidate(void *, gfx_rect_t *);
    89124static 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
    90138static void ui_window_app_invalidate(void *, gfx_rect_t *);
    91139static 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
    92147static void ui_window_expose_cb(void *);
    93148
     
    111166/** Compute where window should be placed on the screen.
    112167 *
    113  * This only applies to windows that do not use default placement.
    114  *
    115  * @param window Window
    116  * @param display Display
    117  * @param info Display info
     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
    118173 * @param params Window parameters
    119174 * @param pos Place to store position of top-left corner
    120175 */
    121 static void ui_window_place(ui_window_t *window, display_t *display,
    122     display_info_t *info, ui_wnd_params_t *params, gfx_coord2_t *pos)
    123 {
    124         assert(params->placement != ui_wnd_place_default);
     176static void ui_window_place(ui_window_t *window, gfx_rect_t *drect,
     177    ui_wnd_params_t *params, gfx_coord2_t *pos)
     178{
     179        gfx_coord2_t dims;
     180        gfx_coord2_t below_pos;
     181        gfx_rect_t below_rect;
     182
     183        assert(params->placement != ui_wnd_place_default ||
     184            ui_is_fullscreen(window->ui));
    125185
    126186        pos->x = 0;
     
    129189        switch (params->placement) {
    130190        case ui_wnd_place_default:
    131                 assert(false);
     191        case ui_wnd_place_center:
     192                assert(params->placement != ui_wnd_place_default ||
     193                    ui_is_fullscreen(window->ui));
     194                /* Center window */
     195                gfx_rect_dims(&params->rect, &dims);
     196                pos->x = (drect->p0.x + drect->p1.x) / 2 - dims.x / 2;
     197                pos->y = (drect->p0.y + drect->p1.y) / 2 - dims.y / 2;
     198                break;
    132199        case ui_wnd_place_top_left:
    133200        case ui_wnd_place_full_screen:
    134                 pos->x = info->rect.p0.x - params->rect.p0.x;
    135                 pos->y = info->rect.p0.y - params->rect.p0.y;
     201                pos->x = drect->p0.x - params->rect.p0.x;
     202                pos->y = drect->p0.y - params->rect.p0.y;
    136203                break;
    137204        case ui_wnd_place_top_right:
    138                 pos->x = info->rect.p1.x - params->rect.p1.x;
    139                 pos->y = info->rect.p0.y - params->rect.p0.y;
     205                pos->x = drect->p1.x - params->rect.p1.x;
     206                pos->y = drect->p0.y - params->rect.p0.y;
    140207                break;
    141208        case ui_wnd_place_bottom_left:
    142                 pos->x = info->rect.p0.x - params->rect.p0.x;
    143                 pos->y = info->rect.p1.y - params->rect.p1.y;
     209                pos->x = drect->p0.x - params->rect.p0.x;
     210                pos->y = drect->p1.y - params->rect.p1.y;
    144211                break;
    145212        case ui_wnd_place_bottom_right:
    146                 pos->x = info->rect.p1.x - params->rect.p1.x;
    147                 pos->y = info->rect.p1.y - params->rect.p1.y;
     213                pos->x = drect->p1.x - params->rect.p1.x;
     214                pos->y = drect->p1.y - params->rect.p1.y;
    148215                break;
    149216        case ui_wnd_place_popup:
    150                 /* Place popup window below parent rectangle */
    151                 pos->x = params->prect.p0.x;
    152                 pos->y = params->prect.p1.y;
     217                /* Compute rectangle when placed below */
     218                below_pos.x = params->prect.p0.x;
     219                below_pos.y = params->prect.p1.y;
     220                gfx_rect_translate(&below_pos, &params->rect, &below_rect);
     221
     222                /* Does below_rect fit within the display? */
     223                if (gfx_rect_is_inside(&below_rect, drect)) {
     224                        /* Place popup window below parent rectangle */
     225                        pos->x = params->prect.p0.x - params->rect.p0.x;
     226                        pos->y = params->prect.p1.y - params->rect.p0.y;
     227                } else {
     228                        /* Place popup window above parent rectangle */
     229                        pos->x = params->prect.p0.x;
     230                        pos->y = params->prect.p0.y -
     231                            (params->rect.p1.y - params->rect.p0.y);
     232                }
    153233                break;
    154234        }
     235}
     236
     237/** Create window's system menu.
     238 *
     239 * @param window Window
     240 * @return EOK on success or an error code
     241 */
     242static errno_t ui_window_sysmenu_create(ui_window_t *window)
     243{
     244        errno_t rc;
     245        ui_menu_entry_t *mrestore;
     246        ui_menu_entry_t *mmin;
     247        ui_menu_entry_t *mmax;
     248        ui_menu_entry_t *msep;
     249        ui_menu_entry_t *mclose;
     250
     251        rc = ui_menu_create(window, &window->sysmenu);
     252        if (rc != EOK)
     253                goto error;
     254
     255        ui_menu_set_cb(window->sysmenu, &wnd_sysmenu_cb, (void *)window);
     256
     257        rc = ui_menu_entry_create(window->sysmenu, "~R~estore",
     258            "", &mrestore);
     259        if (rc != EOK)
     260                goto error;
     261
     262        if (!window->wdecor->maximized)
     263                ui_menu_entry_set_disabled(mrestore, true);
     264
     265        ui_menu_entry_set_cb(mrestore, wnd_sysmenu_erestore, (void *)window);
     266
     267        rc = ui_menu_entry_create(window->sysmenu, "Mi~n~imize",
     268            "", &mmin);
     269        if (rc != EOK)
     270                goto error;
     271
     272        if ((window->wdecor->style & ui_wds_minimize_btn) == 0)
     273                ui_menu_entry_set_disabled(mmin, true);
     274
     275        ui_menu_entry_set_cb(mmin, wnd_sysmenu_eminimize, (void *)window);
     276
     277        rc = ui_menu_entry_create(window->sysmenu, "Ma~x~imize",
     278            "", &mmax);
     279        if (rc != EOK)
     280                goto error;
     281
     282        if ((window->wdecor->style & ui_wds_maximize_btn) == 0 ||
     283            window->wdecor->maximized)
     284                ui_menu_entry_set_disabled(mmax, true);
     285
     286        ui_menu_entry_set_cb(mmax, wnd_sysmenu_emaximize, (void *)window);
     287
     288        rc = ui_menu_entry_sep_create(window->sysmenu, &msep);
     289        if (rc != EOK)
     290                goto error;
     291
     292        rc = ui_menu_entry_create(window->sysmenu, "~C~lose", "Alt-F4",
     293            &mclose);
     294        if (rc != EOK)
     295                goto error;
     296
     297        if ((window->wdecor->style & ui_wds_close_btn) == 0)
     298                ui_menu_entry_set_disabled(mclose, true);
     299
     300        ui_menu_entry_set_cb(mclose, wnd_sysmenu_eclose, (void *)window);
     301
     302        window->sysmenu_restore = mrestore;
     303        window->sysmenu_minimize = mmin;
     304        window->sysmenu_maximize = mmax;
     305
     306        return EOK;
     307error:
     308        return rc;
    155309}
    156310
     
    166320{
    167321        ui_window_t *window;
     322        ui_window_t *pwindow = NULL;
    168323        display_info_t info;
    169324        gfx_coord2_t scr_dims;
     
    176331        gfx_bitmap_alloc_t alloc;
    177332        gfx_bitmap_t *bmp = NULL;
     333        gfx_coord2_t off;
    178334        mem_gc_t *memgc = NULL;
     335        xlate_gc_t *xgc = NULL;
    179336        errno_t rc;
    180337
     
    183340                return ENOMEM;
    184341
     342        window->ui = ui;
     343
    185344        display_wnd_params_init(&dparams);
    186345        dparams.rect = params->rect;
    187         /* Only allow making the window larger */
    188         gfx_rect_dims(&params->rect, &dparams.min_size);
     346        dparams.caption = params->caption;
     347        dparams.min_size = params->min_size;
     348
     349        /*
     350         * If idev_id is not specified, use the UI default (probably
     351         * obtained from display specification. This creates the
     352         * main window in the seat specified on the command line.
     353         */
     354        if (params->idev_id != 0)
     355                dparams.idev_id = params->idev_id;
     356        else
     357                dparams.idev_id = ui->idev_id;
    189358
    190359        if ((params->flags & ui_wndf_popup) != 0)
    191360                dparams.flags |= wndf_popup;
     361        if ((params->flags & ui_wndf_nofocus) != 0)
     362                dparams.flags |= wndf_nofocus;
     363        if ((params->flags & ui_wndf_topmost) != 0)
     364                dparams.flags |= wndf_topmost;
     365        if ((params->flags & ui_wndf_system) != 0)
     366                dparams.flags |= wndf_system;
     367        if ((params->flags & ui_wndf_avoid) != 0)
     368                dparams.flags |= wndf_avoid;
    192369
    193370        if (ui->display != NULL) {
     
    207384                if (params->placement != ui_wnd_place_default) {
    208385                        /* Set initial display window position */
    209                         ui_window_place(window, ui->display, &info,
    210                             params, &dparams.pos);
     386                        ui_window_place(window, &info.rect, params,
     387                            &dparams.pos);
    211388
    212389                        dparams.flags |= wndf_setpos;
     
    223400        } else if (ui->console != NULL) {
    224401                gc = console_gc_get_ctx(ui->cgc);
     402
     403                if (params->placement == ui_wnd_place_full_screen) {
     404                        /* Make window the size of the screen */
     405                        gfx_rect_dims(&ui->rect, &scr_dims);
     406                        gfx_coord2_add(&dparams.rect.p0, &scr_dims,
     407                            &dparams.rect.p1);
     408                        (void) console_set_caption(ui->console,
     409                            params->caption);
     410                }
    225411        } else {
    226412                /* Needed for unit tests */
     
    242428
    243429        /* Move rectangle so that top-left corner is 0,0 */
    244         gfx_rect_rtranslate(&params->rect.p0, &params->rect, &bparams.rect);
     430        gfx_rect_rtranslate(&dparams.rect.p0, &dparams.rect, &bparams.rect);
    245431
    246432        rc = gfx_bitmap_create(gc, &bparams, NULL, &bmp);
     
    255441        }
    256442
    257         rc = mem_gc_create(&bparams.rect, &alloc, ui_window_invalidate,
    258             ui_window_update, (void *) window, &memgc);
     443        rc = mem_gc_create(&bparams.rect, &alloc, &ui_window_mem_gc_cb,
     444            (void *) window, &memgc);
    259445        if (rc != EOK) {
    260446                gfx_bitmap_destroy(window->app_bmp);
     
    266452        window->gc = mem_gc_get_ctx(memgc);
    267453        window->realgc = gc;
     454        (void) off;
    268455#else
    269         (void) ui_window_update;
    270         (void) ui_window_invalidate;
     456        /* Server-side rendering */
     457
     458        /* Full-screen mode? */
     459        if (ui->display == NULL) {
     460                /* Create translating GC to translate window contents */
     461                off.x = 0;
     462                off.y = 0;
     463                rc = xlate_gc_create(&off, gc, &xgc);
     464                if (rc != EOK)
     465                        goto error;
     466
     467                window->xgc = xgc;
     468                window->gc = xlate_gc_get_ctx(xgc);
     469                window->realgc = gc;
     470        } else {
     471                window->gc = gc;
     472        }
     473
     474        (void) ui_window_mem_gc_cb;
    271475        (void) alloc;
    272476        (void) bparams;
    273         window->gc = gc;
    274477#endif
     478        if (ui->display == NULL) {
     479                ui_window_place(window, &ui->rect, params, &window->dpos);
     480
     481                if (window->xgc != NULL)
     482                        xlate_gc_set_off(window->xgc, &window->dpos);
     483        }
    275484
    276485        rc = ui_resource_create(window->gc, ui_is_textmode(ui), &res);
     
    288497        ui_resource_set_expose_cb(res, ui_window_expose_cb, (void *) window);
    289498
    290         window->ui = ui;
    291499        window->rect = dparams.rect;
    292 
    293500        window->res = res;
    294501        window->wdecor = wdecor;
    295502        window->cursor = ui_curs_arrow;
     503        window->placement = params->placement;
     504
     505        rc = ui_window_sysmenu_create(window);
     506        if (rc != EOK)
     507                goto error;
     508
    296509        *rwindow = window;
    297510
     511        if (ui_is_fullscreen(ui))
     512                pwindow = ui_window_get_active(ui);
     513
    298514        list_append(&window->lwindows, &ui->windows);
     515
     516        if (ui_is_fullscreen(ui)) {
     517                /* Send unfocus event to previously active window */
     518                if (pwindow != NULL)
     519                        ui_window_send_unfocus(pwindow, 0);
     520        }
     521
    299522        return EOK;
    300523error:
     
    305528        if (memgc != NULL)
    306529                mem_gc_delete(memgc);
     530        if (xgc != NULL)
     531                xlate_gc_delete(xgc);
    307532        if (bmp != NULL)
    308533                gfx_bitmap_destroy(bmp);
     
    320545{
    321546        ui_t *ui;
     547        ui_window_t *nwindow;
    322548
    323549        if (window == NULL)
     
    328554        list_remove(&window->lwindows);
    329555        ui_control_destroy(window->control);
     556        ui_menu_destroy(window->sysmenu);
    330557        ui_wdecor_destroy(window->wdecor);
    331558        ui_resource_destroy(window->res);
    332         if (0 && window->app_mgc != NULL)
     559        if (window->app_mgc != NULL)
    333560                mem_gc_delete(window->app_mgc);
    334         if (0 && window->app_bmp != NULL)
     561        if (window->app_bmp != NULL)
    335562                gfx_bitmap_destroy(window->app_bmp);
    336563        if (window->mgc != NULL) {
     
    340567        if (window->bmp != NULL)
    341568                gfx_bitmap_destroy(window->bmp);
    342         gfx_context_delete(window->gc);
    343569        if (window->dwindow != NULL)
    344570                display_window_destroy(window->dwindow);
    345 
    346         free(window);
    347571
    348572        /* Need to repaint if windows are emulated */
    349573        if (ui_is_fullscreen(ui)) {
    350574                ui_paint(ui);
    351         }
     575                /* Send focus event to newly active window */
     576                nwindow = ui_window_get_active(ui);
     577                if (nwindow != NULL)
     578                        ui_window_send_focus(nwindow, 0);
     579        }
     580
     581        if (ui->console != NULL &&
     582            window->placement == ui_wnd_place_full_screen) {
     583                (void) console_set_caption(ui->console, "");
     584        }
     585
     586        free(window);
    352587}
    353588
     
    359594 * @param window Window
    360595 * @param control Control
    361  * @return EOK on success, ENOMEM if out of memory
    362596 */
    363597void ui_window_add(ui_window_t *window, ui_control_t *control)
     
    399633}
    400634
    401 /** Resize/move window.
    402  *
    403  * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
    404  * the top-left corner of the window will move on the screen accordingly.
     635/** Resize or (un)maximize window.
    405636 *
    406637 * @param window Window
    407638 * @param rect Rectangle
     639 * @param scop Size change operation
    408640 *
    409641 * @return EOK on success or an error code
    410642 */
    411 errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
     643errno_t ui_window_size_change(ui_window_t *window, gfx_rect_t *rect,
     644    ui_wnd_sc_op_t scop)
    412645{
    413646        gfx_coord2_t offs;
     
    475708        }
    476709
    477         /* dwindow can be NULL in case of unit tests */
     710        /* dwindow can be NULL in case of unit tests or fullscreen mode */
    478711        if (window->dwindow != NULL) {
    479                 rc = display_window_resize(window->dwindow, &offs, &nrect);
    480                 if (rc != EOK)
    481                         goto error;
     712                switch (scop) {
     713                case ui_wsc_resize:
     714                        rc = display_window_resize(window->dwindow, &offs,
     715                            &nrect);
     716                        if (rc != EOK)
     717                                goto error;
     718                        break;
     719                case ui_wsc_maximize:
     720                        rc = display_window_maximize(window->dwindow);
     721                        if (rc != EOK)
     722                                goto error;
     723                        break;
     724                case ui_wsc_unmaximize:
     725                        rc = display_window_unmaximize(window->dwindow);
     726                        if (rc != EOK)
     727                                goto error;
     728                        break;
     729                }
    482730        }
    483731
     
    499747                        goto error;
    500748#endif
    501 
    502749                mem_gc_retarget(window->mgc, &win_params.rect, &win_alloc);
    503750
     
    506753        }
    507754
     755        window->rect = nrect;
    508756        ui_wdecor_set_rect(window->wdecor, &nrect);
    509757        ui_wdecor_paint(window->wdecor);
     
    527775}
    528776
     777/** Resize/move window.
     778 *
     779 * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
     780 * the top-left corner of the window will move on the screen accordingly.
     781 *
     782 * @param window Window
     783 * @param rect Rectangle
     784 *
     785 * @return EOK on success or an error code
     786 */
     787errno_t ui_window_resize(ui_window_t *window, gfx_rect_t *rect)
     788{
     789        return ui_window_size_change(window, rect, ui_wsc_resize);
     790}
     791
    529792/** Set window callbacks.
    530793 *
     
    537800        window->cb = cb;
    538801        window->arg = arg;
     802}
     803
     804/** Change window caption.
     805 *
     806 * @param window Window
     807 * @param caption New caption
     808 *
     809 * @return EOK on success or an error code
     810 */
     811errno_t ui_window_set_caption(ui_window_t *window, const char *caption)
     812{
     813        errno_t rc;
     814
     815        /* Set console caption if fullscreen window on console */
     816        if (window->ui->console != NULL && window->placement ==
     817            ui_wnd_place_full_screen) {
     818                rc = console_set_caption(window->ui->console, caption);
     819                if (rc != EOK)
     820                        return rc;
     821        }
     822
     823        /* Set display window caption if running on display service */
     824        if (window->dwindow != NULL) {
     825                rc = display_window_set_caption(window->dwindow, caption);
     826                if (rc != EOK)
     827                        return rc;
     828        }
     829
     830        return ui_wdecor_set_caption(window->wdecor, caption);
     831}
     832
     833/** Get window's containing UI.
     834 *
     835 * @param window Window
     836 * @return Containing UI
     837 */
     838ui_t *ui_window_get_ui(ui_window_t *window)
     839{
     840        return window->ui;
    539841}
    540842
     
    574876                        return rc;
    575877        } else {
    576                 pos->x = 0;
    577                 pos->y = 0;
     878                *pos = window->dpos;
    578879        }
    579880
     
    618919                }
    619920
    620                 rc = mem_gc_create(&params.rect, &alloc, ui_window_app_invalidate,
    621                     ui_window_app_update, (void *) window, &memgc);
     921                rc = mem_gc_create(&params.rect, &alloc,
     922                    &ui_window_app_mem_gc_cb, (void *) window, &memgc);
    622923                if (rc != EOK) {
    623924                        gfx_bitmap_destroy(window->app_bmp);
     
    675976{
    676977        ui_window_t *window = (ui_window_t *) arg;
    677 
     978        ui_t *ui = window->ui;
     979
     980        ui_lock(ui);
    678981        ui_window_send_close(window);
     982        ui_unlock(ui);
    679983}
    680984
    681985/** Handle window focus event. */
    682 static void dwnd_focus_event(void *arg)
    683 {
    684         ui_window_t *window = (ui_window_t *) arg;
     986static void dwnd_focus_event(void *arg, unsigned nfocus)
     987{
     988        ui_window_t *window = (ui_window_t *) arg;
     989        ui_t *ui = window->ui;
     990
     991        ui_lock(ui);
     992        (void)nfocus;
    685993
    686994        if (window->wdecor != NULL) {
     
    689997        }
    690998
    691         ui_window_send_focus(window);
     999        ui_window_send_focus(window, nfocus);
     1000        ui_unlock(ui);
    6921001}
    6931002
     
    6961005{
    6971006        ui_window_t *window = (ui_window_t *) arg;
    698 
    699         (void) window;
     1007        ui_t *ui = window->ui;
     1008
     1009        ui_lock(ui);
    7001010        ui_window_send_kbd(window, kbd_event);
     1011        ui_unlock(ui);
    7011012}
    7021013
     
    7051016{
    7061017        ui_window_t *window = (ui_window_t *) arg;
     1018        ui_t *ui = window->ui;
     1019        ui_evclaim_t claim;
    7071020
    7081021        /* Make sure we don't process events until fully initialized */
     
    7101023                return;
    7111024
    712         ui_wdecor_pos_event(window->wdecor, event);
     1025        ui_lock(ui);
     1026
     1027        claim = ui_wdecor_pos_event(window->wdecor, event);
     1028        if (claim == ui_claimed) {
     1029                ui_unlock(ui);
     1030                return;
     1031        }
     1032
    7131033        ui_window_send_pos(window, event);
     1034        ui_unlock(ui);
    7141035}
    7151036
     
    7181039{
    7191040        ui_window_t *window = (ui_window_t *) arg;
     1041        ui_t *ui = window->ui;
    7201042
    7211043        /* Make sure we don't process events until fully initialized */
     
    7261048                return;
    7271049
     1050        ui_lock(ui);
    7281051        (void) ui_window_resize(window, rect);
    729         (void) ui_window_paint(window);
     1052        ui_window_send_resize(window);
     1053        ui_unlock(ui);
    7301054}
    7311055
    7321056/** Handle window unfocus event. */
    733 static void dwnd_unfocus_event(void *arg)
    734 {
    735         ui_window_t *window = (ui_window_t *) arg;
    736 
    737         if (window->wdecor != NULL) {
     1057static void dwnd_unfocus_event(void *arg, unsigned nfocus)
     1058{
     1059        ui_window_t *window = (ui_window_t *) arg;
     1060        ui_t *ui = window->ui;
     1061
     1062        ui_lock(ui);
     1063
     1064        if (window->wdecor != NULL && nfocus == 0) {
    7381065                ui_wdecor_set_active(window->wdecor, false);
    7391066                ui_wdecor_paint(window->wdecor);
    7401067        }
    7411068
    742         ui_window_send_unfocus(window);
     1069        ui_window_send_unfocus(window, nfocus);
     1070        ui_unlock(ui);
     1071}
     1072
     1073/** Window decoration requested opening of system menu.
     1074 *
     1075 * @param wdecor Window decoration
     1076 * @param arg Argument (window)
     1077 * @param idev_id Input device ID
     1078 */
     1079static void wd_sysmenu_open(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
     1080{
     1081        ui_window_t *window = (ui_window_t *) arg;
     1082
     1083        ui_window_send_sysmenu(window, idev_id);
     1084}
     1085
     1086/** Window decoration requested moving left from system menu handle.
     1087 *
     1088 * @param wdecor Window decoration
     1089 * @param arg Argument (window)
     1090 * @param idev_id Input device ID
     1091 */
     1092static void wd_sysmenu_left(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
     1093{
     1094        ui_window_t *window = (ui_window_t *) arg;
     1095
     1096        if (window->mbar != NULL) {
     1097                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1098                ui_menu_close(window->sysmenu);
     1099                ui_menu_bar_select_last(window->mbar, false, idev_id);
     1100        }
     1101}
     1102
     1103/** Window decoration requested moving right from system menu handle.
     1104 *
     1105 * @param wdecor Window decoration
     1106 * @param arg Argument (window)
     1107 * @param idev_id Input device ID
     1108 */
     1109static void wd_sysmenu_right(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
     1110{
     1111        ui_window_t *window = (ui_window_t *) arg;
     1112
     1113        if (window->mbar != NULL) {
     1114                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1115                ui_menu_close(window->sysmenu);
     1116                ui_menu_bar_select_first(window->mbar, false, idev_id);
     1117        }
     1118}
     1119
     1120/** Window decoration detected accelerator press from system menu handle.
     1121 *
     1122 * @param wdecor Window decoration
     1123 * @param arg Argument (window)
     1124 * @param c Accelerator key
     1125 * @param idev_id Input device ID
     1126 */
     1127static void wd_sysmenu_accel(ui_wdecor_t *wdecor, void *arg, char32_t c,
     1128    sysarg_t idev_id)
     1129{
     1130        ui_window_t *window = (ui_window_t *) arg;
     1131
     1132        if (window->mbar != NULL) {
     1133                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1134                ui_menu_close(window->sysmenu);
     1135                ui_menu_bar_press_accel(window->mbar, c, idev_id);
     1136        }
     1137}
     1138
     1139/** Window decoration requested window minimization.
     1140 *
     1141 * @param wdecor Window decoration
     1142 * @param arg Argument (window)
     1143 */
     1144static void wd_minimize(ui_wdecor_t *wdecor, void *arg)
     1145{
     1146        ui_window_t *window = (ui_window_t *) arg;
     1147
     1148        ui_window_send_minimize(window);
     1149}
     1150
     1151/** Window decoration requested window maximization.
     1152 *
     1153 * @param wdecor Window decoration
     1154 * @param arg Argument (window)
     1155 */
     1156static void wd_maximize(ui_wdecor_t *wdecor, void *arg)
     1157{
     1158        ui_window_t *window = (ui_window_t *) arg;
     1159
     1160        ui_window_send_maximize(window);
     1161}
     1162
     1163/** Window decoration requested window unmaximization.
     1164 *
     1165 * @param wdecor Window decoration
     1166 * @param arg Argument (window)
     1167 */
     1168static void wd_unmaximize(ui_wdecor_t *wdecor, void *arg)
     1169{
     1170        ui_window_t *window = (ui_window_t *) arg;
     1171
     1172        ui_window_send_unmaximize(window);
    7431173}
    7441174
     
    7601190 * @param arg Argument (window)
    7611191 * @param pos Position where the title bar was pressed
    762  */
    763 static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos)
     1192 * @param pos_id Positioning device ID
     1193 */
     1194static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *pos,
     1195    sysarg_t pos_id)
    7641196{
    7651197        ui_window_t *window = (ui_window_t *) arg;
    7661198
    7671199        if (window->dwindow != NULL)
    768                 (void) display_window_move_req(window->dwindow, pos);
     1200                (void) display_window_move_req(window->dwindow, pos, pos_id);
    7691201}
    7701202
     
    7751207 * @param rsztype Resize type
    7761208 * @param pos Position where the button was pressed
     1209 * @param pos_id Positioning device ID
    7771210 */
    7781211static void wd_resize(ui_wdecor_t *wdecor, void *arg,
    779     ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos)
    780 {
    781         ui_window_t *window = (ui_window_t *) arg;
    782 
    783         if (window->dwindow != NULL)
    784                 (void) display_window_resize_req(window->dwindow, rsztype, pos);
     1212    ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos, sysarg_t pos_id)
     1213{
     1214        ui_window_t *window = (ui_window_t *) arg;
     1215
     1216        if (window->dwindow != NULL) {
     1217                (void) display_window_resize_req(window->dwindow,
     1218                    (display_wnd_rsztype_t) rsztype, // Same constants in the enums
     1219                    pos, pos_id);
     1220        }
    7851221}
    7861222
     
    8431279}
    8441280
     1281/** Send window sysmenu event.
     1282 *
     1283 * @param window Window
     1284 * @parma idev_id Input device ID
     1285 */
     1286void ui_window_send_sysmenu(ui_window_t *window, sysarg_t idev_id)
     1287{
     1288        if (window->cb != NULL && window->cb->sysmenu != NULL)
     1289                window->cb->sysmenu(window, window->arg, idev_id);
     1290        else
     1291                ui_window_def_sysmenu(window, idev_id);
     1292}
     1293
     1294/** Send window minimize event.
     1295 *
     1296 * @param window Window
     1297 */
     1298void ui_window_send_minimize(ui_window_t *window)
     1299{
     1300        if (window->cb != NULL && window->cb->minimize != NULL)
     1301                window->cb->minimize(window, window->arg);
     1302        else
     1303                ui_window_def_minimize(window);
     1304}
     1305
     1306/** Send window maximize event.
     1307 *
     1308 * @param window Window
     1309 */
     1310void ui_window_send_maximize(ui_window_t *window)
     1311{
     1312        if (window->cb != NULL && window->cb->maximize != NULL)
     1313                window->cb->maximize(window, window->arg);
     1314        else
     1315                ui_window_def_maximize(window);
     1316}
     1317
     1318/** Send window unmaximize event.
     1319 *
     1320 * @param window Window
     1321 */
     1322void ui_window_send_unmaximize(ui_window_t *window)
     1323{
     1324        if (window->cb != NULL && window->cb->unmaximize != NULL)
     1325                window->cb->unmaximize(window, window->arg);
     1326        else
     1327                ui_window_def_unmaximize(window);
     1328}
     1329
    8451330/** Send window close event.
    8461331 *
     
    8561341 *
    8571342 * @param window Window
    858  */
    859 void ui_window_send_focus(ui_window_t *window)
     1343 * @param nfocus New number of foci
     1344 */
     1345void ui_window_send_focus(ui_window_t *window, unsigned nfocus)
    8601346{
    8611347        if (window->cb != NULL && window->cb->focus != NULL)
    862                 window->cb->focus(window, window->arg);
     1348                window->cb->focus(window, window->arg, nfocus);
    8631349}
    8641350
     
    8711357        if (window->cb != NULL && window->cb->kbd != NULL)
    8721358                window->cb->kbd(window, window->arg, kbd);
     1359        else
     1360                ui_window_def_kbd(window, kbd);
    8731361}
    8741362
     
    9001388 *
    9011389 * @param window Window
    902  */
    903 void ui_window_send_unfocus(ui_window_t *window)
     1390 * @param nfocus Number of remaining foci
     1391 */
     1392void ui_window_send_unfocus(ui_window_t *window, unsigned nfocus)
    9041393{
    9051394        if (window->cb != NULL && window->cb->unfocus != NULL)
    906                 window->cb->unfocus(window, window->arg);
     1395                window->cb->unfocus(window, window->arg, nfocus);
    9071396        else
    908                 return ui_window_def_unfocus(window);
     1397                return ui_window_def_unfocus(window, nfocus);
     1398}
     1399
     1400/** Send window resize event.
     1401 *
     1402 * @param window Window
     1403 */
     1404void ui_window_send_resize(ui_window_t *window)
     1405{
     1406        if (window->cb != NULL && window->cb->resize != NULL)
     1407                window->cb->resize(window, window->arg);
     1408        else
     1409                return ui_window_def_resize(window);
     1410}
     1411
     1412/** Default window sysmenu routine.
     1413 *
     1414 * @param window Window
     1415 * @param idev_id Input device ID
     1416 * @return EOK on success or an error code
     1417 */
     1418errno_t ui_window_def_sysmenu(ui_window_t *window, sysarg_t idev_id)
     1419{
     1420        errno_t rc;
     1421        ui_wdecor_geom_t geom;
     1422
     1423        if (ui_menu_is_open(window->sysmenu)) {
     1424                ui_menu_close(window->sysmenu);
     1425        } else {
     1426                ui_wdecor_get_geom(window->wdecor, &geom);
     1427
     1428                rc = ui_menu_open(window->sysmenu, &geom.title_bar_rect,
     1429                    idev_id);
     1430                if (rc != EOK)
     1431                        goto error;
     1432        }
     1433
     1434        return EOK;
     1435error:
     1436        return rc;
     1437}
     1438
     1439/** Default window minimize routine.
     1440 *
     1441 * @param window Window
     1442 * @return EOK on success or an error code
     1443 */
     1444errno_t ui_window_def_minimize(ui_window_t *window)
     1445{
     1446        errno_t rc;
     1447
     1448        if (window->dwindow != NULL) {
     1449                rc = display_window_minimize(window->dwindow);
     1450                if (rc != EOK)
     1451                        goto error;
     1452        }
     1453
     1454        return EOK;
     1455error:
     1456        return rc;
     1457}
     1458
     1459/** Default window maximize routine.
     1460 *
     1461 * @param window Window
     1462 * @return EOK on success or an error code
     1463 */
     1464errno_t ui_window_def_maximize(ui_window_t *window)
     1465{
     1466        errno_t rc;
     1467        gfx_rect_t old_rect;
     1468        gfx_rect_t rect;
     1469
     1470        old_rect = window->rect;
     1471
     1472        if (window->dwindow != NULL) {
     1473                rc = display_window_get_max_rect(window->dwindow, &rect);
     1474                if (rc != EOK)
     1475                        return rc;
     1476        } else {
     1477                rect = window->ui->rect;
     1478        }
     1479
     1480        ui_wdecor_set_maximized(window->wdecor, true);
     1481        ui_menu_entry_set_disabled(window->sysmenu_restore, false);
     1482        ui_menu_entry_set_disabled(window->sysmenu_maximize, true);
     1483
     1484        rc = ui_window_size_change(window, &rect, ui_wsc_maximize);
     1485        if (rc != EOK) {
     1486                ui_wdecor_set_maximized(window->wdecor, false);
     1487                return rc;
     1488        }
     1489
     1490        window->normal_rect = old_rect;
     1491        (void) ui_window_paint(window);
     1492        return EOK;
     1493}
     1494
     1495/** Default window unmaximize routine.
     1496 *
     1497 * @param window Window
     1498 * @return EOK on success or an error code
     1499 */
     1500errno_t ui_window_def_unmaximize(ui_window_t *window)
     1501{
     1502        errno_t rc;
     1503
     1504        ui_wdecor_set_maximized(window->wdecor, false);
     1505        ui_menu_entry_set_disabled(window->sysmenu_restore, true);
     1506        ui_menu_entry_set_disabled(window->sysmenu_maximize, false);
     1507
     1508        rc = ui_window_size_change(window, &window->normal_rect,
     1509            ui_wsc_unmaximize);
     1510        if (rc != EOK) {
     1511                ui_wdecor_set_maximized(window->wdecor, true);
     1512                printf("ui_window_size_change->error\n");
     1513                return rc;
     1514        }
     1515
     1516        (void) ui_window_paint(window);
     1517        return EOK;
     1518}
     1519
     1520/** Default window keyboard event routine.
     1521 *
     1522 * @param window Window
     1523 * @return ui_claimed iff event was claimed
     1524 */
     1525ui_evclaim_t ui_window_def_kbd(ui_window_t *window, kbd_event_t *kbd)
     1526{
     1527        ui_evclaim_t claim;
     1528
     1529        if (window->control != NULL)
     1530                claim = ui_control_kbd_event(window->control, kbd);
     1531        else
     1532                claim = ui_unclaimed;
     1533
     1534        if (claim == ui_unclaimed)
     1535                return ui_wdecor_kbd_event(window->wdecor, kbd);
     1536
     1537        return ui_unclaimed;
    9091538}
    9101539
     
    9521581 *
    9531582 * @param window Window
     1583 * @param nfocus Number of remaining foci
    9541584 * @return EOK on success or an error code
    9551585 */
    956 void ui_window_def_unfocus(ui_window_t *window)
     1586void ui_window_def_unfocus(ui_window_t *window, unsigned nfocus)
    9571587{
    9581588        if (window->control != NULL)
    959                 ui_control_unfocus(window->control);
     1589                ui_control_unfocus(window->control, nfocus);
     1590}
     1591
     1592/** Default window resize routine.
     1593 *
     1594 * @param window Window
     1595 * @return EOK on success or an error code
     1596 */
     1597void ui_window_def_resize(ui_window_t *window)
     1598{
     1599        ui_window_paint(window);
     1600}
     1601
     1602/** Handle system menu left event.
     1603 *
     1604 * @param sysmenu System menu
     1605 * @param arg Argument (ui_window_t *)
     1606 * @param idev_id Input device ID
     1607 */
     1608static void wnd_sysmenu_left(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
     1609{
     1610        ui_window_t *window = (ui_window_t *)arg;
     1611
     1612        if (window->mbar != NULL) {
     1613                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1614                ui_menu_close(sysmenu);
     1615                ui_menu_bar_select_last(window->mbar, true, idev_id);
     1616        }
     1617}
     1618
     1619/** Handle system menu right event.
     1620 *
     1621 * @param sysmenu System menu
     1622 * @param arg Argument (ui_window_t *)
     1623 * @param idev_id Input device ID
     1624 */
     1625static void wnd_sysmenu_right(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
     1626{
     1627        ui_window_t *window = (ui_window_t *)arg;
     1628
     1629        if (window->mbar != NULL) {
     1630                ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1631                ui_menu_close(sysmenu);
     1632                ui_menu_bar_select_first(window->mbar, true, idev_id);
     1633        }
     1634}
     1635
     1636/** Handle system menu close request event.
     1637 *
     1638 * @param sysmenu System menu
     1639 * @param arg Argument (ui_window_t *)
     1640 * @param idev_id Input device ID
     1641 */
     1642static void wnd_sysmenu_close_req(ui_menu_t *sysmenu, void *arg)
     1643{
     1644        ui_window_t *window = (ui_window_t *)arg;
     1645
     1646        ui_wdecor_sysmenu_hdl_set_active(window->wdecor, false);
     1647        ui_menu_close(sysmenu);
     1648}
     1649
     1650/** Handle system menu Restore entry activation.
     1651 *
     1652 * @param mentry Menu entry
     1653 * @param arg Argument (ui_window_t *)
     1654 */
     1655static void wnd_sysmenu_erestore(ui_menu_entry_t *mentry, void *arg)
     1656{
     1657        ui_window_t *window = (ui_window_t *)arg;
     1658
     1659        ui_window_send_unmaximize(window);
     1660}
     1661
     1662/** Handle system menu Minimize entry activation.
     1663 *
     1664 * @param mentry Menu entry
     1665 * @param arg Argument (ui_window_t *)
     1666 */
     1667static void wnd_sysmenu_eminimize(ui_menu_entry_t *mentry, void *arg)
     1668{
     1669        ui_window_t *window = (ui_window_t *)arg;
     1670
     1671        ui_window_send_minimize(window);
     1672}
     1673
     1674/** Handle system menu Maximize entry activation.
     1675 *
     1676 * @param mentry Menu entry
     1677 * @param arg Argument (ui_window_t *)
     1678 */
     1679static void wnd_sysmenu_emaximize(ui_menu_entry_t *mentry, void *arg)
     1680{
     1681        ui_window_t *window = (ui_window_t *)arg;
     1682
     1683        ui_window_send_maximize(window);
     1684}
     1685
     1686/** Handle system menu Close entry activation.
     1687 *
     1688 * @param mentry Menu entry
     1689 * @param arg Argument (ui_window_t *)
     1690 */
     1691static void wnd_sysmenu_eclose(ui_menu_entry_t *mentry, void *arg)
     1692{
     1693        ui_window_t *window = (ui_window_t *)arg;
     1694
     1695        ui_window_send_close(window);
     1696}
     1697
     1698/** Handle system menu press accelerator key event.
     1699 *
     1700 * @param sysmenu System menu
     1701 * @param arg Argument (ui_window_t *)
     1702 * @param idev_id Input device ID
     1703 */
     1704static void wnd_sysmenu_press_accel(ui_menu_t *sysmenu, void *arg,
     1705    char32_t c, sysarg_t idev_id)
     1706{
     1707        (void)sysmenu;
     1708        (void)arg;
     1709        (void)c;
     1710        (void)idev_id;
    9601711}
    9611712
     
    9821733        ui_window_t *window = (ui_window_t *) arg;
    9831734
    984         if (!gfx_rect_is_empty(&window->dirty_rect))
    985                 (void) gfx_bitmap_render(window->bmp, &window->dirty_rect, NULL);
     1735        if (!gfx_rect_is_empty(&window->dirty_rect)) {
     1736                (void) gfx_bitmap_render(window->bmp, &window->dirty_rect,
     1737                    &window->dpos);
     1738        }
    9861739
    9871740        window->dirty_rect.p0.x = 0;
     
    9891742        window->dirty_rect.p1.x = 0;
    9901743        window->dirty_rect.p1.y = 0;
     1744}
     1745
     1746/** Window cursor get position callback
     1747 *
     1748 * @param arg Argument (ui_window_t *)
     1749 * @param pos Place to store position
     1750 */
     1751static errno_t ui_window_cursor_get_pos(void *arg, gfx_coord2_t *pos)
     1752{
     1753        ui_window_t *window = (ui_window_t *) arg;
     1754        gfx_coord2_t cpos;
     1755        errno_t rc;
     1756
     1757        rc = gfx_cursor_get_pos(window->realgc, &cpos);
     1758        if (rc != EOK)
     1759                return rc;
     1760
     1761        pos->x = cpos.x - window->dpos.x;
     1762        pos->y = cpos.y - window->dpos.y;
     1763        return EOK;
     1764}
     1765
     1766/** Window cursor set position callback
     1767 *
     1768 * @param arg Argument (ui_window_t *)
     1769 * @param pos New position
     1770 */
     1771static errno_t ui_window_cursor_set_pos(void *arg, gfx_coord2_t *pos)
     1772{
     1773        ui_window_t *window = (ui_window_t *) arg;
     1774        gfx_coord2_t cpos;
     1775
     1776        cpos.x = pos->x + window->dpos.x;
     1777        cpos.y = pos->y + window->dpos.y;
     1778
     1779        return gfx_cursor_set_pos(window->realgc, &cpos);
     1780}
     1781
     1782/** Window cursor set visibility callback
     1783 *
     1784 * @param arg Argument (ui_window_t *)
     1785 * @param visible @c true iff cursor is to be made visible
     1786 */
     1787static errno_t ui_window_cursor_set_visible(void *arg, bool visible)
     1788{
     1789        ui_window_t *window = (ui_window_t *) arg;
     1790
     1791        return gfx_cursor_set_visible(window->realgc, visible);
    9911792}
    9921793
Note: See TracChangeset for help on using the changeset viewer.