mirror of
https://github.com/tmux/tmux.git
synced 2026-10-06 17:49:52 +00:00
187 lines
5.5 KiB
Bash
Executable File
187 lines
5.5 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Redraw a moved floating pane on both attached clients viewing the same
|
|
# window. Window redraw work must not be consumed by only one client.
|
|
#
|
|
# Uses ASCII pane borders (rather than the default UTF-8 box-drawing) because
|
|
# this test nests a real tmux client inside another tmux's pane to get a
|
|
# genuine terminal to capture from; that nested-tmux relay has been observed
|
|
# to mis-render a cell that previously held a multi-byte UTF-8 border
|
|
# character being overwritten later by plain content, on the outer instance's
|
|
# own interpretation, independent of anything the inner tmux sends. That is a
|
|
# nested-test-harness artifact, not a real tmux bug - confirmed by replaying
|
|
# the exact same drag sequence against a real terminal (xterm), where it
|
|
# never reproduces. ASCII borders avoid the artifact entirely.
|
|
|
|
PATH=/bin:/usr/bin
|
|
TERM=screen
|
|
LC_ALL=C.UTF-8
|
|
export PATH TERM LC_ALL
|
|
|
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
|
|
|
DIR=$(mktemp -d) || exit 1
|
|
INNER="$TEST_TMUX -Lredraw-multi-inner-$$ -f/dev/null"
|
|
OUTER="$TEST_TMUX -Lredraw-multi-outer-$$ -f/dev/null"
|
|
CAPTURE=$DIR/capture
|
|
|
|
fail()
|
|
{
|
|
echo "$*" >&2
|
|
[ -s "$CAPTURE" ] && cat "$CAPTURE" >&2
|
|
exit 1
|
|
}
|
|
|
|
cleanup()
|
|
{
|
|
$OUTER kill-server 2>/dev/null
|
|
$INNER kill-server 2>/dev/null
|
|
rm -rf "$DIR"
|
|
}
|
|
trap cleanup 0 1 15
|
|
|
|
wait_for_clients()
|
|
{
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
count=$($INNER list-clients 2>/dev/null | wc -l)
|
|
[ "$count" -eq 2 ] && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "two inner clients did not attach"
|
|
}
|
|
|
|
wait_outer_has()
|
|
{
|
|
target=$1
|
|
marker=$2
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
$OUTER capture-pane -p -t "$target" >"$CAPTURE" 2>/dev/null || true
|
|
grep -q "$marker" "$CAPTURE" && return 0
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "outer pane $target did not show $marker"
|
|
}
|
|
|
|
wait_float_left()
|
|
{
|
|
comparison=$1
|
|
limit=$2
|
|
i=0
|
|
while [ "$i" -lt 50 ]; do
|
|
left=$($INNER display-message -p -t "$FLOAT" '#{pane_left}')
|
|
if [ "$comparison" = gt ] && [ "$left" -gt "$limit" ]; then
|
|
return 0
|
|
fi
|
|
if [ "$comparison" = lt ] && [ "$left" -lt "$limit" ]; then
|
|
return 0
|
|
fi
|
|
sleep 0.1
|
|
i=$((i + 1))
|
|
done
|
|
fail "floating pane did not move"
|
|
}
|
|
|
|
mouse()
|
|
{
|
|
sequence=$(printf '\033[<%s;%s;%s%s' "$2" "$3" "$4" "$5")
|
|
$OUTER send-keys -t "$1" -l "$sequence" || exit 1
|
|
sleep 0.1
|
|
}
|
|
|
|
drag_float()
|
|
{
|
|
target=$1
|
|
startcol=$2
|
|
startrow=$3
|
|
endcol=$4
|
|
mouse "$target" 0 "$startcol" "$startrow" M
|
|
mouse "$target" 32 "$endcol" "$startrow" M
|
|
mouse "$target" 0 "$endcol" "$startrow" m
|
|
}
|
|
|
|
assert_scene()
|
|
{
|
|
target=$1
|
|
base=$2
|
|
firstcol=$3
|
|
lastcol=$4
|
|
|
|
$OUTER capture-pane -p -t "$target" >"$CAPTURE" || exit 1
|
|
|
|
# With ASCII (simple) borders every corner and junction is the same
|
|
# '+', so one rectangular floating pane always draws exactly 4 of
|
|
# them; more means a stale frame was left behind somewhere.
|
|
corners=$(grep -o '+' "$CAPTURE" | wc -l)
|
|
[ "$corners" -eq 4 ] ||
|
|
fail "outer pane $target had $corners floating frames"
|
|
|
|
sed -n '6,11p' "$base" | cut -c"$firstcol-$lastcol" >"$DIR/want"
|
|
sed -n '6,11p' "$CAPTURE" | cut -c"$firstcol-$lastcol" >"$DIR/got"
|
|
cmp -s "$DIR/want" "$DIR/got" ||
|
|
fail "outer pane $target did not restore the old floating area"
|
|
}
|
|
|
|
C="sh -c 'i=0; while [ \$i -lt 20 ]; do printf \"\\033[%d;1HBG-ROW-%02d-abcdefghijklmnopqrstuvwxyz0123456789\" \$((i + 1)) \$i; i=\$((i + 1)); done; exec sleep 100'"
|
|
|
|
$INNER new-session -d -s inner -x 60 -y 20 "$C" || exit 1
|
|
$INNER set-option -g status off || exit 1
|
|
$INNER set-option -g window-size manual || exit 1
|
|
$INNER set-option -g mouse on || exit 1
|
|
$INNER set-option -g default-command 'sleep 100' || exit 1
|
|
$INNER set-option -g pane-border-lines simple || exit 1
|
|
|
|
$OUTER new-session -d -s outer -x 121 -y 20 'sleep 100' || exit 1
|
|
$OUTER set-option -g status off || exit 1
|
|
$OUTER set-option -g window-size manual || exit 1
|
|
$OUTER set-option -g default-terminal screen || exit 1
|
|
$OUTER split-window -h -t outer:0.0 'sleep 100' || exit 1
|
|
|
|
PANES=$($OUTER list-panes -t outer:0 -F '#{pane_id} #{pane_left}')
|
|
LEFT=$(echo "$PANES" | sort -k2 -n | head -1 | cut -d' ' -f1)
|
|
RIGHT=$(echo "$PANES" | sort -k2 -n | tail -1 | cut -d' ' -f1)
|
|
[ -n "$LEFT" ] && [ -n "$RIGHT" ] || fail "could not find outer panes"
|
|
|
|
$OUTER respawn-pane -k -t "$LEFT" \
|
|
"$TEST_TMUX -Lredraw-multi-inner-$$ -f/dev/null attach-session -t inner" ||
|
|
exit 1
|
|
$OUTER respawn-pane -k -t "$RIGHT" \
|
|
"$TEST_TMUX -Lredraw-multi-inner-$$ -f/dev/null attach-session -t inner" ||
|
|
exit 1
|
|
|
|
wait_for_clients
|
|
wait_outer_has "$LEFT" BG-ROW-19
|
|
wait_outer_has "$RIGHT" BG-ROW-19
|
|
$OUTER capture-pane -p -t "$LEFT" >"$DIR/base-left" || exit 1
|
|
$OUTER capture-pane -p -t "$RIGHT" >"$DIR/base-right" || exit 1
|
|
|
|
FLOAT=$($INNER new-pane -dPF '#{pane_id}' -x 16 -y 5 -X 5 -Y 5) ||
|
|
fail "could not create floating pane"
|
|
wait_outer_has "$LEFT" '+'
|
|
wait_outer_has "$RIGHT" '+'
|
|
|
|
FTOP=$($INNER display-message -p -t "$FLOAT" '#{pane_top}')
|
|
FLEFT=$($INNER display-message -p -t "$FLOAT" '#{pane_left}')
|
|
FWIDTH=$($INNER display-message -p -t "$FLOAT" '#{pane_width}')
|
|
GRABCOL=$((FLEFT + FWIDTH / 2 + 1))
|
|
|
|
# Move right through one client and require both clients to restore the old
|
|
# left-hand footprint.
|
|
drag_float "$LEFT" "$GRABCOL" "$FTOP" $((GRABCOL + 30))
|
|
wait_float_left gt 30
|
|
assert_scene "$LEFT" "$DIR/base-left" 1 20
|
|
assert_scene "$RIGHT" "$DIR/base-right" 1 20
|
|
|
|
# Move back through the other client and check the old right-hand footprint.
|
|
FLEFT=$($INNER display-message -p -t "$FLOAT" '#{pane_left}')
|
|
GRABCOL=$((FLEFT + FWIDTH / 2 + 1))
|
|
drag_float "$RIGHT" "$GRABCOL" "$FTOP" $((GRABCOL - 30))
|
|
wait_float_left lt 10
|
|
assert_scene "$LEFT" "$DIR/base-left" 35 60
|
|
assert_scene "$RIGHT" "$DIR/base-right" 35 60
|
|
|
|
exit 0
|