From f769203238e62bb909ea1e035e41ba1e586c8876 Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Sun, 14 Sep 2025 16:13:08 +0200 Subject: [PATCH] Fixes session lock surfaces not being able to switch focused output --- include/sway/server.h | 2 ++ sway/input/seat.c | 18 ++++++++++++++++++ sway/lock.c | 17 +++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/include/sway/server.h b/include/sway/server.h index f50d48f05..a5b6d3320 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 1b63f625b..ba64babe3 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 c8975c747..a75c1e7e2 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -59,6 +59,23 @@ 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) {