Skip to content

Preserve waybar tray icons on theme changes#6020

Open
oqlatulesba3 wants to merge 5 commits into
basecamp:masterfrom
oqlatulesba3:fix/waybar-restart-preserves-tray
Open

Preserve waybar tray icons on theme changes#6020
oqlatulesba3 wants to merge 5 commits into
basecamp:masterfrom
oqlatulesba3:fix/waybar-restart-preserves-tray

Conversation

@oqlatulesba3
Copy link
Copy Markdown

@oqlatulesba3 oqlatulesba3 commented Jun 2, 2026

Problem

omarchy-restart-waybar kills waybar with pkill -9, which briefly releases waybar's org.kde.StatusNotifierWatcher D-Bus role. When waybar restarts and re-acquires the role, some apps don't re-register their tray icons, leaving the user without tray access for those apps until they're manually restarted.

This is most visible when running omarchy theme set, which calls omarchy-restart-waybar for every theme change.

When called from a shell environment without DBUS_SESSION_BUS_ADDRESS or XDG_RUNTIME_DIR (a TTY, an SSH session, a service with no graphical context), pkill -x waybar still kills the running waybar, but setsid uwsm-app -- waybar then fails to start a replacement, leaving the user with no bar at all.

Fix

Make the in-place CSS hot-reload the opt-in (for theme-set, which wants to avoid the tray flicker), and a full restart with SNI re-registration the default (so picking "Restart Waybar" from the menu actually applies any pending config.jsonc change).

  • bin/omarchy-restart-waybar:

    • Aborts with exit 0 and a stderr note if no D-Bus session is available. File-system side effects of omarchy-theme-set still apply; only the in-place restart is skipped.
    • Default behaviour: kill waybar, start a fresh one, then wait for the new watcher to acquire its bus name and call RegisterStatusNotifierItem on every org.kde.StatusNotifierItem-* name on the session bus. This restores tray icons from SNI clients that don't watch the watcher name and re-register themselves (notably ProtonVPN, which is non-compliant with the SNI spec in this respect).
    • With OMARCHY_WAYBAR_HOT_RELOAD=1: re-trigger the file monitor by adding a fresh /* reloaded: ... */ comment to the first @import in style.css. Falls back to a full restart if the file is missing or doesn't start with @import.
    • Drops the -9 from pkill so waybar can release the watcher name cleanly.
  • bin/omarchy-theme-set: Now sets OMARCHY_WAYBAR_HOT_RELOAD=1 so theme changes stay flicker-free.

Why it works

For theme changes, hot-reloading style.css is enough — reload_style_on_change: true is on by default in the omarchy waybar config, so waybar re-parses the CSS (including its @import of the current theme file) without destroying any modules. The D-Bus watcher role is never released, so apps don't need to re-register.

For config changes (the menu's "Restart Waybar" item, or after editing config.jsonc in the editor), a full restart is needed. The post-restart re-registration step uses busctl to find every SNI item already on the session bus and tell the new watcher about it. Compliant clients ignore duplicate registrations.

Related

Testing

  1. Start waybar with the default config and a tray app.
  2. Run omarchy theme set <any-theme> — tray icons should stay visible (no flicker).
  3. Edit ~/.config/waybar/config.jsonc (e.g. change height), save, then pick Update → Process → Waybar from the omarchy menu — the bar should restart with the new config applied and all tray icons reappear within ~2s.
  4. From a TTY (Ctrl+Alt+F2) or a stripped shell (env -i HOME=$HOME PATH=/usr/bin bash -c omarchy-restart-waybar): the script should print omarchy-restart-waybar: no D-Bus session; skipping waybar restart and leave the running waybar alone.

omarchy-restart-waybar previously killed waybar with pkill -9, which
briefly released the org.kde.StatusNotifierWatcher D-Bus role. Apps
with buggy SNI implementations (e.g. some VPN clients) did not
re-register after the new waybar claimed the role, leaving the user
without tray access.

By default, hot-reload waybar's CSS via the reload_style_on_change
file monitor. This re-applies the CSS without tearing down modules,
so the watcher role is preserved and all tray icons stay visible.

Set OMARCHY_WAYBAR_FULL_RESTART=1 to force a full restart (used by
omarchy-refresh-waybar, which needs a real restart for config
changes to take effect).

Also drop the -9 from pkill so waybar can release the watcher name
cleanly when a full restart is needed.
Copilot AI review requested due to automatic review settings June 2, 2026 07:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…accumulation

Some SNI clients (notably ProtonVPN) do not watch for the
org.kde.StatusNotifierWatcher name and re-register themselves when it
re-appears. After a full waybar restart, the new watcher's
RegisteredStatusNotifierItems list is missing these items, and the
tray icons disappear until the apps are restarted manually.

After pkill+setsid, wait for the new watcher to acquire its bus name
and then walk org.kde.StatusNotifierItem-* names on the session bus,
calling RegisterStatusNotifierItem on each via busctl. Compliant
clients ignore duplicate registrations.

Also tighten the CSS hot-reload sed: the previous pattern matched only
up to the first semicolon, so each call appended a new timestamp
comment instead of replacing the previous one, leaving an ever-growing
trail of /* reloaded: ... */ on line 1.
When invoked from an environment without DBUS_SESSION_BUS_ADDRESS or
XDG_RUNTIME_DIR (e.g. a TTY, SSH session, or service with no graphical
context), pkill -x waybar still kills the running waybar but
setsid uwsm-app -- waybar then fails to start a replacement, leaving
the user with no bar at all. Same for busctl --user in the re-registration
loop.

Detect the missing session early and exit 0 with a brief stderr note.
This makes omarchy-theme-set safe to run from a stripped shell (the
file changes still apply; only the in-place restart is skipped).
Copilot AI review requested due to automatic review settings June 2, 2026 08:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

…eload

The menu entry omarchy restart waybar (Update > Process > Waybar) and
the inline call from omarchy-theme-set both invoke omarchy-restart-waybar
without the env var, so a single default has to serve both. The old
default (hot-reload) silently dropped config.jsonc changes whenever the
user picked the menu, because CSS hot-reload does not re-parse
config.jsonc.

Flip the default: a bare omarchy-restart-waybar now does a full restart
plus the SNI re-registration step so the tray comes back. omarchy-theme-set
sets OMARCHY_WAYBAR_HOT_RELOAD=1 to opt into the in-place CSS reload that
preserves the tray.
With the new design where omarchy-restart-waybar's default IS a full
restart, the OMARCHY_WAYBAR_FULL_RESTART=1 prefix on this call became
a no-op. Drop it to match the actual semantics.
Copilot AI review requested due to automatic review settings June 2, 2026 09:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

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