aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-12-27 17:29:05 +0800
committerGitHub <noreply@github.com>2022-12-27 17:29:05 +0800
commitcd6ec1db068f9f4c1900a00b5392e39e59f0a7cb (patch)
tree62a308bd578bfbe0cc2374366770b6722632486b
parentd4af8c6202e8734ef4a3a3dfe249353f8d5ba551 (diff)
downloadrneovim-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.c44
-rw-r--r--test/functional/ui/float_spec.lua28
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()