summaryrefslogtreecommitdiffstats
path: root/extensions/44/vertical-workspaces/lib
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/44/vertical-workspaces/lib')
-rw-r--r--extensions/44/vertical-workspaces/lib/appDisplay.js1243
-rw-r--r--extensions/44/vertical-workspaces/lib/appFavorites.js72
-rw-r--r--extensions/44/vertical-workspaces/lib/dash.js1410
-rw-r--r--extensions/44/vertical-workspaces/lib/extensionsSearchProvider.js423
-rw-r--r--extensions/44/vertical-workspaces/lib/iconGrid.js131
-rw-r--r--extensions/44/vertical-workspaces/lib/layout.js211
-rw-r--r--extensions/44/vertical-workspaces/lib/messageTray.js112
-rw-r--r--extensions/44/vertical-workspaces/lib/optionsFactory.js251
-rw-r--r--extensions/44/vertical-workspaces/lib/osdWindow.js145
-rw-r--r--extensions/44/vertical-workspaces/lib/overlayKey.js180
-rw-r--r--extensions/44/vertical-workspaces/lib/overview.js140
-rw-r--r--extensions/44/vertical-workspaces/lib/overviewControls.js827
-rw-r--r--extensions/44/vertical-workspaces/lib/panel.js375
-rw-r--r--extensions/44/vertical-workspaces/lib/recentFilesSearchProvider.js292
-rw-r--r--extensions/44/vertical-workspaces/lib/search.js247
-rw-r--r--extensions/44/vertical-workspaces/lib/searchController.js94
-rw-r--r--extensions/44/vertical-workspaces/lib/settings.js300
-rw-r--r--extensions/44/vertical-workspaces/lib/swipeTracker.js95
-rw-r--r--extensions/44/vertical-workspaces/lib/util.js199
-rw-r--r--extensions/44/vertical-workspaces/lib/winTmb.js525
-rw-r--r--extensions/44/vertical-workspaces/lib/windowAttentionHandler.js80
-rw-r--r--extensions/44/vertical-workspaces/lib/windowManager.js148
-rw-r--r--extensions/44/vertical-workspaces/lib/windowPreview.js544
-rw-r--r--extensions/44/vertical-workspaces/lib/windowSearchProvider.js229
-rw-r--r--extensions/44/vertical-workspaces/lib/workspace.js75
-rw-r--r--extensions/44/vertical-workspaces/lib/workspaceAnimation.js234
-rw-r--r--extensions/44/vertical-workspaces/lib/workspaceSwitcherPopup.js75
-rw-r--r--extensions/44/vertical-workspaces/lib/workspaceThumbnail.js248
-rw-r--r--extensions/44/vertical-workspaces/lib/workspacesView.js359
29 files changed, 6083 insertions, 3181 deletions
diff --git a/extensions/44/vertical-workspaces/lib/appDisplay.js b/extensions/44/vertical-workspaces/lib/appDisplay.js
index 2ac70b1..aeb2808 100644
--- a/extensions/44/vertical-workspaces/lib/appDisplay.js
+++ b/extensions/44/vertical-workspaces/lib/appDisplay.js
@@ -10,246 +10,501 @@
'use strict';
-const { Clutter, GLib, GObject, Meta, Shell, St, Graphene, Pango } = imports.gi;
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Graphene = imports.gi.Graphene;
+const Meta = imports.gi.Meta;
+const Pango = imports.gi.Pango;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
const AppDisplay = imports.ui.appDisplay;
+const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
+const Main = imports.ui.main;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-const IconGridOverride = Me.imports.lib.iconGrid;
-const _Util = Me.imports.lib.util;
+let Me;
+let opt;
-const DIALOG_SHADE_NORMAL = Clutter.Color.from_pixel(0x00000022);
-const DIALOG_SHADE_HIGHLIGHT = Clutter.Color.from_pixel(0x00000000);
+let _timeouts;
-// gettext
-const _ = Me.imports.lib.settings._;
+// DIALOG_SHADE_NORMAL = Clutter.Color.from_pixel(0x00000022);
+// DIALOG_SHADE_HIGHLIGHT = Clutter.Color.from_pixel(0x00000000);
-let _overrides;
+var AppDisplayModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
-let _appGridLayoutSettings;
-let _appDisplayScrollConId;
-let _appSystemStateConId;
-let _appGridLayoutConId;
-let _origAppViewItemAcceptDrop;
-let _updateFolderIcons;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
-let opt;
-let shellVersion = _Util.shellVersion;
-let _firstRun = true;
+ this._appGridLayoutSettings = null;
+ this._appDisplayScrollConId = 0;
+ this._appSystemStateConId = 0;
+ this._appGridLayoutConId = 0;
+ this._origAppViewItemAcceptDrop = null;
+ this._updateFolderIcons = 0;
+ }
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('appDisplayModule', true);
- reset = reset || !moduleEnabled;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ update(reset) {
+ this._removeTimeouts();
+ this.moduleEnabled = opt.get('appDisplayModule');
+ const conflict = false;
- _firstRun = false;
+ reset = reset || !this.moduleEnabled || conflict;
- if (_overrides)
- _overrides.removeAll();
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ this.moduleEnabled = false;
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation) {
+ this.moduleEnabled = false;
+ console.debug(' AppDisplayModule - Keeping untouched');
+ }
+ }
- if (reset) {
- _setAppDisplayOrientation(false);
- _updateAppGridProperties(reset);
- _updateAppGridDND(reset);
- _restoreOverviewGroup();
- _overrides = null;
- opt = null;
- return;
+ _activateModule() {
+ Me.Modules.iconGridModule.update();
+
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ _timeouts = {};
+
+ // Common
+ this._overrides.addOverride('FolderView', AppDisplay.FolderView.prototype, FolderView);
+ this._overrides.addOverride('FolderIcon', AppDisplay.FolderIcon.prototype, FolderIcon);
+ if (opt.APP_GRID_ACTIVE_PREVIEW)
+ this._overrides.addOverride('ActiveFolderIcon', AppDisplay.FolderIcon, ActiveFolderIcon);
+ this._overrides.addOverride('AppIcon', AppDisplay.AppIcon.prototype, AppIcon);
+ this._overrides.addOverride('AppDisplay', AppDisplay.AppDisplay.prototype, AppDisplayCommon);
+ this._overrides.addOverride('AppViewItem', AppDisplay.AppViewItem.prototype, AppViewItemCommon);
+ this._overrides.addOverride('BaseAppViewCommon', AppDisplay.BaseAppView.prototype, BaseAppViewCommon);
+
+ if (opt.ORIENTATION === Clutter.Orientation.VERTICAL) {
+ this._overrides.addOverride('AppDisplayVertical', AppDisplay.AppDisplay.prototype, AppDisplayVertical);
+ this._overrides.addOverride('BaseAppViewVertical', AppDisplay.BaseAppView.prototype, BaseAppViewVertical);
+ }
+
+ // Custom App Grid
+ this._overrides.addOverride('AppFolderDialog', AppDisplay.AppFolderDialog.prototype, AppFolderDialog);
+ if (Me.shellVersion >= 43) {
+ // const defined class needs to be touched before real access
+ this._dummy = AppDisplay.AppGrid;
+ delete this._dummy;
+ // BaseAppViewGridLayout is not exported, we can only access current instance
+ this._overrides.addOverride('BaseAppViewGridLayout', Main.overview._overview.controls._appDisplay._appGridLayout, BaseAppViewGridLayout);
+ this._overrides.addOverride('FolderGrid', AppDisplay.FolderGrid.prototype, FolderGrid);
+ } else {
+ this._overrides.addOverride('FolderGrid', AppDisplay.FolderGrid.prototype, FolderGridLegacy);
+ }
+
+ this._setAppDisplayOrientation(opt.ORIENTATION === Clutter.Orientation.VERTICAL);
+ this._updateDND();
+ if (!Main.sessionMode.isGreeter)
+ this._updateAppDisplayProperties();
+
+ console.debug(' AppDisplayModule - Activated');
}
- _overrides = new _Util.Overrides();
+ _disableModule() {
+ Me.Modules.iconGridModule.update(true);
+
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
- if (opt.ORIENTATION === Clutter.Orientation.VERTICAL) {
- _overrides.addOverride('AppDisplayVertical', AppDisplay.AppDisplay.prototype, AppDisplayVertical);
- _overrides.addOverride('BaseAppViewVertical', AppDisplay.BaseAppView.prototype, BaseAppViewVertical);
+ const reset = true;
+ this._setAppDisplayOrientation(false);
+ this._updateAppDisplayProperties(reset);
+ this._updateDND(reset);
+ this._restoreOverviewGroup();
+ this._removeStatusMessage();
+
+ console.debug(' AppDisplayModule - Disabled');
}
- // Custom App Grid
- _overrides.addOverride('AppFolderDialog', AppDisplay.AppFolderDialog.prototype, AppFolderDialog);
- if (shellVersion >= 43) {
- // const defined class needs to be touched before real access
- AppDisplay.BaseAppViewGridLayout;
- _overrides.addOverride('BaseAppViewGridLayout', AppDisplay.BaseAppViewGridLayout.prototype, BaseAppViewGridLayout);
+ _removeTimeouts() {
+ if (_timeouts) {
+ Object.values(_timeouts).forEach(t => {
+ if (t)
+ GLib.source_remove(t);
+ });
+ _timeouts = null;
+ }
}
- _overrides.addOverride('FolderView', AppDisplay.FolderView.prototype, FolderView);
- _overrides.addOverride('FolderIcon', AppDisplay.FolderIcon.prototype, FolderIcon);
- _overrides.addOverride('AppIcon', AppDisplay.AppIcon.prototype, AppIcon);
- _overrides.addOverride('AppDisplay', AppDisplay.AppDisplay.prototype, AppDisplayCommon);
- _overrides.addOverride('AppViewItem', AppDisplay.AppViewItem.prototype, AppViewItemCommon);
- _overrides.addOverride('BaseAppViewCommon', AppDisplay.BaseAppView.prototype, BaseAppViewCommon);
-
- _setAppDisplayOrientation(opt.ORIENTATION === Clutter.Orientation.VERTICAL);
- _updateAppGridProperties();
- _updateAppGridDND();
- opt._appGridNeedsRedisplay = true;
-}
-
-function _setAppDisplayOrientation(vertical = false) {
- const CLUTTER_ORIENTATION = vertical ? Clutter.Orientation.VERTICAL : Clutter.Orientation.HORIZONTAL;
- const scroll = vertical ? 'vscroll' : 'hscroll';
- // app display to vertical has issues - page indicator not working
- // global appDisplay orientation switch is not built-in
- let appDisplay = Main.overview._overview._controls._appDisplay;
- // following line itself only changes in which axis will operate overshoot detection which switches appDisplay pages while dragging app icon to vertical
- appDisplay._orientation = CLUTTER_ORIENTATION;
- appDisplay._grid.layoutManager._orientation = CLUTTER_ORIENTATION;
- appDisplay._swipeTracker.orientation = CLUTTER_ORIENTATION;
- appDisplay._swipeTracker._reset();
- if (vertical) {
- appDisplay._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.EXTERNAL);
-
- // move and change orientation of page indicators
- // needs corrections in appgrid page calculations, e.g. appDisplay.adaptToSize() fnc,
- // which complicates use of super call inside the function
- const pageIndicators = appDisplay._pageIndicators;
- pageIndicators.vertical = true;
- appDisplay._box.vertical = false;
- pageIndicators.x_expand = false;
- pageIndicators.y_align = Clutter.ActorAlign.CENTER;
- pageIndicators.x_align = Clutter.ActorAlign.START;
-
- const scrollContainer = appDisplay._scrollView.get_parent();
- if (shellVersion < 43) {
- // remove touch friendly side navigation bars / arrows
- if (appDisplay._hintContainer && appDisplay._hintContainer.get_parent())
- scrollContainer.remove_child(appDisplay._hintContainer);
+
+ _setAppDisplayOrientation(vertical = false) {
+ const CLUTTER_ORIENTATION = vertical ? Clutter.Orientation.VERTICAL : Clutter.Orientation.HORIZONTAL;
+ const scroll = vertical ? 'vscroll' : 'hscroll';
+ // app display to vertical has issues - page indicator not working
+ // global appDisplay orientation switch is not built-in
+ let appDisplay = Main.overview._overview._controls._appDisplay;
+ // following line itself only changes in which axis will operate overshoot detection which switches appDisplay pages while dragging app icon to vertical
+ appDisplay._orientation = CLUTTER_ORIENTATION;
+ appDisplay._grid.layoutManager._orientation = CLUTTER_ORIENTATION;
+ appDisplay._swipeTracker.orientation = CLUTTER_ORIENTATION;
+ appDisplay._swipeTracker._reset();
+ if (vertical) {
+ appDisplay._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.EXTERNAL);
+
+ // move and change orientation of page indicators
+ const pageIndicators = appDisplay._pageIndicators;
+ pageIndicators.vertical = true;
+ appDisplay._box.vertical = false;
+ pageIndicators.x_expand = false;
+ pageIndicators.y_align = Clutter.ActorAlign.CENTER;
+ pageIndicators.x_align = Clutter.ActorAlign.START;
+
+ const scrollContainer = appDisplay._scrollView.get_parent();
+ if (Me.shellVersion < 43) {
+ // remove touch friendly side navigation bars / arrows
+ if (appDisplay._hintContainer && appDisplay._hintContainer.get_parent())
+ scrollContainer.remove_child(appDisplay._hintContainer);
+ } else {
+ // moving these bars needs more patching of the appDisplay's code
+ // for now we just change bars style to be more like vertically oriented arrows indicating direction to prev/next page
+ appDisplay._nextPageIndicator.add_style_class_name('nextPageIndicator');
+ appDisplay._prevPageIndicator.add_style_class_name('prevPageIndicator');
+ }
+
+ // setting their x_scale to 0 removes the arrows and avoid allocation issues compared to .hide() them
+ appDisplay._nextPageArrow.scale_x = 0;
+ appDisplay._prevPageArrow.scale_x = 0;
} else {
- // moving these bars needs more patching of the appDisplay's code
- // for now we just change bars style to be more like vertically oriented arrows indicating direction to prev/next page
- appDisplay._nextPageIndicator.add_style_class_name('nextPageIndicator');
- appDisplay._prevPageIndicator.add_style_class_name('prevPageIndicator');
- }
+ appDisplay._scrollView.set_policy(St.PolicyType.EXTERNAL, St.PolicyType.NEVER);
+ if (this._appDisplayScrollConId) {
+ appDisplay._adjustment.disconnect(this._appDisplayScrollConId);
+ this._appDisplayScrollConId = 0;
+ }
- // setting their x_scale to 0 removes the arrows and avoid allocation issues compared to .hide() them
- appDisplay._nextPageArrow.scale_x = 0;
- appDisplay._prevPageArrow.scale_x = 0;
- } else {
- appDisplay._scrollView.set_policy(St.PolicyType.EXTERNAL, St.PolicyType.NEVER);
- if (_appDisplayScrollConId) {
- appDisplay._adjustment.disconnect(_appDisplayScrollConId);
- _appDisplayScrollConId = 0;
+ // restore original page indicators
+ const pageIndicators = appDisplay._pageIndicators;
+ pageIndicators.vertical = false;
+ appDisplay._box.vertical = true;
+ pageIndicators.x_expand = true;
+ pageIndicators.y_align = Clutter.ActorAlign.END;
+ pageIndicators.x_align = Clutter.ActorAlign.CENTER;
+
+ // put back touch friendly navigation bars/buttons
+ const scrollContainer = appDisplay._scrollView.get_parent();
+ if (appDisplay._hintContainer && !appDisplay._hintContainer.get_parent()) {
+ scrollContainer.add_child(appDisplay._hintContainer);
+ // the hit container covers the entire app grid and added at the top of the stack blocks DND drops
+ // so it needs to be pushed below
+ scrollContainer.set_child_below_sibling(appDisplay._hintContainer, null);
+ }
+
+ appDisplay._nextPageArrow.scale_x = 1;
+ appDisplay._prevPageArrow.scale_x = 1;
+
+ appDisplay._nextPageIndicator.remove_style_class_name('nextPageIndicator');
+ appDisplay._prevPageIndicator.remove_style_class_name('prevPageIndicator');
}
- // restore original page indicators
- const pageIndicators = appDisplay._pageIndicators;
- pageIndicators.vertical = false;
- appDisplay._box.vertical = true;
- pageIndicators.x_expand = true;
- pageIndicators.y_align = Clutter.ActorAlign.END;
- pageIndicators.x_align = Clutter.ActorAlign.CENTER;
-
- // put back touch friendly navigation bars/buttons
- const scrollContainer = appDisplay._scrollView.get_parent();
- if (appDisplay._hintContainer && !appDisplay._hintContainer.get_parent()) {
- scrollContainer.add_child(appDisplay._hintContainer);
- // the hit container covers the entire app grid and added at the top of the stack blocks DND drops
- // so it needs to be pushed below
- scrollContainer.set_child_below_sibling(appDisplay._hintContainer, null);
+ // value for page indicator is calculated from scroll adjustment, horizontal needs to be replaced by vertical
+ appDisplay._adjustment = appDisplay._scrollView[scroll].adjustment;
+
+ // no need to connect already connected signal (wasn't removed the original one before)
+ if (!vertical) {
+ // reset used appDisplay properties
+ Main.overview._overview._controls._appDisplay.scale_y = 1;
+ Main.overview._overview._controls._appDisplay.scale_x = 1;
+ Main.overview._overview._controls._appDisplay.opacity = 255;
+ return;
}
- appDisplay._nextPageArrow.scale_x = 1;
- appDisplay._prevPageArrow.scale_x = 1;
+ // update appGrid dot pages indicators
+ this._appDisplayScrollConId = appDisplay._adjustment.connect('notify::value', adj => {
+ const value = adj.value / adj.page_size;
+ appDisplay._pageIndicators.setCurrentPosition(value);
+ });
+ }
+
+ // Set App Grid columns, rows, icon size, incomplete pages
+ _updateAppDisplayProperties(reset = false) {
+ opt._appGridNeedsRedisplay = false;
+ // columns, rows, icon size
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ appDisplay.visible = true;
+ if (reset) {
+ appDisplay._grid.layoutManager.fixedIconSize = -1;
+ appDisplay._grid.layoutManager.allow_incomplete_pages = true;
+ appDisplay._grid._currentMode = -1;
+ appDisplay._grid.setGridModes();
+ if (this._appGridLayoutSettings) {
+ this._appGridLayoutSettings.disconnect(this._appGridLayoutConId);
+ this._appGridLayoutConId = 0;
+ this._appGridLayoutSettings = null;
+ }
+ appDisplay._redisplay();
- appDisplay._nextPageIndicator.remove_style_class_name('nextPageIndicator');
- appDisplay._prevPageIndicator.remove_style_class_name('prevPageIndicator');
+ appDisplay._grid.set_style('');
+ this._updateAppGrid(reset);
+ } else {
+ // update grid on layout reset
+ if (!this._appGridLayoutSettings) {
+ this._appGridLayoutSettings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
+ this._appGridLayoutConId = this._appGridLayoutSettings.connect('changed::app-picker-layout', this._updateLayout);
+ }
+
+ appDisplay._grid.layoutManager.allow_incomplete_pages = opt.APP_GRID_ALLOW_INCOMPLETE_PAGES;
+ // appDisplay._grid.set_style(`column-spacing: ${opt.APP_GRID_SPACING}px; row-spacing: ${opt.APP_GRID_SPACING}px;`);
+ // APP_GRID_SPACING constant is used for grid dimensions calculation
+ // but sometimes the actual grid spacing properties affect/change the calculated size, therefore we set it lower to avoid this problem
+ // main app grid always use available space and the spacing is optimized for the grid dimensions
+ appDisplay._grid.set_style('column-spacing: 5px; row-spacing: 5px;');
+
+ // force redisplay
+ appDisplay._grid._currentMode = -1;
+ appDisplay._grid.setGridModes();
+ appDisplay._grid.layoutManager.fixedIconSize = opt.APP_GRID_ICON_SIZE;
+ // avoid resetting appDisplay before startup animation
+ // x11 shell restart skips startup animation
+ if (!Main.layoutManager._startingUp) {
+ this._updateAppGrid();
+ } else if (Main.layoutManager._startingUp && (Meta.is_restart() || Me.Util.dashIsDashToDock())) {
+ _timeouts.three = GLib.idle_add(GLib.PRIORITY_LOW, () => {
+ this._updateAppGrid();
+ _timeouts.three = 0;
+ return GLib.SOURCE_REMOVE;
+ });
+ }
+ }
}
- // value for page indicator is calculated from scroll adjustment, horizontal needs to be replaced by vertical
- appDisplay._adjustment = appDisplay._scrollView[scroll].adjustment;
+ _updateDND(reset) {
+ if (!reset) {
+ if (!this._appSystemStateConId && opt.APP_GRID_INCLUDE_DASH >= 3) {
+ this._appSystemStateConId = Shell.AppSystem.get_default().connect(
+ 'app-state-changed',
+ () => {
+ this._updateFolderIcons = true;
+ Main.overview._overview.controls._appDisplay._redisplay();
+ }
+ );
+ }
+ } else if (this._appSystemStateConId) {
+ Shell.AppSystem.get_default().disconnect(this._appSystemStateConId);
+ this._appSystemStateConId = 0;
+ }
+ }
- // no need to connect already connected signal (wasn't removed the original one before)
- if (!vertical) {
- // reset used appDisplay properties
- Main.overview._overview._controls._appDisplay.scale_y = 1;
- Main.overview._overview._controls._appDisplay.scale_x = 1;
+ _restoreOverviewGroup() {
+ Main.overview.dash.showAppsButton.checked = false;
+ Main.layoutManager.overviewGroup.opacity = 255;
+ Main.layoutManager.overviewGroup.scale_x = 1;
+ Main.layoutManager.overviewGroup.scale_y = 1;
+ Main.layoutManager.overviewGroup.hide();
+ Main.overview._overview._controls._appDisplay.translation_x = 0;
+ Main.overview._overview._controls._appDisplay.translation_y = 0;
+ Main.overview._overview._controls._appDisplay.visible = true;
Main.overview._overview._controls._appDisplay.opacity = 255;
- return;
}
- // update appGrid dot pages indicators
- _appDisplayScrollConId = appDisplay._adjustment.connect('notify::value', adj => {
- const value = adj.value / adj.page_size;
- appDisplay._pageIndicators.setCurrentPosition(value);
- });
-}
-
-// Set App Grid columns, rows, icon size, incomplete pages
-function _updateAppGridProperties(reset = false) {
- opt._appGridNeedsRedisplay = false;
- // columns, rows, icon size
- const appDisplay = Main.overview._overview._controls._appDisplay;
- appDisplay.visible = true;
-
- if (reset) {
- appDisplay._grid.layoutManager.fixedIconSize = -1;
- appDisplay._grid.layoutManager.allow_incomplete_pages = true;
- appDisplay._grid.setGridModes();
- if (_appGridLayoutSettings) {
- _appGridLayoutSettings.disconnect(_appGridLayoutConId);
- _appGridLayoutConId = 0;
- _appGridLayoutSettings = null;
+ // update all invalid positions that may be result of grid/icon size change
+ _updateIconPositions() {
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ const layout = JSON.stringify(global.settings.get_value('app-picker-layout').recursiveUnpack());
+ // if app grid layout is empty, sort source alphabetically to avoid misplacing
+ if (layout === JSON.stringify([]) && appDisplay._sortOrderedItemsAlphabetically)
+ appDisplay._sortOrderedItemsAlphabetically();
+ const icons = [...appDisplay._orderedItems];
+ for (let i = 0; i < icons.length; i++)
+ appDisplay._moveItem(icons[i], -1, -1);
+ }
+
+ _removeIcons() {
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ const icons = [...appDisplay._orderedItems];
+ for (let i = 0; i < icons.length; i++) {
+ const icon = icons[i];
+ if (icon._dialog)
+ Main.layoutManager.overviewGroup.remove_child(icon._dialog);
+ appDisplay._removeItem(icon);
+ icon.destroy();
}
- appDisplay._redisplay();
+ appDisplay._folderIcons = [];
+ }
+
+ _removeStatusMessage() {
+ if (Me._vShellStatusMessage) {
+ if (Me._vShellMessageTimeoutId) {
+ GLib.source_remove(Me._vShellMessageTimeoutId);
+ Me._vShellMessageTimeoutId = 0;
+ }
+ Me._vShellStatusMessage.destroy();
+ Me._vShellStatusMessage = null;
+ }
+ }
- appDisplay._grid.set_style('');
- _resetAppGrid();
- } else {
- // update grid on layout reset
- if (!_appGridLayoutSettings) {
- _appGridLayoutSettings = ExtensionUtils.getSettings('org.gnome.shell');
- _appGridLayoutConId = _appGridLayoutSettings.connect('changed::app-picker-layout', _resetAppGrid);
+ _updateLayout(settings, key) {
+ const currentValue = JSON.stringify(settings.get_value(key).deep_unpack());
+ const emptyValue = JSON.stringify([]);
+ const customLayout = currentValue !== emptyValue;
+ if (!customLayout) {
+ this._updateAppGrid();
+ }
+ }
+
+ _updateAppGrid(reset = false, callback) {
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ // reset the grid only if called directly without args or if all folders where removed by using reset button in Settings window
+ // otherwise this function is called every time a user moves icon to another position as a settings callback
+
+ // force update icon size using adaptToSize(), the page size cannot be the same as the current one
+ appDisplay._grid.layoutManager._pageWidth += 1;
+ appDisplay._grid.layoutManager.adaptToSize(appDisplay._grid.layoutManager._pageWidth - 1, appDisplay._grid.layoutManager._pageHeight);
+
+ // don't delay the first screen lock on GS < 44, removing icons takes a time and with other 15 enabled extensions it can be multiplied by 15
+ if (!Main.sessionMode.isLocked)
+ this._removeIcons();
+
+ appDisplay._redisplay();
+ // don't realize appDisplay on disable, or at startup if disabled
+ // always realize appDisplay otherwise to avoid errors while opening folders (that I was unable to trace)
+ if (reset || (!opt.APP_GRID_PERFORMANCE && callback)) {
+ this._removeStatusMessage();
+ if (callback)
+ callback();
+ return;
}
- appDisplay._grid.layoutManager.allow_incomplete_pages = opt.APP_GRID_ALLOW_INCOMPLETE_PAGES;
- appDisplay._grid.set_style(`column-spacing: ${opt.APP_GRID_SPACING}px; row-spacing: ${opt.APP_GRID_SPACING}px;`);
+ // workaround - silently realize appDisplay
+ // appDisplay and its content must be "visible" (opacity > 0) on the screen (within monitor geometry)
+ // to realize its objects
+ // this action takes some time and affects animations during the first use
+ // if we do it invisibly before user needs it, it can improve the user's experience
+
+ this._exposeAppGrid();
+
+ // let the main loop process our changes before continuing
+ _timeouts.one = GLib.idle_add(GLib.PRIORITY_LOW, () => {
+ this._updateIconPositions();
+ if (appDisplay._sortOrderedItemsAlphabetically) {
+ appDisplay._sortOrderedItemsAlphabetically();
+ appDisplay._grid.layoutManager._pageWidth += 1;
+ appDisplay._grid.layoutManager.adaptToSize(appDisplay._grid.layoutManager._pageWidth - 1, appDisplay._grid.layoutManager._pageHeight);
+ appDisplay._setLinearPositions(appDisplay._orderedItems);
+ }
- // force redisplay
- appDisplay._grid._currentMode = -1;
- appDisplay._grid.setGridModes();
- appDisplay._grid.layoutManager.fixedIconSize = opt.APP_GRID_ICON_SIZE;
- // appDisplay._folderIcons.forEach(folder => folder._dialog?._updateFolderSize());
- _resetAppGrid();
+ appDisplay._redisplay();
+ // realize also all app folders (by opening them) so the first popup is as smooth as the second one
+ // let the main loop process our changes before continuing
+ _timeouts.two = GLib.idle_add(GLib.PRIORITY_LOW, () => {
+ this._restoreAppGrid();
+ Me._resetInProgress = false;
+ this._removeStatusMessage();
+
+ if (callback)
+ callback();
+
+ _timeouts.two = 0;
+ return GLib.SOURCE_REMOVE;
+ });
+ _timeouts.one = 0;
+ return GLib.SOURCE_REMOVE;
+ });
}
-}
-function _updateAppGridDND(reset) {
- if (!reset) {
- if (!_appSystemStateConId && opt.APP_GRID_INCLUDE_DASH >= 3) {
- _appSystemStateConId = Shell.AppSystem.get_default().connect(
- 'app-state-changed',
- () => {
- _updateFolderIcons = true;
- Main.overview._overview._controls._appDisplay._redisplay();
- }
- );
+ _exposeAppGrid() {
+ const overviewGroup = Main.layoutManager.overviewGroup;
+ if (!overviewGroup.visible) {
+ // scale down the overviewGroup so it don't cover uiGroup
+ overviewGroup.scale_y = 0.001;
+ // make it invisible to the eye, but visible for the renderer
+ overviewGroup.opacity = 1;
+ // if overview is hidden, show it
+ overviewGroup.visible = true;
}
- } else if (_appSystemStateConId) {
- Shell.AppSystem.get_default().disconnect(_appSystemStateConId);
- _appSystemStateConId = 0;
+
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ appDisplay.opacity = 1;
+
+ // find usable value, sometimes it's one, sometime the other...
+ let [x, y] = appDisplay.get_position();
+ let { x1, y1 } = appDisplay.allocation;
+ x = x === Infinity ? 0 : x;
+ y = y === Infinity ? 0 : y;
+ x1 = x1 === Infinity ? 0 : x1;
+ y1 = y1 === Infinity ? 0 : y1;
+ appDisplay.translation_x = -(x ? x : x1);
+ appDisplay.translation_y = -(y ? y : y1);
+ this._exposeAppFolders();
+ }
+
+ _exposeAppFolders() {
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ appDisplay._folderIcons.forEach(d => {
+ d._ensureFolderDialog();
+ d._dialog._updateFolderSize();
+ d._dialog.scale_y = 0.0001;
+ d._dialog.show();
+ });
+ }
+
+ _restoreAppGrid() {
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ appDisplay.translation_x = 0;
+ appDisplay.translation_y = 0;
+ // appDisplay.opacity = 0;
+ this._hideAppFolders();
+
+ const overviewGroup = Main.layoutManager.overviewGroup;
+ if (!Main.overview._shown)
+ overviewGroup.hide();
+ overviewGroup.scale_y = 1;
+ overviewGroup.opacity = 255;
+
+ this._removeStatusMessage();
+ }
+
+ _hideAppFolders() {
+ const appDisplay = Main.overview._overview._controls._appDisplay;
+ appDisplay._folderIcons.forEach(d => {
+ if (d._dialog) {
+ d._dialog._updateFolderSize();
+ d._dialog.hide();
+ d._dialog.scale_y = 1;
+ }
+ });
+ }
+
+ _getWindowApp(metaWin) {
+ const tracker = Shell.WindowTracker.get_default();
+ return tracker.get_window_app(metaWin);
}
- if (opt.APP_GRID_ORDER && !reset) {
- if (!_origAppViewItemAcceptDrop)
- _origAppViewItemAcceptDrop = AppDisplay.AppViewItem.prototype.acceptDrop;
- AppDisplay.AppViewItem.prototype.acceptDrop = () => false;
- } else if (_origAppViewItemAcceptDrop) {
- AppDisplay.AppViewItem.prototype.acceptDrop = _origAppViewItemAcceptDrop;
+
+ _getAppLastUsedWindow(app) {
+ let recentWin;
+ global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null).forEach(metaWin => {
+ const winApp = this._getWindowApp(metaWin);
+ if (!recentWin && winApp === app)
+ recentWin = metaWin;
+ });
+ return recentWin;
}
-}
-function _restoreOverviewGroup() {
- Main.overview.dash.showAppsButton.checked = false;
- Main.layoutManager.overviewGroup.opacity = 255;
- Main.layoutManager.overviewGroup.scale_x = 1;
- Main.layoutManager.overviewGroup.hide();
-}
+ _getAppRecentWorkspace(app) {
+ const recentWin = this._getAppLastUsedWindow(app);
+ if (recentWin)
+ return recentWin.get_workspace();
+
+ return null;
+ }
+};
const AppDisplayVertical = {
// correction of the appGrid size when page indicators were moved from the bottom to the right
@@ -302,7 +557,7 @@ const AppDisplayCommon = {
const appsInsideFolders = new Set();
this._folderIcons = [];
- if (!opt.APP_GRID_ORDER) {
+ if (!opt.APP_GRID_USAGE) {
let folders = this._folderSettings.get_strv('folder-children');
folders.forEach(id => {
let path = `${this._folderSettings.path}folders/${id}/`;
@@ -317,8 +572,8 @@ const AppDisplayCommon = {
if (icon.pressed)
this.updateDragFocus(icon);
});
- } else if (_updateFolderIcons && opt.APP_GRID_EXCLUDE_RUNNING) {
- // if any app changed its running state, update folder icon
+ } else if (this._updateFolderIcons && opt.APP_GRID_EXCLUDE_RUNNING) {
+ // if any app changed its running state, update folder icon
icon.icon.update();
}
@@ -334,8 +589,9 @@ const AppDisplayCommon = {
icon.getAppIds().forEach(appId => appsInsideFolders.add(appId));
});
}
+
// reset request to update active icon
- _updateFolderIcons = false;
+ this._updateFolderIcons = false;
// Allow dragging of the icon only if the Dash would accept a drop to
// change favorite-apps. There are no other possible drop targets from
@@ -348,7 +604,7 @@ const AppDisplayCommon = {
global.settings.is_writable('app-picker-layout');
apps.forEach(appId => {
- if (!opt.APP_GRID_ORDER && appsInsideFolders.has(appId))
+ if (!opt.APP_GRID_USAGE && appsInsideFolders.has(appId))
return;
let icon = this._items.get(appId);
@@ -380,7 +636,7 @@ const AppDisplayCommon = {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
- if (shellVersion < 43)
+ if (Me.shellVersion < 43)
this._slideSidePages(AppDisplay.SidePages.PREVIOUS | AppDisplay.SidePages.NEXT | AppDisplay.SidePages.DND);
else
this._appGridLayout.showPageIndicators();
@@ -419,50 +675,16 @@ const AppDisplayCommon = {
this._redisplay();
},
- // accept source from active preview
+ // accept source from active folder preview
acceptDrop(source) {
- if (opt.APP_GRID_ORDER)
+ if (opt.APP_GRID_USAGE)
return false;
if (source._sourceItem)
source = source._sourceItem;
- let dropTarget = null;
- if (shellVersion >= 43) {
- dropTarget = this._dropTarget;
- delete this._dropTarget;
- }
-
- if (!this._canAccept(source))
+ if (!BaseAppViewCommon.acceptDrop.bind(this)(source))
return false;
- if ((shellVersion < 43 && this._dropPage) ||
- (shellVersion >= 43 && (dropTarget === this._prevPageIndicator ||
- dropTarget === this._nextPageIndicator))) {
- let increment;
-
- if (shellVersion < 43)
- increment = this._dropPage === AppDisplay.SidePages.NEXT ? 1 : -1;
- else
- increment = dropTarget === this._prevPageIndicator ? -1 : 1;
-
- const { currentPage, nPages } = this._grid;
- const page = Math.min(currentPage + increment, nPages);
- const position = page < nPages ? -1 : 0;
-
- this._moveItem(source, page, position);
- this.goToPage(page);
- } else if (this._delayedMoveData) {
- // Dropped before the icon was moved
- const { page, position } = this._delayedMoveData;
-
- try {
- this._moveItem(source, page, position);
- } catch (e) {
- log(`Warning:${e}`);
- }
- this._removeDelayedMove();
- }
-
this._savePages();
let view = AppDisplay._getViewFromIcon(source);
@@ -493,7 +715,7 @@ const BaseAppViewVertical = {
this._pageIndicators.x_align = Clutter.ActorAlign.START;
this._pageIndicators.set_style('margin-right: 10px;');
const scrollContainer = this._scrollView.get_parent();
- if (shellVersion < 43) {
+ if (Me.shellVersion < 43) {
// remove touch friendly side navigation bars / arrows
if (this._hintContainer && this._hintContainer.get_parent())
scrollContainer.remove_child(this._hintContainer);
@@ -536,7 +758,7 @@ const BaseAppViewCommon = {
try {
this._moveItem(icon, page, position);
} catch (e) {
- log(`Warning:${e}`);
+ console.warn(`Warning:${e}`);
}
});
},
@@ -570,14 +792,19 @@ const BaseAppViewCommon = {
}
});
- // sort all alphabetically
- if (opt.APP_GRID_ORDER > 0) {
+ // different options for root app grid and app folders
+ const thisIsFolder = this instanceof AppDisplay.FolderView;
+ const thisIsAppDisplay = !thisIsFolder;
+ if ((opt.APP_GRID_ORDER && thisIsAppDisplay) ||
+ (opt.APP_FOLDER_ORDER && thisIsFolder)) {
// const { itemsPerPage } = this._grid;
let appIcons = this._orderedItems;
+ // sort all alphabetically
this._sortOrderedItemsAlphabetically(appIcons);
// appIcons.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
// then sort used apps by usage
- if (opt.APP_GRID_ORDER === 2)
+ if ((opt.APP_GRID_USAGE && thisIsAppDisplay) ||
+ (opt.APP_FOLDER_USAGE && thisIsFolder))
appIcons.sort((a, b) => Shell.AppUsage.get_default().compare(a.app.id, b.app.id));
// sort favorites first
@@ -595,9 +822,14 @@ const BaseAppViewCommon = {
}
// sort running first
- if (opt.APP_GRID_DASH_FIRST)
+ if (opt.APP_GRID_DASH_FIRST && thisIsAppDisplay)
appIcons.sort((a, b) => a.app.get_state() !== Shell.AppState.RUNNING && b.app.get_state() === Shell.AppState.RUNNING);
+ if (opt.APP_GRID_FOLDERS_FIRST)
+ appIcons.sort((a, b) => b._folder && !a._folder);
+ else if (opt.APP_GRID_FOLDERS_LAST)
+ appIcons.sort((a, b) => a._folder && !b._folder);
+
this._setLinearPositions(appIcons);
this._orderedItems = appIcons;
@@ -611,7 +843,7 @@ const BaseAppViewCommon = {
},
_canAccept(source) {
- return opt.APP_GRID_ORDER ? false : source instanceof AppDisplay.AppViewItem;
+ return source instanceof AppDisplay.AppViewItem;
},
// support active preview icons
@@ -619,12 +851,25 @@ const BaseAppViewCommon = {
if (!this._canAccept(source))
return false;
- if (source._sourceItem)
- source = source._sourceItem;
+ let dropTarget = null;
+ if (Me.shellVersion >= 43) {
+ dropTarget = this._dropTarget;
+ delete this._dropTarget;
+ }
+
+ if (!this._canAccept(source))
+ return false;
+ if ((Me.shellVersion < 43 && this._dropPage) ||
+ (Me.shellVersion >= 43 && (dropTarget === this._prevPageIndicator ||
+ dropTarget === this._nextPageIndicator))) {
+ let increment;
+
+ if (Me.shellVersion < 43)
+ increment = this._dropPage === AppDisplay.SidePages.NEXT ? 1 : -1;
+ else
+ increment = dropTarget === this._prevPageIndicator ? -1 : 1;
- if (this._dropPage) {
- const increment = this._dropPage === AppDisplay.SidePages.NEXT ? 1 : -1;
const { currentPage, nPages } = this._grid;
const page = Math.min(currentPage + increment, nPages);
const position = page < nPages ? -1 : 0;
@@ -635,7 +880,11 @@ const BaseAppViewCommon = {
// Dropped before the icon was moved
const { page, position } = this._delayedMoveData;
- this._moveItem(source, page, position);
+ try {
+ this._moveItem(source, page, position);
+ } catch (e) {
+ console.warn(`Warning:${e}`);
+ }
this._removeDelayedMove();
}
@@ -652,7 +901,7 @@ const BaseAppViewCommon = {
const appIcon = dragEvent.source;
- if (shellVersion < 43) {
+ if (Me.shellVersion < 43) {
this._dropPage = this._pageForCoords(dragEvent.x, dragEvent.y);
if (this._dropPage &&
this._dropPage === AppDisplay.SidePages.PREVIOUS &&
@@ -663,7 +912,7 @@ const BaseAppViewCommon = {
}
if (appIcon instanceof AppDisplay.AppViewItem) {
- if (shellVersion < 44) {
+ if (Me.shellVersion < 44) {
// Handle the drag overshoot. When dragging to above the
// icon grid, move to the page above; when dragging below,
// move to the page below.
@@ -685,7 +934,10 @@ const BaseAppViewCommon = {
}
}
- this._maybeMoveItem(dragEvent);
+ const thisIsFolder = this instanceof AppDisplay.FolderView;
+ const thisIsAppDisplay = !thisIsFolder;
+ if ((!opt.APP_GRID_ORDER && thisIsAppDisplay) || (!opt.APP_FOLDER_ORDER && thisIsFolder))
+ this._maybeMoveItem(dragEvent);
return DND.DragMotionResult.CONTINUE;
},
@@ -771,16 +1023,12 @@ const FolderIcon = {
: St.ButtonMask.ONE | St.ButtonMask.TWO;
this.button_mask = buttonMask;*/
this.button_mask = St.ButtonMask.ONE | St.ButtonMask.TWO;
-
- // build the folders now to avoid node errors when dragging active folder preview icons
- if (this.visible && opt.APP_GRID_ACTIVE_PREVIEW)
- this._ensureFolderDialog();
},
open() {
this._ensureFolderDialog();
- if (this._dialog._designCapacity !== this.view._orderedItems.length)
- this._dialog._updateFolderSize();
+ // if (this._dialog._designCapacity !== this.view._orderedItems.length)
+ this._dialog._updateFolderSize();
this.view._scrollView.vscroll.adjustment.value = 0;
this._dialog.popup();
@@ -789,15 +1037,7 @@ const FolderIcon = {
const FolderView = {
_createGrid() {
- let grid;
- if (shellVersion < 43)
- grid = new FolderGrid();
- else
- grid = new FolderGrid43();
-
- // IconGrid algorithm for adaptive icon size
- // counts with different default(max) size for folders
- grid.layoutManager._isFolder = true;
+ let grid = new AppDisplay.FolderGrid();
return grid;
},
@@ -832,11 +1072,15 @@ const FolderView = {
bin.child = this._orderedItems[i].app.create_icon_texture(subSize);
} else {
const app = this._orderedItems[i].app;
- const child = new ActiveFolderIcon(app);
+ const child = new AppDisplay.AppIcon(app, {
+ setSizeManually: true,
+ showLabel: false,
+ });
child._sourceItem = this._orderedItems[i];
child._sourceFolder = this;
child.icon.style_class = '';
child.icon.set_style('margin: 0; padding: 0;');
+ child._dot.set_style('margin-bottom: 1px;');
child.icon.setIconSize(subSize);
bin.child = child;
@@ -863,9 +1107,9 @@ const FolderView = {
layout.attach(bin, rtl ? (i + 1) % gridSize : i % gridSize, Math.floor(i / gridSize), 1, 1);
}
- // if folder content changed, update folder size
- if (this._dialog && this._dialog._designCapacity !== this._orderedItems.length)
- this._dialog._updateFolderSize();
+ // if folder content changed, update folder size, but not if it's empty
+ /* if (this._dialog && this._dialog._designCapacity !== this._orderedItems.length && this._orderedItems.length)
+ this._dialog._updateFolderSize();*/
return icon;
},
@@ -927,6 +1171,13 @@ const FolderView = {
items.push(icon);
});
+
+ if (opt.APP_FOLDER_ORDER)
+ Main.overview._overview.controls._appDisplay._sortOrderedItemsAlphabetically(items);
+
+ if (opt.APP_FOLDER_USAGE)
+ items.sort((a, b) => Shell.AppUsage.get_default().compare(a.app.id, b.app.id));
+
this._appIds = this._apps.map(app => app.get_id());
return items;
},
@@ -942,10 +1193,9 @@ const FolderView = {
};
// folder columns and rows
-const FolderGrid = GObject.registerClass(
-class FolderGrid extends IconGrid.IconGrid {
+const FolderGridLegacy = {
_init() {
- super._init({
+ IconGrid.IconGrid.prototype._init.bind(this)({
allow_incomplete_pages: false,
// For adaptive size (0), set the numbers high enough to fit all the icons
// to avoid splitting the icons to pages
@@ -954,56 +1204,52 @@ class FolderGrid extends IconGrid.IconGrid {
page_halign: Clutter.ActorAlign.CENTER,
page_valign: Clutter.ActorAlign.CENTER,
});
-
+ this.layout_manager._isFolder = true;
// if (!opt.APP_GRID_FOLDER_DEFAULT)
const spacing = opt.APP_GRID_SPACING;
this.set_style(`column-spacing: ${spacing}px; row-spacing: ${spacing}px;`);
- this.layout_manager.fixedIconSize = opt.APP_GRID_FOLDER_ICON_SIZE;
- }
+ this.layoutManager.fixedIconSize = opt.APP_GRID_FOLDER_ICON_SIZE;
+ },
adaptToSize(width, height) {
this.layout_manager.adaptToSize(width, height);
- }
-});
-
-
-let FolderGrid43;
-// first reference to constant defined using const in other module returns undefined, the AppGrid const will remain empty and unused
-const AppGrid = AppDisplay.AppGrid;
-if (AppDisplay.AppGrid) {
- FolderGrid43 = GObject.registerClass(
- class FolderGrid43 extends AppDisplay.AppGrid {
- _init() {
- super._init({
- allow_incomplete_pages: false,
- columns_per_page: opt.APP_GRID_FOLDER_COLUMNS ? opt.APP_GRID_FOLDER_COLUMNS : 20,
- rows_per_page: opt.APP_GRID_FOLDER_ROWS ? opt.APP_GRID_FOLDER_ROWS : 20,
- page_halign: Clutter.ActorAlign.CENTER,
- page_valign: Clutter.ActorAlign.CENTER,
- });
+ },
+};
+
+const FolderGrid = {
+ _init() {
+ AppDisplay.AppGrid.prototype._init.bind(this)({
+ allow_incomplete_pages: false,
+ columns_per_page: opt.APP_GRID_FOLDER_COLUMNS ? opt.APP_GRID_FOLDER_COLUMNS : 20,
+ rows_per_page: opt.APP_GRID_FOLDER_ROWS ? opt.APP_GRID_FOLDER_ROWS : 20,
+ page_halign: Clutter.ActorAlign.CENTER,
+ page_valign: Clutter.ActorAlign.CENTER,
+ });
+ this.layout_manager._isFolder = true;
+ const spacing = opt.APP_GRID_SPACING;
+ this.set_style(`column-spacing: ${spacing}px; row-spacing: ${spacing}px;`);
+ this.layoutManager.fixedIconSize = opt.APP_GRID_FOLDER_ICON_SIZE;
- const spacing = opt.APP_GRID_SPACING;
- this.set_style(`column-spacing: ${spacing}px; row-spacing: ${spacing}px;`);
- this.layout_manager.fixedIconSize = opt.APP_GRID_FOLDER_ICON_SIZE;
+ this.setGridModes([
+ {
+ columns: opt.APP_GRID_FOLDER_COLUMNS ? opt.APP_GRID_FOLDER_COLUMNS : 3,
+ rows: opt.APP_GRID_FOLDER_ROWS ? opt.APP_GRID_FOLDER_ROWS : 3,
+ },
+ ]);
+ },
- this.setGridModes([
- {
- columns: opt.APP_GRID_FOLDER_COLUMNS ? opt.APP_GRID_FOLDER_COLUMNS : 3,
- rows: opt.APP_GRID_FOLDER_ROWS ? opt.APP_GRID_FOLDER_ROWS : 3,
- },
- ]);
- }
+ adaptToSize(width, height) {
+ this.layout_manager.adaptToSize(width, height);
+ },
+};
- adaptToSize(width, height) {
- this.layout_manager.adaptToSize(width, height);
- }
- });
-}
const FOLDER_DIALOG_ANIMATION_TIME = 200; // AppDisplay.FOLDER_DIALOG_ANIMATION_TIME
const AppFolderDialog = {
// injection to _init()
after__init() {
+ this._viewBox.add_style_class_name('app-folder-dialog-vshell');
+
// delegate this dialog to the FolderIcon._view
// so its _createFolderIcon function can update the dialog if folder content changed
this._view._dialog = this;
@@ -1023,18 +1269,65 @@ const AppFolderDialog = {
});
this.child.add_action(clickAction);
+
+ // Adjust empty actor to center the title
+ this._entryBox.get_first_child().width = 82;
+ },
+
+ after__addFolderNameEntry() {
+ // Edit button
+ this._removeButton = new St.Button({
+ style_class: 'edit-folder-button',
+ button_mask: St.ButtonMask.ONE,
+ toggle_mode: false,
+ reactive: true,
+ can_focus: true,
+ x_align: Clutter.ActorAlign.END,
+ y_align: Clutter.ActorAlign.CENTER,
+ child: new St.Icon({
+ icon_name: 'user-trash-symbolic',
+ icon_size: 16,
+ }),
+ });
+
+ this._removeButton.connect('clicked', () => {
+ if (Date.now() - this._removeButton._lastClick < Clutter.Settings.get_default().double_click_time) {
+ this._grabHelper.ungrab({ actor: this });
+ // without hiding the dialog, Shell crashes (at least on X11)
+ this.hide();
+ this._view._deletingFolder = true;
+
+ // Resetting all keys deletes the relocatable schema
+ let keys = this._folder.settings_schema.list_keys();
+ for (const key of keys)
+ this._folder.reset(key);
+
+ let settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
+ let folders = settings.get_strv('folder-children');
+ folders.splice(folders.indexOf(this._view._id), 1);
+
+ // remove all abandoned folders (usually my own garbage and unwanted default folders...)
+ /* const appFolders = this._appDisplay._folderIcons.map(icon => icon._id);
+ folders.forEach(folder => {
+ if (!appFolders.includes(folder)) {
+ folders.splice(folders.indexOf(folder._id), 1);
+ }
+ });*/
+ settings.set_strv('folder-children', folders);
+
+ this._view._deletingFolder = false;
+ return;
+ }
+ this._removeButton._lastClick = Date.now();
+ });
+
+ this._entryBox.add_child(this._removeButton);
},
popup() {
if (this._isOpen)
return;
- /* if (!this._correctSize) {
- // update folder with the precise app item size when the dialog is realized
- GLib.idle_add(0, () => this._updateFolderSize(true));
- this._correctSize = true;
- }*/
-
this._isOpen = this._grabHelper.grab({
actor: this,
onUngrab: () => this.popdown(),
@@ -1046,26 +1339,48 @@ const AppFolderDialog = {
this.get_parent().set_child_above_sibling(this, null);
this._needsZoomAndFade = true;
- this.show();
+ // the first folder dialog realization needs size correction
+ // so set the folder size, let it realize and then update the folder content
+ if (!this.realized) {
+ this._updateFolderSize();
+ GLib.idle_add(
+ GLib.PRIORITY_DEFAULT,
+ () => {
+ this._updateFolderSize();
+ }
+ );
+ }
+
+ this.show();
this.emit('open-state-changed', true);
},
_updateFolderSize() {
- // adapt folder size according to the settings and number of icons
const view = this._view;
+ const [firstItem] = view._grid.layoutManager._container;
+ if (!firstItem)
+ return;
+ // adapt folder size according to the settings and number of icons
+ const appDisplay = this._source._parentView;
+ if (!appDisplay.width || appDisplay.allocation.x2 === Infinity || appDisplay.allocation.x2 === -Infinity) {
+ return;
+ }
+
view._grid.layoutManager.fixedIconSize = opt.APP_GRID_FOLDER_ICON_SIZE;
view._grid.set_style(`column-spacing: ${opt.APP_GRID_SPACING}px; row-spacing: ${opt.APP_GRID_SPACING}px;`);
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const dialogMargin = 30;
+ const itemPadding = 55; // default icon item padding on Fedora 44
+ // const dialogMargin = 30;
const nItems = view._orderedItems.length;
let columns = opt.APP_GRID_FOLDER_COLUMNS;
let rows = opt.APP_GRID_FOLDER_ROWS;
+ const fullAdaptiveGrid = !columns && !rows;
let spacing = opt.APP_GRID_SPACING;
- const monitor = global.display.get_monitor_geometry(global.display.get_primary_monitor());
+ const minItemSize = 48 + itemPadding;
- if (!columns && !rows) {
+ if (fullAdaptiveGrid) {
columns = Math.ceil(Math.sqrt(nItems));
rows = columns;
if (columns * (columns - 1) >= nItems) {
@@ -1081,38 +1396,67 @@ const AppFolderDialog = {
}
const iconSize = opt.APP_GRID_FOLDER_ICON_SIZE < 0 ? opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT : opt.APP_GRID_FOLDER_ICON_SIZE;
- let itemSize = iconSize + 53; // icon padding
+ view._grid.layoutManager.fixedIconSize = iconSize;
+
+ let itemSize = iconSize + 55; // icon padding
// first run sets the grid before we can read the real icon size
// so we estimate the size from default properties
// and correct it in the second run
- if (this._notFirstRun) {
- const [firstItem] = view._grid.layoutManager._container;
+ if (this.realized) {
firstItem.icon.setIconSize(iconSize);
const [firstItemWidth] = firstItem.get_preferred_size();
const realSize = firstItemWidth / scaleFactor;
- if (realSize > iconSize)
+ // if the preferred item size is smaller than icon plus some padding, ignore it
+ // (icons that are not yet realized are returning sizes like 45 or 53)
+ if (realSize > (iconSize + 24))
itemSize = realSize;
- } else {
- this._needsUpdateSize = true;
- this._notFirstRun = true;
}
-
let width = columns * (itemSize + spacing) + /* padding for nav arrows*/64;
- width = Math.round(width + (opt.ORIENTATION || !opt.APP_GRID_FOLDER_COLUMNS ? 100 : 160/* space for navigation arrows*/));
- let height = rows * (itemSize + spacing) + /* header*/75 + /* padding*/100;
+ width = Math.round(width + (opt.ORIENTATION ? 100 : 160/* space for navigation arrows*/));
+ let height = rows * (itemSize + spacing) + /* header*/75 + /* padding*/ 2 * 30 + /* padding + ?page indicator*/(!opt.ORIENTATION || !opt.APP_GRID_FOLDER_COLUMNS ? 100 : 70);
+
+ // allocation is more reliable than appDisplay width/height properties
+ const appDisplayWidth = appDisplay.allocation.x2 - appDisplay.allocation.x1;
+ const appDisplayHeight = appDisplay.allocation.y2 - appDisplay.allocation.y1 + (opt.SHOW_SEARCH_ENTRY ? Main.overview._overview.controls._searchEntryBin.height : 0);
- // folder must fit the primary monitor
+ // folder must fit the appDisplay area
// reduce columns/rows if needed and count with the scaled values
- while (width * scaleFactor > monitor.width - 2 * dialogMargin) {
- width -= itemSize + spacing;
- columns -= 1;
+ if (!opt.APP_GRID_FOLDER_ROWS) {
+ while ((height * scaleFactor) > appDisplayHeight) {
+ height -= itemSize + spacing;
+ rows -= 1;
+ }
+ }
+
+ if (!opt.APP_GRID_FOLDER_COLUMNS) {
+ while ((width * scaleFactor) > appDisplayWidth) {
+ width -= itemSize + spacing;
+ columns -= 1;
+ }
}
- while (height * scaleFactor > monitor.height - 2 * dialogMargin) {
- height -= itemSize + spacing;
- rows -= 1;
+ // try to compensate for the previous reduction if there is a space
+ if (!opt.APP_GRID_FOLDER_COLUMNS) {
+ while ((nItems > columns * rows) && ((width * scaleFactor + itemSize + spacing) <= appDisplayWidth)) {
+ width += itemSize + spacing;
+ columns += 1;
+ }
+ // remove columns that cannot be displayed
+ if ((columns * minItemSize + (columns - 1) * spacing) > appDisplayWidth)
+ columns = Math.floor(appDisplayWidth / (minItemSize + spacing));
}
- width = Math.max(540, width);
+ if (!opt.APP_GRID_FOLDER_ROWS) {
+ while ((nItems > columns * rows) && ((height * scaleFactor + itemSize + spacing) <= appDisplayHeight)) {
+ height += itemSize + spacing;
+ rows += 1;
+ }
+ // remove rows that cannot be displayed
+ if ((rows * minItemSize + (rows - 1) * spacing) > appDisplayHeight)
+ rows = Math.floor(appDisplayWidth / (minItemSize + spacing));
+ }
+
+ width = Math.clamp(width, 640, appDisplayWidth);
+ height = Math.min(height, appDisplayHeight);
const layoutManager = view._grid.layoutManager;
layoutManager.rows_per_page = rows;
@@ -1127,6 +1471,8 @@ const AppFolderDialog = {
padding: 30px;
`);
+ view._grid.layoutManager._pageWidth += 1;
+ view._grid.layoutManager.adaptToSize(view._grid.layoutManager._pageWidth - 1, view._grid.layoutManager._pageHeight);
view._redisplay();
// store original item count
@@ -1145,40 +1491,34 @@ const AppFolderDialog = {
// this. covers the whole screen
let dialogTargetX = dialogX;
let dialogTargetY = dialogY;
- if (!opt.APP_GRID_FOLDER_CENTER) {
- const appDisplay = this._source._parentView;
- dialogTargetX = Math.round(sourceCenterX - this.child.width / 2);
- dialogTargetY = Math.round(sourceCenterY - this.child.height / 2);
+ const appDisplay = this._source._parentView;
+ const [appDisplayX, appDisplayY] = this._source._parentView.get_transformed_position();
- // keep the dialog in appDisplay area if possible
- dialogTargetX = Math.clamp(
- dialogTargetX,
- this.x + appDisplay.x,
- this.x + appDisplay.x + appDisplay.width - this.child.width
- );
+ if (!opt.APP_GRID_FOLDER_CENTER) {
+ dialogTargetX = sourceCenterX - this.child.width / 2;
+ dialogTargetY = sourceCenterY - this.child.height / 2;
- dialogTargetY = Math.clamp(
- dialogTargetY,
- this.y + appDisplay.y,
- this.y + appDisplay.y + appDisplay.height - this.child.height
- );
- // or at least in the monitor area
- const monitor = global.display.get_monitor_geometry(global.display.get_primary_monitor());
+ // keep the dialog in appDisplay area if possible
dialogTargetX = Math.clamp(
dialogTargetX,
- this.x + monitor.x,
- this.x + monitor.x + monitor.width - this.child.width
+ appDisplayX,
+ appDisplayX + appDisplay.width - this.child.width
);
dialogTargetY = Math.clamp(
dialogTargetY,
- this.y + monitor.y,
- this.y + monitor.y + monitor.height - this.child.height
+ appDisplayY,
+ appDisplayY + appDisplay.height - this.child.height
);
+ } else {
+ const searchEntryHeight = opt.SHOW_SEARCH_ENTRY ? Main.overview._overview.controls._searchEntryBin.height : 0;
+ dialogTargetX = appDisplayX + appDisplay.width / 2 - this.child.width / 2;
+ dialogTargetY = appDisplayY - searchEntryHeight + ((appDisplay.height + searchEntryHeight) / 2 - this.child.height / 2) / 2;
}
- const dialogOffsetX = -dialogX + dialogTargetX;
- const dialogOffsetY = -dialogY + dialogTargetY;
+
+ const dialogOffsetX = Math.round(dialogTargetX - dialogX);
+ const dialogOffsetY = Math.round(dialogTargetY - dialogY);
this.child.set({
translation_x: sourceX - dialogX,
@@ -1188,12 +1528,6 @@ const AppFolderDialog = {
opacity: 0,
});
- this.ease({
- background_color: DIALOG_SHADE_NORMAL,
- duration: FOLDER_DIALOG_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
-
this.child.ease({
translation_x: dialogOffsetX,
translation_y: dialogOffsetY,
@@ -1202,17 +1536,22 @@ const AppFolderDialog = {
opacity: 255,
duration: FOLDER_DIALOG_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- // if the folder grid was build with the estimated icon item size because the real size wasn't available
- // rebuild it with the real size now, after the folder was realized
- if (this._needsUpdateSize) {
- this._updateFolderSize();
- this._view._redisplay();
- this._needsUpdateSize = false;
- }
- },
});
+ appDisplay.ease({
+ opacity: 0,
+ duration: FOLDER_DIALOG_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+
+ if (opt.SHOW_SEARCH_ENTRY) {
+ Main.overview.searchEntry.ease({
+ opacity: 0,
+ duration: FOLDER_DIALOG_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+ }
+
this._needsZoomAndFade = false;
if (this._sourceMappedId === 0) {
@@ -1230,17 +1569,20 @@ const AppFolderDialog = {
return;
}
+ // if the dialog was shown silently, skip animation
+ if (this.scale_y < 1) {
+ this._needsZoomAndFade = false;
+ this.hide();
+ this._popdownCallbacks.forEach(func => func());
+ this._popdownCallbacks = [];
+ return;
+ }
+
let [sourceX, sourceY] =
this._source.get_transformed_position();
let [dialogX, dialogY] =
this.child.get_transformed_position();
- this.ease({
- background_color: Clutter.Color.from_pixel(0x00000000),
- duration: FOLDER_DIALOG_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
-
this.child.ease({
translation_x: sourceX - dialogX + this.child.translation_x,
translation_y: sourceY - dialogY + this.child.translation_y,
@@ -1264,11 +1606,35 @@ const AppFolderDialog = {
},
});
+ const appDisplay = this._source._parentView;
+ appDisplay.ease({
+ opacity: 255,
+ duration: FOLDER_DIALOG_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+
+ if (opt.SHOW_SEARCH_ENTRY) {
+ Main.overview.searchEntry.ease({
+ opacity: 255,
+ duration: FOLDER_DIALOG_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+ }
+
this._needsZoomAndFade = false;
},
_setLighterBackground(lighter) {
- const backgroundColor = lighter
+ if (this._isOpen) {
+ const appDisplay = this._source._parentView;
+ appDisplay.ease({
+ opacity: lighter ? 20 : 0,
+ duration: FOLDER_DIALOG_ANIMATION_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+ }
+
+ /* const backgroundColor = lighter
? DIALOG_SHADE_HIGHLIGHT
: DIALOG_SHADE_NORMAL;
@@ -1276,91 +1642,10 @@ const AppFolderDialog = {
backgroundColor,
duration: FOLDER_DIALOG_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
+ }); */
},
};
-// just make app grid to update all invalid positions that may be result of grid/icon size change
-function _updateIconPositions() {
- const appDisplay = Main.overview._overview._controls._appDisplay;
- const icons = [...appDisplay._orderedItems];
- for (let i = 0; i < icons.length; i++)
- appDisplay._moveItem(icons[i], -1, -1);
-}
-
-function _removeIcons() {
- const appDisplay = Main.overview._overview._controls._appDisplay;
- const icons = [...appDisplay._orderedItems];
- for (let i = 0; i < icons.length; i++) {
- const icon = icons[i];
- if (icon._dialog)
- Main.layoutManager.overviewGroup.remove_child(icon._dialog);
- appDisplay._removeItem(icon);
- icon.destroy();
- }
- appDisplay._folderIcons = [];
-}
-
-function _resetAppGrid(settings) {
- const appDisplay = Main.overview._overview._controls._appDisplay;
- // reset the grid only if called directly without args or if all folders where removed by using reset button in Settings window
- // otherwise this function is called every time a user moves icon to another position as a settings callback
- if (settings) {
- const currentValue = JSON.stringify(global.settings.get_value('app-picker-layout').deep_unpack());
- const emptyValue = JSON.stringify([]);
- const customLayout = currentValue !== emptyValue;
- // appDisplay._customLayout = customLayout;
- if (customLayout)
- return;
- else
- opt._appGridNeedsRedisplay = true;
- }
-
- // force update icon size using adaptToSize(). the page size cannot be the same as the current one
- appDisplay._grid.layoutManager._pageWidth += 1;
- appDisplay._grid.layoutManager.adaptToSize(appDisplay._grid.layoutManager._pageWidth - 1, appDisplay._grid.layoutManager._pageHeight);
- _removeIcons();
- appDisplay._redisplay();
- // force appDisplay to move all icons to proper positions and update all properties
- GLib.idle_add(0, () => {
- _updateIconPositions();
- if (appDisplay._sortOrderedItemsAlphabetically) {
- appDisplay._sortOrderedItemsAlphabetically();
- appDisplay._grid.layoutManager._pageWidth += 1;
- appDisplay._grid.layoutManager.adaptToSize(appDisplay._grid.layoutManager._pageWidth - 1, appDisplay._grid.layoutManager._pageHeight);
- appDisplay._setLinearPositions(appDisplay._orderedItems);
- } else {
- appDisplay._removeItem(appDisplay._orderedItems[0]);
- appDisplay._redisplay();
- }
-
- appDisplay._redisplay();
- });
-}
-
-function _getWindowApp(metaWin) {
- const tracker = Shell.WindowTracker.get_default();
- return tracker.get_window_app(metaWin);
-}
-
-function _getAppLastUsedWindow(app) {
- let recentWin;
- global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null).forEach(metaWin => {
- const winApp = _getWindowApp(metaWin);
- if (!recentWin && winApp === app)
- recentWin = metaWin;
- });
- return recentWin;
-}
-
-function _getAppRecentWorkspace(app) {
- const recentWin = _getAppLastUsedWindow(app);
- if (recentWin)
- return recentWin.get_workspace();
-
- return null;
-}
-
const AppIcon = {
after__init() {
// update the app label behavior
@@ -1377,7 +1662,7 @@ const AppIcon = {
return source !== this &&
(source instanceof this.constructor) &&
(view instanceof AppDisplay.AppDisplay &&
- !opt.APP_GRID_ORDER);
+ !opt.APP_GRID_USAGE);
},
};
@@ -1427,7 +1712,7 @@ const AppViewItemCommon = {
// support active preview icons
acceptDrop(source, _actor, x) {
- if (opt.APP_GRID_ORDER)
+ if (opt.APP_GRID_USAGE)
return DND.DragMotionResult.NO_DROP;
this._setHoveringByDnd(false);
@@ -1449,26 +1734,18 @@ const AppViewItemCommon = {
};
-const ActiveFolderIcon = GObject.registerClass(
-class ActiveFolderIcon extends AppDisplay.AppIcon {
- _init(app) {
- super._init(app, {
- setSizeManually: true,
- showLabel: false,
- });
- }
-
+const ActiveFolderIcon = {
handleDragOver() {
return DND.DragMotionResult.CONTINUE;
- }
+ },
acceptDrop() {
return false;
- }
+ },
_onDragEnd() {
this._dragging = false;
this.undoScaleAndFade();
Main.overview.endItemDrag(this._sourceItem.icon);
- }
-});
+ },
+};
diff --git a/extensions/44/vertical-workspaces/lib/appFavorites.js b/extensions/44/vertical-workspaces/lib/appFavorites.js
index 50ebce9..3efb68c 100644
--- a/extensions/44/vertical-workspaces/lib/appFavorites.js
+++ b/extensions/44/vertical-workspaces/lib/appFavorites.js
@@ -10,45 +10,63 @@
'use strict';
-const { Shell } = imports.gi;
const AppFavorites = imports.ui.appFavorites;
-const Main = imports.ui.main;
-
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
+let Me;
let opt;
-let _overrides;
-let _firstRun = true;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('appFavoritesModule', true);
- reset = reset || !moduleEnabled;
+var AppFavoritesModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
- _firstRun = false;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- if (_overrides)
- _overrides.removeAll();
+ update(reset) {
+ this.moduleEnabled = opt.get('appFavoritesModule');
+ // if notifications are enabled no override is needed
+ reset = reset || !this.moduleEnabled || opt.SHOW_FAV_NOTIFICATION;
- // if notifications are enabled no override is needed
- if (reset || opt.SHOW_FAV_NOTIFICATION) {
- _overrides = null;
- opt = null;
- return;
+ // don't touch original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation) {
+ this.moduleEnabled = false;
+ console.debug(' AppFavoritesModule - Keeping untouched');
+ }
}
- _overrides = new _Util.Overrides();
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ // use actual instance instead of prototype
+ this._overrides.addOverride('AppFavorites', AppFavorites.getAppFavorites(), AppFavoritesCommon);
- // AppFavorites.AppFavorites is const, first access returns undefined
- const dummy = AppFavorites.AppFavorites;
- _overrides.addOverride('AppFavorites', AppFavorites.AppFavorites.prototype, AppFavoritesCommon);
-}
+ console.debug(' AppFavoritesModule - Activated');
+ }
+
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ console.debug(' AppFavoritesModule - Deactivated');
+ }
+};
const AppFavoritesCommon = {
addFavoriteAtPos(appId, pos) {
diff --git a/extensions/44/vertical-workspaces/lib/dash.js b/extensions/44/vertical-workspaces/lib/dash.js
index bf832bd..17d43ea 100644
--- a/extensions/44/vertical-workspaces/lib/dash.js
+++ b/extensions/44/vertical-workspaces/lib/dash.js
@@ -8,309 +8,523 @@
* modified dash module of https://github.com/RensAlthuis/vertical-overview extension
*/
-const { Clutter, GObject, St, Shell, Meta } = imports.gi;
-const AppDisplay = imports.ui.appDisplay;
+'use strict';
+
+const Clutter = imports.gi.Clutter;
+const GLib = imports.gi.GLib;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const AltTab = imports.ui.altTab;
const AppFavorites = imports.ui.appFavorites;
+const AppDisplay = imports.ui.appDisplay;
+const AppMenu = imports.ui.appMenu;
+const BoxPointer = imports.ui.boxpointer;
+const Dash = imports.ui.dash;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
-const Overview = imports.ui.overview;
-const Dash = imports.ui.dash;
const PopupMenu = imports.ui.popupMenu;
-const { AppMenu } = imports.ui.appMenu;
-const BoxPointer = imports.ui.boxpointer;
-const AltTab = imports.ui.altTab;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const Util = Me.imports.lib.util;
-const _ = Me.imports.lib.settings._;
+let Me;
+let opt;
+// gettext
+let _;
-const shellVersion = Util.shellVersion;
-let _origWorkId;
-let _newWorkId;
-let _showAppsIconBtnPressId;
+let _moduleEnabled;
+let _timeouts;
// added values to achieve a better ability to scale down according to available space
var BaseIconSizes = [16, 24, 32, 40, 44, 48, 56, 64, 72, 80, 96, 112, 128];
-const RecentFilesSearchProviderPrefix = Me.imports.lib.recentFilesSearchProvider.prefix;
-const WindowSearchProviderPrefix = Me.imports.lib.windowSearchProvider.prefix;
+const DASH_ITEM_LABEL_SHOW_TIME = 150;
-let _overrides;
-let opt;
-let _firstRun = true;
+var DashModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ _ = Me.gettext;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ this._originalWorkId = null;
+ this._customWorkId = null;
+ this._showAppsIconBtnPressId = 0;
+ }
-const DASH_ITEM_LABEL_SHOW_TIME = 150;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ _ = null;
+ }
+
+ update(reset) {
+ this._removeTimeouts();
+
+ this.moduleEnabled = opt.get('dashModule');
+ const conflict = !!(Me.Util.getEnabledExtensions('dash-to-dock').length ||
+ Me.Util.getEnabledExtensions('ubuntu-dock').length ||
+ Me.Util.getEnabledExtensions('dash-to-panel').length);
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('dashModule', true);
- reset = reset || !moduleEnabled;
+ if (conflict && !reset)
+ console.warn(`[${Me.metadata.name}] Warning: "Dash" module disabled due to potential conflict with another extension`);
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ reset = reset || !this.moduleEnabled || conflict;
+ this._conflict = conflict;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' DashModule - Keeping untouched');
+ }
- _firstRun = false;
+ updateStyle(dash) {
+ if (opt.DASH_BG_LIGHT)
+ dash._background.add_style_class_name('dash-background-light');
+ else
+ dash._background.remove_style_class_name('dash-background-light');
+
+ dash._background.opacity = opt.DASH_BG_OPACITY;
+ let radius = opt.DASH_BG_RADIUS;
+ if (radius) {
+ let style;
+ switch (opt.DASH_POSITION) {
+ case 1:
+ style = opt.DASH_BG_GS3_STYLE ? `border-radius: ${radius}px 0 0 ${radius}px;` : `border-radius: ${radius}px;`;
+ break;
+ case 3:
+ style = opt.DASH_BG_GS3_STYLE ? `border-radius: 0 ${radius}px ${radius}px 0;` : `border-radius: ${radius}px;`;
+ break;
+ default:
+ style = `border-radius: ${radius}px;`;
+ }
+ dash._background.set_style(style);
+ } else {
+ dash._background.set_style('');
+ }
+ }
- if (_overrides)
- _overrides.removeAll();
+ _activateModule() {
+ _moduleEnabled = true;
+ _timeouts = {};
+ const dash = Main.overview._overview._controls.layoutManager._dash;
+ if (!this._originalWorkId)
+ this._originalWorkId = dash._workId;
- const dash = Main.overview._overview._controls.layoutManager._dash;
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- setToHorizontal();
+ this._resetStyle(dash);
+ this.updateStyle(dash);
- dash.remove_style_class_name('vertical');
- dash.remove_style_class_name('vertical-left');
- dash.remove_style_class_name('vertical-right');
+ this._overrides.addOverride('DashItemContainer', Dash.DashItemContainer.prototype, DashItemContainerCommon);
+ this._overrides.addOverride('DashCommon', Dash.Dash.prototype, DashCommon);
+ this._overrides.addOverride('AppIcon', AppDisplay.AppIcon.prototype, AppIconCommon);
+ this._overrides.addOverride('DashIcon', Dash.DashIcon.prototype, DashIconCommon);
+ this._overrides.addOverride('AppMenu', AppMenu.AppMenu.prototype, AppMenuCommon);
- if (reset) {
- _moveDashAppGridIcon(reset);
- _connectShowAppsIcon(reset);
- _updateSearchWindowsIcon(false);
- _updateRecentFilesIcon(false);
- dash.visible = true;
- dash._background.opacity = 255;
- dash._background.remove_style_class_name('v-shell-dash-background');
- _overrides = null;
- opt = null;
- return;
+ if (opt.DASH_VERTICAL) {
+ dash.add_style_class_name('vertical');
+ this._setOrientation(Clutter.Orientation.VERTICAL);
+ } else {
+ this._setOrientation(Clutter.Orientation.HORIZONTAL);
+ }
+
+ 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._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');
}
- _overrides = new Util.Overrides();
+ _disableModule() {
+ const dash = Main.overview._overview._controls.layoutManager._dash;
+ this._resetStyle(dash);
- _overrides.addOverride('DashItemContainer', Dash.DashItemContainer.prototype, DashItemContainerCommon);
- _overrides.addOverride('DashCommon', Dash.Dash.prototype, DashCommon);
- _overrides.addOverride('AppIcon', AppDisplay.AppIcon.prototype, AppIconCommon);
- _overrides.addOverride('DashIcon', Dash.DashIcon.prototype, DashIconCommon);
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
- if (opt.DASH_VERTICAL) {
- _overrides.addOverride('Dash', Dash.Dash.prototype, DashOverride);
- setToVertical();
- dash.add_style_class_name('vertical');
+ dash._workId = this._originalWorkId;
- if (!_newWorkId) {
- _origWorkId = dash._workId;
- dash._workId = Main.initializeDeferredWork(dash._box, dash._redisplay.bind(dash));
- _newWorkId = dash._workId;
- } else {
- dash._workId = _newWorkId;
+ if (this._wmSwitchWsConId) {
+ global.windowManager.disconnect(this._wmSwitchWsConId);
+ this._wmSwitchWsConId = 0;
+ }
+ if (this._newWindowConId) {
+ global.windowManager.disconnect(this._newWindowConId);
+ this._newWindowConId = 0;
}
- } else {
- setToHorizontal();
- if (_origWorkId)
- dash._workId = _origWorkId;
+
+ const reset = true;
+ this._setOrientation(Clutter.Orientation.HORIZONTAL);
+ this._moveDashAppGridIcon(reset);
+ this._connectShowAppsIcon(reset);
+ this._updateSearchWindowsIcon(false);
+ this._updateRecentFilesIcon(false);
+ this._updateExtensionsIcon(false);
+ dash.visible = !this._conflict;
+ dash._background.opacity = 255;
+
+ _moduleEnabled = false;
+ console.debug(' DashModule - Disabled');
}
- _updateSearchWindowsIcon();
- _updateRecentFilesIcon();
- _moveDashAppGridIcon();
- _connectShowAppsIcon();
-
- if (dash._showWindowsIcon && !dash._showWindowsIconClickedId)
- dash._showWindowsIconClickedId = dash._showWindowsIcon.toggleButton.connect('clicked', (a, c) => c && Util.activateSearchProvider(WindowSearchProviderPrefix));
-
- if (dash._recentFilesIcon && !dash._recentFilesIconClickedId)
- dash._recentFilesIconClickedId = dash._recentFilesIcon.toggleButton.connect('clicked', (a, c) => c && Util.activateSearchProvider(RecentFilesSearchProviderPrefix));
-
- dash.visible = opt.DASH_VISIBLE;
- dash._background.add_style_class_name('v-shell-dash-background');
- dash._redisplay();
-}
-
-function setToVertical() {
- let dash = Main.overview._overview._controls.layoutManager._dash;
-
- dash._box.layout_manager.orientation = Clutter.Orientation.VERTICAL;
- dash._dashContainer.layout_manager.orientation = Clutter.Orientation.VERTICAL;
- dash._dashContainer.y_expand = false;
- dash._dashContainer.x_expand = true;
- dash.x_align = Clutter.ActorAlign.START;
- dash.y_align = Clutter.ActorAlign.CENTER;
-
- let sizerBox = dash._background.get_children()[0];
- sizerBox.clear_constraints();
- sizerBox.add_constraint(new Clutter.BindConstraint({
- source: dash._showAppsIcon.icon,
- coordinate: Clutter.BindCoordinate.WIDTH,
- }));
- sizerBox.add_constraint(new Clutter.BindConstraint({
- source: dash._dashContainer,
- coordinate: Clutter.BindCoordinate.HEIGHT,
- }));
- dash._box.remove_all_children();
- dash._separator = null;
- dash._queueRedisplay();
- dash._adjustIconSize();
-
- dash.add_style_class_name(opt.DASH_LEFT ? 'vertical-left' : 'vertical-right');
-}
-
-function setToHorizontal() {
- let dash = Main.overview._overview._controls.layoutManager._dash;
- if (_origWorkId)
- dash._workId = _origWorkId; // pretty sure this is a leak, but there no provided way to disconnect these...
- dash._box.layout_manager.orientation = Clutter.Orientation.HORIZONTAL;
- dash._dashContainer.layout_manager.orientation = Clutter.Orientation.HORIZONTAL;
- dash._dashContainer.y_expand = true;
- dash._dashContainer.x_expand = false;
- dash.x_align = Clutter.ActorAlign.CENTER;
- dash.y_align = 0;
-
- let sizerBox = dash._background.get_children()[0];
- sizerBox.clear_constraints();
- sizerBox.add_constraint(new Clutter.BindConstraint({
- source: dash._showAppsIcon.icon,
- coordinate: Clutter.BindCoordinate.HEIGHT,
- }));
- sizerBox.add_constraint(new Clutter.BindConstraint({
- source: dash._dashContainer,
- coordinate: Clutter.BindCoordinate.WIDTH,
- }));
-
- dash._box.remove_all_children();
- dash._separator = null;
- dash._queueRedisplay();
- dash._adjustIconSize();
-}
-
-function _moveDashAppGridIcon(reset = false) {
- // move dash app grid icon to the front
- const dash = Main.overview._overview._controls.layoutManager._dash;
-
- const appIconPosition = opt.get('showAppsIconPosition', true);
- dash._showAppsIcon.remove_style_class_name('show-apps-icon-vertical-hide');
- dash._showAppsIcon.remove_style_class_name('show-apps-icon-horizontal-hide');
- dash._showAppsIcon.opacity = 255;
- if (!reset && appIconPosition === 0) // 0 - start
- dash._dashContainer.set_child_at_index(dash._showAppsIcon, 0);
- if (reset || appIconPosition === 1) { // 1 - end
- const index = dash._dashContainer.get_children().length - 1;
- dash._dashContainer.set_child_at_index(dash._showAppsIcon, index);
+ _resetStyle(dash) {
+ dash.remove_style_class_name('vertical');
+ dash.remove_style_class_name('vertical-gs3-left');
+ dash.remove_style_class_name('vertical-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');
+ dash._background.remove_style_class_name('dash-background-reduced');
}
- if (!reset && appIconPosition === 2) { // 2 - hide
- const style = opt.DASH_VERTICAL ? 'show-apps-icon-vertical-hide' : 'show-apps-icon-horizontal-hide';
- dash._showAppsIcon.add_style_class_name(style);
- // for some reason even if the icon height in vertical mode should be set to 0 by the style, it stays visible in full size returning height 1px
- dash._showAppsIcon.opacity = 0;
+
+ _removeTimeouts() {
+ if (_timeouts) {
+ Object.values(_timeouts).forEach(t => {
+ if (t)
+ GLib.source_remove(t);
+ });
+ _timeouts = null;
+ }
}
-}
-function _connectShowAppsIcon(reset = false) {
- if (!reset) {
- if (_showAppsIconBtnPressId || Util.dashIsDashToDock()) {
- // button is already connected || dash is Dash to Dock
- return;
+ _setOrientation(orientation, dash) {
+ dash = dash ?? Main.overview._overview._controls.layoutManager._dash;
+
+ dash._box.layout_manager.orientation = orientation;
+ dash._dashContainer.layout_manager.orientation = orientation;
+ dash._dashContainer.y_expand = !orientation;
+ dash._dashContainer.x_expand = !!orientation;
+ dash.x_align = orientation ? Clutter.ActorAlign.START : Clutter.ActorAlign.CENTER;
+ dash.y_align = orientation ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.FILL;
+
+ let sizerBox = dash._background.get_children()[0];
+ sizerBox.clear_constraints();
+ sizerBox.add_constraint(new Clutter.BindConstraint({
+ source: dash._showAppsIcon.icon,
+ coordinate: orientation ? Clutter.BindCoordinate.WIDTH : Clutter.BindCoordinate.HEIGHT,
+ }));
+ sizerBox.add_constraint(new Clutter.BindConstraint({
+ source: dash._dashContainer,
+ coordinate: orientation ? Clutter.BindCoordinate.HEIGHT : Clutter.BindCoordinate.WIDTH,
+ }));
+ dash._box.remove_all_children();
+ 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');
}
+ }
- Main.overview.dash._showAppsIcon.reactive = true;
- _showAppsIconBtnPressId = Main.overview.dash._showAppsIcon.connect('button-press-event', (actor, event) => {
- const button = event.get_button();
- if (button === Clutter.BUTTON_MIDDLE)
- Util.openPreferences();
- else if (button === Clutter.BUTTON_SECONDARY)
- Util.activateSearchProvider(WindowSearchProviderPrefix);
- else
- return Clutter.EVENT_PROPAGATE;
- return Clutter.EVENT_STOP;
- });
- } else if (_showAppsIconBtnPressId) {
- Main.overview.dash._showAppsIcon.disconnect(_showAppsIconBtnPressId);
- _showAppsIconBtnPressId = 0;
- Main.overview.dash._showAppsIcon.reactive = false;
+ _moveDashAppGridIcon(reset = false, dash) {
+ // move dash app grid icon to the front
+ dash = dash ?? Main.overview._overview._controls.layoutManager._dash;
+
+ const appIconPosition = opt.get('showAppsIconPosition');
+ dash._showAppsIcon.remove_style_class_name('show-apps-icon-vertical-hide');
+ dash._showAppsIcon.remove_style_class_name('show-apps-icon-horizontal-hide');
+ dash._showAppsIcon.opacity = 255;
+ if (!reset && appIconPosition === 0) // 0 - start
+ dash._dashContainer.set_child_at_index(dash._showAppsIcon, 0);
+ if (reset || appIconPosition === 1) { // 1 - end
+ const index = dash._dashContainer.get_children().length - 1;
+ dash._dashContainer.set_child_at_index(dash._showAppsIcon, index);
+ }
+ if (!reset && appIconPosition === 2) { // 2 - hide
+ const style = opt.DASH_VERTICAL ? 'show-apps-icon-vertical-hide' : 'show-apps-icon-horizontal-hide';
+ dash._showAppsIcon.add_style_class_name(style);
+ // for some reason even if the icon height in vertical mode should be set to 0 by the style, it stays visible in full size returning height 1px
+ dash._showAppsIcon.opacity = 0;
+ }
}
-}
-const DashOverride = {
- handleDragOver(source, actor, _x, y, _time) {
- let app = Dash.getAppFromSource(source);
+ _connectShowAppsIcon(reset = false, dash) {
+ dash = dash ?? Main.overview._overview._controls.layoutManager._dash;
+ if (!reset) {
+ if (this._showAppsIconBtnPressId || Me.Util.dashIsDashToDock()) {
+ // button is already connected || dash is Dash to Dock
+ return;
+ }
+ dash._showAppsIcon.reactive = true;
+ this._showAppsIconBtnPressId = dash._showAppsIcon.connect('button-press-event', (actor, event) => {
+ const button = event.get_button();
+ if (button === Clutter.BUTTON_MIDDLE)
+ Me.Util.openPreferences();
+ else if (button === Clutter.BUTTON_SECONDARY)
+ Me.Util.activateSearchProvider(Me.WSP_PREFIX);
+ else
+ return Clutter.EVENT_PROPAGATE;
+ return Clutter.EVENT_STOP;
+ });
+ } else if (this._showAppsIconBtnPressId) {
+ dash._showAppsIcon.disconnect(this._showAppsIconBtnPressId);
+ this._showAppsIconBtnPressId = 0;
+ dash._showAppsIcon.reactive = false;
+ }
+ }
- // Don't allow favoriting of transient apps
- if (app === null || app.is_window_backed())
- return DND.DragMotionResult.NO_DROP;
+ _updateSearchWindowsIcon(show = opt.SHOW_WINDOWS_ICON, dash) {
+ dash = dash ?? Main.overview._overview._controls.layoutManager._dash;
+ const dashContainer = dash._dashContainer;
- if (!global.settings.is_writable('favorite-apps'))
- return DND.DragMotionResult.NO_DROP;
+ 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;
+ }
- let favorites = AppFavorites.getAppFavorites().getFavorites();
- let numFavorites = favorites.length;
+ if (!show || !opt.get('windowSearchProviderModule'))
+ return;
- let favPos = favorites.indexOf(app);
+ 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);
+ }
- let children = this._box.get_children();
- let numChildren = children.length;
- let boxHeight = this._box.height;
+ 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);
+ }
- // Keep the placeholder out of the index calculation; assuming that
- // the remove target has the same size as "normal" items, we don't
- // need to do the same adjustment there.
- if (this._dragPlaceholder) {
- boxHeight -= this._dragPlaceholder.height;
- numChildren--;
+ 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);
+ });
}
+ }
- // Same with the separator
- if (this._separator) {
- boxHeight -= this._separator.height;
- numChildren--;
+ _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;
}
- let pos;
- if (!this._emptyDropTarget)
- pos = Math.floor(y * numChildren / boxHeight);
- else
- pos = 0; // always insert at the top when dash is empty
+ if (!show || !opt.get('recentFilesSearchProviderModule'))
+ return;
- // Put the placeholder after the last favorite if we are not
- // in the favorites zone
- if (pos > numFavorites)
- pos = numFavorites;
+ 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);
+ }
- if (pos !== this._dragPlaceholderPos && this._animatingPlaceholdersCount === 0) {
- this._dragPlaceholderPos = pos;
+ 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);
+ }
- // Don't allow positioning before or after self
- if (favPos !== -1 && (pos === favPos || pos === favPos + 1)) {
- this._clearDragPlaceholder();
- return DND.DragMotionResult.CONTINUE;
- }
+ Main.overview._overview._controls.layoutManager._dash._adjustIconSize();
- // If the placeholder already exists, we just move
- // it, but if we are adding it, expand its size in
- // an animation
- let fadeIn;
- if (this._dragPlaceholder) {
- this._dragPlaceholder.destroy();
- fadeIn = false;
- } else {
- fadeIn = true;
+ 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;
+ }
- this._dragPlaceholder = new Dash.DragPlaceholderItem();
- this._dragPlaceholder.child.set_width(this.iconSize / 2);
- this._dragPlaceholder.child.set_height(this.iconSize);
- this._box.insert_child_at_index(this._dragPlaceholder,
- this._dragPlaceholderPos);
- this._dragPlaceholder.show(fadeIn);
+ 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);
}
- if (!this._dragPlaceholder)
- return DND.DragMotionResult.NO_DROP;
+ 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);
+ }
- let srcIsFavorite = favPos !== -1;
+ Main.overview._overview._controls.layoutManager._dash._adjustIconSize();
- if (srcIsFavorite)
- return DND.DragMotionResult.MOVE_DROP;
+ if (dash._extensionsIcon && !dash._extensionsIconClickedId) {
+ dash._extensionsIconClickedId = dash._extensionsIcon.toggleButton.connect('clicked', () => {
+ Me.Util.activateSearchProvider(Me.ESP_PREFIX);
+ });
+ }
+ }
+};
- return DND.DragMotionResult.COPY_DROP;
+const DashItemContainerCommon = {
+ // move labels according dash position
+ showLabel() {
+ if (!this._labelText)
+ return;
+
+ const windows = this.child.app?.get_windows();
+ const recentWindowTitle = windows && windows.length ? windows[0].get_title() : '';
+ const windowCount = this.child.app?.get_windows().length;
+ let labelSuffix = '';
+ if (windowCount > 1)
+ labelSuffix = ` (${windowCount})`;
+ if (recentWindowTitle && recentWindowTitle !== this._labelText)
+ labelSuffix += `\n ${recentWindowTitle}`;
+
+
+ this.label.set_text(this._labelText + labelSuffix);
+
+ this.label.opacity = 0;
+ this.label.show();
+
+ let [stageX, stageY] = this.get_transformed_position();
+
+ const itemWidth = this.allocation.get_width();
+ const itemHeight = this.allocation.get_height();
+
+ const labelWidth = this.label.get_width();
+ const labelHeight = this.label.get_height();
+ let xOffset = Math.floor((itemWidth - labelWidth) / 2);
+ let x = Math.clamp(stageX + xOffset, 0, global.stage.width - labelWidth);
+ const primaryMonitor = global.display.get_monitor_geometry(global.display.get_primary_monitor());
+ x = Math.clamp(x, primaryMonitor.x, primaryMonitor.x + primaryMonitor.width - labelWidth);
+
+ let node = this.label.get_theme_node();
+ let y;
+
+ if (opt.DASH_TOP) {
+ const yOffset = 0.75 * itemHeight + 3 * node.get_length('-y-offset');
+ 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;
+
+ 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;
+
+ x = stageX + this.width + xOffset;
+ y = Math.clamp(stageY + yOffset, 0, global.stage.height - labelHeight);
+ }
+
+ this.label.set_position(x, y);
+ this.label.ease({
+ opacity: 255,
+ duration: DASH_ITEM_LABEL_SHOW_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
+
+ this.label.set_position(x, y);
+ this.label.ease({
+ opacity: 255,
+ duration: DASH_ITEM_LABEL_SHOW_TIME,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ });
},
+};
+const DashCommon = {
_redisplay() {
+ // After disabling V-Shell queueRedisplay() may call this function
+ // In that case redirect the call to the current _redisplay()
+ if (!_moduleEnabled) {
+ this._redisplay();
+ return;
+ }
+
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
let running = this._appSystem.get_running();
+ if (opt.DASH_ISOLATE_WS) {
+ const currentWs = global.workspace_manager.get_active_workspace();
+ running = running.filter(app => {
+ return app.get_windows().filter(w => w.get_workspace() === currentWs).length;
+ });
+ this._box.get_children().forEach(a => a.child?._updateRunningStyle());
+ }
+
let children = this._box.get_children().filter(actor => {
return actor.child &&
actor.child._delegate &&
@@ -405,7 +619,8 @@ const DashOverride = {
}
for (let i = 0; i < addedItems.length; i++) {
- this._box.insert_child_at_index(addedItems[i].item,
+ this._box.insert_child_at_index(
+ addedItems[i].item,
addedItems[i].pos);
}
@@ -450,14 +665,14 @@ const DashOverride = {
style_class: 'dash-separator',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
- width: this.iconSize,
- height: 1,
+ width: opt.DASH_VERTICAL ? this.iconSize : 1,
+ height: opt.DASH_VERTICAL ? 1 : this.iconSize,
});
this._box.add_child(this._separator);
}
// FIXME: separator placement is broken (also in original dash)
- let pos = nFavorites;
+ let pos = nFavorites + this._animatingPlaceholdersCount;
if (this._dragPlaceholder)
pos++;
this._box.set_child_at_index(this._separator, pos);
@@ -474,8 +689,13 @@ const DashOverride = {
let appIcon = new Dash.DashIcon(app);
let indicator = appIcon._dot;
- indicator.x_align = opt.DASH_LEFT ? Clutter.ActorAlign.START : Clutter.ActorAlign.END;
- indicator.y_align = Clutter.ActorAlign.CENTER;
+ if (opt.DASH_VERTICAL) {
+ indicator.x_align = opt.DASH_LEFT ? Clutter.ActorAlign.START : Clutter.ActorAlign.END;
+ indicator.y_align = Clutter.ActorAlign.CENTER;
+ } else {
+ indicator.x_align = Clutter.ActorAlign.CENTER;
+ indicator.y_align = Clutter.ActorAlign.END;
+ }
appIcon.connect('menu-state-changed',
(o, opened) => {
@@ -495,68 +715,7 @@ const DashOverride = {
return item;
},
-};
-
-const DashItemContainerCommon = {
- // move labels according dash position
- showLabel() {
- if (!this._labelText)
- return;
-
- this.label.set_text(this._labelText);
- this.label.opacity = 0;
- this.label.show();
-
- let [stageX, stageY] = this.get_transformed_position();
-
- const itemWidth = this.allocation.get_width();
- const itemHeight = this.allocation.get_height();
-
- const labelWidth = this.label.get_width();
- const labelHeight = this.label.get_height();
- let xOffset = Math.floor((itemWidth - labelWidth) / 2);
- let x = Math.clamp(stageX + xOffset, 0, global.stage.width - labelWidth);
-
- let node = this.label.get_theme_node();
- let y;
-
- if (opt.DASH_TOP) {
- const yOffset = itemHeight - labelHeight + 3 * node.get_length('-y-offset');
- 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;
-
- 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;
-
- x = stageX + this.width + xOffset;
- y = Math.clamp(stageY + yOffset, 0, global.stage.height - labelHeight);
- }
-
- this.label.set_position(x, y);
- this.label.ease({
- opacity: 255,
- duration: DASH_ITEM_LABEL_SHOW_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
-
- this.label.set_position(x, y);
- this.label.ease({
- opacity: 255,
- duration: DASH_ITEM_LABEL_SHOW_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- },
-};
-const DashCommon = {
// use custom BaseIconSizes and add support for custom icons
_adjustIconSize() {
// if a user launches multiple apps at once, this function may be called again before the previous call has finished
@@ -585,6 +744,8 @@ const DashCommon = {
if (this._recentFilesIcon)
iconChildren.push(this._recentFilesIcon);
+ if (this._extensionsIcon)
+ iconChildren.push(this._extensionsIcon);
if (!iconChildren.length)
return;
@@ -706,168 +867,313 @@ const DashCommon = {
this._adjustingInProgress = false;
},
+
+ handleDragOver(source, actor, x, y, _time) {
+ let app = Dash.getAppFromSource(source);
+
+ // Don't allow favoriting of transient apps
+ if (app === null || app.is_window_backed())
+ return DND.DragMotionResult.NO_DROP;
+ if (!global.settings.is_writable('favorite-apps'))
+ return DND.DragMotionResult.NO_DROP;
+ let favorites = AppFavorites.getAppFavorites().getFavorites();
+ let numFavorites = favorites.length;
+
+ let favPos = favorites.indexOf(app);
+
+ let children = this._box.get_children();
+ let numChildren = children.length;
+ let boxSize = opt.DASH_VERTICAL ? this._box.height : this._box.width;
+
+ // Keep the placeholder out of the index calculation; assuming that
+ // the remove target has the same size as "normal" items, we don't
+ // need to do the same adjustment there.
+ if (this._dragPlaceholder) {
+ boxSize -= opt.DASH_VERTICAL ? this._dragPlaceholder.height : this._dragPlaceholder.width;
+ numChildren--;
+ }
+
+ // Same with the separator
+ if (this._separator) {
+ boxSize -= opt.DASH_VERTICAL ? this._separator.height : this._separator.width;
+ numChildren--;
+ }
+
+ let pos;
+ if (this._emptyDropTarget)
+ pos = 0; // always insert at the start when dash is empty
+ else if (this.text_direction === Clutter.TextDirection.RTL)
+ pos = numChildren - Math.floor((opt.DASH_VERTICAL ? y : x) * numChildren / boxSize);
+ else
+ pos = Math.floor((opt.DASH_VERTICAL ? y : x) * numChildren / boxSize);
+
+ // Put the placeholder after the last favorite if we are not
+ // in the favorites zone
+ if (pos > numFavorites)
+ pos = numFavorites;
+
+ if (pos !== this._dragPlaceholderPos && this._animatingPlaceholdersCount === 0) {
+ this._dragPlaceholderPos = pos;
+
+ // Don't allow positioning before or after self
+ if (favPos !== -1 && (pos === favPos || pos === favPos + 1)) {
+ this._clearDragPlaceholder();
+ return DND.DragMotionResult.CONTINUE;
+ }
+
+ // If the placeholder already exists, we just move
+ // it, but if we are adding it, expand its size in
+ // an animation
+ let fadeIn;
+ if (this._dragPlaceholder) {
+ this._dragPlaceholder.destroy();
+ fadeIn = false;
+ } else {
+ fadeIn = true;
+ }
+
+ this._dragPlaceholder = new Dash.DragPlaceholderItem();
+ this._dragPlaceholder.child.set_width(this.iconSize / (opt.DASH_VERTICAL ? 2 : 1));
+ this._dragPlaceholder.child.set_height(this.iconSize / (opt.DASH_VERTICAL ? 1 : 2));
+ this._box.insert_child_at_index(
+ this._dragPlaceholder,
+ this._dragPlaceholderPos);
+ this._dragPlaceholder.show(fadeIn);
+ }
+
+ if (!this._dragPlaceholder)
+ return DND.DragMotionResult.NO_DROP;
+
+ let srcIsFavorite = favPos !== -1;
+
+ if (srcIsFavorite)
+ return DND.DragMotionResult.MOVE_DROP;
+
+ return DND.DragMotionResult.COPY_DROP;
+ },
};
const DashIconCommon = {
after__init() {
- if (opt.DASH_ICON_SCROLL) {
- this._scrollConId = this.connect('scroll-event', _onScrollEvent.bind(this));
- this._leaveConId = this.connect('leave-event', _onLeaveEvent.bind(this));
+ if (opt.DASH_ICON_SCROLL && !Me.Util.dashNotDefault()) {
+ this._scrollConId = this.connect('scroll-event', DashExtensions.onScrollEvent.bind(this));
+ this._leaveConId = this.connect('leave-event', DashExtensions.onLeaveEvent.bind(this));
}
},
-};
-function _onScrollEvent(source, event) {
- if ((this.app && !opt.DASH_ICON_SCROLL) || (this._isSearchWindowsIcon && !opt.SEARCH_WINDOWS_ICON_SCROLL)) {
- if (this._scrollConId)
- this.disconnect(this._scrollConId);
- if (this._leaveConId)
- this.disconnect(this._leaveConId);
- return Clutter.EVENT_PROPAGATE;
- }
+ popupMenu() {
+ const side = opt.DASH_VERTICAL ? St.Side.LEFT : St.Side.BOTTOM;
+ AppIconCommon.popupMenu.bind(this)(side);
+ },
- let direction = Util.getScrollDirection(event);
- if (direction === Clutter.ScrollDirection.UP)
- direction = 1;
- else if (direction === Clutter.ScrollDirection.DOWN)
- direction = -1;
- else
- return Clutter.EVENT_STOP;
+ _updateRunningStyle() {
+ const currentWs = global.workspace_manager.get_active_workspace();
+ const show = opt.DASH_ISOLATE_WS
+ ? this.app.get_windows().filter(w => w.get_workspace() === currentWs).length
+ : this.app.state !== Shell.AppState.STOPPED;
- // avoid uncontrollable switching if smooth scroll wheel or trackpad is used
- if (this._lastScroll && Date.now() - this._lastScroll < 160)
- return Clutter.EVENT_STOP;
+ if (show)
+ this._dot.show();
+ else
+ this._dot.hide();
+ },
+};
- this._lastScroll = Date.now();
-
- _switchWindow.bind(this)(direction);
- return Clutter.EVENT_STOP;
-}
-
-function _onLeaveEvent() {
- if (!this._selectedMetaWin || this.has_pointer || this.toggleButton?.has_pointer)
- return;
-
- this._selectedPreview._activateSelected = false;
- this._selectedMetaWin = null;
- this._scrolledWindows = null;
- _showWindowPreview.bind(this)(null);
-}
-
-function _switchWindow(direction) {
- if (!this._scrolledWindows) {
- // source is app icon
- if (this.app) {
- this._scrolledWindows = this.app.get_windows();
- 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 = AltTab.getWindows(null);
- else
- this._scrolledWindows = AltTab.getWindows(global.workspace_manager.get_active_workspace());
+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;
}
- }
- let windows = this._scrolledWindows;
+ 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;
- if (!windows.length)
- return;
+ this._lastScroll = Date.now();
- // if window selection is in the process, the previewed window must be the current one
- let currentWin = this._selectedMetaWin ? this._selectedMetaWin : windows[0];
+ DashExtensions.switchWindow.bind(this)(direction);
+ return Clutter.EVENT_STOP;
+ },
- const currentIdx = windows.indexOf(currentWin);
- let targetIdx = currentIdx + direction;
+ onLeaveEvent() {
+ if (!this._selectedMetaWin || this.has_pointer || this.toggleButton?.has_pointer)
+ return;
- if (targetIdx > windows.length - 1)
- targetIdx = 0;
- else if (targetIdx < 0)
- targetIdx = windows.length - 1;
+ this._selectedPreview._activateSelected = false;
+ this._selectedMetaWin = null;
+ this._scrolledWindows = null;
+ DashExtensions.showWindowPreview.bind(this)(null);
+ },
- const metaWin = windows[targetIdx];
- _showWindowPreview.bind(this)(metaWin);
- this._selectedMetaWin = metaWin;
-}
-function _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);
- });
+ 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);
+ }
- viewsIter.forEach(view => {
- // if workspaces are on primary monitor only
- if (!view || !view._workspaces)
+ 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 = AltTab.getWindows(null);
+ else
+ this._scrolledWindows = AltTab.getWindows(global.workspace_manager.get_active_workspace());
+ }
+ }
+
+ let windows = this._scrolledWindows;
+
+ if (!windows.length)
return;
- view._workspaces.forEach(ws => {
- ws._windows.forEach(windowPreview => {
- // metaWin === null resets opacity
- let opacity = metaWin ? 50 : 255;
- windowPreview._activateSelected = false;
+ // 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 = AltTab.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;
- // minimized windows are invisible if windows are not exposed (WORKSPACE_MODE === 0)
- if (!windowPreview.opacity)
- windowPreview.opacity = 255;
+ if (targetIdx > windows.length - 1)
+ targetIdx = 0;
+ else if (targetIdx < 0)
+ targetIdx = windows.length - 1;
- // 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());
+ const metaWin = windows[targetIdx];
+ DashExtensions.showWindowPreview.bind(this)(metaWin);
+ this._selectedMetaWin = metaWin;
+ },
- windowPreview.get_parent().set_child_above_sibling(windowPreview, null);
+ 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);
+ });
- opacity = 255;
- this._selectedPreview = windowPreview;
- windowPreview._activateSelected = true;
- }
+ viewsIter.forEach(view => {
+ // if workspaces are on primary monitor only
+ if (!view || !view._workspaces)
+ return;
- // 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,
- });
- }
+ 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() {
+ 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');
+ },
+
activate(button) {
const event = Clutter.get_current_event();
const state = event ? event.get_state() : 0;
const isMiddleButton = button && button === Clutter.BUTTON_MIDDLE;
- const isCtrlPressed = Util.isCtrlPressed(state);
- const isShiftPressed = Util.isShiftPressed(state);
- const openNewWindow = (this.app.can_open_new_window() &&
- this.app.state === Shell.AppState.RUNNING &&
- (isCtrlPressed || isMiddleButton) && !opt.DASH_CLICK_ACTION === 2) ||
- (opt.DASH_CLICK_ACTION === 2 && !this._selectedMetaWin && !isMiddleButton);
+ const isCtrlPressed = Me.Util.isCtrlPressed(state);
+ const isShiftPressed = Me.Util.isShiftPressed(state);
const currentWS = global.workspace_manager.get_active_workspace();
- const appRecentWorkspace = _getAppRecentWorkspace(this.app);
+ const appRecentWorkspace = this._getAppRecentWorkspace(this.app);
// this feature shouldn't affect search results, dash icons don't have labels, so we use them as a condition
const showWidowsBeforeActivation = opt.DASH_CLICK_ACTION === 1 && !this.icon.label;
@@ -882,6 +1188,12 @@ const AppIconCommon = {
);
}
+ const openNewWindow = this.app.can_open_new_window() &&
+ this.app.state === Shell.AppState.RUNNING &&
+ (((isCtrlPressed || isMiddleButton) && !opt.DASH_CLICK_OPEN_NEW_WIN) ||
+ (opt.DASH_CLICK_OPEN_NEW_WIN && !this._selectedMetaWin && !isMiddleButton) ||
+ ((opt.DASH_CLICK_PREFER_WORKSPACE || opt.DASH_ISOLATE_WS) && !targetWindowOnCurrentWs));
+
if ((this.app.state === Shell.AppState.STOPPED || openNewWindow) && !isShiftPressed)
this.animateLaunch();
@@ -890,19 +1202,23 @@ const AppIconCommon = {
// if DASH_CLICK_ACTION == "SHOW_WINS_BEFORE", the app has more than one window and has no window on the current workspace,
// don't activate the app immediately, only move the overview to the workspace with the app's recent window
} else if (showWidowsBeforeActivation && !isShiftPressed && this.app.get_n_windows() > 1 && !targetWindowOnCurrentWs/* && !(opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE)*/) {
- // this._scroll = true;
- // this._scrollTime = Date.now();
+
Main.wm.actionMoveWorkspace(appRecentWorkspace);
Main.overview.dash.showAppsButton.checked = false;
return;
} else if (this._selectedMetaWin) {
this._selectedMetaWin.activate(global.get_current_time());
- } else if (showWidowsBeforeActivation && opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE && !isShiftPressed && this.app.get_n_windows() > 1) {
+ } else if (showWidowsBeforeActivation && opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE && !isShiftPressed && this.app.get_n_windows() > 1) {
// expose windows
Main.overview._overview._controls._thumbnailsBox._activateThumbnailAtPoint(0, 0, global.get_current_time(), true);
return;
- } else if (opt.DASH_SHIFT_CLICK_MV && isShiftPressed && this.app.get_windows().length) {
+ } else if (((opt.DASH_SHIFT_CLICK_MV && isShiftPressed) || ((opt.DASH_CLICK_PREFER_WORKSPACE || opt.DASH_ISOLATE_WS) && !openNewWindow)) && this.app.get_windows().length) {
this._moveAppToCurrentWorkspace();
+ if (opt.DASH_ISOLATE_WS) {
+ this.app.activate();
+ // hide the overview after the window is re-created
+ GLib.idle_add(GLib.PRIORITY_LOW, () => Main.overview.hide());
+ }
return;
} else if (isShiftPressed) {
return;
@@ -918,8 +1234,7 @@ const AppIconCommon = {
},
popupMenu(side = St.Side.LEFT) {
- if (shellVersion >= 42)
- this.setForcedHighlight(true);
+ this.setForcedHighlight(true);
this._removeMenuTimeout();
this.fake_release();
@@ -939,7 +1254,7 @@ const AppIconCommon = {
}
if (!this._menu) {
- this._menu = new AppMenu(this, side, {
+ this._menu = new AppMenu.AppMenu(this, side, {
favoritesSection: true,
showSingleWindows: true,
});
@@ -986,8 +1301,12 @@ const AppIconCommon = {
}]);
}
- if (/* opt.APP_MENU_MV_TO_WS && */this._windowsOnOtherWs())
- popupItems.push([_('Move App to Current Workspace ( Shift + Click )'), this._moveAppToCurrentWorkspace]);
+ 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]);
+ }]);
+ }
}
this._addedMenuItems = [];
@@ -996,6 +1315,8 @@ const AppIconCommon = {
let item = new PopupMenu.PopupMenuItem(i[0]);
this._menu.addMenuItem(item);
item.connect('activate', i[1].bind(this));
+ if (i[1] === this._moveAppToCurrentWorkspace && !this._windowsOnOtherWs())
+ item.setSensitive(false);
this._addedMenuItems.push(item);
});
@@ -1007,71 +1328,33 @@ const AppIconCommon = {
return false;
},
-};
-function _getWindowApp(metaWin) {
- const tracker = Shell.WindowTracker.get_default();
- return tracker.get_window_app(metaWin);
-}
-
-function _getAppLastUsedWindow(app) {
- let recentWin;
- global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null).forEach(metaWin => {
- const winApp = _getWindowApp(metaWin);
- if (!recentWin && winApp === app)
- recentWin = metaWin;
- });
- return recentWin;
-}
-
-function _getAppRecentWorkspace(app) {
- const recentWin = _getAppLastUsedWindow(app);
- if (recentWin)
- return recentWin.get_workspace();
-
- return null;
-}
-
-function _updateSearchWindowsIcon(show = opt.SHOW_WINDOWS_ICON) {
- const 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 = undefined;
- if (dash._showWindowsIcon)
- dash._showWindowsIcon.destroy();
- dash._showWindowsIcon = undefined;
- }
-
- if (!show || !opt.WINDOW_SEARCH_PROVIDER_ENABLED)
- return;
-
- if (!dash._showWindowsIcon) {
- dash._showWindowsIcon = new ShowWindowsIcon();
- dash._showWindowsIcon.show(false);
- dashContainer.add_child(dash._showWindowsIcon);
- dash._hookUpLabel(dash._showWindowsIcon);
- }
+ _getWindowApp(metaWin) {
+ const tracker = Shell.WindowTracker.get_default();
+ return tracker.get_window_app(metaWin);
+ },
- 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);
- }
+ _getAppLastUsedWindow(app) {
+ let recentWin;
+ global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null).forEach(metaWin => {
+ const winApp = this._getWindowApp(metaWin);
+ if (!recentWin && winApp === app)
+ recentWin = metaWin;
+ });
+ return recentWin;
+ },
- Main.overview._overview._controls.layoutManager._dash._adjustIconSize();
-}
+ _getAppRecentWorkspace(app) {
+ const recentWin = this._getAppLastUsedWindow(app);
+ if (recentWin)
+ return recentWin.get_workspace();
-const ShowWindowsIcon = GObject.registerClass(
-class ShowWindowsIcon extends Dash.DashItemContainer {
- _init() {
- super._init();
+ return null;
+ },
+};
+const ShowWindowsIcon = {
+ _afterInit() {
this._isSearchWindowsIcon = true;
this._labelText = _('Search Open Windows (Hotkey: Space)');
this.toggleButton = new St.Button({
@@ -1096,10 +1379,10 @@ class ShowWindowsIcon extends Dash.DashItemContainer {
if (opt.SEARCH_WINDOWS_ICON_SCROLL) {
this.reactive = true;
- this._scrollConId = this.connect('scroll-event', _onScrollEvent.bind(this));
- this._leaveConId = this.connect('leave-event', _onLeaveEvent.bind(this));
+ this._scrollConId = this.connect('scroll-event', DashExtensions.onScrollEvent.bind(this));
+ this._leaveConId = this.connect('leave-event', DashExtensions.onLeaveEvent.bind(this));
}
- }
+ },
_createIcon(size) {
this._iconActor = new St.Icon({
@@ -1109,50 +1392,47 @@ class ShowWindowsIcon extends Dash.DashItemContainer {
track_hover: true,
});
return this._iconActor;
- }
-});
-
-function _updateRecentFilesIcon(show = opt.SHOW_RECENT_FILES_ICON) {
- const 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 = undefined;
- if (dash._recentFilesIcon)
- dash._recentFilesIcon.destroy();
- dash._recentFilesIcon = undefined;
- }
+ },
+};
- if (!show || !opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED)
- return;
+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,
+ });
- if (!dash._recentFilesIcon) {
- dash._recentFilesIcon = new ShowRecentFilesIcon();
- dash._recentFilesIcon.show(false);
- dashContainer.add_child(dash._recentFilesIcon);
- dash._hookUpLabel(dash._recentFilesIcon);
- }
+ 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;
- 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);
- }
+ this.toggleButton.add_actor(this.icon);
+ this.toggleButton._delegate = this;
- Main.overview._overview._controls.layoutManager._dash._adjustIconSize();
-}
+ this.setChild(this.toggleButton);
+ },
-const ShowRecentFilesIcon = GObject.registerClass(
-class ShowRecentFilesIcon extends Dash.DashItemContainer {
- _init() {
- super._init();
+ _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;
+ },
+};
- this._labelText = _('Search Recent Files (Hotkey: Ctrl + Space)');
+const ShowExtensionsIcon = {
+ _afterInit() {
+ this._labelText = _('Search Extensions (Hotkey: Ctrl + Shift + Space)');
this.toggleButton = new St.Button({
style_class: 'show-apps',
track_hover: true,
@@ -1172,15 +1452,55 @@ class ShowRecentFilesIcon extends Dash.DashItemContainer {
this.toggleButton._delegate = this;
this.setChild(this.toggleButton);
- }
+ },
_createIcon(size) {
this._iconActor = new St.Icon({
- icon_name: 'document-open-recent-symbolic',
+ icon_name: 'application-x-addon-symbolic',
icon_size: size,
style_class: 'show-apps-icon',
track_hover: true,
});
return this._iconActor;
- }
-});
+ },
+};
+
+const AppMenuCommon = {
+ _updateWindowsSection() {
+ if (global.compositor) {
+ if (this._updateWindowsLaterId) {
+ const laters = global.compositor.get_laters();
+ laters.remove(this._updateWindowsLaterId);
+ }
+ } else if (this._updateWindowsLaterId) {
+ Meta.later_remove(this._updateWindowsLaterId);
+ }
+
+ this._updateWindowsLaterId = 0;
+
+ this._windowSection.removeAll();
+ this._openWindowsHeader.hide();
+
+ if (!this._app)
+ return;
+
+ const minWindows = this._showSingleWindows ? 1 : 2;
+ const currentWs = global.workspaceManager.get_active_workspace();
+ const isolateWs = opt.DASH_ISOLATE_WS && !Main.overview.dash.showAppsButton.checked;
+ const windows = this._app.get_windows().filter(w => !w.skip_taskbar && (isolateWs ? w.get_workspace() === currentWs : true));
+ if (windows.length < minWindows)
+ return;
+
+ this._openWindowsHeader.show();
+
+ windows.forEach(window => {
+ const title = window.title || this._app.get_name();
+ const item = this._windowSection.addAction(title, event => {
+ Main.activateWindow(window, event.get_time());
+ });
+ window.connectObject('notify::title', () => {
+ item.label.text = window.title || this._app.get_name();
+ }, item);
+ });
+ },
+};
diff --git a/extensions/44/vertical-workspaces/lib/extensionsSearchProvider.js b/extensions/44/vertical-workspaces/lib/extensionsSearchProvider.js
new file mode 100644
index 0000000..5d0f28a
--- /dev/null
+++ b/extensions/44/vertical-workspaces/lib/extensionsSearchProvider.js
@@ -0,0 +1,423 @@
+/**
+* V-Shell (Vertical Workspaces)
+ * extensionsSearchProvider.js
+ *
+ * @author GdH <G-dH@github.com>
+ * @copyright 2022 - 2023
+ * @license GPL-3.0
+ */
+
+'use strict';
+
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const St = imports.gi.St;
+const Shell = imports.gi.Shell;
+const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
+
+const Main = imports.ui.main;
+
+const ExtensionState = {
+ 1: 'ENABLED',
+ 2: 'DISABLED',
+ 3: 'ERROR',
+ 4: 'INCOMPATIBLE',
+ 5: 'DOWNLOADING',
+ 6: 'INITIALIZED',
+ 7: 'DISABLING',
+ 8: 'ENABLING',
+};
+
+let Me;
+let opt;
+// gettext
+let _;
+let _toggleTimeout;
+
+// prefix helps to eliminate results from other search providers
+// so it needs to be something less common
+// needs to be accessible from vw module
+const PREFIX = 'eq//';
+
+var ExtensionsSearchProviderModule = class {
+ // export for other modules
+ static _PREFIX = PREFIX;
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ _ = Me.gettext;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._extensionsSearchProvider = null;
+ this._enableTimeoutId = 0;
+ }
+
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ _ = null;
+ }
+
+ update(reset) {
+ if (_toggleTimeout)
+ GLib.source_remove(_toggleTimeout);
+
+ this.moduleEnabled = opt.get('extensionsSearchProviderModule');
+
+ reset = reset || !this.moduleEnabled;
+
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' ExtensionsSearchProviderModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ // delay because Fedora had problem to register a new provider soon after Shell restarts
+ this._enableTimeoutId = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ 2000,
+ () => {
+ if (!this._extensionsSearchProvider) {
+ this._extensionsSearchProvider = new extensionsSearchProvider(opt);
+ this._getOverviewSearchResult()._registerProvider(this._extensionsSearchProvider);
+ }
+ this._enableTimeoutId = 0;
+ return GLib.SOURCE_REMOVE;
+ }
+ );
+ console.debug(' ExtensionsSearchProviderModule - Activated');
+ }
+
+ _disableModule() {
+ if (this._enableTimeoutId) {
+ GLib.source_remove(this._enableTimeoutId);
+ this._enableTimeoutId = 0;
+ }
+
+ if (this._extensionsSearchProvider) {
+ this._getOverviewSearchResult()._unregisterProvider(this._extensionsSearchProvider);
+ this._extensionsSearchProvider = null;
+ }
+
+ console.debug(' ExtensionsSearchProviderModule - Disabled');
+ }
+
+ _getOverviewSearchResult() {
+ return Main.overview._overview.controls._searchController._searchResults;
+ }
+};
+
+class extensionsSearchProvider {
+ constructor() {
+ this.id = 'extensions';
+ const appSystem = Shell.AppSystem.get_default();
+ let appInfo = appSystem.lookup_app('com.matjakeman.ExtensionManager.desktop')?.get_app_info();
+ if (!appInfo)
+ appInfo = appSystem.lookup_app('org.gnome.Extensions.desktop')?.get_app_info();
+ if (!appInfo)
+ appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/gnome-extensions-app', 'Extensions', null);
+ appInfo.get_description = () => _('Search extensions');
+ appInfo.get_name = () => _('Extensions');
+ appInfo.get_id = () => 'org.gnome.Extensions.desktop';
+ appInfo.get_icon = () => Gio.icon_new_for_string('application-x-addon');
+ appInfo.should_show = () => true;
+
+ this.appInfo = appInfo;
+ this.canLaunchSearch = true;
+ this.isRemoteProvider = false;
+ }
+
+ getInitialResultSet(terms, callback /* , cancellable = null*/) {
+ // In GS 43 callback arg has been removed
+ /* if (Me.shellVersion >= 43)
+ cancellable = callback; */
+
+ const extensions = {};
+ Main.extensionManager._extensions.forEach(
+ e => {
+ extensions[e.uuid] = e;
+ }
+ );
+ this.extensions = extensions;
+
+ if (Me.shellVersion >= 43)
+ return new Promise(resolve => resolve(this._getResultSet(terms)));
+ else
+ callback(this._getResultSet(terms));
+
+ return null;
+ }
+
+ _getResultSet(terms) {
+ // do not modify original terms
+ let termsCopy = [...terms];
+ // search for terms without prefix
+ termsCopy[0] = termsCopy[0].replace(PREFIX, '');
+
+ const candidates = this.extensions;
+ const _terms = [].concat(termsCopy);
+
+ const term = _terms.join(' ');
+
+ const results = [];
+ let m;
+ for (let id in candidates) {
+ const extension = this.extensions[id];
+ const text = extension.metadata.name + (extension.state === 1 ? 'enabled' : '') + ([6, 2].includes(extension.state) ? 'disabled' : '');
+ if (opt.SEARCH_FUZZY)
+ m = Me.Util.fuzzyMatch(term, text);
+ else
+ m = Me.Util.strictMatch(term, text);
+
+ if (m !== -1)
+ results.push({ weight: m, id });
+ }
+
+ // sort alphabetically
+ results.sort((a, b) => this.extensions[a.id].metadata.name.localeCompare(this.extensions[b.id].metadata.name));
+ // enabled first
+ // results.sort((a, b) => this.extensions[a.id].state !== 1 && this.extensions[b.id].state === 1);
+ // incompatible last
+ results.sort((a, b) => this.extensions[a.id].state === 4 && this.extensions[b.id].state !== 4);
+
+ this.resultIds = results.map(item => item.id);
+ return this.resultIds;
+ }
+
+ getResultMetas(resultIds, callback = null) {
+ const metas = resultIds.map(id => this.getResultMeta(id));
+ if (Me.shellVersion >= 43)
+ return new Promise(resolve => resolve(metas));
+ else if (callback)
+ callback(metas);
+ return null;
+ }
+
+ getResultMeta(resultId) {
+ const result = this.extensions[resultId];
+
+ const versionName = result.metadata['version-name'] ?? '';
+ let version = result.metadata['version'] ?? '';
+ version = versionName && version ? `/${version}` : version;
+ const versionStr = `${versionName}${version}`;
+
+ return {
+ 'id': resultId,
+ 'name': `${result.metadata.name}`,
+ 'version': versionStr,
+ 'description': versionStr, // description will be updated in result object
+ 'createIcon': size => {
+ let icon = this.getIcon(result, size);
+ return icon;
+ },
+ };
+ }
+
+ getIcon(extension, size) {
+ let opacity = 0;
+ let iconName = 'process-stop-symbolic';
+
+ switch (extension.state) {
+ case 1:
+ if (extension.hasUpdate)
+ iconName = 'software-update-available'; // 'software-update-available-symbolic';
+ else
+ iconName = 'object-select';// 'object-select-symbolic';
+
+ opacity = 255;
+ break;
+ case 3:
+ if (Main.extensionManager._enabledExtensions.includes(extension.uuid))
+ iconName = 'emblem-ok-symbolic';
+ else
+ iconName = 'dialog-error';
+ opacity = 100;
+ break;
+ case 4:
+ iconName = 'software-update-urgent'; // 'software-update-urgent-symbolic';
+ opacity = 100;
+ break;
+ }
+
+ if (extension.hasUpdate) {
+ iconName = 'software-update-available'; // 'software-update-available-symbolic';
+ opacity = 100;
+ }
+
+ const icon = new St.Icon({ icon_name: iconName, icon_size: size });
+ icon.set({
+ reactive: true,
+ opacity,
+ });
+
+ return icon;
+ }
+
+ createResultObject(meta) {
+ return new ListSearchResult(this, meta, this.extensions[meta.id]);
+ }
+
+ launchSearch(terms, timeStamp) {
+ this.appInfo.launch([], global.create_app_launch_context(timeStamp, -1), null);
+ }
+
+ activateResult(resultId/* terms, timeStamp*/) {
+ const extension = this.extensions[resultId];
+ if (Me.Util.isShiftPressed())
+ this._toggleExtension(extension);
+ else if (extension.hasPrefs)
+ Me.Util.openPreferences(extension.metadata);
+ }
+
+ filterResults(results /* , maxResults*/) {
+ // return results.slice(0, maxResults);
+ return results;
+ }
+
+ getSubsearchResultSet(previousResults, terms, callback) {
+ if (Me.shellVersion < 43) {
+ this.getSubsearchResultSet42(terms, callback);
+ return null;
+ }
+ return this.getInitialResultSet(terms);
+ }
+
+ getSubsearchResultSet42(terms, callback) {
+ callback(this._getResultSet(terms));
+ }
+}
+
+const ListSearchResult = GObject.registerClass(
+class ListSearchResult extends St.Button {
+ _init(provider, metaInfo, extension) {
+ this.provider = provider;
+ this.metaInfo = metaInfo;
+ this.extension = extension;
+
+ super._init({
+ reactive: true,
+ can_focus: true,
+ track_hover: true,
+ });
+
+ this.style_class = 'list-search-result';
+
+ let content = new St.BoxLayout({
+ style_class: 'list-search-result-content',
+ vertical: false,
+ x_align: Clutter.ActorAlign.START,
+ x_expand: true,
+ y_expand: true,
+ });
+ this.set_child(content);
+
+ let titleBox = new St.BoxLayout({
+ style_class: 'list-search-result-title',
+ y_align: Clutter.ActorAlign.CENTER,
+ });
+
+ content.add_child(titleBox);
+
+ // An icon for, or thumbnail of, content
+ let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
+ let iconBox = new St.Button();
+ iconBox.set_child(icon);
+ titleBox.add(iconBox);
+ iconBox.set_style('border: 1px solid rgba(200,200,200,0.2); padding: 2px; border-radius: 8px;');
+ this._iconBox = iconBox;
+ this.icon = icon;
+
+ iconBox.connect('clicked', () => {
+ this._toggleExtension();
+ return Clutter.EVENT_STOP;
+ });
+
+ let title = new St.Label({
+ text: this.metaInfo['name'],
+ y_align: Clutter.ActorAlign.CENTER,
+ opacity: extension.hasPrefs ? 255 : 150,
+ });
+ titleBox.add_child(title);
+
+ this.label_actor = title;
+
+ this._descriptionLabel = new St.Label({
+ style_class: 'list-search-result-description',
+ y_align: Clutter.ActorAlign.CENTER,
+ });
+ content.add_child(this._descriptionLabel);
+
+ this._highlightTerms();
+
+ this.connect('destroy', () => {
+ if (_toggleTimeout) {
+ GLib.source_remove(_toggleTimeout);
+ _toggleTimeout = 0;
+ }
+ });
+ }
+
+ _toggleExtension() {
+ const state = this.extension.state;
+ if (![1, 2, 6, 3].includes(state) || this.extension.metadata.uuid.includes('vertical-workspaces'))
+ return;
+
+ if ([2, 6].includes(state))
+ Main.extensionManager.enableExtension(this.extension.uuid);
+ else if ([1, 3].includes(state))
+ Main.extensionManager.disableExtension(this.extension.uuid);
+
+ if (_toggleTimeout)
+ GLib.source_remove(_toggleTimeout);
+
+ _toggleTimeout = GLib.timeout_add(GLib.PRIORITY_LOW, 200,
+ () => {
+ if ([7, 8].includes(this.extension.state))
+ return GLib.SOURCE_CONTINUE;
+
+ this.icon?.destroy();
+ this.icon = this.metaInfo['createIcon'](this.ICON_SIZE);
+ this._iconBox.set_child(this.icon);
+ this._highlightTerms();
+
+ _toggleTimeout = 0;
+ return GLib.SOURCE_REMOVE;
+ }
+ );
+ }
+
+ get ICON_SIZE() {
+ return 24;
+ }
+
+ _highlightTerms() {
+ const extension = this.extension;
+ const state = extension.state === 4 ? ExtensionState[this.extension.state] : '';
+ const error = extension.state === 3 ? ` ERROR: ${this.extension.error}` : '';
+ const update = extension.hasUpdate ? ' | UPDATE PENDING' : '';
+ const text = `${this.metaInfo.version} ${state}${error}${update}`;
+ let markup = text;// this.metaInfo['description'].split('\n')[0];
+ this._descriptionLabel.clutter_text.set_markup(markup);
+ }
+
+ vfunc_clicked() {
+ this.activate();
+ }
+
+ activate() {
+ this.provider.activateResult(this.metaInfo.id);
+
+ if (this.metaInfo.clipboardText) {
+ St.Clipboard.get_default().set_text(
+ St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
+ }
+ Main.overview.toggle();
+ }
+});
diff --git a/extensions/44/vertical-workspaces/lib/iconGrid.js b/extensions/44/vertical-workspaces/lib/iconGrid.js
index 1aa980e..1f7516b 100644
--- a/extensions/44/vertical-workspaces/lib/iconGrid.js
+++ b/extensions/44/vertical-workspaces/lib/iconGrid.js
@@ -9,11 +9,13 @@
*/
'use strict';
-const { GLib, St, Meta } = imports.gi;
+
+const St = imports.gi.St;
+
const IconGrid = imports.ui.iconGrid;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-const shellVersion = _Util.shellVersion;
+
+let Me;
+let opt;
// added sizes for better scaling
const IconSize = {
@@ -29,47 +31,58 @@ const IconSize = {
LARGE: 96,
80: 80,
64: 64,
- 48: 48,
- TINY: 32,
+ TINY: 48,
};
const PAGE_WIDTH_CORRECTION = 100;
-let opt;
-let _overrides;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('appDisplayModule', true);
- reset = reset || !moduleEnabled;
+var IconGridModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
- _firstRun = false;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- if (_overrides)
- _overrides.removeAll();
+ update(reset) {
+ this.moduleEnabled = opt.get('appDisplayModule');
+ // if notifications are enabled no override is needed
+ reset = reset || !this.moduleEnabled;
+
+ // don't touch original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ }
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- if (reset) {
- _overrides = null;
- opt = null;
- return;
+ if (Me.shellVersion < 43 && IconGridCommon._findBestModeForSize) {
+ IconGridCommon['findBestModeForSize'] = IconGridCommon._findBestModeForSize;
+ delete IconGridCommon['_findBestModeForSize'];
+ }
+ this._overrides.addOverride('IconGrid', IconGrid.IconGrid.prototype, IconGridCommon);
+ this._overrides.addOverride('IconGridLayout', IconGrid.IconGridLayout.prototype, IconGridLayoutCommon);
}
- _overrides = new _Util.Overrides();
-
- if (shellVersion < 43 && IconGridCommon._findBestModeForSize) {
- IconGridCommon['findBestModeForSize'] = IconGridCommon._findBestModeForSize;
- IconGridCommon['_findBestModeForSize'] = undefined;
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
}
- _overrides.addOverride('IconGrid', IconGrid.IconGrid.prototype, IconGridCommon);
- _overrides.addOverride('IconGridLayout', IconGrid.IconGridLayout.prototype, IconGridLayoutCommon);
-}
-// workaround - silence page -2 error on gnome 43 while cleaning app grid
+};
const IconGridCommon = {
getItemsAtPage(page) {
@@ -87,7 +100,7 @@ const IconGridCommon = {
return;
const { pagePadding } = this.layout_manager;
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const iconPadding = 53 * scaleFactor;
+ const iconPadding = 51 * scaleFactor;
// provided width is usually about 100px wider in horizontal orientation with prev/next page indicators
const pageIndicatorCompensation = opt.ORIENTATION ? 0 : PAGE_WIDTH_CORRECTION;
@@ -99,8 +112,13 @@ const IconGridCommon = {
this.layoutManager._gridWidth = width;
this.layoutManager._gridHeight = height;
+ width -= 80; // compensation for default padding
+ height -= 80;
+
const spacing = opt.APP_GRID_SPACING;
- const iconSize = (opt.APP_GRID_ICON_SIZE > 0 ? opt.APP_GRID_ICON_SIZE : opt.APP_GRID_ICON_SIZE_DEFAULT) * scaleFactor;
+ // set the icon size as fixed to avoid changes in size later
+ const iconSize = opt.APP_GRID_ICON_SIZE > 0 ? opt.APP_GRID_ICON_SIZE : opt.APP_GRID_ICON_SIZE_DEFAULT;
+ const itemSize = iconSize * scaleFactor + iconPadding;
// if this._gridModes.length === 1, custom grid should be used
// if (iconSize > 0 && this._gridModes.length > 1) {
let columns = opt.APP_GRID_COLUMNS;
@@ -109,17 +127,20 @@ const IconGridCommon = {
let unusedSpaceH = -1;
let unusedSpaceV = -1;
if (!columns) {
- columns = Math.floor(width / (iconSize + iconPadding)) + 1;
+ // calculate #columns + 1 without spacing
+ columns = Math.floor(width / itemSize) + 1;
+ // check if columns with spacing fits the available width
+ // and reduce the number until it fits
while (unusedSpaceH < 0) {
columns -= 1;
- unusedSpaceH = width - columns * (iconSize + iconPadding) - (columns - 1) * spacing;
+ unusedSpaceH = width - columns * itemSize - (columns - 1) * spacing;
}
}
if (!rows) {
- rows = Math.floor(height / (iconSize + iconPadding)) + 1;
+ rows = Math.floor(height / itemSize) + 1;
while (unusedSpaceV < 0) {
rows -= 1;
- unusedSpaceV = height - rows * (iconSize + iconPadding) - (rows - 1) * spacing;
+ unusedSpaceV = height - rows * itemSize - ((rows - 1) * spacing);
}
}
@@ -135,9 +156,16 @@ const IconGridLayoutCommon = {
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
const nColumns = this.columnsPerPage;
const nRows = this.rowsPerPage;
+
+ // if grid is not defined return default icon size
+ if (nColumns < 1 && nRows < 1) {
+ return this._isFolder
+ ? opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT : opt.APP_GRID_ICON_SIZE_DEFAULT;
+ }
+
const columnSpacingPerPage = opt.APP_GRID_SPACING * (nColumns - 1);
const rowSpacingPerPage = opt.APP_GRID_SPACING * (nRows - 1);
- const iconPadding = 53 * scaleFactor;
+ const iconPadding = 55 * scaleFactor;
const paddingH = this._isFolder ? this.pagePadding.left + this.pagePadding.right : 0;
const paddingV = this._isFolder ? this.pagePadding.top + this.pagePadding.bottom : 0;
@@ -156,10 +184,14 @@ const IconGridLayoutCommon = {
return opt.APP_GRID_ICON_SIZE_DEFAULT;*/
let iconSizes = Object.values(IconSize).sort((a, b) => b - a);
-
- // limit max icon size for folders, the whole range is for the main grid with active folders
- if (this._isFolder)
+ // limit max icon size for folders and fully adaptive folder grids, the whole range is for the main grid with active folders
+ if (this._isFolder && opt.APP_GRID_FOLDER_ADAPTIVE && opt.APP_GRID_FOLDER_ICON_SIZE < 0)
+ iconSizes = iconSizes.slice(iconSizes.indexOf(opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT), -1);
+ else if (this._isFolder)
iconSizes = iconSizes.slice(iconSizes.indexOf(IconSize.LARGE), -1);
+ else if (opt.APP_GRID_ADAPTIVE && opt.APP_GRID_ICON_SIZE < 0)
+ iconSizes = iconSizes.slice(iconSizes.indexOf(opt.APP_GRID_ICON_SIZE_DEFAULT), -1);
+
let sizeInvalid = false;
for (const size of iconSizes) {
@@ -167,10 +199,9 @@ const IconGridLayoutCommon = {
if (firstItem) {
firstItem.icon.setIconSize(size);
- const [firstItemWidth, firstItemHeight] =
- firstItem.get_preferred_size();
+ const [firstItemWidth] = firstItem.get_preferred_size();
- const itemSize = Math.max(firstItemWidth, firstItemHeight);
+ const itemSize = firstItemWidth;
if (itemSize < size)
sizeInvalid = true;
@@ -199,7 +230,7 @@ const IconGridLayoutCommon = {
removeItem(item) {
if (!this._items.has(item)) {
- log(`Item ${item} is not part of the IconGridLayout`);
+ console.error(`Item ${item} is not part of the IconGridLayout`);
return;
// throw new Error(`Item ${item} is not part of the IconGridLayout`);
}
@@ -215,13 +246,13 @@ const IconGridLayoutCommon = {
addItem(item, page = -1, index = -1) {
if (this._items.has(item)) {
- log(`iconGrid: Item ${item} already added to IconGridLayout`);
+ console.error(`iconGrid: Item ${item} already added to IconGridLayout`);
return;
// throw new Error(`Item ${item} already added to IconGridLayout`);
}
if (page > this._pages.length) {
- log(`iconGrid: Cannot add ${item} to page ${page}`);
+ console.error(`iconGrid: Cannot add ${item} to page ${page}`);
page = -1;
index = -1;
// throw new Error(`Cannot add ${item} to page ${page}`);
@@ -240,7 +271,7 @@ const IconGridLayoutCommon = {
moveItem(item, newPage, newPosition) {
if (!this._items.has(item)) {
- log(`iconGrid: Item ${item} is not part of the IconGridLayout`);
+ console.error(`iconGrid: Item ${item} is not part of the IconGridLayout`);
return;
// throw new Error(`Item ${item} is not part of the IconGridLayout`);
}
diff --git a/extensions/44/vertical-workspaces/lib/layout.js b/extensions/44/vertical-workspaces/lib/layout.js
index f6562fd..6e72645 100644
--- a/extensions/44/vertical-workspaces/lib/layout.js
+++ b/extensions/44/vertical-workspaces/lib/layout.js
@@ -10,67 +10,107 @@
'use strict';
-const { Meta, GLib, Shell, Clutter, GObject } = imports.gi;
+const GLib = imports.gi.GLib;
+const Meta = imports.gi.Meta;
+const Gio = imports.gi.Gio;
-const Main = imports.ui.main;
const Layout = imports.ui.layout;
-const Ripples = imports.ui.ripples;
-const DND = imports.ui.dnd;
+const Main = imports.ui.main;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
+let Me;
+let opt;
-let _overrides;
let _timeouts;
-let opt;
-let _firstRun = true;
-let _originalUpdateHotCorners;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('layoutModule', true);
- const conflict = _Util.getEnabledExtensions('custom-hot-corners').length ||
- _Util.getEnabledExtensions('dash-to-panel').length;
- reset = reset || !moduleEnabled;
+var LayoutModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ _timeouts = {};
- // don't even touch this module if disabled or in conflict
- if (_firstRun && (reset || conflict))
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ this._originalUpdateHotCorners = null;
+ }
- _firstRun = false;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
+
+ update(reset) {
+ this._removeTimeouts();
+
+ this.moduleEnabled = opt.get('layoutModule');
+ const conflict = Me.Util.getEnabledExtensions('custom-hot-corners').length ||
+ Me.Util.getEnabledExtensions('dash-to-panel').length;
- if (!_originalUpdateHotCorners)
- _originalUpdateHotCorners = Layout.LayoutManager.prototype._updateHotCorners;
+ if (conflict && !reset)
+ console.warn(`[${Me.metadata.name}] Warning: "Layout" module disabled due to potential conflict with another extension`);
- if (_overrides)
- _overrides.removeAll();
+ reset = reset || !this.moduleEnabled || conflict;
- if (_timeouts) {
- Object.values(_timeouts).forEach(t => {
- if (t)
- GLib.source_remove(t);
- });
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' LayoutModule - Keeping untouched');
}
- if (reset) {
- _overrides = null;
- opt = null;
- _timeouts = null;
- Main.layoutManager._updateHotCorners = _originalUpdateHotCorners;
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ _timeouts = {};
+
+ this._overrides.addOverride('LayoutManager', Main.layoutManager, LayoutManagerCommon);
+ this._overrides.addOverride('HotCorner', Layout.HotCorner.prototype, HotCornerCommon);
+
+ Main.layoutManager._updatePanelBarrier();
Main.layoutManager._updateHotCorners();
- return;
+
+ if (!this._hotCornersEnabledConId) {
+ this._interfaceSettings = new Gio.Settings({
+ schema_id: 'org.gnome.desktop.interface',
+ });
+ this._hotCornersEnabledConId = this._interfaceSettings.connect('changed::enable-hot-corners',
+ () => Main.layoutManager._updateHotCorners());
+ }
+
+ console.debug(' LayoutModule - Activated');
}
- _timeouts = {};
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
- _overrides = new _Util.Overrides();
- _overrides.addOverride('LayoutManager', Layout.LayoutManager.prototype, LayoutManagerCommon);
+ Main.layoutManager._updateHotCorners();
- Main.layoutManager._updateHotCorners = LayoutManagerCommon._updateHotCorners.bind(Main.layoutManager);
+ if (this._hotCornersEnabledConId) {
+ this._interfaceSettings.disconnect(this._hotCornersEnabledConId);
+ this._hotCornersEnabledConId = 0;
+ this._interfaceSettings = null;
+ }
- Main.layoutManager._updatePanelBarrier();
- Main.layoutManager._updateHotCorners();
-}
+ console.debug(' LayoutModule - Disabled');
+ }
+
+ _removeTimeouts() {
+ if (_timeouts) {
+ Object.values(_timeouts).forEach(t => {
+ if (t)
+ GLib.source_remove(t);
+ });
+ _timeouts = null;
+ }
+ }
+};
const LayoutManagerCommon = {
_updatePanelBarrier() {
@@ -84,7 +124,7 @@ const LayoutManagerCommon = {
this._leftPanelBarrier = null;
}
- if (!this.primaryMonitor || !opt)
+ if (!this.primaryMonitor || !opt || Me.Util.getEnabledExtensions('hidetopbar'))
return;
if (this.panelBox.height) {
@@ -113,6 +153,7 @@ const LayoutManagerCommon = {
// avoid errors if called from foreign override
if (!opt)
return;
+
// destroy old hot corners
this.hotCorners.forEach(corner => corner?.destroy());
this.hotCorners = [];
@@ -122,7 +163,7 @@ const LayoutManagerCommon = {
return;
}
- let size = this.panelBox.height;
+ let size = this.panelBox.height ? this.panelBox.height : 27;
// position 0 - default, 1-TL, 2-TR, 3-BL, 4-BR
const position = opt.HOT_CORNER_POSITION;
@@ -181,8 +222,8 @@ const LayoutManagerCommon = {
}
if (haveCorner) {
- let corner = new HotCorner(this, monitor, cornerX, cornerY);
- corner.setBarrierSize(size);
+ let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY);
+ corner.setBarrierSize(size, false);
this.hotCorners.push(corner);
} else {
this.hotCorners.push(null);
@@ -193,11 +234,8 @@ const LayoutManagerCommon = {
},
};
-var HotCorner = GObject.registerClass(
-class HotCorner extends Layout.HotCorner {
- _init(layoutManager, monitor, x, y) {
- super._init(layoutManager, monitor, x, y);
-
+const HotCornerCommon = {
+ after__init() {
let angle = 0;
switch (opt.HOT_CORNER_POSITION) {
case 2:
@@ -214,9 +252,14 @@ class HotCorner extends Layout.HotCorner {
this._ripples._ripple1.rotation_angle_z = angle;
this._ripples._ripple2.rotation_angle_z = angle;
this._ripples._ripple3.rotation_angle_z = angle;
- }
+ },
+
+ setBarrierSize(size, notMyCall = true) {
+ // ignore calls from the original _updateHotCorners() callback to avoid building barriers outside screen
+ if (notMyCall && size > 0) {
+ return;
+ }
- setBarrierSize(size) {
if (this._verticalBarrier) {
this._pressureBarrier.removeBarrier(this._verticalBarrier);
this._verticalBarrier.destroy();
@@ -232,8 +275,8 @@ class HotCorner extends Layout.HotCorner {
if (size > 0) {
const primaryMonitor = global.display.get_primary_monitor();
const monitor = this._monitor;
- const extendV = opt && opt.HOT_CORNER_EDGE && opt.DASH_VERTICAL && monitor.index === primaryMonitor;
- const extendH = opt && opt.HOT_CORNER_EDGE && !opt.DASH_VERTICAL && monitor.index === primaryMonitor;
+ const extendV = opt && opt.HOT_CORNER_ACTION && opt.HOT_CORNER_EDGE && opt.DASH_VERTICAL && monitor.index === primaryMonitor;
+ const extendH = opt && opt.HOT_CORNER_ACTION && opt.HOT_CORNER_EDGE && !opt.DASH_VERTICAL && monitor.index === primaryMonitor;
if (opt.HOT_CORNER_POSITION <= 1) {
this._verticalBarrier = new Meta.Barrier({
@@ -284,25 +327,52 @@ class HotCorner extends Layout.HotCorner {
this._pressureBarrier.addBarrier(this._verticalBarrier);
this._pressureBarrier.addBarrier(this._horizontalBarrier);
}
- }
+ },
_toggleOverview() {
if (!opt.HOT_CORNER_ACTION || (!opt.HOT_CORNER_FULLSCREEN && this._monitor.inFullscreen && !Main.overview.visible))
return;
if (Main.overview.shouldToggleByCornerOrButton()) {
- if ((opt.HOT_CORNER_ACTION === 1 && !_Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 2 && _Util.isCtrlPressed()))
+ if (Main.overview._shown) {
this._toggleWindowPicker(true);
- else if ((opt.HOT_CORNER_ACTION === 2 && !_Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 1 && _Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 3 && _Util.isCtrlPressed()))
+ } else if ((opt.HOT_CORNER_ACTION === 2 && !Me.Util.isCtrlPressed()) || ([3, 4, 5, 6].includes(opt.HOT_CORNER_ACTION) && Me.Util.isCtrlPressed())) {
+ // Default overview
+ opt.OVERVIEW_MODE = 0;
+ opt.OVERVIEW_MODE2 = false;
+ opt.WORKSPACE_MODE = 1;
+ this._toggleWindowPicker(true, true);
+ } else if (opt.HOT_CORNER_ACTION === 1) {
+ Main.overview.resetOverviewMode();
+ this._toggleWindowPicker(true, true);
+ } else if ((opt.HOT_CORNER_ACTION === 3 && !Me.Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 2 && Me.Util.isCtrlPressed()) || (opt.HOT_CORNER_ACTION === 6 && Me.Util.isCtrlPressed())) {
+ // Applications
this._toggleApplications(true);
- else if (opt.HOT_CORNER_ACTION === 3 && !_Util.isCtrlPressed())
+ } else if (opt.HOT_CORNER_ACTION === 4 && !Me.Util.isCtrlPressed()) {
+ // Overview - static ws preview
+ opt.OVERVIEW_MODE = 1;
+ opt.OVERVIEW_MODE2 = false;
+ opt.WORKSPACE_MODE = 0;
+ this._toggleWindowPicker(true, true);
+ } else if (opt.HOT_CORNER_ACTION === 5 && !Me.Util.isCtrlPressed()) {
+ // Overview - static ws
+ opt.OVERVIEW_MODE = 2;
+ opt.OVERVIEW_MODE2 = true;
+ opt.WORKSPACE_MODE = 0;
+ this._toggleWindowPicker(true, true);
+ } else if (opt.HOT_CORNER_ACTION === 6 && !Me.Util.isCtrlPressed()) {
+ // Window search provider
+ opt.OVERVIEW_MODE = 2;
+ opt.OVERVIEW_MODE2 = true;
+ opt.WORKSPACE_MODE = 0;
this._toggleWindowSearchProvider();
+ }
if (opt.HOT_CORNER_RIPPLES && Main.overview.animationInProgress)
this._ripples.playAnimation(this._x, this._y);
}
- }
+ },
- _toggleWindowPicker(leaveOverview = false) {
+ _toggleWindowPicker(leaveOverview = false, customOverviewMode = false) {
if (Main.overview._shown && (leaveOverview || !Main.overview.dash.showAppsButton.checked)) {
Main.overview.hide();
} else if (Main.overview.dash.showAppsButton.checked) {
@@ -320,17 +390,17 @@ class HotCorner extends Layout.HotCorner {
// delay cannot be too short
200,
() => {
- Main.overview.show();
+ Main.overview.show(1, customOverviewMode);
_timeouts.releaseKeyboardTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}
);
} else {
- Main.overview.show();
+ Main.overview.show(1, customOverviewMode);
}
}
- }
+ },
_toggleApplications(leaveOverview = false) {
if ((leaveOverview && Main.overview._shown) || Main.overview.dash.showAppsButton.checked) {
@@ -360,12 +430,15 @@ class HotCorner extends Layout.HotCorner {
Main.overview.show(2); // 2 for App Grid
}
}
- }
+ },
_toggleWindowSearchProvider() {
if (!Main.overview._overview._controls._searchController._searchActive) {
- this._toggleWindowPicker();
- const prefix = 'wq// ';
+ opt.OVERVIEW_MODE = 2;
+ opt.OVERVIEW_MODE2 = true;
+ opt.WORKSPACE_MODE = 0;
+ this._toggleWindowPicker(false, true);
+ const prefix = Me.WSP_PREFIX;
const position = prefix.length;
const searchEntry = Main.overview.searchEntry;
searchEntry.set_text(prefix);
@@ -376,5 +449,5 @@ class HotCorner extends Layout.HotCorner {
// Main.overview.searchEntry.text = '';
Main.overview.hide();
}
- }
-});
+ },
+};
diff --git a/extensions/44/vertical-workspaces/lib/messageTray.js b/extensions/44/vertical-workspaces/lib/messageTray.js
index b35541a..ef7a51b 100644
--- a/extensions/44/vertical-workspaces/lib/messageTray.js
+++ b/extensions/44/vertical-workspaces/lib/messageTray.js
@@ -10,58 +10,82 @@
'use strict';
-const { Clutter } = imports.gi;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
+const Clutter = imports.gi.Clutter;
+
const Main = imports.ui.main;
+let Me;
let opt;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('messageTrayModule', true);
- reset = reset || !moduleEnabled;
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+var MessageTrayModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- _firstRun = false;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ }
- if (reset) {
+ cleanGlobals() {
+ Me = null;
opt = null;
- setNotificationPosition(1);
- return;
}
- setNotificationPosition(opt.NOTIFICATION_POSITION);
-}
+ update(reset) {
+ this.moduleEnabled = opt.get('messageTrayModule');
+ const conflict = false;
+
+ reset = reset || !this.moduleEnabled || conflict;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' MessageTrayModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ this._setNotificationPosition(opt.NOTIFICATION_POSITION);
+
+ console.debug(' MessageTrayModule - Activated');
+ }
+
+ _disableModule() {
+ this._setNotificationPosition(1);
+
+ console.debug(' MessageTrayModule - Disabled');
+ }
-function setNotificationPosition(position) {
- switch (position) {
- case 0:
- Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START;
- Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
- break;
- case 1:
- Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER;
- Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
- break;
- case 2:
- Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
- Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
- break;
- case 3:
- Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START;
- Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
- break;
- case 4:
- Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER;
- Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
- break;
- case 5:
- Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
- Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
- break;
+ _setNotificationPosition(position) {
+ switch (position) {
+ case 0:
+ Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START;
+ Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
+ break;
+ case 1:
+ Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER;
+ Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
+ break;
+ case 2:
+ Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
+ Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.START;
+ break;
+ case 3:
+ Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.START;
+ Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
+ break;
+ case 4:
+ Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.CENTER;
+ Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
+ break;
+ case 5:
+ Main.messageTray._bannerBin.x_align = Clutter.ActorAlign.END;
+ Main.messageTray._bannerBin.y_align = Clutter.ActorAlign.END;
+ break;
+ }
}
-}
+};
diff --git a/extensions/44/vertical-workspaces/lib/optionsFactory.js b/extensions/44/vertical-workspaces/lib/optionsFactory.js
index da62dd1..df6c970 100644
--- a/extensions/44/vertical-workspaces/lib/optionsFactory.js
+++ b/extensions/44/vertical-workspaces/lib/optionsFactory.js
@@ -9,41 +9,35 @@
'use strict';
-const { Gtk, Gio, GObject } = imports.gi;
+const Adw = imports.gi.Adw;
+const Gtk = imports.gi.Gtk;
+const Gio = imports.gi.Gio;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-const Settings = Me.imports.lib.settings;
-
-const shellVersion = Settings.shellVersion;
+let Me;
// gettext
-const _ = Settings._;
+let _; // = Settings._;
-const ProfileNames = [
- _('GNOME 3'),
- _('GNOME 40+ - Bottom Hot Edge'),
- _('Hot Corner Centric - Top Left Hot Corner'),
- _('Dock Overview - Bottom Hot Edge'),
-];
+function init(me) {
+ Me = me;
+ _ = Me.gettext;
+}
-// libadwaita is available starting with GNOME Shell 42.
-let Adw = null;
-try {
- Adw = imports.gi.Adw;
-} catch (e) {}
+function cleanGlobals() {
+ Me = null;
+ _ = null;
+}
function _newImageFromIconName(name) {
return Gtk.Image.new_from_icon_name(name);
}
var ItemFactory = class ItemFactory {
- constructor(gOptions) {
- this._gOptions = gOptions;
- this._settings = this._gOptions._gsettings;
+ constructor() {
+ this._settings = Me.Opt._gsettings;
}
- getRowWidget(text, caption, widget, variable, options = []) {
+ getRowWidget(text, caption, widget, variable, options = [], dependsOn) {
let item = [];
let label;
if (widget) {
@@ -81,8 +75,8 @@ var ItemFactory = class ItemFactory {
let key;
- if (variable && this._gOptions.options[variable]) {
- const opt = this._gOptions.options[variable];
+ if (variable && Me.Opt.options[variable]) {
+ const opt = Me.Opt.options[variable];
key = opt[1];
}
@@ -95,6 +89,11 @@ var ItemFactory = class ItemFactory {
this._connectComboBox(widget, key, variable, options);
else if (widget._isDropDown)
this._connectDropDown(widget, key, variable, options);
+
+ if (dependsOn) {
+ const dKey = Me.Opt.options[dependsOn][1];
+ this._settings.bind(dKey, widget, 'sensitive', Gio.SettingsBindFlags.GET);
+ }
}
return item;
@@ -111,7 +110,7 @@ var ItemFactory = class ItemFactory {
_connectComboBox(widget, key, variable, options) {
let model = widget.get_model();
widget._comboMap = {};
- const currentValue = this._gOptions.get(variable);
+ const currentValue = Me.Opt.get(variable);
for (const [label, value] of options) {
let iter;
model.set(iter = model.append(), [0, 1], [label, value]);
@@ -120,8 +119,8 @@ var ItemFactory = class ItemFactory {
widget._comboMap[value] = iter;
}
- this._gOptions.connect(`changed::${key}`, () => {
- widget.set_active_iter(widget._comboMap[this._gOptions.get(variable, true)]);
+ Me.Opt.connect(`changed::${key}`, () => {
+ widget.set_active_iter(widget._comboMap[Me.Opt.get(variable, true)]);
});
widget.connect('changed', () => {
const [success, iter] = widget.get_active_iter();
@@ -129,17 +128,17 @@ var ItemFactory = class ItemFactory {
if (!success)
return;
- this._gOptions.set(variable, model.get_value(iter, 1));
+ Me.Opt.set(variable, model.get_value(iter, 1));
});
}
_connectDropDown(widget, key, variable, options) {
const model = widget.get_model();
- const currentValue = this._gOptions.get(variable);
+ const currentValue = Me.Opt.get(variable);
for (let i = 0; i < options.length; i++) {
const text = options[i][0];
const id = options[i][1];
- model.append(new DropDownItem({ text, id }));
+ model.append(new DropDownItemVW({ text, id }));
if (id === currentValue)
widget.set_selected(i);
}
@@ -157,11 +156,11 @@ var ItemFactory = class ItemFactory {
widget.connect('notify::selected-item', dropDown => {
const item = dropDown.get_selected_item();
- this._gOptions.set(variable, item.id);
+ Me.Opt.set(variable, item.id);
});
- this._gOptions.connect(`changed::${key}`, () => {
- const newId = this._gOptions.get(variable, true);
+ Me.Opt.connect(`changed::${key}`, () => {
+ const newId = Me.Opt.get(variable, true);
for (let i = 0; i < options.length; i++) {
const id = options[i][1];
if (id === newId)
@@ -214,7 +213,7 @@ var ItemFactory = class ItemFactory {
newDropDown() {
const dropDown = new Gtk.DropDown({
model: new Gio.ListStore({
- item_type: DropDownItem,
+ item_type: DropDownItemVW,
}),
halign: Gtk.Align.END,
valign: Gtk.Align.CENTER,
@@ -255,11 +254,11 @@ var ItemFactory = class ItemFactory {
newLinkButton(uri) {
const linkBtn = new Gtk.LinkButton({
- label: shellVersion < 42 ? 'Click Me!' : '',
uri,
halign: Gtk.Align.END,
valign: Gtk.Align.CENTER,
hexpand: true,
+ icon_name: 'emblem-symbolic-link',
});
return linkBtn;
}
@@ -298,18 +297,23 @@ var ItemFactory = class ItemFactory {
entry.set_text(opt.get(`profileName${profileIndex}`));
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'edit-clear-symbolic');
entry.set_icon_activatable(Gtk.EntryIconPosition.SECONDARY, true);
- entry.connect('icon-press', e => e.set_text(''));
- entry.connect('changed', e => opt.set(`profileName${profileIndex}`, e.get_text()));
const resetProfile = this.newButton();
resetProfile.set({
tooltip_text: _('Reset profile to defaults'),
- icon_name: 'edit-delete-symbolic',
+ icon_name: 'document-revert-symbolic',
hexpand: false,
css_classes: ['destructive-action'],
});
function setName() {
+ const ProfileNames = [
+ _('GNOME 3'),
+ _('GNOME 40+ - Bottom Hot Edge'),
+ _('Hot Corner Centric - Top Left Hot Corner'),
+ _('Dock Overview - Bottom Hot Edge'),
+ ];
+
let name = opt.get(`profileName${profileIndex}`, true);
if (!name)
name = ProfileNames[profileIndex - 1];
@@ -317,6 +321,10 @@ var ItemFactory = class ItemFactory {
}
setName();
+
+ entry.connect('icon-press', e => e.set_text(''));
+ entry.connect('changed', e => opt.set(`profileName${profileIndex}`, e.get_text()));
+
resetProfile.connect('clicked', () => {
reset(profileIndex);
setName();
@@ -366,7 +374,7 @@ var ItemFactory = class ItemFactory {
valign: Gtk.Align.CENTER,
hexpand: true,
css_classes: ['destructive-action'],
- icon_name: 'edit-delete-symbolic',
+ icon_name: 'document-revert-symbolic',
});
btn.connect('clicked', () => {
@@ -382,7 +390,7 @@ var ItemFactory = class ItemFactory {
var AdwPrefs = class {
constructor(gOptions) {
- this._gOptions = gOptions;
+ Me.Opt = gOptions;
}
getFilledWindow(window, pages) {
@@ -457,158 +465,9 @@ var AdwPrefs = class {
}
};
-var LegacyPrefs = class {
- constructor(gOptions) {
- this._gOptions = gOptions;
- }
-
- getPrefsWidget(pages) {
- const prefsWidget = new Gtk.Box({
- orientation: Gtk.Orientation.VERTICAL,
- });
- const stack = new Gtk.Stack({
- hexpand: true,
- });
- const stackSwitcher = new Gtk.StackSwitcher({
- halign: Gtk.Align.CENTER,
- hexpand: true,
- });
-
- const context = stackSwitcher.get_style_context();
- context.add_class('caption');
-
- stackSwitcher.set_stack(stack);
- stack.set_transition_duration(300);
- stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT);
-
- const pageProperties = {
- hscrollbar_policy: Gtk.PolicyType.NEVER,
- vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
- vexpand: true,
- hexpand: true,
- visible: true,
- };
-
- const pagesBtns = [];
-
- for (let page of pages) {
- const name = page.name;
- const title = page.title;
- const iconName = page.iconName;
- const optionList = page.optionList;
-
- stack.add_named(this._getLegacyPage(optionList, pageProperties), name);
- pagesBtns.push(
- [new Gtk.Label({ label: title }), _newImageFromIconName(iconName, Gtk.IconSize.BUTTON)]
- );
- }
-
- let stBtn = stackSwitcher.get_first_child ? stackSwitcher.get_first_child() : null;
- for (let i = 0; i < pagesBtns.length; i++) {
- const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 6, visible: true });
- const icon = pagesBtns[i][1];
- icon.margin_start = 30;
- icon.margin_end = 30;
- box.append(icon);
- box.append(pagesBtns[i][0]);
- if (stackSwitcher.get_children) {
- stBtn = stackSwitcher.get_children()[i];
- stBtn.add(box);
- } else {
- stBtn.set_child(box);
- stBtn.visible = true;
- stBtn = stBtn.get_next_sibling();
- }
- }
-
- if (stack.show_all)
- stack.show_all();
- if (stackSwitcher.show_all)
- stackSwitcher.show_all();
-
- prefsWidget.append(stack);
-
- if (prefsWidget.show_all)
- prefsWidget.show_all();
-
- prefsWidget._stackSwitcher = stackSwitcher;
-
- return prefsWidget;
- }
-
- _getLegacyPage(optionList, pageProperties) {
- const page = new Gtk.ScrolledWindow(pageProperties);
- const mainBox = new Gtk.Box({
- orientation: Gtk.Orientation.VERTICAL,
- spacing: 5,
- homogeneous: false,
- margin_start: 30,
- margin_end: 30,
- margin_top: 12,
- margin_bottom: 12,
- });
-
- let context = page.get_style_context();
- context.add_class('background');
-
- let frame;
- let frameBox;
- for (let item of optionList) {
- // label can be plain text for Section Title
- // or GtkBox for Option
- const option = item[0];
- const widget = item[1];
-
- if (!widget) {
- const lbl = new Gtk.Label({
- label: option,
- xalign: 0,
- margin_bottom: 4,
- });
-
- context = lbl.get_style_context();
- context.add_class('heading');
-
- mainBox.append(lbl);
-
- frame = new Gtk.Frame({
- margin_bottom: 16,
- });
-
- frameBox = new Gtk.ListBox({
- selection_mode: null,
- });
-
- mainBox.append(frame);
- frame.set_child(frameBox);
- continue;
- }
-
- const grid = new Gtk.Grid({
- column_homogeneous: false,
- column_spacing: 20,
- margin_start: 8,
- margin_end: 8,
- margin_top: 8,
- margin_bottom: 8,
- hexpand: true,
- });
-
- grid.attach(option, 0, 0, 5, 1);
-
- if (widget)
- grid.attach(widget, 5, 0, 2, 1);
-
- frameBox.append(grid);
- }
- page.set_child(mainBox);
-
- return page;
- }
-};
-
-const DropDownItem = GObject.registerClass({
- GTypeName: 'DropdownItem',
+const { GObject } = imports.gi;
+const DropDownItemVW = GObject.registerClass({
+ GTypeName: 'DropDownItemVW',
Properties: {
'text': GObject.ParamSpec.string(
'text',
@@ -622,10 +481,11 @@ const DropDownItem = GObject.registerClass({
'Id',
'Item id stored in settings',
GObject.ParamFlags.READWRITE,
- 0, 100, 0
+ // min, max, default
+ -2147483648, 2147483647, 0
),
},
-}, class DropDownItem extends GObject.Object {
+}, class DropDownItemVW extends GObject.Object {
get text() {
return this._text;
}
@@ -641,5 +501,4 @@ const DropDownItem = GObject.registerClass({
set id(id) {
this._id = id;
}
-}
-);
+});
diff --git a/extensions/44/vertical-workspaces/lib/osdWindow.js b/extensions/44/vertical-workspaces/lib/osdWindow.js
index a010558..4699ddf 100644
--- a/extensions/44/vertical-workspaces/lib/osdWindow.js
+++ b/extensions/44/vertical-workspaces/lib/osdWindow.js
@@ -10,79 +10,104 @@
'use strict';
-const { Clutter } = imports.gi;
+const Clutter = imports.gi.Clutter;
+
const Main = imports.ui.main;
const OsdWindow = imports.ui.osdWindow;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-
-const OsdPositions = {
- 1: {
- x_align: Clutter.ActorAlign.START,
- y_align: Clutter.ActorAlign.START,
- },
- 2: {
- x_align: Clutter.ActorAlign.CENTER,
- y_align: Clutter.ActorAlign.START,
- },
- 3: {
- x_align: Clutter.ActorAlign.END,
- y_align: Clutter.ActorAlign.START,
- },
- 4: {
- x_align: Clutter.ActorAlign.CENTER,
- y_align: Clutter.ActorAlign.CENTER,
- },
- 5: {
- x_align: Clutter.ActorAlign.START,
- y_align: Clutter.ActorAlign.END,
- },
- 6: {
- x_align: Clutter.ActorAlign.CENTER,
- y_align: Clutter.ActorAlign.END,
- },
- 7: {
- x_align: Clutter.ActorAlign.END,
- y_align: Clutter.ActorAlign.END,
- },
-};
-
-let _overrides;
+let Me;
let opt;
-let _firstRun = true;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('osdWindowModule', true);
- reset = reset || !moduleEnabled;
+let OsdPositions;
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+var OsdWindowModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- _firstRun = false;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
- if (_overrides)
- _overrides.removeAll();
+ OsdPositions = {
+ 1: {
+ x_align: Clutter.ActorAlign.START,
+ y_align: Clutter.ActorAlign.START,
+ },
+ 2: {
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.START,
+ },
+ 3: {
+ x_align: Clutter.ActorAlign.END,
+ y_align: Clutter.ActorAlign.START,
+ },
+ 4: {
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.CENTER,
+ },
+ 5: {
+ x_align: Clutter.ActorAlign.START,
+ y_align: Clutter.ActorAlign.END,
+ },
+ 6: {
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.END,
+ },
+ 7: {
+ x_align: Clutter.ActorAlign.END,
+ y_align: Clutter.ActorAlign.END,
+ },
+ };
+ }
- if (reset || !moduleEnabled) {
- updateExistingOsdWindows(6);
- _overrides = null;
+ cleanGlobals() {
+ Me = null;
opt = null;
- return;
+ OsdPositions = null;
}
- _overrides = new _Util.Overrides();
- _overrides.addOverride('osdWindow', OsdWindow.OsdWindow.prototype, OsdWindowCommon);
-}
+ update(reset) {
+ this.moduleEnabled = opt.get('osdWindowModule');
+ const conflict = false;
-function updateExistingOsdWindows(position) {
- position = position ? position : opt.OSD_POSITION;
- Main.osdWindowManager._osdWindows.forEach(osd => {
- osd.set(OsdPositions[position]);
- });
-}
+ reset = reset || !this.moduleEnabled || conflict;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' OsdWindowModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ this._overrides.addOverride('osdWindow', OsdWindow.OsdWindow.prototype, OsdWindowCommon);
+ console.debug(' OsdWindowModule - Activated');
+ }
+
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+ this._updateExistingOsdWindows(6);
+
+ console.debug(' WorkspaceSwitcherPopupModule - Disabled');
+ }
+
+ _updateExistingOsdWindows(position) {
+ position = position ? position : opt.OSD_POSITION;
+ Main.osdWindowManager._osdWindows.forEach(osd => {
+ osd.set(OsdPositions[position]);
+ });
+ }
+};
const OsdWindowCommon = {
after_show() {
diff --git a/extensions/44/vertical-workspaces/lib/overlayKey.js b/extensions/44/vertical-workspaces/lib/overlayKey.js
index e0fc11d..815abaa 100644
--- a/extensions/44/vertical-workspaces/lib/overlayKey.js
+++ b/extensions/44/vertical-workspaces/lib/overlayKey.js
@@ -9,81 +9,94 @@
*/
'use strict';
-const { GObject, Gio, GLib, Meta, St } = imports.gi;
+
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Meta = imports.gi.Meta;
+const St = imports.gi.St;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-
-const _ = Me.imports.lib.settings._;
-const shellVersion = _Util.shellVersion;
-const WIN_SEARCH_PREFIX = Me.imports.lib.windowSearchProvider.prefix;
-const RECENT_FILES_PREFIX = Me.imports.lib.recentFilesSearchProvider.prefix;
-const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
-
+let Me;
let opt;
-let _firstRun = true;
-let _originalOverlayKeyHandlerId;
-let _overlayKeyHandlerId;
+var OverlayKeyModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('overlayKeyModule', true);
- reset = reset || (!_firstRun && !moduleEnabled);
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._originalOverlayKeyHandlerId = 0;
+ this._overlayKeyHandlerId = 0;
+ }
- // don't even touch this module if disabled
- if (_firstRun && !moduleEnabled)
- return;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- _firstRun = false;
+ update(reset) {
+ this.moduleEnabled = opt.get('overlayKeyModule');
+ const conflict = false;
- if (reset) {
- _updateOverlayKey(reset);
- opt = null;
- return;
+ reset = reset || !this.moduleEnabled || conflict;
+
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' OverlayKeyModule - Keeping untouched');
}
- _updateOverlayKey();
-}
-
-function _updateOverlayKey(reset = false) {
- if (reset) {
- _restoreOverlayKeyHandler();
- } else if (!_originalOverlayKeyHandlerId) {
- _originalOverlayKeyHandlerId = GObject.signal_handler_find(global.display, { signalId: 'overlay-key' });
- if (_originalOverlayKeyHandlerId !== null)
- global.display.block_signal_handler(_originalOverlayKeyHandlerId);
- _connectOverlayKey.bind(Main.overview._overview.controls)();
+ _activateModule() {
+ if (!this._originalOverlayKeyHandlerId) {
+ this._originalOverlayKeyHandlerId = GObject.signal_handler_find(global.display, { signalId: 'overlay-key' });
+ if (this._originalOverlayKeyHandlerId !== null) {
+ global.display.block_signal_handler(this._originalOverlayKeyHandlerId);
+ this._connectOverlayKey();
+ }
+ }
+ console.debug(' OverlayKeyModule - Activated');
}
-}
-function _restoreOverlayKeyHandler() {
- // Disconnect modified overlay key handler
- if (_overlayKeyHandlerId !== null) {
- global.display.disconnect(_overlayKeyHandlerId);
- _overlayKeyHandlerId = null;
+ _disableModule() {
+ this._restoreOverlayKeyHandler();
+
+ console.debug(' OverlayKeyModule - Disabled');
}
- // Unblock original overlay key handler
- if (_originalOverlayKeyHandlerId !== null) {
- global.display.unblock_signal_handler(_originalOverlayKeyHandlerId);
- _originalOverlayKeyHandlerId = null;
+ _restoreOverlayKeyHandler() {
+ // Disconnect modified overlay key handler
+ if (this._overlayKeyHandlerId) {
+ global.display.disconnect(this._overlayKeyHandlerId);
+ this._overlayKeyHandlerId = 0;
+ }
+
+ // Unblock original overlay key handler
+ if (this._originalOverlayKeyHandlerId) {
+ global.display.unblock_signal_handler(this._originalOverlayKeyHandlerId);
+ this._originalOverlayKeyHandlerId = 0;
+ }
}
-}
-function _connectOverlayKey() {
- this._a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA });
+ _connectOverlayKey() {
+ if (this._overlayKeyHandlerId)
+ return;
+
+ this._overlayKeyHandlerId = global.display.connect('overlay-key', this._onOverlayKeyPressed.bind(Main.overview._overview.controls));
+ }
- this._lastOverlayKeyTime = 0;
- _overlayKeyHandlerId = global.display.connect('overlay-key', () => {
+ _onOverlayKeyPressed() {
if (this._a11ySettings.get_boolean('stickykeys-enable'))
return;
const { initialState, finalState, transitioning } =
- this._stateAdjustment.getStateTransitionParams();
+ this._stateAdjustment.getStateTransitionParams();
const time = GLib.get_monotonic_time() / 1000;
const timeDiff = time - this._lastOverlayKeyTime;
@@ -95,14 +108,61 @@ function _connectOverlayKey() {
const mode = opt.OVERLAY_KEY_SECONDARY;
if (shouldShift) {
- if (mode === 1)
+ Me.Util.activateSearchProvider('');
+ if (mode === 1) {
this._shiftState(Meta.MotionDirection.UP);
- else if (mode === 2)
- _Util.activateSearchProvider(WIN_SEARCH_PREFIX);
- else if (mode === 3)
- _Util.activateSearchProvider(RECENT_FILES_PREFIX);
+ } else if (mode === 2) {
+ Me.Util.activateSearchProvider(Me.WSP_PREFIX);
+ } else if (mode === 3) {
+ // Changing the overview mode automatically changes the overview transition
+ opt.OVERVIEW_MODE = 0;
+ opt.OVERVIEW_MODE2 = false;
+ opt.WORKSPACE_MODE = 1;
+ }
} else {
- Main.overview.toggle();
+ if (Main.overview._shown) {
+ Main.overview.hide();
+ return;
+ }
+ switch (opt.OVERLAY_KEY_PRIMARY) {
+ case 0: // Disabled
+ return;
+ case 1: // Follow global overview mode
+ Main.overview.resetOverviewMode();
+ break;
+ case 2: // Default overview
+ opt.OVERVIEW_MODE = 0;
+ opt.OVERVIEW_MODE2 = false;
+ opt.WORKSPACE_MODE = 1;
+ break;
+ case 3: // Default overview
+ if (Main.overview._shown)
+ Main.overview.hide();
+ else
+ Main.overview.show(2);
+ return;
+ case 4: // Static WS preview
+ opt.OVERVIEW_MODE = 1;
+ opt.OVERVIEW_MODE2 = false;
+ if (!Main.overview._shown)
+ opt.WORKSPACE_MODE = 0;
+ break;
+ case 5: // Static WS
+ opt.OVERVIEW_MODE = 2;
+ opt.OVERVIEW_MODE2 = true;
+ opt.WORKSPACE_MODE = 0;
+ break;
+ case 6: // Window Search
+ opt.OVERVIEW_MODE = 2;
+ opt.OVERVIEW_MODE2 = true;
+ if (!Main.overview._shown)
+ opt.WORKSPACE_MODE = 0;
+ break;
+ }
+ const customOverviewMode = !Main.overview._shown;
+ Main.overview.toggle(customOverviewMode);
+ if (opt.OVERLAY_KEY_PRIMARY === 6)
+ Me.Util.activateSearchProvider(Me.WSP_PREFIX);
}
- });
-}
+ }
+};
diff --git a/extensions/44/vertical-workspaces/lib/overview.js b/extensions/44/vertical-workspaces/lib/overview.js
index 2f23d05..833fc58 100644
--- a/extensions/44/vertical-workspaces/lib/overview.js
+++ b/extensions/44/vertical-workspaces/lib/overview.js
@@ -10,43 +10,113 @@
'use strict';
+const Main = imports.ui.main;
const Overview = imports.ui.overview;
+const OverviewControls = imports.ui.overviewControls;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-
-let _overrides;
+let Me;
let opt;
-function update(reset = false) {
- if (_overrides)
- _overrides.removeAll();
+var OverviewModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
- if (reset) {
- _overrides = null;
+ cleanGlobals() {
+ Me = null;
opt = null;
- return;
}
- opt = Me.imports.lib.settings.opt;
- _overrides = new _Util.Overrides();
+ update(reset) {
+ this.moduleEnabled = true;
+ const conflict = false;
+
+ reset = reset || !this.moduleEnabled || conflict;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' OverviewModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- _overrides.addOverride('Overview', Overview.Overview.prototype, OverviewCommon);
-}
+ this._overrides.addOverride('Overview', Overview.Overview.prototype, OverviewCommon);
+ console.debug(' OverviewModule - Activated');
+ }
+
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ console.debug(' OverviewModule - Disabled');
+ }
+};
const OverviewCommon = {
+ show(state = OverviewControls.ControlsState.WINDOW_PICKER, customOverviewMode) {
+ if (!customOverviewMode)
+ this.resetOverviewMode();
+
+ if (state === OverviewControls.ControlsState.HIDDEN)
+ throw new Error('Invalid state, use hide() to hide');
+
+ if (this.isDummy)
+ return;
+ if (this._shown)
+ return;
+ this._shown = true;
+
+ if (!this._syncGrab())
+ return;
+
+ Main.layoutManager.showOverview();
+ this._animateVisible(state);
+ },
+
+ toggle(customOverviewMode) {
+ if (this.isDummy)
+ return;
+
+ if (this._visible)
+ this.hide();
+ else
+ this.show(OverviewControls.ControlsState.WINDOW_PICKER, customOverviewMode);
+ },
+
+ resetOverviewMode() {
+ // reset Overview Mode do default
+ opt.OVERVIEW_MODE = opt.get('overviewMode');
+ opt.OVERVIEW_MODE2 = opt.OVERVIEW_MODE === 2;
+ opt.WORKSPACE_MODE = opt.OVERVIEW_MODE > 0 ? 0 : 1;
+ },
+
_showDone() {
this._animationInProgress = false;
this._coverPane.hide();
- this.emit('shown');
+ if (Me.shellVersion < 44)
+ this.emit('shown');
+ else if (this._shownState !== 'SHOWN')
+ this._changeShownState('SHOWN');
+
// Handle any calls to hide* while we were showing
if (!this._shown)
this._animateNotVisible();
- this._syncGrab();
-
// if user activates overview during startup animation, transition needs to be shifted to the state 2 here
const controls = this._overview._controls;
if (controls._searchController._searchActive && controls._stateAdjustment.value === 1) {
@@ -55,5 +125,41 @@ const OverviewCommon = {
else if (!opt.OVERVIEW_MODE2)
controls._stateAdjustment.value = 2;
}
+
+ this._syncGrab();
+ },
+
+ // Workaround - should probably be fixed elsewhere in the upstream code
+ // If a new window is opened from the overview
+ // and is realized before the overview animation is complete,
+ // the new window will not get focus
+ after__hideDone() {
+ if (!opt.FIX_NEW_WINDOW_FOCUS)
+ return;
+
+ const workspace = global.workspace_manager.get_active_workspace();
+ const recentDesktopWin = global.display.get_tab_list(1, workspace)[0];
+ let recentNormalWin = null;
+ const tabList = global.display.get_tab_list(0, workspace);
+
+ for (let i = 0; i < tabList.length; i++) {
+ if (tabList[i].minimized === false) {
+ recentNormalWin = tabList[i];
+ break;
+ }
+ }
+
+ let recentWin = recentNormalWin;
+ if (recentNormalWin && recentDesktopWin) {
+ recentWin = recentNormalWin.get_user_time() > recentDesktopWin.get_user_time()
+ ? recentNormalWin
+ : recentDesktopWin;
+ }
+
+ const focusedWin = global.display.focus_window;
+
+ if (recentWin && focusedWin !== recentWin)
+ recentWin.activate(global.get_current_time());
},
};
+
diff --git a/extensions/44/vertical-workspaces/lib/overviewControls.js b/extensions/44/vertical-workspaces/lib/overviewControls.js
index 4959b83..7528682 100644
--- a/extensions/44/vertical-workspaces/lib/overviewControls.js
+++ b/extensions/44/vertical-workspaces/lib/overviewControls.js
@@ -10,90 +10,148 @@
'use strict';
-const { Clutter, GLib, GObject, St } = imports.gi;
+const Clutter = imports.gi.Clutter;
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const Background = imports.ui.background;
+const Layout = imports.ui.layout;
const Main = imports.ui.main;
-const Util = imports.misc.util;
+const Overview = imports.ui.overview;
const OverviewControls = imports.ui.overviewControls;
+const Workspace = imports.ui.workspace;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
+const WorkspacesView = imports.ui.workspacesView;
+const Util = imports.misc.util;
-const ControlsState = imports.ui.overviewControls.ControlsState;
-const FitMode = imports.ui.workspacesView.FitMode;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-const _Util = Me.imports.lib.util;
-
-let _overrides;
+let Me;
let opt;
+// gettext
+let _;
+
+const ControlsState = OverviewControls.ControlsState;
+const FitMode = WorkspacesView.FitMode;
-const ANIMATION_TIME = imports.ui.overview.ANIMATION_TIME;
+const ANIMATION_TIME = Overview.ANIMATION_TIME;
const DASH_MAX_SIZE_RATIO = 0.25;
let _originalSearchControllerSigId;
let _searchControllerSigId;
let _timeouts;
-let _startupInitComplete = false;
-function update(reset = false) {
- if (_overrides)
- _overrides.removeAll();
+var OverviewControlsModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ _ = Me.gettext;
- if (_timeouts) {
- Object.values(_timeouts).forEach(id => {
- if (id)
- GLib.source_remove(id);
- });
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
}
- _replaceOnSearchChanged(reset);
-
- if (reset) {
- _overrides = null;
+ cleanGlobals() {
+ Me = null;
opt = null;
- _timeouts = null;
- return;
+ _ = null;
}
- _timeouts = {};
+ update(reset) {
+ this._removeTimeouts();
+ this.moduleEnabled = true;
+ const conflict = false;
- opt = Me.imports.lib.settings.opt;
- _overrides = new _Util.Overrides();
+ reset = reset || !this.moduleEnabled || conflict;
- _overrides.addOverride('ControlsManager', OverviewControls.ControlsManager.prototype, ControlsManager);
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' OverviewControlsModule - Keeping untouched');
+ }
- if (opt.ORIENTATION === Clutter.Orientation.VERTICAL)
- _overrides.addOverride('ControlsManagerLayout', OverviewControls.ControlsManagerLayout.prototype, ControlsManagerLayoutVertical);
- else
- _overrides.addOverride('ControlsManagerLayout', OverviewControls.ControlsManagerLayout.prototype, ControlsManagerLayoutHorizontal);
-}
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ _timeouts = {};
+
+ this._replaceOnSearchChanged();
+
+ this._overrides.addOverride('ControlsManager', OverviewControls.ControlsManager.prototype, ControlsManagerCommon);
+
+ if (opt.ORIENTATION === Clutter.Orientation.VERTICAL)
+ this._overrides.addOverride('ControlsManagerLayout', OverviewControls.ControlsManagerLayout.prototype, ControlsManagerLayoutVertical);
+ else
+ this._overrides.addOverride('ControlsManagerLayout', OverviewControls.ControlsManagerLayout.prototype, ControlsManagerLayoutHorizontal);
+
+ // if DtD is enabled, we need to replace _prepareStartupAnimation() to minimize the mess in the overview
+ // const dashToDockEnabled = Me.Util.getEnabledExtensions('dash-to-dock').length ||
+ // Me.Util.getEnabledExtensions('ubuntu-dock').length;
+ // if (dashToDockEnabled)
+ this._overrides.addOverride('LayoutManagerDtD', Layout.LayoutManager.prototype, LayoutManager);
+
+ console.debug(' OverviewControlsModule - Activated');
+ }
+
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ const reset = true;
+ this._replaceOnSearchChanged(reset);
+ Main.overview._overview._controls._appDisplay.opacity = 255;
-function _replaceOnSearchChanged(reset = false) {
- const searchController = Main.overview._overview.controls._searchController;
- if (reset) {
- if (_searchControllerSigId) {
- searchController.disconnect(_searchControllerSigId);
- _searchControllerSigId = 0;
+ console.debug(' OverviewControlsModule - Disabled');
+ }
+
+ _removeTimeouts() {
+ if (_timeouts) {
+ Object.values(_timeouts).forEach(t => {
+ if (t)
+ GLib.source_remove(t);
+ });
+ _timeouts = null;
}
- if (_originalSearchControllerSigId) {
- searchController.unblock_signal_handler(_originalSearchControllerSigId);
- _originalSearchControllerSigId = 0;
+ }
+
+ _replaceOnSearchChanged(reset) {
+ const searchController = Main.overview._overview.controls._searchController;
+ if (reset) {
+ if (_searchControllerSigId) {
+ searchController.disconnect(_searchControllerSigId);
+ _searchControllerSigId = 0;
+ }
+ if (_originalSearchControllerSigId) {
+ searchController.unblock_signal_handler(_originalSearchControllerSigId);
+ _originalSearchControllerSigId = 0;
+ }
+ Main.overview._overview._controls.layoutManager._searchController._searchResults.translation_x = 0;
+ Main.overview._overview._controls.layoutManager._searchController._searchResults.translation_y = 0;
+ Main.overview.searchEntry.visible = true;
+ Main.overview.searchEntry.opacity = 255;
+ } else {
+ // reconnect signal to use custom function (callbacks cannot be overridden in class prototype, they are already in memory as a copy for the given callback)
+ if (!_originalSearchControllerSigId)
+ _originalSearchControllerSigId = GObject.signal_handler_find(searchController, { signalId: 'notify', detail: 'search-active' });
+ if (_originalSearchControllerSigId)
+ searchController.block_signal_handler(_originalSearchControllerSigId);
+
+ if (!_searchControllerSigId)
+ _searchControllerSigId = searchController.connect('notify::search-active', ControlsManagerCommon._onSearchChanged.bind(Main.overview._overview.controls));
}
- Main.overview._overview._controls.layoutManager._searchController._searchResults.translation_x = 0;
- Main.overview._overview._controls.layoutManager._searchController._searchResults.translation_y = 0;
- Main.overview.searchEntry.visible = true;
- Main.overview.searchEntry.opacity = 255;
- } else {
- // reconnect signal to use custom function (callbacks cannot be overridden in class prototype, they are already in memory as a copy for the given callback)
- _originalSearchControllerSigId = GObject.signal_handler_find(searchController, { signalId: 'notify', detail: 'search-active' });
- if (_originalSearchControllerSigId)
- searchController.block_signal_handler(_originalSearchControllerSigId);
-
- _searchControllerSigId = searchController.connect('notify::search-active', ControlsManager._onSearchChanged.bind(Main.overview._overview.controls));
}
-}
+};
-const ControlsManager = {
+const ControlsManagerCommon = {
// this function is used as a callback by a signal handler, needs to be reconnected after modification as the original callback uses a copy of the original function
/* _update: function() {
...
@@ -105,16 +163,21 @@ const ControlsManager = {
},
_updateThumbnailsBox() {
+ const { currentState } = this._stateAdjustment.getStateTransitionParams();
const { shouldShow } = this._thumbnailsBox;
- const thumbnailsBoxVisible = shouldShow;
+ const thumbnailsBoxVisible = shouldShow &&
+ ((currentState < ControlsState.APP_GRID && opt.SHOW_WS_TMB) ||
+ (currentState > ControlsState.WINDOW_PICKER && opt.SHOW_WS_TMB_APPGRID) ||
+ (currentState > ControlsState.WINDOW_PICKER && this._searchController.searchActive && opt.SHOW_WS_TMB)
+ );
this._thumbnailsBox.visible = thumbnailsBoxVisible;
// this call should be directly in _update(), but it's used as a callback function and it would require to reconnect the signal
- this._updateWorkspacesDisplay();
+ this._updateOverview();
},
// this function is pure addition to the original code and handles wsDisp transition to APP_GRID view
- _updateWorkspacesDisplay() {
+ _updateOverview() {
this._workspacesDisplay.translation_x = 0;
this._workspacesDisplay.translation_y = 0;
this._workspacesDisplay.scale_x = 1;
@@ -167,18 +230,21 @@ const ControlsManager = {
ws._background.opacity = opacity;
}
+ if (opt.WORKSPACE_MODE)
+ Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
+
// if ws preview background is disabled, animate tmb box and dash
const tmbBox = this._thumbnailsBox;
const dash = this.dash;
const searchEntryBin = this._searchEntryBin;
// this dash transition collides with startup animation and freezes GS for good, needs to be delayed (first Main.overview 'hiding' event enables it)
- const skipDash = _Util.dashNotDefault();
+ const skipDash = Me.Util.dashNotDefault();
// OVERVIEW_MODE 2 should animate dash and wsTmbBox only if WORKSPACE_MODE === 0 (windows not spread)
const animateOverviewMode2 = opt.OVERVIEW_MODE2 && !(finalState === 1 && opt.WORKSPACE_MODE);
if (!Main.layoutManager._startingUp && ((!opt.SHOW_WS_PREVIEW_BG && !opt.OVERVIEW_MODE2) || animateOverviewMode2)) {
if (!tmbBox._translationOriginal || Math.abs(tmbBox._translationOriginal[0]) > 500) { // swipe gesture can call this calculation before tmbBox is finalized, giving nonsense width
- const [tmbTranslationX, tmbTranslationY, dashTranslationX, dashTranslationY, searchTranslationY] = _Util.getOverviewTranslations(opt, dash, tmbBox, searchEntryBin);
+ const [dashTranslationX, dashTranslationY, tmbTranslationX, tmbTranslationY, searchTranslationY] = this._getOverviewTranslations(dash, tmbBox, searchEntryBin);
tmbBox._translationOriginal = [tmbTranslationX, tmbTranslationY];
dash._translationOriginal = [dashTranslationX, dashTranslationY];
searchEntryBin._translationOriginal = searchTranslationY;
@@ -229,7 +295,7 @@ const ControlsManager = {
// set searchEntry above appDisplay
this.set_child_above_sibling(this._searchEntryBin, null);
// move dash above wsTmb for case that dash and wsTmb animate from the same side
- if (!_Util.dashNotDefault())
+ if (!Me.Util.dashNotDefault())
this.set_child_above_sibling(dash, null);
this.set_child_below_sibling(this._thumbnailsBox, null);
this.set_child_below_sibling(this._workspacesDisplay, null);
@@ -238,7 +304,7 @@ const ControlsManager = {
// set dash above workspace in the overview
this.set_child_above_sibling(this._thumbnailsBox, null);
this.set_child_above_sibling(this._searchEntryBin, null);
- if (!_Util.dashNotDefault())
+ if (!Me.Util.dashNotDefault())
this.set_child_above_sibling(this.dash, null);
this.dash._isAbove = true;
@@ -247,6 +313,7 @@ const ControlsManager = {
this.set_child_above_sibling(this._workspacesDisplay, null);
this.dash._isAbove = false;
}
+
},
// fix for upstream bug - appGrid.visible after transition from APP_GRID to HIDDEN
@@ -258,12 +325,6 @@ const ControlsManager = {
if (this.dash.showAppsButton.checked)
this._searchTransition = false;
- // update App Grid after settings changed
- // only if the App Grid is currently visible on the screen, the paging updates correctly
- if (currentState === ControlsState.APP_GRID && this._appDisplay.visible && opt._appGridNeedsRedisplay) {
- Me.imports.lib.appDisplay._updateAppGridProperties();
- opt._appGridNeedsRedisplay = false;
- }
// if !APP_GRID_ANIMATION, appGrid needs to be hidden in WINDOW_PICKER mode (1)
// but needs to be visible for transition from HIDDEN (0) to APP_GRID (2)
this._appDisplay.visible =
@@ -305,11 +366,19 @@ const ControlsManager = {
this._workspacesDisplay.reactive = true;
this._workspacesDisplay.setPrimaryWorkspaceVisible(true);
} else {
+ if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE)
+ this._searchController._searchResults._statusText.add_style_class_name('search-statustext-om2');
+ else
+ this._searchController._searchResults._statusText.remove_style_class_name('search-statustext-om2');
this._searchController.show();
entry.visible = true;
entry.opacity = 255;
+ // avoid awkward ws scale animation during search activation
+ WorkspaceThumbnail.RESCALE_ANIMATION_TIME = 0;
}
+ if (opt.SHOW_BG_IN_OVERVIEW && this._bgManagers)
+ this._updateBackground(this._bgManagers[0]);
this._searchTransition = true;
this._searchController._searchResults.translation_x = 0;
@@ -317,34 +386,33 @@ const ControlsManager = {
this._searchController.opacity = 255;
this._searchController.visible = true;
- if (opt.SEARCH_VIEW_ANIMATION && !this.dash.showAppsButton.checked && ![4, 8].includes(opt.WS_TMB_POSITION) /* && !opt.OVERVIEW_MODE2*/) {
+ if (opt.SEARCH_VIEW_ANIMATION && ![4, 8].includes(opt.WS_TMB_POSITION) /* && !opt.OVERVIEW_MODE2*/) {
this._updateAppDisplayVisibility();
+ this.layoutManager._searchController._searchResults._statusBin.opacity = 1;
this._searchController.opacity = searchActive ? 255 : 0;
let translationX = 0;
let translationY = 0;
const geometry = global.display.get_monitor_geometry(global.display.get_primary_monitor());
- if (currentState < ControlsState.APP_GRID) {
- switch (opt.SEARCH_VIEW_ANIMATION) {
- case 1:
- // make it longer to cover the delay before results appears
- translationX = geometry.width;
- translationY = 0;
- break;
- case 2:
- translationX = -geometry.width;
- translationY = 0;
- break;
- case 3:
- translationX = 0;
- translationY = geometry.height;
- break;
- case 5:
- translationX = 0;
- translationY = -geometry.height;
- break;
- }
+ switch (opt.SEARCH_VIEW_ANIMATION) {
+ case 1:
+ // make it longer to cover the delay before results appears
+ translationX = geometry.width;
+ translationY = 0;
+ break;
+ case 2:
+ translationX = -geometry.width;
+ translationY = 0;
+ break;
+ case 3:
+ translationX = 0;
+ translationY = geometry.height;
+ break;
+ case 5:
+ translationX = 0;
+ translationY = -geometry.height;
+ break;
}
if (searchActive) {
@@ -363,6 +431,8 @@ const ControlsManager = {
onComplete: () => {
this._searchController.visible = searchActive;
this._searchTransition = false;
+ this.layoutManager._searchController._searchResults._statusBin.opacity = 255;
+ WorkspaceThumbnail.RESCALE_ANIMATION_TIME = 200;
},
});
@@ -372,7 +442,10 @@ const ControlsManager = {
opacity: searchActive || currentState < 2 ? 0 : 255,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => this._updateAppDisplayVisibility(),
+ onComplete: () => {
+ this._updateAppDisplayVisibility();
+ WorkspaceThumbnail.RESCALE_ANIMATION_TIME = 200;
+ },
});
// this._updateAppDisplayVisibility();
@@ -390,7 +463,7 @@ const ControlsManager = {
this._searchController.opacity = searchActive ? 0 : 255;
this._searchController.ease({
opacity: searchActive ? 255 : 0,
- duration: searchActive ? SIDE_CONTROLS_ANIMATION_TIME * 2 : 0,
+ duration: searchActive ? SIDE_CONTROLS_ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => (this._searchController.visible = searchActive),
});
@@ -398,14 +471,16 @@ const ControlsManager = {
// reuse already tuned overview transition, just replace APP_GRID with the search view
if (!(opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE) && !Main.overview._animationInProgress && finalState !== ControlsState.HIDDEN && !this.dash.showAppsButton.checked) {
- Main.overview._overview._controls.layoutManager._searchController._searchResults._content.remove_style_class_name('search-section-content-om2');
+ Main.overview._overview._controls.layoutManager._searchController._searchResults._content.remove_style_class_name('search-section-content-bg-om2');
+ Main.overview._overview._controls.layoutManager._searchController._searchResults._content.add_style_class_name('search-section-content-bg');
Main.overview.searchEntry.remove_style_class_name('search-entry-om2');
+ const duration = opt.SEARCH_VIEW_ANIMATION ? 150 : 0;
this._stateAdjustment.ease(searchActive ? ControlsState.APP_GRID : ControlsState.WINDOW_PICKER, {
// shorter animation time when entering search view can avoid stuttering in transition
// collecting search results take some time and the problematic part is the realization of the object on the screen
// if the ws animation ends before this event, the whole transition is smoother
// removing the ws transition (duration: 0) seems like the best solution here
- duration: searchActive || (opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE) ? 80 : SIDE_CONTROLS_ANIMATION_TIME,
+ duration: searchActive ? duration : SIDE_CONTROLS_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
this._workspacesDisplay.setPrimaryWorkspaceVisible(!searchActive);
@@ -413,18 +488,20 @@ const ControlsManager = {
});
} else if (opt.OVERVIEW_MODE2 && !(opt.WORKSPACE_MODE || this.dash.showAppsButton.checked)) {
// add background to search results and make searchEntry border thicker for better visibility
- Main.overview._overview._controls.layoutManager._searchController._searchResults._content.add_style_class_name('search-section-content-om2');
+ Main.overview._overview._controls.layoutManager._searchController._searchResults._content.remove_style_class_name('search-section-content-bg');
+ Main.overview._overview._controls.layoutManager._searchController._searchResults._content.add_style_class_name('search-section-content-bg-om2');
Main.overview.searchEntry.add_style_class_name('search-entry-om2');
} else {
- Main.overview._overview._controls.layoutManager._searchController._searchResults._content.remove_style_class_name('search-section-content-om2');
+ Main.overview._overview._controls.layoutManager._searchController._searchResults._content.add_style_class_name('search-section-content-bg');
+ Main.overview._overview._controls.layoutManager._searchController._searchResults._content.remove_style_class_name('search-section-content-bg-om2');
Main.overview.searchEntry.remove_style_class_name('search-entry-om2');
}
},
async runStartupAnimation(callback) {
this._ignoreShowAppsButtonToggle = true;
- this._searchController.prepareToEnterOverview();
- this._workspacesDisplay.prepareToEnterOverview();
+
+ this.prepareToEnterOverview();
this._stateAdjustment.value = ControlsState.HIDDEN;
this._stateAdjustment.ease(ControlsState.WINDOW_PICKER, {
@@ -436,16 +513,20 @@ const ControlsManager = {
this._ignoreShowAppsButtonToggle = false;
// Set the opacity here to avoid a 1-frame flicker
- this.opacity = 0;
+ this.opacity = 1;
+ this._appDisplay.opacity = 1;
// We can't run the animation before the first allocation happens
await this.layout_manager.ensureAllocation();
- const { STARTUP_ANIMATION_TIME } = imports.ui.layout;
+ this._setBackground();
+ Main.panel.opacity = 255;
+
+ const { STARTUP_ANIMATION_TIME } = Layout;
// Opacity
this.ease({
- opacity: 255,
+ opacity: opt.STARTUP_STATE === 1 ? 0 : 255,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
@@ -465,53 +546,24 @@ const ControlsManager = {
}
const searchEntryBin = this._searchEntryBin;
- const [tmbTranslationX, tmbTranslationY, dashTranslationX, dashTranslationY, searchTranslationY] =
- _Util.getOverviewTranslations(opt, dash, tmbBox, searchEntryBin);
+ const [dashTranslationX, dashTranslationY, tmbTranslationX, tmbTranslationY, searchTranslationY] =
+ this._getOverviewTranslations(dash, tmbBox, searchEntryBin);
const onComplete = function () {
// running init callback again causes issues (multiple connections)
- if (!_startupInitComplete)
+ if (!Main.overview._startupInitComplete)
callback();
- _startupInitComplete = true;
-
- // force app grid to build before the first visible animation to remove possible stuttering
- this._appDisplay.opacity = 1;
-
- const [x, y] = this._appDisplay.get_position();
- const translationX = -x;
- const translationY = -y;
- this._appDisplay.translation_x = translationX;
- this._appDisplay.translation_y = translationY;
- GLib.idle_add(0, () => {
- this._appDisplay._removeItem(this._appDisplay._orderedItems[0]);
- this._appDisplay._redisplay();
- });
- // let the main loop realize previous changes before continuing
- _timeouts.startupAnim1 = GLib.timeout_add(
- GLib.PRIORITY_DEFAULT,
- 10,
- () => {
- GLib.idle_add(0, () => {
- this._appDisplay._removeItem(this._appDisplay._orderedItems[0]);
- this._appDisplay._redisplay();
- });
- this._appDisplay.translation_x = 0;
- this._appDisplay.translation_y = 0;
- this._appDisplay.visible = false;
- if (opt.STARTUP_STATE === 1) {
- Main.overview.hide();
- } else if (opt.STARTUP_STATE === 2) {
- this._appDisplay.opacity = 255;
- this.dash.showAppsButton.checked = true;
- }
- _timeouts.startupAnim1 = 0;
- return GLib.SOURCE_REMOVE;
- }
- );
+ const appDisplayModule = Me.Modules.appDisplayModule;
+ if (!appDisplayModule.moduleEnabled)
+ this._finishStartupSequence();
+ else
+ this._realizeAppDisplayAndFinishSequence();
+
+ Main.overview._startupInitComplete = true;
}.bind(this);
- if (dash.visible && !_Util.dashNotDefault()) {
+ if (dash.visible && !Me.Util.dashNotDefault()) {
dash.translation_x = dashTranslationX;
dash.translation_y = dashTranslationY;
dash.opacity = 255;
@@ -521,9 +573,7 @@ const ControlsManager = {
delay: STARTUP_ANIMATION_TIME / 2,
duration: STARTUP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- onComplete();
- },
+ onComplete,
});
} else {
// set dash opacity to make it visible if user enable it later
@@ -535,6 +585,7 @@ const ControlsManager = {
STARTUP_ANIMATION_TIME * 2 * St.Settings.get().slow_down_factor,
() => {
onComplete();
+ Main.overview._startupInitComplete = true;
_timeouts.startupAnim2 = 0;
return GLib.SOURCE_REMOVE;
}
@@ -571,7 +622,6 @@ const ControlsManager = {
if (view._monitorIndex !== global.display.get_primary_monitor() && view._thumbnails.visible) {
const secTmbBox = view._thumbnails;
- _Util.getOverviewTranslations(opt, dash, secTmbBox, searchEntryBin);
if (opt.SEC_WS_TMB_LEFT)
secTmbBox.translation_x = -(secTmbBox.width + 12); // compensate for padding
else if (opt.SEC_WS_TMB_RIGHT)
@@ -594,13 +644,129 @@ const ControlsManager = {
}
},
+ _realizeAppDisplayAndFinishSequence() {
+ const appDisplayModule = Me.Modules.appDisplayModule;
+ // realize app grid for smoother first animation
+ appDisplayModule._updateAppGrid(false, this._finishStartupSequence.bind(this));
+ },
+
+ _finishStartupSequence(priority = GLib.PRIORITY_LOW) {
+ if (!this._bgManagers)
+ this._setBackground();
+
+ _timeouts.finishStartup = GLib.idle_add(
+ priority, () => {
+ this._appDisplay.opacity = 255;
+ if (opt.STARTUP_STATE === 1) {
+ Main.overview.hide();
+ } else if (opt.STARTUP_STATE === 2) {
+ Main.overview.show(2); // just because of DtD, because we skipped startup animation
+ this.dash.showAppsButton.checked = true;
+ } else if (!opt.STARTUP_STATE && Me.Util.dashNotDefault()) {
+ Main.overview.show();
+ }
+
+ _timeouts.finishStartup = 0;
+ return GLib.SOURCE_REMOVE;
+ }
+ );
+ },
+
+ setInitialTranslations() {
+ const dash = this.dash;
+ const tmbBox = this._thumbnailsBox;
+ const searchEntryBin = this._searchEntryBin;
+ const [dashTranslationX, dashTranslationY, tmbTranslationX, tmbTranslationY, searchTranslationY] =
+ this._getOverviewTranslations(dash, tmbBox, searchEntryBin);
+ if (!Me.Util.dashNotDefault()) {
+ dash.translation_x = dashTranslationX;
+ dash.translation_y = dashTranslationY;
+ }
+ tmbBox.translation_x = tmbTranslationX;
+ tmbBox.translation_y = tmbTranslationY;
+ searchEntryBin.translation_y = searchTranslationY;
+ },
+
+ _getOverviewTranslations(dash, tmbBox, searchEntryBin) {
+ // const tmbBox = Main.overview._overview._controls._thumbnailsBox;
+ const animationsDisabled = !St.Settings.get().enable_animations || (opt.SHOW_WS_PREVIEW_BG && !opt.OVERVIEW_MODE2);
+ if (animationsDisabled)
+ return [0, 0, 0, 0, 0];
+
+ let searchTranslationY = 0;
+ if (searchEntryBin.visible) {
+ const offset = (dash.visible && (!opt.DASH_VERTICAL ? dash.height + 12 : 0)) +
+ (opt.WS_TMB_TOP ? tmbBox.height + 12 : 0);
+ searchTranslationY = -searchEntryBin.height - offset - 30;
+ }
+
+ let tmbTranslationX = 0;
+ let tmbTranslationY = 0;
+ let offset;
+ if (tmbBox.visible) {
+ const tmbWidth = tmbBox.width === Infinity ? 0 : tmbBox.width;
+ const tmbHeight = tmbBox.height === Infinity ? 0 : tmbBox.height;
+ switch (opt.WS_TMB_POSITION) {
+ case 3: // left
+ offset = 10 + (dash?.visible && opt.DASH_LEFT ? dash.width : 0);
+ tmbTranslationX = -tmbWidth - offset;
+ tmbTranslationY = 0;
+ break;
+ case 1: // right
+ offset = 10 + (dash?.visible && opt.DASH_RIGHT ? dash.width : 0);
+ tmbTranslationX = tmbWidth + offset;
+ tmbTranslationY = 0;
+ break;
+ case 0: // top
+ offset = 10 + (dash?.visible && opt.DASH_TOP ? dash.height : 0) + Main.panel.height;
+ tmbTranslationX = 0;
+ tmbTranslationY = -tmbHeight - offset;
+ break;
+ case 2: // bottom
+ offset = 10 + (dash?.visible && opt.DASH_BOTTOM ? dash.height : 0) + Main.panel.height; // just for case the panel is at bottom
+ tmbTranslationX = 0;
+ tmbTranslationY = tmbHeight + offset;
+ break;
+ }
+ }
+
+ let dashTranslationX = 0;
+ let dashTranslationY = 0;
+ let position = opt.DASH_POSITION;
+ // if DtD replaced the original Dash, read its position
+ if (Me.Util.dashIsDashToDock())
+ position = dash._position;
+
+ if (dash?.visible) {
+ const dashWidth = dash.width === Infinity ? 0 : dash.width;
+ const dashHeight = dash.height === Infinity ? 0 : dash.height;
+ switch (position) {
+ case 0: // top
+ dashTranslationX = 0;
+ dashTranslationY = -dashHeight - dash.margin_bottom - Main.panel.height;
+ break;
+ case 1: // right
+ dashTranslationX = dashWidth;
+ dashTranslationY = 0;
+ break;
+ case 2: // bottom
+ dashTranslationX = 0;
+ dashTranslationY = dashHeight + dash.margin_bottom + Main.panel.height;
+ break;
+ case 3: // left
+ dashTranslationX = -dashWidth;
+ dashTranslationY = 0;
+ break;
+ }
+ }
+
+ return [dashTranslationX, dashTranslationY, tmbTranslationX, tmbTranslationY, searchTranslationY];
+ },
+
animateToOverview(state, callback) {
this._ignoreShowAppsButtonToggle = true;
this._searchTransition = false;
- this._searchController.prepareToEnterOverview();
- this._workspacesDisplay.prepareToEnterOverview();
-
this._stateAdjustment.value = ControlsState.HIDDEN;
// building window thumbnails takes some time and with many windows on the workspace
@@ -627,10 +793,151 @@ const ControlsManager = {
this._ignoreShowAppsButtonToggle = false;
},
+
+ _setBackground(reset = false) {
+ if (this._bgManagers) {
+ this._bgManagers.forEach(bg => {
+ Main.overview._overview._controls._stateAdjustment.disconnect(bg._fadeSignal);
+ bg.destroy();
+ });
+ }
+
+ // 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)) {
+ delete this._bgManagers;
+ return;
+ }
+
+ this._bgManagers = [];
+ 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;
+
+
+ bgManager._fadeSignal = Main.overview._overview._controls._stateAdjustment.connect('notify::value', v => {
+ this._updateBackground(bgManager, v.value, v);
+ });
+
+ if (monitor.index === global.display.get_primary_monitor()) {
+ bgManager._primary = true;
+ this._bgManagers.unshift(bgManager); // primary monitor first
+ } else {
+ bgManager._primary = false;
+ this._bgManagers.push(bgManager);
+ }
+ }
+ },
+
+ _updateBackground(bgManager, stateValue = 2, stateAdjustment = null) {
+ // Blur My Shell extension destroys all background actors in the overview and doesn't care about consequences
+ if (this._bgManagers[0] && !Main.layoutManager.overviewGroup.get_children().includes(this._bgManagers[0].backgroundActor)) {
+ Main.notifyError(`[${Me.metadata.name}]`, _('Overview background crashed!\nIf you are using Blur My Shell, disable overview blur in its settings and re-enable V-Shell Overview Background to avoid visual glitches.'));
+ // remove and disconnect our destroyed backgrounds to avoid more errors
+ this._setBackground(true);
+ return;
+ }
+
+ const finalState = stateAdjustment?.getStateTransitionParams().finalState;
+ 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 && 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;
+ }
+
+ 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);
+ }
+
+ const searchActive = Main.overview._overview.controls._searchController.searchActive;
+ if (searchActive)
+ BRIGHTNESS = opt.SEARCH_BG_BRIGHTNESS;
+
+ bgManager.backgroundActor.content.vignette_sharpness = VIGNETTE;
+ bgManager.backgroundActor.content.brightness = BRIGHTNESS;
+
+ 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 (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE) {
+ 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));
+ }
+
+ 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 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 && !(opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE)) {
+ const sigma = Math.round(Util.lerp(0, opt.OVERVIEW_BG_BLUR_SIGMA, progress));
+ if (sigma !== blurEffect.sigma)
+ blurEffect.sigma = sigma;
+ } else if (stateValue < 1 && !searchActive && (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE && blurEffect.sigma)) {
+ const sigma = Math.round(Util.lerp(0, opt.OVERVIEW_BG_BLUR_SIGMA, progress));
+ if (sigma !== blurEffect.sigma)
+ blurEffect.sigma = sigma;
+ } else if (stateValue > 1 && !searchActive && (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE && finalState === 1)) {
+ const sigma = Math.round(Util.lerp(0, opt.OVERVIEW_BG_BLUR_SIGMA, progress % 1));
+ 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 && !(opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE)) {
+ blurEffect.sigma = opt.OVERVIEW_BG_BLUR_SIGMA;
+ } else if (stateValue === 0 || (stateValue === 1 && (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE))) {
+ blurEffect.sigma = 0;
+ }
+ }
+ }
+ },
};
const ControlsManagerLayoutVertical = {
- _computeWorkspacesBoxForState(state, box, workAreaBox, dashWidth, dashHeight, thumbnailsWidth, searchHeight, startY) {
+ _computeWorkspacesBoxForState(state, box, workAreaBox, dashWidth, dashHeight, thumbnailsWidth, thumbnailsHeight, searchHeight, startY) {
+ // in case the function is called from the DtD
+ if (startY === undefined) {
+ workAreaBox = box;
+ }
const workspaceBox = box.copy();
let [width, height] = workspaceBox.get_size();
// const { x1: startX/* y1: startY*/ } = workAreaBox;
@@ -640,7 +947,7 @@ const ControlsManagerLayoutVertical = {
const dash = Main.overview.dash;
// including Dash to Dock and clones properties for compatibility
- if (_Util.dashIsDashToDock()) {
+ if (Me.Util.dashIsDashToDock()) {
// Dash to Dock also always affects workAreaBox
Main.layoutManager._trackedActors.forEach(actor => {
if (actor.affectsStruts && actor.actor.width === dash.width) {
@@ -678,7 +985,7 @@ const ControlsManagerLayoutVertical = {
case ControlsState.APP_GRID:
if (opt.WS_ANIMATION && opt.SHOW_WS_TMB && state === ControlsState.APP_GRID) {
workspaceBox.set_origin(...this._workspacesThumbnails.get_position());
- workspaceBox.set_size(...this._workspacesThumbnails.get_size());
+ workspaceBox.set_size(thumbnailsWidth, thumbnailsHeight);
} else if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE) {
if (opt.START_Y_OFFSET) {
let [x, y] = workAreaBox.get_origin();
@@ -693,7 +1000,7 @@ const ControlsManagerLayoutVertical = {
height = opt.PANEL_POSITION_TOP ? height : height - Main.panel.height;
searchHeight = opt.SHOW_SEARCH_ENTRY ? searchHeight : 0;
wWidth = width -
- (opt.DASH_VERTICAL ? dash.width : 0) -
+ (opt.DASH_VERTICAL ? dashWidth : 0) -
thumbnailsWidth -
4 * spacing;
wHeight = height -
@@ -739,7 +1046,7 @@ const ControlsManagerLayoutVertical = {
}
const wsBoxX = /* startX + */xOffset;
- wsBoxY = Math.round(startY + yOffset);
+ wsBoxY = startY + yOffset;
workspaceBox.set_origin(Math.round(wsBoxX), Math.round(wsBoxY));
workspaceBox.set_size(Math.round(wWidth), Math.round(wHeight));
}
@@ -749,6 +1056,10 @@ const ControlsManagerLayoutVertical = {
},
_getAppDisplayBoxForState(state, box, workAreaBox, searchHeight, dashWidth, dashHeight, thumbnailsWidth, startY) {
+ // in case the function is called from the DtD
+ if (startY === undefined) {
+ workAreaBox = box;
+ }
const [width] = box.get_size();
const { x1: startX } = workAreaBox;
// const { y1: startY } = workAreaBox;
@@ -762,11 +1073,11 @@ const ControlsManagerLayoutVertical = {
const xOffsetR = (opt.WS_TMB_RIGHT ? thumbnailsWidth : 0) + (opt.DASH_RIGHT ? dashWidth : 0);
const yOffsetT = (opt.DASH_TOP ? dashHeight : 0) + (opt.SHOW_SEARCH_ENTRY ? searchHeight : 0);
const yOffsetB = opt.DASH_BOTTOM ? dashHeight : 0;
- const adWidth = opt.CENTER_APP_GRID ? width - 2 * Math.max(xOffsetL, xOffsetR) - 4 * spacing : width - xOffsetL - xOffsetR - 4 * spacing;
- const adHeight = height - yOffsetT - yOffsetB - 4 * spacing;
+ const adWidth = opt.CENTER_APP_GRID ? width - 2 * Math.max(xOffsetL, xOffsetR) - 2 * spacing : width - xOffsetL - xOffsetR - 2 * spacing;
+ const adHeight = height - yOffsetT - yOffsetB;
const appDisplayX = opt.CENTER_APP_GRID ? (width - adWidth) / 2 : xOffsetL + 2 * spacing;
- const appDisplayY = startY + yOffsetT + 2 * spacing;
+ const appDisplayY = startY + yOffsetT;
switch (state) {
case ControlsState.HIDDEN:
@@ -774,43 +1085,43 @@ const ControlsManagerLayoutVertical = {
// 1 - left, 2 - right, 3 - bottom, 5 - top
switch (opt.APP_GRID_ANIMATION) {
case 0:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(appDisplayY));
break;
case 1:
- appDisplayBox.set_origin(startX + width, appDisplayY);
+ appDisplayBox.set_origin(Math.round(startX + width), Math.round(appDisplayY));
break;
case 2:
- appDisplayBox.set_origin(startX - adWidth, appDisplayY);
+ appDisplayBox.set_origin(Math.round(startX - adWidth), Math.round(appDisplayY));
break;
case 3:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y2);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(workAreaBox.y2));
break;
case 5:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y1 - adHeight);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(workAreaBox.y1 - adHeight));
break;
}
break;
case ControlsState.APP_GRID:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(appDisplayY));
break;
}
- appDisplayBox.set_size(adWidth, adHeight);
+ appDisplayBox.set_size(Math.round(adWidth), Math.round(adHeight));
return appDisplayBox;
},
vfunc_allocate(container, box) {
- const childBox = new Clutter.ActorBox();
+ const transitionParams = this._stateAdjustment.getStateTransitionParams();
+ const childBox = new Clutter.ActorBox();
const { spacing } = this;
-
+ const halfSpacing = spacing / 2;
const monitor = Main.layoutManager.findMonitorForActor(this._container);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor.index);
const startX = workArea.x - monitor.x;
// if PANEL_OVERVIEW_ONLY, the affectStruts property is set to false to avoid stuttering
// therefore we need to add panel height to startY
let startY = workArea.y - monitor.y + opt.START_Y_OFFSET;
-
const workAreaBox = new Clutter.ActorBox();
workAreaBox.set_origin(startX, startY);
workAreaBox.set_size(workArea.width, workArea.height);
@@ -818,7 +1129,7 @@ const ControlsManagerLayoutVertical = {
box.x1 += startX;
let [width, height] = box.get_size();
// if panel is at bottom position,
- // compensate the height of the available box (the box size is calculated for top panel)
+ // compensate for the height of the available box (the box size is calculated for top panel)
height = opt.PANEL_POSITION_TOP ? height : height - Main.panel.height;
let availableHeight = height;
@@ -830,8 +1141,8 @@ const ControlsManagerLayoutVertical = {
// dash cloud be overridden by the Dash to Dock clone
const dash = Main.overview.dash;
- if (_Util.dashIsDashToDock()) {
- // if Dash to Dock replaced the default dash and its inteli-hide id disabled we need to compensate for affected startY
+ if (Me.Util.dashIsDashToDock()) {
+ // if Dash to Dock replaced the default dash and its inteli-hide is disabled we need to compensate for affected startY
if (!Main.overview.dash.get_parent()?.get_parent()?.get_parent()?._intellihideIsEnabled) {
if (Main.panel.y === monitor.y)
startY = Main.panel.height + spacing;
@@ -857,48 +1168,48 @@ const ControlsManagerLayoutVertical = {
}
}
- const transitionParams = this._stateAdjustment.getStateTransitionParams();
-
// Workspace Thumbnails
let wsTmbWidth = 0;
let wsTmbHeight = 0;
- if (this._workspacesThumbnails.visible) {
- // const { expandFraction } = this._workspacesThumbnails;
+ let maxWsTmbScale = opt.MAX_THUMBNAIL_SCALE;
+ if (opt.SHOW_WS_TMB) {
const dashHeightReservation = !opt.WS_TMB_FULL && !opt.DASH_VERTICAL ? dashHeight : 0;
- let maxScale = opt.MAX_THUMBNAIL_SCALE;
- if (!opt.MAX_THUMBNAIL_SCALE_STABLE) {
+ const searchActive = this._searchController.searchActive;
+ if (!opt.MAX_THUMBNAIL_SCALE_STABLE && !searchActive) {
const initState = transitionParams.initialState === ControlsState.APP_GRID ? opt.MAX_THUMBNAIL_SCALE_APPGRID : opt.MAX_THUMBNAIL_SCALE;
const finalState = transitionParams.finalState === ControlsState.APP_GRID ? opt.MAX_THUMBNAIL_SCALE_APPGRID : opt.MAX_THUMBNAIL_SCALE;
- maxScale = Util.lerp(initState, finalState, transitionParams.progress);
+ maxWsTmbScale = Util.lerp(initState, finalState, transitionParams.progress);
}
- wsTmbWidth = width * maxScale;
+ wsTmbWidth = width * maxWsTmbScale;
let totalTmbSpacing;
- [totalTmbSpacing, wsTmbHeight] = this._workspacesThumbnails.get_preferred_custom_height(wsTmbWidth);
+ [totalTmbSpacing, wsTmbHeight] = this._workspacesThumbnails.get_preferred_height(wsTmbWidth);
wsTmbHeight += totalTmbSpacing;
- const wsTmbHeightMax = height - dashHeightReservation;
+ const wsTmbHeightMax = opt.WS_TMB_FULL
+ ? height - spacing
+ : height - dashHeightReservation - 2 * spacing;
if (wsTmbHeight > wsTmbHeightMax) {
wsTmbHeight = wsTmbHeightMax;
- wsTmbWidth = this._workspacesThumbnails.get_preferred_custom_width(wsTmbHeight)[1];
+ wsTmbWidth = Math.round(this._workspacesThumbnails.get_preferred_width(wsTmbHeight)[1]);
}
let wsTmbX;
if (opt.WS_TMB_RIGHT)
- wsTmbX = Math.round(startX + width - (opt.DASH_RIGHT ? dashWidth : 0) - wsTmbWidth - spacing / 2);
+ wsTmbX = Math.round(startX + width - (opt.DASH_RIGHT ? dashWidth : 0) - wsTmbWidth /* - halfSpacing*/); // this halfSpacing is a part od dash style
else
- wsTmbX = Math.round((opt.DASH_LEFT ? dashWidth : 0) + spacing / 2);
+ wsTmbX = Math.round(opt.DASH_LEFT ? dashWidth : 0/* + halfSpacing*/); // this halfSpacing is a part od dash style
let wstOffset = (height - wsTmbHeight - (opt.DASH_VERTICAL ? 0 : dashHeightReservation)) / 2;
- wstOffset -= opt.WS_TMB_POSITION_ADJUSTMENT * (wstOffset - spacing / 2);
+ wstOffset -= opt.WS_TMB_POSITION_ADJUSTMENT * (wstOffset - halfSpacing);
let wsTmbY = Math.round(startY + (dashHeightReservation && opt.DASH_TOP ? dashHeight : 0) + wstOffset);
childBox.set_origin(wsTmbX, wsTmbY);
- childBox.set_size(Math.round(wsTmbWidth), Math.round(wsTmbHeight));
+ childBox.set_size(Math.max(wsTmbWidth, 1), Math.max(wsTmbHeight, 1));
this._workspacesThumbnails.allocate(childBox);
}
@@ -927,7 +1238,7 @@ const ControlsManagerLayoutVertical = {
if (!opt.DASH_VERTICAL) {
offset = (width - ((opt.WS_TMB_FULL || opt.CENTER_DASH_WS) && !this._xAlignCenter ? wsTmbWidth : 0) - dashWidth) / 2;
- offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - spacing / 2);
+ offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - halfSpacing);
dashX = offset;
if ((opt.WS_TMB_FULL || opt.CENTER_DASH_WS) && !this._xAlignCenter) {
@@ -944,7 +1255,7 @@ const ControlsManagerLayoutVertical = {
}
} else {
offset = (height - dashHeight) / 2;
- dashY = startY + (offset - opt.DASH_POSITION_ADJUSTMENT * offset);
+ dashY = startY + (offset - opt.DASH_POSITION_ADJUSTMENT * (offset - halfSpacing));
}
childBox.set_origin(Math.round(startX + dashX), Math.round(dashY));
@@ -957,7 +1268,7 @@ const ControlsManagerLayoutVertical = {
let [searchHeight] = this._searchEntry.get_preferred_height(width - wsTmbWidth);
// Workspaces
- let params = [box, workAreaBox, dashWidth, dashHeight, wsTmbWidth, searchHeight, startY];
+ let params = [box, workAreaBox, dashWidth, dashHeight, wsTmbWidth, wsTmbHeight, searchHeight, startY];
// Update cached boxes
for (const state of Object.values(ControlsState)) {
@@ -983,7 +1294,7 @@ const ControlsManagerLayoutVertical = {
// Y position under top Dash
let searchEntryX, searchEntryY;
if (opt.DASH_TOP)
- searchEntryY = startY + dashHeight - spacing;
+ searchEntryY = startY + dashHeight;
else
searchEntryY = startY;
@@ -1005,7 +1316,11 @@ const ControlsManagerLayoutVertical = {
availableHeight -= searchHeight + spacing;
// if (this._appDisplay.visible)... ? Can cause problems
- params = [box, workAreaBox, searchHeight, dashWidth, dashHeight, wsTmbWidth, startY]; // send startY, can be corrected
+ // Calculate appDisplay always for AppGrid state WsTmb scale
+ let wsTmbWidthAppGrid = opt.MAX_THUMBNAIL_SCALE_APPGRID > 0
+ ? Math.round(wsTmbWidth / maxWsTmbScale * opt.MAX_THUMBNAIL_SCALE_APPGRID)
+ : Math.round(wsTmbWidth / maxWsTmbScale * opt.MAX_THUMBNAIL_SCALE);
+ params = [box, workAreaBox, searchHeight, dashWidth, dashHeight, wsTmbWidthAppGrid, startY]; // send startY, can be corrected
let appDisplayBox;
if (!transitionParams.transitioning) {
appDisplayBox =
@@ -1024,9 +1339,9 @@ const ControlsManagerLayoutVertical = {
if (opt.CENTER_SEARCH_VIEW) {
const dashW = (opt.DASH_VERTICAL ? dashWidth : 0) + spacing;
searchWidth = width - 2 * wsTmbWidth - 2 * dashW;
- childBox.set_origin(wsTmbWidth + dashW, startY + (opt.DASH_TOP ? dashHeight : spacing) + searchHeight);
+ childBox.set_origin(wsTmbWidth + dashW, startY + (opt.DASH_TOP ? dashHeight + spacing : spacing) + searchHeight);
} else {
- childBox.set_origin(this._xAlignCenter ? wsTmbWidth + spacing : searchXoffset, startY + (opt.DASH_TOP ? dashHeight : spacing) + searchHeight);
+ childBox.set_origin(this._xAlignCenter ? wsTmbWidth + spacing : searchXoffset, startY + (opt.DASH_TOP ? dashHeight + spacing : spacing) + searchHeight);
}
childBox.set_size(searchWidth, availableHeight);
@@ -1037,7 +1352,11 @@ const ControlsManagerLayoutVertical = {
};
const ControlsManagerLayoutHorizontal = {
- _computeWorkspacesBoxForState(state, box, workAreaBox, dashWidth, dashHeight, thumbnailsHeight, searchHeight, startY) {
+ _computeWorkspacesBoxForState(state, box, workAreaBox, dashWidth, dashHeight, thumbnailsWidth, thumbnailsHeight, searchHeight, startY) {
+ // in case the function is called from the DtD
+ if (startY === undefined) {
+ workAreaBox = box;
+ }
const workspaceBox = box.copy();
let [width, height] = workspaceBox.get_size();
// let { x1: startX/* , y1: startY*/ } = workAreaBox;
@@ -1046,7 +1365,7 @@ const ControlsManagerLayoutHorizontal = {
const dash = Main.overview.dash;
// including Dash to Dock and clones properties for compatibility
- if (_Util.dashIsDashToDock()) {
+ if (Me.Util.dashIsDashToDock()) {
// Dash to Dock always affects workAreaBox
Main.layoutManager._trackedActors.forEach(actor => {
if (actor.affectsStruts && actor.actor.width === dash.width) {
@@ -1084,7 +1403,7 @@ const ControlsManagerLayoutHorizontal = {
case ControlsState.APP_GRID:
if (opt.WS_ANIMATION && opt.SHOW_WS_TMB && state === ControlsState.APP_GRID) {
workspaceBox.set_origin(...this._workspacesThumbnails.get_position());
- workspaceBox.set_size(...this._workspacesThumbnails.get_size());
+ workspaceBox.set_size(thumbnailsWidth, thumbnailsHeight);
} else if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE) {
if (opt.START_Y_OFFSET) {
let [x, y] = workAreaBox.get_origin();
@@ -1146,7 +1465,7 @@ const ControlsManagerLayoutHorizontal = {
}
wsBoxX = /* startX + */xOffset;
- wsBoxY = Math.round(startY + yOffset);
+ wsBoxY = startY + yOffset;
workspaceBox.set_origin(Math.round(wsBoxX), Math.round(wsBoxY));
workspaceBox.set_size(Math.round(wWidth), Math.round(wHeight));
}
@@ -1156,6 +1475,10 @@ const ControlsManagerLayoutHorizontal = {
},
_getAppDisplayBoxForState(state, box, workAreaBox, searchHeight, dashWidth, dashHeight, thumbnailsHeight, startY) {
+ // in case the function is called from the DtD
+ if (startY === undefined) {
+ workAreaBox = box;
+ }
const [width] = box.get_size();
const { x1: startX } = workAreaBox;
// const { y1: startY } = workAreaBox;
@@ -1163,16 +1486,16 @@ const ControlsManagerLayoutHorizontal = {
const appDisplayBox = new Clutter.ActorBox();
const { spacing } = this;
- const yOffsetT = (opt.WS_TMB_TOP ? thumbnailsHeight : 0) + (opt.DASH_TOP ? dashHeight : 0) + (opt.SHOW_SEARCH_ENTRY ? searchHeight : 0) + 2 * spacing;
- const yOffsetB = (opt.WS_TMB_BOTTOM ? thumbnailsHeight : 0) + (opt.DASH_BOTTOM ? dashHeight : 0);
+ const yOffsetT = (opt.WS_TMB_TOP ? thumbnailsHeight + spacing : 0) + (opt.DASH_TOP ? dashHeight : 0) + (opt.SHOW_SEARCH_ENTRY ? searchHeight : 0);
+ const yOffsetB = (opt.WS_TMB_BOTTOM ? thumbnailsHeight + spacing : 0) + (opt.DASH_BOTTOM ? dashHeight : 0);
const xOffsetL = opt.DASH_LEFT ? dashWidth : 0;
const xOffsetR = opt.DASH_RIGHT ? dashWidth : 0;
- const hSpacing = xOffsetL + xOffsetR ? 2 * spacing : 0;
+ const hSpacing = xOffsetL + xOffsetR ? spacing : 0;
const adWidth = opt.CENTER_APP_GRID ? width - 2 * Math.max(xOffsetL, xOffsetR) - 2 * hSpacing : width - xOffsetL - xOffsetR - 2 * hSpacing;
- const adHeight = height - yOffsetT - yOffsetB - 4 * spacing;
+ const adHeight = height - yOffsetT - yOffsetB;
const appDisplayX = opt.CENTER_APP_GRID ? (width - adWidth) / 2 : xOffsetL + hSpacing;
- const appDisplayY = startY + yOffsetT + hSpacing;
+ const appDisplayY = startY + yOffsetT;
switch (state) {
case ControlsState.HIDDEN:
@@ -1180,36 +1503,36 @@ const ControlsManagerLayoutHorizontal = {
// 1 - left, 2 - right, 3 - bottom, 5 - top
switch (opt.APP_GRID_ANIMATION) {
case 0:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(appDisplayY));
break;
case 1:
- appDisplayBox.set_origin(startX + width, appDisplayY);
+ appDisplayBox.set_origin(Math.round(startX + width), Math.round(appDisplayY));
break;
case 2:
- appDisplayBox.set_origin(startX - adWidth, appDisplayY);
+ appDisplayBox.set_origin(Math.round(startX - adWidth), Math.round(appDisplayY));
break;
case 3:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y2);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(workAreaBox.y2));
break;
case 5:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y1 - adHeight);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(workAreaBox.y1 - adHeight));
break;
}
break;
case ControlsState.APP_GRID:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
+ appDisplayBox.set_origin(Math.round(appDisplayX), Math.round(appDisplayY));
break;
}
- appDisplayBox.set_size(adWidth, adHeight);
+ appDisplayBox.set_size(Math.round(adWidth), Math.round(adHeight));
return appDisplayBox;
},
vfunc_allocate(container, box) {
+ const transitionParams = this._stateAdjustment.getStateTransitionParams();
const childBox = new Clutter.ActorBox();
-
const { spacing } = this;
-
+ const halfSpacing = spacing / 2;
const monitor = Main.layoutManager.findMonitorForActor(this._container);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor.index);
const startX = workArea.x - monitor.x;
@@ -1235,7 +1558,7 @@ const ControlsManagerLayoutHorizontal = {
// dash cloud be overridden by the Dash to Dock clone
const dash = Main.overview.dash;
- if (_Util.dashIsDashToDock()) {
+ if (Me.Util.dashIsDashToDock()) {
// if Dash to Dock replaced the default dash and its inteli-hide is disabled we need to compensate for affected startY
if (!Main.overview.dash.get_parent()?.get_parent()?.get_parent()?._intellihideIsEnabled) {
// if (Main.panel.y === monitor.y)
@@ -1265,60 +1588,53 @@ const ControlsManagerLayoutHorizontal = {
let [searchHeight] = this._searchEntry.get_preferred_height(width);
- const transitionParams = this._stateAdjustment.getStateTransitionParams();
-
// Workspace Thumbnails
let wsTmbWidth = 0;
let wsTmbHeight = 0;
- if (this._workspacesThumbnails.visible) {
- // const { expandFraction } = this._workspacesThumbnails;
+ let maxWsTmbScale = opt.MAX_THUMBNAIL_SCALE;
+ if (opt.SHOW_WS_TMB) {
const dashWidthReservation = !opt.WS_TMB_FULL && opt.DASH_VERTICAL ? dashWidth : 0;
- let maxScale = opt.MAX_THUMBNAIL_SCALE;
- if (!opt.MAX_THUMBNAIL_SCALE_STABLE) {
+ const searchActive = this._searchController.searchActive;
+ if (!opt.MAX_THUMBNAIL_SCALE_STABLE && !searchActive) {
const initState = transitionParams.initialState === ControlsState.APP_GRID ? opt.MAX_THUMBNAIL_SCALE_APPGRID : opt.MAX_THUMBNAIL_SCALE;
const finalState = transitionParams.finalState === ControlsState.APP_GRID ? opt.MAX_THUMBNAIL_SCALE_APPGRID : opt.MAX_THUMBNAIL_SCALE;
- maxScale = Util.lerp(initState, finalState, transitionParams.progress);
+ maxWsTmbScale = Util.lerp(initState, finalState, transitionParams.progress);
}
- wsTmbHeight = height * maxScale;
+ wsTmbHeight = Math.round(height * maxWsTmbScale);
let totalTmbSpacing;
- [totalTmbSpacing, wsTmbWidth] = this._workspacesThumbnails.get_preferred_custom_width(wsTmbHeight);
+ [totalTmbSpacing, wsTmbWidth] = this._workspacesThumbnails.get_preferred_width(wsTmbHeight);
wsTmbWidth += totalTmbSpacing;
const wsTmbWidthMax = opt.WS_TMB_FULL
- ? width
- : width - (opt.DASH_VERTICAL ? 0 : dashWidthReservation);
+ ? width - spacing
+ : width - dashWidthReservation - 2 * spacing;
if (wsTmbWidth > wsTmbWidthMax) {
wsTmbWidth = wsTmbWidthMax;
- wsTmbHeight = this._workspacesThumbnails.get_preferred_custom_height(wsTmbWidth)[1];
+ wsTmbHeight = Math.round(this._workspacesThumbnails.get_preferred_height(wsTmbWidth)[1]);
}
let wsTmbY;
if (opt.WS_TMB_TOP)
- wsTmbY = Math.round(startY + /* searchHeight + */(opt.DASH_TOP ? dashHeight : spacing / 2));
+ wsTmbY = Math.round(startY + (opt.DASH_TOP ? dashHeight : halfSpacing));
else
- wsTmbY = Math.round(startY + height - (opt.DASH_BOTTOM ? dashHeight : 0) - wsTmbHeight);
+ wsTmbY = Math.round(startY + height - (opt.DASH_BOTTOM ? dashHeight : halfSpacing) - wsTmbHeight);
- let wstOffset = (width - wsTmbWidth) / 2;
- wstOffset -= opt.WS_TMB_POSITION_ADJUSTMENT * (wstOffset - spacing / 2);
- let wsTmbX = Math.round(Math.clamp(
- startX + wstOffset,
- startX + (opt.DASH_LEFT ? dashWidthReservation : 0),
- width - wsTmbWidth - startX - (opt.DASH_RIGHT ? dashWidthReservation : 0)
- ));
+ let wstOffset = (width - wsTmbWidth - dashWidthReservation) / 2;
+ wstOffset -= opt.WS_TMB_POSITION_ADJUSTMENT * wstOffset;
+ let wsTmbX = Math.round(startX + (opt.DASH_LEFT ? dashWidthReservation : 0) + wstOffset);
childBox.set_origin(wsTmbX, wsTmbY);
- childBox.set_size(Math.round(wsTmbWidth), Math.round(wsTmbHeight));
+ childBox.set_size(Math.max(wsTmbWidth, 1), Math.max(wsTmbHeight, 1));
this._workspacesThumbnails.allocate(childBox);
availableHeight -= wsTmbHeight + spacing;
}
-
if (this._dash.visible) {
if (opt.WS_TMB_FULL && opt.DASH_VERTICAL) {
const wMaxHeight = height - spacing - wsTmbHeight;
@@ -1339,25 +1655,24 @@ const ControlsManagerLayoutHorizontal = {
else
dashY = startY + height - dashHeight;
-
if (opt.DASH_VERTICAL) {
if (opt.WS_TMB_FULL) {
offset = (height - dashHeight - wsTmbHeight) / 2;
if (opt.WS_TMB_TOP) {
- offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - spacing / 2);
+ offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - halfSpacing);
dashY = startY + offset + wsTmbHeight;
} else {
- offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - spacing / 2);
+ offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - halfSpacing);
dashY = startY + offset;
}
} else {
offset = (height - dashHeight) / 2;
- offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - spacing / 2);
+ offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - halfSpacing);
dashY = startY + offset;
}
} else {
offset = (width - dashWidth) / 2;
- dashX = startX + (offset - opt.DASH_POSITION_ADJUSTMENT * (offset - spacing));
+ dashX = startX + (offset - opt.DASH_POSITION_ADJUSTMENT * (offset - halfSpacing));
}
childBox.set_origin(Math.round(startX + dashX), Math.round(dashY));
@@ -1368,7 +1683,7 @@ const ControlsManagerLayoutHorizontal = {
availableHeight -= opt.DASH_VERTICAL ? 0 : dashHeight;
// Workspaces
- let params = [box, workAreaBox, dashWidth, dashHeight, wsTmbHeight, searchHeight, startY];
+ let params = [box, workAreaBox, dashWidth, dashHeight, wsTmbWidth, wsTmbHeight, searchHeight, startY];
// Update cached boxes
for (const state of Object.values(ControlsState)) {
@@ -1394,7 +1709,7 @@ const ControlsManagerLayoutHorizontal = {
// Y position under top Dash
let searchEntryX, searchEntryY;
if (opt.DASH_TOP)
- searchEntryY = startY + (opt.WS_TMB_TOP ? wsTmbHeight : 0) + dashHeight - spacing;
+ searchEntryY = startY + (opt.WS_TMB_TOP ? wsTmbHeight : 0) + dashHeight;
else
searchEntryY = startY + (opt.WS_TMB_TOP ? wsTmbHeight + spacing : 0);
@@ -1416,7 +1731,11 @@ const ControlsManagerLayoutHorizontal = {
availableHeight -= searchHeight + spacing;
// if (this._appDisplay.visible)... ? Can cause problems
- params = [box, workAreaBox, searchHeight, dashWidth, dashHeight, wsTmbHeight, startY];
+ // Calculate appDisplay always for AppGrid state WsTmb scale
+ let wsTmbHeightAppGrid = opt.MAX_THUMBNAIL_SCALE_APPGRID > 0
+ ? Math.round(wsTmbHeight / maxWsTmbScale * opt.MAX_THUMBNAIL_SCALE_APPGRID)
+ : Math.round(wsTmbHeight / maxWsTmbScale * opt.MAX_THUMBNAIL_SCALE);
+ params = [box, workAreaBox, searchHeight, dashWidth, dashHeight, wsTmbHeightAppGrid, startY];
let appDisplayBox;
if (!transitionParams.transitioning) {
appDisplayBox =
@@ -1435,9 +1754,9 @@ const ControlsManagerLayoutHorizontal = {
if (opt.CENTER_SEARCH_VIEW) {
const dashW = (opt.DASH_VERTICAL ? dashWidth : 0) + spacing;
searchWidth = width - 2 * dashW;
- childBox.set_origin(dashW, startY + (opt.DASH_TOP ? dashHeight : spacing) + (opt.WS_TMB_TOP ? wsTmbHeight + spacing : 0) + searchHeight);
+ childBox.set_origin(dashW, startY + (opt.DASH_TOP ? dashHeight + spacing : spacing) + (opt.WS_TMB_TOP ? wsTmbHeight + spacing : 0) + searchHeight);
} else {
- childBox.set_origin(this._xAlignCenter ? spacing : searchXoffset, startY + (opt.DASH_TOP ? dashHeight : spacing) + (opt.WS_TMB_TOP ? wsTmbHeight + spacing : 0) + searchHeight);
+ childBox.set_origin(this._xAlignCenter ? spacing : searchXoffset, startY + (opt.DASH_TOP ? dashHeight + spacing : spacing) + (opt.WS_TMB_TOP ? wsTmbHeight + spacing : 0) + searchHeight);
}
childBox.set_size(searchWidth, availableHeight);
@@ -1462,3 +1781,21 @@ function _getFitModeForState(state) {
return FitMode.SINGLE;
}
}
+
+const LayoutManager = {
+ _startupAnimation() {
+ if (Me.Util.dashIsDashToDock() && !Meta.is_restart()) {
+ // DtD breaks overview on startup
+ // Skip animation to hide the mess
+ this._startupAnimationComplete();
+ const controlsManager = Main.overview._overview.controls;
+ controlsManager._finishStartupSequence.bind(controlsManager)();
+ } else if (Meta.is_restart()) {
+ this._startupAnimationComplete();
+ } else if (Main.sessionMode.isGreeter) {
+ this._startupAnimationGreeter();
+ } else {
+ this._startupAnimationSession();
+ }
+ },
+};
diff --git a/extensions/44/vertical-workspaces/lib/panel.js b/extensions/44/vertical-workspaces/lib/panel.js
index 3f44ae7..898407a 100644
--- a/extensions/44/vertical-workspaces/lib/panel.js
+++ b/extensions/44/vertical-workspaces/lib/panel.js
@@ -10,188 +10,247 @@
'use strict';
-const { GLib } = imports.gi;
-const Main = imports.ui.main;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
+const Clutter = imports.gi.Clutter;
-const ANIMATION_TIME = imports.ui.overview.ANIMATION_TIME;
+const Main = imports.ui.main;
+const Overview = imports.ui.overview;
+const Panel = imports.ui.panel;
+let Me;
let opt;
-let _firstRun = true;
-let _showingOverviewConId;
-let _hidingOverviewConId;
-let _styleChangedConId;
+const ANIMATION_TIME = Overview.ANIMATION_TIME;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('panelModule', true);
- // Avoid conflict with other extensions
- const conflict = _Util.getEnabledExtensions('dash-to-panel').length ||
- _Util.getEnabledExtensions('hidetopbar').length;
- reset = reset || (!_firstRun && !moduleEnabled);
+var PanelModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- // don't even touch this module if disabled or in potential conflict
- if (_firstRun && (reset || conflict))
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
- _firstRun = false;
+ this._showingOverviewConId = 0;
+ this._hidingOverviewConId = 0;
+ this._styleChangedConId = 0;
+ }
- const panelBox = Main.layoutManager.panelBox;
- if (reset || !moduleEnabled) {
- // _disconnectPanel();
- reset = true;
- _setPanelPosition(reset);
- _updateOverviewConnection(reset);
- _reparentPanel(false);
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- _updateStyleChangedConnection(reset);
+ update(reset) {
+ this.moduleEnabled = opt.get('panelModule');
+ const conflict = Me.Util.getEnabledExtensions('dash-to-panel').length ||
+ Me.Util.getEnabledExtensions('hidetopbar').length;
- panelBox.translation_y = 0;
- Main.panel.opacity = 255;
- _setPanelStructs(true);
- return;
+ if (conflict && !reset)
+ console.warn(`[${Me.metadata.name}] Warning: "Panel" module disabled due to potential conflict with another extension`);
+
+ reset = reset || !this.moduleEnabled || conflict || Main.sessionMode.isLocked;
+
+ // don't touch original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' PanelModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ const panelBox = Main.layoutManager.panelBox;
+
+ this._setPanelPosition();
+ this._updateStyleChangedConnection();
+
+ if (opt.PANEL_MODE === 0) {
+ this._updateOverviewConnection(true);
+ this._reparentPanel(false);
+ panelBox.translation_y = 0;
+ Main.panel.opacity = 255;
+ this._setPanelStructs(true);
+ } else if (opt.PANEL_MODE === 1) {
+ if (opt.SHOW_WS_PREVIEW_BG) {
+ this._reparentPanel(true);
+ if (opt.OVERVIEW_MODE2) {
+ // in OM2 if the panel has been moved to the overviewGroup move panel above all
+ Main.layoutManager.overviewGroup.set_child_above_sibling(panelBox, null);
+ this._updateOverviewConnection();
+ } else {
+ // otherwise move the panel below overviewGroup so it can get below workspacesDisplay
+ Main.layoutManager.overviewGroup.set_child_below_sibling(panelBox, Main.overview._overview);
+ this._updateOverviewConnection(true);
+ }
+ this._showPanel(true);
+ } else {
+ // if ws preview bg is disabled, panel can stay in uiGroup
+ this._reparentPanel(false);
+ this._showPanel(false);
+ this._updateOverviewConnection();
+ }
+ // _connectPanel();
+ } else if (opt.PANEL_MODE === 2) {
+ this._updateOverviewConnection(true);
+ this._reparentPanel(false);
+ this._showPanel(false);
+ // _connectPanel();
+ }
+ this._setPanelStructs(opt.PANEL_MODE === 0);
+ Main.layoutManager._updateHotCorners();
+
+ this._overrides.addOverride('ActivitiesButton', Panel.ActivitiesButton.prototype, ActivitiesButton);
+
+ console.debug(' PanelModule - Activated');
}
- _setPanelPosition();
- _updateStyleChangedConnection();
+ _disableModule() {
+ const reset = true;
+ this._setPanelPosition(reset);
+ this._updateOverviewConnection(reset);
+ this._reparentPanel(false);
+
+ this._updateStyleChangedConnection(reset);
- if (opt.PANEL_MODE === 0) {
- _updateOverviewConnection(true);
- _reparentPanel(false);
+ const panelBox = Main.layoutManager.panelBox;
panelBox.translation_y = 0;
Main.panel.opacity = 255;
- _setPanelStructs(true);
- } else if (opt.PANEL_MODE === 1) {
- if (opt.SHOW_WS_PREVIEW_BG) {
- _reparentPanel(true);
- if (opt.OVERVIEW_MODE2) {
- // in OM2 if the panel has been moved to the overviewGroup move panel above all
- Main.layoutManager.overviewGroup.set_child_above_sibling(panelBox, null);
- _updateOverviewConnection();
- } else {
- // otherwise move the panel below overviewGroup so it can get below workspacesDisplay
- Main.layoutManager.overviewGroup.set_child_below_sibling(panelBox, Main.overview._overview);
- _updateOverviewConnection(true);
+ this._setPanelStructs(true);
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ console.debug(' PanelModule - Disabled');
+ }
+
+ _setPanelPosition(reset = false) {
+ const geometry = global.display.get_monitor_geometry(global.display.get_primary_monitor());
+ const panelBox = Main.layoutManager.panelBox;
+ const panelHeight = Main.panel.height; // panelBox height can be 0 after shell start
+
+ if (opt.PANEL_POSITION_TOP || reset)
+ panelBox.set_position(geometry.x, geometry.y);
+ else
+ panelBox.set_position(geometry.x, geometry.y + geometry.height - panelHeight);
+ }
+
+ _updateStyleChangedConnection(reset = false) {
+ if (reset) {
+ if (this._styleChangedConId) {
+ Main.panel.disconnect(this._styleChangedConId);
+ this._styleChangedConId = 0;
+ }
+ } else if (!this._styleChangedConId) {
+ this._styleChangedConId = Main.panel.connect('style-changed', () => {
+ if (opt.PANEL_MODE === 1 && !opt.OVERVIEW_MODE2)
+ Main.panel.add_style_pseudo_class('overview');
+ else if (opt.OVERVIEW_MODE2)
+ Main.panel.remove_style_pseudo_class('overview');
+ });
+ }
+ }
+
+ _updateOverviewConnection(reset = false) {
+ if (reset) {
+ if (this._hidingOverviewConId) {
+ Main.overview.disconnect(this._hidingOverviewConId);
+ this._hidingOverviewConId = 0;
+ }
+ if (this._showingOverviewConId) {
+ Main.overview.disconnect(this._showingOverviewConId);
+ this._showingOverviewConId = 0;
}
- _showPanel(true);
} else {
- // if ws preview bg is disabled, panel can stay in uiGroup
- _reparentPanel(false);
- _showPanel(false);
- _updateOverviewConnection();
+ if (!this._hidingOverviewConId) {
+ this._hidingOverviewConId = Main.overview.connect('hiding', () => {
+ if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2)
+ this._showPanel(false);
+ });
+ }
+ if (!this._showingOverviewConId) {
+ this._showingOverviewConId = Main.overview.connect('showing', () => {
+ if (Main.layoutManager._startingUp)
+ return;
+ if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2 || Main.layoutManager.panelBox.translation_y)
+ this._showPanel(true);
+ });
+ }
}
- // _connectPanel();
- } else if (opt.PANEL_MODE === 2) {
- _updateOverviewConnection(true);
- _reparentPanel(false);
- _showPanel(false);
- // _connectPanel();
}
- _setPanelStructs(opt.PANEL_MODE === 0);
- Main.layoutManager._updateHotCorners();
-}
-
-function _setPanelPosition(reset = false) {
- const geometry = global.display.get_monitor_geometry(global.display.get_primary_monitor());
- const panelBox = Main.layoutManager.panelBox;
- const panelHeight = Main.panel.height; // panelBox height can be 0 after shell start
-
- if (opt.PANEL_POSITION_TOP || reset)
- panelBox.set_position(geometry.x, geometry.y);
- else
- panelBox.set_position(geometry.x, geometry.y + geometry.height - panelHeight);
-}
-
-function _updateStyleChangedConnection(reset = false) {
- if (reset) {
- if (_styleChangedConId) {
- Main.panel.disconnect(_styleChangedConId);
- _styleChangedConId = 0;
+
+ _reparentPanel(reparent = false) {
+ const panel = Main.layoutManager.panelBox;
+ if (reparent && panel.get_parent() === Main.layoutManager.uiGroup) {
+ Main.layoutManager.uiGroup.remove_child(panel);
+ Main.layoutManager.overviewGroup.add_child(panel);
+ } else if (!reparent && panel.get_parent() === Main.layoutManager.overviewGroup) {
+ Main.layoutManager.overviewGroup.remove_child(panel);
+ // return the panel at default position, panel shouldn't cover objects that should be above
+ Main.layoutManager.uiGroup.insert_child_at_index(panel, 4);
}
- } else if (!_styleChangedConId) {
- Main.panel.connect('style-changed', () => {
- if (opt.PANEL_MODE === 1)
- Main.panel.add_style_pseudo_class('overview');
- else if (opt.OVERVIEW_MODE2)
- Main.panel.remove_style_pseudo_class('overview');
+ }
+
+ _setPanelStructs(state) {
+ Main.layoutManager._trackedActors.forEach(a => {
+ if (a.actor === Main.layoutManager.panelBox)
+ a.affectsStruts = state;
});
+
+ // workaround to force maximized windows to resize after removing affectsStruts
+ // simulation of minimal swipe gesture to the opposite direction
+ // todo - needs better solution!!!!!!!!!!!
+ // const direction = _getAppGridAnimationDirection() === 2 ? 1 : -1;
+ // Main.overview._swipeTracker._beginTouchSwipe(null, global.get_current_time(), 1, 1);
+ // Main.overview._swipeTracker._updateGesture(null, global.get_current_time(), direction, 1);
+ // GLib.timeout_add(0, 50, () => Main.overview._swipeTracker._endGesture(global.get_current_time(), 1, true));*/
}
-}
-function _updateOverviewConnection(reset = false) {
- if (reset) {
- if (_hidingOverviewConId) {
- Main.overview.disconnect(_hidingOverviewConId);
- _hidingOverviewConId = 0;
- }
- if (_showingOverviewConId) {
- Main.overview.disconnect(_showingOverviewConId);
- _showingOverviewConId = 0;
- }
- } else {
- if (!_hidingOverviewConId) {
- _hidingOverviewConId = Main.overview.connect('hiding', () => {
- if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2)
- _showPanel(false);
+ _showPanel(show = true) {
+ if (show) {
+ Main.panel.opacity = 255;
+ Main.layoutManager.panelBox.ease({
+ duration: ANIMATION_TIME,
+ translation_y: 0,
+ onComplete: () => {
+ this._setPanelStructs(opt.PANEL_MODE === 0);
+ },
});
- }
- if (!_showingOverviewConId) {
- _showingOverviewConId = Main.overview.connect('showing', () => {
- if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2 || Main.layoutManager.panelBox.translation_y)
- _showPanel(true);
+ } else {
+ const panelHeight = Main.panel.height;
+ Main.layoutManager.panelBox.ease({
+ duration: ANIMATION_TIME,
+ translation_y: opt.PANEL_POSITION_TOP ? -panelHeight + 1 : panelHeight - 1,
+ onComplete: () => {
+ Main.panel.opacity = 0;
+ this._setPanelStructs(opt.PANEL_MODE === 0);
+ },
});
}
}
-}
-
-function _reparentPanel(reparent = false) {
- const panel = Main.layoutManager.panelBox;
- if (reparent && panel.get_parent() === Main.layoutManager.uiGroup) {
- Main.layoutManager.uiGroup.remove_child(panel);
- Main.layoutManager.overviewGroup.add_child(panel);
- } else if (!reparent && panel.get_parent() === Main.layoutManager.overviewGroup) {
- Main.layoutManager.overviewGroup.remove_child(panel);
- // return the panel at default position, panel shouldn't cover objects that should be above
- Main.layoutManager.uiGroup.insert_child_at_index(panel, 4);
- }
-}
-
-function _setPanelStructs(state) {
- Main.layoutManager._trackedActors.forEach(a => {
- if (a.actor === Main.layoutManager.panelBox)
- a.affectsStruts = state;
- });
-
- // workaround to force maximized windows to resize after removing affectsStruts
- // simulation of minimal swipe gesture to the opposite direction
- // todo - needs better solution!!!!!!!!!!!
- // const direction = _getAppGridAnimationDirection() === 2 ? 1 : -1;
- // Main.overview._swipeTracker._beginTouchSwipe(null, global.get_current_time(), 1, 1);
- // Main.overview._swipeTracker._updateGesture(null, global.get_current_time(), direction, 1);
- // GLib.timeout_add(0, 50, () => Main.overview._swipeTracker._endGesture(global.get_current_time(), 1, true));*/
-}
-
-function _showPanel(show = true) {
- if (show) {
- Main.panel.opacity = 255;
- Main.layoutManager.panelBox.ease({
- duration: ANIMATION_TIME,
- translation_y: 0,
- onComplete: () => {
- _setPanelStructs(opt.PANEL_MODE === 0);
- },
- });
- } else {
- const panelHeight = Main.panel.height;
- Main.layoutManager.panelBox.ease({
- duration: ANIMATION_TIME,
- translation_y: opt.PANEL_POSITION_TOP ? -panelHeight + 1 : panelHeight - 1,
- onComplete: () => {
- Main.panel.opacity = 0;
- _setPanelStructs(opt.PANEL_MODE === 0);
- },
- });
- }
-}
+};
+
+const ActivitiesButton = {
+ vfunc_event(event) {
+ if (event.type() === Clutter.EventType.TOUCH_END ||
+ event.type() === Clutter.EventType.BUTTON_RELEASE) {
+ if (Main.overview.shouldToggleByCornerOrButton()) {
+ if (event.get_button() === Clutter.BUTTON_SECONDARY && !Main.overview.dash.showAppsButton.checked) {
+ Main.overview.show(2);
+ Main.overview.dash.showAppsButton.checked = true;
+ } else {
+ Main.overview.toggle();
+ }
+ }
+ } else if (event.type() === Clutter.EventType.SCROLL) {
+ Main.wm.handleWorkspaceScroll(event);
+ }
+
+ return Clutter.EVENT_PROPAGATE;
+ },
+};
diff --git a/extensions/44/vertical-workspaces/lib/recentFilesSearchProvider.js b/extensions/44/vertical-workspaces/lib/recentFilesSearchProvider.js
index 86e38f4..b567ff2 100644
--- a/extensions/44/vertical-workspaces/lib/recentFilesSearchProvider.js
+++ b/extensions/44/vertical-workspaces/lib/recentFilesSearchProvider.js
@@ -1,5 +1,5 @@
/**
- * Vertical Workspaces
+* V-Shell (Vertical Workspaces)
* recentFilesSearchProvider.js
*
* @author GdH <G-dH@github.com>
@@ -9,116 +9,146 @@
'use strict';
-const { GLib, Gio, Meta, St, Shell, Gtk } = imports.gi;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const RecentManager = imports.gi.Gtk.RecentManager;
+const St = imports.gi.St;
+const Shell = imports.gi.Shell;
const Main = imports.ui.main;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-const Settings = Me.imports.lib.settings;
-const _Util = Me.imports.lib.util;
+let Me;
+let opt;
// gettext
-const _ = Settings._;
-
-const shellVersion = Settings.shellVersion;
-
-const ModifierType = imports.gi.Clutter.ModifierType;
-
-let recentFilesSearchProvider;
-let _enableTimeoutId = 0;
+let _;
// prefix helps to eliminate results from other search providers
// so it needs to be something less common
// needs to be accessible from vw module
-var prefix = 'fq//';
+const PREFIX = 'fq//';
+
+var RecentFilesSearchProviderModule = class {
+ // export for other modules
+ static _PREFIX = PREFIX;
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ _ = Me.gettext;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._recentFilesSearchProvider = null;
+ this._enableTimeoutId = 0;
+ }
-var opt;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ _ = null;
+ }
-function getOverviewSearchResult() {
- return Main.overview._overview.controls._searchController._searchResults;
-}
+ update(reset) {
+ this.moduleEnabled = opt.get('recentFilesSearchProviderModule');
+ reset = reset || !this.moduleEnabled;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- if (!reset && opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED && !recentFilesSearchProvider) {
- enable();
- } else if (reset || !opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED) {
- disable();
- opt = null;
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' RecentFilesSearchProviderModule - Keeping untouched');
}
-}
-function enable() {
- // delay because Fedora had problem to register a new provider soon after Shell restarts
- _enableTimeoutId = GLib.timeout_add(
- GLib.PRIORITY_DEFAULT,
- 2000,
- () => {
- if (!recentFilesSearchProvider) {
- recentFilesSearchProvider = new RecentFilesSearchProvider(opt);
- getOverviewSearchResult()._registerProvider(recentFilesSearchProvider);
+ _activateModule() {
+ // delay because Fedora had problem to register a new provider soon after Shell restarts
+ this._enableTimeoutId = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ 2000,
+ () => {
+ if (!this._recentFilesSearchProvider) {
+ this._recentFilesSearchProvider = new RecentFilesSearchProvider(opt);
+ this._getOverviewSearchResult()._registerProvider(this._recentFilesSearchProvider);
+ }
+ this._enableTimeoutId = 0;
+ return GLib.SOURCE_REMOVE;
}
- _enableTimeoutId = 0;
- return GLib.SOURCE_REMOVE;
- }
- );
-}
+ );
-function disable() {
- if (recentFilesSearchProvider) {
- getOverviewSearchResult()._unregisterProvider(recentFilesSearchProvider);
- recentFilesSearchProvider = null;
- }
- if (_enableTimeoutId) {
- GLib.source_remove(_enableTimeoutId);
- _enableTimeoutId = 0;
+ console.debug(' RecentFilesSearchProviderModule - Activated');
}
-}
-function makeResult(window, i) {
- const app = Shell.WindowTracker.get_default().get_window_app(window);
- const appName = app ? app.get_name() : 'Unknown';
- const windowTitle = window.get_title();
- const wsIndex = window.get_workspace().index();
-
- return {
- 'id': i,
- // convert all accented chars to their basic form and lower case for search
- 'name': `${wsIndex + 1}: ${windowTitle} ${appName}`.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase(),
- appName,
- windowTitle,
- window,
- };
-}
+ _disableModule() {
+ if (this._recentFilesSearchProvider) {
+ this._getOverviewSearchResult()._unregisterProvider(this._recentFilesSearchProvider);
+ this._recentFilesSearchProvider = null;
+ }
+ if (this._enableTimeoutId) {
+ GLib.source_remove(this._enableTimeoutId);
+ this._enableTimeoutId = 0;
+ }
-const closeSelectedRegex = /^\/x!$/;
-const closeAllResultsRegex = /^\/xa!$/;
-const moveToWsRegex = /^\/m[0-9]+$/;
-const moveAllToWsRegex = /^\/ma[0-9]+$/;
+ console.debug(' RecentFilesSearchProviderModule - Disabled');
+ }
-const RecentFilesSearchProvider = class RecentFilesSearchProvider {
- constructor() {
- this.id = 'org.gnome.Nautilus.desktop';
- this.appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -ws recent:///', 'Recent Files', null);
- // this.appInfo = Shell.AppSystem.get_default().lookup_app('org.gnome.Nautilus.desktop').appInfo;
- this.appInfo.get_description = () => _('Search recent files');
- this.appInfo.get_name = () => _('Recent Files');
- this.appInfo.get_id = () => this.id;
- this.appInfo.get_icon = () => Gio.icon_new_for_string('document-open-recent-symbolic');
- this.appInfo.should_show = () => true;
+ _getOverviewSearchResult() {
+ return Main.overview._overview.controls._searchController._searchResults;
+ }
+};
+class RecentFilesSearchProvider {
+ constructor() {
+ this.id = 'recent-files';
+ const appSystem = Shell.AppSystem.get_default();
+ let appInfo = appSystem.lookup_app('org.gnome.Nautilus.desktop')?.get_app_info();
+ if (!appInfo)
+ appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -w', _('Recent Files'), null);
+ appInfo.get_description = () => _('Search recent files');
+ appInfo.get_name = () => _('Recent Files');
+ appInfo.get_id = () => 'org.gnome.Nautilus.desktop';
+ appInfo.get_icon = () => Gio.icon_new_for_string('document-open-recent-symbolic');
+ appInfo.should_show = () => true;
+
+ this.appInfo = appInfo;
this.canLaunchSearch = true;
this.isRemoteProvider = false;
}
+ getInitialResultSet(terms, callback /* , cancellable = null*/) {
+ // In GS 43 callback arg has been removed
+ /* if (Me.shellVersion >= 43)
+ cancellable = callback; */
+
+ const filesDict = {};
+ let files = [];
+ if (terms[0].startsWith(PREFIX))
+ files = RecentManager.get_default().get_items();
+
+ // Detect whether time stamps are in int, or in GLib.DateTime object
+ this._timeNeedsConversion = files[0]?.get_modified().to_unix;
+
+ for (let file of files)
+ filesDict[file.get_uri()] = file;
+
+ this.files = filesDict;
+
+ if (Me.shellVersion >= 43)
+ return new Promise(resolve => resolve(this._getResultSet(terms)));
+ else
+ callback(this._getResultSet(terms));
+
+ return null;
+ }
+
_getResultSet(terms) {
- if (!terms[0].startsWith(prefix))
+ if (!terms[0].startsWith(PREFIX))
return [];
// do not modify original terms
let termsCopy = [...terms];
// search for terms without prefix
- termsCopy[0] = termsCopy[0].replace(prefix, '');
+ termsCopy[0] = termsCopy[0].replace(PREFIX, '');
const candidates = this.files;
const _terms = [].concat(termsCopy);
@@ -135,15 +165,18 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
const file = this.files[id];
const name = `${file.get_age()}d: ${file.get_display_name()} ${file.get_uri_display().replace(`/${file.get_display_name()}`, '')}`;
if (opt.SEARCH_FUZZY)
- m = _Util.fuzzyMatch(term, name);
+ m = Me.Util.fuzzyMatch(term, name);
else
- m = _Util.strictMatch(term, name);
+ m = Me.Util.strictMatch(term, name);
if (m !== -1)
results.push({ weight: m, id });
}
- results.sort((a, b) => this.files[a.id].get_visited() < this.files[b.id].get_visited());
+ if (this._timeNeedsConversion)
+ results.sort((a, b) => this.files[a.id].get_modified().to_unix() < this.files[b.id].get_modified().to_unix());
+ else
+ results.sort((a, b) => this.files[a.id].get_modified() < this.files[b.id].get_modified());
this.resultIds = results.map(item => item.id);
return this.resultIds;
@@ -151,7 +184,7 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
getResultMetas(resultIds, callback = null) {
const metas = resultIds.map(id => this.getResultMeta(id));
- if (shellVersion >= 43)
+ if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(metas));
else if (callback)
callback(metas);
@@ -172,89 +205,54 @@ const RecentFilesSearchProvider = class RecentFilesSearchProvider {
}
getIcon(result, size) {
- let file = Gio.File.new_for_uri(result.get_uri());
- let info = file.query_info(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH,
- Gio.FileQueryInfoFlags.NONE, null);
- let path = info.get_attribute_byte_string(
- Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH);
-
let icon, gicon;
- if (path) {
- gicon = Gio.FileIcon.new(Gio.File.new_for_path(path));
- } else {
- const appInfo = Gio.AppInfo.get_default_for_type(result.get_mime_type(), false);
- if (appInfo)
- gicon = appInfo.get_icon();
- }
+ const appInfo = Gio.AppInfo.get_default_for_type(result.get_mime_type(), false);
+ if (appInfo)
+ gicon = appInfo.get_icon();
if (gicon)
icon = new St.Icon({ gicon, icon_size: size });
else
icon = new St.Icon({ icon_name: 'icon-missing', icon_size: size });
-
return icon;
}
- launchSearch(/* terms, timeStamp */) {
- this._openNautilus('recent:///');
+ launchSearch(terms, timeStamp) {
+ const appInfo = Gio.AppInfo.create_from_commandline('/usr/bin/nautilus -w recent:///', 'Nautilus', null);
+ appInfo.launch([], global.create_app_launch_context(timeStamp, -1));
}
- _openNautilus(uri) {
- try {
- GLib.spawn_command_line_async(`nautilus -ws ${uri}`);
- } catch (e) {
- log(e);
- }
- }
-
- activateResult(resultId /* , terms, timeStamp */) {
- const file = this.files[resultId];
-
- if (_Util.isShiftPressed()) {
+ activateResult(resultId, terms, timeStamp) {
+ const uri = resultId;
+ const context = global.create_app_launch_context(timeStamp, -1);
+ if (Me.Util.isShiftPressed()) {
Main.overview.toggle();
- this._openNautilus(file.get_uri());
+ this.appInfo.launch_uris([uri], context);
+ } else if (Gio.app_info_launch_default_for_uri(uri, context)) {
+ // update recent list after (hopefully) successful activation
+ const recentManager = RecentManager.get_default();
+ recentManager.add_item(resultId);
} else {
- const appInfo = Gio.AppInfo.get_default_for_type(file.get_mime_type(), false);
- if (!(appInfo && appInfo.launch_uris([file.get_uri()], null)))
- this._openNautilus(file.get_uri());
+ this.appInfo.launch_uris([uri], context);
}
}
- getInitialResultSet(terms, callback /* , cancellable = null*/) {
- // In GS 43 callback arg has been removed
- /* if (shellVersion >= 43)
- cancellable = callback; */
-
- const filesDict = {};
- const files = Gtk.RecentManager.get_default().get_items().filter(f => f.exists());
-
- for (let file of files)
- filesDict[file.get_uri()] = file;
-
-
- this.files = filesDict;
-
- if (shellVersion >= 43)
- return new Promise(resolve => resolve(this._getResultSet(terms)));
- else
- callback(this._getResultSet(terms));
-
- return null;
+ filterResults(results /* , maxResults*/) {
+ // return results.slice(0, maxResults);
+ return results.slice(0, 20);
}
- filterResults(results, maxResults) {
- return results.slice(0, 20);
- // return results.slice(0, maxResults);
+ getSubsearchResultSet(previousResults, terms, callback) {
+ if (Me.shellVersion < 43) {
+ this.getSubsearchResultSet42(terms, callback);
+ return null;
+ }
+ return this.getInitialResultSet(terms);
}
- getSubsearchResultSet(previousResults, terms, callback /* , cancellable*/) {
- // if we return previous results, quick typers get non-actual results
+ getSubsearchResultSet42(terms, callback) {
callback(this._getResultSet(terms));
}
-
- /* createResultObject(resultMeta) {
- return this.files[resultMeta.id];
- }*/
-};
+}
diff --git a/extensions/44/vertical-workspaces/lib/search.js b/extensions/44/vertical-workspaces/lib/search.js
index 8540626..618c5ed 100644
--- a/extensions/44/vertical-workspaces/lib/search.js
+++ b/extensions/44/vertical-workspaces/lib/search.js
@@ -9,92 +9,137 @@
*/
'use strict';
-const { Shell, Gio, St, Clutter } = imports.gi;
-const Main = imports.ui.main;
+
+const Clutter = imports.gi.Clutter;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
const AppDisplay = imports.ui.appDisplay;
+const IconGrid = imports.ui.iconGrid;
+const Main = imports.ui.main;
const Search = imports.ui.search;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-
-const _ = Me.imports.lib.settings._;
-const shellVersion = _Util.shellVersion;
-
+let Me;
+// gettext
+let _;
let opt;
-let _overrides;
-let _firstRun = true;
+
let SEARCH_MAX_WIDTH;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('searchModule', true);
- reset = reset || !moduleEnabled;
+var SearchModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ _ = Me.gettext;
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
- _firstRun = false;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ _ = null;
+ }
- if (_overrides)
- _overrides.removeAll();
+ update(reset) {
+ this.moduleEnabled = opt.get('searchModule');
+ const conflict = false;
- _updateSearchViewWidth(reset);
+ reset = reset || !this.moduleEnabled || conflict;
- if (reset) {
- Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.FILL;
- opt = null;
- _overrides = null;
- return;
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' SearchModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ this._updateSearchViewWidth();
+
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ this._overrides.addOverride('AppSearchProvider', AppDisplay.AppSearchProvider.prototype, AppSearchProvider);
+ this._overrides.addOverride('SearchResult', Search.SearchResult.prototype, SearchResult);
+ this._overrides.addOverride('SearchResultsView', Search.SearchResultsView.prototype, SearchResultsView);
+ this._overrides.addOverride('ProviderInfo', Search.ProviderInfo.prototype, ProviderInfo);
+
+ // Don't expand the search view vertically and align it to the top
+ // this is important in the static workspace mode when the search view bg is not transparent
+ // also the "Searching..." and "No Results" notifications will be closer to the search entry, with the distance given by margin-top in the stylesheet
+ Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.START;
+ console.debug(' SearchModule - Activated');
}
- _overrides = new _Util.Overrides();
+ _disableModule() {
+ const reset = true;
+ this._updateSearchViewWidth(reset);
- _overrides.addOverride('AppSearchProvider', AppDisplay.AppSearchProvider.prototype, AppSearchProvider);
- _overrides.addOverride('SearchResult', Search.SearchResult.prototype, SearchResult);
- _overrides.addOverride('SearchResultsView', Search.SearchResultsView.prototype, SearchResultsView);
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.FILL;
- // Don't expand the search view vertically and align it to the top
- // this is important in the static workspace mode when the search view bg is not transparent
- // also the "Searching..." and "No Results" notifications will be closer to the search entry, with the distance given by margin-top in the stylesheet
- Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.START;
-}
-function _updateSearchViewWidth(reset = false) {
- const searchContent = Main.overview._overview._controls.layoutManager._searchController._searchResults._content;
- if (!SEARCH_MAX_WIDTH) { // just store original value;
- const themeNode = searchContent.get_theme_node();
- const width = themeNode.get_max_width();
- SEARCH_MAX_WIDTH = width;
+ console.debug(' WorkspaceSwitcherPopupModule - Disabled');
}
- if (reset) {
- searchContent.set_style('');
- } else {
- let width = Math.round(SEARCH_MAX_WIDTH * opt.SEARCH_VIEW_SCALE);
- searchContent.set_style(`max-width: ${width}px;`);
+ _updateSearchViewWidth(reset = false) {
+ const searchContent = Main.overview._overview._controls.layoutManager._searchController._searchResults._content;
+ if (!SEARCH_MAX_WIDTH) { // just store original value;
+ const themeNode = searchContent.get_theme_node();
+ const width = themeNode.get_max_width();
+ SEARCH_MAX_WIDTH = width;
+ }
+
+ if (reset) {
+ searchContent.set_style('');
+ } else {
+ let width = Math.round(SEARCH_MAX_WIDTH * opt.SEARCH_VIEW_SCALE);
+ searchContent.set_style(`max-width: ${width}px;`);
+ }
}
-}
+};
// AppDisplay.AppSearchProvider
const AppSearchProvider = {
- getInitialResultSet(terms, callback, _cancellable) {
+ getInitialResultSet(terms, callback, cancellable) {
// Defer until the parental controls manager is initialized, so the
// results can be filtered correctly.
if (!this._parentalControlsManager.initialized) {
- let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
- if (this._parentalControlsManager.initialized) {
- this._parentalControlsManager.disconnect(initializedId);
- this.getInitialResultSet(terms, callback, _cancellable);
- }
- });
- return;
+ if (Me.shellVersion < 43) {
+ let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
+ if (this._parentalControlsManager.initialized) {
+ this._parentalControlsManager.disconnect(initializedId);
+ this.getInitialResultSet(terms, callback, cancellable);
+ }
+ });
+ return null;
+ } else {
+ // callback has been removed in 43
+ cancellable = callback;
+ return new Promise(resolve => {
+ let initializedId = this._parentalControlsManager.connect('app-filter-changed', async () => {
+ if (this._parentalControlsManager.initialized) {
+ this._parentalControlsManager.disconnect(initializedId);
+ resolve(await this.getInitialResultSet(terms, cancellable));
+ }
+ });
+ });
+ }
}
-
const pattern = terms.join(' ');
+
let appInfoList = Shell.AppSystem.get_default().get_installed();
let weightList = {};
@@ -113,22 +158,25 @@ const AppSearchProvider = {
shouldShow = appInfo.should_show() && this._parentalControlsManager.shouldShowApp(appInfo);
if (shouldShow) {
+ let id = appInfo.get_id().split('.');
+ id = id[id.length - 2] || '';
+ let baseName = appInfo.get_string('Name') || '';
let dispName = appInfo.get_display_name() || '';
let gName = appInfo.get_generic_name() || '';
let description = appInfo.get_description() || '';
let categories = appInfo.get_string('Categories') || '';
let keywords = appInfo.get_string('Keywords') || '';
- name = dispName;
- string = `${dispName} ${gName} ${description} ${categories} ${keywords}`;
+ name = `${dispName} ${id}`;
+ string = `${dispName} ${gName} ${baseName} ${description} ${categories} ${keywords} ${id}`;
}
}
let m = -1;
if (shouldShow && opt.SEARCH_FUZZY) {
- m = _Util.fuzzyMatch(pattern, name);
- m = (m + _Util.strictMatch(pattern, string)) / 2;
+ m = Me.Util.fuzzyMatch(pattern, name);
+ m = (m + Me.Util.strictMatch(pattern, string)) / 2;
} else if (shouldShow) {
- m = _Util.strictMatch(pattern, string);
+ m = Me.Util.strictMatch(pattern, string);
}
if (m !== -1)
@@ -143,16 +191,18 @@ const AppSearchProvider = {
// sort apps by usage list
appInfoList.sort((a, b) => usage.compare(a.get_id(), b.get_id()));
// prefer apps where any word in their name starts with the pattern
- appInfoList.sort((a, b) => _Util.isMoreRelevant(a.get_display_name(), b.get_display_name(), pattern));
+ appInfoList.sort((a, b) => Me.Util.isMoreRelevant(a.get_display_name(), b.get_display_name(), pattern));
let results = appInfoList.map(app => app.get_id());
results = results.concat(this._systemActions.getMatchingActions(terms));
- if (shellVersion < 43)
+ if (Me.shellVersion < 43) {
callback(results);
- else
+ return null;
+ } else {
return new Promise(resolve => resolve(results));
+ }
},
// App search result size
@@ -181,12 +231,69 @@ const SearchResult = {
St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
}
// don't close overview if Shift key is pressed - Shift moves windows to the workspace
- if (!_Util.isShiftPressed())
+ if (!Me.Util.isShiftPressed())
Main.overview.toggle();
},
};
const SearchResultsView = {
+ _doSearch() {
+ if (!this._doProviderSearch) {
+ this._doSearchLegacy();
+ return;
+ }
+ this._startingSearch = false;
+
+ let previousResults = this._results;
+ this._results = {};
+
+ this._providers.forEach(provider => {
+ const onlyVShellProviders = this._terms.includes('wq//') || this._terms.includes('fq//');
+ if (!onlyVShellProviders || (onlyVShellProviders && (provider.id.includes('open-windows') || provider.id.includes('recent-files')))) {
+ let previousProviderResults = previousResults[provider.id];
+ this._doProviderSearch(provider, previousProviderResults);
+ }
+ });
+
+ this._updateSearchProgress();
+
+ this._clearSearchTimeout();
+ },
+
+ _doSearchLegacy() {
+ this._startingSearch = false;
+
+ let previousResults = this._results;
+ this._results = {};
+
+ this._providers.forEach(provider => {
+ const onlyVShellProviders = this._terms.includes('wq//') || this._terms.includes('fq//');
+ if (!onlyVShellProviders || (onlyVShellProviders && (provider.id.includes('open-windows') || provider.id.includes('recent-files')))) {
+ provider.searchInProgress = true;
+
+ let previousProviderResults = previousResults[provider.id];
+ if (this._isSubSearch && previousProviderResults) {
+ provider.getSubsearchResultSet(previousProviderResults,
+ this._terms,
+ results => {
+ this._gotResults(results, provider);
+ },
+ this._cancellable);
+ } else {
+ provider.getInitialResultSet(this._terms,
+ results => {
+ this._gotResults(results, provider);
+ },
+ this._cancellable);
+ }
+ }
+ });
+
+ this._updateSearchProgress();
+
+ this._clearSearchTimeout();
+ },
+
_updateSearchProgress() {
let haveResults = this._providers.some(provider => {
let display = provider.display;
@@ -204,3 +311,13 @@ const SearchResultsView = {
}
},
};
+
+// fixes app is null error if search provider id is not a desktop app id.
+const ProviderInfo = {
+ animateLaunch() {
+ let appSys = Shell.AppSystem.get_default();
+ let app = appSys.lookup_app(this.provider.appInfo.get_id());
+ if (app && app.state === Shell.AppState.STOPPED)
+ IconGrid.zoomOutActor(this._content);
+ },
+};
diff --git a/extensions/44/vertical-workspaces/lib/searchController.js b/extensions/44/vertical-workspaces/lib/searchController.js
new file mode 100644
index 0000000..76b65e8
--- /dev/null
+++ b/extensions/44/vertical-workspaces/lib/searchController.js
@@ -0,0 +1,94 @@
+/**
+ * V-Shell (Vertical Workspaces)
+ * searchController.js
+ *
+ * @author GdH <G-dH@github.com>
+ * @copyright 2022 - 2023
+ * @license GPL-3.0
+ *
+ */
+
+'use strict';
+
+const Clutter = imports.gi.Clutter;
+
+const Main = imports.ui.main;
+
+let Me;
+let opt;
+
+var SearchControllerModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._originalOnStageKeyPress = null;
+ }
+
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
+
+ update(reset) {
+ this.moduleEnabled = opt.get('searchControllerModule');
+ const conflict = false;
+
+ reset = reset || !this.moduleEnabled || conflict;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' SearchControllerModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ if (!this._originalOnStageKeyPress)
+ this._originalOnStageKeyPress = Main.overview._overview.controls._searchController._onStageKeyPress;
+
+ Main.overview._overview.controls._searchController._onStageKeyPress = SearchControllerCommon._onStageKeyPress;
+ console.debug(' SearchControllerModule - Activated');
+ }
+
+ _disableModule() {
+ if (this._originalOnStageKeyPress)
+ Main.overview._overview.controls._searchController._onStageKeyPress = this._originalOnStageKeyPress;
+ this._originalOnStageKeyPress = null;
+
+ console.debug(' SearchControlerModule - Disabled');
+ }
+};
+
+// if opt.ESC_BEHAVIOR > 0 force close the overview
+const SearchControllerCommon = {
+ _onStageKeyPress(actor, event) {
+ // Ignore events while anything but the overview has
+ // pushed a modal (system modals, looking glass, ...)
+ if (Main.modalCount > 1)
+ return Clutter.EVENT_PROPAGATE;
+
+ let symbol = event.get_key_symbol();
+ if (symbol === Clutter.KEY_Escape) {
+ if (this._searchActive && !opt.ESC_BEHAVIOR) {
+ this.reset();
+ } else if (this._showAppsButton.checked && !opt.ESC_BEHAVIOR) {
+ this._showAppsButton.checked = false;
+ } else {
+ this.reset();
+ Main.overview.hide();
+ }
+
+ return Clutter.EVENT_STOP;
+ } else if (this._shouldTriggerSearch(symbol)) {
+ this.startSearch(event);
+ }
+ return Clutter.EVENT_PROPAGATE;
+ },
+};
diff --git a/extensions/44/vertical-workspaces/lib/settings.js b/extensions/44/vertical-workspaces/lib/settings.js
index 66f3a45..cbb74f2 100644
--- a/extensions/44/vertical-workspaces/lib/settings.js
+++ b/extensions/44/vertical-workspaces/lib/settings.js
@@ -9,25 +9,15 @@
'use strict';
-const { GLib } = imports.gi;
+const GLib = imports.gi.GLib;
-const Config = imports.misc.config;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-var shellVersion = parseFloat(Config.PACKAGE_VERSION);
-
-const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']);
-var _ = Gettext.gettext;
-const _schema = Me.metadata['settings-schema'];
-
-// common instance of Options accessible from all modules
-var opt;
+let Me;
var Options = class Options {
- constructor() {
- this._gsettings = ExtensionUtils.getSettings(_schema);
+ constructor(me) {
+ Me = me;
+
+ this._gsettings = Me.gSettings;
this._connectionIds = [];
this._writeTimeoutId = 0;
this._gsettings.delay();
@@ -51,8 +41,8 @@ var Options = class Options {
wsMaxSpacing: ['int', 'ws-max-spacing'],
wsPreviewScale: ['int', 'ws-preview-scale'],
secWsPreviewScale: ['int', 'secondary-ws-preview-scale'],
- secWsPreviewShift: ['bool', 'secondary-ws-preview-shift'],
- wsThumbnailsFull: ['bool', 'ws-thumbnails-full'],
+ secWsPreviewShift: ['boolean', 'secondary-ws-preview-shift'],
+ wsThumbnailsFull: ['boolean', 'ws-thumbnails-full'],
secWsThumbnailsPosition: ['int', 'secondary-ws-thumbnails-position'],
dashPosition: ['int', 'dash-position'],
dashPositionAdjust: ['int', 'dash-position-adjust'],
@@ -64,6 +54,7 @@ var Options = class Options {
dashMaxIconSize: ['int', 'dash-max-icon-size'],
dashShowWindowsIcon: ['int', 'dash-show-windows-icon'],
dashShowRecentFilesIcon: ['int', 'dash-show-recent-files-icon'],
+ dashShowExtensionsIcon: ['int', 'dash-show-extensions-icon'],
centerDashToWs: ['boolean', 'center-dash-to-ws'],
showAppsIconPosition: ['int', 'show-app-icon-position'],
wsThumbnailScale: ['int', 'ws-thumbnail-scale'],
@@ -73,13 +64,17 @@ var Options = class Options {
centerSearch: ['boolean', 'center-search'],
centerAppGrid: ['boolean', 'center-app-grid'],
dashBgOpacity: ['int', 'dash-bg-opacity'],
+ dashBgColor: ['int', 'dash-bg-color'],
dashBgRadius: ['int', 'dash-bg-radius'],
+ dashBgGS3Style: ['boolean', 'dash-bg-gs3-style'],
+ runningDotStyle: ['int', 'running-dot-style'],
enablePageShortcuts: ['boolean', 'enable-page-shortcuts'],
showWsSwitcherBg: ['boolean', 'show-ws-switcher-bg'],
showWsPreviewBg: ['boolean', 'show-ws-preview-bg'],
wsPreviewBgRadius: ['int', 'ws-preview-bg-radius'],
showBgInOverview: ['boolean', 'show-bg-in-overview'],
overviewBgBrightness: ['int', 'overview-bg-brightness'],
+ searchBgBrightness: ['int', 'search-bg-brightness'],
overviewBgBlurSigma: ['int', 'overview-bg-blur-sigma'],
appGridBgBlurSigma: ['int', 'app-grid-bg-blur-sigma'],
smoothBlurTransitions: ['boolean', 'smooth-blur-transitions'],
@@ -87,9 +82,8 @@ var Options = class Options {
searchViewAnimation: ['int', 'search-view-animation'],
workspaceAnimation: ['int', 'workspace-animation'],
animationSpeedFactor: ['int', 'animation-speed-factor'],
- fixUbuntuDock: ['boolean', 'fix-ubuntu-dock'],
winPreviewIconSize: ['int', 'win-preview-icon-size'],
- alwaysShowWinTitles: ['boolean', 'always-show-win-titles'],
+ winTitlePosition: ['int', 'win-title-position'],
startupState: ['int', 'startup-state'],
overviewMode: ['int', 'overview-mode'],
workspaceSwitcherAnimation: ['int', 'workspace-switcher-animation'],
@@ -105,17 +99,18 @@ var Options = class Options {
appGridContent: ['int', 'app-grid-content'],
appGridIncompletePages: ['boolean', 'app-grid-incomplete-pages'],
appGridOrder: ['int', 'app-grid-order'],
+ appFolderOrder: ['int', 'app-folder-order'],
appGridNamesMode: ['int', 'app-grid-names'],
appGridActivePreview: ['boolean', 'app-grid-active-preview'],
appGridFolderCenter: ['boolean', 'app-grid-folder-center'],
appGridPageWidthScale: ['int', 'app-grid-page-width-scale'],
appGridSpacing: ['int', 'app-grid-spacing'],
- searchWindowsEnable: ['boolean', 'search-windows-enable'],
- searchRecentFilesEnable: ['boolean', 'search-recent-files-enable'],
+ searchWindowsOrder: ['int', 'search-windows-order'],
searchFuzzy: ['boolean', 'search-fuzzy'],
searchMaxResultsRows: ['int', 'search-max-results-rows'],
dashShowWindowsBeforeActivation: ['int', 'dash-show-windows-before-activation'],
dashIconScroll: ['int', 'dash-icon-scroll'],
+ dashIsolateWorkspaces: ['boolean', 'dash-isolate-workspaces'],
searchWindowsIconScroll: ['int', 'search-windows-icon-scroll'],
panelVisibility: ['int', 'panel-visibility'],
panelPosition: ['int', 'panel-position'],
@@ -123,6 +118,8 @@ var Options = class Options {
wsSwPopupHPosition: ['int', 'ws-sw-popup-h-position'],
wsSwPopupVPosition: ['int', 'ws-sw-popup-v-position'],
wsSwPopupMode: ['int', 'ws-sw-popup-mode'],
+ wsSwitcherWraparound: ['boolean', 'ws-switcher-wraparound'],
+ wsSwitcherIgnoreLast: ['boolean', 'ws-switcher-ignore-last'],
favoritesNotify: ['int', 'favorites-notify'],
notificationPosition: ['int', 'notification-position'],
osdPosition: ['int', 'osd-position'],
@@ -131,17 +128,26 @@ var Options = class Options {
hotCornerFullscreen: ['boolean', 'hot-corner-fullscreen'],
hotCornerRipples: ['boolean', 'hot-corner-ripples'],
alwaysActivateSelectedWindow: ['boolean', 'always-activate-selected-window'],
- windowIconClickSearch: ['boolean', 'window-icon-click-search'],
+ winPreviewSecBtnAction: ['int', 'win-preview-sec-mouse-btn-action'],
+ winPreviewMidBtnAction: ['int', 'win-preview-mid-mouse-btn-action'],
+ winPreviewShowCloseButton: ['boolean', 'win-preview-show-close-button'],
+ windowIconClickAction: ['int', 'window-icon-click-action'],
+ overlayKeyPrimary: ['int', 'overlay-key-primary'],
overlayKeySecondary: ['int', 'overlay-key-secondary'],
+ overviewEscBehavior: ['int', 'overview-esc-behavior'],
+ newWindowFocusFix: ['boolean', 'new-window-focus-fix'],
+ appGridPerformance: ['boolean', 'app-grid-performance'],
+ windowThumbnailScale: ['int', 'window-thumbnail-scale'],
- workspaceThumbnailsModule: ['boolean', 'workspace-thumbnails-module'],
workspaceSwitcherPopupModule: ['boolean', 'workspace-switcher-popup-module'],
workspaceAnimationModule: ['boolean', 'workspace-animation-module'],
workspaceModule: ['boolean', 'workspace-module'],
windowManagerModule: ['boolean', 'window-manager-module'],
windowPreviewModule: ['boolean', 'window-preview-module'],
- winAttentionHandlerModule: ['boolean', 'win-attention-handler-module'],
+ windowAttentionHandlerModule: ['boolean', 'win-attention-handler-module'],
+ windowThumbnailModule: ['boolean', 'window-thumbnail-module'],
swipeTrackerModule: ['boolean', 'swipe-tracker-module'],
+ searchControllerModule: ['boolean', 'search-controller-module'],
searchModule: ['boolean', 'search-module'],
panelModule: ['boolean', 'panel-module'],
overlayKeyModule: ['boolean', 'overlay-key-module'],
@@ -151,6 +157,9 @@ var Options = class Options {
dashModule: ['boolean', 'dash-module'],
appFavoritesModule: ['boolean', 'app-favorites-module'],
appDisplayModule: ['boolean', 'app-display-module'],
+ windowSearchProviderModule: ['boolean', 'window-search-provider-module'],
+ recentFilesSearchProviderModule: ['boolean', 'recent-files-search-provider-module'],
+ extensionsSearchProviderModule: ['boolean', 'extensions-search-provider-module'],
profileName1: ['string', 'profile-name-1'],
profileName2: ['string', 'profile-name-2'],
@@ -158,9 +167,10 @@ var Options = class Options {
profileName4: ['string', 'profile-name-4'],
};
this.cachedOptions = {};
+ }
- this.shellVersion = shellVersion;
- // this.storeProfile(0);
+ cleanGlobals() {
+ Me = null;
}
connect(name, callback) {
@@ -183,7 +193,7 @@ var Options = class Options {
get(option, updateCache = false) {
if (!this.options[option]) {
- log(`[${Me.metadata.name}] Error: Option ${option} is undefined.`);
+ console.error(`[${Me.metadata.name}] Error: Option ${option} is undefined.`);
return null;
}
@@ -195,7 +205,6 @@ var Options = class Options {
else
gSettings = this._gsettings;
-
this.cachedOptions[option] = gSettings.get_value(key).deep_unpack();
}
@@ -242,7 +251,8 @@ var Options = class Options {
storeProfile(index) {
const profile = {};
Object.keys(this.options).forEach(v => {
- profile[v] = this.get(v).toString();
+ if (!v.startsWith('profileName'))
+ profile[v] = this.get(v).toString();
});
this._gsettings.set_value(`profile-data-${index}`, new GLib.Variant('a{ss}', profile));
@@ -250,8 +260,14 @@ var Options = class Options {
loadProfile(index) {
const options = this._gsettings.get_value(`profile-data-${index}`).deep_unpack();
+ // set the aaa-loading-data so extension.js doesn't reset V-Shell after each profile item
+ // delayed gsettings writes are processed alphabetically, so this key will be processed first
this._gsettings.set_boolean('aaa-loading-profile', !this._gsettings.get_boolean('aaa-loading-profile'));
for (let o of Object.keys(options)) {
+ if (!this.options[o]) {
+ console.error(`[${Me.metadata.name}] Error: "${o}" is not a valid profile key -> Update your profile`);
+ continue;
+ }
const [type] = this.options[o];
let value = options[o];
switch (type) {
@@ -275,7 +291,14 @@ var Options = class Options {
}
_updateSettings() {
- this.DASH_POSITION = this.get('dashPosition', true);
+ this._updateCachedSettings();
+ this.DASH_BG_ALPHA = this.get('dashBgOpacity') / 100;
+ this.DASH_BG_OPACITY = this.get('dashBgOpacity') * 2.5;
+ this.DASH_BG_COLOR = this.get('dashBgColor');
+ this.DASH_BG_RADIUS = this.get('dashBgRadius');
+ this.DASH_BG_LIGHT = this.DASH_BG_COLOR === 1;
+ this.DASH_BG_GS3_STYLE = this.get('dashBgGS3Style');
+ this.DASH_POSITION = this.get('dashModule') ? this.get('dashPosition') : 2;
this.DASH_TOP = this.DASH_POSITION === 0;
this.DASH_RIGHT = this.DASH_POSITION === 1;
this.DASH_BOTTOM = this.DASH_POSITION === 2;
@@ -284,26 +307,35 @@ var Options = class Options {
this.DASH_VISIBLE = this.DASH_POSITION !== 4; // 4 - disable
this.DASH_FOLLOW_RECENT_WIN = false;
- this.DASH_CLICK_ACTION = this.get('dashShowWindowsBeforeActivation', true);
- this.DASH_ICON_SCROLL = this.get('dashIconScroll', true);
+ this.DASH_ISOLATE_WS = this.get('dashIsolateWorkspaces');
+
+ this.DASH_CLICK_ACTION = this.get('dashShowWindowsBeforeActivation');
+ this.DASH_CLICK_SWITCH_BEFORE_ACTIVATION = this.DASH_CLICK_ACTION === 1;
+ this.DASH_CLICK_OPEN_NEW_WIN = this.DASH_CLICK_ACTION === 2;
+ this.DASH_CLICK_PREFER_WORKSPACE = this.DASH_CLICK_ACTION === 3;
+
+ this.DASH_ICON_SCROLL = this.get('dashIconScroll');
this.DASH_SHIFT_CLICK_MV = true;
- this.SEARCH_WINDOWS_ICON_SCROLL = this.get('searchWindowsIconScroll', true);
+ this.RUNNING_DOT_STYLE = this.get('runningDotStyle');
+
+ this.SEARCH_WINDOWS_ICON_SCROLL = this.get('searchWindowsIconScroll');
- this.DASH_POSITION_ADJUSTMENT = this.get('dashPositionAdjust', true);
+ this.DASH_POSITION_ADJUSTMENT = this.get('dashPositionAdjust');
this.DASH_POSITION_ADJUSTMENT = this.DASH_POSITION_ADJUSTMENT * -1 / 100; // range 1 to -1
- this.CENTER_DASH_WS = this.get('centerDashToWs', true);
+ this.CENTER_DASH_WS = this.get('centerDashToWs');
- this.MAX_ICON_SIZE = 64; // updates from main module
- this.SHOW_WINDOWS_ICON = this.get('dashShowWindowsIcon', true);
- this.SHOW_RECENT_FILES_ICON = this.get('dashShowRecentFilesIcon', true);
+ this.MAX_ICON_SIZE = this.get('dashMaxIconSize');
+ this.SHOW_WINDOWS_ICON = this.get('dashShowWindowsIcon');
+ this.SHOW_RECENT_FILES_ICON = this.get('dashShowRecentFilesIcon');
+ this.SHOW_EXTENSIONS_ICON = this.get('dashShowExtensionsIcon');
- this.WS_TMB_POSITION = this.get('workspaceThumbnailsPosition', true);
+ this.WS_TMB_POSITION = this.get('workspaceThumbnailsPosition');
this.ORIENTATION = this.WS_TMB_POSITION > 4 ? 0 : 1;
- this.WORKSPACE_MAX_SPACING = this.get('wsMaxSpacing', true);
+ this.WORKSPACE_MAX_SPACING = this.get('wsMaxSpacing');
// ORIENTATION || DASH_LEFT || DASH_RIGHT ? 350 : 80;
this.SHOW_WS_TMB = ![4, 9].includes(this.WS_TMB_POSITION); // 4, 9 - disable
- this.WS_TMB_FULL = this.get('wsThumbnailsFull', true);
+ this.WS_TMB_FULL = this.get('wsThumbnailsFull');
// translate ws tmb position to 0 top, 1 right, 2 bottom, 3 left
// 0L 1R, 2LF, 3RF, 4DV, 5T, 6B, 7TF, 8BF, 9DH
this.WS_TMB_POSITION = [3, 1, 3, 1, 4, 0, 2, 0, 2, 8][this.WS_TMB_POSITION];
@@ -311,81 +343,104 @@ var Options = class Options {
this.WS_TMB_RIGHT = this.WS_TMB_POSITION === 1;
this.WS_TMB_BOTTOM = this.WS_TMB_POSITION === 2;
this.WS_TMB_LEFT = this.WS_TMB_POSITION === 3;
- this.WS_TMB_POSITION_ADJUSTMENT = this.get('wsTmbPositionAdjust', true) * -1 / 100; // range 1 to -1
- this.SEC_WS_TMB_POSITION = this.get('secWsThumbnailsPosition', true);
+ this.WS_TMB_POSITION_ADJUSTMENT = this.get('wsTmbPositionAdjust') * -1 / 100; // range 1 to -1
+ this.SEC_WS_TMB_POSITION = this.get('secWsThumbnailsPosition');
this.SHOW_SEC_WS_TMB = this.SEC_WS_TMB_POSITION !== 3 && this.SHOW_WS_TMB;
this.SEC_WS_TMB_TOP = (this.SEC_WS_TMB_POSITION === 0 && !this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_TOP);
this.SEC_WS_TMB_RIGHT = (this.SEC_WS_TMB_POSITION === 1 && this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_RIGHT);
this.SEC_WS_TMB_BOTTOM = (this.SEC_WS_TMB_POSITION === 1 && !this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_BOTTOM);
this.SEC_WS_TMB_LEFT = (this.SEC_WS_TMB_POSITION === 0 && this.ORIENTATION) || (this.SEC_WS_TMB_POSITION === 2 && this.WS_TMB_LEFT);
- this.SEC_WS_TMB_POSITION_ADJUSTMENT = this.get('secWsTmbPositionAdjust', true) * -1 / 100; // range 1 to -1
- this.SEC_WS_PREVIEW_SHIFT = this.get('secWsPreviewShift', true);
- this.SHOW_WST_LABELS = this.get('showWsTmbLabels', true);
- this.SHOW_WST_LABELS_ON_HOVER = this.get('showWsTmbLabelsOnHover', true);
- this.CLOSE_WS_BUTTON_MODE = this.get('closeWsButtonMode', true);
+ this.SEC_WS_TMB_POSITION_ADJUSTMENT = this.get('secWsTmbPositionAdjust') * -1 / 100; // range 1 to -1
+ this.SEC_WS_PREVIEW_SHIFT = this.get('secWsPreviewShift');
+ this.SHOW_WST_LABELS = this.get('showWsTmbLabels');
+ this.SHOW_WST_LABELS_ON_HOVER = this.get('showWsTmbLabelsOnHover');
+ this.CLOSE_WS_BUTTON_MODE = this.get('closeWsButtonMode');
- this.MAX_THUMBNAIL_SCALE = this.get('wsThumbnailScale', true) / 100;
- this.MAX_THUMBNAIL_SCALE_APPGRID = this.get('wsThumbnailScaleAppGrid', true) / 100;
- if (this.MAX_THUMBNAIL_SCALE_APPGRID === 0)
- this.MAX_THUMBNAIL_SCALE_APPGRID = this.MAX_THUMBNAIL_SCALE;
+ this.MAX_THUMBNAIL_SCALE = this.get('wsThumbnailScale') / 100;
+ if (this.MAX_THUMBNAIL_SCALE === 0) {
+ this.MAX_THUMBNAIL_SCALE = 0.01;
+ this.SHOW_WS_TMB = false;
+ }
+ this.MAX_THUMBNAIL_SCALE_APPGRID = this.get('wsThumbnailScaleAppGrid') / 100;
+ this.SHOW_WS_TMB_APPGRID = true;
+ if (this.MAX_THUMBNAIL_SCALE_APPGRID === 0) {
+ this.MAX_THUMBNAIL_SCALE_APPGRID = 0.01;
+ this.SHOW_WS_TMB_APPGRID = false;
+ }
this.MAX_THUMBNAIL_SCALE_STABLE = this.MAX_THUMBNAIL_SCALE === this.MAX_THUMBNAIL_SCALE_APPGRID;
- this.SEC_MAX_THUMBNAIL_SCALE = this.get('secWsThumbnailScale', true) / 100;
- this.WS_PREVIEW_SCALE = this.get('wsPreviewScale', true) / 100;
- this.SEC_WS_PREVIEW_SCALE = this.get('secWsPreviewScale', true) / 100;
+ this.SEC_MAX_THUMBNAIL_SCALE = this.get('secWsThumbnailScale') / 100;
+ if (this.SEC_MAX_THUMBNAIL_SCALE === 0) {
+ this.SEC_MAX_THUMBNAIL_SCALE = 0.01;
+ this.SHOW_SEC_WS_TMB = false;
+ }
+
+ this.WS_PREVIEW_SCALE = this.get('wsPreviewScale') / 100;
+ this.SEC_WS_PREVIEW_SCALE = this.get('secWsPreviewScale') / 100;
// calculate number of possibly visible neighbor previews according to ws scale
this.NUMBER_OF_VISIBLE_NEIGHBORS = Math.round(1 + (1 - this.WS_PREVIEW_SCALE) / 4);
- this.SHOW_WS_TMB_BG = this.get('showWsSwitcherBg', true) && this.SHOW_WS_TMB;
- this.WS_PREVIEW_BG_RADIUS = this.get('wsPreviewBgRadius', true);
- this.SHOW_WS_PREVIEW_BG = this.get('showWsPreviewBg', true);
+ this.SHOW_WS_TMB_BG = this.get('showWsSwitcherBg') && this.SHOW_WS_TMB;
+ this.WS_PREVIEW_BG_RADIUS = this.get('wsPreviewBgRadius');
+ this.SHOW_WS_PREVIEW_BG = this.get('showWsPreviewBg');
- this.CENTER_APP_GRID = this.get('centerAppGrid', true);
+ this.CENTER_APP_GRID = this.get('centerAppGrid');
- this.SHOW_SEARCH_ENTRY = this.get('showSearchEntry', true);
- this.CENTER_SEARCH_VIEW = this.get('centerSearch', true);
- this.APP_GRID_ANIMATION = this.get('appGridAnimation', true);
+ this.SHOW_SEARCH_ENTRY = this.get('showSearchEntry');
+ this.CENTER_SEARCH_VIEW = this.get('centerSearch');
+ this.APP_GRID_ANIMATION = this.get('appGridAnimation');
if (this.APP_GRID_ANIMATION === 4)
this.APP_GRID_ANIMATION = this._getAnimationDirection();
- this.SEARCH_VIEW_ANIMATION = this.get('searchViewAnimation', true);
+ this.SEARCH_VIEW_ANIMATION = this.get('searchViewAnimation');
if (this.SEARCH_VIEW_ANIMATION === 4)
this.SEARCH_VIEW_ANIMATION = 3;
- this.WS_ANIMATION = this.get('workspaceAnimation', true);
+ this.WS_ANIMATION = this.get('workspaceAnimation');
- this.WIN_PREVIEW_ICON_SIZE = [64, 48, 32, 22, 8][this.get('winPreviewIconSize', true)];
- this.ALWAYS_SHOW_WIN_TITLES = this.get('alwaysShowWinTitles', true);
+ this.WIN_PREVIEW_ICON_SIZE = [64, 48, 32, 22, 8][this.get('winPreviewIconSize')];
+ this.WIN_TITLES_POSITION = this.get('winTitlePosition');
+ this.ALWAYS_SHOW_WIN_TITLES = this.WIN_TITLES_POSITION === 1;
- this.STARTUP_STATE = this.get('startupState', true);
- this.SHOW_BG_IN_OVERVIEW = this.get('showBgInOverview', true);
- this.OVERVIEW_BG_BRIGHTNESS = this.get('overviewBgBrightness', true) / 100;
- this.OVERVIEW_BG_BLUR_SIGMA = this.get('overviewBgBlurSigma', true);
- this.APP_GRID_BG_BLUR_SIGMA = this.get('appGridBgBlurSigma', true);
- this.SMOOTH_BLUR_TRANSITIONS = this.get('smoothBlurTransitions', true);
+ this.STARTUP_STATE = this.get('startupState');
+ this.SHOW_BG_IN_OVERVIEW = this.get('showBgInOverview');
+ this.OVERVIEW_BG_BRIGHTNESS = this.get('overviewBgBrightness') / 100;
+ this.SEARCH_BG_BRIGHTNESS = this.get('searchBgBrightness') / 100;
+ this.OVERVIEW_BG_BLUR_SIGMA = this.get('overviewBgBlurSigma');
+ this.APP_GRID_BG_BLUR_SIGMA = this.get('appGridBgBlurSigma');
+ this.SMOOTH_BLUR_TRANSITIONS = this.get('smoothBlurTransitions');
- this.OVERVIEW_MODE = this.get('overviewMode', true);
+ this.OVERVIEW_MODE = this.get('overviewMode');
this.OVERVIEW_MODE2 = this.OVERVIEW_MODE === 2;
this.WORKSPACE_MODE = this.OVERVIEW_MODE ? 0 : 1;
- this.STATIC_WS_SWITCHER_BG = this.get('workspaceSwitcherAnimation', true);
+ this.STATIC_WS_SWITCHER_BG = this.get('workspaceSwitcherAnimation');
- this.ANIMATION_TIME_FACTOR = this.get('animationSpeedFactor', true) / 100;
+ this.ANIMATION_TIME_FACTOR = this.get('animationSpeedFactor') / 100;
- this.SEARCH_ICON_SIZE = this.get('searchIconSize', true);
- this.SEARCH_VIEW_SCALE = this.get('searchViewScale', true) / 100;
- this.SEARCH_MAX_ROWS = this.get('searchMaxResultsRows', true);
- this.SEARCH_FUZZY = this.get('searchFuzzy', true);
+ this.SEARCH_ICON_SIZE = this.get('searchIconSize');
+ this.SEARCH_VIEW_SCALE = this.get('searchViewScale') / 100;
+ this.SEARCH_MAX_ROWS = this.get('searchMaxResultsRows');
+ this.SEARCH_FUZZY = this.get('searchFuzzy');
- this.APP_GRID_ALLOW_INCOMPLETE_PAGES = this.get('appGridIncompletePages', true);
- this.APP_GRID_ICON_SIZE = this.get('appGridIconSize', true);
- this.APP_GRID_COLUMNS = this.get('appGridColumns', true);
- this.APP_GRID_ROWS = this.get('appGridRows', true);
+ this.APP_GRID_ALLOW_INCOMPLETE_PAGES = this.get('appGridIncompletePages');
+ this.APP_GRID_ICON_SIZE = this.get('appGridIconSize');
+ this.APP_GRID_COLUMNS = this.get('appGridColumns');
+ this.APP_GRID_ROWS = this.get('appGridRows');
this.APP_GRID_ADAPTIVE = !this.APP_GRID_COLUMNS && !this.APP_GRID_ROWS;
- this.APP_GRID_ORDER = this.get('appGridOrder', true);
- this.APP_GRID_INCLUDE_DASH = this.get('appGridContent', true);
+ this.APP_GRID_ORDER = this.get('appGridOrder');
+ this.APP_GRID_ALPHABET = [1, 2].includes(this.APP_GRID_ORDER);
+ this.APP_GRID_FOLDERS_FIRST = this.APP_GRID_ORDER === 1;
+ this.APP_GRID_FOLDERS_LAST = this.APP_GRID_ORDER === 2;
+ this.APP_GRID_USAGE = this.APP_GRID_ORDER === 3;
+
+ this.APP_FOLDER_ORDER = this.get('appFolderOrder');
+ this.APP_FOLDER_ALPHABET = this.APP_FOLDER_ORDER === 1;
+ this.APP_FOLDER_USAGE = this.APP_FOLDER_ORDER === 2;
+
+ this.APP_GRID_INCLUDE_DASH = this.get('appGridContent');
/* APP_GRID_INCLUDE_DASH
0 - Include All
1 - Include All - Favorites and Runnings First
@@ -397,46 +452,50 @@ var Options = class Options {
this.APP_GRID_EXCLUDE_RUNNING = this.APP_GRID_INCLUDE_DASH === 3 || this.APP_GRID_INCLUDE_DASH === 4;
this.APP_GRID_DASH_FIRST = this.APP_GRID_INCLUDE_DASH === 1;
- this.APP_GRID_NAMES_MODE = this.get('appGridNamesMode', true);
+ this.APP_GRID_NAMES_MODE = this.get('appGridNamesMode');
- this.APP_GRID_FOLDER_ICON_SIZE = this.get('appGridFolderIconSize', true);
- this.APP_GRID_FOLDER_ICON_GRID = this.get('appGridFolderIconGrid', true);
- this.APP_GRID_FOLDER_COLUMNS = this.get('appGridFolderColumns', true);
- this.APP_GRID_FOLDER_ROWS = this.get('appGridFolderRows', true);
- this.APP_GRID_SPACING = this.get('appGridSpacing', true);
+ this.APP_GRID_FOLDER_ICON_SIZE = this.get('appGridFolderIconSize');
+ this.APP_GRID_FOLDER_ICON_GRID = this.get('appGridFolderIconGrid');
+ this.APP_GRID_FOLDER_COLUMNS = this.get('appGridFolderColumns');
+ this.APP_GRID_FOLDER_ROWS = this.get('appGridFolderRows');
+ this.APP_GRID_SPACING = this.get('appGridSpacing');
this.APP_GRID_FOLDER_DEFAULT = this.APP_GRID_FOLDER_ROWS === 3 && this.APP_GRID_FOLDER_COLUMNS === 3;
- this.APP_GRID_ACTIVE_PREVIEW = this.get('appGridActivePreview', true);
- this.APP_GRID_FOLDER_CENTER = this.get('appGridFolderCenter', true);
- this.APP_GRID_PAGE_WIDTH_SCALE = this.get('appGridPageWidthScale', true) / 100;
+ this.APP_GRID_FOLDER_ADAPTIVE = !this.APP_GRID_FOLDER_COLUMNS && !this.APP_GRID_FOLDER_ROWS;
+ this.APP_GRID_ACTIVE_PREVIEW = this.get('appGridActivePreview');
+ this.APP_GRID_FOLDER_CENTER = this.get('appGridFolderCenter');
+ this.APP_GRID_PAGE_WIDTH_SCALE = this.get('appGridPageWidthScale') / 100;
- this.APP_GRID_ICON_SIZE_DEFAULT = this.APP_GRID_ACTIVE_PREVIEW && !this.APP_GRID_ORDER ? 176 : 96;
+ this.APP_GRID_ICON_SIZE_DEFAULT = this.APP_GRID_ACTIVE_PREVIEW && !this.APP_GRID_USAGE ? 176 : 96;
this.APP_GRID_FOLDER_ICON_SIZE_DEFAULT = 96;
- this.WINDOW_SEARCH_PROVIDER_ENABLED = this.get('searchWindowsEnable', true);
- this.RECENT_FILES_SEARCH_PROVIDER_ENABLED = this.get('searchRecentFilesEnable', true);
+ this.APP_GRID_PERFORMANCE = this.get('appGridPerformance');
- this.PANEL_POSITION_TOP = this.get('panelPosition', true) === 0;
- this.PANEL_MODE = this.get('panelVisibility', true);
+ this.WINDOW_SEARCH_ORDER = this.get('searchWindowsOrder');
+
+ this.PANEL_POSITION_TOP = this.get('panelPosition') === 0;
+ this.PANEL_MODE = this.get('panelVisibility');
this.PANEL_DISABLED = this.PANEL_MODE === 2;
this.PANEL_OVERVIEW_ONLY = this.PANEL_MODE === 1;
this.START_Y_OFFSET = 0; // set from main module
- this.FIX_UBUNTU_DOCK = this.get('fixUbuntuDock', true);
- this.WINDOW_ATTENTION_MODE = this.get('windowAttentionMode', true);
+ this.WINDOW_ATTENTION_MODE = this.get('windowAttentionMode');
this.WINDOW_ATTENTION_DISABLE_NOTIFICATIONS = this.WINDOW_ATTENTION_MODE === 1;
this.WINDOW_ATTENTION_FOCUS_IMMEDIATELY = this.WINDOW_ATTENTION_MODE === 2;
- this.WS_SW_POPUP_H_POSITION = this.get('wsSwPopupHPosition', true) / 100;
- this.WS_SW_POPUP_V_POSITION = this.get('wsSwPopupVPosition', true) / 100;
- this.WS_SW_POPUP_MODE = this.get('wsSwPopupMode', true);
+ this.WS_SW_POPUP_H_POSITION = this.get('wsSwPopupHPosition') / 100;
+ this.WS_SW_POPUP_V_POSITION = this.get('wsSwPopupVPosition') / 100;
+ this.WS_SW_POPUP_MODE = this.get('wsSwPopupMode');
+
+ this.WS_WRAPAROUND = this.get('wsSwitcherWraparound');
+ this.WS_IGNORE_LAST = this.get('wsSwitcherIgnoreLast');
- this.SHOW_FAV_NOTIFICATION = this.get('favoritesNotify', true);
- this.NOTIFICATION_POSITION = this.get('notificationPosition', true);
+ this.SHOW_FAV_NOTIFICATION = this.get('favoritesNotify');
+ this.NOTIFICATION_POSITION = this.get('notificationPosition');
- this.OSD_POSITION = this.get('osdPosition', true);
+ this.OSD_POSITION = this.get('osdPosition');
- this.HOT_CORNER_ACTION = this.get('hotCornerAction', true);
- this.HOT_CORNER_POSITION = this.get('hotCornerPosition', true);
+ this.HOT_CORNER_ACTION = this.get('hotCornerAction');
+ this.HOT_CORNER_POSITION = this.get('hotCornerPosition');
if (this.HOT_CORNER_POSITION === 6 && this.DASH_VISIBLE)
this.HOT_CORNER_EDGE = true;
else
@@ -451,13 +510,24 @@ var Options = class Options {
else
this.HOT_CORNER_POSITION = 0;
}
- this.HOT_CORNER_FULLSCREEN = this.get('hotCornerFullscreen', true);
- this.HOT_CORNER_RIPPLES = this.get('hotCornerRipples', true);
+ this.HOT_CORNER_FULLSCREEN = this.get('hotCornerFullscreen');
+ this.HOT_CORNER_RIPPLES = this.get('hotCornerRipples');
+
+ this.ALWAYS_ACTIVATE_SELECTED_WINDOW = this.get('alwaysActivateSelectedWindow');
+ this.WIN_PREVIEW_SEC_BTN_ACTION = this.get('winPreviewSecBtnAction');
+ this.WIN_PREVIEW_MID_BTN_ACTION = this.get('winPreviewMidBtnAction');
+ this.SHOW_CLOSE_BUTTON = this.get('winPreviewShowCloseButton');
+ this.WINDOW_ICON_CLICK_ACTION = this.get('windowIconClickAction');
+
+ this.OVERLAY_KEY_PRIMARY = this.get('overlayKeyPrimary');
+ this.OVERLAY_KEY_SECONDARY = this.get('overlayKeySecondary');
+
+ this.ESC_BEHAVIOR = this.get('overviewEscBehavior');
- this.ALWAYS_ACTIVATE_SELECTED_WINDOW = this.get('alwaysActivateSelectedWindow', true);
- this.WINDOW_ICON_CLICK_SEARCH = this.get('windowIconClickSearch', true);
+ this.WINDOW_THUMBNAIL_ENABLED = this.get('windowThumbnailModule');
+ this.WINDOW_THUMBNAIL_SCALE = this.get('windowThumbnailScale') / 100;
- this.OVERLAY_KEY_SECONDARY = this.get('overlayKeySecondary', true);
+ this.FIX_NEW_WINDOW_FOCUS = this.get('newWindowFocusFix');
}
_getAnimationDirection() {
diff --git a/extensions/44/vertical-workspaces/lib/swipeTracker.js b/extensions/44/vertical-workspaces/lib/swipeTracker.js
index d9c3407..7122ead 100644
--- a/extensions/44/vertical-workspaces/lib/swipeTracker.js
+++ b/extensions/44/vertical-workspaces/lib/swipeTracker.js
@@ -10,61 +10,90 @@
'use strict';
-const { Clutter, GObject } = imports.gi;
+const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
+
const Main = imports.ui.main;
const SwipeTracker = imports.ui.swipeTracker;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-
+let Me;
let opt;
-let _firstRun = true;
-let _vwGestureUpdateId;
-let _originalGestureUpdateId;
+var SwipeTrackerModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('swipeTrackerModule', true);
- reset = reset || !moduleEnabled;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ }
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- _firstRun = false;
+ update(reset) {
+ this.moduleEnabled = opt.get('swipeTrackerModule');
+ const conflict = false;
- if (reset || !opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
- // original swipeTrackers' orientation and updateGesture function
- Main.overview._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
- Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
- Main.overview._swipeTracker._updateGesture = SwipeTracker.SwipeTracker.prototype._updateGesture;
- if (_vwGestureUpdateId) {
- Main.overview._swipeTracker._touchpadGesture.disconnect(_vwGestureUpdateId);
- _vwGestureUpdateId = 0;
+ reset = reset || !this.moduleEnabled || conflict;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
}
- if (_originalGestureUpdateId) {
- Main.overview._swipeTracker._touchpadGesture.unblock_signal_handler(_originalGestureUpdateId);
- _originalGestureUpdateId = 0;
+ if (reset && this._firstActivation)
+ console.debug(' SwipeTrackerModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
+ this._setVertical();
+ } else {
+ this._setHorizontal();
}
+ console.debug(' SwipeTrackerModule - Activated');
+ }
- opt = null;
- return;
+ _disableModule() {
+ this._setHorizontal();
+
+ console.debug(' SwipeTrackerModule - Disabled');
}
- if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
+ _setVertical() {
// reverse swipe gestures for enter/leave overview and ws switching
Main.overview._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
// overview's updateGesture() function should reflect ws tmb position to match appGrid/ws animation direction
// function in connection cannot be overridden in prototype of its class because connected is actually another copy of the original function
- if (!_originalGestureUpdateId) {
- _originalGestureUpdateId = GObject.signal_handler_find(Main.overview._swipeTracker._touchpadGesture, { signalId: 'update' });
- Main.overview._swipeTracker._touchpadGesture.block_signal_handler(_originalGestureUpdateId);
+ if (!this._originalGestureUpdateId) {
+ this._originalGestureUpdateId = GObject.signal_handler_find(Main.overview._swipeTracker._touchpadGesture, { signalId: 'update' });
+ Main.overview._swipeTracker._touchpadGesture.block_signal_handler(this._originalGestureUpdateId);
Main.overview._swipeTracker._updateGesture = SwipeTrackerVertical._updateGesture;
- _vwGestureUpdateId = Main.overview._swipeTracker._touchpadGesture.connect('update', SwipeTrackerVertical._updateGesture.bind(Main.overview._swipeTracker));
+ this._vwGestureUpdateId = Main.overview._swipeTracker._touchpadGesture.connect('update', SwipeTrackerVertical._updateGesture.bind(Main.overview._swipeTracker));
+ }
+ }
+
+ _setHorizontal() {
+ // original swipeTrackers' orientation and updateGesture function
+ Main.overview._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
+ Main.wm._workspaceAnimation._swipeTracker.orientation = Clutter.Orientation.HORIZONTAL;
+ Main.overview._swipeTracker._updateGesture = SwipeTracker.SwipeTracker.prototype._updateGesture;
+ if (this._vwGestureUpdateId) {
+ Main.overview._swipeTracker._touchpadGesture.disconnect(this._vwGestureUpdateId);
+ this._vwGestureUpdateId = 0;
+ }
+ if (this._originalGestureUpdateId) {
+ Main.overview._swipeTracker._touchpadGesture.unblock_signal_handler(this._originalGestureUpdateId);
+ this._originalGestureUpdateId = 0;
}
}
-}
+};
const SwipeTrackerVertical = {
_updateGesture(gesture, time, delta, distance) {
diff --git a/extensions/44/vertical-workspaces/lib/util.js b/extensions/44/vertical-workspaces/lib/util.js
index 5f5c069..9bc4365 100644
--- a/extensions/44/vertical-workspaces/lib/util.js
+++ b/extensions/44/vertical-workspaces/lib/util.js
@@ -10,16 +10,27 @@
'use strict';
+const Clutter = imports.gi.Clutter;
+const Meta = imports.gi.Meta;
const Gi = imports._gi;
-const { Shell, Meta, Clutter } = imports.gi;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Shell = imports.gi.Shell;
-const Config = imports.misc.config;
-const Main = imports.ui.main;
+const Main = imports.ui.main;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
+let Me;
-var shellVersion = parseFloat(Config.PACKAGE_VERSION);
+let _installedExtensions;
+
+function init(me) {
+ Me = me;
+}
+
+function cleanGlobals() {
+ Me = null;
+ _installedExtensions = null;
+}
var Overrides = class {
constructor() {
@@ -27,8 +38,13 @@ var Overrides = class {
}
addOverride(name, prototype, overrideList) {
+ const backup = this.overrideProto(prototype, overrideList, name);
+ // don't update originals when override's just refreshing, keep initial content
+ let originals = this._overrides[name]?.originals;
+ if (!originals)
+ originals = backup;
this._overrides[name] = {
- originals: this.overrideProto(prototype, overrideList),
+ originals,
prototype,
};
}
@@ -38,15 +54,15 @@ var Overrides = class {
if (!override)
return false;
- this.overrideProto(override.prototype, override.originals);
- this._overrides[name] = undefined;
+ this.overrideProto(override.prototype, override.originals, name);
+ delete this._overrides[name];
return true;
}
removeAll() {
for (let name in this._overrides) {
this.removeOverride(name);
- this._overrides[name] = undefined;
+ delete this._overrides[name];
}
}
@@ -54,13 +70,17 @@ var Overrides = class {
proto[Gi.hook_up_vfunc_symbol](symbol, func);
}
- overrideProto(proto, overrides) {
+ overrideProto(proto, overrides, name) {
const backup = {};
-
+ const originals = this._overrides[name]?.originals;
for (let symbol in overrides) {
if (symbol.startsWith('after_')) {
const actualSymbol = symbol.slice('after_'.length);
- const fn = proto[actualSymbol];
+ let fn;
+ if (originals && originals[actualSymbol])
+ fn = originals[actualSymbol];
+ else
+ fn = proto[actualSymbol];
const afterFn = overrides[symbol];
proto[actualSymbol] = function (...args) {
args = Array.prototype.slice.call(args);
@@ -72,11 +92,11 @@ var Overrides = class {
} else {
backup[symbol] = proto[symbol];
if (symbol.startsWith('vfunc')) {
- if (shellVersion < 42)
+ if (Me.shellVersion < 42)
this.hookVfunc(proto, symbol.slice(6), overrides[symbol]);
else
this.hookVfunc(proto[Gi.gobject_prototype_symbol], symbol.slice(6), overrides[symbol]);
- } else {
+ } else if (overrides[symbol] !== null) {
proto[symbol] = overrides[symbol];
}
}
@@ -85,87 +105,21 @@ var Overrides = class {
}
};
-function getOverviewTranslations(opt, dash, tmbBox, searchEntryBin) {
- // const tmbBox = Main.overview._overview._controls._thumbnailsBox;
- let searchTranslationY = 0;
- if (searchEntryBin.visible) {
- const offset = (dash.visible && (!opt.DASH_VERTICAL ? dash.height + 12 : 0)) +
- (opt.WS_TMB_TOP ? tmbBox.height + 12 : 0);
- searchTranslationY = -searchEntryBin.height - offset - 30;
- }
-
- let tmbTranslationX = 0;
- let tmbTranslationY = 0;
- let offset;
- if (tmbBox.visible) {
- switch (opt.WS_TMB_POSITION) {
- case 3: // left
- offset = 10 + (dash?.visible && opt.DASH_LEFT ? dash.width : 0);
- tmbTranslationX = -tmbBox.width - offset;
- tmbTranslationY = 0;
- break;
- case 1: // right
- offset = 10 + (dash?.visible && opt.DASH_RIGHT ? dash.width : 0);
- tmbTranslationX = tmbBox.width + offset;
- tmbTranslationY = 0;
- break;
- case 0: // top
- offset = 10 + (dash?.visible && opt.DASH_TOP ? dash.height : 0) + Main.panel.height;
- tmbTranslationX = 0;
- tmbTranslationY = -tmbBox.height - offset;
- break;
- case 2: // bottom
- offset = 10 + (dash?.visible && opt.DASH_BOTTOM ? dash.height : 0) + Main.panel.height; // just for case the panel is at bottom
- tmbTranslationX = 0;
- tmbTranslationY = tmbBox.height + offset;
- break;
- }
- }
-
- let dashTranslationX = 0;
- let dashTranslationY = 0;
- let position = opt.DASH_POSITION;
- // if DtD replaced the original Dash, read its position
- if (dashIsDashToDock())
- position = dash._position;
-
- if (dash?.visible) {
- switch (position) {
- case 0: // top
- dashTranslationX = 0;
- dashTranslationY = -dash.height - dash.margin_bottom - Main.panel.height;
- break;
- case 1: // right
- dashTranslationX = dash.width;
- dashTranslationY = 0;
- break;
- case 2: // bottom
- dashTranslationX = 0;
- dashTranslationY = dash.height + dash.margin_bottom + Main.panel.height;
- break;
- case 3: // left
- dashTranslationX = -dash.width;
- dashTranslationY = 0;
- break;
- }
- }
-
- return [tmbTranslationX, tmbTranslationY, dashTranslationX, dashTranslationY, searchTranslationY];
-}
-
-function openPreferences() {
+function openPreferences(metadata) {
+ if (!metadata)
+ metadata = Me.metadata;
const windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null);
let tracker = Shell.WindowTracker.get_default();
let metaWin, isVW = null;
for (let win of windows) {
const app = tracker.get_window_app(win);
- if (win.get_title().includes(Me.metadata.name) && app.get_name() === 'Extensions') {
+ if (win.get_title()?.includes(metadata.name) && app.get_name() === 'Extensions') {
// this is our existing window
metaWin = win;
isVW = true;
break;
- } else if (win.wm_class.includes('org.gnome.Shell.Extensions')) {
+ } else if (win.wm_class?.includes('org.gnome.Shell.Extensions')) {
// this is prefs window of another extension
metaWin = win;
isVW = false;
@@ -182,17 +136,20 @@ function openPreferences() {
}
if (!metaWin || (metaWin && !isVW)) {
- try {
- Main.extensionManager.openExtensionPrefs(Me.metadata.uuid, '', {});
- } catch (e) {
- log(e);
- }
+ GLib.idle_add(GLib.PRIORITY_LOW, () => {
+ try {
+ Main.extensionManager.openExtensionPrefs(metadata.uuid, '', {});
+ } catch (e) {
+ console.error(e);
+ }
+ });
}
}
function activateSearchProvider(prefix = '') {
const searchEntry = Main.overview.searchEntry;
- if (!searchEntry.get_text() || !searchEntry.get_text().startsWith(prefix)) {
+ const searchEntryText = searchEntry.get_text();
+ if (!searchEntryText || (searchEntryText && !searchEntry.get_text().startsWith(prefix))) {
prefix = `${prefix} `;
const position = prefix.length;
searchEntry.set_text(prefix);
@@ -220,9 +177,16 @@ function reorderWorkspace(direction = 0) {
global.workspace_manager.reorder_workspace(activeWs, targetIdx);
}
+function activateKeyboardForWorkspaceView() {
+ Main.ctrlAltTabManager._items.forEach(i => {
+ if (i.sortGroup === 1 && i.name === 'Windows')
+ Main.ctrlAltTabManager.focusGroup(i);
+ });
+}
+
function exposeWindows(adjustment, activateKeyboard) {
// expose windows for static overview modes
- if (!adjustment.value && !Main.overview._animationInProgress) {
+ if (!adjustment.value/* && !Main.overview._animationInProgress*/) {
if (adjustment.value === 0) {
adjustment.value = 0;
adjustment.ease(1, {
@@ -330,13 +294,48 @@ function isMoreRelevant(stringA, stringB, pattern) {
return !aAny && bAny;
}
-function getEnabledExtensions(uuid = '') {
- let extensions = [];
- Main.extensionManager._extensions.forEach(e => {
- if (e.state === 1 && e.uuid.includes(uuid))
- extensions.push(e);
- });
- return extensions;
+function getEnabledExtensions(pattern = '') {
+ let result = [];
+ // extensionManager is unreliable at startup (if not all extensions were loaded)
+ // but gsettings key can contain removed extensions...
+ // therefore we have to look into filesystem, what's really installed
+ if (!_installedExtensions) {
+ const extensionFiles = [...collectFromDatadirs('extensions', true)];
+ _installedExtensions = extensionFiles.map(({ info }) => {
+ let fileType = info.get_file_type();
+ if (fileType !== Gio.FileType.DIRECTORY)
+ return null;
+ const uuid = info.get_name();
+ return uuid;
+ });
+ }
+ const enabled = Main.extensionManager._enabledExtensions;
+ result = _installedExtensions.filter(ext => enabled.includes(ext));
+ return result.filter(uuid => uuid !== null && uuid.includes(pattern));
+}
+
+function* collectFromDatadirs(subdir, includeUserDir) {
+ let dataDirs = GLib.get_system_data_dirs();
+ if (includeUserDir)
+ dataDirs.unshift(GLib.get_user_data_dir());
+
+ for (let i = 0; i < dataDirs.length; i++) {
+ let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
+ let dir = Gio.File.new_for_path(path);
+
+ let fileEnum;
+ try {
+ fileEnum = dir.enumerate_children('standard::name,standard::type',
+ Gio.FileQueryInfoFlags.NONE, null);
+ } catch (e) {
+ fileEnum = null;
+ }
+ if (fileEnum !== null) {
+ let info;
+ while ((info = fileEnum.next_file(null)))
+ yield { dir: fileEnum.get_child(info), info };
+ }
+ }
}
function getScrollDirection(event) {
diff --git a/extensions/44/vertical-workspaces/lib/winTmb.js b/extensions/44/vertical-workspaces/lib/winTmb.js
new file mode 100644
index 0000000..b18ea18
--- /dev/null
+++ b/extensions/44/vertical-workspaces/lib/winTmb.js
@@ -0,0 +1,525 @@
+/**
+ * V-Shell (Vertical Workspaces)
+ * WinTmb
+ *
+ * @author GdH <G-dH@github.com>
+ * @copyright 2021-2023
+ * @license GPL-3.0
+ */
+
+'use strict';
+
+const Clutter = imports.gi.Clutter;
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Meta = imports.gi.Meta;
+const St = imports.gi.St;
+
+const AltTab = imports.ui.altTab;
+const DND = imports.ui.dnd;
+const Main = imports.ui.main;
+
+let Me;
+let opt;
+
+const SCROLL_ICON_OPACITY = 240;
+const DRAG_OPACITY = 200;
+const CLOSE_BTN_OPACITY = 240;
+
+
+var WinTmbModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ }
+
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
+
+ update(reset) {
+ this._removeTimeouts();
+
+ this.moduleEnabled = opt.get('windowThumbnailModule');
+
+ reset = reset || !this.moduleEnabled;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WinTmb - Keeping untouched');
+ }
+
+ _activateModule() {
+ this._timeouts = {};
+ if (!this._windowThumbnails)
+ this._windowThumbnails = [];
+
+ Main.overview.connectObject('hidden', () => this.showThumbnails(), this);
+ console.debug(' WinTmb - Activated');
+ }
+
+ _disableModule() {
+ Main.overview.disconnectObject(this);
+ this._disconnectStateAdjustment();
+ this.removeAllThumbnails();
+ console.debug(' WinTmb - Disabled');
+ }
+
+ _removeTimeouts() {
+ if (this._timeouts) {
+ Object.values(this._timeouts).forEach(t => {
+ if (t)
+ GLib.source_remove(t);
+ });
+ this._timeouts = null;
+ }
+ }
+
+ createThumbnail(metaWin) {
+ const thumbnail = new WindowThumbnail(metaWin, {
+ 'height': Math.floor(opt.WINDOW_THUMBNAIL_SCALE * global.display.get_monitor_geometry(global.display.get_current_monitor()).height),
+ 'thumbnailsOnScreen': this._windowThumbnails.length,
+ });
+
+ this._windowThumbnails.push(thumbnail);
+ thumbnail.connect('removed', tmb => {
+ this._windowThumbnails.splice(this._windowThumbnails.indexOf(tmb), 1);
+ tmb.destroy();
+ if (!this._windowThumbnails.length)
+ this._disconnectStateAdjustment();
+ });
+
+ if (!this._stateAdjustmentConId) {
+ this._stateAdjustmentConId = Main.overview._overview.controls._stateAdjustment.connectObject('notify::value', () => {
+ if (!this._thumbnailsHidden && (!opt.OVERVIEW_MODE2 || opt.WORKSPACE_MODE))
+ this.hideThumbnails();
+ }, this);
+ }
+ }
+
+ hideThumbnails() {
+ this._windowThumbnails.forEach(tmb => {
+ tmb.ease({
+ opacity: 0,
+ duration: 200,
+ mode: Clutter.AnimationMode.LINEAR,
+ onComplete: () => tmb.hide(),
+ });
+ });
+ this._thumbnailsHidden = true;
+ }
+
+ showThumbnails() {
+ this._windowThumbnails.forEach(tmb => {
+ tmb.show();
+ tmb.ease({
+ opacity: 255,
+ duration: 100,
+ mode: Clutter.AnimationMode.LINEAR,
+ });
+ });
+ this._thumbnailsHidden = false;
+ }
+
+ removeAllThumbnails() {
+ this._windowThumbnails.forEach(tmb => tmb.remove());
+ this._windowThumbnails = [];
+ }
+
+ _disconnectStateAdjustment() {
+ Main.overview._overview.controls._stateAdjustment.disconnectObject(this);
+ }
+};
+
+const WindowThumbnail = GObject.registerClass({
+ Signals: { 'removed': {} },
+}, class WindowThumbnail extends St.Widget {
+ _init(metaWin, args) {
+ this._hoverShowsPreview = false;
+ this._customOpacity = 255;
+ this._initTmbHeight = args.height;
+ this._minimumHeight = Math.floor(5 / 100 * global.display.get_monitor_geometry(global.display.get_current_monitor()).height);
+ this._scrollTimeout = 100;
+ this._positionOffset = args.thumbnailsOnScreen;
+ this._reverseTmbWheelFunc = false;
+ this._click_count = 1;
+ this._prevBtnPressTime = 0;
+ this.w = metaWin;
+ super._init({
+ layout_manager: new Clutter.BinLayout(),
+ visible: true,
+ reactive: true,
+ can_focus: true,
+ track_hover: true,
+ });
+ this.connect('button-release-event', this._onBtnReleased.bind(this));
+ this.connect('scroll-event', this._onScrollEvent.bind(this));
+ // this.connect('motion-event', this._onMouseMove.bind(this)); // may be useful in the future..
+
+ this._delegate = this;
+ this._draggable = DND.makeDraggable(this, { dragActorOpacity: DRAG_OPACITY });
+ this._draggable.connect('drag-end', this._end_drag.bind(this));
+ this._draggable.connect('drag-cancelled', this._end_drag.bind(this));
+ this._draggable._animateDragEnd = eventTime => {
+ this._draggable._animationInProgress = true;
+ this._draggable._onAnimationComplete(this._draggable._dragActor, eventTime);
+ this.opacity = this._customOpacity;
+ };
+
+ this.clone = new Clutter.Clone({ reactive: true });
+ Main.layoutManager.addChrome(this);
+
+ this.window = this.w.get_compositor_private();
+
+ this.clone.set_source(this.window);
+
+ this.add_child(this.clone);
+ this._addCloseButton();
+ this._addScrollModeIcon();
+
+ this.connect('enter-event', () => {
+ global.display.set_cursor(Meta.Cursor.POINTING_HAND);
+ this._closeButton.opacity = CLOSE_BTN_OPACITY;
+ this._scrollModeBin.opacity = SCROLL_ICON_OPACITY;
+ if (this._hoverShowsPreview && !Main.overview._shown) {
+ this._closeButton.opacity = 50;
+ this._showWindowPreview(false, true);
+ }
+ });
+
+ this.connect('leave-event', () => {
+ global.display.set_cursor(Meta.Cursor.DEFAULT);
+ this._closeButton.opacity = 0;
+ this._scrollModeBin.opacity = 0;
+ if (this._winPreview)
+ this._destroyWindowPreview();
+ });
+
+ this._setSize(true);
+ this.set_position(...this._getInitialPosition());
+ this.show();
+ this.window_id = this.w.get_id();
+ this.tmbRedrawDirection = true;
+
+ // remove thumbnail content and hide thumbnail if its window is destroyed
+ this.windowConnect = this.window.connect('destroy', () => {
+ if (this)
+ this.remove();
+ });
+ }
+
+ _getInitialPosition() {
+ const offset = 20;
+ let monitor = Main.layoutManager.monitors[global.display.get_current_monitor()];
+ let x = Math.min(monitor.x + monitor.width - (this.window.width * this.scale) - offset);
+ let y = Math.min(monitor.y + monitor.height - (this.window.height * this.scale) - offset - ((this._positionOffset * this._initTmbHeight) % (monitor.height - this._initTmbHeight)));
+ return [x, y];
+ }
+
+ _setSize(resetScale = false) {
+ if (resetScale)
+ this.scale = Math.min(1.0, this._initTmbHeight / this.window.height);
+
+ const width = this.window.width * this.scale;
+ const height = this.window.height * this.scale;
+ this.set_size(width, height);
+ if (this.icon) {
+ this.icon.scale_x = this.scale;
+ this.icon.scale_y = this.scale;
+ }
+
+ // when the scale of this. actor change, this.clone resize accordingly,
+ // but the reactive area of the actor doesn't change until the actor is redrawn
+ // this updates the actor's input region area:
+ Main.layoutManager._queueUpdateRegions();
+ }
+
+ /* _onMouseMove(actor, event) {
+ let [pos_x, pos_y] = event.get_coords();
+ let state = event.get_state();
+ if (this._ctrlPressed(state)) {
+ }
+ }*/
+
+ _onBtnReleased(actor, event) {
+ // Clutter.Event.click_count property in no longer available, since GS42
+ if ((event.get_time() - this._prevBtnPressTime) < Clutter.Settings.get_default().double_click_time)
+ this._click_count += 1;
+ else
+ this._click_count = 1;
+
+ this._prevBtnPressTime = event.get_time();
+
+ if (this._click_count === 2 && event.get_button() === Clutter.BUTTON_PRIMARY)
+ this.w.activate(global.get_current_time());
+
+
+ const button = event.get_button();
+ const state = event.get_state();
+ switch (button) {
+ case Clutter.BUTTON_PRIMARY:
+ if (this._ctrlPressed(state)) {
+ this._setSize();
+ } else {
+ this._reverseTmbWheelFunc = !this._reverseTmbWheelFunc;
+ this._scrollModeBin.set_child(this._reverseTmbWheelFunc ? this._scrollModeSourceIcon : this._scrollModeResizeIcon);
+ }
+ return Clutter.EVENT_STOP;
+ case Clutter.BUTTON_SECONDARY:
+ if (this._ctrlPressed(state)) {
+ this.remove();
+ } else {
+ this._hoverShowsPreview = !this._hoverShowsPreview;
+ this._showWindowPreview();
+ }
+ return Clutter.EVENT_STOP;
+ case Clutter.BUTTON_MIDDLE:
+ if (this._ctrlPressed(state))
+ this.w.delete(global.get_current_time());
+ return Clutter.EVENT_STOP;
+ default:
+ return Clutter.EVENT_PROPAGATE;
+ }
+ }
+
+ _onScrollEvent(actor, event) {
+ let direction = Me.Util.getScrollDirection(event);
+
+ if (this._actionTimeoutActive())
+ return Clutter.EVENT_PROPAGATE;
+ let state = event.get_state();
+ switch (direction) {
+ case Clutter.ScrollDirection.UP:
+ if (this._shiftPressed(state)) {
+ this.opacity = Math.min(255, this.opacity + 24);
+ this._customOpacity = this.opacity;
+ } else if (this._reverseTmbWheelFunc !== this._ctrlPressed(state)) {
+ this._switchSourceWin(-1);
+ } else if (this._reverseTmbWheelFunc === this._ctrlPressed(state)) {
+ this.scale = Math.max(0.05, this.scale - 0.025);
+ }
+ break;
+ case Clutter.ScrollDirection.DOWN:
+ if (this._shiftPressed(state)) {
+ this.opacity = Math.max(48, this.opacity - 24);
+ this._customOpacity = this.opacity;
+ } else if (this._reverseTmbWheelFunc !== this._ctrlPressed(state)) {
+ this._switchSourceWin(+1);
+ } else if (this._reverseTmbWheelFunc === this._ctrlPressed(state)) {
+ this.scale = Math.min(1, this.scale + 0.025);
+ }
+ break;
+ default:
+ return Clutter.EVENT_PROPAGATE;
+ }
+ this._setSize();
+ return Clutter.EVENT_STOP;
+ }
+
+ remove() {
+ if (this.clone) {
+ this.window.disconnect(this.windowConnect);
+ this.clone.set_source(null);
+ }
+ if (this._winPreview)
+ this._destroyWindowPreview();
+
+ this.emit('removed');
+ }
+
+ _end_drag() {
+ this.set_position(this._draggable._dragOffsetX + this._draggable._dragX, this._draggable._dragOffsetY + this._draggable._dragY);
+ this._setSize();
+ }
+
+ _ctrlPressed(state) {
+ return (state & Clutter.ModifierType.CONTROL_MASK) !== 0;
+ }
+
+ _shiftPressed(state) {
+ return (state & Clutter.ModifierType.SHIFT_MASK) !== 0;
+ }
+
+ _switchSourceWin(direction) {
+ let windows = global.display.get_tab_list(Meta.TabList.NORMAL_ALL, null);
+ windows = windows.filter(w => !(w.skip_taskbar || w.minimized));
+ let idx = -1;
+ for (let i = 0; i < windows.length; i++) {
+ if (windows[i] === this.w) {
+ idx = i + direction;
+ break;
+ }
+ }
+ idx = idx >= windows.length ? 0 : idx;
+ idx = idx < 0 ? windows.length - 1 : idx;
+ let w = windows[idx];
+ let win = w.get_compositor_private();
+ this.clone.set_source(win);
+ this.window.disconnect(this.windowConnect);
+ // the new thumbnail should be the same height as the previous one
+ this.scale = (this.scale * this.window.height) / win.height;
+ this.window = win;
+ this.windowConnect = this.window.connect('destroy', () => {
+ if (this)
+ this.remove();
+ });
+ this.w = w;
+
+ if (this._winPreview)
+ this._showWindowPreview(true);
+ }
+
+ _actionTimeoutActive() {
+ const timeout = this._reverseTmbWheelFunc ? this._scrollTimeout : this._scrollTimeout / 4;
+ if (!this._lastActionTime || Date.now() - this._lastActionTime > timeout) {
+ this._lastActionTime = Date.now();
+ return false;
+ }
+ return true;
+ }
+
+ /* _setIcon() {
+ let tracker = Shell.WindowTracker.get_default();
+ let app = tracker.get_window_app(this.w);
+ let icon = app
+ ? app.create_icon_texture(this.height)
+ : new St.Icon({ icon_name: 'icon-missing', icon_size: this.height });
+ icon.x_expand = icon.y_expand = true;
+ if (this.icon)
+ this.icon.destroy();
+ this.icon = icon;
+ }*/
+
+ _addCloseButton() {
+ const closeButton = new St.Button({
+ opacity: 0,
+ style_class: 'window-close',
+ child: new St.Icon({ icon_name: 'preview-close-symbolic' }),
+ x_align: Clutter.ActorAlign.END,
+ y_align: Clutter.ActorAlign.START,
+ x_expand: true,
+ y_expand: true,
+ });
+
+ closeButton.set_style(`
+ margin: 3px;
+ background-color: rgba(200, 0, 0, 0.9);
+ `);
+
+ closeButton.connect('clicked', () => {
+ this.remove();
+ return Clutter.EVENT_STOP;
+ });
+
+ this._closeButton = closeButton;
+ this.add_child(this._closeButton);
+ }
+
+ _addScrollModeIcon() {
+ this._scrollModeBin = new St.Bin({
+ x_expand: true,
+ y_expand: true,
+ });
+ this._scrollModeResizeIcon = new St.Icon({
+ icon_name: 'view-fullscreen-symbolic',
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.END,
+ x_expand: true,
+ y_expand: true,
+ opacity: SCROLL_ICON_OPACITY,
+ style_class: 'icon-dropshadow',
+ scale_x: 0.5,
+ scale_y: 0.5,
+ });
+ this._scrollModeResizeIcon.set_style(`
+ margin: 13px;
+ color: rgb(255, 255, 255);
+ box-shadow: 0 0 40px 40px rgba(0,0,0,0.7);
+ `);
+ this._scrollModeSourceIcon = new St.Icon({
+ icon_name: 'media-skip-forward-symbolic',
+ x_align: Clutter.ActorAlign.CENTER,
+ y_align: Clutter.ActorAlign.END,
+ x_expand: true,
+ y_expand: true,
+ opacity: SCROLL_ICON_OPACITY,
+ style_class: 'icon-dropshadow',
+ scale_x: 0.5,
+ scale_y: 0.5,
+ });
+ this._scrollModeSourceIcon.set_style(`
+ margin: 13px;
+ color: rgb(255, 255, 255);
+ box-shadow: 0 0 40px 40px rgba(0,0,0,0.7);
+ `);
+ this._scrollModeBin.set_child(this._scrollModeResizeIcon);
+ this.add_child(this._scrollModeBin);
+ this._scrollModeBin.opacity = 0;
+ }
+
+ _showWindowPreview(update = false, dontDestroy = false) {
+ if (this._winPreview && !dontDestroy) {
+ this._destroyWindowPreview();
+ this._previewCreationTime = 0;
+ this._closeButton.opacity = CLOSE_BTN_OPACITY;
+ if (!update)
+ return;
+ }
+
+ if (!this._winPreview) {
+ this._winPreview = new AltTab.CyclerHighlight();
+ global.window_group.add_actor(this._winPreview);
+ [this._winPreview._xPointer, this._winPreview._yPointer] = global.get_pointer();
+ }
+
+ if (!update) {
+ this._winPreview.opacity = 0;
+ this._winPreview.ease({
+ opacity: 255,
+ duration: 70,
+ mode: Clutter.AnimationMode.LINEAR,
+ /* onComplete: () => {
+ this._closeButton.opacity = 50;
+ },*/
+ });
+
+ this.ease({
+ opacity: Math.min(50, this._customOpacity),
+ duration: 70,
+ mode: Clutter.AnimationMode.LINEAR,
+ onComplete: () => {
+ },
+ });
+ } else {
+ this._winPreview.opacity = 255;
+ }
+ this._winPreview.window = this.w;
+ this._winPreview._window = this.w;
+ global.window_group.set_child_above_sibling(this._winPreview, null);
+ }
+
+ _destroyWindowPreview() {
+ if (this._winPreview) {
+ this._winPreview.ease({
+ opacity: 0,
+ duration: 100,
+ mode: Clutter.AnimationMode.LINEAR,
+ onComplete: () => {
+ this._winPreview.destroy();
+ this._winPreview = null;
+ this.opacity = this._customOpacity;
+ },
+ });
+ }
+ }
+});
diff --git a/extensions/44/vertical-workspaces/lib/windowAttentionHandler.js b/extensions/44/vertical-workspaces/lib/windowAttentionHandler.js
index 10703c2..a3db986 100644
--- a/extensions/44/vertical-workspaces/lib/windowAttentionHandler.js
+++ b/extensions/44/vertical-workspaces/lib/windowAttentionHandler.js
@@ -11,47 +11,69 @@
'use strict';
const Main = imports.ui.main;
-const WindowAttentionHandler = imports.ui.windowAttentionHandler;
const MessageTray = imports.ui.messageTray;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-const _Util = Me.imports.lib.util;
+const WindowAttentionHandler = imports.ui.windowAttentionHandler;
+let Me;
let opt;
-let _firstRun = false;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('winAttentionHandlerModule', true);
- reset = reset || !moduleEnabled;
+var WindowAttentionHandlerModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- if (_firstRun && reset)
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
- _firstRun = false;
- if (reset) {
- reset = true;
- _updateConnections(reset);
+ cleanGlobals() {
+ Me = null;
opt = null;
- return;
}
- _updateConnections();
-}
+ update(reset) {
+ this.moduleEnabled = opt.get('windowAttentionHandlerModule');
+ const conflict = false;
-function _updateConnections(reset) {
- global.display.disconnectObject(Main.windowAttentionHandler);
+ reset = reset || !this.moduleEnabled || conflict;
- const handlerFnc = reset
- ? Main.windowAttentionHandler._onWindowDemandsAttention
- : WindowAttentionHandlerCommon._onWindowDemandsAttention;
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WindowAttentionHandlerModule - Keeping untouched');
+ }
+
+ _activateModule() {
+ this._updateConnections();
+ console.debug(' WindowAttentionHandlerModule - Activated');
+ }
- global.display.connectObject(
- 'window-demands-attention', handlerFnc.bind(Main.windowAttentionHandler),
- 'window-marked-urgent', handlerFnc.bind(Main.windowAttentionHandler),
- Main.windowAttentionHandler);
-}
+ _disableModule() {
+ const reset = true;
+ this._updateConnections(reset);
+
+ console.debug(' WindowAttentionHandlerModule - Disabled');
+ }
+
+ _updateConnections(reset) {
+ global.display.disconnectObject(Main.windowAttentionHandler);
+
+ const handlerFnc = reset
+ ? Main.windowAttentionHandler._onWindowDemandsAttention
+ : WindowAttentionHandlerCommon._onWindowDemandsAttention;
+
+ global.display.connectObject(
+ 'window-demands-attention', handlerFnc.bind(Main.windowAttentionHandler),
+ 'window-marked-urgent', handlerFnc.bind(Main.windowAttentionHandler),
+ Main.windowAttentionHandler);
+ }
+};
const WindowAttentionHandlerCommon = {
_onWindowDemandsAttention(display, window) {
diff --git a/extensions/44/vertical-workspaces/lib/windowManager.js b/extensions/44/vertical-workspaces/lib/windowManager.js
index 2d46b0b..0cae6aa 100644
--- a/extensions/44/vertical-workspaces/lib/windowManager.js
+++ b/extensions/44/vertical-workspaces/lib/windowManager.js
@@ -10,81 +10,101 @@
'use strict';
-const { GObject, Clutter, Meta } = imports.gi;
+const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
+const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const WindowManager = imports.ui.windowManager;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-let _overrides;
-
-const MINIMIZE_WINDOW_ANIMATION_TIME = WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME;
-const MINIMIZE_WINDOW_ANIMATION_MODE = WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE;
+let Me;
let opt;
-let _firstRun = true;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('windowManagerModule', true);
- reset = reset || !moduleEnabled;
+var WindowManagerModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
- _firstRun = false;
+ this._originalMinimizeSigId = 0;
+ this._minimizeSigId = 0;
+ this._originalUnminimizeSigId = 0;
+ this._unminimizeSigId = 0;
+ }
- if (_overrides)
- _overrides.removeAll();
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
+ update(reset) {
+ this.moduleEnabled = opt.get('windowManagerModule');
+ const conflict = false;
- _replaceMinimizeFunction(reset);
+ reset = reset || !this.moduleEnabled || conflict;
+ // don't even touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WindowManagerModule - Keeping untouched');
+ }
- if (reset) {
- _overrides = null;
- opt = null;
- return;
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+
+ this._overrides.addOverride('WindowManager', WindowManager.WindowManager.prototype, WindowManagerCommon);
+
+ if (!this._minimizeSigId) {
+ this._originalMinimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'minimize' });
+ if (this._originalMinimizeSigId) {
+ Main.wm._shellwm.block_signal_handler(this._originalMinimizeSigId);
+ this._minimizeSigId = Main.wm._shellwm.connect('minimize', WindowManagerCommon._minimizeWindow.bind(Main.wm));
+ }
+
+ this._originalUnminimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'unminimize' });
+ if (this._originalUnminimizeSigId) {
+ Main.wm._shellwm.block_signal_handler(this._originalUnminimizeSigId);
+ this._unminimizeSigId = Main.wm._shellwm.connect('unminimize', WindowManagerCommon._unminimizeWindow.bind(Main.wm));
+ }
+ }
+ console.debug(' WindowManagerModule - Activated');
}
- _overrides = new _Util.Overrides();
-
- _overrides.addOverride('WindowManager', WindowManager.WindowManager.prototype, WindowManagerCommon);
-}
-
-// ------------- Fix and adapt minimize/unminimize animations --------------------------------------
-
-let _originalMinimizeSigId;
-let _minimizeSigId;
-let _originalUnminimizeSigId;
-let _unminimizeSigId;
-
-function _replaceMinimizeFunction(reset = false) {
- if (reset) {
- Main.wm._shellwm.disconnect(_minimizeSigId);
- _minimizeSigId = 0;
- Main.wm._shellwm.unblock_signal_handler(_originalMinimizeSigId);
- _originalMinimizeSigId = 0;
-
- Main.wm._shellwm.disconnect(_unminimizeSigId);
- _unminimizeSigId = 0;
- Main.wm._shellwm.unblock_signal_handler(_originalUnminimizeSigId);
- _originalUnminimizeSigId = 0;
- } else if (!_minimizeSigId) {
- _originalMinimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'minimize' });
- if (_originalMinimizeSigId) {
- Main.wm._shellwm.block_signal_handler(_originalMinimizeSigId);
- _minimizeSigId = Main.wm._shellwm.connect('minimize', WindowManagerCommon._minimizeWindow.bind(Main.wm));
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ if (this._minimizeSigId) {
+ Main.wm._shellwm.disconnect(this._minimizeSigId);
+ this._minimizeSigId = 0;
+ }
+ if (this._originalMinimizeSigId) {
+ Main.wm._shellwm.unblock_signal_handler(this._originalMinimizeSigId);
+ this._originalMinimizeSigId = 0;
}
- _originalUnminimizeSigId = GObject.signal_handler_find(Main.wm._shellwm, { signalId: 'unminimize' });
- if (_originalUnminimizeSigId) {
- Main.wm._shellwm.block_signal_handler(_originalUnminimizeSigId);
- _unminimizeSigId = Main.wm._shellwm.connect('unminimize', WindowManagerCommon._unminimizeWindow.bind(Main.wm));
+ if (this._unminimizeSigId) {
+ Main.wm._shellwm.disconnect(this._unminimizeSigId);
+ this._unminimizeSigId = 0;
+ }
+ if (this._originalUnminimizeSigId) {
+ Main.wm._shellwm.unblock_signal_handler(this._originalUnminimizeSigId);
+ this._originalUnminimizeSigId = 0;
}
+
+ console.debug(' WindowManagerModule - Disabled');
}
-}
+};
// fix for mainstream bug - fullscreen windows should minimize using opacity transition
// but its being applied directly on window actor and that doesn't work
@@ -109,8 +129,8 @@ const WindowManagerCommon = {
/* if (actor.meta_window.is_monitor_sized()) {
actor.get_first_child().ease({
opacity: 0,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
+ duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
+ mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._minimizeWindowDone(shellwm, actor),
});
} else { */
@@ -140,8 +160,8 @@ const WindowManagerCommon = {
scale_y: yScale,
x: xDest,
y: yDest,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
+ duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
+ mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._minimizeWindowDone(shellwm, actor),
});
// }
@@ -176,8 +196,8 @@ const WindowManagerCommon = {
actor.set_scale(1.0, 1.0);
actor.ease({
opacity: 255,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
+ duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
+ mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._unminimizeWindowDone(shellwm, actor),
});
} else { */
@@ -208,8 +228,8 @@ const WindowManagerCommon = {
scale_y: 1,
x: xDest,
y: yDest,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
+ duration: WindowManager.MINIMIZE_WINDOW_ANIMATION_TIME,
+ mode: WindowManager.MINIMIZE_WINDOW_ANIMATION_MODE,
onStopped: () => this._unminimizeWindowDone(shellwm, actor),
});
// }
diff --git a/extensions/44/vertical-workspaces/lib/windowPreview.js b/extensions/44/vertical-workspaces/lib/windowPreview.js
index 5d2bd61..2766138 100644
--- a/extensions/44/vertical-workspaces/lib/windowPreview.js
+++ b/extensions/44/vertical-workspaces/lib/windowPreview.js
@@ -10,103 +10,372 @@
'use strict';
-const { Clutter, GLib, GObject, Graphene, Meta, Shell, St } = imports.gi;
-
+const Clutter = imports.gi.Clutter;
+const Atk = imports.gi.Atk;
+const GLib = imports.gi.GLib;
+const Graphene = imports.gi.Graphene;
+const Meta = imports.gi.Meta;
+const Pango = imports.gi.Pango;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const DND = imports.ui.dnd;
const Main = imports.ui.main;
+const OverviewControls = imports.ui.overviewControls;
const WindowPreview = imports.ui.windowPreview;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-const _Util = Me.imports.lib.util;
-const shellVersion = _Util.shellVersion;
+let Me;
+let opt;
-let _overrides;
+const WINDOW_SCALE_TIME = 200;
+const WINDOW_ACTIVE_SIZE_INC = 5;
+const WINDOW_OVERLAY_FADE_TIME = 200;
+const WINDOW_DND_SIZE = 256;
+const DRAGGING_WINDOW_OPACITY = 100;
-const WINDOW_SCALE_TIME = imports.ui.windowPreview.WINDOW_SCALE_TIME;
-const WINDOW_ACTIVE_SIZE_INC = imports.ui.windowPreview.WINDOW_ACTIVE_SIZE_INC;
-const WINDOW_OVERLAY_FADE_TIME = imports.ui.windowPreview.WINDOW_OVERLAY_FADE_TIME;
-const SEARCH_WINDOWS_PREFIX = Me.imports.lib.windowSearchProvider.prefix;
+const ControlsState = OverviewControls.ControlsState;
-const ControlsState = imports.ui.overviewControls.ControlsState;
+var WindowPreviewModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
-let opt;
-let _firstRun = true;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('windowPreviewModule', true);
- reset = reset || !moduleEnabled;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ update(reset) {
+ this.moduleEnabled = opt.get('windowPreviewModule');
+ const conflict = false;
- _firstRun = false;
+ reset = reset || !this.moduleEnabled || conflict;
- if (_overrides)
- _overrides.removeAll();
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WindowPreviewModule - Keeping untouched');
+ }
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- if (reset) {
- _overrides = null;
- opt = null;
- WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
- return;
+ this._overrides.addOverride('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewCommon);
+ // A shorter timeout allows user to quickly cancel the selection by leaving the preview with the mouse pointer
+ if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
+ WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 150;
+ console.debug(' WindowPreviewModule - Activated');
}
- _overrides = new _Util.Overrides();
+ _disableModule() {
+ // If WindowPreview._init was injected by another extension (like Burn My Windows)
+ // which enables/disables before V-Shell
+ // don't restore the original if it's not injected,
+ // because it would restore injected _init and recursion would freeze GS when extensions are enabled again.
+ // This can happen when all extension re-enabled, not only when screen is locked/unlocked
+ // If _init doesn't include "fn.apply(this, args)" when reset === true, some extension already restored the original
+ const skipReset = WindowPreview.WindowPreview.prototype._init.toString().includes('fn.apply(this, args)');
+ if (this._overrides && skipReset) {
+ // skip restoring original _init()
+ this._overrides['_init'] = null;
+ }
+
+ if (this._overrides)
+ this._overrides.removeAll();
- _overrides.addOverride('WindowPreview', WindowPreview.WindowPreview.prototype, WindowPreviewCommon);
- // A shorter timeout allows user to quickly cancel the selection by leaving the preview with the mouse pointer
- if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
- WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 150;
-}
+ this._overrides = null;
+
+ console.debug(' WindowPreviewModule - Disabled');
+ }
+};
const WindowPreviewCommon = {
- // injection to _init()
- after__init() {
+ _init(metaWindow, workspace, overviewAdjustment) {
+ this.metaWindow = metaWindow;
+ this.metaWindow._delegate = this;
+ this._windowActor = metaWindow.get_compositor_private();
+ this._workspace = workspace;
+ this._overviewAdjustment = overviewAdjustment;
+
+ const ICON_SIZE = opt.WIN_PREVIEW_ICON_SIZE;
const ICON_OVERLAP = 0.7;
- if (opt.WIN_PREVIEW_ICON_SIZE < 64) {
- this.remove_child(this._icon);
- this._icon.destroy();
- const tracker = Shell.WindowTracker.get_default();
- const app = tracker.get_window_app(this.metaWindow);
- this._icon = app.create_icon_texture(opt.WIN_PREVIEW_ICON_SIZE);
- this._icon.add_style_class_name('icon-dropshadow');
- this._icon.set({
- reactive: true,
- pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ Shell.WindowPreview.prototype._init.bind(this)({
+ reactive: true,
+ can_focus: true,
+ accessible_role: Atk.Role.PUSH_BUTTON,
+ offscreen_redirect: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY,
+ });
+
+ const windowContainer = new Clutter.Actor({
+ pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ });
+ this.window_container = windowContainer;
+
+ windowContainer.connect('notify::scale-x',
+ () => this._adjustOverlayOffsets());
+ // gjs currently can't handle setting an actors layout manager during
+ // the initialization of the actor if that layout manager keeps track
+ // of its container, so set the layout manager after creating the
+ // container
+ windowContainer.layout_manager = new Shell.WindowPreviewLayout();
+ this.add_child(windowContainer);
+
+ this._addWindow(metaWindow);
+
+ this._delegate = this;
+
+ this._stackAbove = null;
+
+ this._cachedBoundingBox = {
+ x: windowContainer.layout_manager.bounding_box.x1,
+ y: windowContainer.layout_manager.bounding_box.y1,
+ width: windowContainer.layout_manager.bounding_box.get_width(),
+ height: windowContainer.layout_manager.bounding_box.get_height(),
+ };
+
+ windowContainer.layout_manager.connect(
+ 'notify::bounding-box', layout => {
+ this._cachedBoundingBox = {
+ x: layout.bounding_box.x1,
+ y: layout.bounding_box.y1,
+ width: layout.bounding_box.get_width(),
+ height: layout.bounding_box.get_height(),
+ };
+
+ // A bounding box of 0x0 means all windows were removed
+ if (layout.bounding_box.get_area() > 0)
+ this.emit('size-changed');
});
- this._icon.add_constraint(new Clutter.BindConstraint({
- source: this.windowContainer,
- coordinate: Clutter.BindCoordinate.POSITION,
- }));
- this._icon.add_constraint(new Clutter.AlignConstraint({
- source: this.windowContainer,
- align_axis: Clutter.AlignAxis.X_AXIS,
- factor: 0.5,
- }));
- this._icon.add_constraint(new Clutter.AlignConstraint({
- source: this.windowContainer,
- align_axis: Clutter.AlignAxis.Y_AXIS,
- pivot_point: new Graphene.Point({ x: -1, y: ICON_OVERLAP }),
- factor: 1,
- }));
- this.add_child(this._icon);
- if (opt.WIN_PREVIEW_ICON_SIZE < 22) {
- // disable app icon
- this._icon.hide();
+
+ this._windowActor.connectObject('destroy', () => this.destroy(), this);
+
+ this._updateAttachedDialogs();
+
+ let clickAction = new Clutter.ClickAction();
+ clickAction.connect('clicked', act => {
+ const button = act.get_button();
+ if (button === Clutter.BUTTON_SECONDARY) {
+ if (opt.WIN_PREVIEW_SEC_BTN_ACTION === 1) {
+ this._closeWinAction();
+ return Clutter.EVENT_STOP;
+ } else if (opt.WIN_PREVIEW_SEC_BTN_ACTION === 2) {
+ this._searchAppWindowsAction();
+ return Clutter.EVENT_STOP;
+ } else if (opt.WIN_PREVIEW_SEC_BTN_ACTION === 3 && opt.WINDOW_THUMBNAIL_ENABLED) {
+ this._removeLaters();
+ Me.Modules.winTmbModule.createThumbnail(metaWindow);
+ return Clutter.EVENT_STOP;
+ }
+ } else if (button === Clutter.BUTTON_MIDDLE) {
+ if (opt.WIN_PREVIEW_MID_BTN_ACTION === 1) {
+ this._closeWinAction();
+ return Clutter.EVENT_STOP;
+ } else if (opt.WIN_PREVIEW_MID_BTN_ACTION === 2) {
+ this._searchAppWindowsAction();
+ return Clutter.EVENT_STOP;
+ } else if (opt.WIN_PREVIEW_MID_BTN_ACTION === 3 && opt.WINDOW_THUMBNAIL_ENABLED) {
+ this._removeLaters();
+ Me.Modules.winTmbModule.createThumbnail(metaWindow);
+ return Clutter.EVENT_STOP;
+ }
}
- this._iconSize = opt.WIN_PREVIEW_ICON_SIZE;
+ return this._activate();
+ });
+
+
+ if (this._onLongPress) {
+ clickAction.connect('long-press', this._onLongPress.bind(this));
+ } else {
+ clickAction.connect('long-press', (action, actor, state) => {
+ if (state === Clutter.LongPressState.ACTIVATE)
+ this.showOverlay(true);
+ return true;
+ });
}
+ this.connect('destroy', this._onDestroy.bind(this));
+
+ this._draggable = DND.makeDraggable(this, {
+ restoreOnSuccess: true,
+ manualMode: !!this._onLongPress,
+ dragActorMaxSize: WINDOW_DND_SIZE,
+ dragActorOpacity: DRAGGING_WINDOW_OPACITY,
+ });
+
+ // _draggable.addClickAction is new in GS45
+ if (this._draggable.addClickAction)
+ this._draggable.addClickAction(clickAction);
+ else
+ this.add_action(clickAction);
+
+ this._draggable.connect('drag-begin', this._onDragBegin.bind(this));
+ this._draggable.connect('drag-cancelled', this._onDragCancelled.bind(this));
+ this._draggable.connect('drag-end', this._onDragEnd.bind(this));
+ this.inDrag = false;
+
+ this._selected = false;
+ this._overlayEnabled = true;
+ this._overlayShown = false;
+ this._closeRequested = false;
+ this._idleHideOverlayId = 0;
+
+ const tracker = Shell.WindowTracker.get_default();
+ const app = tracker.get_window_app(this.metaWindow);
+ this._icon = app.create_icon_texture(ICON_SIZE);
+ this._icon.add_style_class_name('icon-dropshadow');
+ this._icon.set({
+ reactive: true,
+ pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
+ });
+ this._icon.add_constraint(new Clutter.BindConstraint({
+ source: windowContainer,
+ coordinate: Clutter.BindCoordinate.POSITION,
+ }));
+ this._icon.add_constraint(new Clutter.AlignConstraint({
+ source: windowContainer,
+ align_axis: Clutter.AlignAxis.X_AXIS,
+ factor: 0.5,
+ }));
+ this._icon.add_constraint(new Clutter.AlignConstraint({
+ source: windowContainer,
+ align_axis: Clutter.AlignAxis.Y_AXIS,
+ pivot_point: new Graphene.Point({ x: -1, y: ICON_OVERLAP }),
+ factor: 1,
+ }));
+
+ if (opt.WINDOW_ICON_CLICK_ACTION) {
+ const iconClickAction = new Clutter.ClickAction();
+ iconClickAction.connect('clicked', act => {
+ if (act.get_button() === Clutter.BUTTON_PRIMARY) {
+ if (opt.WINDOW_ICON_CLICK_ACTION === 1) {
+ this._searchAppWindowsAction();
+ return Clutter.EVENT_STOP;
+ } else if (opt.WINDOW_ICON_CLICK_ACTION === 2 && opt.WINDOW_THUMBNAIL_ENABLED) {
+ this._removeLaters();
+ Me.Modules.winTmbModule.createThumbnail(metaWindow);
+ return Clutter.EVENT_STOP;
+ }
+ } /* else if (act.get_button() === Clutter.BUTTON_SECONDARY) {
+ return Clutter.EVENT_STOP;
+ }*/
+ return Clutter.EVENT_PROPAGATE;
+ });
+ this._icon.add_action(iconClickAction);
+ }
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const iconOverlap = opt.WIN_PREVIEW_ICON_SIZE * ICON_OVERLAP;
- // we cannot get proper title height before it gets to the stage, so 35 is estimated height + spacing
- this._title.get_constraints()[1].offset = scaleFactor * (-iconOverlap - 35);
- this.set_child_above_sibling(this._title, null);
+ this._title = new St.Label({
+ visible: false,
+ style_class: 'window-caption',
+ text: this._getCaption(),
+ reactive: true,
+ });
+ this._title.clutter_text.single_line_mode = true;
+ this._title.add_constraint(new Clutter.BindConstraint({
+ source: windowContainer,
+ coordinate: Clutter.BindCoordinate.X,
+ }));
+
+ let offset;
+ if (opt.WIN_TITLES_POSITION < 2) {
+ // we cannot get proper title height before it gets to the stage, so 35 is estimated height + spacing
+ offset = -scaleFactor * (ICON_SIZE * ICON_OVERLAP + 35);
+ } else {
+ offset = scaleFactor * (ICON_SIZE * (1 - ICON_OVERLAP) + 4);
+ }
+ this._title.add_constraint(new Clutter.BindConstraint({
+ source: windowContainer,
+ coordinate: Clutter.BindCoordinate.Y,
+ offset,
+ }));
+ this._title.add_constraint(new Clutter.AlignConstraint({
+ source: windowContainer,
+ align_axis: Clutter.AlignAxis.X_AXIS,
+ factor: 0.5,
+ }));
+ this._title.add_constraint(new Clutter.AlignConstraint({
+ source: windowContainer,
+ align_axis: Clutter.AlignAxis.Y_AXIS,
+ pivot_point: new Graphene.Point({ x: -1, y: 0 }),
+ factor: 1,
+ }));
+ this._title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
+ this.label_actor = this._title;
+ this.metaWindow.connectObject(
+ 'notify::title', () => (this._title.text = this._getCaption()),
+ this);
+
+ const layout = Meta.prefs_get_button_layout();
+ this._closeButtonSide =
+ layout.left_buttons.includes(Meta.ButtonFunction.CLOSE)
+ ? St.Side.LEFT : St.Side.RIGHT;
+ if (Me.shellVersion < 43) {
+ this._closeButton = new St.Button({
+ visible: false,
+ style_class: 'window-close',
+ child: new St.Icon({ icon_name: 'preview-close-symbolic' }),
+ });
+ } else {
+ this._closeButton = new St.Button({
+ visible: false,
+ style_class: 'window-close',
+ icon_name: 'preview-close-symbolic',
+ });
+ }
+ this._closeButton.add_constraint(new Clutter.BindConstraint({
+ source: windowContainer,
+ coordinate: Clutter.BindCoordinate.POSITION,
+ }));
+ this._closeButton.add_constraint(new Clutter.AlignConstraint({
+ source: windowContainer,
+ align_axis: Clutter.AlignAxis.X_AXIS,
+ pivot_point: new Graphene.Point({ x: 0.5, y: -1 }),
+ factor: this._closeButtonSide === St.Side.LEFT ? 0 : 1,
+ }));
+ this._closeButton.add_constraint(new Clutter.AlignConstraint({
+ source: windowContainer,
+ align_axis: Clutter.AlignAxis.Y_AXIS,
+ pivot_point: new Graphene.Point({ x: -1, y: 0.5 }),
+ factor: 0,
+ }));
+ this._closeButton.connect('clicked', () => this._deleteAll());
+
+ this.add_child(this._title);
+ this.add_child(this._icon);
+ this.add_child(this._closeButton);
+
+ this._overviewAdjustment.connectObject(
+ 'notify::value', () => this._updateIconScale(), this);
+ this._updateIconScale();
+
+ this.connect('notify::realized', () => {
+ if (!this.realized)
+ return;
+
+ this._title.ensure_style();
+ this._icon.ensure_style();
+ });
+
+ if (ICON_SIZE < 22) {
+ // disable app icon
+ this._icon.hide();
+ } else {
+ this._updateIconScale();
+ }
+
+
+
// if window is created while the overview is shown, icon and title should be visible immediately
if (Main.overview._overview._controls._stateAdjustment.value < 1) {
this._icon.scale_x = 0;
@@ -124,9 +393,9 @@ const WindowPreviewCommon = {
if (global.get_pointer()[0] === opt.showingPointerX || Main.overview._overview._controls._stateAdjustment.value < 1)
return;
- const adjustment = this._workspace._background._stateAdjustment;
opt.WORKSPACE_MODE = 1;
- _Util.exposeWindows(adjustment, false);
+ const view = this._workspace.get_parent();
+ view.exposeWindows(this._workspace.metaWorkspace.index());
this.disconnect(this._wsStateConId);
});
}
@@ -136,53 +405,39 @@ const WindowPreviewCommon = {
this._stateAdjustmentSigId = this._workspace.stateAdjustment.connect('notify::value', this._updateIconScale.bind(this));
}
- // replace click action with custom one
- const action = this.get_actions()[0];
-
- const handlerId = GObject.signal_handler_find(action, { signalId: 'clicked' });
- if (handlerId)
- action.disconnect(handlerId);
+ const metaWin = this.metaWindow;
+ if (opt.DASH_ISOLATE_WS && !metaWin._wsChangedConId) {
+ metaWin._wsChangedConId = metaWin.connect('workspace-changed',
+ () => Main.overview.dash._queueRedisplay());
+ } else if (!opt.DASH_ISOLATE_WS && metaWin._wsChangedConId) {
+ metaWin.disconnect(metaWin._wsChangedConId);
+ }
+ },
- action.connect('clicked', act => {
- const button = act.get_button();
- if (button === Clutter.BUTTON_PRIMARY) {
- this._activate();
- return Clutter.EVENT_STOP;
- } else if (button === Clutter.BUTTON_SECONDARY) {
- // this action cancels long-press event and the 'long-press-cancel' event is used by the Shell to actually initiate DnD
- // so the dnd initiation needs to be removed
- if (this._longPressLater) {
- if (shellVersion >= 44) {
- const laters = global.compositor.get_laters();
- laters.remove(this._longPressLater);
- } else {
- Meta.later_remove(this._longPressLater);
- delete this._longPressLater;
- }
- }
- const tracker = Shell.WindowTracker.get_default();
- const appName = tracker.get_window_app(this.metaWindow).get_name();
- _Util.activateSearchProvider(`${SEARCH_WINDOWS_PREFIX} ${appName}`);
- return Clutter.EVENT_STOP;
- }
- return Clutter.EVENT_PROPAGATE;
- });
+ _closeWinAction() {
+ this.hide();
+ this._deleteAll();
+ },
- if (opt.WINDOW_ICON_CLICK_SEARCH) {
- const iconClickAction = new Clutter.ClickAction();
- iconClickAction.connect('clicked', act => {
- if (act.get_button() === Clutter.BUTTON_PRIMARY) {
- const tracker = Shell.WindowTracker.get_default();
- const appName = tracker.get_window_app(this.metaWindow).get_name();
- _Util.activateSearchProvider(`${SEARCH_WINDOWS_PREFIX} ${appName}`);
- return Clutter.EVENT_STOP;
- }
- return Clutter.EVENT_PROPAGATE;
- });
- this._icon.add_action(iconClickAction);
+ _removeLaters() {
+ // this action cancels long-press event and the 'long-press-cancel' event is used by the Shell to actually initiate DnD
+ // so the dnd initiation needs to be removed
+ if (this._longPressLater) {
+ if (Meta.later_remove)
+ Meta.later_remove(this._longPressLater);
+ else
+ global.compositor.get_laters().remove(this._longPressLater);
+ delete this._longPressLater;
}
},
+ _searchAppWindowsAction() {
+ this._removeLaters();
+ const tracker = Shell.WindowTracker.get_default();
+ const appName = tracker.get_window_app(this.metaWindow).get_name();
+ Me.Util.activateSearchProvider(`${Me.WSP_PREFIX} ${appName}`);
+ },
+
_updateIconScale() {
let { currentState, initialState, finalState } =
this._overviewAdjustment.getStateTransitionParams();
@@ -192,7 +447,7 @@ const WindowPreviewCommon = {
const visible =
(initialState > ControlsState.HIDDEN || finalState > ControlsState.HIDDEN) &&
- !(finalState === ControlsState.APP_GRID && primaryMonitor);
+ !(finalState === ControlsState.APP_GRID && opt.WS_ANIMATION && primaryMonitor);
let scale = 0;
if (visible)
@@ -210,7 +465,6 @@ const WindowPreviewCommon = {
else if (primaryMonitor && currentState > ControlsState.WINDOW_PICKER)
scale = 0;
-
// in static workspace mode show icon and title on windows expose
if (opt.OVERVIEW_MODE) {
if (currentState === 1)
@@ -219,29 +473,32 @@ const WindowPreviewCommon = {
return;
}
+ if (!opt.WS_ANIMATION && (Main.overview._overview.controls._searchController.searchActive ||
+ ((initialState === ControlsState.WINDOW_PICKER && finalState === ControlsState.APP_GRID) ||
+ (initialState === ControlsState.APP_GRID && finalState === ControlsState.WINDOW_PICKER)))
+ )
+ return;
+
+ // if titles are in 'always show' mode, we need to add transition between visible/invisible state
+ // but the transition is quite expensive,
+ // showing the titles at the end of the transition is good enough and workspace preview transition is much smoother
if (scale === 1) {
- this._icon.ease({
- duration: 50,
- scale_x: scale,
- scale_y: scale,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ this._icon.set({
+ scale_x: 1,
+ scale_y: 1,
});
this._title.ease({
duration: 100,
opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
- } else if (this._icon.scale_x !== 0) {
+ } else {
+ this._title.opacity = 0;
this._icon.set({
- scale_x: 0,
- scale_y: 0,
+ scale_x: scale,
+ scale_y: scale,
});
- this._title.opacity = 0;
}
-
- // if titles are in 'always show' mode, we need to add transition between visible/invisible state
- // but the transition is quite expensive,
- // showing the titles at the end of the transition is good enough and workspace preview transition is much smoother
},
showOverlay(animate) {
@@ -252,7 +509,7 @@ const WindowPreviewCommon = {
return;
this._overlayShown = true;
- if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
+ if (opt.WIN_TITLES_POSITION === 2)
this._restack();
// If we're supposed to animate and an animation in our direction
@@ -263,7 +520,7 @@ const WindowPreviewCommon = {
ongoingTransition.get_interval().peek_final_value() === 255)
return;
- const toShow = this._windowCanClose()
+ const toShow = this._windowCanClose() && opt.SHOW_CLOSE_BUTTON
? [this._closeButton]
: [];
@@ -301,12 +558,12 @@ const WindowPreviewCommon = {
if (!this._overlayShown)
return;
this._overlayShown = false;
- if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW && Main.overview._overview.controls._stateAdjustment.value < 1) {
- this.get_parent()?.set_child_above_sibling(this, null);
+
+ if (opt.ALWAYS_ACTIVATE_SELECTED_WINDOW && Main.overview._overview.controls._stateAdjustment.value < 1)
this._activateSelected = true;
- }
- if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
+
+ if (opt.WIN_TITLES_POSITION === 2)
this._restack();
// If we're supposed to animate and an animation in our direction
@@ -353,14 +610,11 @@ const WindowPreviewCommon = {
this._delegate = null;
if (this._longPressLater) {
- if (shellVersion >= 44) {
- const laters = global.compositor.get_laters();
- laters.remove(this._longPressLater);
- delete this._longPressLater;
- } else {
- Meta.later_remove(this._longPressLater);
- delete this._longPressLater;
- }
+ if (Meta.later_add)
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, this._longPressLater);
+ else
+ global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, this._longPressLater);
+ delete this._longPressLater;
}
if (this._idleHideOverlayId > 0) {
diff --git a/extensions/44/vertical-workspaces/lib/windowSearchProvider.js b/extensions/44/vertical-workspaces/lib/windowSearchProvider.js
index 5f90784..b82f365 100644
--- a/extensions/44/vertical-workspaces/lib/windowSearchProvider.js
+++ b/extensions/44/vertical-workspaces/lib/windowSearchProvider.js
@@ -9,30 +9,23 @@
'use strict';
-const { GLib, Gio, Meta, St, Shell } = imports.gi;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
const Main = imports.ui.main;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-const Settings = Me.imports.lib.settings;
-const _Util = Me.imports.lib.util;
+let Me;
+let opt;
// gettext
-const _ = Settings._;
-
-const shellVersion = Settings.shellVersion;
-
-const ModifierType = imports.gi.Clutter.ModifierType;
-
-let windowSearchProvider;
-let _enableTimeoutId = 0;
+let _;
// prefix helps to eliminate results from other search providers
// so it needs to be something less common
// needs to be accessible from vw module
-var prefix = 'wq//';
-
-let opt;
+const PREFIX = 'wq//';
const Action = {
NONE: 0,
@@ -42,66 +35,77 @@ const Action = {
MOVE_ALL_TO_WS: 4,
};
-function getOverviewSearchResult() {
- return Main.overview._overview.controls._searchController._searchResults;
-}
+var WindowSearchProviderModule = class {
+ // export for other modules
+ static _PREFIX = PREFIX;
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+ _ = Me.gettext;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ // export for other modules
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- if (!reset && opt.WINDOW_SEARCH_PROVIDER_ENABLED && !windowSearchProvider) {
- enable();
- } else if (reset || !opt.WINDOW_SEARCH_PROVIDER_ENABLED) {
- disable();
+ this._windowSearchProvider = null;
+ this._enableTimeoutId = 0;
+ }
+
+ cleanGlobals() {
+ Me = null;
opt = null;
+ _ = null;
}
-}
-
-function enable() {
- // delay because Fedora had problem to register a new provider soon after Shell restarts
- _enableTimeoutId = GLib.timeout_add(
- GLib.PRIORITY_DEFAULT,
- 2000,
- () => {
- if (!windowSearchProvider) {
- windowSearchProvider = new WindowSearchProvider(opt);
- getOverviewSearchResult()._registerProvider(
- windowSearchProvider
- );
- }
- _enableTimeoutId = 0;
- return GLib.SOURCE_REMOVE;
+
+ update(reset) {
+ this.moduleEnabled = opt.get('windowSearchProviderModule');
+
+ reset = reset || !this.moduleEnabled;
+
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
}
- );
-}
+ if (reset && this._firstActivation)
+ console.debug(' WindowSearchProviderModule - Keeping untouched');
+ }
-function disable() {
- if (windowSearchProvider) {
- getOverviewSearchResult()._unregisterProvider(
- windowSearchProvider
+ _activateModule() {
+ // delay because Fedora had problem to register a new provider soon after Shell restarts
+ this._enableTimeoutId = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ 2000,
+ () => {
+ if (!this._windowSearchProvider) {
+ this._windowSearchProvider = new WindowSearchProvider(opt);
+ this._getOverviewSearchResult()._registerProvider(this._windowSearchProvider);
+ }
+ this._enableTimeoutId = 0;
+ return GLib.SOURCE_REMOVE;
+ }
);
- windowSearchProvider = null;
+ console.debug(' WindowSearchProviderModule - Activated');
}
- if (_enableTimeoutId) {
- GLib.source_remove(_enableTimeoutId);
- _enableTimeoutId = 0;
+
+ _disableModule() {
+ if (this._windowSearchProvider) {
+ this._getOverviewSearchResult()._unregisterProvider(this._windowSearchProvider);
+ this._windowSearchProvider = null;
+ }
+ if (this._enableTimeoutId) {
+ GLib.source_remove(this._enableTimeoutId);
+ this._enableTimeoutId = 0;
+ }
+
+ console.debug(' WindowSearchProviderModule - Disabled');
}
-}
-
-function makeResult(window, i) {
- const app = Shell.WindowTracker.get_default().get_window_app(window);
- const appName = app ? app.get_name() : 'Unknown';
- const windowTitle = window.get_title();
- const wsIndex = window.get_workspace().index();
-
- return {
- 'id': i,
- // convert all accented chars to their basic form and lower case for search
- 'name': `${wsIndex + 1}: ${windowTitle} ${appName}`.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase(),
- appName,
- windowTitle,
- window,
- };
-}
+
+ _getOverviewSearchResult() {
+ return Main.overview._overview.controls._searchController._searchResults;
+ }
+};
const closeSelectedRegex = /^\/x!$/;
const closeAllResultsRegex = /^\/xa!$/;
@@ -110,15 +114,22 @@ const moveAllToWsRegex = /^\/ma[0-9]+$/;
const WindowSearchProvider = class WindowSearchProvider {
constructor() {
- this.id = `open-windows@${Me.metadata.uuid}`;
- this.appInfo = Gio.AppInfo.create_from_commandline('true', _('Open Windows'), null);
- this.appInfo.get_description = () => _('List of open windows');
- this.appInfo.get_name = () => _('Open Windows');
- this.appInfo.get_id = () => this.id;
- this.appInfo.get_icon = () => Gio.icon_new_for_string('focus-windows-symbolic');
- this.appInfo.should_show = () => true;
-
- this.canLaunchSearch = true;
+ this.id = 'open-windows';
+ const appSystem = Shell.AppSystem.get_default();
+ // use arbitrary app to get complete appInfo object
+ let appInfo = appSystem.lookup_app('com.matjakeman.ExtensionManager.desktop')?.get_app_info();
+ if (!appInfo)
+ appInfo = appSystem.lookup_app('org.gnome.Extensions.desktop')?.get_app_info();
+ if (!appInfo)
+ appInfo = Gio.AppInfo.create_from_commandline('true', _('Open Windows'), null);
+ appInfo.get_description = () => _('Search open windows');
+ appInfo.get_name = () => _('Open Windows');
+ appInfo.get_id = () => this.id;
+ appInfo.get_icon = () => Gio.icon_new_for_string('focus-windows-symbolic');
+ appInfo.should_show = () => true;
+
+ this.appInfo = appInfo;
+ this.canLaunchSearch = false;
this.isRemoteProvider = false;
this.action = 0;
@@ -128,7 +139,7 @@ const WindowSearchProvider = class WindowSearchProvider {
// do not modify original terms
let termsCopy = [...terms];
// search for terms without prefix
- termsCopy[0] = termsCopy[0].replace(prefix, '');
+ termsCopy[0] = termsCopy[0].replace(PREFIX, '');
/* if (gOptions.get('searchWindowsCommands')) {
this.action = 0;
@@ -167,9 +178,9 @@ const WindowSearchProvider = class WindowSearchProvider {
let m;
for (let key in candidates) {
if (opt.SEARCH_FUZZY)
- m = _Util.fuzzyMatch(term, candidates[key].name);
+ m = Me.Util.fuzzyMatch(term, candidates[key].name);
else
- m = _Util.strictMatch(term, candidates[key].name);
+ m = Me.Util.strictMatch(term, candidates[key].name);
if (m !== -1)
results.push({ weight: m, id: key });
@@ -178,7 +189,19 @@ const WindowSearchProvider = class WindowSearchProvider {
results.sort((a, b) => a.weight > b.weight);
const currentWs = global.workspace_manager.get_active_workspace_index();
// prefer current workspace
- results.sort((a, b) => (this.windows[a.id].window.get_workspace().index() !== currentWs) && (this.windows[b.id].window.get_workspace().index() === currentWs));
+ switch (opt.WINDOW_SEARCH_ORDER) {
+ case 1: // MRU - current ws first
+ results.sort((a, b) => (this.windows[a.id].window.get_workspace().index() !== currentWs) && (this.windows[b.id].window.get_workspace().index() === currentWs));
+ break;
+ case 2: // MRU - by workspace
+ results.sort((a, b) => this.windows[a.id].window.get_workspace().index() > this.windows[b.id].window.get_workspace().index());
+ break;
+ case 3: // Stable sequence - by workspace
+ results.sort((a, b) => this.windows[a.id].window.get_stable_sequence() > this.windows[b.id].window.get_stable_sequence());
+ results.sort((a, b) => this.windows[a.id].window.get_workspace().index() > this.windows[b.id].window.get_workspace().index());
+ break;
+ }
+
results.sort((a, b) => (_terms !== ' ') && (a.weight > 0 && b.weight === 0));
this.resultIds = results.map(item => item.id);
@@ -187,7 +210,7 @@ const WindowSearchProvider = class WindowSearchProvider {
getResultMetas(resultIds, callback = null) {
const metas = resultIds.map(id => this.getResultMeta(id));
- if (shellVersion >= 43)
+ if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(metas));
else
callback(metas);
@@ -210,12 +233,29 @@ const WindowSearchProvider = class WindowSearchProvider {
};
}
+ makeResult(window, i) {
+ const app = Shell.WindowTracker.get_default().get_window_app(window);
+ const appName = app ? app.get_name() : 'Unknown';
+ const windowTitle = window.get_title();
+ const wsIndex = window.get_workspace().index();
+
+ return {
+ 'id': i,
+ // convert all accented chars to their basic form and lower case for search
+ 'name': `${wsIndex + 1}: ${windowTitle} ${appName}`.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase(),
+ appName,
+ windowTitle,
+ window,
+ };
+ }
+
launchSearch(/* terms, timeStamp*/) {
+
}
activateResult(resultId/* , terms, timeStamp*/) {
- const isCtrlPressed = _Util.isCtrlPressed();
- const isShiftPressed = _Util.isShiftPressed();
+ const isCtrlPressed = Me.Util.isCtrlPressed();
+ const isShiftPressed = Me.Util.isShiftPressed();
this.action = 0;
this.targetWs = 0;
@@ -276,15 +316,16 @@ const WindowSearchProvider = class WindowSearchProvider {
this.windows = windows = {};
global.display.get_tab_list(Meta.TabList.NORMAL, null).filter(w => w.get_workspace() !== null).map(
(v, i) => {
- windows[`${i}-${v.get_id()}`] = makeResult(v, `${i}-${v.get_id()}`);
+ windows[`${i}-${v.get_id()}`] = this.makeResult(v, `${i}-${v.get_id()}`);
return windows[`${i}-${v.get_id()}`];
}
);
- if (shellVersion >= 43)
+ if (Me.shellVersion >= 43)
return new Promise(resolve => resolve(this._getResultSet(terms)));
else
callback(this._getResultSet(terms));
+
return null;
}
@@ -293,13 +334,15 @@ const WindowSearchProvider = class WindowSearchProvider {
return results;
}
- getSubsearchResultSet(previousResults, terms, callback/* , cancellable*/) {
- // if we return previous results, quick typers get non-actual results
- callback(this._getResultSet(terms));
+ getSubsearchResultSet(previousResults, terms, callback) {
+ if (Me.shellVersion < 43) {
+ this.getSubsearchResultSet42(terms, callback);
+ return null;
+ }
+ return this.getInitialResultSet(terms);
}
- /* createResultObject(resultMeta) {
- const app = Shell.WindowTracker.get_default().get_window_app(resultMeta.id);
- return new AppIcon(app);
- }*/
+ getSubsearchResultSet42(terms, callback) {
+ callback(this._getResultSet(terms));
+ }
};
diff --git a/extensions/44/vertical-workspaces/lib/workspace.js b/extensions/44/vertical-workspaces/lib/workspace.js
index 3b61a6d..be60403 100644
--- a/extensions/44/vertical-workspaces/lib/workspace.js
+++ b/extensions/44/vertical-workspaces/lib/workspace.js
@@ -10,51 +10,68 @@
'use strict';
-const { St, Graphene } = imports.gi;
+const Graphene = imports.gi.Graphene;
+const St = imports.gi.St;
const Main = imports.ui.main;
-const Util = imports.misc.util;
const Workspace = imports.ui.workspace;
+const Util = imports.misc.util;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-const _Util = Me.imports.lib.util;
-
-let _overrides;
+let Me;
let opt;
-let _firstRun = true;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('workspaceModule', true);
- reset = reset || !moduleEnabled;
+var WorkspaceModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
- _firstRun = false;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- if (_overrides)
- _overrides.removeAll();
+ update(reset) {
+ this.moduleEnabled = opt.get('workspaceModule');
+ const conflict = false;
+ reset = reset || !this.moduleEnabled || conflict;
- if (reset) {
- Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
- _overrides = null;
- opt = null;
- return;
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WorkspaceModule - Keeping untouched');
}
- _overrides = new _Util.Overrides();
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- _overrides.addOverride('WorkspaceBackground', Workspace.WorkspaceBackground.prototype, WorkspaceBackground);
+ this._overrides.addOverride('WorkspaceBackground', Workspace.WorkspaceBackground.prototype, WorkspaceBackground);
- // fix overlay base for Vertical Workspaces
- _overrides.addOverride('WorkspaceLayout', Workspace.WorkspaceLayout.prototype, WorkspaceLayout);
-}
+ // fix overlay base for Vertical Workspaces
+ this._overrides.addOverride('WorkspaceLayout', Workspace.WorkspaceLayout.prototype, WorkspaceLayout);
+ console.debug(' WorkspaceModule - Activated');
+ }
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+ Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
+
+ console.debug(' WorkspaceModule - Disabled');
+ }
+};
// workaround for upstream bug (that is not that invisible in default shell)
// smaller window cannot be scaled below 0.95 (WINDOW_PREVIEW_MAXIMUM_SCALE)
diff --git a/extensions/44/vertical-workspaces/lib/workspaceAnimation.js b/extensions/44/vertical-workspaces/lib/workspaceAnimation.js
index 07008c6..d790895 100644
--- a/extensions/44/vertical-workspaces/lib/workspaceAnimation.js
+++ b/extensions/44/vertical-workspaces/lib/workspaceAnimation.js
@@ -9,81 +9,147 @@
*/
'use strict';
+
const Main = imports.ui.main;
-const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const WorkspaceAnimation = imports.ui.workspaceAnimation;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
+const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
+
+let Me;
+let opt;
-// first reference to constant defined using const in other module returns undefined, the MonitorGroup const will remain empty and unused
-let MonitorGroupDummy = WorkspaceAnimation.MonitorGroup;
-MonitorGroupDummy = null;
+var WorkspaceAnimationModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
+
+ // first reference to constant defined using const in other module returns undefined, the MonitorGroup const will remain empty and unused
+ this.dummy = WorkspaceAnimation.MonitorGroup;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ this._origBaseDistance = null;
+ this._wsAnimationSwipeBeginId = 0;
+ this._wsAnimationSwipeUpdateId = 0;
+ this._wsAnimationSwipeEndId = 0;
+ }
-let _origBaseDistance;
-let _wsAnimationSwipeBeginId;
-let _wsAnimationSwipeUpdateId;
-let _wsAnimationSwipeEndId;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
-let _overrides;
-let opt;
-let _firstRun = true;
+ update(reset) {
+ this.moduleEnabled = opt.get('workspaceAnimationModule');
+ const conflict = false;
+
+ reset = reset || !this.moduleEnabled || conflict;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('workspaceAnimationModule', true);
- reset = reset || !moduleEnabled;
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WorkspaceAnimationModule - Keeping untouched');
+ }
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- _firstRun = false;
+ if (opt.STATIC_WS_SWITCHER_BG) {
+ this._overrideMonitorGroupProperty();
+ this._overrides.addOverride('WorkspaceAnimationMonitorGroup', WorkspaceAnimation.MonitorGroup.prototype, MonitorGroup);
+ }
- if (_overrides)
- _overrides.removeAll();
+ this._connectWsAnimationSwipeTracker();
+ console.debug(' WorkspaceAnimationModule - Activated');
+ }
- if (reset || !moduleEnabled) {
- _connectWsAnimationSwipeTracker(true);
- _overrideMonitorGroupProperty(true);
- _overrides = null;
- opt = null;
- return;
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+ const reset = true;
+ this._connectWsAnimationSwipeTracker(reset);
+ this._overrideMonitorGroupProperty(reset);
+ console.debug(' WorkspaceAnimationModule - Disabled');
}
- if (opt.STATIC_WS_SWITCHER_BG) {
- _overrides = new _Util.Overrides();
- _overrideMonitorGroupProperty();
- _overrides.addOverride('WorkspaceAnimationMonitorGroup', WorkspaceAnimation.MonitorGroup.prototype, MonitorGroup);
+ _overrideMonitorGroupProperty(reset = false) {
+ if (!this._origBaseDistance)
+ this._origBaseDistance = Object.getOwnPropertyDescriptor(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance').get;
+
+ let getter;
+ if (reset) {
+ if (this._origBaseDistance)
+ getter = { get: this._origBaseDistance };
+ } else {
+ getter = {
+ get() {
+ // const spacing = 100 * imports.gi.St.ThemeContext.get_for_stage(global.stage).scale_factor;
+ const spacing = 0;
+ if (global.workspace_manager.layout_rows === -1)
+ return this._monitor.height + spacing + (opt.PANEL_MODE ? Main.panel.height : 0); // compensation for hidden panel
+ else
+ return this._monitor.width + spacing;
+ },
+ };
+ }
+
+ if (getter)
+ Object.defineProperty(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance', getter);
+ }
+
+ _connectWsAnimationSwipeTracker(reset = false) {
+ if (reset) {
+ if (this._wsAnimationSwipeBeginId) {
+ Main.wm._workspaceAnimation._swipeTracker.disconnect(this._wsAnimationSwipeBeginId);
+ this._wsAnimationSwipeBeginId = 0;
+ }
+ if (this._wsAnimationSwipeEndId) {
+ Main.wm._workspaceAnimation._swipeTracker.disconnect(this._wsAnimationSwipeEndId);
+ this._wsAnimationSwipeEndId = 0;
+ }
+ } else if (!this._wsAnimationSwipeBeginId) {
+ // display ws switcher popup when gesture begins and connect progress
+ this._wsAnimationSwipeBeginId = Main.wm._workspaceAnimation._swipeTracker.connect('begin', () => this._connectWsAnimationProgress(true));
+ // we want to be sure that popup with the final ws index show up when gesture ends
+ this._wsAnimationSwipeEndId = Main.wm._workspaceAnimation._swipeTracker.connect('end', (tracker, duration, endProgress) => this._connectWsAnimationProgress(false, endProgress));
+ }
}
- _connectWsAnimationSwipeTracker();
-}
-
-// remove spacing between workspaces during transition to remove flashing wallpaper between workspaces with maximized windows
-function _overrideMonitorGroupProperty(reset = false) {
- if (!_origBaseDistance)
- _origBaseDistance = Object.getOwnPropertyDescriptor(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance').get;
-
- let getter;
- if (reset) {
- if (_origBaseDistance)
- getter = { get: _origBaseDistance };
- } else {
- getter = {
- get() {
- // const spacing = 100 * imports.gi.St.ThemeContext.get_for_stage(global.stage).scale_factor;
- const spacing = 0;
- if (global.workspace_manager.layout_rows === -1)
- return this._monitor.height + spacing + (opt.PANEL_MODE ? Main.panel.height : 0); // compensation for hidden panel
- else
- return this._monitor.width + spacing;
- },
- };
+ _connectWsAnimationProgress(connect, endProgress = null) {
+ if (Main.overview.visible)
+ return;
+
+ if (connect && !this._wsAnimationSwipeUpdateId) {
+ this._wsAnimationSwipeUpdateId = Main.wm._workspaceAnimation._swipeTracker.connect('update', (tracker, progress) => this._showWsSwitcherPopup(progress));
+ } else if (!connect && this._wsAnimationSwipeUpdateId) {
+ Main.wm._workspaceAnimation._swipeTracker.disconnect(this._wsAnimationSwipeUpdateId);
+ this._wsAnimationSwipeUpdateId = 0;
+ this._showWsSwitcherPopup(Math.round(endProgress));
+ }
}
- if (getter)
- Object.defineProperty(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance', getter);
-}
+ _showWsSwitcherPopup(progress) {
+ if (Main.overview.visible)
+ return;
+
+ const wsIndex = Math.round(progress);
+ if (Main.wm._workspaceSwitcherPopup === null) {
+ Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
+ Main.wm._workspaceSwitcherPopup.connect('destroy', () => {
+ Main.wm._workspaceSwitcherPopup = null;
+ });
+ }
+
+ Main.wm._workspaceSwitcherPopup.display(wsIndex);
+ }
+};
const MonitorGroup = {
// injection to _init()
@@ -119,7 +185,9 @@ const MonitorGroup = {
// hide (scale to 0) all non-sticky windows, their clones will be animated
global.get_window_actors().forEach(actor => {
const metaWin = actor.metaWindow;
- if (metaWin?.get_monitor() === this._monitor.index && !(metaWin?.wm_class === 'conky' && metaWin?.is_on_all_workspaces())) { //* && !w.is_on_all_workspaces()*/) {
+ if (metaWin?.get_monitor() === this._monitor.index &&
+ !(metaWin?.wm_class === 'conky' && metaWin?.is_on_all_workspaces()) &&
+ !(metaWin?.wm_class === 'Gjs' && metaWin?.is_on_all_workspaces())) { // DING extension uses window with Gjs class
// hide original window. we cannot use opacity since it also affects clones.
// scaling them to 0 works well
actor.scale_x = 0;
@@ -136,49 +204,3 @@ const MonitorGroup = {
});
},
};
-
-function _connectWsAnimationSwipeTracker(reset = false) {
- if (reset) {
- if (_wsAnimationSwipeBeginId) {
- Main.wm._workspaceAnimation._swipeTracker.disconnect(_wsAnimationSwipeBeginId);
- _wsAnimationSwipeBeginId = 0;
- }
- if (_wsAnimationSwipeEndId) {
- Main.wm._workspaceAnimation._swipeTracker.disconnect(_wsAnimationSwipeEndId);
- _wsAnimationSwipeEndId = 0;
- }
- } else if (!_wsAnimationSwipeBeginId) {
- // display ws switcher popup when gesture begins and connect progress
- _wsAnimationSwipeBeginId = Main.wm._workspaceAnimation._swipeTracker.connect('begin', () => _connectWsAnimationProgress(true));
- // we want to be sure that popup with the final ws index show up when gesture ends
- _wsAnimationSwipeEndId = Main.wm._workspaceAnimation._swipeTracker.connect('end', (tracker, duration, endProgress) => _connectWsAnimationProgress(false, endProgress));
- }
-}
-
-function _connectWsAnimationProgress(connect, endProgress = null) {
- if (Main.overview.visible)
- return;
-
- if (connect && !_wsAnimationSwipeUpdateId) {
- _wsAnimationSwipeUpdateId = Main.wm._workspaceAnimation._swipeTracker.connect('update', (tracker, progress) => _showWsSwitcherPopup(progress));
- } else if (!connect && _wsAnimationSwipeUpdateId) {
- Main.wm._workspaceAnimation._swipeTracker.disconnect(_wsAnimationSwipeUpdateId);
- _wsAnimationSwipeUpdateId = 0;
- _showWsSwitcherPopup(Math.round(endProgress));
- }
-}
-
-function _showWsSwitcherPopup(progress) {
- if (Main.overview.visible)
- return;
-
- const wsIndex = Math.round(progress);
- if (Main.wm._workspaceSwitcherPopup === null) {
- Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
- Main.wm._workspaceSwitcherPopup.connect('destroy', () => {
- Main.wm._workspaceSwitcherPopup = null;
- });
- }
-
- Main.wm._workspaceSwitcherPopup.display(wsIndex);
-}
diff --git a/extensions/44/vertical-workspaces/lib/workspaceSwitcherPopup.js b/extensions/44/vertical-workspaces/lib/workspaceSwitcherPopup.js
index 972f35e..5bde6d0 100644
--- a/extensions/44/vertical-workspaces/lib/workspaceSwitcherPopup.js
+++ b/extensions/44/vertical-workspaces/lib/workspaceSwitcherPopup.js
@@ -13,52 +13,71 @@
const Main = imports.ui.main;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
+let Me;
+let opt;
-const _Util = Me.imports.lib.util;
-let _overrides;
+var WorkspaceSwitcherPopupModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
-let opt;
-let _firstRun = true;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('workspaceSwitcherPopupModule', true);
- reset = reset || !moduleEnabled;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
+ update(reset) {
+ this.moduleEnabled = opt.get('workspaceSwitcherPopupModule');
+ const conflict = Me.Util.getEnabledExtensions('workspace-switcher-manager').length ||
+ Me.Util.getEnabledExtensions('WsSwitcherPopupManager').length;
- _firstRun = false;
+ if (conflict && !reset)
+ console.warn(`[${Me.metadata.name}] Warning: "WorkspaceSwitcherPopup" module disabled due to potential conflict with another extension`);
- if (_overrides)
- _overrides.removeAll();
+ reset = reset || !this.moduleEnabled || conflict;
- if (reset) {
- _overrides = null;
- opt = null;
- return;
+ // don't touch original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WorkspaceSwitcherPopupModule - Keeping untouched');
}
- _overrides = new _Util.Overrides();
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- const enabled = global.settings.get_strv('enabled-extensions');
- const allowWsPopupInjection = !(enabled.includes('workspace-switcher-manager@G-dH.github.com') || enabled.includes('WsSwitcherPopupManager@G-dH.github.com-dev'));
- if (allowWsPopupInjection) { // 1-VERTICAL, 0-HORIZONTAL
- _overrides.addOverride('WorkspaceSwitcherPopup', WorkspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype, WorkspaceSwitcherPopupOverride);
+ this._overrides.addOverride('WorkspaceSwitcherPopup', WorkspaceSwitcherPopup.WorkspaceSwitcherPopup.prototype, WorkspaceSwitcherPopupCommon);
+ console.debug(' WorkspaceSwitcherPopupModule - Activated');
}
-}
-const WorkspaceSwitcherPopupOverride = {
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ console.debug(' WorkspaceSwitcherPopupModule - Disabled');
+ }
+};
+
+const WorkspaceSwitcherPopupCommon = {
// injection to _init()
after__init() {
if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
this._list.vertical = true;
}
this._list.set_style('margin: 0;');
- this.remove_constraint(this.get_constraints()[0]);
+ if (this.get_constraints()[0])
+ this.remove_constraint(this.get_constraints()[0]);
},
// injection to display()
diff --git a/extensions/44/vertical-workspaces/lib/workspaceThumbnail.js b/extensions/44/vertical-workspaces/lib/workspaceThumbnail.js
index d0bc206..844c224 100644
--- a/extensions/44/vertical-workspaces/lib/workspaceThumbnail.js
+++ b/extensions/44/vertical-workspaces/lib/workspaceThumbnail.js
@@ -10,56 +10,90 @@
'use strict';
-const { GLib, Clutter, Graphene, Meta, Shell, St } = imports.gi;
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Meta = imports.gi.Meta;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+
+const AppDisplay = imports.ui.appDisplay;
+const Background = imports.ui.background;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
-const Background = imports.ui.background;
+const OverviewControls = imports.ui.overviewControls;
const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
+
+let Me;
+let opt;
+
const ThumbnailState = WorkspaceThumbnail.ThumbnailState;
+const ControlsState = OverviewControls.ControlsState;
-const ControlsState = imports.ui.overviewControls.ControlsState;
+const WORKSPACE_CUT_SIZE = 10;
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
+var WorkspaceThumbnailModule = class {
+ constructor(me) {
+ Me = me;
+ opt = Me.opt;
-// gettext
-const _ = Me.imports.lib.settings._;
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
+ }
-const _Util = Me.imports.lib.util;
-const shellVersion = _Util.shellVersion;
+ cleanGlobals() {
+ Me = null;
+ opt = null;
+ }
-let _overrides;
+ update(reset) {
+ this.moduleEnabled = true;
+ const conflict = false;
-const WORKSPACE_CUT_SIZE = 10;
-const _originalMaxThumbnailScale = WorkspaceThumbnail.MAX_THUMBNAIL_SCALE;
+ reset = reset || !this.moduleEnabled || conflict;
-let opt = null;
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WorkspaceThumbnailModule - Keeping untouched');
+ }
-function update(reset = false) {
- if (_overrides)
- _overrides.removeAll();
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
+ if (!this._originalMaxThumbnailScale)
+ this._originalMaxThumbnailScale = WorkspaceThumbnail.MAX_THUMBNAIL_SCALE;
- if (reset) {
- if (_originalMaxThumbnailScale)
- WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = _originalMaxThumbnailScale;
- _overrides = null;
- opt = null;
- return;
- }
+ // don't limit max thumbnail scale for other clients than overview, specifically AATWS.
+ WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = 1;
+ // WorkspaceThumbnail.ThumbnailsBox._MAX_THUMBNAIL_SCALE = 1;
+
+ this._overrides.addOverride('WorkspaceThumbnail', WorkspaceThumbnail.WorkspaceThumbnail.prototype, WorkspaceThumbnailCommon);
+ this._overrides.addOverride('ThumbnailsBoxCommon', WorkspaceThumbnail.ThumbnailsBox.prototype, ThumbnailsBoxCommon);
- opt = Me.imports.lib.settings.opt;
- _overrides = new _Util.Overrides();
+ // replacing opt.ORIENTATION local constant with boxOrientation internal variable allows external customers such as the AATWS extension to control the box orientation.
+ Main.overview._overview.controls._thumbnailsBox._boxOrientation = opt.ORIENTATION;
+
+ console.debug(' WorkspaceThumbnailModule - Activated');
+ }
- // don't limit max thumbnail scale for other clients than overview, for example AATWS.
- WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = 1;
+ _disableModule() {
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
- _overrides.addOverride('WorkspaceThumbnail', WorkspaceThumbnail.WorkspaceThumbnail.prototype, WorkspaceThumbnailCommon);
- _overrides.addOverride('ThumbnailsBoxCommon', WorkspaceThumbnail.ThumbnailsBox.prototype, ThumbnailsBoxCommon);
+ WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = this._originalMaxThumbnailScale;
- // replacing opt.ORIENTATION local constant with boxOrientation internal variable allows external customers such as the AATWS extension to control the box orientation.
- Main.overview._overview.controls._thumbnailsBox._boxOrientation = opt.ORIENTATION;
-}
+ console.debug(' WorkspaceThumbnailModule - Disabled');
+ }
+};
const WorkspaceThumbnailCommon = {
// injection to _init()
@@ -70,6 +104,8 @@ const WorkspaceThumbnailCommon = {
// unless border is removed
if (opt.SHOW_WS_TMB_BG)
this.add_style_class_name('ws-tmb-labeled');
+ else
+ this.add_style_class_name('ws-tmb-transparent');
// add workspace thumbnails labels if enabled
if (opt.SHOW_WST_LABELS) { // 0 - disable
@@ -77,7 +113,7 @@ const WorkspaceThumbnailCommon = {
const wsIndex = this.metaWorkspace.index();
let label = `${wsIndex + 1}`;
if (opt.SHOW_WST_LABELS === 2) { // 2 - index + workspace name
- const settings = ExtensionUtils.getSettings('org.gnome.desktop.wm.preferences');
+ const settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' });
const wsLabels = settings.get_strv('workspace-names');
if (wsLabels.length > wsIndex && wsLabels[wsIndex])
label += `: ${wsLabels[wsIndex]}`;
@@ -129,7 +165,9 @@ const WorkspaceThumbnailCommon = {
}
});
this._nWindowsConId = this.metaWorkspace.connect('notify::n-windows', () => {
- // wait for new information
+ if (this._updateLabelTimeout)
+ return;
+ // wait for new data
this._updateLabelTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => {
const newLabel = getLabel();
this._wsLabel.text = newLabel;
@@ -168,7 +206,7 @@ const WorkspaceThumbnailCommon = {
closeButton.opacity = 255;
if (!Meta.prefs_get_dynamic_workspaces() || (Meta.prefs_get_dynamic_workspaces() && global.workspace_manager.get_n_workspaces() - 1 !== this.metaWorkspace.index())) {
// color the button red if ready to react on clicks
- if (opt.CLOSE_WS_BUTTON_MODE < 3 || (opt.CLOSE_WS_BUTTON_MODE === 3 && _Util.isCtrlPressed()))
+ if (opt.CLOSE_WS_BUTTON_MODE < 3 || (opt.CLOSE_WS_BUTTON_MODE === 3 && Me.Util.isCtrlPressed()))
closeButton.add_style_class_name('workspace-close-button-hover');
}
});
@@ -220,12 +258,6 @@ const WorkspaceThumbnailCommon = {
this._viewport.set_child_below_sibling(this._bgManager.backgroundActor, null);
- this.connect('destroy', () => {
- if (this._bgManager)
- this._bgManager.destroy();
- this._bgManager = null;
- });
-
// full brightness of the thumbnail bg draws unnecessary attention
// there is a grey bg under the wallpaper
this._bgManager.backgroundActor.opacity = 220;
@@ -256,7 +288,7 @@ const WorkspaceThumbnailCommon = {
this._lastCloseClickTime = Date.now();
return;
}
- } else if (opt.CLOSE_WS_BUTTON_MODE === 3 && !_Util.isCtrlPressed()) {
+ } else if (opt.CLOSE_WS_BUTTON_MODE === 3 && !Me.Util.isCtrlPressed()) {
return;
}
@@ -335,7 +367,7 @@ const WorkspaceThumbnailCommon = {
if (!source.app && source.shellWorkspaceLaunch)
return DND.DragMotionResult.COPY_DROP;
- if (source instanceof imports.ui.appDisplay.FolderIcon)
+ if (source instanceof AppDisplay.FolderIcon)
return DND.DragMotionResult.COPY_DROP;
@@ -369,8 +401,8 @@ const WorkspaceThumbnailCommon = {
timestamp: time,
});
return true;
- } else if (source instanceof imports.ui.appDisplay.FolderIcon) {
- if (shellVersion >= 44) {
+ } else if (source instanceof AppDisplay.FolderIcon) {
+ if (Me.shellVersion >= 44) {
for (let app of source.view._apps) {
// const app = Shell.AppSystem.get_default().lookup_app(id);
app.open_new_window(this.metaWorkspace.index());
@@ -419,7 +451,7 @@ const ThumbnailsBoxCommon = {
if (!source.metaWindow &&
(!source.app || !source.app.can_open_new_window()) &&
(source.app || !source.shellWorkspaceLaunch) &&
- !(source instanceof imports.ui.appDisplay.FolderIcon))
+ !(source instanceof AppDisplay.FolderIcon))
return false;
@@ -448,8 +480,8 @@ const ThumbnailsBoxCommon = {
workspace: newWorkspaceIndex,
timestamp: time,
});
- } else if (source instanceof imports.ui.appDisplay.FolderIcon) {
- if (shellVersion >= 44) {
+ } else if (source instanceof AppDisplay.FolderIcon) {
+ if (Me.shellVersion >= 44) {
for (let app of source.view._apps) {
// const app = Shell.AppSystem.get_default().lookup_app(id);
app.open_new_window(newWorkspaceIndex);
@@ -495,7 +527,7 @@ const ThumbnailsBoxCommon = {
if (!source.metaWindow &&
(!source.app || !source.app.can_open_new_window()) &&
(source.app || !source.shellWorkspaceLaunch) &&
- source !== Main.xdndHandler && !(source instanceof imports.ui.appDisplay.FolderIcon))
+ source !== Main.xdndHandler && !(source instanceof AppDisplay.FolderIcon))
return DND.DragMotionResult.CONTINUE;
const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL;
@@ -551,18 +583,18 @@ const ThumbnailsBoxCommon = {
return ThumbnailsBoxHorizontal._withinWorkspace.bind(this)(...args);
},
- get_preferred_custom_width(...args) {
+ vfunc_get_preferred_width(...args) {
if (this._boxOrientation)
- return ThumbnailsBoxVertical.get_preferred_custom_width.bind(this)(...args);
+ return ThumbnailsBoxVertical.vfunc_get_preferred_width.bind(this)(...args);
else
- return ThumbnailsBoxHorizontal.get_preferred_custom_width.bind(this)(...args);
+ return ThumbnailsBoxHorizontal.vfunc_get_preferred_width.bind(this)(...args);
},
- get_preferred_custom_height(...args) {
+ vfunc_get_preferred_height(...args) {
if (this._boxOrientation)
- return ThumbnailsBoxVertical.get_preferred_custom_height.bind(this)(...args);
+ return ThumbnailsBoxVertical.vfunc_get_preferred_height.bind(this)(...args);
else
- return ThumbnailsBoxHorizontal.get_preferred_custom_height.bind(this)(...args);
+ return ThumbnailsBoxHorizontal.vfunc_get_preferred_height.bind(this)(...args);
},
vfunc_allocate(...args) {
@@ -632,14 +664,9 @@ const ThumbnailsBoxVertical = {
return y > workspaceY1 && y <= workspaceY2;
},
- // vfunc_get_preferred_width: function(forHeight) {
- // override of this vfunc doesn't work for some reason (tested on Ubuntu and Fedora), it's not reachable
- get_preferred_custom_width(forHeight) {
- if (!this.visible)
- return [0, 0];
-
- if (forHeight === -1)
- return this.get_preferred_custom_height(forHeight);
+ vfunc_get_preferred_width(forHeight) {
+ if (forHeight < 10)
+ return [this._porthole.width, this._porthole.width];
let themeNode = this.get_theme_node();
@@ -652,19 +679,14 @@ const ThumbnailsBoxVertical = {
const avail = forHeight - totalSpacing;
let scale = (avail / nWorkspaces) / this._porthole.height;
- // scale = Math.min(scale, opt.MAX_THUMBNAIL_SCALE);
const width = Math.round(this._porthole.width * scale);
return themeNode.adjust_preferred_height(width, width);
},
- get_preferred_custom_height(_forWidth) {
- if (!this.visible)
- return [0, 0];
-
- // Note that for getPreferredHeight/Width we cheat a bit and skip propagating
- // the size request to our children because we know how big they are and know
- // that the actors aren't depending on the virtual functions being called.
+ vfunc_get_preferred_height(forWidth) {
+ if (forWidth < 10)
+ return [0, this._porthole.height];
let themeNode = this.get_theme_node();
let spacing = themeNode.get_length('spacing');
@@ -674,15 +696,14 @@ const ThumbnailsBoxVertical = {
let totalSpacing = (nWorkspaces - 3) * spacing;
const ratio = this._porthole.width / this._porthole.height;
- const tmbHeight = themeNode.adjust_for_width(_forWidth) / ratio;
+ const tmbHeight = themeNode.adjust_for_width(forWidth) / ratio;
const naturalheight = this._thumbnails.reduce((accumulator, thumbnail/* , index*/) => {
const progress = 1 - thumbnail.collapse_fraction;
const height = tmbHeight * progress;
return accumulator + height;
}, 0);
-
- return themeNode.adjust_preferred_width(totalSpacing, naturalheight);
+ return themeNode.adjust_preferred_width(totalSpacing, Math.round(naturalheight));
},
// removes extra space (extraWidth in the original function), we need the box as accurate as possible
@@ -759,16 +780,11 @@ const ThumbnailsBoxVertical = {
this._dropPlaceholder.allocate_preferred_size(
...this._dropPlaceholder.get_position());
- if (shellVersion >= 44) {
- const laters = global.compositor.get_laters();
- laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.hide();
- });
- } else {
- Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.hide();
- });
- }
+ const laterFunc = () => this._dropPlaceholder.hide();
+ if (Meta.later_add)
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
+ else
+ global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
}
let childBox = new Clutter.ActorBox();
@@ -796,16 +812,11 @@ const ThumbnailsBoxVertical = {
this._dropPlaceholder.allocate(childBox);
- if (shellVersion >= 44) {
- const laters = global.compositor.get_laters();
- laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.show();
- });
- } else {
- Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.show();
- });
- }
+ const laterFunc = () => this._dropPlaceholder.show();
+ if (Meta.later_add)
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
+ else
+ global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
y += placeholderHeight + spacing;
}
@@ -925,7 +936,10 @@ const ThumbnailsBoxHorizontal = {
return x > workspaceX1 && x <= workspaceX2;
},
- get_preferred_custom_height(forWidth) {
+ vfunc_get_preferred_height(forWidth) {
+ if (forWidth < 10)
+ return [this._porthole.height, this._porthole.height];
+
let themeNode = this.get_theme_node();
forWidth = themeNode.adjust_for_width(forWidth);
@@ -937,18 +951,15 @@ const ThumbnailsBoxHorizontal = {
const avail = forWidth - totalSpacing;
let scale = (avail / nWorkspaces) / this._porthole.width;
- // scale = Math.min(scale, opt.MAX_THUMBNAIL_SCALE);
const height = Math.round(this._porthole.height * scale);
+
return themeNode.adjust_preferred_height(height, height);
},
- get_preferred_custom_width(_forHeight) {
- // Note that for getPreferredHeight/Width we cheat a bit and skip propagating
- // the size request to our children because we know how big they are and know
- // that the actors aren't depending on the virtual functions being called.
- if (!this.visible)
- return [0, 0];
+ vfunc_get_preferred_width(forHeight) {
+ if (forHeight < 10)
+ return [0, this._porthole.width];
let themeNode = this.get_theme_node();
@@ -959,13 +970,14 @@ const ThumbnailsBoxHorizontal = {
const ratio = this._porthole.height / this._porthole.width;
- const tmbWidth = themeNode.adjust_for_height(_forHeight) / ratio;
+ const tmbWidth = themeNode.adjust_for_height(forHeight) / ratio;
const naturalWidth = this._thumbnails.reduce((accumulator, thumbnail) => {
const progress = 1 - thumbnail.collapse_fraction;
const width = tmbWidth * progress;
return accumulator + width;
}, 0);
+
return themeNode.adjust_preferred_width(totalSpacing, naturalWidth);
},
@@ -1041,16 +1053,11 @@ const ThumbnailsBoxHorizontal = {
this._dropPlaceholder.allocate_preferred_size(
...this._dropPlaceholder.get_position());
- if (shellVersion >= 44) {
- const laters = global.compositor.get_laters();
- laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.hide();
- });
- } else {
- Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.hide();
- });
- }
+ const laterFunc = () => this._dropPlaceholder.hide();
+ if (Meta.later_add)
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
+ else
+ global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
}
let childBox = new Clutter.ActorBox();
@@ -1078,16 +1085,11 @@ const ThumbnailsBoxHorizontal = {
this._dropPlaceholder.allocate(childBox);
- if (shellVersion >= 44) {
- const laters = global.compositor.get_laters();
- laters.add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.show();
- });
- } else {
- Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
- this._dropPlaceholder.show();
- });
- }
+ const laterFunc = () => this._dropPlaceholder.show();
+ if (Meta.later_add)
+ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
+ else
+ global.compositor.get_laters().add(Meta.LaterType.BEFORE_REDRAW, laterFunc);
x += placeholderWidth + spacing;
}
diff --git a/extensions/44/vertical-workspaces/lib/workspacesView.js b/extensions/44/vertical-workspaces/lib/workspacesView.js
index e3575f1..3df7b22 100644
--- a/extensions/44/vertical-workspaces/lib/workspacesView.js
+++ b/extensions/44/vertical-workspaces/lib/workspacesView.js
@@ -10,62 +10,92 @@
'use strict';
-const { GObject, Clutter, Meta, St } = imports.gi;
+const Clutter = imports.gi.Clutter;
+const GObject = imports.gi.GObject;
+const Meta = imports.gi.Meta;
+const St = imports.gi.St;
const Main = imports.ui.main;
-const Util = imports.misc.util;
+const OverviewControls = imports.ui.overviewControls;
const WorkspacesView = imports.ui.workspacesView;
-// first reference to constant defined using const in other module returns undefined, the SecondaryMonitorDisplay const will remain empty and unused
-const SecondaryMonitorDisplay = WorkspacesView.SecondaryMonitorDisplay;
-const ControlsState = imports.ui.overviewControls.ControlsState;
-const FitMode = imports.ui.workspacesView.FitMode;
-
-const SIDE_CONTROLS_ANIMATION_TIME = imports.ui.overview.ANIMATION_TIME;
-
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const SEARCH_WINDOWS_PREFIX = Me.imports.lib.windowSearchProvider.prefix;
-const SEARCH_RECENT_FILES_PREFIX = Me.imports.lib.recentFilesSearchProvider.prefix;
-
-const _Util = Me.imports.lib.util;
-let _overrides;
+const Util = imports.misc.util;
+let Me;
let opt;
+const ControlsState = OverviewControls.ControlsState;
+const FitMode = WorkspacesView.FitMode;
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- opt.DESKTOP_CUBE_ENABLED = Main.extensionManager._enabledExtensions.includes('desktop-cube@schneegans.github.com');
- const cubeSupported = opt.DESKTOP_CUBE_ENABLED && !opt.ORIENTATION && !opt.OVERVIEW_MODE;
+var WorkspacesViewModule = class {
+ constructor(me) {
+ // first reference to constant defined using const in other module returns undefined, the SecondaryMonitorDisplay const will remain empty and unused
+ this.dummy = WorkspacesView.SecondaryMonitorDisplay;
- // if desktop cube extension is enabled while V-Shell is loaded, removeAll() would override its code
- if (_overrides && !cubeSupported) {
- _overrides.removeAll();
- global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1);
+ Me = me;
+ opt = Me.opt;
+
+ this._firstActivation = true;
+ this.moduleEnabled = false;
+ this._overrides = null;
}
- if (reset) {
- _overrides = null;
+ cleanGlobals() {
+ Me = null;
opt = null;
- return;
}
+ update(reset) {
+ this.moduleEnabled = true;
+ const conflict = false;
+
+ reset = reset || !this.moduleEnabled || conflict;
+
+ // don't touch the original code if module disabled
+ if (reset && !this._firstActivation) {
+ this._disableModule();
+ } else if (!reset) {
+ this._firstActivation = false;
+ this._activateModule();
+ }
+ if (reset && this._firstActivation)
+ console.debug(' WorkspacesViewModule - Keeping untouched');
+ }
- _overrides = new _Util.Overrides();
+ _activateModule() {
+ if (!this._overrides)
+ this._overrides = new Me.Util.Overrides();
- if (!cubeSupported)
- _overrides.addOverride('WorkspacesView', WorkspacesView.WorkspacesView.prototype, WorkspacesViewCommon);
+ const desktopCubeEnabled = Me.Util.getEnabledExtensions('desktop-cube@schneegans.github.com').length;
+ const desktopCubeConflict = desktopCubeEnabled && !opt.ORIENTATION && !opt.OVERVIEW_MODE;
- _overrides.addOverride('WorkspacesDisplay', WorkspacesView.WorkspacesDisplay.prototype, WorkspacesDisplay);
- _overrides.addOverride('ExtraWorkspaceView', WorkspacesView.ExtraWorkspaceView.prototype, ExtraWorkspaceView);
+ if (!desktopCubeConflict)
+ this._overrides.addOverride('WorkspacesView', WorkspacesView.WorkspacesView.prototype, WorkspacesViewCommon);
- if (opt.ORIENTATION) {
- // switch internal workspace orientation in GS
- global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, -1, 1);
- _overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayVertical);
- } else {
- _overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayHorizontal);
+ this._overrides.addOverride('WorkspacesDisplay', WorkspacesView.WorkspacesDisplay.prototype, WorkspacesDisplayCommon);
+ this._overrides.addOverride('ExtraWorkspaceView', WorkspacesView.ExtraWorkspaceView.prototype, ExtraWorkspaceViewCommon);
+ this._overrides.addOverride('SecondaryMonitorDisplayCommon', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayCommon);
+
+ if (opt.ORIENTATION) {
+ // switch internal workspace orientation in GS
+ global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, -1, 1);
+ this._overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayVertical);
+ } else {
+ global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1);
+ this._overrides.addOverride('SecondaryMonitorDisplay', WorkspacesView.SecondaryMonitorDisplay.prototype, SecondaryMonitorDisplayHorizontal);
+ }
+
+ console.debug(' WorkspacesViewModule - Activated');
}
-}
+
+ _disableModule() {
+ global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT, false, 1, -1);
+ if (this._overrides)
+ this._overrides.removeAll();
+ this._overrides = null;
+
+ console.debug(' WorkspacesViewModule - Disabled');
+ }
+};
const WorkspacesViewCommon = {
_getFirstFitSingleWorkspaceBox(box, spacing, vertical) {
@@ -91,7 +121,6 @@ const WorkspacesViewCommon = {
}
const fitSingleBox = new Clutter.ActorBox({ x1, y1 });
-
fitSingleBox.set_size(workspaceWidth, workspaceHeight);
return fitSingleBox;
@@ -143,21 +172,7 @@ const WorkspacesViewCommon = {
},
_updateVisibility() {
- // replaced in _updateWorkspacesState
- /* let workspaceManager = global.workspace_manager;
- let active = workspaceManager.get_active_workspace_index();
-
- const fitMode = this._fitModeAdjustment.value;
- const singleFitMode = fitMode === FitMode.SINGLE;
-
- for (let w = 0; w < this._workspaces.length; w++) {
- let workspace = this._workspaces[w];
-
- if (this._animating || this._gestureActive || !singleFitMode)
- workspace.show();
- else
- workspace.visible = Math.abs(w - active) <= opt.NUMBER_OF_VISIBLE_NEIGHBORS;
- }*/
+ // visibility handles _updateWorkspacesState()
},
// disable scaling and hide inactive workspaces
@@ -175,27 +190,21 @@ const WorkspacesViewCommon = {
const primaryMonitor = Main.layoutManager.primaryMonitor.index;
- // define the transition values here to save time in each ws
- let scaleX, scaleY;
- if (opt.ORIENTATION) { // vertical 1 / horizontal 0
- scaleX = 1;
- scaleY = 0.1;
- } else {
- scaleX = 0.1;
- scaleY = 1;
- }
-
const wsScrollProgress = adj.value % 1;
const secondaryMonitor = this._monitorIndex !== global.display.get_primary_monitor();
const blockSecondaryAppGrid = opt.OVERVIEW_MODE && currentState > 1;
+
// Hide inactive workspaces
this._workspaces.forEach((w, index) => {
if (!(blockSecondaryAppGrid && secondaryMonitor))
w.stateAdjustment.value = workspaceMode;
- const distanceToCurrentWorkspace = Math.abs(adj.value - index);
+ let distance = adj.value - index;
+ const distanceToCurrentWorkspace = Math.abs(distance);
const scaleProgress = 1 - Math.clamp(distanceToCurrentWorkspace, 0, 1);
+ // const scale = Util.lerp(0.94, 1, scaleProgress);
+ // w.set_scale(scale, scale);
// if we disable workspaces that we can't or don't need to see, transition animations will be noticeably smoother
// only the current ws needs to be visible during overview transition animations
@@ -210,22 +219,28 @@ const WorkspacesViewCommon = {
// after transition from APP_GRID to WINDOW_PICKER state,
// adjacent workspaces are hidden and we need them to show up
// make them visible during animation can impact smoothness of the animation
- // so we show them after the animation finished, scaling animation will make impression that they move in from outside the monitor
+ // so we show them after the animation finished, move them to their position from outside of the monitor
if (!w.visible && distanceToCurrentWorkspace === 1 && initialState === ControlsState.APP_GRID && currentState === ControlsState.WINDOW_PICKER) {
- w.scale_x = scaleX;
- w.scale_y = scaleY;
w.visible = true;
+ const directionNext = distance > 0;
+ if (!opt.ORIENTATION) {
+ const width = w.width * 0.6 * opt.WS_PREVIEW_SCALE;
+ w.translation_x = directionNext ? -width : width;
+ }
+ if (opt.ORIENTATION) {
+ const height = w.height * 0.6 * opt.WS_PREVIEW_SCALE;
+ w.translation_y = directionNext ? -height : height;
+ }
+
+ w.opacity = 10;
+ w.get_parent().set_child_below_sibling(w, null);
w.ease({
- duration: 100,
- scale_x: 1,
- scale_y: 1,
+ duration: 300,
+ translation_x: 0,
+ translation_y: 0,
+ opacity: 255,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
- } else if (!w.visible && distanceToCurrentWorkspace <= opt.NUMBER_OF_VISIBLE_NEIGHBORS && currentState === ControlsState.WINDOW_PICKER) {
- w.set({
- scale_x: 1,
- scale_y: 1,
- });
}
// force ws preview bg corner radiuses where GS doesn't do it
@@ -238,9 +253,40 @@ const WorkspacesViewCommon = {
w._background.opacity = 0;
});
},
+
+ exposeWindows(workspaceIndex = null, callback) {
+ let adjustments = [];
+ if (workspaceIndex === null) {
+ this._workspaces.forEach(ws => {
+ adjustments.push(ws._background._stateAdjustment);
+ });
+ } else {
+ adjustments.push(this._workspaces[workspaceIndex]._background._stateAdjustment);
+ }
+
+ adjustments.forEach(adj => {
+ if (adj.value === 0) {
+ adj.value = 0;
+ adj.ease(1, {
+ duration: 200,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ onComplete: () => {
+ opt.WORKSPACE_MODE = 1;
+ if (callback)
+ callback();
+ },
+ });
+ }
+ });
+ },
+};
+
+const SecondaryMonitorDisplayCommon = {
+ exposeWindows(...args) {
+ this._workspacesView.exposeWindows(...args);
+ },
};
-// SecondaryMonitorDisplay Vertical
const SecondaryMonitorDisplayVertical = {
_getThumbnailParamsForState(state) {
@@ -270,24 +316,6 @@ const SecondaryMonitorDisplayVertical = {
return { opacity, scale, translationX };
},
- _getThumbnailsWidth(box, spacing) {
- if (opt.SEC_WS_TMB_HIDDEN)
- return 0;
-
- const [width, height] = box.get_size();
- const { expandFraction } = this._thumbnails;
- const [, thumbnailsWidth] = this._thumbnails.get_preferred_custom_width(height - 2 * spacing);
- let scaledWidth;
- if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED)
- scaledWidth = ((height - Main.panel.height) * opt.SEC_MAX_THUMBNAIL_SCALE) * (width / height);
- else
- scaledWidth = width * opt.SEC_MAX_THUMBNAIL_SCALE;
-
- return Math.min(
- thumbnailsWidth * expandFraction,
- Math.round(scaledWidth));
- },
-
_getWorkspacesBoxForState(state, box, padding, thumbnailsWidth, spacing) {
// const { ControlsState } = OverviewControls;
const workspaceBox = box.copy();
@@ -303,7 +331,7 @@ const SecondaryMonitorDisplayVertical = {
break;
yShift = 0;
- if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED) {
+ if (opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible) {
if (opt.PANEL_POSITION_TOP)
yShift = Main.panel.height;
else
@@ -341,26 +369,40 @@ const SecondaryMonitorDisplayVertical = {
const spacing = themeNode.get_length('spacing') * expandFraction;
const padding = Math.round(0.1 * height);
- let thumbnailsWidth = this._getThumbnailsWidth(contentBox, spacing);
- let [, thumbnailsHeight] = this._thumbnails.get_preferred_custom_height(thumbnailsWidth);
- thumbnailsHeight = Math.min(thumbnailsHeight, height - 2 * spacing);
-
+ let thumbnailsWidth = 0;
+ let thumbnailsHeight = 0;
this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
if (this._thumbnails.visible) {
+ const reduceBoxHeight = opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible ? Main.panel.height : 0;
+
+ thumbnailsWidth = width * opt.SEC_MAX_THUMBNAIL_SCALE;
+
+ let totalTmbSpacing;
+ [totalTmbSpacing, thumbnailsHeight] = this._thumbnails.get_preferred_height(thumbnailsWidth);
+ thumbnailsHeight = Math.round(thumbnailsHeight + totalTmbSpacing);
+
+ const thumbnailsHeightMax = height - spacing - reduceBoxHeight;
+
+ if (thumbnailsHeight > thumbnailsHeightMax) {
+ thumbnailsHeight = thumbnailsHeightMax;
+ thumbnailsWidth = Math.round(this._thumbnails.get_preferred_width(thumbnailsHeight)[1]);
+ }
+
let wsTmbX;
if (opt.SEC_WS_TMB_LEFT) { // left
- wsTmbX = Math.round(spacing / 4);
+ wsTmbX = spacing / 2;
this._thumbnails._positionLeft = true;
} else {
- wsTmbX = Math.round(width - spacing / 4 - thumbnailsWidth);
+ wsTmbX = width - spacing / 2 - thumbnailsWidth;
this._thumbnails._positionLeft = false;
}
const childBox = new Clutter.ActorBox();
- const availSpace = height - thumbnailsHeight - 2 * spacing;
+ const availSpace = height - thumbnailsHeight;
let wsTmbY = availSpace / 2;
- wsTmbY -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbY - spacing;
+ wsTmbY -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbY;
+ wsTmbY += opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible ? Main.panel.height : 0;
childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY));
childBox.set_size(thumbnailsWidth, thumbnailsHeight);
@@ -390,22 +432,14 @@ const SecondaryMonitorDisplayVertical = {
if (opt.OVERVIEW_MODE2)
this.set_child_above_sibling(this._thumbnails, null);
-
const visible = !opt.SEC_WS_TMB_HIDDEN;
if (this._thumbnails.visible === visible)
return;
this._thumbnails.show();
+ this._thumbnails.visible = visible;
this._updateThumbnailParams();
- this._thumbnails.ease_property('expand-fraction', visible ? 1 : 0, {
- duration: SIDE_CONTROLS_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- this._thumbnails.visible = visible;
- this._thumbnails._indicator.visible = visible;
- },
- });
},
_updateThumbnailParams() {
@@ -417,7 +451,6 @@ const SecondaryMonitorDisplayVertical = {
if (!this._thumbnails._thumbnails.length)
this._thumbnails._createThumbnails();
-
const { initialState, finalState, progress } =
this._overviewAdjustment.getStateTransitionParams();
@@ -474,7 +507,6 @@ const SecondaryMonitorDisplayVertical = {
},
};
-// SecondaryMonitorDisplay Horizontal
const SecondaryMonitorDisplayHorizontal = {
_getThumbnailParamsForState(state) {
// const { ControlsState } = OverviewControls;
@@ -520,7 +552,7 @@ const SecondaryMonitorDisplayHorizontal = {
break;
yShift = 0;
- if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED) {
+ if (opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible) {
if (opt.PANEL_POSITION_TOP)
yShift = Main.panel.height;
else
@@ -571,24 +603,36 @@ const SecondaryMonitorDisplayHorizontal = {
const spacing = themeNode.get_length('spacing') * expandFraction;
const padding = Math.round(0.1 * height);
- let thumbnailsHeight = this._getThumbnailsHeight(contentBox);
- let [, thumbnailsWidth] = this._thumbnails.get_preferred_custom_width(thumbnailsHeight);
- thumbnailsWidth = Math.min(thumbnailsWidth, width - 2 * spacing);
-
+ let thumbnailsWidth = 0;
+ let thumbnailsHeight = 0;
this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
if (this._thumbnails.visible) {
+ const reservedHeight = opt.SEC_WS_PREVIEW_SHIFT && Main.panel.visible ? Main.panel.height : 0;
+
+ thumbnailsHeight = height * opt.SEC_MAX_THUMBNAIL_SCALE;
+
+ let totalTmbSpacing;
+ [totalTmbSpacing, thumbnailsWidth] = this._thumbnails.get_preferred_width(thumbnailsHeight);
+ thumbnailsWidth = Math.round(thumbnailsWidth + totalTmbSpacing);
+
+ const thumbnailsWidthMax = width - spacing;
+
+ if (thumbnailsWidth > thumbnailsWidthMax) {
+ thumbnailsWidth = thumbnailsWidthMax;
+ thumbnailsHeight = Math.round(this._thumbnails.get_preferred_height(thumbnailsWidth)[1]);
+ }
+
let wsTmbY;
if (opt.SEC_WS_TMB_TOP)
- wsTmbY = Math.round(spacing / 4);
+ wsTmbY = spacing / 2 + reservedHeight;
else
- wsTmbY = Math.round(height - spacing / 4 - thumbnailsHeight);
-
+ wsTmbY = height - spacing / 2 - thumbnailsHeight;
const childBox = new Clutter.ActorBox();
- const availSpace = width - thumbnailsWidth - 2 * spacing;
+ const availSpace = width - thumbnailsWidth;
let wsTmbX = availSpace / 2;
- wsTmbX -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbX - spacing;
+ wsTmbX -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbX;
childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY));
childBox.set_size(thumbnailsWidth, thumbnailsHeight);
@@ -625,7 +669,6 @@ const SecondaryMonitorDisplayHorizontal = {
if (!this._thumbnails._thumbnails.length)
this._thumbnails._createThumbnails();
-
const { initialState, finalState, progress } =
this._overviewAdjustment.getStateTransitionParams();
@@ -682,7 +725,7 @@ const SecondaryMonitorDisplayHorizontal = {
},
};
-const ExtraWorkspaceView = {
+const ExtraWorkspaceViewCommon = {
_updateWorkspaceMode() {
const overviewState = this._overviewAdjustment.value;
@@ -701,9 +744,23 @@ const ExtraWorkspaceView = {
if (!opt.SHOW_WS_PREVIEW_BG && this._workspace._background.opacity)
this._workspace._background.opacity = 0;
},
+
+ exposeWindows() {
+ const adjustment = this._workspace._background._stateAdjustment;
+ if (adjustment.value === 0) {
+ adjustment.value = 0;
+ adjustment.ease(1, {
+ duration: 200,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ onComplete: () => {
+ opt.WORKSPACE_MODE = 1;
+ },
+ });
+ }
+ },
};
-const WorkspacesDisplay = {
+const WorkspacesDisplayCommon = {
_updateWorkspacesViews() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy();
@@ -761,8 +818,8 @@ const WorkspacesDisplay = {
return Clutter.EVENT_STOP;
}
- if (_Util.isShiftPressed()) {
- let direction = _Util.getScrollDirection(event);
+ if (Me.Util.isShiftPressed()) {
+ let direction = Me.Util.getScrollDirection(event);
if (direction === null || (Date.now() - this._lastScrollTime) < 150)
return Clutter.EVENT_STOP;
this._lastScrollTime = Date.now();
@@ -775,11 +832,11 @@ const WorkspacesDisplay = {
else
direction = 0;
-
if (direction) {
- _Util.reorderWorkspace(direction);
+ Me.Util.reorderWorkspace(direction);
// make all workspaces on primary monitor visible for case the new position is hidden
- Main.overview._overview._controls._workspacesDisplay._workspacesViews[0]._workspaces.forEach(w => {
+ const primaryMonitorIndex = global.display.get_primary_monitor();
+ Main.overview._overview._controls._workspacesDisplay._workspacesViews[primaryMonitorIndex]._workspaces.forEach(w => {
w.visible = true;
});
return Clutter.EVENT_STOP;
@@ -806,7 +863,7 @@ const WorkspacesDisplay = {
switch (symbol) {
case Clutter.KEY_Return:
case Clutter.KEY_KP_Enter:
- if (_Util.isCtrlPressed()) {
+ if (Me.Util.isCtrlPressed()) {
Main.ctrlAltTabManager._items.forEach(i => {
if (i.sortGroup === 1 && i.name === 'Dash')
Main.ctrlAltTabManager.focusGroup(i);
@@ -836,17 +893,17 @@ const WorkspacesDisplay = {
which = workspaceManager.n_workspaces - 1;
break;
case Clutter.KEY_space:
- if (_Util.isCtrlPressed() && _Util.isShiftPressed()) {
- _Util.openPreferences();
- } else if (_Util.isAltPressed()) {
+ if (Me.Util.isCtrlPressed() && Me.Util.isShiftPressed()) {
+ Me.Util.activateSearchProvider(Me.ESP_PREFIX);
+ } else if (Me.Util.isAltPressed()) {
Main.ctrlAltTabManager._items.forEach(i => {
if (i.sortGroup === 1 && i.name === 'Dash')
Main.ctrlAltTabManager.focusGroup(i);
});
- } else if (opt.RECENT_FILES_SEARCH_PROVIDER_ENABLED && _Util.isCtrlPressed()) {
- _Util.activateSearchProvider(SEARCH_RECENT_FILES_PREFIX);
- } else if (opt.WINDOW_SEARCH_PROVIDER_ENABLED) {
- _Util.activateSearchProvider(SEARCH_WINDOWS_PREFIX);
+ } else if (opt.get('recentFilesSearchProviderModule') && Me.Util.isCtrlPressed()) {
+ Me.Util.activateSearchProvider(Me.RFSP_PREFIX);
+ } else if (opt.get('windowSearchProviderModule')) {
+ Me.Util.activateSearchProvider(Me.WSP_PREFIX);
}
return Clutter.EVENT_STOP;
@@ -867,16 +924,18 @@ const WorkspacesDisplay = {
});
} else if (opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE && state === 1) {
// expose windows for OVERVIEW_MODE 1
- const adjustment = this._workspacesViews[0]._workspaces[global.workspace_manager.get_active_workspace().index()]._background._stateAdjustment;
- opt.WORKSPACE_MODE = 1;
- _Util.exposeWindows(adjustment, true);
+ const wsIndex = global.workspace_manager.get_active_workspace().index();
+ // after expose animation activate keyboard for window selection
+ const callback = Me.Util.activateKeyboardForWorkspaceView;
+ this._workspacesViews.forEach(
+ view => {
+ view.exposeWindows(wsIndex, callback);
+ }
+ );
} else {
if (state === 2)
return Clutter.EVENT_PROPAGATE;
- Main.ctrlAltTabManager._items.forEach(i => {
- if (i.sortGroup === 1 && i.name === 'Windows')
- Main.ctrlAltTabManager.focusGroup(i);
- });
+ Me.Util.activateKeyboardForWorkspaceView();
}
return Clutter.EVENT_STOP;
@@ -895,14 +954,14 @@ const WorkspacesDisplay = {
// Otherwise it is a workspace index
ws = workspaceManager.get_workspace_by_index(which);
- if (_Util.isShiftPressed()) {
+ if (Me.Util.isShiftPressed()) {
let direction;
if (which === Meta.MotionDirection.UP || which === Meta.MotionDirection.LEFT)
direction = -1;
else if (which === Meta.MotionDirection.DOWN || which === Meta.MotionDirection.RIGHT)
direction = 1;
if (direction)
- _Util.reorderWorkspace(direction);
+ Me.Util.reorderWorkspace(direction);
// make all workspaces on primary monitor visible for case the new position is hidden
Main.overview._overview._controls._workspacesDisplay._workspacesViews[0]._workspaces.forEach(w => {
w.visible = true;