mirror of
https://github.com/tmux/tmux.git
synced 2026-09-21 20:37:42 +00:00
window: redraw border status after moving floating panes
This commit is contained in:
@@ -1,86 +1,152 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Regression test for a KNOWN, NOT YET FIXED bug - this test currently
|
# Regression test for a border-status caching bug: window_make_pane_status()
|
||||||
# FAILS, and is expected to keep failing until the general damage-tracking
|
# (window-border.c) gates the physical redraw of a pane's border-status
|
||||||
# redraw work lands (IMAGE-REDRAW-PLAN.md, steps 2-4). Left failing
|
# title on a logical content diff (grid_compare against a cached copy), not
|
||||||
# deliberately rather than skipped, so `make` in regress/ shows accurate,
|
# on whether the physical screen cells were disturbed by something else in
|
||||||
# live status of whether this is fixed yet.
|
# 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.
|
||||||
#
|
#
|
||||||
# On a client detected as SIXEL-capable, entering copy-mode on a pane and
|
# Reproduction: a tiled pane with pane-border-status on has a floating pane
|
||||||
# moving the cursor can blank a floating pane's border-status title text
|
# dragged, by mouse, from directly over its border-status row to somewhere
|
||||||
# (and can also disturb window-level border/title chrome), without
|
# else. The tiled pane's title should reappear once the floating pane has
|
||||||
# redrawing it back in. Root cause: window_make_pane_status()
|
# moved off it; without the fix it stays blank.
|
||||||
# (window-border.c) gates the physical redraw of border-status text 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. See tmux-image-redraw-known-bugs.md ("border-status text
|
|
||||||
# cache ignores physical damage") and IMAGE-REDRAW-DISCUSSION.md for the
|
|
||||||
# full write-up.
|
|
||||||
#
|
#
|
||||||
# A proper damage-tracking compositor gates redraw on "was this region
|
# The drag starts and ends away from row 0 rather than grabbing the
|
||||||
# touched", not "did the logical content change", so the disturbing erase
|
# floating pane's border while it is already sitting on row 0: when a
|
||||||
# would itself register as damage and force recomposition regardless of
|
# floating pane's own border-status row exactly coincides with the tiled
|
||||||
# content diff. Design requirement for that work: border/status/scrollbar
|
# pane's row 0, mouse hit-testing on that row attributes clicks to the
|
||||||
# spans must participate in the same damage-driven composition as pane
|
# tiled pane, not the floating one on top of it (an unrelated tmux quirk,
|
||||||
# content, or this bug survives the rewrite unchanged.
|
# 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
|
||||||
# No mouse is required to reproduce this - entering copy-mode (matching a
|
# the already-bound per-pane callback without re-resolving which pane owns
|
||||||
# PageUp key binding) and moving the cursor once is enough.
|
# the coordinates, so starting the grab on an unambiguous row and dragging
|
||||||
|
# through row 0 works fine.
|
||||||
|
|
||||||
PATH=/bin:/usr/bin
|
PATH=/bin:/usr/bin
|
||||||
TERM=screen
|
TERM=screen
|
||||||
LC_ALL=C.UTF-8
|
LC_ALL=C.UTF-8
|
||||||
export TERM LC_ALL
|
export TERM LC_ALL
|
||||||
|
|
||||||
CONF=$(mktemp)
|
|
||||||
cat > "$CONF" <<EOF
|
|
||||||
set -g mouse on
|
|
||||||
set -g pane-scrollbars on
|
|
||||||
set -g pane-border-status top
|
|
||||||
set -g status 2
|
|
||||||
bind-key -n PPage "copy-mode -u"
|
|
||||||
bind-key -n NPage "copy-mode -d"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
TMUX="$TEST_TMUX -Libsw$$ -f/dev/null"
|
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||||
TMUX2="$TEST_TMUX -Libsw-inner$$ -f $CONF"
|
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||||
$TMUX kill-server 2>/dev/null
|
|
||||||
$TMUX2 kill-server 2>/dev/null
|
cleanup()
|
||||||
|
{
|
||||||
|
$TMUX kill-server >/dev/null 2>&1
|
||||||
|
$TMUX2 kill-server >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
fail()
|
||||||
|
{
|
||||||
|
echo "$*" >&2
|
||||||
|
cleanup
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# drag COL ROW [ROW ...]
|
||||||
|
#
|
||||||
|
# Write one continuous mouse-1 gesture at column COL: a press at the first
|
||||||
|
# ROW, a drag update at each subsequent ROW in turn, and a release at the
|
||||||
|
# last ROW - all 1-based positions sent to the outer pane holding the
|
||||||
|
# inner client. This matches the default MouseDown1Border/MouseDrag1Border
|
||||||
|
# bindings used to move or resize a floating pane by its border.
|
||||||
|
#
|
||||||
|
# This must be one continuous press/drag/.../release gesture, not several
|
||||||
|
# separate drag() calls chained together: releasing clears the per-pane
|
||||||
|
# drag callback binding, so a later press has to be re-hit-tested from
|
||||||
|
# scratch, which only works reliably away from row 0 (see the header
|
||||||
|
# comment). A drag already under way is not re-hit-tested per motion
|
||||||
|
# event, so it can safely pass through row 0 as an intermediate waypoint.
|
||||||
|
drag()
|
||||||
|
{
|
||||||
|
col="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
row="$1"
|
||||||
|
shift
|
||||||
|
seq=$(printf '\033[<0;%s;%sM' "$col" "$row")
|
||||||
|
$TMUX2 send-keys -t "$OUTER" -l "$seq" 2>/dev/null
|
||||||
|
sleep 0.2
|
||||||
|
|
||||||
|
while [ $# -gt 1 ]; do
|
||||||
|
row="$1"
|
||||||
|
shift
|
||||||
|
seq=$(printf '\033[<32;%s;%sM' "$col" "$row")
|
||||||
|
$TMUX2 send-keys -t "$OUTER" -l "$seq" 2>/dev/null
|
||||||
|
sleep 0.15
|
||||||
|
done
|
||||||
|
|
||||||
|
row="$1"
|
||||||
|
seq=$(printf '\033[<0;%s;%sm' "$col" "$row")
|
||||||
|
$TMUX2 send-keys -t "$OUTER" -l "$seq" 2>/dev/null
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
|
||||||
TMP=$(mktemp)
|
TMP=$(mktemp)
|
||||||
trap "$TMUX kill-server 2>/dev/null; $TMUX2 kill-server 2>/dev/null; rm -f $TMP $CONF" 0 1 15
|
trap "cleanup; rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
$TMUX2 new-session -d -x 60 -y 20 "sh -c 'i=0; while [ \$i -lt 30 ]; do printf \"TILE%02d\\n\" \$i; i=\$((i + 1)); done; exec sleep 100'"
|
$TMUX new-session -d -s inner -x 60 -y 20 'sh -c "sleep 100"' || exit 1
|
||||||
$TMUX2 new-pane -x20 -y6 -X8 -Y3 -T FLOATTITLE "sh -c 'printf FLOATCONTENT; exec sleep 100'"
|
$TMUX set -g mouse on
|
||||||
[ "$($TMUX2 display-message -p '#{image_support}')" = 0 ] && exit 0
|
$TMUX set -g pane-border-status top
|
||||||
$TMUX2 set -as terminal-features ',*:sixel'
|
$TMUX set -g default-command 'sh -c "sleep 100"'
|
||||||
|
|
||||||
$TMUX new-session -d -x 60 -y 20
|
BASE=$($TMUX list-panes -F '#{pane_id}' | head -1)
|
||||||
$TMUX send -l "$TMUX2 attach"
|
[ -n "$BASE" ] || fail "No base pane."
|
||||||
$TMUX send Enter
|
$TMUX select-pane -t "$BASE" -T TILEDTITLE || fail "set base title failed"
|
||||||
|
|
||||||
|
# Float a pane well clear of row 0 to start - its own top border must not
|
||||||
|
# coincide with the base pane's border-status row for the initial mouse
|
||||||
|
# press to unambiguously hit it (see the header comment). -x/-y are the
|
||||||
|
# pane's outer size including its 2-cell border frame, so request 2 more
|
||||||
|
# than the desired 14x3 content area (see layout_floating_args_parse()).
|
||||||
|
FLOAT=$($TMUX new-pane -d -PF '#{pane_id}' -x 16 -y 5 -X 5 -Y 5 -T FLOATTITLE) ||
|
||||||
|
fail "new-pane -X -Y failed"
|
||||||
|
FTOP=$($TMUX display-message -p -t "$FLOAT" '#{pane_top}')
|
||||||
|
FLEFT=$($TMUX display-message -p -t "$FLOAT" '#{pane_left}')
|
||||||
|
FWIDTH=$($TMUX display-message -p -t "$FLOAT" '#{pane_width}')
|
||||||
|
|
||||||
|
$TMUX2 new-session -d -x 60 -y 20 "$TMUX attach -t inner" || exit 1
|
||||||
sleep 1
|
sleep 1
|
||||||
|
OUTER=$($TMUX2 list-panes -F '#{pane_id}' | head -1)
|
||||||
|
[ -n "$OUTER" ] || fail "No outer pane."
|
||||||
|
|
||||||
# Sanity check: the floating pane's OWN border row shows its title before
|
# Sanity check: the base pane's title is visible now (the float starts
|
||||||
# anything disturbs it. (A bare 'FLOATTITLE' grep on the whole capture is
|
# well clear of row 0).
|
||||||
# not enough - the outer client's title bar separately reflects the pane
|
$TMUX2 capturep -p -t "$OUTER" >$TMP || fail "capture failed"
|
||||||
# title via an unrelated OSC title escape, regardless of this bug.)
|
head -1 $TMP | grep -q TILEDTITLE ||
|
||||||
$TMUX capturep -p >$TMP || exit 1
|
fail "base title not visible before the drag - test setup is wrong"
|
||||||
grep '┌' $TMP | grep -q 'FLOATTITLE' || exit 1
|
|
||||||
|
|
||||||
# Enter copy-mode on the (active) floating pane, matching the PageUp
|
# Drag the float up by its top border (an unambiguous row - not row 0) so
|
||||||
# binding, then move the cursor once, matching the Up binding.
|
# it ends up covering row 0, hiding the base pane's title behind its own
|
||||||
$TMUX2 copy-mode -u -t%1
|
# border, then continue the same drag back down again so it ends clear of
|
||||||
sleep 1
|
# row 0 once more - one continuous gesture the whole way (see drag()'s
|
||||||
$TMUX2 send-keys -t%1 -X cursor-up
|
# comment for why).
|
||||||
sleep 1
|
GRABCOL=$((FLEFT + FWIDTH / 2))
|
||||||
|
waypoints="$FTOP"
|
||||||
|
row=$FTOP
|
||||||
|
while [ "$row" != 1 ]; do
|
||||||
|
row=$((row - 1))
|
||||||
|
waypoints="$waypoints $row"
|
||||||
|
done
|
||||||
|
while [ "$row" != "$FTOP" ]; do
|
||||||
|
row=$((row + 1))
|
||||||
|
waypoints="$waypoints $row"
|
||||||
|
done
|
||||||
|
drag $((GRABCOL + 1)) $waypoints
|
||||||
|
drag $((GRABCOL + 1)) 1 $((GRABCOL + 1)) "$FTOP"
|
||||||
|
|
||||||
$TMUX capturep -p >$TMP || exit 1
|
$TMUX2 capturep -p -t "$OUTER" >$TMP || fail "capture failed"
|
||||||
|
|
||||||
# The border frame and its title text should both still be there. This is
|
# The base pane's title should be visible again now the floating pane has
|
||||||
# expected to fail today - see the header comment.
|
# moved off its border-status row. This is expected to fail before the fix
|
||||||
BORDERLINE=$(grep '┌' $TMP)
|
# - see the header comment.
|
||||||
[ -n "$BORDERLINE" ] || exit 1
|
head -1 $TMP | grep -q TILEDTITLE ||
|
||||||
echo "$BORDERLINE" | grep -q 'FLOATTITLE' || exit 1
|
fail "base pane title still blank after floating pane moved away"
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
|||||||
1
window.c
1
window.c
@@ -3016,4 +3016,5 @@ window_pane_redraw_floating(struct window *w, struct window_pane *wp,
|
|||||||
|
|
||||||
/* Session status formats may depend on the pane's new geometry. */
|
/* Session status formats may depend on the pane's new geometry. */
|
||||||
server_status_window(w);
|
server_status_window(w);
|
||||||
|
server_redraw_window(w);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user