diff options
author | 2018-10-02 15:42:16 +1000 | |
---|---|---|
committer | 2018-10-02 15:45:20 +1000 | |
commit | 677e112733c0294f338f7803207e4e2b16146d08 (patch) | |
tree | 056c9c6702ac2753b526c41d5ad857543cab51d2 /sway/input | |
parent | Merge pull request #2740 from RedSoxFan/gap-borders (diff) | |
download | sway-677e112733c0294f338f7803207e4e2b16146d08.tar.gz sway-677e112733c0294f338f7803207e4e2b16146d08.tar.zst sway-677e112733c0294f338f7803207e4e2b16146d08.zip |
Set focus_inactive on a sibling when a container closes in an inactive workspace
To reproduce the problem, create layout
H[view V[view view view-focused]], then switch to another workspace and
have the previously focused view in the vsplit close (eg. using
criteria, or an mpv video finishing). Return to the workspace using
`$mod+<num>` and the entire vsplit would be focused. This happens
because handle_seat_node_destroy would only set a new focus if the
currently focused view or a parent was being destroyed. To fix it, it
needs to set a sibling of the destroying container to focus_inactive
regardless of the current focus, then restore current focus if needed.
This patch changes the function accordingly. Additionally:
* The function now makes an early return if the node being destroyed is
a workspace.
* set_focus has been renamed to needs_new_focus. This variable is true
if the head focus needs to be changed.
Diffstat (limited to 'sway/input')
-rw-r--r-- | sway/input/seat.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index 34b64d9c..e10b6409 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -144,32 +144,43 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) { | |||
144 | struct sway_node *parent = node_get_parent(node); | 144 | struct sway_node *parent = node_get_parent(node); |
145 | struct sway_node *focus = seat_get_focus(seat); | 145 | struct sway_node *focus = seat_get_focus(seat); |
146 | 146 | ||
147 | bool set_focus = | 147 | if (node->type == N_WORKSPACE) { |
148 | focus != NULL && | 148 | seat_node_destroy(seat_node); |
149 | (focus == node || node_has_ancestor(focus, node)) && | 149 | return; |
150 | node->type == N_CONTAINER; | 150 | } |
151 | 151 | ||
152 | seat_node_destroy(seat_node); | 152 | // Even though the container being destroyed might be nowhere near the |
153 | // focused container, we still need to set focus_inactive on a sibling of | ||
154 | // the container being destroyed. | ||
155 | bool needs_new_focus = focus && | ||
156 | (focus == node || node_has_ancestor(focus, node)); | ||
153 | 157 | ||
154 | if (set_focus) { | 158 | seat_node_destroy(seat_node); |
155 | struct sway_node *next_focus = NULL; | ||
156 | while (next_focus == NULL) { | ||
157 | struct sway_container *con = | ||
158 | seat_get_focus_inactive_view(seat, parent); | ||
159 | next_focus = con ? &con->node : NULL; | ||
160 | 159 | ||
161 | if (next_focus == NULL && parent->type == N_WORKSPACE) { | 160 | // Find new focus_inactive (ie. sibling, or workspace if no siblings left) |
162 | next_focus = parent; | 161 | struct sway_node *next_focus = NULL; |
163 | break; | 162 | while (next_focus == NULL) { |
164 | } | 163 | struct sway_container *con = |
164 | seat_get_focus_inactive_view(seat, parent); | ||
165 | next_focus = con ? &con->node : NULL; | ||
165 | 166 | ||
166 | parent = node_get_parent(parent); | 167 | if (next_focus == NULL && parent->type == N_WORKSPACE) { |
168 | next_focus = parent; | ||
169 | break; | ||
167 | } | 170 | } |
168 | 171 | ||
169 | // the structure change might have caused it to move up to the top of | 172 | parent = node_get_parent(parent); |
173 | } | ||
174 | |||
175 | if (needs_new_focus) { | ||
176 | // The structure change might have caused it to move up to the top of | ||
170 | // the focus stack without sending focus notifications to the view | 177 | // the focus stack without sending focus notifications to the view |
171 | seat_send_focus(next_focus, seat); | 178 | seat_send_focus(next_focus, seat); |
172 | seat_set_focus(seat, next_focus); | 179 | seat_set_focus(seat, next_focus); |
180 | } else { | ||
181 | // Setting focus_inactive | ||
182 | seat_set_focus_warp(seat, next_focus, false, false); | ||
183 | seat_set_focus_warp(seat, focus, false, false); | ||
173 | } | 184 | } |
174 | } | 185 | } |
175 | 186 | ||