mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 11:58:17 +00:00
revert: "fix(window): :close crash with autocmd, floats and tabpage" (#27796)
This reverts PR #27793. On second thought, this solution may still crash, because it can leave a window with a NULL buffer if there are autocommand windows or if closing a floating window fails. It also makes close_last_window_tabpage() more complicated, so revert it.
This commit is contained in:
@@ -2539,47 +2539,21 @@ bool can_close_in_cmdwin(win_T *win, Error *err)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close the possibly last non-floating window in a tab page.
|
/// Close the possibly last window in a tab page.
|
||||||
///
|
///
|
||||||
/// @param win window to close
|
/// @param win window to close
|
||||||
/// @param free_buf whether to free the window's current buffer
|
/// @param free_buf whether to free the window's current buffer
|
||||||
/// @param force close floating windows even if they are modified
|
|
||||||
/// @param prev_curtab previous tabpage that will be closed if "win" is the
|
/// @param prev_curtab previous tabpage that will be closed if "win" is the
|
||||||
/// last window in the tabpage
|
/// last window in the tabpage
|
||||||
///
|
///
|
||||||
/// @return false if there are other non-floating windows and nothing is done, true otherwise.
|
/// @return false if there are other windows and nothing is done, true otherwise.
|
||||||
static bool close_last_window_tabpage(win_T *win, bool free_buf, bool force, tabpage_T *prev_curtab)
|
static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev_curtab)
|
||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
if (!one_window(win)) {
|
if (!ONE_WINDOW) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastwin->w_floating && one_window(win)) {
|
|
||||||
if (is_aucmd_win(lastwin)) {
|
|
||||||
emsg(_("E814: Cannot close window, only autocmd window would remain"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || can_close_floating_windows()) {
|
|
||||||
// close the last window until the there are no floating windows
|
|
||||||
while (lastwin->w_floating) {
|
|
||||||
// `force` flag isn't actually used when closing a floating window.
|
|
||||||
if (win_close(lastwin, free_buf, true) == FAIL) {
|
|
||||||
// If closing the window fails give up, to avoid looping forever.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emsg(e_floatonly);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!win_valid_any_tab(win)) {
|
|
||||||
return true; // window already closed by autocommands
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buf_T *old_curbuf = curbuf;
|
buf_T *old_curbuf = curbuf;
|
||||||
|
|
||||||
Terminal *term = win->w_buffer ? win->w_buffer->terminal : NULL;
|
Terminal *term = win->w_buffer ? win->w_buffer->terminal : NULL;
|
||||||
@@ -2675,11 +2649,33 @@ int win_close(win_T *win, bool free_buf, bool force)
|
|||||||
emsg(_(e_autocmd_close));
|
emsg(_(e_autocmd_close));
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
if (lastwin->w_floating && one_window(win)) {
|
||||||
|
if (is_aucmd_win(lastwin)) {
|
||||||
|
emsg(_("E814: Cannot close window, only autocmd window would remain"));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (force || can_close_floating_windows()) {
|
||||||
|
// close the last window until the there are no floating windows
|
||||||
|
while (lastwin->w_floating) {
|
||||||
|
// `force` flag isn't actually used when closing a floating window.
|
||||||
|
if (win_close(lastwin, free_buf, true) == FAIL) {
|
||||||
|
// If closing the window fails give up, to avoid looping forever.
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!win_valid_any_tab(win)) {
|
||||||
|
return FAIL; // window already closed by autocommands
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emsg(e_floatonly);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When closing the last window in a tab page first go to another tab page
|
// When closing the last window in a tab page first go to another tab page
|
||||||
// and then close the window and the tab page to avoid that curwin and
|
// and then close the window and the tab page to avoid that curwin and
|
||||||
// curtab are invalid while we are freeing memory.
|
// curtab are invalid while we are freeing memory.
|
||||||
if (close_last_window_tabpage(win, free_buf, force, prev_curtab)) {
|
if (close_last_window_tabpage(win, free_buf, prev_curtab)) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2774,7 +2770,7 @@ int win_close(win_T *win, bool free_buf, bool force)
|
|||||||
// Autocommands may have closed the window already, or closed the only
|
// Autocommands may have closed the window already, or closed the only
|
||||||
// other window or moved to another tab page.
|
// other window or moved to another tab page.
|
||||||
if (!win_valid(win) || (!win->w_floating && last_window(win))
|
if (!win_valid(win) || (!win->w_floating && last_window(win))
|
||||||
|| close_last_window_tabpage(win, free_buf, force, prev_curtab)) {
|
|| close_last_window_tabpage(win, free_buf, prev_curtab)) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -893,7 +893,7 @@ describe('float window', function()
|
|||||||
assert_alive()
|
assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('does not crash if BufUnload makes it the only non-float in tabpage', function()
|
pending('does not crash if BufUnload makes it the only non-float in tabpage', function()
|
||||||
exec([[
|
exec([[
|
||||||
tabnew
|
tabnew
|
||||||
let g:buf = bufnr()
|
let g:buf = bufnr()
|
||||||
@@ -909,10 +909,9 @@ describe('float window', function()
|
|||||||
assert_alive()
|
assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('does not crash if WinClosed from floating windows closes it', function()
|
it('does not crash if WinClosed from floating window closes it', function()
|
||||||
exec([[
|
exec([[
|
||||||
tabnew
|
tabnew
|
||||||
let g:buf = bufnr()
|
|
||||||
new
|
new
|
||||||
let s:win = win_getid()
|
let s:win = win_getid()
|
||||||
call nvim_win_set_config(s:win,
|
call nvim_win_set_config(s:win,
|
||||||
|
Reference in New Issue
Block a user