wayland/actor-surface: Always store away frame callbacks on commit

We're expected by MetaWaylandSurface to always pick the frame callbacks
out from the pending state when committing (applying) so that no frame
callbacks are unaccounted for. We failed to do this if our actor for
some reason (e.g. associated window was unmanaged) was destroyed. To
handle this situation better, store away the frame callbacks until we
some later point in time need to pass them on forward.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/893
This commit is contained in:
Jonas Ådahl 2019-10-28 18:20:31 +01:00 committed by Georges Basile Stavracas Neto
parent 806ebc464a
commit 0e5a5df5fe

View File

@ -38,6 +38,8 @@ struct _MetaWaylandActorSurfacePrivate
MetaSurfaceActor *actor; MetaSurfaceActor *actor;
gulong actor_destroyed_handler_id; gulong actor_destroyed_handler_id;
struct wl_list frame_callback_list;
}; };
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface, G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface,
@ -78,6 +80,7 @@ meta_wayland_actor_surface_dispose (GObject *object)
MetaWaylandActorSurface *actor_surface = META_WAYLAND_ACTOR_SURFACE (object); MetaWaylandActorSurface *actor_surface = META_WAYLAND_ACTOR_SURFACE (object);
MetaWaylandActorSurfacePrivate *priv = MetaWaylandActorSurfacePrivate *priv =
meta_wayland_actor_surface_get_instance_private (actor_surface); meta_wayland_actor_surface_get_instance_private (actor_surface);
MetaWaylandFrameCallback *cb, *next;
if (priv->actor) if (priv->actor)
{ {
@ -85,6 +88,9 @@ meta_wayland_actor_surface_dispose (GObject *object)
clear_surface_actor (actor_surface); clear_surface_actor (actor_surface);
} }
wl_list_for_each_safe (cb, next, &priv->frame_callback_list, link)
wl_resource_destroy (cb->resource);
G_OBJECT_CLASS (meta_wayland_actor_surface_parent_class)->dispose (object); G_OBJECT_CLASS (meta_wayland_actor_surface_parent_class)->dispose (object);
} }
@ -113,6 +119,9 @@ meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor
if (!priv->actor) if (!priv->actor)
return; return;
meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
&priv->frame_callback_list);
wl_list_init (&priv->frame_callback_list);
meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland, meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
&pending->frame_callback_list); &pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list); wl_list_init (&pending->frame_callback_list);
@ -239,7 +248,12 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
meta_wayland_actor_surface_get_instance_private (actor_surface); meta_wayland_actor_surface_get_instance_private (actor_surface);
if (!priv->actor) if (!priv->actor)
{
wl_list_insert_list (&priv->frame_callback_list,
&pending->frame_callback_list);
wl_list_init (&pending->frame_callback_list);
return; return;
}
if (!wl_list_empty (&pending->frame_callback_list) && if (!wl_list_empty (&pending->frame_callback_list) &&
cairo_region_is_empty (pending->surface_damage) && cairo_region_is_empty (pending->surface_damage) &&
@ -292,8 +306,12 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
} }
static void static void
meta_wayland_actor_surface_init (MetaWaylandActorSurface *role) meta_wayland_actor_surface_init (MetaWaylandActorSurface *actor_surface)
{ {
MetaWaylandActorSurfacePrivate *priv =
meta_wayland_actor_surface_get_instance_private (actor_surface);
wl_list_init (&priv->frame_callback_list);
} }
static void static void