summaryrefslogtreecommitdiffstats
path: root/extensions/vertical-workspaces/lib
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/vertical-workspaces/lib')
-rw-r--r--extensions/vertical-workspaces/lib/appDisplay.js1474
-rw-r--r--extensions/vertical-workspaces/lib/appFavorites.js61
-rw-r--r--extensions/vertical-workspaces/lib/dash.js1186
-rw-r--r--extensions/vertical-workspaces/lib/iconGrid.js314
-rw-r--r--extensions/vertical-workspaces/lib/layout.js380
-rw-r--r--extensions/vertical-workspaces/lib/messageTray.js67
-rw-r--r--extensions/vertical-workspaces/lib/optionsFactory.js645
-rw-r--r--extensions/vertical-workspaces/lib/osdWindow.js93
-rw-r--r--extensions/vertical-workspaces/lib/overlayKey.js108
-rw-r--r--extensions/vertical-workspaces/lib/overview.js59
-rw-r--r--extensions/vertical-workspaces/lib/overviewControls.js1464
-rw-r--r--extensions/vertical-workspaces/lib/panel.js197
-rw-r--r--extensions/vertical-workspaces/lib/recentFilesSearchProvider.js260
-rw-r--r--extensions/vertical-workspaces/lib/search.js206
-rw-r--r--extensions/vertical-workspaces/lib/settings.js469
-rw-r--r--extensions/vertical-workspaces/lib/swipeTracker.js87
-rw-r--r--extensions/vertical-workspaces/lib/util.js364
-rw-r--r--extensions/vertical-workspaces/lib/windowAttentionHandler.js90
-rw-r--r--extensions/vertical-workspaces/lib/windowManager.js217
-rw-r--r--extensions/vertical-workspaces/lib/windowPreview.js379
-rw-r--r--extensions/vertical-workspaces/lib/windowSearchProvider.js305
-rw-r--r--extensions/vertical-workspaces/lib/workspace.js152
-rw-r--r--extensions/vertical-workspaces/lib/workspaceAnimation.js184
-rw-r--r--extensions/vertical-workspaces/lib/workspaceSwitcherPopup.js90
-rw-r--r--extensions/vertical-workspaces/lib/workspaceThumbnail.js1148
-rw-r--r--extensions/vertical-workspaces/lib/workspacesView.js934
26 files changed, 0 insertions, 10933 deletions
diff --git a/extensions/vertical-workspaces/lib/appDisplay.js b/extensions/vertical-workspaces/lib/appDisplay.js
deleted file mode 100644
index 2ac70b1..0000000
--- a/extensions/vertical-workspaces/lib/appDisplay.js
+++ /dev/null
@@ -1,1474 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * appDisplay.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { Clutter, GLib, GObject, Meta, Shell, St, Graphene, Pango } = imports.gi;
-
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
-const AppDisplay = imports.ui.appDisplay;
-const IconGrid = imports.ui.iconGrid;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-const IconGridOverride = Me.imports.lib.iconGrid;
-const _Util = Me.imports.lib.util;
-
-const DIALOG_SHADE_NORMAL = Clutter.Color.from_pixel(0x00000022);
-const DIALOG_SHADE_HIGHLIGHT = Clutter.Color.from_pixel(0x00000000);
-
-// gettext
-const _ = Me.imports.lib.settings._;
-
-let _overrides;
-
-let _appGridLayoutSettings;
-let _appDisplayScrollConId;
-let _appSystemStateConId;
-let _appGridLayoutConId;
-let _origAppViewItemAcceptDrop;
-let _updateFolderIcons;
-
-let opt;
-let shellVersion = _Util.shellVersion;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('appDisplayModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
- if (reset) {
- _setAppDisplayOrientation(false);
- _updateAppGridProperties(reset);
- _updateAppGridDND(reset);
- _restoreOverviewGroup();
- _overrides = null;
- opt = null;
- return;
- }
-
- _overrides = new _Util.Overrides();
-
- if (opt.ORIENTATION === Clutter.Orientation.VERTICAL) {
- _overrides.addOverride('AppDisplayVertical', AppDisplay.AppDisplay.prototype, AppDisplayVertical);
- _overrides.addOverride('BaseAppViewVertical', AppDisplay.BaseAppView.prototype, BaseAppViewVertical);
- }
-
- // 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);
- }
- _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);
- } 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 {
- 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');
- }
-
- // 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;
- }
-
- // 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;
- }
- appDisplay._redisplay();
-
- 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);
- }
-
- 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;`);
-
- // 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();
- }
-}
-
-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();
- }
- );
- }
- } else if (_appSystemStateConId) {
- Shell.AppSystem.get_default().disconnect(_appSystemStateConId);
- _appSystemStateConId = 0;
- }
- 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;
- }
-}
-
-function _restoreOverviewGroup() {
- Main.overview.dash.showAppsButton.checked = false;
- Main.layoutManager.overviewGroup.opacity = 255;
- Main.layoutManager.overviewGroup.scale_x = 1;
- Main.layoutManager.overviewGroup.hide();
-}
-
-const AppDisplayVertical = {
- // correction of the appGrid size when page indicators were moved from the bottom to the right
- adaptToSize(width, height) {
- const [, indicatorWidth] = this._pageIndicators.get_preferred_width(-1);
- width -= indicatorWidth;
-
- this._grid.findBestModeForSize(width, height);
-
- const adaptToSize = AppDisplay.BaseAppView.prototype.adaptToSize.bind(this);
- adaptToSize(width, height);
- },
-};
-
-const AppDisplayCommon = {
- _ensureDefaultFolders() {
- // disable creation of default folders if user deleted them
- },
-
- _redisplay() {
- this._folderIcons.forEach(icon => {
- icon.view._redisplay();
- });
-
- BaseAppViewCommon._redisplay.bind(this)();
- },
-
- // apps load adapted for custom sorting and including dash items
- _loadApps() {
- let appIcons = [];
- const runningApps = Shell.AppSystem.get_default().get_running().map(a => a.id);
-
- this._appInfoList = Shell.AppSystem.get_default().get_installed().filter(appInfo => {
- try {
- appInfo.get_id(); // catch invalid file encodings
- } catch (e) {
- return false;
- }
-
- const appIsRunning = runningApps.includes(appInfo.get_id());
- const appIsFavorite = this._appFavorites.isFavorite(appInfo.get_id());
- const excludeApp = (opt.APP_GRID_EXCLUDE_RUNNING && appIsRunning) || (opt.APP_GRID_EXCLUDE_FAVORITES && appIsFavorite);
-
- return this._parentalControlsManager.shouldShowApp(appInfo) && !excludeApp;
- });
-
- let apps = this._appInfoList.map(app => app.get_id());
-
- let appSys = Shell.AppSystem.get_default();
-
- const appsInsideFolders = new Set();
- this._folderIcons = [];
- if (!opt.APP_GRID_ORDER) {
- let folders = this._folderSettings.get_strv('folder-children');
- folders.forEach(id => {
- let path = `${this._folderSettings.path}folders/${id}/`;
- let icon = this._items.get(id);
- if (!icon) {
- icon = new AppDisplay.FolderIcon(id, path, this);
- icon.connect('apps-changed', () => {
- this._redisplay();
- this._savePages();
- });
- icon.connect('notify::pressed', () => {
- if (icon.pressed)
- this.updateDragFocus(icon);
- });
- } else if (_updateFolderIcons && opt.APP_GRID_EXCLUDE_RUNNING) {
- // if any app changed its running state, update folder icon
- icon.icon.update();
- }
-
- // remove empty folder icons
- if (!icon.visible) {
- icon.destroy();
- return;
- }
-
- appIcons.push(icon);
- this._folderIcons.push(icon);
-
- icon.getAppIds().forEach(appId => appsInsideFolders.add(appId));
- });
- }
- // reset request to update active icon
- _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
- // the app picker, so there's no other need for a drag to start,
- // at least on single-monitor setups.
- // This also disables drag-to-launch on multi-monitor setups,
- // but we hope that is not used much.
- const isDraggable =
- global.settings.is_writable('favorite-apps') ||
- global.settings.is_writable('app-picker-layout');
-
- apps.forEach(appId => {
- if (!opt.APP_GRID_ORDER && appsInsideFolders.has(appId))
- return;
-
- let icon = this._items.get(appId);
- if (!icon) {
- let app = appSys.lookup_app(appId);
- icon = new AppDisplay.AppIcon(app, { isDraggable });
- icon.connect('notify::pressed', () => {
- if (icon.pressed)
- this.updateDragFocus(icon);
- });
- }
-
- appIcons.push(icon);
- });
-
- // At last, if there's a placeholder available, add it
- if (this._placeholder)
- appIcons.push(this._placeholder);
-
- return appIcons;
- },
-
- // support active preview icons
- _onDragBegin(overview, source) {
- if (source._sourceItem)
- source = source._sourceItem;
-
- this._dragMonitor = {
- dragMotion: this._onDragMotion.bind(this),
- };
- DND.addDragMonitor(this._dragMonitor);
- if (shellVersion < 43)
- this._slideSidePages(AppDisplay.SidePages.PREVIOUS | AppDisplay.SidePages.NEXT | AppDisplay.SidePages.DND);
- else
- this._appGridLayout.showPageIndicators();
- this._dragFocus = null;
- this._swipeTracker.enabled = false;
-
- // When dragging from a folder dialog, the dragged app icon doesn't
- // exist in AppDisplay. We work around that by adding a placeholder
- // icon that is either destroyed on cancel, or becomes the effective
- // new icon when dropped.
- if (AppDisplay._getViewFromIcon(source) instanceof AppDisplay.FolderView ||
- (opt.APP_GRID_EXCLUDE_FAVORITES && this._appFavorites.isFavorite(source.id)))
- this._ensurePlaceholder(source);
- },
-
- _ensurePlaceholder(source) {
- if (this._placeholder)
- return;
-
- if (source._sourceItem)
- source = source._sourceItem;
-
- const appSys = Shell.AppSystem.get_default();
- const app = appSys.lookup_app(source.id);
-
- const isDraggable =
- global.settings.is_writable('favorite-apps') ||
- global.settings.is_writable('app-picker-layout');
-
- this._placeholder = new AppDisplay.AppIcon(app, { isDraggable });
- this._placeholder.connect('notify::pressed', () => {
- if (this._placeholder?.pressed)
- this.updateDragFocus(this._placeholder);
- });
- this._placeholder.scaleAndFade();
- this._redisplay();
- },
-
- // accept source from active preview
- acceptDrop(source) {
- if (opt.APP_GRID_ORDER)
- return false;
- if (source._sourceItem)
- source = source._sourceItem;
-
- let dropTarget = null;
- if (shellVersion >= 43) {
- dropTarget = this._dropTarget;
- delete this._dropTarget;
- }
-
- if (!this._canAccept(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);
- if (view instanceof AppDisplay.FolderView)
- view.removeApp(source.app);
-
- if (this._currentDialog)
- this._currentDialog.popdown();
-
- if (opt.APP_GRID_EXCLUDE_FAVORITES && this._appFavorites.isFavorite(source.id))
- this._appFavorites.removeFavorite(source.id);
-
- return true;
- },
-};
-
-const BaseAppViewVertical = {
- after__init() {
- this._grid.layoutManager._orientation = Clutter.Orientation.VERTICAL;
- this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.EXTERNAL);
- this._orientation = Clutter.Orientation.VERTICAL;
- this._swipeTracker.orientation = Clutter.Orientation.VERTICAL;
- this._swipeTracker._reset();
- this._pageIndicators.vertical = true;
- this._box.vertical = false;
- this._pageIndicators.x_expand = false;
- this._pageIndicators.y_align = Clutter.ActorAlign.CENTER;
- this._pageIndicators.x_align = Clutter.ActorAlign.START;
- this._pageIndicators.set_style('margin-right: 10px;');
- const scrollContainer = this._scrollView.get_parent();
- if (shellVersion < 43) {
- // remove touch friendly side navigation bars / arrows
- if (this._hintContainer && this._hintContainer.get_parent())
- scrollContainer.remove_child(this._hintContainer);
- } else {
- // moving these bars needs more patching of the this's code
- // for now we just change bars style to be more like vertically oriented arrows indicating direction to prev/next page
- this._nextPageIndicator.add_style_class_name('nextPageIndicator');
- this._prevPageIndicator.add_style_class_name('prevPageIndicator');
- }
-
- // setting their x_scale to 0 removes the arrows and avoid allocation issues compared to .hide() them
- this._nextPageArrow.scale_x = 0;
- this._prevPageArrow.scale_x = 0;
-
- this._adjustment = this._scrollView.vscroll.adjustment;
-
- this._adjustment.connect('notify::value', adj => {
- const value = adj.value / adj.page_size;
- this._pageIndicators.setCurrentPosition(value);
- });
- },
- // <= 42 only, this fixes dnd from appDisplay to the workspace thumbnail on the left if appDisplay is on page 1 because of appgrid left overshoot
- _pageForCoords() {
- return AppDisplay.SidePages.NONE;
- },
-};
-
-const BaseAppViewCommon = {
- _sortOrderedItemsAlphabetically(icons = null) {
- if (!icons)
- icons = this._orderedItems;
- icons.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
- },
-
- _setLinearPositions(icons) {
- const { itemsPerPage } = this._grid;
- icons.forEach((icon, i) => {
- const page = Math.floor(i / itemsPerPage);
- const position = i % itemsPerPage;
- try {
- this._moveItem(icon, page, position);
- } catch (e) {
- log(`Warning:${e}`);
- }
- });
- },
-
- // adds sorting options and option to add favorites and running apps
- _redisplay() {
- let oldApps = this._orderedItems.slice();
- let oldAppIds = oldApps.map(icon => icon.id);
-
- let newApps = this._loadApps().sort(this._compareItems.bind(this));
- let newAppIds = newApps.map(icon => icon.id);
-
- let addedApps = newApps.filter(icon => !oldAppIds.includes(icon.id));
- let removedApps = oldApps.filter(icon => !newAppIds.includes(icon.id));
-
- // Remove old app icons
- removedApps.forEach(icon => {
- this._removeItem(icon);
- icon.destroy();
- });
-
- // Add new app icons, or move existing ones
- newApps.forEach(icon => {
- const [page, position] = this._getItemPosition(icon);
- if (addedApps.includes(icon)) {
- this._addItem(icon, page, position);
- } else if (page !== -1 && position !== -1) {
- this._moveItem(icon, page, position);
- } else {
- // App is part of a folder
- }
- });
-
- // sort all alphabetically
- if (opt.APP_GRID_ORDER > 0) {
- // const { itemsPerPage } = this._grid;
- let appIcons = this._orderedItems;
- 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)
- appIcons.sort((a, b) => Shell.AppUsage.get_default().compare(a.app.id, b.app.id));
-
- // sort favorites first
- if (opt.APP_GRID_DASH_FIRST) {
- const fav = Object.keys(this._appFavorites._favorites);
- appIcons.sort((a, b) => {
- let aFav = fav.indexOf(a.id);
- if (aFav < 0)
- aFav = 999;
- let bFav = fav.indexOf(b.id);
- if (bFav < 0)
- bFav = 999;
- return bFav < aFav;
- });
- }
-
- // sort running first
- if (opt.APP_GRID_DASH_FIRST)
- appIcons.sort((a, b) => a.app.get_state() !== Shell.AppState.RUNNING && b.app.get_state() === Shell.AppState.RUNNING);
-
- this._setLinearPositions(appIcons);
-
- this._orderedItems = appIcons;
- }
-
- this.emit('view-loaded');
- if (!opt.APP_GRID_ALLOW_INCOMPLETE_PAGES) {
- for (let i = 0; i < this._grid.nPages; i++)
- this._grid.layoutManager._fillItemVacancies(i);
- }
- },
-
- _canAccept(source) {
- return opt.APP_GRID_ORDER ? false : source instanceof AppDisplay.AppViewItem;
- },
-
- // support active preview icons
- acceptDrop(source) {
- if (!this._canAccept(source))
- return false;
-
- if (source._sourceItem)
- source = source._sourceItem;
-
-
- 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;
-
- this._moveItem(source, page, position);
- this.goToPage(page);
- } else if (this._delayedMoveData) {
- // Dropped before the icon was moved
- const { page, position } = this._delayedMoveData;
-
- this._moveItem(source, page, position);
- this._removeDelayedMove();
- }
-
- return true;
- },
-
- // support active preview icons
- _onDragMotion(dragEvent) {
- if (!(dragEvent.source instanceof AppDisplay.AppViewItem))
- return DND.DragMotionResult.CONTINUE;
-
- if (dragEvent.source._sourceItem)
- dragEvent.source = dragEvent.source._sourceItem;
-
- const appIcon = dragEvent.source;
-
- if (shellVersion < 43) {
- this._dropPage = this._pageForCoords(dragEvent.x, dragEvent.y);
- if (this._dropPage &&
- this._dropPage === AppDisplay.SidePages.PREVIOUS &&
- this._grid.currentPage === 0) {
- delete this._dropPage;
- return DND.DragMotionResult.NO_DROP;
- }
- }
-
- if (appIcon instanceof AppDisplay.AppViewItem) {
- if (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.
- this._handleDragOvershoot(dragEvent);
- } else if (!this._dragMaybeSwitchPageImmediately(dragEvent)) {
- // Two ways of switching pages during DND:
- // 1) When "bumping" the cursor against the monitor edge, we switch
- // page immediately.
- // 2) When hovering over the next-page indicator for a certain time,
- // we also switch page.
-
- const { targetActor } = dragEvent;
-
- if (targetActor === this._prevPageIndicator ||
- targetActor === this._nextPageIndicator)
- this._maybeSetupDragPageSwitchInitialTimeout(dragEvent);
- else
- this._resetDragPageSwitch();
- }
- }
-
- this._maybeMoveItem(dragEvent);
-
- return DND.DragMotionResult.CONTINUE;
- },
-
- // adjustable page width for GS <= 42
- adaptToSize(width, height, isFolder = false) {
- let box = new Clutter.ActorBox({
- x2: width,
- y2: height,
- });
- box = this.get_theme_node().get_content_box(box);
- box = this._scrollView.get_theme_node().get_content_box(box);
- box = this._grid.get_theme_node().get_content_box(box);
-
- const availWidth = box.get_width();
- const availHeight = box.get_height();
-
- let pageWidth, pageHeight;
-
- pageHeight = availHeight;
- pageWidth = Math.ceil(availWidth * (isFolder ? 1 : opt.APP_GRID_PAGE_WIDTH_SCALE));
- // subtract space for navigation arrows in horizontal mode
- pageWidth -= opt.ORIENTATION ? 0 : 128;
-
- this._grid.layout_manager.pagePadding.left =
- Math.floor(availWidth * 0.02);
- this._grid.layout_manager.pagePadding.right =
- Math.ceil(availWidth * 0.02);
-
- this._grid.adaptToSize(pageWidth, pageHeight);
-
- const leftPadding = Math.floor(
- (availWidth - this._grid.layout_manager.pageWidth) / 2);
- const rightPadding = Math.ceil(
- (availWidth - this._grid.layout_manager.pageWidth) / 2);
- const topPadding = Math.floor(
- (availHeight - this._grid.layout_manager.pageHeight) / 2);
- const bottomPadding = Math.ceil(
- (availHeight - this._grid.layout_manager.pageHeight) / 2);
-
- this._scrollView.content_padding = new Clutter.Margin({
- left: leftPadding,
- right: rightPadding,
- top: topPadding,
- bottom: bottomPadding,
- });
-
- this._availWidth = availWidth;
- this._availHeight = availHeight;
-
- this._pageIndicatorOffset = leftPadding;
- this._pageArrowOffset = Math.max(
- leftPadding - 80, 0); // 80 is AppDisplay.PAGE_PREVIEW_MAX_ARROW_OFFSET
- },
-};
-
-const BaseAppViewGridLayout = {
- _getIndicatorsWidth(box) {
- const [width, height] = box.get_size();
- const arrows = [
- this._nextPageArrow,
- this._previousPageArrow,
- ];
-
- const minArrowsWidth = arrows.reduce(
- (previousWidth, accessory) => {
- const [min] = accessory.get_preferred_width(height);
- return Math.max(previousWidth, min);
- }, 0);
-
- const idealIndicatorWidth = (width * 0.1/* PAGE_PREVIEW_RATIO*/) / 2;
-
- return Math.max(idealIndicatorWidth, minArrowsWidth);
- },
-};
-
-const FolderIcon = {
- after__init() {
- /* // If folder preview icons are clickable,
- // disable opening the folder with primary mouse button and enable the secondary one
- const buttonMask = opt.APP_GRID_ACTIVE_PREVIEW
- ? St.ButtonMask.TWO | St.ButtonMask.THREE
- : 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();
-
- this.view._scrollView.vscroll.adjustment.value = 0;
- this._dialog.popup();
- },
-};
-
-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;
- return grid;
- },
-
- createFolderIcon(size) {
- const layout = new Clutter.GridLayout({
- row_homogeneous: true,
- column_homogeneous: true,
- });
-
- let icon = new St.Widget({
- layout_manager: layout,
- x_align: Clutter.ActorAlign.CENTER,
- style: `width: ${size}px; height: ${size}px;`,
- });
-
- const numItems = this._orderedItems.length;
- // decide what number of icons switch to 3x3 grid
- // APP_GRID_FOLDER_ICON_GRID: 3 -> more than 4
- // : 4 -> more than 8
- const threshold = opt.APP_GRID_FOLDER_ICON_GRID % 3 ? 8 : 4;
- const gridSize = opt.APP_GRID_FOLDER_ICON_GRID > 2 && numItems > threshold ? 3 : 2;
- const FOLDER_SUBICON_FRACTION = gridSize === 2 ? 0.4 : 0.27;
-
- let subSize = Math.floor(FOLDER_SUBICON_FRACTION * size);
- let rtl = icon.get_text_direction() === Clutter.TextDirection.RTL;
- for (let i = 0; i < gridSize * gridSize; i++) {
- const style = `width: ${subSize}px; height: ${subSize}px;`;
- let bin = new St.Bin({ style, reactive: true });
- bin.pivot_point = new Graphene.Point({ x: 0.5, y: 0.5 });
- if (i < numItems) {
- if (!opt.APP_GRID_ACTIVE_PREVIEW) {
- bin.child = this._orderedItems[i].app.create_icon_texture(subSize);
- } else {
- const app = this._orderedItems[i].app;
- const child = new ActiveFolderIcon(app);
- child._sourceItem = this._orderedItems[i];
- child._sourceFolder = this;
- child.icon.style_class = '';
- child.icon.set_style('margin: 0; padding: 0;');
- child.icon.setIconSize(subSize);
-
- bin.child = child;
-
- bin.connect('enter-event', () => {
- bin.ease({
- duration: 100,
- scale_x: 1.14,
- scale_y: 1.14,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- });
- bin.connect('leave-event', () => {
- bin.ease({
- duration: 100,
- scale_x: 1,
- scale_y: 1,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- });
- }
- }
-
- 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();
-
- return icon;
- },
-
- // this just overrides _redisplay() for GS < 44
- _redisplay() {
- // super._redisplay(); - super doesn't work in my overrides
- AppDisplay.BaseAppView.prototype._redisplay.bind(this)();
- },
-
- _loadApps() {
- this._apps = [];
- const excludedApps = this._folder.get_strv('excluded-apps');
- const appSys = Shell.AppSystem.get_default();
- const addAppId = appId => {
- if (excludedApps.includes(appId))
- return;
-
- if (opt.APP_GRID_EXCLUDE_FAVORITES && this._appFavorites.isFavorite(appId))
- return;
-
- const app = appSys.lookup_app(appId);
- if (!app)
- return;
-
- if (opt.APP_GRID_EXCLUDE_RUNNING) {
- const runningApps = Shell.AppSystem.get_default().get_running().map(a => a.id);
- if (runningApps.includes(appId))
- return;
- }
-
- if (!this._parentalControlsManager.shouldShowApp(app.get_app_info()))
- return;
-
- if (this._apps.indexOf(app) !== -1)
- return;
-
- this._apps.push(app);
- };
-
- const folderApps = this._folder.get_strv('apps');
- folderApps.forEach(addAppId);
-
- const folderCategories = this._folder.get_strv('categories');
- const appInfos = this._parentView.getAppInfos();
- appInfos.forEach(appInfo => {
- let appCategories = AppDisplay._getCategories(appInfo);
- if (!AppDisplay._listsIntersect(folderCategories, appCategories))
- return;
-
- addAppId(appInfo.get_id());
- });
-
- let items = [];
- this._apps.forEach(app => {
- let icon = this._items.get(app.get_id());
- if (!icon)
- icon = new AppDisplay.AppIcon(app);
-
- items.push(icon);
- });
- this._appIds = this._apps.map(app => app.get_id());
- return items;
- },
-
- // 42 only - don't apply appGrid scale on folders
- adaptToSize(width, height) {
- if (!opt.ORIENTATION) {
- const [, indicatorHeight] = this._pageIndicators.get_preferred_height(-1);
- height -= indicatorHeight;
- }
- BaseAppViewCommon.adaptToSize.bind(this)(width, height, true);
- },
-};
-
-// folder columns and rows
-const FolderGrid = GObject.registerClass(
-class FolderGrid extends IconGrid.IconGrid {
- _init() {
- super._init({
- 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
- 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,
- });
-
- // 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;
- }
-
- 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 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,
- },
- ]);
- }
-
- 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() {
- // delegate this dialog to the FolderIcon._view
- // so its _createFolderIcon function can update the dialog if folder content changed
- this._view._dialog = this;
-
- // right click into the folder popup should close it
- this.child.reactive = true;
- const clickAction = new Clutter.ClickAction();
- clickAction.connect('clicked', act => {
- if (act.get_button() === Clutter.BUTTON_PRIMARY)
- return Clutter.EVENT_STOP;
- const [x, y] = clickAction.get_coords();
- const actor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
- // if it's not entry for editing folder title
- if (actor !== this._entry)
- this.popdown();
- return Clutter.EVENT_STOP;
- });
-
- this.child.add_action(clickAction);
- },
-
- 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(),
- });
-
- if (!this._isOpen)
- return;
-
- this.get_parent().set_child_above_sibling(this, null);
-
- this._needsZoomAndFade = true;
- this.show();
-
- this.emit('open-state-changed', true);
- },
-
- _updateFolderSize() {
- // adapt folder size according to the settings and number of icons
- const view = this._view;
- 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 nItems = view._orderedItems.length;
- let columns = opt.APP_GRID_FOLDER_COLUMNS;
- let rows = opt.APP_GRID_FOLDER_ROWS;
- let spacing = opt.APP_GRID_SPACING;
- const monitor = global.display.get_monitor_geometry(global.display.get_primary_monitor());
-
- if (!columns && !rows) {
- columns = Math.ceil(Math.sqrt(nItems));
- rows = columns;
- if (columns * (columns - 1) >= nItems) {
- rows = columns - 1;
- } else if ((columns + 1) * (columns - 1) >= nItems) {
- rows = columns - 1;
- columns += 1;
- }
- } else if (!columns && rows) {
- columns = Math.ceil(nItems / rows);
- } else if (columns && !rows) {
- rows = Math.ceil(nItems / columns);
- }
-
- 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
- // 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;
- firstItem.icon.setIconSize(iconSize);
- const [firstItemWidth] = firstItem.get_preferred_size();
- const realSize = firstItemWidth / scaleFactor;
- if (realSize > iconSize)
- 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;
-
- // folder must fit the primary monitor
- // reduce columns/rows if needed and count with the scaled values
- while (width * scaleFactor > monitor.width - 2 * dialogMargin) {
- width -= itemSize + spacing;
- columns -= 1;
- }
- while (height * scaleFactor > monitor.height - 2 * dialogMargin) {
- height -= itemSize + spacing;
- rows -= 1;
- }
- width = Math.max(540, width);
-
- const layoutManager = view._grid.layoutManager;
- layoutManager.rows_per_page = rows;
- layoutManager.columns_per_page = columns;
-
- // this line is required by GS 43
- view._grid.setGridModes([{ columns, rows }]);
-
- this.child.set_style(`
- width: ${width}px;
- height: ${height}px;
- padding: 30px;
- `);
-
- view._redisplay();
-
- // store original item count
- this._designCapacity = nItems;
- },
-
- _zoomAndFadeIn() {
- let [sourceX, sourceY] =
- this._source.get_transformed_position();
- let [dialogX, dialogY] =
- this.child.get_transformed_position();
-
- const sourceCenterX = sourceX + this._source.width / 2;
- const sourceCenterY = sourceY + this._source.height / 2;
-
- // 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);
-
- // 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
- );
-
- 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());
- dialogTargetX = Math.clamp(
- dialogTargetX,
- this.x + monitor.x,
- this.x + monitor.x + monitor.width - this.child.width
- );
-
- dialogTargetY = Math.clamp(
- dialogTargetY,
- this.y + monitor.y,
- this.y + monitor.y + monitor.height - this.child.height
- );
- }
- const dialogOffsetX = -dialogX + dialogTargetX;
- const dialogOffsetY = -dialogY + dialogTargetY;
-
- this.child.set({
- translation_x: sourceX - dialogX,
- translation_y: sourceY - dialogY,
- scale_x: this._source.width / this.child.width,
- scale_y: this._source.height / this.child.height,
- 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,
- scale_x: 1,
- scale_y: 1,
- 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;
- }
- },
- });
-
- this._needsZoomAndFade = false;
-
- if (this._sourceMappedId === 0) {
- this._sourceMappedId = this._source.connect(
- 'notify::mapped', this._zoomAndFadeOut.bind(this));
- }
- },
-
- _zoomAndFadeOut() {
- if (!this._isOpen)
- return;
-
- if (!this._source.mapped) {
- this.hide();
- 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,
- scale_x: this._source.width / this.child.width,
- scale_y: this._source.height / this.child.height,
- opacity: 0,
- duration: FOLDER_DIALOG_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- this.child.set({
- translation_x: 0,
- translation_y: 0,
- scale_x: 1,
- scale_y: 1,
- opacity: 255,
- });
- this.hide();
-
- this._popdownCallbacks.forEach(func => func());
- this._popdownCallbacks = [];
- },
- });
-
- this._needsZoomAndFade = false;
- },
-
- _setLighterBackground(lighter) {
- const backgroundColor = lighter
- ? DIALOG_SHADE_HIGHLIGHT
- : DIALOG_SHADE_NORMAL;
-
- this.ease({
- 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
- this._updateMultiline();
- },
-
- // avoid accepting by placeholder when dragging active preview
- // and also by icon if alphabet or usage sorting are used
- _canAccept(source) {
- if (source._sourceItem)
- source = source._sourceItem;
- let view = AppDisplay._getViewFromIcon(source);
-
- return source !== this &&
- (source instanceof this.constructor) &&
- (view instanceof AppDisplay.AppDisplay &&
- !opt.APP_GRID_ORDER);
- },
-};
-
-const AppViewItemCommon = {
- _updateMultiline() {
- const { label } = this.icon;
- if (label)
- label.opacity = 255;
- if (!this._expandTitleOnHover || !this.icon.label)
- return;
-
- const { clutterText } = label;
-
- const isHighlighted = this.has_key_focus() || this.hover || this._forcedHighlight;
-
- if (opt.APP_GRID_NAMES_MODE === 2 && this._expandTitleOnHover) { // !_expandTitleOnHover indicates search result icon
- label.opacity = isHighlighted || !this.app ? 255 : 0;
- }
- if (isHighlighted)
- this.get_parent()?.set_child_above_sibling(this, null);
-
- if (!opt.APP_GRID_NAMES_MODE) {
- const layout = clutterText.get_layout();
- if (!layout.is_wrapped() && !layout.is_ellipsized())
- return;
- }
-
- label.remove_transition('allocation');
-
- const id = label.connect('notify::allocation', () => {
- label.restore_easing_state();
- label.disconnect(id);
- });
-
- const expand = opt.APP_GRID_NAMES_MODE === 1 || this._forcedHighlight || this.hover || this.has_key_focus();
-
- label.save_easing_state();
- label.set_easing_duration(expand
- ? AppDisplay.APP_ICON_TITLE_EXPAND_TIME
- : AppDisplay.APP_ICON_TITLE_COLLAPSE_TIME);
- clutterText.set({
- line_wrap: expand,
- line_wrap_mode: expand ? Pango.WrapMode.WORD_CHAR : Pango.WrapMode.NONE,
- ellipsize: expand ? Pango.EllipsizeMode.NONE : Pango.EllipsizeMode.END,
- });
- },
-
- // support active preview icons
- acceptDrop(source, _actor, x) {
- if (opt.APP_GRID_ORDER)
- return DND.DragMotionResult.NO_DROP;
-
- this._setHoveringByDnd(false);
-
- if (!this._canAccept(source))
- return false;
-
- if (this._withinLeeways(x))
- return false;
-
- // added - remove app from the source folder after dnd to other folder
- if (source._sourceItem) {
- const app = source._sourceItem.app;
- source._sourceFolder.removeApp(app);
- }
-
- return true;
- },
-
-};
-
-const ActiveFolderIcon = GObject.registerClass(
-class ActiveFolderIcon extends AppDisplay.AppIcon {
- _init(app) {
- super._init(app, {
- setSizeManually: true,
- showLabel: false,
- });
- }
-
- handleDragOver() {
- return DND.DragMotionResult.CONTINUE;
- }
-
- acceptDrop() {
- return false;
- }
-
- _onDragEnd() {
- this._dragging = false;
- this.undoScaleAndFade();
- Main.overview.endItemDrag(this._sourceItem.icon);
- }
-});
diff --git a/extensions/vertical-workspaces/lib/appFavorites.js b/extensions/vertical-workspaces/lib/appFavorites.js
deleted file mode 100644
index 50ebce9..0000000
--- a/extensions/vertical-workspaces/lib/appFavorites.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * appFavorites.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'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 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;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
-
- // if notifications are enabled no override is needed
- if (reset || opt.SHOW_FAV_NOTIFICATION) {
- _overrides = null;
- opt = null;
- return;
- }
-
- _overrides = new _Util.Overrides();
-
- // AppFavorites.AppFavorites is const, first access returns undefined
- const dummy = AppFavorites.AppFavorites;
- _overrides.addOverride('AppFavorites', AppFavorites.AppFavorites.prototype, AppFavoritesCommon);
-}
-
-const AppFavoritesCommon = {
- addFavoriteAtPos(appId, pos) {
- this._addFavorite(appId, pos);
- },
-
- removeFavorite(appId) {
- this._removeFavorite(appId);
- },
-};
diff --git a/extensions/vertical-workspaces/lib/dash.js b/extensions/vertical-workspaces/lib/dash.js
deleted file mode 100644
index bf832bd..0000000
--- a/extensions/vertical-workspaces/lib/dash.js
+++ /dev/null
@@ -1,1186 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * dash.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022-2023
- * @license GPL-3.0
- * modified dash module of https://github.com/RensAlthuis/vertical-overview extension
- */
-
-const { Clutter, GObject, St, Shell, Meta } = imports.gi;
-const AppDisplay = imports.ui.appDisplay;
-const AppFavorites = imports.ui.appFavorites;
-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._;
-
-const shellVersion = Util.shellVersion;
-let _origWorkId;
-let _newWorkId;
-let _showAppsIconBtnPressId;
-
-// 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;
-
-let _overrides;
-let opt;
-let _firstRun = true;
-
-const DASH_ITEM_LABEL_SHOW_TIME = 150;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('dashModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
-
- const dash = Main.overview._overview._controls.layoutManager._dash;
-
- setToHorizontal();
-
- dash.remove_style_class_name('vertical');
- dash.remove_style_class_name('vertical-left');
- dash.remove_style_class_name('vertical-right');
-
- 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;
- }
-
- _overrides = new Util.Overrides();
-
- _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 (opt.DASH_VERTICAL) {
- _overrides.addOverride('Dash', Dash.Dash.prototype, DashOverride);
- setToVertical();
- dash.add_style_class_name('vertical');
-
- if (!_newWorkId) {
- _origWorkId = dash._workId;
- dash._workId = Main.initializeDeferredWork(dash._box, dash._redisplay.bind(dash));
- _newWorkId = dash._workId;
- } else {
- dash._workId = _newWorkId;
- }
- } else {
- setToHorizontal();
- if (_origWorkId)
- dash._workId = _origWorkId;
- }
-
- _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);
- }
- 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;
- }
-}
-
-function _connectShowAppsIcon(reset = false) {
- if (!reset) {
- if (_showAppsIconBtnPressId || Util.dashIsDashToDock()) {
- // button is already connected || dash is Dash to Dock
- return;
- }
-
- 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;
- }
-}
-
-const DashOverride = {
- 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 boxHeight = this._box.height;
-
- // 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--;
- }
-
- // Same with the separator
- if (this._separator) {
- boxHeight -= this._separator.height;
- numChildren--;
- }
-
- let pos;
- if (!this._emptyDropTarget)
- pos = Math.floor(y * numChildren / boxHeight);
- else
- pos = 0; // always insert at the top when dash is empty
-
- // 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 / 2);
- this._dragPlaceholder.child.set_height(this.iconSize);
- 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;
- },
-
- _redisplay() {
- let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
-
- let running = this._appSystem.get_running();
-
- let children = this._box.get_children().filter(actor => {
- return actor.child &&
- actor.child._delegate &&
- actor.child._delegate.app;
- });
- // Apps currently in the dash
- let oldApps = children.map(actor => actor.child._delegate.app);
- // Apps supposed to be in the dash
- let newApps = [];
-
- for (let id in favorites)
- newApps.push(favorites[id]);
-
- for (let i = 0; i < running.length; i++) {
- let app = running[i];
- if (app.get_id() in favorites)
- continue;
- newApps.push(app);
- }
-
- // Figure out the actual changes to the list of items; we iterate
- // over both the list of items currently in the dash and the list
- // of items expected there, and collect additions and removals.
- // Moves are both an addition and a removal, where the order of
- // the operations depends on whether we encounter the position
- // where the item has been added first or the one from where it
- // was removed.
- // There is an assumption that only one item is moved at a given
- // time; when moving several items at once, everything will still
- // end up at the right position, but there might be additional
- // additions/removals (e.g. it might remove all the launchers
- // and add them back in the new order even if a smaller set of
- // additions and removals is possible).
- // If above assumptions turns out to be a problem, we might need
- // to use a more sophisticated algorithm, e.g. Longest Common
- // Subsequence as used by diff.
- let addedItems = [];
- let removedActors = [];
-
- let newIndex = 0;
- let oldIndex = 0;
- while (newIndex < newApps.length || oldIndex < oldApps.length) {
- let oldApp = oldApps.length > oldIndex ? oldApps[oldIndex] : null;
- let newApp = newApps.length > newIndex ? newApps[newIndex] : null;
-
- // No change at oldIndex/newIndex
- if (oldApp === newApp) {
- oldIndex++;
- newIndex++;
- continue;
- }
-
- // App removed at oldIndex
- if (oldApp && !newApps.includes(oldApp)) {
- removedActors.push(children[oldIndex]);
- oldIndex++;
- continue;
- }
-
- // App added at newIndex
- if (newApp && !oldApps.includes(newApp)) {
- addedItems.push({
- app: newApp,
- item: this._createAppItem(newApp),
- pos: newIndex,
- });
- newIndex++;
- continue;
- }
-
- // App moved
- let nextApp = newApps.length > newIndex + 1
- ? newApps[newIndex + 1] : null;
- let insertHere = nextApp && nextApp === oldApp;
- let alreadyRemoved = removedActors.reduce((result, actor) => {
- let removedApp = actor.child._delegate.app;
- return result || removedApp === newApp;
- }, false);
-
- if (insertHere || alreadyRemoved) {
- let newItem = this._createAppItem(newApp);
- addedItems.push({
- app: newApp,
- item: newItem,
- pos: newIndex + removedActors.length,
- });
- newIndex++;
- } else {
- removedActors.push(children[oldIndex]);
- oldIndex++;
- }
- }
-
- for (let i = 0; i < addedItems.length; i++) {
- this._box.insert_child_at_index(addedItems[i].item,
- addedItems[i].pos);
- }
-
- for (let i = 0; i < removedActors.length; i++) {
- let item = removedActors[i];
-
- // Don't animate item removal when the overview is transitioning
- // or hidden
- if (Main.overview.visible && !Main.overview.animationInProgress)
- item.animateOutAndDestroy();
- else
- item.destroy();
- }
-
- this._adjustIconSize();
-
- // Skip animations on first run when adding the initial set
- // of items, to avoid all items zooming in at once
-
- let animate = this._shownInitially && Main.overview.visible &&
- !Main.overview.animationInProgress;
-
- if (!this._shownInitially)
- this._shownInitially = true;
-
- for (let i = 0; i < addedItems.length; i++)
- addedItems[i].item.show(animate);
-
- // Update separator
- const nFavorites = Object.keys(favorites).length;
- const nIcons = children.length + addedItems.length - removedActors.length;
- if (nFavorites > 0 && nFavorites < nIcons) {
- // destroy the horizontal separator if it exists.
- // this is incredibly janky, but I can't think of a better way atm.
- if (this._separator && this._separator.height !== 1) {
- this._separator.destroy();
- this._separator = null;
- }
-
- if (!this._separator) {
- this._separator = new St.Widget({
- style_class: 'dash-separator',
- x_align: Clutter.ActorAlign.CENTER,
- y_align: Clutter.ActorAlign.CENTER,
- width: this.iconSize,
- height: 1,
- });
- this._box.add_child(this._separator);
- }
-
- // FIXME: separator placement is broken (also in original dash)
- let pos = nFavorites;
- if (this._dragPlaceholder)
- pos++;
- this._box.set_child_at_index(this._separator, pos);
- } else if (this._separator) {
- this._separator.destroy();
- this._separator = null;
- }
- // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
- // Without it, StBoxLayout may use a stale size cache
- this._box.queue_relayout();
- },
-
- _createAppItem(app) {
- 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;
-
- appIcon.connect('menu-state-changed',
- (o, opened) => {
- this._itemMenuStateChanged(item, opened);
- });
-
- let item = new Dash.DashItemContainer();
- item.setChild(appIcon);
-
- // Override default AppIcon label_actor, now the
- // accessible_name is set at DashItemContainer.setLabelText
- appIcon.label_actor = null;
- item.setLabelText(app.get_name());
-
- appIcon.icon.setIconSize(this.iconSize);
- this._hookUpLabel(item, appIcon);
-
- 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
- // as a result, new icons will not reach their full size, or will be missing, if adding a new icon and changing the dash size due to lack of space at the same time
- if (this._adjustingInProgress)
- return;
-
- // For the icon size, we only consider children which are "proper"
- // icons (i.e. ignoring drag placeholders) and which are not
- // animating out (which means they will be destroyed at the end of
- // the animation)
- let iconChildren = this._box.get_children().filter(actor => {
- return actor.child &&
- actor.child._delegate &&
- actor.child._delegate.icon &&
- !actor.animatingOut;
- });
-
- // add new custom icons to the list
- if (this._showAppsIcon.visible)
- iconChildren.push(this._showAppsIcon);
-
- if (this._showWindowsIcon)
- iconChildren.push(this._showWindowsIcon);
-
- if (this._recentFilesIcon)
- iconChildren.push(this._recentFilesIcon);
-
-
- if (!iconChildren.length)
- return;
-
- if (this._maxWidth === -1 || this._maxHeight === -1)
- return;
-
- const dashHorizontal = !opt.DASH_VERTICAL;
-
- const themeNode = this.get_theme_node();
- const maxAllocation = new Clutter.ActorBox({
- x1: 0,
- y1: 0,
- x2: dashHorizontal ? this._maxWidth : 42, // not whatever
- y2: dashHorizontal ? 42 : this._maxHeight,
- });
-
- let maxContent = themeNode.get_content_box(maxAllocation);
-
- let spacing = themeNode.get_length('spacing');
-
- let firstButton = iconChildren[0].child;
- let firstIcon = firstButton._delegate.icon;
-
- if (!firstIcon.icon)
- return;
-
- // Enforce valid spacings during the size request
- firstIcon.icon.ensure_style();
- const [, , iconWidth, iconHeight] = firstIcon.icon.get_preferred_size();
- const [, , buttonWidth, buttonHeight] = firstButton.get_preferred_size();
- let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
-
- let availWidth, availHeight, maxIconSize;
- if (dashHorizontal) {
- availWidth = maxContent.x2 - maxContent.x1;
- // Subtract icon padding and box spacing from the available width
- availWidth -= iconChildren.length * (buttonWidth - iconWidth) +
- (iconChildren.length - 1) * spacing +
- 2 * this._background.get_theme_node().get_horizontal_padding();
-
- availHeight = this._maxHeight;
- availHeight -= this.margin_top + this.margin_bottom;
- availHeight -= this._background.get_theme_node().get_vertical_padding();
- availHeight -= themeNode.get_vertical_padding();
- availHeight -= buttonHeight - iconHeight;
-
- maxIconSize = Math.min(availWidth / iconChildren.length, availHeight, opt.MAX_ICON_SIZE * scaleFactor);
- } else {
- availWidth = this._maxWidth;
- availWidth -= this._background.get_theme_node().get_horizontal_padding();
- availWidth -= themeNode.get_horizontal_padding();
- availWidth -= buttonWidth - iconWidth;
-
- availHeight = maxContent.y2 - maxContent.y1;
- availHeight -= iconChildren.length * (buttonHeight - iconHeight) +
- (iconChildren.length - 1) * spacing +
- 2 * this._background.get_theme_node().get_vertical_padding();
-
- maxIconSize = Math.min(availWidth, availHeight / iconChildren.length, opt.MAX_ICON_SIZE * scaleFactor);
- }
-
- let iconSizes = BaseIconSizes.map(s => s * scaleFactor);
-
- let newIconSize = BaseIconSizes[0];
- for (let i = 0; i < iconSizes.length; i++) {
- if (iconSizes[i] <= maxIconSize)
- newIconSize = BaseIconSizes[i];
- }
-
- if (newIconSize === this.iconSize)
- return;
-
- // set the in-progress state here after all the possible cancels
- this._adjustingInProgress = true;
-
- let oldIconSize = this.iconSize;
- this.iconSize = newIconSize;
- this.emit('icon-size-changed');
-
- let scale = oldIconSize / newIconSize;
- for (let i = 0; i < iconChildren.length; i++) {
- let icon = iconChildren[i].child._delegate.icon;
-
- // Set the new size immediately, to keep the icons' sizes
- // in sync with this.iconSize
- icon.setIconSize(this.iconSize);
-
- // Don't animate the icon size change when the overview
- // is transitioning, not visible or when initially filling
- // the dash
- if (!Main.overview.visible || Main.overview.animationInProgress ||
- !this._shownInitially)
- continue;
-
- let [targetWidth, targetHeight] = icon.icon.get_size();
-
- // Scale the icon's texture to the previous size and
- // tween to the new size
- icon.icon.set_size(icon.icon.width * scale,
- icon.icon.height * scale);
-
- icon.icon.ease({
- width: targetWidth,
- height: targetHeight,
- duration: Dash.DASH_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- }
-
- if (this._separator) {
- this._separator.ease({
- width: dashHorizontal ? 1 : this.iconSize,
- height: dashHorizontal ? this.iconSize : 1,
- duration: Dash.DASH_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- }
-
- this._adjustingInProgress = false;
- },
-};
-
-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));
- }
- },
-};
-
-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;
- }
-
- 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;
-
- // avoid uncontrollable switching if smooth scroll wheel or trackpad is used
- if (this._lastScroll && Date.now() - this._lastScroll < 160)
- return Clutter.EVENT_STOP;
-
- this._lastScroll = Date.now();
-
- _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());
- }
- }
-
- let windows = this._scrolledWindows;
-
- if (!windows.length)
- return;
-
- // if window selection is in the process, the previewed window must be the current one
- let currentWin = this._selectedMetaWin ? this._selectedMetaWin : windows[0];
-
- const currentIdx = windows.indexOf(currentWin);
- let targetIdx = currentIdx + direction;
-
- if (targetIdx > windows.length - 1)
- targetIdx = 0;
- else if (targetIdx < 0)
- targetIdx = windows.length - 1;
-
- 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);
- });
-
- viewsIter.forEach(view => {
- // if workspaces are on primary monitor only
- if (!view || !view._workspaces)
- return;
-
- view._workspaces.forEach(ws => {
- ws._windows.forEach(windowPreview => {
- // metaWin === null resets opacity
- let opacity = metaWin ? 50 : 255;
- windowPreview._activateSelected = false;
-
- // minimized windows are invisible if windows are not exposed (WORKSPACE_MODE === 0)
- if (!windowPreview.opacity)
- windowPreview.opacity = 255;
-
- // app windows set to lower opacity, so they can be recognized
- if (this._scrolledWindows && this._scrolledWindows.includes(windowPreview.metaWindow)) {
- if (opt.DASH_ICON_SCROLL === 2)
- opacity = 254;
- }
- if (windowPreview.metaWindow === metaWin) {
- if (metaWin && metaWin.get_workspace() !== global.workspace_manager.get_active_workspace())
- Main.wm.actionMoveWorkspace(metaWin.get_workspace());
-
- 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 = {
- 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 currentWS = global.workspace_manager.get_active_workspace();
- const appRecentWorkspace = _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;
-
- let targetWindowOnCurrentWs = false;
- if (opt.DASH_FOLLOW_RECENT_WIN) {
- targetWindowOnCurrentWs = appRecentWorkspace === currentWS;
- } else {
- this.app.get_windows().forEach(
- w => {
- targetWindowOnCurrentWs = targetWindowOnCurrentWs || (w.get_workspace() === currentWS);
- }
- );
- }
-
- if ((this.app.state === Shell.AppState.STOPPED || openNewWindow) && !isShiftPressed)
- this.animateLaunch();
-
- if (openNewWindow) {
- this.app.open_new_window(-1);
- // 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) {
- // 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) {
- this._moveAppToCurrentWorkspace();
- return;
- } else if (isShiftPressed) {
- return;
- } else {
- this.app.activate();
- }
-
- Main.overview.hide();
- },
-
- _moveAppToCurrentWorkspace() {
- this.app.get_windows().forEach(w => w.change_workspace(global.workspace_manager.get_active_workspace()));
- },
-
- popupMenu(side = St.Side.LEFT) {
- if (shellVersion >= 42)
- this.setForcedHighlight(true);
- this._removeMenuTimeout();
- this.fake_release();
-
- if (!this._getWindowsOnCurrentWs) {
- this._getWindowsOnCurrentWs = function () {
- const winList = [];
- this.app.get_windows().forEach(w => {
- if (w.get_workspace() === global.workspace_manager.get_active_workspace())
- winList.push(w);
- });
- return winList;
- };
-
- this._windowsOnOtherWs = function () {
- return (this.app.get_windows().length - this._getWindowsOnCurrentWs().length) > 0;
- };
- }
-
- if (!this._menu) {
- this._menu = new AppMenu(this, side, {
- favoritesSection: true,
- showSingleWindows: true,
- });
-
- this._menu.setApp(this.app);
- this._openSigId = this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
- if (!isPoppedUp)
- this._onMenuPoppedDown();
- });
- // Main.overview.connectObject('hiding',
- this._hidingSigId = Main.overview.connect('hiding',
- () => this._menu.close(), this);
-
- Main.uiGroup.add_actor(this._menu.actor);
- this._menuManager.addMenu(this._menu);
- }
-
- // once the menu is created, it stays unchanged and we need to modify our items based on current situation
- if (this._addedMenuItems && this._addedMenuItems.length)
- this._addedMenuItems.forEach(i => i.destroy());
-
-
- const popupItems = [];
-
- const separator = new PopupMenu.PopupSeparatorMenuItem();
- this._menu.addMenuItem(separator);
-
- if (this.app.get_n_windows()) {
- // if (/* opt.APP_MENU_FORCE_QUIT*/true) {}
- popupItems.push([_('Force Quit'), () => {
- this.app.get_windows()[0].kill();
- }]);
-
- // if (opt.APP_MENU_CLOSE_WS) {}
- const nWin = this._getWindowsOnCurrentWs().length;
- if (nWin) {
- popupItems.push([_(`Close ${nWin} Windows on Current Workspace`), () => {
- const windows = this._getWindowsOnCurrentWs();
- let time = global.get_current_time();
- for (let win of windows) {
- // increase time by 1 ms for each window to avoid errors from GS
- win.delete(time++);
- }
- }]);
- }
-
- if (/* opt.APP_MENU_MV_TO_WS && */this._windowsOnOtherWs())
- popupItems.push([_('Move App to Current Workspace ( Shift + Click )'), this._moveAppToCurrentWorkspace]);
- }
-
- this._addedMenuItems = [];
- this._addedMenuItems.push(separator);
- popupItems.forEach(i => {
- let item = new PopupMenu.PopupMenuItem(i[0]);
- this._menu.addMenuItem(item);
- item.connect('activate', i[1].bind(this));
- this._addedMenuItems.push(item);
- });
-
- this.emit('menu-state-changed', true);
-
- this._menu.open(BoxPointer.PopupAnimation.FULL);
- this._menuManager.ignoreRelease();
- this.emit('sync-tooltip');
-
- 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);
- }
-
- dash._showWindowsIcon.icon.setIconSize(dash.iconSize);
- if (opt.SHOW_WINDOWS_ICON === 1) {
- dashContainer.set_child_at_index(dash._showWindowsIcon, 0);
- } else if (opt.SHOW_WINDOWS_ICON === 2) {
- const index = dashContainer.get_children().length - 1;
- dashContainer.set_child_at_index(dash._showWindowsIcon, index);
- }
-
- Main.overview._overview._controls.layoutManager._dash._adjustIconSize();
-}
-
-const ShowWindowsIcon = GObject.registerClass(
-class ShowWindowsIcon extends Dash.DashItemContainer {
- _init() {
- super._init();
-
- this._isSearchWindowsIcon = true;
- this._labelText = _('Search Open Windows (Hotkey: Space)');
- this.toggleButton = new St.Button({
- style_class: 'show-apps',
- track_hover: true,
- can_focus: true,
- toggle_mode: false,
- });
-
- 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;
-
- this.toggleButton.add_actor(this.icon);
- this.toggleButton._delegate = this;
-
- this.setChild(this.toggleButton);
-
- 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));
- }
- }
-
- _createIcon(size) {
- this._iconActor = new St.Icon({
- icon_name: 'focus-windows-symbolic',
- icon_size: size,
- style_class: 'show-apps-icon',
- track_hover: true,
- });
- return this._iconActor;
- }
-});
-
-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;
-
- if (!dash._recentFilesIcon) {
- dash._recentFilesIcon = new ShowRecentFilesIcon();
- dash._recentFilesIcon.show(false);
- dashContainer.add_child(dash._recentFilesIcon);
- dash._hookUpLabel(dash._recentFilesIcon);
- }
-
- dash._recentFilesIcon.icon.setIconSize(dash.iconSize);
- if (opt.SHOW_RECENT_FILES_ICON === 1) {
- dashContainer.set_child_at_index(dash._recentFilesIcon, 0);
- } else if (opt.SHOW_RECENT_FILES_ICON === 2) {
- const index = dashContainer.get_children().length - 1;
- dashContainer.set_child_at_index(dash._recentFilesIcon, index);
- }
-
- Main.overview._overview._controls.layoutManager._dash._adjustIconSize();
-}
-
-const ShowRecentFilesIcon = GObject.registerClass(
-class ShowRecentFilesIcon extends Dash.DashItemContainer {
- _init() {
- super._init();
-
- this._labelText = _('Search Recent Files (Hotkey: Ctrl + Space)');
- this.toggleButton = new St.Button({
- style_class: 'show-apps',
- track_hover: true,
- can_focus: true,
- toggle_mode: false,
- });
-
- this._iconActor = null;
- this.icon = new IconGrid.BaseIcon(this.labelText, {
- setSizeManually: true,
- showLabel: false,
- createIcon: this._createIcon.bind(this),
- });
- this.icon.y_align = Clutter.ActorAlign.CENTER;
-
- this.toggleButton.add_actor(this.icon);
- this.toggleButton._delegate = this;
-
- this.setChild(this.toggleButton);
- }
-
- _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;
- }
-});
diff --git a/extensions/vertical-workspaces/lib/iconGrid.js b/extensions/vertical-workspaces/lib/iconGrid.js
deleted file mode 100644
index 1aa980e..0000000
--- a/extensions/vertical-workspaces/lib/iconGrid.js
+++ /dev/null
@@ -1,314 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * iconGrid.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-const { GLib, St, Meta } = imports.gi;
-const IconGrid = imports.ui.iconGrid;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-const shellVersion = _Util.shellVersion;
-
-// added sizes for better scaling
-const IconSize = {
- LARGEST: 256,
- 224: 224,
- 208: 208,
- 192: 192,
- 176: 176,
- 160: 160,
- 144: 144,
- 128: 128,
- 112: 112,
- LARGE: 96,
- 80: 80,
- 64: 64,
- 48: 48,
- TINY: 32,
-};
-
-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;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
-
- if (reset) {
- _overrides = null;
- opt = null;
- return;
- }
-
- _overrides = new _Util.Overrides();
-
- if (shellVersion < 43 && IconGridCommon._findBestModeForSize) {
- IconGridCommon['findBestModeForSize'] = IconGridCommon._findBestModeForSize;
- IconGridCommon['_findBestModeForSize'] = undefined;
- }
- _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) {
- if (page < 0 || page >= this.nPages)
- return [];
- // throw new Error(`Page ${page} does not exist at IconGrid`);
-
- const layoutManager = this.layout_manager;
- return layoutManager.getItemsAtPage(page);
- },
-
- _findBestModeForSize(width, height) {
- // this function is for main grid only, folder grid calculation is in appDisplay.AppFolderDialog class
- if (this._currentMode > -1 || this.layoutManager._isFolder)
- return;
- const { pagePadding } = this.layout_manager;
- const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const iconPadding = 53 * scaleFactor;
- // provided width is usually about 100px wider in horizontal orientation with prev/next page indicators
- const pageIndicatorCompensation = opt.ORIENTATION ? 0 : PAGE_WIDTH_CORRECTION;
-
- width -= pagePadding.left + pagePadding.right + pageIndicatorCompensation;
- width *= opt.APP_GRID_PAGE_WIDTH_SCALE;
- height -= pagePadding.top + pagePadding.bottom;
-
- // store grid max dimensions for icon size algorithm
- this.layoutManager._gridWidth = width;
- this.layoutManager._gridHeight = height;
-
- 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;
- // if this._gridModes.length === 1, custom grid should be used
- // if (iconSize > 0 && this._gridModes.length > 1) {
- let columns = opt.APP_GRID_COLUMNS;
- let rows = opt.APP_GRID_ROWS;
- // 0 means adaptive size
- let unusedSpaceH = -1;
- let unusedSpaceV = -1;
- if (!columns) {
- columns = Math.floor(width / (iconSize + iconPadding)) + 1;
- while (unusedSpaceH < 0) {
- columns -= 1;
- unusedSpaceH = width - columns * (iconSize + iconPadding) - (columns - 1) * spacing;
- }
- }
- if (!rows) {
- rows = Math.floor(height / (iconSize + iconPadding)) + 1;
- while (unusedSpaceV < 0) {
- rows -= 1;
- unusedSpaceV = height - rows * (iconSize + iconPadding) - (rows - 1) * spacing;
- }
- }
-
- this._gridModes = [{ columns, rows }];
- // }
-
- this._setGridMode(0);
- },
-};
-
-const IconGridLayoutCommon = {
- _findBestIconSize() {
- const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const nColumns = this.columnsPerPage;
- const nRows = this.rowsPerPage;
- const columnSpacingPerPage = opt.APP_GRID_SPACING * (nColumns - 1);
- const rowSpacingPerPage = opt.APP_GRID_SPACING * (nRows - 1);
- const iconPadding = 53 * scaleFactor;
-
- const paddingH = this._isFolder ? this.pagePadding.left + this.pagePadding.right : 0;
- const paddingV = this._isFolder ? this.pagePadding.top + this.pagePadding.bottom : 0;
-
- const width = this._gridWidth ? this._gridWidth : this._pageWidth;
- const height = this._gridHeight ? this._gridHeight : this._pageHeight;
- if (!width || !height)
- return opt.APP_GRID_ICON_SIZE_DEFAULT;
-
- const [firstItem] = this._container;
-
- if (this.fixedIconSize !== -1)
- return this.fixedIconSize;
-
- /* if (opt.APP_GRID_ADAPTIVE && !this._isFolder)
- 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)
- iconSizes = iconSizes.slice(iconSizes.indexOf(IconSize.LARGE), -1);
-
- let sizeInvalid = false;
- for (const size of iconSizes) {
- let usedWidth, usedHeight;
-
- if (firstItem) {
- firstItem.icon.setIconSize(size);
- const [firstItemWidth, firstItemHeight] =
- firstItem.get_preferred_size();
-
- const itemSize = Math.max(firstItemWidth, firstItemHeight);
- if (itemSize < size)
- sizeInvalid = true;
-
- usedWidth = itemSize * nColumns;
- usedHeight = itemSize * nRows;
- }
-
- if (!firstItem || sizeInvalid) {
- usedWidth = (size + iconPadding) * nColumns;
- usedHeight = (size + iconPadding) * nRows;
- }
- const emptyHSpace =
- width - usedWidth - columnSpacingPerPage - paddingH;
- // this.pagePadding.left - this.pagePadding.right;
- const emptyVSpace =
- height - usedHeight - rowSpacingPerPage - paddingV;
- // this.pagePadding.top - this.pagePadding.bottom;
-
- if (emptyHSpace >= 0 && emptyVSpace >= 0) {
- return size;
- }
- }
-
- return IconSize.TINY;
- },
-
- removeItem(item) {
- if (!this._items.has(item)) {
- log(`Item ${item} is not part of the IconGridLayout`);
- return;
- // throw new Error(`Item ${item} is not part of the IconGridLayout`);
- }
-
- if (!this._container)
- return;
-
- this._shouldEaseItems = true;
-
- this._container.remove_child(item);
- this._removeItemData(item);
- },
-
- addItem(item, page = -1, index = -1) {
- if (this._items.has(item)) {
- log(`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}`);
- page = -1;
- index = -1;
- // throw new Error(`Cannot add ${item} to page ${page}`);
- }
-
- if (!this._container)
- return;
-
- if (page !== -1 && index === -1)
- page = this._findBestPageToAppend(page);
-
- this._shouldEaseItems = true;
- this._container.add_child(item);
- this._addItemToPage(item, page, index);
- },
-
- moveItem(item, newPage, newPosition) {
- if (!this._items.has(item)) {
- log(`iconGrid: Item ${item} is not part of the IconGridLayout`);
- return;
- // throw new Error(`Item ${item} is not part of the IconGridLayout`);
- }
-
- this._shouldEaseItems = true;
-
- this._removeItemData(item);
-
- if (newPage !== -1 && newPosition === -1)
- newPage = this._findBestPageToAppend(newPage);
- this._addItemToPage(item, newPage, newPosition);
- },
-
- _addItemToPage(item, pageIndex, index) {
- // Ensure we have at least one page
- if (this._pages.length === 0)
- this._appendPage();
-
- // Append a new page if necessary
- if (pageIndex === this._pages.length)
- this._appendPage();
-
- if (pageIndex >= this._pages.length) {
- pageIndex = -1;
- index = -1;
- }
-
- if (pageIndex === -1)
- pageIndex = this._pages.length - 1;
-
- if (index === -1)
- index = this._pages[pageIndex].children.length;
-
- this._items.set(item, {
- actor: item,
- pageIndex,
- destroyId: item.connect('destroy', () => this._removeItemData(item)),
- visibleId: item.connect('notify::visible', () => {
- const itemData = this._items.get(item);
-
- this._updateVisibleChildrenForPage(itemData.pageIndex);
-
- if (item.visible)
- this._relocateSurplusItems(itemData.pageIndex);
- else if (!this.allowIncompletePages)
- this._fillItemVacancies(itemData.pageIndex);
- }),
- queueRelayoutId: item.connect('queue-relayout', () => {
- this._childrenMaxSize = -1;
- }),
- });
-
- item.icon.setIconSize(this._iconSize);
- this._pages[pageIndex].children.splice(index, 0, item);
- this._updateVisibleChildrenForPage(pageIndex);
- this._relocateSurplusItems(pageIndex);
- },
-
- _findBestPageToAppend(startPage) {
- const itemsPerPage = this.columnsPerPage * this.rowsPerPage;
-
- for (let i = startPage; i < this._pages.length; i++) {
- const visibleItems = this._pages[i].visibleChildren;
-
- if (visibleItems.length < itemsPerPage)
- return i;
- }
-
- return this._pages.length;
- },
-};
diff --git a/extensions/vertical-workspaces/lib/layout.js b/extensions/vertical-workspaces/lib/layout.js
deleted file mode 100644
index f6562fd..0000000
--- a/extensions/vertical-workspaces/lib/layout.js
+++ /dev/null
@@ -1,380 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * layout.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { Meta, GLib, Shell, Clutter, GObject } = imports.gi;
-
-const Main = imports.ui.main;
-const Layout = imports.ui.layout;
-const Ripples = imports.ui.ripples;
-const DND = imports.ui.dnd;
-
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-
-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;
-
- // don't even touch this module if disabled or in conflict
- if (_firstRun && (reset || conflict))
- return;
-
- _firstRun = false;
-
- if (!_originalUpdateHotCorners)
- _originalUpdateHotCorners = Layout.LayoutManager.prototype._updateHotCorners;
-
- if (_overrides)
- _overrides.removeAll();
-
- if (_timeouts) {
- Object.values(_timeouts).forEach(t => {
- if (t)
- GLib.source_remove(t);
- });
- }
-
- if (reset) {
- _overrides = null;
- opt = null;
- _timeouts = null;
- Main.layoutManager._updateHotCorners = _originalUpdateHotCorners;
- Main.layoutManager._updateHotCorners();
- return;
- }
-
- _timeouts = {};
-
- _overrides = new _Util.Overrides();
- _overrides.addOverride('LayoutManager', Layout.LayoutManager.prototype, LayoutManagerCommon);
-
- Main.layoutManager._updateHotCorners = LayoutManagerCommon._updateHotCorners.bind(Main.layoutManager);
-
- Main.layoutManager._updatePanelBarrier();
- Main.layoutManager._updateHotCorners();
-}
-
-const LayoutManagerCommon = {
- _updatePanelBarrier() {
- if (this._rightPanelBarrier) {
- this._rightPanelBarrier.destroy();
- this._rightPanelBarrier = null;
- }
-
- if (this._leftPanelBarrier) {
- this._leftPanelBarrier.destroy();
- this._leftPanelBarrier = null;
- }
-
- if (!this.primaryMonitor || !opt)
- return;
-
- if (this.panelBox.height) {
- let primary = this.primaryMonitor;
- if ([0, 1, 3].includes(opt.HOT_CORNER_POSITION)) {
- this._rightPanelBarrier = new Meta.Barrier({
- display: global.display,
- x1: primary.x + primary.width, y1: this.panelBox.allocation.y1,
- x2: primary.x + primary.width, y2: this.panelBox.allocation.y2,
- directions: Meta.BarrierDirection.NEGATIVE_X,
- });
- }
-
- if ([2, 4].includes(opt.HOT_CORNER_POSITION)) {
- this._leftPanelBarrier = new Meta.Barrier({
- display: global.display,
- x1: primary.x, y1: this.panelBox.allocation.y1,
- x2: primary.x, y2: this.panelBox.allocation.y2,
- directions: Meta.BarrierDirection.POSITIVE_X,
- });
- }
- }
- },
-
- _updateHotCorners() {
- // avoid errors if called from foreign override
- if (!opt)
- return;
- // destroy old hot corners
- this.hotCorners.forEach(corner => corner?.destroy());
- this.hotCorners = [];
-
- if (!this._interfaceSettings.get_boolean('enable-hot-corners')) {
- this.emit('hot-corners-changed');
- return;
- }
-
- let size = this.panelBox.height;
-
- // position 0 - default, 1-TL, 2-TR, 3-BL, 4-BR
- const position = opt.HOT_CORNER_POSITION;
-
- // build new hot corners
- for (let i = 0; i < this.monitors.length; i++) {
- let monitor = this.monitors[i];
- let cornerX, cornerY;
-
- if (position === 0) {
- cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
- cornerY = monitor.y;
- } else if (position === 1) {
- cornerX = monitor.x;
- cornerY = monitor.y;
- } else if (position === 2) {
- cornerX = monitor.x + monitor.width;
- cornerY = monitor.y;
- } else if (position === 3) {
- cornerX = monitor.x;
- cornerY = monitor.y + monitor.height;
- } else {
- cornerX = monitor.x + monitor.width;
- cornerY = monitor.y + monitor.height;
- }
-
- let haveCorner = true;
-
- if (i !== this.primaryIndex) {
- // Check if we have a top left (right for RTL) corner.
- // I.e. if there is no monitor directly above or to the left(right)
- let besideX = this._rtl ? monitor.x + 1 : cornerX - 1;
- let besideY = cornerY;
- let aboveX = cornerX;
- let aboveY = cornerY - 1;
-
- for (let j = 0; j < this.monitors.length; j++) {
- if (i === j)
- continue;
- let otherMonitor = this.monitors[j];
- if (besideX >= otherMonitor.x &&
- besideX < otherMonitor.x + otherMonitor.width &&
- besideY >= otherMonitor.y &&
- besideY < otherMonitor.y + otherMonitor.height) {
- haveCorner = false;
- break;
- }
- if (aboveX >= otherMonitor.x &&
- aboveX < otherMonitor.x + otherMonitor.width &&
- aboveY >= otherMonitor.y &&
- aboveY < otherMonitor.y + otherMonitor.height) {
- haveCorner = false;
- break;
- }
- }
- }
-
- if (haveCorner) {
- let corner = new HotCorner(this, monitor, cornerX, cornerY);
- corner.setBarrierSize(size);
- this.hotCorners.push(corner);
- } else {
- this.hotCorners.push(null);
- }
- }
-
- this.emit('hot-corners-changed');
- },
-};
-
-var HotCorner = GObject.registerClass(
-class HotCorner extends Layout.HotCorner {
- _init(layoutManager, monitor, x, y) {
- super._init(layoutManager, monitor, x, y);
-
- let angle = 0;
- switch (opt.HOT_CORNER_POSITION) {
- case 2:
- angle = 90;
- break;
- case 3:
- angle = 270;
- break;
- case 4:
- angle = 180;
- break;
- }
-
- this._ripples._ripple1.rotation_angle_z = angle;
- this._ripples._ripple2.rotation_angle_z = angle;
- this._ripples._ripple3.rotation_angle_z = angle;
- }
-
- setBarrierSize(size) {
- if (this._verticalBarrier) {
- this._pressureBarrier.removeBarrier(this._verticalBarrier);
- this._verticalBarrier.destroy();
- this._verticalBarrier = null;
- }
-
- if (this._horizontalBarrier) {
- this._pressureBarrier.removeBarrier(this._horizontalBarrier);
- this._horizontalBarrier.destroy();
- this._horizontalBarrier = null;
- }
-
- 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;
-
- if (opt.HOT_CORNER_POSITION <= 1) {
- this._verticalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x, x2: this._x, y1: this._y, y2: this._y + (extendV ? monitor.height : size),
- directions: Meta.BarrierDirection.POSITIVE_X,
- });
- this._horizontalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x, x2: this._x + (extendH ? monitor.width : size), y1: this._y, y2: this._y,
- directions: Meta.BarrierDirection.POSITIVE_Y,
- });
- } else if (opt.HOT_CORNER_POSITION === 2) {
- this._verticalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x, x2: this._x, y1: this._y, y2: this._y + (extendV ? monitor.height : size),
- directions: Meta.BarrierDirection.NEGATIVE_X,
- });
- this._horizontalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x - size, x2: this._x, y1: this._y, y2: this._y,
- directions: Meta.BarrierDirection.POSITIVE_Y,
- });
- } else if (opt.HOT_CORNER_POSITION === 3) {
- this._verticalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x, x2: this._x, y1: this._y, y2: this._y - size,
- directions: Meta.BarrierDirection.POSITIVE_X,
- });
- this._horizontalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x, x2: this._x + (extendH ? monitor.width : size), y1: this._y, y2: this._y,
- directions: Meta.BarrierDirection.NEGATIVE_Y,
- });
- } else if (opt.HOT_CORNER_POSITION === 4) {
- this._verticalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x, x2: this._x, y1: this._y, y2: this._y - size,
- directions: Meta.BarrierDirection.NEGATIVE_X,
- });
- this._horizontalBarrier = new Meta.Barrier({
- display: global.display,
- x1: this._x, x2: this._x - size, y1: this._y, y2: this._y,
- directions: Meta.BarrierDirection.NEGATIVE_Y,
- });
- }
-
- 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()))
- 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()))
- this._toggleApplications(true);
- else if (opt.HOT_CORNER_ACTION === 3 && !_Util.isCtrlPressed())
- this._toggleWindowSearchProvider();
- if (opt.HOT_CORNER_RIPPLES && Main.overview.animationInProgress)
- this._ripples.playAnimation(this._x, this._y);
- }
- }
-
- _toggleWindowPicker(leaveOverview = false) {
- if (Main.overview._shown && (leaveOverview || !Main.overview.dash.showAppsButton.checked)) {
- Main.overview.hide();
- } else if (Main.overview.dash.showAppsButton.checked) {
- Main.overview.dash.showAppsButton.checked = false;
- } else {
- const focusWindow = global.display.get_focus_window();
- // at least GS 42 is unable to show overview in X11 session if VirtualBox Machine window grabbed keyboard
- if (!Meta.is_wayland_compositor() && focusWindow && focusWindow.wm_class.includes('VirtualBox Machine')) {
- // following should help when windowed VBox Machine has focus.
- global.stage.set_key_focus(Main.panel);
- // key focus doesn't take the effect immediately, we must wait for it
- // still looking for better solution!
- _timeouts.releaseKeyboardTimeoutId = GLib.timeout_add(
- GLib.PRIORITY_DEFAULT,
- // delay cannot be too short
- 200,
- () => {
- Main.overview.show();
-
- _timeouts.releaseKeyboardTimeoutId = 0;
- return GLib.SOURCE_REMOVE;
- }
- );
- } else {
- Main.overview.show();
- }
- }
- }
-
- _toggleApplications(leaveOverview = false) {
- if ((leaveOverview && Main.overview._shown) || Main.overview.dash.showAppsButton.checked) {
- Main.overview.hide();
- } else {
- const focusWindow = global.display.get_focus_window();
- // at least GS 42 is unable to show overview in X11 session if VirtualBox Machine window grabbed keyboard
- if (!Meta.is_wayland_compositor() && focusWindow && focusWindow.wm_class.includes('VirtualBox Machine')) {
- // following should help when windowed VBox Machine has focus.
- global.stage.set_key_focus(Main.panel);
- // key focus doesn't take the effect immediately, we must wait for it
- // still looking for better solution!
- _timeouts.releaseKeyboardTimeoutId = GLib.timeout_add(
- GLib.PRIORITY_DEFAULT,
- // delay cannot be too short
- 200,
- () => {
- Main.overview.show(2);
-
- _timeouts.releaseKeyboardTimeoutId = 0;
- return GLib.SOURCE_REMOVE;
- }
- );
- } else if (Main.overview._shown) {
- Main.overview.dash.showAppsButton.checked = true;
- } else {
- Main.overview.show(2); // 2 for App Grid
- }
- }
- }
-
- _toggleWindowSearchProvider() {
- if (!Main.overview._overview._controls._searchController._searchActive) {
- this._toggleWindowPicker();
- const prefix = 'wq// ';
- const position = prefix.length;
- const searchEntry = Main.overview.searchEntry;
- searchEntry.set_text(prefix);
- // searchEntry.grab_key_focus();
- searchEntry.get_first_child().set_cursor_position(position);
- searchEntry.get_first_child().set_selection(position, position);
- } else {
- // Main.overview.searchEntry.text = '';
- Main.overview.hide();
- }
- }
-});
diff --git a/extensions/vertical-workspaces/lib/messageTray.js b/extensions/vertical-workspaces/lib/messageTray.js
deleted file mode 100644
index b35541a..0000000
--- a/extensions/vertical-workspaces/lib/messageTray.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * messageTray.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { Clutter } = imports.gi;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const Main = imports.ui.main;
-
-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;
-
- _firstRun = false;
-
- if (reset) {
- opt = null;
- setNotificationPosition(1);
- return;
- }
-
- setNotificationPosition(opt.NOTIFICATION_POSITION);
-}
-
-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;
- }
-}
diff --git a/extensions/vertical-workspaces/lib/optionsFactory.js b/extensions/vertical-workspaces/lib/optionsFactory.js
deleted file mode 100644
index da62dd1..0000000
--- a/extensions/vertical-workspaces/lib/optionsFactory.js
+++ /dev/null
@@ -1,645 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * optionsFactory.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- */
-
-'use strict';
-
-const { Gtk, Gio, GObject } = imports.gi;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-const Settings = Me.imports.lib.settings;
-
-const shellVersion = Settings.shellVersion;
-
-// gettext
-const _ = Settings._;
-
-const ProfileNames = [
- _('GNOME 3'),
- _('GNOME 40+ - Bottom Hot Edge'),
- _('Hot Corner Centric - Top Left Hot Corner'),
- _('Dock Overview - Bottom Hot Edge'),
-];
-
-// libadwaita is available starting with GNOME Shell 42.
-let Adw = null;
-try {
- Adw = imports.gi.Adw;
-} catch (e) {}
-
-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;
- }
-
- getRowWidget(text, caption, widget, variable, options = []) {
- let item = [];
- let label;
- if (widget) {
- label = new Gtk.Box({
- orientation: Gtk.Orientation.VERTICAL,
- spacing: 4,
- halign: Gtk.Align.START,
- valign: Gtk.Align.CENTER,
- });
- const option = new Gtk.Label({
- halign: Gtk.Align.START,
- });
- option.set_text(text);
- label.append(option);
-
- if (caption) {
- const captionLabel = new Gtk.Label({
- halign: Gtk.Align.START,
- wrap: true,
- /* width_chars: 80, */
- xalign: 0,
- });
- const context = captionLabel.get_style_context();
- context.add_class('dim-label');
- context.add_class('caption');
- captionLabel.set_text(caption);
- label.append(captionLabel);
- }
- label._title = text;
- } else {
- label = text;
- }
- item.push(label);
- item.push(widget);
-
- let key;
-
- if (variable && this._gOptions.options[variable]) {
- const opt = this._gOptions.options[variable];
- key = opt[1];
- }
-
- if (widget) {
- if (widget._isSwitch)
- this._connectSwitch(widget, key, variable);
- else if (widget._isSpinButton || widget._isScale)
- this._connectSpinButton(widget, key, variable);
- else if (widget._isComboBox)
- this._connectComboBox(widget, key, variable, options);
- else if (widget._isDropDown)
- this._connectDropDown(widget, key, variable, options);
- }
-
- return item;
- }
-
- _connectSwitch(widget, key /* , variable */) {
- this._settings.bind(key, widget, 'active', Gio.SettingsBindFlags.DEFAULT);
- }
-
- _connectSpinButton(widget, key /* , variable */) {
- this._settings.bind(key, widget.adjustment, 'value', Gio.SettingsBindFlags.DEFAULT);
- }
-
- _connectComboBox(widget, key, variable, options) {
- let model = widget.get_model();
- widget._comboMap = {};
- const currentValue = this._gOptions.get(variable);
- for (const [label, value] of options) {
- let iter;
- model.set(iter = model.append(), [0, 1], [label, value]);
- if (value === currentValue)
- widget.set_active_iter(iter);
-
- widget._comboMap[value] = iter;
- }
- this._gOptions.connect(`changed::${key}`, () => {
- widget.set_active_iter(widget._comboMap[this._gOptions.get(variable, true)]);
- });
- widget.connect('changed', () => {
- const [success, iter] = widget.get_active_iter();
-
- if (!success)
- return;
-
- this._gOptions.set(variable, model.get_value(iter, 1));
- });
- }
-
- _connectDropDown(widget, key, variable, options) {
- const model = widget.get_model();
- const currentValue = this._gOptions.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 }));
- if (id === currentValue)
- widget.set_selected(i);
- }
-
- const factory = new Gtk.SignalListItemFactory();
- factory.connect('setup', (fact, listItem) => {
- const label = new Gtk.Label({ xalign: 0 });
- listItem.set_child(label);
- });
- factory.connect('bind', (fact, listItem) => {
- const label = listItem.get_child();
- const item = listItem.get_item();
- label.set_text(item.text);
- });
-
- widget.connect('notify::selected-item', dropDown => {
- const item = dropDown.get_selected_item();
- this._gOptions.set(variable, item.id);
- });
-
- this._gOptions.connect(`changed::${key}`, () => {
- const newId = this._gOptions.get(variable, true);
- for (let i = 0; i < options.length; i++) {
- const id = options[i][1];
- if (id === newId)
- widget.set_selected(i);
- }
- });
-
- widget.set_factory(factory);
- }
-
- newSwitch() {
- let sw = new Gtk.Switch({
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- });
- sw._isSwitch = true;
- return sw;
- }
-
- newSpinButton(adjustment) {
- let spinButton = new Gtk.SpinButton({
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- vexpand: false,
- xalign: 0.5,
- });
- spinButton.set_adjustment(adjustment);
- spinButton._isSpinButton = true;
- return spinButton;
- }
-
- newComboBox() {
- const model = new Gtk.ListStore();
- model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT]);
- const comboBox = new Gtk.ComboBox({
- model,
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- });
- const renderer = new Gtk.CellRendererText();
- comboBox.pack_start(renderer, true);
- comboBox.add_attribute(renderer, 'text', 0);
- comboBox._isComboBox = true;
- return comboBox;
- }
-
- newDropDown() {
- const dropDown = new Gtk.DropDown({
- model: new Gio.ListStore({
- item_type: DropDownItem,
- }),
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- });
- dropDown._isDropDown = true;
- return dropDown;
- }
-
- newScale(adjustment) {
- const scale = new Gtk.Scale({
- orientation: Gtk.Orientation.HORIZONTAL,
- draw_value: true,
- has_origin: false,
- value_pos: Gtk.PositionType.LEFT,
- digits: 0,
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- vexpand: false,
- });
- scale.set_size_request(300, -1);
- scale.set_adjustment(adjustment);
- scale._isScale = true;
- return scale;
- }
-
- newLabel(text = '') {
- const label = new Gtk.Label({
- label: text,
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- });
- label._activatable = false;
- return label;
- }
-
- newLinkButton(uri) {
- const linkBtn = new Gtk.LinkButton({
- label: shellVersion < 42 ? 'Click Me!' : '',
- uri,
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- });
- return linkBtn;
- }
-
- newButton() {
- const btn = new Gtk.Button({
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- });
-
- btn._activatable = true;
- return btn;
- }
-
- newPresetButton(opt, profileIndex) {
- const load = opt.loadProfile.bind(opt);
- const save = opt.storeProfile.bind(opt);
- const reset = opt.resetProfile.bind(opt);
-
- const box = new Gtk.Box({
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- spacing: 8,
- });
- box.is_profile_box = true;
-
- const entry = new Gtk.Entry({
- width_chars: 40,
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- xalign: 0,
- });
- 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',
- hexpand: false,
- css_classes: ['destructive-action'],
- });
-
- function setName() {
- let name = opt.get(`profileName${profileIndex}`, true);
- if (!name)
- name = ProfileNames[profileIndex - 1];
- entry.set_text(name);
- }
-
- setName();
- resetProfile.connect('clicked', () => {
- reset(profileIndex);
- setName();
- });
- resetProfile._activatable = false;
-
- const loadProfile = this.newButton();
- loadProfile.set({
- tooltip_text: _('Load profile'),
- icon_name: 'view-refresh-symbolic',
- hexpand: false,
- });
- loadProfile.connect('clicked', () => load(profileIndex));
- loadProfile._activatable = false;
-
- const saveProfile = this.newButton();
- saveProfile.set({
- tooltip_text: _('Save current settings into this profile'),
- icon_name: 'document-save-symbolic',
- hexpand: false,
- });
- saveProfile.connect('clicked', () => save(profileIndex));
- saveProfile._activatable = false;
-
- box.append(resetProfile);
- box.append(entry);
- box.append(saveProfile);
- box.append(loadProfile);
- return box;
- }
-
- newResetButton(callback) {
- const btn = this.newButton();
- btn.set({
- css_classes: ['destructive-action'],
- icon_name: 'edit-delete-symbolic',
- });
-
- btn.connect('clicked', callback);
- btn._activatable = false;
- return btn;
- }
-
- newOptionsResetButton() {
- const btn = new Gtk.Button({
- halign: Gtk.Align.END,
- valign: Gtk.Align.CENTER,
- hexpand: true,
- css_classes: ['destructive-action'],
- icon_name: 'edit-delete-symbolic',
- });
-
- btn.connect('clicked', () => {
- const settings = this._settings;
- settings.list_keys().forEach(
- key => settings.reset(key)
- );
- });
- btn._activatable = false;
- return btn;
- }
-};
-
-var AdwPrefs = class {
- constructor(gOptions) {
- this._gOptions = gOptions;
- }
-
- getFilledWindow(window, pages) {
- for (let page of pages) {
- const title = page.title;
- const iconName = page.iconName;
- const optionList = page.optionList;
-
- window.add(
- this._getAdwPage(optionList, {
- title,
- icon_name: iconName,
- })
- );
- }
-
- window.set_search_enabled(true);
-
- return window;
- }
-
- _getAdwPage(optionList, pageProperties = {}) {
- pageProperties.width_request = 840;
- const page = new Adw.PreferencesPage(pageProperties);
- let group;
- 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) {
- if (group)
- page.add(group);
-
- group = new Adw.PreferencesGroup({
- title: option,
- hexpand: true,
- width_request: 700,
- });
- continue;
- }
-
- const row = new Adw.ActionRow({
- title: option._title,
- });
-
- 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,
- });
- /* for (let i of item) {
- box.append(i);*/
- grid.attach(option, 0, 0, 1, 1);
- if (widget)
- grid.attach(widget, 1, 0, 1, 1);
-
- row.set_child(grid);
- if (widget._activatable === false)
- row.activatable = false;
- else
- row.activatable_widget = widget;
-
- group.add(row);
- }
- page.add(group);
- return page;
- }
-};
-
-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',
- Properties: {
- 'text': GObject.ParamSpec.string(
- 'text',
- 'Text',
- 'DropDown item text',
- GObject.ParamFlags.READWRITE,
- ''
- ),
- 'id': GObject.ParamSpec.int(
- 'id',
- 'Id',
- 'Item id stored in settings',
- GObject.ParamFlags.READWRITE,
- 0, 100, 0
- ),
- },
-}, class DropDownItem extends GObject.Object {
- get text() {
- return this._text;
- }
-
- set text(text) {
- this._text = text;
- }
-
- get id() {
- return this._id;
- }
-
- set id(id) {
- this._id = id;
- }
-}
-);
diff --git a/extensions/vertical-workspaces/lib/osdWindow.js b/extensions/vertical-workspaces/lib/osdWindow.js
deleted file mode 100644
index a010558..0000000
--- a/extensions/vertical-workspaces/lib/osdWindow.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * osdWindow.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { Clutter } = imports.gi;
-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 opt;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('osdWindowModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
- if (reset || !moduleEnabled) {
- updateExistingOsdWindows(6);
- _overrides = null;
- opt = null;
- return;
- }
-
- _overrides = new _Util.Overrides();
- _overrides.addOverride('osdWindow', OsdWindow.OsdWindow.prototype, OsdWindowCommon);
-}
-
-function updateExistingOsdWindows(position) {
- position = position ? position : opt.OSD_POSITION;
- Main.osdWindowManager._osdWindows.forEach(osd => {
- osd.set(OsdPositions[position]);
- });
-}
-
-const OsdWindowCommon = {
- after_show() {
- if (!opt.OSD_POSITION)
- this.opacity = 0;
- this.set(OsdPositions[opt.OSD_POSITION]);
- },
-};
diff --git a/extensions/vertical-workspaces/lib/overlayKey.js b/extensions/vertical-workspaces/lib/overlayKey.js
deleted file mode 100644
index e0fc11d..0000000
--- a/extensions/vertical-workspaces/lib/overlayKey.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * overlayKey.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-const { GObject, Gio, GLib, Meta, St } = imports.gi;
-
-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 opt;
-let _firstRun = true;
-
-let _originalOverlayKeyHandlerId;
-let _overlayKeyHandlerId;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('overlayKeyModule', true);
- reset = reset || (!_firstRun && !moduleEnabled);
-
- // don't even touch this module if disabled
- if (_firstRun && !moduleEnabled)
- return;
-
- _firstRun = false;
-
- if (reset) {
- _updateOverlayKey(reset);
- opt = null;
- return;
- }
-
- _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)();
- }
-}
-
-function _restoreOverlayKeyHandler() {
- // Disconnect modified overlay key handler
- if (_overlayKeyHandlerId !== null) {
- global.display.disconnect(_overlayKeyHandlerId);
- _overlayKeyHandlerId = null;
- }
-
- // Unblock original overlay key handler
- if (_originalOverlayKeyHandlerId !== null) {
- global.display.unblock_signal_handler(_originalOverlayKeyHandlerId);
- _originalOverlayKeyHandlerId = null;
- }
-}
-
-function _connectOverlayKey() {
- this._a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA });
-
- this._lastOverlayKeyTime = 0;
- _overlayKeyHandlerId = global.display.connect('overlay-key', () => {
- if (this._a11ySettings.get_boolean('stickykeys-enable'))
- return;
-
- const { initialState, finalState, transitioning } =
- this._stateAdjustment.getStateTransitionParams();
-
- const time = GLib.get_monotonic_time() / 1000;
- const timeDiff = time - this._lastOverlayKeyTime;
- this._lastOverlayKeyTime = time;
-
- const shouldShift = St.Settings.get().enable_animations
- ? transitioning && finalState > initialState
- : Main.overview.visible && timeDiff < Overview.ANIMATION_TIME;
-
- const mode = opt.OVERLAY_KEY_SECONDARY;
- if (shouldShift) {
- 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 {
- Main.overview.toggle();
- }
- });
-}
diff --git a/extensions/vertical-workspaces/lib/overview.js b/extensions/vertical-workspaces/lib/overview.js
deleted file mode 100644
index 2f23d05..0000000
--- a/extensions/vertical-workspaces/lib/overview.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * overview.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const Overview = imports.ui.overview;
-
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-
-let _overrides;
-let opt;
-
-function update(reset = false) {
- if (_overrides)
- _overrides.removeAll();
-
-
- if (reset) {
- _overrides = null;
- opt = null;
- return;
- }
-
- opt = Me.imports.lib.settings.opt;
- _overrides = new _Util.Overrides();
-
- _overrides.addOverride('Overview', Overview.Overview.prototype, OverviewCommon);
-}
-
-const OverviewCommon = {
- _showDone() {
- this._animationInProgress = false;
- this._coverPane.hide();
-
- this.emit('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) {
- if (opt.SEARCH_VIEW_ANIMATION)
- controls._onSearchChanged();
- else if (!opt.OVERVIEW_MODE2)
- controls._stateAdjustment.value = 2;
- }
- },
-};
diff --git a/extensions/vertical-workspaces/lib/overviewControls.js b/extensions/vertical-workspaces/lib/overviewControls.js
deleted file mode 100644
index 4959b83..0000000
--- a/extensions/vertical-workspaces/lib/overviewControls.js
+++ /dev/null
@@ -1,1464 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * overviewControls.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { Clutter, GLib, GObject, St } = imports.gi;
-const Main = imports.ui.main;
-const Util = imports.misc.util;
-const OverviewControls = imports.ui.overviewControls;
-const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
-
-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 opt;
-
-const ANIMATION_TIME = imports.ui.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();
-
- if (_timeouts) {
- Object.values(_timeouts).forEach(id => {
- if (id)
- GLib.source_remove(id);
- });
- }
-
- _replaceOnSearchChanged(reset);
-
- if (reset) {
- _overrides = null;
- opt = null;
- _timeouts = null;
- return;
- }
-
- _timeouts = {};
-
- opt = Me.imports.lib.settings.opt;
- _overrides = new _Util.Overrides();
-
- _overrides.addOverride('ControlsManager', OverviewControls.ControlsManager.prototype, ControlsManager);
-
- if (opt.ORIENTATION === Clutter.Orientation.VERTICAL)
- _overrides.addOverride('ControlsManagerLayout', OverviewControls.ControlsManagerLayout.prototype, ControlsManagerLayoutVertical);
- else
- _overrides.addOverride('ControlsManagerLayout', OverviewControls.ControlsManagerLayout.prototype, ControlsManagerLayoutHorizontal);
-}
-
-function _replaceOnSearchChanged(reset = false) {
- 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)
- _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 = {
- // 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() {
- ...
- }*/
-
- // this function has duplicate in WorkspaceView so we use one function for both to avoid issues with syncing them
- _getFitModeForState(state) {
- return _getFitModeForState(state);
- },
-
- _updateThumbnailsBox() {
- const { shouldShow } = this._thumbnailsBox;
- const thumbnailsBoxVisible = shouldShow;
- 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 function is pure addition to the original code and handles wsDisp transition to APP_GRID view
- _updateWorkspacesDisplay() {
- this._workspacesDisplay.translation_x = 0;
- this._workspacesDisplay.translation_y = 0;
- this._workspacesDisplay.scale_x = 1;
- this._workspacesDisplay.scale_y = 1;
- const { initialState, finalState, progress, currentState } = this._stateAdjustment.getStateTransitionParams();
-
- const paramsForState = s => {
- let opacity;
- switch (s) {
- case ControlsState.HIDDEN:
- case ControlsState.WINDOW_PICKER:
- opacity = 255;
- break;
- case ControlsState.APP_GRID:
- opacity = 0;
- break;
- default:
- opacity = 255;
- break;
- }
- return { opacity };
- };
-
- let initialParams = paramsForState(initialState);
- let finalParams = paramsForState(finalState);
-
- let opacity = Math.round(Util.lerp(initialParams.opacity, finalParams.opacity, progress));
-
- let workspacesDisplayVisible = opacity !== 0/* && !(searchActive)*/;
-
- // improve transition from search results to desktop
- if (finalState === 0 && this._searchController._searchResults.visible)
- this._searchController.hide();
-
- // reset Static Workspace window picker mode
- if (currentState === 0/* finalState === 0 && progress === 1*/ && opt.OVERVIEW_MODE && opt.WORKSPACE_MODE)
- opt.WORKSPACE_MODE = 0;
-
- if (currentState < 2 && currentState > 1)
- WorkspaceThumbnail.RESCALE_ANIMATION_TIME = 0;
- else
- WorkspaceThumbnail.RESCALE_ANIMATION_TIME = 200;
-
- if (!opt.WS_ANIMATION || !opt.SHOW_WS_TMB) {
- this._workspacesDisplay.opacity = opacity;
- } else if (!opt.SHOW_WS_TMB_BG) {
- // fade out ws wallpaper during transition to ws switcher if ws switcher background disabled
- const ws = this._workspacesDisplay._workspacesViews[global.display.get_primary_monitor()]?._workspaces[this._workspaceAdjustment.value];
- if (ws)
- ws._background.opacity = opacity;
- }
-
- // 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();
-
- // 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);
- tmbBox._translationOriginal = [tmbTranslationX, tmbTranslationY];
- dash._translationOriginal = [dashTranslationX, dashTranslationY];
- searchEntryBin._translationOriginal = searchTranslationY;
- }
- if (finalState === 0 || initialState === 0) {
- const prg = Math.abs((finalState === 0 ? 0 : 1) - progress);
- tmbBox.translation_x = Math.round(prg * tmbBox._translationOriginal[0]);
- tmbBox.translation_y = Math.round(prg * tmbBox._translationOriginal[1]);
- if (!skipDash) {
- dash.translation_x = Math.round(prg * dash._translationOriginal[0]);
- dash.translation_y = Math.round(prg * dash._translationOriginal[1]);
- }
- searchEntryBin.translation_y = Math.round(prg * searchEntryBin._translationOriginal);
- }
- if (progress === 1) {
- tmbBox._translationOriginal = 0;
- if (!skipDash)
- dash._translationOriginal = 0;
-
- searchEntryBin._translationOriginal = 0;
- }
- } else if (!Main.layoutManager._startingUp && (tmbBox.translation_x || tmbBox.translation_y)) {
- tmbBox.translation_x = 0;
- tmbBox.translation_y = 0;
- if (!skipDash) {
- dash.translation_x = 0;
- dash.translation_y = 0;
- }
- searchEntryBin.translation_y = 0;
- }
-
- if (!Main.layoutManager._startingUp) {
- if (initialState === ControlsState.HIDDEN && finalState === ControlsState.APP_GRID)
- this._appDisplay.opacity = Math.round(progress * 255);
- else
- this._appDisplay.opacity = 255 - opacity;
- }
-
- if (currentState === ControlsState.APP_GRID) {
- // in app grid hide workspaces so they're not blocking app grid or ws thumbnails
- this._workspacesDisplay.scale_x = 0;
- } else {
- this._workspacesDisplay.scale_x = 1;
- }
- this._workspacesDisplay.setPrimaryWorkspaceVisible(workspacesDisplayVisible);
-
- if (!this.dash._isAbove && progress > 0 && opt.OVERVIEW_MODE2) {
- // 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())
- this.set_child_above_sibling(dash, null);
- this.set_child_below_sibling(this._thumbnailsBox, null);
- this.set_child_below_sibling(this._workspacesDisplay, null);
- this.set_child_below_sibling(this._appDisplay, null);
- } else if (!this.dash._isAbove && progress === 1 && finalState > ControlsState.HIDDEN) {
- // 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())
- this.set_child_above_sibling(this.dash, null);
-
- this.dash._isAbove = true;
- } else if (this.dash._isAbove && progress < 1) {
- // keep dash below for ws transition between the overview and hidden state
- 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
- _updateAppDisplayVisibility(stateTransitionParams = null) {
- if (!stateTransitionParams)
- stateTransitionParams = this._stateAdjustment.getStateTransitionParams();
-
- const { currentState } = stateTransitionParams;
- 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 =
- currentState > ControlsState.HIDDEN &&
- !this._searchController.searchActive &&
- !(currentState === ControlsState.WINDOW_PICKER && !opt.APP_GRID_ANIMATION) &&
- !this._searchTransition;
- },
-
- _onSearchChanged() {
- const { finalState, currentState } = this._stateAdjustment.getStateTransitionParams();
-
- const { searchActive } = this._searchController;
- const SIDE_CONTROLS_ANIMATION_TIME = 250; // OverviewControls.SIDE_CONTROLS_ANIMATION_TIME = Overview.ANIMATION_TIME = 250
-
- const entry = this._searchEntry;
- if (opt.SHOW_SEARCH_ENTRY) {
- entry.visible = true;
- entry.opacity = 255;
- } else if (!(searchActive && entry.visible)) {
- entry.visible = true;
- entry.opacity = searchActive ? 0 : 255;
- // show search entry only if the user starts typing, and hide it when leaving the search mode
- entry.ease({
- opacity: searchActive ? 255 : 0,
- duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- entry.visible = searchActive;
- },
- });
- }
-
- // if user start typing or activated search provider during overview animation, this switcher will be called again after animation ends
- if (opt.SEARCH_VIEW_ANIMATION && Main.overview._animationInProgress && finalState !== ControlsState.HIDDEN)
- return;
-
- if (!searchActive) {
- this._workspacesDisplay.reactive = true;
- this._workspacesDisplay.setPrimaryWorkspaceVisible(true);
- } else {
- this._searchController.show();
- entry.visible = true;
- entry.opacity = 255;
- }
-
- this._searchTransition = true;
-
- this._searchController._searchResults.translation_x = 0;
- this._searchController._searchResults.translation_y = 0;
- 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*/) {
- this._updateAppDisplayVisibility();
-
- 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;
- }
- }
-
- if (searchActive) {
- this._searchController._searchResults.translation_x = translationX;
- this._searchController._searchResults.translation_y = translationY;
- } else {
- this._searchController._searchResults.translation_x = 0;
- this._searchController._searchResults.translation_y = 0;
- }
-
- this._searchController._searchResults.ease({
- translation_x: searchActive ? 0 : translationX,
- translation_y: searchActive ? 0 : translationY,
- duration: SIDE_CONTROLS_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- this._searchController.visible = searchActive;
- this._searchTransition = false;
- },
- });
-
- this._workspacesDisplay.opacity = 255;
- } else {
- this._appDisplay.ease({
- opacity: searchActive || currentState < 2 ? 0 : 255,
- duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => this._updateAppDisplayVisibility(),
- });
-
- // this._updateAppDisplayVisibility();
- this._workspacesDisplay.setPrimaryWorkspaceVisible(true);
- /* this._workspacesDisplay.ease({
- opacity: searchActive ? 0 : 255,
- duration: searchActive ? SIDE_CONTROLS_ANIMATION_TIME / 2 : 0,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- this._workspacesDisplay.reactive = !searchActive;
- this._workspacesDisplay.setPrimaryWorkspaceVisible(!searchActive);
- },
- });*/
-
- this._searchController.opacity = searchActive ? 0 : 255;
- this._searchController.ease({
- opacity: searchActive ? 255 : 0,
- duration: searchActive ? SIDE_CONTROLS_ANIMATION_TIME * 2 : 0,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => (this._searchController.visible = searchActive),
- });
- }
-
- // 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.searchEntry.remove_style_class_name('search-entry-om2');
- 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,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- this._workspacesDisplay.setPrimaryWorkspaceVisible(!searchActive);
- },
- });
- } 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.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.searchEntry.remove_style_class_name('search-entry-om2');
- }
- },
-
- async runStartupAnimation(callback) {
- this._ignoreShowAppsButtonToggle = true;
- this._searchController.prepareToEnterOverview();
- this._workspacesDisplay.prepareToEnterOverview();
-
- this._stateAdjustment.value = ControlsState.HIDDEN;
- this._stateAdjustment.ease(ControlsState.WINDOW_PICKER, {
- duration: ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
-
- this.dash.showAppsButton.checked = false;
- this._ignoreShowAppsButtonToggle = false;
-
- // Set the opacity here to avoid a 1-frame flicker
- this.opacity = 0;
-
- // We can't run the animation before the first allocation happens
- await this.layout_manager.ensureAllocation();
-
- const { STARTUP_ANIMATION_TIME } = imports.ui.layout;
-
- // Opacity
- this.ease({
- opacity: 255,
- duration: STARTUP_ANIMATION_TIME,
- mode: Clutter.AnimationMode.LINEAR,
- onComplete: () => {
- // part of the workaround for stuttering first app grid animation
- this._appDisplay.visible = true;
- },
- });
-
- const dash = this.dash;
- const tmbBox = this._thumbnailsBox;
-
- // Set the opacity here to avoid a 1-frame flicker
- dash.opacity = 0;
- for (const view of this._workspacesDisplay._workspacesViews) {
- if (view._monitorIndex !== global.display.get_primary_monitor())
- view._thumbnails.opacity = 0;
- }
-
- const searchEntryBin = this._searchEntryBin;
- const [tmbTranslationX, tmbTranslationY, dashTranslationX, dashTranslationY, searchTranslationY] =
- _Util.getOverviewTranslations(opt, dash, tmbBox, searchEntryBin);
-
- const onComplete = function () {
- // running init callback again causes issues (multiple connections)
- if (!_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;
- }
- );
- }.bind(this);
-
- if (dash.visible && !_Util.dashNotDefault()) {
- dash.translation_x = dashTranslationX;
- dash.translation_y = dashTranslationY;
- dash.opacity = 255;
- dash.ease({
- translation_x: 0,
- translation_y: 0,
- delay: STARTUP_ANIMATION_TIME / 2,
- duration: STARTUP_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- onComplete();
- },
- });
- } else {
- // set dash opacity to make it visible if user enable it later
- dash.opacity = 255;
- // if dash is hidden, substitute the ease timeout with GLib.timeout
- _timeouts.startupAnim2 = GLib.timeout_add(
- GLib.PRIORITY_DEFAULT,
- // delay + animation time
- STARTUP_ANIMATION_TIME * 2 * St.Settings.get().slow_down_factor,
- () => {
- onComplete();
- _timeouts.startupAnim2 = 0;
- return GLib.SOURCE_REMOVE;
- }
- );
- }
-
- if (searchEntryBin.visible) {
- searchEntryBin.translation_y = searchTranslationY;
- searchEntryBin.ease({
- translation_y: 0,
- delay: STARTUP_ANIMATION_TIME / 2,
- duration: STARTUP_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- }
-
- if (tmbBox.visible) {
- tmbBox.translation_x = tmbTranslationX;
- tmbBox.translation_y = tmbTranslationY;
- tmbBox.ease({
- translation_x: 0,
- translation_y: 0,
- delay: STARTUP_ANIMATION_TIME / 2,
- duration: STARTUP_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- }
-
- // upstream bug - following animation will be cancelled, don't know where
- // needs further investigation
- const workspacesViews = this._workspacesDisplay._workspacesViews;
- if (workspacesViews.length > 1) {
- for (const view of workspacesViews) {
- 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)
- secTmbBox.translation_x = secTmbBox.width + 12;
- else if (opt.SEC_WS_TMB_TOP)
- secTmbBox.translation_y = -(secTmbBox.height + 12);
- else if (opt.SEC_WS_TMB_BOTTOM)
- secTmbBox.translation_y = secTmbBox.height + 12;
-
- secTmbBox.opacity = 255;
-
- secTmbBox.ease({
- translation_y: 0,
- delay: STARTUP_ANIMATION_TIME / 2,
- duration: STARTUP_ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- }
- }
- }
- },
-
- 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
- // the time can be close to or longer than ANIMATION_TIME
- // in which case the the animation is greatly delayed, stuttering, or even skipped
- // for user it is more acceptable to watch delayed smooth animation,
- // even if it takes little more time, than jumping frames
- let delay = 0;
- if (opt.DELAY_OVERVIEW_ANIMATION)
- delay = global.display.get_tab_list(0, global.workspace_manager.get_active_workspace()).length * 3;
-
- this._stateAdjustment.ease(state, {
- delay,
- duration: 250, // Overview.ANIMATION_TIME,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onStopped: () => {
- if (callback)
- callback();
- },
- });
-
- this.dash.showAppsButton.checked =
- state === ControlsState.APP_GRID;
-
- this._ignoreShowAppsButtonToggle = false;
- },
-};
-
-const ControlsManagerLayoutVertical = {
- _computeWorkspacesBoxForState(state, box, workAreaBox, dashWidth, dashHeight, thumbnailsWidth, searchHeight, startY) {
- const workspaceBox = box.copy();
- let [width, height] = workspaceBox.get_size();
- // const { x1: startX/* y1: startY*/ } = workAreaBox;
- const { spacing } = this;
- // const { expandFraction } = this._workspacesThumbnails;
-
- const dash = Main.overview.dash;
- // including Dash to Dock and clones properties for compatibility
-
- if (_Util.dashIsDashToDock()) {
- // Dash to Dock also always affects workAreaBox
- Main.layoutManager._trackedActors.forEach(actor => {
- if (actor.affectsStruts && actor.actor.width === dash.width) {
- if (dash._isHorizontal) {
- // disabled inteli-hide don't needs compensation
- // startY needs to be corrected in allocate()
- if (dash.get_parent()?.get_parent()?.get_parent()?._intellihideIsEnabled)
- height += dash.height;
- } else {
- width += dash.width;
- }
- }
- });
- }
-
- let wWidth;
- let wHeight;
- let wsBoxY;
-
- switch (state) {
- case ControlsState.HIDDEN:
- // if PANEL_OVERVIEW_ONLY, the affectStruts property is set to false to avoid stuttering
- // therefore we added panel height to startY for the overview allocation,
- // but here we need to remove the correction because the panel will be in the hidden state
- if (opt.START_Y_OFFSET) {
- let [x, y] = workAreaBox.get_origin();
- y -= opt.START_Y_OFFSET;
- workspaceBox.set_origin(x, y);
- } else {
- workspaceBox.set_origin(...workAreaBox.get_origin());
- }
- workspaceBox.set_size(...workAreaBox.get_size());
- break;
- case ControlsState.WINDOW_PICKER:
- 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());
- } else if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE) {
- if (opt.START_Y_OFFSET) {
- let [x, y] = workAreaBox.get_origin();
- y -= opt.START_Y_OFFSET;
- workspaceBox.set_origin(x, y);
- } else {
- workspaceBox.set_origin(...workAreaBox.get_origin());
- }
- workspaceBox.set_size(...workAreaBox.get_size());
- } else {
- // if PANEL_OVERVIEW_ONLY, panel doesn't affect workArea height (affectStruts === false), it is necessary to compensate
- 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) -
- thumbnailsWidth -
- 4 * spacing;
- wHeight = height -
- (opt.DASH_VERTICAL ? 0 : dashHeight) -
- searchHeight -
- 4 * spacing;
-
- const ratio = width / height;
- let wRatio = wWidth / wHeight;
- let scale = ratio / wRatio;
-
- if (scale > 1) {
- wHeight /= scale;
- wWidth = wHeight * ratio;
- } else {
- wWidth *= scale;
- wHeight = wWidth / ratio;
- }
-
- // height decides the actual size, ratio is given by the workarea
- wHeight *= opt.WS_PREVIEW_SCALE;
- wWidth *= opt.WS_PREVIEW_SCALE;
-
- let xOffset = 0;
- let yOffset = 0;
-
- const yOffsetT = (opt.DASH_TOP ? dashHeight : 0) + searchHeight;
- const yOffsetB = opt.DASH_BOTTOM ? dashHeight : 0;
- const yAvailableSpace = (height - yOffsetT - wHeight - yOffsetB) / 2;
- yOffset = yOffsetT + yAvailableSpace;
-
- const centeredBoxX = (width - wWidth) / 2;
-
- const xOffsetL = (opt.DASH_LEFT ? dashWidth : 0) + (opt.WS_TMB_LEFT ? thumbnailsWidth : 0) + 2 * spacing;
- const xOffsetR = (opt.DASH_RIGHT ? dashWidth : 0) + (opt.WS_TMB_RIGHT ? thumbnailsWidth : 0) + 2 * spacing;
-
- this._xAlignCenter = false;
- if (centeredBoxX < Math.max(xOffsetL, xOffsetR)) {
- xOffset = xOffsetL + spacing + (width - xOffsetL - wWidth - xOffsetR - 2 * spacing) / 2;
- } else {
- xOffset = centeredBoxX;
- this._xAlignCenter = true;
- }
-
- const wsBoxX = /* startX + */xOffset;
- wsBoxY = Math.round(startY + yOffset);
- workspaceBox.set_origin(Math.round(wsBoxX), Math.round(wsBoxY));
- workspaceBox.set_size(Math.round(wWidth), Math.round(wHeight));
- }
- }
-
- return workspaceBox;
- },
-
- _getAppDisplayBoxForState(state, box, workAreaBox, searchHeight, dashWidth, dashHeight, thumbnailsWidth, startY) {
- const [width] = box.get_size();
- const { x1: startX } = workAreaBox;
- // const { y1: startY } = workAreaBox;
- let height = workAreaBox.get_height();
- const appDisplayBox = new Clutter.ActorBox();
- const { spacing } = this;
-
- searchHeight = opt.SHOW_SEARCH_ENTRY ? searchHeight : 0;
-
- const xOffsetL = (opt.WS_TMB_LEFT ? thumbnailsWidth : 0) + (opt.DASH_LEFT ? dashWidth : 0);
- 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 appDisplayX = opt.CENTER_APP_GRID ? (width - adWidth) / 2 : xOffsetL + 2 * spacing;
- const appDisplayY = startY + yOffsetT + 2 * spacing;
-
- switch (state) {
- case ControlsState.HIDDEN:
- case ControlsState.WINDOW_PICKER:
- // 1 - left, 2 - right, 3 - bottom, 5 - top
- switch (opt.APP_GRID_ANIMATION) {
- case 0:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
- break;
- case 1:
- appDisplayBox.set_origin(startX + width, appDisplayY);
- break;
- case 2:
- appDisplayBox.set_origin(startX - adWidth, appDisplayY);
- break;
- case 3:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y2);
- break;
- case 5:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y1 - adHeight);
- break;
- }
- break;
- case ControlsState.APP_GRID:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
- break;
- }
-
- appDisplayBox.set_size(adWidth, adHeight);
- return appDisplayBox;
- },
-
- vfunc_allocate(container, box) {
- const childBox = new Clutter.ActorBox();
-
- const { spacing } = this;
-
- 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);
- box.y1 += startY;
- 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)
- height = opt.PANEL_POSITION_TOP ? height : height - Main.panel.height;
- let availableHeight = height;
-
- // Dash
- const maxDashHeight = Math.round(box.get_height() * DASH_MAX_SIZE_RATIO);
- const maxDashWidth = maxDashHeight * 0.8;
- let dashHeight = 0;
- let dashWidth = 0;
-
- // 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 (!Main.overview.dash.get_parent()?.get_parent()?.get_parent()?._intellihideIsEnabled) {
- if (Main.panel.y === monitor.y)
- startY = Main.panel.height + spacing;
- }
- dashHeight = dash.height;
- dashWidth = dash.width;
- opt.DASH_VERTICAL = [1, 3].includes(dash._position);
- this._dash.allocate(childBox);
- } else if (this._dash.visible) {
- // default dock
- if (opt.DASH_VERTICAL) {
- this._dash.setMaxSize(maxDashWidth, height);
- [, dashWidth] = this._dash.get_preferred_width(height);
- [, dashHeight] = this._dash.get_preferred_height(dashWidth);
- dashWidth = Math.min(dashWidth, maxDashWidth);
- dashHeight = Math.min(dashHeight, height);
- } else if (!opt.WS_TMB_FULL) {
- this._dash.setMaxSize(width, maxDashHeight);
- [, dashHeight] = this._dash.get_preferred_height(width);
- [, dashWidth] = this._dash.get_preferred_width(dashHeight);
- dashHeight = Math.min(dashHeight, maxDashHeight);
- dashWidth = Math.min(dashWidth, width);
- }
- }
-
- const transitionParams = this._stateAdjustment.getStateTransitionParams();
-
- // Workspace Thumbnails
- let wsTmbWidth = 0;
- let wsTmbHeight = 0;
-
- if (this._workspacesThumbnails.visible) {
- // const { expandFraction } = this._workspacesThumbnails;
- const dashHeightReservation = !opt.WS_TMB_FULL && !opt.DASH_VERTICAL ? dashHeight : 0;
-
- let maxScale = opt.MAX_THUMBNAIL_SCALE;
- if (!opt.MAX_THUMBNAIL_SCALE_STABLE) {
- 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);
- }
-
- wsTmbWidth = width * maxScale;
- let totalTmbSpacing;
- [totalTmbSpacing, wsTmbHeight] = this._workspacesThumbnails.get_preferred_custom_height(wsTmbWidth);
- wsTmbHeight += totalTmbSpacing;
-
- const wsTmbHeightMax = height - dashHeightReservation;
-
- if (wsTmbHeight > wsTmbHeightMax) {
- wsTmbHeight = wsTmbHeightMax;
- wsTmbWidth = this._workspacesThumbnails.get_preferred_custom_width(wsTmbHeight)[1];
- }
-
- let wsTmbX;
- if (opt.WS_TMB_RIGHT)
- wsTmbX = Math.round(startX + width - (opt.DASH_RIGHT ? dashWidth : 0) - wsTmbWidth - spacing / 2);
- else
- wsTmbX = Math.round((opt.DASH_LEFT ? dashWidth : 0) + spacing / 2);
-
-
- let wstOffset = (height - wsTmbHeight - (opt.DASH_VERTICAL ? 0 : dashHeightReservation)) / 2;
- wstOffset -= opt.WS_TMB_POSITION_ADJUSTMENT * (wstOffset - spacing / 2);
- 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));
-
- this._workspacesThumbnails.allocate(childBox);
- }
-
-
- if (this._dash.visible) {
- const wMaxWidth = width - spacing - wsTmbWidth - 2 * spacing - (opt.DASH_VERTICAL ? dashWidth + spacing : 0);
- if (opt.WS_TMB_FULL && !opt.DASH_VERTICAL) {
- this._dash.setMaxSize(wMaxWidth, maxDashHeight);
- [, dashHeight] = this._dash.get_preferred_height(wMaxWidth);
- [, dashWidth] = this._dash.get_preferred_width(dashHeight);
- dashHeight = Math.round(Math.min(dashHeight, maxDashHeight));
- dashWidth = Math.round(Math.min(dashWidth, wMaxWidth));
- }
-
- let dashX, dashY, offset;
- if (opt.DASH_RIGHT)
- dashX = width - dashWidth;
- else if (opt.DASH_LEFT)
- dashX = 0;
-
- else if (opt.DASH_TOP)
- dashY = startY;
- else
- dashY = startY + height - dashHeight;
-
- 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);
- dashX = offset;
-
- if ((opt.WS_TMB_FULL || opt.CENTER_DASH_WS) && !this._xAlignCenter) {
- if (!opt.WS_TMB_RIGHT) {
- dashX = (wsTmbWidth ? wsTmbWidth : 0) + offset;
- dashX = Math.max(dashX, wsTmbWidth ? wsTmbWidth + spacing : 0);
- dashX = Math.min(dashX, width - dashWidth - spacing);
- }
- }
- if (opt.WS_TMB_FULL && !opt.CENTER_DASH_WS) {
- dashX = opt.WS_TMB_RIGHT
- ? Math.min(width - wsTmbWidth - dashWidth, dashX + wsTmbWidth / 2 * (1 - Math.abs(opt.DASH_POSITION_ADJUSTMENT)))
- : Math.max(wsTmbWidth, dashX - wsTmbWidth / 2 * (1 - Math.abs(opt.DASH_POSITION_ADJUSTMENT)));
- }
- } else {
- offset = (height - dashHeight) / 2;
- dashY = startY + (offset - opt.DASH_POSITION_ADJUSTMENT * offset);
- }
-
- childBox.set_origin(Math.round(startX + dashX), Math.round(dashY));
- childBox.set_size(dashWidth, dashHeight);
- this._dash.allocate(childBox);
- }
-
- availableHeight -= opt.DASH_VERTICAL ? 0 : dashHeight + spacing;
-
- let [searchHeight] = this._searchEntry.get_preferred_height(width - wsTmbWidth);
-
- // Workspaces
- let params = [box, workAreaBox, dashWidth, dashHeight, wsTmbWidth, searchHeight, startY];
-
- // Update cached boxes
- for (const state of Object.values(ControlsState)) {
- this._cachedWorkspaceBoxes.set(
- state, this._computeWorkspacesBoxForState(state, ...params));
- }
-
- let workspacesBox;
- if (!transitionParams.transitioning)
- workspacesBox = this._cachedWorkspaceBoxes.get(transitionParams.currentState);
-
- if (!workspacesBox) {
- const initialBox = this._cachedWorkspaceBoxes.get(transitionParams.initialState);
- const finalBox = this._cachedWorkspaceBoxes.get(transitionParams.finalState);
- workspacesBox = initialBox.interpolate(finalBox, transitionParams.progress);
- }
-
- this._workspacesDisplay.allocate(workspacesBox);
-
- // Search entry
- const searchXoffset = (opt.DASH_LEFT ? dashWidth : 0) + spacing + (opt.WS_TMB_RIGHT ? 0 : wsTmbWidth + spacing);
-
- // Y position under top Dash
- let searchEntryX, searchEntryY;
- if (opt.DASH_TOP)
- searchEntryY = startY + dashHeight - spacing;
- else
- searchEntryY = startY;
-
-
- searchEntryX = searchXoffset;
- let searchWidth = width - 2 * spacing - wsTmbWidth - (opt.DASH_VERTICAL ? dashWidth : 0); // xAlignCenter is given by wsBox
- searchWidth = this._xAlignCenter ? width - 2 * (wsTmbWidth + spacing) : searchWidth;
-
- if (opt.CENTER_SEARCH_VIEW) {
- childBox.set_origin(0, searchEntryY);
- childBox.set_size(width, searchHeight);
- } else {
- childBox.set_origin(this._xAlignCenter ? 0 : searchEntryX, searchEntryY);
- childBox.set_size(this._xAlignCenter ? width : searchWidth - spacing, searchHeight);
- }
-
- this._searchEntry.allocate(childBox);
-
- availableHeight -= searchHeight + spacing;
-
- // if (this._appDisplay.visible)... ? Can cause problems
- params = [box, workAreaBox, searchHeight, dashWidth, dashHeight, wsTmbWidth, startY]; // send startY, can be corrected
- let appDisplayBox;
- if (!transitionParams.transitioning) {
- appDisplayBox =
- this._getAppDisplayBoxForState(transitionParams.currentState, ...params);
- } else {
- const initialBox =
- this._getAppDisplayBoxForState(transitionParams.initialState, ...params);
- const finalBox =
- this._getAppDisplayBoxForState(transitionParams.finalState, ...params);
-
- appDisplayBox = initialBox.interpolate(finalBox, transitionParams.progress);
- }
- this._appDisplay.allocate(appDisplayBox);
-
- // Search
- 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);
- } else {
- childBox.set_origin(this._xAlignCenter ? wsTmbWidth + spacing : searchXoffset, startY + (opt.DASH_TOP ? dashHeight : spacing) + searchHeight);
- }
-
- childBox.set_size(searchWidth, availableHeight);
- this._searchController.allocate(childBox);
-
- this._runPostAllocation();
- },
-};
-
-const ControlsManagerLayoutHorizontal = {
- _computeWorkspacesBoxForState(state, box, workAreaBox, dashWidth, dashHeight, thumbnailsHeight, searchHeight, startY) {
- const workspaceBox = box.copy();
- let [width, height] = workspaceBox.get_size();
- // let { x1: startX/* , y1: startY*/ } = workAreaBox;
- const { spacing } = this;
- // const { expandFraction } = this._workspacesThumbnails;
-
- const dash = Main.overview.dash;
- // including Dash to Dock and clones properties for compatibility
- if (_Util.dashIsDashToDock()) {
- // Dash to Dock always affects workAreaBox
- Main.layoutManager._trackedActors.forEach(actor => {
- if (actor.affectsStruts && actor.actor.width === dash.width) {
- if (dash._isHorizontal) {
- // disabled inteli-hide don't need compensation
- // startY needs to be corrected in allocate()
- if (dash.get_parent()?.get_parent()?.get_parent()?._intellihideIsEnabled)
- height += dash.height;
- else if (opt.DASH_TOP)
- height += dash.height;
- } else {
- width += dash.width;
- }
- }
- });
- }
-
- let wWidth, wHeight, wsBoxY, wsBoxX;
-
- switch (state) {
- case ControlsState.HIDDEN:
- // if PANEL_OVERVIEW_ONLY, the affectStruts property is set to false to avoid stuttering
- // therefore we added panel height to startY for the overview allocation,
- // but here we need to remove the correction since the panel will be in the hidden state
- if (opt.START_Y_OFFSET) {
- let [x, y] = workAreaBox.get_origin();
- y -= opt.START_Y_OFFSET;
- workspaceBox.set_origin(x, y);
- } else {
- workspaceBox.set_origin(...workAreaBox.get_origin());
- }
- workspaceBox.set_size(...workAreaBox.get_size());
- break;
- case ControlsState.WINDOW_PICKER:
- 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());
- } else if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE) {
- if (opt.START_Y_OFFSET) {
- let [x, y] = workAreaBox.get_origin();
- y -= opt.START_Y_OFFSET;
- workspaceBox.set_origin(x, y);
- } else {
- workspaceBox.set_origin(...workAreaBox.get_origin());
- }
- workspaceBox.set_size(...workAreaBox.get_size());
- } else {
- // if PANEL_OVERVIEW_ONLY, panel doesn't affect workArea height (affectStruts === false), it is necessary to compensate
- height = opt.PANEL_POSITION_TOP ? height : height - Main.panel.height;
- searchHeight = opt.SHOW_SEARCH_ENTRY ? searchHeight : 0;
- wWidth = width -
- spacing -
- (opt.DASH_VERTICAL ? dashWidth : 0) -
- 4 * spacing;
- wHeight = height -
- (opt.DASH_VERTICAL ? spacing : dashHeight) -
- thumbnailsHeight -
- searchHeight -
- 4 * spacing;
-
- const ratio = width / height;
- let wRatio = wWidth / wHeight;
- let scale = ratio / wRatio;
-
- if (scale > 1) {
- wHeight /= scale;
- wWidth = wHeight * ratio;
- } else {
- wWidth *= scale;
- wHeight = wWidth / ratio;
- }
-
- // height decides the actual size, ratio is given by the workarea
- wHeight *= opt.WS_PREVIEW_SCALE;
- wWidth *= opt.WS_PREVIEW_SCALE;
-
- let xOffset = 0;
- let yOffset = 0;
-
- const yOffsetT = (opt.DASH_TOP ? dashHeight : 0) + (opt.WS_TMB_TOP ? thumbnailsHeight : 0) + searchHeight;
- const yOffsetB = (opt.DASH_BOTTOM ? dashHeight : 0) + (opt.WS_TMB_BOTTOM ? thumbnailsHeight : 0);
-
- const yAvailableSpace = (height - yOffsetT - wHeight - yOffsetB) / 2;
- yOffset = yOffsetT + yAvailableSpace;
-
- const xOffsetL = (opt.DASH_LEFT ? dashWidth : 0) + spacing;
- const xOffsetR = (opt.DASH_RIGHT ? dashWidth : 0) + spacing;
- const centeredBoxX = (width - wWidth) / 2;
-
- this._xAlignCenter = false;
- if (centeredBoxX < Math.max(xOffsetL, xOffsetR)) {
- xOffset = xOffsetL + spacing + (width - xOffsetL - wWidth - xOffsetR) / 2;
- } else {
- xOffset = centeredBoxX;
- this._xAlignCenter = true;
- }
-
- wsBoxX = /* startX + */xOffset;
- wsBoxY = Math.round(startY + yOffset);
- workspaceBox.set_origin(Math.round(wsBoxX), Math.round(wsBoxY));
- workspaceBox.set_size(Math.round(wWidth), Math.round(wHeight));
- }
- }
-
- return workspaceBox;
- },
-
- _getAppDisplayBoxForState(state, box, workAreaBox, searchHeight, dashWidth, dashHeight, thumbnailsHeight, startY) {
- const [width] = box.get_size();
- const { x1: startX } = workAreaBox;
- // const { y1: startY } = workAreaBox;
- let height = workAreaBox.get_height();
- 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 xOffsetL = opt.DASH_LEFT ? dashWidth : 0;
- const xOffsetR = opt.DASH_RIGHT ? dashWidth : 0;
- const hSpacing = xOffsetL + xOffsetR ? 2 * 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 appDisplayX = opt.CENTER_APP_GRID ? (width - adWidth) / 2 : xOffsetL + hSpacing;
- const appDisplayY = startY + yOffsetT + hSpacing;
-
- switch (state) {
- case ControlsState.HIDDEN:
- case ControlsState.WINDOW_PICKER:
- // 1 - left, 2 - right, 3 - bottom, 5 - top
- switch (opt.APP_GRID_ANIMATION) {
- case 0:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
- break;
- case 1:
- appDisplayBox.set_origin(startX + width, appDisplayY);
- break;
- case 2:
- appDisplayBox.set_origin(startX - adWidth, appDisplayY);
- break;
- case 3:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y2);
- break;
- case 5:
- appDisplayBox.set_origin(appDisplayX, workAreaBox.y1 - adHeight);
- break;
- }
- break;
- case ControlsState.APP_GRID:
- appDisplayBox.set_origin(appDisplayX, appDisplayY);
- break;
- }
-
- appDisplayBox.set_size(adWidth, adHeight);
- return appDisplayBox;
- },
-
- vfunc_allocate(container, box) {
- const childBox = new Clutter.ActorBox();
-
- const { spacing } = this;
-
- 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);
- box.y1 += startY;
- box.x1 += startX;
- let [width, height] = box.get_size();
- // if panel is at bottom position,
- // 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;
-
- // Dash
- const maxDashHeight = Math.round(box.get_height() * DASH_MAX_SIZE_RATIO);
- const maxDashWidth = maxDashHeight * 0.8;
- let dashHeight = 0;
- let dashWidth = 0;
-
- // 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 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;
- }
- dashHeight = dash.height;
- dashWidth = dash.width;
- opt.DASH_TOP = dash._position === 0;
- opt.DASH_VERTICAL = [1, 3].includes(dash._position);
- this._dash.allocate(childBox);
- } else if (this._dash.visible) {
- // default dock
- if (!opt.DASH_VERTICAL) {
- this._dash.setMaxSize(width, maxDashHeight);
- [, dashHeight] = this._dash.get_preferred_height(width);
- [, dashWidth] = this._dash.get_preferred_width(dashHeight);
- dashHeight = Math.min(dashHeight, maxDashHeight);
- dashWidth = Math.min(dashWidth, width - spacing);
- } else if (!opt.WS_TMB_FULL) {
- this._dash.setMaxSize(maxDashWidth, height);
- [, dashWidth] = this._dash.get_preferred_width(height);
- [, dashHeight] = this._dash.get_preferred_height(dashWidth);
- dashHeight = Math.min(dashHeight, height - spacing);
- dashWidth = Math.min(dashWidth, width);
- }
- }
-
- 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;
- const dashWidthReservation = !opt.WS_TMB_FULL && opt.DASH_VERTICAL ? dashWidth : 0;
-
- let maxScale = opt.MAX_THUMBNAIL_SCALE;
- if (!opt.MAX_THUMBNAIL_SCALE_STABLE) {
- 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);
- }
-
- wsTmbHeight = height * maxScale;
- let totalTmbSpacing;
- [totalTmbSpacing, wsTmbWidth] = this._workspacesThumbnails.get_preferred_custom_width(wsTmbHeight);
- wsTmbWidth += totalTmbSpacing;
-
- const wsTmbWidthMax = opt.WS_TMB_FULL
- ? width
- : width - (opt.DASH_VERTICAL ? 0 : dashWidthReservation);
-
- if (wsTmbWidth > wsTmbWidthMax) {
- wsTmbWidth = wsTmbWidthMax;
- wsTmbHeight = this._workspacesThumbnails.get_preferred_custom_height(wsTmbWidth)[1];
- }
-
- let wsTmbY;
- if (opt.WS_TMB_TOP)
- wsTmbY = Math.round(startY + /* searchHeight + */(opt.DASH_TOP ? dashHeight : spacing / 2));
- else
- wsTmbY = Math.round(startY + height - (opt.DASH_BOTTOM ? dashHeight : 0) - 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)
- ));
-
- childBox.set_origin(wsTmbX, wsTmbY);
- childBox.set_size(Math.round(wsTmbWidth), Math.round(wsTmbHeight));
-
- this._workspacesThumbnails.allocate(childBox);
-
- availableHeight -= wsTmbHeight + spacing;
- }
-
-
- if (this._dash.visible) {
- if (opt.WS_TMB_FULL && opt.DASH_VERTICAL) {
- const wMaxHeight = height - spacing - wsTmbHeight;
- this._dash.setMaxSize(maxDashWidth, wMaxHeight);
- [, dashWidth] = this._dash.get_preferred_width(wMaxHeight);
- [, dashHeight] = this._dash.get_preferred_height(dashWidth);
- dashWidth = Math.round(Math.min(dashWidth, maxDashWidth));
- dashHeight = Math.round(Math.min(dashHeight, wMaxHeight));
- }
-
- let dashX, dashY, offset;
- if (opt.DASH_RIGHT)
- dashX = width - dashWidth;
- else if (opt.DASH_LEFT)
- dashX = 0;
- else if (opt.DASH_TOP)
- dashY = startY;
- 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);
- dashY = startY + offset + wsTmbHeight;
- } else {
- offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - spacing / 2);
- dashY = startY + offset;
- }
- } else {
- offset = (height - dashHeight) / 2;
- offset -= opt.DASH_POSITION_ADJUSTMENT * (offset - spacing / 2);
- dashY = startY + offset;
- }
- } else {
- offset = (width - dashWidth) / 2;
- dashX = startX + (offset - opt.DASH_POSITION_ADJUSTMENT * (offset - spacing));
- }
-
- childBox.set_origin(Math.round(startX + dashX), Math.round(dashY));
- childBox.set_size(dashWidth, dashHeight);
- this._dash.allocate(childBox);
- }
-
- availableHeight -= opt.DASH_VERTICAL ? 0 : dashHeight;
-
- // Workspaces
- let params = [box, workAreaBox, dashWidth, dashHeight, wsTmbHeight, searchHeight, startY];
-
- // Update cached boxes
- for (const state of Object.values(ControlsState)) {
- this._cachedWorkspaceBoxes.set(
- state, this._computeWorkspacesBoxForState(state, ...params));
- }
-
- let workspacesBox;
- if (!transitionParams.transitioning)
- workspacesBox = this._cachedWorkspaceBoxes.get(transitionParams.currentState);
-
- if (!workspacesBox) {
- const initialBox = this._cachedWorkspaceBoxes.get(transitionParams.initialState);
- const finalBox = this._cachedWorkspaceBoxes.get(transitionParams.finalState);
- workspacesBox = initialBox.interpolate(finalBox, transitionParams.progress);
- }
-
- this._workspacesDisplay.allocate(workspacesBox);
-
- // Search entry
- const searchXoffset = (opt.DASH_LEFT ? dashWidth : 0) + spacing;
-
- // Y position under top Dash
- let searchEntryX, searchEntryY;
- if (opt.DASH_TOP)
- searchEntryY = startY + (opt.WS_TMB_TOP ? wsTmbHeight : 0) + dashHeight - spacing;
- else
- searchEntryY = startY + (opt.WS_TMB_TOP ? wsTmbHeight + spacing : 0);
-
-
- searchEntryX = searchXoffset;
- let searchWidth = width - 2 * spacing - (opt.DASH_VERTICAL ? dashWidth : 0); // xAlignCenter is given by wsBox
- searchWidth = this._xAlignCenter ? width : searchWidth;
-
- if (opt.CENTER_SEARCH_VIEW) {
- childBox.set_origin(0, searchEntryY);
- childBox.set_size(width, searchHeight);
- } else {
- childBox.set_origin(this._xAlignCenter ? 0 : searchEntryX, searchEntryY);
- childBox.set_size(this._xAlignCenter ? width : searchWidth - spacing, searchHeight);
- }
-
- this._searchEntry.allocate(childBox);
-
- availableHeight -= searchHeight + spacing;
-
- // if (this._appDisplay.visible)... ? Can cause problems
- params = [box, workAreaBox, searchHeight, dashWidth, dashHeight, wsTmbHeight, startY];
- let appDisplayBox;
- if (!transitionParams.transitioning) {
- appDisplayBox =
- this._getAppDisplayBoxForState(transitionParams.currentState, ...params);
- } else {
- const initialBox =
- this._getAppDisplayBoxForState(transitionParams.initialState, ...params);
- const finalBox =
- this._getAppDisplayBoxForState(transitionParams.finalState, ...params);
-
- appDisplayBox = initialBox.interpolate(finalBox, transitionParams.progress);
- }
- this._appDisplay.allocate(appDisplayBox);
-
- // Search
- 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);
- } else {
- childBox.set_origin(this._xAlignCenter ? spacing : searchXoffset, startY + (opt.DASH_TOP ? dashHeight : spacing) + (opt.WS_TMB_TOP ? wsTmbHeight + spacing : 0) + searchHeight);
- }
-
- childBox.set_size(searchWidth, availableHeight);
- this._searchController.allocate(childBox);
-
- this._runPostAllocation();
- },
-};
-
-// same copy of this function should be available in OverviewControls and WorkspacesView
-function _getFitModeForState(state) {
- switch (state) {
- case ControlsState.HIDDEN:
- case ControlsState.WINDOW_PICKER:
- return FitMode.SINGLE;
- case ControlsState.APP_GRID:
- if (opt.WS_ANIMATION && opt.SHOW_WS_TMB)
- return FitMode.ALL;
- else
- return FitMode.SINGLE;
- default:
- return FitMode.SINGLE;
- }
-}
diff --git a/extensions/vertical-workspaces/lib/panel.js b/extensions/vertical-workspaces/lib/panel.js
deleted file mode 100644
index 3f44ae7..0000000
--- a/extensions/vertical-workspaces/lib/panel.js
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * panel.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { GLib } = imports.gi;
-const Main = imports.ui.main;
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-const _Util = Me.imports.lib.util;
-
-const ANIMATION_TIME = imports.ui.overview.ANIMATION_TIME;
-
-let opt;
-let _firstRun = true;
-
-let _showingOverviewConId;
-let _hidingOverviewConId;
-let _styleChangedConId;
-
-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);
-
- // don't even touch this module if disabled or in potential conflict
- if (_firstRun && (reset || conflict))
- return;
-
- _firstRun = false;
-
- const panelBox = Main.layoutManager.panelBox;
- if (reset || !moduleEnabled) {
- // _disconnectPanel();
- reset = true;
- _setPanelPosition(reset);
- _updateOverviewConnection(reset);
- _reparentPanel(false);
-
- _updateStyleChangedConnection(reset);
-
- panelBox.translation_y = 0;
- Main.panel.opacity = 255;
- _setPanelStructs(true);
- return;
- }
-
- _setPanelPosition();
- _updateStyleChangedConnection();
-
- if (opt.PANEL_MODE === 0) {
- _updateOverviewConnection(true);
- _reparentPanel(false);
- 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);
- }
- _showPanel(true);
- } else {
- // if ws preview bg is disabled, panel can stay in uiGroup
- _reparentPanel(false);
- _showPanel(false);
- _updateOverviewConnection();
- }
- // _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;
- }
- } 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');
- });
- }
-}
-
-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);
- });
- }
- if (!_showingOverviewConId) {
- _showingOverviewConId = Main.overview.connect('showing', () => {
- if (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2 || Main.layoutManager.panelBox.translation_y)
- _showPanel(true);
- });
- }
- }
-}
-
-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);
- },
- });
- }
-}
diff --git a/extensions/vertical-workspaces/lib/recentFilesSearchProvider.js b/extensions/vertical-workspaces/lib/recentFilesSearchProvider.js
deleted file mode 100644
index 86e38f4..0000000
--- a/extensions/vertical-workspaces/lib/recentFilesSearchProvider.js
+++ /dev/null
@@ -1,260 +0,0 @@
-/**
- * Vertical Workspaces
- * recentFilesSearchProvider.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- */
-
-'use strict';
-
-const { GLib, Gio, Meta, St, Shell, Gtk } = imports.gi;
-
-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;
-
-// gettext
-const _ = Settings._;
-
-const shellVersion = Settings.shellVersion;
-
-const ModifierType = imports.gi.Clutter.ModifierType;
-
-let recentFilesSearchProvider;
-let _enableTimeoutId = 0;
-
-// 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//';
-
-var opt;
-
-function getOverviewSearchResult() {
- return Main.overview._overview.controls._searchController._searchResults;
-}
-
-
-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;
- }
-}
-
-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);
- }
- _enableTimeoutId = 0;
- return GLib.SOURCE_REMOVE;
- }
- );
-}
-
-function disable() {
- if (recentFilesSearchProvider) {
- getOverviewSearchResult()._unregisterProvider(recentFilesSearchProvider);
- recentFilesSearchProvider = null;
- }
- if (_enableTimeoutId) {
- GLib.source_remove(_enableTimeoutId);
- _enableTimeoutId = 0;
- }
-}
-
-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,
- };
-}
-
-const closeSelectedRegex = /^\/x!$/;
-const closeAllResultsRegex = /^\/xa!$/;
-const moveToWsRegex = /^\/m[0-9]+$/;
-const moveAllToWsRegex = /^\/ma[0-9]+$/;
-
-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;
-
- this.canLaunchSearch = true;
- this.isRemoteProvider = false;
- }
-
- _getResultSet(terms) {
- 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, '');
-
- const candidates = this.files;
- const _terms = [].concat(termsCopy);
- // let match;
-
- const term = _terms.join(' ');
- /* match = s => {
- return fuzzyMatch(term, s);
- }; */
-
- const results = [];
- let m;
- for (let id in candidates) {
- 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);
- else
- m = _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());
-
- this.resultIds = results.map(item => item.id);
- return this.resultIds;
- }
-
- getResultMetas(resultIds, callback = null) {
- const metas = resultIds.map(id => this.getResultMeta(id));
- if (shellVersion >= 43)
- return new Promise(resolve => resolve(metas));
- else if (callback)
- callback(metas);
- return null;
- }
-
- getResultMeta(resultId) {
- const result = this.files[resultId];
- return {
- 'id': resultId,
- 'name': `${result.get_age()}: ${result.get_display_name()}`,
- 'description': `${result.get_uri_display().replace(`/${result.get_display_name()}`, '')}`,
- 'createIcon': size => {
- let icon = this.getIcon(result, size);
- return icon;
- },
- };
- }
-
- 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();
- }
-
- 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:///');
- }
-
- _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()) {
- Main.overview.toggle();
- this._openNautilus(file.get_uri());
- } 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());
- }
- }
-
- 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, 20);
- // return results.slice(0, maxResults);
- }
-
- getSubsearchResultSet(previousResults, terms, callback /* , cancellable*/) {
- // if we return previous results, quick typers get non-actual results
- callback(this._getResultSet(terms));
- }
-
- /* createResultObject(resultMeta) {
- return this.files[resultMeta.id];
- }*/
-};
diff --git a/extensions/vertical-workspaces/lib/search.js b/extensions/vertical-workspaces/lib/search.js
deleted file mode 100644
index 8540626..0000000
--- a/extensions/vertical-workspaces/lib/search.js
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * search.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-const { Shell, Gio, St, Clutter } = imports.gi;
-const Main = imports.ui.main;
-
-const AppDisplay = imports.ui.appDisplay;
-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 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;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
- _updateSearchViewWidth(reset);
-
- if (reset) {
- Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.FILL;
- opt = null;
- _overrides = null;
- return;
- }
-
- _overrides = new _Util.Overrides();
-
- _overrides.addOverride('AppSearchProvider', AppDisplay.AppSearchProvider.prototype, AppSearchProvider);
- _overrides.addOverride('SearchResult', Search.SearchResult.prototype, SearchResult);
- _overrides.addOverride('SearchResultsView', Search.SearchResultsView.prototype, SearchResultsView);
-
- // 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;
- }
-
- 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) {
- // 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;
- }
-
-
- const pattern = terms.join(' ');
- let appInfoList = Shell.AppSystem.get_default().get_installed();
-
- let weightList = {};
- appInfoList = appInfoList.filter(appInfo => {
- try {
- appInfo.get_id(); // catch invalid file encodings
- } catch (e) {
- return false;
- }
-
- let string = '';
- let name;
- let shouldShow = false;
- if (appInfo.get_display_name) {
- // show only launchers that should be visible in this DE
- shouldShow = appInfo.should_show() && this._parentalControlsManager.shouldShowApp(appInfo);
-
- if (shouldShow) {
- 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}`;
- }
- }
-
- let m = -1;
- if (shouldShow && opt.SEARCH_FUZZY) {
- m = _Util.fuzzyMatch(pattern, name);
- m = (m + _Util.strictMatch(pattern, string)) / 2;
- } else if (shouldShow) {
- m = _Util.strictMatch(pattern, string);
- }
-
- if (m !== -1)
- weightList[appInfo.get_id()] = m;
-
- return shouldShow && (m !== -1);
- });
-
- appInfoList.sort((a, b) => weightList[a.get_id()] > weightList[b.get_id()]);
-
- const usage = Shell.AppUsage.get_default();
- // 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));
-
- let results = appInfoList.map(app => app.get_id());
-
- results = results.concat(this._systemActions.getMatchingActions(terms));
-
- if (shellVersion < 43)
- callback(results);
- else
- return new Promise(resolve => resolve(results));
- },
-
- // App search result size
- createResultObject(resultMeta) {
- if (resultMeta.id.endsWith('.desktop')) {
- const icon = new AppDisplay.AppIcon(this._appSys.lookup_app(resultMeta['id']), {
- expandTitleOnHover: false,
- });
- icon.icon.setIconSize(opt.SEARCH_ICON_SIZE);
- return icon;
- } else {
- const icon = new AppDisplay.SystemActionIcon(this, resultMeta);
- icon.icon._setSizeManually = true;
- icon.icon.setIconSize(opt.SEARCH_ICON_SIZE);
- return icon;
- }
- },
-};
-
-const SearchResult = {
- activate() {
- this.provider.activateResult(this.metaInfo.id, this._resultsView.terms);
-
- if (this.metaInfo.clipboardText) {
- St.Clipboard.get_default().set_text(
- St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
- }
- // don't close overview if Shift key is pressed - Shift moves windows to the workspace
- if (!_Util.isShiftPressed())
- Main.overview.toggle();
- },
-};
-
-const SearchResultsView = {
- _updateSearchProgress() {
- let haveResults = this._providers.some(provider => {
- let display = provider.display;
- return display.getFirstResult() !== null;
- });
-
- this._scrollView.visible = haveResults;
- this._statusBin.visible = !haveResults;
-
- if (!haveResults) {
- if (this.searchInProgress)
- this._statusText.set_text(_('Searching…'));
- else
- this._statusText.set_text(_('No results.'));
- }
- },
-};
diff --git a/extensions/vertical-workspaces/lib/settings.js b/extensions/vertical-workspaces/lib/settings.js
deleted file mode 100644
index 66f3a45..0000000
--- a/extensions/vertical-workspaces/lib/settings.js
+++ /dev/null
@@ -1,469 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * settings.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- */
-
-'use strict';
-
-const { GLib } = imports.gi;
-
-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;
-
-var Options = class Options {
- constructor() {
- this._gsettings = ExtensionUtils.getSettings(_schema);
- this._connectionIds = [];
- this._writeTimeoutId = 0;
- this._gsettings.delay();
- this.connect('changed', () => {
- if (this._writeTimeoutId)
- GLib.Source.remove(this._writeTimeoutId);
-
- this._writeTimeoutId = GLib.timeout_add(
- GLib.PRIORITY_DEFAULT,
- 400,
- () => {
- this._gsettings.apply();
- this._updateCachedSettings();
- this._writeTimeoutId = 0;
- return GLib.SOURCE_REMOVE;
- }
- );
- });
- this.options = {
- workspaceThumbnailsPosition: ['int', 'ws-thumbnails-position'],
- 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'],
- secWsThumbnailsPosition: ['int', 'secondary-ws-thumbnails-position'],
- dashPosition: ['int', 'dash-position'],
- dashPositionAdjust: ['int', 'dash-position-adjust'],
- wsTmbPositionAdjust: ['int', 'wst-position-adjust'],
- showWsTmbLabels: ['int', 'show-wst-labels'],
- showWsTmbLabelsOnHover: ['boolean', 'show-wst-labels-on-hover'],
- closeWsButtonMode: ['int', 'close-ws-button-mode'],
- secWsTmbPositionAdjust: ['int', 'sec-wst-position-adjust'],
- dashMaxIconSize: ['int', 'dash-max-icon-size'],
- dashShowWindowsIcon: ['int', 'dash-show-windows-icon'],
- dashShowRecentFilesIcon: ['int', 'dash-show-recent-files-icon'],
- centerDashToWs: ['boolean', 'center-dash-to-ws'],
- showAppsIconPosition: ['int', 'show-app-icon-position'],
- wsThumbnailScale: ['int', 'ws-thumbnail-scale'],
- wsThumbnailScaleAppGrid: ['int', 'ws-thumbnail-scale-appgrid'],
- secWsThumbnailScale: ['int', 'secondary-ws-thumbnail-scale'],
- showSearchEntry: ['boolean', 'show-search-entry'],
- centerSearch: ['boolean', 'center-search'],
- centerAppGrid: ['boolean', 'center-app-grid'],
- dashBgOpacity: ['int', 'dash-bg-opacity'],
- dashBgRadius: ['int', 'dash-bg-radius'],
- 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'],
- overviewBgBlurSigma: ['int', 'overview-bg-blur-sigma'],
- appGridBgBlurSigma: ['int', 'app-grid-bg-blur-sigma'],
- smoothBlurTransitions: ['boolean', 'smooth-blur-transitions'],
- appGridAnimation: ['int', 'app-grid-animation'],
- 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'],
- startupState: ['int', 'startup-state'],
- overviewMode: ['int', 'overview-mode'],
- workspaceSwitcherAnimation: ['int', 'workspace-switcher-animation'],
- searchIconSize: ['int', 'search-icon-size'],
- searchViewScale: ['int', 'search-width-scale'],
- appGridIconSize: ['int', 'app-grid-icon-size'],
- appGridColumns: ['int', 'app-grid-columns'],
- appGridRows: ['int', 'app-grid-rows'],
- appGridFolderIconSize: ['int', 'app-grid-folder-icon-size'],
- appGridFolderColumns: ['int', 'app-grid-folder-columns'],
- appGridFolderRows: ['int', 'app-grid-folder-rows'],
- appGridFolderIconGrid: ['int', 'app-grid-folder-icon-grid'],
- appGridContent: ['int', 'app-grid-content'],
- appGridIncompletePages: ['boolean', 'app-grid-incomplete-pages'],
- appGridOrder: ['int', 'app-grid-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'],
- searchFuzzy: ['boolean', 'search-fuzzy'],
- searchMaxResultsRows: ['int', 'search-max-results-rows'],
- dashShowWindowsBeforeActivation: ['int', 'dash-show-windows-before-activation'],
- dashIconScroll: ['int', 'dash-icon-scroll'],
- searchWindowsIconScroll: ['int', 'search-windows-icon-scroll'],
- panelVisibility: ['int', 'panel-visibility'],
- panelPosition: ['int', 'panel-position'],
- windowAttentionMode: ['int', 'window-attention-mode'],
- wsSwPopupHPosition: ['int', 'ws-sw-popup-h-position'],
- wsSwPopupVPosition: ['int', 'ws-sw-popup-v-position'],
- wsSwPopupMode: ['int', 'ws-sw-popup-mode'],
- favoritesNotify: ['int', 'favorites-notify'],
- notificationPosition: ['int', 'notification-position'],
- osdPosition: ['int', 'osd-position'],
- hotCornerAction: ['int', 'hot-corner-action'],
- hotCornerPosition: ['int', 'hot-corner-position'],
- hotCornerFullscreen: ['boolean', 'hot-corner-fullscreen'],
- hotCornerRipples: ['boolean', 'hot-corner-ripples'],
- alwaysActivateSelectedWindow: ['boolean', 'always-activate-selected-window'],
- windowIconClickSearch: ['boolean', 'window-icon-click-search'],
- overlayKeySecondary: ['int', 'overlay-key-secondary'],
-
- 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'],
- swipeTrackerModule: ['boolean', 'swipe-tracker-module'],
- searchModule: ['boolean', 'search-module'],
- panelModule: ['boolean', 'panel-module'],
- overlayKeyModule: ['boolean', 'overlay-key-module'],
- osdWindowModule: ['boolean', 'osd-window-module'],
- messageTrayModule: ['boolean', 'message-tray-module'],
- layoutModule: ['boolean', 'layout-module'],
- dashModule: ['boolean', 'dash-module'],
- appFavoritesModule: ['boolean', 'app-favorites-module'],
- appDisplayModule: ['boolean', 'app-display-module'],
-
- profileName1: ['string', 'profile-name-1'],
- profileName2: ['string', 'profile-name-2'],
- profileName3: ['string', 'profile-name-3'],
- profileName4: ['string', 'profile-name-4'],
- };
- this.cachedOptions = {};
-
- this.shellVersion = shellVersion;
- // this.storeProfile(0);
- }
-
- connect(name, callback) {
- const id = this._gsettings.connect(name, callback);
- this._connectionIds.push(id);
- return id;
- }
-
- destroy() {
- this._connectionIds.forEach(id => this._gsettings.disconnect(id));
- if (this._writeTimeoutId) {
- GLib.source_remove(this._writeTimeoutId);
- this._writeTimeoutId = 0;
- }
- }
-
- _updateCachedSettings() {
- Object.keys(this.options).forEach(v => this.get(v, true));
- }
-
- get(option, updateCache = false) {
- if (!this.options[option]) {
- log(`[${Me.metadata.name}] Error: Option ${option} is undefined.`);
- return null;
- }
-
- if (updateCache || this.cachedOptions[option] === undefined) {
- const [, key, settings] = this.options[option];
- let gSettings;
- if (settings !== undefined)
- gSettings = settings();
- else
- gSettings = this._gsettings;
-
-
- this.cachedOptions[option] = gSettings.get_value(key).deep_unpack();
- }
-
- return this.cachedOptions[option];
- }
-
- set(option, value) {
- const [format, key, settings] = this.options[option];
-
- let gSettings = this._gsettings;
-
- if (settings !== undefined)
- gSettings = settings();
-
-
- switch (format) {
- case 'boolean':
- gSettings.set_boolean(key, value);
- break;
- case 'int':
- gSettings.set_int(key, value);
- break;
- case 'string':
- gSettings.set_string(key, value);
- break;
- case 'strv':
- gSettings.set_strv(key, value);
- break;
- }
- }
-
- getDefault(option) {
- const [, key, settings] = this.options[option];
-
- let gSettings = this._gsettings;
-
- if (settings !== undefined)
- gSettings = settings();
-
-
- return gSettings.get_default_value(key).deep_unpack();
- }
-
- storeProfile(index) {
- const profile = {};
- Object.keys(this.options).forEach(v => {
- profile[v] = this.get(v).toString();
- });
-
- this._gsettings.set_value(`profile-data-${index}`, new GLib.Variant('a{ss}', profile));
- }
-
- loadProfile(index) {
- const options = this._gsettings.get_value(`profile-data-${index}`).deep_unpack();
- this._gsettings.set_boolean('aaa-loading-profile', !this._gsettings.get_boolean('aaa-loading-profile'));
- for (let o of Object.keys(options)) {
- const [type] = this.options[o];
- let value = options[o];
- switch (type) {
- case 'string':
- break;
- case 'boolean':
- value = value === 'true';
- break;
- case 'int':
- value = parseInt(value);
- break;
- }
-
- this.set(o, value);
- }
- }
-
- resetProfile(index) {
- this._gsettings.reset(`profile-data-${index}`);
- this._gsettings.reset(`profile-name-${index}`);
- }
-
- _updateSettings() {
- this.DASH_POSITION = this.get('dashPosition', true);
- this.DASH_TOP = this.DASH_POSITION === 0;
- this.DASH_RIGHT = this.DASH_POSITION === 1;
- this.DASH_BOTTOM = this.DASH_POSITION === 2;
- this.DASH_LEFT = this.DASH_POSITION === 3;
- this.DASH_VERTICAL = this.DASH_LEFT || this.DASH_RIGHT;
- 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_SHIFT_CLICK_MV = true;
-
- this.SEARCH_WINDOWS_ICON_SCROLL = this.get('searchWindowsIconScroll', true);
-
- this.DASH_POSITION_ADJUSTMENT = this.get('dashPositionAdjust', true);
- this.DASH_POSITION_ADJUSTMENT = this.DASH_POSITION_ADJUSTMENT * -1 / 100; // range 1 to -1
- this.CENTER_DASH_WS = this.get('centerDashToWs', true);
-
- 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.WS_TMB_POSITION = this.get('workspaceThumbnailsPosition', true);
- this.ORIENTATION = this.WS_TMB_POSITION > 4 ? 0 : 1;
- this.WORKSPACE_MAX_SPACING = this.get('wsMaxSpacing', true);
- // 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);
- // 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];
- this.WS_TMB_TOP = this.WS_TMB_POSITION === 0;
- 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.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.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_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;
- // 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.CENTER_APP_GRID = this.get('centerAppGrid', true);
-
- this.SHOW_SEARCH_ENTRY = this.get('showSearchEntry', true);
- this.CENTER_SEARCH_VIEW = this.get('centerSearch', true);
- this.APP_GRID_ANIMATION = this.get('appGridAnimation', true);
- if (this.APP_GRID_ANIMATION === 4)
- this.APP_GRID_ANIMATION = this._getAnimationDirection();
-
- this.SEARCH_VIEW_ANIMATION = this.get('searchViewAnimation', true);
- if (this.SEARCH_VIEW_ANIMATION === 4)
- this.SEARCH_VIEW_ANIMATION = 3;
-
- this.WS_ANIMATION = this.get('workspaceAnimation', true);
-
- this.WIN_PREVIEW_ICON_SIZE = [64, 48, 32, 22, 8][this.get('winPreviewIconSize', true)];
- this.ALWAYS_SHOW_WIN_TITLES = this.get('alwaysShowWinTitles', true);
-
- 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.OVERVIEW_MODE = this.get('overviewMode', true);
- 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.ANIMATION_TIME_FACTOR = this.get('animationSpeedFactor', true) / 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.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_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);
- /* APP_GRID_INCLUDE_DASH
- 0 - Include All
- 1 - Include All - Favorites and Runnings First
- 2 - Exclude Favorites (Default)
- 3 - Exclude Running
- 4 - Exclude Favorites and Running
- */
- this.APP_GRID_EXCLUDE_FAVORITES = this.APP_GRID_INCLUDE_DASH === 2 || this.APP_GRID_INCLUDE_DASH === 4;
- 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_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_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_ICON_SIZE_DEFAULT = this.APP_GRID_ACTIVE_PREVIEW && !this.APP_GRID_ORDER ? 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.PANEL_POSITION_TOP = this.get('panelPosition', true) === 0;
- this.PANEL_MODE = this.get('panelVisibility', true);
- 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_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.SHOW_FAV_NOTIFICATION = this.get('favoritesNotify', true);
- this.NOTIFICATION_POSITION = this.get('notificationPosition', true);
-
- this.OSD_POSITION = this.get('osdPosition', true);
-
- this.HOT_CORNER_ACTION = this.get('hotCornerAction', true);
- this.HOT_CORNER_POSITION = this.get('hotCornerPosition', true);
- if (this.HOT_CORNER_POSITION === 6 && this.DASH_VISIBLE)
- this.HOT_CORNER_EDGE = true;
- else
- this.HOT_CORNER_EDGE = false;
- if ([5, 6].includes(this.HOT_CORNER_POSITION)) {
- if (this.DASH_TOP || this.DASH_LEFT)
- this.HOT_CORNER_POSITION = 1;
- else if (this.DASH_RIGHT)
- this.HOT_CORNER_POSITION = 2;
- else if (this.DASH_BOTTOM)
- this.HOT_CORNER_POSITION = 3;
- else
- this.HOT_CORNER_POSITION = 0;
- }
- this.HOT_CORNER_FULLSCREEN = this.get('hotCornerFullscreen', true);
- this.HOT_CORNER_RIPPLES = this.get('hotCornerRipples', true);
-
- this.ALWAYS_ACTIVATE_SELECTED_WINDOW = this.get('alwaysActivateSelectedWindow', true);
- this.WINDOW_ICON_CLICK_SEARCH = this.get('windowIconClickSearch', true);
-
- this.OVERLAY_KEY_SECONDARY = this.get('overlayKeySecondary', true);
- }
-
- _getAnimationDirection() {
- if (this.ORIENTATION)
- return this.WS_TMB_LEFT || !this.SHOW_WS_TMB ? 1 : 2; // 1 right, 2 left
- else
- return this.WS_TMB_TOP || !this.SHOW_WS_TMB ? 3 : 5; // 3 bottom, 5 top
- }
-};
diff --git a/extensions/vertical-workspaces/lib/swipeTracker.js b/extensions/vertical-workspaces/lib/swipeTracker.js
deleted file mode 100644
index d9c3407..0000000
--- a/extensions/vertical-workspaces/lib/swipeTracker.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * swipeTracker.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { Clutter, GObject } = imports.gi;
-const Main = imports.ui.main;
-const SwipeTracker = imports.ui.swipeTracker;
-
-const Me = imports.misc.extensionUtils.getCurrentExtension();
-
-let opt;
-let _firstRun = true;
-
-let _vwGestureUpdateId;
-let _originalGestureUpdateId;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('swipeTrackerModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = 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;
- }
- if (_originalGestureUpdateId) {
- Main.overview._swipeTracker._touchpadGesture.unblock_signal_handler(_originalGestureUpdateId);
- _originalGestureUpdateId = 0;
- }
-
- opt = null;
- return;
- }
-
- if (opt.ORIENTATION) { // 1-VERTICAL, 0-HORIZONTAL
- // 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);
- Main.overview._swipeTracker._updateGesture = SwipeTrackerVertical._updateGesture;
- _vwGestureUpdateId = Main.overview._swipeTracker._touchpadGesture.connect('update', SwipeTrackerVertical._updateGesture.bind(Main.overview._swipeTracker));
- }
- }
-}
-
-const SwipeTrackerVertical = {
- _updateGesture(gesture, time, delta, distance) {
- if (this._state !== 1) // State.SCROLLING)
- return;
-
- if ((this._allowedModes & Main.actionMode) === 0 || !this.enabled) {
- this._interrupt();
- return;
- }
-
- if (opt.WS_TMB_RIGHT)
- delta = -delta;
- this._progress += delta / distance;
- this._history.append(time, delta);
-
- this._progress = Math.clamp(this._progress, ...this._getBounds(this._initialProgress));
- this.emit('update', this._progress);
- },
-};
diff --git a/extensions/vertical-workspaces/lib/util.js b/extensions/vertical-workspaces/lib/util.js
deleted file mode 100644
index 5f5c069..0000000
--- a/extensions/vertical-workspaces/lib/util.js
+++ /dev/null
@@ -1,364 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * util.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const Gi = imports._gi;
-const { Shell, Meta, Clutter } = imports.gi;
-
-const Config = imports.misc.config;
-const Main = imports.ui.main;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-var shellVersion = parseFloat(Config.PACKAGE_VERSION);
-
-var Overrides = class {
- constructor() {
- this._overrides = {};
- }
-
- addOverride(name, prototype, overrideList) {
- this._overrides[name] = {
- originals: this.overrideProto(prototype, overrideList),
- prototype,
- };
- }
-
- removeOverride(name) {
- const override = this._overrides[name];
- if (!override)
- return false;
-
- this.overrideProto(override.prototype, override.originals);
- this._overrides[name] = undefined;
- return true;
- }
-
- removeAll() {
- for (let name in this._overrides) {
- this.removeOverride(name);
- this._overrides[name] = undefined;
- }
- }
-
- hookVfunc(proto, symbol, func) {
- proto[Gi.hook_up_vfunc_symbol](symbol, func);
- }
-
- overrideProto(proto, overrides) {
- const backup = {};
-
- for (let symbol in overrides) {
- if (symbol.startsWith('after_')) {
- const actualSymbol = symbol.slice('after_'.length);
- const fn = proto[actualSymbol];
- const afterFn = overrides[symbol];
- proto[actualSymbol] = function (...args) {
- args = Array.prototype.slice.call(args);
- const res = fn.apply(this, args);
- afterFn.apply(this, args);
- return res;
- };
- backup[actualSymbol] = fn;
- } else {
- backup[symbol] = proto[symbol];
- if (symbol.startsWith('vfunc')) {
- if (shellVersion < 42)
- this.hookVfunc(proto, symbol.slice(6), overrides[symbol]);
- else
- this.hookVfunc(proto[Gi.gobject_prototype_symbol], symbol.slice(6), overrides[symbol]);
- } else {
- proto[symbol] = overrides[symbol];
- }
- }
- }
- return backup;
- }
-};
-
-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() {
- 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') {
- // this is our existing window
- metaWin = win;
- isVW = true;
- break;
- } else if (win.wm_class.includes('org.gnome.Shell.Extensions')) {
- // this is prefs window of another extension
- metaWin = win;
- isVW = false;
- }
- }
-
- if (metaWin && !isVW) {
- // other prefs window blocks opening another prefs window, so close it
- metaWin.delete(global.get_current_time());
- } else if (metaWin && isVW) {
- // if prefs window already exist, move it to the current WS and activate it
- metaWin.change_workspace(global.workspace_manager.get_active_workspace());
- metaWin.activate(global.get_current_time());
- }
-
- if (!metaWin || (metaWin && !isVW)) {
- try {
- Main.extensionManager.openExtensionPrefs(Me.metadata.uuid, '', {});
- } catch (e) {
- log(e);
- }
- }
-}
-
-function activateSearchProvider(prefix = '') {
- const searchEntry = Main.overview.searchEntry;
- if (!searchEntry.get_text() || !searchEntry.get_text().startsWith(prefix)) {
- prefix = `${prefix} `;
- const position = prefix.length;
- searchEntry.set_text(prefix);
- searchEntry.get_first_child().set_cursor_position(position);
- searchEntry.get_first_child().set_selection(position, position);
- } else {
- searchEntry.set_text('');
- }
-}
-
-function dashNotDefault() {
- return Main.overview.dash !== Main.overview._overview._controls.layoutManager._dash;
-}
-
-function dashIsDashToDock() {
- return Main.overview.dash._isHorizontal !== undefined;
-}
-
-// Reorder Workspaces - callback for Dash and workspacesDisplay
-function reorderWorkspace(direction = 0) {
- let activeWs = global.workspace_manager.get_active_workspace();
- let activeWsIdx = activeWs.index();
- let targetIdx = activeWsIdx + direction;
- if (targetIdx > -1 && targetIdx < global.workspace_manager.get_n_workspaces())
- global.workspace_manager.reorder_workspace(activeWs, targetIdx);
-}
-
-function exposeWindows(adjustment, activateKeyboard) {
- // expose windows for static overview modes
- if (!adjustment.value && !Main.overview._animationInProgress) {
- if (adjustment.value === 0) {
- adjustment.value = 0;
- adjustment.ease(1, {
- duration: 200,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => {
- if (activateKeyboard) {
- Main.ctrlAltTabManager._items.forEach(i => {
- if (i.sortGroup === 1 && i.name === 'Windows')
- Main.ctrlAltTabManager.focusGroup(i);
- });
- }
- },
- });
- }
- }
-}
-
-function isShiftPressed(state = null) {
- if (state === null)
- [,, state] = global.get_pointer();
- return (state & Clutter.ModifierType.SHIFT_MASK) !== 0;
-}
-
-function isCtrlPressed(state = null) {
- if (state === null)
- [,, state] = global.get_pointer();
- return (state & Clutter.ModifierType.CONTROL_MASK) !== 0;
-}
-
-function isAltPressed(state = null) {
- if (state === null)
- [,, state] = global.get_pointer();
- return (state & Clutter.ModifierType.MOD1_MASK) !== 0;
-}
-
-function fuzzyMatch(term, text) {
- let pos = -1;
- const matches = [];
- // convert all accented chars to their basic form and to lower case
- const _text = text.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
- const _term = term.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
-
- // if term matches the substring exactly, gains the highest weight
- if (_text.includes(_term))
- return 0;
-
- for (let i = 0; i < _term.length; i++) {
- let c = _term[i];
- let p;
- if (pos > 0)
- p = _term[i - 1];
- while (true) {
- pos += 1;
- if (pos >= _text.length)
- return -1;
-
- if (_text[pos] === c) {
- matches.push(pos);
- break;
- } else if (_text[pos] === p) {
- matches.pop();
- matches.push(pos);
- }
- }
- }
-
- // add all position to get a weight of the result
- // results closer to the beginning of the text and term characters closer to each other will gain more weight.
- return matches.reduce((r, p) => r + p) - matches.length * matches[0] + matches[0];
-}
-
-function strictMatch(term, text) {
- // remove diacritics and accents from letters
- let s = text.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
- let p = term.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
- let ps = p.split(/ +/);
-
- // allows to use multiple exact patterns separated by a space in arbitrary order
- for (let w of ps) { // escape regex control chars
- if (!s.match(w.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')))
- return -1;
- }
- return 0;
-}
-
-function isMoreRelevant(stringA, stringB, pattern) {
- let regex = /[^a-zA-Z\d]/;
- let strSplitA = stringA.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase().split(regex);
- let strSplitB = stringB.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase().split(regex);
- let aAny = false;
- strSplitA.forEach(w => {
- aAny = aAny || w.startsWith(pattern);
- });
- let bAny = false;
- strSplitB.forEach(w => {
- bAny = bAny || w.startsWith(pattern);
- });
-
- // if both strings contain a word that starts with the pattern
- // prefer the one whose first word starts with the pattern
- if (aAny && bAny)
- return !strSplitA[0].startsWith(pattern) && strSplitB[0].startsWith(pattern);
- else
- 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 getScrollDirection(event) {
- // scroll wheel provides two types of direction information:
- // 1. Clutter.ScrollDirection.DOWN / Clutter.ScrollDirection.UP
- // 2. Clutter.ScrollDirection.SMOOTH + event.get_scroll_delta()
- // first SMOOTH event returns 0 delta,
- // so we need to always read event.direction
- // since mouse without smooth scrolling provides exactly one SMOOTH event on one wheel rotation click
- // on the other hand, under X11, one wheel rotation click sometimes doesn't send direction event, only several SMOOTH events
- // so we also need to convert the delta to direction
- let direction = event.get_scroll_direction();
-
- if (direction !== Clutter.ScrollDirection.SMOOTH)
- return direction;
-
- let [, delta] = event.get_scroll_delta();
-
- if (!delta)
- return null;
-
- direction = delta > 0 ? Clutter.ScrollDirection.DOWN : Clutter.ScrollDirection.UP;
-
- return direction;
-}
diff --git a/extensions/vertical-workspaces/lib/windowAttentionHandler.js b/extensions/vertical-workspaces/lib/windowAttentionHandler.js
deleted file mode 100644
index 10703c2..0000000
--- a/extensions/vertical-workspaces/lib/windowAttentionHandler.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * windowAttentionHandler.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'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;
-
-let opt;
-let _firstRun = false;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('winAttentionHandlerModule', true);
- reset = reset || !moduleEnabled;
-
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
- if (reset) {
- reset = true;
- _updateConnections(reset);
- opt = null;
- return;
- }
-
- _updateConnections();
-}
-
-function _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) {
- // Deny attention notifications if the App Grid is open, to avoid notification spree when opening a folder
- if (Main.overview._shown && Main.overview.dash.showAppsButton.checked) {
- return;
- } else if (opt.WINDOW_ATTENTION_FOCUS_IMMEDIATELY) {
- if (!Main.overview._shown)
- Main.activateWindow(window);
- return;
- }
-
- const app = this._tracker.get_window_app(window);
- const source = new WindowAttentionHandler.WindowAttentionSource(app, window);
- Main.messageTray.add(source);
-
- let [title, banner] = this._getTitleAndBanner(app, window);
-
- const notification = new MessageTray.Notification(source, title, banner);
- notification.connect('activated', () => {
- source.open();
- });
- notification.setForFeedback(true);
-
- if (opt.WINDOW_ATTENTION_DISABLE_NOTIFICATIONS)
- // just push the notification to the message tray without showing notification
- source.pushNotification(notification);
- else
- source.showNotification(notification);
-
- window.connectObject('notify::title', () => {
- [title, banner] = this._getTitleAndBanner(app, window);
- notification.update(title, banner);
- }, source);
- },
-};
diff --git a/extensions/vertical-workspaces/lib/windowManager.js b/extensions/vertical-workspaces/lib/windowManager.js
deleted file mode 100644
index 2d46b0b..0000000
--- a/extensions/vertical-workspaces/lib/windowManager.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * windowManager.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { GObject, Clutter, Meta } = imports.gi;
-
-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 opt;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('windowManagerModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
-
- _replaceMinimizeFunction(reset);
-
-
- if (reset) {
- _overrides = null;
- opt = null;
- return;
- }
-
- _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));
- }
-
- _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));
- }
- }
-}
-
-// fix for mainstream bug - fullscreen windows should minimize using opacity transition
-// but its being applied directly on window actor and that doesn't work
-// anyway, animation is better, even if the Activities button is not visible...
-// and also add support for bottom position of the panel
-const WindowManagerCommon = {
- _minimizeWindow(shellwm, actor) {
- const types = [
- Meta.WindowType.NORMAL,
- Meta.WindowType.MODAL_DIALOG,
- Meta.WindowType.DIALOG,
- ];
- if (!this._shouldAnimateActor(actor, types)) {
- shellwm.completed_minimize(actor);
- return;
- }
-
- actor.set_scale(1.0, 1.0);
-
- this._minimizing.add(actor);
-
- /* if (actor.meta_window.is_monitor_sized()) {
- actor.get_first_child().ease({
- opacity: 0,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
- onStopped: () => this._minimizeWindowDone(shellwm, actor),
- });
- } else { */
- let xDest, yDest, xScale, yScale;
- let [success, geom] = actor.meta_window.get_icon_geometry();
- if (success) {
- xDest = geom.x;
- yDest = geom.y;
- xScale = geom.width / actor.width;
- yScale = geom.height / actor.height;
- } else {
- let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
- if (!monitor) {
- this._minimizeWindowDone();
- return;
- }
- xDest = monitor.x;
- yDest = opt.PANEL_POSITION_TOP ? monitor.y : monitor.y + monitor.height;
- if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
- xDest += monitor.width;
- xScale = 0;
- yScale = 0;
- }
-
- actor.ease({
- scale_x: xScale,
- scale_y: yScale,
- x: xDest,
- y: yDest,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
- onStopped: () => this._minimizeWindowDone(shellwm, actor),
- });
- // }
- },
-
- _minimizeWindowDone(shellwm, actor) {
- if (this._minimizing.delete(actor)) {
- actor.remove_all_transitions();
- actor.set_scale(1.0, 1.0);
- actor.get_first_child().set_opacity(255);
- actor.set_pivot_point(0, 0);
-
- shellwm.completed_minimize(actor);
- }
- },
-
- _unminimizeWindow(shellwm, actor) {
- const types = [
- Meta.WindowType.NORMAL,
- Meta.WindowType.MODAL_DIALOG,
- Meta.WindowType.DIALOG,
- ];
- if (!this._shouldAnimateActor(actor, types)) {
- shellwm.completed_unminimize(actor);
- return;
- }
-
- this._unminimizing.add(actor);
-
- /* if (false/* actor.meta_window.is_monitor_sized()) {
- actor.opacity = 0;
- actor.set_scale(1.0, 1.0);
- actor.ease({
- opacity: 255,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
- onStopped: () => this._unminimizeWindowDone(shellwm, actor),
- });
- } else { */
- let [success, geom] = actor.meta_window.get_icon_geometry();
- if (success) {
- actor.set_position(geom.x, geom.y);
- actor.set_scale(geom.width / actor.width,
- geom.height / actor.height);
- } else {
- let monitor = Main.layoutManager.monitors[actor.meta_window.get_monitor()];
- if (!monitor) {
- actor.show();
- this._unminimizeWindowDone();
- return;
- }
- actor.set_position(monitor.x, opt.PANEL_POSITION_TOP ? monitor.y : monitor.y + monitor.height);
- if (Clutter.get_default_text_direction() === Clutter.TextDirection.RTL)
- actor.x += monitor.width;
- actor.set_scale(0, 0);
- }
-
- let rect = actor.meta_window.get_buffer_rect();
- let [xDest, yDest] = [rect.x, rect.y];
-
- actor.show();
- actor.ease({
- scale_x: 1,
- scale_y: 1,
- x: xDest,
- y: yDest,
- duration: MINIMIZE_WINDOW_ANIMATION_TIME,
- mode: MINIMIZE_WINDOW_ANIMATION_MODE,
- onStopped: () => this._unminimizeWindowDone(shellwm, actor),
- });
- // }
- },
-};
diff --git a/extensions/vertical-workspaces/lib/windowPreview.js b/extensions/vertical-workspaces/lib/windowPreview.js
deleted file mode 100644
index 5d2bd61..0000000
--- a/extensions/vertical-workspaces/lib/windowPreview.js
+++ /dev/null
@@ -1,379 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * windowPreview.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { Clutter, GLib, GObject, Graphene, Meta, Shell, St } = imports.gi;
-
-const Main = imports.ui.main;
-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 _overrides;
-
-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 = imports.ui.overviewControls.ControlsState;
-
-let opt;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('windowPreviewModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
-
- if (reset) {
- _overrides = null;
- opt = null;
- WindowPreview.WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT = 750;
- return;
- }
-
- _overrides = new _Util.Overrides();
-
- _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;
-}
-
-const WindowPreviewCommon = {
- // injection to _init()
- after__init() {
- 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 }),
- });
- 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._iconSize = opt.WIN_PREVIEW_ICON_SIZE;
- }
-
- 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);
- // 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;
- this._icon.scale_y = 0;
- this._title.opacity = 0;
- }
-
- if (opt.ALWAYS_SHOW_WIN_TITLES)
- this._title.show();
-
- if (opt.OVERVIEW_MODE === 1) {
- // spread windows on hover
- this._wsStateConId = this.connect('enter-event', () => {
- // don't spread windows if user don't use pointer device at this moment
- 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);
- this.disconnect(this._wsStateConId);
- });
- }
-
- if (opt.OVERVIEW_MODE) {
- // show window icon and title on ws windows spread
- 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);
-
- 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;
- });
-
- 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);
- }
- },
-
- _updateIconScale() {
- let { currentState, initialState, finalState } =
- this._overviewAdjustment.getStateTransitionParams();
-
- // Current state - 0 - HIDDEN, 1 - WINDOW_PICKER, 2 - APP_GRID
- const primaryMonitor = this.metaWindow.get_monitor() === global.display.get_primary_monitor();
-
- const visible =
- (initialState > ControlsState.HIDDEN || finalState > ControlsState.HIDDEN) &&
- !(finalState === ControlsState.APP_GRID && primaryMonitor);
-
- let scale = 0;
- if (visible)
- scale = currentState >= 1 ? 1 : currentState % 1;
-
- if (!primaryMonitor && opt.WORKSPACE_MODE &&
- ((initialState === ControlsState.WINDOW_PICKER && finalState === ControlsState.APP_GRID) ||
- (initialState === ControlsState.APP_GRID && finalState === ControlsState.WINDOW_PICKER))
- )
- scale = 1;
- else if (!primaryMonitor && opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE)
- scale = 0;
- /* } else if (primaryMonitor && ((initialState === ControlsState.WINDOW_PICKER && finalState === ControlsState.APP_GRID) ||
- initialState === ControlsState.APP_GRID && finalState === ControlsState.HIDDEN)) {*/
- 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)
- scale = opt.WORKSPACE_MODE;
- else if (finalState === 1 || (finalState === 0 && !opt.WORKSPACE_MODE))
- return;
- }
-
- if (scale === 1) {
- this._icon.ease({
- duration: 50,
- scale_x: scale,
- scale_y: scale,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- this._title.ease({
- duration: 100,
- opacity: 255,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- } else if (this._icon.scale_x !== 0) {
- this._icon.set({
- scale_x: 0,
- scale_y: 0,
- });
- 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) {
- if (!this._overlayEnabled)
- return;
-
- if (this._overlayShown)
- return;
-
- this._overlayShown = true;
- if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
- this._restack();
-
- // If we're supposed to animate and an animation in our direction
- // is already happening, let that one continue
- const ongoingTransition = this._title.get_transition('opacity');
- if (animate &&
- ongoingTransition &&
- ongoingTransition.get_interval().peek_final_value() === 255)
- return;
-
- const toShow = this._windowCanClose()
- ? [this._closeButton]
- : [];
-
- if (!opt.ALWAYS_SHOW_WIN_TITLES)
- toShow.push(this._title);
-
-
- toShow.forEach(a => {
- a.opacity = 0;
- a.show();
- a.ease({
- opacity: 255,
- duration: animate ? WINDOW_OVERLAY_FADE_TIME : 0,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- });
-
- const [width, height] = this.window_container.get_size();
- const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const activeExtraSize = WINDOW_ACTIVE_SIZE_INC * 2 * scaleFactor;
- const origSize = Math.max(width, height);
- const scale = (origSize + activeExtraSize) / origSize;
-
- this.window_container.ease({
- scale_x: scale,
- scale_y: scale,
- duration: animate ? WINDOW_SCALE_TIME : 0,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
-
- this.emit('show-chrome');
- },
-
- hideOverlay(animate) {
- 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);
- this._activateSelected = true;
- }
-
- if (!opt.ALWAYS_ACTIVATE_SELECTED_WINDOW)
- this._restack();
-
- // If we're supposed to animate and an animation in our direction
- // is already happening, let that one continue
- const ongoingTransition = this._title.get_transition('opacity');
- if (animate &&
- ongoingTransition &&
- ongoingTransition.get_interval().peek_final_value() === 0)
- return;
-
- const toHide = [this._closeButton];
-
- if (!opt.ALWAYS_SHOW_WIN_TITLES)
- toHide.push(this._title);
-
- toHide.forEach(a => {
- a.opacity = 255;
- a.ease({
- opacity: 0,
- duration: animate ? WINDOW_OVERLAY_FADE_TIME : 0,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- onComplete: () => a.hide(),
- });
- });
-
- if (this.window_container) {
- this.window_container.ease({
- scale_x: 1,
- scale_y: 1,
- duration: animate ? WINDOW_SCALE_TIME : 0,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- }
- },
-
- _onDestroy() {
- // workaround for upstream bug - hideOverlay is called after windowPreview is destroyed, from the leave event callback
- // hiding the preview now avoids firing the post-mortem leave event
- this.hide();
- if (this._activateSelected)
- this._activate();
-
- this.metaWindow._delegate = null;
- 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 (this._idleHideOverlayId > 0) {
- GLib.source_remove(this._idleHideOverlayId);
- this._idleHideOverlayId = 0;
- }
-
- if (this.inDrag) {
- this.emit('drag-end');
- this.inDrag = false;
- }
-
- if (this._stateAdjustmentSigId)
- this._workspace.stateAdjustment.disconnect(this._stateAdjustmentSigId);
- },
-};
diff --git a/extensions/vertical-workspaces/lib/windowSearchProvider.js b/extensions/vertical-workspaces/lib/windowSearchProvider.js
deleted file mode 100644
index 5f90784..0000000
--- a/extensions/vertical-workspaces/lib/windowSearchProvider.js
+++ /dev/null
@@ -1,305 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * windowSearchProvider.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 -2023
- * @license GPL-3.0
- */
-
-'use strict';
-
-const { GLib, Gio, Meta, St, Shell } = imports.gi;
-
-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;
-
-// gettext
-const _ = Settings._;
-
-const shellVersion = Settings.shellVersion;
-
-const ModifierType = imports.gi.Clutter.ModifierType;
-
-let windowSearchProvider;
-let _enableTimeoutId = 0;
-
-// 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 Action = {
- NONE: 0,
- CLOSE: 1,
- CLOSE_ALL: 2,
- MOVE_TO_WS: 3,
- MOVE_ALL_TO_WS: 4,
-};
-
-function getOverviewSearchResult() {
- return Main.overview._overview.controls._searchController._searchResults;
-}
-
-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();
- opt = 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;
- }
- );
-}
-
-function disable() {
- if (windowSearchProvider) {
- getOverviewSearchResult()._unregisterProvider(
- windowSearchProvider
- );
- windowSearchProvider = null;
- }
- if (_enableTimeoutId) {
- GLib.source_remove(_enableTimeoutId);
- _enableTimeoutId = 0;
- }
-}
-
-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,
- };
-}
-
-const closeSelectedRegex = /^\/x!$/;
-const closeAllResultsRegex = /^\/xa!$/;
-const moveToWsRegex = /^\/m[0-9]+$/;
-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.isRemoteProvider = false;
-
- this.action = 0;
- }
-
- _getResultSet(terms) {
- // do not modify original terms
- let termsCopy = [...terms];
- // search for terms without prefix
- termsCopy[0] = termsCopy[0].replace(prefix, '');
-
- /* if (gOptions.get('searchWindowsCommands')) {
- this.action = 0;
- this.targetWs = 0;
-
- const lastTerm = terms[terms.length - 1];
- if (lastTerm.match(closeSelectedRegex)) {
- this.action = Action.CLOSE;
- } else if (lastTerm.match(closeAllResultsRegex)) {
- this.action = Action.CLOSE_ALL;
- } else if (lastTerm.match(moveToWsRegex)) {
- this.action = Action.MOVE_TO_WS;
- } else if (lastTerm.match(moveAllToWsRegex)) {
- this.action = Action.MOVE_ALL_TO_WS;
- }
- if (this.action) {
- terms.pop();
- if (this.action === Action.MOVE_TO_WS || this.action === Action.MOVE_ALL_TO_WS) {
- this.targetWs = parseInt(lastTerm.replace(/^[^0-9]+/, '')) - 1;
- }
- } else if (lastTerm.startsWith('/')) {
- terms.pop();
- }
- }*/
-
- const candidates = this.windows;
- const _terms = [].concat(termsCopy);
- // let match;
-
- const term = _terms.join(' ');
- /* match = s => {
- return fuzzyMatch(term, s);
- }; */
-
- const results = [];
- let m;
- for (let key in candidates) {
- if (opt.SEARCH_FUZZY)
- m = _Util.fuzzyMatch(term, candidates[key].name);
- else
- m = _Util.strictMatch(term, candidates[key].name);
-
- if (m !== -1)
- results.push({ weight: m, id: key });
- }
-
- 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));
- results.sort((a, b) => (_terms !== ' ') && (a.weight > 0 && b.weight === 0));
-
- this.resultIds = results.map(item => item.id);
- return this.resultIds;
- }
-
- getResultMetas(resultIds, callback = null) {
- const metas = resultIds.map(id => this.getResultMeta(id));
- if (shellVersion >= 43)
- return new Promise(resolve => resolve(metas));
- else
- callback(metas);
- return null;
- }
-
- getResultMeta(resultId) {
- const result = this.windows[resultId];
- const wsIndex = result.window.get_workspace().index();
- const app = Shell.WindowTracker.get_default().get_window_app(result.window);
- return {
- 'id': resultId,
- 'name': `${wsIndex + 1}: ${result.windowTitle}`,
- 'description': result.appName,
- 'createIcon': size => {
- return app
- ? app.create_icon_texture(size)
- : new St.Icon({ icon_name: 'icon-missing', icon_size: size });
- },
- };
- }
-
- launchSearch(/* terms, timeStamp*/) {
- }
-
- activateResult(resultId/* , terms, timeStamp*/) {
- const isCtrlPressed = _Util.isCtrlPressed();
- const isShiftPressed = _Util.isShiftPressed();
-
- this.action = 0;
- this.targetWs = 0;
-
- this.targetWs = global.workspaceManager.get_active_workspace().index() + 1;
- if (isShiftPressed && !isCtrlPressed)
- this.action = Action.MOVE_TO_WS;
- else if (isShiftPressed && isCtrlPressed)
- this.action = Action.MOVE_ALL_TO_WS;
-
-
- if (!this.action) {
- const result = this.windows[resultId];
- Main.activateWindow(result.window);
- return;
- }
-
- switch (this.action) {
- case Action.CLOSE:
- this._closeWindows([resultId]);
- break;
- case Action.CLOSE_ALL:
- this._closeWindows(this.resultIds);
- break;
- case Action.MOVE_TO_WS:
- this._moveWindowsToWs(resultId, [resultId]);
- break;
- case Action.MOVE_ALL_TO_WS:
- this._moveWindowsToWs(resultId, this.resultIds);
- break;
- }
- }
-
- _closeWindows(ids) {
- let time = global.get_current_time();
- for (let i = 0; i < ids.length; i++)
- this.windows[ids[i]].window.delete(time + i);
-
- Main.notify('Window Search Provider', `Closed ${ids.length} windows.`);
- }
-
- _moveWindowsToWs(selectedId, resultIds) {
- const workspace = global.workspaceManager.get_active_workspace();
-
- for (let i = 0; i < resultIds.length; i++)
- this.windows[resultIds[i]].window.change_workspace(workspace);
-
- const selectedWin = this.windows[selectedId].window;
- selectedWin.activate_with_workspace(global.get_current_time(), workspace);
- }
-
- getInitialResultSet(terms, callback/* , cancellable = null*/) {
- // In GS 43 callback arg has been removed
- /* if (shellVersion >= 43)
- cancellable = callback;*/
-
- let windows;
- 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()}`);
- return windows[`${i}-${v.get_id()}`];
- }
- );
-
- 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;
- }
-
- getSubsearchResultSet(previousResults, terms, callback/* , cancellable*/) {
- // if we return previous results, quick typers get non-actual results
- callback(this._getResultSet(terms));
- }
-
- /* createResultObject(resultMeta) {
- const app = Shell.WindowTracker.get_default().get_window_app(resultMeta.id);
- return new AppIcon(app);
- }*/
-};
diff --git a/extensions/vertical-workspaces/lib/workspace.js b/extensions/vertical-workspaces/lib/workspace.js
deleted file mode 100644
index 3b61a6d..0000000
--- a/extensions/vertical-workspaces/lib/workspace.js
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * workspace.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { St, Graphene } = imports.gi;
-
-const Main = imports.ui.main;
-const Util = imports.misc.util;
-const Workspace = imports.ui.workspace;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-const _Util = Me.imports.lib.util;
-
-let _overrides;
-let opt;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('workspaceModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
-
- if (reset) {
- Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = 0.95;
- _overrides = null;
- opt = null;
- return;
- }
-
- _overrides = new _Util.Overrides();
-
- _overrides.addOverride('WorkspaceBackground', Workspace.WorkspaceBackground.prototype, WorkspaceBackground);
-
- // fix overlay base for Vertical Workspaces
- _overrides.addOverride('WorkspaceLayout', Workspace.WorkspaceLayout.prototype, WorkspaceLayout);
-}
-
-
-// workaround for upstream bug (that is not that invisible in default shell)
-// smaller window cannot be scaled below 0.95 (WINDOW_PREVIEW_MAXIMUM_SCALE)
-// when its target scale for exposed windows view (workspace state 1) is bigger than the scale needed for ws state 0.
-// in workspace state 0 where windows are not spread and window scale should follow workspace scale,
-// this window follows proper top left corner position, but doesn't scale with the workspace
-// so it looks bad and the window can exceed border of the workspace
-// extremely annoying in OVERVIEW_MODE 1 with single smaller window on the workspace, also affects appGrid transition animation
-
-// disadvantage of following workaround - the WINDOW_PREVIEW_MAXIMUM_SCALE value is common for every workspace,
-// on multi-monitor system can be visible unwanted scaling of windows on workspace in WORKSPACE_MODE 0 (windows not spread)
-// when leaving overview while any other workspace is in the WORKSPACE_MODE 1.
-const WorkspaceLayout = {
- // injection to _init()
- after__init() {
- if (opt.OVERVIEW_MODE === 1) {
- this._stateAdjustment.connect('notify::value', () => {
- // scale 0.1 for window state 0 just needs to be smaller then possible scale of any window in spread view
- const scale = this._stateAdjustment.value ? 0.95 : 0.1;
- if (scale !== this.WINDOW_PREVIEW_MAXIMUM_SCALE) {
- this.WINDOW_PREVIEW_MAXIMUM_SCALE = scale;
- // when transition to ws state 1 (WINDOW_PICKER) begins, replace the constant with the original one
- Workspace.WINDOW_PREVIEW_MAXIMUM_SCALE = scale;
- // and force recalculation of the target layout, so the transition will be smooth
- this._needsLayout = true;
- }
- });
- }
- },
-
- // this fixes wrong size and position calculation of window clones while moving overview to the next (+1) workspace if vertical ws orientation is enabled in GS
- _adjustSpacingAndPadding(rowSpacing, colSpacing, containerBox) {
- if (this._sortedWindows.length === 0)
- return [rowSpacing, colSpacing, containerBox];
-
- // All of the overlays have the same chrome sizes,
- // so just pick the first one.
- const window = this._sortedWindows[0];
-
- const [topOversize, bottomOversize] = window.chromeHeights();
- const [leftOversize, rightOversize] = window.chromeWidths();
-
- const oversize = Math.max(topOversize, bottomOversize, leftOversize, rightOversize);
-
- if (rowSpacing !== null)
- rowSpacing += oversize;
- if (colSpacing !== null)
- colSpacing += oversize;
-
- if (containerBox) {
- const vertical = global.workspaceManager.layout_rows === -1;
-
- const monitor = Main.layoutManager.monitors[this._monitorIndex];
-
- const bottomPoint = new Graphene.Point3D();
- if (vertical)
- bottomPoint.x = containerBox.x2;
- else
- bottomPoint.y = containerBox.y2;
-
-
- const transformedBottomPoint =
- this._container.apply_transform_to_point(bottomPoint);
- const bottomFreeSpace = vertical
- ? (monitor.x + monitor.height) - transformedBottomPoint.x
- : (monitor.y + monitor.height) - transformedBottomPoint.y;
-
- const [, bottomOverlap] = window.overlapHeights();
-
- if ((bottomOverlap + oversize) > bottomFreeSpace && !vertical)
- containerBox.y2 -= (bottomOverlap + oversize) - bottomFreeSpace;
- }
-
- return [rowSpacing, colSpacing, containerBox];
- },
-};
-
-const WorkspaceBackground = {
- _updateBorderRadius(value = false) {
- // don't round already rounded corners during exposing windows
- if (value === false && opt.OVERVIEW_MODE === 1)
- return;
-
- const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const cornerRadius = scaleFactor * opt.WS_PREVIEW_BG_RADIUS;
-
- const backgroundContent = this._bgManager.backgroundActor.content;
- value = value !== false
- ? value
- : this._stateAdjustment.value;
-
- backgroundContent.rounded_clip_radius =
- Util.lerp(0, cornerRadius, value);
- },
-};
diff --git a/extensions/vertical-workspaces/lib/workspaceAnimation.js b/extensions/vertical-workspaces/lib/workspaceAnimation.js
deleted file mode 100644
index 07008c6..0000000
--- a/extensions/vertical-workspaces/lib/workspaceAnimation.js
+++ /dev/null
@@ -1,184 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * workspacesAnimation.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'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;
-
-// 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;
-
-let _origBaseDistance;
-let _wsAnimationSwipeBeginId;
-let _wsAnimationSwipeUpdateId;
-let _wsAnimationSwipeEndId;
-
-let _overrides;
-let opt;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('workspaceAnimationModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
- if (reset || !moduleEnabled) {
- _connectWsAnimationSwipeTracker(true);
- _overrideMonitorGroupProperty(true);
- _overrides = null;
- opt = null;
- return;
- }
-
- if (opt.STATIC_WS_SWITCHER_BG) {
- _overrides = new _Util.Overrides();
- _overrideMonitorGroupProperty();
- _overrides.addOverride('WorkspaceAnimationMonitorGroup', WorkspaceAnimation.MonitorGroup.prototype, MonitorGroup);
- }
-
- _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;
- },
- };
- }
-
- if (getter)
- Object.defineProperty(WorkspaceAnimation.MonitorGroup.prototype, 'baseDistance', getter);
-}
-
-const MonitorGroup = {
- // injection to _init()
- after__init() {
- // we have two options to implement static bg feature
- // one is adding background to monitorGroup
- // but this one has disadvantage - sticky windows will be always on top of animated windows
- // which is bad for conky, for example, that window should be always below
- /* this._bgManager = new Background.BackgroundManager({
- container: this,
- monitorIndex: this._monitor.index,
- controlPosition: false,
- });*/
-
- // the second option is to make background of the monitorGroup transparent so the real desktop content will stay visible,
- // hide windows that should be animated and keep only sticky windows
- // we can keep certain sticky windows bellow and also extensions like DING (icons on desktop) will stay visible
- this.set_style('background-color: transparent;');
- // stickyGroup holds the Always on Visible Workspace windows to keep them static and above other windows during animation
- const stickyGroup = this.get_children()[1];
- stickyGroup._windowRecords.forEach(r => {
- const metaWin = r.windowActor.metaWindow;
- // conky is sticky but should never get above other windows during ws animation
- // so we hide it from the overlay group, we will see the original if not covered by other windows
- if (metaWin.wm_class === 'conky')
- r.clone.opacity = 0;
- });
- this._hiddenWindows = [];
- // remove (hide) background wallpaper from the animation, we will see the original one
- this._workspaceGroups.forEach(w => {
- w._background.opacity = 0;
- });
- // 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()*/) {
- // hide original window. we cannot use opacity since it also affects clones.
- // scaling them to 0 works well
- actor.scale_x = 0;
- this._hiddenWindows.push(actor);
- }
- });
-
- // restore all hidden windows at the end of animation
- // todo - actors removed during transition need to be removed from the list to avoid access to destroyed actor
- this.connect('destroy', () => {
- this._hiddenWindows.forEach(actor => {
- actor.scale_x = 1;
- });
- });
- },
-};
-
-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/vertical-workspaces/lib/workspaceSwitcherPopup.js b/extensions/vertical-workspaces/lib/workspaceSwitcherPopup.js
deleted file mode 100644
index 972f35e..0000000
--- a/extensions/vertical-workspaces/lib/workspaceSwitcherPopup.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * workspacesSwitcherPopup.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const Main = imports.ui.main;
-const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-const _Util = Me.imports.lib.util;
-let _overrides;
-
-let opt;
-let _firstRun = true;
-
-function update(reset = false) {
- opt = Me.imports.lib.settings.opt;
- const moduleEnabled = opt.get('workspaceSwitcherPopupModule', true);
- reset = reset || !moduleEnabled;
-
- // don't even touch this module if disabled
- if (_firstRun && reset)
- return;
-
- _firstRun = false;
-
- if (_overrides)
- _overrides.removeAll();
-
- if (reset) {
- _overrides = null;
- opt = null;
- return;
- }
-
- _overrides = new _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);
- }
-}
-
-const WorkspaceSwitcherPopupOverride = {
- // 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]);
- },
-
- // injection to display()
- after_display() {
- if (opt.WS_SW_POPUP_MODE)
- this._setPopupPosition();
- else
- this.opacity = 0;
- },
-
- _setPopupPosition() {
- let workArea;
- if (opt.WS_SW_POPUP_MODE === 1) {
- // workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);*/
- workArea = global.display.get_monitor_geometry(Main.layoutManager.primaryIndex);
- } else {
- // workArea = Main.layoutManager.getWorkAreaForMonitor(global.display.get_current_monitor());
- workArea = global.display.get_monitor_geometry(global.display.get_current_monitor());
- }
-
- let [, natHeight] = this.get_preferred_height(global.screen_width);
- let [, natWidth] = this.get_preferred_width(natHeight);
- let h = opt.WS_SW_POPUP_H_POSITION;
- let v = opt.WS_SW_POPUP_V_POSITION;
- this.x = workArea.x + Math.floor((workArea.width - natWidth) * h);
- this.y = workArea.y + Math.floor((workArea.height - natHeight) * v);
- this.set_position(this.x, this.y);
- },
-};
diff --git a/extensions/vertical-workspaces/lib/workspaceThumbnail.js b/extensions/vertical-workspaces/lib/workspaceThumbnail.js
deleted file mode 100644
index d0bc206..0000000
--- a/extensions/vertical-workspaces/lib/workspaceThumbnail.js
+++ /dev/null
@@ -1,1148 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * workspaceThumbnail.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { GLib, Clutter, Graphene, Meta, Shell, St } = imports.gi;
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
-const Background = imports.ui.background;
-const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
-const ThumbnailState = WorkspaceThumbnail.ThumbnailState;
-
-const ControlsState = imports.ui.overviewControls.ControlsState;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-const Me = ExtensionUtils.getCurrentExtension();
-
-// gettext
-const _ = Me.imports.lib.settings._;
-
-const _Util = Me.imports.lib.util;
-const shellVersion = _Util.shellVersion;
-
-let _overrides;
-
-const WORKSPACE_CUT_SIZE = 10;
-const _originalMaxThumbnailScale = WorkspaceThumbnail.MAX_THUMBNAIL_SCALE;
-
-let opt = null;
-
-function update(reset = false) {
- if (_overrides)
- _overrides.removeAll();
-
-
- if (reset) {
- if (_originalMaxThumbnailScale)
- WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = _originalMaxThumbnailScale;
- _overrides = null;
- opt = null;
- return;
- }
-
- opt = Me.imports.lib.settings.opt;
- _overrides = new _Util.Overrides();
-
- // don't limit max thumbnail scale for other clients than overview, for example AATWS.
- WorkspaceThumbnail.MAX_THUMBNAIL_SCALE = 1;
-
- _overrides.addOverride('WorkspaceThumbnail', WorkspaceThumbnail.WorkspaceThumbnail.prototype, WorkspaceThumbnailCommon);
- _overrides.addOverride('ThumbnailsBoxCommon', WorkspaceThumbnail.ThumbnailsBox.prototype, ThumbnailsBoxCommon);
-
- // 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;
-}
-
-const WorkspaceThumbnailCommon = {
- // injection to _init()
- after__init() {
- // layout manager allows aligning widget children
- this.layout_manager = new Clutter.BinLayout();
- // adding layout manager to tmb widget breaks wallpaper background aligning and rounded corners
- // unless border is removed
- if (opt.SHOW_WS_TMB_BG)
- this.add_style_class_name('ws-tmb-labeled');
-
- // add workspace thumbnails labels if enabled
- if (opt.SHOW_WST_LABELS) { // 0 - disable
- const getLabel = function () {
- 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 wsLabels = settings.get_strv('workspace-names');
- if (wsLabels.length > wsIndex && wsLabels[wsIndex])
- label += `: ${wsLabels[wsIndex]}`;
- } else if (opt.SHOW_WST_LABELS === 3) { // 3- index + app name
- // global.display.get_tab_list offers workspace filtering using the second argument, but...
- // ... it sometimes includes windows from other workspaces, like minimized VBox machines, after Shell restarts
- const metaWin = global.display.get_tab_list(0, null).filter(
- w => w.get_monitor() === this.monitorIndex && w.get_workspace().index() === wsIndex)[0];
-
- if (metaWin) {
- const tracker = Shell.WindowTracker.get_default();
- const app = tracker.get_window_app(metaWin);
- label += `: ${app ? app.get_name() : ''}`;
- }
- } else if (opt.SHOW_WST_LABELS === 4) {
- const metaWin = global.display.get_tab_list(0, null).filter(
- w => w.get_monitor() === this.monitorIndex && w.get_workspace().index() === wsIndex)[0];
-
- if (metaWin)
- label += `: ${metaWin.title}`;
- }
- return label;
- }.bind(this);
-
- const label = getLabel();
-
- this._wsLabel = new St.Label({
- text: label,
- style_class: 'ws-tmb-label',
- x_align: Clutter.ActorAlign.FILL,
- y_align: Clutter.ActorAlign.END,
- x_expand: true,
- y_expand: true,
- });
-
- this._wsLabel._maxOpacity = 255;
- this._wsLabel.opacity = this._wsLabel._maxOpacity;
-
- this.add_child(this._wsLabel);
- this.set_child_above_sibling(this._wsLabel, null);
-
- this._wsIndexConId = this.metaWorkspace.connect('notify::workspace-index', () => {
- const newLabel = getLabel();
- this._wsLabel.text = newLabel;
- // avoid possibility of accessing non existing ws
- if (this._updateLabelTimeout) {
- GLib.source_remove(this._updateLabelTimeout);
- this._updateLabelTimeout = 0;
- }
- });
- this._nWindowsConId = this.metaWorkspace.connect('notify::n-windows', () => {
- // wait for new information
- this._updateLabelTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 250, () => {
- const newLabel = getLabel();
- this._wsLabel.text = newLabel;
- this._updateLabelTimeout = 0;
- return GLib.SOURCE_REMOVE;
- });
- });
- }
-
- if (opt.CLOSE_WS_BUTTON_MODE) {
- const closeButton = new St.Icon({
- style_class: 'workspace-close-button',
- icon_name: 'window-close-symbolic',
- x_align: Clutter.ActorAlign.END,
- y_align: Clutter.ActorAlign.START,
- x_expand: true,
- y_expand: true,
- reactive: true,
- opacity: 0,
- });
-
- closeButton.connect('button-release-event', () => {
- if (opt.CLOSE_WS_BUTTON_MODE) {
- this._closeWorkspace();
- return Clutter.EVENT_STOP;
- } else {
- return Clutter.EVENT_PROPAGATE;
- }
- });
-
- closeButton.connect('button-press-event', () => {
- return Clutter.EVENT_STOP;
- });
-
- closeButton.connect('enter-event', () => {
- 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()))
- closeButton.add_style_class_name('workspace-close-button-hover');
- }
- });
-
- closeButton.connect('leave-event', () => {
- closeButton.remove_style_class_name('workspace-close-button-hover');
- });
-
- this.add_child(closeButton);
- this._closeButton = closeButton;
-
- this.reactive = true;
- this._lastCloseClickTime = 0;
- }
-
- if (opt.SHOW_WST_LABELS_ON_HOVER)
- this._wsLabel.opacity = 0;
-
- this.connect('enter-event', () => {
- if (opt.CLOSE_WS_BUTTON_MODE && (!Meta.prefs_get_dynamic_workspaces() || (Meta.prefs_get_dynamic_workspaces() && global.workspace_manager.get_n_workspaces() - 1 !== this.metaWorkspace.index())))
- this._closeButton.opacity = 200;
- if (opt.SHOW_WST_LABELS_ON_HOVER) {
- this._wsLabel.ease({
- duration: 100,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- opacity: this._wsLabel._maxOpacity,
- });
- }
- });
-
- this.connect('leave-event', () => {
- this._closeButton.opacity = 0;
- if (opt.SHOW_WST_LABELS_ON_HOVER) {
- this._wsLabel.ease({
- duration: 100,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- opacity: 0,
- });
- }
- });
-
- if (opt.SHOW_WS_TMB_BG) {
- this._bgManager = new Background.BackgroundManager({
- monitorIndex: this.monitorIndex,
- container: this._viewport,
- vignette: false,
- controlPosition: false,
- });
-
- 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;
- }
-
- this.connect('destroy', () => {
- if (this._wsIndexConId)
- this.metaWorkspace.disconnect(this._wsIndexConId);
-
- if (this._nWindowsConId)
- this.metaWorkspace.disconnect(this._nWindowsConId);
-
- if (this._updateLabelTimeout)
- GLib.source_remove(this._updateLabelTimeout);
-
- if (this._bgManager)
- this._bgManager.destroy();
- });
- },
-
- _closeWorkspace() {
- // CLOSE_WS_BUTTON_MODE 1: single click, 2: double-click, 3: Ctrl
-
- if (opt.CLOSE_WS_BUTTON_MODE === 2) {
- const doubleClickTime = Clutter.Settings.get_default().double_click_time;
- const clickDelay = Date.now() - this._lastCloseClickTime;
- if (clickDelay > doubleClickTime) {
- this._lastCloseClickTime = Date.now();
- return;
- }
- } else if (opt.CLOSE_WS_BUTTON_MODE === 3 && !_Util.isCtrlPressed()) {
- return;
- }
-
- // close windows on this monitor
- const windows = global.display.get_tab_list(0, null).filter(
- w => w.get_monitor() === this.monitorIndex && w.get_workspace() === this.metaWorkspace
- );
-
- for (let i = 0; i < windows.length; i++) {
- if (!windows[i].is_on_all_workspaces())
- windows[i].delete(global.get_current_time() + i);
- }
- },
-
- activate(time) {
- if (this.state > ThumbnailState.NORMAL)
- return;
-
- // if Static Workspace overview mode active, a click on the already active workspace should activate the window picker mode
- const wsIndex = this.metaWorkspace.index();
- const lastWsIndex = global.display.get_workspace_manager().get_n_workspaces() - 1;
- const stateAdjustment = Main.overview._overview.controls._stateAdjustment;
-
- if (stateAdjustment.value === ControlsState.APP_GRID) {
- if (this.metaWorkspace.active) {
- Main.overview._overview.controls._shiftState(Meta.MotionDirection.DOWN);
- // if searchActive, hide it immediately
- Main.overview.searchEntry.set_text('');
- } else {
- this.metaWorkspace.activate(time);
- }
- } else if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE && wsIndex < lastWsIndex) {
- if (stateAdjustment.value > 1)
- stateAdjustment.value = 1;
-
-
- // spread windows
- // in OVERVIEW MODE 2 windows are not spread and workspace is not scaled
- // we need to repeat transition to the overview state 1 (window picker), but with spreading windows animation
- if (this.metaWorkspace.active) {
- Main.overview._overview.controls._searchController._setSearchActive(false);
- opt.WORKSPACE_MODE = 1;
- // setting value to 0 would reset WORKSPACE_MODE
- stateAdjustment.value = 0.01;
- stateAdjustment.ease(1, {
- duration: 200,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- });
- } else {
- // switch ws
- this.metaWorkspace.activate(time);
- }
- // a click on the current workspace should go back to the main view
- } else if (this.metaWorkspace.active) {
- Main.overview.hide();
- } else {
- this.metaWorkspace.activate(time);
- }
- },
-
- // Draggable target interface used only by ThumbnailsBox
- handleDragOverInternal(source, actor, time) {
- if (source === Main.xdndHandler) {
- this.metaWorkspace.activate(time);
- return DND.DragMotionResult.CONTINUE;
- }
-
- if (this.state > ThumbnailState.NORMAL)
- return DND.DragMotionResult.CONTINUE;
-
- if (source.metaWindow &&
- !this._isMyWindow(source.metaWindow.get_compositor_private()))
- return DND.DragMotionResult.MOVE_DROP;
- if (source.app && source.app.can_open_new_window())
- return DND.DragMotionResult.COPY_DROP;
- if (!source.app && source.shellWorkspaceLaunch)
- return DND.DragMotionResult.COPY_DROP;
-
- if (source instanceof imports.ui.appDisplay.FolderIcon)
- return DND.DragMotionResult.COPY_DROP;
-
-
- return DND.DragMotionResult.CONTINUE;
- },
-
- acceptDropInternal(source, actor, time) {
- if (this.state > ThumbnailState.NORMAL)
- return false;
-
- if (source.metaWindow) {
- let win = source.metaWindow.get_compositor_private();
- if (this._isMyWindow(win))
- return false;
-
- let metaWindow = win.get_meta_window();
- Main.moveWindowToMonitorAndWorkspace(metaWindow,
- this.monitorIndex, this.metaWorkspace.index());
- return true;
- } else if (source.app && source.app.can_open_new_window()) {
- if (source.animateLaunchAtPos)
- source.animateLaunchAtPos(actor.x, actor.y);
-
- source.app.open_new_window(this.metaWorkspace.index());
- return true;
- } else if (!source.app && source.shellWorkspaceLaunch) {
- // While unused in our own drag sources, shellWorkspaceLaunch allows
- // extensions to define custom actions for their drag sources.
- source.shellWorkspaceLaunch({
- workspace: this.metaWorkspace.index(),
- timestamp: time,
- });
- return true;
- } else if (source instanceof imports.ui.appDisplay.FolderIcon) {
- if (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());
- }
- } else {
- for (let id of source.view._appIds) {
- const app = Shell.AppSystem.get_default().lookup_app(id);
- app.open_new_window(this.metaWorkspace.index());
- }
- }
- }
-
- return false;
- },
-};
-
-const ThumbnailsBoxCommon = {
- after__init(scrollAdjustment, monitorIndex, orientation = opt.ORIENTATION) {
- this._boxOrientation = orientation;
- },
-
- _activateThumbnailAtPoint(stageX, stageY, time, activateCurrent = false) {
- if (activateCurrent) {
- const thumbnail = this._thumbnails.find(t => t.metaWorkspace.active);
- if (thumbnail)
- thumbnail.activate(time);
- return;
- }
- const [r_, x, y] = this.transform_stage_point(stageX, stageY);
-
- let thumbnail;
-
- if (this._boxOrientation)
- thumbnail = this._thumbnails.find(t => y >= t.y && y <= t.y + t.height);
- else
- thumbnail = this._thumbnails.find(t => x >= t.x && x <= t.x + t.width);
-
- if (thumbnail)
- thumbnail.activate(time);
- },
-
- acceptDrop(source, actor, x, y, time) {
- if (this._dropWorkspace !== -1) {
- return this._thumbnails[this._dropWorkspace].acceptDropInternal(source, actor, time);
- } else if (this._dropPlaceholderPos !== -1) {
- if (!source.metaWindow &&
- (!source.app || !source.app.can_open_new_window()) &&
- (source.app || !source.shellWorkspaceLaunch) &&
- !(source instanceof imports.ui.appDisplay.FolderIcon))
- return false;
-
-
- let isWindow = !!source.metaWindow;
-
- let newWorkspaceIndex;
- [newWorkspaceIndex, this._dropPlaceholderPos] = [this._dropPlaceholderPos, -1];
- this._spliceIndex = newWorkspaceIndex;
-
- Main.wm.insertWorkspace(newWorkspaceIndex);
-
- if (isWindow) {
- // Move the window to our monitor first if necessary.
- let thumbMonitor = this._thumbnails[newWorkspaceIndex].monitorIndex;
- Main.moveWindowToMonitorAndWorkspace(source.metaWindow,
- thumbMonitor, newWorkspaceIndex, true);
- } else if (source.app && source.app.can_open_new_window()) {
- if (source.animateLaunchAtPos)
- source.animateLaunchAtPos(actor.x, actor.y);
-
- source.app.open_new_window(newWorkspaceIndex);
- } else if (!source.app && source.shellWorkspaceLaunch) {
- // While unused in our own drag sources, shellWorkspaceLaunch allows
- // extensions to define custom actions for their drag sources.
- source.shellWorkspaceLaunch({
- workspace: newWorkspaceIndex,
- timestamp: time,
- });
- } else if (source instanceof imports.ui.appDisplay.FolderIcon) {
- if (shellVersion >= 44) {
- for (let app of source.view._apps) {
- // const app = Shell.AppSystem.get_default().lookup_app(id);
- app.open_new_window(newWorkspaceIndex);
- }
- } else {
- for (let id of source.view._appIds) {
- const app = Shell.AppSystem.get_default().lookup_app(id);
- app.open_new_window(newWorkspaceIndex);
- }
- }
- }
-
- if (source.app || (!source.app && source.shellWorkspaceLaunch)) {
- // This new workspace will be automatically removed if the application fails
- // to open its first window within some time, as tracked by Shell.WindowTracker.
- // Here, we only add a very brief timeout to avoid the _immediate_ removal of the
- // workspace while we wait for the startup sequence to load.
- let workspaceManager = global.workspace_manager;
- Main.wm.keepWorkspaceAlive(workspaceManager.get_workspace_by_index(newWorkspaceIndex),
- WorkspaceThumbnail.WORKSPACE_KEEP_ALIVE_TIME);
- }
-
- // Start the animation on the workspace (which is actually
- // an old one which just became empty)
- let thumbnail = this._thumbnails[newWorkspaceIndex];
- this._setThumbnailState(thumbnail, ThumbnailState.NEW);
- thumbnail.slide_position = 1;
- thumbnail.collapse_fraction = 1;
-
- this._queueUpdateStates();
-
- return true;
- } else {
- return false;
- }
- },
-
- handleDragOver(source, actor, x, y, time) {
- // switch axis for vertical orientation
- if (this._boxOrientation)
- x = y;
-
- if (!source.metaWindow &&
- (!source.app || !source.app.can_open_new_window()) &&
- (source.app || !source.shellWorkspaceLaunch) &&
- source !== Main.xdndHandler && !(source instanceof imports.ui.appDisplay.FolderIcon))
- return DND.DragMotionResult.CONTINUE;
-
- const rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL;
- let canCreateWorkspaces = Meta.prefs_get_dynamic_workspaces();
- let spacing = this.get_theme_node().get_length('spacing');
-
- this._dropWorkspace = -1;
- let placeholderPos = -1;
- let length = this._thumbnails.length;
- for (let i = 0; i < length; i++) {
- const index = rtl ? length - i - 1 : i;
-
- if (canCreateWorkspaces && source !== Main.xdndHandler) {
- const [targetStart, targetEnd] =
- this._getPlaceholderTarget(index, spacing, rtl);
-
- if (x > targetStart && x <= targetEnd) {
- placeholderPos = index;
- break;
- }
- }
-
- if (this._withinWorkspace(x, index, rtl)) {
- this._dropWorkspace = index;
- break;
- }
- }
-
- if (this._dropPlaceholderPos !== placeholderPos) {
- this._dropPlaceholderPos = placeholderPos;
- this.queue_relayout();
- }
-
- if (this._dropWorkspace !== -1)
- return this._thumbnails[this._dropWorkspace].handleDragOverInternal(source, actor, time);
- else if (this._dropPlaceholderPos !== -1)
- return source.metaWindow ? DND.DragMotionResult.MOVE_DROP : DND.DragMotionResult.COPY_DROP;
- else
- return DND.DragMotionResult.CONTINUE;
- },
-
- _getPlaceholderTarget(...args) {
- if (this._boxOrientation)
- return ThumbnailsBoxVertical._getPlaceholderTarget.bind(this)(...args);
- else
- return ThumbnailsBoxHorizontal._getPlaceholderTarget.bind(this)(...args);
- },
-
- _withinWorkspace(...args) {
- if (this._boxOrientation)
- return ThumbnailsBoxVertical._withinWorkspace.bind(this)(...args);
- else
- return ThumbnailsBoxHorizontal._withinWorkspace.bind(this)(...args);
- },
-
- get_preferred_custom_width(...args) {
- if (this._boxOrientation)
- return ThumbnailsBoxVertical.get_preferred_custom_width.bind(this)(...args);
- else
- return ThumbnailsBoxHorizontal.get_preferred_custom_width.bind(this)(...args);
- },
-
- get_preferred_custom_height(...args) {
- if (this._boxOrientation)
- return ThumbnailsBoxVertical.get_preferred_custom_height.bind(this)(...args);
- else
- return ThumbnailsBoxHorizontal.get_preferred_custom_height.bind(this)(...args);
- },
-
- vfunc_allocate(...args) {
- if (this._boxOrientation)
- return ThumbnailsBoxVertical.vfunc_allocate.bind(this)(...args);
- else
- return ThumbnailsBoxHorizontal.vfunc_allocate.bind(this)(...args);
- },
-
- _updateShouldShow(...args) {
- if (this._boxOrientation)
- return ThumbnailsBoxVertical._updateShouldShow.bind(this)(...args);
- else
- return ThumbnailsBoxHorizontal._updateShouldShow.bind(this)(...args);
- },
-};
-
-const ThumbnailsBoxVertical = {
- _getPlaceholderTarget(index, spacing, rtl) {
- this._dropPlaceholder.add_style_class_name('placeholder-vertical');
- const workspace = this._thumbnails[index];
-
- let targetY1;
- let targetY2;
-
- if (rtl) {
- const baseY = workspace.y + workspace.height;
- targetY1 = baseY - WORKSPACE_CUT_SIZE;
- targetY2 = baseY + spacing + WORKSPACE_CUT_SIZE;
- } else {
- targetY1 = workspace.y - spacing - WORKSPACE_CUT_SIZE;
- targetY2 = workspace.y + WORKSPACE_CUT_SIZE;
- }
-
- if (index === 0) {
- if (rtl)
- targetY2 -= spacing + WORKSPACE_CUT_SIZE;
- else
- targetY1 += spacing + WORKSPACE_CUT_SIZE;
- }
-
- if (index === this._dropPlaceholderPos) {
- const placeholderHeight = this._dropPlaceholder.get_height() + spacing;
- if (rtl)
- targetY2 += placeholderHeight;
- else
- targetY1 -= placeholderHeight;
- }
-
- return [targetY1, targetY2];
- },
-
- _withinWorkspace(y, index, rtl) {
- const length = this._thumbnails.length;
- const workspace = this._thumbnails[index];
-
- let workspaceY1 = workspace.y + WORKSPACE_CUT_SIZE;
- let workspaceY2 = workspace.y + workspace.height - WORKSPACE_CUT_SIZE;
-
- if (index === length - 1) {
- if (rtl)
- workspaceY1 -= WORKSPACE_CUT_SIZE;
- else
- workspaceY2 += WORKSPACE_CUT_SIZE;
- }
-
- 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);
-
- let themeNode = this.get_theme_node();
-
- forHeight = themeNode.adjust_for_width(forHeight);
-
- let spacing = themeNode.get_length('spacing');
- let nWorkspaces = this._thumbnails.length;
- let totalSpacing = (nWorkspaces - 1) * spacing;
-
- 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.
- let themeNode = this.get_theme_node();
-
- let spacing = themeNode.get_length('spacing');
- let nWorkspaces = this._thumbnails.length;
-
- // remove also top/bottom box padding
- let totalSpacing = (nWorkspaces - 3) * spacing;
-
- const ratio = this._porthole.width / this._porthole.height;
- 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);
- },
-
- // removes extra space (extraWidth in the original function), we need the box as accurate as possible
- // for precise app grid transition animation
- vfunc_allocate(box) {
- this.set_allocation(box);
-
- let rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL;
-
- if (this._thumbnails.length === 0) // not visible
- return;
-
- let themeNode = this.get_theme_node();
- box = themeNode.get_content_box(box);
-
- const portholeWidth = this._porthole.width;
- const portholeHeight = this._porthole.height;
- const spacing = themeNode.get_length('spacing');
-
- /* const nWorkspaces = this._thumbnails.length;*/
-
- // Compute the scale we'll need once everything is updated,
- // unless we are currently transitioning
- if (this._expandFraction === 1) {
- // remove size "breathing" during adding/removing workspaces
-
- /* const totalSpacing = (nWorkspaces - 1) * spacing;
- const availableHeight = (box.get_height() - totalSpacing) / nWorkspaces; */
-
- const hScale = box.get_width() / portholeWidth;
- /* const vScale = availableHeight / portholeHeight;*/
- const vScale = box.get_height() / portholeHeight;
- const newScale = Math.min(hScale, vScale);
-
- if (newScale !== this._targetScale) {
- if (this._targetScale > 0) {
- // We don't ease immediately because we need to observe the
- // ordering in queueUpdateStates - if workspaces have been
- // removed we need to slide them out as the first thing.
- this._targetScale = newScale;
- this._pendingScaleUpdate = true;
- } else {
- this._targetScale = this._scale = newScale;
- }
-
- this._queueUpdateStates();
- }
- }
-
- const ratio = portholeWidth / portholeHeight;
- const thumbnailFullHeight = Math.round(portholeHeight * this._scale);
- const thumbnailWidth = Math.round(thumbnailFullHeight * ratio);
- const thumbnailHeight = thumbnailFullHeight * this._expandFraction;
- const roundedVScale = thumbnailHeight / portholeHeight;
-
- let indicatorValue = this._scrollAdjustment.value;
- let indicatorUpperWs = Math.ceil(indicatorValue);
- let indicatorLowerWs = Math.floor(indicatorValue);
-
- let indicatorLowerY1 = 0;
- let indicatorLowerY2 = 0;
- let indicatorUpperY1 = 0;
- let indicatorUpperY2 = 0;
-
- let indicatorThemeNode = this._indicator.get_theme_node();
- let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + indicatorThemeNode.get_border_width(St.Side.TOP);
- let indicatorBottomFullBorder = indicatorThemeNode.get_padding(St.Side.BOTTOM) + indicatorThemeNode.get_border_width(St.Side.BOTTOM);
- let indicatorLeftFullBorder = indicatorThemeNode.get_padding(St.Side.LEFT) + indicatorThemeNode.get_border_width(St.Side.LEFT);
- let indicatorRightFullBorder = indicatorThemeNode.get_padding(St.Side.RIGHT) + indicatorThemeNode.get_border_width(St.Side.RIGHT);
-
- let y = box.y1;
-
- if (this._dropPlaceholderPos === -1) {
- 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();
- });
- }
- }
-
- let childBox = new Clutter.ActorBox();
-
- for (let i = 0; i < this._thumbnails.length; i++) {
- const thumbnail = this._thumbnails[i];
- if (i > 0)
- y += spacing - Math.round(thumbnail.collapse_fraction * spacing);
-
- const x1 = box.x1;
- const x2 = x1 + thumbnailWidth;
-
- if (i === this._dropPlaceholderPos) {
- let [, placeholderHeight] = this._dropPlaceholder.get_preferred_width(-1);
- childBox.x1 = x1;
- childBox.x2 = x2;
-
- if (rtl) {
- childBox.y2 = box.y2 - Math.round(y);
- childBox.y1 = box.y2 - Math.round(y + placeholderHeight);
- } else {
- childBox.y1 = Math.round(y);
- childBox.y2 = Math.round(y + placeholderHeight);
- }
-
- 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();
- });
- }
- y += placeholderHeight + spacing;
- }
-
- // We might end up with thumbnailWidth being something like 99.33
- // pixels. To make this work and not end up with a gap at the end,
- // we need some thumbnails to be 99 pixels and some 100 pixels width;
- // we compute an actual scale separately for each thumbnail.
- const y1 = Math.round(y);
- const y2 = Math.round(y + thumbnailHeight);
- const roundedHScale = (y2 - y1) / portholeHeight;
-
- // Allocating a scaled actor is funny - x1/y1 correspond to the origin
- // of the actor, but x2/y2 are increased by the *unscaled* size.
- if (rtl) {
- childBox.y2 = box.y2 - y1;
- childBox.y1 = box.y2 - (y1 + thumbnailHeight);
- } else {
- childBox.y1 = y1;
- childBox.y2 = y1 + thumbnailHeight;
- }
- childBox.x1 = x1;
- childBox.x2 = x1 + thumbnailWidth;
-
- thumbnail.setScale(roundedHScale, roundedVScale);
- thumbnail.allocate(childBox);
-
- if (i === indicatorUpperWs) {
- indicatorUpperY1 = childBox.y1;
- indicatorUpperY2 = childBox.y2;
- }
- if (i === indicatorLowerWs) {
- indicatorLowerY1 = childBox.y1;
- indicatorLowerY2 = childBox.y2;
- }
-
- // We round the collapsing portion so that we don't get thumbnails resizing
- // during an animation due to differences in rounded, but leave the uncollapsed
- // portion unrounded so that non-animating we end up with the right total
- y += thumbnailHeight - Math.round(thumbnailHeight * thumbnail.collapse_fraction);
- }
-
- childBox.x1 = box.x1;
- childBox.x2 = box.x1 + thumbnailWidth;
-
- const indicatorY1 = indicatorLowerY1 +
- (indicatorUpperY1 - indicatorLowerY1) * (indicatorValue % 1);
- const indicatorY2 = indicatorLowerY2 +
- (indicatorUpperY2 - indicatorLowerY2) * (indicatorValue % 1);
-
- childBox.y1 = indicatorY1 - indicatorTopFullBorder;
- childBox.y2 = indicatorY2 + indicatorBottomFullBorder;
- childBox.x1 -= indicatorLeftFullBorder;
- childBox.x2 += indicatorRightFullBorder;
- this._indicator.allocate(childBox);
- },
-
- _updateShouldShow() {
- const shouldShow = opt.SHOW_WS_TMB;
- if (this._shouldShow === shouldShow)
- return;
-
- this._shouldShow = shouldShow;
- this.notify('should-show');
- },
-};
-
-// ThumbnailsBox Horizontal
-
-const ThumbnailsBoxHorizontal = {
- _getPlaceholderTarget(index, spacing, rtl) {
- const workspace = this._thumbnails[index];
-
- let targetX1;
- let targetX2;
-
- if (rtl) {
- const baseX = workspace.x + workspace.width;
- targetX1 = baseX - WORKSPACE_CUT_SIZE;
- targetX2 = baseX + spacing + WORKSPACE_CUT_SIZE;
- } else {
- targetX1 = workspace.x - spacing - WORKSPACE_CUT_SIZE;
- targetX2 = workspace.x + WORKSPACE_CUT_SIZE;
- }
-
- if (index === 0) {
- if (rtl)
- targetX2 -= spacing + WORKSPACE_CUT_SIZE;
- else
- targetX1 += spacing + WORKSPACE_CUT_SIZE;
- }
-
- if (index === this._dropPlaceholderPos) {
- const placeholderWidth = this._dropPlaceholder.get_width() + spacing;
- if (rtl)
- targetX2 += placeholderWidth;
- else
- targetX1 -= placeholderWidth;
- }
-
- return [targetX1, targetX2];
- },
-
- _withinWorkspace(x, index, rtl) {
- const length = this._thumbnails.length;
- const workspace = this._thumbnails[index];
-
- let workspaceX1 = workspace.x + WORKSPACE_CUT_SIZE;
- let workspaceX2 = workspace.x + workspace.width - WORKSPACE_CUT_SIZE;
-
- if (index === length - 1) {
- if (rtl)
- workspaceX1 -= WORKSPACE_CUT_SIZE;
- else
- workspaceX2 += WORKSPACE_CUT_SIZE;
- }
-
- return x > workspaceX1 && x <= workspaceX2;
- },
-
- get_preferred_custom_height(forWidth) {
- let themeNode = this.get_theme_node();
-
- forWidth = themeNode.adjust_for_width(forWidth);
-
- let spacing = themeNode.get_length('spacing');
- let nWorkspaces = this._thumbnails.length;
- let totalSpacing = (nWorkspaces - 1) * spacing;
-
- 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];
-
- let themeNode = this.get_theme_node();
-
- let spacing = themeNode.get_length('spacing');
- let nWorkspaces = this._thumbnails.length;
- // remove also left/right box padding from the total spacing
- let totalSpacing = (nWorkspaces - 3) * spacing;
-
- const ratio = this._porthole.height / this._porthole.width;
-
- 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);
- },
-
- vfunc_allocate(box) {
- this.set_allocation(box);
-
- let rtl = Clutter.get_default_text_direction() === Clutter.TextDirection.RTL;
-
- if (this._thumbnails.length === 0) // not visible
- return;
-
- let themeNode = this.get_theme_node();
- box = themeNode.get_content_box(box);
-
- const portholeWidth = this._porthole.width;
- const portholeHeight = this._porthole.height;
- const spacing = themeNode.get_length('spacing');
-
- /* const nWorkspaces = this._thumbnails.length; */
-
- // Compute the scale we'll need once everything is updated,
- // unless we are currently transitioning
- if (this._expandFraction === 1) {
- // remove size "breathing" during adding/removing workspaces
-
- /* const totalSpacing = (nWorkspaces - 1) * spacing;
- const availableWidth = (box.get_width() - totalSpacing) / nWorkspaces;
-
- const hScale = availableWidth / portholeWidth; */
- const hScale = box.get_width() / portholeWidth;
- const vScale = box.get_height() / portholeHeight;
- const newScale = Math.min(hScale, vScale);
-
- if (newScale !== this._targetScale) {
- if (this._targetScale > 0) {
- // We don't ease immediately because we need to observe the
- // ordering in queueUpdateStates - if workspaces have been
- // removed we need to slide them out as the first thing.
- this._targetScale = newScale;
- this._pendingScaleUpdate = true;
- } else {
- this._targetScale = this._scale = newScale;
- }
-
- this._queueUpdateStates();
- }
- }
-
- const ratio = portholeWidth / portholeHeight;
- const thumbnailFullHeight = Math.round(portholeHeight * this._scale);
- const thumbnailWidth = Math.round(thumbnailFullHeight * ratio);
- const thumbnailHeight = thumbnailFullHeight * this._expandFraction;
- const roundedVScale = thumbnailHeight / portholeHeight;
-
- let indicatorValue = this._scrollAdjustment.value;
- let indicatorUpperWs = Math.ceil(indicatorValue);
- let indicatorLowerWs = Math.floor(indicatorValue);
-
- let indicatorLowerX1 = 0;
- let indicatorLowerX2 = 0;
- let indicatorUpperX1 = 0;
- let indicatorUpperX2 = 0;
-
- let indicatorThemeNode = this._indicator.get_theme_node();
- let indicatorTopFullBorder = indicatorThemeNode.get_padding(St.Side.TOP) + indicatorThemeNode.get_border_width(St.Side.TOP);
- let indicatorBottomFullBorder = indicatorThemeNode.get_padding(St.Side.BOTTOM) + indicatorThemeNode.get_border_width(St.Side.BOTTOM);
- let indicatorLeftFullBorder = indicatorThemeNode.get_padding(St.Side.LEFT) + indicatorThemeNode.get_border_width(St.Side.LEFT);
- let indicatorRightFullBorder = indicatorThemeNode.get_padding(St.Side.RIGHT) + indicatorThemeNode.get_border_width(St.Side.RIGHT);
-
- let x = box.x1;
-
- if (this._dropPlaceholderPos === -1) {
- 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();
- });
- }
- }
-
- let childBox = new Clutter.ActorBox();
-
- for (let i = 0; i < this._thumbnails.length; i++) {
- const thumbnail = this._thumbnails[i];
- if (i > 0)
- x += spacing - Math.round(thumbnail.collapse_fraction * spacing);
-
- const y1 = box.y1;
- const y2 = y1 + thumbnailHeight;
-
- if (i === this._dropPlaceholderPos) {
- const [, placeholderWidth] = this._dropPlaceholder.get_preferred_width(-1);
- childBox.y1 = y1;
- childBox.y2 = y2;
-
- if (rtl) {
- childBox.x2 = box.x2 - Math.round(x);
- childBox.x1 = box.x2 - Math.round(x + placeholderWidth);
- } else {
- childBox.x1 = Math.round(x);
- childBox.x2 = Math.round(x + placeholderWidth);
- }
-
- 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();
- });
- }
- x += placeholderWidth + spacing;
- }
-
- // We might end up with thumbnailWidth being something like 99.33
- // pixels. To make this work and not end up with a gap at the end,
- // we need some thumbnails to be 99 pixels and some 100 pixels width;
- // we compute an actual scale separately for each thumbnail.
- const x1 = Math.round(x);
- const x2 = Math.round(x + thumbnailWidth);
- const roundedHScale = (x2 - x1) / portholeWidth;
-
- // Allocating a scaled actor is funny - x1/y1 correspond to the origin
- // of the actor, but x2/y2 are increased by the *unscaled* size.
- if (rtl) {
- childBox.x2 = box.x2 - x1;
- childBox.x1 = box.x2 - (x1 + thumbnailWidth);
- } else {
- childBox.x1 = x1;
- childBox.x2 = x1 + thumbnailWidth;
- }
- childBox.y1 = y1;
- childBox.y2 = y1 + thumbnailHeight;
-
- thumbnail.setScale(roundedHScale, roundedVScale);
- thumbnail.allocate(childBox);
-
- if (i === indicatorUpperWs) {
- indicatorUpperX1 = childBox.x1;
- indicatorUpperX2 = childBox.x2;
- }
- if (i === indicatorLowerWs) {
- indicatorLowerX1 = childBox.x1;
- indicatorLowerX2 = childBox.x2;
- }
-
- // We round the collapsing portion so that we don't get thumbnails resizing
- // during an animation due to differences in rounded, but leave the uncollapsed
- // portion unrounded so that non-animating we end up with the right total
- x += thumbnailWidth - Math.round(thumbnailWidth * thumbnail.collapse_fraction);
- }
-
- childBox.y1 = box.y1;
- childBox.y2 = box.y1 + thumbnailHeight;
-
- const indicatorX1 = indicatorLowerX1 +
- (indicatorUpperX1 - indicatorLowerX1) * (indicatorValue % 1);
- const indicatorX2 = indicatorLowerX2 +
- (indicatorUpperX2 - indicatorLowerX2) * (indicatorValue % 1);
-
- childBox.x1 = indicatorX1 - indicatorLeftFullBorder;
- childBox.x2 = indicatorX2 + indicatorRightFullBorder;
- childBox.y1 -= indicatorTopFullBorder;
- childBox.y2 += indicatorBottomFullBorder;
- this._indicator.allocate(childBox);
- },
-
- _updateShouldShow: ThumbnailsBoxVertical._updateShouldShow,
-};
diff --git a/extensions/vertical-workspaces/lib/workspacesView.js b/extensions/vertical-workspaces/lib/workspacesView.js
deleted file mode 100644
index e3575f1..0000000
--- a/extensions/vertical-workspaces/lib/workspacesView.js
+++ /dev/null
@@ -1,934 +0,0 @@
-/**
- * V-Shell (Vertical Workspaces)
- * workspacesView.js
- *
- * @author GdH <G-dH@github.com>
- * @copyright 2022 - 2023
- * @license GPL-3.0
- *
- */
-
-'use strict';
-
-const { GObject, Clutter, Meta, St } = imports.gi;
-
-const Main = imports.ui.main;
-const Util = imports.misc.util;
-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;
-
-let opt;
-
-
-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;
-
- // 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);
- }
-
- if (reset) {
- _overrides = null;
- opt = null;
- return;
- }
-
-
- _overrides = new _Util.Overrides();
-
- if (!cubeSupported)
- _overrides.addOverride('WorkspacesView', WorkspacesView.WorkspacesView.prototype, WorkspacesViewCommon);
-
- _overrides.addOverride('WorkspacesDisplay', WorkspacesView.WorkspacesDisplay.prototype, WorkspacesDisplay);
- _overrides.addOverride('ExtraWorkspaceView', WorkspacesView.ExtraWorkspaceView.prototype, ExtraWorkspaceView);
-
- 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);
- }
-}
-
-const WorkspacesViewCommon = {
- _getFirstFitSingleWorkspaceBox(box, spacing, vertical) {
- let [width, height] = box.get_size();
- const [workspace] = this._workspaces;
-
- const rtl = this.text_direction === Clutter.TextDirection.RTL;
- const adj = this._scrollAdjustment;
- const currentWorkspace = vertical || !rtl
- ? adj.value : adj.upper - adj.value - 1;
-
- // Single fit mode implies centered too
- let [x1, y1] = box.get_origin();
- const [, workspaceWidth] = workspace ? workspace.get_preferred_width(Math.floor(height)) : [0, width];
- const [, workspaceHeight] = workspace ? workspace.get_preferred_height(workspaceWidth) : [0, height];
-
- if (vertical) {
- x1 += (width - workspaceWidth) / 2;
- y1 -= currentWorkspace * (workspaceHeight + spacing);
- } else {
- x1 += (width - workspaceWidth) / 2;
- x1 -= currentWorkspace * (workspaceWidth + spacing);
- }
-
- const fitSingleBox = new Clutter.ActorBox({ x1, y1 });
-
- fitSingleBox.set_size(workspaceWidth, workspaceHeight);
-
- return fitSingleBox;
- },
-
- // set spacing between ws previews
- _getSpacing(box, fitMode, vertical) {
- const [width, height] = box.get_size();
- const [workspace] = this._workspaces;
-
- if (!workspace)
- return 0;
-
- let availableSpace;
- let workspaceSize;
- if (vertical) {
- [, workspaceSize] = workspace.get_preferred_height(width);
- availableSpace = height;
- } else {
- [, workspaceSize] = workspace.get_preferred_width(height);
- availableSpace = width;
- }
-
- const spacing = (availableSpace - workspaceSize * 0.4) * (1 - fitMode);
- const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- return Math.clamp(spacing,
- opt.WORKSPACE_MIN_SPACING * scaleFactor,
- opt.WORKSPACE_MAX_SPACING * scaleFactor);
- },
-
- // this function has duplicate in OverviewControls so we use one function for both to avoid issues with syncing them
- _getFitModeForState(state) {
- return _getFitModeForState(state);
- },
-
- // normal view 0, spread windows 1
- _getWorkspaceModeForOverviewState(state) {
-
- switch (state) {
- case ControlsState.HIDDEN:
- return 0;
- case ControlsState.WINDOW_PICKER:
- return opt.WORKSPACE_MODE;
- case ControlsState.APP_GRID:
- return (this._monitorIndex !== global.display.get_primary_monitor() || !opt.WS_ANIMATION) && !opt.OVERVIEW_MODE ? 1 : 0;
- }
-
- return 0;
- },
-
- _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;
- }*/
- },
-
- // disable scaling and hide inactive workspaces
- _updateWorkspacesState() {
- const adj = this._scrollAdjustment;
- const fitMode = this._fitModeAdjustment.value;
-
- let { initialState, finalState, progress, currentState } =
- this._overviewAdjustment.getStateTransitionParams();
-
- const workspaceMode = (1 - fitMode) * Util.lerp(
- this._getWorkspaceModeForOverviewState(initialState),
- this._getWorkspaceModeForOverviewState(finalState),
- progress);
-
- 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);
-
- const scaleProgress = 1 - Math.clamp(distanceToCurrentWorkspace, 0, 1);
-
- // 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
- // and only current and adjacent ws when switching ws
- w.visible = (this._animating && wsScrollProgress && distanceToCurrentWorkspace <= (opt.NUMBER_OF_VISIBLE_NEIGHBORS + 1)) || scaleProgress === 1 ||
- (opt.WORKSPACE_MAX_SPACING > 340 && distanceToCurrentWorkspace <= opt.NUMBER_OF_VISIBLE_NEIGHBORS && currentState === ControlsState.WINDOW_PICKER) ||
- (this._monitorIndex !== primaryMonitor && distanceToCurrentWorkspace <= opt.NUMBER_OF_VISIBLE_NEIGHBORS) || (!opt.WS_ANIMATION && distanceToCurrentWorkspace < opt.NUMBER_OF_VISIBLE_NEIGHBORS) ||
- (opt.WORKSPACE_MAX_SPACING < 340 && distanceToCurrentWorkspace <= opt.NUMBER_OF_VISIBLE_NEIGHBORS && currentState <= ControlsState.WINDOW_PICKER &&
- ((initialState < ControlsState.APP_GRID && finalState < ControlsState.APP_GRID))
- );
-
- // 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
- if (!w.visible && distanceToCurrentWorkspace === 1 && initialState === ControlsState.APP_GRID && currentState === ControlsState.WINDOW_PICKER) {
- w.scale_x = scaleX;
- w.scale_y = scaleY;
- w.visible = true;
- w.ease({
- duration: 100,
- scale_x: 1,
- scale_y: 1,
- 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
- if (opt.SHOW_WS_PREVIEW_BG && opt.OVERVIEW_MODE === 1 && distanceToCurrentWorkspace < 2)
- w._background._updateBorderRadius(Math.min(1, w._overviewAdjustment.value));
-
-
- // hide workspace background
- if (!opt.SHOW_WS_PREVIEW_BG && w._background.opacity)
- w._background.opacity = 0;
- });
- },
-};
-
-// SecondaryMonitorDisplay Vertical
-const SecondaryMonitorDisplayVertical = {
- _getThumbnailParamsForState(state) {
-
- let opacity, scale, translationX;
- switch (state) {
- case ControlsState.HIDDEN:
- opacity = 255;
- scale = 1;
- translationX = 0;
- if (!Main.layoutManager._startingUp && (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2))
- translationX = this._thumbnails.width * (opt.SEC_WS_TMB_LEFT ? -1 : 1);
-
- break;
- case ControlsState.WINDOW_PICKER:
- case ControlsState.APP_GRID:
- opacity = 255;
- scale = 1;
- translationX = 0;
- break;
- default:
- opacity = 255;
- scale = 1;
- translationX = 0;
- break;
- }
-
- 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();
- const [width, height] = workspaceBox.get_size();
-
- let wWidth, wHeight, wsbX, wsbY, offset, yShift;
- switch (state) {
- case ControlsState.HIDDEN:
- break;
- case ControlsState.WINDOW_PICKER:
- case ControlsState.APP_GRID:
- if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE)
- break;
-
- yShift = 0;
- if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED) {
- if (opt.PANEL_POSITION_TOP)
- yShift = Main.panel.height;
- else
- yShift = -Main.panel.height;
- }
-
- wWidth = width - thumbnailsWidth - 5 * spacing;
- wHeight = Math.min(wWidth / (width / height) - Math.abs(yShift), height - 4 * spacing);
- wWidth = Math.round(wWidth * opt.SEC_WS_PREVIEW_SCALE);
- wHeight = Math.round(wHeight * opt.SEC_WS_PREVIEW_SCALE);
-
- offset = Math.round(width - thumbnailsWidth - wWidth) / 2;
- if (opt.SEC_WS_TMB_LEFT)
- wsbX = thumbnailsWidth + offset;
- else
- wsbX = offset;
-
- wsbY = Math.round((height - wHeight - Math.abs(yShift)) / 2 + yShift);
-
- workspaceBox.set_origin(wsbX, wsbY);
- workspaceBox.set_size(wWidth, wHeight);
- break;
- }
-
- return workspaceBox;
- },
-
- vfunc_allocate(box) {
- this.set_allocation(box);
-
- const themeNode = this.get_theme_node();
- const contentBox = themeNode.get_content_box(box);
- const [width, height] = contentBox.get_size();
- const { expandFraction } = this._thumbnails;
- 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);
-
- this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
- if (this._thumbnails.visible) {
- let wsTmbX;
- if (opt.SEC_WS_TMB_LEFT) { // left
- wsTmbX = Math.round(spacing / 4);
- this._thumbnails._positionLeft = true;
- } else {
- wsTmbX = Math.round(width - spacing / 4 - thumbnailsWidth);
- this._thumbnails._positionLeft = false;
- }
-
- const childBox = new Clutter.ActorBox();
- const availSpace = height - thumbnailsHeight - 2 * spacing;
-
- let wsTmbY = availSpace / 2;
- wsTmbY -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbY - spacing;
-
- childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY));
- childBox.set_size(thumbnailsWidth, thumbnailsHeight);
- this._thumbnails.allocate(childBox);
- }
-
- const {
- currentState, initialState, finalState, transitioning, progress,
- } = this._overviewAdjustment.getStateTransitionParams();
-
- let workspacesBox;
- const workspaceParams = [contentBox, padding, thumbnailsWidth, spacing];
- if (!transitioning) {
- workspacesBox =
- this._getWorkspacesBoxForState(currentState, ...workspaceParams);
- } else {
- const initialBox =
- this._getWorkspacesBoxForState(initialState, ...workspaceParams);
- const finalBox =
- this._getWorkspacesBoxForState(finalState, ...workspaceParams);
- workspacesBox = initialBox.interpolate(finalBox, progress);
- }
- this._workspacesView.allocate(workspacesBox);
- },
-
- _updateThumbnailVisibility() {
- 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._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() {
- if (opt.SEC_WS_TMB_HIDDEN)
- return;
-
- // workaround for upstream bug - secondary thumbnails boxes don't catch 'showing' signal on the shell startup and don't populate the box with thumbnails
- // the tmbBox contents is also destroyed when overview state adjustment gets above 1 when swiping gesture from window picker to app grid
- if (!this._thumbnails._thumbnails.length)
- this._thumbnails._createThumbnails();
-
-
- const { initialState, finalState, progress } =
- this._overviewAdjustment.getStateTransitionParams();
-
- const initialParams = this._getThumbnailParamsForState(initialState);
- const finalParams = this._getThumbnailParamsForState(finalState);
-
- /* const opacity =
- Util.lerp(initialParams.opacity, finalParams.opacity, progress);
- const scale =
- Util.lerp(initialParams.scale, finalParams.scale, progress);*/
-
- // 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);
- const translationX = !Main.layoutManager._startingUp && ((!opt.SHOW_WS_PREVIEW_BG && !opt.OVERVIEW_MODE2) || animateOverviewMode2)
- ? Util.lerp(initialParams.translationX, finalParams.translationX, progress)
- : 0;
-
- this._thumbnails.set({
- opacity: 255,
- // scale_x: scale,
- // scale_y: scale,
- translation_x: translationX,
- });
- },
-
- _updateWorkspacesView() {
- if (this._workspacesView)
- this._workspacesView.destroy();
-
- if (this._settings.get_boolean('workspaces-only-on-primary')) {
- opt.SEC_WS_TMB_HIDDEN = true;
- this._workspacesView = new WorkspacesView.ExtraWorkspaceView(
- this._monitorIndex,
- this._overviewAdjustment);
- } else {
- opt.SEC_WS_TMB_HIDDEN = !opt.SHOW_SEC_WS_TMB;
- this._workspacesView = new WorkspacesView.WorkspacesView(
- this._monitorIndex,
- this._controls,
- this._scrollAdjustment,
- // Secondary monitors don't need FitMode.ALL since there is workspace switcher always visible
- // this._fitModeAdjustment,
- new St.Adjustment({
- actor: this,
- value: 0, // FitMode.SINGLE,
- lower: 0, // FitMode.SINGLE,
- upper: 0, // FitMode.SINGLE,
- }),
- // secondaryOverviewAdjustment);
- this._overviewAdjustment);
- }
- this.add_child(this._workspacesView);
- this._thumbnails.opacity = 0;
- },
-};
-
-// SecondaryMonitorDisplay Horizontal
-const SecondaryMonitorDisplayHorizontal = {
- _getThumbnailParamsForState(state) {
- // const { ControlsState } = OverviewControls;
-
- let opacity, scale, translationY;
- switch (state) {
- case ControlsState.HIDDEN:
- opacity = 255;
- scale = 1;
- translationY = 0;
- if (!Main.layoutManager._startingUp && (!opt.SHOW_WS_PREVIEW_BG || opt.OVERVIEW_MODE2))
- translationY = this._thumbnails.height * (opt.SEC_WS_TMB_TOP ? -1 : 1);
-
- break;
- case ControlsState.WINDOW_PICKER:
- case ControlsState.APP_GRID:
- opacity = 255;
- scale = 1;
- translationY = 0;
- break;
- default:
- opacity = 255;
- scale = 1;
- translationY = 0;
- break;
- }
-
- return { opacity, scale, translationY };
- },
-
- _getWorkspacesBoxForState(state, box, padding, thumbnailsHeight, spacing) {
- // const { ControlsState } = OverviewControls;
- const workspaceBox = box.copy();
- const [width, height] = workspaceBox.get_size();
-
- let wWidth, wHeight, wsbX, wsbY, offset, yShift;
- switch (state) {
- case ControlsState.HIDDEN:
- break;
- case ControlsState.WINDOW_PICKER:
- case ControlsState.APP_GRID:
- if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE)
- break;
-
- yShift = 0;
- if (opt.SEC_WS_PREVIEW_SHIFT && !opt.PANEL_DISABLED) {
- if (opt.PANEL_POSITION_TOP)
- yShift = Main.panel.height;
- else
- yShift = -Main.panel.height;
- }
-
- wHeight = height - Math.abs(yShift) - (thumbnailsHeight ? thumbnailsHeight + 4 * spacing : padding);
- wWidth = Math.min(wHeight * (width / height), width - 5 * spacing);
- wWidth = Math.round(wWidth * opt.SEC_WS_PREVIEW_SCALE);
- wHeight = Math.round(wHeight * opt.SEC_WS_PREVIEW_SCALE);
-
- offset = Math.round((height - thumbnailsHeight - wHeight - Math.abs(yShift)) / 2);
- if (opt.SEC_WS_TMB_TOP)
- wsbY = thumbnailsHeight + offset;
- else
- wsbY = offset;
-
- wsbY += yShift;
- wsbX = Math.round((width - wWidth) / 2);
-
- workspaceBox.set_origin(wsbX, wsbY);
- workspaceBox.set_size(wWidth, wHeight);
- break;
- }
-
- return workspaceBox;
- },
-
- _getThumbnailsHeight(box) {
- if (opt.SEC_WS_TMB_HIDDEN)
- return 0;
-
- const [width, height] = box.get_size();
- const { expandFraction } = this._thumbnails;
- const [thumbnailsHeight] = this._thumbnails.get_preferred_height(width);
- return Math.min(
- thumbnailsHeight * expandFraction,
- height * opt.SEC_MAX_THUMBNAIL_SCALE);
- },
-
- vfunc_allocate(box) {
- this.set_allocation(box);
-
- const themeNode = this.get_theme_node();
- const contentBox = themeNode.get_content_box(box);
- const [width, height] = contentBox.get_size();
- const { expandFraction } = this._thumbnails;
- 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);
-
- this._thumbnails.visible = !opt.SEC_WS_TMB_HIDDEN;
- if (this._thumbnails.visible) {
- let wsTmbY;
- if (opt.SEC_WS_TMB_TOP)
- wsTmbY = Math.round(spacing / 4);
- else
- wsTmbY = Math.round(height - spacing / 4 - thumbnailsHeight);
-
-
- const childBox = new Clutter.ActorBox();
- const availSpace = width - thumbnailsWidth - 2 * spacing;
-
- let wsTmbX = availSpace / 2;
- wsTmbX -= opt.SEC_WS_TMB_POSITION_ADJUSTMENT * wsTmbX - spacing;
-
- childBox.set_origin(Math.round(wsTmbX), Math.round(wsTmbY));
- childBox.set_size(thumbnailsWidth, thumbnailsHeight);
- this._thumbnails.allocate(childBox);
- }
-
- const {
- currentState, initialState, finalState, transitioning, progress,
- } = this._overviewAdjustment.getStateTransitionParams();
-
- let workspacesBox;
- const workspaceParams = [contentBox, padding, thumbnailsHeight, spacing];
- if (!transitioning) {
- workspacesBox =
- this._getWorkspacesBoxForState(currentState, ...workspaceParams);
- } else {
- const initialBox =
- this._getWorkspacesBoxForState(initialState, ...workspaceParams);
- const finalBox =
- this._getWorkspacesBoxForState(finalState, ...workspaceParams);
- workspacesBox = initialBox.interpolate(finalBox, progress);
- }
- this._workspacesView.allocate(workspacesBox);
- },
-
- _updateThumbnailVisibility: SecondaryMonitorDisplayVertical._updateThumbnailVisibility,
-
- _updateThumbnailParams() {
- if (opt.SEC_WS_TMB_HIDDEN)
- return;
-
- // workaround for upstream bug - secondary thumbnails boxes don't catch 'showing' signal on the shell startup and don't populate the box with thumbnails
- // the tmbBox contents is also destroyed when overview state adjustment gets above 1 when swiping gesture from window picker to app grid
- if (!this._thumbnails._thumbnails.length)
- this._thumbnails._createThumbnails();
-
-
- const { initialState, finalState, progress } =
- this._overviewAdjustment.getStateTransitionParams();
-
- const initialParams = this._getThumbnailParamsForState(initialState);
- const finalParams = this._getThumbnailParamsForState(finalState);
-
- /* const opacity =
- Util.lerp(initialParams.opacity, finalParams.opacity, progress);
- const scale =
- Util.lerp(initialParams.scale, finalParams.scale, progress);*/
-
- // 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);
- const translationY = !Main.layoutManager._startingUp && ((!opt.SHOW_WS_PREVIEW_BG && !opt.OVERVIEW_MODE2) || animateOverviewMode2)
- ? Util.lerp(initialParams.translationY, finalParams.translationY, progress)
- : 0;
-
- this._thumbnails.set({
- opacity: 255,
- // scale_x: scale,
- // scale_y: scale,
- translation_y: translationY,
- });
- },
-
- _updateWorkspacesView() {
- if (this._workspacesView)
- this._workspacesView.destroy();
-
- if (this._settings.get_boolean('workspaces-only-on-primary')) {
- opt.SEC_WS_TMB_HIDDEN = true;
- this._workspacesView = new WorkspacesView.ExtraWorkspaceView(
- this._monitorIndex,
- this._overviewAdjustment);
- } else {
- opt.SEC_WS_TMB_HIDDEN = !opt.SHOW_SEC_WS_TMB;
- this._workspacesView = new WorkspacesView.WorkspacesView(
- this._monitorIndex,
- this._controls,
- this._scrollAdjustment,
- // Secondary monitors don't need FitMode.ALL since there is workspace switcher always visible
- // this._fitModeAdjustment,
- new St.Adjustment({
- actor: this,
- value: 0, // FitMode.SINGLE,
- lower: 0, // FitMode.SINGLE,
- upper: 0, // FitMode.SINGLE,
- }),
- // secondaryOverviewAdjustment);
- this._overviewAdjustment);
- }
- this.add_child(this._workspacesView);
- this._thumbnails.opacity = 0;
- },
-};
-
-const ExtraWorkspaceView = {
- _updateWorkspaceMode() {
- const overviewState = this._overviewAdjustment.value;
-
- const progress = Math.clamp(overviewState,
- ControlsState.HIDDEN,
- opt.OVERVIEW_MODE && !opt.WORKSPACE_MODE ? ControlsState.HIDDEN : ControlsState.WINDOW_PICKER);
-
- this._workspace.stateAdjustment.value = progress;
-
- // force ws preview bg corner radiuses where GS doesn't do it
- if (opt.SHOW_WS_PREVIEW_BG && opt.OVERVIEW_MODE === 1)
- this._workspace._background._updateBorderRadius(Math.min(1, this._workspace._overviewAdjustment.value));
-
-
- // hide workspace background
- if (!opt.SHOW_WS_PREVIEW_BG && this._workspace._background.opacity)
- this._workspace._background.opacity = 0;
- },
-};
-
-const WorkspacesDisplay = {
- _updateWorkspacesViews() {
- for (let i = 0; i < this._workspacesViews.length; i++)
- this._workspacesViews[i].destroy();
-
- this._primaryIndex = Main.layoutManager.primaryIndex;
- this._workspacesViews = [];
- let monitors = Main.layoutManager.monitors;
- for (let i = 0; i < monitors.length; i++) {
- let view;
- if (i === this._primaryIndex) {
- view = new WorkspacesView.WorkspacesView(i,
- this._controls,
- this._scrollAdjustment,
- this._fitModeAdjustment,
- this._overviewAdjustment);
-
- view.visible = this._primaryVisible;
- this.bind_property('opacity', view, 'opacity', GObject.BindingFlags.SYNC_CREATE);
- this.add_child(view);
- } else {
- view = new WorkspacesView.SecondaryMonitorDisplay(i,
- this._controls,
- this._scrollAdjustment,
- // Secondary monitors don't need FitMode.ALL since there is workspace switcher always visible
- // this._fitModeAdjustment,
- new St.Adjustment({
- actor: this,
- value: 0, // FitMode.SINGLE,
- lower: 0, // FitMode.SINGLE,
- upper: 0, // FitMode.SINGLE,
- }),
- this._overviewAdjustment);
- Main.layoutManager.overviewGroup.add_actor(view);
- }
-
- this._workspacesViews.push(view);
- }
- },
-
- _onScrollEvent(actor, event) {
- if (this._swipeTracker.canHandleScrollEvent(event))
- return Clutter.EVENT_PROPAGATE;
-
- if (!this.mapped)
- return Clutter.EVENT_PROPAGATE;
-
- if (this._workspacesOnlyOnPrimary &&
- this._getMonitorIndexForEvent(event) !== this._primaryIndex)
- return Clutter.EVENT_PROPAGATE;
-
- if (opt.PANEL_MODE === 1) {
- const panelBox = Main.layoutManager.panelBox;
- const [, y] = global.get_pointer();
- if (y > panelBox.allocation.y1 && y < panelBox.allocation.y2)
- return Clutter.EVENT_STOP;
- }
-
- if (_Util.isShiftPressed()) {
- let direction = _Util.getScrollDirection(event);
- if (direction === null || (Date.now() - this._lastScrollTime) < 150)
- return Clutter.EVENT_STOP;
- this._lastScrollTime = Date.now();
-
- if (direction === Clutter.ScrollDirection.UP)
- direction = -1;
-
- else if (direction === Clutter.ScrollDirection.DOWN)
- direction = 1;
- else
- direction = 0;
-
-
- if (direction) {
- _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;
- });
- return Clutter.EVENT_STOP;
- }
- }
-
- return Main.wm.handleWorkspaceScroll(event);
- },
-
- _onKeyPressEvent(actor, event) {
- const symbol = event.get_key_symbol();
- /* const { ControlsState } = OverviewControls;
- if (this._overviewAdjustment.value !== ControlsState.WINDOW_PICKER && symbol !== Clutter.KEY_space)
- return Clutter.EVENT_PROPAGATE;*/
-
- /* if (!this.reactive)
- return Clutter.EVENT_PROPAGATE; */
- const { workspaceManager } = global;
- const vertical = workspaceManager.layout_rows === -1;
- const rtl = this.get_text_direction() === Clutter.TextDirection.RTL;
- const state = this._overviewAdjustment.value;
-
- let which;
- switch (symbol) {
- case Clutter.KEY_Return:
- case Clutter.KEY_KP_Enter:
- if (_Util.isCtrlPressed()) {
- Main.ctrlAltTabManager._items.forEach(i => {
- if (i.sortGroup === 1 && i.name === 'Dash')
- Main.ctrlAltTabManager.focusGroup(i);
- });
- }
- return Clutter.EVENT_STOP;
- case Clutter.KEY_Page_Up:
- if (vertical)
- which = Meta.MotionDirection.UP;
- else if (rtl)
- which = Meta.MotionDirection.RIGHT;
- else
- which = Meta.MotionDirection.LEFT;
- break;
- case Clutter.KEY_Page_Down:
- if (vertical)
- which = Meta.MotionDirection.DOWN;
- else if (rtl)
- which = Meta.MotionDirection.LEFT;
- else
- which = Meta.MotionDirection.RIGHT;
- break;
- case Clutter.KEY_Home:
- which = 0;
- break;
- case Clutter.KEY_End:
- which = workspaceManager.n_workspaces - 1;
- break;
- case Clutter.KEY_space:
- if (_Util.isCtrlPressed() && _Util.isShiftPressed()) {
- _Util.openPreferences();
- } else if (_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);
- }
-
- return Clutter.EVENT_STOP;
- case Clutter.KEY_Down:
- case Clutter.KEY_Left:
- case Clutter.KEY_Right:
- case Clutter.KEY_Up:
- case Clutter.KEY_Tab:
- if (Main.overview._overview._controls._searchController.searchActive) {
- Main.overview.searchEntry.grab_key_focus();
- } else if (opt.OVERVIEW_MODE2 && !opt.WORKSPACE_MODE && state === 1) {
- // expose windows by "clicking" on ws thumbnail
- // in this case overview stateAdjustment will be used for transition
- Main.overview._overview.controls._thumbnailsBox._activateThumbnailAtPoint(0, 0, global.get_current_time(), true);
- Main.ctrlAltTabManager._items.forEach(i => {
- if (i.sortGroup === 1 && i.name === 'Windows')
- Main.ctrlAltTabManager.focusGroup(i);
- });
- } 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);
- } else {
- if (state === 2)
- return Clutter.EVENT_PROPAGATE;
- Main.ctrlAltTabManager._items.forEach(i => {
- if (i.sortGroup === 1 && i.name === 'Windows')
- Main.ctrlAltTabManager.focusGroup(i);
- });
- }
-
- return Clutter.EVENT_STOP;
- default:
- return Clutter.EVENT_PROPAGATE;
- }
-
- if (state === 2)
- return Clutter.EVENT_PROPAGATE;
-
- let ws;
- if (which < 0)
- // Negative workspace numbers are directions
- ws = workspaceManager.get_active_workspace().get_neighbor(which);
- else
- // Otherwise it is a workspace index
- ws = workspaceManager.get_workspace_by_index(which);
-
- if (_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);
- // 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;
- });
- return Clutter.EVENT_STOP;
- }
-
- if (ws)
- Main.wm.actionMoveWorkspace(ws);
-
- return Clutter.EVENT_STOP;
- },
-};
-
-// same copy of this function should be available in OverviewControls and WorkspacesView
-function _getFitModeForState(state) {
- switch (state) {
- case ControlsState.HIDDEN:
- case ControlsState.WINDOW_PICKER:
- return FitMode.SINGLE;
- case ControlsState.APP_GRID:
- if (opt.WS_ANIMATION && opt.SHOW_WS_TMB)
- return FitMode.ALL;
- else
- return FitMode.SINGLE;
- default:
- return FitMode.SINGLE;
- }
-}