Skip to content

Preclude stale screen content in full-screen mode#75

Draft
seh wants to merge 1 commit intocharmbracelet:mainfrom
seh:force-abs-positioning-in-full-screen-mode
Draft

Preclude stale screen content in full-screen mode#75
seh wants to merge 1 commit intocharmbracelet:mainfrom
seh:force-abs-positioning-in-full-screen-mode

Conversation

@seh
Copy link

@seh seh commented Jan 27, 2026

When ultraviolet runs in full-screen (alternate screen) mode with frequent updates to the same screen positions, relative cursor movements can interact in ways that cause the terminal to fail to overwrite old content, leaving stale screen content visible. Components like the bubbles library's spinner that update repeatedly on the same line can induce this problem.

The original cursor movement optimization logic assumed reasonably that using relative positioning operations (carriage return, cursor up, reverse index) would be safe and efficient for short distances when the cursor position is known. However, in full-screen mode with rapid updates, combinations of these relative movements can cause the terminal state to become inconsistent with what ultraviolet expects, resulting in content that should have been overwritten remaining visible.

Instead, force ultraviolet to always use absolute cursor positioning (e.g. CUP as ESC[<row>;<col>H) in full-screen mode. While the original relative movement approach works for simple or infrequent updates, absolute positioning is more resilient in full-screen mode because each movement is independent, rather than relying on accumulated state. The trade-off is slightly longer escape sequences, but this ensures reliable visual updates without stale content remaining visible.

Note that this changes only how full-screen mode works; the behavior of inline mode behavior remains unchanged.

  • I have read CONTRIBUTING.md.
  • I have created a discussion that was approved by a maintainer (for new features).

When "ultraviolet" runs in full-screen (alternate screen) mode with
frequent updates to the same screen positions, relative cursor
movements can interact in ways that cause the terminal to fail to
overwrite old content, leaving stale screen content visible.
Components like the "bubbles" library's spinner that update repeatedly
on the same line can induce this problem.

The original cursor movement optimization logic assumed reasonably
that using relative positioning operations (carriage return, cursor
up, reverse index) would be safe and efficient for short distances
when the cursor position is known. However, in full-screen mode with
rapid updates, combinations of these relative movements can cause the
terminal state to become inconsistent with what "ultraviolet" expects,
resulting in content that should have been overwritten remaining
visible.

Instead, force "ultraviolet" to always use absolute cursor
positioning (e.g. "CUP" as "ESC[<row>;<col>H") in full-screen
mode. While the original relative movement approach works for simple
or infrequent updates, absolute positioning is more resilient in
full-screen mode because each movement is independent, rather than
relying on accumulated state. The trade-off is slightly longer escape
sequences, but this ensures reliable visual updates without stale
content remaining visible.

Note that this changes only how full-screen mode works; the behavior
of inline mode behavior remains unchanged.
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