forked from aniani/vim
patch 8.2.1966: popup becomes current window after closing a terminal window
Problem: Popup becomes current window after closing a terminal window. Solution: When restoring the window after executing autocommands, check that the window ID is still the same. (Naruhiko Nishino, closes #7272)
This commit is contained in:
parent
46f479c756
commit
cbcd9cbd77
@ -1433,9 +1433,9 @@ aucmd_prepbuf(
|
||||
// window. Expect a few side effects...
|
||||
win = curwin;
|
||||
|
||||
aco->save_curwin = curwin;
|
||||
aco->save_curwin_id = curwin->w_id;
|
||||
aco->save_curbuf = curbuf;
|
||||
aco->save_prevwin = prevwin;
|
||||
aco->save_prevwin_id = prevwin == NULL ? 0 : prevwin->w_id;
|
||||
if (win != NULL)
|
||||
{
|
||||
// There is a window for "buf" in the current tab page, make it the
|
||||
@ -1481,7 +1481,7 @@ aucmd_prepbuf(
|
||||
curwin = aucmd_win;
|
||||
}
|
||||
curbuf = buf;
|
||||
aco->new_curwin = curwin;
|
||||
aco->new_curwin_id = curwin->w_id;
|
||||
set_bufref(&aco->new_curbuf, curbuf);
|
||||
}
|
||||
|
||||
@ -1493,7 +1493,8 @@ aucmd_prepbuf(
|
||||
aucmd_restbuf(
|
||||
aco_save_T *aco) // structure holding saved values
|
||||
{
|
||||
int dummy;
|
||||
int dummy;
|
||||
win_T *save_curwin;
|
||||
|
||||
if (aco->use_aucmd_win)
|
||||
{
|
||||
@ -1533,8 +1534,9 @@ win_found:
|
||||
(void)win_comp_pos(); // recompute window positions
|
||||
unblock_autocmds();
|
||||
|
||||
if (win_valid(aco->save_curwin))
|
||||
curwin = aco->save_curwin;
|
||||
save_curwin = win_find_by_id(aco->save_curwin_id);
|
||||
if (save_curwin != NULL)
|
||||
curwin = save_curwin;
|
||||
else
|
||||
// Hmm, original window disappeared. Just use the first one.
|
||||
curwin = firstwin;
|
||||
@ -1543,9 +1545,7 @@ win_found:
|
||||
// May need to restore insert mode for a prompt buffer.
|
||||
entering_window(curwin);
|
||||
#endif
|
||||
|
||||
if (win_valid(aco->save_prevwin))
|
||||
prevwin = aco->save_prevwin;
|
||||
prevwin = win_find_by_id(aco->save_prevwin_id);
|
||||
#ifdef FEAT_EVAL
|
||||
vars_clear(&aucmd_win->w_vars->dv_hashtab); // free all w: variables
|
||||
hash_init(&aucmd_win->w_vars->dv_hashtab); // re-use the hashtab
|
||||
@ -1571,13 +1571,15 @@ win_found:
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore curwin
|
||||
if (win_valid(aco->save_curwin))
|
||||
// Restore curwin. Use the window ID, a window may have been closed
|
||||
// and the memory re-used for another one.
|
||||
save_curwin = win_find_by_id(aco->save_curwin_id);
|
||||
if (save_curwin != NULL)
|
||||
{
|
||||
// Restore the buffer which was previously edited by curwin, if
|
||||
// it was changed, we are still the same window and the buffer is
|
||||
// valid.
|
||||
if (curwin == aco->new_curwin
|
||||
if (curwin->w_id == aco->new_curwin_id
|
||||
&& curbuf != aco->new_curbuf.br_buf
|
||||
&& bufref_valid(&aco->new_curbuf)
|
||||
&& aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL)
|
||||
@ -1592,10 +1594,9 @@ win_found:
|
||||
++curbuf->b_nwindows;
|
||||
}
|
||||
|
||||
curwin = aco->save_curwin;
|
||||
curwin = save_curwin;
|
||||
curbuf = curwin->w_buffer;
|
||||
if (win_valid(aco->save_prevwin))
|
||||
prevwin = aco->save_prevwin;
|
||||
prevwin = win_find_by_id(aco->save_prevwin_id);
|
||||
// In case the autocommand moves the cursor to a position that
|
||||
// does not exist in curbuf.
|
||||
check_cursor();
|
||||
|
@ -5,6 +5,7 @@ int win_split(int size, int flags);
|
||||
int win_split_ins(int size, int flags, win_T *new_wp, int dir);
|
||||
int win_valid_popup(win_T *win);
|
||||
int win_valid(win_T *win);
|
||||
win_T *win_find_by_id(int id);
|
||||
int win_valid_any_tab(win_T *win);
|
||||
int win_count(void);
|
||||
int make_windows(int count, int vertical);
|
||||
|
@ -3889,13 +3889,13 @@ typedef int vimmenu_T;
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
buf_T *save_curbuf; // saved curbuf
|
||||
int use_aucmd_win; // using aucmd_win
|
||||
win_T *save_curwin; // saved curwin
|
||||
win_T *new_curwin; // new curwin
|
||||
win_T *save_prevwin; // saved prevwin
|
||||
bufref_T new_curbuf; // new curbuf
|
||||
char_u *globaldir; // saved value of globaldir
|
||||
buf_T *save_curbuf; // saved curbuf
|
||||
int use_aucmd_win; // using aucmd_win
|
||||
int save_curwin_id; // ID of saved curwin
|
||||
int new_curwin_id; // ID of new curwin
|
||||
int save_prevwin_id; // ID of saved prevwin
|
||||
bufref_T new_curbuf; // new curbuf
|
||||
char_u *globaldir; // saved value of globaldir
|
||||
} aco_save_T;
|
||||
|
||||
/*
|
||||
|
@ -3737,5 +3737,26 @@ func Test_popupwin_splitmove()
|
||||
bwipe
|
||||
endfunc
|
||||
|
||||
func Test_popupwin_exiting_terminal()
|
||||
CheckFeature terminal
|
||||
|
||||
" Tests that when creating a popup right after closing a terminal window does
|
||||
" not make the popup the current window.
|
||||
let winid = win_getid()
|
||||
try
|
||||
augroup Test_popupwin_exiting_terminal
|
||||
autocmd!
|
||||
autocmd WinEnter * :call popup_create('test', {})
|
||||
augroup END
|
||||
let bnr = term_start(&shell, #{term_finish: 'close'})
|
||||
call term_sendkeys(bnr, "exit\r\n")
|
||||
call WaitForAssert({-> assert_equal(winid, win_getid())})
|
||||
finally
|
||||
call popup_clear(1)
|
||||
augroup Test_popupwin_exiting_terminal
|
||||
autocmd!
|
||||
augroup END
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2
|
||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1966,
|
||||
/**/
|
||||
1965,
|
||||
/**/
|
||||
|
15
src/window.c
15
src/window.c
@ -1460,6 +1460,21 @@ win_valid(win_T *win)
|
||||
return win_valid_popup(win);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find window "id" in the current tab page.
|
||||
* Return NULL if not found.
|
||||
*/
|
||||
win_T *
|
||||
win_find_by_id(int id)
|
||||
{
|
||||
win_T *wp;
|
||||
|
||||
FOR_ALL_WINDOWS(wp)
|
||||
if (wp->w_id == id)
|
||||
return wp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if "win" is a pointer to an existing window in any tab page.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user