diff --git a/regress/floating-pane-geometry.sh b/regress/floating-pane-geometry.sh index b04344ff2..74a3e9e11 100644 --- a/regress/floating-pane-geometry.sh +++ b/regress/floating-pane-geometry.sh @@ -268,5 +268,149 @@ $TMUX kill-pane -t "$floating" || exit 1 $TMUX kill-pane -t "$right" || exit 1 $TMUX kill-pane -t "$lower" || exit 1 +# --- Floating panes clamped when the window shrinks (issue #5581, PR #5582) --- +# +# layout_resize clamps floating panes back inside the window when it shrinks: +# move them and, only if they cannot fit, shrink them (never below +# PANE_MINIMUM). A floating cell is the pane's content, so with the default +# single-line border the clamp counts 1 cell of border per side, exactly as +# layout_floating_args_parse does on creation; with no border it counts 0. +# Each case below gets its own window, since resize-window fixes a window at +# a manual size for the rest of its life. + +# Case 1: a lone floating pane -- break-pane -W on a window's only pane -- +# takes the early-return path in layout_resize, added during PR #5582's +# review round, since there is no tiled tree to walk. +win=$($TMUX new-window -dPF '#{window_id}') || + fail "new-window for lone float failed" + +# -x 20 -y 6 -> pane 18x4; -X 60 -Y 18 -> pane_left 61, pane_top 19: with the +# border, the footprint is columns 60-79, rows 18-23, flush with the 80x24 +# window's right and bottom edges, so the float fits before it is shrunk. +$TMUX break-pane -W -s "$win" -x 20 -y 6 -X 60 -Y 18 || + fail "break-pane -W for lone float failed" +must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 61 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 19 + +# Shrink to 40x16. The float still fits at its own size (18 <= 40-2, 4 <= +# 16-2) so only its position moves, flush to the new right/bottom edges: +# xoff = 40 - 18 - 1 = 21; yoff = 16 - 4 - 1 = 11. +$TMUX resize-window -t "$win" -x 40 -y 16 || + fail "resize-window (lone float) failed" +must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 21 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 11 + +# Case 5: grow the window back. The clamp must not chase the window back +# outward -- it only ever pulls a float in, never restores where it was. +$TMUX resize-window -t "$win" -x 80 -y 24 || + fail "resize-window grow (lone float) failed" +must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 21 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 11 +$TMUX kill-window -t "$win" || exit 1 + +# Case 2: the same float, but with a tiled sibling surviving alongside it, so +# the window's root cell stays tiled and layout_resize takes the normal path +# (the clamp call after layout_fix_offsets) instead of the early return +# above. Same geometry as case 1, so the same numbers should come out. +win=$($TMUX new-window -dPF '#{window_id}') || + fail "new-window for tiled sibling failed" +$TMUX split-window -t "$win" 'sleep 100' || + fail "split-window for tiled sibling failed" +$TMUX break-pane -W -s "$win" -x 20 -y 6 -X 60 -Y 18 || + fail "break-pane -W for tiled sibling failed" +must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 61 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 19 + +$TMUX resize-window -t "$win" -x 40 -y 16 || + fail "resize-window (tiled sibling) failed" +must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 21 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 11 +$TMUX kill-window -t "$win" || exit 1 + +# Case 3: new-pane float, the original repro from issue #5581 and the PR +# body -- also the normal path, via the tiled base pane new-window creates. +win=$($TMUX new-window -dPF '#{window_id}') || + fail "new-window for new-pane repro failed" +$TMUX resize-window -t "$win" -x 120 -y 40 || + fail "resize-window to 120x40 failed" + +# -x 30 -y 10 -> pane 28x8; -X 85 -Y 25 -> pane_left 86, pane_top 26. +floating=$($TMUX new-pane -t "$win" -dPF '#{pane_id}' \ + -x 30 -y 10 -X 85 -Y 25 'sleep 100') || + fail "new-pane for new-pane repro failed" +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 28 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 8 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 86 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 26 + +# Shrink to 60x20: xoff = 60 - 28 - 1 = 31; yoff = 20 - 8 - 1 = 11. +$TMUX resize-window -t "$win" -x 60 -y 20 || + fail "resize-window (new-pane repro) failed" +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 28 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 8 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 31 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 11 +$TMUX kill-window -t "$win" || exit 1 + +# Case 4: a float that already fits inside the shrunk window is left alone -- +# assert position and size are both unchanged, not just one of them. +win=$($TMUX new-window -dPF '#{window_id}') || + fail "new-window for untouched float failed" + +# -x 20 -y 6 -> pane 18x4; -X 8 -Y 3 -> pane_left 9, pane_top 4 (as at the top +# of this file). Footprint columns 8-27, rows 3-8: well inside 60x20 too. +floating=$($TMUX new-pane -t "$win" -dPF '#{pane_id}' \ + -x 20 -y 6 -X 8 -Y 3 'sleep 100') || + fail "new-pane for untouched float failed" +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 18 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 4 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 9 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 4 + +$TMUX resize-window -t "$win" -x 60 -y 20 || + fail "resize-window (untouched float) failed" +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 18 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 4 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 9 +must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 4 +$TMUX kill-window -t "$win" || exit 1 + +# Case 6: pad = 0, via the pane-border-lines window option set to none. The +# border arithmetic differs here (no -2/+1 adjustment either on creation or +# in the clamp). +win=$($TMUX new-window -dPF '#{window_id}') || + fail "new-window for pad=0 float failed" +$TMUX set-option -w -t "$win" pane-border-lines none || + fail "set pane-border-lines none failed" + +# No border: -x 20 -y 6 -> pane 20x6 directly; -X 60 -Y 18 -> pane_left 60, +# pane_top 18 directly. Footprint (== content, no border) is columns 60-79, +# rows 18-23: flush right/bottom of the 80x24 window, same as case 1. +$TMUX break-pane -W -s "$win" -x 20 -y 6 -X 60 -Y 18 || + fail "break-pane -W for pad=0 float failed" +must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 20 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 6 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 60 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 18 + +# Shrink to 40x16 with pad=0: xoff = 40 - 20 - 0 = 20; yoff = 16 - 6 - 0 = 10. +$TMUX resize-window -t "$win" -x 40 -y 16 || + fail "resize-window (pad=0 float) failed" +must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 20 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 6 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 20 +must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 10 +$TMUX kill-window -t "$win" || exit 1 + $TMUX kill-server 2>/dev/null exit 0