From 3cb86e4a2aa8e1938d97e54f15843c4e3dfbae27 Mon Sep 17 00:00:00 2001 From: Konstantin Pospelov Date: Sun, 3 May 2026 21:33:05 +0200 Subject: [PATCH] input/seat: check only the last output workspace on focus `seat_set_workspace_focus()` contains two references to the "last workspace": - `last_workspace` is the last focused workspace on all outputs. - `new_output_last_ws` is the last focused workspace on the new workspace output. They are the same when using a single output, but with multiple outputs they can diverge: `last_workspace` will be the focused workspace on the previous output, `new_output_last_ws` will be the previously focused workspace on the current output. This confusion seems to have led to #9139 when `last_workspace` was used instead of `new_output_last_ws`. However, we can safely drop `last_workspace` and use `new_output_last_ws` for everything that `seat_set_workspace_focus()` does: - Calling `node_set_dirty()` on the new output. - Calling `wlr_ext_workspace_handle_v1_set_active()` on the last workspace (this fixes #9139). - Skip `workspace_consider_destroy()` on `last_workspace`, since the other output still has it focused. This commit also renames `new_output_last_ws` to `last_workspace` to keep the name simple. --- sway/input/seat.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 83772f52c..0434d637c 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1133,8 +1133,6 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n return; } - struct sway_workspace *last_workspace = seat_get_focused_workspace(seat); - if (node == NULL) { seat_send_unfocus(last_focus, seat); sway_input_method_relay_set_focus(&seat->im_relay, NULL); @@ -1157,17 +1155,15 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n return; } + // Find the output's last workspace, which might have to be removed if empty struct sway_output *new_output = new_workspace ? new_workspace->output : NULL; - + struct sway_workspace *last_workspace = + new_output ? output_get_active_workspace(new_output) : NULL; if (last_workspace != new_workspace && new_output) { node_set_dirty(&new_output->node); } - // find new output's old workspace, which might have to be removed if empty - struct sway_workspace *new_output_last_ws = - new_output ? output_get_active_workspace(new_output) : NULL; - // Unfocus the previous focus if (last_focus) { seat_send_unfocus(last_focus, seat); @@ -1211,11 +1207,11 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n } // Move sticky containers to new workspace - if (new_workspace && new_output_last_ws - && new_workspace != new_output_last_ws) { - for (int i = 0; i < new_output_last_ws->floating->length; ++i) { + if (new_workspace && last_workspace + && new_workspace != last_workspace) { + for (int i = 0; i < last_workspace->floating->length; ++i) { struct sway_container *floater = - new_output_last_ws->floating->items[i]; + last_workspace->floating->items[i]; if (container_is_sticky(floater)) { container_detach(floater); workspace_add_floating(new_workspace, floater); @@ -1244,13 +1240,9 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n } } - if (new_output_last_ws) { - workspace_consider_destroy(new_output_last_ws); - } - if (last_workspace && last_workspace != new_output_last_ws) { + if (last_workspace) { workspace_consider_destroy(last_workspace); } - seat->has_focus = true; if (config->smart_gaps && new_workspace) {