Animated transition from overview shrinks windows due to workspace layout being frozen
WorkspaceLayout::_layoutFrozen
is currently set to true during transitions from the overview when pressing super. All other overview transitions do not set this: to overview by pressing super, to overview using gestures and from overview using gestures.
This means for these transitions computeWindowSlots()
is getting called for every frame, while in the super from overview case WorkspaceLayout::_windowSlots
remains at its initial value from when the overview was shown. Now because these initial slots are for the shrunk down size of the workspace shown in the overview, they are smaller than they should be for the current workspace size for every frame except the first one during the transition. These shrunken slots are then interpolated with the final position based on the adjustment, so that this primarily affects the beginning of the animation. This is most noticeable when closing the overview with just a single maximized window on the workspace. During the transition it looks like the window is first shrinking (the slots becoming smaller compared to the growing workspace size) and then expanding again (the final size/position getting more weight as the animation progresses) in the bottom right.
This could be solved by not marking the layout as frozen in Workspace::prepareToLeaveOverview()
, but I suspect that this might lead to issues when launching an app from the overview and triggering the animation that way. But I think there is a workaround that can help mitigate most of this issue:
Whenever we change WorkspaceLayout._windowSlots
in allocate()
store the box this was calculated for and then when allocating scale the slot sizes/positions respective to the current box size:
- if (layoutChanged || containerAllocationChanged)
- this._windowSlots = this._getWindowSlots(box.copy());
+ if (layoutChanged || containerAllocationChanged) {
+ this._windowSlotsBox = box.copy();
+ this._windowSlots = this._getWindowSlots(this._windowSlotsBox);
+ }
And then:
const slotsScale = box.get_width() / this._windowSlotsBox.get_width();
...
x *= slotsScale;
...
This is not 100% correct for everything but the single window case due to it scaling the spacing between the windows as well, but the inaccuracies are not as bad as what we currently have and have a much lower impact the more windows there are (i.e. the case when there is a lot of spacing).
Here is what the issue looks like before and after the fix outlined above for 1 maximized window:
before: 1-maximized-win-before
after: 1-maximized-win-after
And with 4 maximized windows:
before: 4-maximized-wins-before
after: 4-maximized-wins-after
A proper fix for this would probably come automatically once we have the new animations API and this code starts making use of it. Before that a proper fix does not seem feasible, that why I'm suggesting this workaround.