From 77229f99b882ba4e9b09b31617175fdb653738f6 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Sun, 30 Jun 2019 15:18:46 +0200 Subject: [PATCH] wayland: Implement subsurface.place_below() for parents Flatten the subsurface actor tree, making all surface actors children of the window actor. Save the subsurface state in a GNode tree in MetaWaylandSurface, where each surface holds two nodes, one branch, which can be the tree root or be attached to a parent surfaces branch, and a leaf, which is used to save the position relative to child branch nodes. Each time a surface is added or reordered in the tree, unparent all surface actors from the window actor, traverse all leaves of the tree and readd the corresponding surface actors back to the window actor. https://gitlab.gnome.org/GNOME/mutter/merge_requests/664 --- src/compositor/meta-window-actor-wayland.c | 86 ++++++++++++++- src/compositor/meta-window-actor-wayland.h | 4 + src/compositor/meta-window-actor-x11.c | 3 + src/compositor/meta-window-actor.c | 1 - src/wayland/meta-wayland-actor-surface.c | 25 +++-- src/wayland/meta-wayland-pointer.c | 11 +- src/wayland/meta-wayland-shell-surface.c | 15 ++- src/wayland/meta-wayland-subsurface.c | 119 +++++++++++++++------ src/wayland/meta-wayland-surface.c | 50 +++++++-- src/wayland/meta-wayland-surface.h | 3 +- src/wayland/meta-wayland-tablet-tool.c | 11 +- 11 files changed, 261 insertions(+), 67 deletions(-) diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c index f50978e8f..e251e3a27 100644 --- a/src/compositor/meta-window-actor-wayland.c +++ b/src/compositor/meta-window-actor-wayland.c @@ -20,9 +20,10 @@ * Georges Basile Stavracas Neto */ -#include "compositor/meta-surface-actor.h" +#include "compositor/meta-surface-actor-wayland.h" #include "compositor/meta-window-actor-wayland.h" #include "meta/meta-window-actor.h" +#include "wayland/meta-wayland-surface.h" struct _MetaWindowActorWayland { @@ -31,6 +32,88 @@ struct _MetaWindowActorWayland G_DEFINE_TYPE (MetaWindowActorWayland, meta_window_actor_wayland, META_TYPE_WINDOW_ACTOR) +static gboolean +remove_surface_actor_from_children (GNode *node, + gpointer data) +{ + MetaWaylandSurface *surface = node->data; + MetaSurfaceActor *surface_actor = meta_wayland_surface_get_actor (surface); + MetaWindowActor *window_actor = data; + ClutterActor *parent; + + parent = clutter_actor_get_parent (CLUTTER_ACTOR (surface_actor)); + if (!parent) + return FALSE; + + g_return_val_if_fail (parent == CLUTTER_ACTOR (window_actor), FALSE); + + clutter_actor_remove_child (CLUTTER_ACTOR (window_actor), + CLUTTER_ACTOR (surface_actor)); + + return FALSE; +} + +static gboolean +add_surface_actor_to_children (GNode *node, + gpointer data) +{ + MetaWaylandSurface *surface = node->data; + MetaSurfaceActor *surface_actor = meta_wayland_surface_get_actor (surface); + MetaWindowActor *window_actor = data; + + clutter_actor_add_child (CLUTTER_ACTOR (window_actor), + CLUTTER_ACTOR (surface_actor)); + + return FALSE; +} + +void +meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor) +{ + MetaSurfaceActor *surface_actor = + meta_window_actor_get_surface (actor); + MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface ( + META_SURFACE_ACTOR_WAYLAND (surface_actor)); + GNode *root_node = surface->subsurface_branch_node; + + g_node_traverse (root_node, + G_IN_ORDER, + G_TRAVERSE_LEAVES, + -1, + remove_surface_actor_from_children, + actor); + + g_node_traverse (root_node, + G_IN_ORDER, + G_TRAVERSE_LEAVES, + -1, + add_surface_actor_to_children, + actor); +} + +MetaWindowActor * +meta_window_actor_wayland_from_surface (MetaWaylandSurface *surface) +{ + if (surface->window) + return meta_window_actor_from_window (surface->window); + else if (surface->sub.parent) + return meta_window_actor_wayland_from_surface (surface->sub.parent); + else + return NULL; +} + +static void +meta_window_actor_wayland_assign_surface_actor (MetaWindowActor *actor, + MetaSurfaceActor *surface_actor) +{ + MetaWindowActorClass *parent_class = + META_WINDOW_ACTOR_CLASS (meta_window_actor_wayland_parent_class); + + parent_class->assign_surface_actor (actor, surface_actor); + + meta_window_actor_wayland_rebuild_surface_tree (actor); +} + static void meta_window_actor_wayland_frame_complete (MetaWindowActor *actor, ClutterFrameInfo *frame_info, @@ -64,6 +147,7 @@ meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass) { MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass); + window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor; window_actor_class->frame_complete = meta_window_actor_wayland_frame_complete; window_actor_class->queue_frame_drawn = meta_window_actor_wayland_queue_frame_drawn; window_actor_class->pre_paint = meta_window_actor_wayland_pre_paint; diff --git a/src/compositor/meta-window-actor-wayland.h b/src/compositor/meta-window-actor-wayland.h index 560800693..d7e1b7808 100644 --- a/src/compositor/meta-window-actor-wayland.h +++ b/src/compositor/meta-window-actor-wayland.h @@ -24,6 +24,7 @@ #define META_WINDOW_ACTOR_WAYLAND_H #include "compositor/meta-window-actor-private.h" +#include "wayland/meta-wayland-surface.h" #define META_TYPE_WINDOW_ACTOR_WAYLAND (meta_window_actor_wayland_get_type()) G_DECLARE_FINAL_TYPE (MetaWindowActorWayland, @@ -31,4 +32,7 @@ G_DECLARE_FINAL_TYPE (MetaWindowActorWayland, META, WINDOW_ACTOR_WAYLAND, MetaWindowActor) +void meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor); +MetaWindowActor * meta_window_actor_wayland_from_surface (MetaWaylandSurface *surface); + #endif /*META_WINDOW_ACTOR_WAYLAND_H */ diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c index 03035d6bf..a82b923f3 100644 --- a/src/compositor/meta-window-actor-x11.c +++ b/src/compositor/meta-window-actor-x11.c @@ -338,6 +338,9 @@ meta_window_actor_x11_assign_surface_actor (MetaWindowActor *actor, parent_class->assign_surface_actor (actor, surface_actor); + clutter_actor_add_child (CLUTTER_ACTOR (actor), + CLUTTER_ACTOR (surface_actor)); + actor_x11->repaint_scheduled_id = g_signal_connect (surface_actor, "repaint-scheduled", G_CALLBACK (surface_repaint_scheduled), diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 312eb9811..d2d46e6b0 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -377,7 +377,6 @@ meta_window_actor_real_assign_surface_actor (MetaWindowActor *self, priv->size_changed_id = g_signal_connect (priv->surface, "size-changed", G_CALLBACK (surface_size_changed), self); - clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); meta_window_actor_update_shape (self); diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index eb909c3b5..aea67a589 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -26,6 +26,7 @@ #include "backends/meta-backend-private.h" #include "backends/meta-logical-monitor.h" #include "compositor/meta-surface-actor-wayland.h" +#include "compositor/meta-window-actor-wayland.h" #include "compositor/region-utils.h" #include "wayland/meta-wayland-surface.h" #include "wayland/meta-window-wayland.h" @@ -76,18 +77,10 @@ meta_wayland_actor_surface_assigned (MetaWaylandSurfaceRole *surface_role) meta_wayland_actor_surface_get_instance_private (META_WAYLAND_ACTOR_SURFACE (surface_role)); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - GList *l; meta_surface_actor_wayland_add_frame_callbacks (META_SURFACE_ACTOR_WAYLAND (priv->actor), &surface->pending_frame_callback_list); wl_list_init (&surface->pending_frame_callback_list); - - for (l = surface->subsurfaces; l; l = l->next) - { - ClutterActor *subsurface_actor = - CLUTTER_ACTOR (meta_wayland_surface_get_actor (l->data)); - clutter_actor_add_child (CLUTTER_ACTOR (priv->actor), subsurface_actor); - } } void @@ -139,7 +132,7 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor meta_wayland_surface_role_get_surface (surface_role); MetaSurfaceActor *surface_actor; MetaShapedTexture *stex; - GList *l; + GNode *n; cairo_rectangle_int_t surface_rect; int geometry_scale; @@ -205,12 +198,18 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor meta_surface_actor_reset_viewport_dst_size (surface_actor); } - for (l = surface->subsurfaces; l; l = l->next) + for (n = g_node_first_child (surface->subsurface_branch_node); + n; + n = g_node_next_sibling (n)) { - MetaWaylandSurface *subsurface_surface = l->data; - MetaWaylandActorSurface *subsurface_actor_surface = - META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role); + MetaWaylandSurface *subsurface_surface = n->data; + MetaWaylandActorSurface *subsurface_actor_surface; + if (G_NODE_IS_LEAF (n)) + continue; + + subsurface_actor_surface = + META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role); meta_wayland_actor_surface_sync_actor_state (subsurface_actor_surface); } } diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index e41aab8e0..334349e30 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -1194,14 +1194,19 @@ static gboolean pointer_can_grab_surface (MetaWaylandPointer *pointer, MetaWaylandSurface *surface) { - GList *l; + GNode *n; if (pointer->focus_surface == surface) return TRUE; - for (l = surface->subsurfaces; l; l = l->next) + for (n = g_node_first_child (surface->subsurface_branch_node); + n; + n = g_node_next_sibling (n)) { - MetaWaylandSurface *subsurface = l->data; + MetaWaylandSurface *subsurface = n->data; + + if (G_NODE_IS_LEAF (n)) + continue; if (pointer_can_grab_surface (pointer, subsurface)) return TRUE; diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c index 3ebfdd284..32b4d981c 100644 --- a/src/wayland/meta-wayland-shell-surface.c +++ b/src/wayland/meta-wayland-shell-surface.c @@ -43,19 +43,24 @@ meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_su MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaRectangle geometry; - GList *l; + GNode *n; geometry = (MetaRectangle) { .width = meta_wayland_surface_get_width (surface), .height = meta_wayland_surface_get_height (surface), }; - for (l = surface->subsurfaces; l; l = l->next) + for (n = g_node_first_child (surface->subsurface_branch_node); + n; + n = g_node_next_sibling (n)) { - MetaWaylandSurface *subsurface_surface = l->data; - MetaWaylandSubsurface *subsurface = - META_WAYLAND_SUBSURFACE (subsurface_surface->role); + MetaWaylandSurface *subsurface_surface = n->data; + MetaWaylandSubsurface *subsurface; + if (G_NODE_IS_LEAF (n)) + continue; + + subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role); meta_wayland_subsurface_union_geometry (subsurface, 0, 0, &geometry); diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c index 3b813a191..8724da39f 100644 --- a/src/wayland/meta-wayland-subsurface.c +++ b/src/wayland/meta-wayland-subsurface.c @@ -23,6 +23,7 @@ #include "wayland/meta-wayland-subsurface.h" #include "compositor/meta-surface-actor-wayland.h" +#include "compositor/meta-window-actor-wayland.h" #include "wayland/meta-wayland.h" #include "wayland/meta-wayland-actor-surface.h" #include "wayland/meta-wayland-buffer.h" @@ -51,6 +52,21 @@ G_DEFINE_TYPE (MetaWaylandSubsurface, meta_wayland_subsurface, META_TYPE_WAYLAND_ACTOR_SURFACE) +static void +transform_subsurface_position (MetaWaylandSurface *surface, + int *x, + int *y) +{ + do + { + *x += surface->sub.x; + *y += surface->sub.y; + + surface = surface->sub.parent; + } + while (surface); +} + static void sync_actor_subsurface_state (MetaWaylandSurface *surface) { @@ -65,8 +81,8 @@ sync_actor_subsurface_state (MetaWaylandSurface *surface) if (toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11) return; - x = surface->offset_x + surface->sub.x; - y = surface->offset_y + surface->sub.y; + x = y = 0; + transform_subsurface_position (surface, &x, &y); clutter_actor_set_position (actor, x, y); @@ -76,6 +92,26 @@ sync_actor_subsurface_state (MetaWaylandSurface *surface) clutter_actor_hide (actor); } +static gboolean +is_child (MetaWaylandSurface *surface, + MetaWaylandSurface *sibling) +{ + if (surface->sub.parent == sibling) + return TRUE; + else + return FALSE; +} + +static gboolean +is_sibling (MetaWaylandSurface *surface, + MetaWaylandSurface *sibling) +{ + if (surface->sub.parent == sibling->sub.parent) + return TRUE; + else + return FALSE; +} + void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface) { @@ -95,15 +131,16 @@ meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface) if (surface->sub.pending_placement_ops) { GSList *it; - MetaWaylandSurface *parent = surface->sub.parent; - ClutterActor *parent_actor = - clutter_actor_get_parent (CLUTTER_ACTOR (meta_wayland_surface_get_actor (parent))); - ClutterActor *surface_actor = CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); + MetaWaylandSurface *parent; + MetaWindowActor *window_actor; + + parent = surface->sub.parent; for (it = surface->sub.pending_placement_ops; it; it = it->next) { MetaWaylandSubsurfacePlacementOp *op = it->data; - ClutterActor *sibling_actor; + MetaWaylandSurface *sibling; + GNode *sibling_node; if (!op->sibling) { @@ -111,19 +148,25 @@ meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface) continue; } - sibling_actor = CLUTTER_ACTOR (meta_wayland_surface_get_actor (op->sibling)); + sibling = op->sibling; + if (is_child (surface, sibling)) + sibling_node = sibling->subsurface_leaf_node; + else + sibling_node = sibling->subsurface_branch_node; + + g_node_unlink (surface->subsurface_branch_node); switch (op->placement) { case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE: - clutter_actor_set_child_above_sibling (parent_actor, - surface_actor, - sibling_actor); + g_node_insert_after (parent->subsurface_branch_node, + sibling_node, + surface->subsurface_branch_node); break; case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW: - clutter_actor_set_child_below_sibling (parent_actor, - surface_actor, - sibling_actor); + g_node_insert_before (parent->subsurface_branch_node, + sibling_node, + surface->subsurface_branch_node); break; } @@ -133,6 +176,10 @@ meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface) g_slist_free (surface->sub.pending_placement_ops); surface->sub.pending_placement_ops = NULL; + + window_actor = meta_window_actor_wayland_from_surface (surface); + if (window_actor) + meta_window_actor_wayland_rebuild_surface_tree (window_actor); } if (meta_wayland_surface_is_effectively_synchronized (surface)) @@ -151,7 +198,7 @@ meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); MetaRectangle geometry; - GList *l; + GNode *n; geometry = (MetaRectangle) { .x = surface->offset_x + surface->sub.x, @@ -162,12 +209,17 @@ meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, meta_rectangle_union (out_geometry, &geometry, out_geometry); - for (l = surface->subsurfaces; l; l = l->next) + for (n = g_node_first_child (surface->subsurface_branch_node); + n; + n = g_node_next_sibling (n)) { - MetaWaylandSurface *subsurface_surface = l->data; - MetaWaylandSubsurface *subsurface = - META_WAYLAND_SUBSURFACE (subsurface_surface->role); + MetaWaylandSurface *subsurface_surface = n->data; + MetaWaylandSubsurface *subsurface; + if (G_NODE_IS_LEAF (n)) + continue; + + subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role); meta_wayland_subsurface_union_geometry (subsurface, parent_x + geometry.x, parent_y + geometry.y, @@ -242,12 +294,13 @@ wl_subsurface_destructor (struct wl_resource *resource) meta_wayland_compositor_destroy_frame_callbacks (surface->compositor, surface); + + g_node_unlink (surface->subsurface_branch_node); + unparent_actor (surface); + if (surface->sub.parent) { wl_list_remove (&surface->sub.parent_destroy_listener.link); - surface->sub.parent->subsurfaces = - g_list_remove (surface->sub.parent->subsurfaces, surface); - unparent_actor (surface); surface->sub.parent = NULL; } @@ -279,9 +332,9 @@ static gboolean is_valid_sibling (MetaWaylandSurface *surface, MetaWaylandSurface *sibling) { - if (surface->sub.parent == sibling) + if (is_child (surface, sibling)) return TRUE; - if (surface->sub.parent == sibling->sub.parent) + if (is_sibling (surface, sibling)) return TRUE; return FALSE; } @@ -409,7 +462,6 @@ surface_handle_parent_surface_destroyed (struct wl_listener *listener, sub.parent_destroy_listener); surface->sub.parent = NULL; - unparent_actor (surface); } static void @@ -422,6 +474,8 @@ wl_subcompositor_get_subsurface (struct wl_client *client, MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource); MetaWindow *toplevel_window; + MetaWindowActor *window_actor; + MetaSurfaceActor *surface_actor; if (surface->wl_subsurface) { @@ -463,15 +517,16 @@ wl_subcompositor_get_subsurface (struct wl_client *client, surface_handle_parent_surface_destroyed; wl_resource_add_destroy_listener (parent->resource, &surface->sub.parent_destroy_listener); - parent->subsurfaces = g_list_append (parent->subsurfaces, surface); - if (meta_wayland_surface_get_actor (parent)) - { - clutter_actor_add_child (CLUTTER_ACTOR (meta_wayland_surface_get_actor (parent)), - CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface))); - } + g_node_append (parent->subsurface_branch_node, + surface->subsurface_branch_node); - clutter_actor_set_reactive (CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)), TRUE); + window_actor = meta_window_actor_wayland_from_surface (surface); + if (window_actor) + meta_window_actor_wayland_rebuild_surface_tree (window_actor); + + surface_actor = meta_wayland_surface_get_actor (surface); + clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE); } static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = { diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 787265f33..9a1b45ece 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -646,12 +646,16 @@ meta_wayland_surface_is_effectively_synchronized (MetaWaylandSurface *surface) } static void -parent_surface_state_applied (gpointer data, - gpointer user_data) +parent_surface_state_applied (GNode *subsurface_node, + gpointer user_data) { - MetaWaylandSurface *surface = data; - MetaWaylandSubsurface *subsurface = META_WAYLAND_SUBSURFACE (surface->role); + MetaWaylandSurface *surface = subsurface_node->data; + MetaWaylandSubsurface *subsurface; + if (G_NODE_IS_LEAF (subsurface_node)) + return; + + subsurface = META_WAYLAND_SUBSURFACE (surface->role); meta_wayland_subsurface_parent_state_applied (subsurface); } @@ -836,7 +840,10 @@ cleanup: pending_state_reset (pending); - g_list_foreach (surface->subsurfaces, parent_surface_state_applied, NULL); + g_node_children_foreach (surface->subsurface_branch_node, + G_TRAVERSE_ALL, + parent_surface_state_applied, + NULL); } static void @@ -1254,14 +1261,22 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) static void meta_wayland_surface_update_outputs_recursively (MetaWaylandSurface *surface) { - GList *l; + GNode *n; meta_wayland_surface_update_outputs (surface); - for (l = surface->subsurfaces; l != NULL; l = l->next) - meta_wayland_surface_update_outputs_recursively (l->data); + for (n = g_node_first_child (surface->subsurface_branch_node); + n; + n = g_node_next_sibling (n)) + { + if (G_NODE_IS_LEAF (n)) + continue; + + meta_wayland_surface_update_outputs_recursively (n->data); + } } + void meta_wayland_surface_set_window (MetaWaylandSurface *surface, MetaWindow *window) @@ -1306,6 +1321,13 @@ meta_wayland_surface_set_window (MetaWaylandSurface *surface, } } +static void +unlink_note (GNode *node, + gpointer data) +{ + g_node_unlink (node); +} + static void wl_surface_destructor (struct wl_resource *resource) { @@ -1355,6 +1377,15 @@ wl_surface_destructor (struct wl_resource *resource) if (surface->wl_subsurface) wl_resource_destroy (surface->wl_subsurface); + if (surface->subsurface_branch_node) + { + g_node_children_foreach (surface->subsurface_branch_node, + G_TRAVERSE_NON_LEAVES, + unlink_note, + NULL); + g_clear_pointer (&surface->subsurface_branch_node, g_node_destroy); + } + g_hash_table_destroy (surface->shortcut_inhibited_seats); g_object_unref (surface); @@ -1612,6 +1643,9 @@ static void meta_wayland_surface_init (MetaWaylandSurface *surface) { surface->pending = g_object_new (META_TYPE_WAYLAND_PENDING_STATE, NULL); + surface->subsurface_branch_node = g_node_new (surface); + surface->subsurface_leaf_node = + g_node_prepend_data (surface->subsurface_branch_node, surface); g_signal_connect (surface, "geometry-changed", G_CALLBACK (meta_wayland_surface_update_outputs_recursively), diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index e244a3fdf..9b225fc6f 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -145,7 +145,8 @@ struct _MetaWaylandSurface cairo_region_t *opaque_region; int scale; int32_t offset_x, offset_y; - GList *subsurfaces; + GNode *subsurface_branch_node; + GNode *subsurface_leaf_node; GHashTable *outputs_to_destroy_notify_id; MetaMonitorTransform buffer_transform; diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c index cce93030b..fd491fa50 100644 --- a/src/wayland/meta-wayland-tablet-tool.c +++ b/src/wayland/meta-wayland-tablet-tool.c @@ -989,14 +989,19 @@ static gboolean tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool, MetaWaylandSurface *surface) { - GList *l; + GNode *n; if (tool->focus_surface == surface) return TRUE; - for (l = surface->subsurfaces; l; l = l->next) + for (n = g_node_first_child (surface->subsurface_branch_node); + n; + n = g_node_next_sibling (n)) { - MetaWaylandSurface *subsurface = l->data; + MetaWaylandSurface *subsurface = n->data; + + if (G_NODE_IS_LEAF (n)) + continue; if (tablet_tool_can_grab_surface (tool, subsurface)) return TRUE;