diff --git a/SOURCES/0001-desktop-icons-Merge-custom-menu-entries-into-desktop.patch b/SOURCES/0001-desktop-icons-Merge-custom-menu-entries-into-desktop.patch new file mode 100644 index 0000000..ab65685 --- /dev/null +++ b/SOURCES/0001-desktop-icons-Merge-custom-menu-entries-into-desktop.patch @@ -0,0 +1,215 @@ +From 735602e7d3cfea688f741082d8cd8abb97c6b0d4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 19 Mar 2026 16:07:46 +0100 +Subject: [PATCH 1/3] desktop-icons: Always add icons when backgrounds are + updated + +We currently assume that backgrounds are only updated when the +monitor setup changed, so we explicitly track that. + +However backgrounds may be updated for other reasons as well (for +example when enabling the custom-menu extension). + +So instead of making assumptions about when updateBackgrounds() +is called, hook into the function itself to recreate the icons +whenever the backgrounds are updated. +--- + extensions/desktop-icons/desktopManager.js | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/extensions/desktop-icons/desktopManager.js b/extensions/desktop-icons/desktopManager.js +index 84bd79ce..80633901 100644 +--- a/extensions/desktop-icons/desktopManager.js ++++ b/extensions/desktop-icons/desktopManager.js +@@ -45,6 +45,8 @@ const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; + + var S_IWOTH = 0x00002; + ++let updateBackgroundsOrig = null; ++ + function getDpy() { + return global.screen || global.display; + } +@@ -96,7 +98,12 @@ var DesktopManager = GObject.registerClass({ + this._writableByOthers = null; + this._rubberBandActive = false; + +- this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', () => this._recreateDesktopIcons()); ++ updateBackgroundsOrig = Main.layoutManager._updateBackgrounds; ++ Main.layoutManager._updateBackgrounds = () => { ++ updateBackgroundsOrig.call(Main.layoutManager); ++ this._recreateDesktopIcons(); ++ }; ++ + this._rubberBand = new St.Widget({ style_class: 'rubber-band' }); + this._rubberBand.hide(); + Main.layoutManager._backgroundGroup.add_child(this._rubberBand); +@@ -778,6 +785,8 @@ var DesktopManager = GObject.registerClass({ + } + + destroy() { ++ Main.layoutManager._updateBackgrounds = updateBackgroundsOrig; ++ + if (this._monitorDesktopDir) + this._monitorDesktopDir.cancel(); + this._monitorDesktopDir = null; +@@ -797,9 +806,6 @@ var DesktopManager = GObject.registerClass({ + GLib.source_remove(this._deleteChildrenId); + this._deleteChildrenId = 0; + +- if (this._monitorsChangedId) +- Main.layoutManager.disconnect(this._monitorsChangedId); +- this._monitorsChangedId = 0; + if (this._stageReleaseEventId) + global.stage.disconnect(this._stageReleaseEventId); + this._stageReleaseEventId = 0; +-- +2.53.0 + + +From bd110b928c8343e9b595cf38b97e9bc07d209879 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 19 Mar 2026 16:40:23 +0100 +Subject: [PATCH 2/3] desktop-icons: Merge custom-menu entries into desktop + background menu + +When both the desktop-icons and custom-menu extensions are enabled, +the desktop-icons extension creates its own right-click context menu +for the desktop background, bypassing the BackgroundMenu mechanism +that custom-menu hooks into. This causes the custom-menu entries to +be completely hidden when desktop-icons is active. + +This patch adds integration between the two extensions: when the +desktop background menu is created in desktop-icons, it checks if +the custom-menu extension is enabled. If so, it reads the user's +custom menu configuration (~/.entries.json) and appends those entries +below a separator at the bottom of the desktop-icons context menu. + +The integration is non-intrusive: + - If custom-menu is not enabled, no changes are visible + - If ~/.entries.json does not exist or is invalid, the menu + remains unchanged (errors are logged) + - Only affects the desktop background right-click menu, not + file icon context menus + +Resolves: RHEL-136187 +--- + extensions/desktop-icons/desktopGrid.js | 30 +++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/extensions/desktop-icons/desktopGrid.js b/extensions/desktop-icons/desktopGrid.js +index bd27e2ab..f0509595 100644 +--- a/extensions/desktop-icons/desktopGrid.js ++++ b/extensions/desktop-icons/desktopGrid.js +@@ -49,6 +49,8 @@ const Gettext = imports.gettext.domain('gnome-shell-extensions'); + + const _ = Gettext.gettext; + ++const CUSTOM_MENU_UUID = 'custom-menu@gnome-shell-extensions.gcampax.github.com'; ++const CUSTOM_MENU_CONFIG = '/.entries.json'; + + /* From NautilusFileUndoManagerState */ + var UndoStatus = { +@@ -319,6 +321,32 @@ var DesktopGrid = class { + this._syncUndoRedo(); + } + ++ _appendCustomMenuEntries(menu) { ++ const ext = Main.extensionManager.lookup(CUSTOM_MENU_UUID); ++ if (!ext || ext.state !== ExtensionUtils.ExtensionState.ENABLED) ++ return; ++ ++ const CustomMenuConfig = ext.imports.config; ++ const configLoader = new CustomMenuConfig.Loader(); ++ ++ try { ++ configLoader.loadConfig(GLib.get_home_dir() + CUSTOM_MENU_CONFIG); ++ } catch (e) { ++ log('desktop-icons: Error loading custom menu entries: ' + e.message); ++ return; ++ } ++ ++ if (configLoader.entries.length === 0) ++ return; ++ ++ menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ ++ for (let i in configLoader.entries) { ++ const item = configLoader.entries[i].createItem(); ++ menu.addMenuItem(item); ++ } ++ } ++ + _createDesktopBackgroundMenu() { + let menu = new PopupMenu.PopupMenu(Main.layoutManager.dummyCursor, + 0, St.Side.TOP); +@@ -361,6 +389,8 @@ var DesktopGrid = class { + ); + this._pasteMenuItem.setSensitive(false); + ++ this._appendCustomMenuEntries(menu); ++ + return menu; + } + +-- +2.53.0 + + +From b37776779b713b19129a664cfc913488bdff0226 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 19 Mar 2026 16:32:51 +0100 +Subject: [PATCH 3/3] desktop-icons: Recreate desktop menu on custom-menu + changes + +We now add custom menu entries to the background menu when the custom-menu +extension is enabled. That means that the menu contents now depend on +the extension state, so we should make sure to update the menu as +necessary. +--- + extensions/desktop-icons/desktopGrid.js | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/extensions/desktop-icons/desktopGrid.js b/extensions/desktop-icons/desktopGrid.js +index f0509595..2457d0c7 100644 +--- a/extensions/desktop-icons/desktopGrid.js ++++ b/extensions/desktop-icons/desktopGrid.js +@@ -131,6 +131,14 @@ var DesktopGrid = class { + this._grid.connect('key-press-event', this._onKeyPress.bind(this)); + + this._grid.connect('allocation-changed', () => Extension.desktopManager.scheduleReLayoutChildren()); ++ ++ this._extensionStateChangedId = ++ Main.extensionManager.connect('extension-state-changed', (mgr, ext) => { ++ // the custom-menu extension influences the menu contents when enabled, ++ // so recreate the menu on state changes ++ if (ext.uuid === CUSTOM_MENU_UUID) ++ this._addDesktopBackgroundMenu(); ++ }); + } + + _onKeyPress(actor, event) { +@@ -194,6 +202,10 @@ var DesktopGrid = class { + this._bgManager.backgroundActor.disconnect(this._bgDestroyedId); + this._bgDestroyedId = 0; + this._bgManager = null; ++ ++ if (this._extensionStateChangedId) ++ Main.extensionManager.disconnect(this._extensionStateChangedId); ++ this._extensionStateChangedId = 0; + } + + _onNewFolderClicked() { +@@ -557,6 +569,9 @@ var DesktopGrid = class { + } + + _addDesktopBackgroundMenu() { ++ if (this.actor._desktopBackgroundMenu) ++ this.actor._desktopBackgroundMenu.destroy(); ++ + this.actor._desktopBackgroundMenu = this._createDesktopBackgroundMenu(); + this.actor._desktopBackgroundManager = new PopupMenu.PopupMenuManager({ actor: this.actor }); + this.actor._desktopBackgroundManager.addMenu(this.actor._desktopBackgroundMenu); +-- +2.53.0 + diff --git a/SOURCES/scrollable-workspace-menu.patch b/SOURCES/scrollable-workspace-menu.patch new file mode 100644 index 0000000..ddd6d43 --- /dev/null +++ b/SOURCES/scrollable-workspace-menu.patch @@ -0,0 +1,147 @@ +From e8665261d2e99b3cfaa4d784bd47f95a5fdc3b52 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 3 Mar 2026 12:48:13 +0100 +Subject: [PATCH 1/3] workspace-indicator: Use section box to iterate items + +Menu items are added to a menu's box, so it is more correct to +use that to access items, even when for menu sections the box +is also used as the menu's actor. + +Part-of: +--- + extensions/workspace-indicator/workspaceIndicator.js | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js +index eb31fc62..af4c69bf 100644 +--- a/extensions/workspace-indicator/workspaceIndicator.js ++++ b/extensions/workspace-indicator/workspaceIndicator.js +@@ -595,7 +595,7 @@ class WorkspacesMenu extends PopupMenu.PopupMenu { + const {workspaceManager} = global; + const {nWorkspaces} = workspaceManager; + +- const section = this._workspacesSection.actor; ++ const section = this._workspacesSection.box; + while (section.get_n_children() < nWorkspaces) { + const item = new EditableMenuItem(); + item.connect('activate', (o, event) => { +@@ -624,7 +624,7 @@ class WorkspacesMenu extends PopupMenu.PopupMenu { + + _updateWorkspaceLabels() { + const items = +- this._workspacesSection.actor.get_children().map(c => c._delegate); ++ this._workspacesSection.box.get_children().map(c => c._delegate); + items.forEach( + (item, i) => (item.label.text = Meta.prefs_get_workspace_name(i))); + } +@@ -634,7 +634,7 @@ class WorkspacesMenu extends PopupMenu.PopupMenu { + const active = workspaceManager.get_active_workspace_index(); + + const items = +- this._workspacesSection.actor.get_children().map(c => c._delegate); ++ this._workspacesSection.box.get_children().map(c => c._delegate); + items.forEach((item, i) => { + item.setOrnament(i === active + ? PopupMenu.Ornament.CHECK +-- +2.53.0 + + +From 6f2fba8eba7f09834448a5588b825235213314a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 2 Mar 2026 18:49:16 +0100 +Subject: [PATCH 2/3] workspace-indicator: Support scrolling in workspace menu + +While we should always have enough screen estate to fit a reasonable +number of workspaces, the number can go up to 36 where we are pretty +much guaranteed to run out of space. + +Support those less common cases by making the workspace list scrollable. + +Part-of: +--- + .../workspace-indicator/workspaceIndicator.js | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/extensions/workspace-indicator/workspaceIndicator.js b/extensions/workspace-indicator/workspaceIndicator.js +index af4c69bf..287fa13c 100644 +--- a/extensions/workspace-indicator/workspaceIndicator.js ++++ b/extensions/workspace-indicator/workspaceIndicator.js +@@ -6,6 +6,7 @@ const Main = imports.ui.main; + const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; + const Tweener = imports.ui.tweener; ++const { ensureActorVisibleInScrollView } = imports.misc.util; + + const Signals = imports.signals; + +@@ -548,6 +549,16 @@ class WorkspacesMenu extends PopupMenu.PopupMenu { + this.actor.connect('destroy', () => this._onDestroy()); + + this._workspacesSection = new PopupMenu.PopupMenuSection(); ++ ++ // make the section scrollable to avoid growing indefinitely ++ const scrollView = new St.ScrollView({ ++ style_class: 'vfade', ++ hscrollbar_policy: St.PolicyType.NEVER, ++ }); ++ scrollView.add_actor(this._workspacesSection.box); ++ scrollView._delegate = this._workspacesSection; ++ this._workspacesSection.actor = scrollView; ++ + this.addMenuItem(this._workspacesSection); + + this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); +@@ -612,6 +623,11 @@ class WorkspacesMenu extends PopupMenu.PopupMenu { + this._desktopSettings.set_strv('workspace-names', + [...newNames, ...oldNames.slice(nLabels)]); + }); ++ item.connect('active-changed', (i, active) => { ++ const view = this._workspacesSection.actor; ++ if (active) ++ ensureActorVisibleInScrollView(view, item.actor); ++ }); + this._workspacesSection.addMenuItem(item); + } + +-- +2.53.0 + + +From 05615be8a57199d3137692bb9c4537437001628f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 18 Mar 2026 14:04:34 +0100 +Subject: [PATCH 3/3] window-list: Fix flipping menu arrow + +The `updateArrowSide()` method changes the effective arrow side, +but not the "user arrow side" that tracks the explicitly requested +side. + +This breaks scrolling the workspaces menu, because when checking +whether the menu needs flipping due to size constraints, it does +not fit on either side and boxpointer reverts to the originally +requested side. + +This is a shell issue[0], but we can work around it to fix the +immediate issue without a shell update. + +[0] https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/4120 +--- + extensions/window-list/extension.js | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js +index 37b5ea09..d1342898 100644 +--- a/extensions/window-list/extension.js ++++ b/extensions/window-list/extension.js +@@ -1243,6 +1243,7 @@ class BottomWorkspaceIndicator extends WorkspaceIndicator { + return; + + this.menu.actor.updateArrowSide(St.Side.BOTTOM); ++ this.menu.actor._userArrowSide = St.Side.BOTTOM; + this.menu.actor.remove_style_class_name('panel-menu'); + } + }); +-- +2.53.0 + diff --git a/SPECS/gnome-shell-extensions.spec b/SPECS/gnome-shell-extensions.spec index 4ec7c8c..02a8aca 100644 --- a/SPECS/gnome-shell-extensions.spec +++ b/SPECS/gnome-shell-extensions.spec @@ -6,7 +6,7 @@ Name: gnome-shell-extensions Version: 3.32.1 -Release: 49%{?dist} +Release: 52%{?dist} Summary: Modify and extend GNOME Shell functionality and behavior Group: User Interface/Desktops @@ -66,6 +66,8 @@ Patch0037: dash-to-panel-attention-indicator.patch Patch0038: improve-workspace-names.patch Patch0039: 0001-dash-to-panel-Consider-range-around-edges-for-dwelli.patch Patch0040: 0001-dash-to-panel-Don-t-create-main-panel-without-a-moni.patch +Patch0041: scrollable-workspace-menu.patch +Patch0042: 0001-desktop-icons-Merge-custom-menu-entries-into-desktop.patch %description GNOME Shell Extensions is a collection of extensions providing additional and @@ -581,6 +583,18 @@ cp $RPM_SOURCE_DIR/gnome-classic.desktop $RPM_BUILD_ROOT%{_datadir}/xsessions %changelog +* Thu Mar 19 2026 Tomas Pelka - 3.32.1-52 +- Merge custom-menu entries into desktop-icons background menu + Resolves: RHEL-136187 + +* Wed Mar 18 2026 Florian Müllner - 3.32.1-51 +- Fix menu flip in window-list + Related: RHEL-143030 + +* Tue Mar 03 2026 Florian Müllner - 3.32.1-50 +- Support scrolling in workspace menu + Resolves: RHEL-143030 + * Mon Jan 26 2026 Florian Müllner - 3.32.1-49 - Fix style regressions in GNOME classic Resolves: RHEL-136283