[mutter] wayland/actor-surface: Handle surface actor destruction



commit cbb4f6c892c1c795aaabb5b39be91d4defc6ad65
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Thu Oct 3 21:44:34 2019 +0200

    wayland/actor-surface: Handle surface actor destruction
    
    A surface actor may be destroyed without the backing Wayland surface
    being destroyed yet, e.g. by the window being unmanaged. Handle this by
    listening on the "destroy" signal and making late requests (e.g.
    wl_surface_commit()) resilient against the lack of a surface actor.
    
    Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/838
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/825

 src/wayland/meta-wayland-actor-surface.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)
---
diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c
index 5e8cd09b9..21cbe7a7c 100644
--- a/src/wayland/meta-wayland-actor-surface.c
+++ b/src/wayland/meta-wayland-actor-surface.c
@@ -36,6 +36,8 @@ typedef struct _MetaWaylandActorSurfacePrivate MetaWaylandActorSurfacePrivate;
 struct _MetaWaylandActorSurfacePrivate
 {
   MetaSurfaceActor *actor;
+
+  gulong actor_destroyed_handler_id;
 };
 
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface,
@@ -60,6 +62,10 @@ clear_surface_actor (MetaWaylandActorSurface *actor_surface)
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
 
+  if (!priv->actor)
+    return;
+
+  g_clear_signal_handler (&priv->actor_destroyed_handler_id, priv->actor);
   g_signal_handlers_disconnect_by_func (priv->actor,
                                         meta_wayland_surface_notify_geometry_changed,
                                         surface);
@@ -104,6 +110,9 @@ meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor
   MetaSurfaceActorWayland *surface_actor_wayland =
     META_SURFACE_ACTOR_WAYLAND (priv->actor);
 
+  if (!priv->actor)
+    return;
+
   meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
                                                   &pending->frame_callback_list);
   wl_list_init (&pending->frame_callback_list);
@@ -226,6 +235,11 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole  *surface_role,
 {
   MetaWaylandActorSurface *actor_surface =
     META_WAYLAND_ACTOR_SURFACE (surface_role);
+  MetaWaylandActorSurfacePrivate *priv =
+    meta_wayland_actor_surface_get_instance_private (actor_surface);
+
+  if (!priv->actor)
+    return;
 
   meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
 
@@ -304,6 +318,13 @@ meta_wayland_actor_surface_get_actor (MetaWaylandActorSurface *actor_surface)
   return priv->actor;
 }
 
+static void
+on_actor_destroyed (ClutterActor            *actor,
+                    MetaWaylandActorSurface *actor_surface)
+{
+  clear_surface_actor (actor_surface);
+}
+
 void
 meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface)
 {
@@ -315,6 +336,10 @@ meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface)
   clear_surface_actor (actor_surface);
 
   priv->actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
+  priv->actor_destroyed_handler_id =
+    g_signal_connect (priv->actor, "destroy",
+                      G_CALLBACK (on_actor_destroyed),
+                      surface);
 
   g_signal_connect_swapped (priv->actor, "notify::allocation",
                             G_CALLBACK (meta_wayland_surface_notify_geometry_changed),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]