mirror of
https://github.com/tmux/tmux.git
synced 2026-10-10 04:04:27 +00:00
Clean up image support and add regression tests
This commit is contained in:
@@ -1,29 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Regression test for a border-status caching bug: window_make_pane_status()
|
||||
# (window-border.c) gates the physical redraw of a pane's border-status
|
||||
# title on a logical content diff (grid_compare against a cached copy), not
|
||||
# on whether the physical screen cells were disturbed by something else in
|
||||
# the meantime - such as a floating pane's own border, drawn on top of a
|
||||
# tiled pane's border-status row, sliding across it and then away again.
|
||||
# See tmux-image-redraw-known-bugs.md ("border-status text cache ignores
|
||||
# physical damage") for the full write-up.
|
||||
#
|
||||
# Reproduction: a tiled pane with pane-border-status on has a floating pane
|
||||
# dragged, by mouse, from directly over its border-status row to somewhere
|
||||
# else. The tiled pane's title should reappear once the floating pane has
|
||||
# moved off it; without the fix it stays blank.
|
||||
#
|
||||
# The drag starts and ends away from row 0 rather than grabbing the
|
||||
# floating pane's border while it is already sitting on row 0: when a
|
||||
# floating pane's own border-status row exactly coincides with the tiled
|
||||
# pane's row 0, mouse hit-testing on that row attributes clicks to the
|
||||
# tiled pane, not the floating one on top of it (an unrelated tmux quirk,
|
||||
# not what this test is about). That only matters for the initial press,
|
||||
# though - once a drag is under way, further motion events go straight to
|
||||
# the already-bound per-pane callback without re-resolving which pane owns
|
||||
# the coordinates, so starting the grab on an unambiguous row and dragging
|
||||
# through row 0 works fine.
|
||||
# A tiled pane's border title must reappear after a floating pane moves away.
|
||||
# Start the drag below row zero so its initial press hits the floating pane.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
@@ -1,22 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Regression test for a fixed bug: on a client detected as SIXEL-capable, a
|
||||
# pane-content redraw (PANE_REDRAW) erased the image backend's rectangle
|
||||
# using the redrawing pane's raw nominal geometry (wp->xoff/yoff/sx/sy)
|
||||
# instead of the cells it actually owns in the current scene. When a
|
||||
# floating pane occluded part of that rectangle, the erase blanked the
|
||||
# floating pane's on-screen area, and since the subsequent text redraw
|
||||
# correctly only refills cells the redrawing pane owns, nothing repainted
|
||||
# it back in - the floating pane's content stayed blank.
|
||||
#
|
||||
# Fixed in screen-redraw.c:redraw_draw_pane_lines() by erasing only the
|
||||
# cell ranges the pane actually owns per line (its REDRAW_SPAN_PANE spans),
|
||||
# not its raw rectangle. See tmux-sixel-erase-ignores-occlusion.md and
|
||||
# IMAGE-REDRAW-DISCUSSION.md for the full write-up.
|
||||
#
|
||||
# Confirmed by direct A/B test against this exact sequence: reliably wipes
|
||||
# the floating pane's content on the unfixed code, reliably leaves it
|
||||
# intact on the fixed code.
|
||||
# A SIXEL pane redraw must erase only cells owned by that pane, preserving
|
||||
# content in an overlapping floating pane when leaving copy mode.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
@@ -1,21 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Regression test: Alt-dragging a floating pane by its body (move-pane -M,
|
||||
# bound by default to M-MouseDrag1Pane/M-MouseDrag1Border) must not
|
||||
# retransmit images in other panes of the same window.
|
||||
#
|
||||
# cmd_join_pane_mouse_move() (cmd-join-pane.c) is a second, separate
|
||||
# implementation of "drag to move a floating pane" - parallel to the one in
|
||||
# cmd-resize-pane.c already fixed for plain (non-Alt) border drags - and
|
||||
# used to call server_redraw_window() unconditionally on every motion
|
||||
# event, wiping and retransmitting every image in the window on each step
|
||||
# of the drag even though only the floating pane's own rectangle actually
|
||||
# moved. See tmux-image-redraw-known-bugs.md for the full write-up.
|
||||
#
|
||||
# This is checked by counting DCS (\033P) sequences in the client's raw
|
||||
# output while a stationary tiled pane's image is present and an unrelated
|
||||
# floating pane is Alt-dragged elsewhere in the window: with the fix, none
|
||||
# should appear.
|
||||
# Alt-dragging a floating pane must not retransmit images in other panes.
|
||||
|
||||
. ./image-noflash-common.inc
|
||||
|
||||
|
||||
39
regress/image-placeholder-reflow.sh
Normal file
39
regress/image-placeholder-reflow.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Kitty placeholder rows stay cell-aligned when a client becomes narrower.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Limage-placeholder-outer$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -u -Limage-placeholder-inner$$ -f/dev/null"
|
||||
TMP=$(mktemp)
|
||||
trap "$TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null; rm -f $TMP" 0 1 15
|
||||
|
||||
$TMUX2 new-session -d -x 10 -y 4 "
|
||||
i=0
|
||||
while [ \$i -lt 10 ]; do
|
||||
printf '\\364\\216\\273\\256\\314\\205'
|
||||
i=\$((i + 1))
|
||||
done
|
||||
sleep 30" || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX new-session -d -x 10 -y 4 "$TMUX2 attach-session" || exit 1
|
||||
$TMUX set -g status off || 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
|
||||
38
regress/image-resize-many-placements.sh
Normal file
38
regress/image-resize-many-placements.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Widening a pane restores clipped columns for every image placement.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C
|
||||
export TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Limage-resize-outer$$ -f/dev/null"
|
||||
TMUX2="env -u TMUX LC_ALL=C $TEST_TMUX -Limage-resize-inner$$ -f/dev/null"
|
||||
TMP=$(mktemp)
|
||||
trap "$TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null; rm -f $TMP" 0 1 15
|
||||
|
||||
# White placements stay behind the final red placement.
|
||||
$TMUX2 new-session -d -x 8 -y 4 "
|
||||
i=0
|
||||
while [ \$i -lt 64 ]; do
|
||||
printf '\\033_Ga=T,q=2,C=1,f=32,s=1,v=1,c=16,r=1;/////w==\\033\\\\'
|
||||
i=\$((i + 1))
|
||||
done
|
||||
printf '\\033_Ga=T,q=2,C=1,f=32,s=1,v=1,c=16,r=1;/wAA/w==\\033\\\\'
|
||||
sleep 30" || exit 1
|
||||
[ "$($TMUX2 display-message -p '#{image_support}')" = 0 ] && exit 0
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX new-session -d -x 8 -y 4 "$TMUX2 attach-session" || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
sleep 1
|
||||
|
||||
$TMUX capture-pane -pS0 -E0 >$TMP || exit 1
|
||||
[ "$(cat $TMP)" = '........' ] || exit 1
|
||||
$TMUX resize-window -x 16 -y 4 || exit 1
|
||||
sleep 1
|
||||
$TMUX capture-pane -pS0 -E0 >$TMP || exit 1
|
||||
[ "$(cat $TMP)" = '................' ] || exit 1
|
||||
|
||||
exit 0
|
||||
@@ -1,29 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Regression test: an image wider than the pane at the time it was
|
||||
# displayed must show more of itself once the pane grows wide enough,
|
||||
# instead of staying clipped to its original width forever.
|
||||
#
|
||||
# image_write() (image.c) clips an image's width to whatever fit in the
|
||||
# pane when it was first displayed, and never revisits that decision -
|
||||
# unlike height, which recovers naturally through ordinary scrollback,
|
||||
# there is no "scroll right", so the clipped columns were permanently
|
||||
# discarded. window_pane_resize() (window.c) now calls
|
||||
# image_grid_resize_width() after a pane grows wider, which extends each
|
||||
# existing placement's spans - using the image's own retained, immutable
|
||||
# pixel data - up to whichever is smaller: the image's full width or the
|
||||
# new pane width. See tmux-image-redraw-known-bugs.md for the full
|
||||
# write-up.
|
||||
#
|
||||
# This is checked via the SIXEL raster widths reported in the client's raw
|
||||
# output before and after widening the window. The redraw triggered by the
|
||||
# resize is damage-based (only the newly-uncovered columns are dirtied), so
|
||||
# it does not redraw the whole row as one wider raster - it sends the
|
||||
# already-correct clipped portion's width again untouched, plus a *second*,
|
||||
# separate raster covering just the newly-added columns. So rather than
|
||||
# looking for a single wider raster, this checks that the widths seen
|
||||
# across both redraws, added together, account for the fixture's full
|
||||
# pixel width - i.e. the previously-clipped remainder actually appeared.
|
||||
# Widening a pane must recover image columns clipped at placement time.
|
||||
# A damage redraw can send the newly visible columns as a separate raster,
|
||||
# so compare the combined raster widths with the original image width.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
@@ -1,29 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Regression test: an image taller than the pane, at the moment it is first
|
||||
# displayed, must remain visible when scrolling back up through history -
|
||||
# not show blank space for the part that was scrolled off screen before the
|
||||
# user ever got to see it.
|
||||
#
|
||||
# image_write() (image.c) handles this case by scrolling the screen up
|
||||
# (via screen_write_scrollup()) to make room, then only ever wrote spans
|
||||
# for the rows that ended up on screen afterwards - the rows that were
|
||||
# immediately scrolled off (origin_y of them) were pushed into history as
|
||||
# blank, spanless rows and their image data was discarded. Unlike width,
|
||||
# which has no "scroll right" to recover a permanent clip, height already
|
||||
# has ordinary scrollback, so this was pure waste. image_write() now also
|
||||
# calls image_extend_row() for those origin_y history rows (capped to
|
||||
# gd->hsize, since screen_write_scrollup() may not have pushed a real
|
||||
# history row for every one of them - see tmux-uint-subtraction-underflow-
|
||||
# care.md), so scrolling back up recovers the image instead of showing
|
||||
# empty space. See tmux-image-redraw-known-bugs.md for the full write-up.
|
||||
#
|
||||
# This is checked by comparing how many separate SIXEL rasters the client
|
||||
# receives right after entering copy mode (a baseline - copy mode itself
|
||||
# triggers a redraw of the still-visible rows) against how many it
|
||||
# receives after scrolling to the very top of history: with the fix, more
|
||||
# rasters appear (covering the newly-revealed, previously-scrolled-off
|
||||
# rows); without it, scrolling reveals nothing new.
|
||||
# Images scrolled off-screen must reappear when copy mode scrolls back up.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
@@ -1,22 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Regression test: extending a copy-mode selection by cursor movement, with
|
||||
# the view otherwise unmoved (no scrolling), must not retransmit an image
|
||||
# whose row the cursor passes through.
|
||||
#
|
||||
# window_copy_write_one() (window-copy.c) used to write text/highlight
|
||||
# styling directly over image-covered cells, which - since a character
|
||||
# write typically clears whatever pixel content a terminal was showing
|
||||
# there - erased the image with nothing to redraw it back in. Separately,
|
||||
# window_copy_write_line()'s call to image_redraw_area() used to fire
|
||||
# unconditionally on every redraw, so even after fixing the erasure, the
|
||||
# image would still be needlessly recomposited (and briefly flash) on
|
||||
# every single cursor step even though nothing about it had changed. See
|
||||
# tmux-image-redraw-known-bugs.md for the full write-up.
|
||||
#
|
||||
# This is checked by counting DCS (\033P) sequences in the client's raw
|
||||
# output during the cursor movement: with the fix, extending a selection
|
||||
# without scrolling never touches the image, so none should appear.
|
||||
# Moving a copy-mode selection cursor must not retransmit unchanged images.
|
||||
|
||||
. ./image-noflash-common.inc
|
||||
|
||||
|
||||
@@ -1,23 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Regression test: interactively sizing a new floating pane by dragging
|
||||
# (new-pane -M, bound by default to C-MouseDrag1Pane/C-MouseDrag1Empty)
|
||||
# must not retransmit images in other panes of the same window on ongoing
|
||||
# drag steps.
|
||||
#
|
||||
# cmd_split_window_mouse_resize() (cmd-split-window.c) used to call
|
||||
# server_redraw_window() unconditionally on every motion event while
|
||||
# sizing the new floating pane, wiping and retransmitting every image in
|
||||
# the window on each step even though only the new pane's own rectangle
|
||||
# actually changed. See tmux-image-redraw-known-bugs.md for the full
|
||||
# write-up.
|
||||
#
|
||||
# Creating the floating pane itself causes one legitimate, unrelated
|
||||
# redraw (pane creation always redraws the session - see
|
||||
# server_redraw_session() in cmd-split-window.c), so this checks DCS
|
||||
# (\033P) counts only for the *ongoing* drag-motion steps after that
|
||||
# initial creation, once c->tty.mouse_drag_update is already bound to the
|
||||
# resize callback: with the fix, none should appear there.
|
||||
# Sizing a new floating pane must not retransmit images in other panes.
|
||||
# Wait for the initial creation redraw before checking subsequent drag steps.
|
||||
|
||||
. ./image-noflash-common.inc
|
||||
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C
|
||||
export TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Limage$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -Limage-client$$ -f/dev/null"
|
||||
TMUX2="env -u TMUX LC_ALL=C $TEST_TMUX -Limage-client$$ -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
@@ -24,6 +26,7 @@ $TMUX new-session -d -x 20 -y 8 "
|
||||
|
||||
sleep 1
|
||||
[ "$($TMUX display-message -p '#{image_support}')" = 0 ] && exit 0
|
||||
[ "$($TMUX display-message -p '#{sixel_support}')" = 1 ] || exit 1
|
||||
|
||||
# Images scroll as grid cells, while capture output contains ordinary spaces.
|
||||
[ "$($TMUX display-message -p '#{history_size}')" -gt 0 ] || exit 1
|
||||
@@ -187,27 +190,9 @@ $TMUX capture-pane -pS0 -E3 >$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.
|
||||
# Restore the wider client for the remaining placement checks.
|
||||
$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
|
||||
|
||||
# A placement ID supplied with transmit-and-place is reused by a later place.
|
||||
# This is the sequence used by chawan: the newline moves the cursor down before
|
||||
|
||||
Reference in New Issue
Block a user