[mutter/wayland] wayland: Rework how surface destruction works
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wayland] wayland: Rework how surface destruction works
- Date: Tue, 18 Feb 2014 22:03:23 +0000 (UTC)
commit 2a145262c7af22bf379fba69916597f5769d4c1a
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Tue Feb 18 16:39:23 2014 -0500
wayland: Rework how surface destruction works
To prevent the MetaSurfaceActor from being destroyed, we normally
unparent it before we unmanage the window. However, this doesn't
work for XWayland windows, which we unmanage when we get UnmapNotify
or DestroyNotify, not when we get the wl_surface_destroy.
To solve this, add an early hook in meta_window_unmanage that
unparents the surface actor if we have one. At the same time, clean
up the destruction code to remove old comments and assumptions about
how wl_shell behaves.
src/core/window.c | 3 ++
src/wayland/meta-wayland-surface.c | 65 ++++++++++++++---------------------
src/wayland/meta-wayland-surface.h | 3 ++
3 files changed, 32 insertions(+), 39 deletions(-)
---
diff --git a/src/core/window.c b/src/core/window.c
index ccd1749..79b7cb3 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -1498,6 +1498,9 @@ meta_window_unmanage (MetaWindow *window,
meta_verbose ("Unmanaging 0x%lx\n", window->xwindow);
+ if (window->surface)
+ meta_wayland_surface_window_unmanaged (window->surface);
+
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
MetaStackWindow stack_window;
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 496a6bf..b8fc0e7 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -574,23 +574,6 @@ const struct wl_surface_interface meta_wayland_surface_interface = {
};
static void
-meta_wayland_surface_free (MetaWaylandSurface *surface)
-{
- MetaWaylandCompositor *compositor = surface->compositor;
-
- compositor->surfaces = g_list_remove (compositor->surfaces, surface);
-
- surface_set_buffer (surface, NULL);
- double_buffered_state_destroy (&surface->pending);
- g_object_unref (surface->surface_actor);
- if (surface->resource)
- wl_resource_set_user_data (surface->resource, NULL);
- g_slice_free (MetaWaylandSurface, surface);
-
- meta_wayland_compositor_repick (compositor);
-}
-
-static void
unparent_actor (MetaWaylandSurface *surface)
{
ClutterActor *parent_actor;
@@ -599,46 +582,50 @@ unparent_actor (MetaWaylandSurface *surface)
clutter_actor_remove_child (parent_actor, CLUTTER_ACTOR (surface->surface_actor));
}
+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);
+
+ surface->window = NULL;
+}
+
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;
+ g_assert (surface->window == NULL);
}
static void
wl_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
+ MetaWaylandCompositor *compositor = surface->compositor;
- /* There are four cases here:
- - An X11 unmanaged window -> surface is NULL, nothing to do
- - An X11 unmanaged window, but we got the wayland event first ->
- just clear the resource pointer
- - A wayland surface without window (destroyed before set_toplevel) ->
- need to free the surface itself
- - A wayland window -> need to unmanage
- */
+ /* At the time when the wl_surface is destroyed, we should
+ * no longer have a window, unless we're an XWayland window
+ * in which case we received the wl_surface.destroy before
+ * the UnmapNotify/DestroyNotify. */
+ g_assert (surface->window == NULL || surface->window->client_type == META_WINDOW_CLIENT_TYPE_X11);
- if (surface)
- {
- surface->resource = NULL;
+ compositor->surfaces = g_list_remove (compositor->surfaces, surface);
- /* 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)
- destroy_window (surface);
+ surface_set_buffer (surface, NULL);
+ double_buffered_state_destroy (&surface->pending);
+ g_object_unref (surface->surface_actor);
+ if (surface->resource)
+ wl_resource_set_user_data (surface->resource, NULL);
+ g_slice_free (MetaWaylandSurface, surface);
- meta_wayland_surface_free (surface);
- }
+ meta_wayland_compositor_repick (compositor);
}
MetaWaylandSurface *
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index df725db..0fafb8c 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -118,6 +118,9 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
struct wl_client *client,
guint32 id,
guint32 version);
+
+void meta_wayland_surface_window_unmanaged (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]