clutter/actor: Don't allocate actors if only the absolute origin changed

For actors which don't have needs_allocation set to TRUE and where the
new allocation wouldn't be different from the old one, the allocate()
vfunc doesn't have to be called. We still did this in case a parent
actor was moved though (so the absolute origin changed), because we
needed to propagate the ABSOLUTE_ORIGIN_CHANGED allocation flag down to
all actors.

Since that flag is now removed and got replaced with a private property,
we can simply notify the children about the absolute allocation change
using the existing infrastructure and safely stop allocating children at
this point.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
This commit is contained in:
Jonas Dreßler 2020-05-11 15:11:07 +02:00 committed by Jonas Ådahl
parent 9b39e37fee
commit 720360b07a

View File

@ -10115,7 +10115,6 @@ clutter_actor_allocate (ClutterActor *self,
{ {
ClutterActorBox old_allocation, real_allocation; ClutterActorBox old_allocation, real_allocation;
gboolean origin_changed, size_changed; gboolean origin_changed, size_changed;
gboolean stage_allocation_changed;
ClutterActorPrivate *priv; ClutterActorPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (CLUTTER_IS_ACTOR (self));
@ -10178,23 +10177,25 @@ clutter_actor_allocate (ClutterActor *self,
size_changed = (real_allocation.x2 != old_allocation.x2 || size_changed = (real_allocation.x2 != old_allocation.x2 ||
real_allocation.y2 != old_allocation.y2); real_allocation.y2 != old_allocation.y2);
stage_allocation_changed = /* When needs_allocation is set but we didn't move nor resize, we still
priv->absolute_origin_changed || origin_changed || size_changed; * want to call the allocate() vfunc because a child probably called
* queue_relayout() and needs a new allocation.
/* If we get an allocation "out of the blue"
* (we did not queue relayout), then we want to
* ignore it. But if we have needs_allocation set,
* we want to guarantee that allocate() virtual
* method is always called, i.e. that queue_relayout()
* always results in an allocate() invocation on
* an actor.
* *
* The optimization here is to avoid re-allocating * In case needs_allocation isn't set and we didn't move nor resize, we
* actors that did not queue relayout and were * can safely stop allocating, but we need to notify the sub-tree in case
* not moved. * our absolute origin changed.
*/ */
if (!priv->needs_allocation && !stage_allocation_changed) if (!priv->needs_allocation && !origin_changed && !size_changed)
{ {
if (priv->absolute_origin_changed)
{
_clutter_actor_traverse (self,
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
absolute_allocation_changed_cb,
NULL,
NULL);
}
CLUTTER_NOTE (LAYOUT, "No allocation needed"); CLUTTER_NOTE (LAYOUT, "No allocation needed");
goto out; goto out;
} }
@ -10202,10 +10203,10 @@ clutter_actor_allocate (ClutterActor *self,
if (CLUTTER_ACTOR_IS_MAPPED (self)) if (CLUTTER_ACTOR_IS_MAPPED (self))
self->priv->needs_paint_volume_update = TRUE; self->priv->needs_paint_volume_update = TRUE;
if (!stage_allocation_changed) if (!origin_changed && !size_changed)
{ {
/* If the actor didn't move but needs_allocation is set, we just /* If the actor didn't move but needs_allocation is set, we just
* need to allocate the children */ * need to allocate the children (see comment above) */
clutter_actor_allocate_internal (self, &real_allocation); clutter_actor_allocate_internal (self, &real_allocation);
goto out; goto out;
} }