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