From 33354c718f54c816fc92a736b8c0cb23ad3cd931 Mon Sep 17 00:00:00 2001 From: Keyu Tao Date: Sat, 31 Aug 2024 21:51:34 +0800 Subject: [PATCH] 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: --- js/ui/windowPreview.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/js/ui/windowPreview.js b/js/ui/windowPreview.js index cf3fbdaa6..95a2276ca 100644 --- a/js/ui/windowPreview.js +++ b/js/ui/windowPreview.js @@ -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); + } } }