1
0
Fork 0

wayland/surface: Two phase surface destruction

Destroy Wayland protocol related state immediately when the Wayland
resource is destroyed, but keep the rest alive by any transaction which
references the surface.

This makes it easier and cleaner to deal with a surface getting
destroyed while it's still referenced by transactions.

v2:
* No more need to keep references for surfaces in the entries hash
  table.
v3:
* Do not use surface->sub.transaction in wl_surface_destructor, just
  destroy it.
v4:
* No need for wl_surface_destructor to use its own transaction.
v5:
* Use g_steal_pointer & (more) g_clear_pointer in wl_surface_destructor.
v6:
* Leave SURFACE_DESTROY signal emission in wl_surface_destructor.
v7:
* Use finalize instead of dispose callback.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
This commit is contained in:
Michel Dänzer 2021-07-23 18:33:39 +02:00 committed by Michel Dänzer
parent ff707a6de6
commit 4eef08c5c3

View file

@ -1460,14 +1460,12 @@ meta_wayland_surface_notify_unmapped (MetaWaylandSurface *surface)
}
static void
wl_surface_destructor (struct wl_resource *resource)
meta_wayland_surface_finalize (GObject *object)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = META_WAYLAND_SURFACE (object);
MetaWaylandCompositor *compositor = surface->compositor;
MetaWaylandFrameCallback *cb, *next;
g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0);
g_clear_object (&surface->scanout_candidate);
g_clear_object (&surface->role);
@ -1482,9 +1480,6 @@ wl_surface_destructor (struct wl_resource *resource)
g_clear_pointer (&surface->texture, cogl_object_unref);
g_clear_pointer (&surface->buffer_ref, meta_wayland_buffer_ref_unref);
g_clear_object (&surface->pending_state);
g_clear_pointer (&surface->sub.transaction, meta_wayland_transaction_free);
if (surface->opaque_region)
cairo_region_destroy (surface->opaque_region);
if (surface->input_region)
@ -1506,13 +1501,33 @@ wl_surface_destructor (struct wl_resource *resource)
meta_wayland_surface_discard_presentation_feedback (surface);
if (surface->wl_subsurface)
wl_resource_destroy (surface->wl_subsurface);
g_clear_pointer (&surface->subsurface_branch_node, g_node_destroy);
g_hash_table_destroy (surface->shortcut_inhibited_seats);
G_OBJECT_CLASS (meta_wayland_surface_parent_class)->finalize (object);
}
static void
wl_surface_destructor (struct wl_resource *resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0);
g_clear_object (&surface->pending_state);
g_clear_pointer (&surface->sub.transaction, meta_wayland_transaction_free);
if (surface->resource)
wl_resource_set_user_data (g_steal_pointer (&surface->resource), NULL);
g_clear_pointer (&surface->wl_subsurface, wl_resource_destroy);
/*
* Any transactions referencing this surface will keep it alive until they get
* applied/destroyed. The last reference will be dropped in
* meta_wayland_transaction_free.
*/
g_object_unref (surface);
}
@ -1772,6 +1787,7 @@ meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_wayland_surface_finalize;
object_class->get_property = meta_wayland_surface_get_property;
obj_props[PROP_SCANOUT_CANDIDATE] =