]> granicus.if.org Git - vim/commitdiff
patch 8.2.1732: stuck when win_execute() for a popup causes an error v8.2.1732
authorBram Moolenaar <Bram@vim.org>
Wed, 23 Sep 2020 15:41:26 +0000 (17:41 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 23 Sep 2020 15:41:26 +0000 (17:41 +0200)
Problem:    Stuck when win_execute() for a popup causes an error.
Solution:   Disable the filter callback on error. (issue #6999)

src/popupwin.c
src/testdir/dumps/Test_popupwin_win_execute.dump [new file with mode: 0644]
src/testdir/term_util.vim
src/testdir/test_popupwin.vim
src/version.c

index 6080ecbc00bd111af9f132852fc0a0c606b9593d..301c38240ec726a2d0f0c9650db846396235395e 100644 (file)
@@ -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 (file)
index 0000000..f554859
--- /dev/null
@@ -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| 
index 4a5e64989bca61c7604715bbed9aeb9f819f4fa5..53735c8d33597c49ea29c6b234ed4567bad0169a 100644 (file)
@@ -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.
index 6607ea231ced8c517d288ae645e9bc606559dc27..79eaca7c13d3e6276426c3684c7c11dec6bd6e0d 100644 (file)
@@ -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)?', #{
index 9e7825a97c3369398ef15ebf66963b8e4980ab2a..e3d61eb99c409d85d304065f2a11d7dacf61362b 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1732,
 /**/
     1731,
 /**/