display: fill the area beside the camera housing in full screen - #7885
Merged
Merged
Conversation
A full screen VM on a Mac with a camera housing loses the strip beside it, which the guest could otherwise use. Two things keep a native full screen window out of that strip: AppKit insets the full screen frame and the window server covers the strip with an opaque menu bar. There is no public way around either, and a borderless window is not an option because macOS would no longer treat the VM as a full screen app. Add an opt-in preference (macOS 27+) and a window subclass that returns the whole screen as the full screen frame and makes the menu bar of its own full screen space transparent while it is not revealed. When the menu bar is revealed it looks and behaves as it always did. It works within the App Sandbox. All of it relies on private AppKit and SkyLight symbols. None of them are used or hooked until the option is enabled and a window enters full screen, so the window is unaffected by changes to them otherwise. They are looked up at runtime by name and checked against the signatures we expect, so no private symbol is linked or compiled into the binary and if any are missing or different the window behaves like any other. The window server reveals the menu bar as soon as the pointer is over the strip, which would make that area of the guest display unusable. It is instead only revealed when the pointer reaches the top edge of the screen: until then the space uses presentation options that hide the menu bar, which also hides the Dock. AppKit applies the options of the space again when it changes spaces, so they are kept up to date. The window server only lets a window cover the strip if it does so from the moment it enters the full screen space, which shapes the rest: - Every frame query in the transition is answered with the whole screen, and later requests to resize the window are ignored, because asking for any frame again, even the current one, moves it out of the strip. Our window controllers do so to fit the guest display, and AppKit does when the space becomes active again. - Once the strip has been left, such as when tiled in Split View, it is not asked for again until full screen is next entered. - The QEMU window is no longer resized to fit a display the guest just changed while the transition to full screen is still running. The flag the controller kept for that is only set once the transition is over, so the window ended up taller than the screen and lost the strip. - AppKit parks the auto hidden toolbar behind the menu bar, or over our content while the menu bar is hidden, so it is hidden along with it. The window stands down when tiled, on a screen without a camera housing, and when the menu bar is set to always be visible in full screen. Terminal windows do not opt in. Resolves #6183 Assisted-by: Claude:claude-fable-5-1 Assisted-by: Claude:claude-opus-5
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.
On a Mac with a camera housing, a full screen VM loses the strip of screen beside it: AppKit insets the full screen frame and the window server covers the inset area with an opaque menu bar. This adds an opt-in preference (Settings → Display, macOS 27+) that gives that area to the guest display instead.
The window keeps using native full screen — it is not a borderless window, so macOS still treats the VM as a full screen app, and Mission Control, Spaces and Split View behave as before.
The menu bar is normally revealed as soon as the pointer is anywhere over that strip, which would make the area unusable for the guest. With the option on it is only revealed when the pointer reaches the very top edge of the screen; until then the space hides the menu bar (and with it the Dock), and clicks in the strip go to the VM. Once revealed, the menu bar and toolbar look and behave as they always did.
Everything this relies on is private AppKit and SkyLight API. None of it is used or hooked until the option is enabled and a window enters full screen, so with the option off the window behaves exactly as before. The symbols are looked up at runtime by name and checked against the signatures we expect, so nothing private is linked or compiled into the binary, and if any of them is missing or different the window falls back to normal full screen. It also stands down when tiled in Split View, on a screen without a camera housing, and when the menu bar is set to always be visible in full screen. Terminal windows do not opt in.
Resolves #6183
Testing: Tested by a human on macOS 27.0, MacBook Air M3. The author acknowledges that this change has been tested and/or reviewed by a human in accordance with UTM's AI contribution guidelines.
Tested with the option on and off, on QEMU (fixed resolution UEFI guest, and Windows 11 with SPICE tools which changes its resolution) and on an Apple backend VM: entering and leaving full screen, Split View, switching spaces away and back, revealing and hiding the menu bar, and clicking in the strip.