diff options
-rw-r--r-- | src/nvim/buffer.c | 4 | ||||
-rw-r--r-- | src/nvim/window.c | 46 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 33 |
3 files changed, 46 insertions, 37 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index b013f43ceb..7154be36be 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -568,7 +568,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i } buf->b_locked--; buf->b_locked_split--; - if (abort_if_last && last_nonfloat(win)) { + if (abort_if_last && one_window(win)) { // Autocommands made this the only window. emsg(_(e_auabort)); return false; @@ -587,7 +587,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i } buf->b_locked--; buf->b_locked_split--; - if (abort_if_last && last_nonfloat(win)) { + if (abort_if_last && one_window(win)) { // Autocommands made this the only window. emsg(_(e_auabort)); return false; diff --git a/src/nvim/window.c b/src/nvim/window.c index b55dd79260..4dc6ed370e 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -455,7 +455,7 @@ newwindow: case 'H': case 'L': CHECK_CMDWIN; - if (firstwin == curwin && lastwin_nofloating() == curwin) { + if (one_window(curwin)) { beep_flush(); } else { const int dir = ((nchar == 'H' || nchar == 'L') ? WSP_VERT : 0) @@ -1018,7 +1018,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl bool toplevel = flags & (WSP_TOP | WSP_BOT); // add a status line when p_ls == 1 and splitting the first window - if (one_nonfloat() && p_ls == 1 && oldwin->w_status_height == 0) { + if (one_window(firstwin) && p_ls == 1 && oldwin->w_status_height == 0) { if (oldwin->w_height <= p_wmh) { emsg(_(e_noroom)); return NULL; @@ -1741,7 +1741,7 @@ static void win_exchange(int Prenum) return; } - if (firstwin == curwin && lastwin_nofloating() == curwin) { + if (one_window(curwin)) { // just one window beep_flush(); return; @@ -1833,7 +1833,7 @@ static void win_rotate(bool upwards, int count) return; } - if (count <= 0 || (firstwin == curwin && lastwin_nofloating() == curwin)) { + if (count <= 0 || one_window(curwin)) { // nothing to do beep_flush(); return; @@ -2495,37 +2495,13 @@ bool last_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT } /// Check if "win" is the only non-floating window in the current tabpage. -bool one_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - if (win->w_floating) { - return false; - } - - bool seen_one = false; - - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if (!wp->w_floating) { - if (seen_one) { - return false; - } - seen_one = true; - } - } - return true; -} - -/// Like ONE_WINDOW but only considers non-floating windows -bool one_nonfloat(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT -{ - return firstwin->w_next == NULL || firstwin->w_next->w_floating; -} - -/// if wp is the last non-floating window /// -/// always false for a floating window -bool last_nonfloat(win_T *wp) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +/// This should be used in place of ONE_WINDOW when necessary, +/// with "firstwin" or the affected window as argument depending on the situation. +bool one_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - return wp != NULL && firstwin == wp && !(wp->w_next && !wp->w_floating); + assert(!firstwin->w_floating); + return firstwin == win && (win->w_next == NULL || win->w_next->w_floating); } /// Check if floating windows in the current tab can be closed. @@ -3950,7 +3926,7 @@ void close_others(int message, int forceit) return; } - if (one_nonfloat() && !lastwin->w_floating) { + if (one_window(firstwin) && !lastwin->w_floating) { if (message && !autocmd_busy) { msg(_(m_onlyone), 0); @@ -7224,7 +7200,7 @@ int global_stl_height(void) /// @param morewin pretend there are two or more windows if true. int last_stl_height(bool morewin) { - return (p_ls > 1 || (p_ls == 1 && (morewin || !one_nonfloat()))) ? STATUS_HEIGHT : 0; + return (p_ls > 1 || (p_ls == 1 && (morewin || !one_window(firstwin)))) ? STATUS_HEIGHT : 0; } /// Return the minimal number of rows that is needed on the screen to display diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index e324d03b30..8b7107fdf2 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -873,6 +873,39 @@ describe('float window', function() end) end) + describe(':close on non-float with floating windows', function() + it('does not quit Nvim if BufWinLeave makes it the only non-float', function() + exec([[ + let firstbuf = bufnr() + new + let midwin = win_getid() + new + setlocal bufhidden=wipe + call nvim_win_set_config(midwin, + \ #{relative: 'editor', row: 5, col: 5, width: 5, height: 5}) + autocmd BufWinLeave * ++once exe firstbuf .. 'bwipe!' + ]]) + eq('Vim(close):E855: Autocommands caused command to abort', pcall_err(command, 'close')) + assert_alive() + end) + + pending('does not crash if BufWinLeave makes it the only non-float in tabpage', function() + exec([[ + tabnew + let firstbuf = bufnr() + new + let midwin = win_getid() + new + setlocal bufhidden=wipe + call nvim_win_set_config(midwin, + \ #{relative: 'editor', row: 5, col: 5, width: 5, height: 5}) + autocmd BufWinLeave * ++once exe firstbuf .. 'bwipe!' + ]]) + eq('Vim(close):E855: Autocommands caused command to abort', pcall_err(command, 'close')) + assert_alive() + end) + end) + local function with_ext_multigrid(multigrid) local screen, attrs before_each(function() |