Tray icon never appears when the StatusNotifierHost registers after UI startup (tray availability is only checked once)
Describe the bug
opensnitch-ui creates its QSystemTrayIcon exactly once during startup
(_setup_tray(), service.py L219 in v1.7.2). Qt decides at icon creation
time which backend to use: if the StatusNotifier host is not registered
yet (IsStatusNotifierHostRegistered on org.kde.StatusNotifierWatcher),
Qt silently falls back to XEmbed — which does not exist on Wayland — and
never switches back. Result: no tray icon for the whole session, even though
a fully working tray appears a moment later.
The existing 10 s fallback (_show_gui_if_tray_not_available(), L258) only
opens the stats window; it does not retry the tray registration.
This is easy to hit with bars/shells that claim the
org.kde.StatusNotifierWatcher name early in their startup but register
the host only after their UI has finished loading (e.g. Quickshell /
DankMaterialShell). XDG autostart then races the bar on every login: the
watcher name is already on the bus, but the host isn't there yet when
opensnitch-ui performs its one-shot check.
To Reproduce
- Wayland session (Hyprland) with a Quickshell-based bar (DankMaterialShell), opensnitch-ui in XDG autostart.
- Log in. opensnitch-ui starts ~1 s before the bar's tray host is registered.
busctl --user get-property org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.kde.StatusNotifierWatcher RegisteredStatusNotifierItems→as 0although opensnitch-ui is running; no icon for the whole session.systemctl --user restartof the UI (after the bar is up) → icon appears immediately.
Expected behavior
The UI should (re-)register its tray icon when a StatusNotifier host becomes
available after startup — e.g. via a QDBusServiceWatcher on
org.kde.StatusNotifierWatcher plus re-checking IsStatusNotifierHostRegistered,
recreating the QSystemTrayIcon when the host appears. GTK apps and most
Electron apps handle this; any once-only check loses the race by design.
Workaround
systemd user drop-in for the autostart unit that delays the UI until the host is registered:
[Service]
ExecStartPre=/bin/sh -c 'for i in $(seq 100); do busctl --user get-property org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.kde.StatusNotifierWatcher IsStatusNotifierHostRegistered 2>/dev/null | grep -q true && exit 0; sleep 0.1; done'Note: waiting for the watcher name alone is not sufficient (see above) — the host property is the condition Qt actually checks.
Environment
- OpenSnitch 1.7.2 (daemon + UI), Arch Linux / CachyOS
- Qt 5.15.18, PyQt 5.15.11, running via XWayland (
xcbplatform; Wayland plugin not found) - Hyprland + DankMaterialShell 1.5.3 (Quickshell 0.3.1) as StatusNotifier watcher/host
Related: #940 (--background helps starting without a tray, but does not
make the icon appear once a tray shows up later).
Source: evilsocket/opensnitch