From f0cd9b0687789f92e01d629980bbea95774f1b66 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Mon, 24 Feb 2014 13:32:17 -0500 Subject: [PATCH] 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 | 76 ++++++++++++++++++++++-------- src/wayland/meta-wayland-surface.c | 27 ++++++----- src/wayland/meta-wayland-surface.h | 1 + src/wayland/meta-xwayland.c | 2 + 4 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 0817fbe89..d2c16b1cf 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 @@ -294,6 +297,57 @@ meta_window_actor_thaw (MetaWindowActor *self) meta_window_actor_handle_updates (self); } +static void +set_surface (MetaWindowActor *self, + MetaSurfaceActor *surface) +{ + MetaWindowActorPrivate *priv = self->priv; + + 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); + } + + priv->surface = surface; + + if (priv->surface) + { + 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)); + + /* 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) { @@ -303,22 +357,7 @@ meta_window_actor_constructed (GObject *object) priv->screen = window->screen; - 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); - - 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); - meta_window_actor_update_shape (self); - } + 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 0783316fe..a7bf0504e 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; @@ -1249,6 +1242,14 @@ subsurface_parent_surface_committed (MetaWaylandSurface *surface) double_buffered_state_reset (pending_surface_state); } +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) { diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 14305696c..9e12451d4 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 36b538b30..76ca5cb66 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; }