wayland/actor-surface: Handle surface actor destruction

A surface actor may be destroyed without the backing Wayland surface
being destroyed yet, e.g. by the window being unmanaged. Handle this by
listening on the "destroy" signal and making late requests (e.g.
wl_surface_commit()) resilient against the lack of a surface actor.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/838

https://gitlab.gnome.org/GNOME/mutter/merge_requests/825
This commit is contained in:
Jonas Ådahl 2019-10-03 21:44:34 +02:00 committed by Georges Basile Stavracas Neto
parent 092b3edb51
commit cbb4f6c892

View File

@ -36,6 +36,8 @@ typedef struct _MetaWaylandActorSurfacePrivate MetaWaylandActorSurfacePrivate;
struct _MetaWaylandActorSurfacePrivate
{
MetaSurfaceActor *actor;
gulong actor_destroyed_handler_id;
};
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface,
@ -60,6 +62,10 @@ clear_surface_actor (MetaWaylandActorSurface *actor_surface)
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
if (!priv->actor)
return;
g_clear_signal_handler (&priv->actor_destroyed_handler_id, priv->actor);
g_signal_handlers_disconnect_by_func (priv->actor,
meta_wayland_surface_notify_geometry_changed,
surface);
@ -104,6 +110,9 @@ meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor
MetaSurfaceActorWayland *surface_actor_wayland =
META_SURFACE_ACTOR_WAYLAND (priv->actor);
if (!priv->actor)
return;
meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
&pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
@ -226,6 +235,11 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
{
MetaWaylandActorSurface *actor_surface =
META_WAYLAND_ACTOR_SURFACE (surface_role);
MetaWaylandActorSurfacePrivate *priv =
meta_wayland_actor_surface_get_instance_private (actor_surface);
if (!priv->actor)
return;
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
@ -304,6 +318,13 @@ meta_wayland_actor_surface_get_actor (MetaWaylandActorSurface *actor_surface)
return priv->actor;
}
static void
on_actor_destroyed (ClutterActor *actor,
MetaWaylandActorSurface *actor_surface)
{
clear_surface_actor (actor_surface);
}
void
meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface)
{
@ -315,6 +336,10 @@ meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface)
clear_surface_actor (actor_surface);
priv->actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
priv->actor_destroyed_handler_id =
g_signal_connect (priv->actor, "destroy",
G_CALLBACK (on_actor_destroyed),
surface);
g_signal_connect_swapped (priv->actor, "notify::allocation",
G_CALLBACK (meta_wayland_surface_notify_geometry_changed),