windowPreview: Adjust WindowPreview stack when stackAbove overlay shown

When there are 3 or more windows in WorkspaceLayout, showing or hiding
window preview overlay in some certain orders could cause
inconsistencies in windows' vertical arrangement.

Let's take window A, B, C as an example. Initially, A is above B and B
is above C in workspace layout like this: A -> B -> C.

After opening activities, user could:

1. Move cursor to B preview, which would move B above all in layout:
   B -> A -> C
2. Move cursor from B to C preview. When C's showOverlay() is called
   before B's hideOverlay(), _restack() would move C above all and don't
   change B's arrangement:
   C -> B -> A
3. Finally, move cursor away from C's preview:
   B -> A -> C

In this case, when user closes Activities, they would see window
stacking wrong for a while.

This commit adds some extra logic in _restack, checking the
_stackAbove's _stackAbove when this._stackAbove._overlayShown is true.
Though it's still not guaranteed to be always consistent as there could
be several WindowPreview with _overlayShown as true if pointer moves
really fast, this helps avoid glitches in many cases.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4638.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3460>
This commit is contained in:
Keyu Tao 2024-08-31 21:51:34 +08:00 committed by Marge Bot
parent 5115236703
commit 33354c718f

View File

@ -621,12 +621,20 @@ export const WindowPreview = GObject.registerClass({
// with a new one on the target workspace.
const parent = this.get_parent();
if (parent !== null) {
if (this._overlayShown)
if (this._overlayShown) {
parent.set_child_above_sibling(this, null);
else if (this._stackAbove === null)
} else if (this._stackAbove === null) {
parent.set_child_below_sibling(this, null);
else if (!this._stackAbove._overlayShown)
} else if (!this._stackAbove._overlayShown) {
parent.set_child_above_sibling(this, this._stackAbove);
} else {
// This window shall still be above this._stackAbove._stackAbove
const above = this._stackAbove._stackAbove;
if (above === null)
parent.set_child_below_sibling(this, null);
else
parent.set_child_above_sibling(this, above);
}
}
}