[gnome-shell/wip/exalm/gestures: 31/38] windowManager: Use SwipeTracker



commit 61a89c992521d4647172d7350d4fb73f3c8e5fa1
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date:   Sun Jun 30 17:15:44 2019 +0500

    windowManager: Use SwipeTracker
    
    Replace existing four-finger gestures with SwipeTracker.
    
    Since TouchpadWorkspaceSwitchAction and WorkspaceSwitchAction are now
    unused, remove them.
    
    Change programmatic workspace transition to use easeOutCubic interpolator
    to match the gesture.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/756
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605

 js/ui/windowManager.js | 352 +++++++++++++++++++++----------------------------
 1 file changed, 149 insertions(+), 203 deletions(-)
---
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index c911fc26a..6e1195ac9 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -16,6 +16,7 @@ const WindowMenu = imports.ui.windowMenu;
 const PadOsd = imports.ui.padOsd;
 const EdgeDragAction = imports.ui.edgeDragAction;
 const CloseDialog = imports.ui.closeDialog;
+const SwipeTracker = imports.ui.swipeTracker;
 const SwitchMonitor = imports.ui.switchMonitor;
 
 const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -455,142 +456,6 @@ var TilePreview = class {
     }
 };
 
-var TouchpadWorkspaceSwitchAction = class {
-    constructor(actor, allowedModes) {
-        this._allowedModes = allowedModes;
-        this._dx = 0;
-        this._dy = 0;
-        this._enabled = true;
-        actor.connect('captured-event', this._handleEvent.bind(this));
-        this._touchpadSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.peripherals.touchpad' });
-    }
-
-    get enabled() {
-        return this._enabled;
-    }
-
-    set enabled(enabled) {
-        if (this._enabled == enabled)
-            return;
-
-        this._enabled = enabled;
-        if (!enabled)
-            this.emit('cancel');
-    }
-
-    _checkActivated() {
-        let dir;
-
-        if (this._dy < -MOTION_THRESHOLD)
-            dir = Meta.MotionDirection.DOWN;
-        else if (this._dy > MOTION_THRESHOLD)
-            dir = Meta.MotionDirection.UP;
-        else if (this._dx < -MOTION_THRESHOLD)
-            dir = Meta.MotionDirection.RIGHT;
-        else if (this._dx > MOTION_THRESHOLD)
-            dir = Meta.MotionDirection.LEFT;
-        else
-            return false;
-
-        this.emit('activated', dir);
-        return true;
-    }
-
-    _handleEvent(actor, event) {
-        if (event.type() != Clutter.EventType.TOUCHPAD_SWIPE)
-            return Clutter.EVENT_PROPAGATE;
-
-        if (event.get_touchpad_gesture_finger_count() != 4)
-            return Clutter.EVENT_PROPAGATE;
-
-        if ((this._allowedModes & Main.actionMode) == 0)
-            return Clutter.EVENT_PROPAGATE;
-
-        if (!this._enabled)
-            return Clutter.EVENT_PROPAGATE;
-
-        if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.UPDATE) {
-            let [dx, dy] = event.get_gesture_motion_delta();
-
-            // Scale deltas up a bit to make it feel snappier
-            this._dx += dx * 2;
-            if (!(this._touchpadSettings.get_boolean('natural-scroll')))
-                this._dy -= dy * 2;
-            else
-                this._dy += dy * 2;
-
-            this.emit('motion', this._dx, this._dy);
-        } else {
-            if ((event.get_gesture_phase() == Clutter.TouchpadGesturePhase.END && ! this._checkActivated()) 
||
-                event.get_gesture_phase() == Clutter.TouchpadGesturePhase.CANCEL)
-                this.emit('cancel');
-
-            this._dx = 0;
-            this._dy = 0;
-        }
-
-        return Clutter.EVENT_STOP;
-    }
-};
-Signals.addSignalMethods(TouchpadWorkspaceSwitchAction.prototype);
-
-var WorkspaceSwitchAction = GObject.registerClass({
-    Signals: { 'activated': { param_types: [Meta.MotionDirection.$gtype] },
-               'motion':    { param_types: [GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] },
-               'cancel':    { param_types: [] } },
-}, class WorkspaceSwitchAction extends Clutter.SwipeAction {
-    _init(allowedModes) {
-        super._init();
-        this.set_n_touch_points(4);
-        this._swept = false;
-        this._allowedModes = allowedModes;
-    }
-
-    vfunc_gesture_begin(actor, point) {
-        this._swept = false;
-
-        if (!super.vfunc_gesture_begin(actor, point))
-            return false;
-
-        return (this._allowedModes & Main.actionMode);
-    }
-
-    vfunc_gesture_progress(actor, point) {
-        let [x, y] = this.get_motion_coords(0);
-        let [xPress, yPress] = this.get_press_coords(0);
-        this.emit('motion', x - xPress, y - yPress);
-    }
-
-    vfunc_gesture_cancel(actor) {
-        if (!this._swept)
-            this.emit('cancel');
-    }
-
-    vfunc_swipe(actor, direction) {
-        let [x, y] = this.get_motion_coords(0);
-        let [xPress, yPress] = this.get_press_coords(0);
-        if (Math.abs(x - xPress) < MOTION_THRESHOLD &&
-            Math.abs(y - yPress) < MOTION_THRESHOLD) {
-            this.emit('cancel');
-            return;
-        }
-
-        let dir;
-
-        if (direction & Clutter.SwipeDirection.UP)
-            dir = Meta.MotionDirection.DOWN;
-        else if (direction & Clutter.SwipeDirection.DOWN)
-            dir = Meta.MotionDirection.UP;
-        else if (direction & Clutter.SwipeDirection.LEFT)
-            dir = Meta.MotionDirection.RIGHT;
-        else if (direction & Clutter.SwipeDirection.RIGHT)
-            dir = Meta.MotionDirection.LEFT;
-
-        this._swept = true;
-        this.emit('activated', dir);
-    }
-});
-
 var AppSwitchAction = GObject.registerClass(
 class AppSwitchAction extends Clutter.GestureAction {
     _init() {
@@ -1045,10 +910,17 @@ var WindowManager = class {
         Main.overview.connect('showing', () => {
             for (let i = 0; i < this._dimmedWindows.length; i++)
                 this._undimWindow(this._dimmedWindows[i]);
+
+            if (this._switchData) {
+                if (this._switchData.gestureActivated)
+                    this._switchWorkspaceStop();
+                this._swipeTracker.enabled = false;
+            }
         });
         Main.overview.connect('hiding', () => {
             for (let i = 0; i < this._dimmedWindows.length; i++)
                 this._dimWindow(this._dimmedWindows[i]);
+            this._swipeTracker.enabled = true;
         });
 
         this._windowMenuManager = new WindowMenu.WindowMenuManager();
@@ -1060,17 +932,12 @@ var WindowManager = class {
                                                            false, -1, 1);
 
         let allowedModes = Shell.ActionMode.NORMAL;
-        let workspaceSwitchAction = new WorkspaceSwitchAction(allowedModes);
-        workspaceSwitchAction.connect('motion', this._switchWorkspaceMotion.bind(this));
-        workspaceSwitchAction.connect('activated', this._actionSwitchWorkspace.bind(this));
-        workspaceSwitchAction.connect('cancel', this._switchWorkspaceCancel.bind(this));
-        global.stage.add_action(workspaceSwitchAction);
-
-        // This is not a normal Clutter.GestureAction, doesn't need add_action()
-        let touchpadSwitchAction = new TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
-        touchpadSwitchAction.connect('motion', this._switchWorkspaceMotion.bind(this));
-        touchpadSwitchAction.connect('activated', this._actionSwitchWorkspace.bind(this));
-        touchpadSwitchAction.connect('cancel', this._switchWorkspaceCancel.bind(this));
+        let swipeTracker = new SwipeTracker.SwipeTracker(global.stage, allowedModes, false, false);
+        swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
+        swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
+        swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
+        swipeTracker.connect('cancel', this._switchWorkspaceCancel.bind(this));
+        this._swipeTracker = swipeTracker;
 
         let appSwitchAction = new AppSwitchAction();
         global.stage.add_action(appSwitchAction);
@@ -1111,54 +978,6 @@ var WindowManager = class {
         return this._currentPadOsd.actor;
     }
 
-    _switchWorkspaceMotion(action, xRel, yRel) {
-        let workspaceManager = global.workspace_manager;
-        let activeWorkspace = workspaceManager.get_active_workspace();
-
-        if (!this._switchData)
-            this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
-
-        if (yRel < 0 && !this._switchData.surroundings[Meta.MotionDirection.DOWN])
-            yRel = 0;
-        if (yRel > 0 && !this._switchData.surroundings[Meta.MotionDirection.UP])
-            yRel = 0;
-        if (xRel < 0 && !this._switchData.surroundings[Meta.MotionDirection.RIGHT])
-            xRel = 0;
-        if (xRel > 0 && !this._switchData.surroundings[Meta.MotionDirection.LEFT])
-            xRel = 0;
-
-        this._switchData.container.set_position(xRel, yRel);
-    }
-
-    _switchWorkspaceCancel() {
-        if (!this._switchData || this._switchData.inProgress)
-            return;
-        let switchData = this._switchData;
-        this._switchData = null;
-        Tweener.addTween(switchData.container,
-                         { x: 0,
-                           y: 0,
-                           time: WINDOW_ANIMATION_TIME,
-                           transition: 'easeOutQuad',
-                           onComplete: this._finishWorkspaceSwitch,
-                           onCompleteScope: this,
-                           onCompleteParams: [switchData],
-                         });
-    }
-
-    _actionSwitchWorkspace(action, direction) {
-        let workspaceManager = global.workspace_manager;
-        let activeWorkspace = workspaceManager.get_active_workspace();
-        let newWs = activeWorkspace.get_neighbor(direction);
-
-        if (newWs == activeWorkspace) {
-            this._switchWorkspaceCancel();
-        } else {
-            this._switchData.gestureActivated = true;
-            this.actionMoveWorkspace(newWs);
-        }
-    }
-
     insertWorkspace(pos) {
         let workspaceManager = global.workspace_manager;
 
@@ -1847,6 +1666,7 @@ var WindowManager = class {
         switchData.surroundings = {};
         switchData.gestureActivated = false;
         switchData.inProgress = false;
+        switchData.progress = 0;
 
         switchData.container = new Clutter.Actor();
         switchData.container.add_actor(switchData.curGroup);
@@ -1870,13 +1690,15 @@ var WindowManager = class {
                 continue;
             }
 
+            let [x, y] = this._getPositionForDirection(dir, curWs, ws);
             let info = { index: ws.index(),
-                         actor: new Clutter.Actor() };
+                         actor: new Clutter.Actor(),
+                         xDest: x,
+                         yDest: y };
             switchData.surroundings[dir] = info;
             switchData.container.add_actor(info.actor);
             info.actor.raise_top();
 
-            let [x, y] = this._getPositionForDirection(dir, curWs, ws);
             info.actor.set_position(x, y);
         }
 
@@ -1942,6 +1764,7 @@ var WindowManager = class {
                 global.workspace_manager.get_active_workspace())
                 w.window.hide();
         }
+        Tweener.removeTweens(switchData);
         Tweener.removeTweens(switchData.container);
         switchData.container.destroy();
         switchData.movingWindowBin.destroy();
@@ -1955,11 +1778,7 @@ var WindowManager = class {
             return;
         }
 
-        // If we come from a gesture, switchData will already be set,
-        // and we don't want to overwrite it.
-        if (!this._switchData)
-            this._prepareWorkspaceSwitch(from, to, direction);
-
+        this._prepareWorkspaceSwitch(from, to, direction);
         this._switchData.inProgress = true;
 
         let workspaceManager = global.workspace_manager;
@@ -1975,11 +1794,16 @@ var WindowManager = class {
         xDest = -xDest;
         yDest = -yDest;
 
+        Tweener.addTween(this._switchData,
+                         { progress: direction == Meta.MotionDirection.DOWN ? 1 : -1,
+                           time: WINDOW_ANIMATION_TIME,
+                           transition: 'easeOutCubic'
+                         });
         Tweener.addTween(this._switchData.container,
                          { x: xDest,
                            y: yDest,
                            time: WINDOW_ANIMATION_TIME,
-                           transition: 'easeOutQuad',
+                           transition: 'easeOutCubic',
                            onComplete: this._switchWorkspaceDone,
                            onCompleteScope: this,
                            onCompleteParams: [shellwm]
@@ -1991,6 +1815,128 @@ var WindowManager = class {
         shellwm.completed_switch_workspace();
     }
 
+    _switchWorkspaceBegin(tracker, monitor) {
+        if (Meta.prefs_get_workspaces_only_on_primary() && monitor != Main.layoutManager.primaryIndex)
+            return;
+
+        let workspaceManager = global.workspace_manager;
+        let activeWorkspace = workspaceManager.get_active_workspace();
+
+        if (this._switchData && this._switchData.gestureActivated) {
+            Tweener.removeTweens(this._switchData);
+            Tweener.removeTweens(this._switchData.container);
+
+            tracker.continueSwipe(this._switchData.progress);
+            return;
+        }
+
+        this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
+
+        // TODO: horizontal
+
+        let baseDistance = global.screen_height - Main.panel.height;
+
+        let direction = Meta.MotionDirection.DOWN;
+        let backInfo = this._switchData.surroundings[direction];
+        let backExtent = backInfo ? (backInfo.yDest - baseDistance) : 0;
+
+        direction = Meta.MotionDirection.UP;
+        let forwardInfo = this._switchData.surroundings[direction];
+        let forwardExtent = forwardInfo ? (-forwardInfo.yDest - baseDistance) : 0;
+
+        tracker.confirmSwipe((backInfo != null), (forwardInfo != null), baseDistance, backExtent, 
forwardExtent);
+    }
+
+    _switchWorkspaceUpdate(tracker, progress) {
+        if (!this._switchData)
+            return;
+
+        this._switchData.progress = progress;
+
+        let direction = (progress > 0) ? Meta.MotionDirection.DOWN : Meta.MotionDirection.UP;
+        let info = this._switchData.surroundings[direction];
+        let distance = info ? Math.abs(info.yDest) : 0;
+
+        this._switchData.container.set_position(0, Math.round(-progress * distance));
+    }
+
+    _switchWorkspaceEnd(tracker, duration, isBack) {
+        if (!this._switchData)
+            return;
+
+        let direction = isBack ? Meta.MotionDirection.DOWN : Meta.MotionDirection.UP;
+
+        let workspaceManager = global.workspace_manager;
+        let activeWorkspace = workspaceManager.get_active_workspace();
+        let newWs = activeWorkspace.get_neighbor(direction);
+
+        if (newWs == activeWorkspace) {
+            // FIXME: throw an error
+            log('this should never happen')
+            return;
+        }
+
+        let xDest = -this._switchData.surroundings[direction].xDest;
+        let yDest = -this._switchData.surroundings[direction].yDest;
+
+        let switchData = this._switchData;
+        this._switchData.gestureActivated = true;
+
+        Tweener.addTween(switchData,
+                         { progress: direction == Meta.MotionDirection.DOWN ? 1 : -1,
+                           time: duration,
+                           transition: 'easeOutCubic'
+                         });
+        Tweener.addTween(switchData.container,
+                         { x: xDest,
+                           y: yDest,
+                           time: duration,
+                           transition: 'easeOutCubic',
+                           onComplete: () => {
+                               // We've already animated the transition, don't animate it again
+                               this._blockAnimations = true;
+                               this.actionMoveWorkspace(newWs);
+                               this._blockAnimations = false;
+
+                               this._finishWorkspaceSwitch(switchData);
+                           }
+                         });
+    }
+
+    _switchWorkspaceCancel(tracker, duration) {
+        if (!this._switchData)
+            return;
+
+        if (duration == 0) {
+            this._switchWorkspaceStop();
+            return;
+        }
+
+        let switchData = this._switchData;
+
+        Tweener.addTween(switchData,
+                         { progress: 0,
+                           time: duration,
+                           transition: 'easeOutCubic'
+                         });
+        Tweener.addTween(switchData.container,
+                         { x: 0,
+                           y: 0,
+                           time: duration,
+                           transition: 'easeOutCubic',
+                           onComplete: this._finishWorkspaceSwitch,
+                           onCompleteScope: this,
+                           onCompleteParams: [switchData],
+                         });
+    }
+
+    _switchWorkspaceStop() {
+        this._switchData.progress = 0;
+        this._switchData.container.x = 0;
+        this._switchData.container.y = 0;
+        this._finishWorkspaceSwitch(this._switchData);
+    }
+
     _showTilePreview(shellwm, window, tileRect, monitorIndex) {
         if (!this._tilePreview)
             this._tilePreview = new TilePreview();


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