Skip to content

Instantly share code, notes, and snippets.

@christianparpart
Last active November 19, 2024 19:10
Show Gist options
  • Save christianparpart/d8a62cc1ab659194337d73e399004036 to your computer and use it in GitHub Desktop.
Save christianparpart/d8a62cc1ab659194337d73e399004036 to your computer and use it in GitHub Desktop.
Terminal Spec: Synchronized Output

Synchronized Output

Synchronized output is merely implementing the feature as inspired by iTerm2 synchronized output, except that it's not using the rare DCS but rather the well known SM ? and RM ?. iTerm2 has now also adopted to use the new syntax instead of using DCS.

Semantics

When rendering the screen of the terminal, the Emulator usually iterates through each visible grid cell and renders its current state. With applications updating the screen a at higher frequency this can cause tearing.

This mode attempts to mitigate that.

When the synchronization mode is enabled following render calls will keep rendering the last rendered state. The terminal Emulator keeps processing incoming text and sequences. When the synchronized update mode is disabled again the renderer may fetch the latest screen buffer state again, effectively avoiding the tearing effect by unintentionally rendering in the middle a of an application screen update.

Feature detection

Use CSI ? 2026 $ p to query the state of the (DEC) mode 2026. This works for any private mode number. If you get nothing back (DECRQM not implemented at all) or you get back a CSI ? 2026 ; 0 $ y then synchronized output is not supported. See DECRQM (request) and DECRPM (response) for more details.

DECRPM can respond with different values.

Value Documentation Relevance for synchronized output mode ?2026
0 Mode is not recognized not supported
1 Set supported and screen updates are not shown to the user until mode is disabled
2 Reset supported and screen updates are shown as usual (e.g. as soon as they arrive)
3 Permanently set undefined
4 Permanently reset not supported

Using the feature

Use CSI ? 2026 h to enable batching output commands into a command queue.

Use CSI ? 2026 l when done with your current frame rendering, implicitly updating the render state by reading out the latest grid buffer state.

Notation

Some developers name the beginning and end of such a synchronized frame (and therefore the instance)

  • BSU (begin synchronized update, CSI ? 2026 h), and
  • ESU (end synchronized update, CSI ? 2026 l).

Timeout

So far there is no real concensus if and if so how long a timeout should be. The toolkit/application implementer should keep this in mind. However, a too short timeout (maybe due to a very slow connection) won't be worse than having no synchronized output at all.

Adoption State

Support Terminal/Tookit/App Notes
n/a xterm.js see tracker xterm.js#3375
not yet Windows Terminal Proof-of-concept implementation by @j4james exists; tracker: wt#8331
Contour
mintty
Jexer
notcurses see tracker: notcurses#1582
foot terminal emulator https://codeberg.org/dnkl/foot
Wezterm see tracker: wezterm#882
not yet VTE / gnome-terminal see tracker: gitlab/vte#15
iTerm2
Kitty since 5768c54c5b5763e4bbb300726b8ff71b40c128f8
planned Warp see tracker: warpdotdev/Warp#2185
Alacritty since 0.13.0
unknown Konsole
unknown urxvt
unknown st

In case some project is adding support for this feature, please leave a comment or contact me, so we can keep the spec and implementation state table up to date.

@christianparpart
Copy link
Author

It seems GNOME Terminal responds with 4 instead of 0, meaning "mode is permanently disabled", which should also count as "don't bother trying to use this feature".

https://vt100.net/docs/vt510-rm/DECRPM.html

Yeah I think both is fine, even though 4 I personally find semantically a little misleading when not actually knowing about a more at all instead of "just cannot be enabled".

@mochaaP
Copy link

mochaaP commented Dec 17, 2022

st has a patch for this now:
https://st.suckless.org/patches/sync/

@j4james
Copy link

j4james commented Dec 18, 2022

@mochaaP It looks to me like that st patch only supports the old DCS sequence, and not mode 2026, which is what is documented here.

@christianparpart
Copy link
Author

christianparpart commented Dec 18, 2022

@mochaaP if you're updating the patch to work via mode setting instead, then we can update this document. Please ping us then, and I'm gladly updating here. :-)

EDIT: I've read the page behind your link. It refers to iTerm's wiki that specs the initial version of it (as stated by @j4james). This article however was last updated 4 years ago (as of today) and does not reflect what iTerm is doing today anymore. iTerm has adapted to mode setting as well, I think, a year ago or so, but it looks like he simply forgot to update the wiki as well. /cc @gnachman :)

@gnachman
Copy link

@christianparpart I've updated the iTerm2 wiki with DEC(RE)SET 2026.

@imsnif
Copy link

imsnif commented Dec 2, 2023

Just implemented this in Zellij: zellij-org/zellij#2977

I'm curious: are there any apps using this in the wild?

@j4james
Copy link

j4james commented Dec 2, 2023

@imsnif A few apps that I know of: tmux, neovim, btop, kakoune. Also a couple of TUI frameworks: textual, crossterm.

@christianparpart You may also want to add Alacritty to the supported terminal list now. I don't think it's part of a release build yet, but it's in the current dev build (it's mentioned in the CHANGELOG).

@shmerl
Copy link

shmerl commented May 16, 2024

Is anyone working on konsole for it?

@inducer
Copy link

inducer commented Aug 12, 2024

It may be useful to clarify the semantics of this in relation to the alternate screen buffer. The semantics I would prefer (x-ref: inducer/pudb#48) would be for this mode to survive buffer switches, so that, upon a "next" command in a debugger, synchronized output can be enabled, a buffer switch can occur, the debuggee be run, and another buffer switch can occur, and the next rendered state be, once again, of the debugger UI.

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