[mutter/wayland] wayland-surface: Unmanage the window when destroying xdg_surface/xdg_popup



commit fe26cb59893100c52f34ca323b723b18ea62f215
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue Nov 26 13:04:37 2013 -0500

    wayland-surface: Unmanage the window when destroying xdg_surface/xdg_popup
    
    Also, unparent the actor when destroying a subsurface, as well, and
    don't free the surface when we destroy the MetaWindow.

 src/core/window.c                  |    3 -
 src/wayland/meta-wayland-surface.c |  103 +++++++++++++++++++++++++++++-------
 src/wayland/meta-wayland-surface.h |    2 -
 3 files changed, 83 insertions(+), 25 deletions(-)
---
diff --git a/src/core/window.c b/src/core/window.c
index 7435c83..5b1490d 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -2068,9 +2068,6 @@ meta_window_unmanage (MetaWindow  *window,
   else
     meta_display_unregister_wayland_window (window->display, window);
 
-  if (window->surface)
-    meta_wayland_surface_free (window->surface);
-
   g_slist_free_full (window->pending_pings, (GDestroyNotify) ping_data_free);
 
   meta_prefs_remove_listener (prefs_changed_callback, window);
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index d8822cc..cbad045 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -395,7 +395,7 @@ const struct wl_surface_interface meta_wayland_surface_interface = {
   meta_wayland_surface_set_buffer_scale
 };
 
-void
+static void
 meta_wayland_surface_free (MetaWaylandSurface *surface)
 {
   MetaWaylandCompositor *compositor = surface->compositor;
@@ -416,12 +416,38 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
 
   meta_wayland_compositor_repick (compositor);
 
+  g_object_unref (surface->surface_actor);
+
   if (surface->resource)
     wl_resource_set_user_data (surface->resource, NULL);
   g_slice_free (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
+destroy_window (MetaWaylandSurface *surface)
+{
+  MetaDisplay *display = meta_get_display ();
+  guint32 timestamp = meta_display_get_current_time_roundtrip (display);
+
+  /* Remove our actor from the parent, so it doesn't get destroyed when
+   * the MetaWindowActor is destroyed. */
+  unparent_actor (surface);
+
+  g_assert (surface->window != NULL);
+  meta_window_unmanage (surface->window, timestamp);
+  surface->window = NULL;
+}
+
+static void
 meta_wayland_surface_resource_destroy_cb (struct wl_resource *resource)
 {
   MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -441,16 +467,10 @@ meta_wayland_surface_resource_destroy_cb (struct wl_resource *resource)
 
       /* NB: If the surface corresponds to an X window then we will be
        * sure to free the MetaWindow according to some X event. */
-      if (surface->window &&
-         surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
-       {
-         MetaDisplay *display = meta_get_display ();
-         guint32 timestamp = meta_display_get_current_time_roundtrip (display);
-
-         meta_window_unmanage (surface->window, timestamp);
-       }
-      else if (!surface->window)
-       meta_wayland_surface_free (surface);
+      if (surface->window && surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
+        destroy_window (surface);
+
+      meta_wayland_surface_free (surface);
     }
 }
 
@@ -486,14 +506,13 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
     surface_handle_pending_buffer_destroy;
   wl_list_init (&surface->pending.frame_callback_list);
 
-  surface->surface_actor = meta_surface_actor_new ();
+  surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ());
   return surface;
 }
 
 static void
-destroy_surface_extension (struct wl_resource *resource)
+destroy_surface_extension (MetaWaylandSurfaceExtension *extension)
 {
-  MetaWaylandSurfaceExtension *extension = wl_resource_get_user_data (resource);
   wl_list_remove (&extension->surface_destroy_listener.link);
   extension->surface_destroy_listener.notify = NULL;
   extension->resource = NULL;
@@ -522,7 +541,8 @@ create_surface_extension (MetaWaylandSurfaceExtension *extension,
                           guint32                      id,
                           int                          max_version,
                           const struct wl_interface   *interface,
-                          const void                  *implementation)
+                          const void                  *implementation,
+                          wl_resource_destroy_func_t   destructor)
 {
   struct wl_resource *resource;
 
@@ -530,7 +550,7 @@ create_surface_extension (MetaWaylandSurfaceExtension *extension,
     return FALSE;
 
   resource = wl_resource_create (client, interface, get_resource_version (master_resource, max_version), id);
-  wl_resource_set_implementation (resource, implementation, extension, destroy_surface_extension);
+  wl_resource_set_implementation (resource, implementation, extension, destructor);
 
   extension->resource = resource;
   extension->surface_destroy_listener.notify = extension_handle_surface_destroy;
@@ -539,6 +559,16 @@ create_surface_extension (MetaWaylandSurfaceExtension *extension,
 }
 
 static void
+xdg_surface_destructor (struct wl_resource *resource)
+{
+  MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
+
+  destroy_window (surface);
+  destroy_surface_extension (xdg_surface);
+}
+
+static void
 xdg_surface_destroy (struct wl_client *client,
                      struct wl_resource *resource)
 {
@@ -777,7 +807,8 @@ get_xdg_surface (struct wl_client *client,
   if (!create_surface_extension (&surface->xdg_surface, client, surface_resource, resource, id,
                                  META_XDG_SURFACE_VERSION,
                                  &xdg_surface_interface,
-                                 &meta_wayland_xdg_surface_interface))
+                                 &meta_wayland_xdg_surface_interface,
+                                 xdg_surface_destructor))
     {
       wl_resource_post_error (surface_resource,
                               WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -789,6 +820,16 @@ get_xdg_surface (struct wl_client *client,
 }
 
 static void
+xdg_popup_destructor (struct wl_resource *resource)
+{
+  MetaWaylandSurfaceExtension *xdg_popup = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (xdg_popup, surface, xdg_popup);
+
+  destroy_window (surface);
+  destroy_surface_extension (xdg_popup);
+}
+
+static void
 xdg_popup_destroy (struct wl_client *client,
                    struct wl_resource *resource)
 {
@@ -836,7 +877,8 @@ get_xdg_popup (struct wl_client *client,
   if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id,
                                  META_XDG_POPUP_VERSION,
                                  &xdg_popup_interface,
-                                 &meta_wayland_xdg_popup_interface))
+                                 &meta_wayland_xdg_popup_interface,
+                                 xdg_popup_destructor))
     {
       wl_resource_post_error (surface_resource,
                               WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -875,6 +917,15 @@ bind_xdg_shell (struct wl_client *client,
 }
 
 static void
+gtk_surface_destructor (struct wl_resource *resource)
+{
+  MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface);
+
+  destroy_surface_extension (gtk_surface);
+}
+
+static void
 set_dbus_properties (struct wl_client   *client,
                     struct wl_resource *resource,
                     const char         *application_id,
@@ -911,7 +962,8 @@ get_gtk_surface (struct wl_client *client,
   if (!create_surface_extension (&surface->gtk_surface, client, surface_resource, resource, id,
                                  META_GTK_SURFACE_VERSION,
                                  &gtk_surface_interface,
-                                 &meta_wayland_gtk_surface_interface))
+                                 &meta_wayland_gtk_surface_interface,
+                                 gtk_surface_destructor))
     {
       wl_resource_post_error (surface_resource,
                               WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -941,6 +993,16 @@ bind_gtk_shell (struct wl_client *client,
 }
 
 static void
+wl_subsurface_destructor (struct wl_resource *resource)
+{
+  MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
+
+  unparent_actor (surface);
+  destroy_surface_extension (subsurface);
+}
+
+static void
 wl_subsurface_destroy (struct wl_client *client,
                        struct wl_resource *resource)
 {
@@ -1036,7 +1098,8 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
   if (!create_surface_extension (&surface->subsurface, client, surface_resource, resource, id,
                                  META_GTK_SURFACE_VERSION,
                                  &wl_subsurface_interface,
-                                 &meta_wayland_subsurface_interface))
+                                 &meta_wayland_subsurface_interface,
+                                 wl_subsurface_destructor))
     {
       wl_resource_post_error (surface_resource,
                               WL_DISPLAY_ERROR_INVALID_OBJECT,
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 28dfa14..9533731 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -95,8 +95,6 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
                                                 struct wl_client      *client,
                                                 guint32                id,
                                                 guint32                version);
-void                meta_wayland_surface_free   (MetaWaylandSurface    *surface);
-
 void                meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
                                                           int                 width,
                                                           int                 height,


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