Skip to content

Commit 81a3ff9

Browse files
yegappanbrammool
authored andcommitted
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)
1 parent 5154a88 commit 81a3ff9

File tree

7 files changed

+148
-0
lines changed

7 files changed

+148
-0
lines changed

runtime/doc/testing.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ test_gui_event({event}, {args})
9494
"findrepl" search and replace text.
9595
"mouse" mouse button click event.
9696
"scrollbar" move or drag the scrollbar.
97+
"sendevent" send a low-level GUI event.
9798
"tabline" select a tab page by mouse click.
9899
"tabmenu" select a tabline menu entry.
99100

@@ -177,6 +178,15 @@ test_gui_event({event}, {args})
177178
dragging: 1 to drag the scrollbar and 0 to click in the
178179
scrollbar.
179180

181+
"sendevent":
182+
Send a low-level GUI event (e.g. key-up or down).
183+
Currently only supported on MS-Windows.
184+
The supported items in {args} are:
185+
event: The supported string values are:
186+
keyup generate a keyup event
187+
keydown generate a keydown event
188+
keycode: Keycode to use for a keyup or a keydown event.
189+
180190
"tabline":
181191
Inject a mouse click event on the tabline to select a
182192
tabpage. The supported items in {args} are:

src/errors.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3303,4 +3303,6 @@ EXTERN char e_could_not_check_for_pending_sigalrm_str[]
33033303
#ifdef FEAT_EVAL
33043304
EXTERN char e_substitute_nesting_too_deep[]
33053305
INIT(= N_("E1290: substitute nesting too deep"));
3306+
EXTERN char e_invalid_argument_nr[]
3307+
INIT(= N_("E1291: Invalid argument: %ld"));
33063308
#endif

src/gui_w32.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8541,3 +8541,42 @@ netbeans_draw_multisign_indicator(int row)
85418541
SetPixel(s_hdc, x+2, y, gui.currFgColor);
85428542
}
85438543
#endif
8544+
8545+
#if defined(FEAT_EVAL) || defined(PROTO)
8546+
int
8547+
test_gui_w32_sendevent(dict_T *args)
8548+
{
8549+
char_u *event;
8550+
INPUT inputs[1];
8551+
8552+
event = dict_get_string(args, "event", TRUE);
8553+
if (event == NULL)
8554+
return FALSE;
8555+
8556+
ZeroMemory(inputs, sizeof(inputs));
8557+
8558+
if (STRICMP(event, "keydown") == 0 || STRICMP(event, "keyup") == 0)
8559+
{
8560+
WORD vkCode;
8561+
8562+
vkCode = dict_get_number_def(args, "keycode", 0);
8563+
if (vkCode <= 0 || vkCode >= 0xFF)
8564+
{
8565+
semsg(_(e_invalid_argument_nr), (long)vkCode);
8566+
return FALSE;
8567+
}
8568+
8569+
inputs[0].type = INPUT_KEYBOARD;
8570+
inputs[0].ki.wVk = vkCode;
8571+
if (STRICMP(event, "keyup") == 0)
8572+
inputs[0].ki.dwFlags = KEYEVENTF_KEYUP;
8573+
SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
8574+
}
8575+
else
8576+
semsg(_(e_invalid_argument_str), event);
8577+
8578+
vim_free(event);
8579+
8580+
return TRUE;
8581+
}
8582+
#endif

src/proto/gui_w32.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,5 @@ void gui_mch_post_balloon(BalloonEval *beval, char_u *mesg);
9696
BalloonEval *gui_mch_create_beval_area(void *target, char_u *mesg, void (*mesgCB)(BalloonEval *, int), void *clientData);
9797
void gui_mch_destroy_beval_area(BalloonEval *beval);
9898
void netbeans_draw_multisign_indicator(int row);
99+
int test_gui_w32_sendevent(dict_T *args);
99100
/* vim: set ft=c : */

src/testdir/test_gui.vim

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,4 +1606,88 @@ func Test_gui_dialog_file()
16061606
call delete('Xlines')
16071607
endfunc
16081608

