Skip to content

Fix fullscreen new windows opening in current Space - #2345

Merged
austinywang merged 3 commits into
mainfrom
issue-2315-fullscreen-new-window
Mar 30, 2026
Merged

austinywang merged 3 commits into
mainfrom
issue-2315-fullscreen-new-window

Conversation

@austinywang

@austinywang austinywang commented Mar 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • prevent newly created main windows from joining an existing native fullscreen Space
  • add a regression test asserting created main windows disallow fullscreen tiling

Testing

  • ./scripts/reload.sh --tag issue-2315-fullscreen-new-window --launch

Fixes #2315


Summary by cubic

New main windows created from a native fullscreen window no longer join that Space. We temporarily disable fullscreen tiling during creation (when not restoring a session) so they open on a separate Space, then restore normal Split View support. Fixes #2315.

  • Bug Fixes
    • Temporarily set .fullScreenDisallowsTiling only when opened from a native fullscreen source and no session restore is in progress; remove it on the next run loop tick after the window appears.
    • Added and stabilized tests using a debug-only override to simulate a fullscreen source; confirmed default windows still allow Split View and the temporary opt-out is cleared.

Written for commit ab47673. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes

    • Newly created main windows opened from a native macOS fullscreen window now temporarily opt out of fullscreen tiling to avoid layout interference; the restriction is removed shortly after the window appears.
  • Tests

    • Added automated tests verifying the temporary exclusion from fullscreen tiling is applied when appropriate, is cleared afterward, and that test-state overrides are reset between tests.

@vercel

vercel Bot commented Mar 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Mar 30, 2026 8:11am

@coderabbitai

coderabbitai Bot commented Mar 30, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

AppDelegate.createMainWindow now separates resolution of sourceContext and sourceWindow, derives existing frame from sourceWindow?.frame, computes a sourceWindowIsNativeFullScreen check (with a DEBUG override), and temporarily sets .fullScreenDisallowsTiling on the new NSWindow when appropriate, removing it asynchronously after activation.

Changes

Cohort / File(s) Summary
AppDelegate window creation
Sources/AppDelegate.swift
Refactored source resolution into sourceContext + sourceWindow; derive existingFrame from sourceWindow?.frame; compute sourceWindowIsNativeFullScreen (DEBUG override added); set shouldTemporarilyDisallowFullScreenTiling only when no session snapshot and native fullscreen; apply .fullScreenDisallowsTiling to new window before showing and remove it asynchronously after activation.
Fullscreen-behavior tests
cmuxTests/AppDelegateShortcutRoutingTests.swift
Added tests asserting default absence of .fullScreenDisallowsTiling, and that when debugCreateMainWindowSourceIsNativeFullScreenOverride = true the flag is present initially and removed after runloop pumping; tearDown() resets the debug override.

Sequence Diagram(s)

sequenceDiagram
    participant AppDelegate
    participant SourceWindow
    participant NewWindow
    participant MainQueue

    AppDelegate->>SourceWindow: resolve sourceContext and sourceWindow
    AppDelegate->>AppDelegate: derive existingFrame from sourceWindow?.frame
    alt source is native fullscreen and no session snapshot
        AppDelegate->>NewWindow: create NSWindow and add .fullScreenDisallowsTiling
    else
        AppDelegate->>NewWindow: create NSWindow without flag
    end
    AppDelegate->>NewWindow: showAndMakeKeyAndOrderFront / activate
    AppDelegate->>MainQueue: DispatchQueue.main.async { remove .fullScreenDisallowsTiling }
    MainQueue->>NewWindow: remove .fullScreenDisallowsTiling (if still present)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nudged a flag with careful paws,

then hopped away to mind my cause.
For a moment bold, the tiling stayed,
then disappeared as sunlight played.
New windows land in proper laws. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly addresses the main change: preventing fullscreen windows from joining the current Space, which is the core bug fix described in the PR.
Description check ✅ Passed The description includes all required sections: Summary (what changed and why), Testing (testing instructions), and mentions the linked issue. However, the demo video section and Review Trigger checklist items are not explicitly completed.
Linked Issues check ✅ Passed The code changes directly address issue #2315 by preventing new windows from joining a native fullscreen Space through temporary .fullScreenDisallowsTiling, and adds regression tests as required.
Out of Scope Changes check ✅ Passed All changes are within scope: fullscreen window behavior fix, debug override for testing, and regression test coverage directly address the objectives of issue #2315.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-2315-fullscreen-new-window

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@greptile-apps

greptile-apps Bot commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a bug where newly created main windows would join an existing native fullscreen Space instead of opening on a separate Desktop. The fix adds .fullScreenDisallowsTiling to each new window's collectionBehavior immediately after construction in createMainWindow(), mirroring Terminal.app's behavior. A companion unit test creates a real window and asserts the flag is present at runtime.

Key observations:

  • The one-line fix is correct: .insert(_:) is additive and applyWindowDecorations (called later) does not touch collectionBehavior, so the flag is never overwritten.
  • The test verifies observable runtime behavior (the collectionBehavior bitmask on the live NSWindow), which is consistent with the project's test quality policy.
  • The test and the fix are in a single commit, violating the project's two-commit regression test policy (CLAUDE.md / AGENTS.md). CI cannot confirm the test was red before the fix was applied.

Confidence Score: 5/5

Safe to merge; the fix is minimal and correct with no risk of regression.

The only finding is a P2 process issue (single-commit instead of two-commit structure for the regression test). The production code change is a one-liner that correctly adds a flag, and the applyWindowDecorations path was confirmed to not reset collectionBehavior. No logic, syntax, or data-integrity issues found.

No files require special attention for correctness; the regression test commit structure in cmuxTests/AppDelegateShortcutRoutingTests.swift is the only item worth addressing before merge.

