Skip to content

Static (non-dirty) elements vanish from screen after the first redraw because full-screen Clear() runs every frame #109

Description

@matt-edmondson

What's wrong

UIApplication.Render() unconditionally calls ConsoleProvider.Clear() (wiping the entire terminal buffer) on every render pass, but UIElementBase.Render() only actually draws content when IsDirty is true:

if (IsDirty) { OnRender(provider); IsDirty = false; }

IsDirty is reset to false immediately after an element's first draw. ProcessInputAsync calls Render() again after every processed input, regardless of which element(s) the input affected.

These two mechanisms fight each other: the screen is fully cleared every frame, but only elements still flagged dirty get redrawn. Any element that isn't re-marked dirty by the input that just happened disappears from the screen on the very next frame.

Failure scenario

Build any app with a BorderElement wrapping static TextElements plus one interactive child (e.g. a text input). Press any key that the interactive child handles but that doesn't invalidate the border/label. On the next render pass: the terminal is cleared, the interactive child (still dirty) redraws, but the border and static text (no longer dirty) are skipped — they vanish. This reproduces on the very first keystroke in the most ordinary layout (a label next to a focused control).

Suggested fix

Pick one rendering model instead of combining both:

  • Drop the per-Render() ConsoleProvider.Clear() and rely purely on dirty-region drawing (write only changed regions, no full clear), or
  • Drop the dirty-check gate for the full-clear model and always call OnRender on every pass so the whole tree redraws after each clear.

Acceptance criteria

A layout with static and interactive elements retains all static content on screen across multiple render passes triggered by unrelated input.

Activity

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

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions