[gnome-shell/wip/exalm/gestures: 2/2] overview part 1



commit 6f4762f7b2ce28ef3293b3a76d4478d3bd5c8658
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date:   Thu Jun 27 18:15:36 2019 +0500

    overview part 1

 js/ui/overviewControls.js   |   2 +-
 js/ui/swipeTracker.js       |  19 ++++---
 js/ui/viewSelector.js       |   4 +-
 js/ui/windowManager.js      |   2 +-
 js/ui/workspaceThumbnail.js |  38 +++++++++++--
 js/ui/workspacesView.js     | 132 ++++++++++++++++++++++++++++++++------------
 6 files changed, 146 insertions(+), 51 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/swipeTracker.js b/js/ui/swipeTracker.js
index 7ef1e8ef3..45cffeb42 100644
--- a/js/ui/swipeTracker.js
+++ b/js/ui/swipeTracker.js
@@ -30,10 +30,11 @@ function clamp(value, min, max) {
 // TODO: support horizontal
 
 var TouchpadSwipeGesture = class TouchpadSwipeGesture {
-    constructor(actor) {
+    constructor(actor, shouldSkip) {
         this._touchpadSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.peripherals.touchpad'});
 
         actor.connect('captured-event', this._handleEvent.bind(this));
+        this._shouldSkip = shouldSkip;
     }
 
     _handleEvent(actor, event) {
@@ -43,8 +44,8 @@ var TouchpadSwipeGesture = class TouchpadSwipeGesture {
         if (event.get_touchpad_gesture_finger_count() != 4)
             return Clutter.EVENT_PROPAGATE;
 
-//        if ((this._allowedModes & Main.actionMode) == 0 || !this._enabled)
-//            return Clutter.EVENT_PROPAGATE;
+        if (this._shouldSkip())
+            return Clutter.EVENT_PROPAGATE;
 
         let time = event.get_time();
         let [dx, dy] = event.get_gesture_motion_delta();
@@ -69,18 +70,19 @@ var TouchSwipeGesture = GObject.registerClass({
                'end':    { param_types: [GObject.TYPE_UINT] },
                'cancel': { param_types: [GObject.TYPE_UINT] }},
 }, class TouchSwipeGesture extends Clutter.GestureAction {
-    _init(actor) {
+    _init(actor, shouldSkip) {
         super._init();
         this.set_n_touch_points(4);
 
         this._actor = actor;
+        this._shouldSkip = shouldSkip;
     }
 
     vfunc_gesture_begin(actor, point) {
         if (!super.vfunc_gesture_begin(actor, point))
             return false;
 
-        return true; //(this._allowedModes & Main.actionMode) != 0 && this._enabled;
+        return !this._shouldSkip();
     }
 
     // TODO: track center of the fingers instead of the first one
@@ -148,12 +150,15 @@ var SwipeTracker = class {
         this._can_swipe_back = true;
         this._can_swipe_forward = true;
 
-        let gesture = new TouchpadSwipeGesture(actor);
+        let shouldSkip = () =>
+            ((this._allowedModes & Main.actionMode) == 0 || !this._enabled);
+
+        let gesture = new TouchpadSwipeGesture(actor, shouldSkip);
         gesture.connect('update', this._updateGesture.bind(this));
         gesture.connect('end', this._endGesture.bind(this));
 //        gesture.connect('cancel', this._cancelGesture.bind(this)); // End the gesture normally for 
touchpads
 
-        gesture = new TouchSwipeGesture(actor);
+        gesture = new TouchSwipeGesture(actor, shouldSkip);
         gesture.connect('update', this._updateGesture.bind(this));
         gesture.connect('end', this._endGesture.bind(this));
         gesture.connect('cancel', this._cancelGesture.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/windowManager.js b/js/ui/windowManager.js
index b6c168d56..6c5b39323 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -16,8 +16,8 @@ const WindowMenu = imports.ui.windowMenu;
 const PadOsd = imports.ui.padOsd;
 const EdgeDragAction = imports.ui.edgeDragAction;
 const CloseDialog = imports.ui.closeDialog;
-const SwitchMonitor = imports.ui.switchMonitor;
 const SwipeTracker = imports.ui.swipeTracker;
+const SwitchMonitor = imports.ui.switchMonitor;
 
 const { loadInterfaceXML } = imports.misc.fileUtils;
 
diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js
index 969167178..a6f07e6ea 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)
@@ -1001,6 +1002,9 @@ class ThumbnailsBox extends St.Widget {
     }
 
     set indicatorY(indicatorY) {
+        if (indicatorY == this._indicatorY)
+            return;
+
         this._indicatorY = indicatorY;
         this.queue_relayout();
     }
@@ -1009,6 +1013,29 @@ class ThumbnailsBox extends St.Widget {
         return this._indicatorY;
     }
 
+    overrideIndicatorPosition(pos) {
+        if (this._animatingIndicator) {
+            Tweener.removeTweens(this);
+            this._animatingIndicator = false;
+        }
+
+        let index1 = Math.floor(pos);
+        let index2 = Math.ceil(pos);
+        let progress = pos - index1;
+
+        this._gestureActive = true;
+
+        let indicatorY1 = this._thumbnails[index1].actor.allocation.y1;
+        let indicatorY2 = this._thumbnails[index2].actor.allocation.y1;
+
+        this.indicatorY = indicatorY1 + (indicatorY2 - indicatorY1) * progress;
+    }
+
+    resetIndicatorPosition() {
+        this._gestureActive = false;
+        this._queueUpdateStates();
+    }
+
     _setThumbnailState(thumbnail, state) {
         this._stateCounts[thumbnail.state]--;
         thumbnail.state = state;
@@ -1038,7 +1065,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
@@ -1212,7 +1239,7 @@ class ThumbnailsBox extends St.Widget {
         let indicatorY2;
         // when not animating, the workspace position overrides this._indicatorY
         let activeWorkspace = workspaceManager.get_active_workspace();
-        let indicatorWorkspace = !this._animatingIndicator ? activeWorkspace : null;
+        let indicatorWorkspace = (!this._animatingIndicator && !this._gestureActive) ? activeWorkspace : 
null;
         let indicatorThemeNode = this._indicator.get_theme_node();
 
         let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + 
indicatorThemeNode.get_border_width(St.Side.TOP);
@@ -1302,6 +1329,9 @@ class ThumbnailsBox extends St.Widget {
     }
 
     _activeWorkspaceChanged(wm, from, to, direction) {
+        if (this._gestureActive)
+             return;
+
         let thumbnail;
         let workspaceManager = global.workspace_manager;
         let activeWorkspace = workspaceManager.get_active_workspace();
@@ -1319,7 +1349,7 @@ class ThumbnailsBox extends St.Widget {
         Tweener.addTween(this,
                          { indicatorY: thumbnail.actor.allocation.y1,
                            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 f5bd44699..0fd1b5a31 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -4,6 +4,7 @@ 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 Workspace = imports.ui.workspace;
 
@@ -163,7 +164,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);
     }
 
@@ -185,7 +186,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
@@ -232,7 +233,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
         Tweener.addTween(this.scrollAdjustment, {
             value: index,
             time: WORKSPACE_SWITCH_TIME,
-            transition: 'easeOutQuad',
+            transition: 'easeOutCubic',
             onComplete: () => {
                 this._animatingScroll = false;
             }
@@ -306,11 +307,10 @@ var WorkspacesView = class extends WorkspacesViewBase {
     }
 
     endTouchGesture() {
-        this._gestureActive = false;
-
-        // Make sure title captions etc are shown as necessary
-        this._scrollToActive();
+        this._scrollToActive(false);
         this._updateVisibility();
+
+        this._gestureActive = false;
     }
 
     // sync the workspaces' positions to the value of the scroll adjustment
@@ -420,7 +420,9 @@ 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));
@@ -464,25 +466,19 @@ var WorkspacesDisplay = class {
         this.actor.bind_property('mapped', panAction, '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(global.stage, allowedModes); // TODO: somehow teach 
it to work with addAction() too
+        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',
@@ -495,6 +491,8 @@ var WorkspacesDisplay = class {
         this._keyPressEventId = 0;
 
         this._fullGeometry = null;
+
+        this._gestureActive = false;
     }
 
     _onPan(action) {
@@ -507,44 +505,101 @@ var WorkspacesDisplay = class {
     _startSwipeScroll() {
         for (let i = 0; i < this._workspacesViews.length; i++)
             this._workspacesViews[i].startSwipeScroll();
+        this._gestureActive = true;
     }
 
     _endSwipeScroll() {
         for (let i = 0; i < this._workspacesViews.length; i++)
             this._workspacesViews[i].endSwipeScroll();
+        this._gestureActive = false;
+        this._thumbnailsBox.resetIndicatorPosition();
     }
 
-    _startTouchGesture() {
+    _switchWorkspaceBegin(tracker) {
+        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.continueFrom(progress);
+            return;
+        }
+
         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();
 
-    _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();
+        tracker.can_swipe_forward = (activeWs.get_neighbor(Meta.MotionDirection.UP) != activeWs);
+        tracker.can_swipe_back = (activeWs.get_neighbor(Meta.MotionDirection.DOWN) != activeWs);
 
+        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) {
+        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) {
+        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.resetIndicatorPosition();
+    }
+
     navigateFocus(from, direction) {
         return this._getPrimaryView().actor.navigate_focus(from, direction, false);
     }
@@ -650,6 +705,11 @@ var WorkspacesDisplay = class {
             // values map directly
             adjustment.value = this._scrollAdjustment.value;
         }
+
+        if (this._gestureActive) {
+            let position = this._scrollAdjustment.value / this._scrollAdjustment.page_size;
+            this._thumbnailsBox.overrideIndicatorPosition(position);
+        }
     }
 
     _getMonitorIndexForEvent(event) {


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