Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/device.c | 13 --------- dlls/user32/rawinput.c | 55 +++++++++++++++++++++++++++++++++++-- server/protocol.def | 6 ++++ server/queue.c | 24 ++++++++++++++++ 4 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 0bf6936812f..2b7814e3bbc 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -602,7 +602,6 @@ static void test_mouse_keyboard(void)
raw_devices_count = ARRAY_SIZE(raw_devices); GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
hr = IDirectInputDevice8_Acquire(di_keyboard); @@ -624,7 +623,6 @@ static void test_mouse_keyboard(void) ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); raw_devices_count = ARRAY_SIZE(raw_devices); GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
if (raw_devices[0].hwndTarget != NULL) @@ -662,7 +660,6 @@ static void test_mouse_keyboard(void) ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); raw_devices_count = ARRAY_SIZE(raw_devices); GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
/* expect dinput8 to take over any activated raw input devices */ @@ -689,26 +686,18 @@ static void test_mouse_keyboard(void) raw_devices_count = ARRAY_SIZE(raw_devices); memset(raw_devices, 0, sizeof(raw_devices)); hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); - todo_wine ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); - todo_wine ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); todo_wine ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); todo_wine ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget); - todo_wine ok(raw_devices[1].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage); - todo_wine ok(raw_devices[1].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage); ok(raw_devices[1].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags); - todo_wine ok(raw_devices[1].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget); - todo_wine ok(raw_devices[2].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage); - todo_wine ok(raw_devices[2].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage); todo_wine ok(raw_devices[2].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags); @@ -727,12 +716,10 @@ static void test_mouse_keyboard(void) hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); todo_wine ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); - todo_wine ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); todo_wine ok(raw_devices[0].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); ok(raw_devices[0].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); - todo_wine ok(raw_devices[0].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
IDirectInputDevice8_Release(di_mouse); diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 49cf9f73a0d..cb03a6553a6 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -469,14 +469,65 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT return s; }
+static int compare_raw_input_devices(const void *ap, const void *bp) +{ + const RAWINPUTDEVICE a = *(const RAWINPUTDEVICE *)ap; + const RAWINPUTDEVICE b = *(const RAWINPUTDEVICE *)bp; + + if (a.usUsagePage != b.usUsagePage) return a.usUsagePage - b.usUsagePage; + if (a.usUsage != b.usUsage) return a.usUsage - b.usUsage; + return 0; +} + /*********************************************************************** * GetRegisteredRawInputDevices (USER32.@) */ UINT WINAPI DECLSPEC_HOTPATCH GetRegisteredRawInputDevices(RAWINPUTDEVICE *devices, UINT *device_count, UINT size) { - FIXME("devices %p, device_count %p, size %u stub!\n", devices, device_count, size); + struct rawinput_device *d = NULL; + unsigned int count = ~0U;
- return 0; + TRACE("devices %p, device_count %p, size %u\n", devices, device_count, size); + + if (!device_count) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ~0U; + } + + if (devices && !(d = HeapAlloc( GetProcessHeap(), 0, *device_count * sizeof(*d) ))) + return ~0U; + + SERVER_START_REQ( get_rawinput_devices ) + { + if (d) + wine_server_set_reply( req, d, *device_count * sizeof(*d) ); + + if (wine_server_call( req )) + goto done; + + if (!d || reply->device_count > *device_count) + { + *device_count = reply->device_count; + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + goto done; + } + + for (count = 0; count < reply->device_count; ++count) + { + devices[count].usUsagePage = d[count].usage_page; + devices[count].usUsage = d[count].usage; + devices[count].dwFlags = d[count].flags; + devices[count].hwndTarget = wine_server_ptr_handle(d[count].target); + } + } + SERVER_END_REQ; + + qsort(devices, count, sizeof(*devices), compare_raw_input_devices); + +done: + if (d) HeapFree( GetProcessHeap(), 0, d ); + return count; }
diff --git a/server/protocol.def b/server/protocol.def index 6af0ae0cff8..2647e87f1fe 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3864,6 +3864,12 @@ struct handle_info VARARG(devices,rawinput_devices); @END
+/* Retrieve the list of registered rawinput devices */ +@REQ(get_rawinput_devices) +@REPLY + unsigned int device_count; + VARARG(devices,rawinput_devices); +@END
/* Retrieve the suspended context of a thread */ @REQ(get_suspend_context) diff --git a/server/queue.c b/server/queue.c index 96587d11d1e..6207fdb1f7c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -3123,3 +3123,27 @@ DECL_HANDLER(update_rawinput_devices) e = find_rawinput_device( 1, 6 ); current->process->rawinput_kbd = e ? &e->device : NULL; } + +DECL_HANDLER(get_rawinput_devices) +{ + unsigned int device_count = list_count(¤t->process->rawinput_devices); + struct rawinput_device *devices; + struct rawinput_device_entry *e; + unsigned int i; + + reply->device_count = device_count; + if (get_reply_max_size() / sizeof (*devices) < device_count) + return; + + if (!(devices = mem_alloc( device_count * sizeof (*devices) ))) + { + set_error( STATUS_NO_MEMORY ); + return; + } + + i = 0; + LIST_FOR_EACH_ENTRY( e, ¤t->process->rawinput_devices, struct rawinput_device_entry, entry ) + devices[i++] = e->device; + + set_reply_data_ptr( devices, device_count * sizeof (*devices) ); +}
This adds a global message window that will receive WM_INPUT messages, dispatched to every raw input device event_proc.
Devices that use raw input interface will not register low-level hooks anymore. They will also conflict with any raw input device registered outside of dinput, as exposed by the unit tests.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/device_private.h | 3 ++ dlls/dinput/dinput_main.c | 79 +++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 27e9c262869..8d4d6a0b5bf 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -70,6 +70,9 @@ struct IDirectInputDeviceImpl int acquired; DI_EVENT_PROC event_proc; /* function to receive mouse & keyboard events */
+ BOOL use_raw_input; /* use raw input instead of low-level messages */ + RAWINPUTDEVICE raw_device; /* raw device to (un)register */ + LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. */ int queue_len; /* size of the queue - set in 'SetProperty' */ int queue_head; /* position to write new event into queue */ diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 0855cb41cd5..4fd0b9cc5a9 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -97,6 +97,10 @@ static const struct dinput_device *dinput_devices[] =
HINSTANCE DINPUT_instance;
+static ATOM di_em_win_class; +static const WCHAR di_em_winW[] = {'D','I','E','m','W','i','n',0}; +static HWND di_em_win; + static BOOL check_hook_thread(void); static CRITICAL_SECTION dinput_hook_crit; static struct list direct_input_list = LIST_INIT( direct_input_list ); @@ -611,6 +615,59 @@ static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, RE return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj ); }
+static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + IDirectInputImpl *dinput; + + TRACE( "%p %d %lx %lx\n", hwnd, msg, wparam, lparam ); + + if (msg == WM_INPUT) + { + EnterCriticalSection( &dinput_hook_crit ); + LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry ) + { + IDirectInputDeviceImpl *dev; + + EnterCriticalSection( &dinput->crit ); + LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDeviceImpl, entry ) + { + if (dev->acquired && dev->event_proc && dev->use_raw_input) + { + TRACE("calling %p->%p (%lx %lx)\n", dev, dev->event_proc, wparam, lparam); + dev->event_proc( &dev->IDirectInputDevice8A_iface, GET_RAWINPUT_CODE_WPARAM(wparam), lparam ); + } + } + LeaveCriticalSection( &dinput->crit ); + } + LeaveCriticalSection( &dinput_hook_crit ); + } + + return DefWindowProcW(hwnd, msg, wparam, lparam); +} + +static void register_di_em_win_class(void) +{ + static WNDCLASSEXW class; + + ZeroMemory(&class, sizeof(class)); + class.cbSize = sizeof(class); + class.lpfnWndProc = di_em_win_wndproc; + class.hInstance = DINPUT_instance; + class.lpszClassName = di_em_winW; + + if (!(di_em_win_class = RegisterClassExW( &class ))) + WARN( "Unable to register message window class\n" ); +} + +static void unregister_di_em_win_class(void) +{ + if (!di_em_win_class) + return; + + if (!UnregisterClassW( MAKEINTRESOURCEW( di_em_win_class ), DINPUT_instance )) + WARN( "Unable to unregister message window class\n" ); +} + static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwVersion) { if (!This->initialized) @@ -1706,6 +1763,9 @@ static DWORD WINAPI hook_thread_proc(void *param) static HHOOK kbd_hook, mouse_hook; MSG msg;
+ di_em_win = CreateWindowW( MAKEINTRESOURCEW(di_em_win_class), di_em_winW, + 0, 0, 0, 0, 0, HWND_MESSAGE, 0, DINPUT_instance, NULL ); + /* Force creation of the message queue */ PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ); SetEvent(param); @@ -1738,7 +1798,7 @@ static DWORD WINAPI hook_thread_proc(void *param) EnterCriticalSection( &dinput->crit ); LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDeviceImpl, entry ) { - if (!dev->acquired || !dev->event_proc) continue; + if (!dev->acquired || !dev->event_proc || dev->use_raw_input) continue;
if (IsEqualGUID( &dev->guid, &GUID_SysKeyboard )) kbd_cnt++; @@ -1770,6 +1830,9 @@ static DWORD WINAPI hook_thread_proc(void *param) DispatchMessageW(&msg); }
+ DestroyWindow( di_em_win ); + di_em_win = NULL; + FreeLibraryAndExitThread(DINPUT_instance, 0); }
@@ -1851,6 +1914,18 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired) hook_thread_event = NULL; }
+ if (dev->use_raw_input) + { + if (acquired) + dev->raw_device.dwFlags = RIDEV_INPUTSINK; + else + dev->raw_device.dwFlags = RIDEV_REMOVE; + dev->raw_device.hwndTarget = di_em_win; + + if (!RegisterRawInputDevices( &dev->raw_device, 1, sizeof(RAWINPUTDEVICE) )) + WARN( "Unable to (un)register raw device %x:%x\n", dev->raw_device.usUsagePage, dev->raw_device.usUsage ); + } + PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, 0 );
LeaveCriticalSection(&dinput_hook_crit); @@ -1877,9 +1952,11 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved) case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(inst); DINPUT_instance = inst; + register_di_em_win_class(); break; case DLL_PROCESS_DETACH: if (reserved) break; + unregister_di_em_win_class(); DeleteCriticalSection(&dinput_hook_crit); break; }
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=55963
Your paranoid android.
=== debian10 (32 bit report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit Chinese:China report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit WoW report) ===
dinput: keyboard.c:154: Test failed: Keyboard event not processed, skipping test mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (64 bit WoW report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds win.c:10097: Test failed: GetForegroundWindow() = 00000000
Report errors: user32:msg prints too much data (35221 bytes)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/keyboard.c | 69 +++++++++++++++++++++++++++++++++---- dlls/dinput8/tests/device.c | 7 ---- 2 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index b5e665933ec..44f82bee9a6 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -107,17 +107,65 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM { SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); int dik_code, ret = This->base.dwCoopLevel & DISCL_EXCLUSIVE; - KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; BYTE new_diks; + DWORD vkey_code, scan_code; + BOOL is_key_ext, is_key_up;
if (wparam != WM_KEYDOWN && wparam != WM_KEYUP && - wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP) + wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP && + wparam != RIM_INPUT && wparam != RIM_INPUTSINK) return 0;
+ if (wparam == RIM_INPUT || wparam == RIM_INPUTSINK) + { + RAWINPUTHEADER raw_header; + RAWINPUT raw_input; + UINT size; + + TRACE("(%p) wp %08lx, lp %08lx\n", iface, wparam, lparam); + + size = sizeof(raw_header); + if (GetRawInputData( (HRAWINPUT)lparam, RID_HEADER, &raw_header, &size, sizeof(RAWINPUTHEADER) ) != sizeof(raw_header)) + { + WARN( "Unable to read raw input data header\n" ); + return 0; + } + + if (raw_header.dwType != RIM_TYPEKEYBOARD) + return 0; + + if (raw_header.dwSize > sizeof(raw_input)) + { + WARN( "Unexpected size for keyboard raw input data\n" ); + return 0; + } + + size = raw_header.dwSize; + if (GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &raw_input, &size, sizeof(RAWINPUTHEADER) ) != raw_header.dwSize ) + { + WARN( "Unable to read raw input data\n" ); + return 0; + } + + vkey_code = raw_input.data.keyboard.VKey; + scan_code = raw_input.data.keyboard.MakeCode; + is_key_ext = (raw_input.data.keyboard.Flags & RI_KEY_E0); + is_key_up = (raw_input.data.keyboard.Flags & RI_KEY_BREAK); + } + else + { + KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; + + vkey_code = hook->vkCode; + scan_code = hook->scanCode; + is_key_ext = (hook->flags & LLKHF_EXTENDED); + is_key_up = (hook->flags & LLKHF_UP); + } + TRACE("(%p) wp %08lx, lp %08lx, vk %02x, scan %02x\n", - iface, wparam, lparam, hook->vkCode, hook->scanCode); + iface, wparam, lparam, vkey_code, scan_code);
- switch (hook->vkCode) + switch (vkey_code) { /* R-Shift is special - it is an extended key with separate scan code */ case VK_RSHIFT : dik_code = DIK_RSHIFT; break; @@ -125,10 +173,10 @@ static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM case VK_NUMLOCK : dik_code = DIK_NUMLOCK; break; case VK_SUBTRACT: dik_code = DIK_SUBTRACT; break; default: - dik_code = map_dik_code(hook->scanCode & 0xff, hook->vkCode, This->subtype); - if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80; + dik_code = map_dik_code(scan_code & 0xff, vkey_code, This->subtype); + if (is_key_ext) dik_code |= 0x80; } - new_diks = hook->flags & LLKHF_UP ? 0 : 0x80; + new_diks = is_key_up ? 0 : 0x80;
/* returns now if key event already known */ if (new_diks == This->DInputKeyState[dik_code]) @@ -295,6 +343,13 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) list_add_tail(&dinput->devices_list, &newDevice->base.entry); LeaveCriticalSection(&dinput->crit);
+ if (dinput->dwVersion >= 0x800) + { + newDevice->base.use_raw_input = TRUE; + newDevice->base.raw_device.usUsagePage = 1; /* HID generic device page */ + newDevice->base.raw_device.usUsage = 6; /* HID generic keyboard */ + } + return newDevice;
failed: diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 2b7814e3bbc..9f2d0dbd29a 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -609,15 +609,10 @@ static void test_mouse_keyboard(void) raw_devices_count = ARRAY_SIZE(raw_devices); memset(raw_devices, 0, sizeof(raw_devices)); hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); - todo_wine ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); - todo_wine ok(raw_devices[0].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); - todo_wine ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); - todo_wine ok(raw_devices[0].hwndTarget != NULL, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget); hr = IDirectInputDevice8_Unacquire(di_keyboard); ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); @@ -699,9 +694,7 @@ static void test_mouse_keyboard(void) ok(raw_devices[1].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget); ok(raw_devices[2].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage); ok(raw_devices[2].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage); - todo_wine ok(raw_devices[2].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags); - todo_wine ok(raw_devices[2].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget); hr = IDirectInputDevice8_Unacquire(di_keyboard); ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
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=55964
Your paranoid android.
=== w1064v1507 (32 bit report) ===
dinput8: device: Timeout
=== debian10 (32 bit report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit Chinese:China report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit WoW report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (64 bit WoW report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/mouse.c | 117 +++++++++++++++++++++++++++++++++++- dlls/dinput8/tests/device.c | 10 --- 2 files changed, 116 insertions(+), 11 deletions(-)
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index 52a766b2a1a..a94fff0670b 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -246,6 +246,13 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) list_add_tail(&dinput->devices_list, &newDevice->base.entry); LeaveCriticalSection(&dinput->crit);
+ if (dinput->dwVersion >= 0x0800) + { + newDevice->base.use_raw_input = TRUE; + newDevice->base.raw_device.usUsagePage = 1; /* HID generic device page */ + newDevice->base.raw_device.usUsage = 2; /* HID generic mouse */ + } + return newDevice;
failed: @@ -318,7 +325,115 @@ static int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM { MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam; SysMouseImpl* This = impl_from_IDirectInputDevice8A(iface); - int wdata = 0, inst_id = -1, ret = 0; + int wdata = 0, inst_id = -1, ret = 0, i; + + if (wparam == RIM_INPUT || wparam == RIM_INPUTSINK) + { + RAWINPUTHEADER raw_header; + RAWINPUT raw_input; + UINT size; + POINT rel, pt; + + static const USHORT mouse_button_flags[] = + { + RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP, + RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP, + RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP, + RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP, + RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP + }; + + TRACE("(%p) wp %08lx, lp %08lx\n", iface, wparam, lparam); + + size = sizeof(raw_header); + if (GetRawInputData( (HRAWINPUT)lparam, RID_HEADER, &raw_header, &size, sizeof(RAWINPUTHEADER) ) != sizeof(raw_header)) + { + WARN( "Unable to read raw input data header\n" ); + return 0; + } + + if (raw_header.dwType != RIM_TYPEMOUSE) + return 0; + + if (raw_header.dwSize > sizeof(raw_input)) + { + WARN( "Unexpected size for mouse raw input data\n" ); + return 0; + } + + size = raw_header.dwSize; + if (GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &raw_input, &size, sizeof(RAWINPUTHEADER) ) != raw_header.dwSize ) + { + WARN( "Unable to read raw input data\n" ); + return 0; + } + + if (raw_input.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) + FIXME( "Unimplemented MOUSE_VIRTUAL_DESKTOP flag\n" ); + if (raw_input.data.mouse.usFlags & MOUSE_ATTRIBUTES_CHANGED) + FIXME( "Unimplemented MOUSE_ATTRIBUTES_CHANGED flag\n" ); + + EnterCriticalSection(&This->base.crit); + + rel.x = raw_input.data.mouse.lLastX; + rel.y = raw_input.data.mouse.lLastY; + if (raw_input.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) + { + GetCursorPos(&pt); + rel.x -= pt.x; + rel.y -= pt.y; + } + + This->m_state.lX += rel.x; + This->m_state.lY += rel.y; + + if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS) + { + pt.x = This->m_state.lX; + pt.y = This->m_state.lY; + } + else + { + pt = rel; + } + + if (rel.x) + queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS, + pt.x, GetCurrentTime(), This->base.dinput->evsequence); + + if (rel.y) + queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, + pt.y, GetCurrentTime(), This->base.dinput->evsequence); + + if (rel.x || rel.y) + { + if ((This->warp_override == WARP_FORCE_ON) || + (This->warp_override != WARP_DISABLE && (This->base.dwCoopLevel & DISCL_EXCLUSIVE))) + This->need_warp = TRUE; + } + + if (raw_input.data.mouse.usButtonFlags & RI_MOUSE_WHEEL) + { + This->m_state.lZ += (wdata = (SHORT)raw_input.data.mouse.usButtonData); + queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS, + wdata, GetCurrentTime(), This->base.dinput->evsequence); + ret = This->clipped; + } + + for (i = 0; i < ARRAY_SIZE(mouse_button_flags); ++i) + { + if (raw_input.data.mouse.usButtonFlags & mouse_button_flags[i]) + { + This->m_state.rgbButtons[i / 2] = 0x80 - (i % 2) * 0x80; + queue_event(iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_BUTTONS_INSTANCE + (i / 2)) | DIDFT_PSHBUTTON, + This->m_state.rgbButtons[i / 2], GetCurrentTime(), This->base.dinput->evsequence); + } + } + + LeaveCriticalSection(&This->base.crit); + + return ret; + }
TRACE("msg %lx @ (%d %d)\n", wparam, hook->pt.x, hook->pt.y);
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 9f2d0dbd29a..e7fe1302046 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -641,15 +641,10 @@ static void test_mouse_keyboard(void) raw_devices_count = ARRAY_SIZE(raw_devices); memset(raw_devices, 0, sizeof(raw_devices)); hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); - todo_wine ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); - todo_wine ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); - todo_wine ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); - todo_wine ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget); hr = IDirectInputDevice8_Unacquire(di_mouse); ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); @@ -684,9 +679,7 @@ static void test_mouse_keyboard(void) ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); - todo_wine ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); - todo_wine ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget); ok(raw_devices[1].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage); ok(raw_devices[1].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage); @@ -702,15 +695,12 @@ static void test_mouse_keyboard(void) ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); raw_devices_count = ARRAY_SIZE(raw_devices); GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(raw_devices_count == 1, "Unexpected raw devices registered: %d\n", raw_devices_count);
raw_devices_count = ARRAY_SIZE(raw_devices); hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); - todo_wine ok(raw_devices[0].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); ok(raw_devices[0].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); ok(raw_devices[0].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
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=55965
Your paranoid android.
=== debian10 (32 bit report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit Chinese:China report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit WoW report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (64 bit WoW report) ===
dinput: mouse.c:173: Test failed: GetDeviceData() failed: 00000000 cnt:0
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
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=55962
Your paranoid android.
=== debian10 (32 bit report) ===
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit Chinese:China report) ===
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (32 bit WoW report) ===
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)
=== debian10 (64 bit WoW report) ===
user32: msg.c:5145: Test succeeded inside todo block: ShowWindow(SW_SHOWMINIMIZED):overlapped: marked "todo_wine" but succeeds
Report errors: user32:msg prints too much data (35221 bytes)