diff options
-rw-r--r-- | src/popupwin.c | 24 | ||||
-rw-r--r-- | src/testdir/dumps/Test_popupwin_win_execute.dump | 10 | ||||
-rw-r--r-- | src/testdir/term_util.vim | 3 | ||||
-rw-r--r-- | src/testdir/test_popupwin.vim | 24 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 59 insertions, 4 deletions
diff --git a/src/popupwin.c b/src/popupwin.c index 6080ecbc00..301c38240e 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -2250,7 +2250,13 @@ popup_close_and_callback(win_T *wp, typval_T *arg) // Just in case a check higher up is missing. if (wp == curwin && ERROR_IF_POPUP_WINDOW) + { + // To avoid getting stuck when win_execute() does something that causes + // an error, stop calling the filter callback. + free_callback(&wp->w_filter_cb); + return; + } CHECK_CURBUF; if (wp->w_close_cb.cb_name != NULL) @@ -3128,7 +3134,8 @@ find_next_popup(int lowest, int handled_flag) /* * Invoke the filter callback for window "wp" with typed character "c". * Uses the global "mod_mask" for modifiers. - * Returns the return value of the filter. + * Returns the return value of the filter or -1 for CTRL-C in the current + * window. * Careful: The filter may make "wp" invalid! */ static int @@ -3145,12 +3152,18 @@ invoke_popup_filter(win_T *wp, int c) if (c == Ctrl_C) { int save_got_int = got_int; + int was_curwin = wp == curwin; // Reset got_int to avoid the callback isn't called. got_int = FALSE; popup_close_with_retval(wp, -1); got_int |= save_got_int; - return 1; + + // If the popup is the current window it probably fails to close. Then + // do not consume the key. + if (was_curwin && wp == curwin) + return -1; + return TRUE; } argv[0].v_type = VAR_NUMBER; @@ -3238,7 +3251,8 @@ popup_do_filter(int c) popup_reset_handled(POPUP_HANDLED_2); state = get_real_state(); - while (!res && (wp = find_next_popup(FALSE, POPUP_HANDLED_2)) != NULL) + while (res == FALSE + && (wp = find_next_popup(FALSE, POPUP_HANDLED_2)) != NULL) if (wp->w_filter_cb.cb_name != NULL && (wp->w_filter_mode & state) != 0) res = invoke_popup_filter(wp, c); @@ -3254,7 +3268,9 @@ popup_do_filter(int c) } recursive = FALSE; KeyTyped = save_KeyTyped; - return res; + + // When interrupted return FALSE to avoid looping. + return res == -1 ? FALSE : res; } /* diff --git a/src/testdir/dumps/Test_popupwin_win_execute.dump b/src/testdir/dumps/Test_popupwin_win_execute.dump new file mode 100644 index 0000000000..f5548591c7 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_win_execute.dump @@ -0,0 +1,10 @@ +> +0&#ffffff0@74 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @31| +0#0000000&@8| +0#4040ff13&@32 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|0|,|0|-|1| @8|A|l@1| diff --git a/src/testdir/term_util.vim b/src/testdir/term_util.vim index 4a5e64989b..53735c8d33 100644 --- a/src/testdir/term_util.vim +++ b/src/testdir/term_util.vim @@ -5,6 +5,8 @@ if exists('*CanRunVimInTerminal') finish endif +source shared.vim + " For most tests we need to be able to run terminal Vim with 256 colors. On " MS-Windows the console only has 16 colors and the GUI can't run in a " terminal. @@ -51,6 +53,7 @@ endfunc " "rows" - height of the terminal window (max. 20) " "cols" - width of the terminal window (max. 78) " "statusoff" - number of lines the status is offset from default +" "wait_for_ruler" - if zero then don't wait for ruler to show func RunVimInTerminal(arguments, options) " If Vim doesn't exit a swap file remains, causing other tests to fail. " Remove it here. diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 6607ea231c..79eaca7c13 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -1556,6 +1556,30 @@ func Test_popup_filter_normal_cmd() call delete('XtestPopupNormal') endfunc +" this tests that we don't get stuck with an error in "win_execute()" +func Test_popup_filter_win_execute() + CheckScreendump + + let lines =<< trim END + let g:winid = popup_create('some text', {'filter': 'invalidfilter'}) + call timer_start(0, {-> win_execute(g:winid, 'invalidCommand')}) + END + call writefile(lines, 'XtestPopupWinExecute') + let buf = RunVimInTerminal('-S XtestPopupWinExecute', #{rows: 10, wait_for_ruler: 0}) + + call WaitFor({-> term_getline(buf, 9) =~ 'Not an editor command: invalidCommand'}) + call term_sendkeys(buf, "\<CR>") + call WaitFor({-> term_getline(buf, 9) =~ 'Unknown function: invalidfilter'}) + call term_sendkeys(buf, "\<CR>") + call WaitFor({-> term_getline(buf, 9) =~ 'Not allowed in a popup window'}) + call term_sendkeys(buf, "\<CR>") + call term_sendkeys(buf, "\<CR>") + call VerifyScreenDump(buf, 'Test_popupwin_win_execute', {}) + + call StopVimInTerminal(buf) + call delete('XtestPopupWinExecute') +endfunc + func ShowDialog(key, result) let s:cb_res = 999 let winid = popup_dialog('do you want to quit (Yes/no)?', #{ diff --git a/src/version.c b/src/version.c index 9e7825a97c..e3d61eb99c 100644 --- 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 */ /**/ + 1732, +/**/ 1731, /**/ 1730, |