Skip to content

X11: re-read _NET_WORKAREA on WM PropertyNotify#21651

Open
lambgoesbaa wants to merge 1 commit into
AvaloniaUI:masterfrom
lambgoesbaa:x11-workarea-property-refresh
Open

X11: re-read _NET_WORKAREA on WM PropertyNotify#21651
lambgoesbaa wants to merge 1 commit into
AvaloniaUI:masterfrom
lambgoesbaa:x11-workarea-property-refresh

Conversation

@lambgoesbaa

Copy link
Copy Markdown

What does the pull request do?

Fixes a bug on X11 where popups and menus are positioned against a stale work area
after the screen resolution is increased while the application is running. The work
area keeps its pre-resize (smaller) value until the app is restarted, so popups near a
screen edge clamp to the old bounds.

The cause is a two-event race between RandR and the window manager:

  1. RandR RRScreenChangeNotify fires first. Randr15ScreensImpl invalidates its cache
    and the screens are rebuilt with the new Bounds, reading _NET_WORKAREA via
    X11Screen.UpdateWorkArea() at that moment.
  2. The window manager (Mutter, KWin, …) recomputes _NET_WORKAREA and emits a
    root-window PropertyNotify a short time later.

At step 1 the WM has not recomputed the work area yet, so the stale value is cached.
The screen provider only listens for RRScreenChangeNotify and never for the
_NET_WORKAREA PropertyNotify, so it never re-reads. On a resolution decrease the
old work area still fits inside the new bounds, which is why only increases are visibly
broken.

What is the current behavior?

On an X11/EWMH desktop, increase the screen resolution while the app is running, then
open a menu or popup near a screen edge. The popup is clamped against the old, smaller
work area instead of the new screen size. Restarting the app clears it.

What is the updated/expected behavior with this PR?

After a resolution change, the work area refreshes when the window manager publishes the
updated _NET_WORKAREA, and popups use the correct, current work area with no restart.

To test (X11 session, e.g. GNOME/Mutter):

  1. Run a sample app (e.g. ControlCatalog).
  2. Increase the screen resolution while it is running.
  3. Open a menu/popup near a screen edge — it should use the new work area.
  4. Decrease the resolution again — still correct.

Verified manually on Ubuntu 26.04 (GNOME/Mutter): resolution increase no longer leaves
popups clamped to the old work area, and the decrease path remains correct.

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

Randr15ScreensImpl also subscribes to X11Globals.RootPropertyChanged; on a
_NET_WORKAREA change it posts the existing Changed notification, reusing the
established refresh path (OnChangedScreenChangedRefreshUpdateWorkArea).
The root window already has PropertyChangeMask and X11Globals already dispatches
RootPropertyChanged, so this adds only a delegate call and an atom comparison.
Changed is posted via Dispatcher.UIThread.Post, matching the existing RandR
OnEvent. Cache invalidation stays on the RandR path, which owns topology changes.

Checklist

  • Added unit tests (if possible)? -> The behavior is window-manager dependent and
    requires a live machine; there is no X11 test harness; was verified manually.
  • Added XML documentation to any related classes? -> N/A: only a private event handler added to an existing internal class.
  • Consider submitting a PR to https://github.com/AvaloniaUI/avalonia-docs with user documentation

Breaking changes

None.

Obsoletions / Deprecations

None.

@avaloniaui-bot

Copy link
Copy Markdown

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

@cla-avalonia

cla-avalonia commented Jun 25, 2026

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

@lambgoesbaa

Copy link
Copy Markdown
Author

@cla-avalonia agree

1 similar comment
@LucasBoulanger

Copy link
Copy Markdown

@cla-avalonia agree

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.

4 participants