Skip to content

Restore native Window menu move controls - #9546

Closed
austinywang wants to merge 2 commits into
mainfrom
issue-7446-window-menu-move-to-display-fill-center
Closed

austinywang wants to merge 2 commits into
mainfrom
issue-7446-window-menu-move-to-display-fill-center

Conversation

@austinywang

@austinywang austinywang commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • keep normal cmux main windows movable so AppKit enables its native Window menu move and resize commands
  • keep background dragging disabled and preserve the shared pane-tab/folder drag suppression lifecycle
  • retain the existing frame-reconciliation safeguards for disconnected displays

Fixes #7446

Testing

  • Red regression proof at test-only commit 4ae7bec5ae: ./scripts/reload-cloud.sh xctest --tag sym7446-red-unit --only-testing cmuxTests/MainWindowDragBehaviorTests (sym7446-red-unit-6b28fc63f950) failed the two new movability assertions as expected.
  • Green focused proof at f7e50e3b24: ./scripts/reload-cloud.sh xctest --tag sym7446-green-unit with MainWindowDragBehaviorTests, FolderWindowMoveSuppressionTests, WindowMoveSuppressionHitPathTests, TitlebarInteractiveControlTests, CmuxMainWindowConstrainFrameTests, and AppDelegateWindowFrameReconcileTests (sym7446-green-unit-2fbb500a73f0) passed 33 XCTest cases and 6 Swift Testing cases.
  • Dev build: ./scripts/reload-cloud.sh --tag sym7446 --builder blacksmith --launch succeeded on Blacksmith macOS 26 run 30959268214; no local-build fallback was used. The downloaded app embedded ephemeral build commit cb3d7566d, whose parent is exact PR HEAD f7e50e3b24. /tmp/cmux-debug-sym7446.sock returned PONG. With the tagged app active and its CmuxMainWindow both main and key on Studio Display XDR, runtime inspection saw both Studio Display XDR and Built-in Retina Display, isMovable == true, isMovableByWindowBackground == false, and the tracked Window menu reported Fill, Center, Move & Resize, and Move to Built-in Retina Display all enabled. The tagged app was stopped with pkill -f "DerivedData/cmux-sym7446"; PID 82759 exited and the tagged socket was removed.
  • Localization audit: no user-facing strings or localization catalogs changed; a diff scan found no new Swift UI string candidates.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Restores native Window menu move controls for main windows by keeping them movable except during explicit suppression. Background dragging stays off, and off‑screen/titlebar safety remains in place.

  • Bug Fixes
    • Set isMovable = true unless isWindowDragSuppressed to re-enable Window > Fill, Center, and Move & Resize.
    • Keep isMovableByWindowBackground = false so titlebar drag zones control movement and pane-tab/folder drags can suppress it.
    • Preserve frame clamping and reactive reconcile to keep the titlebar reachable after display changes.
    • Updated tests to cover movability, suppression lifecycle, and frame safety.

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

Review in cubic

Summary by CodeRabbit

  • Enhancements

    • Main windows now remain natively movable while background dragging stays disabled.
    • Pane-tab and folder drag operations temporarily suppress window movement, then restore the prior behavior.
    • Window positioning remains safeguarded when display configurations change.
  • Tests

    • Updated coverage verifies native movability, controlled drag suppression, restoration behavior, and display-change positioning.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The main window now remains natively movable while background dragging stays disabled. Active pane-tab and folder drags suppress movability through shared state. Documentation and tests describe this behavior and frame reconciliation after display changes.

Changes

Window drag behavior

Layer / File(s) Summary
Native movability and drag suppression
Sources/App/CmuxMainWindow.swift, Sources/ContentView.swift, cmuxTests/TitlebarInteractiveControlTests.swift, cmuxTests/WindowAndDragTests.swift
Main-window configuration preserves native movability unless drag suppression is active. Tests cover disabled background dragging and suppression across configuration reapplication.
Frame reachability and reconciliation
Sources/App/CmuxMainWindow.swift, Sources/AppDelegate+WindowFramePolicy.swift, cmuxTests/AppDelegateWindowFrameReconcileTests.swift, cmuxTests/CmuxMainWindowConstrainFrameTests.swift
Comments describe titlebar drag handling and AppKit’s unreliable frame re-constraining for custom full-size-content windows after display changes.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BonsplitPaneTabDrag
  participant configureCmuxMainWindowDragBehavior
  participant isWindowDragSuppressed
  participant NSWindow
  BonsplitPaneTabDrag->>NSWindow: Begin pane-tab drag
  configureCmuxMainWindowDragBehavior->>isWindowDragSuppressed: Check suppression state
  isWindowDragSuppressed->>NSWindow: Preserve suppressed movability
  BonsplitPaneTabDrag->>NSWindow: Finish pane-tab drag
