diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-11-07 16:58:59 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-11-07 16:58:59 +0100 |
commit | cbcd9cbd77acc8cc97c0d44683d96c01d3dd0fa7 (patch) | |
tree | 0327591c6c155fec6e557463815968f90bab3e0a | |
parent | 46f479c756c0255e3b6d473590c1857678eff5c6 (diff) | |
download | vim-git-cbcd9cbd77acc8cc97c0d44683d96c01d3dd0fa7.tar.gz |
patch 8.2.1966: popup becomes current window after closing a terminal windowv8.2.1966
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)
-rw-r--r-- | src/autocmd.c | 31 | ||||
-rw-r--r-- | src/proto/window.pro | 1 | ||||
-rw-r--r-- | src/structs.h | 14 | ||||
-rw-r--r-- | src/testdir/test_popupwin.vim | 21 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/window.c | 15 |
6 files changed, 62 insertions, 22 deletions
diff --git a/src/autocmd.c b/src/autocmd.c index be35845c9..a82659f65 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -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(); diff --git a/src/proto/window.pro b/src/proto/window.pro index 24ab0ec82..c10b61dba 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -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); diff --git a/src/structs.h b/src/structs.h index 330bb53fa..90e76203a 100644 --- a/src/structs.h +++ b/src/structs.h @@ -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; /* diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 43dbeb5a1..fdfa305ba 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -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 diff --git a/src/version.c b/src/version.c index 786e05ea7..1fbae19e0 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1966, +/**/ 1965, /**/ 1964, diff --git a/src/window.c b/src/window.c index 2cd06630f..501ea846a 100644 --- a/src/window.c +++ b/src/window.c @@ -1461,6 +1461,21 @@ win_valid(win_T *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. */ int |