Compare commits
	
		
			7 Commits
		
	
	
		
			wip/smcv/i
			...
			wip/exalm/
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					b1afb946b2 | ||
| 
						 | 
					46d5bccfc6 | ||
| 
						 | 
					f0d498062d | ||
| 
						 | 
					eeac4a3b6d | ||
| 
						 | 
					272cb4d523 | ||
| 
						 | 
					6d5446e4a6 | ||
| 
						 | 
					fa31bcaa7a | 
@@ -109,6 +109,7 @@
 | 
			
		||||
    <file>ui/windowMenu.js</file>
 | 
			
		||||
    <file>ui/windowManager.js</file>
 | 
			
		||||
    <file>ui/workspace.js</file>
 | 
			
		||||
    <file>ui/workspaceAnimation.js</file>
 | 
			
		||||
    <file>ui/workspaceSwitcherPopup.js</file>
 | 
			
		||||
    <file>ui/workspaceThumbnail.js</file>
 | 
			
		||||
    <file>ui/workspacesView.js</file>
 | 
			
		||||
 
 | 
			
		||||
@@ -14,9 +14,9 @@ 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 IBusManager = imports.misc.ibusManager;
 | 
			
		||||
const WorkspaceAnimation = imports.ui.workspaceAnimation;
 | 
			
		||||
 | 
			
		||||
const { loadInterfaceXML } = imports.misc.fileUtils;
 | 
			
		||||
 | 
			
		||||
