Fix native child viewports aborting fullscreen on macOS#8286
Open
smoe wants to merge 2 commits into
Open
Conversation
When a native child viewport was opened while the root window was in native fullscreen, macOS renegotiated the active Space: the new window flickered, could get pulled into Split View tiling (ending up unintentionally fullscreen itself), and could abort the root's fullscreen state (emilk#8259). Fix this by marking such windows as NSWindowCollectionBehaviorFullScreenAuxiliary, which lets them be shown on the same Space as a fullscreen window. Since winit 0.30 does not expose the collection behavior, and it must be set before the window is first ordered on screen, the window is created hidden, marked via objc2-app-kit, and then shown. - New `ViewportBuilder::with_fullscreen_auxiliary` (macOS only): `true` = always auxiliary, `false` = never, unset = auto (auxiliary iff created while the app has a fullscreen window on the active Space and the viewport does not itself request fullscreen). - `ViewportCommand::Fullscreen(true)` / `SetMonitor` clear the flag first, since auxiliary windows cannot enter native fullscreen. Verified on macOS with both the wgpu and glow backends: the root stays fullscreen and the child shows on top of it; behavior with a windowed root is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Preview is being built... Preview will be available at https://egui-pr-preview.github.io/pr/8286-macos-fullscreen-auxiliary-viewports View snapshot changes at kitdiff |
Contributor
|
Related: This PR handles native child-window creation on an existing fullscreen Space, while #8280 addresses viewport lifecycle and rendering failures during native fullscreen transitions. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Opening a native child viewport (
show_viewport_deferred/show_viewport_immediate) while the root window is in macOS native fullscreen makes AppKit renegotiate the active Space: the child flickers, can get pulled into Split View tiling — ending up unintentionally fullscreen itself — and the root's fullscreen state can be aborted. Reproduced with both the wgpu and glow backends; window state captured via AppKit before the fix:Fix
AppKit's mechanism for windows accompanying a fullscreen window (palettes, inspectors) is
NSWindowCollectionBehaviorFullScreenAuxiliary. winit 0.30 doesn't expose it, and it must be set before the window is first ordered on screen — but winit shows windows during creation. Soegui-winitnow creates affected windows hidden, sets the collection behavior viaobjc2-app-kit, and then orders them front (respecting the builder'svisible/active). Same pattern as the existing iOSsafe_area.rspolyfill; I have proposed the API upstream (rust-windowing/winit#4614) so most of the newmacos.rsmodule can be deleted when egui moves to winit 0.31.New API:
ViewportBuilder::with_fullscreen_auxiliary(macOS only):true: always mark the window as fullscreen-auxiliary,false: never,Trade-off: an auxiliary window cannot itself enter native fullscreen.
ViewportCommand::Fullscreen(true)/SetMonitortherefore clear the flag before toggling, so runtime fullscreen requests on child viewports keep working.After the fix (same repro):
Testing
NSWindowstate) on macOS 15 / Darwin 25.5.0, run against bothwgpuandglowbackends: root stays fullscreen, child shows on the same Space with the auxiliary bit set.cargo test -p egui -p egui-winit, clippy (debug + release, all features),cargo doc -D warnings,lint.py,cargo fmtall pass.Notes