Skip to content

osx: keep window creation on-screen during display reconfiguration - #21543

Merged
MrJul merged 4 commits into
AvaloniaUI:mainfrom
brianwphamSF:fix/macos-window-offscreen-placement
Aug 19, 2026
Merged

osx: keep window creation on-screen during display reconfiguration#21543
MrJul merged 4 commits into
AvaloniaUI:mainfrom
brianwphamSF:fix/macos-window-offscreen-placement

Conversation

@brianwphamSF

Copy link
Copy Markdown
Contributor

What does the pull request do?

On macOS a newly created NSWindow is given a content rect anchored at Cocoa (0,0), and the screen used to size it is found with .First(m => m.Bounds.Contains(Position)). Both assume the primary screen sits at the origin and that some screen contains the window's position.

During a display reconfiguration that does not hold:

  • a multi-monitor layout where the primary screen is not at the origin, or
  • a wake-from-sleep / Spaces race where CGMainDisplayID() briefly returns 0 and the primary screen's frame.origin goes negative.

In those cases the window is created off-screen, and WindowImplBase.Init throws Sequence contains no matching element, aborting window construction.

What is the updated behavior?

  • WindowBaseImpl::CreateNSWindow anchors the content rect to the primary screen's actual frame.origin, so the window is created on a real screen.
  • WindowImplBase.Init uses FirstOrDefault and falls back to a default window size when no screen contains the position. The window is repositioned on the next ScreenChanged event once the display server settles (the same pattern X11Window already uses).

Related issue(s)

Part of #18895. Split out of the render-timer change in #21453 per review.

Notes

macOS-only. No behavioral change on a healthy single-monitor Mac, where the primary screen is at (0,0) and the position is contained.

Breaking changes

None.

brianwphamSF and others added 2 commits June 10, 2026 09:45
WindowBaseImpl::CreateNSWindow anchors the new NSWindow's content rect to the
primary screen's frame.origin. The primary screen is at Cocoa (0,0) on a
healthy Mac, but can be offset (often negative) while the display server is
mid-reconfiguration -- e.g. CGMainDisplayID() briefly returns 0 after
wake-from-sleep -- or on multi-monitor layouts where the primary is not at the
origin. Anchoring keeps the window on a real screen so it is positioned
on-screen and its flipped Position lands inside a Screen.Bounds.

See AvaloniaUI#18895.

Co-authored-by: Cursor <cursoragent@cursor.com>
When locating the screen that sizes a new window, fall back to a default size
if AppKit reports no screens -- or none whose bounds contain the last-known
position -- during a display reconfiguration. The window is repositioned on the
next ScreenChanged event once the display server settles.

See AvaloniaUI#18895.

Co-authored-by: Cursor <cursoragent@cursor.com>
@avaloniaui-bot

Copy link
Copy Markdown

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

@MrJul MrJul added bug os-macos backport-candidate-12.0.x Consider this PR for backporting to 12.0 branch labels Jun 11, 2026
@MrJul MrJul added backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch and removed backport-candidate-12.0.x Consider this PR for backporting to 12.0 branch labels Jul 9, 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.

The changes look good, but please trim down the overly verbose AI comments as per our AI guidelines.

Edit: I've edited one and removed the other.

@avaloniaui-bot

Copy link
Copy Markdown

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

@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.

LGTM!

@MrJul
MrJul enabled auto-merge August 19, 2026 15:06
@MrJul
MrJul added this pull request to the merge queue Aug 19, 2026
@avaloniaui-bot

Copy link
Copy Markdown

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

Merged via the queue into AvaloniaUI:main with commit 4918bdf Aug 19, 2026
9 checks passed
MrJul added a commit to MrJul/Avalonia that referenced this pull request Sep 2, 2026
…valoniaUI#21543)

* osx: anchor new windows to the primary screen origin

WindowBaseImpl::CreateNSWindow anchors the new NSWindow's content rect to the
primary screen's frame.origin. The primary screen is at Cocoa (0,0) on a
healthy Mac, but can be offset (often negative) while the display server is
mid-reconfiguration -- e.g. CGMainDisplayID() briefly returns 0 after
wake-from-sleep -- or on multi-monitor layouts where the primary is not at the
origin. Anchoring keeps the window on a real screen so it is positioned
on-screen and its flipped Position lands inside a Screen.Bounds.

See AvaloniaUI#18895.

Co-authored-by: Cursor <cursoragent@cursor.com>

* osx: keep window construction resilient when no screen contains it

When locating the screen that sizes a new window, fall back to a default size
if AppKit reports no screens -- or none whose bounds contain the last-known
position -- during a display reconfiguration. The window is repositioned on the
next ScreenChanged event once the display server settles.

See AvaloniaUI#18895.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Less verbose comments

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
@MrJul MrJul added backported-12.1.x and removed backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants