workspace: Use Util.lerp() instead of actor box for interpolating

Instead of interpolating our workspace and layout boxes for each child
using clutter_actor_box_interpolate(), use our Util.lerp() function and
stay in JS land instead.

This is quite a large performance improvement since it avoids
heap-allocating a new ClutterActorBox for every child. With this, we're
finally at a duration of 1.0 ms to allocate the Workspace with 20
windows.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1743>
This commit is contained in:
Jonas Dreßler 2021-02-25 17:20:42 +01:00 committed by Marge Bot
parent afb56df55c
commit 59b97a3095

View File

@ -616,8 +616,7 @@ var WorkspaceLayout = GObject.registerClass({
const allocationScale = containerBox.get_width() / workareaWidth;
const workspaceBox = new Clutter.ActorBox();
const layoutBox = new Clutter.ActorBox();
const childBox = new Clutter.ActorBox();
const { ControlsState } = OverviewControls;
const inSessionTransition =
@ -625,44 +624,46 @@ var WorkspaceLayout = GObject.registerClass({
const nSlots = this._windowSlots.length;
for (let i = 0; i < nSlots; i++) {
const [x, y, width, height, child] = this._windowSlots[i];
let [x, y, width, height, child] = this._windowSlots[i];
if (!child.visible)
continue;
const windowInfo = this._windows.get(child);
let workspaceBoxX, workspaceBoxY;
let workspaceBoxWidth, workspaceBoxHeight;
if (windowInfo.metaWindow.showing_on_its_workspace()) {
workspaceBox.set_origin(
child.boundingBox.x - workareaX,
child.boundingBox.y - workareaY);
workspaceBox.set_size(
child.boundingBox.width,
child.boundingBox.height);
workspaceBoxX = (child.boundingBox.x - workareaX) * allocationScale;
workspaceBoxY = (child.boundingBox.y - workareaY) * allocationScale;
workspaceBoxWidth = child.boundingBox.width * allocationScale;
workspaceBoxHeight = child.boundingBox.height * allocationScale;
} else {
workspaceBox.set_origin(workareaX, workareaY);
workspaceBox.set_size(0, 0);
workspaceBoxX = workareaX * allocationScale;
workspaceBoxY = workareaY * allocationScale;
workspaceBoxWidth = 0;
workspaceBoxHeight = 0;
child.opacity = stateAdjustementValue * 255;
}
workspaceBox.scale(allocationScale);
// Don't allow the scaled floating size to drop below
// the target layout size.
// We only want to apply this when the scaled floating size is
// actually larger than the target layout size, that is while
// animating between the session and the window picker.
if (inSessionTransition) {
workspaceBox.set_size(
Math.max(workspaceBox.get_width(), width),
Math.max(workspaceBox.get_height(), height));
workspaceBoxWidth = Math.max(workspaceBoxWidth, width);
workspaceBoxHeight = Math.max(workspaceBoxHeight, height);
}
layoutBox.set_origin(x, y);
layoutBox.set_size(width, height);
x = Util.lerp(workspaceBoxX, x, stateAdjustementValue);
y = Util.lerp(workspaceBoxY, y, stateAdjustementValue);
width = Util.lerp(workspaceBoxWidth, width, stateAdjustementValue);
height = Util.lerp(workspaceBoxHeight, height, stateAdjustementValue);
const childBox = workspaceBox.interpolate(layoutBox,
stateAdjustementValue);
childBox.set_origin(x, y);
childBox.set_size(width, height);
if (windowInfo.currentTransition) {
windowInfo.currentTransition.get_interval().set_final(childBox);