iconGrid: Create icon clones in a separate loop
For reasons not yet fully understood, `Main.uiGroup.add_actor` takes around
10 milliseconds to complete.
Because of this, each `actor.opacity = 0` has a good chance of falling
on a different frame. And when it does, `_opacityChangedId` also lands
on multiple different frames each incurring a separate relayout cycle.
It is this excessive number of relayouts that causes stuttering in the
icon grid animation (#2065). But it is the slowness of `uiGroup.add_actor`
that causes the number to be excessive when it should be one.
By creating the clones and adding them to `uiGroup` early, we then enable
the existing loop starting the animation to complete within a single frame.
And by completing within a single frame all the opacity changes land within
the same frame interval, thus incurring only a single relayout instead of
many.
This issue went unnoticed until 004a5e1042
(!704), after which the slow
emissions of `notify::opacity` became a more visible performance problem.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/2065
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1002
This commit is contained in:
parent
12de4e67f8
commit
e781e1fdba
@ -556,15 +556,25 @@ var IconGrid = GObject.registerClass({
|
|||||||
}, Infinity);
|
}, Infinity);
|
||||||
let normalization = maxDist - minDist;
|
let normalization = maxDist - minDist;
|
||||||
|
|
||||||
for (let index = 0; index < actors.length; index++) {
|
actors.forEach(actor => {
|
||||||
let actor = actors[index];
|
let clone = new Clutter.Clone({ source: actor });
|
||||||
|
this._clonesAnimating.push(clone);
|
||||||
|
Main.uiGroup.add_actor(clone);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ^
|
||||||
|
* | These need to be separate loops because Main.uiGroup.add_actor
|
||||||
|
* | is excessively slow if done inside the below loop and we want the
|
||||||
|
* | below loop to complete within one frame interval (#2065, !1002).
|
||||||
|
* v
|
||||||
|
*/
|
||||||
|
|
||||||
|
this._clonesAnimating.forEach(actorClone => {
|
||||||
|
let actor = actorClone.source;
|
||||||
actor.opacity = 0;
|
actor.opacity = 0;
|
||||||
actor.reactive = false;
|
actor.reactive = false;
|
||||||
|
|
||||||
let actorClone = new Clutter.Clone({ source: actor });
|
|
||||||
this._clonesAnimating.push(actorClone);
|
|
||||||
Main.uiGroup.add_actor(actorClone);
|
|
||||||
|
|
||||||
let [width, height] = this._getAllocatedChildSizeAndSpacing(actor);
|
let [width, height] = this._getAllocatedChildSizeAndSpacing(actor);
|
||||||
actorClone.set_size(width, height);
|
actorClone.set_size(width, height);
|
||||||
let scaleX = sourceScaledWidth / width;
|
let scaleX = sourceScaledWidth / width;
|
||||||
@ -631,7 +641,7 @@ var IconGrid = GObject.registerClass({
|
|||||||
|
|
||||||
actorClone.ease(movementParams);
|
actorClone.ease(movementParams);
|
||||||
actorClone.ease(fadeParams);
|
actorClone.ease(fadeParams);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_getAllocatedChildSizeAndSpacing(child) {
|
_getAllocatedChildSizeAndSpacing(child) {
|
||||||
|
Loading…
Reference in New Issue
Block a user