clutter/stage: Don't assume stage relayouts reallocate everything
With the introduction of "shallow" relayouts, we are now able to enter allocation cycles not only at the stage but also deeper down the hierarchy if we know an actors allocation isn't affected by its children since the NO_LAYOUT flag is set. Now that means when queuing relayouts it's possible that `priv->needs_allocation` gets set to TRUE for some actors down the hierarchy, but not for actors higher up in the hierarchy. An actor tree where that happens could look like that: stage -> container -> container2 (NO_LAYOUT) -> textActor With that tree, if the "textActor" queues a relayout, "container2" will be added to the relayout hashtable of the stage and the actors "stage" and "container" will have `priv->needs_allocation` set to FALSE. Now if another relayout on the stage actor is queued, `clutter_stage_queue_actor_relayout()` currently removes all the other hashtable entries in favour of the stage entry, (wrongly) assuming that will allocate everything. It doesn't allocate everything because in the example above "container" has `priv->needs_allocation` set to FALSE, which makes clutter_actor_allocate() return early before allocating its children, so in the end "container2" will never get a new allocation. To fix this, stop flushing the relayout hashtable when queuing a stage-relayout and still add new entries to the hashtable if a stage relayout is already queued to make sure we still go through all the previously queued "shallow" relayouts. That shouldn't hurt performance, too, because as soon as an actor got allocated once, it doesn't need an allocation anymore and should bail out in clutter_actor_allocate() as long as it's absolute position didn't change. Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2538 https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1173
This commit is contained in:
parent
ce64ab5449
commit
e74c2e42cf
@ -1310,15 +1310,9 @@ clutter_stage_queue_actor_relayout (ClutterStage *stage,
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
|
||||
if (g_hash_table_contains (priv->pending_relayouts, stage))
|
||||
return;
|
||||
|
||||
if (g_hash_table_size (priv->pending_relayouts) == 0)
|
||||
_clutter_stage_schedule_update (stage);
|
||||
|
||||
if (actor == (ClutterActor *) stage)
|
||||
g_hash_table_remove_all (priv->pending_relayouts);
|
||||
|
||||
g_hash_table_add (priv->pending_relayouts, g_object_ref (actor));
|
||||
priv->pending_relayouts_version++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user