[gnome-shell/wip/exalm/gestures: 15/17] workspacesView: Use SwipeTracker



commit 5b37c4fbd63397b7c60483828586010f5d444ec2
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date:   Sun Jun 30 17:15:18 2019 +0500

    workspacesView: Use SwipeTracker

 js/ui/overviewControls.js   |   2 +-
 js/ui/viewSelector.js       |   4 +-
 js/ui/workspaceThumbnail.js |  45 ++++++++--
 js/ui/workspacesView.js     | 207 +++++++++++++++++++++++---------------------
 4 files changed, 151 insertions(+), 107 deletions(-)
---
diff --git a/js/ui/overviewControls.js b/js/ui/overviewControls.js
index f10ba7306..b93c34a7e 100644
--- a/js/ui/overviewControls.js
+++ b/js/ui/overviewControls.js
@@ -400,7 +400,7 @@ var ControlsManager = class {
         this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
         this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox);
 
-        this.viewSelector = new ViewSelector.ViewSelector(searchEntry,
+        this.viewSelector = new ViewSelector.ViewSelector(searchEntry, this._thumbnailsBox,
                                                           this.dash.showAppsButton);
         this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
         this.viewSelector.connect('page-empty', this._onPageEmpty.bind(this));
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index ba32163f0..9119af793 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -120,7 +120,7 @@ var ShowOverviewAction = GObject.registerClass({
 });
 
 var ViewSelector = class {
-    constructor(searchEntry, showAppsButton) {
+    constructor(searchEntry, thumbnailsBox, showAppsButton) {
         this.actor = new Shell.Stack({ name: 'viewSelector' });
 
         this._showAppsButton = showAppsButton;
@@ -160,7 +160,7 @@ var ViewSelector = class {
         this._iconClickedId = 0;
         this._capturedEventId = 0;
 
-        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
+        this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay(thumbnailsBox);
         this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
                                              _("Windows"), 'focus-windows-symbolic');
 
diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
index 25629b814..b747da25d 100644
--- a/js/ui/workspaceThumbnail.js
+++ b/js/ui/workspaceThumbnail.js
@@ -626,7 +626,8 @@ class ThumbnailsBox extends St.Widget {
         this._pendingScaleUpdate = false;
         this._stateUpdateQueued = false;
         this._animatingIndicator = false;
-        this._indicatorY = 0; // only used when _animatingIndicator is true
+        this._gestureActive = false;
+        this._indicatorY = 0; // only used when _animatingIndicator or_gestureActive is true
 
         this._stateCounts = {};
         for (let key in ThumbnailState)
@@ -1009,6 +1010,37 @@ class ThumbnailsBox extends St.Widget {
         return this._indicatorY;
     }
 
+    overrideIndicatorProgress(progress) {
+        if (this._animatingIndicator) {
+            Tweener.removeTweens(this);
+            this._animatingIndicator = false;
+        }
+
+        let workspaceManager = global.workspace_manager;
+        let activeWorkspace = workspaceManager.get_active_workspace();
+
+        let active;
+        for (let i = 0; i < this._thumbnails.length; i++) {
+            if (this._thumbnails[i].metaWorkspace == activeWorkspace) {
+                active = i;
+                break;
+            }
+        }
+
+        this._gestureActive = true;
+
+//        log("WTF", progress);
+        let indicatorY1 = this._thumbnails[active].actor.allocation.y1;
+        let indicatorY2 = this._thumbnails[active + Math.sign(progress)].actor.allocation.y1;
+        this.indicatorY = (indicatorY2 - indicatorY1) * Math.abs(progress);
+    }
+
+    resetIndicatorProgress() {
+        this.indicatorY = 0;
+        this._gestureActive = false;
+        this._queueUpdateStates();
+    }
+
     _setThumbnailState(thumbnail, state) {
         this._stateCounts[thumbnail.state]--;
         thumbnail.state = state;
@@ -1038,7 +1070,7 @@ class ThumbnailsBox extends St.Widget {
         this._stateUpdateQueued = false;
 
         // If we are animating the indicator, wait
-        if (this._animatingIndicator)
+        if (this._animatingIndicator || this._gestureActive)
             return;
 
         // Then slide out any thumbnails that have been destroyed
@@ -1301,6 +1333,11 @@ class ThumbnailsBox extends St.Widget {
     }
 
     _activeWorkspaceChanged(wm, from, to, direction) {
+        this.queue_relayout();
+
+        if (this._gestureActive)
+             return;
+
         let thumbnail;
         let workspaceManager = global.workspace_manager;
         let activeWorkspace = workspaceManager.get_active_workspace();
@@ -1311,15 +1348,13 @@ class ThumbnailsBox extends St.Widget {
             }
         }
 
-        this.queue_relayout();
-
         this._animatingIndicator = true;
         this.indicatorY = this._indicator.allocation.y1 - thumbnail.actor.allocation.y1;
 
         Tweener.addTween(this,
                          { indicatorY: 0,
                            time: WorkspacesView.WORKSPACE_SWITCH_TIME,
-                           transition: 'easeOutQuad',
+                           transition: 'easeOutCubic',
                            onComplete() {
                                this._animatingIndicator = false;
                                this._queueUpdateStates();
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 53dd1dce1..bd45e6d7d 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._animatingScroll = false; // programmatically updating the adjustment
 
@@ -164,7 +163,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);
         this._updateScrollAdjustment(active);
     }
 
@@ -186,7 +185,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
             if (showAnimation) {
                 let params = { y: y,
                                time: WORKSPACE_SWITCH_TIME,
-                               transition: 'easeOutQuad'
+                               transition: 'easeOutCubic'
                              };
                 // we have to call _updateVisibility() once before the
                 // animation and once afterwards - it does not really
@@ -213,7 +212,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)
@@ -225,7 +224,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
     }
 
     _updateScrollAdjustment(index) {
-        if (this._scrolling || this._gestureActive)
+        if (this._gestureActive)
             return;
 
         this._animatingScroll = true;
@@ -233,7 +232,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
         Tweener.addTween(this.scrollAdjustment, {
             value: index,
             time: WORKSPACE_SWITCH_TIME,
-            transition: 'easeOutQuad',
+            transition: 'easeOutCubic',
             onComplete: () => {
                 this._animatingScroll = false;
             }
@@ -274,7 +273,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
     }
 
     _activeWorkspaceChanged(wm, from, to, direction) {
-        if (this._scrolling)
+        if (this._gestureActive)
             return;
 
         this._scrollToActive();
@@ -290,28 +289,15 @@ var WorkspacesView = class extends WorkspacesViewBase {
         workspaceManager.disconnect(this._updateWorkspacesId);
     }
 
-    startSwipeScroll() {
-        this._scrolling = true;
-    }
-
-    endSwipeScroll() {
-        this._scrolling = false;
-
-        // Make sure title captions etc are shown as necessary
-        this._scrollToActive();
-        this._updateVisibility();
-    }
-
     startTouchGesture() {
         this._gestureActive = true;
     }
 
     endTouchGesture() {
-        this._gestureActive = false;
-
-        // Make sure title captions etc are shown as necessary
         this._scrollToActive();
         this._updateVisibility();
+
+        this._gestureActive = false;
     }
 
     // sync the workspaces' positions to the value of the scroll adjustment
@@ -400,12 +386,6 @@ var ExtraWorkspaceView = class extends WorkspacesViewBase {
         this._workspace.syncStacking(stackIndices);
     }
 
-    startSwipeScroll() {
-    }
-
-    endSwipeScroll() {
-    }
-
     startTouchGesture() {
     }
 
@@ -421,14 +401,16 @@ class DelegateFocusNavigator extends St.Widget {
 });
 
 var WorkspacesDisplay = class {
-    constructor() {
+    constructor(thumbnailsBox) {
+        this._thumbnailsBox = thumbnailsBox;
+
         this.actor = new DelegateFocusNavigator({ clip_to_allocation: true });
         this.actor._delegate = this;
         this.actor.connect('notify::allocation', this._updateWorkspacesActualGeometry.bind(this));
         this.actor.connect('parent-set', this._parentSet.bind(this));
 
-        let clickAction = new Clutter.ClickAction();
-        clickAction.connect('clicked', action => {
+        this._clickAction = new Clutter.ClickAction();
+        this._clickAction.connect('clicked', action => {
             // Only switch to the workspace when there's no application
             // windows open. The problem is that it's too easy to miss
             // an app window and get the wrong one focused.
@@ -438,52 +420,23 @@ var WorkspacesDisplay = class {
                 this._workspacesViews[index].getActiveWorkspace().isEmpty())
                 Main.overview.hide();
         });
-        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);
+        Main.overview.addAction(this._clickAction);
+        this.actor.bind_property('mapped', this._clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
 
         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.overview, allowedModes);
+        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.actor.connect('notify::mapped', () => {
-            switchGesture.enabled = this.actor.mapped;
+            swipeTracker.enabled = this.actor.mapped;
         });
 
         this._primaryIndex = Main.layoutManager.primaryIndex;
 
         this._workspacesViews = [];
-        switchGesture.enabled = this.actor.mapped;
+        swipeTracker.enabled = this.actor.mapped;
 
         this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA });
         this._settings.connect('changed::workspaces-only-on-primary',
@@ -496,56 +449,103 @@ var WorkspacesDisplay = class {
         this._keyPressEventId = 0;
 
         this._fullGeometry = null;
-    }
 
-    _onPan(action) {
-        let [dist, dx, dy] = action.get_motion_delta(0);
-        let adjustment = this._scrollAdjustment;
-        adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
-        return false;
+        this._gestureActive = false;
     }
 
-    _startSwipeScroll() {
-        for (let i = 0; i < this._workspacesViews.length; i++)
-            this._workspacesViews[i].startSwipeScroll();
-    }
+    _switchWorkspaceBegin(tracker, monitor) {
+        if (this._workspacesOnlyOnPrimary && monitor != this._primaryIndex)
+            return;
 
-    _endSwipeScroll() {
-        for (let i = 0; i < this._workspacesViews.length; i++)
-            this._workspacesViews[i].endSwipeScroll();
-    }
+        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;
+        }
 
-    _startTouchGesture() {
         for (let i = 0; i < this._workspacesViews.length; i++)
             this._workspacesViews[i].startTouchGesture();
-    }
 
-    _endTouchGesture() {
-        for (let i = 0; i < this._workspacesViews.length; i++)
-            this._workspacesViews[i].endTouchGesture();
-    }
+        let workspaceManager = global.workspace_manager;
+        let activeWs = workspaceManager.get_active_workspace();
+
+        let canSwipeBack = (activeWs.get_neighbor(Meta.MotionDirection.DOWN) != activeWs);
+        let canSwipeForward = (activeWs.get_neighbor(Meta.MotionDirection.UP) != activeWs);
+        tracker.confirmSwipe(canSwipeBack, canSwipeForward, this.actor.height, 0, 0);
 
-    _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();
+        this._gestureActive = true;
+    }
 
+    _switchWorkspaceUpdate(tracker, progress) {
         let workspaceManager = global.workspace_manager;
         let active = workspaceManager.get_active_workspace_index();
         let adjustment = this._scrollAdjustment;
-        adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size;
+        adjustment.value = (active + progress) * adjustment.page_size;
     }
 
-    _onSwitchWorkspaceActivated(action, direction) {
+    _switchWorkspaceEnd(tracker, duration, isBack) {
+        this._clickAction.release();
+
+        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)
-            newWs.activate(global.get_current_time());
+
+        if (newWs == activeWorkspace) {
+            // FIXME: throw an error
+            log('this should never happen')
+        } else {
+            let active = workspaceManager.get_active_workspace_index();
+            Tweener.addTween(this._scrollAdjustment,
+                             { value: active + (isBack ? 1 : -1),
+                               time: duration,
+                               transition: 'easeOutCubic',
+                               onComplete: this._switchWorkspaceActivate,
+                               onCompleteScope: this,
+                               onCompleteParams: [newWs]
+                             });
+        }
+    }
+
+    _switchWorkspaceCancel(tracker, duration) {
+        this._clickAction.release();
+
+        if (duration == 0) {
+            this._endTouchGesture();
+            return;
+        }
+
+        let workspaceManager = global.workspace_manager;
+        let active = workspaceManager.get_active_workspace_index();
+        Tweener.addTween(this._scrollAdjustment,
+                         { value: active,
+                           time: duration,
+                           transition: 'easeOutCubic',
+                           onComplete: this._endTouchGesture,
+                           onCompleteScope: this
+                         });
+    }
+
+    _switchWorkspaceActivate(newWs) {
+        newWs.activate(global.get_current_time());
 
         this._endTouchGesture();
     }
 
+    _endTouchGesture() {
+        for (let i = 0; i < this._workspacesViews.length; i++)
+            this._workspacesViews[i].endTouchGesture();
+        this._gestureActive = false;
+        this._thumbnailsBox.resetIndicatorProgress();
+    }
+
     navigateFocus(from, direction) {
         return this._getPrimaryView().actor.navigate_focus(from, direction, false);
     }
@@ -623,7 +623,6 @@ var WorkspacesDisplay = class {
             else
                 view = new WorkspacesView(i);
 
-            view.actor.connect('scroll-event', this._onScrollEvent.bind(this));
             if (i == this._primaryIndex) {
                 this._scrollAdjustment = view.scrollAdjustment;
                 this._scrollAdjustment.connect('notify::value',
@@ -651,6 +650,13 @@ var WorkspacesDisplay = class {
             // values map directly
             adjustment.value = this._scrollAdjustment.value;
         }
+
+        if (this._gestureActive) {
+            let workspaceManager = global.workspace_manager;
+            let active = workspaceManager.get_active_workspace_index();
+            let progress = this._scrollAdjustment.value / this._scrollAdjustment.page_size - active;
+            this._thumbnailsBox.overrideIndicatorProgress(progress);
+        }
     }
 
     _getMonitorIndexForEvent(event) {
@@ -735,6 +741,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]