From e26df6ac140b739447947741b2db9e7771993638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Mon, 13 Jun 2022 18:58:56 +0200 Subject: [PATCH] wayland/surface: Keep transaction entries for all referenced surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This keeps all surfaces referenced by a transaction alive until the transaction is destroyed, and makes sure transactions are applied in the same order as they were committed with respect to all surfaces they reference. v2: * Guard against NULL entry in meta_wayland_transaction_apply. v3: * Keep single entries hash table. v4: * Unref the surface in the meta_wayland_transaction_merge_into while loop only if the "to" transaction didn't already have an entry for it, to prevent premature finalization of the surface (likely followed by a crash). v5: * Unref the surface (implicitly via g_hash_table_iter_remove) in the meta_wayland_transaction_merge_into while loop even if the "to" transaction already had an entry for it, or we leak a reference. * Use g_clear_object & g_steal_pointer to not leave behind a dangling from->state pointer in meta_wayland_transaction_entry_merge_into. v6: * Add curly braces around meta_wayland_transaction_add_placement_surfaces calls. (Jonas Ã…dahl) Part-of: --- src/wayland/meta-wayland-transaction.c | 56 +++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c index 81470a199..54f7dec34 100644 --- a/src/wayland/meta-wayland-transaction.c +++ b/src/wayland/meta-wayland-transaction.c @@ -35,6 +35,10 @@ struct _MetaWaylandTransaction MetaWaylandTransaction *next_candidate; uint64_t committed_sequence; + /* + * Keys: All surfaces referenced in the transaction + * Values: Pointer to MetaWaylandTransactionEntry for the surface + */ GHashTable *entries; }; @@ -303,7 +307,7 @@ meta_wayland_transaction_ensure_entry (MetaWaylandTransaction *transaction, return entry; entry = g_new0 (MetaWaylandTransactionEntry, 1); - g_hash_table_insert (transaction->entries, surface, entry); + g_hash_table_insert (transaction->entries, g_object_ref (surface), entry); return entry; } @@ -315,6 +319,39 @@ meta_wayland_transaction_entry_free (MetaWaylandTransactionEntry *entry) g_free (entry); } +static void +meta_wayland_transaction_add_placement_surfaces (MetaWaylandTransaction *transaction, + MetaWaylandSurface *surface, + MetaWaylandSurfaceState *state) +{ + GSList *l; + + for (l = state->subsurface_placement_ops; l; l = l->next) + { + MetaWaylandSubsurfacePlacementOp *op = l->data; + + if (op->surface) + meta_wayland_transaction_ensure_entry (transaction, op->surface); + + if (op->sibling) + meta_wayland_transaction_ensure_entry (transaction, op->sibling); + } +} + +static void +meta_wayland_transaction_add_entry (MetaWaylandTransaction *transaction, + MetaWaylandSurface *surface, + MetaWaylandTransactionEntry *entry) +{ + g_hash_table_insert (transaction->entries, g_object_ref (surface), entry); + + if (entry->state) + { + meta_wayland_transaction_add_placement_surfaces (transaction, surface, + entry->state); + } +} + void meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *transaction, MetaWaylandSurface *surface, @@ -347,7 +384,7 @@ meta_wayland_transaction_entry_merge_into (MetaWaylandTransactionEntry *from, return; } - to->state = from->state; + to->state = g_steal_pointer (&from->state); } void @@ -362,16 +399,23 @@ meta_wayland_transaction_merge_into (MetaWaylandTransaction *from, while (g_hash_table_iter_next (&iter, (gpointer *) &surface, (gpointer *) &from_entry)) { - g_hash_table_iter_steal (&iter); to_entry = meta_wayland_transaction_get_entry (to, surface); if (!to_entry) { - g_hash_table_insert (to->entries, surface, from_entry); + g_hash_table_iter_steal (&iter); + meta_wayland_transaction_add_entry (to, surface, from_entry); + g_object_unref (surface); continue; } + if (from_entry->state) + { + meta_wayland_transaction_add_placement_surfaces (to, surface, + from_entry->state); + } + meta_wayland_transaction_entry_merge_into (from_entry, to_entry); - meta_wayland_transaction_entry_free (from_entry); + g_hash_table_iter_remove (&iter); } meta_wayland_transaction_free (from); @@ -405,7 +449,7 @@ meta_wayland_transaction_new (MetaWaylandCompositor *compositor) transaction = g_new0 (MetaWaylandTransaction, 1); transaction->compositor = compositor; - transaction->entries = g_hash_table_new_full (NULL, NULL, NULL, + transaction->entries = g_hash_table_new_full (NULL, NULL, g_object_unref, (GDestroyNotify) meta_wayland_transaction_entry_free); return transaction;