Repository navigation
fix(core): force full repaint after resume - #1008
Merged
Merged
Conversation
altendky
requested review from
Hona,
kommander,
msmps and
simonklee
as code owners
May 1, 2026 20:31
kitlangton
enabled auto-merge (squash)
May 3, 2026 02:44
simonklee
approved these changes
May 4, 2026
Contributor
Author
|
thanks! |
3 of 6 tasks
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
CliRenderer.resume()so terminal contents are fully repainted after process suspend/resume.currentRenderBuffer.clear(this.backgroundColor)with the existing one-shotforceFullRepaintRequestedlatch.Problem
After
Ctrl+Z/fg, or equivalentSIGTSTP/SIGCONTflows, the terminal can contain stale content while OpenTUI's render buffers still believe cells are current.This is especially visible for blank or background-only regions: text and other non-background content may repaint, but blank/background cells can remain stale because diff rendering skips cells that compare equal.
The previous
resume()behavior tried to invalidate rendering with:That was the wrong invalidation model for this bug. It clears OpenTUI's current render buffer to the terminal background/default renderer background, not necessarily to the application's themed background, such as opencode's theme background. For cells that should repaint as blanks or background-only theme cells, this can make the current buffer compare equal to the next frame and skip exactly the cells that need to overwrite stale terminal content.
Fix
resume()now requests a one-shot full repaint:The existing
renderNative()paths consume that latch and passforce=trueto native rendering:lib.render(..., true)This keeps repaint recovery inside the normal render loop instead of issuing immediate native renders or raw terminal clear sequences from
resume().Screenshots
Fixes
Fixes #922
Fixes anomalyco/opencode#16327
Fixes anomalyco/opencode#22423
Replaces
Closes #928
Closes anomalyco/opencode#16326
The core idea from #928 is retained: use native forced repaint instead of clearing
currentRenderBuffer. This PR differs by using the existing one-shot render latch rather than calling native render immediately insideresume().The repaint portion of anomalyco/opencode#16326 should no longer be needed because stale terminal repaint recovery belongs in OpenTUI rather than opencode app code.
Related But Not Replaced
These address external suspend cleanup / mouse/raw-mode leakage and are complementary:
If OpenTUI later handles external
SIGTSTP/SIGCONTdirectly, that path should call the samesuspend()/resume()methods so this repaint recovery still applies.Testing
bun test src/tests/renderer.control.test.ts src/tests/renderer.console-startup.test.tsbunx tsc --noEmit -p tsconfig.build.jsonCtrl+Zthenfg