Skip to content

Send a synthetic UnmapNotify when hiding an X11 window - #22135

Merged
MrJul merged 1 commit into
AvaloniaUI:mainfrom
liuclare:fix-x11-withdraw-on-hide
Sep 4, 2026
Merged

Send a synthetic UnmapNotify when hiding an X11 window#22135
MrJul merged 1 commit into
AvaloniaUI:mainfrom
liuclare:fix-x11-withdraw-on-hide

Conversation

@liuclare

@liuclare liuclare commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

What does the pull request do?

DefaultWindowMode.Hide() calls XUnmapWindow only. ICCCM 4.1.4 requires a client withdrawing a top-level window to also send a synthetic UnmapNotify to the root window, which this PR now does.

What is the current behavior?

When the window manager has already unmapped the window because it is minimized, XUnmapWindow on an already-unmapped window generates no event, so the window manager never learns that the client withdrew the window and keeps it listed as managed and iconic.

For an application that hides to a tray icon, calling Hide() on a minimized window therefore leaves a stale taskbar entry. Activating that entry maps the window again, but Window.Hide() has already called StopRendering() and MapNotify does not restart it, so the frame comes back empty. Closing it again does nothing either, since Window.Hide() returns early on !_shown. Only Show() from the tray icon restores the content.

What is the updated/expected behavior with this PR?

Hide() withdraws the window in that case: WM_STATE is removed and the window leaves _NET_CLIENT_LIST, so no stale entry remains.

Tested on KDE Plasma 6.6.6 under XWayland, with a minimal window whose Closing handler calls Hide(), and with an unmodified v2rayN 7.24.7 build with only Avalonia.X11.dll replaced. Hiding a mapped window still withdraws it correctly: the real and the synthetic UnmapNotify both arrive, which is the sequence ICCCM describes. mutter and native X11 sessions were not tested.

How was the solution implemented (if it's not obvious)?

The event is built and sent the same way SendNetWMMessage does. Override-redirect windows are skipped, since the window manager does not manage them.

No unit test: the behavior depends on the window manager's response, which the X11 test setup does not cover.

Fixed issues

Related to #18148. That report also covers rendering not restarting when the system maps a hidden window, which is not addressed here.


The patch, the testing described above and this description were produced with AI assistance (Claude Code) on my machine. I have reviewed the change and reproduced both the original problem and the fix myself.

ICCCM 4.1.4 requires a client withdrawing a top-level window to also send
a synthetic UnmapNotify to the root window. XUnmapWindow alone generates
no event when the window manager has already unmapped the window, leaving
a minimized window listed as managed and iconic after Hide().
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0069369-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@cla-avalonia

cla-avalonia commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator
  • All contributors have signed the CLA.

@liuclare

liuclare commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

@cla-avalonia agree

@MrJul MrJul added bug area-x11 backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Sep 3, 2026

@MrJul MrJul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good catch on ICCCM §4.1.4 not being respected.
Minimizing then hiding the window now works correctly with this PR.
LGTM!

@MrJul
MrJul added this pull request to the merge queue Sep 4, 2026
@MrJul

MrJul commented Sep 4, 2026

Copy link
Copy Markdown
Member

The patch, the testing described above and this description were produced with AI assistance (Claude Code) on my machine. I have reviewed the change and reproduced both the original problem and the fix myself.

Thank you! The AI disclaimer and manual testing are rare enough these days :)

Merged via the queue into AvaloniaUI:main with commit 486058f Sep 4, 2026
11 checks passed
@liuclare

liuclare commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the quick review and for testing it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-x11 backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants