# HG changeset patch # User Bram Moolenaar # Date 1589370304 -7200 # Node ID 42ab4d40e78f6af3ae6e1722e7eb25451b113a06 # Parent 1ebebb9b62e7ac36254d2d1e679b170dd2b22118 patch 8.2.0747: cannot forcefully close all popups Commit: https://github.com/vim/vim/commit/03a9f848175b182372fb33403998059724a8bf31 Author: Bram Moolenaar Date: Wed May 13 13:40:16 2020 +0200 patch 8.2.0747: cannot forcefully close all popups Problem: Cannot forcefully close all popups. Solution: Add the "force" argument to popup_clear(). Use it after running a test. Put back the check for a popup when editing a file. diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt --- a/runtime/doc/popup.txt +++ b/runtime/doc/popup.txt @@ -236,8 +236,15 @@ popup_beval({what}, {options}) *popup_ GetText()->popup_beval({}) < *popup_clear()* -popup_clear() Emergency solution to a misbehaving plugin: close all popup +popup_clear([{force}]) + Emergency solution to a misbehaving plugin: close all popup windows for the current tab and global popups. + Close callbacks are not invoked. + When {force} is not present this will fail if the current + window is a popup. + When {force} is present and |TRUE| the popup is also closed + when it is the current window. If a terminal is running in a + popup it is killed. popup_close({id} [, {result}]) *popup_close()* diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -156,9 +156,9 @@ ch_logfile(char_u *fname, char_u *opt) if (log_fd != NULL) { if (*fname != NUL) - ch_log(NULL, "closing, opening %s", fname); + ch_log(NULL, "closing this logfile, opening %s", fname); else - ch_log(NULL, "closing"); + ch_log(NULL, "closing logfile"); fclose(log_fd); } diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -704,7 +704,7 @@ static funcentry_T global_functions[] = }, {"popup_atcursor", 2, 2, FEARG_1, ret_number, PROP_FUNC(f_popup_atcursor)}, {"popup_beval", 2, 2, FEARG_1, ret_number, PROP_FUNC(f_popup_beval)}, - {"popup_clear", 0, 0, 0, ret_void, PROP_FUNC(f_popup_clear)}, + {"popup_clear", 0, 1, 0, ret_void, PROP_FUNC(f_popup_clear)}, {"popup_close", 1, 2, FEARG_1, ret_void, PROP_FUNC(f_popup_close)}, {"popup_create", 2, 2, FEARG_1, ret_number, PROP_FUNC(f_popup_create)}, {"popup_dialog", 2, 2, FEARG_1, ret_number, PROP_FUNC(f_popup_dialog)}, diff --git a/src/ex_cmds.c b/src/ex_cmds.c --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -2484,6 +2484,11 @@ do_ecmd( int did_inc_redrawing_disabled = FALSE; long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so; +#ifdef FEAT_PROP_POPUP + if (ERROR_IF_TERM_POPUP_WINDOW) + return FAIL; +#endif + if (eap != NULL) command = eap->do_ecmd_cmd; set_bufref(&old_curbuf, curbuf); diff --git a/src/misc2.c b/src/misc2.c --- a/src/misc2.c +++ b/src/misc2.c @@ -1069,13 +1069,9 @@ free_all_mem(void) # if defined(FEAT_BEVAL_TERM) ui_remove_balloon(); # endif -# if defined(FEAT_PROP_POPUP) +# ifdef FEAT_PROP_POPUP if (curwin != NULL) - { - while (popup_is_popup(curwin)) - popup_close_with_retval(curwin, 0); - close_all_popups(); - } + close_all_popups(TRUE); # endif // Clear user commands (before deleting buffers). diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -2054,9 +2054,13 @@ popup_create(typval_T *argvars, typval_T * popup_clear() */ void -f_popup_clear(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +f_popup_clear(typval_T *argvars, typval_T *rettv UNUSED) { - close_all_popups(); + int force = FALSE; + + if (argvars[0].v_type != VAR_UNKNOWN) + force = (int)tv_get_number(&argvars[0]); + close_all_popups(force); } /* @@ -2163,7 +2167,7 @@ popup_close_and_callback(win_T *wp, typv // Careful: This may make "wp" invalid. invoke_popup_callback(wp, arg); - popup_close(id); + popup_close(id, FALSE); CHECK_CURBUF; } @@ -2250,7 +2254,7 @@ filter_handle_drag(win_T *wp, int c, typ } /* - * popup_filter_menu({text}, {options}) + * popup_filter_menu({id}, {key}) */ void f_popup_filter_menu(typval_T *argvars, typval_T *rettv) @@ -2305,7 +2309,7 @@ f_popup_filter_menu(typval_T *argvars, t } /* - * popup_filter_yesno({text}, {options}) + * popup_filter_yesno({id}, {key}) */ void f_popup_filter_yesno(typval_T *argvars, typval_T *rettv) @@ -2534,7 +2538,7 @@ error_if_popup_window(int also_with_term * Return OK if the popup was closed, FAIL otherwise. */ int -popup_close(int id) +popup_close(int id, int force) { win_T *wp; tabpage_T *tp; @@ -2546,8 +2550,12 @@ popup_close(int id) { if (wp == curwin) { - error_for_popup_window(); - return FAIL; + if (!force) + { + error_for_popup_window(); + return FAIL; + } + win_enter(firstwin, FALSE); } if (prev == NULL) first_popupwin = wp->w_next; @@ -2559,7 +2567,7 @@ popup_close(int id) // go through tab-local popups FOR_ALL_TABPAGES(tp) - if (popup_close_tabpage(tp, id) == OK) + if (popup_close_tabpage(tp, id, force) == OK) return OK; return FAIL; } @@ -2568,7 +2576,7 @@ popup_close(int id) * Close a popup window with Window-id "id" in tabpage "tp". */ int -popup_close_tabpage(tabpage_T *tp, int id) +popup_close_tabpage(tabpage_T *tp, int id, int force) { win_T *wp; win_T **root = &tp->tp_first_popupwin; @@ -2579,8 +2587,12 @@ popup_close_tabpage(tabpage_T *tp, int i { if (wp == curwin) { - error_for_popup_window(); - return FAIL; + if (!force) + { + error_for_popup_window(); + return FAIL; + } + win_enter(firstwin, FALSE); } if (prev == NULL) *root = wp->w_next; @@ -2593,15 +2605,15 @@ popup_close_tabpage(tabpage_T *tp, int i } void -close_all_popups(void) +close_all_popups(int force) { - if (ERROR_IF_ANY_POPUP_WINDOW) + if (!force && ERROR_IF_ANY_POPUP_WINDOW) return; while (first_popupwin != NULL) - if (popup_close(first_popupwin->w_id) == FAIL) + if (popup_close(first_popupwin->w_id, force) == FAIL) return; while (curtab->tp_first_popupwin != NULL) - if (popup_close(curtab->tp_first_popupwin->w_id) == FAIL) + if (popup_close(curtab->tp_first_popupwin->w_id, force) == FAIL) return; } diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro --- a/src/proto/popupwin.pro +++ b/src/proto/popupwin.pro @@ -34,9 +34,9 @@ void popup_show(win_T *wp); void f_popup_show(typval_T *argvars, typval_T *rettv); void f_popup_settext(typval_T *argvars, typval_T *rettv); int error_if_popup_window(int also_with_term); -int popup_close(int id); -int popup_close_tabpage(tabpage_T *tp, int id); -void close_all_popups(void); +int popup_close(int id, int force); +int popup_close_tabpage(tabpage_T *tp, int id, int force); +void close_all_popups(int force); void f_popup_move(typval_T *argvars, typval_T *rettv); void f_popup_setoptions(typval_T *argvars, typval_T *rettv); void f_popup_getpos(typval_T *argvars, typval_T *rettv); diff --git a/src/tag.c b/src/tag.c --- a/src/tag.c +++ b/src/tag.c @@ -3684,7 +3684,7 @@ jumpto_tag( if (win_valid(curwin_save)) win_enter(curwin_save, TRUE); - popup_close(wp->w_id); + popup_close(wp->w_id, FALSE); } #endif } diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -188,9 +188,9 @@ func RunTheTest(test) au! au SwapExists * call HandleSwapExists() - " Close any stray popup windows + " Close any stray popup windows. if has('popupwin') - call popup_clear() + call popup_clear(1) endif " Close any extra tab pages and windows and make the current one not modified. diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -2617,27 +2617,15 @@ endfunc func Test_term_nasty_callback() CheckExecutable sh - func OpenTerms() - set hidden - let g:buf0 = term_start('sh', #{hidden: 1}) - call popup_create(g:buf0, {}) - let g:buf1 = term_start('sh', #{hidden: 1, term_finish: 'close'}) - call popup_create(g:buf1, {}) - let g:buf2 = term_start(['sh', '-c'], #{curwin: 1, exit_cb: function('TermExit')}) - call TermWait(g:buf2, 50) - call popup_close(win_getid()) - endfunc - func TermExit(...) - let altbuf = bufnr('#') - call term_sendkeys(altbuf, "exit\") - call TermWait(altbuf) - call popup_close(win_getid()) - endfunc - call OpenTerms() - - call term_sendkeys(g:buf0, "exit\") - call TermWait(g:buf0, 50) - exe g:buf0 .. 'bwipe!' + + set hidden + let g:buf0 = term_start('sh', #{hidden: 1}) + call popup_create(g:buf0, {}) + let g:buf1 = term_start('sh', #{hidden: 1, term_finish: 'close'}) + call popup_create(g:buf1, {}) + call assert_fails("call term_start(['sh', '-c'], #{curwin: 1})", 'E863:') + + call popup_clear(1) set hidden& endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 747, +/**/ 746, /**/ 745, diff --git a/src/window.c b/src/window.c --- a/src/window.c +++ b/src/window.c @@ -2766,9 +2766,6 @@ win_free_all(void) (void)win_free_mem(aucmd_win, &dummy, NULL); aucmd_win = NULL; } -# ifdef FEAT_PROP_POPUP - close_all_popups(); -# endif while (firstwin != NULL) (void)win_free_mem(firstwin, &dummy, NULL); @@ -3801,7 +3798,7 @@ free_tabpage(tabpage_T *tp) # endif # ifdef FEAT_PROP_POPUP while (tp->tp_first_popupwin != NULL) - popup_close_tabpage(tp, tp->tp_first_popupwin->w_id); + popup_close_tabpage(tp, tp->tp_first_popupwin->w_id, TRUE); #endif for (idx = 0; idx < SNAP_COUNT; ++idx) clear_snapshot(tp, idx);