[gnome-shell/wip/exalm/gestures2: 5/7] workspaceAnimation: Use a workspace strip



commit 785a566f32f0220685d383ef53d07d5771e8cab9
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date:   Sat Jun 20 22:01:25 2020 +0500

    workspaceAnimation: Use a workspace strip
    
    Currently, the workspace swipe transition only has one workspace in each
    direction. This works until you try to do multiple swipes in quick
    succession. The second swipe would continue the existing transition, which
    only has 2 or 3 workspaces in it, and will hit a wall.
    
    To prevent this, take all workspaces and arrange them into a column or row,
    depending on the layout, and use that as a transition.
    
    For the transition that happens when focusing a window on another workspace
    (for example, via Alt+Tab), still use only two workspaces instead of all of
    them.
    
    Since we don't support layouts other than single rows/columns anymore,
    diagonal transitions aren't supported anymore, and will be shown as
    horizontal or vertical instead.
    
    https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1326

 js/ui/workspaceAnimation.js | 270 ++++++++++++++++++--------------------------
 1 file changed, 108 insertions(+), 162 deletions(-)
---
diff --git a/js/ui/workspaceAnimation.js b/js/ui/workspaceAnimation.js
index e27bc192c8..2a60979d46 100644
--- a/js/ui/workspaceAnimation.js
+++ b/js/ui/workspaceAnimation.js
@@ -97,7 +97,7 @@ var WorkspaceAnimationController = class {
         Main.overview.connect('showing', () => {
             if (this._switchData) {
                 if (this._switchData.gestureActivated)
-                    this._switchWorkspaceStop();
+                    this._finishWorkspaceSwitch(this._switchData);
                 this._swipeTracker.enabled = false;
             }
         });
@@ -113,89 +113,84 @@ var WorkspaceAnimationController = class {
         this._swipeTracker = swipeTracker;
     }
 
-    _getPositionForDirection(direction, fromWs, toWs) {
-        let xDest = 0, yDest = 0;
-
-        let oldWsIsFullscreen = fromWs.list_windows().some(w => w.is_fullscreen());
-        let newWsIsFullscreen = toWs.list_windows().some(w => w.is_fullscreen());
-
-        // We have to shift windows up or down by the height of the panel to prevent having a
-        // visible gap between the windows while switching workspaces. Since fullscreen windows
-        // hide the panel, they don't need to be shifted up or down.
-        let shiftHeight = Main.panel.height;
-
-        if (direction === Meta.MotionDirection.UP ||
-            direction === Meta.MotionDirection.UP_LEFT ||
-            direction === Meta.MotionDirection.UP_RIGHT)
-            yDest = -global.screen_height + (oldWsIsFullscreen ? 0 : shiftHeight);
-        else if (direction === Meta.MotionDirection.DOWN ||
-            direction === Meta.MotionDirection.DOWN_LEFT ||
-            direction === Meta.MotionDirection.DOWN_RIGHT)
-            yDest = global.screen_height - (newWsIsFullscreen ? 0 : shiftHeight);
-
-        if (direction === Meta.MotionDirection.LEFT ||
-            direction === Meta.MotionDirection.UP_LEFT ||
-            direction === Meta.MotionDirection.DOWN_LEFT)
-            xDest = -global.screen_width;
-        else if (direction === Meta.MotionDirection.RIGHT ||
-                 direction === Meta.MotionDirection.UP_RIGHT ||
-                 direction === Meta.MotionDirection.DOWN_RIGHT)
-            xDest = global.screen_width;
-
-        return [xDest, yDest];
-    }
-
-    _prepareWorkspaceSwitch(from, to, direction) {
+    _prepareWorkspaceSwitch(workspaces) {
         if (this._switchData)
             return;
 
         let wgroup = global.window_group;
         let workspaceManager = global.workspace_manager;
-        let curWs = workspaceManager.get_workspace_by_index(from);
+        let vertical = workspaceManager.layout_rows === -1;
+        let nWorkspaces = workspaceManager.get_n_workspaces();
+        let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
 
         let switchData = {};
 
         this._switchData = switchData;
-        switchData.curGroup = new WorkspaceGroup(this, curWs);
         switchData.movingWindowBin = new Clutter.Actor();
         switchData.movingWindow = null;
-        switchData.surroundings = {};
+        switchData.workspaces = [];
         switchData.gestureActivated = false;
         switchData.inProgress = false;
 
         switchData.container = new Clutter.Actor();
-        switchData.container.add_actor(switchData.curGroup);
 
         wgroup.add_actor(switchData.movingWindowBin);
         wgroup.add_actor(switchData.container);
 
-        for (let dir of Object.values(Meta.MotionDirection)) {
-            let ws = null;
+        let x = 0;
+        let y = 0;
 
-            if (to < 0)
-                ws = curWs.get_neighbor(dir);
-            else if (dir === direction)
-                ws = workspaceManager.get_workspace_by_index(to);
+        if (!workspaces) {
+            workspaces = [];
+
+            for (let i = 0; i < nWorkspaces; i++)
+                workspaces.push(i);
+        }
 
-            if (ws === null || ws === curWs) {
-                switchData.surroundings[dir] = null;
-                continue;
+        for (let i of workspaces) {
+            let ws = workspaceManager.get_workspace_by_index(i);
+            let fullscreen = ws.list_windows().some(w => w.is_fullscreen());
+
+            if (y > 0 && vertical && !fullscreen) {
+                // We have to shift windows up or down by the height of the panel to prevent having a
+                // visible gap between the windows while switching workspaces. Since fullscreen windows
+                // hide the panel, they don't need to be shifted up or down.
+                y -= Main.panel.height;
             }
 
-            let [x, y] = this._getPositionForDirection(dir, curWs, ws);
             let info = {
-                index: ws.index(),
+                ws,
                 actor: new WorkspaceGroup(this, ws),
-                xDest: x,
-                yDest: y,
+                fullscreen,
+                x,
+                y,
             };
-            switchData.surroundings[dir] = info;
+
+            if (vertical)
+                info.position = info.y / global.screen_height;
+            else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
+                info.position = -info.x / global.screen_width;
+            else
+                info.position = info.x / global.screen_width;
+
+            switchData.workspaces[i] = info;
             switchData.container.add_actor(info.actor);
             switchData.container.set_child_above_sibling(info.actor, null);
-
             info.actor.set_position(x, y);
+
+            if (vertical)
+                y += global.screen_height;
+            else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
+                x -= global.screen_width;
+            else
+                x += global.screen_width;
         }
 
+        if (global.workspace_manager.layout_rows === -1)
+            switchData.container.y = -switchData.workspaces[activeWorkspaceIndex].y;
+        else
+            switchData.container.x = -switchData.workspaces[activeWorkspaceIndex].x;
+
         wgroup.set_child_above_sibling(switchData.movingWindowBin, null);
 
         if (this.movingWindow) {
@@ -233,25 +228,44 @@ var WorkspaceAnimationController = class {
     }
 
     animateSwitchWorkspace(from, to, direction, onComplete) {
-        this._prepareWorkspaceSwitch(from, to, direction);
-        this._switchData.inProgress = true;
+        if (this._switchData)
+            this._switchData.container.remove_all_transitions();
 
-        let workspaceManager = global.workspace_manager;
-        let fromWs = workspaceManager.get_workspace_by_index(from);
-        let toWs = workspaceManager.get_workspace_by_index(to);
+        let workspaces = [];
+
+        switch (direction) {
+        case Meta.MotionDirection.UP:
+        case Meta.MotionDirection.LEFT:
+        case Meta.MotionDirection.UP_LEFT:
+        case Meta.MotionDirection.UP_RIGHT:
+            workspaces = [to, from];
+            break;
+
+        case Meta.MotionDirection.DOWN:
+        case Meta.MotionDirection.RIGHT:
+        case Meta.MotionDirection.DOWN_LEFT:
+        case Meta.MotionDirection.DOWN_RIGHT:
+            workspaces = [from, to];
+            break;
+        }
 
-        let [xDest, yDest] = this._getPositionForDirection(direction, fromWs, toWs);
+        if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL &&
+            direction !== Meta.MotionDirection.UP &&
+            direction !== Meta.MotionDirection.DOWN)
+            workspaces.reverse();
 
-        /* @direction is the direction that the "camera" moves, so the
-         * screen contents have to move one screen's worth in the
-         * opposite direction.
-         */
-        xDest = -xDest;
-        yDest = -yDest;
+        this._prepareWorkspaceSwitch(workspaces);
+        this._switchData.inProgress = true;
+
+        let fromWs = this._switchData.workspaces[from];
+        let toWs = this._switchData.workspaces[to];
+
+        this._switchData.container.x = -fromWs.x;
+        this._switchData.container.y = -fromWs.y;
 
         this._switchData.container.ease({
-            x: xDest,
-            y: yDest,
+            x: -toWs.x,
+            y: -toWs.y,
             duration: WINDOW_ANIMATION_TIME,
             mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
             onComplete: () => {
@@ -261,51 +275,10 @@ var WorkspaceAnimationController = class {
         });
     }
 
-    _directionForProgress(progress) {
-        if (global.workspace_manager.layout_rows === -1) {
-            return progress > 0
-                ? Meta.MotionDirection.DOWN
-                : Meta.MotionDirection.UP;
-        } else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL) {
-            return progress > 0
-                ? Meta.MotionDirection.LEFT
-                : Meta.MotionDirection.RIGHT;
-        } else {
-            return progress > 0
-                ? Meta.MotionDirection.RIGHT
-                : Meta.MotionDirection.LEFT;
-        }
-    }
-
-    _getProgressRange() {
-        if (!this._switchData)
-            return [0, 0];
-
-        let lower = 0;
-        let upper = 0;
-
-        let horiz = global.workspace_manager.layout_rows !== -1;
-        let baseDistance;
-        if (horiz)
-            baseDistance = global.screen_width;
-        else
-            baseDistance = global.screen_height;
-
-        let direction = this._directionForProgress(-1);
-        let info = this._switchData.surroundings[direction];
-        if (info !== null) {
-            let distance = horiz ? info.xDest : info.yDest;
-            lower = -Math.abs(distance) / baseDistance;
-        }
-
-        direction = this._directionForProgress(1);
-        info = this._switchData.surroundings[direction];
-        if (info !== null) {
-            let distance = horiz ? info.xDest : info.yDest;
-            upper = Math.abs(distance) / baseDistance;
-        }
-
-        return [lower, upper];
+    _findClosestWorkspace(position) {
+        let distances = this._switchData.workspaces.map(ws => Math.abs(ws.position - position));
+        let index = distances.indexOf(Math.min(...distances));
+        return this._switchData.workspaces[index];
     }
 
     _switchWorkspaceBegin(tracker, monitor) {
@@ -319,15 +292,10 @@ var WorkspaceAnimationController = class {
             ? Clutter.Orientation.HORIZONTAL
             : Clutter.Orientation.VERTICAL;
 
-        let activeWorkspace = workspaceManager.get_active_workspace();
-
-        let baseDistance;
-        if (horiz)
-            baseDistance = global.screen_width;
-        else
-            baseDistance = global.screen_height;
+        let baseDistance = horiz ? global.screen_width : global.screen_height;
 
         let progress;
+        let cancelProgress;
         if (this._switchData && this._switchData.gestureActivated) {
             this._switchData.container.remove_all_transitions();
             if (!horiz)
@@ -336,41 +304,35 @@ var WorkspaceAnimationController = class {
                 progress = this._switchData.container.x / baseDistance;
             else
                 progress = -this._switchData.container.x / baseDistance;
-        } else {
-            this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
-            progress = 0;
-        }
 
-        let points = [];
-        let [lower, upper] = this._getProgressRange();
+            cancelProgress = this._findClosestWorkspace(progress).position;
+        } else {
+            this._prepareWorkspaceSwitch();
 
-        if (lower !== 0)
-            points.push(lower);
+            let activeIndex = workspaceManager.get_active_workspace_index();
+            let ws = this._switchData.workspaces[activeIndex];
 
-        points.push(0);
+            progress = cancelProgress = ws.position;
+        }
 
-        if (upper !== 0)
-            points.push(upper);
+        let points = this._switchData.workspaces.map(ws => ws.position);
 
-        tracker.confirmSwipe(baseDistance, points, progress, 0);
+        tracker.confirmSwipe(baseDistance, points, progress, cancelProgress);
     }
 
     _switchWorkspaceUpdate(tracker, progress) {
         if (!this._switchData)
             return;
 
-        let direction = this._directionForProgress(progress);
-        let info = this._switchData.surroundings[direction];
         let xPos = 0;
         let yPos = 0;
-        if (info) {
-            if (global.workspace_manager.layout_rows === -1)
-                yPos = -Math.round(progress * global.screen_height);
-            else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
-                xPos = Math.round(progress * global.screen_width);
-            else
-                xPos = -Math.round(progress * global.screen_width);
-        }
+
+        if (global.workspace_manager.layout_rows === -1)
+            yPos = -Math.round(progress * global.screen_height);
+        else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
+            xPos = Math.round(progress * global.screen_width);
+        else
+            xPos = -Math.round(progress * global.screen_width);
 
         this._switchData.container.set_position(xPos, yPos);
     }
@@ -379,40 +341,24 @@ var WorkspaceAnimationController = class {
         if (!this._switchData)
             return;
 
-        let workspaceManager = global.workspace_manager;
-        let activeWorkspace = workspaceManager.get_active_workspace();
-        let newWs = activeWorkspace;
-        let xDest = 0;
-        let yDest = 0;
-        if (endProgress !== 0) {
-            let direction = this._directionForProgress(endProgress);
-            newWs = activeWorkspace.get_neighbor(direction);
-            xDest = -this._switchData.surroundings[direction].xDest;
-            yDest = -this._switchData.surroundings[direction].yDest;
-        }
+        let newWs = this._findClosestWorkspace(endProgress);
 
         let switchData = this._switchData;
         switchData.gestureActivated = true;
 
         this._switchData.container.ease({
-            x: xDest,
-            y: yDest,
+            x: -newWs.x,
+            y: -newWs.y,
             duration,
             mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
             onComplete: () => {
-                if (!newWs.active)
-                    newWs.activate(global.get_current_time());
+                if (!newWs.ws.active)
+                    newWs.ws.activate(global.get_current_time());
                 this._finishWorkspaceSwitch(switchData);
             },
         });
     }
 
-    _switchWorkspaceStop() {
-        this._switchData.container.x = 0;
-        this._switchData.container.y = 0;
-        this._finishWorkspaceSwitch(this._switchData);
-    }
-
     isAnimating() {
         return this._switchData !== null;
     }


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