mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 11:32:04 +00:00
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:
parent
1783bf20ec
commit
f0cd9b0687
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user