From 982c0053f4059fb4558ce83a0b8d250be1058980 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Dec 2022 10:30:50 +0800 Subject: fix(float): make closing float in another tab return to correct window --- src/nvim/window.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'src/nvim') diff --git a/src/nvim/window.c b/src/nvim/window.c index e761f7e40b..80c51516b1 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -1643,12 +1643,21 @@ bool win_valid_floating(const win_T *win) /// /// @param win window to check bool win_valid(const win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return tabpage_win_valid(curtab, win); +} + +/// Check if "win" is a pointer to an existing window in tabpage "tp". +/// +/// @param win window to check +static bool tabpage_win_valid(const tabpage_T *tp, const win_T *win) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { if (win == NULL) { return false; } - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + FOR_ALL_WINDOWS_IN_TAB(wp, tp) { if (wp == win) { return true; } @@ -3057,10 +3066,18 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp) xfree(frp); } else { *dirp = 'h'; // Dummy value. - if (win_valid(prevwin) && prevwin != win) { - wp = prevwin; + if (tp == NULL) { + if (win_valid(prevwin) && prevwin != win) { + wp = prevwin; + } else { + wp = firstwin; + } } else { - wp = firstwin; + if (tabpage_win_valid(tp, tp->tp_prevwin) && tp->tp_prevwin != win) { + wp = tp->tp_prevwin; + } else { + wp = tp->tp_firstwin; + } } } win_free(win, tp); @@ -3068,11 +3085,7 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp) // When deleting the current window of another tab page select a new // current window. if (tp != NULL && win == tp->tp_curwin) { - if (win_valid(tp->tp_prevwin) && tp->tp_prevwin != win) { - tp->tp_curwin = tp->tp_prevwin; - } else { - tp->tp_curwin = tp->tp_firstwin; - } + tp->tp_curwin = wp; } return wp; -- cgit From 47d3d0102fffbfd52b950c521e5d1e443ac7885f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Dec 2022 10:28:35 +0800 Subject: vim-patch:8.2.1748: closing split window in other tab may cause a crash Problem: Closing split window in other tab may cause a crash. Solution: Set tp_curwin properly. (Rob Pilling, closes vim/vim#7018) https://github.com/vim/vim/commit/f3c51bbff1256a52bdd9ede7887f40062be2628c Co-authored-by: Bram Moolenaar --- src/nvim/testdir/test_winbuf_close.vim | 18 +++++++++++++++++- src/nvim/window.c | 9 +++++---- 2 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src/nvim') diff --git a/src/nvim/testdir/test_winbuf_close.vim b/src/nvim/testdir/test_winbuf_close.vim index 643c1068bd..26b4ba8778 100644 --- a/src/nvim/testdir/test_winbuf_close.vim +++ b/src/nvim/testdir/test_winbuf_close.vim @@ -192,7 +192,23 @@ func Test_tabwin_close() call win_execute(l:wid, 'close') " Should not crash. call assert_true(v:true) - %bwipe! + + " This tests closing a window in another tab, while leaving the tab open + " i.e. two windows in another tab. + tabedit + let w:this_win = 42 + new + let othertab_wid = win_getid() + tabprevious + call win_execute(othertab_wid, 'q') + " drawing the tabline helps check that the other tab's windows and buffers + " are still valid + redrawtabline + " but to be certain, ensure we can focus the other tab too + tabnext + call assert_equal(42, w:this_win) + + bwipe! endfunc " Test when closing a split window (above/below) restores space to the window diff --git a/src/nvim/window.c b/src/nvim/window.c index 80c51516b1..79a90ab8af 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3058,6 +3058,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp) static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp) { win_T *wp; + tabpage_T *win_tp = tp == NULL ? curtab : tp; if (!win->w_floating) { // Remove the window and its frame from the tree of frames. @@ -3082,10 +3083,10 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp) } win_free(win, tp); - // When deleting the current window of another tab page select a new - // current window. - if (tp != NULL && win == tp->tp_curwin) { - tp->tp_curwin = wp; + // When deleting the current window in the tab, select a new current + // window. + if (win == win_tp->tp_curwin) { + win_tp->tp_curwin = wp; } return wp; -- cgit