Skip to content

Fix omnibar arrow key focus races - #4183

Merged
austinywang merged 14 commits into
mainfrom
issue-4141-omnibar-arrow-keys
May 16, 2026
Merged

austinywang merged 14 commits into
mainfrom
issue-4141-omnibar-arrow-keys

Conversation

@austinywang

@austinywang austinywang commented May 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • adds regression coverage for stale omnibar field-editor ownership and transient WebView first-responder arrow routing
  • restores live omnibar field fallback lookup for stale/nil window ownership cases
  • prevents browser arrow forwarding from treating the omnibar field editor as web content, and restores the logically focused omnibar before dispatching arrows

Fixes #4141

Testing

  • Not run locally, per repo policy; CI is the validation path.

Note

Medium Risk
Touches AppKit first-responder tracking and keyboard event routing for the browser omnibar, which is easy to regress and can affect typing/navigation behavior across windows and panels.

Overview
Fixes browser omnibar arrow-key race conditions by resolving the focused panel from the current omnibar responder/intent (not just stale tracked state) and by making omnibar selection repeat state panel-specific.

Adds a BrowserOmnibarNativeFieldRegistry and browserOmnibarField(panelId:in:) fallback lookup to reliably find the live omnibar field/field-editor even when AppKit leaves stale responder chains, and updates arrow-key forwarding to route plain arrows through keyDown for omnibar responders (including restoring omnibar focus before forwarding).

Refactors address-bar tracking preservation into shouldPreserveBrowserAddressBarTrackingDuringWebViewFocus with pointer-initiated WebView focus signals (propagated via .browserDidBecomeFirstResponderWebView userInfo), and adds regression tests covering stale field-editor ownership, transient first-responder states, and arrow routing.

Reviewed by Cursor Bugbot for commit 0dd9e94. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Registry and lookup support for live omnibar fields and improved omnibar focus resolution
    • First-responder notifications now include pointer-initiated info for focus transitions
  • Bug Fixes

    • Improved preservation/clearing of address-bar tracking across webview focus changes (pointer-initiated, suppression, live omnibar)
    • More reliable arrow-key routing that restores and forwards keys to the omnibar when appropriate
  • Tests

    • Added tests for tracking policy, omnibar lookup/resolution, and key-event routing

Review Change Stack

@vercel

vercel Bot commented May 14, 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 May 16, 2026 0:03am
cmux-staging Building Building Preview, Comment May 16, 2026 0:03am

@coderabbitai

coderabbitai Bot commented May 14, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an omnibar-native-field registry and focused-field APIs, introduces BrowserAddressBarTrackingContext and a preservation decision helper wired to pointer-initiated WebView focus, restores omnibar focus before forwarding arrow keys, refactors omnibar selection-repeat state, and adds tests for field resolution and arrow-key routing.

Changes

Browser omnibar arrow-key fix with resilient field registry

