Pictures
Programs that draw pictures in a terminal show them in a Terminal Delight pane. Run kitten icat photo.png, chafa, or an agent that renders a chart with the Kitty graphics protocol, and the picture lands in the cells the program asked for, scrolls with the text around it, and bends with the glass like everything else in the tube.
Pictures stay while you are looking at their pane. When you switch to another tab, the pane forgets them, and coming back shows the text alone. They are not saved with the session and do not come back when a window reattaches.
Nothing to switch on. Sixel and iTerm2 pictures are not drawn yet.
The Technical version lists what is supported, what a program is told when it asks, and how a picture reaches a window attached to a session host.
Pictures
What draws
The terminal core, rio-vt, receives and stores Kitty graphics; the pane draws what the core holds over the grid.1
| Part of the protocol | In a pane |
|---|---|
Formats: PNG (f=100), RGB (f=24), RGBA (f=32) | Drawn |
Sending: inline data (t=d), a file (t=f), a temporary file (t=t), shared memory (t=s) | All four |
A file, temporary file or shared memory that also says more chunks follow (m=1), as mpv's shared-memory mode sends every frame | Not drawn yet: the picture waits for a chunk that never comes (issue 833) |
| One picture command, as a single escape sequence | Up to 4 MiB. The protocol's chunks are 4 KB each, so only a sender that skips chunking meets the limit |
Placement in cells (c=, r=), cropping (x= y= w= h=), offsets within a cell (X=, Y=) | Drawn |
Stacking (z=) | Negative draws under the text, zero and above over it |
Deleting (a=d) | Honoured |
Unicode placeholders (U=1, U+10EEEE cells) | Not drawn yet: the cells show as text |
| Sixel, iTerm2 inline images | Not drawn yet |
A picture is not drawn while the rows are read upside down (the anchor-to-top read) or in text crawl, where it has no single cell to sit in. It is still held, and it returns with the plain read.
A temporary file (t=t) is deleted by kitty's rule: only when its name contains tty-graphics-protocol and it sits in /tmp, /dev/shm or $TMPDIR. Terminal Delight deletes it itself after the core has read it, because the core's own check looks for that marker anywhere in the path. Shared memory (t=s) reaches the core only when it names a regular file in /dev/shm.
When a picture goes
No snapshot carries a picture, so a window that attaches to a pane shows its text and none of the pictures drawn before it arrived. TD_PICTUREDEBUG=1 makes a window print one line to its log each time a hidden pane lets pictures go, for checking this by script.
What a program is told
Picture programs ask the terminal what it is before they draw. Terminal Delight answers as itself.2
| Question | Answer |
|---|---|
Kitty graphics query (a=q) | OK, from the core |
Primary device attributes (CSI c) | ?62;22c: a VT220 with ANSI colour, and no claim to sixel or clipboard access |
XTVERSION (CSI > 0 q) | terminal-delight 0.3.0 |
Cell size in pixels (CSI 16 t) | The cell the pane told the pseudoterminal, in device pixels |
Kitty keyboard protocol (CSI ? u) | No answer: keys are sent in the legacy encodings |
kitten icat decides from the first two answers together. Before the core swap it waited ten seconds in every pane and then gave up, because the old device-attributes answer was too short for its detector.3
Panes on a session host
A pane on a session host is parsed twice: by the host, which answers the program, and by your window, which draws. A picture sent as a temporary file or as shared memory is deleted by the first terminal that reads it, and the host reads first, so for those two methods the host rewrites the picture into its copy of the stream as inline data before the original is deleted. Inline data and plain files reach the window as the program sent them.4
A window attached to a session host started before the core swap still draws pictures sent as inline data or a file, because the bytes pass through the old host to the window's own core. That host answers the questions in the table above the old way, so kitten icat still waits there until the host is replaced.
Try it
printf '\033_Ga=T,f=24,s=2,v=1,c=8,r=2;/wAAAP8A\033\\\n'
Two pixels, red and green, stretched over eight cells by two. The line after it starts below the picture.
What would prove this page wrong
A picture that stays on screen after its tab has been hidden and shown again; a picture drawn over the wrong cells after the pane scrolls; a temporary-file picture that shows in a window-owned pane and not in a hosted one; or kitten icat pausing before it draws in a pane whose host was started from this build.
Sources
- The core boundary and the picture verbs:
app/src/vt/mod.rsandapp/src/vt/rio.rs; drawing:picture_elementsinapp/src/pane.rs; forgetting:Workspace::forget_pictures_out_of_sightinapp/src/main.rs. - The answers and their tests:
app/src/vt/rio.rs,as_terminal_delightand the tests beside it. - The ten-second wait, measured at 10,076 ms and 10,044 ms in a hidden window: issue 750; the detector's length check is in kitty's
kittens/icat/detect.go. - The rewrite:
app/src/picturewire.rs; the test that fails without it:a_picture_sent_as_a_temporary_file_reaches_the_attached_windowinapp/src/host.rs.