Repository navigation
Conversation
Placing an image with a placement id (p=) that the image already has names the same appearance, so it must replace the one on screen. That is the protocol's move operation: notcurses re-sends a=p with the same i= and p= at every step of a moving sprite and never sends a delete. PlaceKittyImage always added a placement, so each step left a copy behind and one sprite became a trail of them (visible in the notcurses-demo intro). Drop the existing placement for (image, placement id) before placing. Placements with no id are anonymous and still accumulate, and placement ids stay scoped to their image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0146GFSWj55CpWULQWNetAgB
Perf comparison — this change, against its base3 run(s) of each side, alternating on one machine. Allocation is a count and is gated exactly. Time is a measurement, so its gate is derived from the spread this job just observed in itself rather than fixed in advance.
Each corpus is gated at assemblies measured
Perf comparison — cumulative, everything since 2.0.33 run(s) of each side, alternating on one machine. Allocation is a count and is gated exactly. Time is a measurement, so its gate is derived from the spread this job just observed in itself rather than fixed in advance.
Each corpus is gated at assemblies measured
|
|
Closing as a duplicate of #163, which fixes the same bug in the same place. Generated by Claude Code |
Problem
Running
notcurses-demoin a host built on XTerm.NET, the intro's moving sprite leaves a copy of itself at every step, so one picture becomes a trail across the screen.Notcurses moves a Kitty image by re-sending
a=pwith the samei=andp=at the new position. It never sends a delete. Per the Kitty graphics protocol, placing with a placement id the image already has replaces that placement.PlaceKittyImagealways added a new placement. The only callers ofDropPlacementswere the two delete paths.Fix
In
PlaceKittyImage, when the command carries a non-zero placement id, drop the existing placement for that (image, placement id) before placing. It reuses the predicate thed=idelete path already uses.p=0) are anonymous and still accumulate.p=1do not replace each other.Tests
KittyPlacementReplaceTestscovers: a move (both rows of the old position cleared), a 20-step walk leaving one picture, anonymous placements accumulating, a different placement id being a second appearance, the same placement id on another image being left alone, and the stored image surviving a replace.Not run locally. The environment this was written in has no .NET SDK and could not download one, so the change has not been compiled or tested. CI is the first build of it.
Notes for review
DropPlacementswalks every line of both buffers, scrollback included, on each id'd placement. This is not the print path, but a client animating at a high frame rate with a long scrollback pays it per frame. An index from (image, placement id) to rows would remove the walk if it shows up in a profile.a=tora=Twith the samei=) replaces the registry entry, but the placements of the previous image stay on screen, becauseTerminalImage.Idis a fresh serial per transmission. Kitty removes the old image's placements in that case. A client that re-sends pixels each frame witha=Twould still leave a trail.🤖 Generated with Claude Code
https://claude.ai/code/session_0146GFSWj55CpWULQWNetAgB
Generated by Claude Code