From f7768874e5ec2a808ccec424ed9e238e3dc13987 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Fri, 16 Apr 2021 15:15:41 +0200 Subject: [PATCH 1/2] window-actor/wayland: Cleaner subsurface reordering Currently when reordering subsurfaces, we un- and reparent all child actors of the window actor. This is unnecessarily wasteful and triggers bugs in clutter. While the underlying issue should be fixed eventually, simply reorder the actors with the tools clutter provides us with, avoiding those bugs and likely being faster as well. Part-of: --- src/compositor/meta-window-actor-wayland.c | 65 +++++++++++----------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c index 7c3be569042..b1fe6164150 100644 --- a/src/compositor/meta-window-actor-wayland.c +++ b/src/compositor/meta-window-actor-wayland.c @@ -32,37 +32,36 @@ 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) +typedef struct _SurfaceTreeTraverseData { - 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; -} + MetaWindowActor *window_actor; + int index; +} SurfaceTreeTraverseData; static gboolean -add_surface_actor_to_children (GNode *node, - gpointer data) +set_surface_actor_index (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)); + SurfaceTreeTraverseData *traverse_data = data; + + if (clutter_actor_contains (CLUTTER_ACTOR (traverse_data->window_actor), + CLUTTER_ACTOR (surface_actor))) + { + clutter_actor_set_child_at_index ( + CLUTTER_ACTOR (traverse_data->window_actor), + CLUTTER_ACTOR (surface_actor), + traverse_data->index); + } + else + { + clutter_actor_insert_child_at_index ( + CLUTTER_ACTOR (traverse_data->window_actor), + CLUTTER_ACTOR (surface_actor), + traverse_data->index); + } + traverse_data->index++; return FALSE; } @@ -75,20 +74,18 @@ meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor) MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface ( META_SURFACE_ACTOR_WAYLAND (surface_actor)); GNode *root_node = surface->subsurface_branch_node; + SurfaceTreeTraverseData traverse_data; + traverse_data = (SurfaceTreeTraverseData) { + .window_actor = actor, + .index = 0, + }; 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); + set_surface_actor_index, + &traverse_data); } static void -- GitLab From 6e00e5e6e7c7bab6c2ba408b528e1bdee8f17239 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Fri, 16 Apr 2021 19:38:40 +0200 Subject: [PATCH 2/2] wayland/subsurface: Avoid placement ops for detached subsurfaces If a subsurface first gets reordered and afterwards detached from the parent before the parent surface got commited, we currently would end up reattaching the subsurface to its previous parent. While clients should avoid this behaviour, it's legit according to the spec. We already prevent similar cases where the subsurface is destroyed - extend that check to detaching, which includes the destroy case. Part-of: --- src/wayland/meta-wayland-subsurface.c | 16 ++++++++-------- src/wayland/meta-wayland-subsurface.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c index 27bd91f0c6e..d7f56b66e83 100644 --- a/src/wayland/meta-wayland-subsurface.c +++ b/src/wayland/meta-wayland-subsurface.c @@ -355,11 +355,11 @@ is_valid_sibling (MetaWaylandSurface *surface, } static void -subsurface_handle_pending_surface_destroyed (struct wl_listener *listener, - void *data) +subsurface_handle_pending_subsurface_destroyed (struct wl_listener *listener, + void *data) { MetaWaylandSubsurfacePlacementOp *op = - wl_container_of (listener, op, surface_destroy_listener); + wl_container_of (listener, op, subsurface_destroy_listener); op->surface = NULL; } @@ -378,7 +378,7 @@ void meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op) { if (op->surface) - wl_list_remove (&op->surface_destroy_listener.link); + wl_list_remove (&op->subsurface_destroy_listener.link); if (op->sibling) wl_list_remove (&op->sibling_destroy_listener.link); g_free (op); @@ -396,12 +396,12 @@ queue_subsurface_placement (MetaWaylandSurface *surface, op->placement = placement; op->surface = surface; op->sibling = sibling; - op->surface_destroy_listener.notify = - subsurface_handle_pending_surface_destroyed; + op->subsurface_destroy_listener.notify = + subsurface_handle_pending_subsurface_destroyed; op->sibling_destroy_listener.notify = subsurface_handle_pending_sibling_destroyed; - wl_resource_add_destroy_listener (surface->resource, - &op->surface_destroy_listener); + wl_resource_add_destroy_listener (surface->wl_subsurface, + &op->subsurface_destroy_listener); wl_resource_add_destroy_listener (sibling->resource, &op->sibling_destroy_listener); diff --git a/src/wayland/meta-wayland-subsurface.h b/src/wayland/meta-wayland-subsurface.h index 7ea6bc5ae12..45dbf86269b 100644 --- a/src/wayland/meta-wayland-subsurface.h +++ b/src/wayland/meta-wayland-subsurface.h @@ -40,7 +40,7 @@ typedef struct MetaWaylandSubsurfacePlacement placement; MetaWaylandSurface *surface; MetaWaylandSurface *sibling; - struct wl_listener surface_destroy_listener; + struct wl_listener subsurface_destroy_listener; struct wl_listener sibling_destroy_listener; } MetaWaylandSubsurfacePlacementOp; -- GitLab