From f81c41929bc9c9921b109bdd5539c0d0fc114d77 Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Wed, 5 Aug 2026 13:51:07 +0100 Subject: [PATCH] Fix kitty image resize issue when the kitty image resized smaller than the image, the image was overflowing lines and banding. --- grid.c | 34 ++++++++++++++++++++++++++++++++++ regress/image-support.sh | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/grid.c b/grid.c index 1c17544b2..6bd8e3162 100644 --- a/grid.c +++ b/grid.c @@ -1448,6 +1448,30 @@ grid_reflow_dead(struct grid_line *gl) gl->flags = GRID_LINE_DEAD; } +/* Image rows are cell-aligned and must not be reflowed like text. */ +static int +grid_reflow_has_image(struct grid_line *gl) +{ + struct grid_cell gc; + u_int i; + + if (~gl->flags & GRID_LINE_EXTENDED) + return (0); + for (i = 0; i < gl->cellused; i++) { + grid_get_cell1(gl, i, &gc); +#ifdef ENABLE_IMAGES + if (gc.flags & GRID_FLAG_IMAGE) + return (1); +#endif + /* Kitty Unicode placeholder base character (U+10EEEE). */ + if (gc.data.size >= 4 && gc.data.data[0] == 0xf4 && + gc.data.data[1] == 0x8e && gc.data.data[2] == 0xbb && + gc.data.data[3] == 0xae) + return (1); + } + return (0); +} + /* Add lines, return the first new one. */ static struct grid_line * grid_reflow_add(struct grid *gd, u_int n) @@ -1510,6 +1534,10 @@ grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy, break; line = yy + 1 + lines; + /* Do not join wrapped text to a cell-aligned image row. */ + if (grid_reflow_has_image(&gd->linedata[line])) + break; + /* If the next line is empty, skip it. */ if (~gd->linedata[line].flags & GRID_LINE_WRAPPED) wrapped = 0; @@ -1681,6 +1709,12 @@ grid_reflow(struct grid *gd, u_int sx) if (gl->flags & GRID_LINE_DEAD) continue; + /* Keep image markers at their original cell coordinates. */ + if (grid_reflow_has_image(gl)) { + grid_reflow_move(target, gl); + continue; + } + /* * Work out the width of this line. at is the point at which * the available width is hit, and width is the full line diff --git a/regress/image-support.sh b/regress/image-support.sh index b4e59ed7b..39e1ad3d7 100755 --- a/regress/image-support.sh +++ b/regress/image-support.sh @@ -143,4 +143,42 @@ $TMUX capture-pane -pS0 -E3 >$TMP || exit 1 [ "$(sed -n 2p $TMP)" = "*" ] || exit 1 [ "$(sed -n 3p $TMP)" = "@" ] || exit 1 +# Image marker rows remain cell-aligned when a narrower terminal causes text +# reflow. The ten-column rows are clipped to five columns, not split into four +# wrapped rows. +$TMUX2 new-window -d " + printf '\033_Ga=T,q=2,C=1,f=32,s=1,v=2,c=10,r=2;/wAA//////8=\033\\' + sleep 10" || exit 1 +$TMUX2 select-window -t:3 || exit 1 +sleep 1 +$TMUX resize-window -x 5 -y 4 || exit 1 +sleep 1 +[ "$($TMUX2 display-message -p '#{window_width}x#{window_height}')" = "5x4" ] || exit 1 +$TMUX capture-pane -pS0 -E3 >$TMP || exit 1 +[ "$(sed -n 1p $TMP)" = "....." ] || exit 1 +[ "$(sed -n 2p $TMP)" = "@@@@@" ] || exit 1 +[ -z "$(sed -n 3p $TMP)" ] || exit 1 + +# Kitty virtual placements use U+10EEEE placeholder cells. Keep their rows at +# fixed coordinates when narrowing the terminal, clipping instead of reflowing +# the second half onto the following row. +$TMUX resize-window -x 10 -y 4 || exit 1 +sleep 1 +$TMUX2 new-window -d " + printf '\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205' + printf '\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205\\364\\216\\273\\256\\314\\205' + sleep 10" || exit 1 +$TMUX2 select-window -t:4 || exit 1 +sleep 1 +$TMUX resize-window -x 5 -y 4 || exit 1 +sleep 1 +$TMUX capture-pane -pS0 -E3 >$TMP || exit 1 +[ -n "$(sed -n 1p $TMP)" ] || exit 1 +[ -z "$(sed -n 2p $TMP)" ] || exit 1 +$TMUX resize-window -x 10 -y 4 || exit 1 +sleep 1 +$TMUX capture-pane -pS0 -E3 >$TMP || exit 1 +[ "$(sed -n 1p $TMP | wc -c)" = 61 ] || exit 1 +[ -z "$(sed -n 2p $TMP)" ] || exit 1 + exit 0