From 291a94173c5ea022f75b4eee07e6e0c97a04ff7a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 14 Apr 2024 08:06:59 +0200 Subject: Adding 45/vertical-workspaces version 37+20240412 [9b05a79]. Signed-off-by: Daniel Baumann --- .../45/vertical-workspaces/lib/windowManager.js | 169 +++++++++++++++++++-- 1 file changed, 156 insertions(+), 13 deletions(-) (limited to 'extensions/45/vertical-workspaces/lib/windowManager.js') diff --git a/extensions/45/vertical-workspaces/lib/windowManager.js b/extensions/45/vertical-workspaces/lib/windowManager.js index dd467cb..a6f9b09 100644 --- a/extensions/45/vertical-workspaces/lib/windowManager.js +++ b/extensions/45/vertical-workspaces/lib/windowManager.js @@ -3,7 +3,7 @@ * windowManager.js * * @author GdH - * @copyright 2022 - 2023 + * @copyright 2022 - 2024 * @license GPL-3.0 * */ @@ -16,6 +16,10 @@ import GObject from 'gi://GObject'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as WindowManager from 'resource:///org/gnome/shell/ui/windowManager.js'; +import * as WorkspaceAnimation from 'resource:///org/gnome/shell/ui/workspaceAnimation.js'; + +const MINIMIZE_WINDOW_ANIMATION_TIME = 400; // windowManager.MINIMIZE_WINDOW_ANIMATION_TIME +const MINIMIZE_WINDOW_ANIMATION_MODE = Clutter.AnimationMode.EASE_OUT_EXPO; // WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE let Me; let opt; @@ -62,6 +66,8 @@ export const WindowManagerModule = class { this._overrides = new Me.Util.Overrides(); this._overrides.addOverride('WindowManager', WindowManager.WindowManager.prototype, WindowManagerCommon); + if (opt.WS_SWITCHER_CURRENT_MONITOR) + this._overrides.addOverride('WorkspaceAnimationController', WorkspaceAnimation.WorkspaceAnimationController.prototype, WorkspaceAnimationController); if (!this._minimizeSigId) { this._originalMinimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'minimize' }); @@ -106,11 +112,108 @@ export const WindowManagerModule = class { } }; -// fix for mainstream bug - fullscreen windows should minimize using opacity transition -// but its being applied directly on window actor and that doesn't work -// anyway, animation is better, even if the Activities button is not visible... -// and also add support for bottom position of the panel const WindowManagerCommon = { + actionMoveWorkspace(workspace) { + if (!Main.sessionMode.hasWorkspaces) + return; + + if (opt.WS_SWITCHER_CURRENT_MONITOR) + this._switchWorkspaceCurrentMonitor(workspace); + else if (!workspace.active) + workspace.activate(global.get_current_time()); + }, + + actionMoveWindow(window, workspace) { + if (!Main.sessionMode.hasWorkspaces) + return; + + if (!workspace.active) { + // This won't have any effect for "always sticky" windows + // (like desktop windows or docks) + + this._workspaceAnimation.movingWindow = window; + window.change_workspace(workspace); + + global.display.clear_mouse_mode(); + + if (opt.SWITCH_ONLY_CURRENT_MONITOR_WS) { + this._switchWorkspaceCurrentMonitor(workspace, window.get_monitor()); + window.activate(global.get_current_time()); + } else { + workspace.activate_with_focus(window, global.get_current_time()); + } + } + }, + + _switchWorkspaceCurrentMonitor(workspace, monitor) { + // const focusedWindow = global.display.get_focus_window(); + // const currentMonitor = focusedWindow ? focusedWindow.get_monitor() : global.display.get_current_monitor(); + // using focused window to determine the current monitor can lead to inconsistent behavior and switching monitors between switches + // depending on which window takes focus on each workspace + // mouse pointer is more stable and predictable source + const currentMonitor = monitor ? monitor : global.display.get_current_monitor(); + const primaryMonitor = currentMonitor === Main.layoutManager.primaryIndex; + const nMonitors = Main.layoutManager.monitors.length; + const lastIndexCorrection = Meta.prefs_get_dynamic_workspaces() ? 2 : 1; + const lastIndex = global.workspaceManager.get_n_workspaces() - lastIndexCorrection; + const targetWsIndex = workspace.index(); + const activeWs = global.workspaceManager.get_active_workspace(); + const activeWsIndex = activeWs.index(); + const diff = activeWsIndex - targetWsIndex; + + let direction = diff > 0 ? Meta.MotionDirection.UP : Meta.MotionDirection.DOWN; + if (diff === 0) { + // no actual ws to switch, but secondary monitors are always in wraparound mode so we need to get direction + direction = activeWsIndex >= lastIndex ? Meta.MotionDirection.DOWN : Meta.MotionDirection.UP; + } + if (Math.abs(diff) > 1) { + // workspace is probably in wraparound mode and just wrapped so so we need to translate direction + direction = diff > 0 ? Meta.MotionDirection.DOWN : Meta.MotionDirection.UP; + } + + if (!primaryMonitor) { + this._rotateWorkspaces(direction, currentMonitor); + return; + } + + // avoid ws rotations if the last empty dynamic workspace is involved, but allow to rotate from the last to the first, if wraparound is enabled + if (workspace !== activeWs && !((targetWsIndex > lastIndex && direction === Meta.MotionDirection.DOWN) || (activeWsIndex > lastIndex && targetWsIndex >= lastIndex))) { + for (let i = 0; i < nMonitors; i++) { + if (i !== currentMonitor) { + const oppositeDirection = direction === Meta.MotionDirection.UP ? Meta.MotionDirection.DOWN : Meta.MotionDirection.UP; + this._rotateWorkspaces(oppositeDirection, i); + } + } + } + workspace.activate(global.get_current_time()); + }, + + _rotateWorkspaces(direction = 0, monitorIndex = -1, step = 1) { + step = direction === Meta.MotionDirection.UP ? Number(step) : -step; + const monitor = monitorIndex > -1 ? monitorIndex : global.display.get_current_monitor(); + // don't move windows to the last empty workspace if dynamic workspaces are enabled + const lastIndexCorrection = Meta.prefs_get_dynamic_workspaces() ? 2 : 1; + const lastIndex = global.workspaceManager.get_n_workspaces() - lastIndexCorrection; + let windows = Me.Util.getWindows(null); + for (let win of windows.reverse()) { + // avoid moving modal windows as they move with their parents (and vice versa) immediately, before we move the parent window. + if (win.get_monitor() === monitor && !win.is_always_on_all_workspaces() && !win.is_attached_dialog() && !win.get_transient_for()) { + let wWs = win.get_workspace().index(); + wWs += step; + if (wWs < 0) + wWs = lastIndex; + if (wWs > lastIndex) + wWs = 0; + const ws = global.workspaceManager.get_workspace_by_index(wWs); + win.change_workspace(ws); + } + } + }, + + // fix for mainstream bug - fullscreen windows should minimize using opacity transition + // but its being applied directly on window actor and that doesn't work + // anyway, animation is better, even if the Activities button is not visible... + // and also add support for bottom position of the panel _minimizeWindow(shellwm, actor) { const types = [ Meta.WindowType.NORMAL, @@ -129,8 +232,8 @@ const WindowManagerCommon = { /* if (actor.meta_window.is_monitor_sized()) { actor.get_first_child().ease({ opacity: 0, - duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME, - mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE, + duration: MINIMIZE_WINDOW_ANIMATION_TIME, + mode: MINIMIZE_WINDOW_ANIMATION_MODE, onStopped: () => this._minimizeWindowDone(shellwm, actor), }); } else { */ @@ -160,8 +263,8 @@ const WindowManagerCommon = { scale_y: yScale, x: xDest, y: yDest, - duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME, - mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE, + duration: MINIMIZE_WINDOW_ANIMATION_TIME, + mode: MINIMIZE_WINDOW_ANIMATION_MODE, onStopped: () => this._minimizeWindowDone(shellwm, actor), }); // } @@ -196,8 +299,8 @@ const WindowManagerCommon = { actor.set_scale(1.0, 1.0); actor.ease({ opacity: 255, - duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME, - mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE, + duration: MINIMIZE_WINDOW_ANIMATION_TIME, + mode: MINIMIZE_WINDOW_ANIMATION_MODE, onStopped: () => this._unminimizeWindowDone(shellwm, actor), }); } else { */ @@ -228,10 +331,50 @@ const WindowManagerCommon = { scale_y: 1, x: xDest, y: yDest, - duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME, - mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE, + duration: MINIMIZE_WINDOW_ANIMATION_TIME, + mode: MINIMIZE_WINDOW_ANIMATION_MODE, onStopped: () => this._unminimizeWindowDone(shellwm, actor), }); // } }, }; + +const WorkspaceAnimationController = { + _prepareWorkspaceSwitch(workspaceIndices) { + if (this._switchData) + return; + + const workspaceManager = global.workspace_manager; + const nWorkspaces = workspaceManager.get_n_workspaces(); + + const switchData = {}; + + this._switchData = switchData; + switchData.monitors = []; + + switchData.gestureActivated = false; + switchData.inProgress = false; + + if (!workspaceIndices) + workspaceIndices = [...Array(nWorkspaces).keys()]; + + let monitors = opt.WS_SWITCHER_CURRENT_MONITOR + ? [Main.layoutManager.currentMonitor] : Main.layoutManager.monitors; + monitors = Meta.prefs_get_workspaces_only_on_primary() + ? [Main.layoutManager.primaryMonitor] : monitors; + + for (const monitor of monitors) { + if (Meta.prefs_get_workspaces_only_on_primary() && + monitor.index !== Main.layoutManager.primaryIndex) + continue; + + const group = new WorkspaceAnimation.MonitorGroup(monitor, workspaceIndices, this.movingWindow); + + Main.uiGroup.insert_child_above(group, global.window_group); + + switchData.monitors.push(group); + } + + Meta.disable_unredirect_for_display(global.display); + }, +}; -- cgit v1.2.3