cmux NEXT: live resize content follows the window edge every frame
Summary
Leo, on the latest nightly-next: live resize was smoother, but the content still snapped instead of following the window edge. During a drag, the content now keeps up with the window on every frame.
-
Terminal grid.
ResizeCoordinatorheld each new grid until it had been stable for 3 frames (ResizeSettle). The size changes on every frame of a drag, so the grid trailed the window by 3ā4 frames, then jumped. While the window is in a live resize, it now applies after 1 stable frame. At rest it still waits 3. -
Springs.
MotionPolicynow knows about live resize (Motion.isLiveResizing, from NSWindow's live-resize notifications).animatesMovementis false during a drag, so a layout change that lands mid-drag snaps to the next frame's size instead of springing toward a stale one. -
Tab strip. The edge-fade mask no longer animates when overflow starts mid-drag.
-
Agent transcript. Rows rewrap to new heights when the width changes, and the 180 ms glide used to run on every one of those commits during a drag. It now runs only when the rows themselves change, and any glide already running finishes at once when the rows rewrap.
-
Sidebar and the web view frame: no change needed. Both already followed the window in the same frame.
-
One grid in flight. Mid-drag, a terminal keeps at most one grid waiting for the daemon's echo. A newer size waits in the settle queue until that echo lands, so a fast drag no longer floods the daemon with resizes or overflows its queue.
ResizeCoordinator moves into CmuxNextBridge, next to ResizeSettle, so CmuxNextApp stays under its line cap. The DEBUG per-frame resize trace used during the investigation is not part of this PR.
Testing
-
Frame trace. Measured on cmux-mac-mini-cua-4 (60 Hz) in tagged DEV builds: base 48afd67, fix d82294f. Each build ran the same scene through 4 scripted ±300 pt corner drags.
base fix terminal grid lag behind the window (frames) p50 3, p95 4 p50 1, p95 2 live frames where the grid matches the window 5/240 91/240 transcript samples with a glide running 234/238 0/240 frame time p50/p95/max 16.7 ms, 0 missed 16.7 ms, 0 missed -
Swift
LiveResizeTrackingTests: -
Web
agent-pane-chat-column: -
One grid in flight,
aDragKeepsOneGridInFlightPerTerminal: -
On the merged head:
-
Other checks: check-concurrency, check-motion, crash_ratchet, check-system-blue, check-no-godfiles (every touched Swift file is line-neutral),
bun run check, and ui-rules.
Left over
- The terminal still trails the window by 1ā2 frames. That remaining lag is the daemon round trip (resize, then the
resizedevent, thenset_grid). - WebKit and CEF composite inside the engine, outside this change.
Motion.isLiveResizingis app-wide. A drag in one window also snaps springs and the transcript glide in other windows for its duration. This is cosmetic; making it per window is a possible follow-up.ui.paneAnimationsis off by default on base now, so the mid-drag spring snap matters only with pane animations on.- A spring already running when a drag starts is not snapped.
- A reply streaming during a drag can still glide the transcript once between width frames: a new row clears the rewrap guard. Idle chats are covered by the web test.
Review fixes (2e77006): a terminal now keeps the claims still awaiting their echo, so a drag no longer leaves it re-claiming on the next key press; the agent page's motion tokens leave live resize out, so a page loaded mid-drag keeps its move duration; the DEBUG resize trace stops with the probe.
Changelog
Fixed: During a window resize, the terminal, tab strip and agent chat follow the window edge instead of snapping a few frames behind.
Proof
Before and after, the same scripted drag (sidebar, tab strip, a real agent chat, a terminal):

Full quality:


The host name in the terminal prompt and the composer chip is blurred.
š¤ Generated with Claude Code