Repository navigation
fix: terminal content duplication on window resize (revives #4765) - #6386
Conversation
…he-window-duplicates-terminal
…he-window-duplicates-terminal
…esizes Revives @austinpower1258's stalled fix for terminal content duplication on window resize (manaflow-ai#3052), rebased onto current main. Root cause is cmux's embedding layer, not the vendored ghostty fork (1.3.2-dev already carries the upstream emulator reflow fix manaflow-ai#10258): ghostty's single set_size API drives both renderer pixels and PTY geometry, so sub-cell pixel churn during an AppKit live-resize drag fires a SIGWINCH storm and the child app repaints over itself. The fix coalesces pixel-only resizes (only forward set_size when the grid's columns/rows actually change) and flushes the exact final size on viewDidEndLiveResize. Coalescing is gated strictly to the live window-resize phase so programmatic/SSH/split resizes always apply. Conflict resolution: main added manual-I/O (tmux mirror) reflow suppression in the same `if sizeChanged` block. Resolved by running the coalescing guard FIRST, so a coalesced (skipped) resize never leaves a manual-I/O pane with DECAWM disabled, then the DECAWM-suppressed apply. Original implementation by @austinpower1258 in manaflow-ai#4765. Co-Authored-By: austinpower1258 <austinwang115@gmail.com> Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SyBXh77E4z96v18JS77oaN
|
@mvanhorn is attempting to deploy a commit to the Manaflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a ChangesPixel-only resize coalescing
Sequence DiagramsequenceDiagram
participant GhosttyNSView
participant updateSurfaceSize
participant TerminalSurface.updateSize
participant shouldApplySurfacePixelSizeChange
participant GhosttyTerminal
GhosttyNSView->>GhosttyNSView: viewDidEndLiveResize()
GhosttyNSView->>updateSurfaceSize: bypassLiveResizeCoalescing=true
updateSurfaceSize->>TerminalSurface.updateSize: coalescePixelOnlyResize=(isWindowLiveResizeActive && !bypassLiveResizeCoalescing)
TerminalSurface.updateSize->>GhosttyTerminal: query current surface metrics
TerminalSurface.updateSize->>shouldApplySurfacePixelSizeChange: current/target pixel dimensions
shouldApplySurfacePixelSizeChange-->>TerminalSurface.updateSize: false (pixel-only, no grid change)
TerminalSurface.updateSize-->>updateSurfaceSize: return early with scaleChanged only
updateSurfaceSize->>GhosttyNSView: invalidateTextInputCoordinates()
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 21 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (21 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…uplication # Conflicts: # .github/swift-file-length-budget.tsv
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Thanks for landing this, @austinywang. Reviving the stalled resize fix and clearing the terminal content duplication is great to see merged. |
|
Thank you for reviving this, @austinywang. Resolving the terminal content duplication on window resize is a fix a lot of people will feel. |
…n HEAD's resize model) main's #7318 viewDidEndLiveResize called updateSurfaceSize(bypassLiveResizeCoalescing:), but HEAD's refactored updateSurfaceSize lacks the coalescePixelOnlyResize model (#6386); HEAD applies resizes continuously during live resize. Call HEAD's updateSurfaceSize() (kept the new viewDidEndLiveResize + resetCursorRects cursor-shape). #6386 divergence recorded in merge-deferred-gaps. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Revives @austinpower1258's stalled fix in #4765, rebased onto current
mainwith the merge conflict resolved. Closes #3052.The bug
Drag-resizing the window duplicates/overlaps terminal content. This is not the vendored ghostty fork's emulator reflow — that's already fixed (the fork is
1.3.2-dev, past upstream's #10258). It's in the embedding layer: ghostty's singleset_sizeAPI drives both renderer pixels and PTY geometry, so sub-cell pixel churn during an AppKit live-resize drag (1 point = 2 Retina px) fires aSIGWINCHstorm and the child app repaints over itself.The fix (@austinpower1258's approach, preserved)
Coalesce pixel-only resizes: only forward
ghostty_surface_set_sizewhen the change actually alters the terminal's column/row grid, and flush the exact final size onviewDidEndLiveResize. Coalescing is gated strictly to the live window-resize phase, so programmatic / split / SSH-driven resizes always apply immediately.What this PR adds over #4765
main(the original PR was conflicting + red).mainadded manual-I/O (tmux mirror) reflow suppression in the sameif sizeChangedblock. Resolved by running the coalescing guard first, so a coalesced (skipped) resize never leaves a manual-I/O pane with DECAWM disabled — then the DECAWM-suppressed apply. This is directly relevant to the reportedcmux sshresize breakage.Original implementation and tests by @austinpower1258 (commits preserved in this branch's history).
Verification
xcodebuild ... -derivedDataPath ... build(CMUX_SKIP_ZIG_BUILD=1): BUILD SUCCEEDED, 0 errors.TerminalSurfaceResizePolicyTestswired (pbxproj test-wiring lint passes); CI runs the suite.cmux ssh, tmux reflow) on a maintainer machine.Planning + conflict resolution assisted by Claude Code.
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Fixes terminal content duplication on live window resize by skipping same‑grid pixel-only size changes, then applying the exact final size after the drag. Non‑live resizes and backing‑scale changes apply immediately.
viewDidEndLiveResize, bypass coalescing to apply the final size and invalidate text input coordinates.TerminalSurface.shouldApplySurfacePixelSizeChangeand addTerminalSurfaceResizePolicyTests; update test wiring and the file‑length budget.Written for commit 36d5d33. Summary will update on new commits.
Summary by CodeRabbit