diff --git a/include/common/surface-helpers.h b/include/common/surface-helpers.h new file mode 100644 index 00000000..1dd7fd74 --- /dev/null +++ b/include/common/surface-helpers.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LABWC_SURFACE_HELPERS_H +#define LABWC_SURFACE_HELPERS_H + +struct wlr_surface; +struct wlr_layer_surface_v1; + +/** + * subsurface_parent_layer() - Get wlr_layer_surface from layer-subsurface + * @wlr_surface: The wlr_surface of the wlr_subsurface for which to get the + * layer-surface. + */ +struct wlr_layer_surface_v1 *subsurface_parent_layer( + struct wlr_surface *wlr_surface); + +#endif /* LABWC_SURFACE_HELPERS_H */ diff --git a/src/common/meson.build b/src/common/meson.build index 72ad6f2b..6a90f9b3 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -13,6 +13,7 @@ labwc_sources += files( 'scaled_font_buffer.c', 'scaled_scene_buffer.c', 'scene-helpers.c', + 'surface-helpers.c', 'spawn.c', 'string-helpers.c', ) diff --git a/src/common/surface-helpers.c b/src/common/surface-helpers.c new file mode 100644 index 00000000..76102e8b --- /dev/null +++ b/src/common/surface-helpers.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include "common/surface-helpers.h" + +struct wlr_layer_surface_v1 * +subsurface_parent_layer(struct wlr_surface *wlr_surface) +{ + struct wlr_subsurface *subsurface = + wlr_subsurface_try_from_wlr_surface(wlr_surface); + if (!subsurface) { + wlr_log(WLR_DEBUG, "surface %p is not subsurface", subsurface); + return NULL; + } + struct wlr_surface *parent = subsurface->parent; + if (!parent) { + wlr_log(WLR_DEBUG, "subsurface %p has no parent", subsurface); + return NULL; + } + struct wlr_layer_surface_v1 *wlr_layer_surface = + wlr_layer_surface_v1_try_from_wlr_surface(parent); + if (wlr_layer_surface) { + return wlr_layer_surface; + } + /* Recurse in case there are nested sub-surfaces */ + return subsurface_parent_layer(parent); +} diff --git a/src/desktop.c b/src/desktop.c index 412de004..4aca14b8 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -2,6 +2,7 @@ #include "config.h" #include #include "common/scene-helpers.h" +#include "common/surface-helpers.h" #include "dnd.h" #include "labwc.h" #include "layers.h" @@ -255,21 +256,6 @@ get_surface_from_layer_node(struct wlr_scene_node *node) return NULL; } -static bool -is_layer_descendant(struct wlr_scene_node *node) -{ - goto start; - while (node) { - struct node_descriptor *desc = node->data; - if (desc && desc->type == LAB_NODE_DESC_LAYER_SURFACE) { - return true; - } -start: - node = node->parent ? &node->parent->node : NULL; - } - return false; -} - /* TODO: make this less big and scary */ struct cursor_context get_cursor_context(struct server *server) @@ -354,24 +340,23 @@ get_cursor_context(struct server *server) /* Edge-case nodes without node-descriptors */ if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_surface *surface = lab_wlr_surface_from_node(node); - if (surface) { - if (wlr_layer_surface_v1_try_from_wlr_surface(surface)) { - ret.type = LAB_SSD_LAYER_SURFACE; - } - if (is_layer_descendant(node)) { - /* - * layer-shell subsurfaces need to be - * able to receive pointer actions. - * - * Test by running - * `gtk-layer-demo -k exclusive`, then - * open the 'set margin' dialog and try - * setting the margin with the pointer. - */ - ret.surface = surface; - ret.type = LAB_SSD_LAYER_SUBSURFACE; - return ret; - } + + /* + * Handle layer-shell subsurfaces + * + * These don't have node-descriptors, but need to be + * able to receive pointer actions so we have to process + * them here. + * + * Test by running `gtk-layer-demo -k exclusive`, then + * open the 'set margin' dialog and try setting the + * margin with the pointer. + */ + if (surface && wlr_subsurface_try_from_wlr_surface(surface) + && subsurface_parent_layer(surface)) { + ret.surface = surface; + ret.type = LAB_SSD_LAYER_SUBSURFACE; + return ret; } } diff --git a/src/input/cursor.c b/src/input/cursor.c index b06a9ca4..fd7d0e61 100644 --- a/src/input/cursor.c +++ b/src/input/cursor.c @@ -11,6 +11,7 @@ #include "common/macros.h" #include "common/mem.h" #include "common/scene-helpers.h" +#include "common/surface-helpers.h" #include "config/mousebind.h" #include "dnd.h" #include "idle.h" @@ -965,11 +966,19 @@ cursor_button_press(struct seat *seat, uint32_t button, * the Focus action (used for normal views) does not work. */ if (ctx.type == LAB_SSD_LAYER_SURFACE) { + wlr_log(WLR_DEBUG, "press on layer-surface"); struct wlr_layer_surface_v1 *layer = wlr_layer_surface_v1_try_from_wlr_surface(ctx.surface); if (layer && layer->current.keyboard_interactive) { seat_set_focus_layer(seat, layer); } + } else if (ctx.type == LAB_SSD_LAYER_SUBSURFACE) { + wlr_log(WLR_DEBUG, "press on layer-subsurface"); + struct wlr_layer_surface_v1 *layer = + subsurface_parent_layer(ctx.surface); + if (layer && layer->current.keyboard_interactive) { + seat_set_focus_layer(seat, layer); + } #ifdef HAVE_XWAYLAND } else if (ctx.type == LAB_SSD_UNMANAGED) { desktop_focus_view_or_surface(seat, NULL, ctx.surface, @@ -977,12 +986,6 @@ cursor_button_press(struct seat *seat, uint32_t button, #endif } - /* - * TODO: We may need to handle press on layer-shell subsurfaces here, - * but need to check keyboard interactivity before focusing them - * otherwise we break waybar. See issue #1131 - */ - if (ctx.type != LAB_SSD_CLIENT && ctx.type != LAB_SSD_LAYER_SUBSURFACE && wlr_seat_pointer_has_grab(seat->seat)) { /*