summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mader <robert.mader@posteo.de>2019-06-30 15:18:46 +0200
committerRobert Mader <robert.mader@posteo.de>2019-08-27 11:31:00 +0300
commit77229f99b882ba4e9b09b31617175fdb653738f6 (patch)
treec071f7e1a4f93087cdc27c6408320ecf63dbeb65
parenta51437ee2beede3d4d64f14d68df3ec557d0fdd0 (diff)
downloadmutter-77229f99b882ba4e9b09b31617175fdb653738f6.tar.gz
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
-rw-r--r--src/compositor/meta-window-actor-wayland.c86
-rw-r--r--src/compositor/meta-window-actor-wayland.h4
-rw-r--r--src/compositor/meta-window-actor-x11.c3
-rw-r--r--src/compositor/meta-window-actor.c1
-rw-r--r--src/wayland/meta-wayland-actor-surface.c25
-rw-r--r--src/wayland/meta-wayland-pointer.c11
-rw-r--r--src/wayland/meta-wayland-shell-surface.c15
-rw-r--r--src/wayland/meta-wayland-subsurface.c119
-rw-r--r--src/wayland/meta-wayland-surface.c50
-rw-r--r--src/wayland/meta-wayland-surface.h3
-rw-r--r--src/wayland/meta-wayland-tablet-tool.c11
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 <gbsneto@gnome.org>
*/
-#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"
@@ -52,6 +53,21 @@ G_DEFINE_TYPE (MetaWaylandSubsurface,
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)
{
ClutterActor *actor = CLUTTER_ACTOR (meta_wayland_surface_get_actor (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);
+
+ window_actor = meta_window_actor_wayland_from_surface (surface);
+ if (window_actor)
+ meta_window_actor_wayland_rebuild_surface_tree (window_actor);
- clutter_actor_set_reactive (CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)), TRUE);
+ 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)
@@ -1307,6 +1322,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)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (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;