Mercurial > vim
changeset 29432:339fe2968690 v9.0.0058
patch 9.0.0058: Win32: cannot test low level events
Commit: https://github.com/vim/vim/commit/81a3ff97e2012bdafc3ece796289f2e11e2754f3
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Sat Jul 23 05:04:16 2022 +0100
patch 9.0.0058: Win32: cannot test low level events
Problem: Win32: cannot test low level events.
Solution: Add "sendevent" to test_gui_event(). (Yegappan Lakshmanan,
closes #10679)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 23 Jul 2022 06:15:07 +0200 |
parents | 6d6fa84d617c |
children | 7f047c9af319 |
files | 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 |
diffstat | 7 files changed, 148 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -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:
--- a/src/errors.h +++ b/src/errors.h @@ -3303,4 +3303,6 @@ EXTERN char e_could_not_check_for_pendin #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
--- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -8541,3 +8541,42 @@ netbeans_draw_multisign_indicator(int ro 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
--- a/src/proto/gui_w32.pro +++ b/src/proto/gui_w32.pro @@ -96,4 +96,5 @@ void gui_mch_post_balloon(BalloonEval *b 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 : */
--- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -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
--- a/src/testing.c +++ b/src/testing.c @@ -1500,6 +1500,12 @@ f_test_gui_event(typval_T *argvars UNUSE 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 UNUSE 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);