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; }