Changeset 6baab83 in mainline


Ignore:
Timestamp:
2021-05-27T17:00:30Z (3 years ago)
Author:
Jiri Svoboda <jiri@…>
Children:
b4b4dafe
Parents:
f2416ec3
Message:

Set menu popup position based on parent window position

Added a method for getting the position of a display window.
This is then combined with the menu bar entry rectangle (which is
relative to the parent window) to compute a screen-relative
rectangle close to which the popup should be placed.

Location:
uspace
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/display/include/disp_srv.h

    rf2416ec3 r6baab83  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    6161            gfx_coord2_t *);
    6262        errno_t (*window_move)(void *, sysarg_t, gfx_coord2_t *);
     63        errno_t (*window_get_pos)(void *, sysarg_t, gfx_coord2_t *);
    6364        errno_t (*window_resize)(void *, sysarg_t, gfx_coord2_t *, gfx_rect_t *);
    6465        errno_t (*window_set_cursor)(void *, sysarg_t, display_stock_cursor_t);
  • uspace/lib/display/include/display.h

    rf2416ec3 r6baab83  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    5858    display_wnd_rsztype_t, gfx_coord2_t *);
    5959extern errno_t display_window_move(display_window_t *, gfx_coord2_t *);
     60extern errno_t display_window_get_pos(display_window_t *, gfx_coord2_t *);
    6061extern errno_t display_window_resize(display_window_t *,
    6162    gfx_coord2_t *, gfx_rect_t *);
  • uspace/lib/display/include/ipc/display.h

    rf2416ec3 r6baab83  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    4444        DISPLAY_WINDOW_MOVE,
    4545        DISPLAY_WINDOW_MOVE_REQ,
     46        DISPLAY_WINDOW_GET_POS,
    4647        DISPLAY_WINDOW_RESIZE,
    4748        DISPLAY_WINDOW_RESIZE_REQ,
  • uspace/lib/display/src/disp_srv.c

    rf2416ec3 r6baab83  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    187187}
    188188
     189static void display_window_get_pos_srv(display_srv_t *srv, ipc_call_t *icall)
     190{
     191        sysarg_t wnd_id;
     192        ipc_call_t call;
     193        gfx_coord2_t dpos;
     194        size_t size;
     195        errno_t rc;
     196
     197        wnd_id = ipc_get_arg1(icall);
     198
     199        if (srv->ops->window_get_pos == NULL) {
     200                async_answer_0(icall, ENOTSUP);
     201                return;
     202        }
     203
     204        if (!async_data_read_receive(&call, &size)) {
     205                async_answer_0(icall, EREFUSED);
     206                return;
     207        }
     208
     209        rc = srv->ops->window_get_pos(srv->arg, wnd_id, &dpos);
     210        if (rc != EOK) {
     211                async_answer_0(&call, rc);
     212                async_answer_0(icall, rc);
     213                return;
     214        }
     215
     216        if (size != sizeof(gfx_coord2_t)) {
     217                async_answer_0(&call, EINVAL);
     218                async_answer_0(icall, EINVAL);
     219                return;
     220        }
     221
     222        rc = async_data_read_finalize(&call, &dpos, size);
     223        if (rc != EOK) {
     224                async_answer_0(&call, rc);
     225                async_answer_0(icall, rc);
     226                return;
     227        }
     228
     229        async_answer_0(icall, EOK);
     230}
     231
    189232static void display_window_resize_req_srv(display_srv_t *srv, ipc_call_t *icall)
    190233{
     
    398441                case DISPLAY_WINDOW_MOVE:
    399442                        display_window_move_srv(srv, &call);
     443                        break;
     444                case DISPLAY_WINDOW_GET_POS:
     445                        display_window_get_pos_srv(srv, &call);
    400446                        break;
    401447                case DISPLAY_WINDOW_RESIZE_REQ:
  • uspace/lib/display/src/display.c

    rf2416ec3 r6baab83  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    319319}
    320320
     321/** Get display window position.
     322 *
     323 * Get display window position on the display.
     324 *
     325 * @param window Window
     326 * @param dpos Place to store position
     327 * @return EOK on success or an error code
     328 */
     329errno_t display_window_get_pos(display_window_t *window, gfx_coord2_t *dpos)
     330{
     331        async_exch_t *exch;
     332        aid_t req;
     333        ipc_call_t answer;
     334        errno_t rc;
     335
     336        exch = async_exchange_begin(window->display->sess);
     337        req = async_send_1(exch, DISPLAY_WINDOW_GET_POS, window->id, &answer);
     338        rc = async_data_read_start(exch, dpos, sizeof (gfx_coord2_t));
     339        async_exchange_end(exch);
     340        if (rc != EOK) {
     341                async_forget(req);
     342                return rc;
     343        }
     344
     345        async_wait_for(req, &rc);
     346        if (rc != EOK)
     347                return rc;
     348
     349        return EOK;
     350}
     351
    321352/** Request a window resize.
    322353 *
  • uspace/lib/display/test/display.c

    rf2416ec3 r6baab83  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    5959static errno_t test_window_move_req(void *, sysarg_t, gfx_coord2_t *);
    6060static errno_t test_window_move(void *, sysarg_t, gfx_coord2_t *);
     61static errno_t test_window_get_pos(void *, sysarg_t, gfx_coord2_t *);
    6162static errno_t test_window_resize_req(void *, sysarg_t, display_wnd_rsztype_t,
    6263    gfx_coord2_t *);
     
    7475        .window_move_req = test_window_move_req,
    7576        .window_move = test_window_move,
     77        .window_get_pos = test_window_get_pos,
    7678        .window_resize_req = test_window_resize_req,
    7779        .window_resize = test_window_resize,
     
    115117        sysarg_t move_wnd_id;
    116118        gfx_coord2_t move_dpos;
     119
     120        bool window_get_pos_called;
     121        sysarg_t get_pos_wnd_id;
     122        gfx_coord2_t get_pos_rpos;
    117123
    118124        bool window_resize_req_called;
     
    556562}
    557563
     564/** display_window_get_pos() with server returning error response works. */
     565PCUT_TEST(window_get_pos_failure)
     566{
     567        errno_t rc;
     568        service_id_t sid;
     569        display_t *disp = NULL;
     570        display_wnd_params_t params;
     571        display_window_t *wnd;
     572        gfx_coord2_t dpos;
     573        test_response_t resp;
     574
     575        async_set_fallback_port_handler(test_display_conn, &resp);
     576
     577        // FIXME This causes this test to be non-reentrant!
     578        rc = loc_server_register(test_display_server);
     579        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     580
     581        rc = loc_service_register(test_display_svc, &sid);
     582        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     583
     584        rc = display_open(test_display_svc, &disp);
     585        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     586        PCUT_ASSERT_NOT_NULL(disp);
     587
     588        resp.rc = EOK;
     589        display_wnd_params_init(&params);
     590        params.rect.p0.x = 0;
     591        params.rect.p0.y = 0;
     592        params.rect.p0.x = 100;
     593        params.rect.p0.y = 100;
     594
     595        rc = display_window_create(disp, &params, &test_display_wnd_cb,
     596            (void *) &resp, &wnd);
     597        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     598        PCUT_ASSERT_NOT_NULL(wnd);
     599
     600        resp.rc = EIO;
     601        resp.window_get_pos_called = false;
     602
     603        dpos.x = 0;
     604        dpos.y = 0;
     605
     606        rc = display_window_get_pos(wnd, &dpos);
     607        PCUT_ASSERT_TRUE(resp.window_get_pos_called);
     608        PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
     609        PCUT_ASSERT_INT_EQUALS(wnd->id, resp.get_pos_wnd_id);
     610        PCUT_ASSERT_INT_EQUALS(0, dpos.x);
     611        PCUT_ASSERT_INT_EQUALS(0, dpos.y);
     612
     613        display_window_destroy(wnd);
     614        display_close(disp);
     615        rc = loc_service_unregister(sid);
     616        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     617}
     618
     619/** display_window_get_pos() with server returning success response works. */
     620PCUT_TEST(window_get_pos_success)
     621{
     622        errno_t rc;
     623        service_id_t sid;
     624        display_t *disp = NULL;
     625        display_wnd_params_t params;
     626        display_window_t *wnd;
     627        gfx_coord2_t dpos;
     628        test_response_t resp;
     629
     630        async_set_fallback_port_handler(test_display_conn, &resp);
     631
     632        // FIXME This causes this test to be non-reentrant!
     633        rc = loc_server_register(test_display_server);
     634        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     635
     636        rc = loc_service_register(test_display_svc, &sid);
     637        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     638
     639        rc = display_open(test_display_svc, &disp);
     640        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     641        PCUT_ASSERT_NOT_NULL(disp);
     642
     643        resp.rc = EOK;
     644        display_wnd_params_init(&params);
     645        params.rect.p0.x = 0;
     646        params.rect.p0.y = 0;
     647        params.rect.p0.x = 100;
     648        params.rect.p0.y = 100;
     649
     650        rc = display_window_create(disp, &params, &test_display_wnd_cb,
     651            (void *) &resp, &wnd);
     652        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     653        PCUT_ASSERT_NOT_NULL(wnd);
     654
     655        resp.rc = EOK;
     656        resp.window_get_pos_called = false;
     657        resp.get_pos_rpos.x = 11;
     658        resp.get_pos_rpos.y = 12;
     659
     660        dpos.x = 0;
     661        dpos.y = 0;
     662
     663        rc = display_window_get_pos(wnd, &dpos);
     664        PCUT_ASSERT_TRUE(resp.window_get_pos_called);
     665        PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
     666        PCUT_ASSERT_INT_EQUALS(wnd->id, resp.get_pos_wnd_id);
     667        PCUT_ASSERT_INT_EQUALS(resp.get_pos_rpos.x, dpos.x);
     668        PCUT_ASSERT_INT_EQUALS(resp.get_pos_rpos.y, dpos.y);
     669
     670        display_window_destroy(wnd);
     671        display_close(disp);
     672        rc = loc_service_unregister(sid);
     673        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     674}
     675
    558676/** display_window_resize_req() with server returning error response works. */
    559677PCUT_TEST(window_resize_req_failure)
     
    9371055        resp.rc = ENOMEM;
    9381056        rc = display_window_get_gc(wnd, &gc);
    939         /* async_connect_me_to() does not return specific error */
    940         PCUT_ASSERT_ERRNO_VAL(EIO, rc);
     1057        PCUT_ASSERT_ERRNO_VAL(resp.rc, rc);
    9411058        PCUT_ASSERT_NULL(gc);
    9421059
     
    15891706}
    15901707
     1708static errno_t test_window_get_pos(void *arg, sysarg_t wnd_id, gfx_coord2_t *dpos)
     1709{
     1710        test_response_t *resp = (test_response_t *) arg;
     1711
     1712        resp->window_get_pos_called = true;
     1713        resp->get_pos_wnd_id = wnd_id;
     1714
     1715        if (resp->rc == EOK)
     1716                *dpos = resp->get_pos_rpos;
     1717
     1718        return resp->rc;
     1719}
     1720
    15911721static errno_t test_window_resize_req(void *arg, sysarg_t wnd_id,
    15921722    display_wnd_rsztype_t rsztype, gfx_coord2_t *pos)
  • uspace/lib/ui/include/types/ui/window.h

    rf2416ec3 r6baab83  
    5858        ui_wnd_place_bottom_right,
    5959        /** Place window accross the entire screen */
    60         ui_wnd_place_full_screen
     60        ui_wnd_place_full_screen,
     61        /** Place window as a popup window adjacent to rectangle */
     62        ui_wnd_place_popup
    6163} ui_wnd_placement_t;
    6264
     
    7173        /** Window placement */
    7274        ui_wnd_placement_t placement;
     75        /** Parent rectangle for popup windows */
     76        gfx_rect_t prect;
    7377} ui_wnd_params_t;
    7478
  • uspace/lib/ui/include/ui/window.h

    rf2416ec3 r6baab83  
    5757extern ui_resource_t *ui_window_get_res(ui_window_t *);
    5858extern gfx_context_t *ui_window_get_gc(ui_window_t *);
     59extern errno_t ui_window_get_pos(ui_window_t *, gfx_coord2_t *);
    5960extern errno_t ui_window_get_app_gc(ui_window_t *, gfx_context_t **);
    6061extern void ui_window_get_app_rect(ui_window_t *, gfx_rect_t *);
  • uspace/lib/ui/src/menu.c

    rf2416ec3 r6baab83  
    245245        ui_popup_params_init(&params);
    246246        params.rect = geom.outer_rect;
     247        params.place = *prect;
    247248
    248249        rc = ui_popup_create(menu->mbar->ui, menu->mbar->window, &params,
  • uspace/lib/ui/src/popup.c

    rf2416ec3 r6baab83  
    7878        ui_window_t *window = NULL;
    7979        ui_wnd_params_t wparams;
     80        gfx_coord2_t parent_pos;
    8081        errno_t rc;
    8182
     
    8384        if (popup == NULL)
    8485                return ENOMEM;
     86
     87        rc = ui_window_get_pos(parent, &parent_pos);
     88        if (rc != EOK)
     89                goto error;
    8590
    8691        ui_wnd_params_init(&wparams);
     
    8893        wparams.caption = "";
    8994        wparams.style &= ~ui_wds_decorated;
     95        wparams.placement = ui_wnd_place_popup;
     96
     97        /* Compute position of parent rectangle relative to the screen */
     98        gfx_rect_translate(&parent_pos, &params->place, &wparams.prect);
    9099
    91100        rc = ui_window_create(ui, &wparams, &window);
  • uspace/lib/ui/src/window.c

    rf2416ec3 r6baab83  
    109109}
    110110
     111static errno_t ui_window_place(ui_window_t *window, display_t *display,
     112    display_info_t *info, ui_wnd_params_t *params)
     113{
     114        gfx_coord2_t pos;
     115        errno_t rc;
     116
     117        assert(params->placement != ui_wnd_place_default);
     118
     119        pos.x = 0;
     120        pos.y = 0;
     121        switch (params->placement) {
     122        case ui_wnd_place_default:
     123                assert(false);
     124        case ui_wnd_place_top_left:
     125        case ui_wnd_place_full_screen:
     126                pos.x = info->rect.p0.x - params->rect.p0.x;
     127                pos.y = info->rect.p0.y - params->rect.p0.y;
     128                break;
     129        case ui_wnd_place_top_right:
     130                pos.x = info->rect.p1.x - params->rect.p1.x;
     131                pos.y = info->rect.p0.y - params->rect.p0.y;
     132                break;
     133        case ui_wnd_place_bottom_left:
     134                pos.x = info->rect.p0.x - params->rect.p0.x;
     135                pos.y = info->rect.p1.y - params->rect.p1.y;
     136                break;
     137        case ui_wnd_place_bottom_right:
     138                pos.x = info->rect.p1.x - params->rect.p1.x;
     139                pos.y = info->rect.p1.y - params->rect.p1.y;
     140                break;
     141        case ui_wnd_place_popup:
     142                /* Place popup window below parent rectangle */
     143                pos.x = params->prect.p0.x;
     144                pos.y = params->prect.p1.y;
     145                break;
     146        }
     147
     148        rc = display_window_move(window->dwindow, &pos);
     149        if (rc != EOK)
     150                goto error;
     151
     152        return EOK;
     153error:
     154        return rc;
     155}
     156
    111157/** Create new window.
    112158 *
     
    121167        ui_window_t *window;
    122168        display_info_t info;
    123         gfx_coord2_t pos;
    124169        gfx_coord2_t scr_dims;
    125170        display_wnd_params_t dparams;
    126         display_window_t *dwindow = NULL;
    127171        gfx_context_t *gc = NULL;
    128172        ui_resource_t *res = NULL;
     
    159203
    160204                rc = display_window_create(ui->display, &dparams, &dwnd_cb,
    161                     (void *) window, &dwindow);
     205                    (void *) window, &window->dwindow);
    162206                if (rc != EOK)
    163207                        goto error;
    164208
    165209                if (params->placement != ui_wnd_place_default) {
    166                         pos.x = 0;
    167                         pos.y = 0;
    168 
    169                         switch (params->placement) {
    170                         case ui_wnd_place_default:
    171                                 assert(false);
    172                         case ui_wnd_place_top_left:
    173                         case ui_wnd_place_full_screen:
    174                                 pos.x = info.rect.p0.x - params->rect.p0.x;
    175                                 pos.y = info.rect.p0.y - params->rect.p0.y;
    176                                 break;
    177                         case ui_wnd_place_top_right:
    178                                 pos.x = info.rect.p1.x - params->rect.p1.x;
    179                                 pos.y = info.rect.p0.y - params->rect.p0.y;
    180                                 break;
    181                         case ui_wnd_place_bottom_left:
    182                                 pos.x = info.rect.p0.x - params->rect.p0.x;
    183                                 pos.y = info.rect.p1.y - params->rect.p1.y;
    184                                 break;
    185                         case ui_wnd_place_bottom_right:
    186                                 pos.x = info.rect.p1.x - params->rect.p1.x;
    187                                 pos.y = info.rect.p1.y - params->rect.p1.y;
    188                                 break;
    189                         }
    190 
    191                         rc = display_window_move(dwindow, &pos);
     210                        rc = ui_window_place(window, ui->display, &info,
     211                            params);
    192212                        if (rc != EOK)
    193213                                goto error;
    194214                }
    195215
    196                 rc = display_window_get_gc(dwindow, &gc);
     216                rc = display_window_get_gc(window->dwindow, &gc);
    197217                if (rc != EOK)
    198218                        goto error;
     
    265285
    266286        window->ui = ui;
    267         window->dwindow = dwindow;
    268287        window->rect = dparams.rect;
    269288
     
    286305        if (dgc != NULL)
    287306                dummygc_destroy(dgc);
    288         if (dwindow != NULL)
    289                 display_window_destroy(dwindow);
    290307        free(window);
    291308        return rc;
     
    536553{
    537554        return window->gc;
     555}
     556
     557/** Get window position.
     558 *
     559 * @param window Window
     560 * @param pos Place to store position
     561 * @return EOK on success or an error code
     562 */
     563errno_t ui_window_get_pos(ui_window_t *window, gfx_coord2_t *pos)
     564{
     565        errno_t rc;
     566
     567        if (window->dwindow != NULL) {
     568                rc = display_window_get_pos(window->dwindow, pos);
     569                if (rc != EOK)
     570                        return rc;
     571        } else {
     572                pos->x = 0;
     573                pos->y = 0;
     574        }
     575
     576        return EOK;
    538577}
    539578
  • uspace/srv/hid/display/dsops.c

    rf2416ec3 r6baab83  
    4848static errno_t disp_window_move_req(void *, sysarg_t, gfx_coord2_t *);
    4949static errno_t disp_window_move(void *, sysarg_t, gfx_coord2_t *);
     50static errno_t disp_window_get_pos(void *, sysarg_t, gfx_coord2_t *);
    5051static errno_t disp_window_resize_req(void *, sysarg_t,
    5152    display_wnd_rsztype_t, gfx_coord2_t *);
     
    6162        .window_move_req = disp_window_move_req,
    6263        .window_move = disp_window_move,
     64        .window_get_pos = disp_window_get_pos,
    6365        .window_resize_req = disp_window_resize_req,
    6466        .window_resize = disp_window_resize,
     
    162164}
    163165
     166static errno_t disp_window_get_pos(void *arg, sysarg_t wnd_id,
     167    gfx_coord2_t *pos)
     168{
     169        ds_client_t *client = (ds_client_t *) arg;
     170        ds_window_t *wnd;
     171
     172        ds_display_lock(client->display);
     173
     174        wnd = ds_client_find_window(client, wnd_id);
     175        if (wnd == NULL) {
     176                ds_display_unlock(client->display);
     177                return ENOENT;
     178        }
     179
     180        log_msg(LOG_DEFAULT, LVL_DEBUG, "disp_window_get_pos()");
     181        ds_window_get_pos(wnd, pos);
     182        ds_display_unlock(client->display);
     183        return EOK;
     184}
     185
    164186static errno_t disp_window_resize_req(void *arg, sysarg_t wnd_id,
    165187    display_wnd_rsztype_t rsztype, gfx_coord2_t *pos)
  • uspace/srv/hid/display/window.c

    rf2416ec3 r6baab83  
    11/*
    2  * Copyright (c) 2019 Jiri Svoboda
     2 * Copyright (c) 2021 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    658658}
    659659
     660/** Get window position.
     661 *
     662 * @param wnd Window
     663 */
     664void ds_window_get_pos(ds_window_t *wnd, gfx_coord2_t *dpos)
     665{
     666        *dpos = wnd->dpos;
     667}
     668
    660669/** Start resizing a window, detected by client.
    661670 *
  • uspace/srv/hid/display/window.h

    rf2416ec3 r6baab83  
    6363extern void ds_window_move_req(ds_window_t *, gfx_coord2_t *);
    6464extern void ds_window_move(ds_window_t *, gfx_coord2_t *);
     65extern void ds_window_get_pos(ds_window_t *, gfx_coord2_t *);
    6566extern void ds_window_resize_req(ds_window_t *, display_wnd_rsztype_t,
    6667    gfx_coord2_t *);
Note: See TracChangeset for help on using the changeset viewer.