[mutter/wip/surface-two: 3/4] wayland-surface: Rework construction / destruction yet again



commit f0cd9b0687789f92e01d629980bbea95774f1b66
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Feb 24 13:32:17 2014 -0500

    wayland-surface: Rework construction / destruction yet again
    
    This time, to make way for MetaSurfaceActorEmpty. This also fixes
    destroy effects as a side effect. It still has issues if we try
    to re-assign an actor that's already toplevel (e.g. somebody
    re-popping up a menu that's already being destroyed), but this
    will be fixed soon.
    
    The idea here is that MetaWindowActor will do the unparenting of
    the surface actor when it itself is destroyed. To prevent bad issues
    with picking, we only make the surface actor reactive when it's
    toplevel.

 src/compositor/meta-window-actor.c |   74 ++++++++++++++++++++++++++---------
 src/wayland/meta-wayland-surface.c |   27 +++++++------
 src/wayland/meta-wayland-surface.h |    1 +
 src/wayland/meta-xwayland.c        |    2 +
 4 files changed, 72 insertions(+), 32 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 0817fbe..d2c16b1 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -68,6 +68,9 @@ struct _MetaWindowActorPrivate
   guint             send_frame_messages_timer;
   gint64            frame_drawn_time;
 
+  guint             repaint_scheduled_id;
+  guint             allocation_changed_id;
+
   /*
    * These need to be counters rather than flags, since more plugins
    * can implement same effect; the practicality of stacking effects
@@ -295,30 +298,66 @@ meta_window_actor_thaw (MetaWindowActor *self)
 }
 
 static void
-meta_window_actor_constructed (GObject *object)
+set_surface (MetaWindowActor  *self,
+             MetaSurfaceActor *surface)
 {
-  MetaWindowActor        *self     = META_WINDOW_ACTOR (object);
-  MetaWindowActorPrivate *priv     = self->priv;
-  MetaWindow             *window   = priv->window;
+  MetaWindowActorPrivate *priv = self->priv;
 
-  priv->screen = window->screen;
+  if (priv->surface)
+    {
+      g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id);
+      priv->repaint_scheduled_id = 0;
+      g_signal_handler_disconnect (priv->surface, priv->allocation_changed_id);
+      priv->allocation_changed_id = 0;
+      clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
+      g_object_unref (priv->surface);
+    }
 
-  if (!priv->surface)
+  priv->surface = surface;
+
+  if (priv->surface)
     {
-      if (window->surface)
-        priv->surface = window->surface->surface_actor;
-      else
-        priv->surface = meta_surface_actor_x11_new (window);
       g_object_ref_sink (priv->surface);
-
+      priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled",
+                                                     G_CALLBACK (surface_repaint_scheduled), self);
+      priv->allocation_changed_id = g_signal_connect (priv->surface, "allocation-changed",
+                                                      G_CALLBACK (surface_allocation_changed_notify), self);
       clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
 
-      g_signal_connect_object (priv->surface, "repaint-scheduled",
-                               G_CALLBACK (surface_repaint_scheduled), self, 0);
-      g_signal_connect_object (priv->surface, "allocation-changed",
-                               G_CALLBACK (surface_allocation_changed_notify), self, 0);
+      /* If the previous surface actor was frozen, start out
+       * frozen as well... */
+      if (priv->updates_frozen)
+        meta_surface_actor_freeze (priv->surface);
+
       meta_window_actor_update_shape (self);
     }
+}
+
+static void
+meta_window_actor_update_surface (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+  MetaWindow *window = priv->window;
+  MetaSurfaceActor *surface_actor;
+
+  if (window->surface)
+    surface_actor = window->surface->surface_actor;
+  else
+    surface_actor = meta_surface_actor_x11_new (window);
+
+  set_surface (self, surface_actor);
+}
+
+static void
+meta_window_actor_constructed (GObject *object)
+{
+  MetaWindowActor        *self     = META_WINDOW_ACTOR (object);
+  MetaWindowActorPrivate *priv     = self->priv;
+  MetaWindow             *window   = priv->window;
+
+  priv->screen = window->screen;
+
+  meta_window_actor_update_surface (self);
 
   meta_window_actor_update_opacity (self);
 
@@ -361,10 +400,7 @@ meta_window_actor_dispose (GObject *object)
 
   g_clear_object (&priv->window);
 
-  /*
-   * Release the extra reference we took on the actor.
-   */
-  g_clear_object (&priv->surface);
+  set_surface (self, NULL);
 
   G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
 }
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 0783316..a7bf050 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -574,23 +574,16 @@ const struct wl_surface_interface meta_wayland_surface_interface = {
   meta_wayland_surface_set_buffer_scale
 };
 
-static void
-unparent_actor (MetaWaylandSurface *surface)
+void
+meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface)
 {
-  ClutterActor *parent_actor;
-
-  parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
-  clutter_actor_remove_child (parent_actor, CLUTTER_ACTOR (surface->surface_actor));
+  clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
 }
 
 void
 meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface)
 {
-  /* The window is being unmanaged. Unparent our surface actor
-   * before the window actor is destroyed, as we need to hold
-   * onto it... */
-  unparent_actor (surface);
-
+  clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), FALSE);
   surface->window = NULL;
 }
 
@@ -649,10 +642,8 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
 
   surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
   surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
-  clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
 
   double_buffered_state_init (&surface->pending);
-
   return surface;
 }
 
@@ -980,6 +971,7 @@ xdg_shell_get_xdg_surface (struct wl_client *client,
       return;
     }
 
+  meta_wayland_surface_make_toplevel (surface);
   surface->window = meta_window_wayland_new (meta_get_display (), surface);
 }
 
@@ -1035,6 +1027,7 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
       return;
     }
 
+  meta_wayland_surface_make_toplevel (surface);
   surface->window = meta_window_wayland_new (meta_get_display (), surface);
   surface->window->rect.x = parent_surf->window->rect.x + x;
   surface->window->rect.y = parent_surf->window->rect.y + y;
@@ -1250,6 +1243,14 @@ subsurface_parent_surface_committed (MetaWaylandSurface *surface)
 }
 
 static void
+unparent_actor (MetaWaylandSurface *surface)
+{
+  ClutterActor *parent_actor;
+  parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
+  clutter_actor_remove_child (parent_actor, CLUTTER_ACTOR (surface->surface_actor));
+}
+
+static void
 wl_subsurface_destructor (struct wl_resource *resource)
 {
   MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 1430569..9e12451 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -118,6 +118,7 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
                                                 guint32                id,
                                                 guint32                version);
 
+void                meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface);
 void                meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface);
 
 void                meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index 36b538b..76ca5cb 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -47,6 +47,8 @@ xserver_set_window_id (struct wl_client *client,
   if (!window)
     return;
 
+  meta_wayland_surface_make_toplevel (surface);
+
   surface->window = window;
   window->surface = surface;
 }


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