diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-12-27 17:29:05 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-27 17:29:05 +0800 |
commit | cd6ec1db068f9f4c1900a00b5392e39e59f0a7cb (patch) | |
tree | 62a308bd578bfbe0cc2374366770b6722632486b | |
parent | d4af8c6202e8734ef4a3a3dfe249353f8d5ba551 (diff) | |
download | rneovim-cd6ec1db068f9f4c1900a00b5392e39e59f0a7cb.tar.gz rneovim-cd6ec1db068f9f4c1900a00b5392e39e59f0a7cb.tar.bz2 rneovim-cd6ec1db068f9f4c1900a00b5392e39e59f0a7cb.zip |
fix(win_close): remove float grid after closing buffer (#21551)
It is not safe to remove the float grid when autocommands can still be
triggered, as autocommands may use the float grid.
-rw-r--r-- | src/nvim/window.c | 44 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 28 |
2 files changed, 50 insertions, 22 deletions
diff --git a/src/nvim/window.c b/src/nvim/window.c index d026f4551a..fe771c52c6 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2764,28 +2764,6 @@ int win_close(win_T *win, bool free_buf, bool force) } } - bool was_floating = win->w_floating; - if (ui_has(kUIMultigrid)) { - ui_call_win_close(win->w_grid_alloc.handle); - } - - if (win->w_floating) { - ui_comp_remove_grid(&win->w_grid_alloc); - assert(first_tabpage != NULL); // suppress clang "Dereference of NULL pointer" - if (win->w_float_config.external) { - for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) { - if (tp == curtab) { - continue; - } - if (tp->tp_curwin == win) { - // NB: an autocmd can still abort the closing of this window, - // bur carring out this change anyway shouldn't be a catastrophe. - tp->tp_curwin = tp->tp_firstwin; - } - } - } - } - // Fire WinClosed just before starting to free window-related resources. do_autocmd_winclosed(win); // autocmd may have freed the window already. @@ -2831,6 +2809,28 @@ int win_close(win_T *win, bool free_buf, bool force) // let terminal buffers know that this window dimensions may be ignored win->w_closing = true; + bool was_floating = win->w_floating; + if (ui_has(kUIMultigrid)) { + ui_call_win_close(win->w_grid_alloc.handle); + } + + if (win->w_floating) { + ui_comp_remove_grid(&win->w_grid_alloc); + assert(first_tabpage != NULL); // suppress clang "Dereference of NULL pointer" + if (win->w_float_config.external) { + for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) { + if (tp == curtab) { + continue; + } + if (tp->tp_curwin == win) { + // NB: an autocmd can still abort the closing of this window, + // bur carring out this change anyway shouldn't be a catastrophe. + tp->tp_curwin = tp->tp_firstwin; + } + } + } + } + // Free the memory used for the window and get the window that received // the screen space. int dir; diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index bb09cfd504..ab87384194 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -8831,6 +8831,34 @@ describe('float window', function() ]]} end end) + + describe('no crash after moving and closing float window #21547', function() + local function test_float_move_close(cmd) + local float_opts = {relative = 'editor', row = 1, col = 1, width = 10, height = 10} + meths.open_win(meths.create_buf(false, false), true, float_opts) + if multigrid then + screen:expect({float_pos = {[4] = {{id = 1001}, 'NW', 1, 1, 1, true}}}) + end + command(cmd) + exec_lua([[ + vim.api.nvim_win_set_config(0, {relative = 'editor', row = 2, col = 2}) + vim.api.nvim_win_close(0, {}) + vim.api.nvim_echo({{''}}, false, {}) + ]]) + if multigrid then + screen:expect({float_pos = {}}) + end + assert_alive() + end + + it('if WinClosed autocommand flushes UI', function() + test_float_move_close('autocmd WinClosed * ++once redraw') + end) + + it('if closing buffer flushes UI', function() + test_float_move_close('autocmd BufWinLeave * ++once redraw') + end) + end) end describe('with ext_multigrid', function() |