@@ -559,7 +559,6 @@ var WindowManager = class {
 | 
			
		||||
        this._resizing = new Set();
 | 
			
		||||
        this._resizePending = new Set();
 | 
			
		||||
        this._destroying = new Set();
 | 
			
		||||
        this._movingWindow = null;
 | 
			
		||||
 | 
			
		||||
        this._dimmedWindows = [];
 | 
			
		||||
 | 
			
		||||
@@ -569,15 +568,6 @@ var WindowManager = class {
 | 
			
		||||
 | 
			
		||||
        this._isWorkspacePrepended = false;
 | 
			
		||||
 | 
			
		||||
        this._switchData = null;
 | 
			
		||||
        this._shellwm.connect('kill-switch-workspace', shellwm => {
 | 
			
		||||
            if (this._switchData) {
 | 
			
		||||
                if (this._switchData.inProgress)
 | 
			
		||||
                    this._switchWorkspaceDone(shellwm);
 | 
			
		||||
                else if (!this._switchData.gestureActivated)
 | 
			
		||||
                    this._finishWorkspaceSwitch(this._switchData);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        this._shellwm.connect('kill-window-effects', (shellwm, actor) => {
 | 
			
		||||
            this._minimizeWindowDone(shellwm, actor);
 | 
			
		||||
            this._mapWindowDone(shellwm, actor);
 | 
			
		||||
@@ -599,7 +589,6 @@ var WindowManager = class {
 | 
			
		||||
        this._shellwm.connect('confirm-display-change', this._confirmDisplayChange.bind(this));
 | 
			
		||||
        this._shellwm.connect('create-close-dialog', this._createCloseDialog.bind(this));
 | 
			
		||||
        this._shellwm.connect('create-inhibit-shortcuts-dialog', this._createInhibitShortcutsDialog.bind(this));
 | 
			
		||||
        global.display.connect('restacked', this._syncStacking.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._workspaceSwitcherPopup = null;
 | 
			
		||||
        this._tilePreview = null;
 | 
			
		||||
@@ -908,17 +897,10 @@ 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();
 | 
			
		||||
@@ -929,13 +911,6 @@ var WindowManager = class {
 | 
			
		||||
        global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT,
 | 
			
		||||
                                                           false, -1, 1);
 | 
			
		||||
 | 
			
		||||
        let swipeTracker = new SwipeTracker.SwipeTracker(global.stage,
 | 
			
		||||
            Shell.ActionMode.NORMAL, { allowDrag: false, allowScroll: false });
 | 
			
		||||
        swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
 | 
			
		||||
        swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
 | 
			
		||||
        swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
 | 
			
		||||
        this._swipeTracker = swipeTracker;
 | 
			
		||||
 | 
			
		||||
        let appSwitchAction = new AppSwitchAction();
 | 
			
		||||
        appSwitchAction.connect('activated', this._switchApp.bind(this));
 | 
			
		||||
        global.stage.add_action(appSwitchAction);
 | 
			
		||||
@@ -967,6 +942,17 @@ var WindowManager = class {
 | 
			
		||||
        global.display.connect('in-fullscreen-changed', updateUnfullscreenGesture);
 | 
			
		||||
 | 
			
		||||
        global.stage.add_action(topDragAction);
 | 
			
		||||
 | 
			
		||||
        this._workspaceAnimation =
 | 
			
		||||
            new WorkspaceAnimation.WorkspaceAnimationController();
 | 
			
		||||
 | 
			
		||||
        this._shellwm.connect('kill-switch-workspace', () => {
 | 
			
		||||
            if (!this._workspaceAnimation.isAnimating() || this._workspaceAnimation.canCancelGesture())
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            this._workspaceAnimation.cancelSwitchAnimation();
 | 
			
		||||
            this._shellwm.completed_switch_workspace();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _showPadOsd(display, device, settings, imagePath, editionMode, monitorIndex) {
 | 
			
		||||
@@ -1089,8 +1075,7 @@ var WindowManager = class {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _shouldAnimate() {
 | 
			
		||||
        return !(Main.overview.visible ||
 | 
			
		||||
            (this._switchData && this._switchData.gestureActivated));
 | 
			
		||||
        return !(Main.overview.visible || this._workspaceAnimation.isAnimating());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _shouldAnimateActor(actor, types) {
 | 
			
		||||
@@ -1571,379 +1556,17 @@ var WindowManager = class {
 | 
			
		||||
        return !(this._allowedKeybindings[binding.get_name()] & Main.actionMode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _syncStacking() {
 | 
			
		||||
        if (this._switchData == null)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let windows = global.get_window_actors();
 | 
			
		||||
        let lastCurSibling = null;
 | 
			
		||||
        let lastDirSibling = [];
 | 
			
		||||
        for (let i = 0; i < windows.length; i++) {
 | 
			
		||||
            if (windows[i].get_parent() == this._switchData.curGroup) {
 | 
			
		||||
                this._switchData.curGroup.set_child_above_sibling(windows[i], lastCurSibling);
 | 
			
		||||
                lastCurSibling = windows[i];
 | 
			
		||||
            } else {
 | 
			
		||||
                for (let dir of Object.values(Meta.MotionDirection)) {
 | 
			
		||||
                    let info = this._switchData.surroundings[dir];
 | 
			
		||||
                    if (!info || windows[i].get_parent() != info.actor)
 | 
			
		||||
                        continue;
 | 
			
		||||
 | 
			
		||||
                    let sibling = lastDirSibling[dir];
 | 
			
		||||
                    if (sibling == undefined)
 | 
			
		||||
                        sibling = null;
 | 
			
		||||
 | 
			
		||||
                    info.actor.set_child_above_sibling(windows[i], sibling);
 | 
			
		||||
                    lastDirSibling[dir] = windows[i];
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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) {
 | 
			
		||||
        if (this._switchData)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let wgroup = global.window_group;
 | 
			
		||||
        let windows = global.get_window_actors();
 | 
			
		||||
        let switchData = {};
 | 
			
		||||
 | 
			
		||||
        this._switchData = switchData;
 | 
			
		||||
        switchData.curGroup = new Clutter.Actor();
 | 
			
		||||
        switchData.movingWindowBin = new Clutter.Actor();
 | 
			
		||||
        switchData.windows = [];
 | 
			
		||||
        switchData.surroundings = {};
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let curWs = workspaceManager.get_workspace_by_index(from);
 | 
			
		||||
 | 
			
		||||
        for (let dir of Object.values(Meta.MotionDirection)) {
 | 
			
		||||
            let ws = null;
 | 
			
		||||
 | 
			
		||||
            if (to < 0)
 | 
			
		||||
                ws = curWs.get_neighbor(dir);
 | 
			
		||||
            else if (dir == direction)
 | 
			
		||||
                ws = workspaceManager.get_workspace_by_index(to);
 | 
			
		||||
 | 
			
		||||
            if (ws == null || ws == curWs) {
 | 
			
		||||
                switchData.surroundings[dir] = null;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let [x, y] = this._getPositionForDirection(dir, curWs, ws);
 | 
			
		||||
            let info = {
 | 
			
		||||
                index: ws.index(),
 | 
			
		||||
                actor: new Clutter.Actor(),
 | 
			
		||||
                xDest: x,
 | 
			
		||||
                yDest: y,
 | 
			
		||||
            };
 | 
			
		||||
            switchData.surroundings[dir] = info;
 | 
			
		||||
            switchData.container.add_actor(info.actor);
 | 
			
		||||
            switchData.container.set_child_above_sibling(info.actor, null);
 | 
			
		||||
 | 
			
		||||
            info.actor.set_position(x, y);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        wgroup.set_child_above_sibling(switchData.movingWindowBin, null);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < windows.length; i++) {
 | 
			
		||||
            let actor = windows[i];
 | 
			
		||||
            let window = actor.get_meta_window();
 | 
			
		||||
 | 
			
		||||
            if (!window.showing_on_its_workspace())
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            if (window.is_on_all_workspaces())
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            let record = { window: actor,
 | 
			
		||||
                           parent: actor.get_parent() };
 | 
			
		||||
 | 
			
		||||
            if (this._movingWindow && window == this._movingWindow) {
 | 
			
		||||
                record.parent.remove_child(actor);
 | 
			
		||||
                switchData.movingWindow = record;
 | 
			
		||||
                switchData.windows.push(switchData.movingWindow);
 | 
			
		||||
                switchData.movingWindowBin.add_child(actor);
 | 
			
		||||
            } else if (window.get_workspace().index() == from) {
 | 
			
		||||
                record.parent.remove_child(actor);
 | 
			
		||||
                switchData.windows.push(record);
 | 
			
		||||
                switchData.curGroup.add_child(actor);
 | 
			
		||||
            } else {
 | 
			
		||||
                let visible = false;
 | 
			
		||||
                for (let dir of Object.values(Meta.MotionDirection)) {
 | 
			
		||||
                    let info = switchData.surroundings[dir];
 | 
			
		||||
 | 
			
		||||
                    if (!info || info.index != window.get_workspace().index())
 | 
			
		||||
                        continue;
 | 
			
		||||
 | 
			
		||||
                    record.parent.remove_child(actor);
 | 
			
		||||
                    switchData.windows.push(record);
 | 
			
		||||
                    info.actor.add_child(actor);
 | 
			
		||||
                    visible = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                actor.visible = visible;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < switchData.windows.length; i++) {
 | 
			
		||||
            let w = switchData.windows[i];
 | 
			
		||||
 | 
			
		||||
            w.windowDestroyId = w.window.connect('destroy', () => {
 | 
			
		||||
                switchData.windows.splice(switchData.windows.indexOf(w), 1);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _finishWorkspaceSwitch(switchData) {
 | 
			
		||||
        this._switchData = null;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < switchData.windows.length; i++) {
 | 
			
		||||
            let w = switchData.windows[i];
 | 
			
		||||
 | 
			
		||||
            w.window.disconnect(w.windowDestroyId);
 | 
			
		||||
            w.window.get_parent().remove_child(w.window);
 | 
			
		||||
            w.parent.add_child(w.window);
 | 
			
		||||
 | 
			
		||||
            if (w.window.get_meta_window().get_workspace() !=
 | 
			
		||||
                global.workspace_manager.get_active_workspace())
 | 
			
		||||
                w.window.hide();
 | 
			
		||||
        }
 | 
			
		||||
        switchData.container.destroy();
 | 
			
		||||
        switchData.movingWindowBin.destroy();
 | 
			
		||||
 | 
			
		||||
        this._movingWindow = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspace(shellwm, from, to, direction) {
 | 
			
		||||
        if (!Main.sessionMode.hasWorkspaces || !this._shouldAnimate()) {
 | 
			
		||||
            shellwm.completed_switch_workspace();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._prepareWorkspaceSwitch(from, to, direction);
 | 
			
		||||
        this._switchData.inProgress = true;
 | 
			
		||||
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let fromWs = workspaceManager.get_workspace_by_index(from);
 | 
			
		||||
        let toWs = workspaceManager.get_workspace_by_index(to);
 | 
			
		||||
 | 
			
		||||
        let [xDest, yDest] = this._getPositionForDirection(direction, fromWs, toWs);
 | 
			
		||||
 | 
			
		||||
        /* @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._switchData.container.ease({
 | 
			
		||||
            x: xDest,
 | 
			
		||||
            y: yDest,
 | 
			
		||||
            duration: WINDOW_ANIMATION_TIME,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
 | 
			
		||||
            onComplete: () => this._switchWorkspaceDone(shellwm),
 | 
			
		||||
        this._workspaceAnimation.animateSwitchWorkspace(from, to, direction, () => {
 | 
			
		||||
            this._shellwm.completed_switch_workspace();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceDone(shellwm) {
 | 
			
		||||
        this._finishWorkspaceSwitch(this._switchData);
 | 
			
		||||
        shellwm.completed_switch_workspace();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceBegin(tracker, monitor) {
 | 
			
		||||
        if (Meta.prefs_get_workspaces_only_on_primary() &&
 | 
			
		||||
            monitor !== Main.layoutManager.primaryIndex)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let horiz = workspaceManager.layout_rows !== -1;
 | 
			
		||||
        tracker.orientation = horiz
 | 
			
		||||
            ? 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 progress;
 | 
			
		||||
        if (this._switchData && this._switchData.gestureActivated) {
 | 
			
		||||
            this._switchData.container.remove_all_transitions();
 | 
			
		||||
            if (!horiz)
 | 
			
		||||
                progress = -this._switchData.container.y / baseDistance;
 | 
			
		||||
            else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
 | 
			
		||||
                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();
 | 
			
		||||
 | 
			
		||||
        if (lower !== 0)
 | 
			
		||||
            points.push(lower);
 | 
			
		||||
 | 
			
		||||
        points.push(0);
 | 
			
		||||
 | 
			
		||||
        if (upper !== 0)
 | 
			
		||||
            points.push(upper);
 | 
			
		||||
 | 
			
		||||
        tracker.confirmSwipe(baseDistance, points, progress, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._switchData.container.set_position(xPos, yPos);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceEnd(tracker, duration, endProgress) {
 | 
			
		||||
        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 switchData = this._switchData;
 | 
			
		||||
        switchData.gestureActivated = true;
 | 
			
		||||
 | 
			
		||||
        this._switchData.container.ease({
 | 
			
		||||
            x: xDest,
 | 
			
		||||
            y: yDest,
 | 
			
		||||
            duration,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
 | 
			
		||||
            onComplete: () => {
 | 
			
		||||
                if (newWs !== activeWorkspace)
 | 
			
		||||
                    this.actionMoveWorkspace(newWs);
 | 
			
		||||
                this._finishWorkspaceSwitch(switchData);
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceStop() {
 | 
			
		||||
        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();
 | 
			
		||||
@@ -2141,7 +1764,7 @@ var WindowManager = class {
 | 
			
		||||
            // This won't have any effect for "always sticky" windows
 | 
			
		||||
            // (like desktop windows or docks)
 | 
			
		||||
 | 
			
		||||
            this._movingWindow = window;
 | 
			
		||||
            this._workspaceAnimation.movingWindow = window;
 | 
			
		||||
            window.change_workspace(workspace);
 | 
			
		||||
 | 
			
		||||
            global.display.clear_mouse_mode();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										511
									
								
								js/ui/workspaceAnimation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										511
									
								
								js/ui/workspaceAnimation.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,511 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/* exported WorkspaceAnimationController */
 | 
			
		||||
 | 
			
		||||
const { Clutter, GObject, Meta, Shell } = imports.gi;
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const Layout = imports.ui.layout;
 | 
			
		||||
const SwipeTracker = imports.ui.swipeTracker;
 | 
			
		||||
 | 
			
		||||
const WINDOW_ANIMATION_TIME = 250;
 | 
			
		||||
 | 
			
		||||
const WorkspaceGroup = GObject.registerClass(
 | 
			
		||||
class WorkspaceGroup extends Clutter.Actor {
 | 
			
		||||
    _init(controller, workspace, monitor) {
 | 
			
		||||
        super._init();
 | 
			
		||||
 | 
			
		||||
        this._controller = controller;
 | 
			
		||||
        this._workspace = workspace;
 | 
			
		||||
        this._monitor = monitor;
 | 
			
		||||
        this._windows = [];
 | 
			
		||||
 | 
			
		||||
        this._refreshWindows();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
        this._restackedId = global.display.connect('restacked',
 | 
			
		||||
            this._refreshWindows.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _shouldShowWindow(window) {
 | 
			
		||||
        if (window.get_workspace() !== this._workspace)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        let geometry = global.display.get_monitor_geometry(this._monitor.index);
 | 
			
		||||
        let [intersects, intersection_] = window.get_frame_rect().intersect(geometry);
 | 
			
		||||
        if (!intersects)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (!window.showing_on_its_workspace())
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (window.is_on_all_workspaces())
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (this._controller.movingWindow &&
 | 
			
		||||
            window === this._controller.movingWindow)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _refreshWindows() {
 | 
			
		||||
        if (this._windows.length > 0)
 | 
			
		||||
            this._removeWindows();
 | 
			
		||||
 | 
			
		||||
        let windows = global.get_window_actors();
 | 
			
		||||
        windows = windows.filter(w => this._shouldShowWindow(w.meta_window));
 | 
			
		||||
 | 
			
		||||
        for (let window of windows) {
 | 
			
		||||
            let clone = new Clutter.Clone({
 | 
			
		||||
                source: window,
 | 
			
		||||
                x: window.x - this._monitor.x,
 | 
			
		||||
                y: window.y - this._monitor.y,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            this.add_actor(clone);
 | 
			
		||||
            window.hide();
 | 
			
		||||
 | 
			
		||||
            let record = { window, clone };
 | 
			
		||||
 | 
			
		||||
            record.windowDestroyId = window.connect('destroy', () => {
 | 
			
		||||
                clone.destroy();
 | 
			
		||||
                this._windows.splice(this._windows.indexOf(record), 1);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            this._windows.push(record);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _removeWindows() {
 | 
			
		||||
        for (let i = 0; i < this._windows.length; i++) {
 | 
			
		||||
            let w = this._windows[i];
 | 
			
		||||
 | 
			
		||||
            w.window.disconnect(w.windowDestroyId);
 | 
			
		||||
            w.clone.destroy();
 | 
			
		||||
 | 
			
		||||
            if (w.window.get_meta_window().get_workspace() ===
 | 
			
		||||
                global.workspace_manager.get_active_workspace())
 | 
			
		||||
                w.window.show();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._windows = [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        global.display.disconnect(this._restackedId);
 | 
			
		||||
        this._removeWindows();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const WorkspaceAnimation = GObject.registerClass({
 | 
			
		||||
    Properties: {
 | 
			
		||||
        'progress': GObject.ParamSpec.double(
 | 
			
		||||
            'progress', 'progress', 'progress',
 | 
			
		||||
            GObject.ParamFlags.READWRITE,
 | 
			
		||||
            -1, 1, 0),
 | 
			
		||||
    },
 | 
			
		||||
}, class WorkspaceAnimation extends Clutter.Actor {
 | 
			
		||||
    _init(controller, from, to, direction) {
 | 
			
		||||
        super._init();
 | 
			
		||||
 | 
			
		||||
        this.connect('destroy', this._onDestroy.bind(this));
 | 
			
		||||
 | 
			
		||||
        this._controller = controller;
 | 
			
		||||
        this._movingWindow = null;
 | 
			
		||||
        this._monitors = [];
 | 
			
		||||
        this._progress = 0;
 | 
			
		||||
 | 
			
		||||
        global.window_group.add_actor(this);
 | 
			
		||||
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let curWs = workspaceManager.get_workspace_by_index(from);
 | 
			
		||||
 | 
			
		||||
        for (let monitor of Main.layoutManager.monitors) {
 | 
			
		||||
            let record = {
 | 
			
		||||
                index: monitor.index,
 | 
			
		||||
                clipBin: new Clutter.Actor({
 | 
			
		||||
                    x_expand: true,
 | 
			
		||||
                    y_expand: true,
 | 
			
		||||
                    clip_to_allocation: true,
 | 
			
		||||
                }),
 | 
			
		||||
                container: new Clutter.Actor(),
 | 
			
		||||
                surroundings: {},
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            let constraint = new Layout.MonitorConstraint({ index: monitor.index });
 | 
			
		||||
            record.clipBin.add_constraint(constraint);
 | 
			
		||||
 | 
			
		||||
            record.clipBin.add_actor(record.container);
 | 
			
		||||
 | 
			
		||||
            this.add_actor(record.clipBin);
 | 
			
		||||
 | 
			
		||||
            record.curGroup = new WorkspaceGroup(controller, curWs, monitor);
 | 
			
		||||
            record.container.add_actor(record.curGroup);
 | 
			
		||||
 | 
			
		||||
            for (let dir of Object.values(Meta.MotionDirection)) {
 | 
			
		||||
                let ws = null;
 | 
			
		||||
 | 
			
		||||
                if (to < 0)
 | 
			
		||||
                    ws = curWs.get_neighbor(dir);
 | 
			
		||||
                else if (dir === direction)
 | 
			
		||||
                    ws = workspaceManager.get_workspace_by_index(to);
 | 
			
		||||
 | 
			
		||||
                if (ws === null || ws === curWs) {
 | 
			
		||||
                    record.surroundings[dir] = null;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                let [x, y] = this._getPositionForDirection(dir, curWs, ws,
 | 
			
		||||
                    monitor.index);
 | 
			
		||||
                let info = {
 | 
			
		||||
                    index: ws.index(),
 | 
			
		||||
                    actor: new WorkspaceGroup(controller, ws, monitor),
 | 
			
		||||
                    xDest: x,
 | 
			
		||||
                    yDest: y,
 | 
			
		||||
                };
 | 
			
		||||
                record.surroundings[dir] = info;
 | 
			
		||||
                record.container.add_actor(info.actor);
 | 
			
		||||
                record.container.set_child_above_sibling(info.actor, null);
 | 
			
		||||
 | 
			
		||||
                info.actor.set_position(x, y);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._monitors.push(record);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._controller.movingWindow) {
 | 
			
		||||
            let actor = this._controller.movingWindow.get_compositor_private();
 | 
			
		||||
            let container = new Clutter.Actor();
 | 
			
		||||
 | 
			
		||||
            this._movingWindow = {
 | 
			
		||||
                container,
 | 
			
		||||
                window: actor,
 | 
			
		||||
                parent: actor.get_parent(),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            this._movingWindow.parent.remove_child(actor);
 | 
			
		||||
            this._movingWindow.container.add_child(actor);
 | 
			
		||||
            this._movingWindow.windowDestroyId = actor.connect('destroy', () => {
 | 
			
		||||
                this._movingWindow = null;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            global.window_group.add_actor(container);
 | 
			
		||||
            global.window_group.set_child_above_sibling(container, null);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _onDestroy() {
 | 
			
		||||
        this._monitors = [];
 | 
			
		||||
 | 
			
		||||
        if (this._movingWindow) {
 | 
			
		||||
            let record = this._movingWindow;
 | 
			
		||||
            record.window.disconnect(record.windowDestroyId);
 | 
			
		||||
            record.window.get_parent().remove_child(record.window);
 | 
			
		||||
            record.parent.add_child(record.window);
 | 
			
		||||
            record.container.destroy();
 | 
			
		||||
 | 
			
		||||
            this._movingWindow = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getPositionForDirection(direction, fromWs, toWs, monitor) {
 | 
			
		||||
        let xDest = 0, yDest = 0;
 | 
			
		||||
 | 
			
		||||
        let condition = w => w.get_monitor() === monitor && w.is_fullscreen();
 | 
			
		||||
 | 
			
		||||
        let oldWsIsFullscreen = fromWs.list_windows().some(condition);
 | 
			
		||||
        let newWsIsFullscreen = toWs.list_windows().some(condition);
 | 
			
		||||
 | 
			
		||||
        let geometry = Main.layoutManager.monitors[monitor];
 | 
			
		||||
 | 
			
		||||
        // 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 = monitor === Main.layoutManager.primaryIndex
 | 
			
		||||
            ? Main.panel.height : 0;
 | 
			
		||||
 | 
			
		||||
        if (direction === Meta.MotionDirection.UP ||
 | 
			
		||||
            direction === Meta.MotionDirection.UP_LEFT ||
 | 
			
		||||
            direction === Meta.MotionDirection.UP_RIGHT)
 | 
			
		||||
            yDest = -geometry.height + (oldWsIsFullscreen ? 0 : shiftHeight);
 | 
			
		||||
        else if (direction === Meta.MotionDirection.DOWN ||
 | 
			
		||||
            direction === Meta.MotionDirection.DOWN_LEFT ||
 | 
			
		||||
            direction === Meta.MotionDirection.DOWN_RIGHT)
 | 
			
		||||
            yDest = geometry.height - (newWsIsFullscreen ? 0 : shiftHeight);
 | 
			
		||||
 | 
			
		||||
        if (direction === Meta.MotionDirection.LEFT ||
 | 
			
		||||
            direction === Meta.MotionDirection.UP_LEFT ||
 | 
			
		||||
            direction === Meta.MotionDirection.DOWN_LEFT)
 | 
			
		||||
            xDest = -geometry.width;
 | 
			
		||||
        else if (direction === Meta.MotionDirection.RIGHT ||
 | 
			
		||||
                 direction === Meta.MotionDirection.UP_RIGHT ||
 | 
			
		||||
                 direction === Meta.MotionDirection.DOWN_RIGHT)
 | 
			
		||||
            xDest = geometry.width;
 | 
			
		||||
 | 
			
		||||
        return [xDest, yDest];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    progressForDirection(dir) {
 | 
			
		||||
        if (global.workspace_manager.layout_rows === -1)
 | 
			
		||||
            return dir === Meta.MotionDirection.DOWN ? 1 : -1;
 | 
			
		||||
        else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
 | 
			
		||||
            return dir === Meta.MotionDirection.LEFT ? 1 : -1;
 | 
			
		||||
        else
 | 
			
		||||
            return dir === Meta.MotionDirection.RIGHT ? 1 : -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get progress() {
 | 
			
		||||
        return this._progress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set progress(progress) {
 | 
			
		||||
        this._progress = progress;
 | 
			
		||||
 | 
			
		||||
        let direction = this.directionForProgress(progress);
 | 
			
		||||
 | 
			
		||||
        for (let monitorData of this._monitors) {
 | 
			
		||||
            let xPos = 0;
 | 
			
		||||
            let yPos = 0;
 | 
			
		||||
 | 
			
		||||
            if (global.workspace_manager.layout_rows === -1)
 | 
			
		||||
                yPos = -Math.round(progress * this._getDistance(monitorData, direction));
 | 
			
		||||
            else if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
 | 
			
		||||
                xPos = Math.round(progress * this._getDistance(monitorData, direction));
 | 
			
		||||
            else
 | 
			
		||||
                xPos = -Math.round(progress * this._getDistance(monitorData, direction));
 | 
			
		||||
 | 
			
		||||
            monitorData.container.set_position(xPos, yPos);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _getDistance(monitorData, direction) {
 | 
			
		||||
        let info = monitorData.surroundings[direction];
 | 
			
		||||
        if (!info)
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        switch (direction) {
 | 
			
		||||
        case Meta.MotionDirection.UP:
 | 
			
		||||
            return -info.yDest;
 | 
			
		||||
        case Meta.MotionDirection.DOWN:
 | 
			
		||||
            return info.yDest;
 | 
			
		||||
        case Meta.MotionDirection.LEFT:
 | 
			
		||||
            return -info.xDest;
 | 
			
		||||
        case Meta.MotionDirection.RIGHT:
 | 
			
		||||
            return info.xDest;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getProgressRange(monitor) {
 | 
			
		||||
        let monitorData = null;
 | 
			
		||||
        for (let data of this._monitors) {
 | 
			
		||||
            if (data.index === monitor) {
 | 
			
		||||
                monitorData = data;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!monitorData)
 | 
			
		||||
            return 0;
 | 
			
		||||
 | 
			
		||||
        let baseDistance;
 | 
			
		||||
        if (global.workspace_manager.layout_rows !== -1)
 | 
			
		||||
            baseDistance = Main.layoutManager.monitors[monitor].width;
 | 
			
		||||
        else
 | 
			
		||||
            baseDistance = Main.layoutManager.monitors[monitor].height;
 | 
			
		||||
 | 
			
		||||
        let direction = this.directionForProgress(-1);
 | 
			
		||||
        let distance = this._getDistance(monitorData, direction);
 | 
			
		||||
        let lower = -distance / baseDistance;
 | 
			
		||||
 | 
			
		||||
        direction = this.directionForProgress(1);
 | 
			
		||||
        distance = this._getDistance(monitorData, direction);
 | 
			
		||||
        let upper = distance / baseDistance;
 | 
			
		||||
 | 
			
		||||
        return [lower, upper];
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var WorkspaceAnimationController = class {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this._blockAnimations = false;
 | 
			
		||||
        this._movingWindow = null;
 | 
			
		||||
        this._inProgress = false;
 | 
			
		||||
        this._gestureActivated = false;
 | 
			
		||||
        this._animation = null;
 | 
			
		||||
 | 
			
		||||
        Main.overview.connect('showing', () => {
 | 
			
		||||
            if (this._gestureActivated)
 | 
			
		||||
                this._switchWorkspaceStop();
 | 
			
		||||
 | 
			
		||||
            this._swipeTracker.enabled = false;
 | 
			
		||||
        });
 | 
			
		||||
        Main.overview.connect('hiding', () => {
 | 
			
		||||
            this._swipeTracker.enabled = true;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        let swipeTracker = new SwipeTracker.SwipeTracker(global.stage,
 | 
			
		||||
            Shell.ActionMode.NORMAL, { allowDrag: false, allowScroll: false });
 | 
			
		||||
        swipeTracker.connect('begin', this._switchWorkspaceBegin.bind(this));
 | 
			
		||||
        swipeTracker.connect('update', this._switchWorkspaceUpdate.bind(this));
 | 
			
		||||
        swipeTracker.connect('end', this._switchWorkspaceEnd.bind(this));
 | 
			
		||||
        this._swipeTracker = swipeTracker;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _prepareWorkspaceSwitch(from, to, direction) {
 | 
			
		||||
        if (this._animation)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        this._animation = new WorkspaceAnimation(this, from, to, direction);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _finishWorkspaceSwitch() {
 | 
			
		||||
        if (this._animation)
 | 
			
		||||
            this._animation.destroy();
 | 
			
		||||
        this._animation = null;
 | 
			
		||||
        this._inProgress = false;
 | 
			
		||||
        this._gestureActivated = false;
 | 
			
		||||
        this.movingWindow = null;
 | 
			
		||||
        this._monitor = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    animateSwitchWorkspace(from, to, direction, onComplete) {
 | 
			
		||||
        this._prepareWorkspaceSwitch(from, to, direction);
 | 
			
		||||
        this._inProgress = true;
 | 
			
		||||
 | 
			
		||||
        let progress = this._animation.progressForDirection(direction);
 | 
			
		||||
 | 
			
		||||
        this._animation.ease_property('progress', progress, {
 | 
			
		||||
            duration: WINDOW_ANIMATION_TIME,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
 | 
			
		||||
            onComplete: () => {
 | 
			
		||||
                this._finishWorkspaceSwitch();
 | 
			
		||||
                onComplete();
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceBegin(tracker, monitor) {
 | 
			
		||||
        if (Meta.prefs_get_workspaces_only_on_primary() &&
 | 
			
		||||
            monitor !== Main.layoutManager.primaryIndex)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let horiz = workspaceManager.layout_rows !== -1;
 | 
			
		||||
        tracker.orientation = horiz
 | 
			
		||||
            ? Clutter.Orientation.HORIZONTAL
 | 
			
		||||
            : Clutter.Orientation.VERTICAL;
 | 
			
		||||
 | 
			
		||||
        let activeWorkspace = workspaceManager.get_active_workspace();
 | 
			
		||||
 | 
			
		||||
        let baseDistance;
 | 
			
		||||
        if (horiz)
 | 
			
		||||
            baseDistance = Main.layoutManager.monitors[monitor].width;
 | 
			
		||||
        else
 | 
			
		||||
            baseDistance = Main.layoutManager.monitors[monitor].height;
 | 
			
		||||
 | 
			
		||||
        let progress;
 | 
			
		||||
        if (this._gestureActivated) {
 | 
			
		||||
            this._animation.remove_all_transitions();
 | 
			
		||||
            progress = this._animation.progress;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
 | 
			
		||||
            progress = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._monitor = monitor;
 | 
			
		||||
        let [lower, upper] = this._animation.getProgressRange(monitor);
 | 
			
		||||
        if (progress < 0)
 | 
			
		||||
            progress *= -lower;
 | 
			
		||||
        else if (progress > 0)
 | 
			
		||||
            progress *= upper;
 | 
			
		||||
 | 
			
		||||
        let points = [];
 | 
			
		||||
        if (lower !== 0)
 | 
			
		||||
            points.push(lower);
 | 
			
		||||
 | 
			
		||||
        points.push(0);
 | 
			
		||||
 | 
			
		||||
        if (upper !== 0)
 | 
			
		||||
            points.push(upper);
 | 
			
		||||
 | 
			
		||||
        tracker.confirmSwipe(baseDistance, points, progress, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceUpdate(tracker, progress) {
 | 
			
		||||
        // Translate the progress into [-1;1] range
 | 
			
		||||
        let [lower, upper] = this._animation.getProgressRange(this._monitor);
 | 
			
		||||
        if (progress < 0)
 | 
			
		||||
            progress /= -lower;
 | 
			
		||||
        else if (progress > 0)
 | 
			
		||||
            progress /= upper;
 | 
			
		||||
 | 
			
		||||
        this._animation.progress = progress;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceEnd(tracker, duration, endProgress) {
 | 
			
		||||
        if (!this._animation)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        // Translate the progress into [-1;1] range
 | 
			
		||||
        endProgress = Math.sign(endProgress);
 | 
			
		||||
 | 
			
		||||
        let workspaceManager = global.workspace_manager;
 | 
			
		||||
        let activeWorkspace = workspaceManager.get_active_workspace();
 | 
			
		||||
        let newWs = activeWorkspace;
 | 
			
		||||
        if (endProgress !== 0) {
 | 
			
		||||
            let direction = this._animation.directionForProgress(endProgress);
 | 
			
		||||
            newWs = activeWorkspace.get_neighbor(direction);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._gestureActivated = true;
 | 
			
		||||
 | 
			
		||||
        this._animation.ease_property('progress', endProgress, {
 | 
			
		||||
            duration,
 | 
			
		||||
            mode: Clutter.AnimationMode.EASE_OUT_CUBIC,
 | 
			
		||||
            onComplete: () => {
 | 
			
		||||
                if (newWs !== activeWorkspace)
 | 
			
		||||
                    newWs.activate(global.get_current_time());
 | 
			
		||||
                this._finishWorkspaceSwitch();
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _switchWorkspaceStop() {
 | 
			
		||||
        this._animation.progress = 0;
 | 
			
		||||
        this._finishWorkspaceSwitch();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isAnimating() {
 | 
			
		||||
        return this._animation !== null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    canCancelGesture() {
 | 
			
		||||
        return this.isAnimating() && this._gestureActivated;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set movingWindow(movingWindow) {
 | 
			
		||||
        this._movingWindow = movingWindow;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get movingWindow() {
 | 
			
		||||
        return this._movingWindow;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user