^[control-codes live in libghostty-vt

Control sequences

XTWINOPS Window Operations

Move, resize and raise the window, report its size and state, and save and restore its title.

CSI Ps ; Ps ; Ps t
Defaults
Ps = 0
xterm
Functions using CSI

CSI Ps ; Ps ; Ps t is xterm’s window manipulation sequence, taken from dtterm. The first parameter says what to do:

PsDoesAnswers
1, 2de-iconify, iconify
3 ; x ; ymove the window
4 ; h ; w, 8 ; rows ; colsresize it, in pixels or in characters
5, 6, 7raise, lower, refresh
9 ; n, 10 ; nmaximize, full screen
11report whether iconifiedCSI 1 t or CSI 2 t
13report the window’s positionCSI 3 ; x ; y t
14, 15, 16report the window, the screen, a character cell, in pixelsCSI 4 ; h ; w t, CSI 5 ; h ; w t, CSI 6 ; h ; w t
18, 19report the text area, the screen, in charactersCSI 8 ; rows ; cols t, CSI 9 ; rows ; cols t
20, 21report the icon name, the window titleOSC L name ST, OSC l title ST
22 ; n, 23 ; npush the title on a stack, pop it
24 and upresize to that many lines, as DECSLPP

For 22 and 23 the second parameter says which title: 0 both, 1 the icon name, 2 the window title. The stack holds ten, and popping an empty one does nothing (xtermPushTitle, xtermPopTitle). Programs push the title before setting their own and pop it on leaving, so the shell’s title comes back.

xterm gates each operation by the allowWindowOps and disallowedWindowOps resources. allowWindowOps is off by default, but that only applies the list, and the default list names just GetIconTitle and GetWinTitle here, since reporting a title back lets a program type whatever it put there into the shell. A default xterm does everything else, resizing included (window_ops, main.h). The cases follow it.

libghostty-vt answers 14, 16 and 18 through its host’s SIZE callback, which the runner installs, giving the case’s own size and an arbitrary cell of 6 by 13 pixels; the cases check only 18, since the pixel sizes depend on xterm’s font. It does nothing with the rest, which are the host’s window to move: it has no title stack, and does not report whether the window is iconified. Those cases are known differences.

Validation

XTWINOPS-1: The text area in characters

\e[18t
|______|
|______|
reply \e[8;2;6t

XTWINOPS-2: Whether the window is iconified

\e[11t
|______|
reply \e[1t

XTWINOPS-3: The title is not reported

\e]2;secret\a
\e[21t
\e[20t
|______|
title "secret"
reply none

XTWINOPS-4: Push and pop the title

\e]2;shell\a
\e[22;0t   # push
\e]2;editor\a
\e[23;0t   # pop
|______|
title "shell"

XTWINOPS-5: A stack of them

\e]2;one\a
\e[22t
\e]2;two\a
\e[22t
\e]2;three\a
\e[23t
\e[23t
|______|
title "one"

XTWINOPS-6: Popping only the icon name

\e]2;one\a
\e[22;1t   # push the icon name
\e]2;two\a
\e[23;1t   # pop it: the window title stays
|______|
title "two"

XTWINOPS-7: Popping an empty stack

\e]2;same\a
\e[23;0t
|______|
title "same"
Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.