[gnome-shell/wip/exalm/gestures: 21/30] workspacesView: Use SwipeTracker



commit 8ef846183f8bc6c5e034c5df125326a3695f21f2
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date:   Mon Jul 8 13:47:04 2019 +0500

    workspacesView: Use SwipeTracker
    
    Replace existing panning, touchpad scrolling and four-finger gesture by
    SwipeTracker.
    
    Change programmatic workspace animation to use easeOutCubic interpolator
    to match the gesture.
    
    Also change the dragging distance to always match the current monitor.
    
    Fixes touchpad parts of https://gitlab.gnome.org/GNOME/gnome-shell/issues/1338
    
    https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/605

 js/ui/workspacesView.js | 196 ++++++++++++++++++++++--------------------------
 1 file changed, 90 insertions(+), 106 deletions(-)
---
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 770c3c4ba..e58240271 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -4,8 +4,8 @@ const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
 const Signals = imports.signals;
 
 const Main = imports.ui.main;
+const SwipeTracker = imports.ui.swipeTracker;
 const Tweener = imports.ui.tweener;
-const WindowManager = imports.ui.windowManager;
 const Workspace = imports.ui.workspace;
 
 var WORKSPACE_SWITCH_TIME = 0.25;
@@ -82,7 +82,6 @@ var WorkspacesView = class extends WorkspacesViewBase {
         super(monitorIndex);
 
         this._animating = false; // tweening
-        this._scrolling = false; // swipe-scrolling
         this._gestureActive = false; // touch(pad) gestures
 
         this._workspaces = [];
@@ -158,7 +157,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
         let workspaceManager = global.workspace_manager;
         let active = workspaceManager.get_active_workspace_index();
 
-        this.updateWorkspaceActors(true);
+        this.updateWorkspaceActors(!this._gestureActive);
     }
 
     // Update workspace actors parameters
