Apply winterm-ghostty lessons: output-pump coalescing, gated blink, kitty graphics protocol - #4
Merged
Marc-André Moreau (mamoreau-devolutions) merged 3 commits intoSep 5, 2026
Conversation
Applies the winterm-ghostty throughput lessons to the Devolutions Terminal output path: - TermControl collapses queued engine invalidations into a single trailing UI-thread drain (interlocked pending flag) instead of one dispatcher post per 16 KiB ConPTY read; accessibility/scroll-mark/viewport/IME listener fan-out now runs once per burst. Engine.Feed stays on the PTY thread for CSI 6n response timing. - Cursor blink timer is damage-gated: ticks only invalidate when pixels can change (focused pane, blinking + visible cursor per DECSET 12/25, effectively visible control); focus loss repaints once out of a mid-blink dark phase. - New tools/Devolutions.Terminal.Bench harness (engine/control modes, 16 KiB chunks, frame-paced dispatcher drains, medians): an 8 MiB burst drops from 514 UI drains to ~1 per frame. - Correctness pins from the winterm-ghostty audit: paste vs WriteInput separation, ConPTY per-sequence write serialization under a two-writer race, event-resolved key symbols for shifted Ctrl keys (modifyOtherKeys and kitty associated text), and libghostty-vt stack headroom (survives an adversarial corpus on a 256 KB thread, 4x under the host default). - Docs: renderer.md coalescing/blink contract, ghostty-engine.md stack note, parity-status.md measurement entry.
Adds APC G support end to end: - VtParser: APC string states (ESC _ / C1 0x9F entry, ST-only termination, CAN/SUB abort, 1 MiB bound) with a default IVtDispatch.ApcDispatch member. - Core: KittyGraphicsDecoder parses control keys (a/t/f/o/s/v/i/I/p/c/r/x/y/ X/Y/w/h/z/q/C/m/d), validates, decodes base64 + zlib, and converts raw RGB/RGBA to RGBA32; format 100 retains codec bytes for the renderer (the OSC 1337 contract). - TerminalEngine: image store keyed by image id with independent budget and oldest-first eviction, chunked transmission assembly, actions t/T/p/d/q, OK/error responses honoring quiet flags, cursor advance below the image for a=T (C=1 opts out; a=p never moves), deletes by all/id/placement with uppercase forms freeing data, and logical-line anchored overlays that survive scrollback/reflow. New KittyImages capability flag. - Renderer: kitty placements decode via the existing image cache, size to c/r cells with aspect preservation, honor in-cell pixel offsets and source crops, and composite below text for z<0 or above text for z>=0. - Ghostty engine: deterministic image.kitty.unsupported diagnostic, deduped per engine lifetime for chunked transmissions. - Rejected without I/O per repository policy: file/temp-file/shared-memory media; animation frames and Unicode placeholders are ENOTSUP; cell/z/number deletes are silent no-ops. Tests: 19 Core tests (decoder, engine, parser boundaries incl. split APC, C1 entry, CAN cancel, BEL non-termination), 6 renderer pixel tests (raw, PNG, cell sizing, z-order both directions, crop), Ghostty diagnostic test. Docs: advanced-vt-protocols.md, parity-status.md.
Awaiting Task.Run let the headless dispatcher interleave drains mid-burst on the macOS and Linux CI runners (55 drains instead of <= 2). Drive the producer on a raw Thread and block the UI thread on Join so every chunk queues before any drain runs, on every platform.
Marc-André Moreau (mamoreau-devolutions)
merged commit Sep 5, 2026
7b0d7cb
into
master
24 checks passed
Marc-André Moreau (mamoreau-devolutions)
deleted the
copilot/analyze-winterm-ghostty
branch
September 5, 2026 02:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Analysis of winterm-ghostty (Windows Terminal shell + ghostty engine) for portable lessons, followed by implementation of the top findings — culminating in kitty graphics protocol support.
Performance & correctness lessons applied (commit 1)
TermControlno longer posts one UI dispatch per 16 KiB ConPTY read. Queued engine invalidations collapse into a single trailing drain (interlocked pending flag, re-queues on mid-drain arrivals); accessibility/scroll-mark/viewport/IME listener fan-out runs once per burst.Engine.Feedstays on the PTY thread to preserve CSI 6n response timing. Newtools/Devolutions.Terminal.Benchharness (engine/control modes, frame-paced drains, medians): an 8 MiB burst drops from 514 UI drains to ~1 per frame.WriteInputbyte separation, ConPTY per-sequence write serialization under a live two-writer race, event-resolved key symbols (Ctrl+Shift+/ →?, never the unshifted/), and a libghostty-vt stack-headroom stress test (adversarial corpus on a 256 KB thread — 4× under the host default; their full-libghostty host needed 16 MB).Kitty graphics protocol (commit 2)
Implements APC G end to end:
VtParser(ESC_/ C1 entry, ST-only termination, CAN/SUB abort, bounded), defaultIVtDispatch.ApcDispatch.KittyGraphicsDecoder— control keys, base64 + zlib, raw RGB/RGBA → RGBA32, format 100 retains codec bytes for the renderer. Engine: image store with independent budget, chunked assembly (m=), actionst/T/p/d/q,OK/error responses honoring quiet flags, cursor advance below image fora=T(C=1opts out), deletes by all/id/placement, logical-line anchored overlays surviving scrollback/reflow. NewKittyImagescapability.c/rcells (aspect-preserving with one axis), in-cell pixel offsets, source crop, z-order (z<0below text,z≥0above).image.kitty.unsupporteddiagnostic (deduped per engine lifetime).ENOTSUP), cell/z/number-targeted deletes.Validation
dotnet tools/Devolutions.Terminal.Bench/bin/Release/net10.0/Devolutions.Terminal.Bench.dll control.Remaining analysis items (not in this PR)
Kitty graphics was priority 4. Still available from the analysis: DirectWrite
MapCharacterslocale-aware fallback, WGC latency probe + vttest matrix, winghostty UIA bridge.