From: Evan Tang etang@codeweavers.com
Windows sends a WM_INPUT_DEVICE_CHANGE for every matching connected device on registration --- dlls/user32/tests/input.c | 2 +- dlls/win32u/rawinput.c | 46 +++++++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index b0c4b699141..eb6419d7122 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2448,7 +2448,7 @@ static void test_GetRawInputBuffer(void) mouse_event(MOUSEEVENTF_MOVE, 4, 0, 0, 0); empty_message_queue(); ok(rawinputbuffer_wndproc_wm_input_count == 2, "Spurious WM_INPUT messages\n"); - todo_wine ok(rawinputbuffer_wndproc_wm_input_device_change_count == num_mice, "Got %d WM_INPUT_DEVICE_CHANGE messages (expected %d)\n", rawinputbuffer_wndproc_wm_input_device_change_count, num_mice); + ok(rawinputbuffer_wndproc_wm_input_device_change_count == num_mice, "Got %d WM_INPUT_DEVICE_CHANGE messages (expected %d)\n", rawinputbuffer_wndproc_wm_input_device_change_count, num_mice);
raw_devices[0].dwFlags = RIDEV_REMOVE; raw_devices[0].hwndTarget = 0; diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 1ddbca0896a..2240237b378 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -828,7 +828,7 @@ static void register_rawinput_device( const RAWINPUTDEVICE *device ) /********************************************************************** * NtUserRegisterRawInputDevices (win32u.@) */ -BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT device_count, UINT device_size ) +BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *device_list, UINT device_count, UINT device_size ) { struct rawinput_device *server_devices; RAWINPUTDEVICE *new_registered_devices; @@ -836,7 +836,7 @@ BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT d BOOL ret; UINT i;
- TRACE( "devices %p, device_count %u, device_size %u.\n", devices, device_count, device_size ); + TRACE( "devices %p, device_count %u, device_size %u.\n", device_list, device_count, device_size );
if (device_size != sizeof(RAWINPUTDEVICE)) { @@ -846,23 +846,23 @@ BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT d
for (i = 0; i < device_count; ++i) { - TRACE( "device %u: page %#x, usage %#x, flags %#x, target %p.\n", i, devices[i].usUsagePage, - devices[i].usUsage, (int)devices[i].dwFlags, devices[i].hwndTarget ); + TRACE( "device %u: page %#x, usage %#x, flags %#x, target %p.\n", i, device_list[i].usUsagePage, + device_list[i].usUsage, (int)device_list[i].dwFlags, device_list[i].hwndTarget );
- if ((devices[i].dwFlags & RIDEV_INPUTSINK) && !devices[i].hwndTarget) + if ((device_list[i].dwFlags & RIDEV_INPUTSINK) && !device_list[i].hwndTarget) { RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); return FALSE; }
- if ((devices[i].dwFlags & RIDEV_REMOVE) && devices[i].hwndTarget) + if ((device_list[i].dwFlags & RIDEV_REMOVE) && device_list[i].hwndTarget) { RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); return FALSE; }
- if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK|RIDEV_DEVNOTIFY)) - FIXME( "Unhandled flags %#x for device %u.\n", (int)devices[i].dwFlags, i ); + if (device_list[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK|RIDEV_DEVNOTIFY)) + FIXME( "Unhandled flags %#x for device %u.\n", (int)device_list[i].dwFlags, i ); }
pthread_mutex_lock( &rawinput_mutex ); @@ -882,7 +882,7 @@ BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT d }
registered_devices = new_registered_devices; - for (i = 0; i < device_count; ++i) register_rawinput_device( devices + i ); + for (i = 0; i < device_count; ++i) register_rawinput_device( device_list + i );
if (!(device_count = registered_device_count)) server_devices = NULL; else if (!(server_devices = malloc( device_count * sizeof(*server_devices) ))) @@ -909,6 +909,34 @@ BOOL WINAPI NtUserRegisterRawInputDevices( const RAWINPUTDEVICE *devices, UINT d
free( server_devices );
+ if (ret) + { + // Send WM_INPUT_DEVICE_CHANGE for existing devices when registering for notifications + for (i = 0; i < device_count; ++i) + { + HWND hwnd = device_list[i].hwndTarget; + USHORT page = device_list[i].usUsagePage, usage = device_list[i].usUsage; + struct device *device; + if (!(device_list[i].dwFlags & RIDEV_DEVNOTIFY) || !hwnd) + continue; + + rawinput_update_device_list(); + LIST_FOR_EACH_ENTRY(device, &devices, struct device, entry) + { + BOOL matches = FALSE; + if (device->info.dwType == RIM_TYPEMOUSE) + matches = page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_MOUSE; + else if (device->info.dwType == RIM_TYPEKEYBOARD) + matches = page == HID_USAGE_PAGE_GENERIC && usage == HID_USAGE_GENERIC_KEYBOARD; + else if (device->info.dwType == RIM_TYPEHID) + matches = page == device->info.hid.usUsagePage && usage == device->info.hid.usUsage; + + if (matches) + NtUserPostMessage(hwnd, WM_INPUT_DEVICE_CHANGE, GIDC_ARRIVAL, (LPARAM)device->handle); + } + } + } + pthread_mutex_unlock( &rawinput_mutex );
return ret;