Skip to content

Conversation

@chrislloyd
Copy link

@chrislloyd chrislloyd commented Dec 4, 2025

Summary

Implements synchronized output mode (DEC private mode 2026) as specified in the VT extension.

  • BSU (CSI ? 2026 h) - Begin Synchronized Update: defers rendering
  • ESU (CSI ? 2026 l) - End Synchronized Update: flushes buffer atomically
  • DECRQM (CSI ? 2026 $ p) - Query mode support

This allows applications to batch terminal updates and render them atomically, preventing screen tearing during rapid output.

Features

  • Rendering is deferred when mode 2026 is enabled
  • Row updates are tracked and rendered atomically when mode is disabled
  • Safety timeout of 1 second auto-flushes if ESU is not received
  • Feature detection via DECRQM query

Test Plan

Before:

Screen.Recording.2025-12-09.at.09.15.57.mov

After:

Screen.Recording.2025-12-09.at.09.16.45.mov
  • Integration tests in SharedRendererTests.ts
  • Unit tests for DECRQM response
  • Manual testing with escape sequences in demo
  • All existing tests pass
  • Lint passes

Manual Testing

# Lines appear atomically after delay
printf '\e[?2026h'; for i in 1 2 3 4 5; do echo "Line $i"; sleep 0.2; done; printf '\e[?2026l'

# Feature detection - should respond with CSI ? 2026 ; 2 $ y (supported, inactive)
printf '\e[?2026$p'

Closes #3375

🤖 Generated with Claude Code

Implement synchronized output mode (CSI ? 2026 h/l) which allows
applications to batch terminal updates and render them atomically,
preventing screen tearing during rapid output.

Features:
- BSU (CSI ? 2026 h) pauses rendering, buffering row updates
- ESU (CSI ? 2026 l) flushes buffer and renders atomically
- Configurable timeout via synchronizedOutputTimeout option (default 5s)
- Exposed via terminal.modes.synchronizedOutputMode

Closes xtermjs#3375

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link
Member

@Tyriar Tyriar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you confirming the feature?

Bunch of CI failues

Comment on lines 157 to 159
// First request in this sync cycle
this._synchronizedOutputStart = start;
this._synchronizedOutputEnd = end;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very similar to DirtyRowTracker, pulling that out of InputHandler and using it would reduce some repetition.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked into this - the shared logic is just the min/max row tracking (~4 lines). DirtyRowTracker has different reset semantics (resets to cursor position via IBufferService) and doesn't need timeout management. Felt like an abstraction would add complexity without much benefit, but happy to revisit if you feel strongly.

@chrislloyd
Copy link
Author

Thanks for the quick review!

How are you confirming the feature?

Works in the example project - will record a video and put it up.

chrislloyd and others added 3 commits December 9, 2025 07:58
- Remove synchronizedOutputTimeout public API, hardcode 1s timeout
- Extract SynchronizedOutputHandler class for cleaner code
- Update spec URL to contour-terminal/vt-extensions
- Remove unnecessary comment in InputHandler
- Delete unit tests, add integration tests in SharedRendererTests
- Fix whitespace issue

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Applications can now detect synchronized output support by querying
CSI ? 2026 $ p and receiving CSI ? 2026 ; <mode> $ y response.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@chrislloyd
Copy link
Author

Updated with videos in the description.

@chrislloyd chrislloyd requested a review from Tyriar December 9, 2025 17:33
@Tyriar
Copy link
Member

Tyriar commented Dec 10, 2025

Posix test script:

clear;c=$(tput cols);r=$(tput lines);for f in $(seq 0 10 200); do printf '\e[?2026h\e[H';for y in $(seq 0 $((r-1)));do for x in $(seq 0 $((c-1)));do printf "\e[48;5;$((16+(x+y+f)%216))m ";done;echo;done;printf '\e[?2026l';sleep 0.03;done

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.

Synchronized Output

2 participants