shell: On output_remove, focus moved workspace instead of empty one

On `output_remove`, if the output a workspace is moved to had no
non-empty workspaces (or did, but had an empty one active), the empty
workspace would remain active, and the workspace that was active on the
removed output is no longer visible.

Instead, change the active workspace to the one that was active on the
removed output.

This addresses another edge case where hotplug results in an empty
workspace, followed by other non-empty workspaces, and generally seems
like a better experience.

This could be further restricted by only applying if `new_set` is not on
the active output (to not mess with what the user is interacting with,
even it's an empty workspace) or only if the old `set` was the active
output, etc. But it seems good without further restriction.
This commit is contained in:
Ian Douglas Scott 2025-03-11 12:49:56 -07:00 committed by Victoria Brekenfeld
parent f9dd922af3
commit f8fae8a5b0

View file

@ -767,7 +767,7 @@ impl Workspaces {
let new_set = self.sets.get_mut(&new_output).unwrap();
let workspace_group = new_set.group;
for mut workspace in set.workspaces.into_iter() {
for (i, mut workspace) in set.workspaces.into_iter().enumerate() {
if workspace.is_empty() {
workspace_state.remove_workspace(workspace.handle);
} else {
@ -778,6 +778,21 @@ impl Workspaces {
workspace.set_output(&new_output);
workspace.refresh(xdg_activation_state);
new_set.workspaces.push(workspace);
// If workspace was active, and the new set's active workspace is empty, make this workspace
// active on the new set. Instead of leaving an empty workspace active, and a previously active
// workspace hidden.
if i == set.active && new_set.workspaces[new_set.active].is_empty() {
workspace_state.remove_workspace_state(
&new_set.workspaces[new_set.active].handle,
WState::Active,
);
new_set.active = new_set.workspaces.len() - 1;
workspace_state.add_workspace_state(
&new_set.workspaces[new_set.active].handle,
WState::Active,
);
}
}
}