Fix blank first page of scrollback after initial output burst#100
Merged
Conversation
When a fresh terminal rendered its initial (mostly empty) viewport and then received a burst of output that overflowed the screen, the scrollback promotion optimisation incorrectly kept the stale empty buffer rows as scrollback instead of fetching the real content from libghostty. The promotion assumes buffer rows match what libghostty scrolled off. This holds in steady state (cursor at bottom, top rows scroll off unmodified) but fails during bootstrap: the cursor starts at the top, output overwrites the empty viewport rows before they scroll off, so the buffer has stale content. Skip promotion when scrollback_in_buffer == 0 AND delta >= rows (the entire viewport scrolled off). When delta < rows, only the topmost rows scrolled off — those sat above the cursor and were not overwritten, so promotion (and its text-property preservation) remains safe.
There was a problem hiding this comment.
Pull request overview
Fixes a rendering/scrollback sync edge case where the first page of scrollback could appear blank after a fresh terminal receives an initial burst of output, by preventing promotion of stale viewport rows during bootstrap and instead re-fetching the correct scrollback rows from libghostty.
Changes:
- Add a regression test covering “bootstrap + burst output” to ensure scrollback contains real content (not stale empty rows).
- Update scrollback promotion logic in
redraw()to skip promotion whenscrollback_in_buffer == 0and the scroll delta is at least a full viewport height, falling back toinsertScrollbackRange.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
test/ghostel-test.el |
Adds an ERT regression test asserting scrollback isn’t populated with blank/stale rows after an initial output burst. |
src/render.zig |
Adjusts scrollback sync/promotion logic during redraw to avoid promoting stale initial viewport rows when the entire viewport scrolls off before first scrollback materialization. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scrollback_in_buffer == 0anddelta >= rows(entire viewport scrolled off during bootstrap)delta < rows) still promote — the top rows sat above the cursor and weren't overwritten, preserving text properties (URLs, prompt markers)Test plan
ghostel-test-scrollback-bootstrap-not-blank— fails without fix, passes with itghostel-test-scrollback-preserves-url-propertiesstill passes (promotion preserved for small deltas)make -j4 all— 140 tests passls -l /usr, enter copy mode, scroll to top — should show actual content