fix(window): don't enter unfocusable or hidden prevwin (#34486)

Problem:  When closing a floating window, the next window to be entered
          may be unfocusable or hidden.
Solution: Don't enter prevwin when it is unfocusable or hidden. Enter
          firstwin instead (like for when prevwin is no longer valid).
This commit is contained in:
luukvbaal
2025-06-14 23:42:23 +02:00
committed by GitHub
parent c7f38e3bc8
commit 0d658660c2
3 changed files with 32 additions and 12 deletions

View File

@ -2753,15 +2753,7 @@ int win_close(win_T *win, bool free_buf, bool force)
// Guess which window is going to be the new current window.
// This may change because of the autocommands (sigh).
if (!win->w_floating) {
wp = frame2win(win_altframe(win, NULL));
} else {
if (win_valid(prevwin) && prevwin != win) {
wp = prevwin;
} else {
wp = firstwin;
}
}
wp = win->w_floating ? win_float_find_altwin(win, NULL) : frame2win(win_altframe(win, NULL));
// Be careful: If autocommands delete the window or cause this window
// to be the last one left, return now.

View File

@ -362,13 +362,15 @@ win_T *win_float_find_preview(void)
win_T *win_float_find_altwin(const win_T *win, const tabpage_T *tp)
FUNC_ATTR_NONNULL_ARG(1)
{
win_T *wp = prevwin;
if (tp == NULL) {
return (win_valid(prevwin) && prevwin != win) ? prevwin : firstwin;
return (win_valid(wp) && wp != win && wp->w_config.focusable
&& !wp->w_config.hide) ? wp : firstwin;
}
assert(tp != curtab);
return (tabpage_win_valid(tp, tp->tp_prevwin) && tp->tp_prevwin != win) ? tp->tp_prevwin
: tp->tp_firstwin;
wp = tabpage_win_valid(tp, tp->tp_prevwin) ? tp->tp_prevwin : tp->tp_firstwin;
return (wp->w_config.focusable && !wp->w_config.hide) ? wp : tp->tp_firstwin;
}
/// Inline helper function for handling errors and cleanup in win_float_create.

View File

@ -730,6 +730,32 @@ describe('API/win', function()
eq(prevwin, api.nvim_tabpage_get_win(tab))
assert_alive()
end)
it('closing a float does not enter unfocusable or hidden prevwin', function()
local firstwin = api.nvim_get_current_win()
local wins = {} ---@type integer[]
for _ = 1, 4 do
wins[#wins + 1] = api.nvim_open_win(0, true, {
relative = 'editor',
row = 10,
col = 10,
width = 50,
height = 10,
})
end
api.nvim_win_set_config(wins[3], { hide = true })
api.nvim_win_close(0, false)
eq(firstwin, api.nvim_get_current_win())
api.nvim_set_current_win(wins[2])
api.nvim_set_current_win(wins[3])
api.nvim_win_set_config(wins[2], { focusable = false })
api.nvim_win_close(0, false)
eq(firstwin, api.nvim_get_current_win())
api.nvim_set_current_win(wins[1])
api.nvim_set_current_win(wins[2])
api.nvim_win_close(0, false)
eq(wins[1], api.nvim_get_current_win())
end)
end)
describe('hide', function()