From a557f0eea04455dc1f0d48932957a1f7b9bb57d8 Mon Sep 17 00:00:00 2001 From: Steve <48870638+svan71@users.noreply.github.com> Date: Thu, 23 Jul 2026 19:13:09 -0400 Subject: [PATCH 1/2] Fix trash full/empty icon never updating: resolve state before renderer paints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updateIcon() ran after the renderer already read icon_name, so the full/empty flip always lagged one animation tick — and the debounced loop usually ended before a second tick, leaving the icon stale. Split the state flip into updateIconState(), called at the top of the renderer loop; positioning (clock/calendar overlays) stays post-paint. Also: guard ignoreRelease() (removed from PopupMenuManager in GNOME 50, threw on every dock context menu), and empty-trash.sh now uses 'gio trash --empty' so the trash:// monitor gets proper events. --- animator.js | 1 + apps/empty-trash.sh | 8 +++++++- dockItems.js | 3 ++- services.js | 24 ++++++++++++++++-------- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/animator.js b/animator.js index e3d19be..0e15bff 100644 --- a/animator.js +++ b/animator.js @@ -548,6 +548,7 @@ export let Animator = class { animateIcons.forEach((icon) => { if (!icon._icon) return; // dock.renderArea.opacity = 100; + dock.extension.services?.updateIconState(icon); { let icon_name = icon._icon.icon_name; let app_name = diff --git a/apps/empty-trash.sh b/apps/empty-trash.sh index 3585cb5..4fac69e 100755 --- a/apps/empty-trash.sh +++ b/apps/empty-trash.sh @@ -1,2 +1,8 @@ #!/usr/bin/sh -rm -rf ~/.local/share/Trash/* +# gio emits proper trash:// change events (raw rm can miss the monitor); +# fall back to rm where gio is unavailable +if command -v gio >/dev/null 2>&1; then + gio trash --empty +else + rm -rf ~/.local/share/Trash/* +fi diff --git a/dockItems.js b/dockItems.js index db66ad3..9ae1336 100644 --- a/dockItems.js +++ b/dockItems.js @@ -60,7 +60,8 @@ class DockItemMenu extends PopupMenu.PopupMenu { popup() { this.open(BoxPointer.PopupAnimation.FULL); - this._menuManager.ignoreRelease(); + // removed in GNOME 50's PopupMenuManager + this._menuManager.ignoreRelease?.(); } } diff --git a/services.js b/services.js index 792400b..bb9071b 100644 --- a/services.js +++ b/services.js @@ -683,6 +683,22 @@ export const Services = class { } //! this is out of place - services should only do background process - no rendering + // Resolve state-dependent icon names (trash full/empty) — must run BEFORE + // the renderer reads icon_name so the same frame paints the new state; + // updateIcon() runs after paint and would lag one animation tick. + updateIconState(item) { + let icon = item?._icon; + if (!icon || !icon.icon_name) { + return; + } + if (this.extension.trash_icon && icon.icon_name.startsWith('user-trash')) { + let new_icon = this.trashFull ? 'user-trash-full' : 'user-trash'; + if (new_icon != icon.icon_name) { + icon.icon_name = new_icon; + } + } + } + updateIcon(item, settings) { if (!item) { return; @@ -696,14 +712,6 @@ export const Services = class { // todo move dots and badges here? - // the trash - if (this.extension.trash_icon && icon.icon_name.startsWith('user-trash')) { - let new_icon = this.trashFull ? 'user-trash-full' : 'user-trash'; - if (new_icon != icon.icon_name) { - icon.icon_name = new_icon; - } - } - // clock if (icon.icon_name == 'org.gnome.clocks') { if (this.extension.clock_icon) { From a2432f43880032c4ef9a4f7a6f6b6c04e36f53ed Mon Sep 17 00:00:00 2001 From: Steve <48870638+svan71@users.noreply.github.com> Date: Thu, 23 Jul 2026 19:33:03 -0400 Subject: [PATCH 2/2] Fix Empty Trash: remove leftover rm -rf override, force gvfs volume-trash enumeration setupTrashIcon pointed trash_action at empty-trash.sh but an upstream leftover block immediately overwrote it with rm -rf on the home Trash dir, so volume trash (NAS mounts) was never emptied and no gvfs events fired. Also drop Terminal=true from the action and pre-enumerate trash:// in empty-trash.sh so lazily-discovered .Trash-$UID dirs get emptied too. --- apps/empty-trash.sh | 3 +++ services.js | 6 +----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/empty-trash.sh b/apps/empty-trash.sh index 4fac69e..2d87099 100755 --- a/apps/empty-trash.sh +++ b/apps/empty-trash.sh @@ -2,6 +2,9 @@ # gio emits proper trash:// change events (raw rm can miss the monitor); # fall back to rm where gio is unavailable if command -v gio >/dev/null 2>&1; then + # gvfs discovers mounted-volume .Trash-$UID dirs lazily; enumerate first + # so --empty reaches volume trash too, not just the home trash + gio list trash:// >/dev/null 2>&1 gio trash --empty else rm -rf ~/.local/share/Trash/* diff --git a/services.js b/services.js index bb9071b..834c5b0 100644 --- a/services.js +++ b/services.js @@ -218,12 +218,8 @@ export const Services = class { let open_app = 'nautilus --select'; let trash_action = `${extension_path}/apps/empty-trash.sh`; - { - let fn = Gio.File.new_for_path('.local/share/Trash'); - trash_action = `rm -rf "${fn.get_path()}"`; - } - let content = `[Desktop Entry]\nVersion=1.0\nTerminal=false\nType=Application\nName=Trash\nExec=${open_app} trash:///\nIcon=user-trash\nStartupWMClass=trash-dash2dock-lite\nActions=trash\n\n[Desktop Action trash]\nName=Empty Trash\nExec=${trash_action}\nTerminal=true\n`; + let content = `[Desktop Entry]\nVersion=1.0\nTerminal=false\nType=Application\nName=Trash\nExec=${open_app} trash:///\nIcon=user-trash\nStartupWMClass=trash-dash2dock-lite\nActions=trash\n\n[Desktop Action trash]\nName=Empty Trash\nExec=${trash_action}\nTerminal=false\n`; const [, etag] = fn.replace_contents( content, null,