fix(next terminal): a divider drag resizes each terminal's PTY once, when the drag lands

Merged
LA
4d ago
+87-2

Summary

A person's divider, column-edge or row-edge drag resized each terminal's PTY once per cell the divider crossed. The program in each terminal (htop, vim, any TUI that redraws on SIGWINCH) redrew at every size while the daemon's grid announcements came a round trip behind the view, so the panes showed torn and stale rows during the drag. RESIZE VIDEOS P0 target (Lawrence 2026-11-02): "terminals reflow once at the end (one SIGWINCH), never garbage mid-animation". Audit item A3 in handoff/resize-videos/AUDIT.md.

Cause: during a drag the pane frames follow the pointer with no spring, so isInPaneMotion was false and TerminalSurfaceView.updateSurfaceSize reported every new grid. A split, a close and a zoom already hold: the final grid goes once at the spring's start. A Chromium page already holds through a drag (PaneResizeGestureFollowing).

Fix: TerminalSurfaceView follows the resize gesture too. Through the drag it holds the grid report and draws its grid reflowed to the pane locally (the reflow preview a split's spring uses); when the drag and its release's spring landed, it reports the grid it fits once. A release that springs already sends its final grid at the spring's start, and nothing more goes at the landing. The terminal size sample counts the drag as not settled. A terminal that leaves its window stops following (its layout root may go away before the drag's end reaches it), so it never holds reports for a drag that is gone (from the review).

Testing

Red/green on the fleet, DividerDragTerminalResizeCountTests (new): two real terminal sessions behind the app's ResizeCoordinator (the SplitTerminalResizeCountTests harness), a divider drag of 30 events of 8 pt with a frame and a delivery after each, then the release and its landing. It checks no PTY resize during the drag, exactly one per terminal for the whole drag, at the grid the view fits.

  • Red at d67ad0a906f3 (test only, base): step 7dec24846480dc792dc4f570 failed as expected: PTY resizes during the drag, and 28 PTY resizes per terminal for one drag (applied.count → 28).
  • Green at 409c037c11b7: step b9c818c91f2859f3b6eab604 on aws-m4pro-8 passed: DividerDragTerminalResizeCountTests, SplitTerminalResizeCountTests, PaneResizeGestureTests, TerminalPaneMotionFinalGridTests, PaneZoomTerminalResizeTests.
  • GUI-session proof at the head 302a63ea5868 (cmux-bot's merge of feat into the branch; the PR's own patch is unchanged): step baffbaa16b717bf9699fce9a on a gui-session-v1 worker (cmux10s, --display) passed: DividerDragTerminalResizeCountTests, PaneResizeGestureTests, SplitTerminalResizeCountTests.
  • GUI-session proof at 6c9b81b2c9db51645a39f6c3946c9fad633ba3c6: step df1af57e464e181b6ceb0104 on a gui-session-v1 worker (--display: the console session with a real window server) passed: DividerDragTerminalResizeCountTests, PaneResizeGestureTests, SplitTerminalResizeCountTests.
  • Green at 6c9b81b2c9db (head) on a GUI-session worker (--display, gui-session-v1, real window server and console session): step df1af57e464e181b6ceb0104 passed: DividerDragTerminalResizeCountTests, PaneResizeGestureTests, SplitTerminalResizeCountTests.
  • Green at 6c9b81b2c9db (head): step a74fa8584f0c5f385178e3a7 passed: DividerDragTerminalResizeCountTests, SplitTerminalResizeCountTests, PaneResizeGestureTests, TerminalPaneMotionFinalGridTests.
  • Compile: cmux-ci compile-check of 6c9b81b2c9db (app + CmuxNext, recipe 2) passed; 6e16dc60bda90252a40f8c60 passed at 409c037c11b7.

Observed / Not run

Observed: the steps above and scripts/cmux-next/prepush-gate.py (no new violations).
Not run: the real-app video of a divider drag over TUI panes (the RESIZE VIDEOS suite records it on a build with this change). A window live resize still reports per daemon echo (ResizeCoordinator, by design); this PR changes only pane drags.

Changelog

Changed: Dragging a pane divider resizes the programs in its terminals once, when you let go, so full-screen programs no longer redraw at every size mid-drag

Proof

No capture: the change is in what reaches the PTY; the test above counts PTY resizes with real terminals, and the RESIZE VIDEOS suite records the real-app video.