Adding flaky_wine to some SetActiveWindow tests and refactor SendInput tests to make them more readable, try to fix some spurious failures and extend them with more tests and non-US layout support.
From: Rémi Bernon rbernon@codeweavers.com
They are constantly failing on Gitlab, and may be caused various race conditions around window focus, both in Wine and in Fvwm. It would be nice to fix them but it's been going for many years now and unlikely to be the case soon. --- dlls/user32/tests/win.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 2fd31be3314..8dad718e357 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -3814,10 +3814,13 @@ static void test_SetActiveWindow_0( char **argv ) flush_events( TRUE );
tmp = GetForegroundWindow(); + flaky_wine ok( tmp == hwnd, "GetForegroundWindow returned %p\n", tmp ); tmp = GetActiveWindow(); + flaky_wine ok( tmp == hwnd, "GetActiveWindow returned %p\n", tmp ); tmp = GetFocus(); + flaky_wine ok( tmp == hwnd, "GetFocus returned %p\n", tmp );
events[1] = CreateEventW( NULL, FALSE, FALSE, L"test_SetActiveWindow_0_start" );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index f92b839f1cb..30e0ad06823 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -5386,6 +5386,21 @@ static void test_ClipCursor( char **argv ) if (!EqualRect( &rect, &virtual_rect )) ok_ret( 1, ClipCursor( NULL ) ); }
+/* run the tests in a separate desktop to avoid interaction with other + * tests, current desktop state, or user actions. */ +static void test_input_desktop( char **argv ) +{ + POINT pos; + + ok_ret( 1, GetCursorPos( &pos ) ); + + test_SendInput(); + test_Input_blackbox(); + test_Input_whitebox(); + + ok_ret( 1, SetCursorPos( pos.x, pos.y ) ); +} + START_TEST(input) { char **argv; @@ -5408,10 +5423,10 @@ START_TEST(input) return test_ClipCursor_process(); if (argc >= 3 && !strcmp( argv[2], "test_ClipCursor_desktop" )) return test_ClipCursor_desktop( argv ); + if (argc >= 3 && !strcmp( argv[2], "test_input_desktop" )) + return test_input_desktop( argv );
- test_SendInput(); - test_Input_blackbox(); - test_Input_whitebox(); + run_in_desktop( argv, "test_input_desktop", 1 ); test_Input_unicode(); test_Input_mouse(); test_keynames();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 1575 +++++++++++++++++-------------------- 1 file changed, 707 insertions(+), 868 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 30e0ad06823..c67b59b8abe 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -64,9 +64,240 @@ #define check_member( val, exp, fmt, member ) \ check_member_( __FILE__, __LINE__, val, exp, fmt, member )
+static const char *debugstr_ok( const char *cond ) +{ + int c, n = 0; + /* skip possible casts */ + while ((c = *cond++)) + { + if (c == '(') n++; + if (!n) break; + if (c == ')') n--; + } + if (!strchr( cond - 1, '(' )) return wine_dbg_sprintf( "got %s", cond - 1 ); + return wine_dbg_sprintf( "%.*s returned", (int)strcspn( cond - 1, "( " ), cond - 1 ); +} + +#define ok_eq( e, r, t, f, ... ) \ + do \ + { \ + t v = (r); \ + ok( v == (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ + } while (0) +#define ok_ne( e, r, t, f, ... ) \ + do \ + { \ + t v = (r); \ + ok( v != (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ + } while (0) +#define ok_rect( e, r ) \ + do \ + { \ + RECT v = (r); \ + ok( EqualRect( &v, &(e) ), "%s %s\n", debugstr_ok(#r), wine_dbgstr_rect(&v) ); \ + } while (0) +#define ok_point( e, r ) \ + do \ + { \ + POINT v = (r); \ + ok( !memcmp( &v, &(e), sizeof(v) ), "%s %s\n", debugstr_ok(#r), wine_dbgstr_point(&v) ); \ + } while (0) +#define ok_ret( e, r ) ok_eq( e, r, UINT_PTR, "%Iu, error %ld", GetLastError() ) + +enum user_function +{ + MSG_TEST_WIN = 1, + LL_HOOK_KEYBD, +}; + +struct user_call +{ + enum user_function func; + + union + { + struct + { + UINT msg; + WPARAM wparam; + LPARAM lparam; + } message; + struct + { + UINT msg; + UINT scan; + UINT vkey; + UINT flags; + UINT_PTR extra; + } ll_hook_kbd; + }; + + BOOL todo; + BOOL todo_value; + BOOL broken; +}; + +static const struct user_call empty_sequence[] = {{0}}; +static struct user_call current_sequence[1024]; +static LONG current_sequence_len; + +static const char *debugstr_wm( UINT msg ) +{ + switch (msg) + { + case WM_CHAR: return "WM_CHAR"; + case WM_KEYDOWN: return "WM_KEYDOWN"; + case WM_KEYUP: return "WM_KEYUP"; + case WM_SYSCHAR: return "WM_SYSCHAR"; + case WM_SYSCOMMAND: return "WM_SYSCOMMAND"; + case WM_SYSKEYDOWN: return "WM_SYSKEYDOWN"; + case WM_SYSKEYUP: return "WM_SYSKEYUP"; + } + return wine_dbg_sprintf( "%#x", msg ); +} + +static const char *debugstr_vk( UINT vkey ) +{ + switch (vkey) + { + case VK_CONTROL: return "VK_CONTROL"; + case VK_LCONTROL: return "VK_LCONTROL"; + case VK_LMENU: return "VK_LMENU"; + case VK_LSHIFT: return "VK_LSHIFT"; + case VK_MENU: return "VK_MENU"; + case VK_RCONTROL: return "VK_RCONTROL"; + case VK_RMENU: return "VK_RMENU"; + case VK_RSHIFT: return "VK_RSHIFT"; + case VK_SHIFT: return "VK_SHIFT"; + } + + if (vkey >= '0' && vkey <= '9') return wine_dbg_sprintf( "%c", vkey ); + if (vkey >= 'A' && vkey <= 'Z') return wine_dbg_sprintf( "%c", vkey ); + return wine_dbg_sprintf( "%#x", vkey ); +} + +#define ok_call( a, b ) ok_call_( __FILE__, __LINE__, a, b ) +static int ok_call_( const char *file, int line, const struct user_call *expected, const struct user_call *received ) +{ + int ret; + + if ((ret = expected->func - received->func)) goto done; + + switch (expected->func) + { + case MSG_TEST_WIN: + if ((ret = expected->message.msg - received->message.msg)) goto done; + if ((ret = (expected->message.wparam - received->message.wparam))) goto done; + if ((ret = (expected->message.lparam - received->message.lparam))) goto done; + break; + case LL_HOOK_KEYBD: + if ((ret = expected->ll_hook_kbd.msg - received->ll_hook_kbd.msg)) goto done; + if ((ret = (expected->ll_hook_kbd.scan - received->ll_hook_kbd.scan))) goto done; + if ((ret = expected->ll_hook_kbd.vkey - received->ll_hook_kbd.vkey)) goto done; + if ((ret = (expected->ll_hook_kbd.flags - received->ll_hook_kbd.flags))) goto done; + if ((ret = (expected->ll_hook_kbd.extra - received->ll_hook_kbd.extra))) goto done; + break; + } + +done: + if (ret && broken( expected->broken )) return ret; + + switch (received->func) + { + case MSG_TEST_WIN: + todo_wine_if( expected->todo || expected->todo_value ) + ok_(file, line)( !ret, "got msg %s, wparam %#Ix, lparam %#Ix\n", debugstr_wm(received->message.msg), + received->message.wparam, received->message.lparam ); + return ret; + case LL_HOOK_KEYBD: + todo_wine_if( expected->todo || expected->todo_value ) + ok_(file, line)( !ret, "got hook msg %s scan %#x, vkey %s, flags %#x, extra %#Ix\n", debugstr_wm(received->ll_hook_kbd.msg), + received->ll_hook_kbd.scan, debugstr_vk(received->ll_hook_kbd.vkey), received->ll_hook_kbd.flags, + received->ll_hook_kbd.extra ); + return ret; + } + + switch (expected->func) + { + case MSG_TEST_WIN: + todo_wine_if( expected->todo || expected->todo_value ) + ok_(file, line)( !ret, "msg %s, wparam %#Ix, lparam %#Ix\n", debugstr_wm(expected->message.msg), + expected->message.wparam, expected->message.lparam ); + break; + case LL_HOOK_KEYBD: + todo_wine_if( expected->todo || expected->todo_value ) + ok_(file, line)( !ret, "hook msg %s scan %#x, vkey %s, flags %#x, extra %#Ix\n", debugstr_wm(expected->ll_hook_kbd.msg), + expected->ll_hook_kbd.scan, debugstr_vk(expected->ll_hook_kbd.vkey), expected->ll_hook_kbd.flags, + expected->ll_hook_kbd.extra ); + break; + } + + return 0; +} + +#define ok_seq( a ) ok_seq_( __FILE__, __LINE__, a, #a ) +static void ok_seq_( const char *file, int line, const struct user_call *expected, const char *context ) +{ + const struct user_call *received = current_sequence; + UINT i = 0, ret; + + while (expected->func || received->func) + { + winetest_push_context( "%u%s%s", i++, !expected->func ? " (spurious)" : "", + !received->func ? " (missing)" : "" ); + ret = ok_call_( file, line, expected, received ); + if (ret && expected->todo && expected->func && + !strcmp( winetest_platform, "wine" )) + expected++; + else if (ret && broken(expected->broken)) + expected++; + else + { + if (expected->func) expected++; + if (received->func) received++; + } + winetest_pop_context(); + } + + memset( current_sequence, 0, sizeof(current_sequence) ); + current_sequence_len = 0; +} + +static void append_ll_hook_kbd( UINT msg, const KBDLLHOOKSTRUCT *info ) +{ + struct user_call call = + { + .func = LL_HOOK_KEYBD, .ll_hook_kbd = + { + .msg = msg, .scan = info->scanCode, .vkey = info->vkCode, + .flags = info->flags, .extra = info->dwExtraInfo + } + }; + ULONG index = InterlockedIncrement( ¤t_sequence_len ) - 1; + ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index ); + current_sequence[index] = call; +} + +static BOOL (*p_accept_message)( UINT msg ); +static void append_message( UINT msg, WPARAM wparam, LPARAM lparam ) +{ + if (!p_accept_message || p_accept_message( msg )) + { + struct user_call call = {.func = MSG_TEST_WIN, .message = {.msg = msg, .wparam = wparam, .lparam = lparam}}; + ULONG index = InterlockedIncrement( ¤t_sequence_len ) - 1; + ok( index < ARRAY_SIZE(current_sequence), "got %lu calls\n", index ); + current_sequence[index] = call; + } +} + +static LRESULT CALLBACK append_message_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + append_message( msg, wparam, lparam ); + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} + /* globals */ static HWND hWndTest; -static LONG timetag = 0x10000000;
#define DESKTOP_ALL_ACCESS 0x01ff
@@ -100,55 +331,8 @@ static UINT (WINAPI *pGetRawInputDeviceInfoW) (HANDLE, UINT, void *, UINT *); static UINT (WINAPI *pGetRawInputDeviceInfoA) (HANDLE, UINT, void *, UINT *); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
-#define MAXKEYEVENTS 12 -#define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one - and only one message */ - -/* keyboard message names, sorted as their value */ -static const char *MSGNAME[]={"WM_KEYDOWN", "WM_KEYUP", "WM_CHAR","WM_DEADCHAR", - "WM_SYSKEYDOWN", "WM_SYSKEYUP", "WM_SYSCHAR", "WM_SYSDEADCHAR" ,"WM_KEYLAST"}; - -/* keyevents, add more as needed */ -typedef enum KEVtag -{ ALTDOWN = 1, ALTUP, XDOWN, XUP, SHIFTDOWN, SHIFTUP, CTRLDOWN, CTRLUP } KEV; -/* matching VK's */ -static const int GETVKEY[]={0, VK_MENU, VK_MENU, 'X', 'X', VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL}; -/* matching scan codes */ -static const int GETSCAN[]={0, 0x38, 0x38, 0x2D, 0x2D, 0x2A, 0x2A, 0x1D, 0x1D }; -/* matching updown events */ -static const int GETFLAGS[]={0, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP}; -/* matching descriptions */ -static const char *getdesc[]={"", "+alt","-alt","+X","-X","+shift","-shift","+ctrl","-ctrl"}; - -typedef struct { - UINT message; - WPARAM wParam; - LPARAM lParam; -} KMSG; - -/******************************************* - * add new test sets here - * the software will make all combinations of the - * keyevent defined here - */ -static const struct { - int nrkev; - KEV keydwn[MAXKEYEVENTS]; - KEV keyup[MAXKEYEVENTS]; -} testkeyset[]= { - { 2, { ALTDOWN, XDOWN }, { ALTUP, XUP}}, - { 3, { ALTDOWN, XDOWN , SHIFTDOWN}, { ALTUP, XUP, SHIFTUP}}, - { 3, { ALTDOWN, XDOWN , CTRLDOWN}, { ALTUP, XUP, CTRLUP}}, - { 3, { SHIFTDOWN, XDOWN , CTRLDOWN}, { SHIFTUP, XUP, CTRLUP}}, - { 0 } /* mark the end */ -}; - /**********************adapted from input.c **********************************/
-static BYTE InputKeyStateTable[256]; -static BYTE AsyncKeyStateTable[256]; -static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP - or a WM_KEYUP message */ static BOOL is_wow64;
static void init_function_pointers(void) @@ -180,34 +364,6 @@ static void init_function_pointers(void) is_wow64 = FALSE; }
-static const char *debugstr_ok( const char *cond ) -{ - int c, n = 0; - /* skip possible casts */ - while ((c = *cond++)) - { - if (c == '(') n++; - if (!n) break; - if (c == ')') n--; - } - if (!strchr( cond - 1, '(' )) return wine_dbg_sprintf( "got %s", cond - 1 ); - return wine_dbg_sprintf( "%.*s returned", (int)strcspn( cond - 1, "( " ), cond - 1 ); -} - -#define ok_eq( e, r, t, f, ... ) \ - do \ - { \ - t v = (r); \ - ok( v == (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \ - } while (0) -#define ok_rect( e, r ) \ - do \ - { \ - RECT v = (r); \ - ok( EqualRect( &v, &(e) ), "%s %s\n", debugstr_ok(#r), wine_dbgstr_rect(&v) ); \ - } while (0) -#define ok_ret( e, r ) ok_eq( e, r, UINT_PTR, "%Iu, error %ld", GetLastError() ) - #define run_in_process( a, b ) run_in_process_( __FILE__, __LINE__, a, b ) static void run_in_process_( const char *file, int line, char **argv, const char *args ) { @@ -268,8 +424,9 @@ static void run_in_desktop_( const char *file, int line, char **argv, ok_(file, line)( ret, "CloseDesktop failed, error %lu\n", GetLastError() ); }
-#define msg_wait_for_events( a, b, c ) msg_wait_for_events_( __FILE__, __LINE__, a, b, c ) -static DWORD msg_wait_for_events_( const char *file, int line, DWORD count, HANDLE *events, DWORD timeout ) +#define wait_messages( a, b ) msg_wait_for_events_( __FILE__, __LINE__, 0, NULL, a, b ) +#define msg_wait_for_events( a, b, c ) msg_wait_for_events_( __FILE__, __LINE__, a, b, c, FALSE ) +static DWORD msg_wait_for_events_( const char *file, int line, DWORD count, HANDLE *events, DWORD timeout, BOOL append_peeked ) { DWORD ret, end = GetTickCount() + min( timeout, 5000 ); MSG msg; @@ -278,6 +435,7 @@ static DWORD msg_wait_for_events_( const char *file, int line, DWORD count, HAND { while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) { + if (append_peeked) append_message( msg.message, msg.wParam, msg.lParam ); TranslateMessage( &msg ); DispatchMessageW( &msg ); } @@ -292,226 +450,6 @@ static DWORD msg_wait_for_events_( const char *file, int line, DWORD count, HAND return ret; }
-static int KbdMessage( KEV kev, WPARAM *pwParam, LPARAM *plParam ) -{ - UINT message; - int VKey = GETVKEY[kev]; - WORD flags; - - flags = LOBYTE(GETSCAN[kev]); - if (GETFLAGS[kev] & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED; - - if (GETFLAGS[kev] & KEYEVENTF_KEYUP ) - { - message = WM_KEYUP; - if( (InputKeyStateTable[VK_MENU] & 0x80) && ( - (VKey == VK_MENU) || (VKey == VK_CONTROL) || - !(InputKeyStateTable[VK_CONTROL] & 0x80))) { - if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */ - (VKey != VK_MENU)) /* <ALT>-down...<something else>-up */ - message = WM_SYSKEYUP; - TrackSysKey = 0; - } - InputKeyStateTable[VKey] &= ~0x80; - flags |= KF_REPEAT | KF_UP; - } - else - { - if (InputKeyStateTable[VKey] & 0x80) flags |= KF_REPEAT; - if (!(InputKeyStateTable[VKey] & 0x80)) InputKeyStateTable[VKey] ^= 0x01; - InputKeyStateTable[VKey] |= 0x80; - AsyncKeyStateTable[VKey] |= 0x80; - - message = WM_KEYDOWN; - if( (InputKeyStateTable[VK_MENU] & 0x80) && - !(InputKeyStateTable[VK_CONTROL] & 0x80)) { - message = WM_SYSKEYDOWN; - TrackSysKey = VKey; - } - } - - if (InputKeyStateTable[VK_MENU] & 0x80) flags |= KF_ALTDOWN; - - if( plParam) *plParam = MAKELPARAM( 1, flags ); - if( pwParam) *pwParam = VKey; - return message; -} - -/****************************** end copy input.c ****************************/ - -/* - * . prepare the keyevents for SendInputs - * . calculate the "expected" messages - * . Send the events to our window - * . retrieve the messages from the input queue - * . verify - */ -static BOOL do_test( HWND hwnd, int seqnr, const KEV td[] ) -{ - INPUT inputs[MAXKEYEVENTS]; - KMSG expmsg[MAXKEYEVENTS]; - MSG msg; - char buf[100]; - UINT evtctr=0, ret; - int kmctr, i; - - buf[0]='\0'; - TrackSysKey=0; /* see input.c */ - for (i = 0; i < MAXKEYEVENTS; i++) - { - inputs[evtctr].type = INPUT_KEYBOARD; - inputs[evtctr].ki.wVk = GETVKEY[td[i]]; - inputs[evtctr].ki.wScan = GETSCAN[td[i]]; - inputs[evtctr].ki.dwFlags = GETFLAGS[td[i]]; - inputs[evtctr].ki.dwExtraInfo = 0; - inputs[evtctr].ki.time = ++timetag; - if (td[i]) evtctr++; - - strcat(buf, getdesc[td[i]]); - if(td[i]) - expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam)); - else - expmsg[i].message = 0; - } - for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++) - ; - ok( evtctr <= MAXKEYEVENTS, "evtctr is above MAXKEYEVENTS\n" ); - ret = SendInput(evtctr, inputs, sizeof(INPUT)); - ok(ret == evtctr, "SendInput failed to send some events\n"); - i = 0; - if (winetest_debug > 1) - trace("======== key stroke sequence #%d: %s =============\n", - seqnr + 1, buf); - while( PeekMessageA(&msg,hwnd,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE) ) { - if (winetest_debug > 1) - trace("message[%d] %-15s wParam %04Ix lParam %08Ix time %lx\n", i, - MSGNAME[msg.message - WM_KEYFIRST], msg.wParam, msg.lParam, msg.time); - if( i < kmctr ) { - ok( msg.message == expmsg[i].message && - msg.wParam == expmsg[i].wParam && - msg.lParam == expmsg[i].lParam, - "%u/%u: wrong message %x/%08Ix/%08Ix expected %s/%08Ix/%08Ix\n", - seqnr, i, msg.message, msg.wParam, msg.lParam, - MSGNAME[(expmsg[i]).message - WM_KEYFIRST], expmsg[i].wParam, expmsg[i].lParam ); - } - i++; - } - if (winetest_debug > 1) - trace("%d messages retrieved\n", i); - if (!i && kmctr) - { - skip( "simulated keyboard input doesn't work\n" ); - return FALSE; - } - ok( i == kmctr, "message count is wrong: got %d expected: %d\n", i, kmctr); - return TRUE; -} - -/* test all combinations of the specified key events */ -static BOOL TestASet( HWND hWnd, int nrkev, const KEV kevdwn[], const KEV kevup[] ) -{ - int i,j,k,l,m,n; - static int count=0; - KEV kbuf[MAXKEYEVENTS]; - BOOL us_kbd = (GetKeyboardLayout(0) == (HKL)(ULONG_PTR)0x04090409); - if (!us_kbd) - { - skip( "skipping test with inconsistent results on non-us keyboard\n" ); - return TRUE; - } - - assert( nrkev==2 || nrkev==3); - for(i=0;i<MAXKEYEVENTS;i++) kbuf[i]=0; - /* two keys involved gives 4 test cases */ - if(nrkev==2) { - for(i=0;i<nrkev;i++) { - for(j=0;j<nrkev;j++) { - kbuf[0] = kevdwn[i]; - kbuf[1] = kevdwn[1-i]; - kbuf[2] = kevup[j]; - kbuf[3] = kevup[1-j]; - if (!do_test( hWnd, count++, kbuf)) return FALSE; - } - } - } - /* three keys involved gives 36 test cases */ - if(nrkev==3){ - for(i=0;i<nrkev;i++){ - for(j=0;j<nrkev;j++){ - if(j==i) continue; - for(k=0;k<nrkev;k++){ - if(k==i || k==j) continue; - for(l=0;l<nrkev;l++){ - for(m=0;m<nrkev;m++){ - if(m==l) continue; - for(n=0;n<nrkev;n++){ - if(n==l ||n==m) continue; - kbuf[0] = kevdwn[i]; - kbuf[1] = kevdwn[j]; - kbuf[2] = kevdwn[k]; - kbuf[3] = kevup[l]; - kbuf[4] = kevup[m]; - kbuf[5] = kevup[n]; - if (!do_test( hWnd, count++, kbuf)) return FALSE; - } - } - } - } - } - } - } - return TRUE; -} - -/* test each set specified in the global testkeyset array */ -static void TestSysKeys( HWND hWnd) -{ - int i; - for(i=0; testkeyset[i].nrkev;i++) - if (!TestASet( hWnd, testkeyset[i].nrkev, testkeyset[i].keydwn, testkeyset[i].keyup)) break; -} - -static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam ) -{ - return DefWindowProcA( hWnd, msg, wParam, lParam ); -} - -static void test_Input_whitebox(void) -{ - MSG msg; - WNDCLASSA wclass; - HANDLE hInstance = GetModuleHandleA( NULL ); - - wclass.lpszClassName = "InputSysKeyTestClass"; - wclass.style = CS_HREDRAW | CS_VREDRAW; - wclass.lpfnWndProc = WndProc; - wclass.hInstance = hInstance; - wclass.hIcon = LoadIconA( 0, (LPCSTR)IDI_APPLICATION ); - wclass.hCursor = LoadCursorA( NULL, (LPCSTR)IDC_ARROW ); - wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 ); - wclass.lpszMenuName = 0; - wclass.cbClsExtra = 0; - wclass.cbWndExtra = 0; - RegisterClassA( &wclass ); - /* create the test window that will receive the keystrokes */ - hWndTest = CreateWindowA( wclass.lpszClassName, "InputSysKeyTest", - WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100, - NULL, NULL, hInstance, NULL); - assert( hWndTest ); - ShowWindow( hWndTest, SW_SHOW); - SetWindowPos( hWndTest, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); - SetForegroundWindow( hWndTest ); - UpdateWindow( hWndTest); - - /* flush pending messages */ - while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); - - SetFocus( hWndTest ); - TestSysKeys( hWndTest ); - DestroyWindow(hWndTest); -} - static inline BOOL is_keyboard_message( UINT message ) { return (message >= WM_KEYFIRST && message <= WM_KEYLAST); @@ -545,558 +483,456 @@ static void empty_message_queue(void) } }
-struct transition_s { - WORD wVk; - BYTE before_state; - BYTE optional; +struct send_input_test +{ + WORD scan; + WORD vkey; + DWORD flags; + struct user_call expect[8]; + BYTE expect_state[256]; + BOOL todo_state[256]; };
-typedef enum { - sent=0x1, - posted=0x2, - parent=0x4, - wparam=0x8, - lparam=0x10, - defwinproc=0x20, - beginpaint=0x40, - optional=0x80, - hook=0x100, - winevent_hook=0x200 -} msg_flags_t; - -struct message { - UINT message; /* the WM_* code */ - msg_flags_t flags; /* message props */ - WPARAM wParam; /* expected value of wParam */ - LPARAM lParam; /* expected value of lParam */ -}; +static LRESULT CALLBACK ll_hook_kbd_proc(int code, WPARAM wparam, LPARAM lparam) +{ + KBDLLHOOKSTRUCT *hook_info = (KBDLLHOOKSTRUCT *)lparam;
-static const struct sendinput_test_s { - WORD wVk; - DWORD dwFlags; - BOOL _todo_wine; - struct transition_s expected_transitions[MAXKEYEVENTS+1]; - struct message expected_messages[MAXKEYMESSAGES+1]; -} sendinput_test[] = { - /* test ALT+F */ - /* 0 */ - {VK_LMENU, 0, FALSE, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}}, - {{WM_SYSKEYDOWN, hook|wparam, VK_LMENU}, {WM_SYSKEYDOWN}, {0}}}, - {'F', 0, FALSE, {{'F', 0x00}, {0}}, - {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN}, - {WM_SYSCHAR}, - {WM_SYSCOMMAND}, {0}}}, - {'F', KEYEVENTF_KEYUP, FALSE, {{'F', 0x80}, {0}}, - {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}}, - {VK_LMENU, KEYEVENTF_KEYUP, FALSE, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}}, - {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, - - /* test CTRL+O */ - /* 4 */ - {VK_LCONTROL, 0, FALSE, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}}, - {'O', 0, FALSE, {{'O', 0x00}, {0}}, - {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}}, - {'O', KEYEVENTF_KEYUP, FALSE, {{'O', 0x80}, {0}}, - {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, - {VK_LCONTROL, KEYEVENTF_KEYUP, FALSE, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, - - /* test ALT+CTRL+X */ - /* 8 */ - {VK_LMENU, 0, FALSE, {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}}, - {{WM_SYSKEYDOWN, hook}, {WM_SYSKEYDOWN}, {0}}}, - {VK_LCONTROL, 0, FALSE, {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}}, - {'X', 0, FALSE, {{'X', 0x00}, {0}}, - {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}}, - {'X', KEYEVENTF_KEYUP, FALSE, {{'X', 0x80}, {0}}, - {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, - {VK_LCONTROL, KEYEVENTF_KEYUP, FALSE, {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}}, - {{WM_SYSKEYUP, hook}, {WM_SYSKEYUP}, {0}}}, - {VK_LMENU, KEYEVENTF_KEYUP, FALSE, {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}}, - {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, - - /* test SHIFT+A */ - /* 14 */ - {VK_LSHIFT, 0, FALSE, {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {0}}}, - {'A', 0, FALSE, {{'A', 0x00}, {0}}, - {{WM_KEYDOWN, hook}, {WM_KEYDOWN}, {WM_CHAR}, {0}}}, - {'A', KEYEVENTF_KEYUP, FALSE, {{'A', 0x80}, {0}}, - {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, - {VK_LSHIFT, KEYEVENTF_KEYUP, FALSE, {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook}, {WM_KEYUP}, {0}}}, - /* test L-SHIFT & R-SHIFT: */ - /* RSHIFT == LSHIFT */ - /* 18 */ - {VK_RSHIFT, 0, FALSE, - /* recent windows versions (>= w2k3) correctly report an RSHIFT transition */ - {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00, TRUE}, {VK_RSHIFT, 0x00, TRUE}, {0}}, - {{WM_KEYDOWN, hook|wparam, VK_RSHIFT}, - {WM_KEYDOWN}, {0}}}, - {VK_RSHIFT, KEYEVENTF_KEYUP, FALSE, - {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80, TRUE}, {VK_RSHIFT, 0x80, TRUE}, {0}}, - {{WM_KEYUP, hook, hook|wparam, VK_RSHIFT}, - {WM_KEYUP}, {0}}}, - - /* LSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */ - /* 20 */ - {VK_LSHIFT, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, - {VK_LSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_LSHIFT, LLKHF_UP|LLKHF_EXTENDED}, - {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, - /* RSHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */ - /* 22 */ - {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, - {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED}, - {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, - - /* Note about wparam for hook with generic key (VK_SHIFT, VK_CONTROL, VK_MENU): - win2k - sends to hook whatever we generated here - winXP+ - Attempts to convert key to L/R key but not always correct - */ - /* SHIFT == LSHIFT */ - /* 24 */ - {VK_SHIFT, 0, FALSE, - {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook/* |wparam */|lparam, VK_SHIFT, 0}, - {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, - {VK_SHIFT, KEYEVENTF_KEYUP, FALSE, - {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP}, - {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, - /* SHIFT | KEYEVENTF_EXTENDEDKEY == RSHIFT */ - /* 26 */ - {VK_SHIFT, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_SHIFT, 0x00}, {VK_RSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, - {VK_SHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_SHIFT, 0x80}, {VK_RSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook/*|wparam*/|lparam, VK_SHIFT, LLKHF_UP|LLKHF_EXTENDED}, - {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, - - /* test L-CONTROL & R-CONTROL: */ - /* RCONTROL == LCONTROL */ - /* 28 */ - {VK_RCONTROL, 0, FALSE, - {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam, VK_RCONTROL}, - {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}}, - {VK_RCONTROL, KEYEVENTF_KEYUP, FALSE, - {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam, VK_RCONTROL}, - {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}}, - /* LCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */ - /* 30 */ - {VK_LCONTROL, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_LCONTROL, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}}, - {VK_LCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_LCONTROL, LLKHF_UP|LLKHF_EXTENDED}, - {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}}, - /* RCONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */ - /* 32 */ - {VK_RCONTROL, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_RCONTROL, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}}, - {VK_RCONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_RCONTROL, LLKHF_UP|LLKHF_EXTENDED}, - {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}}, - /* CONTROL == LCONTROL */ - /* 34 */ - {VK_CONTROL, 0, FALSE, - {{VK_CONTROL, 0x00}, {VK_LCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook/*|wparam, VK_CONTROL*/}, - {WM_KEYDOWN, wparam|lparam, VK_CONTROL, 0}, {0}}}, - {VK_CONTROL, KEYEVENTF_KEYUP, FALSE, - {{VK_CONTROL, 0x80}, {VK_LCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook/*|wparam, VK_CONTROL*/}, - {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP}, {0}}}, - /* CONTROL | KEYEVENTF_EXTENDEDKEY == RCONTROL */ - /* 36 */ - {VK_CONTROL, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_CONTROL, 0x00}, {VK_RCONTROL, 0x00}, {0}}, - {{WM_KEYDOWN, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam, VK_CONTROL, KF_EXTENDED}, {0}}}, - {VK_CONTROL, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_CONTROL, 0x80}, {VK_RCONTROL, 0x80}, {0}}, - {{WM_KEYUP, hook/*|wparam*/|lparam, VK_CONTROL, LLKHF_UP|LLKHF_EXTENDED}, - {WM_KEYUP, wparam|lparam, VK_CONTROL, KF_UP|KF_EXTENDED}, {0}}}, - - /* test L-MENU & R-MENU: */ - /* RMENU == LMENU */ - /* 38 */ - {VK_RMENU, 0, FALSE, - {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}}, - {{WM_SYSKEYDOWN, hook|wparam|optional, VK_LCONTROL}, - {WM_SYSKEYDOWN, hook|wparam, VK_RMENU}, - {WM_KEYDOWN, wparam|lparam|optional, VK_CONTROL, 0}, - {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}}, - {VK_RMENU, KEYEVENTF_KEYUP, TRUE, - {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}}, - {{WM_KEYUP, hook|wparam|optional, VK_LCONTROL}, - {WM_KEYUP, hook|wparam, VK_RMENU}, - {WM_SYSKEYUP, wparam|lparam|optional, VK_CONTROL, KF_UP}, - {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP}, - {WM_SYSCOMMAND, optional}, {0}}}, - /* LMENU | KEYEVENTF_EXTENDEDKEY == RMENU */ - /* 40 */ - {VK_LMENU, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {0}}, - {{WM_SYSKEYDOWN, hook|wparam|lparam, VK_LMENU, LLKHF_EXTENDED}, - {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}}, - {VK_LMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, TRUE, - {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_LMENU, LLKHF_UP|LLKHF_EXTENDED}, - {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED}, - {WM_SYSCOMMAND}, {0}}}, - /* RMENU | KEYEVENTF_EXTENDEDKEY == RMENU */ - /* 42 */ - {VK_RMENU, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}}, - {{WM_SYSKEYDOWN, hook|wparam|lparam|optional, VK_LCONTROL, 0}, - {WM_SYSKEYDOWN, hook|wparam|lparam, VK_RMENU, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam|optional, VK_CONTROL, 0}, - {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}}, - {VK_RMENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, TRUE, - {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}}, - {{WM_KEYUP, hook|wparam|lparam|optional, VK_LCONTROL, LLKHF_UP}, - {WM_KEYUP, hook|wparam|lparam, VK_RMENU, LLKHF_UP|LLKHF_EXTENDED}, - {WM_SYSKEYUP, wparam|lparam|optional, VK_CONTROL, KF_UP}, - {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED}, - {WM_SYSCOMMAND, optional}, {0}}}, - /* MENU == LMENU */ - /* 44 */ - {VK_MENU, 0, FALSE, - {{VK_MENU, 0x00}, {VK_LMENU, 0x00}, {0}}, - {{WM_SYSKEYDOWN, hook/*|wparam, VK_MENU*/}, - {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, 0}, {0}}}, - {VK_MENU, KEYEVENTF_KEYUP, TRUE, - {{VK_MENU, 0x80}, {VK_LMENU, 0x80}, {0}}, - {{WM_KEYUP, hook/*|wparam, VK_MENU*/}, - {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP}, - {WM_SYSCOMMAND}, {0}}}, - /* MENU | KEYEVENTF_EXTENDEDKEY == RMENU */ - /* 46 */ - {VK_MENU, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_MENU, 0x00}, {VK_RMENU, 0x00}, {VK_CONTROL, 0x00, 1}, {VK_LCONTROL, 0x01, 1}, {0}}, - {{WM_SYSKEYDOWN, hook|wparam|lparam|optional, VK_CONTROL, 0}, - {WM_SYSKEYDOWN, hook/*|wparam*/|lparam, VK_MENU, LLKHF_EXTENDED}, - {WM_SYSKEYDOWN, wparam|lparam, VK_MENU, KF_EXTENDED}, {0}}}, - {VK_MENU, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, TRUE, - {{VK_MENU, 0x80}, {VK_RMENU, 0x80}, {VK_CONTROL, 0x81, 1}, {VK_LCONTROL, 0x80, 1}, {0}}, - {{WM_KEYUP, hook|wparam|lparam|optional, VK_CONTROL, LLKHF_UP}, - {WM_KEYUP, hook/*|wparam*/|lparam, VK_MENU, LLKHF_UP|LLKHF_EXTENDED}, - {WM_SYSKEYUP, wparam|lparam, VK_MENU, KF_UP|KF_EXTENDED}, - {WM_SYSCOMMAND}, {0}}}, - - /* test LSHIFT & RSHIFT */ - /* 48 */ - {VK_LSHIFT, 0, FALSE, - {{VK_SHIFT, 0x00}, {VK_LSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_LSHIFT, 0}, - {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, - {VK_RSHIFT, KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_RSHIFT, 0x00}, {0}}, - {{WM_KEYDOWN, hook|wparam|lparam, VK_RSHIFT, LLKHF_EXTENDED}, - {WM_KEYDOWN, wparam|lparam, VK_SHIFT, 0}, {0}}}, - {VK_RSHIFT, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, FALSE, - {{VK_RSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam|lparam, VK_RSHIFT, LLKHF_UP|LLKHF_EXTENDED}, - {WM_KEYUP, optional}, {0}}}, - {VK_LSHIFT, KEYEVENTF_KEYUP, FALSE, - {{VK_SHIFT, 0x80}, {VK_LSHIFT, 0x80}, {0}}, - {{WM_KEYUP, hook|wparam, VK_LSHIFT}, - {WM_KEYUP, wparam|lparam, VK_SHIFT, KF_UP}, {0}}}, - - {0, 0, FALSE, {{0}}, {{0}}} /* end */ -}; + if (code == HC_ACTION) + { + append_ll_hook_kbd( wparam, hook_info );
-static struct message sent_messages[MAXKEYMESSAGES]; -static UINT sent_messages_cnt; +if(0) /* For some reason not stable on Wine */ +{ + if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN) + ok(!(GetAsyncKeyState(hook_info->vkCode) & 0x8000), "key %lx should be up\n", hook_info->vkCode); + else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP) + ok(GetAsyncKeyState(hook_info->vkCode) & 0x8000, "key %lx should be down\n", hook_info->vkCode); +}
-/* Verify that only specified key state transitions occur */ -static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, - const struct sendinput_test_s *test, BOOL foreground) + if (winetest_debug > 1) + trace("Hook: w=%Ix vk:%8lx sc:%8lx fl:%8lx %Ix\n", wparam, + hook_info->vkCode, hook_info->scanCode, hook_info->flags, hook_info->dwExtraInfo); + } + return CallNextHookEx( 0, code, wparam, lparam ); +} + +#define check_keyboard_state( a, b ) check_keyboard_state_( __LINE__, a, b ) +static void check_keyboard_state_( int line, const BYTE expect_state[256], const BOOL todo_state[256] ) { - int i, failcount = 0; - const struct transition_s *t = test->expected_transitions; - UINT actual_cnt = 0; - const struct message *expected = test->expected_messages; - - while (t->wVk && foreground) { - /* We won't receive any information from GetKeyboardState() if we're - * not the foreground window. */ - BOOL matched = ((ks1[t->wVk]&0x80) == (t->before_state&0x80) - && (ks2[t->wVk]&0x80) == (~t->before_state&0x80)); - - if (!matched && !t->optional && test->_todo_wine) - { - failcount++; - todo_wine { - ok(matched, "%2d (%x/%lx): %02x from %02x -> %02x " - "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags, - t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state, - ~t->before_state&0x80); - } - } else { - ok(matched || t->optional, "%2d (%x/%lx): %02x from %02x -> %02x " - "instead of %02x -> %02x\n", id, test->wVk, test->dwFlags, - t->wVk, ks1[t->wVk]&0x80, ks2[t->wVk]&0x80, t->before_state, - ~t->before_state&0x80); - } - ks2[t->wVk] = ks1[t->wVk]; /* clear the match */ - t++; + BYTE state[256]; + UINT i; + + ok_ret( 1, GetKeyboardState( state ) ); + for (i = 0; i < ARRAY_SIZE(state); i++) + { + todo_wine_if( todo_state[i] ) + ok_(__FILE__, line)( (expect_state[i] & 0x80) == (state[i] & 0x80), + "got %s: %#x\n", debugstr_vk( i ), state[i] ); } - for (i = 0; i < 256; i++) - if (ks2[i] != ks1[i] && test->_todo_wine) - { - failcount++; - todo_wine - ok(FALSE, "%2d (%x/%lx): %02x from %02x -> %02x unexpected\n", - id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]); - } - else - ok(ks2[i] == ks1[i], "%2d (%x/%lx): %02x from %02x -> %02x unexpected\n", - id, test->wVk, test->dwFlags, i, ks1[i], ks2[i]); +}
- while (expected->message && actual_cnt < sent_messages_cnt) +#define check_send_input_test( a, b ) check_send_input_test_( a, #a, b ) +static void check_send_input_test_( const struct send_input_test *test, const char *context, BOOL peeked ) +{ + static BYTE empty_state[256] = {0}; + INPUT input = {.type = INPUT_KEYBOARD}; + UINT i; + + winetest_push_context( "%s", context ); + SetKeyboardState( empty_state ); + + for (i = 0; test->vkey || test->scan; i++, test++) { - const struct message *actual = &sent_messages[actual_cnt]; + winetest_push_context( "%u", i ); + + input.ki.wScan = test->flags & KEYEVENTF_SCANCODE ? test->scan : i + 1; + input.ki.dwFlags = test->flags; + input.ki.wVk = test->vkey; + ok_ret( 1, SendInput( 1, &input, sizeof(input) ) ); + wait_messages( 5, peeked ); + + ok_seq( test->expect ); + check_keyboard_state( test->expect_state, test->todo_state ); + + winetest_pop_context(); + } + + SetKeyboardState( empty_state ); + winetest_pop_context(); +}
- if (expected->message == actual->message) +static BOOL test_send_input_accept_message( UINT msg ) +{ + return is_keyboard_message( msg ) || msg == WM_SYSCOMMAND; +} + +static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, WCHAR wch_shift, WCHAR wch_control ) +{ +#define WIN_MSG(m, w, l, ...) {.func = MSG_TEST_WIN, .message = {.msg = m, .wparam = w, .lparam = l}, ## __VA_ARGS__} +#define KBD_HOOK(m, s, v, f, ...) {.func = LL_HOOK_KEYBD, .ll_hook_kbd = {.msg = m, .scan = s, .vkey = v, .flags = f}, ## __VA_ARGS__} + +#define KEY_HOOK_(m, s, v, f, ...) KBD_HOOK( m, s, v, LLKHF_INJECTED | (m == WM_KEYUP || m == WM_SYSKEYUP ? LLKHF_UP : 0) | (f), ## __VA_ARGS__ ) +#define KEY_HOOK(m, s, v, ...) KEY_HOOK_( m, s, v, 0, ## __VA_ARGS__ ) + +#define KEY_MSG_(m, s, v, f, ...) WIN_MSG( m, v, MAKELONG(1, (s) | (m == WM_KEYUP || m == WM_SYSKEYUP ? (KF_UP | KF_REPEAT) : 0) | (f)), ## __VA_ARGS__ ) +#define KEY_MSG(m, s, v, ...) KEY_MSG_( m, s, v, 0, ## __VA_ARGS__ ) + + struct send_input_test lmenu_vkey[] = + { + {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}}, { - if (expected->flags & wparam) + .vkey = vkey, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, /*[vkey] = 0x80*/}, + .expect = { - if ((expected->flags & optional) && (expected->wParam != actual->wParam)) - { - expected++; - continue; - } - if (expected->wParam != actual->wParam && test->_todo_wine) - { - failcount++; - todo_wine - ok(FALSE, "%2d (%x/%lx): in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n", - id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam); - } - else - ok(expected->wParam == actual->wParam, - "%2d (%x/%lx): in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n", - id, test->wVk, test->dwFlags, expected->message, expected->wParam, actual->wParam); + KEY_HOOK_(WM_SYSKEYDOWN, 2, vkey, LLKHF_ALTDOWN, .todo_value = TRUE), + KEY_MSG_(WM_SYSKEYDOWN, 2, vkey, KF_ALTDOWN), + WIN_MSG(WM_SYSCHAR, wch, MAKELONG(1, 2|KF_ALTDOWN)), + WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, wch), + {0} } - if (expected->flags & lparam) - { - if (expected->lParam != actual->lParam && test->_todo_wine) - { - failcount++; - todo_wine - ok(FALSE, "%2d (%x/%lx): in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n", - id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam); - } - else - ok(expected->lParam == actual->lParam, - "%2d (%x/%lx): in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n", - id, test->wVk, test->dwFlags, expected->message, expected->lParam, actual->lParam); - } - ok((expected->flags & hook) == (actual->flags & hook), - "%2d (%x/%lx): the msg 0x%04x should have been sent by a hook\n", - id, test->wVk, test->dwFlags, expected->message); + }, + {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYUP, 3, vkey, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 3, vkey, KF_ALTDOWN), {0}}}, + {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LMENU), KEY_MSG(WM_KEYUP, 4, VK_MENU), {0}}}, + {0}, + };
- } - else if (expected->flags & optional) - { - expected++; - continue; - } - else if (!(expected->flags & hook) && !foreground) - { - /* If we weren't able to receive foreground status, we won't get - * any window messages. */ - expected++; - continue; - } - /* NT4 doesn't send SYSKEYDOWN/UP to hooks, only KEYDOWN/UP */ - else if ((expected->flags & hook) && - (expected->message == WM_SYSKEYDOWN || expected->message == WM_SYSKEYUP) && - (actual->message == expected->message - 4)) - { - ok((expected->flags & hook) == (actual->flags & hook), - "%2d (%x/%lx): the msg 0x%04x should have been sent by a hook\n", - id, test->wVk, test->dwFlags, expected->message); - } - /* For VK_RMENU, at least localized Win2k/XP sends KEYDOWN/UP - * instead of SYSKEYDOWN/UP to the WNDPROC */ - else if (test->wVk == VK_RMENU && !(expected->flags & hook) && - (expected->message == WM_SYSKEYDOWN || expected->message == WM_SYSKEYUP) && - (actual->message == expected->message - 4)) - { - ok(expected->wParam == actual->wParam && expected->lParam == actual->lParam, - "%2d (%x/%lx): the msg 0x%04x was expected, but got msg 0x%04x instead\n", - id, test->wVk, test->dwFlags, expected->message, actual->message); - } - else if (test->_todo_wine) + struct send_input_test lmenu_vkey_peeked[] = + { + {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}}, { - failcount++; - todo_wine - ok(FALSE, - "%2d (%x/%lx): the msg 0x%04x was expected, but got msg 0x%04x instead\n", - id, test->wVk, test->dwFlags, expected->message, actual->message); - } - else - ok(FALSE, - "%2d (%x/%lx): the msg 0x%04x was expected, but got msg 0x%04x instead\n", - id, test->wVk, test->dwFlags, expected->message, actual->message); - - actual_cnt++; - expected++; - } - /* skip all optional trailing messages */ - while (expected->message && ((expected->flags & optional) || (!(expected->flags & hook) && !foreground))) - expected++; + .vkey = vkey, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, /*[vkey] = 0x80*/}, + .expect = + { + KEY_HOOK_(WM_SYSKEYDOWN, 2, vkey, LLKHF_ALTDOWN, .todo_value = TRUE), + KEY_MSG_(WM_SYSKEYDOWN, 2, vkey, KF_ALTDOWN), + WIN_MSG(WM_SYSCHAR, wch, MAKELONG(1, 2|KF_ALTDOWN)), + {0} + } + }, + {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYUP, 3, vkey, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 3, vkey, KF_ALTDOWN), {0}}}, + {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LMENU), KEY_MSG(WM_KEYUP, 4, VK_MENU), {0}}}, + {0}, + };
+ struct send_input_test lcontrol_vkey[] = + { + {.vkey = VK_LCONTROL, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LCONTROL), KEY_MSG(WM_KEYDOWN, 1, VK_CONTROL), {0}}}, + {.vkey = vkey, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80, /*[vkey] = 0x80*/}, + .expect = {KEY_HOOK(WM_KEYDOWN, 2, vkey), KEY_MSG(WM_KEYDOWN, 2, vkey), WIN_MSG(WM_CHAR, wch_control, MAKELONG(1, 2)), {0}}}, + {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = {KEY_HOOK(WM_KEYUP, 3, vkey), KEY_MSG(WM_KEYUP, 3, vkey), {0}}}, + {.vkey = VK_LCONTROL, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LCONTROL), KEY_MSG(WM_KEYUP, 4, VK_CONTROL), {0}}}, + {0}, + };
- if (expected->message || actual_cnt < sent_messages_cnt) + struct send_input_test lmenu_lcontrol_vkey[] = { - if (test->_todo_wine) - { - failcount++; - todo_wine - ok(FALSE, "%2d (%x/%lx): the msg sequence is not complete: expected %04x - actual %04x\n", - id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message); - } - else - ok(FALSE, "%2d (%x/%lx): the msg sequence is not complete: expected %04x - actual %04x\n", - id, test->wVk, test->dwFlags, expected->message, sent_messages[actual_cnt].message); - } + {.vkey = VK_LMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}}, + {.vkey = VK_LCONTROL, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = {KEY_HOOK(WM_KEYDOWN, 2, VK_LCONTROL), KEY_MSG_(WM_KEYDOWN, 2, VK_CONTROL, KF_ALTDOWN), {0}}}, + {.vkey = vkey, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80, /*[vkey] = 0x80*/}, + .expect = {KEY_HOOK(WM_KEYDOWN, 3, vkey), KEY_MSG_(WM_KEYDOWN, 3, vkey, KF_ALTDOWN), {0}}}, + {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = {KEY_HOOK(WM_KEYUP, 4, vkey), KEY_MSG_(WM_KEYUP, 4, vkey, KF_ALTDOWN), {0}}}, + {.vkey = VK_LCONTROL, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYUP, 5, VK_LCONTROL, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 5, VK_CONTROL, KF_ALTDOWN), {0}}}, + {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 6, VK_LMENU), KEY_MSG(WM_KEYUP, 6, VK_MENU), {0}}}, + {0}, + };
- if( test->_todo_wine && !failcount) /* succeeded yet marked todo */ - todo_wine - ok(TRUE, "%2d (%x/%lx): marked "todo_wine" but succeeds\n", id, test->wVk, test->dwFlags); + struct send_input_test shift_vkey[] = + { + {.vkey = VK_LSHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, + .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LSHIFT), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}}, + {.vkey = vkey, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80, /*[vkey] = 0x80*/}, + .expect = {KEY_HOOK(WM_KEYDOWN, 2, vkey), KEY_MSG(WM_KEYDOWN, 2, vkey), WIN_MSG(WM_CHAR, wch_shift, MAKELONG(1, 2)), {0}}}, + {.vkey = vkey, .flags = KEYEVENTF_KEYUP, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, + .expect = {KEY_HOOK(WM_KEYUP, 3, vkey), KEY_MSG(WM_KEYUP, 3, vkey), {0}}}, + {.vkey = VK_LSHIFT, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LSHIFT), KEY_MSG(WM_KEYUP, 4, VK_SHIFT), {0}}}, + {0}, + };
- sent_messages_cnt = 0; -} + static const struct send_input_test rshift[] = + { + {.vkey = VK_RSHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80}, .todo_state = {[VK_RSHIFT] = TRUE, [VK_LSHIFT] = TRUE}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_RSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}}, + {.vkey = VK_RSHIFT, .flags = KEYEVENTF_KEYUP, .expect_state = {0}, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}}, + {0}, + }; + static const struct send_input_test lshift_ext[] = + { + {.vkey = VK_LSHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_LSHIFT, LLKHF_EXTENDED), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}}, + {.vkey = VK_LSHIFT, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LSHIFT, LLKHF_EXTENDED), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}}, + {0}, + }; + static const struct send_input_test rshift_ext[] = + { + {.vkey = VK_RSHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_RSHIFT, LLKHF_EXTENDED), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}}, + {.vkey = VK_RSHIFT, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, .expect_state = {0}, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RSHIFT, LLKHF_EXTENDED), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}}, + {0}, + }; + static const struct send_input_test shift[] = + { + {.vkey = VK_SHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, + .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LSHIFT, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}}, + {.vkey = VK_SHIFT, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LSHIFT, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}}, + {0}, + }; + static const struct send_input_test shift_ext[] = + { + {.vkey = VK_SHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_RSHIFT] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_LSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}}, + {.vkey = VK_SHIFT, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LSHIFT, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 2, VK_SHIFT), {0}}}, + {0}, + };
-/* WndProc2 checks that we get at least the messages specified */ -static LRESULT CALLBACK WndProc2(HWND hWnd, UINT Msg, WPARAM wParam, - LPARAM lParam) -{ - if (winetest_debug > 1) trace("MSG: %8x W:%8Ix L:%8Ix\n", Msg, wParam, lParam); + static const struct send_input_test rcontrol[] = + { + {.vkey = VK_RCONTROL, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_RCONTROL), KEY_MSG(WM_KEYDOWN, 1, VK_CONTROL), {0}}}, + {.vkey = VK_RCONTROL, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 2, VK_RCONTROL), KEY_MSG(WM_KEYUP, 2, VK_CONTROL), {0}}}, + {0}, + }; + static const struct send_input_test lcontrol_ext[] = + { + {.vkey = VK_LCONTROL, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_CONTROL] = 0x80, [VK_RCONTROL] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_LCONTROL, LLKHF_EXTENDED), KEY_MSG_(WM_KEYDOWN, 1, VK_CONTROL, KF_EXTENDED), {0}}}, + {.vkey = VK_LCONTROL, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LCONTROL, LLKHF_EXTENDED), KEY_MSG_(WM_KEYUP, 2, VK_CONTROL, KF_EXTENDED), {0}}}, + {0}, + }; + static const struct send_input_test rcontrol_ext[] = + { + {.vkey = VK_RCONTROL, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_CONTROL] = 0x80, [VK_RCONTROL] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_RCONTROL, LLKHF_EXTENDED), KEY_MSG_(WM_KEYDOWN, 1, VK_CONTROL, KF_EXTENDED), {0}}}, + {.vkey = VK_RCONTROL, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RCONTROL, LLKHF_EXTENDED), KEY_MSG_(WM_KEYUP, 2, VK_CONTROL, KF_EXTENDED), {0}}}, + {0}, + }; + static const struct send_input_test control[] = + { + {.vkey = VK_CONTROL, .expect_state = {[VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LCONTROL, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 1, VK_CONTROL), {0}}}, + {.vkey = VK_CONTROL, .flags = KEYEVENTF_KEYUP, .expect_state = {0}, + .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LCONTROL, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 2, VK_CONTROL), {0}}}, + {0}, + }; + static const struct send_input_test control_ext[] = + { + {.vkey = VK_CONTROL, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_CONTROL] = 0x80, [VK_RCONTROL] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 1, VK_RCONTROL, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_KEYDOWN, 1, VK_CONTROL, KF_EXTENDED), {0}}}, + {.vkey = VK_CONTROL, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RCONTROL, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_KEYUP, 2, VK_CONTROL, KF_EXTENDED), {0}}}, + {0}, + };
- if ((Msg >= WM_KEYFIRST && Msg <= WM_KEYLAST) || Msg == WM_SYSCOMMAND) + static const struct send_input_test rmenu[] = { - ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n"); - if (sent_messages_cnt < MAXKEYMESSAGES) - { - sent_messages[sent_messages_cnt].message = Msg; - sent_messages[sent_messages_cnt].flags = 0; - sent_messages[sent_messages_cnt].wParam = wParam; - sent_messages[sent_messages_cnt++].lParam = HIWORD(lParam) & (KF_UP|KF_EXTENDED); - } - } - return DefWindowProcA(hWnd, Msg, wParam, lParam); -} + {.vkey = VK_RMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}}, + {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 2, VK_RMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, 0), {0}}}, + {0}, + }; + static const struct send_input_test lmenu_ext[] = + { + {.vkey = VK_LMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), {0}}}, + {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, 0), {0}}}, + {0}, + }; + static const struct send_input_test rmenu_ext[] = + { + {.vkey = VK_RMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), {0}}}, + {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, 0), {0}}}, + {0}, + }; + static const struct send_input_test menu[] = + { + {.vkey = VK_MENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}}, + {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP, .expect_state = {0}, + .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, 0), {0}}}, + {0}, + }; + static const struct send_input_test menu_ext[] = + { + {.vkey = VK_MENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), {0}}}, + {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), WIN_MSG(WM_SYSCOMMAND, SC_KEYMENU, 0), {0}}}, + {0}, + };
-static LRESULT CALLBACK hook_proc(int code, WPARAM wparam, LPARAM lparam) -{ - KBDLLHOOKSTRUCT *hook_info = (KBDLLHOOKSTRUCT *)lparam; + static const struct send_input_test rmenu_peeked[] = + { + {.vkey = VK_RMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}}, + {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 2, VK_RMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), {0}}}, + {0}, + }; + static const struct send_input_test lmenu_ext_peeked[] = + { + {.vkey = VK_LMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), {0}}}, + {.vkey = VK_LMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_LMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), {0}}}, + {0}, + }; + static const struct send_input_test rmenu_ext_peeked[] = + { + {.vkey = VK_RMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), {0}}}, + {.vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), {0}}}, + {0}, + }; + static const struct send_input_test menu_peeked[] = + { + {.vkey = VK_MENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_LMENU, LLKHF_ALTDOWN, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN), {0}}}, + {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP, .expect_state = {0}, + .expect = {KEY_HOOK(WM_KEYUP, 2, VK_LMENU, .todo_value = TRUE), KEY_MSG(WM_SYSKEYUP, 2, VK_MENU), {0}}}, + {0}, + }; + static const struct send_input_test menu_ext_peeked[] = + { + {.vkey = VK_MENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80}, + .expect = {KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), {0}}}, + {.vkey = VK_MENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = {KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), KEY_MSG_(WM_SYSKEYUP, 2, VK_MENU, KF_EXTENDED), {0}}}, + {0}, + };
- if (code == HC_ACTION) + static const struct send_input_test lrshift_ext[] = { - ok(sent_messages_cnt < MAXKEYMESSAGES, "Too many messages\n"); - if (sent_messages_cnt < MAXKEYMESSAGES) - { - sent_messages[sent_messages_cnt].message = wparam; - sent_messages[sent_messages_cnt].flags = hook; - sent_messages[sent_messages_cnt].wParam = hook_info->vkCode; - sent_messages[sent_messages_cnt++].lParam = hook_info->flags & (LLKHF_UP|LLKHF_EXTENDED); - } + {.vkey = VK_LSHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, + .expect = {KEY_HOOK(WM_KEYDOWN, 1, VK_LSHIFT), KEY_MSG(WM_KEYDOWN, 1, VK_SHIFT), {0}}}, + {.vkey = VK_RSHIFT, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80, [VK_RSHIFT] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYDOWN, 2, VK_RSHIFT, LLKHF_EXTENDED), KEY_MSG_(WM_KEYDOWN, 2, VK_SHIFT, KF_REPEAT, .todo_value = TRUE), {0}}}, + {.vkey = VK_RSHIFT, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, + .expect = {KEY_HOOK_(WM_KEYUP, 3, VK_RSHIFT, LLKHF_EXTENDED), {0, .todo = TRUE}, {0}}}, + {.vkey = VK_LSHIFT, .flags = KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 4, VK_LSHIFT), KEY_MSG(WM_KEYUP, 4, VK_SHIFT), {0}}}, + {0}, + };
-if(0) /* For some reason not stable on Wine */ -{ - if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN) - ok(!(GetAsyncKeyState(hook_info->vkCode) & 0x8000), "key %lx should be up\n", hook_info->vkCode); - else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP) - ok(GetAsyncKeyState(hook_info->vkCode) & 0x8000, "key %lx should be down\n", hook_info->vkCode); -} +#undef WIN_MSG +#undef KBD_HOOK +#undef KEY_HOOK_ +#undef KEY_HOOK +#undef KEY_MSG_ +#undef KEY_MSG
- if (winetest_debug > 1) - trace("Hook: w=%Ix vk:%8lx sc:%8lx fl:%8lx %Ix\n", wparam, - hook_info->vkCode, hook_info->scanCode, hook_info->flags, hook_info->dwExtraInfo); - } - return CallNextHookEx( 0, code, wparam, lparam ); -} -static void test_Input_blackbox(void) -{ - INPUT i; - int ii; - BYTE ks1[256], ks2[256]; - LONG_PTR prevWndProc; - BOOL foreground; - HWND window; + LONG_PTR old_proc; HHOOK hook; + HWND hwnd;
if (GetKeyboardLayout(0) != (HKL)(ULONG_PTR)0x04090409) { skip("Skipping Input_blackbox test on non-US keyboard\n"); return; } - window = CreateWindowA("Static", NULL, WS_POPUP|WS_HSCROLL|WS_VSCROLL - |WS_VISIBLE, 0, 0, 200, 60, NULL, NULL, - NULL, NULL); - ok(window != NULL, "error: %d\n", (int) GetLastError()); - SetWindowPos( window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); - foreground = SetForegroundWindow( window ); - if (!foreground) - skip("Failed to set foreground window; some tests will be skipped.\n"); - - if (!(hook = SetWindowsHookExA(WH_KEYBOARD_LL, hook_proc, GetModuleHandleA( NULL ), 0))) - { - DestroyWindow(window); - win_skip("WH_KEYBOARD_LL is not supported\n"); - return; - } - - /* must process all initial messages, otherwise X11DRV_KeymapNotify unsets - * key state set by SendInput(). */ - empty_message_queue();
- prevWndProc = SetWindowLongPtrA(window, GWLP_WNDPROC, (LONG_PTR) WndProc2); - ok(prevWndProc != 0 || GetLastError() == 0, "error: %d\n", (int) GetLastError()); + hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL ); + ok_ne( NULL, hwnd, HWND, "%p" ); + wait_messages( 100, FALSE ); + + hook = SetWindowsHookExW( WH_KEYBOARD_LL, ll_hook_kbd_proc, GetModuleHandleW( NULL ), 0 ); + ok_ne( NULL, hook, HHOOK, "%p" ); + + p_accept_message = test_send_input_accept_message; + ok_seq( empty_sequence ); + + lmenu_vkey_peeked[1].expect_state[vkey] = 0x80; + lmenu_vkey[1].expect_state[vkey] = 0x80; + lcontrol_vkey[1].expect_state[vkey] = 0x80; + lmenu_lcontrol_vkey[2].expect_state[vkey] = 0x80; + shift_vkey[1].expect_state[vkey] = 0x80; + + /* test peeked messages */ + winetest_push_context( "peek" ); + check_send_input_test( lmenu_vkey_peeked, TRUE ); + check_send_input_test( lcontrol_vkey, TRUE ); + check_send_input_test( lmenu_lcontrol_vkey, TRUE ); + check_send_input_test( shift_vkey, TRUE ); + check_send_input_test( rshift, TRUE ); + check_send_input_test( lshift_ext, TRUE ); + check_send_input_test( rshift_ext, TRUE ); + check_send_input_test( shift, TRUE ); + check_send_input_test( shift_ext, TRUE ); + check_send_input_test( rcontrol, TRUE ); + check_send_input_test( lcontrol_ext, TRUE ); + check_send_input_test( rcontrol_ext, TRUE ); + check_send_input_test( control, TRUE ); + check_send_input_test( control_ext, TRUE ); + check_send_input_test( rmenu_peeked, TRUE ); + check_send_input_test( lmenu_ext_peeked, TRUE ); + check_send_input_test( rmenu_ext_peeked, TRUE ); + check_send_input_test( menu_peeked, TRUE ); + check_send_input_test( menu_ext_peeked, TRUE ); + check_send_input_test( lrshift_ext, TRUE ); + winetest_pop_context();
- i.type = INPUT_KEYBOARD; - i.ki.time = 0; - i.ki.dwExtraInfo = 0; + wait_messages( 100, FALSE ); + ok_seq( empty_sequence ); + + /* test received messages */ + old_proc = SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)append_message_wndproc ); + ok_ne( 0, old_proc, LONG_PTR, "%#Ix" ); + + winetest_push_context( "receive" ); + check_send_input_test( lmenu_vkey, FALSE ); + check_send_input_test( lcontrol_vkey, FALSE ); + check_send_input_test( lmenu_lcontrol_vkey, FALSE ); + check_send_input_test( shift_vkey, FALSE ); + check_send_input_test( rshift, FALSE ); + check_send_input_test( lshift_ext, FALSE ); + check_send_input_test( rshift_ext, FALSE ); + check_send_input_test( shift, FALSE ); + check_send_input_test( shift_ext, FALSE ); + check_send_input_test( rcontrol, FALSE ); + check_send_input_test( lcontrol_ext, FALSE ); + check_send_input_test( rcontrol_ext, FALSE ); + check_send_input_test( control, FALSE ); + check_send_input_test( control_ext, FALSE ); + check_send_input_test( rmenu, FALSE ); + check_send_input_test( lmenu_ext, FALSE ); + check_send_input_test( rmenu_ext, FALSE ); + check_send_input_test( menu, FALSE ); + check_send_input_test( menu_ext, FALSE ); + check_send_input_test( lrshift_ext, FALSE ); + winetest_pop_context();
- for (ii = 0; ii < ARRAY_SIZE(sendinput_test)-1; ii++) { - GetKeyboardState(ks1); - i.ki.wScan = ii+1 /* useful for debugging */; - i.ki.dwFlags = sendinput_test[ii].dwFlags; - i.ki.wVk = sendinput_test[ii].wVk; - SendInput(1, &i, sizeof(INPUT)); - empty_message_queue(); - GetKeyboardState(ks2); - compare_and_check(ii, ks1, ks2, &sendinput_test[ii], foreground); - } + ok_ret( 1, DestroyWindow( hwnd ) ); + ok_ret( 1, UnhookWindowsHookEx( hook ) );
- empty_message_queue(); - DestroyWindow(window); - UnhookWindowsHookEx(hook); + wait_messages( 100, FALSE ); + ok_seq( empty_sequence ); + p_accept_message = NULL; }
static void reset_key_status(WORD vk) @@ -4837,70 +4673,75 @@ static void test_UnregisterDeviceNotification(void) ok(ret == FALSE, "Unregistering NULL Device Notification returned: %d\n", ret); }
-static void test_SendInput(void) +static void test_SendInput( WORD vkey, WCHAR wch ) { + const struct user_call broken_sequence[] = + { + {.func = MSG_TEST_WIN, .message = {.msg = WM_KEYDOWN, .wparam = vkey, .lparam = MAKELONG(1, 0)}}, + {.func = MSG_TEST_WIN, .message = {.msg = WM_CHAR, .wparam = wch, .lparam = MAKELONG(1, 0)}}, + {.func = MSG_TEST_WIN, .message = {.msg = WM_KEYUP, .wparam = vkey, .lparam = MAKELONG(1, KF_UP | KF_REPEAT)}}, + {0} + }; + INPUT input[16]; UINT res, i; HWND hwnd; - MSG msg;
- hwnd = CreateWindowW( L"static", L"test", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, 0, 0 ); - ok( hwnd != 0, "CreateWindowW failed\n" ); - - ShowWindow( hwnd, SW_SHOWNORMAL ); - UpdateWindow( hwnd ); - SetForegroundWindow( hwnd ); - SetFocus( hwnd ); - empty_message_queue(); + hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL ); + ok_ne( NULL, hwnd, HWND, "%p" ); + wait_messages( 100, FALSE );
SetLastError( 0xdeadbeef ); - res = SendInput( 0, NULL, 0 ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 0, NULL, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 1, NULL, 0 ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 1, NULL, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 1, NULL, sizeof(*input) ); - ok( res == 0 && (GetLastError() == ERROR_NOACCESS || GetLastError() == ERROR_INVALID_PARAMETER), - "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 1, NULL, sizeof(*input) ) ); + ok( GetLastError() == ERROR_NOACCESS || GetLastError() == ERROR_INVALID_PARAMETER, + "GetLastError returned %#lx\n", GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 0, input, sizeof(*input) ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 0, input, sizeof(*input) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 0, NULL, sizeof(*input) ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 0, NULL, sizeof(*input) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
memset( input, 0, sizeof(input) ); SetLastError( 0xdeadbeef ); - res = SendInput( 1, input, sizeof(*input) ); - ok( res == 1 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 1, SendInput( 1, input, sizeof(*input) ) ); + ok_ret( 0xdeadbeef, GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 16, input, sizeof(*input) ); - ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 16, SendInput( 16, input, sizeof(*input) ) ); + ok_ret( 0xdeadbeef, GetLastError() );
SetLastError( 0xdeadbeef ); - res = SendInput( 1, input, 0 ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 1, input, 0 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 1, input, sizeof(*input) + 1 ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 1, input, sizeof(*input) + 1 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 1, input, sizeof(*input) - 1 ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 1, input, sizeof(*input) - 1 ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() );
for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_KEYBOARD; SetLastError( 0xdeadbeef ); - res = SendInput( 16, input, offsetof( INPUT, ki ) + sizeof(KEYBDINPUT) ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 16, input, offsetof( INPUT, ki ) + sizeof(KEYBDINPUT) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); SetLastError( 0xdeadbeef ); - res = SendInput( 16, input, sizeof(*input) ); - ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#lx\n", res, GetLastError() ); - empty_message_queue(); + ok_ret( 16, SendInput( 16, input, sizeof(*input) ) ); + ok_ret( 0xdeadbeef, GetLastError() );
for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE; SetLastError( 0xdeadbeef ); - res = SendInput( 16, input, offsetof( INPUT, hi ) + sizeof(HARDWAREINPUT) ); - ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#lx\n", res, GetLastError() ); + ok_ret( 0, SendInput( 16, input, offsetof( INPUT, hi ) + sizeof(HARDWAREINPUT) ) ); + ok_ret( ERROR_INVALID_PARAMETER, GetLastError() ); + + wait_messages( 100, FALSE ); + ok_seq( empty_sequence ); + p_accept_message = is_keyboard_message;
input[0].hi.uMsg = WM_KEYDOWN; input[0].hi.wParamL = 0; @@ -4913,38 +4754,37 @@ static void test_SendInput(void) ok( (res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) || broken(res == 16 && GetLastError() == 0xdeadbeef) /* 32bit */, "SendInput returned %u, error %#lx\n", res, GetLastError() ); - while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); - ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); - empty_message_queue(); + wait_messages( 100, TRUE ); + ok_seq( empty_sequence );
memset( input, 0, sizeof(input) ); input[0].type = INPUT_HARDWARE; input[1].type = INPUT_KEYBOARD; - input[1].ki.wVk = 'A'; + input[1].ki.wVk = vkey; input[1].ki.dwFlags = 0; input[2].type = INPUT_KEYBOARD; - input[2].ki.wVk = 'A'; + input[2].ki.wVk = vkey; input[2].ki.dwFlags = KEYEVENTF_KEYUP; SetLastError( 0xdeadbeef ); res = SendInput( 16, input, sizeof(*input) ); ok( (res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) || broken(res == 16 && GetLastError() == 0xdeadbeef), "SendInput returned %u, error %#lx\n", res, GetLastError() ); - while ((res = wait_for_message(&msg)) && (msg.message == WM_TIMER || broken(msg.message == WM_KEYDOWN || msg.message == WM_KEYUP))) - DispatchMessageA(&msg); - ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); - empty_message_queue(); + wait_messages( 100, TRUE ); + if (broken(res == 16)) ok_seq( broken_sequence ); + else ok_seq( empty_sequence );
for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE + 1; SetLastError( 0xdeadbeef ); - res = SendInput( 16, input, sizeof(*input) ); - ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#lx\n", res, GetLastError() ); - while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); - ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); - empty_message_queue(); + ok_ret( 16, SendInput( 16, input, sizeof(*input) ) ); + ok_ret( 0xdeadbeef, GetLastError() ); + wait_messages( 100, TRUE ); + ok_seq( empty_sequence );
- trace( "done\n" ); - DestroyWindow( hwnd ); + ok_ret( 1, DestroyWindow( hwnd ) ); + wait_messages( 100, FALSE ); + ok_seq( empty_sequence ); + p_accept_message = NULL; }
#define check_pointer_info( a, b ) check_pointer_info_( __LINE__, a, b ) @@ -5394,9 +5234,8 @@ static void test_input_desktop( char **argv )
ok_ret( 1, GetCursorPos( &pos ) );
- test_SendInput(); - test_Input_blackbox(); - test_Input_whitebox(); + test_SendInput( 'F', 'f' ); + test_SendInput_keyboard_messages( 'F', 0x21, 'f', 'F', '\x06' );
ok_ret( 1, SetCursorPos( pos.x, pos.y ) ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index c67b59b8abe..4da8022f361 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -840,6 +840,22 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W {0}, };
+ struct send_input_test rshift_scan[] = + { + {.scan = 0x36, .flags = KEYEVENTF_SCANCODE, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, + .todo_state = {[0] = TRUE, [VK_SHIFT] = TRUE, [VK_LSHIFT] = TRUE}, + .expect = {KEY_HOOK(WM_KEYDOWN, 0x36, VK_RSHIFT, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, 0x36, VK_SHIFT, .todo_value = TRUE), {0}}}, + {.scan = scan, .flags = KEYEVENTF_SCANCODE, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80, /*[vkey] = 0x80*/}, + .todo_state = {[0] = TRUE, [VK_SHIFT] = TRUE, [VK_LSHIFT] = TRUE, /*[vkey] = TRUE*/}, + .expect = {KEY_HOOK(WM_KEYDOWN, scan, vkey, .todo_value = TRUE), KEY_MSG(WM_KEYDOWN, scan, vkey, .todo_value = TRUE), WIN_MSG(WM_CHAR, wch_shift, MAKELONG(1, scan), .todo = TRUE), {0}}}, + {.scan = scan, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, + .todo_state = {[VK_SHIFT] = TRUE, [VK_LSHIFT] = TRUE}, + .expect = {KEY_HOOK(WM_KEYUP, scan, vkey, .todo_value = TRUE), KEY_MSG(WM_KEYUP, scan, vkey, .todo_value = TRUE), {0}}}, + {.scan = 0x36, .flags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP, + .expect = {KEY_HOOK(WM_KEYUP, 0x36, VK_RSHIFT, .todo_value = TRUE), KEY_MSG(WM_KEYUP, 0x36, VK_SHIFT, .todo_value = TRUE), {0}}}, + {0}, + }; + #undef WIN_MSG #undef KBD_HOOK #undef KEY_HOOK_ @@ -872,6 +888,8 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W lcontrol_vkey[1].expect_state[vkey] = 0x80; lmenu_lcontrol_vkey[2].expect_state[vkey] = 0x80; shift_vkey[1].expect_state[vkey] = 0x80; + rshift_scan[1].expect_state[vkey] = 0x80; + rshift_scan[1].todo_state[vkey] = 0x80;
/* test peeked messages */ winetest_push_context( "peek" ); @@ -895,6 +913,7 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W check_send_input_test( menu_peeked, TRUE ); check_send_input_test( menu_ext_peeked, TRUE ); check_send_input_test( lrshift_ext, TRUE ); + check_send_input_test( rshift_scan, TRUE ); winetest_pop_context();
wait_messages( 100, FALSE ); @@ -925,6 +944,7 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W check_send_input_test( menu, FALSE ); check_send_input_test( menu_ext, FALSE ); check_send_input_test( lrshift_ext, FALSE ); + check_send_input_test( rshift_scan, FALSE ); winetest_pop_context();
ok_ret( 1, DestroyWindow( hwnd ) );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 186 +++++++++++++++++++++++++++++++++++--- 1 file changed, 173 insertions(+), 13 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 4da8022f361..12fa459205a 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -56,6 +56,7 @@ #include "winreg.h" #include "ddk/hidsdi.h" #include "imm.h" +#include "kbd.h"
#include "wine/test.h"
@@ -566,6 +567,70 @@ static BOOL test_send_input_accept_message( UINT msg ) return is_keyboard_message( msg ) || msg == WM_SYSCOMMAND; }
+static BOOL keyboard_layout_has_altgr(void) +{ + typedef struct + { + UINT64 pCharModifiers; + UINT64 pVkToWcharTable; + UINT64 pDeadKey; + UINT64 pKeyNames; + UINT64 pKeyNamesExt; + UINT64 pKeyNamesDead; + UINT64 pusVSCtoVK; + BYTE bMaxVSCtoVK; + UINT64 pVSCtoVK_E0; + UINT64 pVSCtoVK_E1; + DWORD fLocaleFlags; + } KBDTABLES64; + + WCHAR layout_path[MAX_PATH] = {L"System\CurrentControlSet\Control\Keyboard Layouts\"}, value[MAX_PATH]; + KBDTABLES *(CDECL *pKbdLayerDescriptor)(void); + DWORD value_size = sizeof(value), flags; + KBDTABLES *tables; + HMODULE module; + + ok_ret( 1, GetKeyboardLayoutNameW( layout_path + wcslen(layout_path) ) ); + todo_wine + ok_ret( 0, RegGetValueW( HKEY_LOCAL_MACHINE, layout_path, L"Layout File", RRF_RT_REG_SZ, + NULL, (void *)&value, &value_size) ); + + module = LoadLibraryW( value ); + todo_wine + ok_ne( NULL, module, HMODULE, "%p" ); + pKbdLayerDescriptor = (void *)GetProcAddress( module, "KbdLayerDescriptor" ); + todo_wine + ok_ne( NULL, pKbdLayerDescriptor, void *, "%p" ); + /* FIXME: Wine doesn't implement ALTGR behavior */ + if (!pKbdLayerDescriptor) return FALSE; + tables = pKbdLayerDescriptor(); + ok_ne( NULL, tables, KBDTABLES *, "%p" ); + flags = is_wow64 ? ((KBDTABLES64 *)tables)->fLocaleFlags : tables->fLocaleFlags; + ok_ret( 1, FreeLibrary( module ) ); + + trace( "%s flags %#lx\n", debugstr_w(value), flags ); + return !!(flags & KLLF_ALTGR); +} + +static void get_test_scan( WORD vkey, WORD *scan, WCHAR *wch, WCHAR *wch_shift ) +{ + HKL hkl = GetKeyboardLayout( 0 ); + BYTE state[256] = {0}; + + *scan = MapVirtualKeyExW( vkey, MAPVK_VK_TO_VSC_EX, hkl ); + ok_ne( 0, *scan, WORD, "%#x" ); + ok_ret( 1, ToUnicodeEx( vkey, *scan, state, wch, 1, 0, hkl ) ); + state[VK_SHIFT] = 0x80; + ok_ret( 1, ToUnicodeEx( vkey, *scan, state, wch_shift, 1, 0, hkl ) ); + + /* zh_CN returns a different WM_(SYS)CHAR, possibly coming from IME */ + if (HIWORD(hkl) == 0x0804) + { + *wch = 0x430; + *wch_shift = 0x410; + } +} + static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, WCHAR wch_shift, WCHAR wch_control ) { #define WIN_MSG(m, w, l, ...) {.func = MSG_TEST_WIN, .message = {.msg = m, .wparam = w, .lparam = l}, ## __VA_ARGS__} @@ -827,6 +892,85 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W {0}, };
+ struct send_input_test rmenu_altgr[] = + { + { + .vkey = VK_RMENU, .expect_state = {[VK_MENU] = 0x80, [VK_LMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = + { + KEY_HOOK_(WM_SYSKEYDOWN, 0x21d, VK_LCONTROL, LLKHF_ALTDOWN), + KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN, .todo_value = TRUE), + KEY_MSG(WM_KEYDOWN, 0x1d, VK_CONTROL), + KEY_MSG_(WM_KEYDOWN, 1, VK_MENU, KF_ALTDOWN), + {0} + } + }, + { + .vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP, + .expect = + { + KEY_HOOK(WM_KEYUP, 0x21d, VK_LCONTROL), + KEY_HOOK(WM_KEYUP, 2, VK_RMENU), + KEY_MSG_(WM_SYSKEYUP, 0x1d, VK_CONTROL, KF_ALTDOWN), + KEY_MSG(WM_KEYUP, 2, VK_MENU), + {0} + } + }, + {0}, + }; + struct send_input_test rmenu_ext_altgr[] = + { + { + .vkey = VK_RMENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = + { + KEY_HOOK_(WM_SYSKEYDOWN, 0x21d, VK_LCONTROL, LLKHF_ALTDOWN), + KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), + KEY_MSG(WM_KEYDOWN, 0x1d, VK_CONTROL), + KEY_MSG_(WM_KEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), + {0} + } + }, + { + .vkey = VK_RMENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = + { + KEY_HOOK(WM_KEYUP, 0x21d, VK_LCONTROL), + KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), + KEY_MSG_(WM_SYSKEYUP, 0x1d, VK_CONTROL, KF_ALTDOWN), + KEY_MSG_(WM_KEYUP, 2, VK_MENU, KF_EXTENDED), + {0} + } + }, + {0}, + }; + struct send_input_test menu_ext_altgr[] = + { + { + .vkey = VK_MENU, .flags = KEYEVENTF_EXTENDEDKEY, .expect_state = {[VK_MENU] = 0x80, [VK_RMENU] = 0x80, [VK_CONTROL] = 0x80, [VK_LCONTROL] = 0x80}, + .expect = + { + KEY_HOOK_(WM_SYSKEYDOWN, 0x21d, VK_LCONTROL, LLKHF_ALTDOWN), + KEY_HOOK_(WM_SYSKEYDOWN, 1, VK_RMENU, LLKHF_ALTDOWN|LLKHF_EXTENDED, .todo_value = TRUE), + KEY_MSG(WM_KEYDOWN, 0x1d, VK_CONTROL), + KEY_MSG_(WM_KEYDOWN, 1, VK_MENU, KF_ALTDOWN|KF_EXTENDED), + {0} + } + }, + { + .vkey = VK_MENU, .flags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, + .expect = + { + KEY_HOOK(WM_KEYUP, 0x21d, VK_LCONTROL), + KEY_HOOK_(WM_KEYUP, 2, VK_RMENU, LLKHF_EXTENDED, .todo_value = TRUE), + KEY_MSG_(WM_SYSKEYUP, 0x1d, VK_CONTROL, KF_ALTDOWN), + KEY_MSG_(WM_KEYUP, 2, VK_MENU, KF_EXTENDED), + {0} + } + }, + {0}, + }; + static const struct send_input_test lrshift_ext[] = { {.vkey = VK_LSHIFT, .expect_state = {[VK_SHIFT] = 0x80, [VK_LSHIFT] = 0x80}, @@ -863,15 +1007,14 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W #undef KEY_MSG_ #undef KEY_MSG
+ BOOL altgr = keyboard_layout_has_altgr(), skip_altgr = FALSE; LONG_PTR old_proc; HHOOK hook; HWND hwnd;
- if (GetKeyboardLayout(0) != (HKL)(ULONG_PTR)0x04090409) - { - skip("Skipping Input_blackbox test on non-US keyboard\n"); - return; - } + /* on 32-bit with ALTGR keyboard, the CONTROL key is sent to the hooks without the + * LLKHF_INJECTED flag, skip the tests to keep it simple */ + if (altgr && sizeof(void *) == 4 && !is_wow64) skip_altgr = TRUE;
hwnd = CreateWindowW( L"static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL ); ok_ne( NULL, hwnd, HWND, "%p" ); @@ -907,11 +1050,17 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W check_send_input_test( rcontrol_ext, TRUE ); check_send_input_test( control, TRUE ); check_send_input_test( control_ext, TRUE ); - check_send_input_test( rmenu_peeked, TRUE ); + if (skip_altgr) skip( "skipping rmenu_altgr test\n" ); + else if (altgr) check_send_input_test( rmenu_altgr, TRUE ); + else check_send_input_test( rmenu_peeked, TRUE ); check_send_input_test( lmenu_ext_peeked, TRUE ); - check_send_input_test( rmenu_ext_peeked, TRUE ); + if (skip_altgr) skip( "skipping rmenu_ext_altgr test\n" ); + else if (altgr) check_send_input_test( rmenu_ext_altgr, TRUE ); + else check_send_input_test( rmenu_ext_peeked, TRUE ); check_send_input_test( menu_peeked, TRUE ); - check_send_input_test( menu_ext_peeked, TRUE ); + if (skip_altgr) skip( "skipping menu_ext_altgr test\n" ); + else if (altgr) check_send_input_test( menu_ext_altgr, TRUE ); + else check_send_input_test( menu_ext_peeked, TRUE ); check_send_input_test( lrshift_ext, TRUE ); check_send_input_test( rshift_scan, TRUE ); winetest_pop_context(); @@ -938,11 +1087,17 @@ static void test_SendInput_keyboard_messages( WORD vkey, WORD scan, WCHAR wch, W check_send_input_test( rcontrol_ext, FALSE ); check_send_input_test( control, FALSE ); check_send_input_test( control_ext, FALSE ); - check_send_input_test( rmenu, FALSE ); + if (skip_altgr) skip( "skipping rmenu_altgr test\n" ); + else if (altgr) check_send_input_test( rmenu_altgr, FALSE ); + else check_send_input_test( rmenu, FALSE ); check_send_input_test( lmenu_ext, FALSE ); - check_send_input_test( rmenu_ext, FALSE ); + if (skip_altgr) skip( "skipping rmenu_ext_altgr test\n" ); + else if (altgr) check_send_input_test( rmenu_ext_altgr, FALSE ); + else check_send_input_test( rmenu_ext, FALSE ); check_send_input_test( menu, FALSE ); - check_send_input_test( menu_ext, FALSE ); + if (skip_altgr) skip( "skipping menu_ext_altgr test\n" ); + else if (altgr) check_send_input_test( menu_ext_altgr, FALSE ); + else check_send_input_test( menu_ext, FALSE ); check_send_input_test( lrshift_ext, FALSE ); check_send_input_test( rshift_scan, FALSE ); winetest_pop_context(); @@ -5250,12 +5405,17 @@ static void test_ClipCursor( char **argv ) * tests, current desktop state, or user actions. */ static void test_input_desktop( char **argv ) { + HKL hkl = GetKeyboardLayout( 0 ); + WCHAR wch, wch_shift; POINT pos; + WORD scan;
+ trace( "hkl %p\n", hkl ); ok_ret( 1, GetCursorPos( &pos ) );
- test_SendInput( 'F', 'f' ); - test_SendInput_keyboard_messages( 'F', 0x21, 'f', 'F', '\x06' ); + get_test_scan( 'F', &scan, &wch, &wch_shift ); + test_SendInput( 'F', wch ); + test_SendInput_keyboard_messages( 'F', scan, wch, wch_shift, '\x06' );
ok_ret( 1, SetCursorPos( pos.x, pos.y ) ); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=141891
Your paranoid android.
=== w10pro64_zh_CN (64 bit report) ===
user32: input.c:3319: Test failed: ToAscii(A) returned 2, expected 0
=== w1064_2qxl (64 bit report) ===
user32: win.c:4583: Test failed: hwnd 000000000003003E/000000000003003E message 0200 win.c:4587: Test failed: hwnd 000000000003003E/000000000003003E message 0201 win.c:4596: Test failed: hwnd 0000000000100268/0000000000100268 message 0202 win.c:4599: Test failed: hwnd 0000000000100268/0000000000100268 message 0201
=== w10pro64 (64 bit report) ===
user32: win.c:3818: Test failed: GetForegroundWindow returned 00000000000202C0 win.c:3749: Test failed: SetForegroundWindow failed, error 0 win.c:3752: Test failed: GetForegroundWindow returned 00000000000202C0 win.c:3789: Test failed: GetForegroundWindow returned 00000000000202C0 win.c:3877: Test failed: GetActiveWindow() = 00000000000301D6 win.c:3881: Test failed: GetFocus() = 0000000000000000 win.c:3884: Test failed: GetFocus() = 0000000000000000
Windows test failures look unrelated, there's unrelated cursoricon and sysparam test failures as well as `input.c:1553: Test failed: Wrong new pos: (150,150)` which also happened from time to time before and part of tests that have not been modified here.
Linux test failures also look unrelated, fails in ddraw, dinput, nsi, quartz.