Skip to content

kitty shared memory object transmit - #198

Open
benjajaja wants to merge 4 commits into
masterfrom
kitty_shared_memory_object
Open

benjajaja wants to merge 4 commits into
masterfrom
kitty_shared_memory_object

Conversation

@benjajaja

Copy link
Copy Markdown
Collaborator

Should be much faster than base64(PNG) sequence.

@benjajaja benjajaja self-assigned this Sep 6, 2026
@benjajaja
benjajaja force-pushed the kitty_shared_memory_object branch 2 times, most recently from 6e55a5f to 49d4d96 Compare September 6, 2026 13:12
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Merge of f62baa2 to master

Screenshots from all terminal emulators:

alacritty

alacritty screenshot

Image diff vs master:
alacritty diff

blackbox

blackbox screenshot

Image diff vs master:
blackbox diff

contour

contour screenshot

Image diff vs master:
contour diff

foot

foot screenshot

Image diff vs master:
foot diff

ghostty

ghostty screenshot

Image diff vs master:
ghostty diff

kitty

kitty screenshot

Image diff vs master:
kitty diff

konsole

konsole screenshot

Image diff vs master:
konsole diff

mlterm

mlterm screenshot

Image diff vs master:
mlterm diff

rio

rio screenshot

Image diff vs master:
rio diff

wezterm

wezterm screenshot

Image diff vs master:
wezterm diff

xfce4-terminal

xfce4-terminal screenshot

Image diff vs master:
xfce4-terminal diff

xterm

xterm screenshot

Image diff vs master:
xterm diff

xterm-vt340

xterm-vt340 screenshot

Image diff vs master:
xterm-vt340 diff

@benjajaja
benjajaja force-pushed the kitty_shared_memory_object branch 4 times, most recently from b9f1539 to 9232ae8 Compare September 6, 2026 19:35
@sharkusk

sharkusk commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Nice, this is the transmit lanthorn has wanted for local play. One thing worth adding before it sees much use: kitty_shared_memory_object is a blind opt-in, and a terminal that cannot reach the object — anything over SSH, mosh, or a browser-hosted terminal — stores no image and draws nothing, silently. That is the same cliff the o=z probe in #190 was written to avoid.

The protocol has the answer built in: an a=q query with t=s naming a one-pixel object the client creates (and unlinks itself), on the same query Picker::from_query_stdio already sends, costs no extra round trip. A local terminal answers OK; a remote one answers with an error or not at all. I'd propose a kitty_shared_memory_probe: bool option that adds that probe and reports Capability::KittySharedMemory, so kitty_shared_memory_object becomes "use it if the terminal answered" rather than unconditional. Detecting SSH from the environment doesn't work in either direction: the variables vanish inside tmux, sudo and containers, and appear when you ssh to localhost.

Happy to send the PR if you're open to it.

@benjajaja

Copy link
Copy Markdown
Collaborator Author

Good point, we should always probe if possible.

benjajaja and others added 3 commits September 11, 2026 20:27
Should be much faster than base64(PNG) sequence.
Probe whether a terminal can actually read a POSIX shared memory
object before ever relying on one for a real transmission — a blind
opt-in silently draws nothing on a remote session, since the terminal
can never open an object that lives on another machine's filesystem.

Address of review on PR #200:

- One option. `QueryStdioOptions::kitty_shared_memory_object` now
  means both things at once: probe for shared memory during the stdio
  query, and use it for real transmissions if the terminal answered.
  The separate probe flag and the `ShmProbe`/`resolve_kitty_shm`
  machinery are gone; `Picker` folds the answer in with
  `if caps.contains(&Capability::KittySharedMemory) { kitty_shm } else { None }`
  on every path, including the ones where nothing answered at all.

- The probe goes out through the same write path a real transmission
  uses (`kitty::shm_name` + `kitty::shm_write`), not a separate
  deterministic-name scheme. `Parser::query` now returns the probe
  object's name alongside the query string, and `Picker` unlinks it
  once the query's replies are read — kitty/Ghostty unlink it
  themselves on success, so a gone object at that point is the
  success case, not an error.

- A shared memory transmission still names a fresh object every time,
  never the kitty image id, but the per-transmit suffix is now drawn
  from `rand::random` — the same way `Picker` already draws kitty
  image ids — rather than a second `AtomicU32`. A repeated base64
  transmit under one id is harmless because the wire is ordered; a
  repeated shm name is not, because the terminal reads the object
  asynchronously and a second transmit recreating it can race a
  reader still working through the first.

- `transmit_or_shm` now decides shm vs. inline over raw `(bytes, w,
  h)` rather than a `DynamicImage`, with `to_rgba8()` hoisted to
  `KittyProtoState::new`, the one caller that actually holds one.
  `transmit_virtual` is renamed `transmit_base64` to match. This is
  what lets the probe call the exact same write primitives a real
  transmit does, down to a shared four-byte constant pixel.

- The write-vs-map split moves from `target_os = "macos"`-shaped
  reasoning to "Linux writes, every other Unix maps": `mmap` is the
  one operation POSIX actually promises on a shared memory object,
  `write` is a per-kernel courtesy (macOS refuses it with ENXIO,
  FreeBSD happens to allow it but is untested here), and the crate
  draws no line between non-Linux Unixes anywhere else.

- Documented, without a code change: a transmit the caller never
  consumes with a render leaves its shm object behind for the caller
  to clean up by hand, the same way an untransmitted base64 image is
  left marked transmitted but never shown.

Quest: none
@benjajaja
benjajaja force-pushed the kitty_shared_memory_object branch from 09bf9d6 to 022f202 Compare September 11, 2026 19:44
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.

2 participants