changeset 22442:73be82f278c0 v8.2.1769

patch 8.2.1769: popup filter interferes with using :normal to move the cursor Commit: https://github.com/vim/vim/commit/4934ad0e448bfa03ba19c7c5b411c457a9910442 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Sep 28 22:29:58 2020 +0200 patch 8.2.1769: popup filter interferes with using :normal to move the cursor Problem: A popup filter interferes with using :normal to move the cursor in a popup. Solution: Do not invoke the filter when ex_normal_busy is set.
author Bram Moolenaar <Bram@vim.org>
date Mon, 28 Sep 2020 22:45:05 +0200
parents a3bb84cd0f59
children db8b2b99f59e
files runtime/doc/popup.txt src/evalfunc.c src/ex_docmd.c src/getchar.c src/globals.h src/menu.c src/testdir/dumps/Test_popupwin_normal_cmd.dump src/testdir/test_popupwin.vim src/version.c
diffstat 9 files changed, 27 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/popup.txt
+++ b/runtime/doc/popup.txt
@@ -1,4 +1,4 @@
-*popup.txt*  For Vim version 8.2.  Last change: 2020 Sep 27
+*popup.txt*  For Vim version 8.2.  Last change: 2020 Sep 28
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -910,6 +910,11 @@ A mouse click arrives as <LeftMouse>.  T
 Vim provides standard filters |popup_filter_menu()| and
 |popup_filter_yesno()|.
 
+Keys coming from a `:normal` command do not pass through the filter.  This can
+be used to move the cursor in a popup where the "cursorline" option is set: >
+	call win_execute(winid, 'normal! 10Gzz')
+Keys coming from `feedkeys()` are passed through the filter.
+
 Note that "x" is the normal way to close a popup.  You may want to use Esc,
 but since many keys start with an Esc character, there may be a delay before
 Vim recognizes the Esc key.  If you do use Esc, it is recommended to set the
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -2616,15 +2616,15 @@ f_feedkeys(typval_T *argvars, typval_T *
 		msg_scroll = FALSE;
 
 		if (!dangerous)
+		{
 		    ++ex_normal_busy;
+		    ++in_feedkeys;
+		}
 		exec_normal(TRUE, lowlevel, TRUE);
 		if (!dangerous)
 		{
 		    --ex_normal_busy;
-#ifdef FEAT_PROP_POPUP
-		    if (ex_normal_busy == 0)
-			ex_normal_busy_done = FALSE;
-#endif
+		    --in_feedkeys;
 		}
 
 		msg_scroll |= save_msg_scroll;
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -8037,10 +8037,6 @@ ex_normal(exarg_T *eap)
 
     restore_current_state(&save_state);
     --ex_normal_busy;
-#ifdef FEAT_PROP_POPUP
-    if (ex_normal_busy == 0)
-	ex_normal_busy_done = FALSE;
-#endif
     setmouse();
 #ifdef CURSOR_SHAPE
     ui_cursor_shape();		// may show different cursor shape
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1888,7 +1888,9 @@ vgetc(void)
     }
 #endif
 #ifdef FEAT_PROP_POPUP
-    if (!ex_normal_busy_done && popup_do_filter(c))
+    // Only filter keys that do not come from ":normal".  Keys from feedkeys()
+    // are filtered.
+    if ((!ex_normal_busy || in_feedkeys) && popup_do_filter(c))
     {
 	if (c == Ctrl_C)
 	    got_int = FALSE;  // avoid looping
@@ -3168,9 +3170,6 @@ vgetorpeek(int advance)
 			timedout = TRUE;
 			continue;
 		    }
-#ifdef FEAT_PROP_POPUP
-		    ex_normal_busy_done = TRUE;
-#endif
 
 		    // When 'insertmode' is set, ESC just beeps in Insert
 		    // mode.  Use CTRL-L to make edit() return.
--- a/src/globals.h
+++ b/src/globals.h
@@ -1150,12 +1150,9 @@ EXTERN typebuf_T typebuf		// typeahead b
 		    = {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}
 #endif
 		    ;
-EXTERN int	ex_normal_busy INIT(= 0); // recursiveness of ex_normal()
-EXTERN int	ex_normal_lock INIT(= 0); // forbid use of ex_normal()
-#ifdef FEAT_PROP_POPUP
-// Set to TRUE when ex_normal_busy is set and out of typeahead.
-EXTERN int	ex_normal_busy_done INIT(= FALSE);
-#endif
+EXTERN int	ex_normal_busy INIT(= 0);   // recursiveness of ex_normal()
+EXTERN int	in_feedkeys INIT(= 0);	    // ex_normal_busy set in feedkeys()
+EXTERN int	ex_normal_lock INIT(= 0);   // forbid use of ex_normal()
 
 #ifdef FEAT_EVAL
 EXTERN int	ignore_script INIT(= FALSE);  // ignore script input
--- a/src/menu.c
+++ b/src/menu.c
@@ -2398,10 +2398,6 @@ execute_menu(exarg_T *eap, vimmenu_T *me
 							   menu->silent[idx]);
 	    restore_current_state(&save_state);
 	    --ex_normal_busy;
-#ifdef FEAT_PROP_POPUP
-	    if (ex_normal_busy == 0)
-		ex_normal_busy_done = FALSE;
-#endif
 	}
 	else
 	    ins_typebuf(menu->strings[idx], menu->noremap[idx], 0,
--- a/src/testdir/dumps/Test_popupwin_normal_cmd.dump
+++ b/src/testdir/dumps/Test_popupwin_normal_cmd.dump
@@ -1,10 +1,10 @@
 > +0&#ffffff0@74
 |~+0#4040ff13&| @73
-|~| @73
-|~| @73
-|~| @31| +0#0000000&@8| +0#4040ff13&@32
-|~| @73
-|~| @73
+|~| @33|8+0#0000001#ffd7ff255| @1| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@35
+|~| @33|9+0#0000001#ffd7ff255| @1| +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@35
+|~| @33|1+0#0000001#ffd7ff255|0| | +0#0000000#0000001| +0#4040ff13#ffffff0@35
+|~| @33|1+0#0000001#ffd7ff255@1| | +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@35
+|~| @33|1+0#0000001#ffd7ff255|2| | +0#0000000#a8a8a8255| +0#4040ff13#ffffff0@35
 |~| @73
 |~| @73
 | +0#0000000&@56|0|,|0|-|1| @8|A|l@1| 
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -1539,13 +1539,14 @@ func Test_popup_filter()
   call popup_clear()
 endfunc
 
-" this tests that the "ex_normal_busy_done" flag works
+" this tests that the filter is not used for :normal command
 func Test_popup_filter_normal_cmd()
   CheckScreendump
 
   let lines =<< trim END
-      let g:winid = popup_create('some text', {'filter': 'invalidfilter'})
-      call timer_start(0, {-> win_execute(g:winid, 'norm! zz')})
+      let text = range(1, 20)->map({_, v -> string(v)})
+      let g:winid = popup_create(text, #{maxheight: 5, minwidth: 3, filter: 'invalidfilter'})
+      call timer_start(0, {-> win_execute(g:winid, 'norm! 10Gzz')})
   END
   call writefile(lines, 'XtestPopupNormal')
   let buf = RunVimInTerminal('-S XtestPopupNormal', #{rows: 10})
--- 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 */
 /**/
+    1769,
+/**/
     1768,
 /**/
     1767,