]> granicus.if.org Git - vim/commitdiff
patch 9.0.0058: Win32: cannot test low level events v9.0.0058
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sat, 23 Jul 2022 04:04:16 +0000 (05:04 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 23 Jul 2022 04:04:16 +0000 (05:04 +0100)
Problem:    Win32: cannot test low level events.
Solution:   Add "sendevent" to test_gui_event(). (Yegappan Lakshmanan,
            closes #10679)

runtime/doc/testing.txt
src/errors.h
src/gui_w32.c
src/proto/gui_w32.pro
src/testdir/test_gui.vim
src/testing.c
src/version.c

index 6998a6edc28970c4ae1a3dd6bb702be94d1c3e13..7e8e8b9cc07e9ed1bc6fbd5feee0cc6e1acb75f0 100644 (file)
@@ -94,6 +94,7 @@ test_gui_event({event}, {args})
                    "findrepl"  search and replace text.
                    "mouse"     mouse button click event.
                    "scrollbar" move or drag the scrollbar.
+                   "sendevent" send a low-level GUI event.
                    "tabline"   select a tab page by mouse click.
                    "tabmenu"   select a tabline menu entry.
 
@@ -177,6 +178,15 @@ test_gui_event({event}, {args})
                    dragging:   1 to drag the scrollbar and 0 to click in the
                                scrollbar.
 
+               "sendevent":
+                 Send a low-level GUI event (e.g. key-up or down).
+                 Currently only supported on MS-Windows.
+                 The supported items in {args} are:
+                   event:      The supported string values are:
+                                   keyup   generate a keyup event
+                                   keydown generate a keydown event
+                   keycode:    Keycode to use for a keyup or a keydown event.
+
                "tabline":
                  Inject a mouse click event on the tabline to select a
                  tabpage. The supported items in {args} are:
index 43a1c9b95507b201cf4d605adbf56a6ab88d70fb..90aa2921a6eb573aa9650724c5a0cb08693d25d0 100644 (file)
@@ -3303,4 +3303,6 @@ EXTERN char e_could_not_check_for_pending_sigalrm_str[]
 #ifdef FEAT_EVAL
 EXTERN char e_substitute_nesting_too_deep[]
        INIT(= N_("E1290: substitute nesting too deep"));
+EXTERN char e_invalid_argument_nr[]
+       INIT(= N_("E1291: Invalid argument: %ld"));
 #endif
index f53318d6774564aa0ab7298401e1a74140127e09..472cebf733506d8241557851dd57677d7dfb9384 100644 (file)
@@ -8541,3 +8541,42 @@ netbeans_draw_multisign_indicator(int row)
     SetPixel(s_hdc, x+2, y, gui.currFgColor);
 }
 #endif
+
+#if defined(FEAT_EVAL) || defined(PROTO)
+    int
+test_gui_w32_sendevent(dict_T *args)
+{
+    char_u     *event;
+    INPUT      inputs[1];
+
+    event = dict_get_string(args, "event", TRUE);
+    if (event == NULL)
+       return FALSE;
+
+    ZeroMemory(inputs, sizeof(inputs));
+
+    if (STRICMP(event, "keydown") == 0 || STRICMP(event, "keyup") == 0)
+    {
+       WORD        vkCode;
+
+       vkCode = dict_get_number_def(args, "keycode", 0);
+       if (vkCode <= 0 || vkCode >= 0xFF)
+       {
+           semsg(_(e_invalid_argument_nr), (long)vkCode);
+           return FALSE;
+       }
+
+       inputs[0].type = INPUT_KEYBOARD;
+       inputs[0].ki.wVk = vkCode;
+       if (STRICMP(event, "keyup") == 0)
+           inputs[0].ki.dwFlags = KEYEVENTF_KEYUP;
+       SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
+    }
+    else
+       semsg(_(e_invalid_argument_str), event);
+
+    vim_free(event);
+
+    return TRUE;
+}
+#endif
index 43484ad802a20373008fad0c75e804599406934b..cab3343249682931e90c664904690100dd78630b 100644 (file)
@@ -96,4 +96,5 @@ void gui_mch_post_balloon(BalloonEval *beval, char_u *mesg);
 BalloonEval *gui_mch_create_beval_area(void *target, char_u *mesg, void (*mesgCB)(BalloonEval *, int), void *clientData);
 void gui_mch_destroy_beval_area(BalloonEval *beval);
 void netbeans_draw_multisign_indicator(int row);
+int test_gui_w32_sendevent(dict_T *args);
 /* vim: set ft=c : */
index 2612812b62f6157f246ab971fbf1498d1482daea..1fadd5eaed6f6641096afa247db8ca3a0ff5bfc7 100644 (file)
@@ -1606,4 +1606,88 @@ func Test_gui_dialog_file()
   call delete('Xlines')
 endfunc
 
+" Test for sending low level key presses
+func SendKeys(keylist)
+  for k in a:keylist
+    call test_gui_event("sendevent", #{event: "keydown", keycode: k})
+  endfor
+  for k in reverse(a:keylist)
+    call test_gui_event("sendevent", #{event: "keyup", keycode: k})
+  endfor
+endfunc
+
+func Test_gui_lowlevel_keyevent()
+  CheckMSWindows
+  new
+
+  " Test for <Ctrl-A> to <Ctrl-Z> keys
+  for kc in range(65, 90)
+    call SendKeys([0x11, kc])
+    let ch = getcharstr()
+    call assert_equal(nr2char(kc - 64), ch)
+  endfor
+
+  " Test for the various Ctrl and Shift key combinations.
+  let keytests = [
+    \ [[0x10, 0x21], "\<S-Pageup>", 2],
+    \ [[0x11, 0x21], "\<C-Pageup>", 4],
+    \ [[0x10, 0x22], "\<S-PageDown>", 2],
+    \ [[0x11, 0x22], "\<C-PageDown>", 4],
+    \ [[0x10, 0x23], "\<S-End>", 0],
+    \ [[0x11, 0x23], "\<C-End>", 0],
+    \ [[0x10, 0x24], "\<S-Home>", 0],
+    \ [[0x11, 0x24], "\<C-Home>", 0],
+    \ [[0x10, 0x25], "\<S-Left>", 0],
+    \ [[0x11, 0x25], "\<C-Left>", 0],
+    \ [[0x10, 0x26], "\<S-Up>", 0],
+    \ [[0x11, 0x26], "\<C-Up>", 4],
+    \ [[0x10, 0x27], "\<S-Right>", 0],
+    \ [[0x11, 0x27], "\<C-Right>", 0],
+    \ [[0x10, 0x28], "\<S-Down>", 0],
+    \ [[0x11, 0x28], "\<C-Down>", 4],
+    \ [[0x11, 0x30], "\<C-0>", 4],
+    \ [[0x11, 0x31], "\<C-1>", 4],
+    \ [[0x11, 0x32], "\<C-2>", 4],
+    \ [[0x11, 0x33], "\<C-3>", 4],
+    \ [[0x11, 0x34], "\<C-4>", 4],
+    \ [[0x11, 0x35], "\<C-5>", 4],
+    \ [[0x11, 0x36], "\<C-^>", 0],
+    \ [[0x11, 0x37], "\<C-7>", 4],
+    \ [[0x11, 0x38], "\<C-8>", 4],
+    \ [[0x11, 0x39], "\<C-9>", 4],
+    \ [[0x11, 0x60], "\<C-0>", 4],
+    \ [[0x11, 0x61], "\<C-1>", 4],
+    \ [[0x11, 0x62], "\<C-2>", 4],
+    \ [[0x11, 0x63], "\<C-3>", 4],
+    \ [[0x11, 0x64], "\<C-4>", 4],
+    \ [[0x11, 0x65], "\<C-5>", 4],
+    \ [[0x11, 0x66], "\<C-6>", 4],
+    \ [[0x11, 0x67], "\<C-7>", 4],
+    \ [[0x11, 0x68], "\<C-8>", 4],
+    \ [[0x11, 0x69], "\<C-9>", 4],
+    \ [[0x11, 0x6A], "\<C-*>", 4],
+    \ [[0x11, 0x6B], "\<C-+>", 4],
+    \ [[0x11, 0x6D], "\<C-->", 4],
+    \ [[0x11, 0x70], "\<C-F1>", 4],
+    \ [[0x11, 0x71], "\<C-F2>", 4],
+    \ [[0x11, 0x72], "\<C-F3>", 4],
+    \ [[0x11, 0x73], "\<C-F4>", 4],
+    \ [[0x11, 0x74], "\<C-F5>", 4],
+    \ [[0x11, 0x75], "\<C-F6>", 4],
+    \ [[0x11, 0x76], "\<C-F7>", 4],
+    \ [[0x11, 0x77], "\<C-F8>", 4],
+    \ [[0x11, 0x78], "\<C-F9>", 4],
+    \ ]
+
+  for [kcodes, kstr, kmod] in keytests
+    call SendKeys(kcodes)
+    let ch = getcharstr()
+    let mod = getcharmod()
+    call assert_equal(kstr, ch, $"key = {kstr}")
+    call assert_equal(kmod, mod)
+  endfor
+
+  bw!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 66a3281d8f2847a7bf116efe6a014cabc743a390..b1f632223a69d1b3355bea75e9c7e3ea2e502c3f 100644 (file)
@@ -1500,6 +1500,12 @@ f_test_gui_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
     rettv->v_type = VAR_BOOL;
     rettv->vval.v_number = FALSE;
 
+    if (sandbox != 0)
+    {
+       emsg(_(e_not_allowed_in_sandbox));
+       return;
+    }
+
     if (check_for_string_arg(argvars, 0) == FAIL
            || check_for_dict_arg(argvars, 1) == FAIL
            || argvars[1].vval.v_dict == NULL)
@@ -1520,6 +1526,10 @@ f_test_gui_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
        rettv->vval.v_number = test_gui_tabline_event(argvars[1].vval.v_dict);
     else if (STRCMP(event, "tabmenu") == 0)
        rettv->vval.v_number = test_gui_tabmenu_event(argvars[1].vval.v_dict);
+#  ifdef FEAT_GUI_MSWIN
+    else if (STRCMP(event, "sendevent") == 0)
+       rettv->vval.v_number = test_gui_w32_sendevent(argvars[1].vval.v_dict);
+#  endif
     else
     {
        semsg(_(e_invalid_argument_str), event);
index ee421e4760ef08e5f11ec11b9f67235dfeef3d42..4db3a24ae544bf2ad48f9cc1425ebd2f003809be 100644 (file)
@@ -735,6 +735,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    58,
 /**/
     57,
 /**/