From 4d8b071804d73b7a733f2b7696fde40caf8800bb Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 8 Apr 2024 18:02:53 +0200 Subject: Updating 44/vertical-workspaces to version 37+20231208 [0d82192]. Signed-off-by: Daniel Baumann --- extensions/44/vertical-workspaces/extension.js | 1215 +++++++++++++----------- 1 file changed, 672 insertions(+), 543 deletions(-) (limited to 'extensions/44/vertical-workspaces/extension.js') diff --git a/extensions/44/vertical-workspaces/extension.js b/extensions/44/vertical-workspaces/extension.js index 0a22994..911d7dd 100644 --- a/extensions/44/vertical-workspaces/extension.js +++ b/extensions/44/vertical-workspaces/extension.js @@ -10,655 +10,784 @@ 'use strict'; -const { GLib, Shell, St } = imports.gi; +const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; +const Meta = imports.gi.Meta; +const St = imports.gi.St; const Main = imports.ui.main; - -const Util = imports.misc.util; -const Background = imports.ui.background; +const Search = imports.ui.search; +const Workspace = imports.ui.workspace; const ExtensionUtils = imports.misc.extensionUtils; -const Me = ExtensionUtils.getCurrentExtension(); -const Settings = Me.imports.lib.settings; -const _Util = Me.imports.lib.util; - -const WindowSearchProvider = Me.imports.lib.windowSearchProvider; -const RecentFilesSearchProvider = Me.imports.lib.recentFilesSearchProvider; -const LayoutOverride = Me.imports.lib.layout; -const AppDisplayOverride = Me.imports.lib.appDisplay; -const WorkspaceThumbnailOverride = Me.imports.lib.workspaceThumbnail; -const WorkspaceOverride = Me.imports.lib.workspace; -const WorkspacesViewOverride = Me.imports.lib.workspacesView; -const WindowPreviewOverride = Me.imports.lib.windowPreview; -const IconGridOverride = Me.imports.lib.iconGrid; -const WorkspaceAnimationOverride = Me.imports.lib.workspaceAnimation; -const WindowManagerOverride = Me.imports.lib.windowManager; -const OverviewOverride = Me.imports.lib.overview; -const OverviewControlsOverride = Me.imports.lib.overviewControls; -const SwipeTrackerOverride = Me.imports.lib.swipeTracker; -const WorkspaceSwitcherPopupOverride = Me.imports.lib.workspaceSwitcherPopup; -const SearchOverride = Me.imports.lib.search; -const PanelOverride = Me.imports.lib.panel; -const DashOverride = Me.imports.lib.dash; -const WindowAttentionHandlerOverride = Me.imports.lib.windowAttentionHandler; -const AppFavoritesOverride = Me.imports.lib.appFavorites; -const MessageTrayOverride = Me.imports.lib.messageTray; -const OsdWindowOverride = Me.imports.lib.osdWindow; -const OverlayKey = Me.imports.lib.overlayKey; +const MyExtension = ExtensionUtils.getCurrentExtension(); +let Me; +// gettext +let _; let opt; -let _bgManagers; - -let _enabled; -let _resetExtensionIfEnabled; -let _prevDash; - -let _showingOverviewConId; -let _monitorsChangedSigId; -let _loadingProfileTimeoutId; -let _watchDockSigId; - -let _resetTimeoutId; - -let _enableTimeoutId = 0; -let _sessionLockActive = false; - - function init() { ExtensionUtils.initTranslations(); + return new Extension(); } -function enable() { - // globally readable flag for other extensions - global.verticalWorkspacesEnabled = true; - - _enableTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - 400, - () => { - activateVShell(); - // unlock after modules update to avoid unnecessary appGrid rebuild - _sessionLockActive = Main.sessionMode.isLocked; - log(`${Me.metadata.name}: enabled`); - _enableTimeoutId = 0; - return GLib.SOURCE_REMOVE; - } - ); -} +class Extension { + _init() { + Me = {}; -function disable() { - _sessionLockActive = Main.sessionMode.isLocked; - if (_enableTimeoutId) { - GLib.source_remove(_enableTimeoutId); - _enableTimeoutId = 0; - } else { - resetVShell(); - } + Me.shellVersion = parseFloat(imports.misc.config.PACKAGE_VERSION); + Me.imports = MyExtension.imports; + Me.metadata = MyExtension.metadata; + Me.gSettings = ExtensionUtils.getSettings(Me.metadata['settings-schema']); + Me.Settings = MyExtension.imports.lib.settings; + Me.gettext = imports.gettext.domain(Me.metadata['gettext-domain']).gettext; + Me.Util = MyExtension.imports.lib.util; - global.verticalWorkspacesEnabled = undefined; - log(`${Me.metadata.name}: ${_sessionLockActive ? 'suspended' : 'disabled'}`); -} + Me.Modules = this._importModules(); + Me.moduleList = this._getModuleList(); -// ------------------------------------------------------------------------------------------ + Me.WSP_PREFIX = Me.Modules.windowSearchProviderModule._PREFIX; + Me.RFSP_PREFIX = Me.Modules.recentFilesSearchProviderModule._PREFIX; + Me.ESP_PREFIX = Me.Modules.extensionsSearchProviderModule._PREFIX; -function activateVShell() { - _enabled = true; + Me.opt = new Me.Settings.Options(Me); + _ = Me.gettext; + opt = Me.opt; - _bgManagers = []; + Me.Util.init(Me); - Settings.opt = new Settings.Options(); - opt = Settings.opt; + Me.moduleList.forEach(module => { + Me.Modules[module] = new Me.Modules[module](Me); + }); - _updateSettings(); + Me.repairOverrides = this._repairOverrides; + } - opt.connect('changed', _updateSettings); + _importModules() { + return { + appDisplayModule: Me.imports.lib.appDisplay.AppDisplayModule, + appFavoritesModule: Me.imports.lib.appFavorites.AppFavoritesModule, + dashModule: Me.imports.lib.dash.DashModule, + iconGridModule: Me.imports.lib.iconGrid.IconGridModule, + layoutModule: Me.imports.lib.layout.LayoutModule, + messageTrayModule: Me.imports.lib.messageTray.MessageTrayModule, + osdWindowModule: Me.imports.lib.osdWindow.OsdWindowModule, + overviewModule: Me.imports.lib.overview.OverviewModule, + overlayKeyModule: Me.imports.lib.overlayKey.OverlayKeyModule, + overviewControlsModule: Me.imports.lib.overviewControls.OverviewControlsModule, + panelModule: Me.imports.lib.panel.PanelModule, + searchModule: Me.imports.lib.search.SearchModule, + searchControllerModule: Me.imports.lib.searchController.SearchControllerModule, + swipeTrackerModule: Me.imports.lib.swipeTracker.SwipeTrackerModule, + windowAttentionHandlerModule: Me.imports.lib.windowAttentionHandler.WindowAttentionHandlerModule, + windowManagerModule: Me.imports.lib.windowManager.WindowManagerModule, + windowPreviewModule: Me.imports.lib.windowPreview.WindowPreviewModule, + workspaceAnimationModule: Me.imports.lib.workspaceAnimation.WorkspaceAnimationModule, + workspaceModule: Me.imports.lib.workspace.WorkspaceModule, + workspaceSwitcherPopupModule: Me.imports.lib.workspaceSwitcherPopup.WorkspaceSwitcherPopupModule, + workspaceThumbnailModule: Me.imports.lib.workspaceThumbnail.WorkspaceThumbnailModule, + workspacesViewModule: Me.imports.lib.workspacesView.WorkspacesViewModule, + windowSearchProviderModule: Me.imports.lib.windowSearchProvider.WindowSearchProviderModule, + winTmbModule: Me.imports.lib.winTmb.WinTmbModule, + recentFilesSearchProviderModule: Me.imports.lib.recentFilesSearchProvider.RecentFilesSearchProviderModule, + extensionsSearchProviderModule: Me.imports.lib.extensionsSearchProvider.ExtensionsSearchProviderModule, + }; + } - _updateOverrides(); + _getModuleList() { + return Object.keys(Me.Modules); + } - _prevDash = {}; - const dash = Main.overview.dash; - _prevDash.dash = dash; - _prevDash.position = dash.position; + _cleanGlobals() { + Me = null; + opt = null; + _ = null; + } - _monitorsChangedSigId = Main.layoutManager.connect('monitors-changed', () => _resetExtension(2000)); + enable() { + this._init(); + // flag for Util.getEnabledExtensions() + Me.extensionsLoadIncomplete = Main.layoutManager._startingUp; - // static bg animations conflict with startup animation - // enable it on first hiding from the overview and disconnect the signal - _showingOverviewConId = Main.overview.connect('showing', _onShowingOverview); + this._activateVShell(); + Me.extensionsLoadIncomplete = false; + console.debug(`${Me.metadata.name}: enabled`); + } - // switch PageUp/PageDown workspace switcher shortcuts - _switchPageShortcuts(); - _setStaticBackground(); + // Reason for using "unlock-dialog" session mode: + // Updating the "appDisplay" content every time the screen is locked/unlocked takes quite a lot of time and affects the user experience. + disable() { + this._removeVShell(); + this._disposeModules(); - // fix for upstream bug - overview always shows workspace 1 instead of the active one after restart - Main.overview._overview.controls._workspaceAdjustment.set_value(global.workspace_manager.get_active_workspace_index()); + // If Dash to Dock is enabled, disabling V-Shell can end in broken overview + Main.overview.hide(); - // if Dash to Dock detected force enable "Fix for DtD" option - if (_Util.dashIsDashToDock()) { - opt.set('fixUbuntuDock', true); - _fixUbuntuDock(true); - } else { - _fixUbuntuDock(opt.get('fixUbuntuDock')); - } -} + console.debug(`${Me.metadata.name}: disabled`); -function resetVShell() { - _enabled = 0; + this._cleanGlobals(); + } - _fixUbuntuDock(false); + _disposeModules() { + Me.opt.destroy(); + Me.opt = null; - const reset = true; - _updateOverrides(reset); + for (let module of Me.moduleList) { + if (!Me.Modules[module].moduleEnabled) + Me.Modules[module].cleanGlobals(); + } - if (_monitorsChangedSigId) { - Main.layoutManager.disconnect(_monitorsChangedSigId); - _monitorsChangedSigId = 0; + Me.Util.cleanGlobals(); + Me.Modules = null; } - _prevDash = null; + _activateVShell() { + this._enabled = true; - // switch PageUp/PageDown workspace switcher shortcuts - _switchPageShortcuts(); + this._originalGetNeighbor = Meta.Workspace.prototype.get_neighbor; - _setStaticBackground(reset); + this._removeTimeouts(); + this._timeouts = {}; - // remove any position offsets from dash and ws thumbnails - if (!_Util.dashNotDefault()) { - Main.overview.dash.translation_x = 0; - Main.overview.dash.translation_y = 0; - } - Main.overview._overview._controls._thumbnailsBox.translation_x = 0; - Main.overview._overview._controls._thumbnailsBox.translation_y = 0; - Main.overview._overview._controls._searchEntryBin.translation_y = 0; + // load VShell configuration + this._updateSettings(); - Main.overview._overview._controls.set_child_above_sibling(Main.overview._overview._controls._workspacesDisplay, null); + // activate all enabled VShell modules + this._updateOverrides(); - if (_showingOverviewConId) { - Main.overview.disconnect(_showingOverviewConId); - _showingOverviewConId = 0; - } + // connect signals to help VShell adapt to changes in DE configuration + this._updateConnections(); - if (_loadingProfileTimeoutId) { - GLib.source_remove(_loadingProfileTimeoutId); - _loadingProfileTimeoutId = 0; - } + // switch PageUp/PageDown workspace switcher shortcuts + this._switchPageShortcuts(); - St.Settings.get().slow_down_factor = 1; + // if Dash to Dock detected force enable "Fix for DtD" option + this._updateFixDashToDockOption(); - Main.overview.dash._background.set_style(''); + // update overview background wallpaper if enabled, but don't set it too early on session startup + // because it crashes wayland + if (!Main.layoutManager._startingUp || Meta.is_restart()) + Main.overview._overview.controls._setBackground(); - opt.destroy(); - opt = null; -} + this._updateSettingsConnection(); -function _updateOverrides(reset = false) { - WorkspacesViewOverride.update(reset); - WorkspaceThumbnailOverride.update(reset); - OverviewOverride.update(reset); - OverviewControlsOverride.update(reset); + // store dash _workId so we will be able to detect replacement when entering overview + this._storeDashId(); - WorkspaceOverride.update(reset); - WindowPreviewOverride.update(reset); - WindowManagerOverride.update(reset); + // workaround for upstream bug - overview always shows workspace 1 instead of the active one after restart + this._setInitialWsIndex(); + } - LayoutOverride.update(reset); - DashOverride.update(reset); - PanelOverride.update(reset); + _removeVShell() { + this._enabled = false; - WorkspaceAnimationOverride.update(reset); - WorkspaceSwitcherPopupOverride.update(reset); + const reset = true; + this._removeTimeouts(); - SwipeTrackerOverride.update(reset); + this._removeConnections(); + Main.overview._overview.controls._setBackground(reset); - SearchOverride.update(reset); - WindowSearchProvider.update(reset); - RecentFilesSearchProvider.update(reset); + // remove changes mede by VShell modules + this._updateOverrides(reset); - // don't rebuild app grid on every screen lock - if (!_sessionLockActive) { - // IconGrid needs to be patched before AppDisplay - IconGridOverride.update(reset); - AppDisplayOverride.update(reset); - } + // switch PageUp/PageDown workspace switcher shortcuts + this._switchPageShortcuts(); - WindowAttentionHandlerOverride.update(reset); - AppFavoritesOverride.update(reset); - MessageTrayOverride.update(reset); - OsdWindowOverride.update(reset); - OverlayKey.update(reset); -} + // remove any position offsets from dash and ws thumbnails + if (!Me.Util.dashNotDefault()) { + Main.overview.dash.translation_x = 0; + Main.overview.dash.translation_y = 0; + } + Main.overview._overview._controls._thumbnailsBox.translation_x = 0; + Main.overview._overview._controls._thumbnailsBox.translation_y = 0; + Main.overview._overview._controls._searchEntryBin.translation_y = 0; + Main.overview._overview._controls.set_child_above_sibling(Main.overview._overview._controls._workspacesDisplay, null); + // restore default animation speed + St.Settings.get().slow_down_factor = 1; + + // restore default dash background style + Main.overview.dash._background.set_style(''); + // hide status message if shown + this._showStatusMessage(false); + this._prevDash = null; + + Meta.Workspace.prototype.get_neighbor = this._originalGetNeighbor; + } -function _onShowingOverview() { - // store pointer X coordinate for OVERVIEW_MODE 1 window spread - if mouse pointer is steady, don't spread - opt.showingPointerX = global.get_pointer()[0]; + _removeTimeouts() { + if (this._timeouts) { + Object.values(this._timeouts).forEach(id => { + if (id) + GLib.source_remove(id); + }); + } + this._timeouts = null; + } - if (opt.FIX_UBUNTU_DOCK) { - // workaround for Ubuntu Dock breaking overview allocations after changing position + _storeDashId() { const dash = Main.overview.dash; - if (_prevDash.dash !== dash || _prevDash.position !== dash._position) - _resetExtensionIfEnabled(0); + this._prevDash = dash._workId; } -} - -function _resetExtension(timeout = 200) { - if (_resetTimeoutId) - GLib.source_remove(_resetTimeoutId); - _resetTimeoutId = GLib.timeout_add( - GLib.PRIORITY_DEFAULT, - timeout, - () => { - if (!_enabled) - return GLib.SOURCE_REMOVE; - const dash = Main.overview.dash; - if (!timeout && _prevDash.dash && dash !== _prevDash.dash) { // !timeout means DtD workaround callback - _prevDash.dash = dash; - log(`[${Me.metadata.name}]: Dash has been replaced, resetting extension...`); - resetVShell(); - activateVShell(); - } else if (timeout) { - log(`[${Me.metadata.name}]: resetting extension...`); - resetVShell(); - activateVShell(); - } - _resetTimeoutId = 0; - return GLib.SOURCE_REMOVE; + _setInitialWsIndex() { + if (Main.layoutManager._startingUp) { + GLib.idle_add(GLib.PRIORITY_LOW, () => { + Main.overview._overview.controls._workspaceAdjustment.set_value(global.workspace_manager.get_active_workspace_index()); + }); } - ); -} - -function _fixUbuntuDock(activate = true) { - // Workaround for Ubuntu Dock breaking overview allocations after changing monitor configuration and deactivating dock - if (_watchDockSigId) { - global.settings.disconnect(_watchDockSigId); - _watchDockSigId = 0; } - if (_resetTimeoutId) { - GLib.source_remove(_resetTimeoutId); - _resetTimeoutId = 0; + _updateSettingsConnection() { + if (!opt._extensionUpdateId) + opt._extensionUpdateId = opt.connect('changed', this._updateSettings.bind(this)); } - _resetExtensionIfEnabled = () => {}; + _updateFixDashToDockOption() { + const dtdEnabled = !!(Me.Util.getEnabledExtensions('dash-to-dock').length || + Me.Util.getEnabledExtensions('ubuntu-dock').length); - if (!activate) - return; + // force enable Fix Dash to Dock option if DtD detected + opt._watchDashToDock = dtdEnabled; + // opt.set('fixUbuntuDock', dtdEnabled); + } - _watchDockSigId = global.settings.connect('changed::enabled-extensions', () => _resetExtension()); - _resetExtensionIfEnabled = _resetExtension; -} + _updateConnections() { + if (!this._monitorsChangedConId) + this._monitorsChangedConId = Main.layoutManager.connect('monitors-changed', () => this._updateVShell(2000)); + + + if (!this._showingOverviewConId) + this._showingOverviewConId = Main.overview.connect('showing', this._onShowingOverview.bind(this)); + + if (!this._sessionModeConId) { + // the panel must be visible when screen is locked + this._sessionModeConId = Main.sessionMode.connect('updated', session => { + if (session.currentMode === 'user' || session.parentMode === 'user') { + this._timeouts.unlock = GLib.idle_add(GLib.PRIORITY_LOW, + () => { + Me.Modules.panelModule.update(); + Me.Modules.overviewControlsModule.update(); + Me.Modules.winTmbModule.showThumbnails(); + + this._timeouts.unlock = 0; + return GLib.SOURCE_REMOVE; + } + ); + } else if (session.currentMode === 'unlock-dialog') { + Me.Modules.panelModule.update(true); + Me.Modules.winTmbModule.hideThumbnails(); + } + }); + } -function _updateSettings(settings, key) { - if (key?.includes('profile-data')) { - const index = key.replace('profile-data-', ''); - Main.notify(`${Me.metadata.name}`, `Profile ${index} has been saved`); - } - // avoid overload while loading profile - update only once - // delayed gsettings writes are processed alphabetically - if (key === 'aaa-loading-profile') { - Main.notify(`${Me.metadata.name}`, 'Profile has been loaded'); - if (_loadingProfileTimeoutId) - GLib.source_remove(_loadingProfileTimeoutId); - _loadingProfileTimeoutId = GLib.timeout_add(100, 0, () => { - _resetExtension(); - _loadingProfileTimeoutId = 0; - return GLib.SOURCE_REMOVE; - }); - } - if (_loadingProfileTimeoutId) - return; - - opt._updateSettings(); - - opt.WORKSPACE_MIN_SPACING = Main.overview._overview._controls._thumbnailsBox.get_theme_node().get_length('spacing'); - // update variables that cannot be processed within settings - const dash = Main.overview.dash; - if (_Util.dashIsDashToDock()) { - opt.DASH_POSITION = dash._position; - opt.DASH_TOP = opt.DASH_POSITION === 0; - opt.DASH_RIGHT = opt.DASH_POSITION === 1; - opt.DASH_BOTTOM = opt.DASH_POSITION === 2; - opt.DASH_LEFT = opt.DASH_POSITION === 3; - opt.DASH_VERTICAL = opt.DASH_LEFT || opt.DASH_RIGHT; + if (!this._watchDockSigId) { + this._watchDockSigId = Main.extensionManager.connect('extension-state-changed', + (source, extension) => { + const uuid = extension.uuid; + // ExtensionState = { + // ENABLED: 1, + // DISABLED: 2, + // ERROR: 3, + // OUT_OF_DATE: 4, + // DOWNLOADING: 5, + // INITIALIZED: 6, + // DISABLING: 7, + // ENABLING: 8, + // + // // Used as an error state for operations on unknown extensions, + // // should never be in a real extensionMeta object. + // UNINSTALLED: 99, + // }; + // no need to restart on disable/remove + // - if DtD was enabled before VShell, VShell will be rebased by extensionSystem + // - if DtD was enabled after VShell, the first _showingOverview detect replacement of the dash and repair VShell + const reset = [1, 2].includes(extension.state); + const dashReplacement = uuid.includes('dash-to-dock') || uuid.includes('ubuntu-dock') || uuid.includes('dash-to-panel'); + if (dashReplacement && reset) + opt._watchDashToDock = true; + if (!Main.layoutManager._startingUp && reset && dashReplacement) + this._updateVShell(1999); + } + ); + } } - opt.DASH_VISIBLE = opt.DASH_VISIBLE && !_Util.getEnabledExtensions('dash-to-panel@jderose9.github.com').length; + _removeConnections() { + if (this._monitorsChangedConId) { + Main.layoutManager.disconnect(this._monitorsChangedConId); + this._monitorsChangedConId = 0; + } + + if (this._showingOverviewConId) { + Main.overview.disconnect(this._showingOverviewConId); + this._showingOverviewConId = 0; + } - opt.MAX_ICON_SIZE = opt.get('dashMaxIconSize', true); - if (opt.MAX_ICON_SIZE < 16) { - opt.MAX_ICON_SIZE = 64; - opt.set('dashMaxIconSize', 64); - } + if (this._sessionModeConId) { + Main.sessionMode.disconnect(this._sessionModeConId); + this._sessionModeConId = 0; + } - const monitorWidth = global.display.get_monitor_geometry(global.display.get_primary_monitor()).width; - if (monitorWidth < 1600) { - opt.APP_GRID_ICON_SIZE_DEFAULT = opt.APP_GRID_ACTIVE_PREVIEW ? 128 : 64; - opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT = 64; + if (this._watchDockSigId) { + Main.extensionManager.disconnect(this._watchDockSigId); + this._watchDockSigId = 0; + } } - imports.ui.workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = opt.OVERVIEW_MODE === 1 ? 0.1 : 0.95; - - if (!_Util.dashIsDashToDock()) { // DtD has its own opacity control - Main.overview.dash._background.opacity = Math.round(opt.get('dashBgOpacity', true) * 2.5); // conversion % to 0-255 - const radius = opt.get('dashBgRadius', true); - if (radius) { - let style; - switch (opt.DASH_POSITION) { - case 1: - style = `border-radius: ${radius}px 0 0 ${radius}px;`; - break; - case 3: - style = `border-radius: 0 ${radius}px ${radius}px 0;`; - break; - default: - style = `border-radius: ${radius}px;`; - } - Main.overview.dash._background.set_style(style); - } else { - Main.overview.dash._background.set_style(''); + _updateOverrides(reset = false) { + Me.Modules.workspacesViewModule.update(reset); + Me.Modules.workspaceThumbnailModule.update(reset); + Me.Modules.overviewModule.update(reset); + Me.Modules.overviewControlsModule.update(reset); + + Me.Modules.workspaceModule.update(reset); + Me.Modules.windowPreviewModule.update(reset); + Me.Modules.windowManagerModule.update(reset); + + Me.Modules.layoutModule.update(reset); + Me.Modules.dashModule.update(reset); + // avoid enabling panel module when session is locked + if (reset || (!reset && !Main.sessionMode.isLocked)) + Me.Modules.panelModule.update(reset); + // the panel must be visible when screen is locked + // at startup time, panel will be updated from the startupAnimation after allocation + if (!reset && Main.sessionMode.isLocked && !Main.layoutManager._startingUp) + Me.Modules.panelModule._showPanel(true); + // PanelModule._showPanel(true); + // hide panel so it appears directly on the final place + /* else if (Main.layoutManager._startingUp && !Meta.is_restart()) + Main.panel.opacity = 0;*/ + + Me.Modules.workspaceAnimationModule.update(reset); + Me.Modules.workspaceSwitcherPopupModule.update(reset); + + Me.Modules.swipeTrackerModule.update(reset); + + Me.Modules.searchModule.update(reset); + + Me.Modules.windowSearchProviderModule.update(reset); + Me.Modules.recentFilesSearchProviderModule.update(reset); + Me.Modules.extensionsSearchProviderModule.update(reset); + + // don't rebuild app grid on any screen lock + // even if the extension includes unlock-screen session mode + // disable/enable is called at least once even on GS44 + // when screen lock is activated for the first time + // because every first disable of each extension rebases + // the entire extensions stack that was enabled later + if (Main.sessionMode.isLocked) + this._sessionLockActive = true; + + // This covers unnecessary enable/disable cycles during first screen lock when extensions are rebased, but is not allowed by the EGO rules + if (!this._sessionLockActive || !Main.extensionManager._getEnabledExtensions().includes(Me.metadata.uuid)) { + // iconGridModule will be updated from appDisplayModule + Me.Modules.appDisplayModule.update(reset); } - } - // adjust search entry style for OM2 - if (opt.OVERVIEW_MODE2) - Main.overview.searchEntry.add_style_class_name('search-entry-om2'); - else - Main.overview.searchEntry.remove_style_class_name('search-entry-om2'); + if (!this._sessionLockActive && !Main.layoutManager._startingUp && opt.APP_GRID_PERFORMANCE) { + // Avoid showing status at startup, can cause freeze + this._showStatusMessage(); + } - Main.overview.searchEntry.visible = opt.SHOW_SEARCH_ENTRY; - St.Settings.get().slow_down_factor = opt.ANIMATION_TIME_FACTOR; - imports.ui.search.MAX_LIST_SEARCH_RESULTS_ROWS = opt.SEARCH_MAX_ROWS; + if (!Main.sessionMode.isLocked) + this._sessionLockActive = false; - opt.START_Y_OFFSET = (opt.get('panelModule', true) && opt.PANEL_OVERVIEW_ONLY && opt.PANEL_POSITION_TOP) || - // better to add unnecessary space than to have a panel overlapping other objects - _Util.getEnabledExtensions('hidetopbar@mathieu.bidon.ca').length - ? Main.panel.height - : 0; + // iconGridModule will be updated from appDisplayModule + // Me.Modules.appDisplayModule.update(reset); - if (settings) - _applySettings(key); -} + Me.Modules.windowAttentionHandlerModule.update(reset); + Me.Modules.appFavoritesModule.update(reset); + Me.Modules.messageTrayModule.update(reset); + Me.Modules.osdWindowModule.update(reset); + Me.Modules.overlayKeyModule.update(reset); + Me.Modules.searchControllerModule.update(reset); + Me.Modules.winTmbModule.update(reset); -function _applySettings(key) { - if (key?.endsWith('-module')) { - _updateOverrides(); - return; + if (!reset && !Main.layoutManager._startingUp) + Main.overview._overview.controls.setInitialTranslations(); } - _setStaticBackground(); - _updateOverviewTranslations(); - _switchPageShortcuts(); + _onShowingOverview() { + if (Main.layoutManager._startingUp) + return; + + Main.overview._overview.controls.opacity = 255; + + // store pointer X coordinate for OVERVIEW_MODE 1 window spread - if mouse pointer is steady, don't spread + opt.showingPointerX = global.get_pointer()[0]; + + if (!Main.overview._overview.controls._bgManagers && (opt.SHOW_BG_IN_OVERVIEW || opt.SHOW_WS_PREVIEW_BG)) + Main.overview._overview.controls._setBackground(); - if (key?.includes('app-grid')) { - AppDisplayOverride.update(); - return; + if (opt._watchDashToDock) { + // workaround for Dash to Dock (Ubuntu Dock) breaking overview allocations after enabled and changed position + // DtD replaces dock and its _workId on every position change + const dash = Main.overview.dash; + if (this._prevDash !== dash._workId) + this._updateVShell(0); + } } - if (key?.includes('panel')) - PanelOverride.update(); - - if (key?.includes('dash') || key?.includes('search') || key?.includes('icon')) - DashOverride.update(); - - if (key?.includes('hot-corner') || key?.includes('dash')) - LayoutOverride.update(); - - switch (key) { - case 'fix-ubuntu-dock': - _fixUbuntuDock(opt.get('fixUbuntuDock', true)); - break; - case 'ws-thumbnails-position': - _updateOverrides(); - break; - case 'workspace-switcher-animation': - WorkspaceAnimationOverride.update(); - break; - case 'search-width-scale': - SearchOverride.update(); - break; - case 'favorites-notify': - AppFavoritesOverride.update(); - break; - case 'window-attention-mode': - WindowAttentionHandlerOverride.update(); - break; - case 'show-ws-preview-bg': - PanelOverride.update(); - break; - case 'notification-position': - MessageTrayOverride.update(); - break; - case 'osd-position': - OsdWindowOverride.update(); - break; - case 'overlay-key': - OverlayKey.update(); + _updateVShell(timeout = 200) { + if (!this._enabled || Main.layoutManager._startingUp) + return; + + if (this._timeouts.reset) + GLib.source_remove(this._timeouts.reset); + this._timeouts.reset = GLib.timeout_add( + GLib.PRIORITY_DEFAULT, + timeout, + () => { + if (!this._enabled) + return GLib.SOURCE_REMOVE; + + const dash = Main.overview.dash; + if (timeout < 2000) { // timeout < 2000 for partial update + this._prevDash = dash._workId; + console.warn(`[${Me.metadata.name}]: Dash has been replaced, updating extension ...`); + Me._resetInProgress = true; + // update only necessary modules if dash has been replaced + this._repairOverrides(); + Me._resetInProgress = false; + } else { + console.warn(`[${Me.metadata.name}]: Updating extension ...`); + // for case the monitor configuration has been changed, update all + Me._resetInProgress = true; + this._activateVShell(); + Me._resetInProgress = false; + } + this._timeouts.reset = 0; + return GLib.SOURCE_REMOVE; + } + ); } -} -function _switchPageShortcuts() { - if (!opt.get('enablePageShortcuts', true)) - return; - - const vertical = global.workspaceManager.layout_rows === -1; - const schema = 'org.gnome.desktop.wm.keybindings'; - const settings = ExtensionUtils.getSettings(schema); - - const keyLeft = 'switch-to-workspace-left'; - const keyRight = 'switch-to-workspace-right'; - const keyUp = 'switch-to-workspace-up'; - const keyDown = 'switch-to-workspace-down'; - - const keyMoveLeft = 'move-to-workspace-left'; - const keyMoveRight = 'move-to-workspace-right'; - const keyMoveUp = 'move-to-workspace-up'; - const keyMoveDown = 'move-to-workspace-down'; - - const switchPrevSc = 'Page_Up'; - const switchNextSc = 'Page_Down'; - const movePrevSc = 'Page_Up'; - const moveNextSc = 'Page_Down'; - - let switchLeft = settings.get_strv(keyLeft); - let switchRight = settings.get_strv(keyRight); - let switchUp = settings.get_strv(keyUp); - let switchDown = settings.get_strv(keyDown); - - let moveLeft = settings.get_strv(keyMoveLeft); - let moveRight = settings.get_strv(keyMoveRight); - let moveUp = settings.get_strv(keyMoveUp); - let moveDown = settings.get_strv(keyMoveDown); - - if (vertical) { - if (switchLeft.includes(switchPrevSc)) - switchLeft.splice(switchLeft.indexOf(switchPrevSc), 1); - if (switchRight.includes(switchNextSc)) - switchRight.splice(switchRight.indexOf(switchNextSc), 1); - if (moveLeft.includes(movePrevSc)) - moveLeft.splice(moveLeft.indexOf(movePrevSc), 1); - if (moveRight.includes(moveNextSc)) - moveRight.splice(moveRight.indexOf(moveNextSc), 1); - - if (!switchUp.includes(switchPrevSc)) - switchUp.push(switchPrevSc); - if (!switchDown.includes(switchNextSc)) - switchDown.push(switchNextSc); - if (!moveUp.includes(movePrevSc)) - moveUp.push(movePrevSc); - if (!moveDown.includes(moveNextSc)) - moveDown.push(moveNextSc); - } else { - if (!switchLeft.includes(switchPrevSc)) - switchLeft.push(switchPrevSc); - if (!switchRight.includes(switchNextSc)) - switchRight.push(switchNextSc); - if (!moveLeft.includes(movePrevSc)) - moveLeft.push(movePrevSc); - if (!moveRight.includes(moveNextSc)) - moveRight.push(moveNextSc); - - if (switchUp.includes(switchPrevSc)) - switchUp.splice(switchUp.indexOf(switchPrevSc), 1); - if (switchDown.includes(switchNextSc)) - switchDown.splice(switchDown.indexOf(switchNextSc), 1); - if (moveUp.includes(movePrevSc)) - moveUp.splice(moveUp.indexOf(movePrevSc), 1); - if (moveDown.includes(moveNextSc)) - moveDown.splice(moveDown.indexOf(moveNextSc), 1); + // the key modules that can be affected by the supported incompatible extensions + _repairOverrides() { + Me.Modules.overviewModule.update(); + Me.Modules.overviewControlsModule.update(); + Me.Modules.workspacesViewModule.update(); + Me.Modules.windowPreviewModule.update(); + Me.Modules.panelModule.update(); + Me.Modules.dashModule.update(); } - settings.set_strv(keyLeft, switchLeft); - settings.set_strv(keyRight, switchRight); - settings.set_strv(keyUp, switchUp); - settings.set_strv(keyDown, switchDown); + _updateSettings(settings, key) { + // update settings cache and option variables + opt._updateSettings(); + + // avoid overload while loading profile - update only once + // delayed gsettings writes are processed alphabetically + if (key === 'aaa-loading-profile') { + this._showStatusMessage(); + if (this._timeouts.loadingProfile) + GLib.source_remove(this._timeouts.loadingProfile); + this._timeouts.loadingProfile = GLib.timeout_add( + GLib.PRIORITY_DEFAULT, + 100, () => { + this._activateVShell(); + this._timeouts.loadingProfile = 0; + return GLib.SOURCE_REMOVE; + }); + } + if (this._timeouts.loadingProfile) + return; - settings.set_strv(keyMoveLeft, moveLeft); - settings.set_strv(keyMoveRight, moveRight); - settings.set_strv(keyMoveUp, moveUp); - settings.set_strv(keyMoveDown, moveDown); -} + if (key?.includes('profile-data')) { + const index = key.replace('profile-data-', ''); + Main.notify(`${Me.metadata.name}`, `Profile ${index} has been updated`); + } + opt.WORKSPACE_MIN_SPACING = Main.overview._overview._controls._thumbnailsBox.get_theme_node().get_length('spacing'); + // update variables that cannot be processed within settings + const dash = Main.overview.dash; + if (Me.Util.dashIsDashToDock()) { + opt.DASH_POSITION = dash._position; + opt.DASH_TOP = opt.DASH_POSITION === 0; + opt.DASH_RIGHT = opt.DASH_POSITION === 1; + opt.DASH_BOTTOM = opt.DASH_POSITION === 2; + opt.DASH_LEFT = opt.DASH_POSITION === 3; + opt.DASH_VERTICAL = opt.DASH_LEFT || opt.DASH_RIGHT; + } -function _shouldAnimateOverview() { - return !opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2; -} + opt.DASH_VISIBLE = opt.DASH_VISIBLE && !Me.Util.getEnabledExtensions('dash-to-panel@jderose9.github.com').length; -function _updateOverviewTranslations(dash = null, tmbBox = null, searchEntryBin = null) { - dash = dash ?? Main.overview.dash; - tmbBox = tmbBox ?? Main.overview._overview._controls._thumbnailsBox; - searchEntryBin = searchEntryBin ?? Main.overview._overview._controls._searchEntryBin; - - if (!_shouldAnimateOverview()) { - tmbBox.translation_x = 0; - tmbBox.translation_y = 0; - dash.translation_x = 0; - dash.translation_y = 0; - searchEntryBin.translation_x = 0; - searchEntryBin.translation_y = 0; - return; - } + const monitorWidth = global.display.get_monitor_geometry(global.display.get_primary_monitor()).width; + if (monitorWidth < 1600) { + opt.APP_GRID_ICON_SIZE_DEFAULT = opt.APP_GRID_ACTIVE_PREVIEW && !opt.APP_GRID_USAGE ? 128 : 64; + opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT = 64; + } - const [tmbTranslationX, tmbTranslationY, dashTranslationX, dashTranslationY, searchTranslationY] = _Util.getOverviewTranslations(opt, dash, tmbBox, searchEntryBin); - tmbBox.translation_x = tmbTranslationX; - tmbBox.translation_y = tmbTranslationY; - if (!_Util.dashNotDefault()) { // only if dash is not dash to dock - dash.translation_x = dashTranslationX; - dash.translation_y = dashTranslationY; + Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = opt.OVERVIEW_MODE === 1 ? 0.1 : 0.95; + + // adjust search entry style for OM2 + if (opt.OVERVIEW_MODE2) + Main.overview.searchEntry.add_style_class_name('search-entry-om2'); + else + Main.overview.searchEntry.remove_style_class_name('search-entry-om2'); + + Main.overview.searchEntry.visible = opt.SHOW_SEARCH_ENTRY; + Main.overview.searchEntry.opacity = 255; + St.Settings.get().slow_down_factor = opt.ANIMATION_TIME_FACTOR; + Search.MAX_LIST_SEARCH_RESULTS_ROWS = opt.SEARCH_MAX_ROWS; + + opt.START_Y_OFFSET = (opt.get('panelModule') && opt.PANEL_OVERVIEW_ONLY && opt.PANEL_POSITION_TOP) || + // better to add unnecessary space than to have a panel overlapping other objects + Me.Util.getEnabledExtensions('hidetopbar').length + ? Main.panel.height + : 0; + + // Options for workspace switcher, apply custom function only if needed + if (opt.WS_WRAPAROUND || opt.WS_IGNORE_LAST) + Meta.Workspace.prototype.get_neighbor = this._getNeighbor; + else + Meta.Workspace.prototype.get_neighbor = this._originalGetNeighbor; + + if (settings) + this._applySettings(key); } - searchEntryBin.translation_y = searchTranslationY; -} - -function _setStaticBackground(reset = false) { - _bgManagers.forEach(bg => { - Main.overview._overview._controls._stateAdjustment.disconnect(bg._fadeSignal); - bg.destroy(); - }); - - _bgManagers = []; - // if (!SHOW_BG_IN_OVERVIEW && !SHOW_WS_PREVIEW_BG) the background is used for static transition from wallpaper to empty bg in the overview - if (reset || (!opt.SHOW_BG_IN_OVERVIEW && opt.SHOW_WS_PREVIEW_BG)) - return; - - for (const monitor of Main.layoutManager.monitors) { - const bgManager = new Background.BackgroundManager({ - monitorIndex: monitor.index, - container: Main.layoutManager.overviewGroup, - vignette: true, - }); - bgManager.backgroundActor.content.vignette_sharpness = 0; - bgManager.backgroundActor.content.brightness = 1; + _applySettings(key) { + if (key?.endsWith('-module')) { + for (let module of Me.moduleList) { + if (opt.options[module] && key === opt.options[module][1]) { + if (key === 'app-display-module') + this._showStatusMessage(); + Me.Modules[module].update(); + break; + } + } + return; + } + Main.overview._overview.controls._setBackground(); + this._switchPageShortcuts(); + + if (key?.includes('panel')) + Me.Modules.panelModule.update(); + + if (key?.includes('dash') || key?.includes('icon') || key?.includes('dot-style')) + Me.Modules.dashModule.update(); + + if (key?.includes('hot-corner') || key?.includes('dash')) + Me.Modules.layoutModule.update(); + + switch (key) { + case 'ws-thumbnails-position': + this._updateOverrides(); + break; + case 'workspace-switcher-animation': + Me.Modules.workspaceAnimationModule.update(); + break; + case 'search-width-scale': + Me.Modules.searchModule.update(); + break; + case 'favorites-notify': + Me.Modules.appFavoritesModule.update(); + break; + case 'window-attention-mode': + Me.Modules.windowAttentionHandlerModule.update(); + break; + case 'show-ws-preview-bg': + Me.Modules.panelModule.update(); + break; + case 'notification-position': + Me.Modules.messageTrayModule.update(); + break; + case 'osd-position': + Me.Modules.osdWindowModule.update(); + break; + case 'overlay-key': + Me.Modules.overlayKeyModule.update(); + break; + case 'always-activate-selected-window': + Me.Modules.windowPreviewModule.update(); + break; + } - bgManager._fadeSignal = Main.overview._overview._controls._stateAdjustment.connect('notify::value', v => { - _updateStaticBackground(bgManager, v.value, v); - }); + if (key?.includes('app-grid') || + key?.includes('app-folder') || + key?.includes('dot-style') || + key === 'show-search-entry' || + key === 'ws-thumbnail-scale' || + key === 'ws-thumbnail-scale-appgrid') { + this._showStatusMessage(); + Me.Modules.appDisplayModule.update(); + } + } - if (monitor.index === global.display.get_primary_monitor()) { - bgManager._primary = true; - _bgManagers.unshift(bgManager); // primary monitor first + _switchPageShortcuts() { + // ignore screen lock + if (!opt.get('enablePageShortcuts') || this._sessionLockActive) + return; + + const vertical = global.workspaceManager.layout_rows === -1; + const schema = 'org.gnome.desktop.wm.keybindings'; + const settings = new Gio.Settings({ schema_id: schema }); + + const keyLeft = 'switch-to-workspace-left'; + const keyRight = 'switch-to-workspace-right'; + const keyUp = 'switch-to-workspace-up'; + const keyDown = 'switch-to-workspace-down'; + + const keyMoveLeft = 'move-to-workspace-left'; + const keyMoveRight = 'move-to-workspace-right'; + const keyMoveUp = 'move-to-workspace-up'; + const keyMoveDown = 'move-to-workspace-down'; + + const switchPrevSc = 'Page_Up'; + const switchNextSc = 'Page_Down'; + const movePrevSc = 'Page_Up'; + const moveNextSc = 'Page_Down'; + + let switchLeft = settings.get_strv(keyLeft); + let switchRight = settings.get_strv(keyRight); + let switchUp = settings.get_strv(keyUp); + let switchDown = settings.get_strv(keyDown); + + let moveLeft = settings.get_strv(keyMoveLeft); + let moveRight = settings.get_strv(keyMoveRight); + let moveUp = settings.get_strv(keyMoveUp); + let moveDown = settings.get_strv(keyMoveDown); + + if (vertical) { + if (switchLeft.includes(switchPrevSc)) + switchLeft.splice(switchLeft.indexOf(switchPrevSc), 1); + if (switchRight.includes(switchNextSc)) + switchRight.splice(switchRight.indexOf(switchNextSc), 1); + if (moveLeft.includes(movePrevSc)) + moveLeft.splice(moveLeft.indexOf(movePrevSc), 1); + if (moveRight.includes(moveNextSc)) + moveRight.splice(moveRight.indexOf(moveNextSc), 1); + + if (!switchUp.includes(switchPrevSc)) + switchUp.push(switchPrevSc); + if (!switchDown.includes(switchNextSc)) + switchDown.push(switchNextSc); + if (!moveUp.includes(movePrevSc)) + moveUp.push(movePrevSc); + if (!moveDown.includes(moveNextSc)) + moveDown.push(moveNextSc); } else { - bgManager._primary = false; - _bgManagers.push(bgManager); + if (!switchLeft.includes(switchPrevSc)) + switchLeft.push(switchPrevSc); + if (!switchRight.includes(switchNextSc)) + switchRight.push(switchNextSc); + if (!moveLeft.includes(movePrevSc)) + moveLeft.push(movePrevSc); + if (!moveRight.includes(moveNextSc)) + moveRight.push(moveNextSc); + + if (switchUp.includes(switchPrevSc)) + switchUp.splice(switchUp.indexOf(switchPrevSc), 1); + if (switchDown.includes(switchNextSc)) + switchDown.splice(switchDown.indexOf(switchNextSc), 1); + if (moveUp.includes(movePrevSc)) + moveUp.splice(moveUp.indexOf(movePrevSc), 1); + if (moveDown.includes(moveNextSc)) + moveDown.splice(moveDown.indexOf(moveNextSc), 1); } + + settings.set_strv(keyLeft, switchLeft); + settings.set_strv(keyRight, switchRight); + settings.set_strv(keyUp, switchUp); + settings.set_strv(keyDown, switchDown); + + settings.set_strv(keyMoveLeft, moveLeft); + settings.set_strv(keyMoveRight, moveRight); + settings.set_strv(keyMoveUp, moveUp); + settings.set_strv(keyMoveDown, moveDown); } -} -function _updateStaticBackground(bgManager, stateValue, stateAdjustment = null) { - if (!opt.SHOW_BG_IN_OVERVIEW && !opt.SHOW_WS_PREVIEW_BG) { - // if no bg shown in the overview, fade out the wallpaper - if (!(opt.OVERVIEW_MODE2 && opt.WORKSPACE_MODE && stateAdjustment?.getStateTransitionParams().finalState === 1)) - bgManager.backgroundActor.opacity = Util.lerp(255, 0, Math.min(stateValue, 1)); - } else { - let VIGNETTE, BRIGHTNESS, bgValue; - if (opt.OVERVIEW_MODE2 && stateValue <= 1 && !opt.WORKSPACE_MODE) { - VIGNETTE = 0; - BRIGHTNESS = 1; - bgValue = stateValue; - } else { - VIGNETTE = 0.2; - BRIGHTNESS = opt.OVERVIEW_BG_BRIGHTNESS; - if (opt.OVERVIEW_MODE2 && stateValue > 1 && !opt.WORKSPACE_MODE) - bgValue = stateValue - 1; - else - bgValue = stateValue; + // Status dialog that appears during updating V-Shell configuration and blocks inputs + _showStatusMessage(show = true) { + if ((show && Me._resetInProgress) || Main.layoutManager._startingUp || !Main.overview._overview.controls._appDisplay._sortOrderedItemsAlphabetically) + return; + + if (Me._vShellMessageTimeoutId) { + GLib.source_remove(Me._vShellMessageTimeoutId); + Me._vShellMessageTimeoutId = 0; } - let blurEffect = bgManager.backgroundActor.get_effect('blur'); - if (!blurEffect) { - blurEffect = new Shell.BlurEffect({ - brightness: 1, - sigma: 0, - mode: Shell.BlurMode.ACTOR, - }); - bgManager.backgroundActor.add_effect_with_name('blur', blurEffect); + if (Me._vShellStatusMessage && !show) { + Me._vShellStatusMessage.close(); + Me._vShellStatusMessage.destroy(); + Me._vShellStatusMessage = null; } - bgManager.backgroundActor.content.vignette_sharpness = VIGNETTE; - bgManager.backgroundActor.content.brightness = BRIGHTNESS; + if (!show) + return; - let vignetteInit, brightnessInit;// , sigmaInit; - if (opt.SHOW_BG_IN_OVERVIEW && opt.SHOW_WS_PREVIEW_BG) { - vignetteInit = VIGNETTE; - brightnessInit = BRIGHTNESS; - // sigmaInit = opt.OVERVIEW_BG_BLUR_SIGMA; - } else { - vignetteInit = 0; - brightnessInit = 1; - // sigmaInit = 0; + if (!Me._vShellStatusMessage) { + const sm = new Main.RestartMessage(_('Updating V-Shell...')); + sm.set_style('background-color: rgba(0,0,0,0.3);'); + sm.open(); + Me._vShellStatusMessage = sm; } - if (opt.OVERVIEW_MODE2) { - bgManager.backgroundActor.content.vignette_sharpness = Util.lerp(vignetteInit, VIGNETTE, bgValue); - bgManager.backgroundActor.content.brightness = Util.lerp(brightnessInit, BRIGHTNESS, bgValue); - } else { - bgManager.backgroundActor.content.vignette_sharpness = Util.lerp(vignetteInit, VIGNETTE, Math.min(stateValue, 1)); - bgManager.backgroundActor.content.brightness = Util.lerp(brightnessInit, BRIGHTNESS, Math.min(stateValue, 1)); - } + // just for case the message wasn't removed from appDisplay after App Grid realization + Me._vShellMessageTimeoutId = GLib.timeout_add_seconds( + GLib.PRIORITY_DEFAULT, + 5, + () => { + if (Me._vShellStatusMessage) { + Me._vShellStatusMessage.close(); + Me._vShellStatusMessage.destroy(); + Me._vShellStatusMessage = null; + Me._resetInProgress = false; + } + + Me._vShellMessageTimeoutId = 0; + return GLib.SOURCE_REMOVE; + } + ); + } - if (opt.OVERVIEW_BG_BLUR_SIGMA || opt.APP_GRID_BG_BLUR_SIGMA) { - // reduce number of steps of blur transition to improve performance - const step = opt.SMOOTH_BLUR_TRANSITIONS ? 0.05 : 0.2; - const searchActive = Main.overview._overview.controls._searchController.searchActive; - const progress = stateValue - (stateValue % step); - if (opt.SHOW_WS_PREVIEW_BG && stateValue < 1 && !searchActive) { // no need to animate transition, unless appGrid state is involved, static bg is covered by the ws preview bg - if (blurEffect.sigma !== opt.OVERVIEW_BG_BLUR_SIGMA) - blurEffect.sigma = opt.OVERVIEW_BG_BLUR_SIGMA; - } else if (stateValue < 1 && !searchActive) { - const sigma = Math.round(Util.lerp(0, opt.OVERVIEW_BG_BLUR_SIGMA, progress)); - if (sigma !== blurEffect.sigma) - blurEffect.sigma = sigma; - } else if ((stateValue > 1 && bgManager._primary) || searchActive) { - const sigma = Math.round(Util.lerp(opt.OVERVIEW_BG_BLUR_SIGMA, opt.APP_GRID_BG_BLUR_SIGMA, progress % 1)); - if (sigma !== blurEffect.sigma) - blurEffect.sigma = sigma; - } else if (stateValue === 1) { - blurEffect.sigma = opt.OVERVIEW_BG_BLUR_SIGMA; - } else if (stateValue === 0) { - blurEffect.sigma = 0; + _getNeighbor(direction) { + // workspace matrix is supported + const activeIndex = this.index(); + const ignoreLast = opt.WS_IGNORE_LAST && !Main.overview._shown ? 1 : 0; + const wraparound = opt.WS_WRAPAROUND; + const nWorkspaces = global.workspace_manager.n_workspaces; + const lastIndex = nWorkspaces - 1 - ignoreLast; + const rows = global.workspace_manager.layout_rows > -1 ? global.workspace_manager.layout_rows : nWorkspaces; + const columns = global.workspace_manager.layout_columns > -1 ? global.workspace_manager.layout_columns : nWorkspaces; + + let index = activeIndex; + let neighborExists; + + if (direction === Meta.MotionDirection.LEFT) { + index -= 1; + const currentRow = Math.floor(activeIndex / columns); + const indexRow = Math.floor(index / columns); + neighborExists = index > -1 && indexRow === currentRow; + if (wraparound && !neighborExists) { + index = currentRow * columns + columns - 1; + const maxIndexOnLastRow = lastIndex % columns; + index = index < (lastIndex - ignoreLast) ? index : currentRow * columns + maxIndexOnLastRow; } + } else if (direction === Meta.MotionDirection.RIGHT) { + index += 1; + const currentRow = Math.floor(activeIndex / columns); + const indexRow = Math.floor(index / columns); + neighborExists = index <= lastIndex && indexRow === currentRow; + if (wraparound && !neighborExists) + index = currentRow * columns; + } else if (direction === Meta.MotionDirection.UP) { + index -= columns; + neighborExists = index > -1; + if (wraparound && !neighborExists) { + index = rows * columns + index; + index = index < nWorkspaces - ignoreLast ? index : index - columns; + } + } else if (direction === Meta.MotionDirection.DOWN) { + index += columns; + neighborExists = index <= lastIndex; + if (wraparound && !neighborExists) + index %= columns; } + + return global.workspace_manager.get_workspace_by_index(neighborExists || wraparound ? index : activeIndex); } } - -- cgit v1.2.3