Avoid refocusing destroyed lock surfaces
886699c1fffd9ea083edf76b167a76fd6991a114
1 parent
d85b756f
swm.c
+17 -3
| 2953 | 2953 | wlr_scene_node_destroy(&lock->scene->node); |
|
| 2954 | 2954 | cur_lock = nullptr; |
|
| 2955 | 2955 | pool_release(&session_lock_pool, lock); |
|
| 2956 | 2956 | } |
|
| 2957 | 2957 | ||
| 2958 | + | /* Return the first surface available to receive lock-screen keyboard focus. */ |
|
| 2959 | + | static struct wlr_session_lock_surface_v1 *lock_surface_next( |
|
| 2960 | + | struct wlr_session_lock_v1 *lock, struct wlr_session_lock_surface_v1 *removed |
|
| 2961 | + | ) { |
|
| 2962 | + | struct wlr_session_lock_surface_v1 *surface; |
|
| 2963 | + | ||
| 2964 | + | if (!lock) |
|
| 2965 | + | return nullptr; |
|
| 2966 | + | wl_list_for_each(surface, &lock->surfaces, link) { |
|
| 2967 | + | if (surface != removed) |
|
| 2968 | + | return surface; |
|
| 2969 | + | } |
|
| 2970 | + | return nullptr; |
|
| 2971 | + | } |
|
| 2972 | + | ||
| 2958 | 2973 | /* Remove a display's session-lock surface and restore its background. */ |
|
| 2959 | 2974 | void destroy_lock_surface(struct wl_listener *listener, void *data) { |
|
| 2960 | 2975 | monitor_t *m = wl_container_of(listener, m, destroy_lock_surface); |
|
| 2961 | 2976 | struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; |
|
| 2962 | 2977 |
| 2967 | 2982 | lock_surface->surface->data = nullptr; |
|
| 2968 | 2983 | ||
| 2969 | 2984 | if (lock_surface->surface != seat->keyboard_state.focused_surface) |
|
| 2970 | 2985 | return; |
|
| 2971 | 2986 | ||
| 2972 | - | if (locked && cur_lock && !wl_list_empty(&cur_lock->surfaces)) { |
|
| 2973 | - | surface = wl_container_of(cur_lock->surfaces.next, surface, link); |
|
| 2987 | + | if (locked && (surface = lock_surface_next(cur_lock, lock_surface))) |
|
| 2974 | 2988 | client_notify_enter(surface->surface, wlr_seat_get_keyboard(seat)); |
|
| 2975 | - | } else if (!locked) { |
|
| 2989 | + | else if (!locked) { |
|
| 2976 | 2990 | focus_client(focus_top(selmon), 1); |
|
| 2977 | 2991 | } else { |
|
| 2978 | 2992 | wlr_seat_keyboard_clear_focus(seat); |
|
| 2979 | 2993 | input_method_set_focus(nullptr); |
|
| 2980 | 2994 | } |
test/unit.c
+12 -0
| 385 | 385 | scaled_surface = nullptr; |
|
| 386 | 386 | monitor_set_scale(&monitor); |
|
| 387 | 387 | assert(scaled_surface == &surface); |
|
| 388 | 388 | } |
|
| 389 | 389 | ||
| 390 | + | /* Verify destroying a focused lock surface skips that surface during refocus. */ |
|
| 391 | + | static void test_lock_surface_refocus(void) { |
|
| 392 | + | struct wlr_session_lock_v1 lock = {}; |
|
| 393 | + | struct wlr_session_lock_surface_v1 removed = {}, remaining = {}; |
|
| 394 | + | ||
| 395 | + | wl_list_init(&lock.surfaces); |
|
| 396 | + | wl_list_insert(lock.surfaces.prev, &removed.link); |
|
| 397 | + | wl_list_insert(lock.surfaces.prev, &remaining.link); |
|
| 398 | + | assert(lock_surface_next(&lock, &removed) == &remaining); |
|
| 399 | + | } |
|
| 400 | + | ||
| 390 | 401 | /* Verify directed output moves preserve a window's display-relative position. */ |
|
| 391 | 402 | static void test_monitor_translation(void) { |
|
| 392 | 403 | monitor_t oldmon = { .m = { 0, 0, 1920, 1080 } }; |
|
| 393 | 404 | monitor_t newmon = { .m = { 1920, 100, 2560, 1440 } }; |
|
| 394 | 405 | client_t client = { .geom = { 100, 50, 640, 480 }, .prev = { 200, 75, 800, 600 } }; |
| 1152 | 1163 | { "input-method", test_input_method_lifecycle }, |
|
| 1153 | 1164 | { "output-role-scale-change", test_output_role_scale_change }, |
|
| 1154 | 1165 | { "input-early-paths", test_input_early_paths }, |
|
| 1155 | 1166 | { "command-line", test_command_line_errors }, |
|
| 1156 | 1167 | { "monitor-translation", test_monitor_translation }, |
|
| 1168 | + | { "lock-surface-refocus", test_lock_surface_refocus }, |
|
| 1157 | 1169 | { "pointer-and-decoration", test_pointer_and_decoration_lifecycle }, |
|
| 1158 | 1170 | { "keybindings-and-repeat", test_keybindings_and_repeat }, |
|
| 1159 | 1171 | }; |
|
| 1160 | 1172 | ||
| 1161 | 1173 | if (argc == 2 && !strcmp(argv[1], "--list")) { |