mirror of
https://github.com/vim/vim.git
synced 2025-10-08 06:04:08 -04:00
patch 9.0.1084: code handling low level MS-Windows events cannot be tested
Problem: Code handling low level MS-Windows events cannot be tested. Solution: Add test_mswin_event() and tests using it. (Christopher Plewright, closes #11622)
This commit is contained in:
committed by
Bram Moolenaar
parent
418b547881
commit
20b795e0eb
165
src/gui_w32.c
165
src/gui_w32.c
@@ -8643,41 +8643,176 @@ netbeans_draw_multisign_indicator(int row)
|
||||
#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)
|
||||
// TODO: at the moment, this is just a copy of test_gui_mouse_event.
|
||||
// But, we could instead generate actual Win32 mouse event messages,
|
||||
// ie. to make it consistent wih test_gui_w32_sendevent_keyboard.
|
||||
static int
|
||||
test_gui_w32_sendevent_mouse(dict_T *args)
|
||||
{
|
||||
if (!dict_has_key(args, "row") || !dict_has_key(args, "col"))
|
||||
return FALSE;
|
||||
|
||||
ZeroMemory(inputs, sizeof(inputs));
|
||||
// Note: "move" is optional, requires fewer arguments
|
||||
int move = (int)dict_get_bool(args, "move", FALSE);
|
||||
|
||||
if (STRICMP(event, "keydown") == 0 || STRICMP(event, "keyup") == 0)
|
||||
if (!move && (!dict_has_key(args, "button")
|
||||
|| !dict_has_key(args, "multiclick")
|
||||
|| !dict_has_key(args, "modifiers")))
|
||||
return FALSE;
|
||||
|
||||
int row = (int)dict_get_number(args, "row");
|
||||
int col = (int)dict_get_number(args, "col");
|
||||
|
||||
if (move)
|
||||
{
|
||||
WORD vkCode;
|
||||
// the "move" argument expects row and col coordnates to be in pixels,
|
||||
// unless "cell" is specified and is TRUE.
|
||||
if (dict_get_bool(args, "cell", FALSE))
|
||||
{
|
||||
// calculate the middle of the character cell
|
||||
// Note: Cell coordinates are 1-based from vimscript
|
||||
int pY = (row - 1) * gui.char_height + gui.char_height / 2;
|
||||
int pX = (col - 1) * gui.char_width + gui.char_width / 2;
|
||||
gui_mouse_moved(pX, pY);
|
||||
}
|
||||
else
|
||||
gui_mouse_moved(col, row);
|
||||
}
|
||||
else
|
||||
{
|
||||
int button = (int)dict_get_number(args, "button");
|
||||
int repeated_click = (int)dict_get_number(args, "multiclick");
|
||||
int_u mods = (int)dict_get_number(args, "modifiers");
|
||||
|
||||
vkCode = dict_get_number_def(args, "keycode", 0);
|
||||
// Reset the scroll values to known values.
|
||||
// XXX: Remove this when/if the scroll step is made configurable.
|
||||
mouse_set_hor_scroll_step(6);
|
||||
mouse_set_vert_scroll_step(3);
|
||||
|
||||
gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1),
|
||||
repeated_click, mods);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
test_gui_w32_sendevent_keyboard(dict_T *args)
|
||||
{
|
||||
INPUT inputs[1];
|
||||
INPUT modkeys[3];
|
||||
SecureZeroMemory(inputs, sizeof(INPUT));
|
||||
SecureZeroMemory(modkeys, 3 * sizeof(INPUT));
|
||||
|
||||
char_u *event = dict_get_string(args, "event", TRUE);
|
||||
|
||||
if (event && (STRICMP(event, "keydown") == 0
|
||||
|| STRICMP(event, "keyup") == 0))
|
||||
{
|
||||
WORD vkCode = dict_get_number_def(args, "keycode", 0);
|
||||
if (vkCode <= 0 || vkCode >= 0xFF)
|
||||
{
|
||||
semsg(_(e_invalid_argument_nr), (long)vkCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL isModKey = (vkCode == VK_SHIFT || vkCode == VK_CONTROL
|
||||
|| vkCode == VK_MENU || vkCode == VK_LSHIFT || vkCode == VK_RSHIFT
|
||||
|| vkCode == VK_LCONTROL || vkCode == VK_RCONTROL
|
||||
|| vkCode == VK_LMENU || vkCode == VK_RMENU );
|
||||
|
||||
BOOL unwrapMods = FALSE;
|
||||
int mods = (int)dict_get_number(args, "modifiers");
|
||||
|
||||
// If there are modifiers in the args, and it is not a keyup event and
|
||||
// vkCode is not a modifier key, then we generate virtual modifier key
|
||||
// messages before sending the actual key message.
|
||||
if(mods && STRICMP(event, "keydown") == 0 && !isModKey)
|
||||
{
|
||||
int n = 0;
|
||||
if (mods & MOD_MASK_SHIFT)
|
||||
{
|
||||
modkeys[n].type = INPUT_KEYBOARD;
|
||||
modkeys[n].ki.wVk = VK_LSHIFT;
|
||||
n++;
|
||||
}
|
||||
if (mods & MOD_MASK_CTRL)
|
||||
{
|
||||
modkeys[n].type = INPUT_KEYBOARD;
|
||||
modkeys[n].ki.wVk = VK_LCONTROL;
|
||||
n++;
|
||||
}
|
||||
if (mods & MOD_MASK_ALT)
|
||||
{
|
||||
modkeys[n].type = INPUT_KEYBOARD;
|
||||
modkeys[n].ki.wVk = VK_LMENU;
|
||||
n++;
|
||||
}
|
||||
if (n)
|
||||
{
|
||||
(void)SetForegroundWindow(s_hwnd);
|
||||
SendInput(n, modkeys, sizeof(INPUT));
|
||||
}
|
||||
}
|
||||
|
||||
inputs[0].type = INPUT_KEYBOARD;
|
||||
inputs[0].ki.wVk = vkCode;
|
||||
if (STRICMP(event, "keyup") == 0)
|
||||
{
|
||||
inputs[0].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
if(!isModKey)
|
||||
unwrapMods = TRUE;
|
||||
}
|
||||
|
||||
(void)SetForegroundWindow(s_hwnd);
|
||||
SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
|
||||
vim_free(event);
|
||||
|
||||
if (unwrapMods)
|
||||
{
|
||||
modkeys[0].type = INPUT_KEYBOARD;
|
||||
modkeys[0].ki.wVk = VK_LSHIFT;
|
||||
modkeys[0].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
|
||||
modkeys[1].type = INPUT_KEYBOARD;
|
||||
modkeys[1].ki.wVk = VK_LCONTROL;
|
||||
modkeys[1].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
|
||||
modkeys[2].type = INPUT_KEYBOARD;
|
||||
modkeys[2].ki.wVk = VK_LMENU;
|
||||
modkeys[2].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
|
||||
(void)SetForegroundWindow(s_hwnd);
|
||||
SendInput(3, modkeys, sizeof(INPUT));
|
||||
}
|
||||
}
|
||||
else
|
||||
semsg(_(e_invalid_argument_str), event);
|
||||
|
||||
vim_free(event);
|
||||
|
||||
{
|
||||
if (event == NULL)
|
||||
{
|
||||
semsg(_(e_missing_argument_str), "event");
|
||||
}
|
||||
else
|
||||
{
|
||||
semsg(_(e_invalid_value_for_argument_str_str), "event", event);
|
||||
vim_free(event);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
test_gui_w32_sendevent(char_u *event, dict_T *args)
|
||||
{
|
||||
if (STRICMP(event, "key") == 0)
|
||||
return test_gui_w32_sendevent_keyboard(args);
|
||||
else if (STRICMP(event, "mouse") == 0)
|
||||
return test_gui_w32_sendevent_mouse(args);
|
||||
else
|
||||
{
|
||||
semsg(_(e_invalid_value_for_argument_str_str), "event", event);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user