Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 17c0f5d in mainline


Ignore:
Timestamp:
2023-01-05T19:28:22Z (4 weeks ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
ededdc4
Parents:
5d86797
Message:

Switch to another window when window is minimized

And do it properly. Never switch to a minimized window. Only switch to
a system window (Task bar) when no other is available.

Location:
uspace/srv/hid/display
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hid/display/seat.c

    r5d86797 r17c0f5d  
    11/*
    2  * Copyright (c) 2022 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    142142 *
    143143 * @param seat Seat
    144  * @param wnd Window to evacuate focus from
     144 * @param wnd Window to evacuate references from
    145145 */
    146146void ds_seat_evac_wnd_refs(ds_seat_t *seat, ds_window_t *wnd)
     
    160160        if (seat->popup == wnd)
    161161                ds_seat_set_popup(seat, NULL);
     162}
     163
     164/** Unfocus window.
     165 *
     166 * If seat's focus is @a wnd, it will be set to a different window
     167 * that is not minimized, preferably not a system window.
     168 *
     169 * @param seat Seat
     170 * @param wnd Window to remove focus from
     171 */
     172void ds_seat_unfocus_wnd(ds_seat_t *seat, ds_window_t *wnd)
     173{
     174        ds_window_t *nwnd;
     175
     176        if (seat->focus != wnd)
     177                return;
     178
     179        /* Find alternate window that is neither system nor minimized */
     180        nwnd = ds_window_find_alt(wnd, ~(wndf_minimized | wndf_system));
     181
     182        if (nwnd == NULL) {
     183                /* Find alternate window that is not minimized */
     184                nwnd = ds_window_find_alt(wnd, ~wndf_minimized);
     185        }
     186
     187        ds_seat_set_focus(seat, nwnd);
    162188}
    163189
  • uspace/srv/hid/display/seat.h

    r5d86797 r17c0f5d  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    5151extern void ds_seat_set_popup(ds_seat_t *, ds_window_t *);
    5252extern void ds_seat_evac_wnd_refs(ds_seat_t *, ds_window_t *);
     53extern void ds_seat_unfocus_wnd(ds_seat_t *, ds_window_t *);
    5354extern void ds_seat_switch_focus(ds_seat_t *);
    5455extern errno_t ds_seat_post_kbd_event(ds_seat_t *, kbd_event_t *);
  • uspace/srv/hid/display/test/seat.c

    r5d86797 r17c0f5d  
    11/*
    2  * Copyright (c) 2021 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    224224}
    225225
     226/** Unfocus window when three windows are available */
     227PCUT_TEST(unfocus_wnd_three_windows)
     228{
     229        ds_display_t *disp;
     230        ds_client_t *client;
     231        ds_seat_t *seat;
     232        ds_window_t *w0;
     233        ds_window_t *w1;
     234        ds_window_t *w2;
     235        display_wnd_params_t params;
     236        bool called_cb = false;
     237        errno_t rc;
     238
     239        rc = ds_display_create(NULL, df_none, &disp);
     240        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     241
     242        rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
     243        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     244
     245        rc = ds_seat_create(disp, &seat);
     246        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     247
     248        display_wnd_params_init(&params);
     249        params.rect.p0.x = params.rect.p0.y = 0;
     250        params.rect.p1.x = params.rect.p1.y = 1;
     251
     252        rc = ds_window_create(client, &params, &w2);
     253        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     254
     255        rc = ds_window_create(client, &params, &w1);
     256        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     257
     258        rc = ds_window_create(client, &params, &w0);
     259        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     260
     261        PCUT_ASSERT_EQUALS(w0, seat->focus);
     262
     263        ds_window_unfocus(w0);
     264
     265        /* The previous window, w2, should be focused now */
     266        PCUT_ASSERT_EQUALS(w2, seat->focus);
     267
     268        ds_window_destroy(w0);
     269        ds_window_destroy(w1);
     270        ds_seat_destroy(seat);
     271        ds_client_destroy(client);
     272        ds_display_destroy(disp);
     273}
     274
     275/** Unfocus window when two windows and one system window are available */
     276PCUT_TEST(unfocus_wnd_two_windows_one_sys)
     277{
     278        ds_display_t *disp;
     279        ds_client_t *client;
     280        ds_seat_t *seat;
     281        ds_window_t *w0;
     282        ds_window_t *w1;
     283        ds_window_t *w2;
     284        display_wnd_params_t params;
     285        bool called_cb = false;
     286        errno_t rc;
     287
     288        rc = ds_display_create(NULL, df_none, &disp);
     289        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     290
     291        rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
     292        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     293
     294        rc = ds_seat_create(disp, &seat);
     295        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     296
     297        display_wnd_params_init(&params);
     298        params.rect.p0.x = params.rect.p0.y = 0;
     299        params.rect.p1.x = params.rect.p1.y = 1;
     300
     301        params.flags |= wndf_system;
     302        rc = ds_window_create(client, &params, &w2);
     303        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     304
     305        params.flags &= ~wndf_system;
     306        rc = ds_window_create(client, &params, &w1);
     307        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     308
     309        rc = ds_window_create(client, &params, &w0);
     310        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     311
     312        PCUT_ASSERT_EQUALS(w0, seat->focus);
     313
     314        ds_window_unfocus(w0);
     315
     316        /* The previous non-system window is w1, w2 should be skipped */
     317        PCUT_ASSERT_EQUALS(w1, seat->focus);
     318
     319        ds_window_destroy(w0);
     320        ds_window_destroy(w1);
     321        ds_seat_destroy(seat);
     322        ds_client_destroy(client);
     323        ds_display_destroy(disp);
     324}
     325
     326/** Unfocus window when one window and one system window is available */
     327PCUT_TEST(unfocus_wnd_one_window_one_sys)
     328{
     329        ds_display_t *disp;
     330        ds_client_t *client;
     331        ds_seat_t *seat;
     332        ds_window_t *w0;
     333        ds_window_t *w1;
     334        display_wnd_params_t params;
     335        bool called_cb = false;
     336        errno_t rc;
     337
     338        rc = ds_display_create(NULL, df_none, &disp);
     339        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     340
     341        rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
     342        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     343
     344        rc = ds_seat_create(disp, &seat);
     345        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     346
     347        display_wnd_params_init(&params);
     348        params.rect.p0.x = params.rect.p0.y = 0;
     349        params.rect.p1.x = params.rect.p1.y = 1;
     350
     351        params.flags |= wndf_system;
     352        rc = ds_window_create(client, &params, &w1);
     353        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     354
     355        params.flags &= ~wndf_system;
     356        rc = ds_window_create(client, &params, &w0);
     357        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     358
     359        PCUT_ASSERT_EQUALS(w0, seat->focus);
     360
     361        ds_window_unfocus(w0);
     362
     363        /* Since no non-system window is available, w1 should be focused */
     364        PCUT_ASSERT_EQUALS(w1, seat->focus);
     365
     366        ds_window_destroy(w0);
     367        ds_window_destroy(w1);
     368        ds_seat_destroy(seat);
     369        ds_client_destroy(client);
     370        ds_display_destroy(disp);
     371}
     372
     373/** Unfocus window when one window is available */
     374PCUT_TEST(unfocus_wnd_one_window)
     375{
     376        ds_display_t *disp;
     377        ds_client_t *client;
     378        ds_seat_t *seat;
     379        ds_window_t *w0;
     380        display_wnd_params_t params;
     381        bool called_cb = false;
     382        errno_t rc;
     383
     384        rc = ds_display_create(NULL, df_none, &disp);
     385        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     386
     387        rc = ds_client_create(disp, &test_ds_client_cb, &called_cb, &client);
     388        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     389
     390        rc = ds_seat_create(disp, &seat);
     391        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     392
     393        display_wnd_params_init(&params);
     394        params.rect.p0.x = params.rect.p0.y = 0;
     395        params.rect.p1.x = params.rect.p1.y = 1;
     396
     397        rc = ds_window_create(client, &params, &w0);
     398        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     399
     400        PCUT_ASSERT_EQUALS(w0, seat->focus);
     401
     402        ds_window_unfocus(w0);
     403
     404        /* Since no other window is availabe, no window should be focused */
     405        PCUT_ASSERT_EQUALS(NULL, seat->focus);
     406
     407        ds_window_destroy(w0);
     408        ds_seat_destroy(seat);
     409        ds_client_destroy(client);
     410        ds_display_destroy(disp);
     411}
     412
    226413/** Switch focus when another window is available. */
    227414PCUT_TEST(switch_focus_two_windows)
  • uspace/srv/hid/display/test/window.c

    r5d86797 r17c0f5d  
    11621162}
    11631163
     1164/** ds_window_find_alt() finds alternate window by flags */
     1165PCUT_TEST(window_find_alt)
     1166{
     1167        gfx_context_t *gc;
     1168        ds_display_t *disp;
     1169        ds_client_t *client;
     1170        ds_seat_t *seat;
     1171        ds_window_t *w0;
     1172        ds_window_t *w1;
     1173        ds_window_t *w2;
     1174        ds_window_t *wnd;
     1175        display_wnd_params_t params;
     1176        errno_t rc;
     1177
     1178        rc = gfx_context_new(&dummy_ops, NULL, &gc);
     1179        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1180
     1181        rc = ds_display_create(gc, df_none, &disp);
     1182        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1183
     1184        rc = ds_client_create(disp, NULL, NULL, &client);
     1185        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1186
     1187        rc = ds_seat_create(disp, &seat);
     1188        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1189
     1190        display_wnd_params_init(&params);
     1191        params.rect.p0.x = params.rect.p0.y = 0;
     1192        params.rect.p1.x = params.rect.p1.y = 1;
     1193
     1194        rc = ds_window_create(client, &params, &w0);
     1195        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1196
     1197        rc = ds_window_create(client, &params, &w1);
     1198        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1199        w1->flags |= wndf_minimized;
     1200
     1201        rc = ds_window_create(client, &params, &w2);
     1202        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1203        w2->flags |= wndf_system;
     1204
     1205        wnd = ds_window_find_alt(w0, wndf_minimized);
     1206        PCUT_ASSERT_EQUALS(w1, wnd);
     1207
     1208        wnd = ds_window_find_alt(w0, wndf_system);
     1209        PCUT_ASSERT_EQUALS(w2, wnd);
     1210
     1211        wnd = ds_window_find_alt(w0, wndf_maximized);
     1212        PCUT_ASSERT_NULL(wnd);
     1213
     1214        ds_window_destroy(w0);
     1215        ds_window_destroy(w1);
     1216        ds_window_destroy(w2);
     1217        ds_seat_destroy(seat);
     1218        ds_client_destroy(client);
     1219        ds_display_destroy(disp);
     1220}
     1221
     1222/** ds_window_unfocus() switches to another window */
     1223PCUT_TEST(window_unfocus)
     1224{
     1225        gfx_context_t *gc;
     1226        ds_display_t *disp;
     1227        ds_client_t *client;
     1228        ds_seat_t *seat;
     1229        ds_window_t *w0;
     1230        ds_window_t *w1;
     1231        display_wnd_params_t params;
     1232        errno_t rc;
     1233
     1234        rc = gfx_context_new(&dummy_ops, NULL, &gc);
     1235        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1236
     1237        rc = ds_display_create(gc, df_none, &disp);
     1238        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1239
     1240        rc = ds_client_create(disp, NULL, NULL, &client);
     1241        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1242
     1243        rc = ds_seat_create(disp, &seat);
     1244        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1245
     1246        display_wnd_params_init(&params);
     1247        params.rect.p0.x = params.rect.p0.y = 0;
     1248        params.rect.p1.x = params.rect.p1.y = 1;
     1249
     1250        rc = ds_window_create(client, &params, &w1);
     1251        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1252
     1253        rc = ds_window_create(client, &params, &w0);
     1254        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     1255
     1256        PCUT_ASSERT_EQUALS(w0, seat->focus);
     1257
     1258        ds_window_unfocus(w0);
     1259
     1260        PCUT_ASSERT_EQUALS(w1, seat->focus);
     1261
     1262        ds_window_destroy(w0);
     1263        ds_window_destroy(w1);
     1264        ds_seat_destroy(seat);
     1265        ds_client_destroy(client);
     1266        ds_display_destroy(disp);
     1267}
     1268
    11641269static errno_t dummy_set_color(void *arg, gfx_color_t *color)
    11651270{
  • uspace/srv/hid/display/window.c

    r5d86797 r17c0f5d  
    6767 * @param client Client owning the window
    6868 * @param params Window parameters
    69  * @param rgc Place to store pointer to new GC.
     69 * @param rwnd Place to store pointer to new window.
    7070 *
    7171 * @return EOK on success or an error code
    7272 */
    7373errno_t ds_window_create(ds_client_t *client, display_wnd_params_t *params,
    74     ds_window_t **rgc)
     74    ds_window_t **rwnd)
    7575{
    7676        ds_window_t *wnd = NULL;
     
    155155        (void) ds_display_paint(wnd->display, NULL);
    156156
    157         *rgc = wnd;
     157        *rwnd = wnd;
    158158        return EOK;
    159159error:
     
    867867                return EOK;
    868868
     869        ds_window_unfocus(wnd);
     870
    869871        wnd->flags |= wndf_minimized;
    870872        (void) ds_display_paint(wnd->display, NULL);
     
    10441046}
    10451047
     1048/** Find alternate window with the allowed flags.
     1049 *
     1050 * An alternate window is a *different* window that is preferably previous
     1051 * in the display order and only has the @a allowed flags.
     1052 *
     1053 * @param wnd Window
     1054 * @param allowed_flags Bitmask of flags that the window is allowed to have
     1055 *
     1056 * @return Alternate window matching the criteria or @c NULL if there is none
     1057 */
     1058ds_window_t *ds_window_find_alt(ds_window_t *wnd,
     1059    display_wnd_flags_t allowed_flags)
     1060{
     1061        ds_window_t *nwnd;
     1062
     1063        /* Try preceding windows in display order */
     1064        nwnd = ds_display_prev_window(wnd);
     1065        while (nwnd != NULL && (nwnd->flags & ~allowed_flags) != 0) {
     1066                nwnd = ds_display_prev_window(nwnd);
     1067        }
     1068
     1069        /* Do we already have a matching window? */
     1070        if (nwnd != NULL && (nwnd->flags & ~allowed_flags) == 0) {
     1071                return nwnd;
     1072        }
     1073
     1074        /* Try succeeding windows in display order */
     1075        nwnd = ds_display_last_window(wnd->display);
     1076        while (nwnd != NULL && nwnd != wnd &&
     1077            (nwnd->flags & ~allowed_flags) != 0) {
     1078                nwnd = ds_display_prev_window(nwnd);
     1079        }
     1080
     1081        if (nwnd == wnd)
     1082                return NULL;
     1083
     1084        return nwnd;
     1085}
     1086
     1087/** Remove focus from window.
     1088 *
     1089 * Used to switch focus to another window when closing or minimizing window.
     1090 *
     1091 * @param wnd Window
     1092 */
     1093void ds_window_unfocus(ds_window_t *wnd)
     1094{
     1095        ds_seat_t *seat;
     1096
     1097        /* Make sure window is no longer focused in any seat */
     1098        seat = ds_display_first_seat(wnd->display);
     1099        while (seat != NULL) {
     1100                ds_seat_unfocus_wnd(seat, wnd);
     1101                seat = ds_display_next_seat(seat);
     1102        }
     1103}
     1104
    10461105/** Window memory GC invalidate callback.
    10471106 *
  • uspace/srv/hid/display/window.h

    r5d86797 r17c0f5d  
    11/*
    2  * Copyright (c) 2022 Jiri Svoboda
     2 * Copyright (c) 2023 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    7878extern errno_t ds_window_set_cursor(ds_window_t *, display_stock_cursor_t);
    7979extern errno_t ds_window_set_caption(ds_window_t *, const char *);
     80extern ds_window_t *ds_window_find_alt(ds_window_t *, display_wnd_flags_t);
     81extern void ds_window_unfocus(ds_window_t *);
    8082
    8183#endif
Note: See TracChangeset for help on using the changeset viewer.