]> granicus.if.org Git - vim/commitdiff
patch 8.2.1966: popup becomes current window after closing a terminal window v8.2.1966
authorBram Moolenaar <Bram@vim.org>
Sat, 7 Nov 2020 15:58:59 +0000 (16:58 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 7 Nov 2020 15:58:59 +0000 (16:58 +0100)
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)

src/autocmd.c
src/proto/window.pro
src/structs.h
src/testdir/test_popupwin.vim
src/version.c
src/window.c

index be35845c9d26d8ab8c658bb4f441a1f5ebb91378..a82659f654f417d9df8f9eb4d5eb91fbd8ed71ff 100644 (file)
@@ -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();
index 24ab0ec821afd21db61b488af6a1312212b7af96..c10b61dba44a672beb63aa2588cf6a2606a15e69 100644 (file)
@@ -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);
index 330bb53fa03c787a0cca44440677f9d66282972a..90e76203a9bcc5676849ff48a221bfec8f4d9ebc 100644 (file)
@@ -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;
 
 /*
index 43dbeb5a12671374afa22ee2cf4de1d8c822ef50..fdfa305ba572a32a69cb2fafc7385b6d932f04eb 100644 (file)
@@ -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
index 786e05ea72cfa78cb732e7dac88133e7e5ce4364..1fbae19e06206d6767edad196c3da9a8d0272fd8 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1966,
 /**/
     1965,
 /**/
index 2cd06630fff6a1fef6abc42e6d1ef15bb0e2a364..501ea846a8a5eb70563de8e52e28a59896984d18 100644 (file)
@@ -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.
  */