Terminal: measure characters with Unicode 11 widths, so an emoji takes the two columns the remote counts
ci / build and test (push) Successful in 3m37s
ci / android head (push) Successful in 3m45s
ci / api image (push) Successful in 8s
ci / desktop nightly (push) Successful in 1m44s

This commit is contained in:
jaap-jan committed 2026-10-04 13:55:20 +02:00
1 parent ad1a129159
commit 6806e542f9
9 files changed
+136 -6

No files matched your search

@@ -387,6 +387,28 @@ function createSession(sessionId) {
const fit = new FitAddon.FitAddon();
term.loadAddon(fit);
/*
── CHARACTER WIDTHS FROM UNICODE 11, NOT 6 ────────────────────────────────────────────────────────
How many columns a character takes is not something the terminal and the remote can each decide for
themselves: the shell's line editor counts columns to know where the cursor is, and the terminal
counts them to know where to draw. When the two disagree, every character after the one they
disagree about lands a column away from where the remote believes it is — a prompt that redraws over
itself, a cursor one cell off, a line that wraps early.
xterm.js ships with Unicode 6's table, which predates emoji as a wide class. So 😀 was one column
here and two on any current remote (glibc, musl and every modern wcwidth follow Unicode 9 and later),
and a line with an emoji in it drifted from the first emoji on. Measured against xterm.js 6.0
headless: 😀 took one cell as shipped and two with this addon, and CJK, combining marks and every
escape sequence behaved the same either way.
Before open() so the first frame is measured with the right table. activeVersion is a proposed API,
which is what allowProposedApi above is already on for.
*/
term.loadAddon(new Unicode11Addon.Unicode11Addon());
term.unicode.activeVersion = '11';
term.open(pane);
// WebGL where it is available. Falling back rather than failing matters because a software