Skip to content

Fix Dock paste routing to selected terminal - #9112

Merged
austinywang merged 4 commits into
mainfrom
issue-9097-dock-paste-wrong-pane
Aug 1, 2026
Merged

austinywang merged 4 commits into
mainfrom
issue-9097-dock-paste-wrong-pane

Conversation

@austinywang

@austinywang austinywang commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • make Dock panel selection converge the AppKit first responder with the selected terminal
  • restore the selected Dock pane after transient clipboard-manager window activation
  • add real Ghostty responder-chain regression coverage in a red/green commit pair

Testing

  • CI is the test gate; local xcodebuild/tests are intentionally skipped per issue instructions
  • project wiring and Swift source checks only on this Mac

Closes #9097


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

Fixes Dock paste routing so keyboard input always goes to the selected terminal pane. The AppKit first responder now follows Dock selection and is restored to the selected pane after transient focus (e.g., window becomes key) changes.

  • Bug Fixes
    • Prefer focusedPaneId in focusFirstControl() so Dock selection focuses the intended terminal, not the first pane.
    • Add tests ensuring Dock selection sets the first responder and that focus restoration keeps it on the selected terminal.

Written for commit 42345ff. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved dock focus restoration so the selected terminal remains active after switching focus.
    • Ensured keyboard input stays directed to the selected terminal when focus is reset or restored.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds DEBUG-only regression coverage for selecting and restoring focus to a bottom Dock terminal, verifying that the Dock focus state and window first responder remain associated with the selected terminal surface.

Changes

Dock focus regression

Layer / File(s) Summary
Selection and responder assertions
cmuxTests/DockTerminalPointerFocusTests.swift
Adds an async DEBUG-only test that builds a two-terminal Dock, simulates bottom-panel selection, and verifies focused-panel and first-responder state through focus reset and restoration.

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

Possibly related PRs

  • manaflow-ai/cmux#9051: Adds related Dock terminal pointer-focus regression coverage and store-based focus routing.
🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds regression coverage, but the linked issue requires the actual first-responder routing fix, which isn't shown in the changed files. Add the Dock first-responder handoff fix in production code so the selected terminal receives paste actions, then keep the regression test.
✅ Passed checks (24 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The changes stay focused on Dock focus regression coverage and are aligned with the reported bug.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Cmux Swift Actor Isolation ✅ Passed Only a test file changed, and it is explicitly @MainActor; the rule file allows test/UI types on the main actor and no isolation debt is introduced.
Cmux Swift Blocking Runtime ✅ Passed Only changed Swift file is cmuxTests/DockTerminalPointerFocusTests.swift; its polling RunLoop helper is DEBUG test scaffolding, and no production Swift files were touched.
Cmux Browser Automation Off-Main ✅ Passed Diff only adds Dock focus tests in cmuxTests; no browser.* routing or policy files changed, so the off-main browser-automation rule isn’t implicated.
Cmux Expensive Synchronous Load ✅ Passed Only a DEBUG test file was added; it contains no agent-history loads, JSON/JSONL parsing, or other heavy synchronous loaders on main/interactive paths.
Cmux Cache Substitution Correctness ✅ Passed Only a DEBUG test file changed; no production persistence/history/undo/snapshot path was altered, so cache-substitution rules don’t apply.
Cmux No Hacky Sleeps ✅ Passed The only added wait is a bounded run-loop poll inside Swift test scaffolding, which the rule explicitly allows; no production/runtime sleep was introduced.
Cmux Algorithmic Complexity ✅ Passed Diff only adds DEBUG-only test scaffolding in cmuxTests; the rule explicitly passes test-only code and no production complexity change appears.
Cmux Swift Concurrency ✅ Passed Test-only diff uses AppKit/XCTest async boundaries and an existing gate helper; it adds no new DispatchQueue, Combine, completion-handler, or fire-and-forget Task pattern.
Cmux Swift @Concurrent ✅ Passed The new async tests stay on @MainActor and use a @MainActor gate; no nonisolated async work, invalid @concurrent, or heavy off-main helper was added.
Cmux Swift Package Boundaries ✅ Passed Only a test-target file changed, and the rules explicitly allow test fixtures and AppKit/Ghostty glue.
Cmux Swiftpm Lockfiles ✅ Passed PR only touches cmuxTests/DockTerminalPointerFocusTests.swift; no Package.swift, Package.resolved, .gitignore, workflow, or Xcode project changes are present.
Cmux Swift Logging ✅ Passed Added test code only; no print/debugPrint/dump/NSLog/Logger or ad hoc stdout/file logging appears in the diff.
Cmux User-Facing Error Privacy ✅ Passed The only changed file is a test under cmuxTests, and the new strings are DEBUG-only test diagnostics, not user-facing production copy.
Cmux Full Internationalization ✅ Passed Only a debug-only test file changed; its strings are test/Issue text, and no production Swift/UI, xcstrings, plist, or web locale files were touched.
Cmux Swiftui State Layout ✅ Passed The only touched code is an AppKit test harness; no new SwiftUI state/layout patterns, GeometryReader, lazy-row store refs, or render-time state writes were introduced.
Cmux Architecture Rethink ✅ Passed The commit only adds a DEBUG-gated test file; its run-loop waiting is test-only synchronization and the rule explicitly allows that.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed Only cmuxTests/DockTerminalPointerFocusTests.swift changed; its NSWindow use is test-only and the rule explicitly allows test-only fixture windows.
Cmux Source Artifacts ✅ Passed The only changed path is a hand-written Swift test source in cmuxTests, which the policy explicitly allows; no generated artifact paths appear.
Cmux No Test Or Debug Seam In Production Source ✅ Passed HEAD changes only cmuxTests/DockTerminalPointerFocusTests.swift; no Sources/ file changed, so the production-seam rule isn’t triggered.
Cmux No Ambient Global State ✅ Passed The diff only adds methods inside a test struct; no new top-level funcs, mutable vars, namespace types, or singleton/global runtime state.
Title check ✅ Passed The title clearly matches the main change: fixing Dock paste routing to the selected terminal.
Description check ✅ Passed The description covers Summary and Testing well, but omits Demo Video, Review Trigger, and Checklist sections from the template.
✨ 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-9097-dock-paste-wrong-pane

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.

@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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmuxTests/DockTerminalPointerFocusTests.swift`:
- Line 215: Update the test setup before the Dock interaction to initialize and
mount the synchronous main-tree terminal, capture its workspace and panel IDs,
and make its surface first responder. Invoke
noteMainPanelKeyboardFocusIntent(workspaceId:panelId:in:) with those captured
IDs before calling dock.noteKeyboardFocusIntent(window:), mirroring the setup
used in the existing Lines 89-126 flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8eadb13d-4756-4881-956b-45446bf1871d

📥 Commits

Reviewing files that changed from the base of the PR and between 32f1e83 and 1f5634a.

📒 Files selected for processing (1)
  • cmuxTests/DockTerminalPointerFocusTests.swift

Comment thread cmuxTests/DockTerminalPointerFocusTests.swift Outdated
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.

Dock: paste (Raycast clipboard manager / Cmd+V) lands in the top Dock terminal instead of the selected bottom one

1 participant