@@ -185,7 +184,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
             if (showAnimation) {
                 let tweenParams = Object.assign(params, {
                     time: WORKSPACE_SWITCH_TIME,
-                    transition: 'easeOutQuad'
+                    transition: 'easeOutCubic'
                 });
                 // we have to call _updateVisibility() once before the
                 // animation and once afterwards - it does not really
@@ -212,7 +211,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
 
         for (let w = 0; w < this._workspaces.length; w++) {
             let workspace = this._workspaces[w];
-            if (this._animating || this._scrolling || this._gestureActive) {
+            if (this._animating || this._gestureActive) {
                 workspace.actor.show();
             } else {
                 if (this._inDrag)
@@ -262,17 +261,6 @@ var WorkspacesView = class extends WorkspacesViewBase {
         workspaceManager.disconnect(this._reorderWorkspacesId);
     }
 
-    startSwipeScroll() {
-        this._scrolling = true;
-    }
-
-    endSwipeScroll() {
-        this._scrolling = false;
-
-        // Make sure title captions etc are shown as necessary
-        this._updateVisibility();
-    }
-
     startTouchGesture() {
         this._gestureActive = true;
     }
@@ -387,12 +375,6 @@ var ExtraWorkspaceView = class extends WorkspacesViewBase {
     updateWorkspaceActors(showAnimation) {
     }
 
-    startSwipeScroll() {
-    }
-
-    endSwipeScroll() {
-    }
-
     startTouchGesture() {
     }
 
@@ -440,50 +422,22 @@ var WorkspacesDisplay = class {
         });
         Main.overview.addAction(clickAction);
         this.actor.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
-
-        let panAction = new Clutter.PanAction({ trigger_edge: Clutter.TriggerEdge.AFTER });
-        panAction.connect('pan', this._onPan.bind(this));
-        panAction.connect('gesture-begin', () => {
-            if (this._workspacesOnlyOnPrimary) {
-                let event = Clutter.get_current_event();
-                if (this._getMonitorIndexForEvent(event) != this._primaryIndex)
-                    return false;
-            }
-
-            this._startSwipeScroll();
-            return true;
-        });
-        panAction.connect('gesture-cancel', () => {
-            clickAction.release();
-            this._endSwipeScroll();
-        });
-        panAction.connect('gesture-end', () => {
-            clickAction.release();
-            this._endSwipeScroll();
-        });
-        Main.overview.addAction(panAction);
-        this.actor.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
+        this._clickAction = clickAction;
 
         let allowedModes = Shell.ActionMode.OVERVIEW;
-        let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes);
-        switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
-        switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
-        switchGesture.connect('cancel', this._endTouchGesture.bind(this));
-        Main.overview.addAction(switchGesture);
-        this.actor.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
-
-        switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
-        switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
-        switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
-        switchGesture.connect('cancel', this._endTouchGesture.bind(this));
+        let swipeTracker = new SwipeTracker.SwipeTracker(Main.layoutManager.overviewGroup, allowedModes);
+        swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
+        swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
+        swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
         this.actor.connect('notify::mapped', () => {
-            switchGesture.enabled = this.actor.mapped;
+            swipeTracker.enabled = this.actor.mapped;
         });
 
+        swipeTracker.enabled = this.actor.mapped;
+
         this._primaryIndex = Main.layoutManager.primaryIndex;
 
         this._workspacesViews = [];
-        switchGesture.enabled = this.actor.mapped;
 
         this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA });
         this._settings.connect('changed::workspaces-only-on-primary',
@@ -497,13 +451,12 @@ var WorkspacesDisplay = class {
 
         this._fullGeometry = null;
 
-        this._scrolling = false; // swipe-scrolling
         this._gestureActive = false; // touch(pad) gestures
         this._animatingScroll = false; // programmatically updating the adjustment
     }
 
     _activeWorkspaceChanged(wm, from, to, direction) {
-        if (this._scrolling)
+        if (this._gestureActive)
             return;
 
         this._scrollToActive();
@@ -520,7 +473,7 @@ var WorkspacesDisplay = class {
     }
 
     _updateScrollAdjustment(index) {
-        if (this._scrolling || this._gestureActive)
+        if (this._gestureActive)
             return;
 
         this._animatingScroll = true;
@@ -528,75 +481,105 @@ var WorkspacesDisplay = class {
         Tweener.addTween(this._scrollAdjustment, {
             value: index,
             time: WORKSPACE_SWITCH_TIME,
-            transition: 'easeOutQuad',
+            transition: 'easeOutCubic',
             onComplete: () => {
                 this._animatingScroll = false;
             }
         });
     }
 
-    _onPan(action) {
-        let [dist, dx, dy] = action.get_motion_delta(0);
-        let adjustment = this._scrollAdjustment;
+    _directionForProgress(progress) {
         if (global.workspace_manager.layout_rows == -1)
-            adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
+            return (progress > 0) ? Meta.MotionDirection.DOWN : Meta.MotionDirection.UP;
         else if (this.actor.text_direction == Clutter.TextDirection.RTL)
-            adjustment.value += (dx / this.actor.width) * adjustment.page_size;
+            return (progress > 0) ? Meta.MotionDirection.LEFT : Meta.MotionDirection.RIGHT;
         else
-            adjustment.value -= (dx / this.actor.width) * adjustment.page_size;
-        return false;
+            return (progress > 0) ? Meta.MotionDirection.RIGHT : Meta.MotionDirection.LEFT;
     }
 
-    _startSwipeScroll() {
-        for (let i = 0; i < this._workspacesViews.length; i++)
-            this._workspacesViews[i].startSwipeScroll();
-        this._scrolling = true;
-    }
+    _switchWorkspaceBegin(tracker, monitor) {
+        if (this._workspacesOnlyOnPrimary && monitor != this._primaryIndex)
+            return;
 
-    _endSwipeScroll() {
-        for (let i = 0; i < this._workspacesViews.length; i++)
-            this._workspacesViews[i].endSwipeScroll();
-        this._scrolling = false;
-        this._scrollToActive();
-    }
+        if (this._gestureActive) {
+            let workspaceManager = global.workspace_manager;
+            let active = workspaceManager.get_active_workspace_index();
+            let adjustment = this._scrollAdjustment;
+
+            Tweener.removeTweens(adjustment);
+
+            let progress = adjustment.value / adjustment.page_size - active;
+            tracker.continueSwipe(progress);
+            return;
+        }
+
+        let horiz = (global.workspace_manager.layout_rows != -1);
+        tracker.orientation = horiz ? Clutter.Orientation.HORIZONTAL : Clutter.Orientation.VERTICAL;
 
-    _startTouchGesture() {
         for (let i = 0; i < this._workspacesViews.length; i++)
             this._workspacesViews[i].startTouchGesture();
-        this._gestureActive = true;
-    }
 
-    _endTouchGesture() {
-        for (let i = 0; i < this._workspacesViews.length; i++)
-            this._workspacesViews[i].endTouchGesture();
-        this._gestureActive = false;
-        this._scrollToActive();
-    }
+        let workspaceManager = global.workspace_manager;
+        let activeWs = workspaceManager.get_active_workspace();
+
+        let backDir = this._directionForProgress(1);
+        let forwardDir = this._directionForProgress(-1);
 
-    _onSwitchWorkspaceMotion(action, xRel, yRel) {
-        // We don't have a way to hook into start of touchpad actions,
-        // luckily this is safe to call repeatedly.
-        this._startTouchGesture();
+        let canSwipeBack = (activeWs.get_neighbor(backDir) != activeWs);
+        let canSwipeForward = (activeWs.get_neighbor(forwardDir) != activeWs);
 
+        let monitors = Main.layoutManager.monitors;
+        let geometry = (monitor == this._primaryIndex) ? this._fullGeometry : monitors[monitor];
+        let distance = (global.workspace_manager.layout_rows == -1) ? geometry.height : geometry.width;
+
+        tracker.confirmSwipe(canSwipeBack, canSwipeForward, distance, 0, 0);
+
+        this._gestureActive = true;
+    }
+
+    _switchWorkspaceUpdate(tracker, progress) {
         let workspaceManager = global.workspace_manager;
         let active = workspaceManager.get_active_workspace_index();
         let adjustment = this._scrollAdjustment;
-        if (workspaceManager.layout_rows == -1)
-            adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size;
-        else if (this.actor.text_direction == Clutter.TextDirection.RTL)
-            adjustment.value = (active + xRel / this.actor.width) * adjustment.page_size;
-        else
-            adjustment.value = (active - xRel / this.actor.width) * adjustment.page_size;
+        adjustment.value = (active + progress) * adjustment.page_size;
     }
 
-    _onSwitchWorkspaceActivated(action, direction) {
+    _switchWorkspaceEnd(tracker, duration, endProgress) {
+        this._clickAction.release();
+
         let workspaceManager = global.workspace_manager;
         let activeWorkspace = workspaceManager.get_active_workspace();
-        let newWs = activeWorkspace.get_neighbor(direction);
-        if (newWs != activeWorkspace)
-            newWs.activate(global.get_current_time());
+        let newWs = activeWorkspace;
+        if (endProgress != 0) {
+            let direction = this._directionForProgress(endProgress);
+            newWs = activeWorkspace.get_neighbor(direction);
+        }
+
+        if (duration == 0) {
+            if (newWs != activeWorkspace)
+                newWs.activate(global.get_current_time());
+
+            this._endTouchGesture();
+            return;
+        }
+
+        let active = workspaceManager.get_active_workspace_index();
+        Tweener.addTween(this._scrollAdjustment,
+                         { value: active + endProgress,
+                           time: duration,
+                           transition: 'easeOutCubic',
+                           onComplete: () => {
+                               if (newWs != activeWorkspace)
+                                   newWs.activate(global.get_current_time());
+                               this._endTouchGesture();
+                           }
+                         });
+    }
 
-        this._endTouchGesture();
+    _endTouchGesture() {
+        for (let i = 0; i < this._workspacesViews.length; i++)
+            this._workspacesViews[i].endTouchGesture();
+        this._gestureActive = false;
     }
 
     navigateFocus(from, direction) {
@@ -676,8 +659,6 @@ var WorkspacesDisplay = class {
             else
                 view = new WorkspacesView(i);
 
-            view.actor.connect('scroll-event', this._onScrollEvent.bind(this));
-
             // HACK: Avoid spurious allocation changes while updating views
             view.actor.hide();
 
@@ -781,6 +762,9 @@ var WorkspacesDisplay = class {
     }
 
     _onScrollEvent(actor, event) {
+        if (event.get_scroll_source() == Clutter.ScrollSource.FINGER || 
event.get_source_device().get_device_type() == Clutter.InputDeviceType.TOUCHPAD_DEVICE) // TODO: remove this 
and handle it in SwipeTracker too
+            return Clutter.EVENT_PROPAGATE;
+
         if (!this.actor.mapped)
             return Clutter.EVENT_PROPAGATE;
 


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