aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/layer_shell.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-10-04 19:23:04 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-10-04 19:36:19 +1000
commit32cb631143fe9087d9d14e96f42a38f602369212 (patch)
tree1f7e9fcb9858e02b3d97e5a8cf78f54829954e2b /sway/desktop/layer_shell.c
parentMerge pull request #2759 from minus7/fix-view-container-null (diff)
downloadsway-32cb631143fe9087d9d14e96f42a38f602369212.tar.gz
sway-32cb631143fe9087d9d14e96f42a38f602369212.tar.zst
sway-32cb631143fe9087d9d14e96f42a38f602369212.zip
Give focus to another swaylock surface when output is disconnected
* Have multiple outputs * Launch swaylock * Unplug an output (possibly has to be the last "connected" one) * The swaylock surface on the remaining output would not respond to key events This was happening because when the output destroys, focus was not given to the other swaylock surface. This patch makes focus be transferred to another surface owned by the same Wayland client, but only if input was inhibited by the surface being destroyed, and only if it's in the overlay layer. I figure it's best to be overly specific and relax the requirements later if needed. This patch removes a check in seat_set_focus_surface which was preventing focus from being passed from a layer surface to any other surface. I don't know of a use case for this check, but it's possible that this change could produce issues.
Diffstat (limited to 'sway/desktop/layer_shell.c')
-rw-r--r--sway/desktop/layer_shell.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
index e09282b2..269864d4 100644
--- a/sway/desktop/layer_shell.c
+++ b/sway/desktop/layer_shell.c
@@ -216,12 +216,48 @@ void arrange_layers(struct sway_output *output) {
216 } 216 }
217} 217}
218 218
219static struct sway_layer_surface *find_any_layer_by_client(
220 struct wl_client *client, struct wlr_output *ignore_output) {
221 for (int i = 0; i < root->outputs->length; ++i) {
222 struct sway_output *output = root->outputs->items[i];
223 if (output->wlr_output == ignore_output) {
224 continue;
225 }
226 // For now we'll only check the overlay layer
227 struct sway_layer_surface *lsurface;
228 wl_list_for_each(lsurface,
229 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) {
230 struct wl_resource *resource = lsurface->layer_surface->resource;
231 if (wl_resource_get_client(resource) == client) {
232 return lsurface;
233 }
234 }
235 }
236 return NULL;
237}
238
219static void handle_output_destroy(struct wl_listener *listener, void *data) { 239static void handle_output_destroy(struct wl_listener *listener, void *data) {
220 struct sway_layer_surface *sway_layer = 240 struct sway_layer_surface *sway_layer =
221 wl_container_of(listener, sway_layer, output_destroy); 241 wl_container_of(listener, sway_layer, output_destroy);
242 // Determine if this layer is being used by an exclusive client. If it is,
243 // try and find another layer owned by this client to pass focus to.
244 struct sway_seat *seat = input_manager_get_default_seat(input_manager);
245 struct wl_client *client =
246 wl_resource_get_client(sway_layer->layer_surface->resource);
247 bool set_focus = seat->exclusive_client == client;
248
222 wl_list_remove(&sway_layer->output_destroy.link); 249 wl_list_remove(&sway_layer->output_destroy.link);
223 wl_list_remove(&sway_layer->link); 250 wl_list_remove(&sway_layer->link);
224 wl_list_init(&sway_layer->link); 251 wl_list_init(&sway_layer->link);
252
253 if (set_focus) {
254 struct sway_layer_surface *layer =
255 find_any_layer_by_client(client, sway_layer->layer_surface->output);
256 if (layer) {
257 seat_set_focus_layer(seat, layer->layer_surface);
258 }
259 }
260
225 sway_layer->layer_surface->output = NULL; 261 sway_layer->layer_surface->output = NULL;
226 wlr_layer_surface_v1_close(sway_layer->layer_surface); 262 wlr_layer_surface_v1_close(sway_layer->layer_surface);
227} 263}