Skip to content

Commit cbcd9cb

Browse files
committed
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)
1 parent 46f479c commit cbcd9cb

6 files changed

Lines changed: 62 additions & 22 deletions

File tree

src/autocmd.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,9 +1433,9 @@ aucmd_prepbuf(
14331433
// window. Expect a few side effects...
14341434
win = curwin;
14351435

1436-
aco->save_curwin = curwin;
1436+
aco->save_curwin_id = curwin->w_id;
14371437
aco->save_curbuf = curbuf;
1438-
aco->save_prevwin = prevwin;
1438+
aco->save_prevwin_id = prevwin == NULL ? 0 : prevwin->w_id;
14391439
if (win != NULL)
14401440
{
14411441
// There is a window for "buf" in the current tab page, make it the
@@ -1481,7 +1481,7 @@ aucmd_prepbuf(
14811481
curwin = aucmd_win;
14821482
}
14831483
curbuf = buf;
1484-
aco->new_curwin = curwin;
1484+
aco->new_curwin_id = curwin->w_id;
14851485
set_bufref(&aco->new_curbuf, curbuf);
14861486
}
14871487

@@ -1493,7 +1493,8 @@ aucmd_prepbuf(
14931493
aucmd_restbuf(
14941494
aco_save_T *aco) // structure holding saved values
14951495
{
1496-
int dummy;
1496+
int dummy;
1497+
win_T *save_curwin;
14971498

14981499
if (aco->use_aucmd_win)
14991500
{
@@ -1533,8 +1534,9 @@ aucmd_restbuf(
15331534
(void)win_comp_pos(); // recompute window positions
15341535
unblock_autocmds();
15351536

1536-
if (win_valid(aco->save_curwin))
1537-
curwin = aco->save_curwin;
1537+
save_curwin = win_find_by_id(aco->save_curwin_id);
1538+
if (save_curwin != NULL)
1539+
curwin = save_curwin;
15381540
else
15391541
// Hmm, original window disappeared. Just use the first one.
15401542
curwin = firstwin;
@@ -1543,9 +1545,7 @@ aucmd_restbuf(
15431545
// May need to restore insert mode for a prompt buffer.
15441546
entering_window(curwin);
15451547
#endif
1546-
1547-
if (win_valid(aco->save_prevwin))
1548-
prevwin = aco->save_prevwin;
1548+
prevwin = win_find_by_id(aco->save_prevwin_id);
15491549
#ifdef FEAT_EVAL
15501550
vars_clear(&aucmd_win->w_vars->dv_hashtab); // free all w: variables
15511551
hash_init(&aucmd_win->w_vars->dv_hashtab); // re-use the hashtab
@@ -1571,13 +1571,15 @@ aucmd_restbuf(
15711571
}
15721572
else
15731573
{
1574-
// restore curwin
1575-
if (win_valid(aco->save_curwin))
1574+
// Restore curwin. Use the window ID, a window may have been closed
1575+
// and the memory re-used for another one.
1576+
save_curwin = win_find_by_id(aco->save_curwin_id);
1577+
if (save_curwin != NULL)
15761578
{
15771579
// Restore the buffer which was previously edited by curwin, if
15781580
// it was changed, we are still the same window and the buffer is
15791581
// valid.
1580-
if (curwin == aco->new_curwin
1582+
if (curwin->w_id == aco->new_curwin_id
15811583
&& curbuf != aco->new_curbuf.br_buf
15821584
&& bufref_valid(&aco->new_curbuf)
15831585
&& aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL)
@@ -1592,10 +1594,9 @@ aucmd_restbuf(
15921594
++curbuf->b_nwindows;
15931595
}
15941596

1595-
curwin = aco->save_curwin;
1597+
curwin = save_curwin;
15961598
curbuf = curwin->w_buffer;
1597-
if (win_valid(aco->save_prevwin))
1598-
prevwin = aco->save_prevwin;
1599+
prevwin = win_find_by_id(aco->save_prevwin_id);
15991600
// In case the autocommand moves the cursor to a position that
16001601
// does not exist in curbuf.
16011602
check_cursor();

src/proto/window.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ int win_split(int size, int flags);
55
int win_split_ins(int size, int flags, win_T *new_wp, int dir);
66
int win_valid_popup(win_T *win);
77
int win_valid(win_T *win);
8+
win_T *win_find_by_id(int id);
89
int win_valid_any_tab(win_T *win);
910
int win_count(void);
1011
int make_windows(int count, int vertical);

src/structs.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,13 +3889,13 @@ typedef int vimmenu_T;
38893889
*/
38903890
typedef struct
38913891
{
3892-
buf_T *save_curbuf; // saved curbuf
3893-
int use_aucmd_win; // using aucmd_win
3894-
win_T *save_curwin; // saved curwin
3895-
win_T *new_curwin; // new curwin
3896-
win_T *save_prevwin; // saved prevwin
3897-
bufref_T new_curbuf; // new curbuf
3898-
char_u *globaldir; // saved value of globaldir
3892+
buf_T *save_curbuf; // saved curbuf
3893+
int use_aucmd_win; // using aucmd_win
3894+
int save_curwin_id; // ID of saved curwin
3895+
int new_curwin_id; // ID of new curwin
3896+
int save_prevwin_id; // ID of saved prevwin
3897+
bufref_T new_curbuf; // new curbuf
3898+
char_u *globaldir; // saved value of globaldir
38993899
} aco_save_T;
39003900

39013901
/*

src/testdir/test_popupwin.vim

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3737,5 +3737,26 @@ func Test_popupwin_splitmove()
37373737
bwipe
37383738
endfunc
37393739

3740+
func Test_popupwin_exiting_terminal()
3741+
CheckFeature terminal
3742+
3743+
" Tests that when creating a popup right after closing a terminal window does
3744+
" not make the popup the current window.
3745+
let winid = win_getid()
3746+
try
3747+
augroup Test_popupwin_exiting_terminal
3748+
autocmd!
3749+
autocmd WinEnter * :call popup_create('test', {})
3750+
augroup END
3751+
let bnr = term_start(&shell, #{term_finish: 'close'})
3752+
call term_sendkeys(bnr, "exit\r\n")
3753+
call WaitForAssert({-> assert_equal(winid, win_getid())})
3754+
finally
3755+
call popup_clear(1)
3756+
augroup Test_popupwin_exiting_terminal
3757+
autocmd!
3758+
augroup END
3759+
endtry
3760+
endfunc
37403761

37413762
" vim: shiftwidth=2 sts=2

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
1966,
753755
/**/
754756
1965,
755757
/**/

src/window.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,21 @@ win_valid(win_T *win)
14601460
return win_valid_popup(win);
14611461
}
14621462

1463+
/*
1464+
* Find window "id" in the current tab page.
1465+
* Return NULL if not found.
1466+
*/
1467+
win_T *
1468+
win_find_by_id(int id)
1469+
{
1470+
win_T *wp;
1471+
1472+
FOR_ALL_WINDOWS(wp)
1473+
if (wp->w_id == id)
1474+
return wp;
1475+
return NULL;
1476+
}
1477+
14631478
/*
14641479
* Check if "win" is a pointer to an existing window in any tab page.
14651480
*/

0 commit comments

Comments
 (0)