cmux NEXT keys: a focused text field keeps Return, Esc and ↑ from unscoped defaults

Merged
TE
16d ago
+82-1

Leo pressed ⌘↩ in the chat composer to steer and got the toast "the workspace checklist has no item to do". The composer never saw the key: toggleChecklistItemComplete has ⌘↩ as its default and took it first.

#22616 (Austin) fixes this for the agent chat and web pages by surface. This PR is the general rule Leo asked for, on top of it and without touching its lines: a default binding on a key a text field or composer uses itself steps aside while text input has the keyboard. The keys are ↩, ⌘↩, ⇧↩, ⌥↩, Esc and ↑. The exception is an action scoped to a surface through requires (the omnibar's ⌘↩, the file explorer's ↩), which keeps its key.

This also covers what #22616 leaves out: the Home/Chief composer (surfaceKind == home), the terminal TextBox, sidebar fields and the rename sheet.

  • KeyBindingDefaults.textInputKeys and notTextInput (textInputFocus or textBoxFocused unset).
  • RegistryKeyBindings.makeTable adds notTextInput to the default entry of any action with no requires whose key is in textInputKeys. A user binding keeps its own when.
  • Today this changes only the checklist toggle's ⌘↩. A guard test fails if a later unscoped default lands on one of these keys.

Changelog

Fixed: ⌘Return in a chat or Home composer, or any focused text field, reaches the field instead of toggling a checklist item.

Testing

Packages/macOS/CmuxNext/Tests/CmuxNextAppTests/TextInputKeysYieldTests.swift sends ⌘↩ through KeyRouter.decide, the dispatcher's real decision path.

Command: cmux-ci run --class light --script scripts/ci/run-swift-testing-suites.sh --arg=Packages/macOS/CmuxNext --ref <sha>

  • Red, at 1986c238ef4f (test only), step 6996c7dd3dfdd75a8eea7756: theChatComposerGetsCommandReturn, theHomeComposerGetsCommandReturn and aSidebarFieldGetsCommandReturn fail (== "deliver"). theTodoPageStillToggles passes.
  • Green, at ca52c47cc84e (the same tree as the head 36b8bd14588c, before I split the guard test out of the red commit), step 4cb61a00f92a2c942b949d67: TextInputKeysYieldTests passes all 5, including noUnscopedDefaultTakesATextFieldKey.

Observed / Not run

  • Observed: the red and green runs above. Other suites failed in the green run as well (AccountsCmuxRowTests, AgentPaneSendPickedFolderPromptTests, BrowserImportFolderGrantTests, DebugPaletteCaptureTests, SidebarOneMorphingCardTests and others). They are about accounts, folders, sidebar motion and capture, not key routing. I did not run them on base to compare.
  • Not run: the head SHA itself on the fleet (same tree as ca52c47), and a live ⌘↩ in a tagged build.

Agent session: cosmic-gray

🤖 Generated with Claude Code


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


Summary by cubic

Fixes key routing so a focused text field or composer keeps its own keys (Return and its ⌘/⇧/⌥ forms, Esc, ↑) instead of an unscoped default binding taking them. Previously ⌘Return in the chat composer triggered the checklist toggle, which refused with a "no todo items" toast.

  • Default bindings on those keys now add a notTextInput condition unless the action is scoped to a surface through requires (the omnibar's ⌘Return, the file explorer's Return keep their keys).
  • Covers the Home/Chief composer, terminal TextBox, sidebar fields, and the rename sheet, which the existing surface-specific fix leaves out.
  • Adds tests for the chat and Home composers and a sidebar field, plus a guard test that fails if a later unscoped default lands on one of these keys.