From 0257a23c31244774a7dddec356cd98b85cb2a2a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 17 Dec 2014 22:57:44 +0100
Subject: [PATCH] windowManager: Update stacking during workspace switches

When animating workspace switches, windows on the old and new workspaces
are temporarily reparented. If windows are restacked, those windows will
thus be ignored by mutter until meta_switch_workspace_completed() resyncs
the stacking at the end of the animation.
As a result, activating a window on another workspace that is not on top
of the stack is very noticeably a two-step operation of switching workspace
and raising the window. There is a technical reason for that order[0], but
we can avoid the visible disruption by manually syncing the stack during
the switch operation.

[0] https://git.gnome.org/browse/mutter/tree/src/core/workspace.c#n590

https://bugzilla.gnome.org/show_bug.cgi?id=741680
---
 js/ui/windowManager.js | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index d88c02242..b8af0e0b6 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -618,6 +618,7 @@ const WindowManager = new Lang.Class({
         this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
         this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
         this._shellwm.connect('confirm-display-change', Lang.bind(this, this._confirmDisplayChange));
+        global.screen.connect('restacked', Lang.bind(this, this._syncStacking));
 
         this._workspaceSwitcherPopup = null;
         this._tilePreview = null;
@@ -1248,6 +1249,24 @@ const WindowManager = new Lang.Class({
         return !(this._allowedKeybindings[binding.get_name()] & Main.actionMode);
     },
 
+    _syncStacking: function() {
+        if (this._switchData == null)
+            return;
+
+        // Update stacking of windows in inGroup (aka the workspace we are
+        // switching to). Windows in outGroup are about to be hidden anyway,
+        // so we just ignore them here.
+        let windows = global.get_window_actors();
+        let sibling = null;
+        for (let i = 0; i < windows.length; i++) {
+            if (windows[i].get_parent() != this._switchData.inGroup)
+                continue;
+
+            this._switchData.inGroup.set_child_above_sibling(windows[i], sibling);
+            sibling = windows[i];
+        }
+    },
+
     _switchWorkspace : function(shellwm, from, to, direction) {
         if (!Main.sessionMode.hasWorkspaces || !this._shouldAnimate()) {
             shellwm.completed_switch_workspace();