Ignore:
File:
1 edited

Legend:

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

    r1215db9 rb979ffb  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2026 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4747#include <stdlib.h>
    4848#include <ui/control.h>
     49#include <ui/menubar.h>
     50#include <ui/menu.h>
     51#include <ui/menuentry.h>
    4952#include <ui/resource.h>
    5053#include <ui/ui.h>
     
    5962
    6063static void dwnd_close_event(void *);
    61 static void dwnd_focus_event(void *);
     64static void dwnd_focus_event(void *, unsigned);
    6265static void dwnd_kbd_event(void *, kbd_event_t *);
    6366static void dwnd_pos_event(void *, pos_event_t *);
    6467static void dwnd_resize_event(void *, gfx_rect_t *);
    65 static void dwnd_unfocus_event(void *);
     68static void dwnd_unfocus_event(void *, unsigned);
    6669
    6770static display_wnd_cb_t dwnd_cb = {
     
    7477};
    7578
     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 *);
    7686static void wd_close(ui_wdecor_t *, void *);
    77 static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *);
     87static void wd_move(ui_wdecor_t *, void *, gfx_coord2_t *, sysarg_t);
    7888static void wd_resize(ui_wdecor_t *, void *, ui_wdecor_rsztype_t,
    79     gfx_coord2_t *);
     89    gfx_coord2_t *, sysarg_t);
    8090static void wd_set_cursor(ui_wdecor_t *, void *, ui_stock_cursor_t);
    8191
    8292static 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,
    83100        .close = wd_close,
    84101        .move = wd_move,
     
    86103        .set_cursor = wd_set_cursor
    87104};
     105
     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 *);
    88122
    89123static void ui_window_invalidate(void *, gfx_rect_t *);
     
    132166/** Compute where window should be placed on the screen.
    133167 *
    134  * This only applies to windows that do not use default placement.
    135  *
    136  * @param window Window
    137  * @param display Display
    138  * @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
     173 * @param wrect Window rectangle
     174 * @param prect Parent rectangle for popup placement or @c NULL
     175 * @param placement Window placement
    139176 * @param params Window parameters
    140177 * @param pos Place to store position of top-left corner
    141178 */
    142 static void ui_window_place(ui_window_t *window, display_t *display,
    143     display_info_t *info, ui_wnd_params_t *params, gfx_coord2_t *pos)
    144 {
    145         assert(params->placement != ui_wnd_place_default);
     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));
    146189
    147190        pos->x = 0;
    148191        pos->y = 0;
    149192
    150         switch (params->placement) {
     193        switch (placement) {
    151194        case ui_wnd_place_default:
    152                 assert(false);
     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;
    153203        case ui_wnd_place_top_left:
    154204        case ui_wnd_place_full_screen:
    155                 pos->x = info->rect.p0.x - params->rect.p0.x;
    156                 pos->y = info->rect.p0.y - params->rect.p0.y;
     205                pos->x = drect->p0.x - wrect->p0.x;
     206                pos->y = drect->p0.y - wrect->p0.y;
    157207                break;
    158208        case ui_wnd_place_top_right:
    159                 pos->x = info->rect.p1.x - params->rect.p1.x;
    160                 pos->y = info->rect.p0.y - params->rect.p0.y;
     209                pos->x = drect->p1.x - wrect->p1.x;
     210                pos->y = drect->p0.y - wrect->p0.y;
    161211                break;
    162212        case ui_wnd_place_bottom_left:
    163                 pos->x = info->rect.p0.x - params->rect.p0.x;
    164                 pos->y = info->rect.p1.y - params->rect.p1.y;
     213                pos->x = drect->p0.x - wrect->p0.x;
     214                pos->y = drect->p1.y - wrect->p1.y;
    165215                break;
    166216        case ui_wnd_place_bottom_right:
    167                 pos->x = info->rect.p1.x - params->rect.p1.x;
    168                 pos->y = info->rect.p1.y - params->rect.p1.y;
     217                pos->x = drect->p1.x - wrect->p1.x;
     218                pos->y = drect->p1.y - wrect->p1.y;
    169219                break;
    170220        case ui_wnd_place_popup:
    171                 /* Place popup window below parent rectangle */
    172                 pos->x = params->prect.p0.x;
    173                 pos->y = params->prect.p1.y;
     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                }
    174237                break;
    175238        }
     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;
    176320}
    177321
     
    187331{
    188332        ui_window_t *window;
     333        ui_window_t *pwindow = NULL;
    189334        display_info_t info;
    190335        gfx_coord2_t scr_dims;
     
    197342        gfx_bitmap_alloc_t alloc;
    198343        gfx_bitmap_t *bmp = NULL;
     344        gfx_coord2_t off;
    199345        mem_gc_t *memgc = NULL;
     346        xlate_gc_t *xgc = NULL;
     347        gfx_coord2_t dpos;
    200348        errno_t rc;
    201349
     
    204352                return ENOMEM;
    205353
     354        window->ui = ui;
     355
    206356        display_wnd_params_init(&dparams);
    207357        dparams.rect = params->rect;
    208         /* Only allow making the window larger */
    209         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;
    210370
    211371        if ((params->flags & ui_wndf_popup) != 0)
    212372                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;
    213381
    214382        if (ui->display != NULL) {
     
    228396                if (params->placement != ui_wnd_place_default) {
    229397                        /* Set initial display window position */
    230                         ui_window_place(window, ui->display, &info,
    231                             params, &dparams.pos);
     398                        ui_window_place(window, &info.rect, &params->rect,
     399                            &params->prect, params->placement, &dparams.pos);
    232400
    233401                        dparams.flags |= wndf_setpos;
     
    244412        } else if (ui->console != NULL) {
    245413                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                }
    246423        } else {
    247424                /* Needed for unit tests */
     
    263440
    264441        /* Move rectangle so that top-left corner is 0,0 */
    265         gfx_rect_rtranslate(&params->rect.p0, &params->rect, &bparams.rect);
     442        gfx_rect_rtranslate(&dparams.rect.p0, &dparams.rect, &bparams.rect);
    266443
    267444        rc = gfx_bitmap_create(gc, &bparams, NULL, &bmp);
     
    287464        window->gc = mem_gc_get_ctx(memgc);
    288465        window->realgc = gc;
     466        (void) off;
    289467#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
    290486        (void) ui_window_mem_gc_cb;
    291487        (void) alloc;
    292488        (void) bparams;
    293         window->gc = gc;
    294489#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        }
    295495
    296496        rc = ui_resource_create(window->gc, ui_is_textmode(ui), &res);
     
    308508        ui_resource_set_expose_cb(res, ui_window_expose_cb, (void *) window);
    309509
    310         window->ui = ui;
    311510        window->rect = dparams.rect;
    312 
    313511        window->res = res;
    314512        window->wdecor = wdecor;
    315513        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
    316520        *rwindow = window;
    317521
     522        if (ui_is_fullscreen(ui))
     523                pwindow = ui_window_get_active(ui);
     524
    318525        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
    319533        return EOK;
    320534error:
     
    325539        if (memgc != NULL)
    326540                mem_gc_delete(memgc);
     541        if (xgc != NULL)
     542                xlate_gc_delete(xgc);
    327543        if (bmp != NULL)
    328544                gfx_bitmap_destroy(bmp);
     
    333549}
    334550
     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
    335565/** Destroy window.
    336566 *
     
    340570{
    341571        ui_t *ui;
     572        ui_window_t *nwindow;
    342573
    343574        if (window == NULL)
     
    348579        list_remove(&window->lwindows);
    349580        ui_control_destroy(window->control);
     581        ui_menu_destroy(window->sysmenu);
    350582        ui_wdecor_destroy(window->wdecor);
    351583        ui_resource_destroy(window->res);
    352         if (0 && window->app_mgc != NULL)
     584        if (window->app_mgc != NULL)
    353585                mem_gc_delete(window->app_mgc);
    354         if (0 && window->app_bmp != NULL)
     586        if (window->app_bmp != NULL)
    355587                gfx_bitmap_destroy(window->app_bmp);
    356588        if (window->mgc != NULL) {
     
    360592        if (window->bmp != NULL)
    361593                gfx_bitmap_destroy(window->bmp);
    362         gfx_context_delete(window->gc);
    363594        if (window->dwindow != NULL)
    364595                display_window_destroy(window->dwindow);
    365596
    366         free(window);
    367 
    368597        /* Need to repaint if windows are emulated */
    369598        if (ui_is_fullscreen(ui)) {
    370                 ui_paint(ui);
    371         }
     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
     611        free(window);
    372612}
    373613
     
    379619 * @param window Window
    380620 * @param control Control
    381  * @return EOK on success, ENOMEM if out of memory
    382621 */
    383622void ui_window_add(ui_window_t *window, ui_control_t *control)
     
    401640        window->control = NULL;
    402641        control->elemp = NULL;
     642}
     643
     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);
    403674}
    404675
     
    419690}
    420691
    421 /** Resize/move window.
    422  *
    423  * Resize window to the dimensions of @a rect. If @a rect.p0 is not 0,0,
    424  * the top-left corner of the window will move on the screen accordingly.
     692/** Resize or (un)maximize window.
    425693 *
    426694 * @param window Window
    427695 * @param rect Rectangle
     696 * @param scop Size change operation
    428697 *
    429698 * @return EOK on success or an error code
    430699 */
    431 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)
    432702{
    433703        gfx_coord2_t offs;
     
    440710        gfx_bitmap_alloc_t app_alloc;
    441711        gfx_bitmap_alloc_t win_alloc;
     712        gfx_coord2_t dpos;
    442713        errno_t rc;
    443714
     
    495766        }
    496767
    497         /* dwindow can be NULL in case of unit tests */
     768        /* dwindow can be NULL in case of unit tests or fullscreen mode */
    498769        if (window->dwindow != NULL) {
    499                 rc = display_window_resize(window->dwindow, &offs, &nrect);
    500                 if (rc != EOK)
    501                         goto error;
     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                }
    502803        }
    503804
     
    507808                /* Window is resized, now we can map the window bitmap again */
    508809                gfx_bitmap_params_init(&win_params);
    509                 win_params.flags |= bmpf_direct_output;
     810                if (window->ui->display != NULL)
     811                        win_params.flags |= bmpf_direct_output;
    510812                win_params.rect = nrect;
    511813
     
    519821                        goto error;
    520822#endif
    521 
    522823                mem_gc_retarget(window->mgc, &win_params.rect, &win_alloc);
    523824
     
    526827        }
    527828
     829        window->rect = nrect;
    528830        ui_wdecor_set_rect(window->wdecor, &nrect);
    529831        ui_wdecor_paint(window->wdecor);
     
    536838                gfx_bitmap_destroy(window->app_bmp);
    537839                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;
    538851        }
    539852
     
    547860}
    548861
     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
    549887/** Set window callbacks.
    550888 *
     
    557895        window->cb = cb;
    558896        window->arg = arg;
     897}
     898
     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;
    559936}
    560937
     
    594971                        return rc;
    595972        } else {
    596                 pos->x = 0;
    597                 pos->y = 0;
     973                *pos = window->dpos;
    598974        }
    599975
     
    6951071{
    6961072        ui_window_t *window = (ui_window_t *) arg;
    697 
     1073        ui_t *ui = window->ui;
     1074
     1075        fibril_mutex_lock(&ui->lock);
    6981076        ui_window_send_close(window);
     1077        fibril_mutex_unlock(&ui->lock);
    6991078}
    7001079
    7011080/** Handle window focus event. */
    702 static void dwnd_focus_event(void *arg)
    703 {
    704         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;
    7051088
    7061089        if (window->wdecor != NULL) {
     
    7091092        }
    7101093
    711         ui_window_send_focus(window);
     1094        ui_window_send_focus(window, nfocus);
     1095        fibril_mutex_unlock(&ui->lock);
    7121096}
    7131097
     
    7161100{
    7171101        ui_window_t *window = (ui_window_t *) arg;
    718 
    719         (void) window;
     1102        ui_t *ui = window->ui;
     1103
     1104        fibril_mutex_lock(&ui->lock);
    7201105        ui_window_send_kbd(window, kbd_event);
     1106        fibril_mutex_unlock(&ui->lock);
    7211107}
    7221108
     
    7251111{
    7261112        ui_window_t *window = (ui_window_t *) arg;
     1113        ui_t *ui = window->ui;
     1114        ui_evclaim_t claim;
    7271115
    7281116        /* Make sure we don't process events until fully initialized */
     
    7301118                return;
    7311119
    732         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
    7331128        ui_window_send_pos(window, event);
     1129        fibril_mutex_unlock(&ui->lock);
    7341130}
    7351131
     
    7381134{
    7391135        ui_window_t *window = (ui_window_t *) arg;
     1136        ui_t *ui = window->ui;
    7401137
    7411138        /* Make sure we don't process events until fully initialized */
     
    7461143                return;
    7471144
     1145        fibril_mutex_lock(&ui->lock);
    7481146        (void) ui_window_resize(window, rect);
    749         (void) ui_window_paint(window);
     1147        ui_window_send_resize(window);
     1148        fibril_mutex_unlock(&ui->lock);
    7501149}
    7511150
    7521151/** Handle window unfocus event. */
    753 static void dwnd_unfocus_event(void *arg)
    754 {
    755         ui_window_t *window = (ui_window_t *) arg;
    756 
    757         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) {
    7581160                ui_wdecor_set_active(window->wdecor, false);
    7591161                ui_wdecor_paint(window->wdecor);
    7601162        }
    7611163
    762         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);
    7631268}
    7641269
     
    7801285 * @param arg Argument (window)
    7811286 * @param pos Position where the title bar was pressed
    782  */
    783 static void wd_move(ui_wdecor_t *wdecor, void *arg, gfx_coord2_t *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)
    7841291{
    7851292        ui_window_t *window = (ui_window_t *) arg;
    7861293
    7871294        if (window->dwindow != NULL)
    788                 (void) display_window_move_req(window->dwindow, pos);
     1295                (void) display_window_move_req(window->dwindow, pos, pos_id);
    7891296}
    7901297
     
    7951302 * @param rsztype Resize type
    7961303 * @param pos Position where the button was pressed
     1304 * @param pos_id Positioning device ID
    7971305 */
    7981306static void wd_resize(ui_wdecor_t *wdecor, void *arg,
    799     ui_wdecor_rsztype_t rsztype, gfx_coord2_t *pos)
    800 {
    801         ui_window_t *window = (ui_window_t *) arg;
    802 
    803         if (window->dwindow != NULL)
    804                 (void) display_window_resize_req(window->dwindow, rsztype, pos);
     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        }
    8051316}
    8061317
     
    8631374}
    8641375
     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);
     1423}
     1424
    8651425/** Send window close event.
    8661426 *
     
    8761436 *
    8771437 * @param window Window
    878  */
    879 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)
    8801441{
    8811442        if (window->cb != NULL && window->cb->focus != NULL)
    882                 window->cb->focus(window, window->arg);
     1443                window->cb->focus(window, window->arg, nfocus);
    8831444}
    8841445
     
    8921453                window->cb->kbd(window, window->arg, kbd);
    8931454        else
    894                 return ui_window_def_kbd(window, kbd);
     1455                ui_window_def_kbd(window, kbd);
    8951456}
    8961457
     
    9221483 *
    9231484 * @param window Window
    924  */
    925 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)
    9261488{
    9271489        if (window->cb != NULL && window->cb->unfocus != NULL)
    928                 window->cb->unfocus(window, window->arg);
     1490                window->cb->unfocus(window, window->arg, nfocus);
    9291491        else
    930                 return ui_window_def_unfocus(window);
     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;
    9311623}
    9321624
     
    9341626 *
    9351627 * @param window Window
    936  */
    937 void ui_window_def_kbd(ui_window_t *window, kbd_event_t *kbd)
    938 {
     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
    9391634        if (window->control != NULL)
    940                 ui_control_kbd_event(window->control, kbd);
     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;
    9411643}
    9421644
     
    9841686 *
    9851687 * @param window Window
     1688 * @param nfocus Number of remaining foci
    9861689 * @return EOK on success or an error code
    9871690 */
    988 void ui_window_def_unfocus(ui_window_t *window)
     1691void ui_window_def_unfocus(ui_window_t *window, unsigned nfocus)
    9891692{
    9901693        if (window->control != NULL)
    991                 ui_control_unfocus(window->control);
     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;
    9921816}
    9931817
     
    10141838        ui_window_t *window = (ui_window_t *) arg;
    10151839
    1016         if (!gfx_rect_is_empty(&window->dirty_rect))
    1017                 (void) gfx_bitmap_render(window->bmp, &window->dirty_rect, NULL);
     1840        if (!gfx_rect_is_empty(&window->dirty_rect)) {
     1841                (void) gfx_bitmap_render(window->bmp, &window->dirty_rect,
     1842                    &window->dpos);
     1843        }
    10181844
    10191845        window->dirty_rect.p0.x = 0;
     
    10311857{
    10321858        ui_window_t *window = (ui_window_t *) arg;
    1033 
    1034         return gfx_cursor_get_pos(window->realgc, pos);
     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;
    10351869}
    10361870
     
    10431877{
    10441878        ui_window_t *window = (ui_window_t *) arg;
    1045 
    1046         return gfx_cursor_set_pos(window->realgc, pos);
     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);
    10471885}
    10481886
Note: See TracChangeset for help on using the changeset viewer.