The implementation now distinguishes a newly placed image cell from one later overwritten by text. On a SIXEL terminal, damaged cells are omitted from image output; on Kitty they remain ordinary positional placements.

This commit is contained in:
Michael Grant
2026-08-08 22:35:10 +01:00
parent ed63826b15
commit 54d3f77c2c
4 changed files with 19 additions and 7 deletions

4
grid.c
View File

@@ -808,7 +808,7 @@ grid_set_cells(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc,
if (old_id != 0 && (~gc->flags & GRID_FLAG_IMAGE)) {
grid_get_cell1(gl, px + i, &old_gc);
memcpy(&image_gc, gc, sizeof image_gc);
image_gc.flags |= GRID_FLAG_IMAGE;
image_gc.flags |= GRID_FLAG_IMAGE|GRID_FLAG_IMAGE_DAMAGED;
image_gc.image_id = old_gc.image_id;
image_gc.image_x = old_gc.image_x;
image_gc.image_y = old_gc.image_y;
@@ -1344,7 +1344,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
#ifdef ENABLE_IMAGES
if (gc.flags & GRID_FLAG_IMAGE) {
utf8_set(&gc.data, ' ');
gc.flags &= ~GRID_FLAG_IMAGE;
gc.flags &= ~(GRID_FLAG_IMAGE|GRID_FLAG_IMAGE_DAMAGED);
gc.image_id = gc.image_x = gc.image_y = 0;
}
#endif

18
image.c
View File

@@ -104,7 +104,8 @@ static const struct image_backend image_backend_kitty = {
kitty_draw_rect, kitty_free_output, kitty_geometry_changed
};
static const struct image_backend image_backend_sixel = {
"sixel", IMAGE_BACKEND_GRAPHICAL, sixel_draw_rect,
"sixel", IMAGE_BACKEND_GRAPHICAL|IMAGE_BACKEND_TEMPORAL,
sixel_draw_rect,
sixel_free_output, sixel_geometry_changed
};
@@ -553,7 +554,7 @@ image_get_fallback_cell(__unused struct tty *tty, struct image *im, u_int x,
if (cell != NULL)
level = cell->whole.brightness * (sizeof ramp - 2) / 255;
utf8_set(&out->data, ramp[level]);
out->flags &= ~GRID_FLAG_IMAGE;
out->flags &= ~(GRID_FLAG_IMAGE|GRID_FLAG_IMAGE_DAMAGED);
}
/* Get the terminal cell used to draw an image marker. */
@@ -565,7 +566,8 @@ image_get_draw_cell(struct tty *tty, const struct grid_cell *gc,
if (image_backend_flags(tty) & IMAGE_BACKEND_GRAPHICAL) {
memcpy(out, gc, sizeof *out);
out->flags &= ~(GRID_FLAG_IMAGE|GRID_FLAG_SELECTED);
out->flags &= ~(GRID_FLAG_IMAGE|GRID_FLAG_IMAGE_DAMAGED|
GRID_FLAG_SELECTED);
return (1);
}
image_get_fallback_cell(tty, im, gc->image_x, gc->image_y, gc, out,
@@ -578,6 +580,7 @@ void
image_set_cell(struct grid_cell *gc, struct image *im, u_int x, u_int y)
{
/* Keep the cell contents as the underlay for transparent pixels. */
gc->flags &= ~GRID_FLAG_IMAGE_DAMAGED;
gc->flags |= GRID_FLAG_IMAGE;
gc->image_id = im->id;
gc->image_x = x;
@@ -724,7 +727,7 @@ image_clear(struct screen_write_ctx *ctx, u_int id)
if (y >= gd->hsize)
image_redraw_area(ctx, x, y - gd->hsize,
1, 1);
gc.flags &= ~GRID_FLAG_IMAGE;
gc.flags &= ~(GRID_FLAG_IMAGE|GRID_FLAG_IMAGE_DAMAGED);
gc.image_id = gc.image_x = gc.image_y = 0;
grid_set_cell(gd, x, y, &gc);
}
@@ -806,6 +809,11 @@ image_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py,
run = 1;
continue;
}
if ((backend->flags & IMAGE_BACKEND_TEMPORAL) &&
(gc.flags & GRID_FLAG_IMAGE_DAMAGED)) {
run = 1;
continue;
}
im = image_find(gc.image_id);
if (im == NULL) {
run = 1;
@@ -814,6 +822,8 @@ image_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py,
for (run = 1; i + run < nx; run++) {
grid_view_get_cell(s->grid, px + i + run, py, &next);
if (~next.flags & GRID_FLAG_IMAGE ||
((backend->flags & IMAGE_BACKEND_TEMPORAL) &&
(next.flags & GRID_FLAG_IMAGE_DAMAGED)) ||
next.image_id != gc.image_id ||
next.image_y != gc.image_y ||
next.image_x != gc.image_x + run)

View File

@@ -2720,7 +2720,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
(~gc->flags & GRID_FLAG_IMAGE)) {
image_redraw_area(ctx, s->cx, s->cy, width, 1);
memcpy(&image_gc, gc, sizeof image_gc);
image_gc.flags |= GRID_FLAG_IMAGE;
image_gc.flags |= GRID_FLAG_IMAGE|GRID_FLAG_IMAGE_DAMAGED;
image_gc.image_id = now_gc.image_id;
image_gc.image_x = now_gc.image_x;
image_gc.image_y = now_gc.image_y;

2
tmux.h
View File

@@ -810,6 +810,7 @@ struct colour_palette {
#define GRID_FLAG_CLEARED 0x40
#define GRID_FLAG_TAB 0x80
#define GRID_FLAG_IMAGE 0x100
#define GRID_FLAG_IMAGE_DAMAGED 0x200
/* Grid line flags. */
#define GRID_LINE_WRAPPED 0x1
@@ -4237,6 +4238,7 @@ char *regsub(const char *, const char *, const char *, int);
/* image.c */
#define IMAGE_BACKEND_GRAPHICAL 0x1
#define IMAGE_BACKEND_SCROLLS 0x2
#define IMAGE_BACKEND_TEMPORAL 0x4
struct image *image_create(u_int, u_int, u_int, u_int, u_int, u_int,
u_char *);