From 620c6556778a0df15be4fa33647fff1f6ab36255 Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Sun, 5 Oct 2025 17:00:58 +0000 Subject: [PATCH] patch 9.1.1831: stray vseps in right-most 'winfixwidth' window Problem: vertical separator of 'winfixwidth' windows may remain if they become right-most windows from closing windows to the right. Solution: Don't implicitly rely on frame_new_width to fix vseps, as the call may be skipped for 'winfixwidth' windows to preserve their width; do it explicitly in winframe_remove (Sean Dewar). Note that I prefer win_new_width here over setting w_width directly, which would've previously been done by win_split_ins after frame_add_vsep, as this wasn't true for winframe_remove. Though the equivalent issue of bottom 'winfixheight' windows leaving stray statuslines with &ls=0 doesn't seem to exist, test it anyway. closes: #18481 Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com> Signed-off-by: Christian Brabandt --- .../Test_winfixsize_vsep_statusline_1.dump | 8 ++++ .../Test_winfixsize_vsep_statusline_2.dump | 8 ++++ src/testdir/test_window_cmd.vim | 46 +++++++++++++++++++ src/version.c | 2 + src/window.c | 28 +++++++---- 5 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 src/testdir/dumps/Test_winfixsize_vsep_statusline_1.dump create mode 100644 src/testdir/dumps/Test_winfixsize_vsep_statusline_2.dump diff --git a/src/testdir/dumps/Test_winfixsize_vsep_statusline_1.dump b/src/testdir/dumps/Test_winfixsize_vsep_statusline_1.dump new file mode 100644 index 0000000000..60dbb3b425 --- /dev/null +++ b/src/testdir/dumps/Test_winfixsize_vsep_statusline_1.dump @@ -0,0 +1,8 @@ +> +0&#ffffff0@35||+1&&| +0&&@37 +|~+0#4040ff13&| @34||+1#0000000&|~+0#4040ff13&| @36 +|~| @34||+1#0000000&|~+0#4040ff13&| @36 +|~| @34||+1#0000000&|~+0#4040ff13&| @36 +|~| @34||+1#0000000&|~+0#4040ff13&| @36 +|~| @34||+1#0000000&|~+0#4040ff13&| @36 +|[+3#0000000&|N|o| |N|a|m|e|]| @8|0|,|0|-|1| @9|A|l@1| |[+1&&|N|o| |N|a|m|e|]| @10|0|,|0|-|1| @9|A|l@1 +|:+0&&|q|u|i|t| @69 diff --git a/src/testdir/dumps/Test_winfixsize_vsep_statusline_2.dump b/src/testdir/dumps/Test_winfixsize_vsep_statusline_2.dump new file mode 100644 index 0000000000..f22090be93 --- /dev/null +++ b/src/testdir/dumps/Test_winfixsize_vsep_statusline_2.dump @@ -0,0 +1,8 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|[+3#0000000&|N|o| |N|a|m|e|]| @47|0|,|0|-|1| @9|A|l@1 +| +0&&@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|:+0#0000000&|q|u|i|t| @51|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 2e00ab4538..c00f60e394 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -2305,4 +2305,50 @@ func Test_winfixsize_positions() %bwipe endfunc +func Test_winfixsize_vsep_statusline() + CheckScreendump + let lines =<< trim END + set noequalalways splitbelow splitright + vsplit + setlocal winfixwidth + vsplit + func SetupWfh() + set laststatus=0 + only + split + set winfixheight + split + endfunc + END + call writefile(lines, 'XTestWinfixsizeVsepStatusline', 'D') + let buf = RunVimInTerminal('-S XTestWinfixsizeVsepStatusline', #{rows: 8}) + + call term_sendkeys(buf, ":echo winwidth(1) winwidth(2) winwidth(3)\n") + call WaitForAssert({-> assert_match('^16 37 20\>', term_getline(buf, 8))}) + + call term_sendkeys(buf, ":quit\n") + call VerifyScreenDump(buf, 'Test_winfixsize_vsep_statusline_1', {}) + + " Reported widths should be consistent with the screen dump. + call term_sendkeys(buf, ":echo winwidth(1) winwidth(2)\n") + " (May be better if 'wfw' window remains at 37 columns, but the resize is + " consistent with how things currently work for 'winfix*' windows) + call WaitForAssert({-> assert_match('^36 38\>', term_getline(buf, 8))}) + + " For good measure, also check bottom-most 'winfixheight' windows don't leave + " stray statuslines with &laststatus=0. + call term_sendkeys(buf, + \ ":call SetupWfh() | echo winheight(1) winheight(2) winheight(3)\n") + call WaitForAssert({-> assert_match('^1 3 1\>', term_getline(buf, 8))}) + + call term_sendkeys(buf, ":quit\n") + call VerifyScreenDump(buf, 'Test_winfixsize_vsep_statusline_2', {}) + + call term_sendkeys(buf, ":echo winheight(1) winheight(2)\n") + " (Likewise, may be better if 'wfh' window remains at 3 rows) + call WaitForAssert({-> assert_match('^2 4\>', term_getline(buf, 8))}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 8e65ddf1a2..27edfb16ce 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1831, /**/ 1830, /**/ diff --git a/src/window.c b/src/window.c index f071a0e7d7..364b532b15 100644 --- a/src/window.c +++ b/src/window.c @@ -32,7 +32,7 @@ static int frame_fixed_height(frame_T *frp); static int frame_fixed_width(frame_T *frp); static void frame_add_statusline(frame_T *frp); static void frame_new_width(frame_T *topfrp, int width, int leftfirst, int wfw); -static void frame_add_vsep(frame_T *frp); +static void frame_set_vsep(frame_T *frp, int add); static int frame_minwidth(frame_T *topfrp, win_T *next_curwin); static void frame_fix_width(win_T *wp); static int win_alloc_firstwin(win_T *oldwin); @@ -1363,7 +1363,7 @@ win_split_ins( if (flags & (WSP_TOP | WSP_BOT)) { if (flags & WSP_BOT) - frame_add_vsep(curfrp); + frame_set_vsep(curfrp, TRUE); // Set width of neighbor frame frame_new_width(curfrp, curfrp->fr_width - (new_size + ((flags & WSP_TOP) != 0)), flags & WSP_TOP, @@ -3577,6 +3577,11 @@ winframe_remove( frp2 = win_altframe(win, tp); wp = frame2win(frp2); + // If this is a rightmost window, remove vertical separators to the left. + if (win->w_vsep_width == 0 && frp_close->fr_parent->fr_layout == FR_ROW && + frp_close->fr_prev != NULL) + frame_set_vsep(frp_close->fr_prev, FALSE); + // Remove this frame from the list of frames. frame_remove(frp_close); @@ -3742,7 +3747,7 @@ winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr) // Vertical separators to the left may have been lost. Restore them. if (wp->w_vsep_width == 0 && frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) - frame_add_vsep(frp->fr_prev); + frame_set_vsep(frp->fr_prev, TRUE); // Statuslines above may have been lost. Restore them. if (wp->w_status_height == 0 @@ -4223,29 +4228,34 @@ frame_new_width( } /* - * Add the vertical separator to windows at the right side of "frp". + * Add or remove the vertical separator of windows to the right side of "frp". * Note: Does not check if there is room! */ static void -frame_add_vsep(frame_T *frp) +frame_set_vsep(frame_T *frp, int add) { win_T *wp; if (frp->fr_layout == FR_LEAF) { wp = frp->fr_win; - if (wp->w_vsep_width == 0) + if (add && wp->w_vsep_width == 0) { if (wp->w_width > 0) // don't make it negative - --wp->w_width; + win_new_width(wp, wp->w_width - 1); wp->w_vsep_width = 1; } + else if (!add && wp->w_vsep_width == 1) + { + win_new_width(wp, wp->w_width + 1); + wp->w_vsep_width = 0; + } } else if (frp->fr_layout == FR_COL) { // Handle all the frames in the column. FOR_ALL_FRAMES(frp, frp->fr_child) - frame_add_vsep(frp); + frame_set_vsep(frp, add); } else // frp->fr_layout == FR_ROW { @@ -4253,7 +4263,7 @@ frame_add_vsep(frame_T *frp) frp = frp->fr_child; while (frp->fr_next != NULL) frp = frp->fr_next; - frame_add_vsep(frp); + frame_set_vsep(frp, add); } }