Layer / File(s) Summary
Focused omnibar field API & shortcut fast-path
Sources/AppDelegate.swift
Adds focusedBrowserOmnibarField(for:in:)/overload and updates shortcut routing to fast-path when the current first responder is an omnibar responder; introduces focusedAddressBarPanelIdInShortcutContext for shortcut contexts.
Address-bar tracking context & decision helper
Sources/App/ShortcutRoutingSupport.swift, Sources/AppDelegate.swift
Adds BrowserAddressBarTrackingContext and shouldPreserveBrowserAddressBarTrackingDuringWebViewFocus(_:); expands the preservation helper to accept webview-match and pointer-initiated inputs and delegates to the context helper.
Selection-move repeat lifecycle refactor
Sources/AppDelegate.swift
Introduces browserOmnibarRepeatPanelId and reworks repeat arming/ticking to use the stored panel id for selection-move repeat behavior.
WebView pointerInitiated wiring & owning-webview tweak
Sources/Panels/CmuxWebView.swift, Sources/TabManager.swift, Sources/AppDelegate.swift
CmuxWebView posts pointerInitiated in .browserDidBecomeFirstResponderWebView; pointerInitiated userInfo key added; AppDelegate reads and threads it into preservation decisions. Omnibar-panel responders are treated as having no owning web view to avoid misrouting.
Arrow-key forwarding and responder restoration
Sources/AppDelegate.swift
NSWindow.cmux_performKeyEquivalent restores first responder to the omnibar native field/editor when needed, avoids reentry loops, blocks forwarding when the omnibar responder has marked text, and forwards arrow keys directly to the restored omnibar responder.
Omnibar field registry and lookup (collapsed with view plumbing)
Sources/Panels/BrowserPanelView.swift
Adds a weak, panel-scoped BrowserOmnibarNativeFieldRegistry and @MainActor lookup helpers; OmnibarTextFieldRepresentable registers/unregisters fields so lookups succeed even with stale responder chains.
Field resolution & arrow-key tests
cmuxTests/BrowserConfigTests.swift, cmuxTests/OmnibarAndToolsTests.swift, cmuxTests/AppDelegateShortcutRoutingTests.swift
Adds BrowserAddressBarTrackingPolicyTests, BrowserOmnibarNativeFieldRegistryTests, BrowserOmnibarFieldEditorResolutionTests, updates FieldEditorProbeTextView keyDown recording, and adds tests asserting arrow events reach the omnibar and selection routing targets the responder-resolved panel id.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A registry of fields, weak but true,
Pointer whispers tell which focus is due,
Arrows return to the omnibar's light,
Carets and suggestions dance back right. ✨


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (2 errors, 1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Cmux Swift Logging ❌ Error PR adds unguarded NSLog in AppDelegate.swift app/runtime code, violating swift-logging.md. Multiple NSLog statements not guarded by #if DEBUG found in auth callback and command surface code. Guard NSLog statements with #if DEBUG or remove them. Affected: auth.callback error, Command send timeout, and LaunchServices registration failure logging.
Cmux Architecture Rethink ❌ Error Duplicate wiring of arrow restoration: sticky fallback bypasses tracking-preservation gate, restoring omnibar after preservation rejected it. Remove sticky fallback ?? browserAddressBarFocusedPanelId from focusedBrowserOmnibarField (line 12270) to enforce single tracking-preservation path.
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.
Description check ❓ Inconclusive The PR description covers the what (fixes omnibar arrow-key races), why (regression in address-bar tracking, stale field lookups), but lacks comprehensive testing details and demo video. Provide details on local testing verification, specific test scenarios covered, and link to demo video if UI behavior changed. CI-only testing should still document what was validated.
✅ Passed checks (12 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly and concisely identifies the main change: fixing omnibar arrow key focus races. It is specific and directly related to the core problem being solved.
Linked Issues check ✅ Passed Changes fully address issue #4141 requirements: restore arrow-key behavior via fallback field lookup, add regression tests, prevent WKWebView misclassification, and ensure omnibar field-editor restoration before arrow dispatch.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing omnibar arrow-key focus races. Registry additions, focus tracking context, arrow forwarding restoration, and test coverage are all necessary for resolving the linked issue.
Cmux Swift Actor Isolation ✅ Passed All new types properly isolated: @MainActor on BrowserOmnibarNativeFieldRegistry and UI functions; pure value structs need no isolation; properly nested in @MainActor AppDelegate context.
Cmux Swift Blocking Runtime ✅ Passed PR introduces omnibar focus/routing fixes with no new blocking or timing-based synchronization primitives. All new code uses pure logic, data structures, and weak reference caching.
Cmux No Hacky Sleeps ✅ Passed PR changes are entirely Swift-based omnibar fixes. Custom check targets non-Swift production code; Swift covered by separate rule. Shell scripts are build/CI infrastructure only.
Cmux Swift Concurrency ✅ Passed All new code is synchronous or properly annotated with @MainActor. No DispatchQueue.global(), Combine, completion handlers, or fire-and-forget Tasks added. Test synchronization is test-only.
Cmux Swift @Concurrent ✅ Passed All new Swift code is synchronous. New @MainActor annotations correctly mark UI-bound functions. No @concurrent annotations present. No violations of swift-concurrent-annotation.md rules detected.
Cmux Swift File And Package Boundaries ✅ Passed File additions below 250-line threshold (AppDelegate +230, BrowserPanelView +147). Focused bug fix with coherent file responsibilities. No mixed-responsibility files introduced.
Cmux User-Facing Error Privacy ✅ Passed PR contains no new user-facing error messages, alerts, or sensitive data exposure. All changes are internal keyboard/focus routing improvements with no violations of user-facing error privacy rules.
Cmux Swiftui State Layout ✅ Passed No SwiftUI state violations found. PR adds AppKit code and bridge utilities without new @Published/@StateObject/@observable patterns. Safe control flow changes only.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR introduces no new standalone cmux-owned windows. All changes are helper functions, registries, and notification payloads for existing omnibar routing.
✨ 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-4141-omnibar-arrow-keys

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.

@austinywang
austinywang force-pushed the issue-4141-omnibar-arrow-keys branch from 5071acc to 23af49a Compare May 14, 2026 23:52
@greptile-apps

greptile-apps Bot commented May 15, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes omnibar arrow-key focus races by making the panel-ID resolution path in focusedBrowserAddressBarPanelIdForShortcutEvent fall back through live responder → tracked state → address-bar intent, and by routing plain arrow keyDown events directly to the omnibar field editor (bypassing the WebView forwarding path) both when the omnibar is already first responder and when it needs to be restored.

  • Introduces BrowserOmnibarNativeFieldRegistry, a @MainActor weak-cache that resolves the live OmnibarNativeTextField for a panel when AppKit's nextResponder chain is stale after a focus transition.
  • Adds BrowserAddressBarTrackingContext and shouldPreserveBrowserAddressBarTrackingDuringWebViewFocus to centralise the five-step tracking-preservation policy, now including pointerInitiated (threaded through browserDidBecomeFirstResponderWebView) and liveOmnibarFieldExists signals.
  • Threads an explicit panelId through dispatchBrowserOmnibarSelectionMove and the repeat machinery, removing the implicit reliance on browserAddressBarFocusedPanelId at tick time; guards resolvedBrowserWebViewResponder to short-circuit for omnibar responders so they are never treated as web content.

Confidence Score: 5/5

Safe to merge; the changes are well-scoped to omnibar arrow routing and focus-tracking, backed by new unit tests covering the stale-responder, transient-responder, and restore-before-dispatch scenarios.

All modified paths are on MainActor, the repeat machinery now carries an explicit panelId rather than reading mutable shared state at tick time, and the new tracking-preservation logic is fully unit-tested as a pure function. The only nit is unnecessary WeakOmnibarNativeTextField allocation on every SwiftUI update in updateNSView.

Sources/Panels/BrowserPanelView.swift — the updateNSView re-registration pattern; everything else is clean.

Important Files Changed

Filename Overview
Sources/App/ShortcutRoutingSupport.swift Adds shouldDispatchBrowserOmnibarArrowViaFirstResponderKeyDown for direct arrow routing when omnibar is first responder, and BrowserAddressBarTrackingContext + shouldPreserveBrowserAddressBarTrackingDuringWebViewFocus for the refactored tracking policy; pure logic with no side effects and well-exercised by new unit tests.
Sources/Panels/BrowserPanelView.swift Adds BrowserOmnibarNativeFieldRegistry weak-cache singleton, canHandleOmnibarSelectionNavigation fallback chain, and register/unregister lifecycle hooks in OmnibarTextFieldRepresentable; the updateNSView path unconditionally re-registers on every SwiftUI update, allocating a new wrapper object even when panelId is unchanged.
Sources/AppDelegate.swift Significant refactor of focusedBrowserAddressBarPanelIdForShortcutEvent to resolve panel from live responder, tracked state, and address-bar intent; threads explicit panelId through dispatchBrowserOmnibarSelectionMove and repeat machinery; adds omnibar-first-responder restore path in performKeyEquivalent; logic is correct and thoroughly documented with debug traces.
Sources/Panels/CmuxWebView.swift Threads pointerInitiated boolean into the browserDidBecomeFirstResponderWebView notification so downstream handlers can distinguish pointer-driven vs programmatic focus transitions; minimal and correct.
Sources/TabManager.swift Adds BrowserFirstResponderNotificationUserInfoKey enum with a pointerInitiated string constant; trivial change.
cmuxTests/AppDelegateShortcutRoutingTests.swift Adds two end-to-end shortcut routing tests covering stale-tracking and transient-window-first-responder cases; tests correctly clean up after themselves.
cmuxTests/BrowserConfigTests.swift Adds BrowserAddressBarTrackingPolicyTests, BrowserOmnibarNativeFieldRegistryTests, and three FieldEditorProbeWindow-backed arrow-routing tests; thorough coverage of the new code paths.
cmuxTests/OmnibarAndToolsTests.swift Adds BrowserOmnibarFieldEditorResolutionTests with a stale-nextResponder repro test that validates the registry lookup bypasses a manually poisoned responder chain.

Sequence Diagram

sequenceDiagram
    participant W as NSWindow.performKeyEquivalent
    participant D as AppDelegate
    participant R as BrowserOmnibarNativeFieldRegistry
    participant FE as OmnibarFieldEditor (NSTextView)

    W->>W: browserOmnibarPanelId(firstResponder)
    alt firstResponder IS omnibar field editor
        W->>W: shouldDispatchBrowserOmnibarArrowViaFirstResponderKeyDown → true
        W->>FE: keyDown(arrowEvent)
    else firstResponder is WebView / other
        W->>W: shouldDispatchBrowserArrowViaFirstResponderKeyDown → true
        W->>D: focusedBrowserOmnibarField(event, window)
        D->>D: focusedBrowserAddressBarPanelIdForShortcutEvent(responder → tracked → intent)
        D->>R: field(for: panelId, in: window)
        R-->>D: OmnibarNativeTextField?
        D-->>W: focusedOmnibarField?
        alt focusedOmnibarField exists and not first responder
            W->>W: makeFirstResponder(focusedOmnibarField)
            W->>FE: keyDown(arrowEvent)
        else no focused omnibar
            W->>W: normal browser arrow forward
        end
    end
Loading

Reviews (11): Last reviewed commit: "fix: route omnibar arrows through active..." | Re-trigger Greptile

Comment thread Sources/Panels/BrowserPanelView.swift
Comment thread Sources/AppDelegate.swift Outdated
Comment thread Sources/Panels/BrowserPanelView.swift
coderabbitai[bot]
coderabbitai Bot previously requested changes May 15, 2026

@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: 4

🤖 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 `@Sources/App/ShortcutRoutingSupport.swift`:
- Around line 95-108: Refactor the boolean-heavy function
shouldPreserveBrowserAddressBarTrackingDuringWebViewFocus by introducing a
single parameter struct (e.g., BrowserAddressBarTrackingContext) that contains
the six Bool properties, replace the function signature to accept that context,
update all call sites to construct and pass the struct, and add a concise doc
comment above the function that lists the decision steps
(trackedPanelMatchesWebView check, omnibarResponderActive shortcut,
preferredFocusIntentIsAddressBar and pointerInitiatedWebFocus gates, then
suppressesWebViewFocus || liveOmnibarFieldExists). Ensure property names in the
struct match the existing parameter names so the internal logic (guards and
final return) can be used without behavioral changes.

In `@Sources/AppDelegate.swift`:
- Around line 12379-12393: The helper shouldPreserveBrowserAddressBarTracking is
always passing trackedPanelMatchesWebView: true which allows a stale tracked
panel to be preserved when a different panel's web view actually took
first-responder; change the call site to compute trackedPanelMatchesWebView by
comparing the panel's actual webView against the window's current firstResponder
(or the webView instance passed into the browserDidBecomeFirstResponderWebView
observer) instead of hardcoding true, e.g. determine whether
resolvedWindow?.firstResponder (or the observer-supplied webView) is the same
webView instance as panel.webView and pass that boolean into
shouldPreserveBrowserAddressBarTrackingDuringWebViewFocus so stale
browserAddressBarFocusedPanelId values are not preserved for the wrong panel.

In `@Sources/Panels/BrowserPanelView.swift`:
- Around line 53-62: The selection logic in field(for:in:) should prefer a live
OmnibarNativeTextField that is attached to a window before falling back to
detached registry entries; keep calling pruneDeadEntries(for:) and the existing
behavior when a specific window is provided, but when window is nil change the
fallback to first where field.window != nil (attached) and only then return
liveFields.first (detached) so transient registered-but-not-yet-attached fields
don't get chosen; update the logic in field(for:in:) accordingly and keep
references to the fields dictionary, pruneDeadEntries(for:), and
OmnibarTextFieldRepresentable.makeNSView/updateNSView semantics in mind.

In `@Sources/Panels/CmuxWebView.swift`:
- Around line 430-434: Extract the literal "pointerInitiated" into a shared
constant and use it when posting and reading the notification: add a static
constant (e.g. BrowserFirstResponderKeys.pointerInitiated) alongside the
existing Notification.Name.browserDidBecomeFirstResponderWebView declaration,
replace the inline userInfo key in the NotificationCenter.post call with that
constant, and update any consumers to read userInfo[.pointerInitiatedConstant]
(casting to Bool) so producer and consumers share a single typed key.
🪄 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

Run ID: c4b4032e-db50-4262-83f0-8dffdfd19c14

📥 Commits

Reviewing files that changed from the base of the PR and between c83f585 and 3601446.

📒 Files selected for processing (6)
  • Sources/App/ShortcutRoutingSupport.swift
  • Sources/AppDelegate.swift
  • Sources/Panels/BrowserPanelView.swift
  • Sources/Panels/CmuxWebView.swift
  • cmuxTests/BrowserConfigTests.swift
  • cmuxTests/OmnibarAndToolsTests.swift

Comment thread Sources/App/ShortcutRoutingSupport.swift
Comment thread Sources/AppDelegate.swift
Comment thread Sources/Panels/BrowserPanelView.swift
Comment thread Sources/Panels/CmuxWebView.swift
coderabbitai[bot]
coderabbitai Bot previously requested changes May 15, 2026

@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 `@Sources/AppDelegate.swift`:
- Around line 13741-13750: The preserve-check is using a hardcoded false for
trackedPanelMatchesWebView, ignoring the current webview-focus context; update
the call to
shouldPreserveBrowserAddressBarTracking(for:trackedPanelMatchesWebView:) to pass
the pointerInitiated boolean (the local pointerInitiated variable) instead of
false so the preservation logic receives the actual pointer-initiated
webview-focus context when evaluating browserAddressBarFocusedPanelId and
browserPanel(for:).
🪄 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

Run ID: 25708bcc-6ed0-4169-9f5d-00a2e146aecd

📥 Commits

Reviewing files that changed from the base of the PR and between 3601446 and aaa62d1.

📒 Files selected for processing (6)
  • Sources/App/ShortcutRoutingSupport.swift
  • Sources/AppDelegate.swift
  • Sources/Panels/BrowserPanelView.swift
  • Sources/Panels/CmuxWebView.swift
  • Sources/TabManager.swift
  • cmuxTests/BrowserConfigTests.swift

Comment thread Sources/AppDelegate.swift Outdated

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Sources/AppDelegate.swift (1)

12274-12320: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Resolve the omnibar panel from the current responder before falling back to tracked state.

This still returns nil when the omnibar is first responder but browserAddressBarFocusedPanelId was cleared, and it can also return the wrong panel when the tracked id lags behind the responder. The fast-path should derive the panel with browserOmnibarPanelId(for: shortcutResponder) before consulting tracked state.

Suggested fix
 func focusedBrowserAddressBarPanelIdForShortcutEvent(_ event: NSEvent) -> UUID? {
-    guard let panelId = browserAddressBarFocusedPanelId else { return nil }
+    let shortcutWindow = resolvedShortcutEventWindow(event) ?? NSApp.keyWindow ?? NSApp.mainWindow
+    let shortcutResponder = shortcutWindow?.firstResponder
+
+    if let omnibarPanelId = browserOmnibarPanelId(for: shortcutResponder),
+       isBrowserOmnibarResponder(shortcutResponder) {
+        return omnibarPanelId
+    }
+
+    guard let panelId = browserAddressBarFocusedPanelId else { return nil }
@@
-    let shortcutWindow = resolvedShortcutEventWindow(event) ?? NSApp.keyWindow ?? NSApp.mainWindow
-    let shortcutResponder = shortcutWindow?.firstResponder
-
-    if isBrowserOmnibarResponder(shortcutResponder) {
+    if isBrowserOmnibarResponder(shortcutResponder) {
 `#if` DEBUG
         cmuxDebugLog(
             "browser.focus.addressBar.shortcutContext panel=\(panelId.uuidString.prefix(5)) " +
                 "accepted=1 reason=omnibar_responder workspace=\(workspace.id.uuidString.prefix(5)) " +
                 "event=\(NSWindow.keyDescription(event))"
         )
 `#endif`
-        return panelId
+        return browserOmnibarPanelId(for: shortcutResponder) ?? panelId
     }
🤖 Prompt for 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.

In `@Sources/AppDelegate.swift` around lines 12274 - 12320, The fast-path should
resolve the omnibar's panel from the current responder before relying on tracked
state: in focusedBrowserAddressBarPanelIdForShortcutEvent(_:) call
browserOmnibarPanelId(for: shortcutResponder) (or equivalent) immediately after
computing shortcutResponder and use that derived panelId if non-nil; only if
that returns nil fall back to browserAddressBarFocusedPanelId. Update subsequent
guard checks and DEBUG cmuxDebugLog messages to reference the derived panelId
(or the fallback) so the accepted/rejected logging and workspace/panel lookup
use the responder-derived panel id instead of stale tracked state.
🤖 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.

Outside diff comments:
In `@Sources/AppDelegate.swift`:
- Around line 12274-12320: The fast-path should resolve the omnibar's panel from
the current responder before relying on tracked state: in
focusedBrowserAddressBarPanelIdForShortcutEvent(_:) call
browserOmnibarPanelId(for: shortcutResponder) (or equivalent) immediately after
computing shortcutResponder and use that derived panelId if non-nil; only if
that returns nil fall back to browserAddressBarFocusedPanelId. Update subsequent
guard checks and DEBUG cmuxDebugLog messages to reference the derived panelId
(or the fallback) so the accepted/rejected logging and workspace/panel lookup
use the responder-derived panel id instead of stale tracked state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 30ffb542-0950-4dd9-89ab-ba34cc2fea86

📥 Commits

Reviewing files that changed from the base of the PR and between aaa62d1 and cf668a0.

📒 Files selected for processing (1)
  • Sources/AppDelegate.swift

@lawrencecchen
lawrencecchen dismissed stale reviews from coderabbitai[bot] and coderabbitai[bot] May 15, 2026 01:14

Stale CodeRabbit changes-request review. All four actionable threads were fixed, replied to, and resolved; CodeRabbit subsequently passed on the updated head.

Comment thread Sources/AppDelegate.swift Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes May 15, 2026

@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: 2

🤖 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 `@Sources/AppDelegate.swift`:
- Around line 12352-12361: The code hard-codes trackedPanelMatchesWebView: true
when constructing BrowserAddressBarTrackingContext; instead compute it from the
live responder so it reflects whether the current first responder actually
belongs to this browser panel. Replace the literal true with a boolean derived
by checking the live omnibar/first-responder state (e.g., use the previously
computed liveOmnibarFieldExists combined with a check that the current first
responder’s browser panel ID equals panelId — determine that panel ID via the
same responder lookup you use elsewhere), so trackedPanelMatchesWebView
accurately reflects the live responder before calling
shouldPreserveBrowserAddressBarTrackingDuringWebViewFocus.
- Around line 14894-14908: The code forwards the arrow key even when
makeFirstResponder(focusedOmnibarField) fails, which can swallow the event;
update the logic around makeFirstResponder, currentEditor() and
self.firstResponder so you only call omnibarResponder.keyDown(with:) and return
true when focusedOmnibarField actually became first responder (i.e.,
makeFirstResponder returned true and currentEditorResponder equals
self.firstResponder or otherwise confirms focus); if the focus change was
rejected, do not call keyDown on focusedOmnibarField and return false so the
browser/webview retains the event. Ensure you reference
makeFirstResponder(focusedOmnibarField), focusedOmnibarField.currentEditor(),
self.firstResponder, browserResponderHasMarkedText(_:), and
omnibarResponder.keyDown(with:) in your conditional checks.
🪄 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

Run ID: 4c1ad567-0b38-4213-89ce-47840ae208d5

📥 Commits

Reviewing files that changed from the base of the PR and between cf668a0 and e5c01bb.

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

Comment thread Sources/AppDelegate.swift
Comment thread Sources/AppDelegate.swift Outdated
Comment thread Sources/AppDelegate.swift Outdated

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@lawrencecchen
lawrencecchen dismissed coderabbitai[bot]’s stale review May 15, 2026 01:50

Stale CodeRabbit review from e5c01bb. The inline comments were addressed in 2fb9704, replied to, resolved, and CodeRabbit confirmed them as addressed on the current branch.

Comment thread Sources/AppDelegate.swift
coderabbitai[bot]
coderabbitai Bot previously requested changes May 15, 2026

@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 `@Sources/AppDelegate.swift`:
- Around line 12269-12272: The function focusedBrowserOmnibarField(for:in:)
currently falls back to browserAddressBarFocusedPanelId which allows stale
omnibar focus to be used; change it to only use the result of
focusedBrowserAddressBarPanelIdForShortcutEvent(_:) and return nil when that
call returns nil so shortcut-context resolution is respected (i.e., remove the
sticky fallback to browserAddressBarFocusedPanelId), leaving the rest of the
call to browserOmnibarField(panelId:in:) intact; this prevents
cmux_performKeyEquivalent's arrow-key restore from re-focusing a stale omnibar.
🪄 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

Run ID: 31b143be-406f-4b4e-b024-7fe1d9f6a1dd

📥 Commits

Reviewing files that changed from the base of the PR and between e5c01bb and 2fb9704.

📒 Files selected for processing (1)
  • Sources/AppDelegate.swift

Comment thread Sources/AppDelegate.swift
@lawrencecchen
lawrencecchen dismissed coderabbitai[bot]’s stale review May 15, 2026 03:20

Stale CodeRabbit review from 2fb9704. The sticky fallback was removed in 41df02b, and both inline threads were replied to and resolved.

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 41df02b. Configure here.

Comment thread Sources/AppDelegate.swift Outdated

@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 8 files

Re-trigger cubic

@austinywang
austinywang merged commit 073e07b into main May 16, 2026
25 checks passed

This branch was successfully deployed

1 active deployment
Preview – cmux — 0dd9e94f Deployed May 16, 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.

Arrow keys do not work in the cmux browser omnibar (regression from f4d6339ef)

2 participants