changeset 20384:42ab4d40e78f v8.2.0747

patch 8.2.0747: cannot forcefully close all popups Commit: https://github.com/vim/vim/commit/03a9f848175b182372fb33403998059724a8bf31 Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Wed, 13 May 2020 13:45:04 +0200
parents 1ebebb9b62e7
children 3613c433a314
files runtime/doc/popup.txt src/channel.c src/evalfunc.c src/ex_cmds.c src/misc2.c src/popupwin.c src/proto/popupwin.pro src/tag.c src/testdir/runtest.vim src/testdir/test_terminal.vim src/version.c src/window.c
diffstat 12 files changed, 64 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- 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()*
--- 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);
     }
 
--- 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)},
--- 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);
--- 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).
--- 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;
 }
 
--- 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);
--- 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
     }
--- 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.
--- 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\<CR>")
-    call TermWait(altbuf)
-    call popup_close(win_getid())
-  endfunc
-  call OpenTerms()
-
-  call term_sendkeys(g:buf0, "exit\<CR>")
-  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
 
--- 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,
--- 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);