Repository navigation
Fix 50 bugs and add 50 performance optimizations in Sixel and Kitty implementations - #67
Merged
Marc-André Moreau (mamoreau-devolutions) merged 6 commits intoNov 12, 2026
Conversation
…tions Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…mizations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ng optimizations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
… optimizations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…oard/blitter optimizations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 14:57 — with
GitHub Actions
Active
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 14:57 — with
GitHub Actions
Active
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 14:57 — with
GitHub Actions
Active
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 14:57 — with
GitHub Actions
Active
…and TermControl Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 15:30 — with
GitHub Actions
Active
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 15:30 — with
GitHub Actions
Active
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 15:30 — with
GitHub Actions
Active
Marc-André Moreau (mamoreau-devolutions)
deployed
to
publish-dry-run
November 12, 2026 15:30 — with
GitHub Actions
Active
Marc-André Moreau (mamoreau-devolutions)
merged commit Nov 12, 2026
bf3425a
into
master
77 of 78 checks passed
Marc-André Moreau (mamoreau-devolutions)
deleted the
copilot/sixel-and-kitty-fixes-and-optimizations
branch
November 12, 2026 15:57
This branch was successfully deployed
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
Completes 5 iterative rounds of Sixel and Kitty graphics/keyboard protocol bug fixes and performance optimizations across
Devolutions.Terminal.Core,Devolutions.Terminal.Render,Devolutions.Terminal.Control,Devolutions.Terminal.Automation, anddocs/advanced-vt-protocols.md(50 bug fixes + 50 performance improvements).Highlights by Round
Round 1 — Parser & Sixel Decoder
DEL(0x7F) in APC; preventBELfrom terminatingStringIgnoreon oversized APC strings and handle non-\escapes inStringEscape; ignore whitespace/C0 inside Sixel!Pn<sixel>and parameter lists; preserve parameter indices on leading;; default omitted DECGRAPadto1and ignore mid-stream"mutations; charge_remainingPixelWriteson'?'repeats to prevent CPU DoS; wrap color register indices modulo 256 and HLS hues modulo 360°; resolveWrapPendingand report post-scrollAnchorRowinDispatchSixel.SearchValues<byte>bulk scanning for DCS and APC payloads; zero-allocationTerminateDcsspan dispatch and pooledFinishApcUTF-8 decoding; staticDefaultPalette,stackallocparameter parsing,BitOperations.PopCount, fast1:1pixel writes,ArrayPool<ushort>Sixel working buffer with single-pass background fill, DECGRA pre-sizing, andPercentToByteTableLUT.Round 2 — Kitty Graphics Decoder, Chunking & Store
m=1/m=0chunked base64 reassembly; pre-scani=,I=, andq=on parse failures; inheritq=andI=across continuation chunk errors; abort incomplete chunked transfers when non-continuation actions (a=d,a=p) arrive; validate and resolveI=<uint32>image numbers; replace existing non-zero(imageId, placementId)overlays on active buffer; reference-count sharedKittyImageDatabytes across placements; validateo=,C=,m=, andq=; supportd=i/d=Iwithp=and free unreferenced data ond=P; scoped=a/d=Ato the active buffer.Convert.TryFromBase64Chars; direct streaming base64 quantum decode into_kittyChunkPayload;ArrayPool<byte>inflate scratch buffer; exact-size rawf=24/f=32zlib inflate withoutMemoryStream; zero-copyf=32ownership transfer;Vector128.ShuffleSIMDRGB24 -> RGBA32expansion; zero-alloc comma key scanning and inline integer parsers; structKittyContinuationChunkfast path;Utf8.TryWritestackallocAPC responses; O(1)LinkedList<uint>store eviction.Round 3 — Skia Renderer, Planner & Frame Differ
CellGeometry, image data identity, and allKittyImageplacement fields inTerminalFrameDiffer; support partial Kitty crops (X/Y/w/hindividually); render nothing on out-of-boundsCropX/CropY; clip viewport-overflowing Sixel/Kitty overlays instead of squishing aspect ratio; cull off-screen scrollback images beforeDecodeImage; scale natural Kitty dimensions and pixel offsets byPhysicalPixelon HiDPI displays; clampPixelOffsetX/PixelOffsetYwithin a single cell; sort negative-z placements by(ZIndex, Id); fixDictionary.First()cache eviction with trueLinkedListLRU; clear cached images and_invalidImagesinInvalidate().DrawImages; directGetPixelSpan()Sixel and Kitty RGBA blits withoutSKColor[]LOH allocations; span-basedDecodeCodecImage; sharedSKBitmapcache keyed by underlying pixel-data identity (ReferenceEqualityComparer); early exit beforeSave/ClipRect/Restorewhen empty; skip sort when monotonic; guard stale-cache sweep; zero-allocFilterActiveBufferImagesinTerminalRenderPlanner; fastTerminalFrameDifferchecks.Round 4 — Kitty Keyboard Protocol & Buffer Image Anchors
Nonewhen popping past bottom and evict oldest entry on full 16-entry stack; validateCSI =mode (1/2/3); add Kitty functional key codepoints (F13–F24, keypad, lock/system, and modifier keys); colon-join multi-rune associated text; lowercase non-ASCII Unicode base codepoints; emitSS3 P/Q/Sfor unmodifiedF1/F2/F4; gateEncodeKittyTextInputonReportAllKeysAsEscapeCodesand suppress duplicateOnTextInputon modified Kitty keys; track(Key, PhysicalKey)inProcessKeyUpInputto suppress orphan releases; validate raws/vdimensions before zlib decompression.ImageAnchorLayoutVersionO(1) gate onPruneEvictedImages; viewport-first scan + monotonic O(log N) binary search inTryResolveImageAnchor; zero-LINQExtractBufferAnchorson resize; min/maxLogicalLineIdfast skip inReflow/LastTextLine; reuse pre-resolved anchors inCreateSnapshotImages;stackallocReapUnplacedKittyImages; closure-freeRemoveKittyOverlays; span-hoistedSixelImage.ToRgba32; layout-version sync inAddImage; zero-LINQ/zero-Enum.ToString()CreateObservedImagesin Automation.Round 5 — Sixel/Kitty Lifecycle, Screen Erase & Blitter Optimizations
XTSMGRAPHICS(CSI ? Pi;Pa;Pv S); implementDECSET/DECRST/DECRQM1070(private Sixel palette) and8452(Sixel cursor-right mode); avoid advancing auto Kitty image ID ona=qqueries or rejected payloads; preserve primarya=timages across\e[?1049halternate-screen entry; clear erased viewport overlays onCSI 0/1/2 Jand prune scrollback onCSI 3 J; resolveWrapPendingand aspect-scaled cursor rows (c > 0, r == 0) on Kittya=T; validate unsigned Kitty control values and allow tall/wider/cplacements beyond current viewport size; useSKAlphaType.Opaquefor opaque codec images (e.g. JPEG); honorDECOMinDECSDM; clamp non-reflowed alternate-buffer anchors on narrowing.stackallocformatting + cached literals inKeyMapper.EncodeKitty,EncodeLegacyFunctionalKey, andEncodeKittyTextInput; boxing-freeIsTextInputCandidate; pre-builtCSI ? ubyte response table; consecutive identical sixel byte run coalescing; fast'?'skip and contiguous'~'fill inWriteSixel;Utf8.TryWritestackallocXTSMGRAPHICS responses;SKAlphaType.Opaquetagging for opaque Sixel andf=24Kitty bitmaps; branchless 257-entrystackallocSixel palette LUT in Skia; boundedTextBuffer.AdvanceLinesbatching.Validation
dotnet build Devolutions.Terminal.slnx -c Debug(0 warnings, 0 errors)dotnet build Devolutions.Terminal.slnx -c Release(0 warnings, 0 errors)dotnet test Devolutions.Terminal.slnx -c Release— 3,360 passed, 0 failed across all test suites (Core,Render,Control,Automation,Connection,App,UI,Settings,Settings.Editor,Cli,Package,Broker,Compatibility)