forked from aniani/vim
patch 8.2.1732: stuck when win_execute() for a popup causes an error
Problem: Stuck when win_execute() for a popup causes an error. Solution: Disable the filter callback on error. (issue #6999)
This commit is contained in:
@@ -2250,7 +2250,13 @@ popup_close_and_callback(win_T *wp, typval_T *arg)
|
|||||||
|
|
||||||
// Just in case a check higher up is missing.
|
// Just in case a check higher up is missing.
|
||||||
if (wp == curwin && ERROR_IF_POPUP_WINDOW)
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CHECK_CURBUF;
|
CHECK_CURBUF;
|
||||||
if (wp->w_close_cb.cb_name != NULL)
|
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".
|
* Invoke the filter callback for window "wp" with typed character "c".
|
||||||
* Uses the global "mod_mask" for modifiers.
|
* 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!
|
* Careful: The filter may make "wp" invalid!
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@@ -3145,12 +3152,18 @@ invoke_popup_filter(win_T *wp, int c)
|
|||||||
if (c == Ctrl_C)
|
if (c == Ctrl_C)
|
||||||
{
|
{
|
||||||
int save_got_int = got_int;
|
int save_got_int = got_int;
|
||||||
|
int was_curwin = wp == curwin;
|
||||||
|
|
||||||
// Reset got_int to avoid the callback isn't called.
|
// Reset got_int to avoid the callback isn't called.
|
||||||
got_int = FALSE;
|
got_int = FALSE;
|
||||||
popup_close_with_retval(wp, -1);
|
popup_close_with_retval(wp, -1);
|
||||||
got_int |= save_got_int;
|
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;
|
argv[0].v_type = VAR_NUMBER;
|
||||||
@@ -3238,7 +3251,8 @@ popup_do_filter(int c)
|
|||||||
|
|
||||||
popup_reset_handled(POPUP_HANDLED_2);
|
popup_reset_handled(POPUP_HANDLED_2);
|
||||||
state = get_real_state();
|
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
|
if (wp->w_filter_cb.cb_name != NULL
|
||||||
&& (wp->w_filter_mode & state) != 0)
|
&& (wp->w_filter_mode & state) != 0)
|
||||||
res = invoke_popup_filter(wp, c);
|
res = invoke_popup_filter(wp, c);
|
||||||
@@ -3254,7 +3268,9 @@ popup_do_filter(int c)
|
|||||||
}
|
}
|
||||||
recursive = FALSE;
|
recursive = FALSE;
|
||||||
KeyTyped = save_KeyTyped;
|
KeyTyped = save_KeyTyped;
|
||||||
return res;
|
|
||||||
|
// When interrupted return FALSE to avoid looping.
|
||||||
|
return res == -1 ? FALSE : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
10
src/testdir/dumps/Test_popupwin_win_execute.dump
Normal file
10
src/testdir/dumps/Test_popupwin_win_execute.dump
Normal file
@@ -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|
|
@@ -5,6 +5,8 @@ if exists('*CanRunVimInTerminal')
|
|||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
source shared.vim
|
||||||
|
|
||||||
" For most tests we need to be able to run terminal Vim with 256 colors. On
|
" 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
|
" MS-Windows the console only has 16 colors and the GUI can't run in a
|
||||||
" terminal.
|
" terminal.
|
||||||
@@ -51,6 +53,7 @@ endfunc
|
|||||||
" "rows" - height of the terminal window (max. 20)
|
" "rows" - height of the terminal window (max. 20)
|
||||||
" "cols" - width of the terminal window (max. 78)
|
" "cols" - width of the terminal window (max. 78)
|
||||||
" "statusoff" - number of lines the status is offset from default
|
" "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)
|
func RunVimInTerminal(arguments, options)
|
||||||
" If Vim doesn't exit a swap file remains, causing other tests to fail.
|
" If Vim doesn't exit a swap file remains, causing other tests to fail.
|
||||||
" Remove it here.
|
" Remove it here.
|
||||||
|
@@ -1556,6 +1556,30 @@ func Test_popup_filter_normal_cmd()
|
|||||||
call delete('XtestPopupNormal')
|
call delete('XtestPopupNormal')
|
||||||
endfunc
|
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)
|
func ShowDialog(key, result)
|
||||||
let s:cb_res = 999
|
let s:cb_res = 999
|
||||||
let winid = popup_dialog('do you want to quit (Yes/no)?', #{
|
let winid = popup_dialog('do you want to quit (Yes/no)?', #{
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1732,
|
||||||
/**/
|
/**/
|
||||||
1731,
|
1731,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user