fix(app): held Control shortcuts, replays and hold ends deliver each key to its own terminal (P0 1193 follow-up)

LA
5d ago
+237-42

Summary

Follow-up of #29301 (P0 1193, held keys during a pending creation). It fixes the low findings of #29301's independent review (receipt at 201b1e4c804) and one gap of the same class found while checking #29530's finding. All of them can send a key to a terminal other than the one it was typed for, or lose it.

  1. A held Control shortcut runs on the terminal it was typed for. Before, only Command chords of a lane whose terminal is not focused went through app dispatch; Ctrl-`, Ctrl-Tab and Ctrl-1..9 were typed into that terminal as bytes. Now every chord (Command or Control) runs with that terminal's tab as its target and its key context; a chord that is no app shortcut (Ctrl-C) stays that terminal's key.
  2. A replay keeps each key's own terminal. When a replayed key opened a new creation (a held Cmd-D), prepend gave every later key the new creation's lane, so a line held for another terminal ran in the new split. Now each key keeps its lane (HeldKey carries it); only the issuing key's own lane moves to the new creation; keys carried into a new hold keep their terminal (adopted lanes).
  3. A remote split's keys reach its machine. A split's held keys record the split pane's own machine (daemon.machineID), not the window's, so the daemon path reaches a remote split whose view was evicted.
  4. At a hold's end, a key runs "as typed" only into its own terminal. Before, the focused lane's keys ran again through NSApplication.sendEvent into whatever had the keyboard, so a hold that ended at its bound while the terminal's view was out of the window (a remount) lost them. Now the end names a focused terminal only when its shown view has the keyboard (keyboardTerminal, the check the early view already used); otherwise the terminal's own encoder types the keys. (#29530's claim that the 2 s bound counts from the hold's start does not hold: a pending creation has no bound; the bound starts at the reply.)

Base: this PR is stacked on #29301's branch fix/p0-1193-key-lanes. After #29301 merges, its base moves to feat-cmux-next (no rebase).

Testing

SecondCreationKeysTests (CmuxNextAppTests, real same-tree daemon, display steps on the fleet, CMUX_TEST_REQUIRE_GUI=1, console session):

RefWhat it isJobResult
cb962cf53bd (fix/p0-1193-followup-red-base)#29301's code 201b1e4c804 + these tests only43fa946541a7fd8f597a307d6 pass; 3 fail, each first on the outcome: test 7 "the held Ctrl-` opened no tab" (1); test 8 "the line typed for the second terminal ran in the new split" (2); test 9 "lost at the hold's end" (4)
bd1112a1cfa (this head)the fix92b8615008f3941cdf53fa799 of 9 pass; HeldKeyInputTests 3 of 3

More reds for test 9 alone (only the hold-end fix taken back): 8141f17fd895332cac6f392a, e6197633b8b7838f3220b23e, f65f2f0a64d66bc7c8012bed. Compiles: head 6df16fb0dc239829df48219d, base red ref e39660a3bfcf30538a45bbe9.

Observed / Not run

Observed: the runs above, each log read before counting. An earlier test-8 failure on red and green alike was the test rig: its 20 s wait-for ran on the app's own daemon connection, whose requests run in order, and held back the split it waited for; the test now reads app state first.
Not run: finding 3 (remote split with an evicted view) has no test of its own (it needs a second machine); a journey round of the follow-up cases.

Performance

No perf numbers: a correctness fix. The added work runs only when a creation hold ends or a held key is replayed; no work moves onto the main thread outside those paths. perf claim: none.

Changelog

Fixed: Shortcuts and lines typed while new panes open no longer run in a pane other than the one they were typed for

Proof

No capture: key routing between terminals; the evidence is the fleet display tests above.


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


Summary by cubic

Fixes P0 1193 follow-up key-routing bugs so held shortcuts, replayed keys, and keys at a hold's end reach the terminal they were typed for instead of another terminal or no terminal at all.

  • Held Control shortcuts (Ctrl-`, Ctrl-Tab, Ctrl-1..9) now run as app shortcuts on the terminal they were typed for; previously only Command chords did, and Control chords were typed into that terminal as bytes.
  • A replayed key that opens a new creation keeps every later key on its own terminal; only the issuing key's lane moves to the new creation, and keys carried over from another hold keep their terminal.
  • A remote split's held keys record the split pane's own machine, not the window's, so the daemon path reaches a split whose view was evicted.
  • At a hold's end, a key runs "as typed" only when its terminal's view has the keyboard; otherwise the terminal's own encoder types it.
  • A held chord with no app shortcut (Ctrl-C) stays in its terminal's typing run, so keys keep the order they were typed in even when the terminal's view is gone.

This PR is stacked on fix/p0-1193-key-lanes and moves to feat-cmux-next once #29301 merges.