Fix focus after a non-visible workspace's last container is destroyed

The code being changed is responsible for updating the focus stack when
a container is destroyed in a different part of the tree to where the
real focus is. It's attempting to set focus_inactive to a sibling (or
parent if no siblings) of the container that is being destroyed, then
put our real focus back on the end of the focus stack.

The problem occurs when the container being destroyed is in a different
workspace. For example:

* Have a focused view on workspace 1
* Have workspace 2 not visible with a single view that is unmapping
* The first call to seat_set_raw_focus sets focus to workspace 2 because
it's the parent
* Prior to this patch, the second call to seat_set_raw_focus would set
focus to the view on workspace 1
* Later, when using output_get_active_workspace, this function would
return workspace 2 because it's the first workspace it finds in the
focus stack.

To fix this, workspace 1 must be placed on the focus stack between
workspace 2 and the focused view. That's what this patch does.

Lastly, it also uses seat_get_focus_inactive to choose the focus. This
fixes a crash when a view unmaps while a non-container is focused (eg.
swaylock), because focus is NULL.
This commit is contained in:
Ryan Dwyer 2018-10-26 19:15:12 +10:00
parent b29beb1aa0
commit 63d076dc2a

View File

@ -185,7 +185,11 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) {
seat_set_focus(seat, next_focus); seat_set_focus(seat, next_focus);
} else { } else {
// Setting focus_inactive // Setting focus_inactive
focus = seat_get_focus_inactive(seat, &root->node);
seat_set_raw_focus(seat, next_focus); seat_set_raw_focus(seat, next_focus);
if (focus->type == N_CONTAINER) {
seat_set_raw_focus(seat, &focus->sway_container->workspace->node);
}
seat_set_raw_focus(seat, focus); seat_set_raw_focus(seat, focus);
} }
} }