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.
This commit is contained in:
Konstantin Pospelov 2026-05-03 21:33:05 +02:00 committed by Simon Ser
parent 3774506bd0
commit 3cb86e4a2a

View file

@ -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) {