diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index c2041742..e3a46872 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -201,10 +201,6 @@ struct sway_workspace *seat_get_last_known_workspace(struct sway_seat *seat); struct sway_container *seat_get_focused_container(struct sway_seat *seat); -// Force focus to a particular surface that is not part of the workspace -// hierarchy (used for lockscreen) -void sway_force_focus(struct wlr_surface *surface); - /** * Return the last container to be focused for the seat (or the most recently * opened if no container has received focused) that is a child of the given diff --git a/include/sway/server.h b/include/sway/server.h index 055c067d..6a5a60c8 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -96,6 +96,7 @@ struct sway_server { struct wlr_session_lock_manager_v1 *manager; struct wlr_session_lock_v1 *lock; + struct wlr_surface *focused; struct wl_listener lock_new_surface; struct wl_listener lock_unlock; struct wl_listener lock_destroy; diff --git a/sway/input/seat.c b/sway/input/seat.c index 987e1c9f..a7408287 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -214,15 +214,6 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { } } -void sway_force_focus(struct wlr_surface *surface) { - struct sway_seat *seat; - wl_list_for_each(seat, &server.input->seats, link) { - seat_keyboard_notify_enter(seat, surface); - seat_tablet_pads_notify_enter(seat, surface); - sway_input_method_relay_set_focus(&seat->im_relay, surface); - } -} - void seat_for_each_node(struct sway_seat *seat, void (*f)(struct sway_node *node, void *data), void *data) { struct sway_seat_node *current = NULL; diff --git a/sway/lock.c b/sway/lock.c index 04f80079..3c7c06cf 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -17,9 +17,20 @@ struct sway_session_lock_surface { struct wl_listener output_commit; }; +static void set_lock_focused_surface(struct wlr_surface *focused) { + server.session_lock.focused = focused; + + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + seat_set_focus_surface(seat, focused, false); + } +} + static void handle_surface_map(struct wl_listener *listener, void *data) { struct sway_session_lock_surface *surf = wl_container_of(listener, surf, map); - sway_force_focus(surf->surface); + if (server.session_lock.focused == NULL) { + set_lock_focused_surface(surf->surface); + } output_damage_whole(surf->output); } @@ -48,6 +59,21 @@ static void handle_output_commit(struct wl_listener *listener, void *data) { static void handle_surface_destroy(struct wl_listener *listener, void *data) { struct sway_session_lock_surface *surf = wl_container_of(listener, surf, destroy); + + // Move the seat focus to another surface if one is available + if (server.session_lock.focused == surf->surface) { + struct wlr_surface *next_focus = NULL; + + struct wlr_session_lock_surface_v1 *other; + wl_list_for_each(other, &server.session_lock.lock->surfaces, link) { + if (other != surf->lock_surface && other->mapped) { + next_focus = other->surface; + break; + } + } + set_lock_focused_surface(next_focus); + } + wl_list_remove(&surf->map.link); wl_list_remove(&surf->destroy.link); wl_list_remove(&surf->surface_commit.link); @@ -88,6 +114,7 @@ static void handle_unlock(struct wl_listener *listener, void *data) { sway_log(SWAY_DEBUG, "session unlocked"); server.session_lock.locked = false; server.session_lock.lock = NULL; + server.session_lock.focused = NULL; wl_list_remove(&server.session_lock.lock_new_surface.link); wl_list_remove(&server.session_lock.lock_unlock.link); @@ -115,6 +142,7 @@ static void handle_unlock(struct wl_listener *listener, void *data) { static void handle_abandon(struct wl_listener *listener, void *data) { sway_log(SWAY_INFO, "session lock abandoned"); server.session_lock.lock = NULL; + server.session_lock.focused = NULL; wl_list_remove(&server.session_lock.lock_new_surface.link); wl_list_remove(&server.session_lock.lock_unlock.link);