fix(focus): keys typed after Cmd-N then Ctrl-` go to the new terminal (P0 STATUS 1729)

Closed
LA
4d ago
+79-7

Summary

P0 (STATUS 1729): after Cmd-N, then Ctrl-in the new workspace, the line the person typed did not run in the new terminal. In 6 of 14 rounds of the journeyfocus-switch-corner-dragevery typed key got thedebug.keyreply{handled_by: "app", action: "newSurface"}`, and the line was not in the shell.

Cause

  • Cmd-N begins a New Tab key hold for its window (NewTabInputCoordinator.beginIncoming). An incoming hold owns every key of the window (Entry.owns is always true for it) until the new page reports its field ready, the creation makes no page, another New Tab opening begins, or 4 s pass.
  • A chord with no held keys passes the hold and does not end it. So the person's Ctrl-` made a terminal tab, which hid the New Tab page, and the hold stayed.
  • If the page is not ready yet at the Ctrl-, the hold keeps every key typed into the new terminal: the page is hidden now, so drain()(itsfocusField check) cannot give them to it, and they wait for the 4 s limit. Journey base round s1: the Ctrl- came about 150 ms after Cmd-N, the page reported ready at +275 ms (hidden by then), the keys were held from +2727 ms and the line ran 1129 ms after Return, at the limit. A probe of 60 cycles without a Ctrl- (Cmd-N, readiness, type) drained at the readiness in 58 of 58: ready-but-not-drained needs the Ctrl-.
  • The debug.key reply said action: newSurface because the New Tab hold takes a key before KeyRouter.interceptKeyDown clears lastInterception: it was the router's stale last action (the Ctrl-`), not a second newSurface.
  • The evidence in the rounds: all 17 keys handled_by: app with an empty trace, typed 2.65-2.9 s after Cmd-N (inside the 4 s bound) and 2.5 s after Ctrl-. The creation hold of the Ctrl- cannot be the holder: it ends at most 2 s after the create's reply, and the reply came before the driver adopted the terminal (0.5-1.2 s after the key). It never happens without Cmd-N (focus-corner-drag: no New Tab hold).

Fix

A creation that moves focus (CreationInputCoordinator.begin: a new terminal tab, a split, a browser tab, a column, a row) ends the window's New Tab hold first, with its held keys in order, as another New Tab opening already does (NewTabInputCoordinator.begin releases the earlier one). The creation hold then owns the window's keys until the new terminal has the keyboard. No delay, no dropped key, no retry: the keys typed into the new terminal go to it, and keys typed before the Ctrl-` were already given on by the chord rule.

Tests

  • Red-first: CmdNThenNewTerminalKeysTests (commit 74a4ffe477d, test only). Cmd-N's hold (beginIncoming, page made, not ready), the person's newSurface, then a line typed through the app's key path; the line must run in the new terminal (same-tree daemon).
    • Red at 74a4ffe477d (test only): step bfe445c244248af013827e55 (aws-m4pro-8) FAILED on the bug's own outcome: CmdNThenNewTerminalKeysTests.swift:37 the New Tab hold still holds after Ctrl-; :67held == 23 (every typed key taken by the hold);:70` the line never ran in the new terminal.
    • Green at 8df486e71e8: step 4915fa268d74a2c730aaefde (aws-m4pro-1) PASSED, 3 of 3: CmdNThenNewTerminalKeysTests, NewTerminalOnPendingSplitTests, NewTabHoldFocusTests; no FLAKY notice.
  • Compile check of the head: 3d9cc706d9dd91a69f9cf068 PASSED (CmuxNext, app, cmux-tui).
  • Journey cmdn-ctrlbt-type (kit cp/journey-cmdn-ctrlbt = pinned harness d616df71938 + this journey file only), whole host, through the mini scheduler: running (base build 36f99fd60cd8db2005c2a85f, head build 937a3d05b62f8efcdba10ea2, 6 rounds each, every round counted).

Observed / Not run

  • Observed: the compile, the red and green steps above (their logs read).
  • Not run yet: the rest of the journey rounds (running); the full CmuxNext suite; macOS 14/15.

Changelog

  • Fixed: Text typed right after Cmd-N and then Ctrl-` now goes into the new terminal at once.

No capture: key routing only; nothing on screen changes.