# HG changeset patch # User Bram Moolenaar # Date 1601325905 -7200 # Node ID 73be82f278c0c48ce08ec4f0ecd217f89adbcfa9 # Parent a3bb84cd0f593a9fed08420281adb175b5472137 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 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. diff --git a/runtime/doc/popup.txt b/runtime/doc/popup.txt --- 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 . 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 diff --git a/src/evalfunc.c b/src/evalfunc.c --- 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; diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- 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 diff --git a/src/getchar.c b/src/getchar.c --- 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. diff --git a/src/globals.h b/src/globals.h --- 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 diff --git a/src/menu.c b/src/menu.c --- 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, diff --git a/src/testdir/dumps/Test_popupwin_normal_cmd.dump b/src/testdir/dumps/Test_popupwin_normal_cmd.dump --- 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| diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim --- 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}) diff --git a/src/version.c b/src/version.c --- 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,