Important Files Changed

Filename Overview
Sources/AppDelegate.swift Inserts .fullScreenDisallowsTiling into the new window's collectionBehavior immediately after construction, before any decoration pass. The change is minimal, additive (uses .insert), and applyWindowDecorations does not touch collectionBehavior, so the flag is safe from later clobbering.
cmuxTests/AppDelegateShortcutRoutingTests.swift Adds a well-structured regression test that creates a real window and asserts the .fullScreenDisallowsTiling flag is present at runtime. The only concern is that the test and fix land in a single commit, violating the project's two-commit regression test policy.

Sequence Diagram

sequenceDiagram
    participant User
    participant AppDelegate
    participant NSWindow

    User->>AppDelegate: Cmd+Shift+N (createMainWindow)
    AppDelegate->>NSWindow: init(contentRect:styleMask:backing:defer:)
    Note over NSWindow: Default collectionBehavior<br/>(e.g. .managed)
    AppDelegate->>NSWindow: collectionBehavior.insert(.fullScreenDisallowsTiling)
    Note over NSWindow: Now disallows joining<br/>existing fullscreen Space
    AppDelegate->>NSWindow: applyWindowDecorations(to:)
    Note over NSWindow: collectionBehavior unchanged<br/>(decorations only touch traffic lights)
    AppDelegate->>NSWindow: orderFront / makeKeyAndOrderFront
    NSWindow-->>User: New window opens on separate Space
Loading

Reviews (1): Last reviewed commit: "Fix fullscreen new windows opening in cu..." | Re-trigger Greptile

Comment on lines +101 to +121
func testCreateMainWindowDisallowsFullScreenTiling() {
guard let appDelegate = AppDelegate.shared else {
XCTFail("Expected AppDelegate.shared")
return
}

let windowId = appDelegate.createMainWindow()
defer {
closeWindow(withId: windowId)
}

guard let window = window(withId: windowId) else {
XCTFail("Expected test window")
return
}

XCTAssertTrue(
window.collectionBehavior.contains(.fullScreenDisallowsTiling),
"Main windows should opt out of fullscreen tiling so new windows do not join an existing fullscreen Space"
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Single commit violates two-commit regression test policy

Both the failing test and the fix are bundled in the same commit (cade637b). CLAUDE.md (and AGENTS.md) require a two-commit structure for regression tests so that CI can confirm the test actually fails without the fix:

Commit 1: Add the failing test only (no fix). CI should go red.
Commit 2: Add the fix. CI should go green.

As submitted, there's no way to verify in the PR's commit history that testCreateMainWindowDisallowsFullScreenTiling would have caught the bug, since the test and the fix land together. Please rebase into two commits so the Commits tab on GitHub shows a red check on commit 1 and green on commit 2.

Context Used: CLAUDE.md (source)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
cmuxTests/AppDelegateShortcutRoutingTests.swift (1)

102-122: Make the non-fullscreen regression test deterministic.

This test currently depends on ambient window state. If the resolved source window is fullscreen, the assertion can fail for environment reasons rather than a real regression. Force the source condition explicitly in-test.

Proposed tweak
 func testCreateMainWindowDoesNotDisallowFullScreenTilingByDefault() {
     guard let appDelegate = AppDelegate.shared else {
         XCTFail("Expected AppDelegate.shared")
         return
     }
+    appDelegate.debugCreateMainWindowSourceIsNativeFullScreenOverride = false
+    defer {
+        appDelegate.debugCreateMainWindowSourceIsNativeFullScreenOverride = nil
+    }

     let windowId = appDelegate.createMainWindow()
     defer {
         closeWindow(withId: windowId)
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmuxTests/AppDelegateShortcutRoutingTests.swift` around lines 102 - 122, The
test can flake if an ambient window is fullscreen—make it deterministic by
explicitly forcing a non-fullscreen source before calling createMainWindow():
obtain AppDelegate.shared (or NSApp.windows) and ensure any candidate source
window is not fullscreen (exit fullscreen or clear full-screen
collectionBehavior) or create a new dummy non-fullscreen window and use that as
the resolved source, then call createMainWindow(), proceed with window(withId:)
and the existing assertions; target symbols: AppDelegate.shared,
createMainWindow(), window(withId:), closeWindow(withId:).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cmuxTests/AppDelegateShortcutRoutingTests.swift`:
- Around line 102-122: The test can flake if an ambient window is
fullscreen—make it deterministic by explicitly forcing a non-fullscreen source
before calling createMainWindow(): obtain AppDelegate.shared (or NSApp.windows)
and ensure any candidate source window is not fullscreen (exit fullscreen or
clear full-screen collectionBehavior) or create a new dummy non-fullscreen
window and use that as the resolved source, then call createMainWindow(),
proceed with window(withId:) and the existing assertions; target symbols:
AppDelegate.shared, createMainWindow(), window(withId:), closeWindow(withId:).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1e2e6803-f68f-424e-ad32-514d8fa0de68

📥 Commits

Reviewing files that changed from the base of the PR and between 7ef25ea and ab47673.

📒 Files selected for processing (2)
  • Sources/AppDelegate.swift
  • cmuxTests/AppDelegateShortcutRoutingTests.swift

@austinywang
austinywang merged commit 63dd728 into main Mar 30, 2026
15 checks passed
bn-l pushed a commit to bn-l/cmux that referenced this pull request Apr 3, 2026
* Fix fullscreen new windows opening in current Space

* works

* Stabilize fullscreen tiling regression test

This branch was successfully deployed

1 active deployment
Preview — ab476733 Deployed Mar 30, 2026 by vercel[bot]
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.

New window opens on top of existing fullscreen window instead of a new Space

1 participant