To: vim_dev@googlegroups.com Subject: Patch 8.2.1966 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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) Files: src/autocmd.c, src/window.c, src/proto/window.pro, src/structs.h, src/testdir/test_popupwin.vim *** ../vim-8.2.1965/src/autocmd.c 2020-10-21 12:19:50.080854732 +0200 --- src/autocmd.c 2020-11-07 16:45:35.814707017 +0100 *************** *** 1433,1441 **** // window. Expect a few side effects... win = curwin; ! aco->save_curwin = curwin; aco->save_curbuf = curbuf; ! aco->save_prevwin = prevwin; if (win != NULL) { // There is a window for "buf" in the current tab page, make it the --- 1433,1441 ---- // window. Expect a few side effects... win = curwin; ! aco->save_curwin_id = curwin->w_id; aco->save_curbuf = curbuf; ! 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,1487 **** curwin = aucmd_win; } curbuf = buf; ! aco->new_curwin = curwin; set_bufref(&aco->new_curbuf, curbuf); } --- 1481,1487 ---- curwin = aucmd_win; } curbuf = buf; ! aco->new_curwin_id = curwin->w_id; set_bufref(&aco->new_curbuf, curbuf); } *************** *** 1493,1499 **** aucmd_restbuf( aco_save_T *aco) // structure holding saved values { ! int dummy; if (aco->use_aucmd_win) { --- 1493,1500 ---- aucmd_restbuf( aco_save_T *aco) // structure holding saved values { ! int dummy; ! win_T *save_curwin; if (aco->use_aucmd_win) { *************** *** 1533,1540 **** (void)win_comp_pos(); // recompute window positions unblock_autocmds(); ! if (win_valid(aco->save_curwin)) ! curwin = aco->save_curwin; else // Hmm, original window disappeared. Just use the first one. curwin = firstwin; --- 1534,1542 ---- (void)win_comp_pos(); // recompute window positions unblock_autocmds(); ! 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,1551 **** // May need to restore insert mode for a prompt buffer. entering_window(curwin); #endif ! ! if (win_valid(aco->save_prevwin)) ! prevwin = aco->save_prevwin; #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 --- 1545,1551 ---- // May need to restore insert mode for a prompt buffer. entering_window(curwin); #endif ! 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,1583 **** } else { ! // restore curwin ! if (win_valid(aco->save_curwin)) { // 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 && curbuf != aco->new_curbuf.br_buf && bufref_valid(&aco->new_curbuf) && aco->new_curbuf.br_buf->b_ml.ml_mfp != NULL) --- 1571,1585 ---- } else { ! // 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->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,1601 **** ++curbuf->b_nwindows; } ! curwin = aco->save_curwin; curbuf = curwin->w_buffer; ! if (win_valid(aco->save_prevwin)) ! prevwin = aco->save_prevwin; // In case the autocommand moves the cursor to a position that // does not exist in curbuf. check_cursor(); --- 1594,1602 ---- ++curbuf->b_nwindows; } ! curwin = save_curwin; curbuf = curwin->w_buffer; ! 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(); *** ../vim-8.2.1965/src/window.c 2020-11-04 11:03:08.372891857 +0100 --- src/window.c 2020-11-07 16:55:40.479270357 +0100 *************** *** 1461,1466 **** --- 1461,1481 ---- } /* + * 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 *** ../vim-8.2.1965/src/proto/window.pro 2020-10-01 22:37:36.403376674 +0200 --- src/proto/window.pro 2020-11-07 16:36:12.130134001 +0100 *************** *** 5,10 **** --- 5,11 ---- 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); *** ../vim-8.2.1965/src/structs.h 2020-11-05 20:50:45.331984998 +0100 --- src/structs.h 2020-11-07 16:36:45.270027261 +0100 *************** *** 3889,3901 **** */ 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 } aco_save_T; /* --- 3889,3901 ---- */ typedef struct { ! 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; /* *** ../vim-8.2.1965/src/testdir/test_popupwin.vim 2020-11-06 17:58:31.727138982 +0100 --- src/testdir/test_popupwin.vim 2020-11-07 16:55:29.183325154 +0100 *************** *** 3737,3741 **** --- 3737,3762 ---- 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 *** ../vim-8.2.1965/src/version.c 2020-11-07 13:09:09.209143607 +0100 --- src/version.c 2020-11-07 16:58:47.566392798 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 1966, /**/ -- hundred-and-one symptoms of being an internet addict: 213. Your kids start referring to you as "that guy in front of the monitor." /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///