Skip to content

fix: prevent WM-managed windows from being embedded during tray restart recovery#59

Draft
Copilot wants to merge 4 commits intomasterfrom
copilot/fix-stalonetray-app-visibility
Draft

fix: prevent WM-managed windows from being embedded during tray restart recovery#59
Copilot wants to merge 4 commits intomasterfrom
copilot/fix-stalonetray-app-visibility

Conversation

Copy link

Copilot AI commented Mar 8, 2026

find_unmanaged_icons() was embedding regular application windows (including fullscreen ones) as blank tray icons on restart. The _NET_CLIENT_LIST filter silently became a no-op on any WM that doesn't maintain that property — XInternAtom(..., True) returns None, the fetch is skipped, nclient_wins stays 0, and every window with _XEMBED_INFO passes through unchecked.

Changes

  • Add ICCCM WM_STATE filter (primary gate): Skip any window whose WM_STATE is NormalState (1) or IconicState (3). Per the system tray protocol, tray icons must be in WithdrawnState (0) and are never managed by the WM. This works universally — EWMH and non-EWMH WMs alike (i3, bspwm, sway, openbox, etc.).
  • Retain _NET_CLIENT_LIST filter (supplementary): Still useful as a secondary guard on EWMH-compliant WMs; now clearly documented as such rather than the sole line of defence.
/* skip windows the WM is actively managing */
if (xa_wm_state != None) {
    rc = x11_get_window_prop32(..., xa_wm_state, xa_wm_state,
                               &wm_state_data, &wm_state_len);
    if (rc == SUCCESS && wm_state_data != NULL) {
        long wm_state = ((long *)wm_state_data)[0];
        XFree(wm_state_data);
        if (wm_state != WithdrawnState) continue;
    }
}
Original prompt

This section details on the original issue you should resolve

<issue_title>Stalonetray does not find apps in system tray after restarting stalone tray</issue_title>
<issue_description>Describe the bug
If you close stalonetray during a session, say to reconfigure it, and then start it again, apps that were on system tray are no longer visible. However restarting the app, say discord, allows it to show back up in the system tray.

To Reproduce
Steps to reproduce the buggy behavior (even if intermittent):

  1. Use bswpwm
  2. Launch any app that appears in system tray
  3. close then reopen stalonetray
  4. See error

Expected behavior
I expect stalonetray to show apps that are in the system tray

Log files
I dont have stalonetray built from source so I currently have no log trace option.
</issue_description>

Comments on the Issue (you are @copilot in this section)

@d3adb5 Can you produce logs now that #58 was merged, @Tomaqa? By the way, if you build stalonetray from source using `meson setup --debug`, you should be able to use the `trace` log level even with 1.0.1.

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

When stalonetray is restarted, applications previously in the system tray
should re-dock by responding to the MANAGER broadcast. However, some apps
miss this broadcast (race conditions, implementation bugs, etc.), leaving
the tray empty after restart.

Add find_unmanaged_icons() which scans all top-level windows at startup for
_XEMBED_INFO property. Any such window is an XEMBED client that wants to be
embedded; passing it to add_icon() recovers icons that failed to re-request
docking. This mirrors the existing find_unmanaged_chromium_icons() approach.

The function is called in tray_main() after xembed_init() (which initialises
xa_xembed_info), right after the Chromium-specific scan.

Co-authored-by: d3adb5 <8827351+d3adb5@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix stalonetray app visibility after restart Recover tray icons with _XEMBED_INFO on startup to fix missing icons after restart Mar 8, 2026
The previous implementation scanned ALL top-level windows for _XEMBED_INFO
with no filtering, causing blank icons to appear from GTK plug windows,
browser XEMBED clients, and other WM-managed windows that carry the property.

Two filters are now applied, mirroring the logic in kde_tray_init():

1. old_selection_owner != None guard: skip the scan entirely on a fresh
   start. Tray clients respond to the MANAGER broadcast on their own; the
   recovery scan is only needed when restarting over an existing session.

2. _NET_CLIENT_LIST exclusion: fetch the list of WM-managed windows and
   skip any window present in it. System tray icons are not managed by the
   WM and therefore never appear in _NET_CLIENT_LIST, while the spurious
   windows that caused blank icons do.

Co-authored-by: d3adb5 <8827351+d3adb5@users.noreply.github.com>
Copilot AI changed the title Recover tray icons with _XEMBED_INFO on startup to fix missing icons after restart Recover unembedded tray icons on restart without false positives Mar 8, 2026
…d on restart

The _NET_CLIENT_LIST filter silently did nothing on WMs that don't maintain
that root property (non-EWMH tiling WMs, etc.): XInternAtom(..., True)
returns None when the atom was never interned, nclient_wins stays 0, and
every window with _XEMBED_INFO — including fullscreen app windows — passed
through and was embedded as a blank tray icon.

Add an ICCCM WM_STATE check as an additional guard. Every ICCCM-compliant
WM sets WM_STATE to NormalState (1) or IconicState (3) on every window it
manages. System tray icons must be in WithdrawnState (0) and are not
managed by the WM. If WM_STATE is absent the window is also unmanaged.

This check works with all WMs, including non-EWMH tiling WMs (i3, bspwm,
sway, etc.), and acts as the primary gate. _NET_CLIENT_LIST is retained as
a supplementary EWMH filter.

Co-authored-by: d3adb5 <8827351+d3adb5@users.noreply.github.com>
Copilot AI changed the title Recover unembedded tray icons on restart without false positives fix: prevent WM-managed windows from being embedded during tray restart recovery Mar 9, 2026
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.

Stalonetray does not find apps in system tray after restarting stalone tray

2 participants