diff --git a/include/sway/server.h b/include/sway/server.h index f50d48f05b..a5b6d3320d 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -178,6 +178,8 @@ void sway_session_lock_add_output(struct sway_session_lock *lock, struct sway_output *output); bool sway_session_lock_has_surface(struct sway_session_lock *lock, struct wlr_surface *surface); +void sway_session_lock_focus_output(struct sway_session_lock *lock, + struct sway_output *output); void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data); #if WLR_HAS_XWAYLAND void handle_xwayland_surface(struct wl_listener *listener, void *data); diff --git a/sway/input/seat.c b/sway/input/seat.c index 1b63f625bc..ba64babe3a 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1273,6 +1273,24 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { seat_set_workspace_focus(seat, node); } if (server.session_lock.lock) { + struct sway_output *output = NULL; + if (node != NULL) { + switch (node->type) { + case N_OUTPUT: + output = node->sway_output; + break; + case N_WORKSPACE: + output = node->sway_workspace->output; + break; + default: + break; + } + } + if (output != NULL) { + sway_session_lock_focus_output(server.session_lock.lock, output); + return; + } + // Fallback to the previously focused lock surface seat_set_focus_surface(seat, server.session_lock.lock->focused, false); } } diff --git a/sway/lock.c b/sway/lock.c index c8975c7475..2b9b74b03f 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -8,6 +8,7 @@ #include "sway/layers.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/tree/workspace.h" #include "sway/lock.h" struct sway_session_lock_output { @@ -59,9 +60,34 @@ static void refocus_output(struct sway_session_lock_output *output) { } } +void sway_session_lock_focus_output(struct sway_session_lock *lock, + struct sway_output *output) { + // Try focusing the lock surface on the provided output + struct sway_session_lock_output *candidate; + wl_list_for_each(candidate, &lock->outputs, link) { + if (candidate->output != output || !candidate->surface) { + continue; + } + + if (candidate->surface->surface->mapped) { + // Set the focus for all seats + focus_surface(lock, candidate->surface->surface); + break; + } + } +} + static void handle_surface_map(struct wl_listener *listener, void *data) { struct sway_session_lock_output *surf = wl_container_of(listener, surf, surface_map); - if (surf->lock->focused == NULL) { + + struct sway_seat *seat = input_manager_current_seat(); + struct sway_workspace *focused_ws = seat_get_focused_workspace(seat); + struct sway_output *focused_output = NULL; + if (focused_ws != NULL) { + focused_output = focused_ws->output; + } + + if (surf->lock->focused == NULL || focused_output == surf->output) { focus_surface(surf->lock, surf->surface->surface); } cursor_rebase_all();