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.
This commit is contained in:
Jasper St. Pierre 2014-02-24 13:32:17 -05:00
parent 1783bf20ec
commit f0cd9b0687
4 changed files with 73 additions and 33 deletions

View File

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

View File

@ -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)
{

View File

@ -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,

View File

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