Changeset 1af103e in mainline


Ignore:
Timestamp:
2023-09-13T17:29:07Z (16 months ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
61643c8
Parents:
46bd63c9
Message:

System menu (WIP)

The system menu provides browsable, keyboard-accessible access to window
management functions (such as closing, minimizing, maximizing, resizing,
moving).

Location:
uspace/lib/ui
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ui/include/types/ui/wdecor.h

    r46bd63c9 r1af103e  
    3838
    3939#include <gfx/coord.h>
     40#include <types/common.h>
    4041#include <types/ui/cursor.h>
    4142
     
    5152        /** Window has a title bar */
    5253        ui_wds_titlebar = 0x2,
     54        /** Window has a system menu */
     55        ui_wds_sysmenu = 0x4,
    5356        /** Window has a minimize button */
    54         ui_wds_minimize_btn = 0x4,
     57        ui_wds_minimize_btn = 0x8,
    5558        /** Window has a maximize button */
    56         ui_wds_maximize_btn = 0x8,
     59        ui_wds_maximize_btn = 0x10,
    5760        /** Window has a close button */
    58         ui_wds_close_btn = 0x10,
     61        ui_wds_close_btn = 0x20,
    5962        /** Window is resizable */
    60         ui_wds_resizable = 0x20,
     63        ui_wds_resizable = 0x40,
    6164        /** Window is decorated (default decoration) */
    62         ui_wds_decorated = ui_wds_frame | ui_wds_titlebar |
     65        ui_wds_decorated = ui_wds_frame | ui_wds_titlebar | ui_wds_sysmenu |
    6366            ui_wds_minimize_btn | ui_wds_close_btn
    6467} ui_wdecor_style_t;
     
    8184/** Window decoration callbacks */
    8285typedef struct ui_wdecor_cb {
     86        void (*sysmenu)(ui_wdecor_t *, void *, sysarg_t);
    8387        void (*minimize)(ui_wdecor_t *, void *);
    8488        void (*maximize)(ui_wdecor_t *, void *);
  • uspace/lib/ui/include/types/ui/window.h

    r46bd63c9 r1af103e  
    4040#include <io/kbd_event.h>
    4141#include <io/pos_event.h>
     42#include <types/common.h>
    4243#include <types/ui/wdecor.h>
    4344
     
    9596/** Window callbacks */
    9697typedef struct ui_window_cb {
     98        void (*sysmenu)(ui_window_t *, void *, sysarg_t);
    9799        void (*minimize)(ui_window_t *, void *);
    98100        void (*maximize)(ui_window_t *, void *);
  • uspace/lib/ui/include/ui/wdecor.h

    r46bd63c9 r1af103e  
    11/*
    2  * Copyright (c) 2022 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939#include <errno.h>
    4040#include <gfx/coord.h>
     41#include <io/kbd_event.h>
    4142#include <io/pos_event.h>
    4243#include <stdbool.h>
     
    5455extern errno_t ui_wdecor_set_caption(ui_wdecor_t *, const char *);
    5556extern errno_t ui_wdecor_paint(ui_wdecor_t *);
     57extern ui_evclaim_t ui_wdecor_kbd_event(ui_wdecor_t *, kbd_event_t *);
    5658extern ui_evclaim_t ui_wdecor_pos_event(ui_wdecor_t *, pos_event_t *);
    5759extern void ui_wdecor_rect_from_app(ui_wdecor_style_t, gfx_rect_t *,
  • uspace/lib/ui/include/ui/window.h

    r46bd63c9 r1af103e  
    4242#include <io/kbd_event.h>
    4343#include <io/pos_event.h>
     44#include <types/common.h>
    4445#include <types/ui/control.h>
    4546#include <types/ui/ui.h>
     
    6566extern void ui_window_set_ctl_cursor(ui_window_t *, ui_stock_cursor_t);
    6667extern errno_t ui_window_paint(ui_window_t *);
     68extern errno_t ui_window_def_sysmenu(ui_window_t *, sysarg_t);
    6769extern errno_t ui_window_def_minimize(ui_window_t *);
    6870extern errno_t ui_window_def_maximize(ui_window_t *);
  • uspace/lib/ui/private/wdecor.h

    r46bd63c9 r1af103e  
    4141#include <io/pos_event.h>
    4242#include <stdbool.h>
     43#include <types/common.h>
    4344#include <types/ui/cursor.h>
    4445#include <types/ui/wdecor.h>
     
    9495} ui_wdecor_geom_t;
    9596
     97extern void ui_wdecor_sysmenu(ui_wdecor_t *, sysarg_t);
    9698extern void ui_wdecor_minimize(ui_wdecor_t *);
    9799extern void ui_wdecor_maximize(ui_wdecor_t *);
  • uspace/lib/ui/private/window.h

    r46bd63c9 r1af103e  
    4747#include <memgfx/memgc.h>
    4848#include <memgfx/xlategc.h>
     49#include <types/common.h>
    4950#include <types/ui/cursor.h>
    5051#include <types/ui/window.h>
     
    9394        /** Window decoration */
    9495        struct ui_wdecor *wdecor;
     96        /** System menu */
     97        struct ui_menu *sysmenu;
    9598        /** Top-level control in the application area */
    9699        struct ui_control *control;
     
    112115
    113116extern display_stock_cursor_t wnd_dcursor_from_cursor(ui_stock_cursor_t);
     117extern void ui_window_send_sysmenu(ui_window_t *, sysarg_t);
    114118extern void ui_window_send_minimize(ui_window_t *);
    115119extern void ui_window_send_maximize(ui_window_t *);
  • uspace/lib/ui/src/wdecor.c

    r46bd63c9 r1af103e  
    421421}
    422422
     423/** Send decoration sysmenu event.
     424 *
     425 * @param wdecor Window decoration
     426 * @param idev_id Input device ID
     427 */
     428void ui_wdecor_sysmenu(ui_wdecor_t *wdecor, sysarg_t idev_id)
     429{
     430        if (wdecor->cb != NULL && wdecor->cb->sysmenu != NULL)
     431                wdecor->cb->sysmenu(wdecor, wdecor->arg, idev_id);
     432}
     433
    423434/** Send decoration minimize event.
    424435 *
     
    805816}
    806817
     818/** Handle window decoration keyboard event.
     819 *
     820 * @param wdecor Window decoration
     821 * @param kbd_event Keyboard event
     822 * @return @c ui_claimed iff event was claimed
     823 */
     824ui_evclaim_t ui_wdecor_kbd_event(ui_wdecor_t *wdecor, kbd_event_t *event)
     825{
     826        (void)wdecor;
     827
     828        if (event->type == KEY_PRESS && (event->mods & (KM_CTRL | KM_ALT |
     829            KM_SHIFT)) == 0) {
     830                if (event->key == KC_F9)
     831                        ui_wdecor_sysmenu(wdecor, event->kbd_id);
     832        }
     833
     834        return ui_unclaimed;
     835}
     836
    807837/** Handle window frame position event.
    808838 *
  • uspace/lib/ui/src/window.c

    r46bd63c9 r1af103e  
    4747#include <stdlib.h>
    4848#include <ui/control.h>
     49#include <ui/menu.h>
     50#include <ui/menuentry.h>
    4951#include <ui/resource.h>
    5052#include <ui/ui.h>
     
    7476};
    7577
     78static void wd_sysmenu(ui_wdecor_t *, void *, sysarg_t);
    7679static void wd_minimize(ui_wdecor_t *, void *);
    7780static void wd_maximize(ui_wdecor_t *, void *);
     
    8487
    8588static ui_wdecor_cb_t wdecor_cb = {
     89        .sysmenu = wd_sysmenu,
    8690        .minimize = wd_minimize,
    8791        .maximize = wd_maximize,
     
    9296        .set_cursor = wd_set_cursor
    9397};
     98
     99static void wnd_sysmenu_left(ui_menu_t *, void *, sysarg_t);
     100static void wnd_sysmenu_right(ui_menu_t *, void *, sysarg_t);
     101static void wnd_sysmenu_close_req(ui_menu_t *, void *);
     102static void wnd_sysmenu_press_accel(ui_menu_t *, void *, char32_t, sysarg_t);
     103
     104static ui_menu_cb_t wnd_sysmenu_cb = {
     105        .left = wnd_sysmenu_left,
     106        .right = wnd_sysmenu_right,
     107        .close_req = wnd_sysmenu_close_req,
     108        .press_accel = wnd_sysmenu_press_accel
     109};
     110
     111static void wnd_sysmenu_eclose(ui_menu_entry_t *, void *);
    94112
    95113static void ui_window_invalidate(void *, gfx_rect_t *);
     
    417435        list_remove(&window->lwindows);
    418436        ui_control_destroy(window->control);
     437        ui_menu_destroy(window->sysmenu);
    419438        ui_wdecor_destroy(window->wdecor);
    420439        ui_resource_destroy(window->res);
     
    929948}
    930949
     950/** Window decoration requested opening of system menu.
     951 *
     952 * @param wdecor Window decoration
     953 * @param arg Argument (window)
     954 * @param idev_id Input device ID
     955 */
     956static void wd_sysmenu(ui_wdecor_t *wdecor, void *arg, sysarg_t idev_id)
     957{
     958        ui_window_t *window = (ui_window_t *) arg;
     959
     960        ui_window_send_sysmenu(window, idev_id);
     961}
     962
    931963/** Window decoration requested window minimization.
    932964 *
     
    10701102}
    10711103
     1104/** Send window sysmenu event.
     1105 *
     1106 * @param window Window
     1107 * @parma idev_id Input device ID
     1108 */
     1109void ui_window_send_sysmenu(ui_window_t *window, sysarg_t idev_id)
     1110{
     1111        if (window->cb != NULL && window->cb->sysmenu != NULL)
     1112                window->cb->sysmenu(window, window->arg, idev_id);
     1113        else
     1114                ui_window_def_sysmenu(window, idev_id);
     1115}
     1116
    10721117/** Send window minimize event.
    10731118 *
     
    11741219        else
    11751220                return ui_window_def_unfocus(window, nfocus);
     1221}
     1222
     1223/** Default window sysmenu routine.
     1224 *
     1225 * @param window Window
     1226 * @param idev_id Input device ID
     1227 * @return EOK on success or an error code
     1228 */
     1229errno_t ui_window_def_sysmenu(ui_window_t *window, sysarg_t idev_id)
     1230{
     1231        errno_t rc;
     1232        ui_menu_entry_t *mclose;
     1233        ui_wdecor_geom_t geom;
     1234
     1235        if (window->sysmenu == NULL) {
     1236                rc = ui_menu_create(window, &window->sysmenu);
     1237                if (rc != EOK)
     1238                        goto error;
     1239
     1240                ui_menu_set_cb(window->sysmenu, &wnd_sysmenu_cb,
     1241                    (void *)window);
     1242
     1243                rc = ui_menu_entry_create(window->sysmenu, "~C~lose", "Alt-F4",
     1244                    &mclose);
     1245                if (rc != EOK)
     1246                        goto error;
     1247
     1248                ui_menu_entry_set_cb(mclose, wnd_sysmenu_eclose,
     1249                    (void *)window);
     1250        }
     1251
     1252        if (ui_menu_is_open(window->sysmenu)) {
     1253                ui_menu_close(window->sysmenu);
     1254        } else {
     1255                ui_wdecor_get_geom(window->wdecor, &geom);
     1256
     1257                rc = ui_menu_open(window->sysmenu, &geom.title_bar_rect,
     1258                    idev_id);
     1259                if (rc != EOK)
     1260                        goto error;
     1261        }
     1262
     1263        return EOK;
     1264error:
     1265        return rc;
    11761266}
    11771267
     
    12601350ui_evclaim_t ui_window_def_kbd(ui_window_t *window, kbd_event_t *kbd)
    12611351{
     1352        ui_evclaim_t claim;
     1353
    12621354        if (window->control != NULL)
    1263                 return ui_control_kbd_event(window->control, kbd);
     1355                claim = ui_control_kbd_event(window->control, kbd);
     1356        else
     1357                claim = ui_unclaimed;
     1358
     1359        if (claim == ui_unclaimed)
     1360                return ui_wdecor_kbd_event(window->wdecor, kbd);
    12641361
    12651362        return ui_unclaimed;
     
    13161413        if (window->control != NULL)
    13171414                ui_control_unfocus(window->control, nfocus);
     1415}
     1416
     1417/** Handle system menu left event.
     1418 *
     1419 * @param sysmenu System menu
     1420 * @param arg Argument (ui_window_t *)
     1421 * @param idev_id Input device ID
     1422 */
     1423static void wnd_sysmenu_left(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
     1424{
     1425        (void)sysmenu;
     1426        (void)arg;
     1427        (void)idev_id;
     1428}
     1429
     1430/** Handle system menu right event.
     1431 *
     1432 * @param sysmenu System menu
     1433 * @param arg Argument (ui_window_t *)
     1434 * @param idev_id Input device ID
     1435 */
     1436static void wnd_sysmenu_right(ui_menu_t *sysmenu, void *arg, sysarg_t idev_id)
     1437{
     1438        (void)sysmenu;
     1439        (void)arg;
     1440        (void)idev_id;
     1441}
     1442
     1443/** Handle system menu close request event.
     1444 *
     1445 * @param sysmenu System menu
     1446 * @param arg Argument (ui_window_t *)
     1447 * @param idev_id Input device ID
     1448 */
     1449static void wnd_sysmenu_close_req(ui_menu_t *sysmenu, void *arg)
     1450{
     1451        (void)arg;
     1452
     1453        ui_menu_close(sysmenu);
     1454}
     1455
     1456/** Handle system menu Close entry activation.
     1457 *
     1458 * @param mentry Menu entry
     1459 * @param arg Argument (ui_window_t *)
     1460 */
     1461static void wnd_sysmenu_eclose(ui_menu_entry_t *mentry, void *arg)
     1462{
     1463        ui_window_t *window = (ui_window_t *)arg;
     1464
     1465        ui_window_send_close(window);
     1466}
     1467
     1468/** Handle system menu press accelerator key event.
     1469 *
     1470 * @param sysmenu System menu
     1471 * @param arg Argument (ui_window_t *)
     1472 * @param idev_id Input device ID
     1473 */
     1474static void wnd_sysmenu_press_accel(ui_menu_t *sysmenu, void *arg,
     1475    char32_t c, sysarg_t idev_id)
     1476{
     1477        (void)sysmenu;
     1478        (void)arg;
     1479        (void)c;
     1480        (void)idev_id;
    13181481}
    13191482
  • uspace/lib/ui/test/wdecor.c

    r46bd63c9 r1af103e  
    6262};
    6363
     64static void test_wdecor_sysmenu(ui_wdecor_t *, void *, sysarg_t);
    6465static void test_wdecor_minimize(ui_wdecor_t *, void *);
    6566static void test_wdecor_maximize(ui_wdecor_t *, void *);
     
    7273
    7374static ui_wdecor_cb_t test_wdecor_cb = {
     75        .sysmenu = test_wdecor_sysmenu,
    7476        .minimize = test_wdecor_minimize,
    7577        .maximize = test_wdecor_maximize,
     
    102104
    103105typedef struct {
     106        bool sysmenu;
    104107        bool minimize;
    105108        bool maximize;
     
    109112        gfx_coord2_t pos;
    110113        sysarg_t pos_id;
     114        sysarg_t idev_id;
    111115        bool resize;
    112116        ui_wdecor_rsztype_t rsztype;
     
    241245        rc = gfx_context_delete(gc);
    242246        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     247}
     248
     249/** Test ui_wdecor_sysmenu() */
     250PCUT_TEST(sysmenu)
     251{
     252        errno_t rc;
     253        ui_wdecor_t *wdecor;
     254        test_cb_resp_t resp;
     255
     256        rc = ui_wdecor_create(NULL, "Hello", ui_wds_none, &wdecor);
     257        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     258
     259        /* Sysmenu callback with no callbacks set */
     260        ui_wdecor_sysmenu(wdecor, 42);
     261
     262        /* Sysmenu callback with sysmenu callback not implemented */
     263        ui_wdecor_set_cb(wdecor, &dummy_wdecor_cb, NULL);
     264        ui_wdecor_sysmenu(wdecor, 42);
     265
     266        /* Sysmenu callback with real callback set */
     267        resp.sysmenu = false;
     268        resp.idev_id = 0;
     269        ui_wdecor_set_cb(wdecor, &test_wdecor_cb, &resp);
     270        ui_wdecor_sysmenu(wdecor, 42);
     271        PCUT_ASSERT_TRUE(resp.sysmenu);
     272        PCUT_ASSERT_INT_EQUALS(42, resp.idev_id);
     273
     274        ui_wdecor_destroy(wdecor);
    243275}
    244276
     
    544576        PCUT_ASSERT_INT_EQUALS(event.hpos, resp.pos.x);
    545577        PCUT_ASSERT_INT_EQUALS(event.vpos, resp.pos.y);
     578
     579        ui_wdecor_destroy(wdecor);
     580        ui_resource_destroy(resource);
     581
     582        rc = gfx_context_delete(gc);
     583        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     584}
     585
     586/** Pressing F9 generates sysmenu event */
     587PCUT_TEST(kbd_f9_sysmenu)
     588{
     589        errno_t rc;
     590        gfx_rect_t rect;
     591        kbd_event_t event;
     592        gfx_context_t *gc = NULL;
     593        test_gc_t tgc;
     594        test_cb_resp_t resp;
     595        ui_resource_t *resource = NULL;
     596        ui_wdecor_t *wdecor;
     597
     598        memset(&tgc, 0, sizeof(tgc));
     599        rc = gfx_context_new(&ops, &tgc, &gc);
     600        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     601
     602        rc = ui_resource_create(gc, false, &resource);
     603        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     604        PCUT_ASSERT_NOT_NULL(resource);
     605
     606        rc = ui_wdecor_create(resource, "Hello", ui_wds_decorated, &wdecor);
     607        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     608
     609        rect.p0.x = 10;
     610        rect.p0.y = 20;
     611        rect.p1.x = 100;
     612        rect.p1.y = 200;
     613
     614        ui_wdecor_set_rect(wdecor, &rect);
     615
     616        ui_wdecor_set_cb(wdecor, &test_wdecor_cb, (void *) &resp);
     617
     618        resp.move = false;
     619        resp.pos.x = 0;
     620        resp.pos.y = 0;
     621
     622        event.type = KEY_PRESS;
     623        event.mods = 0;
     624        event.key = KC_F9;
     625        event.kbd_id = 42;
     626        ui_wdecor_kbd_event(wdecor, &event);
     627
     628        PCUT_ASSERT_TRUE(resp.sysmenu);
     629        PCUT_ASSERT_INT_EQUALS(event.kbd_id, resp.idev_id);
    546630
    547631        ui_wdecor_destroy(wdecor);
     
    11111195}
    11121196
     1197static void test_wdecor_sysmenu(ui_wdecor_t *wdecor, void *arg,
     1198    sysarg_t idev_id)
     1199{
     1200        test_cb_resp_t *resp = (test_cb_resp_t *) arg;
     1201
     1202        resp->sysmenu = true;
     1203        resp->idev_id = idev_id;
     1204}
     1205
    11131206static void test_wdecor_minimize(ui_wdecor_t *wdecor, void *arg)
    11141207{
  • uspace/lib/ui/test/window.c

    r46bd63c9 r1af103e  
    4545PCUT_TEST_SUITE(window);
    4646
     47static void test_window_sysmenu(ui_window_t *, void *, sysarg_t);
    4748static void test_window_minimize(ui_window_t *, void *);
    4849static void test_window_maximize(ui_window_t *, void *);
     
    5657
    5758static ui_window_cb_t test_window_cb = {
     59        .sysmenu = test_window_sysmenu,
    5860        .minimize = test_window_minimize,
    5961        .maximize = test_window_maximize,
     
    8284typedef struct {
    8385        errno_t rc;
     86        bool sysmenu;
     87        sysarg_t sysmenu_idev_id;
    8488        bool minimize;
    8589        bool maximize;
     
    544548}
    545549
     550/** ui_window_send_sysmenu() calls sysmenu callback set via ui_window_set_cb() */
     551PCUT_TEST(send_sysmenu)
     552{
     553        errno_t rc;
     554        ui_t *ui = NULL;
     555        ui_wnd_params_t params;
     556        ui_window_t *window = NULL;
     557        test_cb_resp_t resp;
     558
     559        rc = ui_create_disp(NULL, &ui);
     560        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     561
     562        ui_wnd_params_init(&params);
     563        params.caption = "Hello";
     564
     565        rc = ui_window_create(ui, &params, &window);
     566        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     567        PCUT_ASSERT_NOT_NULL(window);
     568
     569        /* Sysmenu callback with no callbacks set */
     570        ui_window_send_sysmenu(window, 42);
     571
     572        /* Sysmenu callback with sysmenu callback not implemented */
     573        ui_window_set_cb(window, &dummy_window_cb, NULL);
     574        ui_window_send_sysmenu(window, 42);
     575
     576        /* Sysmenu callback with real callback set */
     577        resp.sysmenu = false;
     578        resp.sysmenu_idev_id = 0;
     579        ui_window_set_cb(window, &test_window_cb, &resp);
     580        ui_window_send_sysmenu(window, 42);
     581        PCUT_ASSERT_TRUE(resp.sysmenu);
     582        PCUT_ASSERT_INT_EQUALS(42, resp.sysmenu_idev_id);
     583
     584        ui_window_destroy(window);
     585        ui_destroy(ui);
     586}
     587
    546588/** ui_window_send_minimize() calls minimize callback set via ui_window_set_cb() */
    547589PCUT_TEST(send_minimize)
     
    894936}
    895937
     938static void test_window_sysmenu(ui_window_t *window, void *arg, sysarg_t idev_id)
     939{
     940        test_cb_resp_t *resp = (test_cb_resp_t *) arg;
     941
     942        resp->sysmenu = true;
     943        resp->sysmenu_idev_id = idev_id;
     944}
     945
    896946static void test_window_minimize(ui_window_t *window, void *arg)
    897947{
Note: See TracChangeset for help on using the changeset viewer.