mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
wayland/surface: Keep transaction entries for all referenced surfaces
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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
This commit is contained in:
parent
5fa4ce6fa8
commit
e26df6ac14
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user