commit d788864cdea705a981aa90ec0625516466c04bec
parent 756e1eb017aa5fe7fae409ede3d50ecebe785e7f
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date: Wed, 17 Dec 2025 16:38:52 +0000
fix(api): ignore split_disallowed when opening a float
Problem: split_disallowed seemingly exists to prevent issues from changing
frames to accomodate a split window, which doesn't apply to floats.
Solution: remove the restriction for nvim_open_win, but only for floats.
(continue to check b_locked_split though)
NOTE: like before, the buffer we check b_locked_split for may not actually be
the target buffer "buf", as the later call to win_set_buf can fail to switch to
"buf" due to autocommands. (among other things)
Maybe we could attempt to close the new window in that case (or switch to a
different buffer if that also fails), but this is safer. (and simpler)
Fixes #36857 (and possibly some spurious E242s I've observed from extui)
Diffstat:
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
@@ -280,8 +280,12 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
}
}
} else {
- if (!check_split_disallowed_err(curwin, err)) {
- goto cleanup; // error already set
+ // Unlike check_split_disallowed_err, ignore `split_disallowed`, as opening a float shouldn't
+ // mess with the frame structure. Still check `b_locked_split` to avoid opening more windows
+ // into a closing buffer, though.
+ if (curwin->w_buffer->b_locked_split) { // Can't instead check `buf` in case win_set_buf fails!
+ api_set_error(err, kErrorTypeException, "E1159: Cannot open a float when closing the buffer");
+ goto cleanup;
}
wp = win_new_float(NULL, false, fconfig, err);
}
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
@@ -2000,6 +2000,13 @@ describe('API/win', function()
it('checks if splitting disallowed', function()
command('split | autocmd WinEnter * ++once call nvim_open_win(0, 0, #{split: "right"})')
matches("E242: Can't split a window while closing another$", pcall_err(command, 'quit'))
+ -- E242 is not needed for floats.
+ exec([[
+ split
+ autocmd WinEnter * ++once let g:win = nvim_open_win(0, 0, #{relative: "editor", row: 0, col: 0, width: 5, height: 5})
+ quit
+ ]])
+ eq('editor', eval('nvim_win_get_config(g:win).relative'))
command('only | autocmd BufHidden * ++once call nvim_open_win(0, 0, #{split: "left"})')
matches(
@@ -2033,10 +2040,10 @@ describe('API/win', function()
only
new
let g:buf = bufnr()
- autocmd BufUnload * ++once let g:win = nvim_open_win(g:buf, 0, #{relative: "editor", width: 5, height: 5, row: 1, col: 1})
+ autocmd BufUnload * ++once call nvim_open_win(g:buf, 0, #{relative: "editor", width: 5, height: 5, row: 1, col: 1})
setlocal bufhidden=unload
]])
- matches('E1159: Cannot split a window when closing the buffer$', pcall_err(command, 'quit'))
+ matches('E1159: Cannot open a float when closing the buffer$', pcall_err(command, 'quit'))
eq(false, eval('nvim_buf_is_loaded(g:buf)'))
eq(0, eval('win_findbuf(g:buf)->len()'))
@@ -2052,7 +2059,7 @@ describe('API/win', function()
\| call nvim_open_win(g:buf2, 1, #{relative: 'editor', width: 5, height: 5, col: 5, row: 5})
setlocal bufhidden=wipe
]])
- matches('E1159: Cannot split a window when closing the buffer$', pcall_err(command, 'quit'))
+ matches('E1159: Cannot open a float when closing the buffer$', pcall_err(command, 'quit'))
eq(false, eval('nvim_buf_is_loaded(g:buf)'))
eq(0, eval('win_findbuf(g:buf)->len()'))
-- BufLeave shouldn't run here (buf2 isn't deleted and remains hidden)