Repository navigation
m14 drags: each terminal follows its pane in every frame of a divider drag (delete the drag hold) - #36328
Conversation
…rame of a divider drag (red) cmux-ad m14 (Lawrence's P0) and m18: in every frame of a divider drag and of its release spring, each terminal takes that frame's pane size (its text re-wrapped by the reflow preview), never the drag-start size. On feat the drag hold (terminalDrag.holdSurface, default on) keeps each surface at its drag-start size through the drag, and the release spring holds its final size. - DividerDragTerminalSteadyTests (rewritten to the m14 contract; switch motion.frameOwner.terminals off): every drag step and release frame, each surface's size is its host area's; a drag that catches a split's spring follows from its first frame; a surface swapped in mid-drag takes its pane's size. - TerminalDividerDragFrameTests (display; switch off and on): per committed frame, top-left on its area, a size its pane had, a new size in at least half of the 20 drag frames; after the landing, the pane's size and the PTY's newest grid the one the view fits. Sidebar-Look: no visual change
…llows its pane in every drag frame cmux-ad m14 (Lawrence's P0, "resizing splits/columns, still not animating the terminals") and m18 T-DRAGS. The drag hold (terminalDrag.holdSurface, RESIZE VIDEOS A3, default on) kept each terminal's surface at its drag-start size for the whole drag, clipped or beside the terminal background, and the release spring held its final size (pixel-perfect's trace, STATUS 13764: 157-159 held ticks per col-drag-2 film). - Delete TerminalDragTunables.holdsSurfaceDuringDrag (`terminalDrag.holdSurface`) and its path. - A drag's first frame ends a spring's hold it caught (endPaneMotion); from there the surface takes its pane's size in every frame through the placement every resize uses (TerminalHostView.placeSurface, the frame owner's place(_:anchor:)), with motion.frameOwner.terminals' present rule. The reflow preview re-wraps the text at each size (no final grid is reported during the gesture, so it stays on). - The release spring of a drag holds no final size and reports no final grid at its start (paneMotionWillRest and joinPaneMotion skip restAt while the drag is followed): the surface keeps following its pane, and the grid goes when the release lands, as before (one PTY resize per drag). The m18 25 ms coalescer replaces that hold in frame-owner-s4's T-KEYS report path. - stopFollowingResizeGesture() has no hold to release. Sidebar-Look: no visual change
The What's New highlight for 96ad37a (cmux-ad m14 drags): each terminal resizes with its pane and re-wraps its text in every frame of a divider or column-edge drag. Sidebar-Look: no visual change
… (red at b72c7e2) Codex review of b72c7e2 (blocker): the drag was told only to the surfaces shown at its start (ScreenContentView.resizeGestureMoved collects the followers once). A fresh surface a replay installs mid-drag (TerminalSession.swapSurface -> TerminalHostView.install) did not follow it: its release spring held its final size (restAt) and it reported a grid on every drag frame. aSurfaceSwappedInMidDragFollowsTheDrag (replaces aSurfaceSwappedInMidDragTakesItsPanesSize): the fresh surface follows the drag under way, takes its pane's size in every drag step and release frame, and stops following when the release lands. Sidebar-Look: no visual change
…e swapped in mid-drag follows it too Codex review of b72c7e2: - (blocker) The drag is told to the TerminalHostView, which outlives a surface swap (PaneResizeGestureFollowing moves from TerminalSurfaceView to the host). The host tells the surface it shows (followResizeGesture), and a surface joins its new host's drag when it moves into it (viewWillMove(toSuperview:)); leaving its host, it stops. The host forgets a drag when it leaves its window (no end may reach it then), as the surface already did. - (should-fix) TerminalDividerDragFrameTests pins motion.frameOwner.terminals before each frame: the store is process-wide and another suite may set it at an await. - (nit) Its comment said a drag does not read the switch; a drag takes the switch's present rule. Sidebar-Look: no visual change
… count (god-file rule) b78df0c added the host's followsResizeGesture (2 lines) to a file already over its 400-line limit on the base (558 lines); two doc comments it touches each take one line now. Sidebar-Look: no visual change
…gs-live-terminals
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Default changesThis pull request changes 3 defaults at
Signed off on this commit by Merge receipt: merged as Regenerate the snapshot with Shipped in:
|
|
Base finding, not this PR: |
|
Review (claude-review-subagent): SHIP at 216a6d1 Independent review subagent (correctness first, read-only, no build), relayed by the lead at 11:00Z. No blocker. Nits for a follow-up PR (not pushed here, a push voids this receipt):
|
|
Review (claude-review-subagent): SHIP at 216a6d1 Independent review subagent, posted by the perf lead because the owner stopped on an API overload. No blocker. Follow-up nits (a later PR, not this head): the release-spring guard in paneMotionWillRest needs a red/green test (release away from the last move); rename or assert the TerminalDividerDragFrameTests resize count; update the PaneResizeGestureFollowing doc (RestingPlacement.swift:64) and the stale holdSurface text in bench-terminal-resize.py; clear followsResizeGesture on any window change. |
|
Check classification at head
|
…gs-live-terminals # Conflicts: # Packages/macOS/CmuxNext/Sources/CmuxNextDesign/Tunables/TerminalDragTunables.swift # Packages/macOS/CmuxNext/Sources/CmuxNextTerminal/TerminalHostView+PaneMotion.swift # Packages/macOS/CmuxNext/Tests/CmuxNextAppTests/DividerDragTerminalSteadyTests.swift
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (claude-review-subagent, started by lead): SHIP at 9d57187 Scope: only the merge of feat Method
#36311 lines: none lost
#36328 lines: none lost
Tests
One PTY grid per drag with
Observed / Not run
|
Conflicts, both sides kept: - TerminalDragTunables: feat (#36328, m14) deleted terminalDrag.holdSurface; this branch (m26) deleted motion.frameOwner.terminals. Neither switch is left (all: []). - TerminalHostView+PaneMotion: feat's drag-following extension (PaneResizeGestureFollowing on the host) plus this branch's switch-free key-resize doc. - TerminalHostView: releaseSurfaceHold doc names a caught drag and a followed key press. Tests feat added with the deleted switch pinned (DividerDragTerminalSteadyTests, TerminalDividerDragFrameTests) no longer pin it; the drag frame test checks the always-on rule (no stretched frame). Sidebar-Look: no visual change
cmux-ad m14 and m18 (Lawrence's P0, "resizing splits/columns, still not animating the terminals"): in every frame of a divider or column-edge drag, and of the spring its release starts, each terminal takes that frame's pane size and its text re-wraps at that size. The program in it gets its new size when the drag lands.
Why
terminalDrag.holdSurface, RESIZE VIDEOS A3, on by default) kept each terminal's surface at its drag-start size for the whole drag: cut where the pane was narrower, the terminal background beside it where the pane was wider.restAtmoved the hold to the final size, so the release spring showed the final grid, not the pane's size.motion.frameOwner.terminalson or off.Fix
TerminalDragTunables.holdsSurfaceDuringDrag(terminalDrag.holdSurface) and its path (TerminalSurfaceView+PaneMotion.swift).endPaneMotion()).TerminalHostView.placeSurfaceand the frame owner'splace(_:anchor:)), with the present rule ofmotion.frameOwner.terminals:TerminalFramePresenter(frame-owner-s4's T-KEYS changes "keep").TerminalGridPolicy.previewsViewGridstays true.paneMotionWillRestandjoinPaneMotionskiprestAtwhile the drag is followed). A final grid at the start would setgeometry.finaland turn the preview off for the spring.stopFollowingResizeGesture()has no drag hold to release any more.No present-mode override for drags: the drag follows the switch, which T-KEYS turns on by default (m18).
Changelog
Frames
motion.frameOwner.terminalsoff, Ghostty's frame of each size shows 1-4 refreshes after the bounds (top-left, not stretched); with it on, the frame owner's ready-or-keep.Tests
Red first (
2399b3523bf, tests only, on feat9ac955e274c), then the fix (96ad37a03a3); a second red/green pair for Codex round 1's blocker (ca64d25e72etest,b78df0c4f55fix). The head merges feat (216a6d14b74).2399b3523bf7c4ee94d75b6ddb8d88e290dDividerDragTerminalSteadyTestsFAIL: p1's surface took 1 width in 30 drag steps (widths.count → 1), "drag step 1: p1's surface (600.0, 800.0) in a (592.0, 800.0) area" ...; the swap test: the surface held at 600 pt.DividerDragTerminalResizeCountTestspasses.2399b3523bf58d8d7065b215146f8919a23TerminalDividerDragFrameTestsFAIL, both switch values: "new sizes in drag frames [0, 0]" of 20; frames behind their pane [20, 20] (off), [21, 21] (on)96ad37a03a3807d9ee21deb7bfe0713d1ffSplitSpringMotionTests.fiveRapidSplitsAreOneMotionfails on its 8.33 ms frame-time bound (28.1 ms), a timing test with no drag, the same test that failed at #35940's head (2ff367f37c3d6070185f8309, 11.66 ms)ca64d25e72e4de6e21ebb4e7fb530560fffaSurfaceSwappedInMidDragFollowsTheDragFAIL:fresh.isFollowingResizeGesture → false216a6d14b745cf38b4cf9c34221b74af108ci-step m14d2-green exited 0: 36 suites, 187 tests216a6d14b74dd5500c490fe9bed76d6b35eci-step m14d2-display-216a6d14b74 exited 0. TerminalDividerDragFrameTests: switch off, new sizes in drag frames [20, 20] of 20, 0 frames behind their pane; switch on, [17, 17] of 20, 20 frames behind (the presenter's keep path: each size shows one commit later; T-KEYS deletes "keep"); misplaced 0, unsized 0, stretched 0, PTY grids [1, 1]216a6d14b74bdb41a9fe9c381e4682715ac(tag m14-drags-v1)Observed / Not run
b72c7e2d3fa: FIX. (1) blocker: a surface swapped in mid-drag did not follow the drag; fixed red-first (ca64d25e72e,b78df0c4f55): the host follows the drag and a surface joins its host's drag. (5) should-fix: the display test pins the switch before each frame; fixed. (4) The PTY count is asserted byDividerDragTerminalResizeCountTests(one grid per drag, none mid-drag; unchanged and green); this PR keeps that rule until T-KEYS' 25 ms coalescer. (2) A forced report (a terminal shown mid-drag) still sends at once, as before this PR. (3) Not verified: a drag that catches a running key-resize hold (FRAME OWNER S3followedHold). With the switch off the host's follow rule may keep the key hold's size until that hold ends; no test here covers a drag during a key spring.motion.frameOwner.terminalson (the default from perf: resize perf paths on by default (cmux-ad m19, no switches) #36311), a drag shows each size one commit late, through the presenter's "keep" (display stepdd5500c490fe9bed76d6b35e: 17 of 20 drag frames take a new size, 20 frames one commit behind the pane). frame-owner-s4's T-KEYS PR deletes "keep". With the switch off: 20 of 20, 0 behind.px-col-drag-2-sw-terminalsat96ad37a03a3against base feat9ac955e: held terminal frames 155-161 at the base, 0 at the head. One terminal edge frame per film at the release (p0's high side cut by 102 px or more). No other new red.9d5718797f84a02bed13ebd4b57d527e84e449d5(after the feat merge): launch smoke PASS on macOS 14.8.7 and 15.7.7 (os-matrix step5d88e49aad86d5579008326d, builddc809e30886d6b7643c3ce94, 0 crashes, 0 hangs); focused suites8b429b07ee626b091b4c0cfcexit 0 (10 suites, 51 tests).