vim-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: vim/vim#18481

620c655677

Nvim: calling win_new_width over setting w_width directly is especially
important in making sure stuff like w_view_width is correct here.

Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
This commit is contained in:
Sean Dewar
2025-10-05 18:17:43 +01:00
parent a4a8838178
commit 7923e847ca
3 changed files with 116 additions and 8 deletions

View File

@@ -1440,7 +1440,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
}
if (toplevel) {
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
@@ -3230,6 +3230,12 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp, frame_T **unflat_al
int row = topleft->w_winrow;
int col = topleft->w_wincol;
// 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);
@@ -3422,7 +3428,7 @@ void 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 or horizontal separators above may have been lost. Restore them.
@@ -3868,23 +3874,26 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw
topfrp->fr_width = 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(const frame_T *frp)
static void frame_set_vsep(const frame_T *frp, bool add)
FUNC_ATTR_NONNULL_ARG(1)
{
if (frp->fr_layout == FR_LEAF) {
win_T *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 {
assert(frp->fr_layout == FR_ROW);
@@ -3893,7 +3902,7 @@ static void frame_add_vsep(const frame_T *frp)
while (frp->fr_next != NULL) {
frp = frp->fr_next;
}
frame_add_vsep(frp);
frame_set_vsep(frp, add);
}
}