Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- v2: Don't leak hwnd or di in case of errors.
dlls/dinput8/tests/device.c | 108 ++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index f3e7b54235..ea5ab75109 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -742,6 +742,113 @@ static void test_mouse_keyboard(void) DestroyWindow(hwnd); }
+static void test_keyboard_events(void) +{ + HRESULT hr; + HWND hwnd = INVALID_HANDLE_VALUE; + IDirectInput8A *di; + IDirectInputDevice8A *di_keyboard; + DIPROPDWORD dp; + DIDEVICEOBJECTDATA obj_data[10]; + DWORD data_size; + BYTE kbdata[256]; + + hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&di); + if (hr == DIERR_OLDDIRECTINPUTVERSION || + hr == DIERR_BETADIRECTINPUTVERSION || + hr == REGDB_E_CLASSNOTREG) + { + win_skip("test_keyboard_events requires dinput8\n"); + return; + } + ok(SUCCEEDED(hr), "DirectInput8Create failed: %08x\n", hr); + + hr = IDirectInput8_Initialize(di, GetModuleHandleA(NULL), DIRECTINPUT_VERSION); + if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION) + { + win_skip("test_keyboard_events requires dinput8\n"); + IDirectInput8_Release(di); + return; + } + ok(SUCCEEDED(hr), "IDirectInput8_Initialize failed: %08x\n", hr); + + hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL); + ok(hwnd != NULL, "CreateWindowExA failed\n"); + + hr = IDirectInput8_CreateDevice(di, &GUID_SysKeyboard, &di_keyboard, NULL); + ok(SUCCEEDED(hr), "IDirectInput8_CreateDevice failed: %08x\n", hr); + hr = IDirectInputDevice8_SetCooperativeLevel(di_keyboard, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE); + ok(SUCCEEDED(hr), "IDirectInput8_SetCooperativeLevel failed: %08x\n", hr); + hr = IDirectInputDevice8_SetDataFormat(di_keyboard, &c_dfDIKeyboard); + ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr); + dp.diph.dwSize = sizeof(DIPROPDWORD); + dp.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dp.diph.dwObj = 0; + dp.diph.dwHow = DIPH_DEVICE; + dp.dwData = ARRAY_SIZE(obj_data); + IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_BUFFERSIZE, &(dp.diph)); + + hr = IDirectInputDevice8_Acquire(di_keyboard); + ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); + + /* Test injecting keyboard events with both VK and scancode given. */ + keybd_event(VK_SPACE, DIK_SPACE, 0, 0); + flush_events(); + IDirectInputDevice8_Poll(di_keyboard); + data_size = ARRAY_SIZE(obj_data); + hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); + ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); + todo_wine + ok(data_size == 1, "Expected 1 element, received %d\n", data_size); + + hr = IDirectInputDevice8_GetDeviceState(di_keyboard, sizeof(kbdata), kbdata); + ok(SUCCEEDED(hr), "IDirectInputDevice8_GetDeviceState failed: %08x\n", hr); + todo_wine + ok(kbdata[DIK_SPACE], "Expected DIK_SPACE key state down\n"); + + keybd_event(VK_SPACE, DIK_SPACE, KEYEVENTF_KEYUP, 0); + flush_events(); + IDirectInputDevice8_Poll(di_keyboard); + data_size = ARRAY_SIZE(obj_data); + hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); + ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); + todo_wine + ok(data_size == 1, "Expected 1 element, received %d\n", data_size); + + /* Test injecting keyboard events with scancode=0. + * Windows DInput ignores the VK, sets scancode 0 to be pressed, and GetDeviceData returns no elements. */ + keybd_event(VK_SPACE, 0, 0, 0); + flush_events(); + IDirectInputDevice8_Poll(di_keyboard); + data_size = ARRAY_SIZE(obj_data); + hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); + ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); + todo_wine + ok(data_size == 0, "Expected 0 elements, received %d\n", data_size); + + hr = IDirectInputDevice8_GetDeviceState(di_keyboard, sizeof(kbdata), kbdata); + ok(SUCCEEDED(hr), "IDirectInputDevice8_GetDeviceState failed: %08x\n", hr); + todo_wine + ok(kbdata[0], "Expected key 0 state down\n"); + + keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0); + flush_events(); + IDirectInputDevice8_Poll(di_keyboard); + data_size = ARRAY_SIZE(obj_data); + hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); + ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); + todo_wine + ok(data_size == 0, "Expected 0 elements, received %d\n", data_size); + + hr = IDirectInputDevice8_Unacquire(di_keyboard); + ok(SUCCEEDED(hr), "IDirectInputDevice8_Unacquire failed: %08x\n", hr); + + IDirectInputDevice8_Release(di_keyboard); + IDirectInput8_Release(di); + + DestroyWindow(hwnd); +} + START_TEST(device) { CoInitialize(NULL); @@ -749,6 +856,7 @@ START_TEST(device) test_action_mapping(); test_save_settings(); test_mouse_keyboard(); + test_keyboard_events();
CoUninitialize(); }
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/dinput/dinput_main.c | 15 ++++++++++++--- dlls/dinput8/tests/device.c | 3 --- 2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 0855cb41cd..d70e9c86f2 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -1717,10 +1717,11 @@ static DWORD WINAPI hook_thread_proc(void *param) if (msg.message == WM_USER+0x10) { IDirectInputImpl *dinput; + HANDLE finished_event = (HANDLE)msg.lParam;
- TRACE( "Processing hook change notification lp:%ld\n", msg.lParam ); + TRACE( "Processing hook change notification wp:%ld lp:%#lx\n", msg.wParam, msg.lParam );
- if (!msg.wParam && !msg.lParam) + if (!msg.wParam) { if (kbd_hook) UnhookWindowsHookEx( kbd_hook ); if (mouse_hook) UnhookWindowsHookEx( mouse_hook ); @@ -1765,6 +1766,9 @@ static DWORD WINAPI hook_thread_proc(void *param) UnhookWindowsHookEx( mouse_hook ); mouse_hook = NULL; } + + if (finished_event) + SetEvent(finished_event); } TranslateMessage(&msg); DispatchMessageW(&msg); @@ -1824,6 +1828,7 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired) static HHOOK callwndproc_hook; static ULONG foreground_cnt; IDirectInputDeviceImpl *dev = impl_from_IDirectInputDevice8W(iface); + HANDLE hook_change_finished_event;
EnterCriticalSection(&dinput_hook_crit);
@@ -1851,9 +1856,13 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired) hook_thread_event = NULL; }
- PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, 0 ); + hook_change_finished_event = CreateEventW( NULL, FALSE, FALSE, NULL ); + PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, (LPARAM)hook_change_finished_event );
LeaveCriticalSection(&dinput_hook_crit); + + WaitForSingleObject(hook_change_finished_event, INFINITE); + CloseHandle(hook_change_finished_event); }
void check_dinput_events(void) diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index ea5ab75109..bb82855d40 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -798,12 +798,10 @@ static void test_keyboard_events(void) data_size = ARRAY_SIZE(obj_data); hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); - todo_wine ok(data_size == 1, "Expected 1 element, received %d\n", data_size);
hr = IDirectInputDevice8_GetDeviceState(di_keyboard, sizeof(kbdata), kbdata); ok(SUCCEEDED(hr), "IDirectInputDevice8_GetDeviceState failed: %08x\n", hr); - todo_wine ok(kbdata[DIK_SPACE], "Expected DIK_SPACE key state down\n");
keybd_event(VK_SPACE, DIK_SPACE, KEYEVENTF_KEYUP, 0); @@ -812,7 +810,6 @@ static void test_keyboard_events(void) data_size = ARRAY_SIZE(obj_data); hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); - todo_wine ok(data_size == 1, "Expected 1 element, received %d\n", data_size);
/* Test injecting keyboard events with scancode=0.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=69415
Your paranoid android.
=== debiant (32 bit report) ===
dinput: mouse: Timeout
=== debiant (32 bit Chinese:China report) ===
dinput: mouse: Timeout
=== debiant (32 bit WoW report) ===
dinput: mouse: Timeout
=== debiant (64 bit WoW report) ===
dinput: mouse: Timeout
Grand Theft Auto IV injects VK_F8 and scancode=0, and expects DirectInput not to report that F8 is pressed.
Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- dlls/dinput/keyboard.c | 3 --- dlls/dinput8/tests/device.c | 2 -- 2 files changed, 5 deletions(-)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index 47f28cac52..cecf6c546f 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -70,9 +70,6 @@ static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(SysKeyboardIm
static BYTE map_dik_code(DWORD scanCode, DWORD vkCode, DWORD subType) { - if (!scanCode) - scanCode = MapVirtualKeyW(vkCode, MAPVK_VK_TO_VSC); - if (subType == DIDEVTYPEKEYBOARD_JAPAN106) { switch (scanCode) diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index bb82855d40..39c635f2fb 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -820,7 +820,6 @@ static void test_keyboard_events(void) data_size = ARRAY_SIZE(obj_data); hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); - todo_wine ok(data_size == 0, "Expected 0 elements, received %d\n", data_size);
hr = IDirectInputDevice8_GetDeviceState(di_keyboard, sizeof(kbdata), kbdata); @@ -834,7 +833,6 @@ static void test_keyboard_events(void) data_size = ARRAY_SIZE(obj_data); hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0); ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr); - todo_wine ok(data_size == 0, "Expected 0 elements, received %d\n", data_size);
hr = IDirectInputDevice8_Unacquire(di_keyboard);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=69416
Your paranoid android.
=== debiant (32 bit report) ===
dinput: keyboard.c:154: Test failed: Keyboard event not processed, skipping test mouse: Timeout
=== debiant (32 bit Chinese:China report) ===
dinput: mouse: Timeout
=== debiant (32 bit WoW report) ===
dinput: mouse: Timeout
=== debiant (64 bit WoW report) ===
dinput: mouse: Timeout