diff --git a/layout-custom.c b/layout-custom.c index f801108ec..6164dc924 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -126,8 +126,7 @@ layout_append_geometry(char *buf, size_t len, u_int sx, u_int sy, int xoff, y = -(long long)yoff; } else y = yoff; - return (xsnprintf(buf, len, "%ux%u%s%llu%s%llu", sx, sy, xs, x, - ys, y)); + return (xsnprintf(buf, len, "%ux%u%s%llu%s%llu", sx, sy, xs, x, ys, y)); } /* Dump layout as a string. */ diff --git a/regress/layout-custom.sh b/regress/layout-custom.sh index a9e1bd821..3846dca64 100755 --- a/regress/layout-custom.sh +++ b/regress/layout-custom.sh @@ -27,6 +27,7 @@ must_fail() } $TMUX kill-server 2>/dev/null +sleep 0.5 $TMUX new-session -d -x 80 -y 24 || exit 1 $TMUX split-window -h || fail "split-window failed" @@ -47,6 +48,34 @@ must_equal "$($TMUX display-message -p '#{window_layout}')" "$layout" must_fail $TMUX select-layout \ '0000,80x24+0+0{%0,0:39x24+0+0;%1,1:40x24+40+0}' +# Top-bottom containers are accepted in both current and legacy formats. +topbottom='081e,80x24+0+0[%0,0:80x11+0+0;%1,1:80x12+0+12]' +$TMUX select-layout "$topbottom" || fail "top-bottom layout was rejected" +must_equal "$($TMUX display-message -p '#{window_layout}')" "$topbottom" +must_equal "$($TMUX list-panes -F '#{pane_width}x#{pane_height},#{pane_left},#{pane_top}')" \ + '80x11,0,0 +80x12,0,12' +$TMUX select-layout '80x24,0,0[80x11,0,0,0,80x12,0,12,1]' || \ + fail "legacy top-bottom layout was rejected" +must_equal "$($TMUX display-message -p '#{window_layout}')" "$topbottom" +$TMUX select-layout "$layout" || fail "layout could not be restored" + +# Exercise select-layout command paths around custom layout parsing. +$TMUX select-layout even-vertical || fail "named layout failed" +$TMUX select-layout -n || fail "next layout failed" +$TMUX select-layout -p || fail "previous layout failed" +$TMUX select-layout -o || fail "old layout failed" +$TMUX select-layout -E || fail "spread layout failed" +$TMUX select-layout "$layout" || fail "layout could not be restored" + +# A command-zoomed tiled pane emits the z flag without changing its saved +# tiled geometry. +$TMUX resize-pane -t %0 -Z || fail "tiled zoom failed" +must_equal "$($TMUX display-message -p '#{window_layout}')" \ + '8e46,80x24+0+0{%0,0:39x24+0+0:z;%1,1:40x24+40+0}' +$TMUX resize-pane -t %0 -Z || fail "tiled unzoom failed" +$TMUX select-layout "$layout" || fail "layout could not be restored" + # Whitespace and newlines between tokens do not affect the checksum. indented='93fc, 80x24 +0 +0 { @@ -109,6 +138,7 @@ must_fail $TMUX select-layout \ # assigns the remaining cells in tree order. A target with more panes fails. fewer='80x24+0+0{%100,1:26x24+0+0;%101,2:26x24+27+0;%102,0:26x24+54+0:z}' $TMUX select-layout "$fewer" || fail "surplus current cells were not removed" +must_equal "$($TMUX display-message -p '#{window_panes}')" 2 must_equal "$($TMUX display-message -p -t %0 '#{pane_left},#{pane_width}')" \ '0,26' must_equal "$($TMUX display-message -p -t %1 '#{pane_left},#{pane_width}')" \ @@ -123,15 +153,40 @@ esac must_fail $TMUX select-layout \ '80x24+0+0{%100,0:39x24+0+0;%101,1:20x24+40+0;%102,2:19x10+61+0}' must_fail $TMUX select-layout '%100,0:80x24+0+0' +must_fail $TMUX select-layout '80x24,0,0,0' $TMUX select-layout "$legacy" || fail "legacy layout could not be restored" -# Mixed legacy and new separators, duplicate z-indices and unknown flags fail. +# Mixed legacy and new syntax, malformed containers, duplicate z-indices, +# non-contiguous z-indices, invalid z-ordering and unknown flags fail. must_fail $TMUX select-layout \ '93ed,80x24+0+0{%0,0:39x24+0+0,%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24,0,0{39x24,0,0,0;%1,1:40x24+40+0}' +must_fail $TMUX select-layout '80x24+0+0{}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0;}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0|%1,1:40x24+40+0}' must_fail $TMUX select-layout \ '93ec,80x24+0+0{%0,0:39x24+0+0;%1,0:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0;%1,2:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0;%1,1:40x24+40+0:f}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:38x24+0+0;%1,1:40x24+39+0}' must_fail $TMUX select-layout \ '0e42,80x24+0+0{%0,0:39x24+0+0:q;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0:ff;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0:hh;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0:zz;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+0:z;%1,1:40x24+40+0:z}' +must_fail $TMUX select-layout \ + '80x24,0,0{39x24,0,0,0,40x24,40,0,}' # Truncated and overflowing values must fail without terminating the server. must_fail $TMUX select-layout '0000,' @@ -143,6 +198,23 @@ must_fail $TMUX select-layout \ '80x24+0+0{%0,0:39x24+2147483647+0;%1,1:40x24+40+0}' must_fail $TMUX select-layout \ '80x24+0+0{%0,0:39x24+0+0;%1,1:40x24+-10001+0}' +must_fail $TMUX select-layout \ + '80x24-1+0{%0,0:39x24+0+0;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24-1+0;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24+0+;%1,1:40x24+40+0}' +must_fail $TMUX select-layout \ + '80x24+0+0{%0,0:39x24++ +0;%1,1:40x24+40+0}' +long='80x24+0+0{%0,0:39x24+0+0;%1,1:40x24+40+0}' +i=0 +while [ $i -lt 9000 ]; do + long="${long}x" + i=$((i + 1)) +done +must_fail $TMUX select-layout "$long" $TMUX list-windows >/dev/null || fail "server exited after invalid layouts" # Invalid custom layouts must not unzoom the target window. @@ -154,7 +226,11 @@ $TMUX resize-pane -t %0 -Z || fail "unzoom failed" # The parser accepts its maximum nesting depth and safely rejects one more. $TMUX kill-server 2>/dev/null +sleep 0.5 $TMUX new-session -d -x 80 -y 24 || exit 1 +legacy_negative='a9af,%0,0:20x8+0+0' +$TMUX select-layout '20x8,-10,-20,0' || fail "legacy negative layout failed" +must_equal "$($TMUX display-message -p '#{window_layout}')" "$legacy_negative" deep='%0,0:1x1+0+0' i=1 while [ $i -lt 64 ]; do @@ -167,8 +243,20 @@ must_fail $TMUX select-layout "1x1+0+0{$deep}" # X-style geometry supports right/bottom-relative offsets, absolute negative # offsets, doubled plus signs, and omitted positions. $TMUX kill-server 2>/dev/null +sleep 0.5 $TMUX new-session -d -x 120 -y 40 || exit 1 $TMUX new-pane -d -x 20 -y 8 'sleep 100' || fail "floating pane failed" + +# A real floating pane moved partly outside the window emits absolute negative +# offsets in canonical X-style form. +$TMUX move-pane -t %1 -X -10 -Y -20 || fail "negative move-pane failed" +must_equal "$($TMUX display-message -p -t %1 '#{pane_left},#{pane_top},#{pane_width},#{pane_height}')" \ + '-9,-19,18,6' +case "$($TMUX display-message -p '#{window_layout}')" in +*'%1,0:18x6+-9+-19:f'*) ;; +*) fail "negative floating pane was not serialized with +- offsets" ;; +esac + relative='1442,120x40+0+0{%0,1:120x40+0+0;%1,0:30x10-10-20:f}' $TMUX select-layout "$relative" || fail "relative geometry was rejected" must_equal "$($TMUX display-message -p -t %1 '#{pane_left},#{pane_top}')" \ @@ -176,12 +264,32 @@ must_equal "$($TMUX display-message -p -t %1 '#{pane_left},#{pane_top}')" \ must_equal "$($TMUX display-message -p '#{window_layout}')" \ '0041,120x40+0+0{%0,1:120x40+0+0;%1,0:30x10+80+10:f}' +bottomright='120x40+0+0{%0,1:120x40+0+0;%1,0:30x10-0-0:f}' +$TMUX select-layout "$bottomright" || fail "bottom-right geometry failed" +must_equal "$($TMUX display-message -p -t %1 '#{pane_left},#{pane_top}')" \ + '90,30' +must_equal "$($TMUX display-message -p '#{window_layout}')" \ + '2242,120x40+0+0{%0,1:120x40+0+0;%1,0:30x10+90+30:f}' + absolute='3a22,120x40+0+0{%0,1:120x40+0+0;%1,0:20x8+-10+-20:f}' $TMUX select-layout "$absolute" || fail "absolute negative geometry failed" must_equal "$($TMUX display-message -p -t %1 '#{pane_left},#{pane_top}')" \ '-10,-20' must_equal "$($TMUX display-message -p '#{window_layout}')" "$absolute" +hiddenfloat='120x40+0+0{%0,1:120x40+0+0;%1,0:20x8+-10+-20:fh}' +$TMUX select-layout "$hiddenfloat" || fail "hidden floating layout failed" +must_equal "$($TMUX display-message -p -t %1 '#{pane_left},#{pane_top},#{pane_width},#{pane_height}')" \ + '-10,-20,20,8' +must_equal "$($TMUX display-message -p '#{window_layout}')" \ + '9d83,120x40+0+0{%0,1:120x40+0+0;%1,0:20x8+-10+-20:fh}' +must_fail $TMUX select-layout \ + '120x40+0+0{%0,1:120x40+0+0;%1,0:20x8+-10+-20:fhz}' +must_equal "$($TMUX display-message -p '#{window_layout}')" \ + '9d83,120x40+0+0{%0,1:120x40+0+0;%1,0:20x8+-10+-20:fh}' +must_fail $TMUX select-layout \ + '120x40+0+0{%0,1:120x40+0+0;%1,0:10000x8-10000+0:f}' + defaults='fcb6,120x40{%0,1:120x40;%1,0:30x10++80+10:f}' $TMUX select-layout "$defaults" || fail "default or doubled offsets failed" must_equal "$($TMUX display-message -p '#{window_layout}')" \ @@ -193,6 +301,7 @@ must_equal "$($TMUX display-message -p '#{window_layout}')" \ '5fb9,120x40+0+0{%0,1:120x40+0+0;%1,0:30x10+80+0:f}' $TMUX kill-server 2>/dev/null +sleep 0.5 $TMUX new-session -d -x 80 -y 24 || exit 1 $TMUX split-window -h || fail "split-window failed" @@ -212,11 +321,14 @@ before=$($TMUX display-message -p -t @0 '#{window_width}x#{window_height}') must_fail $TMUX select-layout "@0:$reported@1:0000," must_equal "$($TMUX display-message -p -t @0 '#{window_width}x#{window_height}')" \ "$before" +must_fail $TMUX select-layout '@0' +must_fail $TMUX select-layout '@0:' must_fail $TMUX select-layout "@0:$legacy@0:$legacy" must_fail $TMUX select-layout "@999999:$legacy" # Add floating panes and verify exact z-order, semicolon output and zoom state. $TMUX kill-server 2>/dev/null +sleep 0.5 $TMUX new-session -d -x 120 -y 40 || exit 1 $TMUX split-window -h || fail "split-window failed" $TMUX new-pane -d -x 30 -y 10 -X 10 -Y 5 'sleep 100' || \ @@ -225,6 +337,8 @@ $TMUX new-pane -d -x 24 -y 8 -X 50 -Y 12 'sleep 100' || \ fail "second floating pane failed" layout=$($TMUX display-message -p '#{window_layout}') +must_equal "$layout" \ + 'a6f2,120x40+0+0{%0,2:60x40+0+0;%1,3:59x40+61+0;%3,0:22x6+51+13:f;%2,1:28x8+11+6:f}' case "$layout" in *'<'*|*'>'*) fail "obsolete floating delimiters were emitted" ;; esac