Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ad18b3f

Browse files
glepnirseandewar
andcommitted
fix(win): respect window size constraints and separator state
Problem: 1. Rightmost window retained vsep after adjacent window closed 2. Explicit width/height ignored due to win_equal() override 3. winfixwidth windows expanded when receiving space from closed windows Solution: 1. Clear vsep_width for new lastwin in win_remove() 2. Add WSP_NOEQUAL flag to skip equalization when size explicitly set 3. Skip frame resizing for winfixwidth windows in winframe_remove() Co-authored-by: Sean Dewar <[email protected]>
1 parent 2b421d5 commit ad18b3f

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

src/nvim/api/win_config.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
260260
}
261261
}
262262
int flags = win_split_flags(fconfig.split, parent == NULL) | WSP_NOENTER;
263+
if (config->width != 0 || config->height != 0) {
264+
flags |= WSP_NOEQUAL;
265+
}
263266

264267
TRY_WRAP(err, {
265268
int size = (flags & WSP_VERT) ? fconfig.width : fconfig.height;

src/nvim/window.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,7 +1440,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
14401440
}
14411441
if (toplevel) {
14421442
if (flags & WSP_BOT) {
1443-
frame_add_vsep(curfrp);
1443+
frame_set_vsep(curfrp, true);
14441444
}
14451445
// Set width of neighbor frame
14461446
frame_new_width(curfrp, curfrp->fr_width
@@ -1547,7 +1547,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl
15471547
}
15481548

15491549
// equalize the window sizes.
1550-
if (do_equal || dir != 0) {
1550+
if ((do_equal || dir != 0) && !(flags & WSP_NOEQUAL)) {
15511551
win_equal(wp, true, vertical ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
15521552
} else if (!is_aucmd_win(wp)) {
15531553
win_fix_scroll(false);
@@ -3218,6 +3218,12 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp, frame_T **unflat_al
32183218
int row = topleft->w_winrow;
32193219
int col = topleft->w_wincol;
32203220

3221+
// If this is a rightmost window, remove vertical separators to the left.
3222+
if (win->w_vsep_width == 0 && frp_close->fr_parent->fr_layout == FR_ROW
3223+
&& frp_close->fr_prev != NULL) {
3224+
frame_set_vsep(frp_close->fr_prev, false);
3225+
}
3226+
32213227
// Remove this frame from the list of frames.
32223228
frame_remove(frp_close);
32233229

@@ -3409,7 +3415,7 @@ void winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr)
34093415

34103416
// Vertical separators to the left may have been lost. Restore them.
34113417
if (wp->w_vsep_width == 0 && frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) {
3412-
frame_add_vsep(frp->fr_prev);
3418+
frame_set_vsep(frp->fr_prev, true);
34133419
}
34143420

34153421
// Statuslines or horizontal separators above may have been lost. Restore them.
@@ -3855,23 +3861,26 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw
38553861
topfrp->fr_width = width;
38563862
}
38573863

3858-
/// Add the vertical separator to windows at the right side of "frp".
3864+
/// Add or remove the vertical separator to windows at the right side of "frp".
38593865
/// Note: Does not check if there is room!
3860-
static void frame_add_vsep(const frame_T *frp)
3866+
static void frame_set_vsep(const frame_T *frp, bool add)
38613867
FUNC_ATTR_NONNULL_ARG(1)
38623868
{
38633869
if (frp->fr_layout == FR_LEAF) {
38643870
win_T *wp = frp->fr_win;
3865-
if (wp->w_vsep_width == 0) {
3871+
if (add && wp->w_vsep_width == 0) {
38663872
if (wp->w_width > 0) { // don't make it negative
38673873
wp->w_width--;
38683874
}
38693875
wp->w_vsep_width = 1;
3876+
} else if (!add && wp->w_vsep_width == 1) {
3877+
win_new_width(wp, wp->w_width + 1);
3878+
wp->w_vsep_width = 0;
38703879
}
38713880
} else if (frp->fr_layout == FR_COL) {
38723881
// Handle all the frames in the column.
38733882
FOR_ALL_FRAMES(frp, frp->fr_child) {
3874-
frame_add_vsep(frp);
3883+
frame_set_vsep(frp, add);
38753884
}
38763885
} else {
38773886
assert(frp->fr_layout == FR_ROW);
@@ -3880,7 +3889,7 @@ static void frame_add_vsep(const frame_T *frp)
38803889
while (frp->fr_next != NULL) {
38813890
frp = frp->fr_next;
38823891
}
3883-
frame_add_vsep(frp);
3892+
frame_set_vsep(frp, add);
38843893
}
38853894
}
38863895

src/nvim/window.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ enum {
2020
WSP_ABOVE = 0x80, ///< put new window above/left
2121
WSP_NEWLOC = 0x100, ///< don't copy location list
2222
WSP_NOENTER = 0x200, ///< don't enter the new window
23+
WSP_NOEQUAL = 0x400, ///< don't equalize the new window
2324
};
2425

2526
enum {

test/functional/api/window_spec.lua

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,6 +2259,44 @@ describe('API/win', function()
22592259
)
22602260
eq(true, eval 'nvim_tabpage_is_valid(g:tp)')
22612261
end)
2262+
it('removes vsep from new lastwin when rightmost window closed #32854', function()
2263+
local screen = Screen.new(50, 10)
2264+
exec_lua([[
2265+
local win1 = vim.api.nvim_open_win(0, false, { win = -1, split = "right", width=20})
2266+
vim.api.nvim_set_option_value("winfixwidth", true, { win = win1 })
2267+
local win2 = nil
2268+
local toggle_win2 = function()
2269+
if win2 == nil then
2270+
win2 = vim.api.nvim_open_win(0, false, { win = -1, split = "right", width=20})
2271+
else
2272+
vim.api.nvim_win_close(win2, true)
2273+
win2 = nil
2274+
end
2275+
end
2276+
vim.keymap.set("n", "w", toggle_win2)
2277+
vim.o.winbar = "%{%v:lua.wn()%}"
2278+
_G.wn = function()
2279+
return vim.api.nvim_get_current_win()
2280+
end
2281+
]])
2282+
feed('w')
2283+
local wins = api.nvim_list_wins()
2284+
eq(20, api.nvim_win_get_width(wins[#wins]))
2285+
feed('w')
2286+
screen:expect([[
2287+
{5:1000 }│{5:1001 }|
2288+
^ │ |
2289+
{1:~ }│{1:~ }|*6
2290+
{3:[No Name] }{2:[No Name] }|
2291+
|
2292+
]])
2293+
feed('wwwww')
2294+
wins = api.nvim_list_wins()
2295+
eq(
2296+
{ 20, 20 },
2297+
{ api.nvim_win_get_width(wins[#wins]), api.nvim_win_get_width(wins[#wins - 1]) }
2298+
)
2299+
end)
22622300
end)
22632301

22642302
describe('set_config', function()

0 commit comments

Comments
 (0)