There's already some in dinput, but this is a more appropriate location.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/tests/input.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index bab0fd97536..52fd31501f8 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1765,6 +1765,7 @@ static void test_RegisterRawInputDevices(void) { HWND hwnd; RAWINPUTDEVICE raw_devices[1]; + UINT count, raw_devices_count; BOOL res;
raw_devices[0].usUsagePage = 0x01; @@ -1791,6 +1792,42 @@ static void test_RegisterRawInputDevices(void) ok(res == TRUE, "RegisterRawInputDevices failed\n"); ok(GetLastError() == 0xdeadbeef, "RegisterRawInputDevices returned %08x\n", GetLastError());
+ SetLastError(0xdeadbeef); + count = GetRegisteredRawInputDevices(NULL, NULL, 0); + todo_wine + ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + raw_devices_count = 0; + count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, 0); + todo_wine + ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); + ok(raw_devices_count == 0, "Unexpected registered devices count: %u\n", raw_devices_count); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + raw_devices_count = 0; + count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); + ok(count == 0, "GetRegisteredRawInputDevices returned %u\n", count); + todo_wine + ok(raw_devices_count == 1, "Unexpected registered devices count: %u\n", raw_devices_count); + ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); + + SetLastError(0xdeadbeef); + memset(raw_devices, 0, sizeof(raw_devices)); + raw_devices_count = ARRAY_SIZE(raw_devices); + count = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); + todo_wine + ok(count == 1, "GetRegisteredRawInputDevices returned %u\n", count); + ok(raw_devices_count == 1, "Unexpected registered devices count: %u\n", raw_devices_count); + ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); + todo_wine + ok(raw_devices[0].usUsagePage == 0x01, "Unexpected usage page: %x\n", raw_devices[0].usUsagePage); + todo_wine + ok(raw_devices[0].usUsage == 0x05, "Unexpected usage: %x\n", raw_devices[0].usUsage);
/* RIDEV_REMOVE requires hwndTarget == NULL */ raw_devices[0].dwFlags = RIDEV_REMOVE;
This is not strictly required but it'll help tracking the next patches results in the tests.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Rewrite a few error cases conditionals.
dlls/dinput8/tests/device.c | 13 ---------- dlls/user32/rawinput.c | 50 +++++++++++++++++++++++++++++++++++-- dlls/user32/tests/input.c | 8 ------ server/protocol.def | 6 +++++ server/queue.c | 21 ++++++++++++++++ 5 files changed, 75 insertions(+), 23 deletions(-)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 39c635f2fb9..328174e5796 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 b5af008e885..2c3c54b9c4f 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -732,14 +732,60 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT return *data_size; }
+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 *buffer = NULL; + unsigned int i, status, count = ~0U, buffer_size;
- return 0; + TRACE("devices %p, device_count %p, size %u\n", devices, device_count, size); + + if (!device_count || size != sizeof(RAWINPUTDEVICE)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ~0U; + } + + buffer_size = *device_count * sizeof(*buffer); + if (devices && !(buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size))) + return ~0U; + + SERVER_START_REQ(get_rawinput_devices) + { + if (buffer) wine_server_set_reply(req, buffer, buffer_size); + status = wine_server_call(req); + *device_count = reply->device_count; + } + SERVER_END_REQ; + + if (buffer && !status) + { + for (i = 0, count = *device_count; i < count; ++i) + { + devices[i].usUsagePage = buffer[i].usage_page; + devices[i].usUsage = buffer[i].usage; + devices[i].dwFlags = buffer[i].flags; + devices[i].hwndTarget = wine_server_ptr_handle(buffer[i].target); + } + + qsort(devices, count, sizeof(*devices), compare_raw_input_devices); + } + + if (buffer) HeapFree(GetProcessHeap(), 0, buffer); + else count = 0; + return count; }
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 52fd31501f8..7e31b3e3de1 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1794,25 +1794,20 @@ static void test_RegisterRawInputDevices(void)
SetLastError(0xdeadbeef); count = GetRegisteredRawInputDevices(NULL, NULL, 0); - todo_wine ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError());
SetLastError(0xdeadbeef); raw_devices_count = 0; count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, 0); - todo_wine ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); ok(raw_devices_count == 0, "Unexpected registered devices count: %u\n", raw_devices_count); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError());
SetLastError(0xdeadbeef); raw_devices_count = 0; count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); ok(count == 0, "GetRegisteredRawInputDevices returned %u\n", count); - todo_wine ok(raw_devices_count == 1, "Unexpected registered devices count: %u\n", raw_devices_count); ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError());
@@ -1820,13 +1815,10 @@ static void test_RegisterRawInputDevices(void) memset(raw_devices, 0, sizeof(raw_devices)); raw_devices_count = ARRAY_SIZE(raw_devices); count = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(count == 1, "GetRegisteredRawInputDevices returned %u\n", count); ok(raw_devices_count == 1, "Unexpected registered devices count: %u\n", raw_devices_count); ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); - todo_wine ok(raw_devices[0].usUsagePage == 0x01, "Unexpected usage page: %x\n", raw_devices[0].usUsagePage); - todo_wine ok(raw_devices[0].usUsage == 0x05, "Unexpected usage: %x\n", raw_devices[0].usUsage);
/* RIDEV_REMOVE requires hwndTarget == NULL */ diff --git a/server/protocol.def b/server/protocol.def index 6416306c0a1..56fda14932d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3899,6 +3899,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
/* Create a new job object */ @REQ(create_job) diff --git a/server/queue.c b/server/queue.c index 432885f9e4c..5f27e449e8c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -3283,3 +3283,24 @@ DECL_HANDLER(update_rawinput_devices) e = find_rawinput_device( 1, 6 ); current->process->rawinput_kbd = e ? &e->device : NULL; } + +DECL_HANDLER(get_rawinput_devices) +{ + struct rawinput_device_entry *e; + struct rawinput_device *devices; + unsigned int i = 0, device_count = list_count( ¤t->process->rawinput_devices ); + unsigned int size = device_count * sizeof(*devices); + + reply->device_count = device_count; + if (!get_reply_max_size()) return; + + if (size > get_reply_max_size()) + set_error( STATUS_NO_MEMORY ); + else if ((devices = mem_alloc( size ))) + { + LIST_FOR_EACH_ENTRY( e, ¤t->process->rawinput_devices, struct rawinput_device_entry, entry ) + devices[i++] = e->device; + + set_reply_data_ptr( devices, size ); + } +}
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=74709
Your paranoid android.
=== debiant (32 bit report) ===
user32: monitor: Timeout msg: Timeout
=== debiant (32 bit Chinese:China report) ===
user32: monitor: Timeout msg: Timeout resource: Timeout scroll: Timeout static: Timeout
=== debiant (32 bit WoW report) ===
user32: monitor: Timeout msg: Timeout resource: Timeout scroll: Timeout static: Timeout sysparams: Timeout text: Timeout
=== debiant (64 bit WoW report) ===
user32: input.c:2514: Test failed: 4: Unexpected cursor movement input.c:2514: Test failed: 5: Unexpected cursor movement input.c:2514: Test failed: 6: Unexpected cursor movement input.c:2514: Test failed: 7: Unexpected cursor movement input.c:2514: Test failed: 8: Unexpected cursor movement input.c:2235: Test failed: 9: foreground process expected WM_MOUSEMOVE message input.c:2514: Test failed: 9: Unexpected cursor movement input.c:2235: Test failed: 10: foreground process expected WM_MOUSEMOVE message input.c:2514: Test failed: 10: Unexpected cursor movement input.c:2235: Test failed: 11input.c: foreground process expected WM_MOUSEMOVE message :2514: Test failed: 11: Unexpected cursor movement input.c:2235input.c: Test failed: :122514: foreground process expected WM_MOUSEMOVE message : Test failed: 12: Unexpected cursor movement input.c:2514: Test failed: 13: Unexpected cursor movement input.c:2514: Test failed: 14: Unexpected cursor movement input.c:2514: Test failed: 15: Unexpected cursor movement input.c:2514: Test failed: 16: Unexpected cursor movement monitor: Timeout msg: Timeout resource: Timeout scroll: Timeout static: Timeout
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput8/tests/device.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 328174e5796..6fe9a635510 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -712,6 +712,26 @@ static void test_mouse_keyboard(void) todo_wine ok(raw_devices_count == 1, "Unexpected raw devices registered: %d\n", raw_devices_count);
+ IDirectInputDevice8_SetCooperativeLevel(di_mouse, hwnd, DISCL_FOREGROUND|DISCL_EXCLUSIVE); + IDirectInputDevice8_SetCooperativeLevel(di_keyboard, hwnd, DISCL_FOREGROUND|DISCL_EXCLUSIVE); + + hr = IDirectInputDevice8_Acquire(di_keyboard); + ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); + hr = IDirectInputDevice8_Acquire(di_mouse); + ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); + raw_devices_count = ARRAY_SIZE(raw_devices); + memset(raw_devices, 0, sizeof(raw_devices)); + hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); + ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); + todo_wine + ok(raw_devices[0].dwFlags == (RIDEV_CAPTUREMOUSE|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); + todo_wine + ok(raw_devices[2].dwFlags == (RIDEV_NOHOTKEYS|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags); + hr = IDirectInputDevice8_Unacquire(di_keyboard); + ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); + hr = IDirectInputDevice8_Unacquire(di_mouse); + ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); + raw_devices_count = ARRAY_SIZE(raw_devices); hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); todo_wine
This adds a message window that will be used as the rawinput target window for WM_INPUT messages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Rewrite GetRawInputData return value check.
dlls/dinput/device_private.h | 3 ++ dlls/dinput/dinput_main.c | 77 ++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+)
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index fe5644f21c7..2fac4f0e61e 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -69,6 +69,9 @@ struct IDirectInputDeviceImpl HWND win; int acquired;
+ 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; /* valid size of the queue */ 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 2e561502406..cd1a11b02fb 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -97,6 +97,9 @@ static const struct dinput_device *dinput_devices[] =
HINSTANCE DINPUT_instance;
+static const WCHAR di_em_win_w[] = {'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 ); @@ -637,6 +640,45 @@ 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) +{ + IDirectInputDeviceImpl *dev; + RAWINPUT ri; + UINT size = sizeof(ri); + int rim = GET_RAWINPUT_CODE_WPARAM( wparam ); + + TRACE( "%p %d %lx %lx\n", hwnd, msg, wparam, lparam ); + + if (msg == WM_INPUT && (rim == RIM_INPUT || rim == RIM_INPUTSINK)) + { + size = GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER) ); + if (size == (UINT)-1 || size < sizeof(RAWINPUTHEADER)) + WARN( "Unable to read raw input data\n" ); + } + + return DefWindowProcW( hwnd, msg, wparam, lparam ); +} + +static void register_di_em_win_class(void) +{ + WNDCLASSEXW class; + + memset(&class, 0, sizeof(class)); + class.cbSize = sizeof(class); + class.lpfnWndProc = di_em_win_wndproc; + class.hInstance = DINPUT_instance; + class.lpszClassName = di_em_win_w; + + if (!RegisterClassExW( &class ) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) + WARN( "Unable to register message window class\n" ); +} + +static void unregister_di_em_win_class(void) +{ + if (!UnregisterClassW( di_em_win_w, NULL ) && GetLastError() != ERROR_CLASS_DOES_NOT_EXIST) + WARN( "Unable to unregister message window class\n" ); +} + static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwVersion) { if (!This->initialized) @@ -1668,11 +1710,13 @@ static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam ) EnterCriticalSection( &dinput_hook_crit ); LIST_FOR_EACH_ENTRY( dev, &acquired_mouse_list, IDirectInputDeviceImpl, entry ) { + if (dev->use_raw_input) continue; TRACE("calling dinput_mouse_hook (%p %lx %lx)\n", dev, wparam, lparam); skip |= dinput_mouse_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam ); } LIST_FOR_EACH_ENTRY( dev, &acquired_keyboard_list, IDirectInputDeviceImpl, entry ) { + if (dev->use_raw_input) continue; TRACE("calling dinput_keyboard_hook (%p %lx %lx)\n", dev, wparam, lparam); skip |= dinput_keyboard_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam ); } @@ -1728,6 +1772,9 @@ static DWORD WINAPI hook_thread_proc(void *param) static HHOOK kbd_hook, mouse_hook; MSG msg;
+ di_em_win = CreateWindowW( di_em_win_w, di_em_win_w, 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); @@ -1778,6 +1825,9 @@ static DWORD WINAPI hook_thread_proc(void *param) DispatchMessageW(&msg); }
+ DestroyWindow( di_em_win ); + di_em_win = NULL; + FreeLibraryAndExitThread(DINPUT_instance, 0); }
@@ -1860,6 +1910,31 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired) hook_thread_event = NULL; }
+ if (dev->use_raw_input) + { + if (acquired) + { + dev->raw_device.dwFlags = 0; + if (dev->dwCoopLevel & DISCL_BACKGROUND) + dev->raw_device.dwFlags |= RIDEV_INPUTSINK; + if (dev->dwCoopLevel & DISCL_EXCLUSIVE) + dev->raw_device.dwFlags |= RIDEV_NOLEGACY; + if ((dev->dwCoopLevel & DISCL_EXCLUSIVE) && dev->raw_device.usUsage == 2) + dev->raw_device.dwFlags |= RIDEV_CAPTUREMOUSE; + if ((dev->dwCoopLevel & DISCL_EXCLUSIVE) && dev->raw_device.usUsage == 6) + dev->raw_device.dwFlags |= RIDEV_NOHOTKEYS; + dev->raw_device.hwndTarget = di_em_win; + } + else + { + dev->raw_device.dwFlags = RIDEV_REMOVE; + dev->raw_device.hwndTarget = NULL; + } + + 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 ); + } + if (acquired) hook_change_finished_event = CreateEventW( NULL, FALSE, FALSE, NULL ); PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, (LPARAM)hook_change_finished_event ); @@ -1894,9 +1969,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; }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/dinput_main.c | 10 ++++ dlls/dinput/dinput_private.h | 1 + dlls/dinput/mouse.c | 90 ++++++++++++++++++++++++++++++++++++ dlls/dinput8/tests/device.c | 11 ++--- 4 files changed, 104 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index cd1a11b02fb..1c4a26987f9 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -654,6 +654,16 @@ static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR size = GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER) ); if (size == (UINT)-1 || size < sizeof(RAWINPUTHEADER)) WARN( "Unable to read raw input data\n" ); + else if (ri.header.dwType == RIM_TYPEMOUSE) + { + EnterCriticalSection( &dinput_hook_crit ); + LIST_FOR_EACH_ENTRY( dev, &acquired_mouse_list, IDirectInputDeviceImpl, entry ) + { + if (!dev->use_raw_input) continue; + dinput_mouse_rawinput_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam, &ri ); + } + LeaveCriticalSection( &dinput_hook_crit ); + } }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h index 06a439d6a41..c0c88da9674 100644 --- a/dlls/dinput/dinput_private.h +++ b/dlls/dinput/dinput_private.h @@ -73,6 +73,7 @@ extern void dinput_hooks_acquire_device(LPDIRECTINPUTDEVICE8W iface); extern void dinput_hooks_unacquire_device(LPDIRECTINPUTDEVICE8W iface); extern int dinput_mouse_hook(LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam); extern int dinput_keyboard_hook(LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam); +extern void dinput_mouse_rawinput_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam, RAWINPUT *raw );
extern void check_dinput_hooks(LPDIRECTINPUTDEVICE8W, BOOL) DECLSPEC_HIDDEN; extern void check_dinput_events(void) DECLSPEC_HIDDEN; diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index 5e6f34f0eca..e50731fda41 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -239,6 +239,13 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) newDevice->base.data_format.wine_df = df; IDirectInput_AddRef(&newDevice->base.dinput->IDirectInput7A_iface);
+ 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: @@ -306,6 +313,89 @@ const struct dinput_device mouse_device = { * SysMouseA (DInput Mouse support) */
+void dinput_mouse_rawinput_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam, RAWINPUT *ri ) +{ + SysMouseImpl* This = impl_from_IDirectInputDevice8A( iface ); + POINT rel, pt; + DWORD seq; + int i, wdata = 0; + + 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 ); + + if (ri->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) + FIXME( "Unimplemented MOUSE_VIRTUAL_DESKTOP flag\n" ); + if (ri->data.mouse.usFlags & MOUSE_ATTRIBUTES_CHANGED) + FIXME( "Unimplemented MOUSE_ATTRIBUTES_CHANGED flag\n" ); + + EnterCriticalSection( &This->base.crit ); + seq = This->base.dinput->evsequence++; + + rel.x = ri->data.mouse.lLastX; + rel.y = ri->data.mouse.lLastY; + if (ri->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(), seq ); + + if (rel.y) + queue_event( iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, + pt.y, GetCurrentTime(), seq ); + + 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 (ri->data.mouse.usButtonFlags & RI_MOUSE_WHEEL) + { + This->m_state.lZ += (wdata = (SHORT)ri->data.mouse.usButtonData); + queue_event( iface, DIDFT_MAKEINSTANCE(WINE_MOUSE_Z_AXIS_INSTANCE) | DIDFT_RELAXIS, + wdata, GetCurrentTime(), seq ); + } + + for (i = 0; i < ARRAY_SIZE(mouse_button_flags); ++i) + { + if (ri->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(), seq ); + } + } + + LeaveCriticalSection( &This->base.crit ); +} + /* low-level mouse hook */ int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam ) { diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 6fe9a635510..80a7fe26c3b 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -646,13 +646,9 @@ 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); @@ -662,6 +658,9 @@ static void test_mouse_keyboard(void) GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
+ if (raw_devices[0].hwndTarget != NULL) + di_hwnd = raw_devices[0].hwndTarget; + /* expect dinput8 to take over any activated raw input devices */ raw_devices[0].usUsagePage = 0x01; raw_devices[0].usUsage = 0x05; @@ -689,9 +688,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); @@ -723,7 +720,6 @@ static void test_mouse_keyboard(void) memset(raw_devices, 0, sizeof(raw_devices)); hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); - todo_wine ok(raw_devices[0].dwFlags == (RIDEV_CAPTUREMOUSE|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); todo_wine ok(raw_devices[2].dwFlags == (RIDEV_NOHOTKEYS|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags); @@ -737,7 +733,6 @@ static void test_mouse_keyboard(void) 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);
LL hooks are heavy and using them cause performance hit with high polling rate mice. We don't need them anymore since we now use rawinput API for mouse device.
This also uses a separate list for rawinput mouse devices.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/dinput_main.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 1c4a26987f9..45023fc104a 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -104,6 +104,7 @@ static BOOL check_hook_thread(void); static CRITICAL_SECTION dinput_hook_crit; static struct list direct_input_list = LIST_INIT( direct_input_list ); static struct list acquired_mouse_list = LIST_INIT( acquired_mouse_list ); +static struct list acquired_rawmouse_list = LIST_INIT( acquired_rawmouse_list ); static struct list acquired_keyboard_list = LIST_INIT( acquired_keyboard_list ); static struct list acquired_device_list = LIST_INIT( acquired_device_list );
@@ -116,7 +117,7 @@ void dinput_hooks_acquire_device(LPDIRECTINPUTDEVICE8W iface)
EnterCriticalSection( &dinput_hook_crit ); if (IsEqualGUID( &dev->guid, &GUID_SysMouse )) - list_add_tail( &acquired_mouse_list, &dev->entry ); + list_add_tail( dev->use_raw_input ? &acquired_rawmouse_list : &acquired_mouse_list, &dev->entry ); else if (IsEqualGUID( &dev->guid, &GUID_SysKeyboard )) list_add_tail( &acquired_keyboard_list, &dev->entry ); else @@ -657,11 +658,8 @@ static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR else if (ri.header.dwType == RIM_TYPEMOUSE) { EnterCriticalSection( &dinput_hook_crit ); - LIST_FOR_EACH_ENTRY( dev, &acquired_mouse_list, IDirectInputDeviceImpl, entry ) - { - if (!dev->use_raw_input) continue; + LIST_FOR_EACH_ENTRY( dev, &acquired_rawmouse_list, IDirectInputDeviceImpl, entry ) dinput_mouse_rawinput_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam, &ri ); - } LeaveCriticalSection( &dinput_hook_crit ); } } @@ -1720,7 +1718,6 @@ static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam ) EnterCriticalSection( &dinput_hook_crit ); LIST_FOR_EACH_ENTRY( dev, &acquired_mouse_list, IDirectInputDeviceImpl, entry ) { - if (dev->use_raw_input) continue; TRACE("calling dinput_mouse_hook (%p %lx %lx)\n", dev, wparam, lparam); skip |= dinput_mouse_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam ); } @@ -1764,6 +1761,14 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8A_iface ); } } + LIST_FOR_EACH_ENTRY_SAFE( dev, next, &acquired_rawmouse_list, IDirectInputDeviceImpl, entry ) + { + if (msg->hwnd == dev->win && msg->hwnd != foreground) + { + TRACE( "%p window is not foreground - unacquiring %p\n", dev->win, dev ); + IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8A_iface ); + } + } LIST_FOR_EACH_ENTRY_SAFE( dev, next, &acquired_keyboard_list, IDirectInputDeviceImpl, entry ) { if (msg->hwnd == dev->win && msg->hwnd != foreground)