Loading

Possibly related PRs

Suggested reviewers: lawrencecchen

🚥 Pre-merge checks | ✅ 25
✅ Passed checks (25 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #7446 by restoring native movability while preserving drag suppression and multi-display safeguards.
Out of Scope Changes check ✅ Passed All code, documentation, and test changes support the linked issue objectives and contain no unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Cmux Swift Actor Isolation ✅ Passed Production diff keeps window configuration @MainActor and changes only movability logic/comments; no new models, protocols, Sendable references, or background UI access. Changed tests are @MainActor.
Cmux Swift Blocking Runtime ✅ Passed The PR diff adds no blocking or timing primitive. Production changes only movability and comments; existing ContentView asyncAfter calls are unchanged, and test changes are deterministic.
Cmux Browser Automation Off-Main ✅ Passed The commit changes only window movement/frame-policy comments and tests; it adds or moves no browser.* socket command, WebKit wait, worker route, or browser policy test.
Cmux Expensive Synchronous Load ✅ Passed The PR adds only window movability and documentation changes; production additions contain no agent-history loader, file scan, JSON parse, transcript, or JSONL operation.
Cmux Cache Substitution Correctness ✅ Passed The diff changes NSWindow movability plus comments/tests only; it does not replace authoritative reads in persistence, history, undo, or snapshot paths. Suppression state is transient AppKit state.
Cmux No Hacky Sleeps ✅ Passed The PR changes only Swift source and Swift test files; it introduces no covered TypeScript, JavaScript, shell, or build/runtime-script sleeps or timers.
Cmux Algorithmic Complexity ✅ Passed The production diff adds only an O(1) suppression-state lookup and a boolean assignment; no scalable collection scan or hot-path algorithm changed. Other executable changes are test-only.
Cmux Swift Concurrency ✅ Passed The Swift diff adds no DispatchQueue, Task, Combine, completion-handler, or other legacy async pattern; production changes only update NSWindow movability, and tests cover suppression state.
Cmux Swift @Concurrent ✅ Passed The PR changes only synchronous window-drag configuration, comments, and tests; no async, nonisolated, @concurrent, or async call-site changes were introduced.
Cmux Swift Package Boundaries ✅ Passed The production diff changes only NSWindow movability, background-drag configuration, and related comments. It uses the existing suppression lifecycle, so it is allowed AppKit/UI glue, not reusable...
Cmux Swiftpm Lockfiles ✅ Passed The complete PR diff contains only seven Swift source/test files; no Package.swift, Package.resolved, .gitignore, workflow, or Xcode project files changed.
Cmux Swift Logging ✅ Passed The PR adds or changes no Swift logging; added lines contain only window behavior, comments, and test assertions, with no print, NSLog, Logger, or ad hoc diagnostic output.
Cmux User-Facing Error Privacy ✅ Passed The full PR diff adds window behavior, comments, and test assertions only; it adds no user-facing errors, alerts, command output, API bodies, recovery copy, or sensitive diagnostics.
Cmux Full Internationalization ✅ Passed The PR changes window behavior and developer comments/tests only; it adds no production user-facing text, localization keys, catalogs, or web messages.
Cmux Swiftui State Layout ✅ Passed The PR adds no SwiftUI state or layout patterns. ContentView changes are comment-only, and CmuxMainWindow changes are in an AppKit NSHostingView/window bridge.
Cmux Architecture Rethink ✅ Passed The diff adds no timing, blocking, observer, or duplicate lifecycle wiring; it uses the existing suppression owner and tests the movable/immovable invariant during reconfiguration.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The diff changes only the CmuxMainWindow workspace window and related comments/tests; it adds no standalone auxiliary window. The auxiliary-window lint also passes.
Cmux Source Artifacts ✅ Passed The cumulative PR changes only seven intentional Swift source and test files; no logs, screenshots, caches, temp directories, build output, or other artifact paths appear in the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The production diff changes window behavior and comments only; it adds no DEBUG/test guard, test/debug-named member, visibility widening, or test accessor.
Cmux No Ambient Global State ✅ Passed The PR adds no production global state or declarations; it only changes the pre-existing configureCmuxMainWindowDragBehavior body and updates comments/tests.
Title check ✅ Passed The title clearly identifies the primary change: restoring native Window menu movement controls.
Description check ✅ Passed The description clearly explains the change and includes detailed testing evidence, but omits the template's demo video, review trigger, and checklist sections.
✨ 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-7446-window-menu-move-to-display-fill-center

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.

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Window menu "Move to <display>", "Fill", "Center" greyed out on multi-monitor (main window isMovable = false)

4 participants