Fix viewport blanking after large programmatic scroll (setFrameSize re-entrance) (#110)
## Summary Cmd-End → Cmd-Home on a document taller than one viewport leaves the editor blank except for the first wrapped fragment. Viewport layout is correct; rendering is clipped because `contentView` and `contentViewportView` end up pinned to ~one-line tall while the textView itself is at full document height. ## Root cause When `relocateViewport(to: docStart)` calls `setFrameSize(width, lineHeight)` from a scrolled-down position, AppKit must synchronously retract the clip view to fit the new bounds. That fires `prepareContent` from inside `super.setFrameSize`, which calls `updateContentSizeIfNeeded` and re-enters `setFrameSize` with the full document height. The recursive call correctly resizes `contentView`. When control returns to the outer call, `newSize` is still the original (small) value, and `contentView.frame.size = newSize` stomps the recursive call's result. End state: textView at full height, `contentView` and `contentViewportView` at one-line height, fragment views past line 1 clipped. ## Repro Open a multi-screen word-wrapped document, Cmd-End, then Cmd-Home. The editor renders only the first wrapped fragment of paragraph 1. Resizing the window or toggling word-wrap restores rendering because both go through a fresh non-re-entrant `setFrameSize`. Verified in the bundled \`TextEdit.SwiftUI\` example with a ~24KB document; reverting the change reproduces the blanking. ## Fix After \`super.setFrameSize\`, read \`frame.size\` (which reflects any recursive resize) rather than the stale \`newSize\` parameter. When no re-entrance occurred, \`frame.size == newSize\`, so the common path is unchanged.
I
Ilia Sazonov committed
a534d12b48cca9b8fc6f99d0eb4cc827f128042f
Parent: c36bf60
Committed by GitHub <noreply@github.com>
on 4/28/2026, 8:22:57 PM