mirror of
https://github.com/tmux/tmux.git
synced 2026-08-28 09:31:34 +00:00
Ordinary text writes replaced the entire grid cell, dropping GRID_FLAG_IMAGE and releasing the
mage reference. Deferred pane redraws explain the intermittent “image never appears” behavior. Fixed: - Preserves image metadata while updating the text underlay in the collected ASCII path: grid.c:779 - Handles the single-cell/non-ASCII path and schedules an image redraw: screen-write.c:2631 - Uses the requested if/else for new_id. - Adds a deterministic regression reproducing point (2): regress/image-support.sh:240 This matches Kitty’s requirement that normal text operations must not affect graphics; graphics require explicit deletion. Kitty graphics protocol
This commit is contained in:
28
grid.c
28
grid.c
@@ -782,6 +782,10 @@ grid_set_cells(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc,
|
||||
struct grid_line *gl;
|
||||
struct grid_cell_entry *gce;
|
||||
struct grid_extd_entry *gee;
|
||||
const struct grid_cell *new_gc;
|
||||
#ifdef ENABLE_IMAGES
|
||||
struct grid_cell old_gc, image_gc;
|
||||
#endif
|
||||
u_int i;
|
||||
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
@@ -795,11 +799,25 @@ grid_set_cells(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc,
|
||||
|
||||
for (i = 0; i < slen; i++) {
|
||||
gce = &gl->celldata[px + i];
|
||||
new_gc = gc;
|
||||
#ifdef ENABLE_IMAGES
|
||||
{
|
||||
u_int old_id = grid_entry_image(gl, gce);
|
||||
u_int new_id = (gc->flags & GRID_FLAG_IMAGE) ?
|
||||
gc->image_id : 0;
|
||||
u_int new_id;
|
||||
|
||||
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.image_id = old_gc.image_id;
|
||||
image_gc.image_x = old_gc.image_x;
|
||||
image_gc.image_y = old_gc.image_y;
|
||||
new_gc = &image_gc;
|
||||
}
|
||||
if (new_gc->flags & GRID_FLAG_IMAGE)
|
||||
new_id = new_gc->image_id;
|
||||
else
|
||||
new_id = 0;
|
||||
|
||||
if (old_id != new_id) {
|
||||
if (old_id != 0)
|
||||
@@ -809,11 +827,11 @@ grid_set_cells(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (grid_need_extended_cell(gce, gc)) {
|
||||
gee = grid_extended_cell(gl, gce, gc);
|
||||
if (grid_need_extended_cell(gce, new_gc)) {
|
||||
gee = grid_extended_cell(gl, gce, new_gc);
|
||||
gee->data = utf8_build_one(s[i]);
|
||||
} else
|
||||
grid_store_cell(gce, gc, s[i]);
|
||||
grid_store_cell(gce, new_gc, s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,10 +36,12 @@ $TMUX send-keys -X history-top || exit 1
|
||||
$TMUX capture-pane -p >$TMP || exit 1
|
||||
$TMUX send-keys -X cancel || exit 1
|
||||
|
||||
# Ordinary text overwrites marker cells through the normal grid write path.
|
||||
# Ordinary text updates the image underlay through the normal grid write path.
|
||||
# Deleting the image reveals the newly written text.
|
||||
$TMUX new-window -d "
|
||||
printf '\033_Ga=T,q=2,f=32,s=2,v=2,c=2,r=2;/wAA/wD/AP8AAP///////w==\033\\'
|
||||
printf '\033_Ga=T,q=2,f=32,s=2,v=2,c=2,r=2,i=8;/wAA/wD/AP8AAP///////w==\033\\'
|
||||
printf '\033[HXY'
|
||||
printf '\033_Ga=d,d=i,q=2,i=8\033\\'
|
||||
sleep 10"
|
||||
sleep 1
|
||||
[ "$($TMUX capture-pane -pt:1 -S0 -E0)" = "XY" ] || exit 1
|
||||
@@ -235,6 +237,28 @@ $TMUX2 select-window -t"$PLACEMENT_WINDOW" || exit 1
|
||||
sleep 1
|
||||
[ "$($TMUX2 capture-pane -pS0 -E0)" = "XY" ] || exit 1
|
||||
|
||||
# Text written over a Kitty placement updates its underlay without deleting
|
||||
# the image. Deleting the placement afterwards reveals the updated text.
|
||||
TEXT_WINDOW=$($TMUX2 new-window -dP -F '#{window_id}' "
|
||||
printf 'test\r'
|
||||
printf '\033_Ga=T,q=2,C=1,f=32,s=2,v=2,c=2,r=2,i=14,p=7;/wAA/wD/AP8AAP///////w==\033\\'
|
||||
printf '\r'
|
||||
printf 'test\n'
|
||||
printf 'test\n'
|
||||
$TEST_TMUX wait-for image-text-delete-$$
|
||||
printf '\033_Ga=d,d=i,q=2,i=14,p=7\033\\'
|
||||
sleep 10") || exit 1
|
||||
$TMUX2 select-window -t"$TEXT_WINDOW" || exit 1
|
||||
sleep 1
|
||||
$TMUX capture-pane -pS0 -E1 >$TMP || exit 1
|
||||
[ "$(sed -n 1p $TMP)" = ".*st" ] || exit 1
|
||||
[ "$(sed -n 2p $TMP)" = " @st" ] || exit 1
|
||||
$TMUX2 wait-for -S image-text-delete-$$ || exit 1
|
||||
sleep 1
|
||||
$TMUX capture-pane -pS0 -E1 >$TMP || exit 1
|
||||
[ "$(sed -n 1p $TMP)" = "test" ] || exit 1
|
||||
[ "$(sed -n 2p $TMP)" = "test" ] || exit 1
|
||||
|
||||
# A weighted median at the maximum channel level must still leave colours on
|
||||
# both sides of the split. This skewed black, grey and white image used to stop
|
||||
# palette generation after one colour instead of producing three.
|
||||
|
||||
@@ -2666,6 +2666,9 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
struct grid_line *gl;
|
||||
struct grid_cell_entry *gce;
|
||||
struct grid_cell tmp_gc, now_gc;
|
||||
#ifdef ENABLE_IMAGES
|
||||
struct grid_cell image_gc;
|
||||
#endif
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
u_int width = ud->width, xx, not_wrap, i, n, vis;
|
||||
@@ -2710,6 +2713,21 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
return;
|
||||
screen_write_initctx(ctx, &ttyctx, 0, 0);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
/* Update the text underlay without removing an image placement. */
|
||||
grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
|
||||
if ((now_gc.flags & GRID_FLAG_IMAGE) &&
|
||||
(~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.image_id = now_gc.image_id;
|
||||
image_gc.image_x = now_gc.image_x;
|
||||
image_gc.image_y = now_gc.image_y;
|
||||
gc = &image_gc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Handle overwriting of UTF-8 characters. */
|
||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||
if (gl->flags & GRID_LINE_EXTENDED) {
|
||||
|
||||
Reference in New Issue
Block a user