Skip to content

fix: enable fullscreen support for all titleBarStyle options#358

Open
raymondreaming wants to merge 1 commit intoblackboardsh:mainfrom
raymondreaming:fix/fullscreen-collection-behavior
Open

fix: enable fullscreen support for all titleBarStyle options#358
raymondreaming wants to merge 1 commit intoblackboardsh:mainfrom
raymondreaming:fix/fullscreen-collection-behavior

Conversation

@raymondreaming
Copy link
Copy Markdown

Screenshot 2026-04-02 at 10 27 04 AM

Problem

BrowserWindow.setFullScreen(true) silently fails when titleBarStyle is "hidden". The call completes without error, but the window does not enter fullscreen and isFullScreen() returns false.

This prevents apps using custom window chrome from offering native macOS fullscreen.

const win = new BrowserWindow({
  title: "App",
  url: "https://example.com",
  titleBarStyle: "hidden",
  frame: { x: 100, y: 100, width: 800, height: 600 },
});

win.setFullScreen(true);
console.log(win.isFullScreen()); // false

Root Cause

Traced through package/src/native/macos/nativeWrapper.mm. Three factors combine:

1. createNSWindowWithFrameAndStyle never sets collectionBehavior

The window is allocated with initWithContentRect:styleMask:backing:defer:screen: but setCollectionBehavior: is never called. macOS requires NSWindowCollectionBehaviorFullScreenPrimary for [window toggleFullScreen:nil] to be honored. Without it, AppKit silently drops the call.

2. titleBarStyle: "hidden" removes NSWindowStyleMaskTitled

BrowserWindow.ts maps "hidden" to Titled: false, FullSizeContentView: true. Untitled windows cannot enter fullscreen without explicit collectionBehavior configuration.

3. setWindowFullScreen logic is correct but ineffective

// nativeWrapper.mm ~line 7217
extern "C" void setWindowFullScreen(NSWindow *window, bool fullScreen) {
    dispatch_sync(dispatch_get_main_queue(), ^{
        bool isCurrentlyFullScreen = ([window styleMask] & NSWindowStyleMaskFullScreen) != 0;
        if (fullScreen != isCurrentlyFullScreen) {
            [window toggleFullScreen:nil]; // no-op without fullScreenPrimary
        }
    });
}

The state check and toggle logic are correct. The call is simply ignored at the AppKit level because the window lacks the required collection behavior.

Approaches Investigated

Approach Result
setFullScreen(true) with titleBarStyle: "hidden" Silently ignored
styleMask: { FullScreen: true } at creation Broken layout. NSWindowStyleMaskFullScreen (bit 14) is a read-only state flag, not a configuration option. Setting it at creation produces a corrupted window state with a gray title bar remnant.
Menu item with role: "toggleFullScreen" Same underlying issue. toggleFullScreen: is ignored regardless of invocation method.
titleBarStyle: "hiddenInset" Works. Preserves Titled, which allows fullscreen. Serves as a viable workaround but forces native traffic light visibility.

Fix

Set collectionBehavior after window allocation in createNSWindowWithFrameAndStyle:

[window setCollectionBehavior:
    NSWindowCollectionBehaviorFullScreenPrimary |
    NSWindowCollectionBehaviorMoveToActiveSpace];

Applied at creation time rather than lazily in setWindowFullScreen so behavior is consistent across all fullscreen triggers (programmatic API, application menu, native window button).

No API changes. No new configuration. Enables fullscreen for all titleBarStyle values.

Verification

Tested on macOS Sequoia (Darwin 25.3.0, arm64), Electrobun v1.16.0:

Scenario Before After
"hidden" + setFullScreen(true) No-op Enters native fullscreen
"hidden" + setFullScreen(false) N/A Exits correctly
"hidden" + isFullScreen() Always false Reflects actual state
"hiddenInset" Works No regression
"default" Works No regression

setFullScreen() silently fails when titleBarStyle is "hidden" because
createNSWindowWithFrameAndStyle never sets collectionBehavior on the
window. macOS requires NSWindowCollectionBehaviorFullScreenPrimary for
toggleFullScreen: to work — without it, the call is silently ignored.

Add setCollectionBehavior with fullScreenPrimary after window creation
so setFullScreen() works regardless of titleBarStyle.

Fixes: setFullScreen() no-op with titleBarStyle "hidden"
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.

1 participant