1609+
" Test for sending low level key presses
1610+
func SendKeys(keylist)
1611+
for k in a:keylist
1612+
call test_gui_event("sendevent", #{event: "keydown", keycode: k})
1613+
endfor
1614+
for k in reverse(a:keylist)
1615+
call test_gui_event("sendevent", #{event: "keyup", keycode: k})
1616+
endfor
1617+
endfunc
1618+
1619+
func Test_gui_lowlevel_keyevent()
1620+
CheckMSWindows
1621+
new
1622+
1623+
" Test for <Ctrl-A> to <Ctrl-Z> keys
1624+
for kc in range(65, 90)
1625+
call SendKeys([0x11, kc])
1626+
let ch = getcharstr()
1627+
call assert_equal(nr2char(kc - 64), ch)
1628+
endfor
1629+
1630+
" Test for the various Ctrl and Shift key combinations.
1631+
let keytests = [
1632+
\ [[0x10, 0x21], "\<S-Pageup>", 2],
1633+
\ [[0x11, 0x21], "\<C-Pageup>", 4],
1634+
\ [[0x10, 0x22], "\<S-PageDown>", 2],
1635+
\ [[0x11, 0x22], "\<C-PageDown>", 4],
1636+
\ [[0x10, 0x23], "\<S-End>", 0],
1637+
\ [[0x11, 0x23], "\<C-End>", 0],
1638+
\ [[0x10, 0x24], "\<S-Home>", 0],
1639+
\ [[0x11, 0x24], "\<C-Home>", 0],
1640+
\ [[0x10, 0x25], "\<S-Left>", 0],
1641+
\ [[0x11, 0x25], "\<C-Left>", 0],
1642+
\ [[0x10, 0x26], "\<S-Up>", 0],
1643+
\ [[0x11, 0x26], "\<C-Up>", 4],
1644+
\ [[0x10, 0x27], "\<S-Right>", 0],
1645+
\ [[0x11, 0x27], "\<C-Right>", 0],
1646+
\ [[0x10, 0x28], "\<S-Down>", 0],
1647+
\ [[0x11, 0x28], "\<C-Down>", 4],
1648+
\ [[0x11, 0x30], "\<C-0>", 4],
1649+
\ [[0x11, 0x31], "\<C-1>", 4],
1650+
\ [[0x11, 0x32], "\<C-2>", 4],
1651+
\ [[0x11, 0x33], "\<C-3>", 4],
1652+
\ [[0x11, 0x34], "\<C-4>", 4],
1653+
\ [[0x11, 0x35], "\<C-5>", 4],
1654+
\ [[0x11, 0x36], "\<C-^>", 0],
1655+
\ [[0x11, 0x37], "\<C-7>", 4],
1656+
\ [[0x11, 0x38], "\<C-8>", 4],
1657+
\ [[0x11, 0x39], "\<C-9>", 4],
1658+
\ [[0x11, 0x60], "\<C-0>", 4],
1659+
\ [[0x11, 0x61], "\<C-1>", 4],
1660+
\ [[0x11, 0x62], "\<C-2>", 4],
1661+
\ [[0x11, 0x63], "\<C-3>", 4],
1662+
\ [[0x11, 0x64], "\<C-4>", 4],
1663+
\ [[0x11, 0x65], "\<C-5>", 4],
1664+
\ [[0x11, 0x66], "\<C-6>", 4],
1665+
\ [[0x11, 0x67], "\<C-7>", 4],
1666+
\ [[0x11, 0x68], "\<C-8>", 4],
1667+
\ [[0x11, 0x69], "\<C-9>", 4],
1668+
\ [[0x11, 0x6A], "\<C-*>", 4],
1669+
\ [[0x11, 0x6B], "\<C-+>", 4],
1670+
\ [[0x11, 0x6D], "\<C-->", 4],
1671+
\ [[0x11, 0x70], "\<C-F1>", 4],
1672+
\ [[0x11, 0x71], "\<C-F2>", 4],
1673+
\ [[0x11, 0x72], "\<C-F3>", 4],
1674+
\ [[0x11, 0x73], "\<C-F4>", 4],
1675+
\ [[0x11, 0x74], "\<C-F5>", 4],
1676+
\ [[0x11, 0x75], "\<C-F6>", 4],
1677+
\ [[0x11, 0x76], "\<C-F7>", 4],
1678+
\ [[0x11, 0x77], "\<C-F8>", 4],
1679+
\ [[0x11, 0x78], "\<C-F9>", 4],
1680+
\ ]
1681+
1682+
for [kcodes, kstr, kmod] in keytests
1683+
call SendKeys(kcodes)
1684+
let ch = getcharstr()
1685+
let mod = getcharmod()
1686+
call assert_equal(kstr, ch, $"key = {kstr}")
1687+
call assert_equal(kmod, mod)
1688+
endfor
1689+
1690+
bw!
1691+
endfunc
1692+
16091693
" vim: shiftwidth=2 sts=2 expandtab

src/testing.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,12 @@ f_test_gui_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
15001500
rettv->v_type = VAR_BOOL;
15011501
rettv->vval.v_number = FALSE;
15021502

1503+
if (sandbox != 0)
1504+
{
1505+
emsg(_(e_not_allowed_in_sandbox));
1506+
return;
1507+
}
1508+
15031509
if (check_for_string_arg(argvars, 0) == FAIL
15041510
|| check_for_dict_arg(argvars, 1) == FAIL
15051511
|| argvars[1].vval.v_dict == NULL)
@@ -1520,6 +1526,10 @@ f_test_gui_event(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
15201526
rettv->vval.v_number = test_gui_tabline_event(argvars[1].vval.v_dict);
15211527
else if (STRCMP(event, "tabmenu") == 0)
15221528
rettv->vval.v_number = test_gui_tabmenu_event(argvars[1].vval.v_dict);
1529+
# ifdef FEAT_GUI_MSWIN
1530+
else if (STRCMP(event, "sendevent") == 0)
1531+
rettv->vval.v_number = test_gui_w32_sendevent(argvars[1].vval.v_dict);
1532+
# endif
15231533
else
15241534
{
15251535
semsg(_(e_invalid_argument_str), event);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,8 @@ static char *(features[]) =
735735

736736
static int included_patches[] =
737737
{ /* Add new patch number below this line */
738+
/**/
739+
58,
738740
/**/
739741
57,
740742
/**/

0 commit comments

Comments
 (0)