Skip to content

feat: support synchronized output (DEC private mode 2026) - #237

Open
smohekey wants to merge 1 commit into
TerminalStudio:masterfrom
smohekey:feat/synchronized-output-2026
Open

feat: support synchronized output (DEC private mode 2026)#237
smohekey wants to merge 1 commit into
TerminalStudio:masterfrom
smohekey:feat/synchronized-output-2026

Conversation

@smohekey

Copy link
Copy Markdown

What

Honour DEC private mode 2026 (synchronized output). Applications that redraw a full frame bracket each atomic update in ESC[?2026hESC[?2026l to tell the terminal "don't paint until I'm done." xterm.dart ignored the mode and painted every intermediate write, which shows as flicker during redraws — notably with ratatui-based TUIs such as the Codex CLI, which brackets every frame this way.

How

Suspend notifyListeners() between begin and end, then flush a single repaint on end so the completed frame appears atomically. A 150 ms safety timeout force-ends the update if the matching ?2026l is lost (e.g. across a reconnect), so the display can never stay frozen.

Reproduce

final terminal = Terminal()..resize(20, 5);
var repaints = 0;
terminal.addListener(() => repaints++);
terminal.write('\x1b[?2026h'); // begin
terminal.write('hello');       // held - no repaint
terminal.write('\x1b[?2026l'); // end - one repaint of the finished frame

Test

Adds test/src/synchronized_output_test.dart covering repaint suppression between begin/end, the flush on end, and that normal writes still repaint when no update is held.

Applications that redraw a full frame (e.g. ratatui-based TUIs such as the Codex
CLI) bracket each atomic update in `ESC[?2026h` … `ESC[?2026l` to tell the
terminal "don't paint until I'm done". xterm.dart ignored the mode and painted
every intermediate write, which shows as flicker during redraws.

Honour mode 2026: suspend `notifyListeners()` between begin and end, then flush a
single repaint on end so the completed frame appears atomically. A 150ms safety
timeout force-ends the update if the matching `?2026l` is lost (e.g. across a
reconnect) so the display can never stay frozen.
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