P0 RESIZE KEYS K4: Ctrl-Shift-J/K and Ctrl-Cmd-Down/Up move a row edge one exact step

Merged
LA
2d ago
+253-9

Summary

P0 RESIZE KEYS K4 (cmux-ad 2026-11-02, "pixel perfect ctrl shift hjkl"). In a column with two or more rows (rows-v1, New Row), Ctrl-Shift-J/K and Ctrl-Cmd-Down/Up on a row's pane did nothing (films rk-rows on feat 507438d and on the dogfood source: 4 presses, 0 motion). PaneResize.change looked for a vertical split in the pane's own row tree, then for a column dock band, and found neither.

Fix: with no vertical split in the pane's row, a vertical press moves the edge below that row (above it for the last row) one step, 5 % of the column height. ShownResizeRange.rowHeights(moving:in:by:) trades whole permille between the two rows (scaled as a filled stack places them), the exact inverse of RowStackGeometry.compute, so every press moves the edge (height + gap) * 5 % points; each row keeps 100 permille and its tree's minimum height, and a press there changes nothing. The press sends one setRowHeights intent, as a row drag's release. PaneResize.press (CmuxNextBridge) now holds the press for the App handler (app_lines -8).

Based on feat-cmux-next 4729158bf95, after #32421 (K1) landed. Commits cherry-picked from the earlier stacked branch fix/resize-keys-rows-3.

Testing

Red first, on the fleet (scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext ...), compile-checked first:
On the earlier branch (same code on the K1 branch):

  • Red 33c86843377 (test + stub): step 4c7110360ce6031586c0c741 FAILED (KeyboardResizeRowsTests: the first press moved nothing).
  • First fix 81d26743739: step 4695da174e153e514523a0b2 FAILED (each press 1.85 pt over the step: it reused the drag math without the row gap). Replaced by the third commit.
  • Fix 0ffb8453eb2: step b3ff1df9b1269bdae00d4ce6 PASSED: KeyboardResizeRowsTests 2/2, KeyboardResizeShownLimitTests 2/2, PaneResizeGestureTests 4/4.
    At this PR's commits:
  • compile-check 5507dfe5e6c7103b60fb1c4e at d5d5c04fcf0 PASSED. Red 1caf8f84c5c: step 00b1b53e90539096f0dcfea1 FAILED as expected (the first press moved nothing).
  • Review FIX FIRST at d5d5c04fcf0 (comment 6583295487): a row stored below its minimum stepped from the stored value (Down moved the edge up to 168 pt UP); rows off with [1000, 1000] sent heights the model drops; a band dock with rows lost its up/down extent.
    • Red 92e30dbe5f0 (new KeyboardResizeRowsEdgeCasesTests, code unchanged): step c76c7d3ce9744b135cc465fd FAILED (4 of 5 tests).
    • Fix 5d856196742 (step from the shown permille, stay in 100...1000, scrolling stack stops at the filling sum, band docks keep their extent); test fix 76e9d242628 (two edge cases pressed a pane in its own split and a dock already at its widest: test faults, see STATUS 7291).
    • Never-merge red 8e255ff2e21 (= 92e30dbe5f0 + the test fix, the code before 5d856196742): compile-check 2fe13ddd21f6138b91e048e8 PASSED; step b599ecb3f1e640255c355d85 FAILED as expected (4 of 5 tests, 9 issues).
    • Head 76e9d242628: compile-check 435bc457d32371945d989106 PASSED (CmuxNext with tests, app); green + GUI proof (display worker gui-session-v1, CMUX_TEST_REQUIRE_GUI=1) at the exact head 76e9d242628032a426f51e0527de064db24dc367: step 3d9875597a2de2ee67df63d9 PASSED: KeyboardResizeRowsEdgeCasesTests 5/5, KeyboardResizeRowsTests 2/2, KeyboardResizeShownLimitTests 2/2, PaneResizeGestureTests 4/4.

Observed / Not run

  • Observed: the red and green above; the before films rk-rows (feat and dogfood).
  • Not run: an after-fix film of rk-rows on a build of this head.

No capture: keyboard resize motion is filmed by the RESIZE KEYS kit (cp/resize-keys-kit).

Changelog

  • Fixed: Ctrl-Shift-J/K and Ctrl-Cmd-Down/Up resize a pane that sits in a row of a column.

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


Summary by cubic

Fixes Ctrl-Shift-J/K and Ctrl-Cmd-Down/Up so a vertical press on a pane in a rows-v1 column moves the neighboring row edge by exactly one step. Previously these presses did nothing because PaneResize.change only looked for a vertical split or dock band in the pane's row.

  • PaneResize.press (in CmuxNextBridge) now handles the new .rowHeights change and writes one setRowHeights intent, replacing the split-ratio and column-width handling in PaneHandlers.
  • ShownResizeRange.rowHeights(moving:in:by:) trades whole permille between the two rows as the exact inverse of row placement, so each press moves the edge (height + gap) * 5% toward the press; a press at a row minimum refuses quietly instead of moving.

Edge cases

  • The press steps from the shown row height, so a row stored below its panes' minimum never moves the edge the wrong way.
  • Presses never send heights outside 100...1000 (which the model would drop), and a scrolling stack never jumps more than one step when it fills the column.
  • A top or bottom dock band keeps resizing with up/down as before rows.