diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 428f96796..04f0e0ea0 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h @@ -99,6 +99,7 @@ struct sway_seat { char *prev_workspace_name; // for workspace back_and_forth struct wlr_layer_surface_v1 *focused_layer; + struct wlr_surface *focused_lock; // If the exclusive layer is set, views cannot receive keyboard focus bool has_exclusive_layer; diff --git a/include/sway/server.h b/include/sway/server.h index 64419de03..000371995 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -13,7 +13,6 @@ struct sway_transaction; struct sway_session_lock { struct wlr_session_lock_v1 *lock; - struct wlr_surface *focused; bool abandoned; struct wl_list outputs; // struct sway_session_lock_output @@ -182,7 +181,7 @@ void sway_session_lock_add_output(struct sway_session_lock *lock, 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); + struct sway_seat* seat, 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 ca6c2ec2e..e7a95ea64 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1269,11 +1269,11 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { // Try focusing the current sway_output's lock-surface struct sway_output *output = node ? node_get_output(node) : NULL; if (output) { - sway_session_lock_focus_output(server.session_lock.lock, output); + sway_session_lock_focus_output(server.session_lock.lock, seat, output); return; } // Fallback to the previously focused lock surface - seat_set_focus_surface(seat, server.session_lock.lock->focused, false); + seat_set_focus_surface(seat, seat->focused_lock, false); } } diff --git a/sway/lock.c b/sway/lock.c index 43384fdb5..d4d59adf7 100644 --- a/sway/lock.c +++ b/sway/lock.c @@ -30,38 +30,39 @@ struct sway_session_lock_output { }; static void focus_surface(struct sway_session_lock *lock, - struct wlr_surface *focused) { - lock->focused = focused; - - struct sway_seat *seat; - wl_list_for_each(seat, &server.input->seats, link) { + struct sway_seat *seat, struct wlr_surface *focused) { + if (seat) { + seat->focused_lock = focused; seat_set_focus_surface(seat, focused, false); } } static void refocus_output(struct sway_session_lock_output *output) { // Move the seat focus to another surface if one is available - if (output->lock->focused == output->surface->surface) { - struct wlr_surface *next_focus = NULL; + struct wlr_surface *next_focus = NULL; - struct sway_session_lock_output *candidate; - wl_list_for_each(candidate, &output->lock->outputs, link) { - if (candidate == output || !candidate->surface) { - continue; - } - - if (candidate->surface->surface->mapped) { - next_focus = candidate->surface->surface; - break; - } + struct sway_session_lock_output *candidate; + wl_list_for_each(candidate, &output->lock->outputs, link) { + if (candidate == output || !candidate->surface) { + continue; } - focus_surface(output->lock, next_focus); + if (candidate->surface->surface->mapped) { + next_focus = candidate->surface->surface; + break; + } + } + + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + if (seat->focused_lock == output->surface->surface) { + focus_surface(output->lock, seat, next_focus); + } } } void sway_session_lock_focus_output(struct sway_session_lock *lock, - struct sway_output *output) { + struct sway_seat* seat, 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) { @@ -70,8 +71,7 @@ void sway_session_lock_focus_output(struct sway_session_lock *lock, } if (candidate->surface->surface->mapped) { - // Set the focus for all seats - focus_surface(lock, candidate->surface->surface); + focus_surface(lock, seat, candidate->surface->surface); break; } } @@ -80,15 +80,18 @@ void sway_session_lock_focus_output(struct sway_session_lock *lock, static void handle_surface_map(struct wl_listener *listener, void *data) { struct sway_session_lock_output *surf = wl_container_of(listener, surf, surface_map); - struct sway_seat *seat = input_manager_current_seat(); - struct sway_workspace *focused_ws = seat_get_focused_workspace(seat); - struct sway_output *focused_output = focused_ws ? focused_ws->output : NULL; + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + struct sway_workspace *focused_ws = seat_get_focused_workspace(seat); + struct sway_output *focused_output = focused_ws ? focused_ws->output : NULL; - // Only set the initial focus surface when it's on the focused output. - // Fallback to the first mapped surface if no focused output can be found. - if (focused_output == surf->output - || (!focused_output && surf->lock->focused == NULL)) { - focus_surface(surf->lock, surf->surface->surface); + // Only set the initial focus lock-surface when the surface is on the + // focused output. Fallback to the first mapped surface if no focused + // output can be found. + if (focused_output == surf->output + || (!focused_output && seat->focused_lock == NULL)) { + focus_surface(surf->lock, seat, surf->surface->surface); + } } cursor_rebase_all(); } @@ -224,6 +227,11 @@ static void sway_session_lock_destroy(struct sway_session_lock* lock) { wlr_scene_node_destroy(&lock_output->tree->node); } + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + seat->focused_lock = NULL; + } + if (server.session_lock.lock == lock) { server.session_lock.lock = NULL; } @@ -245,6 +253,8 @@ static void handle_unlock(struct wl_listener *listener, void *data) { struct sway_seat *seat; wl_list_for_each(seat, &server.input->seats, link) { + seat->focused_lock = NULL; + // copied from seat_set_focus_layer -- deduplicate? struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); if (previous) {