Skip to content

fix: add TrayRecoveryService with bidirectional SNI dedup (Go server)#2137

Open
Dimariqe wants to merge 3 commits intoAvengeMedia:masterfrom
Dimariqe:fix/icons-system-tray-disappeared-go-impl
Open

fix: add TrayRecoveryService with bidirectional SNI dedup (Go server)#2137
Dimariqe wants to merge 3 commits intoAvengeMedia:masterfrom
Dimariqe:fix/icons-system-tray-disappeared-go-impl

Conversation

@Dimariqe
Copy link
Copy Markdown

@Dimariqe Dimariqe commented Apr 3, 2026

Go server: add TrayRecoveryService with bidirectional SNI dedup

Go-side implementation of the TrayRecoveryService introduced in #2117.

What

New trayrecovery package (core/internal/server/trayrecovery/) that
re-registers lost system tray icons after resume from suspend using
native DBus calls (godbus/dbus/v5) instead of shelling out to bash.

How it works

  1. On startup (3 s delay) and on PrepareForSleep true→false
    transition from loginctl, the service scans the session bus for
    unregistered SNI items.
  2. Every registered item (well-known name or :1.xxx) is resolved to a
    canonical connection ID, building a unified registeredConnIDs set.
    This prevents duplicates in both directions — same logic as the QML
    version from fix: tray icons duplicating and disappearing after session restore #2117.
  3. Well-known names (DinoX, nm-applet, etc.) are probed sequentially
    at /StatusNotifierItem and /org/ayatana/NotificationItem/$SHORT
    with a 300 ms timeout.
  4. Connection IDs (Vesktop, Electron apps) are probed in parallel
    (batches of 30, 150 ms timeout) with case-insensitive SNI Id dedup.
  5. Found items are re-registered via
    org.kde.StatusNotifierWatcher.RegisterStatusNotifierItem.

Why startup scan is needed

The DMS systemd unit is Type=dbus with
BusName=org.freedesktop.Notifications. During suspend the bus name can
briefly disappear, causing systemd to kill and restart the process. The
fresh process never sees the PrepareForSleep true→false transition, so
the loginctl watcher alone is not enough. The startup scan covers this
case and is harmless on a normal boot — it finds all items already
registered and exits early.

Files changed

File Description
core/internal/server/trayrecovery/manager.go Manager lifecycle, loginctl watcher, startup scan
core/internal/server/trayrecovery/recovery.go DBus scanning and registration logic
core/internal/server/server.go Integration: init, cleanup, loginctl bridge

Dimariqe added 2 commits April 3, 2026 11:48
Add TrayRecoveryService manager that re-registers lost tray icons after
resume from suspend via native DBus scanning in the Go server.

The service resolves every registered SNI item (both well-known names and
:1.xxx connection IDs) to a canonical connection ID, building a unified
registeredConnIDs set before either scan section runs. This prevents
duplicates in both directions:

- If an app registered via well-known name, the connection-ID section
  skips its :1.xxx entry.
- If an app registered via connection ID, the well-known-name section
  skips its well-known name (checked through registeredConnIDs).
- After successfully registering via well-known name, registeredConnIDs
  is updated immediately so the connection-ID section won't probe the
  same app in the same run.

A startup scan (3 s delay) covers the common case where the DMS process
is killed during suspend and restarted by systemd (Type=dbus), so the
loginctl PrepareForSleep watcher alone is not sufficient. The startup
scan is harmless on a normal boot — it finds all items already registered
and exits early.

Go port of quickshell commit 1470aa3.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants