aboutsummaryrefslogtreecommitdiffstats
path: root/src/app_draw.c
diff options
context:
space:
mode:
authorIngmar Steen <iksteen@gmail.com>2026-09-06 19:41:18 +0200
committerIngmar Steen <iksteen@gmail.com>2026-09-06 19:41:18 +0200
commit06b22770e0ff2d03dffafed223c63d7d4608020c (patch)
tree1e83190fa17ca21530502608e705923e8134cc07 /src/app_draw.c
parentserver: one synchronized message per frame, cells and images together (diff)
downloadslosh-06b22770e0ff2d03dffafed223c63d7d4608020c.tar.gz
slosh-06b22770e0ff2d03dffafed223c63d7d4608020c.tar.xz
slosh-06b22770e0ff2d03dffafed223c63d7d4608020c.zip
graphics: place an image once, not once per frame
Every frame re-emitted `a=p` for every visible placement. On a terminal that is invisible: a kitty placement is a standing instruction, not a per-frame one ("the other commands to erase text must have no effect on graphics"), so a repaint of the cells under a picture does not disturb it and saying it again says nothing new. It is not free anywhere else. A mirror cannot know that the identical placement is identical: shellglass re-decodes and re-encodes the image on every one, holds the placement back while that runs, and -- because an image change rides only in a full frame -- republishes the whole screen each time. Measured on one image and a pane printing text for twenty seconds, the mirror published 430 full frames and re-sent the image list 215 times; 215 of those fulls carried no image at all, because the placement was still mid-decode. That alternation is what was visible in the browser: a picture that flickered while anything on screen moved and vanished when it stopped. The same twenty seconds now costs one full frame, 412 diffs and one image list. So a placement is emitted only when it is new or has actually changed, and the client's state records what it is holding. Three things have to be right for that to be safe: a dropped frame un-marks the placements it carried (they are owed again, exactly as transmissions and deletions already were); a retransmit of the pixels invalidates the placement, because kitty deletes an image's placements when its data is replaced; and a full repaint clears the screen, which takes the images with it, so every placement is owed again -- gfx_repaint(), not gfx_reset(), because the pixels the terminal was sent survive a clear and a deletion still owed from a dropped frame is still owed. The live check drives a picture that does not move while the screen around it repaints: one placement across 121 frames, where the old behaviour emitted 120. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CRz3zwZJvBvzsR9k4cj6dd
Diffstat (limited to 'src/app_draw.c')
-rw-r--r--src/app_draw.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/src/app_draw.c b/src/app_draw.c
index 2955c11..c3486fc 100644
--- a/src/app_draw.c
+++ b/src/app_draw.c
@@ -2532,6 +2532,8 @@ const char *app_graphics(app_t *a, size_t *len) {
void app_graphics_reset(app_t *a) { gfx_reset(a->gfx); }
+void app_graphics_view_repaint(graphics_t *state) { gfx_repaint(state); }
+
void app_graphics_commit(app_t *a, bool delivered) {
gfx_commit(a->gfx, delivered);
}