diff options
Diffstat (limited to 'extensions/45/vertical-workspaces/lib/dash.js')
-rw-r--r-- | extensions/45/vertical-workspaces/lib/dash.js | 667 |
1 files changed, 231 insertions, 436 deletions
diff --git a/extensions/45/vertical-workspaces/lib/dash.js b/extensions/45/vertical-workspaces/lib/dash.js index f26151d..719c3de 100644 --- a/extensions/45/vertical-workspaces/lib/dash.js +++ b/extensions/45/vertical-workspaces/lib/dash.js @@ -3,10 +3,9 @@ * dash.js * * @author GdH <G-dH@github.com> - * @copyright 2022-2023 + * @copyright 2022-2024 * @license GPL-3.0 - * modified dash module of https://github.com/RensAlthuis/vertical-overview extension - */ + */ 'use strict'; @@ -23,7 +22,6 @@ import * as AppFavorites from 'resource:///org/gnome/shell/ui/appFavorites.js'; import * as AppMenu from 'resource:///org/gnome/shell/ui/appMenu.js'; import * as BoxPointer from 'resource:///org/gnome/shell/ui/boxpointer.js'; import * as DND from 'resource:///org/gnome/shell/ui/dnd.js'; -import * as IconGrid from 'resource:///org/gnome/shell/ui/iconGrid.js'; import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; let Me; @@ -39,6 +37,8 @@ export const BaseIconSizes = [16, 24, 32, 40, 44, 48, 56, 64, 72, 80, 96, 112, 1 const DASH_ITEM_LABEL_SHOW_TIME = 150; +const shellVersion46 = !Clutter.Container; // Container has been removed in 46 + export const DashModule = class { constructor(me) { Me = me; @@ -130,32 +130,53 @@ export const DashModule = class { this._overrides.addOverride('DashIcon', Dash.DashIcon.prototype, DashIconCommon); this._overrides.addOverride('AppMenu', AppMenu.AppMenu.prototype, AppMenuCommon); + if (shellVersion46) + dash.add_style_class_name('dash-46'); + if (opt.DASH_VERTICAL) { // this._overrides.addOverride('Dash', Dash.Dash.prototype, DashVerticalOverride); - dash.add_style_class_name('vertical'); + dash.add_style_class_name(shellVersion46 + ? 'vertical-46' + : 'vertical' + ); this._setOrientation(Clutter.Orientation.VERTICAL); } else { this._setOrientation(Clutter.Orientation.HORIZONTAL); } + if (opt.DASH_VERTICAL && opt.DASH_BG_GS3_STYLE) { + if (opt.DASH_LEFT) { + dash.add_style_class_name(shellVersion46 + ? 'vertical-46-gs3-left' + : 'vertical-gs3-left'); + } else if (opt.DASH_RIGHT) { + dash.add_style_class_name(shellVersion46 + ? 'vertical-46-gs3-right' + : 'vertical-gs3-right'); + } + } else { + dash.remove_style_class_name('vertical-gs3-left'); + dash.remove_style_class_name('vertical-gs3-right'); + dash.remove_style_class_name('vertical-46-gs3-left'); + dash.remove_style_class_name('vertical-46-gs3-right'); + } + if (!this._customWorkId) this._customWorkId = Main.initializeDeferredWork(dash._box, dash._redisplay.bind(dash)); dash._workId = this._customWorkId; - this._updateSearchWindowsIcon(); - this._updateRecentFilesIcon(); - this._updateExtensionsIcon(); this._moveDashAppGridIcon(); this._connectShowAppsIcon(); dash.visible = opt.DASH_VISIBLE; - dash._background.add_style_class_name('dash-background-reduced'); + // dash._background.add_style_class_name('dash-background-reduced'); dash._queueRedisplay(); if (opt.DASH_ISOLATE_WS && !this._wmSwitchWsConId) { this._wmSwitchWsConId = global.windowManager.connect('switch-workspace', () => dash._queueRedisplay()); this._newWindowConId = global.display.connect_after('window-created', () => dash._queueRedisplay()); } + console.debug(' DashModule - Activated'); } @@ -181,9 +202,7 @@ export const DashModule = class { this._setOrientation(Clutter.Orientation.HORIZONTAL); this._moveDashAppGridIcon(reset); this._connectShowAppsIcon(reset); - this._updateSearchWindowsIcon(false); - this._updateRecentFilesIcon(false); - this._updateExtensionsIcon(false); + this._resetStyle(dash); dash.visible = !this._conflict; dash._background.opacity = 255; @@ -194,8 +213,11 @@ export const DashModule = class { _resetStyle(dash) { dash.remove_style_class_name('vertical'); + dash.remove_style_class_name('vertical-46'); dash.remove_style_class_name('vertical-gs3-left'); dash.remove_style_class_name('vertical-gs3-right'); + dash.remove_style_class_name('vertical-46-gs3-left'); + dash.remove_style_class_name('vertical-46-gs3-right'); dash.remove_style_class_name('vertical-left'); dash.remove_style_class_name('vertical-right'); dash._background.remove_style_class_name('dash-background-light'); @@ -237,16 +259,6 @@ export const DashModule = class { dash._separator = null; dash._queueRedisplay(); dash._adjustIconSize(); - - if (orientation && opt.DASH_BG_GS3_STYLE) { - if (opt.DASH_LEFT) - dash.add_style_class_name('vertical-gs3-left'); - else if (opt.DASH_RIGHT) - dash.add_style_class_name('vertical-gs3-right'); - } else { - dash.remove_style_class_name('vertical-gs3-left'); - dash.remove_style_class_name('vertical-gs3-right'); - } } _moveDashAppGridIcon(reset = false) { @@ -295,141 +307,6 @@ export const DashModule = class { dash._showAppsIcon.reactive = false; } } - - _updateSearchWindowsIcon(show = opt.SHOW_WINDOWS_ICON, dash) { - dash = dash ?? Main.overview._overview._controls.layoutManager._dash; - const dashContainer = dash._dashContainer; - - if (dash._showWindowsIcon) { - dashContainer.remove_child(dash._showWindowsIcon); - if (dash._showWindowsIconClickedId) { - dash._showWindowsIcon.toggleButton.disconnect(dash._showWindowsIconClickedId); - dash._showWindowsIconClickedId = 0; - } - delete dash._showWindowsIconClickedId; - if (dash._showWindowsIcon) - dash._showWindowsIcon.destroy(); - delete dash._showWindowsIcon; - } - - if (!show || !opt.get('windowSearchProviderModule')) - return; - - if (!dash._showWindowsIcon) { - dash._showWindowsIcon = new Dash.DashItemContainer(); - new Me.Util.Overrides().addOverride('showWindowsIcon', dash._showWindowsIcon, ShowWindowsIcon); - dash._showWindowsIcon._afterInit(); - dash._showWindowsIcon.show(false); - dashContainer.add_child(dash._showWindowsIcon); - dash._hookUpLabel(dash._showWindowsIcon); - } - - dash._showWindowsIcon.icon.setIconSize(dash.iconSize); - if (opt.SHOW_WINDOWS_ICON === 1) { - dashContainer.set_child_at_index(dash._showWindowsIcon, 0); - } else if (opt.SHOW_WINDOWS_ICON === 2) { - const index = dashContainer.get_children().length - 1; - dashContainer.set_child_at_index(dash._showWindowsIcon, index); - } - - Main.overview._overview._controls.layoutManager._dash._adjustIconSize(); - - if (dash._showWindowsIcon && !dash._showWindowsIconClickedId) { - dash._showWindowsIconClickedId = dash._showWindowsIcon.toggleButton.connect('clicked', () => { - Me.Util.activateSearchProvider(Me.WSP_PREFIX); - }); - } - } - - _updateRecentFilesIcon(show = opt.SHOW_RECENT_FILES_ICON, dash) { - dash = dash ?? Main.overview._overview._controls.layoutManager._dash; - const dashContainer = dash._dashContainer; - - if (dash._recentFilesIcon) { - dashContainer.remove_child(dash._recentFilesIcon); - if (dash._recentFilesIconClickedId) { - dash._recentFilesIcon.toggleButton.disconnect(dash._recentFilesIconClickedId); - dash._recentFilesIconClickedId = 0; - } - delete dash._recentFilesIconClickedId; - if (dash._recentFilesIcon) - dash._recentFilesIcon.destroy(); - delete dash._recentFilesIcon; - } - - if (!show || !opt.get('recentFilesSearchProviderModule')) - return; - - if (!dash._recentFilesIcon) { - dash._recentFilesIcon = new Dash.DashItemContainer(); - new Me.Util.Overrides().addOverride('recentFilesIcon', dash._recentFilesIcon, ShowRecentFilesIcon); - dash._recentFilesIcon._afterInit(); - dash._recentFilesIcon.show(false); - dashContainer.add_child(dash._recentFilesIcon); - dash._hookUpLabel(dash._recentFilesIcon); - } - - dash._recentFilesIcon.icon.setIconSize(dash.iconSize); - if (opt.SHOW_RECENT_FILES_ICON === 1) { - dashContainer.set_child_at_index(dash._recentFilesIcon, 0); - } else if (opt.SHOW_RECENT_FILES_ICON === 2) { - const index = dashContainer.get_children().length - 1; - dashContainer.set_child_at_index(dash._recentFilesIcon, index); - } - - Main.overview._overview._controls.layoutManager._dash._adjustIconSize(); - - if (dash._recentFilesIcon && !dash._recentFilesIconClickedId) { - dash._recentFilesIconClickedId = dash._recentFilesIcon.toggleButton.connect('clicked', () => { - Me.Util.activateSearchProvider(Me.RFSP_PREFIX); - }); - } - } - - _updateExtensionsIcon(show = opt.SHOW_EXTENSIONS_ICON, dash) { - dash = dash ?? Main.overview._overview._controls.layoutManager._dash; - const dashContainer = dash._dashContainer; - - if (dash._extensionsIcon) { - dashContainer.remove_child(dash._extensionsIcon); - if (dash._extensionsIconClickedId) { - dash._extensionsIcon.toggleButton.disconnect(dash._extensionsIconClickedId); - dash._extensionsIconClickedId = 0; - } - delete dash._extensionsIconClickedId; - if (dash._extensionsIcon) - dash._extensionsIcon.destroy(); - delete dash._extensionsIcon; - } - - if (!show || !opt.get('extensionsSearchProviderModule')) - return; - - if (!dash._extensionsIcon) { - dash._extensionsIcon = new Dash.DashItemContainer(); - new Me.Util.Overrides().addOverride('extensionsIcon', dash._extensionsIcon, ShowExtensionsIcon); - dash._extensionsIcon._afterInit(); - dash._extensionsIcon.show(false); - dashContainer.add_child(dash._extensionsIcon); - dash._hookUpLabel(dash._extensionsIcon); - } - - dash._extensionsIcon.icon.setIconSize(dash.iconSize); - if (opt.SHOW_EXTENSIONS_ICON === 1) { - dashContainer.set_child_at_index(dash._extensionsIcon, 0); - } else if (opt.SHOW_EXTENSIONS_ICON === 2) { - const index = dashContainer.get_children().length - 1; - dashContainer.set_child_at_index(dash._extensionsIcon, index); - } - - Main.overview._overview._controls.layoutManager._dash._adjustIconSize(); - - if (dash._extensionsIcon && !dash._extensionsIconClickedId) { - dash._extensionsIconClickedId = dash._extensionsIcon.toggleButton.connect('clicked', () => { - Me.Util.activateSearchProvider(Me.ESP_PREFIX); - }); - } - } }; function getAppFromSource(source) { @@ -475,20 +352,20 @@ const DashItemContainerCommon = { let y; if (opt.DASH_TOP) { - const yOffset = 0.75 * itemHeight + 3 * node.get_length('-y-offset'); + const yOffset = itemHeight + (shellVersion46 ? 0 : -3); y = stageY + yOffset; } else if (opt.DASH_BOTTOM) { const yOffset = node.get_length('-y-offset'); y = stageY - this.label.height - yOffset; } else if (opt.DASH_RIGHT) { const yOffset = Math.floor((itemHeight - labelHeight) / 2); - xOffset = 4; + xOffset = shellVersion46 ? 8 : 4; x = stageX - xOffset - this.label.width; y = Math.clamp(stageY + yOffset, 0, global.stage.height - labelHeight); } else if (opt.DASH_LEFT) { const yOffset = Math.floor((itemHeight - labelHeight) / 2); - xOffset = 4; + xOffset = shellVersion46 ? 8 : 4; x = stageX + this.width + xOffset; y = Math.clamp(stageY + yOffset, 0, global.stage.height - labelHeight); @@ -744,15 +621,15 @@ const DashCommon = { if (this._showAppsIcon.visible) iconChildren.push(this._showAppsIcon); + + // showWindowsIcon and extensionsIcon can be provided by the WSP and ESP extensions if (this._showWindowsIcon) iconChildren.push(this._showWindowsIcon); - if (this._recentFilesIcon) - iconChildren.push(this._recentFilesIcon); - if (this._extensionsIcon) iconChildren.push(this._extensionsIcon); + if (!iconChildren.length) return; @@ -967,12 +844,15 @@ const DashIconCommon = { this._scrollConId = this.connect('scroll-event', DashExtensions.onScrollEvent.bind(this)); this._leaveConId = this.connect('leave-event', DashExtensions.onLeaveEvent.bind(this)); } + + if (this._updateRunningDotStyle) + this._updateRunningDotStyle(); }, - popupMenu() { + /* popupMenu() { const side = opt.DASH_VERTICAL ? St.Side.LEFT : St.Side.BOTTOM; AppIconCommon.popupMenu.bind(this)(side); - }, + },*/ _updateRunningStyle() { const currentWs = global.workspace_manager.get_active_workspace(); @@ -985,193 +865,27 @@ const DashIconCommon = { else this._dot.hide(); }, -}; - -const DashExtensions = { - onScrollEvent(source, event) { - if ((this.app && !opt.DASH_ICON_SCROLL) || (this._isSearchWindowsIcon && !opt.SEARCH_WINDOWS_ICON_SCROLL)) { - if (this._scrollConId) { - this.disconnect(this._scrollConId); - this._scrollConId = 0; - } - if (this._leaveConId) { - this.disconnect(this._leaveConId); - this._leaveConId = 0; - } - return Clutter.EVENT_PROPAGATE; - } - - if (Main.overview._overview.controls._stateAdjustment.value > 1) - return Clutter.EVENT_PROPAGATE; - - let direction = Me.Util.getScrollDirection(event); - if (direction === Clutter.ScrollDirection.UP) - direction = 1; - else if (direction === Clutter.ScrollDirection.DOWN) - direction = -1; - else - return Clutter.EVENT_STOP; - - // avoid uncontrollable switching if smooth scroll wheel or trackpad is used - if (this._lastScroll && Date.now() - this._lastScroll < 160) - return Clutter.EVENT_STOP; - - this._lastScroll = Date.now(); - - DashExtensions.switchWindow.bind(this)(direction); - return Clutter.EVENT_STOP; - }, - - onLeaveEvent() { - if (!this._selectedMetaWin || this.has_pointer || this.toggleButton?.has_pointer) - return; - - this._selectedPreview._activateSelected = false; - this._selectedMetaWin = null; - this._scrolledWindows = null; - DashExtensions.showWindowPreview.bind(this)(null); - }, - - - switchWindow(direction) { - if (!this._scrolledWindows) { - this._initialSelection = true; - // source is app icon - if (this.app) { - this._scrolledWindows = this.app.get_windows(); - if (opt.DASH_ISOLATE_WS) { - const currentWs = global.workspaceManager.get_active_workspace(); - this._scrolledWindows = this._scrolledWindows.filter(w => w.get_workspace() === currentWs); - } - - const wsList = []; - this._scrolledWindows.forEach(w => { - const ws = w.get_workspace(); - if (!wsList.includes(ws)) - wsList.push(ws); - }); - - // sort windows by workspaces in MRU order - this._scrolledWindows.sort((a, b) => wsList.indexOf(a.get_workspace()) > wsList.indexOf(b.get_workspace())); - // source is Search Windows icon - } else if (this._isSearchWindowsIcon) { - if (opt.SEARCH_WINDOWS_ICON_SCROLL === 1) // all windows - this._scrolledWindows = Me.Util.getWindows(null); - else - this._scrolledWindows = Me.Util.getWindows(global.workspace_manager.get_active_workspace()); - } - } - - let windows = this._scrolledWindows; - - if (!windows.length) - return; - - // if window selection is in the process, the previewed window must be the current one - let currentWin = this._selectedMetaWin ? this._selectedMetaWin : windows[0]; - - const currentIdx = windows.indexOf(currentWin); - let targetIdx = currentIdx; - // const focusWindow = Me.Util.getWindows(null)[0]; // incompatible 45 - const focusWindow = Me.Util.getWindows(null)[0]; - const appFocused = this._scrolledWindows[0] === focusWindow && this._scrolledWindows[0].get_workspace() === global.workspace_manager.get_active_workspace(); - // only if the app has focus, immediately switch to the previous window - // otherwise just set the current window above others - if (!this._initialSelection || appFocused) - targetIdx += direction; - else - this._initialSelection = false; - - if (targetIdx > windows.length - 1) - targetIdx = 0; - else if (targetIdx < 0) - targetIdx = windows.length - 1; - - const metaWin = windows[targetIdx]; - DashExtensions.showWindowPreview.bind(this)(metaWin); - this._selectedMetaWin = metaWin; - }, - - showWindowPreview(metaWin) { - const views = Main.overview._overview.controls._workspacesDisplay._workspacesViews; - const viewsIter = [views[0]]; - // secondary monitors use different structure - views.forEach(v => { - if (v._workspacesView) - viewsIter.push(v._workspacesView); - }); - - viewsIter.forEach(view => { - // if workspaces are on primary monitor only - if (!view || !view._workspaces) - return; - - view._workspaces.forEach(ws => { - ws._windows.forEach(windowPreview => { - // metaWin === null resets opacity - let opacity = metaWin ? 50 : 255; - windowPreview._activateSelected = false; - - // minimized windows are invisible if windows are not exposed (WORKSPACE_MODE === 0) - if (!windowPreview.opacity) - windowPreview.opacity = 255; - - // app windows set to lower opacity, so they can be recognized - if (this._scrolledWindows && this._scrolledWindows.includes(windowPreview.metaWindow)) { - if (opt.DASH_ICON_SCROLL === 2) - opacity = 254; - } - if (windowPreview.metaWindow === metaWin) { - if (metaWin && metaWin.get_workspace() !== global.workspace_manager.get_active_workspace()) { - Main.wm.actionMoveWorkspace(metaWin.get_workspace()); - if (_timeouts.wsSwitcherAnimation) - GLib.source_remove(_timeouts.wsSwitcherAnimation); - // setting window preview above siblings before workspace switcher animation has no effect - // we need to set the window above after the ws preview become visible on the screen - // the default switcher animation time is 250, 200 ms delay should be enough - _timeouts.wsSwitcherAnimation = GLib.timeout_add(0, 200 * St.Settings.get().slow_down_factor, () => { - windowPreview.get_parent().set_child_above_sibling(windowPreview, null); - _timeouts.wsSwitcherAnimation = 0; - return GLib.SOURCE_REMOVE; - }); - } else { - windowPreview.get_parent().set_child_above_sibling(windowPreview, null); - } - - opacity = 255; - this._selectedPreview = windowPreview; - windowPreview._activateSelected = true; - } - - // if windows are exposed, highlight selected using opacity - if ((opt.OVERVIEW_MODE && opt.WORKSPACE_MODE) || !opt.OVERVIEW_MODE) { - if (metaWin && opacity === 255) - windowPreview.showOverlay(true); - else - windowPreview.hideOverlay(true); - windowPreview.ease({ - duration: 200, - opacity, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - }); - } - }); - }); - }); - }, -}; -const AppIconCommon = { - after__init() { + /* after__init() { if (this._updateRunningDotStyle) this._updateRunningDotStyle(); - }, + },*/ _updateRunningDotStyle() { if (opt.RUNNING_DOT_STYLE) this._dot.add_style_class_name('app-well-app-running-dot-custom'); else this._dot.remove_style_class_name('app-well-app-running-dot-custom'); + + if (!this.label && shellVersion46) { + if (opt.DASH_VERTICAL) { + this._dot.translation_y = 0; + this._dot.translation_x = 0; // opt.DASH_LEFT ? -4 : 4; + } else { + this._dot.translation_y = 8; + this._dot.translation_x = 0; + } + } }, activate(button) { @@ -1243,6 +957,9 @@ const AppIconCommon = { }, popupMenu(side = St.Side.LEFT) { + side = opt.DASH_VERTICAL ? St.Side.LEFT : St.Side.BOTTOM; + // AppIconCommon.popupMenu.bind(this)(side); + this.setForcedHighlight(true); this._removeMenuTimeout(); this.fake_release(); @@ -1277,7 +994,7 @@ const AppIconCommon = { this._hidingSigId = Main.overview.connect('hiding', () => this._menu.close(), this); - Main.uiGroup.add_actor(this._menu.actor); + Main.uiGroup.add_child(this._menu.actor); this._menuManager.addMenu(this._menu); } @@ -1310,10 +1027,12 @@ const AppIconCommon = { }]); } + popupItems.push([_('Move App to Current Workspace ( Shift + Click )'), this._moveAppToCurrentWorkspace]); - if (opt.WINDOW_THUMBNAIL_ENABLED) { - popupItems.push([_('Create Window Thumbnail - PIP'), () => { - Me.Modules.winTmbModule.createThumbnail(this.app.get_windows()[0]); + // WTMB (Windows Thumbnails) extension required + if (global.windowThumbnails) { + popupItems.push([_('Create Window Thumbnail/PiP'), () => { + global.windowThumbnails?.createThumbnail(this.app.get_windows()[0]); }]); } } @@ -1362,115 +1081,191 @@ const AppIconCommon = { }, }; -const ShowWindowsIcon = { - _afterInit() { - this._isSearchWindowsIcon = true; - this._labelText = _('Search Open Windows (Hotkey: Space)'); - this.toggleButton = new St.Button({ - style_class: 'show-apps', - track_hover: true, - can_focus: true, - toggle_mode: false, - }); +const DashExtensions = { + onScrollEvent(source, event) { + if ((this.app && !opt.DASH_ICON_SCROLL) || (this._isSearchWindowsIcon && !opt.SEARCH_WINDOWS_ICON_SCROLL)) { + if (this._scrollConId) { + this.disconnect(this._scrollConId); + this._scrollConId = 0; + } + if (this._leaveConId) { + this.disconnect(this._leaveConId); + this._leaveConId = 0; + } + return Clutter.EVENT_PROPAGATE; + } - this._iconActor = null; - this.icon = new IconGrid.BaseIcon(this.labelText, { - setSizeManually: true, - showLabel: false, - createIcon: this._createIcon.bind(this), - }); - this.icon.y_align = Clutter.ActorAlign.CENTER; + if (Main.overview._overview.controls._stateAdjustment.value > 1) + return Clutter.EVENT_PROPAGATE; - this.toggleButton.add_actor(this.icon); - this.toggleButton._delegate = this; + let direction = Me.Util.getScrollDirection(event); + if (direction === Clutter.ScrollDirection.UP) + direction = 1; + else if (direction === Clutter.ScrollDirection.DOWN) + direction = -1; + else + return Clutter.EVENT_STOP; - this.setChild(this.toggleButton); + // avoid uncontrollable switching if smooth scroll wheel or trackpad is used + if (this._lastScroll && Date.now() - this._lastScroll < 160) + return Clutter.EVENT_STOP; - if (opt.SEARCH_WINDOWS_ICON_SCROLL) { - this.reactive = true; - this._scrollConId = this.connect('scroll-event', DashExtensions.onScrollEvent.bind(this)); - this._leaveConId = this.connect('leave-event', DashExtensions.onLeaveEvent.bind(this)); - } + this._lastScroll = Date.now(); + + DashExtensions.switchWindow.bind(this)(direction); + return Clutter.EVENT_STOP; }, - _createIcon(size) { - this._iconActor = new St.Icon({ - icon_name: 'focus-windows-symbolic', - icon_size: size, - style_class: 'show-apps-icon', - track_hover: true, - }); - return this._iconActor; + onLeaveEvent() { + if (!this._selectedMetaWin || this.has_pointer || this.toggleButton?.has_pointer) + return; + + this._selectedPreview._activateSelected = false; + this._selectedMetaWin = null; + this._scrolledWindows = null; + DashExtensions.showWindowPreview.bind(this)(null); }, -}; -const ShowRecentFilesIcon = { - _afterInit() { - this._labelText = _('Search Recent Files (Hotkey: Ctrl + Space)'); - this.toggleButton = new St.Button({ - style_class: 'show-apps', - track_hover: true, - can_focus: true, - toggle_mode: false, - }); - this._iconActor = null; - this.icon = new IconGrid.BaseIcon(this.labelText, { - setSizeManually: true, - showLabel: false, - createIcon: this._createIcon.bind(this), - }); - this.icon.y_align = Clutter.ActorAlign.CENTER; + switchWindow(direction) { + if (!this._scrolledWindows) { + this._initialSelection = true; + // source is app icon + if (this.app) { + this._scrolledWindows = this.app.get_windows(); + if (opt.DASH_ISOLATE_WS) { + const currentWs = global.workspaceManager.get_active_workspace(); + this._scrolledWindows = this._scrolledWindows.filter(w => w.get_workspace() === currentWs); + } - this.toggleButton.add_actor(this.icon); - this.toggleButton._delegate = this; + const wsList = []; + this._scrolledWindows.forEach(w => { + const ws = w.get_workspace(); + if (!wsList.includes(ws)) + wsList.push(ws); + }); - this.setChild(this.toggleButton); - }, + // sort windows by workspaces in MRU order + this._scrolledWindows.sort((a, b) => wsList.indexOf(a.get_workspace()) > wsList.indexOf(b.get_workspace())); + // source is Search Windows icon + } else if (this._isSearchWindowsIcon) { + if (opt.SEARCH_WINDOWS_ICON_SCROLL === 1) // all windows + this._scrolledWindows = Me.Util.getWindows(null); + else + this._scrolledWindows = Me.Util.getWindows(global.workspace_manager.get_active_workspace()); + } + } - _createIcon(size) { - this._iconActor = new St.Icon({ - icon_name: 'document-open-recent-symbolic', - icon_size: size, - style_class: 'show-apps-icon', - track_hover: true, - }); - return this._iconActor; + let windows = this._scrolledWindows; + + if (!windows.length) + return; + + // if window selection is in the process, the previewed window must be the current one + let currentWin = this._selectedMetaWin ? this._selectedMetaWin : windows[0]; + + const currentIdx = windows.indexOf(currentWin); + let targetIdx = currentIdx; + // const focusWindow = Me.Util.getWindows(null)[0]; // incompatible 45 + const focusWindow = Me.Util.getWindows(null)[0]; + const appFocused = this._scrolledWindows[0] === focusWindow && this._scrolledWindows[0].get_workspace() === global.workspace_manager.get_active_workspace(); + // only if the app has focus, immediately switch to the previous window + // otherwise just set the current window above others + if (!this._initialSelection || appFocused) + targetIdx += direction; + else + this._initialSelection = false; + + if (targetIdx > windows.length - 1) + targetIdx = 0; + else if (targetIdx < 0) + targetIdx = windows.length - 1; + + const metaWin = windows[targetIdx]; + DashExtensions.showWindowPreview.bind(this)(metaWin); + this._selectedMetaWin = metaWin; }, -}; -const ShowExtensionsIcon = { - _afterInit() { - this._labelText = _('Search Extensions (Hotkey: Ctrl + Shift + Space)'); - this.toggleButton = new St.Button({ - style_class: 'show-apps', - track_hover: true, - can_focus: true, - toggle_mode: false, + showWindowPreview(metaWin) { + const views = Main.overview._overview.controls._workspacesDisplay._workspacesViews; + const viewsIter = [views[0]]; + // secondary monitors use different structure + views.forEach(v => { + if (v._workspacesView) + viewsIter.push(v._workspacesView); }); - this._iconActor = null; - this.icon = new IconGrid.BaseIcon(this.labelText, { - setSizeManually: true, - showLabel: false, - createIcon: this._createIcon.bind(this), - }); - this.icon.y_align = Clutter.ActorAlign.CENTER; + viewsIter.forEach(view => { + // if workspaces are on primary monitor only + if (!view || !view._workspaces) + return; - this.toggleButton.add_actor(this.icon); - this.toggleButton._delegate = this; + view._workspaces.forEach(ws => { + ws._windows.forEach(windowPreview => { + // metaWin === null resets opacity + let opacity = metaWin ? 50 : 255; + windowPreview._activateSelected = false; - this.setChild(this.toggleButton); - }, + // minimized windows are invisible if windows are not exposed (WORKSPACE_MODE === 0) + if (!windowPreview.opacity) + windowPreview.opacity = 255; + + // app windows set to lower opacity, so they can be recognized + if (this._scrolledWindows && this._scrolledWindows.includes(windowPreview.metaWindow)) { + if (opt.DASH_ICON_SCROLL === 2) + opacity = 254; + } + if (windowPreview.metaWindow === metaWin) { + if (metaWin && metaWin.get_workspace() !== global.workspace_manager.get_active_workspace()) { + Main.wm.actionMoveWorkspace(metaWin.get_workspace()); + if (_timeouts.wsSwitcherAnimation) + GLib.source_remove(_timeouts.wsSwitcherAnimation); + // setting window preview above siblings before workspace switcher animation has no effect + // we need to set the window above after the ws preview become visible on the screen + // the default switcher animation time is 250, 200 ms delay should be enough + _timeouts.wsSwitcherAnimation = GLib.timeout_add(0, 200 * St.Settings.get().slow_down_factor, () => { + windowPreview.get_parent().set_child_above_sibling(windowPreview, null); + _timeouts.wsSwitcherAnimation = 0; + return GLib.SOURCE_REMOVE; + }); + } else { + windowPreview.get_parent().set_child_above_sibling(windowPreview, null); + } - _createIcon(size) { - this._iconActor = new St.Icon({ - icon_name: 'application-x-addon-symbolic', - icon_size: size, - style_class: 'show-apps-icon', - track_hover: true, + opacity = 255; + this._selectedPreview = windowPreview; + windowPreview._activateSelected = true; + } + + // if windows are exposed, highlight selected using opacity + if ((opt.OVERVIEW_MODE && opt.WORKSPACE_MODE) || !opt.OVERVIEW_MODE) { + if (metaWin && opacity === 255) + windowPreview.showOverlay(true); + else + windowPreview.hideOverlay(true); + windowPreview.ease({ + duration: 200, + opacity, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + }); + } + }); + }); }); - return this._iconActor; + }, +}; + +const AppIconCommon = { + after__init() { + if (this._updateRunningDotStyle) + this._updateRunningDotStyle(); + }, + + _updateRunningDotStyle() { + if (opt.RUNNING_DOT_STYLE) + this._dot.add_style_class_name('app-well-app-running-dot-custom'); + else + this._dot.remove_style_class_name('app-well-app-running-dot-custom'); }, }; |