[gnome-shell] windowManager: Fix fullscreen animations of wayland clients



commit 7bc1d57ad7f2093bce3e1856c949be3df21a7177
Author: Rui Matos <tiagomatos gmail com>
Date:   Mon Sep 26 17:58:25 2016 +0200

    windowManager: Fix fullscreen animations of wayland clients
    
    Wayland clients are in control of their window size so the existing
    mutter plugin API, which assumes size changes are synchronous, doesn't
    work for them since when our size-change handler runs the MetaWindow's
    size isn't final yet.
    
    To fix this, the mutter plugin API was extended with a size-changed
    vfunc that lets us know when the MetaWindow size has actually
    changed. This way we can make the window snapshot and get the old
    window size on the existing size-change handler and later, on the new
    size-changed handler, get the new size and start the animation.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=770345

 js/ui/windowManager.js |   89 +++++++++++++++++++++++++-----------------------
 1 files changed, 46 insertions(+), 43 deletions(-)
---
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index fc34aab..9864a15 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -706,6 +706,7 @@ const WindowManager = new Lang.Class({
         this._shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
         this._shellwm.connect('unminimize', Lang.bind(this, this._unminimizeWindow));
         this._shellwm.connect('size-change', Lang.bind(this, this._sizeChangeWindow));
+        this._shellwm.connect('size-changed', Lang.bind(this, this._sizeChangedWindow));
         this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
         this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
         this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
@@ -1255,37 +1256,16 @@ const WindowManager = new Lang.Class({
             return;
         }
 
-        if (whichChange == Meta.SizeChange.FULLSCREEN)
-            this._fullscreenWindow(shellwm, actor, oldFrameRect, oldBufferRect);
-        else if (whichChange == Meta.SizeChange.UNFULLSCREEN)
-            this._unfullscreenWindow(shellwm, actor, oldFrameRect, oldBufferRect);
+        if (whichChange == Meta.SizeChange.FULLSCREEN ||
+            whichChange == Meta.SizeChange.UNFULLSCREEN)
+            this._fullscreenAnimation(shellwm, actor, oldFrameRect, whichChange);
         else
             shellwm.completed_size_change(actor);
     },
 
-    _fullscreenWindow: function(shellwm, actor, oldFrameRect, oldBufferRect) {
-        let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
-        actor.translation_x = oldFrameRect.x - monitor.x;
-        actor.translation_y = oldFrameRect.y - monitor.y;
-        this._fullscreenAnimation(shellwm, actor, oldFrameRect);
-    },
-
-    _unfullscreenWindow: function(shellwm, actor, oldFrameRect, oldBufferRect) {
-        let targetRect = actor.meta_window.get_frame_rect();
-        let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
-        actor.translation_x = -(targetRect.x - monitor.x);
-        actor.translation_y = -(targetRect.y - monitor.y);
-        this._fullscreenAnimation(shellwm, actor, oldFrameRect);
-    },
-
-    _fullscreenAnimation: function(shellwm, actor, oldFrameRect) {
-        this._resizing.push(actor);
-
+    _fullscreenAnimation: function(shellwm, actor, oldFrameRect, change) {
         // Position a clone of the window on top of the old position,
         // while actor updates are frozen.
-        // Note that the MetaWindow has up to date sizing information for
-        // the new geometry already.
-        let targetRect = actor.meta_window.get_frame_rect();
         let actorContent = Shell.util_get_content_for_window_actor(actor, oldFrameRect);
         let actorClone = new St.Widget({ content: actorContent });
         actorClone.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
@@ -1293,10 +1273,26 @@ const WindowManager = new Lang.Class({
         actorClone.set_size(oldFrameRect.width, oldFrameRect.height);
         Main.uiGroup.add_actor(actorClone);
 
-        actor.__fullscreenClone = actorClone;
+        let rect = change == Meta.SizeChange.FULLSCREEN ? oldFrameRect : null;
+
+        if (this._clearFullscreenInfo(actor))
+            this._shellwm.completed_size_change(actor);
+
+        actor.__fullscreenInfo = { clone: actorClone,
+                                   oldRect: rect };
+    },
+
+    _sizeChangedWindow: function(shellwm, actor) {
+        if (!actor.__fullscreenInfo)
+            return;
+
+        let actorClone = actor.__fullscreenInfo.clone;
+        let targetRect = actor.meta_window.get_frame_rect();
 
-        let scaleX = targetRect.width / oldFrameRect.width;
-        let scaleY = targetRect.height / oldFrameRect.height;
+        let scaleX = targetRect.width / actorClone.width;
+        let scaleY = targetRect.height / actorClone.height;
+
+        this._resizing.push(actor);
 
         // Now scale and fade out the clone
         Tweener.addTween(actorClone,
@@ -1309,9 +1305,17 @@ const WindowManager = new Lang.Class({
                            transition: 'easeOutQuad'
                          });
 
+        let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
+        let oldRect = actor.__fullscreenInfo.oldRect;
+        if (oldRect) {
+            actor.translation_x = oldRect.x - monitor.x;
+            actor.translation_y = oldRect.y - monitor.y;
+        } else {
+            actor.translation_x = -(targetRect.x - monitor.x);
+            actor.translation_y = -(targetRect.y - monitor.y);
+        }
+
         // Now set scale the actor to size it as the clone.
-        // Note that the caller of this function already set a translation
-        // on the actor.
         actor.scale_x = 1 / scaleX;
         actor.scale_y = 1 / scaleY;
 
@@ -1337,6 +1341,15 @@ const WindowManager = new Lang.Class({
         shellwm.completed_size_change(actor);
     },
 
+    _clearFullscreenInfo: function(actor) {
+        if (actor.__fullscreenInfo) {
+            actor.__fullscreenInfo.clone.destroy();
+            delete actor.__fullscreenInfo;
+            return true;
+        }
+        return false;
+    },
+
     _sizeChangeWindowDone: function(shellwm, actor) {
         if (this._removeEffect(this._resizing, actor)) {
             Tweener.removeTweens(actor);
@@ -1344,23 +1357,13 @@ const WindowManager = new Lang.Class({
             actor.scale_y = 1.0;
             actor.translation_x = 0;
             actor.translation_y = 0;
-
-            let actorClone = actor.__fullscreenClone;
-            if (actorClone) {
-                actorClone.destroy();
-                delete actor.__fullscreenClone;
-            }
+            this._clearFullscreenInfo(actor);
         }
     },
 
     _sizeChangeWindowOverwritten: function(shellwm, actor) {
-        if (this._removeEffect(this._resizing, actor)) {
-            let actorClone = actor.__fullscreenClone;
-            if (actorClone) {
-                actorClone.destroy();
-                delete actor.__fullscreenClone;
-            }
-        }
+        if (this._removeEffect(this._resizing, actor))
+            this._clearFullscreenInfo(actor);
     },
 
     _hasAttachedDialogs: function(window, ignoreWindow) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]