mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 04:42:03 +00:00
vim-patch:9.1.2001: cursor may end up in wrong window after :botright copen (#37056)
Problem: After :botright copen and closing the quikfix window, the
cursor ends up in the wrong window. The problem is fr_child
always points to the first (leftmost for FR_ROW, topmost for
FR_COL) child frame. When do :vsplit, the new window is
created on the left, and frame_insert() updates the parent's
fr_child to point to this new left window.
Solution: Create a snapshot before open the quickfix window and restore
it when close it (glepnir).
closes: vim/vim#18961
b43f9ded7e
Co-authored-by: glepnir <glephunter@gmail.com>
This commit is contained in:
@@ -821,9 +821,10 @@ struct diffline_S {
|
||||
int lineoff;
|
||||
};
|
||||
|
||||
#define SNAP_HELP_IDX 0
|
||||
#define SNAP_AUCMD_IDX 1
|
||||
#define SNAP_COUNT 2
|
||||
#define SNAP_HELP_IDX 0
|
||||
#define SNAP_AUCMD_IDX 1
|
||||
#define SNAP_QUICKFIX_IDX 2
|
||||
#define SNAP_COUNT 3
|
||||
|
||||
/// Tab pages point to the top frame of each tab page.
|
||||
/// Note: Most values are NOT valid for the current tab page! Use "curwin",
|
||||
|
||||
@@ -3884,6 +3884,13 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height)
|
||||
flags = IS_QF_STACK(qi) ? WSP_BOT : WSP_BELOW;
|
||||
}
|
||||
flags |= WSP_NEWLOC;
|
||||
|
||||
// Create a snapshot for quickfix window (not for location list)
|
||||
// so that when closing it, we can restore to the previous window
|
||||
if (IS_QF_STACK(qi)) {
|
||||
flags |= WSP_QUICKFIX;
|
||||
}
|
||||
|
||||
if (win_split(height, flags) == FAIL) {
|
||||
return FAIL; // not enough room for window
|
||||
}
|
||||
|
||||
@@ -1057,6 +1057,12 @@ int win_split(int size, int flags)
|
||||
clear_snapshot(curtab, SNAP_HELP_IDX);
|
||||
}
|
||||
|
||||
if (flags & WSP_QUICKFIX) {
|
||||
make_snapshot(SNAP_QUICKFIX_IDX);
|
||||
} else {
|
||||
clear_snapshot(curtab, SNAP_QUICKFIX_IDX);
|
||||
}
|
||||
|
||||
return win_split_ins(size, flags, NULL, 0, NULL) == NULL ? FAIL : OK;
|
||||
}
|
||||
|
||||
@@ -2747,6 +2753,7 @@ int win_close(win_T *win, bool free_buf, bool force)
|
||||
}
|
||||
|
||||
bool help_window = false;
|
||||
bool quickfix_window = false;
|
||||
|
||||
// When closing the help window, try restoring a snapshot after closing
|
||||
// the window. Otherwise clear the snapshot, it's now invalid.
|
||||
@@ -2756,6 +2763,12 @@ int win_close(win_T *win, bool free_buf, bool force)
|
||||
clear_snapshot(curtab, SNAP_HELP_IDX);
|
||||
}
|
||||
|
||||
if (bt_quickfix(win->w_buffer)) {
|
||||
quickfix_window = true;
|
||||
} else {
|
||||
clear_snapshot(curtab, SNAP_QUICKFIX_IDX);
|
||||
}
|
||||
|
||||
win_T *wp;
|
||||
bool other_buffer = false;
|
||||
|
||||
@@ -2861,10 +2874,10 @@ int win_close(win_T *win, bool free_buf, bool force)
|
||||
int dir;
|
||||
wp = win_free_mem(win, &dir, NULL);
|
||||
|
||||
if (help_window) {
|
||||
if (help_window || quickfix_window) {
|
||||
// Closing the help window moves the cursor back to the current window
|
||||
// of the snapshot.
|
||||
win_T *prev_win = get_snapshot_curwin(SNAP_HELP_IDX);
|
||||
win_T *prev_win = get_snapshot_curwin(help_window ? SNAP_HELP_IDX : SNAP_QUICKFIX_IDX);
|
||||
if (win_valid(prev_win)) {
|
||||
wp = prev_win;
|
||||
}
|
||||
@@ -2939,10 +2952,10 @@ int win_close(win_T *win, bool free_buf, bool force)
|
||||
|
||||
split_disallowed--;
|
||||
|
||||
// After closing the help window, try restoring the window layout from
|
||||
// before it was opened.
|
||||
if (help_window) {
|
||||
restore_snapshot(SNAP_HELP_IDX, close_curwin);
|
||||
// After closing the help or quickfix window, try restoring the window
|
||||
// layout from before it was opened.
|
||||
if (help_window || quickfix_window) {
|
||||
restore_snapshot(help_window ? SNAP_HELP_IDX : SNAP_QUICKFIX_IDX, close_curwin);
|
||||
}
|
||||
|
||||
// If the window had 'diff' set and now there is only one window left in
|
||||
|
||||
@@ -10,16 +10,17 @@
|
||||
|
||||
/// arguments for win_split()
|
||||
enum {
|
||||
WSP_ROOM = 0x01, ///< require enough room
|
||||
WSP_VERT = 0x02, ///< split/equalize vertically
|
||||
WSP_HOR = 0x04, ///< equalize horizontally
|
||||
WSP_TOP = 0x08, ///< window at top-left of shell
|
||||
WSP_BOT = 0x10, ///< window at bottom-right of shell
|
||||
WSP_HELP = 0x20, ///< creating the help window
|
||||
WSP_BELOW = 0x40, ///< put new window below/right
|
||||
WSP_ABOVE = 0x80, ///< put new window above/left
|
||||
WSP_NEWLOC = 0x100, ///< don't copy location list
|
||||
WSP_NOENTER = 0x200, ///< don't enter the new window
|
||||
WSP_ROOM = 0x01, ///< require enough room
|
||||
WSP_VERT = 0x02, ///< split/equalize vertically
|
||||
WSP_HOR = 0x04, ///< equalize horizontally
|
||||
WSP_TOP = 0x08, ///< window at top-left of shell
|
||||
WSP_BOT = 0x10, ///< window at bottom-right of shell
|
||||
WSP_HELP = 0x20, ///< creating the help window
|
||||
WSP_BELOW = 0x40, ///< put new window below/right
|
||||
WSP_ABOVE = 0x80, ///< put new window above/left
|
||||
WSP_NEWLOC = 0x100, ///< don't copy location list
|
||||
WSP_NOENTER = 0x200, ///< don't enter the new window
|
||||
WSP_QUICKFIX = 0x400, ///< creating the quickfix window
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
@@ -6980,4 +6980,15 @@ func Test_vimgrep_dummy_buffer_keep()
|
||||
%bw!
|
||||
endfunc
|
||||
|
||||
func Test_quickfix_restore_current_win()
|
||||
let curwin = win_getid()
|
||||
vsplit Xb
|
||||
wincmd p
|
||||
botright copen
|
||||
cclose
|
||||
|
||||
call assert_equal(curwin, win_getid())
|
||||
bw! Xb
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
Reference in New Issue
Block a user