P0 RESIZE KEYS K1: keyboard pane resize steps from the shown size and stops at the shown limit (no dead presses)

Merged
LA
2d ago
+170-9

Summary

P0 RESIZE KEYS K1 (cmux-ad 2026-11-02: "still dont have pixel perfect ctrl shift hjkl for resizing"). At a pane's minimum or maximum size, keyboard pane resize (Ctrl-Shift-H/J/K/L and Ctrl-Cmd-arrows, resizePane*) went dead:

  • Film rk-limit (feat 507438d, 120 Hz 2x virtual display, real HID keys): Ctrl-Shift-H twelve times on p1 of p0 | p1 moves the divider 57.5 pt per press until p0 reaches its minimum width. Presses 8 to 12 move nothing. Of the four Ctrl-Shift-L after them, the first two move nothing and the third moves 30.5 pt. At the maximum, the first press back moves 30.5 pt.
  • Cause: PaneResize.change clamped the ratio to SplitRatio.range (0.05...0.95) and a column width to 0.1...1.0. SplitGeometry and the strip hold each pane at its minimum size much earlier. So presses past the visible limit changed the model and the daemon value but not the screen, and the way back had dead presses and then a part step.
  • Fix: PaneResize.change takes the screen's ShownResizeRange (new, CmuxNextLayout; LayoutRootView.shownResizeRange(ofScreenContaining:) reads the geometry the last sync computed: no layout pass). A press now moves one whole step, the part step that reaches the limit, or nothing (refused quietly, as before at 0.05). A value already past the limit counts as the limit, so the first press back is a whole step. The App line it adds is paid in the same handler (app_lines -1).

Films and judge: https://cmux-orchestrator-1.tail137216.ts.net/resize-videos/rk-feat507-g2-120x2/ (rk-limit), judge scripts/journeys/video-cases/judge_keys.py on kit branch cp/resize-keys-kit.

Testing

Red first, on the fleet (scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext ...):

  • Red: step 78090406fa3de322bdd0261d at e4672b8ad98 (test + stub): KeyboardResizeShownLimitTests FAILED (the column test: a press toward the minimum moved 0, and the way back moved [0.0, 23.5, 57.5] pt).
  • Green: step dc7229973226ef57e3a8b299 at aff6931be8a: KeyboardResizeShownLimitTests, PaneResizeGestureTests, DividerResizeMathTests PASSED.
  • GUI proof (display worker, gui-session-v1, CMUX_TEST_REQUIRE_GUI=1) at the exact head: step f400feeedb7572ed320806e9 PASSED at aff6931be8af56c030ea613cd8f27b05810ffbc9 (KeyboardResizeShownLimitTests 2/2, PaneResizeGestureTests 4/4, DividerResizeMathTests 6/6).
  • After-fix films on a build of this head (fb5d3a1e): 3 of 3 runs show the fix (rk-k1fix-l1/l2/l3-120x2).
  • Note: the red result line was written when the step was still compiling; the step then failed as written (review comment 6581536125).

Observed / Not run

  • Observed: the red and green steps above; the films of the bug on feat and on the dogfood source (rk-limit, both builds).
  • Not run: Release build. Docked columns (left/right/top/bottom docks) keep today's behavior at their limits (review note 1).

No capture: keyboard resize motion is filmed by the RESIZE KEYS kit at 120 Hz (gallery link above), not by a still.

Dogfood port: fix/resize-keys-shown-limit-dogfood-2 into cp/dogfood-v2-2-12-opt (separate PR).

Changelog

  • Fixed: Keyboard pane resize (Ctrl-Shift-H/J/K/L, Ctrl-Cmd-arrows) no longer has dead key presses at a split pane's or a strip column's minimum or maximum size; the first press back moves a whole step. (Docked columns are not changed.)

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


Summary by cubic

Fixes keyboard pane resizing (Ctrl-Shift-H/J/K/L, Ctrl-Cmd-arrows) so presses at a pane's minimum or maximum size no longer go dead: a press now steps from the size the screen actually shows and stops at the shown limit, and the first press back moves a whole step.

  • PaneResize.change now takes a ShownResizeRange computed from the last synced screen geometry and clamps its step to what the screen can show instead of the full model range.
  • A value already past the shown limit counts as the limit itself, so a press back from a limit is a full step rather than dead presses followed by a partial move.
  • Adds KeyboardResizeShownLimitTests covering split and column resize toward both minimum and maximum limits.

No migration steps required.