summaryrefslogtreecommitdiffstats
path: root/extensions/46/vertical-workspaces/lib/iconGrid.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/46/vertical-workspaces/lib/iconGrid.js')
-rw-r--r--extensions/46/vertical-workspaces/lib/iconGrid.js185
1 files changed, 134 insertions, 51 deletions
diff --git a/extensions/46/vertical-workspaces/lib/iconGrid.js b/extensions/46/vertical-workspaces/lib/iconGrid.js
index 87f6adb..f0c6b18 100644
--- a/extensions/46/vertical-workspaces/lib/iconGrid.js
+++ b/extensions/46/vertical-workspaces/lib/iconGrid.js
@@ -11,14 +11,16 @@
'use strict';
import St from 'gi://St';
+import GLib from 'gi://GLib';
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as IconGrid from 'resource:///org/gnome/shell/ui/iconGrid.js';
let Me;
let opt;
// added sizes for better scaling
-const IconSize = {
+export const IconSize = {
LARGEST: 256,
224: 224,
208: 208,
@@ -34,8 +36,6 @@ const IconSize = {
TINY: 48,
};
-const PAGE_WIDTH_CORRECTION = 100;
-
export const IconGridModule = class {
constructor(me) {
Me = me;
@@ -90,39 +90,52 @@ const IconGridCommon = {
return layoutManager.getItemsAtPage(page);
},
+ _shouldUpdateGrid(width, height) {
+ if (this.layoutManager._isFolder)
+ return false;
+ else if (this._currentMode === -1)
+ return true;
+
+ // Update if page size changed
+ // Page dimensions may change within a small range
+ const range = 5;
+ return (Math.abs(width - (this._gridForWidth ?? 0)) > range) ||
+ (Math.abs(height - (this._gridForHeight ?? 0)) > range);
+ },
+
_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)
+ if (!this._shouldUpdateGrid(width, height))
return;
+
+ this._gridForWidth = width;
+ this._gridForHeight = height;
+
+ this._updateDefaultIconSize();
const { pagePadding } = this.layout_manager;
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const iconPadding = 51 * scaleFactor;
- // provided width is usually about 100px wider in horizontal orientation with prev/next page indicators
- const pageIndicatorCompensation = opt.ORIENTATION ? 0 : PAGE_WIDTH_CORRECTION;
+ const itemPadding = 55;
- width -= pagePadding.left + pagePadding.right + pageIndicatorCompensation;
- width *= opt.APP_GRID_PAGE_WIDTH_SCALE;
+ // pagePadding is already affected by the scaleFactor
+ width -= pagePadding.left + pagePadding.right;
height -= pagePadding.top + pagePadding.bottom;
- // store grid max dimensions for icon size algorithm
+ // Sync with _findBestIconSize()
+ this.layoutManager._gridSizeChanged = true;
this.layoutManager._gridWidth = width;
this.layoutManager._gridHeight = height;
- width -= 80; // compensation for default padding
- height -= 80;
+ // All widgets are affected by the scaleFactor so we need to apply it also on the page size
+ width /= scaleFactor;
+ height /= scaleFactor;
const spacing = opt.APP_GRID_SPACING;
- // set the icon size as fixed to avoid changes in size later
const iconSize = opt.APP_GRID_ICON_SIZE > 0 ? opt.APP_GRID_ICON_SIZE : opt.APP_GRID_ICON_SIZE_DEFAULT;
- // this.layout_manager.fixedIconSize = iconSize;
- const itemSize = iconSize * scaleFactor + iconPadding;
- // if this._gridModes.length === 1, custom grid should be used
- // if (iconSize > 0 && this._gridModes.length > 1) {
+ const itemSize = iconSize + itemPadding;
let columns = opt.APP_GRID_COLUMNS;
let rows = opt.APP_GRID_ROWS;
// 0 means adaptive size
let unusedSpaceH = -1;
- let unusedSpaceV = -1;
if (!columns) {
// calculate #columns + 1 without spacing
columns = Math.floor(width / itemSize) + 1;
@@ -133,6 +146,7 @@ const IconGridCommon = {
unusedSpaceH = width - columns * itemSize - (columns - 1) * spacing;
}
}
+ let unusedSpaceV = -1;
if (!rows) {
rows = Math.floor(height / itemSize) + 1;
while (unusedSpaceV < 0) {
@@ -142,9 +156,45 @@ const IconGridCommon = {
}
this._gridModes = [{ columns, rows }];
- // }
-
+ this._currentMode = -1;
this._setGridMode(0);
+ this.layoutManager.updateIconSize();
+ // Call _redisplay() from timeout to avoid allocation errors
+ GLib.idle_add(GLib.PRIORITY_LOW, () =>
+ Main.overview._overview.controls.appDisplay._redisplay()
+ );
+ },
+
+ _updateDefaultIconSize() {
+ // Reduce default icon size for low resolution screens and high screen scales
+ if (Me.Util.monitorHasLowResolution()) {
+ opt.APP_GRID_ICON_SIZE_DEFAULT = opt.APP_GRID_ACTIVE_PREVIEW && !opt.APP_GRID_USAGE ? 128 : 64;
+ opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT = 64;
+ } else {
+ opt.APP_GRID_ICON_SIZE_DEFAULT = opt.APP_GRID_ACTIVE_PREVIEW && !opt.APP_GRID_USAGE ? 192 : 96;
+ }
+ },
+
+ // Workaround for the upstream bug
+ // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5753
+ // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5240
+ // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6892
+ // The appGridLayout._currentPage is not updated when the page is changed in the grid
+ // For example, when user navigates app icons using a keyboard
+ // Related issues open on GNOME's gitlab:
+ after_goToPage() {
+ if (this._delegate._appGridLayout._currentPage !== this._currentPage)
+ this._delegate._appGridLayout.goToPage(this._currentPage);
+ },
+
+ // Workaround for the upstream bug
+ // https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7700
+ // Return INVALID target if x or y is out of the grid view to prevent pages[page] undefined error (horizontal orientation only)
+ getDropTarget(x, y) {
+ if (x < 0 || y < 0)
+ return [0, 0, 0]; // [0, 0, DragLocation.INVALID]
+ const layoutManager = this.layout_manager;
+ return layoutManager.getDropTarget(x, y, this._currentPage);
},
};
@@ -153,45 +203,45 @@ const IconGridLayoutCommon = {
if (this.fixedIconSize !== -1)
return this.fixedIconSize;
+ if (!this._isFolder && !this._gridSizeChanged)
+ return this._iconSize;
+ this._gridSizeChanged = false;
+
+
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
const nColumns = this.columnsPerPage;
const nRows = this.rowsPerPage;
- // if grid is not defined return default icon size
+ // If grid is not defined, return default icon size
if (nColumns < 1 && nRows < 1) {
- let iconSize;
- if (this._isFolder)
- iconSize = opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT;
- else
- iconSize = opt.APP_GRID_ICON_SIZE_DEFAULT;
-
- return iconSize;
+ return this._isFolder
+ ? opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT
+ : opt.APP_GRID_ICON_SIZE_DEFAULT;
}
- const columnSpacingPerPage = /* opt.APP_GRID_SPACING*/ 1 * (nColumns - 1);
- const rowSpacingPerPage = /* opt.APP_GRID_SPACING*/ 1 * (nRows - 1);
- const iconPadding = 55 * scaleFactor;
+ const spacing = this._isFolder
+ ? opt.APP_GRID_FOLDER_SPACING
+ : opt.APP_GRID_SPACING;
- const paddingH = this._isFolder ? this.pagePadding.left + this.pagePadding.right : 0;
- const paddingV = this._isFolder ? this.pagePadding.top + this.pagePadding.bottom : 0;
+ const columnSpacingPerPage = spacing * (nColumns - 1);
+ const rowSpacingPerPage = spacing * (nRows - 1);
+ const itemPadding = 55;
+
+ const width = (this._gridWidth ? this._gridWidth : this._pageWidth) / scaleFactor;
+ let height = (this._gridHeight ? this._gridHeight : this._pageHeight) / scaleFactor;
- 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 (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 and fully adaptive folder grids, the whole range is for the main grid with active folders
- if (this._isFolder && opt.APP_GRID_FOLDER_ADAPTIVE && opt.APP_GRID_FOLDER_ICON_SIZE < 0)
+ // Limit max icon size for folders and fully adaptive folder grids, the whole range is for the main grid with active folders
+ if (this._isFolder && opt.APP_GRID_FOLDER_ICON_SIZE < 0)
iconSizes = iconSizes.slice(iconSizes.indexOf(opt.APP_GRID_FOLDER_ICON_SIZE_DEFAULT), -1);
else if (this._isFolder)
iconSizes = iconSizes.slice(iconSizes.indexOf(IconSize.LARGE), -1);
- else if (opt.APP_GRID_ADAPTIVE && opt.APP_GRID_ICON_SIZE < 0)
+ else if (opt.APP_GRID_ICON_SIZE < 0)
iconSizes = iconSizes.slice(iconSizes.indexOf(opt.APP_GRID_ICON_SIZE_DEFAULT), -1);
let sizeInvalid = false;
@@ -202,7 +252,7 @@ const IconGridLayoutCommon = {
firstItem.icon.setIconSize(size);
const [firstItemWidth] = firstItem.get_preferred_size();
- const itemSize = firstItemWidth;
+ const itemSize = firstItemWidth / scaleFactor;
if (itemSize < size)
sizeInvalid = true;
@@ -211,19 +261,16 @@ const IconGridLayoutCommon = {
}
if (!firstItem || sizeInvalid) {
- usedWidth = (size + iconPadding) * nColumns;
- usedHeight = (size + iconPadding) * nRows;
+ usedWidth = (size + itemPadding) * nColumns;
+ usedHeight = (size + itemPadding) * nRows;
}
const emptyHSpace =
- width - usedWidth - columnSpacingPerPage - paddingH;
- // this.pagePadding.left - this.pagePadding.right;
+ width - usedWidth - columnSpacingPerPage;
const emptyVSpace =
- height - usedHeight - rowSpacingPerPage - paddingV;
- // this.pagePadding.top - this.pagePadding.bottom;
+ height - usedHeight - rowSpacingPerPage;
- if (emptyHSpace >= 0 && emptyVSpace >= 0) {
+ if (emptyHSpace >= 0 && emptyVSpace >= 0)
return size;
- }
}
return IconSize.TINY;
@@ -266,7 +313,9 @@ const IconGridLayoutCommon = {
page = this._findBestPageToAppend(page);
this._shouldEaseItems = true;
- this._container.add_child(item);
+
+ if (!this._container.get_children().includes(item))
+ this._container.add_child(item);
this._addItemToPage(item, page, index);
},
@@ -331,6 +380,28 @@ const IconGridLayoutCommon = {
this._relocateSurplusItems(pageIndex);
},
+ _relocateSurplusItems(pageIndex) {
+ // Avoid recursion during relocations in _redisplay()
+ if (this._skipRelocateSurplusItems)
+ return;
+
+ const visiblePageItems = this._pages[pageIndex].visibleChildren;
+ const itemsPerPage = this.columnsPerPage * this.rowsPerPage;
+
+ // No overflow
+ if (visiblePageItems.length <= itemsPerPage)
+ return;
+
+ const nExtraItems = visiblePageItems.length - itemsPerPage;
+ for (let i = 0; i < nExtraItems; i++) {
+ const overflowIndex = visiblePageItems.length - i - 1;
+ const overflowItem = visiblePageItems[overflowIndex];
+
+ this._removeItemData(overflowItem);
+ this._addItemToPage(overflowItem, pageIndex + 1, 0);
+ }
+ },
+
_findBestPageToAppend(startPage) {
const itemsPerPage = this.columnsPerPage * this.rowsPerPage;
@@ -343,4 +414,16 @@ const IconGridLayoutCommon = {
return this._pages.length;
},
+
+ updateIconSize() {
+ const iconSize = this._findBestIconSize();
+ if (this._iconSize !== iconSize) {
+ this._iconSize = iconSize;
+
+ for (const child of this._container)
+ child.icon.setIconSize(iconSize);
+
+ this.notify('icon-size');
+ }
+ },
};