cmux next: cmd-n's new tab chat takes the keyboard, and the arrow keys come back to the text
After Cmd-N, the New Tab page in Chromium sometimes showed no caret, and typing went nowhere. Its page got the keys in the workspace's provisional pane, then moved to the real pane; presenting its window there gave the keys back to the cmux window. ChildPageFocus still listed the page as focused, so the model's re-apply granted nothing. Separately, in the New Tab field's suggestion list the arrow keys never came back to the text: Up and Down wrapped through the rows, so the caret could not move up a line in a prompt of several lines.
- Cmd-N focus: when the cmux window becomes key without a click while a Chromium page is listed as focused,
ChildPageFocus.keysReturned(to:)blurs that page (no key change) andFocusEffectApplierre-applies the model's target, which grants the page the keys again. Nothing happens inside a grant, so the grant's own key change cannot ping-pong; a click decides itself. - One
isChromiumPageWindow: anNSWindowproperty inCmuxNextFocusUIreplaces the two App copies (FocusEffectApplier,KeyWindowRole), which pays for the App lines (App source lines go down). - Arrow keys in the suggestion list (
stepSelection, now inomnibar.tsfor the New Tab screen and the classic page): the top row stays selected while typing, so Return still takes it. Down on the last row wraps to the first; Up on the first row returns to the text (no row selected, Return sends the prompt). From the text, Down takes the first row and Up the last. - The caret in a prompt of several lines (
NewTabScreen.tsx): with no row selected, Up and Down move the caret while there is a line to go to, as in the chat's composer, and enter the rows from the first or last line. Left and Right while a row is selected return to the text and move the caret. Typing selects the top row again.
Unchanged: Tab, Ctrl-N / Ctrl-P, Right / End inline completion, Escape.
Changelog
- Fixed: after Cmd-N, the New Tab chat takes the keyboard, also when its page shows in Chromium.
- Changed: in the New Tab suggestions, Up on the top row returns to the text, and Up and Down move the caret in a prompt of several lines.
| Preview (Cmd-N, then typing: the New Tab chat takes the keyboard) |
|---|
| Preview (Arrow keys: down wraps to the top, up from the top goes back to the text, the caret moves between lines) |
|---|
Tests
Packages/macOS/CmuxNext/Tests/CmuxNextAppTests/ChildPageFocusKeyChangeTests.swift: a page that lost the keys to the cmux window is granted again; no change while the page window is key, with no focused page, or inside the grant.webviews/test/new-tab-omnibar.test.tsx: Down wraps to the top and Up on the top row returns to the text (Return asks the agent); in the text Up and Down keep the caret in a prompt of several lines, in the list they step the rows, and Left returns to the text.webviews/test/new-tab-auto-action.test.tsx,webviews/test/new-tab-create-rows.test.tsx: reach the last row with two Ups (the top row's Up now goes back to the text first).
Observed / Not run
No capture: the native change is keyboard focus only (which window has the keys), with no visible UI change; the recordings above show the behavior in a tagged build.
- Observed: the Cmd-N failure reproduced in a tagged build of the base;
debug.focusand the input journal showed the page focused in the provisional pane, thenwindowKey(true)on the cmux window after the pane swap, with no later grant. The fixed tagged build was checked by hand for the arrow keys and Cmd-N. - Observed:
bun test test/new-tab-omnibar.test.tsx13 pass (the new tests fail on the base rule),bun run typecheckpass,prepush-gate.pypass,check-app-size.sh --basepass. - Observed: every
webviews/test/new-tab-*file andNewTabScreen.test.tsx: 377 pass, 4 fail. Three fail on the base too (new-tab-no-entry-motionnoEntry.css,new-tab-widget-editedit mode,new-tab-minimal-defaultgreeting room);new-tab-composer-first-framefails only in the batch and passes alone. - Observed: after Cmd-N in the fixed build, one key-window change (the page's grant) about 135 ms after the press; the new hook did not run when nothing took the keys back. Page-ready time was not measured as an A/B against the base.
- Known limit: Up and Down check typed line breaks only. In one long line that wraps on screen, they still step the rows, as in the chat's composer.
- Not run:
ChildPageFocusKeyChangeTests(Swift tests run on the fleet or CI only); real IME composition. - Base finding:
scripts/web-lint.shreports warnings inDynamicWorkflow.gallery.tsxandchat-environment-scroll-stability.test.tsx, files this PR does not touch.
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.