Skip to content

display: fill the area beside the camera housing in full screen - #7885

Merged
osy merged 1 commit into
mainfrom
feature/fullscreen-notch
Sep 20, 2026
Merged

osy merged 1 commit into
mainfrom
feature/fullscreen-notch

Conversation

@osy

@osy osy commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

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.

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
@osy osy added this to the v5.0 milestone Sep 20, 2026
@osy
osy merged commit 9d00a54 into main Sep 20, 2026
54 checks passed
@osy
osy deleted the feature/fullscreen-notch branch September 20, 2026 03:45
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.

"true" fullscreen on macbook with notch

1 participant