Skip to content

Paint the scene only on the theme's own page background - #38

Closed
NguyenDTAnh wants to merge 1 commit into
vaprdev:mainfrom
NguyenDTAnh:fix/panels-under-dialogs
Closed

NguyenDTAnh wants to merge 1 commit into
vaprdev:mainfrom
NguyenDTAnh:fix/panels-under-dialogs

Conversation

@NguyenDTAnh

@NguyenDTAnh NguyenDTAnh commented Oct 13, 2026 •

Copy link
Copy Markdown

Fixes the flicker in #37.

On a dark theme the wallpaper paints into dialogs, menus, the prompt, and the message, tool and code blocks in a session. The engine guessed the page color as the most common one in the frame, and on a session with a screenful of messages or tool output the most common color is those blocks' own surface - so the engine took it for the page and painted the scene into them. It recomputes its surfaces, and the tint it applies to them, every tenth frame and holds color changes under 3 levels back, so those cells flip back and forth, which reads as the block flashing.

The plugin already has the real page color: context.theme.background.base. This passes it into the engine and paints the scene only on cells the UI filled with it. Every other background - a dialog, a menu, a message, a tool block, the prompt - belongs to the UI. When the page color is not passed in the engine still falls back to the most common color, so dev/mock.ts and the checks are unchanged.

Measured on a real session (OpenCode 2.0.28, 160x45, dusk-aurora, ocean):

before after
cells the UI painted with a non-page background that the engine repainted 783 0
engine octant glyphs on a non-page background 252 0

dev/panels.ts covers the dialog case on a mock screen: a dialog window over a dusk-aurora-like scene carries no scene glyphs and is not repainted on surface recounts, on every wallpaper it is run against.

  • bun dev/panels.ts ocean (and the other wallpapers): ok
  • bun dev/check.ts --quiet: 126 runs, 0 failed
  • bun run typecheck: clean for src/ and tui.tsx

The scene no longer glows through surfaces that are a touch off the page color, which is what TINT_RANGE did for animated highlights; a highlight that is not the page color now reads as the UI's own.

@NguyenDTAnh
NguyenDTAnh force-pushed the fix/panels-under-dialogs branch from 7147040 to 7bc025d Compare October 13, 2026 17:50
@NguyenDTAnh NguyenDTAnh changed the title Keep the scene out of panels the UI draws over the page Show the scene only where the UI painted the page's background Oct 13, 2026
The engine guessed the page color as the most common one in the frame. On a
session with a screenful of messages, tool output or code, the most common color
is the message block's own surface, so the engine took that for the page and
painted the scene into the blocks. It recomputes its surfaces, and the tint it
applies to them, every tenth frame and holds color changes under 3 levels, so
those cells flip back and forth, which is the flicker.

The plugin already has the real page color: `context.theme.background.base`.
Pass it in and paint the scene only on cells the UI filled with it. Every other
background - a dialog, a menu, a message or tool block, the prompt - belongs to
the UI. Without it the engine still falls back to the most common color, so
`dev/mock.ts` and the checks are unchanged.

Measured on a real session (Opencode 2.0.28, 160x45, dusk-aurora, `ocean`):
after the change, no cell the UI painted with a non-page background is
repainted by the engine, and no engine octant glyph lands on one (0, was 783
repaints and 252 glyphs with the earlier heuristic).
@NguyenDTAnh
NguyenDTAnh force-pushed the fix/panels-under-dialogs branch from 7bc025d to 20ae146 Compare October 13, 2026 23:59
@NguyenDTAnh NguyenDTAnh changed the title Show the scene only where the UI painted the page's background Paint the scene only on the theme's own page background Oct 14, 2026
@NguyenDTAnh

Copy link
Copy Markdown
Author

Closing: the approach is wrong. The engine reads each cell's background color to decide what the scene may paint, but OpenTUI renders only the cells that changed, so a cell the UI did not repaint still holds the scene color from a previous frame. Restricting the scene to the theme's page color therefore makes the wallpaper vanish, and the original heuristic paints into dialogs, menus and message blocks. The right fix needs the frame diff (current buffer vs the buffer the engine wrote last frame) or a per-frame ownership mask from the host; I've rewritten issue #37 with the evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant