fix(float): :bufdelete in floatwin may change focus #39858

Problem:
(Followup to 54f22a8f01c0feb27a531b52aedf5cdbd5e51b24.)
Deleting another buffer from a floatwin could move focus into the holder
window and fire BufEnter for the buffer being deleted.

Solution:
Use switch_win_noblock() instead of buf_jump_open_win() before
recursing into do_buffer_ext().
This commit is contained in:
glepnir
2026-05-21 17:06:50 +08:00
committed by GitHub
parent 7337e02563
commit 26df751add
3 changed files with 51 additions and 10 deletions

View File

@@ -764,6 +764,7 @@ describe('float window', function()
it('if called from floating window with another buffer', function()
api.nvim_set_current_win(other_buf_float)
api.nvim_buf_delete(old_buf, { force = true })
eq(other_buf_float, curwin())
end)
end)
describe('creates an empty buffer when there is only one listed buffer', function()
@@ -776,13 +777,11 @@ describe('float window', function()
command('set nobuflisted')
api.nvim_set_current_win(old_win)
end)
after_each(function()
expect('')
eq(2, #api.nvim_list_wins())
end)
it('if called from non-floating window', function()
api.nvim_buf_delete(old_buf, { force = true })
eq(old_win, curwin())
expect('')
eq(2, #api.nvim_list_wins())
end)
it('if called from floating window with the same buffer', function()
api.nvim_set_current_win(same_buf_float)
@@ -792,12 +791,36 @@ describe('float window', function()
eq(same_buf_float, eval('g:win_leave'))
eq(old_win, eval('g:win_enter'))
eq(old_win, curwin())
expect('')
eq(2, #api.nvim_list_wins())
end)
it('if called from floating window with an unlisted buffer', function()
api.nvim_set_current_win(unlisted_buf_float)
api.nvim_buf_delete(old_buf, { force = true })
eq(unlisted_buf_float, curwin())
expect('unlisted')
eq('', fn.bufname(api.nvim_win_get_buf(old_win)))
eq(false, api.nvim_buf_is_valid(old_buf))
eq(2, #api.nvim_list_wins())
end)
end)
it('keeps focus in the floating window #39800', function()
api.nvim_open_win(old_buf, false, float_opts)
local other_float = api.nvim_open_win(api.nvim_create_buf(true, false), true, float_opts)
api.nvim_buf_delete(old_buf, { force = true })
eq(other_float, curwin())
end)
it('does not trigger BufEnter for deleted buffer #39800', function()
api.nvim_open_win(old_buf, false, float_opts)
api.nvim_open_win(api.nvim_create_buf(true, false), true, float_opts)
command('let g:abufs = []')
command('autocmd BufEnter * call add(g:abufs, +expand("<abuf>"))')
api.nvim_buf_delete(old_buf, { force = true })
for _, b in ipairs(eval('g:abufs')) do
neq(old_buf, b)
end
end)
end)
describe('with splits, deleting the last listed buffer creates an empty buffer', function()
describe('when a non-floating window has an unlisted buffer', function()