sway

i3-compatible Wayland compositor
git clone https://git.awy.one/sway
Log | Files | Refs | README | LICENSE

commit 4d4c88f0a73f6ee3da1c99355f04362ef2ad68c9
parent 3f327b3db0c1fc6985c0ed3231e1bd6296584dad
Author: Joan Bruguera Micó <joanbrugueram@gmail.com>
Date:   Sat, 20 Jul 2024 22:34:01 +0000

layer-shell: Restore interactive layer focus code

Commit 188811f80861 ("scene_graph: Port layer_shell") accidentally
removed code in `arrange_layers` to handle focus on layer shell
surfaces with keyboard interactivity.

Due to this, layer shell surfaces requesting exclusive keyboard
interactivity may not get automatically focused, and layer shell
surfaces giving up exclusive keyboard interactivity can remain focused.

Add the previous code back to fix the problem.

Note the non-rename change included in b4d7e84d3852 ("desktop: Rename
layers to shell_layers") is not included as it also seems accidental.

Fixes: #7936

Diffstat:
Msway/desktop/layer_shell.c | 37+++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+), 0 deletions(-)

diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c @@ -90,6 +90,43 @@ void arrange_layers(struct sway_output *output) { } else { arrange_popups(root->layers.popup); } + + // Find topmost keyboard interactive layer, if such a layer exists + struct wlr_scene_tree *layers_above_shell[] = { + output->layers.shell_overlay, + output->layers.shell_top, + }; + size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]); + struct wlr_scene_node *node; + struct sway_layer_surface *topmost = NULL; + for (size_t i = 0; i < nlayers; ++i) { + wl_list_for_each_reverse(node, + &layers_above_shell[i]->children, link) { + struct sway_layer_surface *surface = scene_descriptor_try_get(node, + SWAY_SCENE_DESC_LAYER_SHELL); + if (surface && surface->layer_surface->current.keyboard_interactive + == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE && + surface->layer_surface->surface->mapped) { + topmost = surface; + break; + } + } + if (topmost != NULL) { + break; + } + } + + struct sway_seat *seat; + wl_list_for_each(seat, &server.input->seats, link) { + seat->has_exclusive_layer = false; + if (topmost != NULL) { + seat_set_focus_layer(seat, topmost->layer_surface); + } else if (seat->focused_layer && + seat->focused_layer->current.keyboard_interactive + != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { + seat_set_focus_layer(seat, NULL); + } + } } static struct wlr_scene_tree *sway_layer_get_scene(struct sway_output *output,