diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 725b6185..45f9ff9c 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -240,6 +240,9 @@ patch_enable_all () enable_user32_ScrollWindowEx="$1" enable_user32_message_order="$1" enable_user32_msgbox_Support_WM_COPY_mesg="$1" + enable_user32_rawinput_hid="$1" + enable_user32_rawinput_mouse="$1" + enable_user32_rawinput_mouse_experimental="$1" enable_user32_recursive_activation="$1" enable_uxtheme_CloseThemeClass="$1" enable_version_VerQueryValue="$1" @@ -777,6 +780,15 @@ patch_enable () user32-msgbox-Support-WM_COPY-mesg) enable_user32_msgbox_Support_WM_COPY_mesg="$2" ;; + user32-rawinput-hid) + enable_user32_rawinput_hid="$2" + ;; + user32-rawinput-mouse) + enable_user32_rawinput_mouse="$2" + ;; + user32-rawinput-mouse-experimental) + enable_user32_rawinput_mouse_experimental="$2" + ;; user32-recursive-activation) enable_user32_recursive_activation="$2" ;; @@ -1320,6 +1332,27 @@ if test "$enable_wineboot_ProxySettings" -eq 1; then enable_wineboot_drivers_etc_Stubs=1 fi +if test "$enable_user32_rawinput_mouse_experimental" -eq 1; then + if test "$enable_user32_rawinput_mouse" -gt 1; then + abort "Patchset user32-rawinput-mouse disabled, but user32-rawinput-mouse-experimental depends on that." + fi + enable_user32_rawinput_mouse=1 +fi + +if test "$enable_user32_rawinput_mouse" -eq 1; then + if test "$enable_user32_rawinput_hid" -gt 1; then + abort "Patchset user32-rawinput-hid disabled, but user32-rawinput-mouse depends on that." + fi + enable_user32_rawinput_hid=1 +fi + +if test "$enable_user32_rawinput_hid" -eq 1; then + if test "$enable_loader_KeyboardLayouts" -gt 1; then + abort "Patchset loader-KeyboardLayouts disabled, but user32-rawinput-hid depends on that." + fi + enable_loader_KeyboardLayouts=1 +fi + if test "$enable_stdole32_tlb_SLTG_Typelib" -eq 1; then if test "$enable_widl_SLTG_Typelib_Support" -gt 1; then abort "Patchset widl-SLTG_Typelib_Support disabled, but stdole32.tlb-SLTG_Typelib depends on that." @@ -3864,6 +3897,89 @@ if test "$enable_user32_msgbox_Support_WM_COPY_mesg" -eq 1; then patch_apply user32-msgbox-Support-WM_COPY-mesg/0002-user32-msgbox-Use-a-windows-hook-to-trap-Ctrl-C.patch fi +# Patchset user32-rawinput-hid +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * loader-KeyboardLayouts +# | +# | This patchset fixes the following Wine bugs: +# | * [#50506] WM_INPUT messages are not received for HID devices registered with RegisterRawInputDevices +# | +# | Modified files: +# | * dlls/hidclass.sys/Makefile.in, dlls/hidclass.sys/device.c, dlls/hidclass.sys/hid.h, dlls/hidclass.sys/pnp.c, +# | dlls/ntoskrnl.exe/ntoskrnl.exe.spec, dlls/ntoskrnl.exe/pnp.c, dlls/user32/input.c, dlls/user32/message.c, +# | dlls/user32/rawinput.c, dlls/user32/tests/input.c, dlls/user32/user32.spec, dlls/user32/user_private.h, +# | dlls/wineandroid.drv/keyboard.c, dlls/wineandroid.drv/window.c, dlls/winemac.drv/ime.c, dlls/winemac.drv/keyboard.c, +# | dlls/winemac.drv/mouse.c, dlls/winex11.drv/keyboard.c, dlls/winex11.drv/mouse.c, include/ddk/wdm.h, include/winuser.h, +# | server/protocol.def, server/queue.c, server/trace.c +# | +if test "$enable_user32_rawinput_hid" -eq 1; then + patch_apply user32-rawinput-hid/0001-user32-tests-Add-more-SendInput-tests.patch + patch_apply user32-rawinput-hid/0002-user32-Implement-SendInput-INPUT_HARDWARE-check.patch + patch_apply user32-rawinput-hid/0003-user32-Add-RAWINPUT-parameter-to-__wine_send_input.patch + patch_apply user32-rawinput-hid/0004-hidclass.sys-Assign-rawinput-device-handle-in-HID_Li.patch + patch_apply user32-rawinput-hid/0005-hidclass.sys-Use-__wine_send_input-to-send-device-no.patch + patch_apply user32-rawinput-hid/0006-server-Implement-desktop-broadcast-in-queue_rawinput.patch + patch_apply user32-rawinput-hid/0007-server-Add-rawinput-union-to-hw_input_t-INPUT_HARDWA.patch + patch_apply user32-rawinput-hid/0008-server-Add-RIM_TYPEHID-type-hid-member-to-rawinput-u.patch + patch_apply user32-rawinput-hid/0009-user32-Send-WM_INPUT_DEVICE_CHANGE-RAWINPUT-to-the-s.patch + patch_apply user32-rawinput-hid/0010-server-Track-known-HID-rawinput-devices-on-addition-.patch + patch_apply user32-rawinput-hid/0011-server-Add-process-argument-to-find_rawinput_device.patch + patch_apply user32-rawinput-hid/0012-server-Implement-WM_INPUT_DEVICE_CHANGE-message-disp.patch + patch_apply user32-rawinput-hid/0013-hidclass.sys-Send-rawinput-messages-with-HID-report.patch + patch_apply user32-rawinput-hid/0014-server-Add-extra-data-to-hardware_msg_data.patch + patch_apply user32-rawinput-hid/0015-server-Implement-WM_INPUT-RIM_TYPEHID-message-dispat.patch + patch_apply user32-rawinput-hid/0016-ntoskrnl-Implement-IoSetDevicePropertyData.patch + patch_apply user32-rawinput-hid/0017-hidclass.sys-Assign-rawinput-handles-through-device-.patch + patch_apply user32-rawinput-hid/0018-user32-Enumerate-mouse-rawinput-device-before-HID-de.patch + patch_apply user32-rawinput-hid/0019-user32-Use-device-handles-assigned-by-hidclass.sys.patch +fi + +# Patchset user32-rawinput-mouse +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * loader-KeyboardLayouts, user32-rawinput-hid +# | +# | This patchset fixes the following Wine bugs: +# | * [#42631] Mouse drift, jump or don't react to small slow movements in Unity-engine games and Fallout 4 (partly fixed in +# | Unity games, have walkaround in Fallout4 ) +# | * [#42675] Overwatch: Phantom mouse input / view pulled up to ceiling +# | +# | Modified files: +# | * dlls/user32/input.c, dlls/user32/message.c, dlls/wineandroid.drv/keyboard.c, dlls/wineandroid.drv/window.c, +# | dlls/winemac.drv/ime.c, dlls/winemac.drv/keyboard.c, dlls/winemac.drv/mouse.c, dlls/winex11.drv/desktop.c, +# | dlls/winex11.drv/event.c, dlls/winex11.drv/keyboard.c, dlls/winex11.drv/mouse.c, dlls/winex11.drv/window.c, +# | dlls/winex11.drv/x11drv.h, dlls/winex11.drv/x11drv_main.c, server/protocol.def, server/queue.c +# | +if test "$enable_user32_rawinput_mouse" -eq 1; then + patch_apply user32-rawinput-mouse/0001-winex11.drv-Split-XInput2-thread-initialization.patch + patch_apply user32-rawinput-mouse/0002-winex11.drv-Support-XInput2-events-for-individual-wi.patch + patch_apply user32-rawinput-mouse/0003-winex11.drv-Advertise-XInput2-version-2.1-support.patch + patch_apply user32-rawinput-mouse/0004-winex11.drv-Keep-track-of-pointer-and-device-button-.patch + patch_apply user32-rawinput-mouse/0005-server-Add-send_hardware_message-flags-for-rawinput-.patch + patch_apply user32-rawinput-mouse/0006-user32-Set-SEND_HWMSG_RAWINPUT-flags-only-when-RAWIN.patch + patch_apply user32-rawinput-mouse/0007-user32-Support-sending-RIM_TYPEMOUSE-through-__wine_.patch + patch_apply user32-rawinput-mouse/0008-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch +fi + +# Patchset user32-rawinput-mouse-experimental +# | +# | This patchset has the following (direct or indirect) dependencies: +# | * loader-KeyboardLayouts, user32-rawinput-hid, user32-rawinput-mouse +# | +# | This patchset fixes the following Wine bugs: +# | * [#45882] - Raw Input should use untransformed mouse values (affects Overwatch, several Source games). +# | +# | Modified files: +# | * dlls/user32/rawinput.c, dlls/winex11.drv/mouse.c, dlls/winex11.drv/window.c, dlls/winex11.drv/x11drv.h, +# | dlls/winex11.drv/x11drv_main.c, server/queue.c +# | +if test "$enable_user32_rawinput_mouse_experimental" -eq 1; then + patch_apply user32-rawinput-mouse-experimental/0001-winex11.drv-Add-support-for-absolute-RawMotion-event.patch + patch_apply user32-rawinput-mouse-experimental/0002-winex11.drv-Send-relative-RawMotion-events-unprocess.patch + patch_apply user32-rawinput-mouse-experimental/0003-winex11.drv-Accumulate-mouse-movement-to-avoid-round.patch +fi + # Patchset user32-recursive-activation # | # | This patchset fixes the following Wine bugs: diff --git a/patches/user32-rawinput-hid/0001-user32-tests-Add-more-SendInput-tests.patch b/patches/user32-rawinput-hid/0001-user32-tests-Add-more-SendInput-tests.patch new file mode 100644 index 00000000..22c19908 --- /dev/null +++ b/patches/user32-rawinput-hid/0001-user32-tests-Add-more-SendInput-tests.patch @@ -0,0 +1,185 @@ +From ce4894689736dc2e49b2b7550802ab1f2a4eb462 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 9 Mar 2021 12:02:18 +0100 +Subject: [PATCH] user32/tests: Add more SendInput tests. + +Validating that SendInput with INPUT_HARDWARE type should be no-op. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/user32/input.c | 18 ++++++ + dlls/user32/tests/input.c | 122 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 140 insertions(+) + +diff --git a/dlls/user32/input.c b/dlls/user32/input.c +index 8992c463c48..22e53585f00 100644 +--- a/dlls/user32/input.c ++++ b/dlls/user32/input.c +@@ -182,6 +182,24 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) + UINT i; + NTSTATUS status; + ++ if (size != sizeof(INPUT)) ++ { ++ SetLastError( ERROR_INVALID_PARAMETER ); ++ return 0; ++ } ++ ++ if (!count) ++ { ++ SetLastError( ERROR_INVALID_PARAMETER ); ++ return 0; ++ } ++ ++ if (!inputs) ++ { ++ SetLastError( ERROR_NOACCESS ); ++ return 0; ++ } ++ + for (i = 0; i < count; i++) + { + if (inputs[i].type == INPUT_MOUSE) +diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c +index 06f90291fd1..0584f89f55a 100644 +--- a/dlls/user32/tests/input.c ++++ b/dlls/user32/tests/input.c +@@ -4246,6 +4246,127 @@ static void test_GetKeyboardLayoutList(void) + } + } + ++static void test_SendInput(void) ++{ ++ 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(); ++ ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 0, NULL, 0 ); ++ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 1, NULL, 0 ); ++ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 1, NULL, sizeof(*input) ); ++ ok( res == 0 && (GetLastError() == ERROR_NOACCESS || GetLastError() == ERROR_INVALID_PARAMETER), ++ "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 0, input, sizeof(*input) ); ++ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 0, NULL, sizeof(*input) ); ++ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ ++ memset( input, 0, sizeof(input) ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 1, input, sizeof(*input) ); ++ ok( res == 1 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 16, input, sizeof(*input) ); ++ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 1, input, 0 ); ++ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 1, input, sizeof(*input) + 1 ); ++ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 1, input, sizeof(*input) - 1 ); ++ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, 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 %#x\n", res, GetLastError() ); ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 16, input, sizeof(*input) ); ++ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ empty_message_queue(); ++ ++ 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 %#x\n", res, GetLastError() ); ++ ++ input[0].hi.uMsg = WM_KEYDOWN; ++ input[0].hi.wParamL = 0; ++ input[0].hi.wParamH = 'A'; ++ input[1].hi.uMsg = WM_KEYUP; ++ input[1].hi.wParamL = 0; ++ input[1].hi.wParamH = 'A' | 0xc000; ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 16, input, sizeof(*input) ); ++#ifdef _WIN64 ++ todo_wine ++ ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++#else ++ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++#endif ++ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); ++ todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); ++ empty_message_queue(); ++ ++ memset( input, 0, sizeof(input) ); ++ input[0].type = INPUT_HARDWARE; ++ input[1].type = INPUT_KEYBOARD; ++ input[1].ki.wVk = 'A'; ++ input[1].ki.dwFlags = 0; ++ input[2].type = INPUT_KEYBOARD; ++ input[2].ki.wVk = 'A'; ++ input[2].ki.dwFlags = KEYEVENTF_KEYUP; ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 16, input, sizeof(*input) ); ++#ifdef _WIN64 ++ todo_wine ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); ++ todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); ++ empty_message_queue(); ++#else ++ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); ++ ok( !!res, "SendInput did not trigger any message\n" ); ++ todo_wine ok( msg.message == WM_KEYDOWN, "SendInput triggered unexpected message %#x\n", msg.message ); ++ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); ++ ok( !!res, "SendInput did not trigger any message\n" ); ++ todo_wine ok( msg.message == WM_KEYUP, "SendInput triggered unexpected message %#x\n", msg.message ); ++ empty_message_queue(); ++#endif ++ ++ for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE + 1; ++ SetLastError( 0xdeadbeef ); ++ res = SendInput( 16, input, sizeof(*input) ); ++ todo_wine ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); ++ todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); ++ empty_message_queue(); ++ ++ trace( "done\n" ); ++ DestroyWindow( hwnd ); ++} ++ + START_TEST(input) + { + char **argv; +@@ -4268,6 +4389,7 @@ START_TEST(input) + return; + } + ++ test_SendInput(); + test_Input_blackbox(); + test_Input_whitebox(); + test_Input_unicode(); +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0002-user32-Implement-SendInput-INPUT_HARDWARE-check.patch b/patches/user32-rawinput-hid/0002-user32-Implement-SendInput-INPUT_HARDWARE-check.patch new file mode 100644 index 00000000..7e4fd228 --- /dev/null +++ b/patches/user32-rawinput-hid/0002-user32-Implement-SendInput-INPUT_HARDWARE-check.patch @@ -0,0 +1,106 @@ +From d9554c180611116398e700ed7f2d8f021bd06924 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 7 Apr 2021 10:34:23 +0200 +Subject: [PATCH] user32: Implement SendInput INPUT_HARDWARE check. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/user32/input.c | 16 ++++++++++++---- + dlls/user32/tests/input.c | 15 +++++++-------- + 2 files changed, 19 insertions(+), 12 deletions(-) + +diff --git a/dlls/user32/input.c b/dlls/user32/input.c +index 22e53585f00..e97264960ea 100644 +--- a/dlls/user32/input.c ++++ b/dlls/user32/input.c +@@ -180,7 +180,7 @@ static void update_mouse_coords( INPUT *input ) + UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) + { + UINT i; +- NTSTATUS status; ++ NTSTATUS status = STATUS_SUCCESS; + + if (size != sizeof(INPUT)) + { +@@ -202,14 +202,22 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) + + for (i = 0; i < count; i++) + { +- if (inputs[i].type == INPUT_MOUSE) ++ INPUT input = inputs[i]; ++ switch (input.type) + { ++ case INPUT_MOUSE: + /* we need to update the coordinates to what the server expects */ +- INPUT input = inputs[i]; + update_mouse_coords( &input ); ++ /* fallthrough */ ++ case INPUT_KEYBOARD: + status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED ); ++ break; ++#ifdef _WIN64 ++ case INPUT_HARDWARE: ++ SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); ++ return 0; ++#endif + } +- else status = send_hardware_message( 0, &inputs[i], SEND_HWMSG_INJECTED ); + + if (status) + { +diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c +index f48807a27a0..564ab2e1ba0 100644 +--- a/dlls/user32/tests/input.c ++++ b/dlls/user32/tests/input.c +@@ -4286,13 +4286,12 @@ static void test_SendInput(void) + SetLastError( 0xdeadbeef ); + res = SendInput( 16, input, sizeof(*input) ); + #ifdef _WIN64 +- todo_wine + ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() ); + #else + ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); + #endif + while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); +- todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); ++ ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); + empty_message_queue(); + + memset( input, 0, sizeof(input) ); +@@ -4306,27 +4305,27 @@ static void test_SendInput(void) + SetLastError( 0xdeadbeef ); + res = SendInput( 16, input, sizeof(*input) ); + #ifdef _WIN64 +- todo_wine ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() ); + while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); +- todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); ++ ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); + empty_message_queue(); + #else + ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); + while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); + ok( !!res, "SendInput did not trigger any message\n" ); +- todo_wine ok( msg.message == WM_KEYDOWN, "SendInput triggered unexpected message %#x\n", msg.message ); ++ ok( msg.message == WM_KEYDOWN, "SendInput triggered unexpected message %#x\n", msg.message ); + while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); + ok( !!res, "SendInput did not trigger any message\n" ); +- todo_wine ok( msg.message == WM_KEYUP, "SendInput triggered unexpected message %#x\n", msg.message ); ++ ok( msg.message == WM_KEYUP, "SendInput triggered unexpected message %#x\n", msg.message ); + empty_message_queue(); + #endif + + for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE + 1; + SetLastError( 0xdeadbeef ); + res = SendInput( 16, input, sizeof(*input) ); +- todo_wine ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); ++ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() ); + while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg); +- todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); ++ ok( !res, "SendInput triggered unexpected message %#x\n", msg.message ); + empty_message_queue(); + + trace( "done\n" ); +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0003-server-Make-it-possible-to-queue-rawinput-message-on.patch b/patches/user32-rawinput-hid/0003-server-Make-it-possible-to-queue-rawinput-message-on.patch deleted file mode 100644 index e120ed38..00000000 --- a/patches/user32-rawinput-hid/0003-server-Make-it-possible-to-queue-rawinput-message-on.patch +++ /dev/null @@ -1,64 +0,0 @@ -From eee5ecbed5c813be03d4b540675f1c4792101567 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Mon, 11 Nov 2019 18:35:18 +0100 -Subject: [PATCH] server: Make it possible to queue rawinput message on all - desktops. - ---- - server/queue.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/server/queue.c b/server/queue.c -index f5d19031485..59c6cbb6921 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -1658,8 +1658,8 @@ static int queue_rawinput_message( struct process* process, void *arg ) - { - const struct rawinput_message* raw_msg = arg; - const struct rawinput_device *device = NULL; -- struct desktop *target_desktop = NULL; -- struct thread *target_thread = NULL; -+ struct desktop *target_desktop = NULL, *desktop = NULL; -+ struct thread *target_thread = NULL, *foreground = NULL; - struct message *msg; - struct hardware_msg_data *msg_data; - int wparam = RIM_INPUT; -@@ -1670,12 +1670,18 @@ static int queue_rawinput_message( struct process* process, void *arg ) - device = process->rawinput_kbd; - if (!device) return 0; - -- if (process != raw_msg->foreground->process) -+ if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop ); -+ else if (!(desktop = get_desktop_obj( process, process->desktop, 0 ))) goto done; -+ -+ if (raw_msg->foreground) foreground = (struct thread *)grab_object( raw_msg->foreground ); -+ else if (!(foreground = get_foreground_thread( desktop, 0 ))) goto done; -+ -+ if (process != foreground->process) - { - if (!(device->flags & RIDEV_INPUTSINK)) goto done; - if (!(target_thread = get_window_thread( device->target ))) goto done; - if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done; -- if (target_desktop != raw_msg->desktop) goto done; -+ if (target_desktop != desktop) goto done; - wparam = RIM_INPUTSINK; - } - -@@ -1692,11 +1698,13 @@ static int queue_rawinput_message( struct process* process, void *arg ) - if (raw_msg->extra_len && raw_msg->extra) - memcpy( msg_data + 1, raw_msg->extra, raw_msg->extra_len ); - -- queue_hardware_message( raw_msg->desktop, msg, 1 ); -+ queue_hardware_message( desktop, msg, 1 ); - - done: - if (target_thread) release_object( target_thread ); - if (target_desktop) release_object( target_desktop ); -+ if (foreground) release_object( foreground ); -+ if (desktop) release_object( desktop ); - return 0; - } - --- -2.27.0 - diff --git a/patches/user32-rawinput-mouse/0007-user32-Add-__wine_send_input-flags-to-hint-raw-input.patch b/patches/user32-rawinput-hid/0003-user32-Add-RAWINPUT-parameter-to-__wine_send_input.patch similarity index 54% rename from patches/user32-rawinput-mouse/0007-user32-Add-__wine_send_input-flags-to-hint-raw-input.patch rename to patches/user32-rawinput-hid/0003-user32-Add-RAWINPUT-parameter-to-__wine_send_input.patch index 3da89010..acc66ef3 100644 --- a/patches/user32-rawinput-mouse/0007-user32-Add-__wine_send_input-flags-to-hint-raw-input.patch +++ b/patches/user32-rawinput-hid/0003-user32-Add-RAWINPUT-parameter-to-__wine_send_input.patch @@ -1,51 +1,94 @@ -From c74a22af02a816e81bf84b2f80fcd05582e01187 Mon Sep 17 00:00:00 2001 +From 1d4f802b393ca552ec262f359794277c9ecf2c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Mon, 26 Aug 2019 15:20:32 +0200 -Subject: [PATCH] user32: Add __wine_send_input flags to hint raw input - translation. +Date: Wed, 7 Apr 2021 14:52:00 +0200 +Subject: [PATCH] user32: Add RAWINPUT parameter to __wine_send_input. +And send_hardware_message. + +This makes it possible to use __wine_send_input to send extended input +data, such as HID device notifications and WM_INPUT messages carrying +HID reports. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 --- - dlls/user32/input.c | 4 ++-- + dlls/user32/input.c | 6 +++--- + dlls/user32/message.c | 2 +- dlls/user32/user32.spec | 2 +- + dlls/user32/user_private.h | 2 +- dlls/wineandroid.drv/keyboard.c | 2 +- dlls/wineandroid.drv/window.c | 4 ++-- - dlls/winemac.drv/ime.c | 5 +++-- + dlls/winemac.drv/ime.c | 4 ++-- dlls/winemac.drv/keyboard.c | 2 +- dlls/winemac.drv/mouse.c | 2 +- dlls/winex11.drv/keyboard.c | 2 +- dlls/winex11.drv/mouse.c | 8 ++++---- include/winuser.h | 2 +- - 10 files changed, 17 insertions(+), 16 deletions(-) + 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c -index f0b95c7fc6c..150b7de9704 100644 +index e97264960ea..3fc818a2510 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c -@@ -123,9 +123,9 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) +@@ -119,9 +119,9 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) * * Internal SendInput function to allow the graphics driver to inject real events. */ -BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input ) -+BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, UINT flags ) ++BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput ) { -- NTSTATUS status = send_hardware_message( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); -+ NTSTATUS status = send_hardware_message( hwnd, input, flags ); +- NTSTATUS status = send_hardware_message( hwnd, input, 0 ); ++ NTSTATUS status = send_hardware_message( hwnd, input, rawinput, 0 ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; } +@@ -210,7 +210,7 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) + update_mouse_coords( &input ); + /* fallthrough */ + case INPUT_KEYBOARD: +- status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED ); ++ status = send_hardware_message( 0, &input, NULL, SEND_HWMSG_INJECTED ); + break; + #ifdef _WIN64 + case INPUT_HARDWARE: +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index def59998a52..f87ef9fb3af 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -3227,7 +3227,7 @@ static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BO + /*********************************************************************** + * send_hardware_message + */ +-NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) ++NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput, UINT flags ) + { + struct user_key_state_info *key_state_info = get_user_thread_info()->key_state; + struct send_message_info info; diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec -index d2a14879714..6ffc7d44096 100644 +index 4ef75247d71..190ee74fd6c 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec -@@ -833,5 +833,5 @@ +@@ -834,5 +834,5 @@ # All functions must be prefixed with '__wine_' (for internal functions) # or 'wine_' (for user-visible functions) to avoid namespace conflicts. # -@ cdecl __wine_send_input(long ptr) -+@ cdecl __wine_send_input(long ptr long) ++@ cdecl __wine_send_input(long ptr ptr) @ cdecl __wine_set_pixel_format(long long) +diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h +index 7761a1ceb4f..dfd52421e66 100644 +--- a/dlls/user32/user_private.h ++++ b/dlls/user32/user_private.h +@@ -263,7 +263,7 @@ extern RECT get_virtual_screen_rect(void) DECLSPEC_HIDDEN; + extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; + extern DWORD get_input_codepage( void ) DECLSPEC_HIDDEN; + extern BOOL map_wparam_AtoW( UINT message, WPARAM *wparam, enum wm_char_mapping mapping ) DECLSPEC_HIDDEN; +-extern NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) DECLSPEC_HIDDEN; ++extern NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput, UINT flags ) DECLSPEC_HIDDEN; + extern LRESULT MSG_SendInternalMessageTimeout( DWORD dest_pid, DWORD dest_tid, + UINT msg, WPARAM wparam, LPARAM lparam, + UINT flags, UINT timeout, PDWORD_PTR res_ptr ) DECLSPEC_HIDDEN; diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c -index a0f3257f74b..1af8a98f1f9 100644 +index 1c8a1e4f68f..0a6ede0ec5f 100644 --- a/dlls/wineandroid.drv/keyboard.c +++ b/dlls/wineandroid.drv/keyboard.c @@ -680,7 +680,7 @@ static void send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD flags ) @@ -53,12 +96,12 @@ index a0f3257f74b..1af8a98f1f9 100644 input.u.ki.dwExtraInfo = 0; - __wine_send_input( hwnd, &input ); -+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( hwnd, &input, NULL ); } /*********************************************************************** diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c -index eb05aaf2832..c1e7b000a8f 100644 +index 79bc471a984..1cb1bbbadc9 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -521,7 +521,7 @@ static int process_events( DWORD mask ) @@ -66,7 +109,7 @@ index eb05aaf2832..c1e7b000a8f 100644 SERVER_END_REQ; } - __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input ); -+ __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, NULL ); } break; @@ -75,37 +118,29 @@ index eb05aaf2832..c1e7b000a8f 100644 event->data.kbd.input.u.ki.wScan ); update_keyboard_lock_state( event->data.kbd.input.u.ki.wVk, event->data.kbd.lock_state ); - __wine_send_input( 0, &event->data.kbd.input ); -+ __wine_send_input( 0, &event->data.kbd.input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( 0, &event->data.kbd.input, NULL ); break; default: diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c -index dabe6654f98..3593374a613 100644 +index dabe6654f98..f2368c10743 100644 --- a/dlls/winemac.drv/ime.c +++ b/dlls/winemac.drv/ime.c -@@ -42,6 +42,7 @@ - #include "winuser.h" - #include "imm.h" - #include "ddk/imm.h" -+#include "wine/server.h" - - WINE_DEFAULT_DEBUG_CHANNEL(imm); - -@@ -1427,10 +1428,10 @@ void macdrv_im_set_text(const macdrv_event *event) +@@ -1427,10 +1427,10 @@ void macdrv_im_set_text(const macdrv_event *event) { input.ki.wScan = chars[i]; input.ki.dwFlags = KEYEVENTF_UNICODE; - __wine_send_input(hwnd, &input); -+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW); ++ __wine_send_input(hwnd, &input, NULL); input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; - __wine_send_input(hwnd, &input); -+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW); ++ __wine_send_input(hwnd, &input, NULL); } } diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c -index bb408cb20c5..41919baafc7 100644 +index 1b74300e93a..1ea15f59341 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -929,7 +929,7 @@ static void macdrv_send_keyboard_input(HWND hwnd, WORD vkey, WORD scan, DWORD fl @@ -113,12 +148,12 @@ index bb408cb20c5..41919baafc7 100644 input.ki.dwExtraInfo = 0; - __wine_send_input(hwnd, &input); -+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW); ++ __wine_send_input(hwnd, &input, NULL); } diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c -index dd6443fe1ba..91cafdf1362 100644 +index dd6443fe1ba..d2278ae0e4c 100644 --- a/dlls/winemac.drv/mouse.c +++ b/dlls/winemac.drv/mouse.c @@ -165,7 +165,7 @@ static void send_mouse_input(HWND hwnd, macdrv_window cocoa_window, UINT flags, @@ -126,12 +161,12 @@ index dd6443fe1ba..91cafdf1362 100644 input.mi.dwExtraInfo = 0; - __wine_send_input(top_level_hwnd, &input); -+ __wine_send_input(top_level_hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW); ++ __wine_send_input(top_level_hwnd, &input, NULL); } diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c -index 48da12c0292..2a3bed787ab 100644 +index 35a801fc895..01620c5e4a4 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1148,7 +1148,7 @@ static void X11DRV_send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD f @@ -139,52 +174,52 @@ index 48da12c0292..2a3bed787ab 100644 input.u.ki.dwExtraInfo = 0; - __wine_send_input( hwnd, &input ); -+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( hwnd, &input, NULL ); } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index 7f11ba86e49..aaa34d8ff0f 100644 +index 94dece652b6..42bac332664 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c -@@ -657,7 +657,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU +@@ -659,7 +659,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU + sync_window_cursor( window ); + last_cursor_change = input->u.mi.time; } - input->u.mi.dx += clip_rect.left; - input->u.mi.dy += clip_rect.top; - __wine_send_input( hwnd, input ); -+ __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( hwnd, input, NULL ); return; } -@@ -697,7 +697,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU +@@ -699,7 +699,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU SERVER_END_REQ; } - __wine_send_input( hwnd, input ); -+ __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( hwnd, input, NULL ); } #ifdef SONAME_LIBXCURSOR -@@ -1643,7 +1643,7 @@ void move_resize_window( HWND hwnd, int dir ) +@@ -1669,7 +1669,7 @@ void move_resize_window( HWND hwnd, int dir ) input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; input.u.mi.time = GetTickCount(); input.u.mi.dwExtraInfo = 0; - __wine_send_input( hwnd, &input ); -+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( hwnd, &input, NULL ); } while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) -@@ -1882,7 +1882,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1900,7 +1900,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); input.type = INPUT_MOUSE; - __wine_send_input( 0, &input ); -+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); ++ __wine_send_input( 0, &input, NULL ); return TRUE; } diff --git a/include/winuser.h b/include/winuser.h -index 311b1481be4..4bc18a63e31 100644 +index 53661f6c788..0b1571c0a95 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -4406,7 +4406,7 @@ static inline BOOL WINAPI SetRectEmpty(LPRECT rect) @@ -192,10 +227,10 @@ index 311b1481be4..4bc18a63e31 100644 #ifdef __WINESRC__ -WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input ); -+WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, UINT flags ); ++WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput ); #endif #ifdef __cplusplus -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-hid/0004-hidclass.sys-Assign-rawinput-device-handle-in-HID_Li.patch b/patches/user32-rawinput-hid/0004-hidclass.sys-Assign-rawinput-device-handle-in-HID_Li.patch new file mode 100644 index 00000000..329ec7c4 --- /dev/null +++ b/patches/user32-rawinput-hid/0004-hidclass.sys-Assign-rawinput-device-handle-in-HID_Li.patch @@ -0,0 +1,69 @@ +From 1da5b77304f9ef71340692a9d3d6e95526101ea6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 22 Mar 2021 18:41:55 +0100 +Subject: [PATCH] hidclass.sys: Assign rawinput device handle in + HID_LinkDevice. + +The handles are just numeric values and not real object handles, they +are used in the hDevice field of the RAWINPUTHEADER struct. + +They will also be used as an HID rawinput device array index on the +server side. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/hidclass.sys/device.c | 17 +++++++++++++++++ + dlls/hidclass.sys/hid.h | 1 + + 2 files changed, 18 insertions(+) + +diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c +index fc1dfd07db1..9a3c92b3576 100644 +--- a/dlls/hidclass.sys/device.c ++++ b/dlls/hidclass.sys/device.c +@@ -71,6 +71,17 @@ NTSTATUS HID_CreateDevice(DEVICE_OBJECT *native_device, HID_MINIDRIVER_REGISTRAT + return STATUS_SUCCESS; + } + ++/* user32 reserves 1 & 2 for winemouse and winekeyboard, ++ * keep this in sync with user_private.h */ ++#define WINE_MOUSE_HANDLE 1 ++#define WINE_KEYBOARD_HANDLE 2 ++ ++static UINT32 alloc_rawinput_handle(void) ++{ ++ static LONG counter = WINE_KEYBOARD_HANDLE + 1; ++ return InterlockedIncrement(&counter); ++} ++ + NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device) + { + WCHAR device_instance_id[MAX_DEVICE_ID_LEN]; +@@ -125,7 +136,13 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device) + { + if (!IoRegisterDeviceInterface(device, &GUID_DEVINTERFACE_MOUSE, NULL, &ext->mouse_link_name)) + ext->is_mouse = TRUE; ++ ext->rawinput_handle = WINE_MOUSE_HANDLE; + } ++ else if (ext->preparseData->caps.UsagePage == HID_USAGE_PAGE_GENERIC ++ && ext->preparseData->caps.Usage == HID_USAGE_GENERIC_KEYBOARD) ++ ext->rawinput_handle = WINE_KEYBOARD_HANDLE; ++ else ++ ext->rawinput_handle = alloc_rawinput_handle(); + + return STATUS_SUCCESS; + +diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h +index 889b8c625c0..41f3766a535 100644 +--- a/dlls/hidclass.sys/hid.h ++++ b/dlls/hidclass.sys/hid.h +@@ -51,6 +51,7 @@ typedef struct _BASE_DEVICE_EXTENSION { + struct ReportRingBuffer *ring_buffer; + HANDLE halt_event; + HANDLE thread; ++ UINT32 rawinput_handle; + + KSPIN_LOCK irp_queue_lock; + LIST_ENTRY irp_queue; +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0004-server-Add-HID-input-message-type-to-send_hardware_m.patch b/patches/user32-rawinput-hid/0004-server-Add-HID-input-message-type-to-send_hardware_m.patch deleted file mode 100644 index 5f7f13a1..00000000 --- a/patches/user32-rawinput-hid/0004-server-Add-HID-input-message-type-to-send_hardware_m.patch +++ /dev/null @@ -1,426 +0,0 @@ -From 3d61d04751da0d7267d83ddc374e0f7be550348e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Mon, 11 Nov 2019 18:35:18 +0100 -Subject: [PATCH] server: Add HID input message type to send_hardware_message - request. - ---- - dlls/user32/message.c | 4 ++- - dlls/user32/rawinput.c | 60 ++++++++++++++++++++++++++++++++++++-- - dlls/user32/user_private.h | 2 ++ - server/protocol.def | 26 +++++++++++++++-- - server/queue.c | 60 ++++++++++++++++++++++++++++++++------ - server/trace.c | 10 +++++-- - 6 files changed, 144 insertions(+), 18 deletions(-) - -diff --git a/dlls/user32/message.c b/dlls/user32/message.c -index f7ce262f90d..01d1a0eed97 100644 ---- a/dlls/user32/message.c -+++ b/dlls/user32/message.c -@@ -3240,10 +3240,10 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) - { - req->win = wine_server_user_handle( hwnd ); - req->flags = flags; -- req->input.type = input->type; - switch (input->type) - { - case INPUT_MOUSE: -+ req->input.type = HW_INPUT_MOUSE; - req->input.mouse.x = input->u.mi.dx; - req->input.mouse.y = input->u.mi.dy; - req->input.mouse.data = input->u.mi.mouseData; -@@ -3252,6 +3252,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) - req->input.mouse.info = input->u.mi.dwExtraInfo; - break; - case INPUT_KEYBOARD: -+ req->input.type = HW_INPUT_KEYBOARD; - req->input.kbd.vkey = input->u.ki.wVk; - req->input.kbd.scan = input->u.ki.wScan; - req->input.kbd.flags = input->u.ki.dwFlags; -@@ -3259,6 +3260,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) - req->input.kbd.info = input->u.ki.dwExtraInfo; - break; - case INPUT_HARDWARE: -+ req->input.type = HW_INPUT_HARDWARE; - req->input.hw.msg = input->u.hi.uMsg; - req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH ); - break; -diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c -index ba11a121bc5..a6327b06422 100644 ---- a/dlls/user32/rawinput.c -+++ b/dlls/user32/rawinput.c -@@ -46,6 +46,7 @@ struct device - { - WCHAR *path; - HANDLE file; -+ HANDLE handle; - RID_DEVICE_INFO info; - PHIDP_PREPARSED_DATA data; - }; -@@ -62,6 +63,8 @@ static CRITICAL_SECTION_DEBUG rawinput_devices_cs_debug = - }; - static CRITICAL_SECTION rawinput_devices_cs = { &rawinput_devices_cs_debug, -1, 0, 0, 0, 0 }; - -+extern DWORD WINAPI GetFinalPathNameByHandleW(HANDLE file, LPWSTR path, DWORD charcount, DWORD flags); -+ - static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size) - { - unsigned int new_capacity, max_capacity; -@@ -143,10 +146,43 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) - device->path = path; - device->file = file; - device->info.cbSize = sizeof(RID_DEVICE_INFO); -+ device->handle = INVALID_HANDLE_VALUE; - - return device; - } - -+HANDLE rawinput_handle_from_device_handle(HANDLE device) -+{ -+ WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1]; -+ OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer; -+ ULONG dummy; -+ unsigned int i; -+ -+ for (i = 0; i < rawinput_devices_count; ++i) -+ { -+ if (rawinput_devices[i].handle == device) -+ return &rawinput_devices[i]; -+ } -+ -+ if (NtQueryObject( device, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy ) || !info->Name.Buffer) -+ return NULL; -+ -+ /* replace \??\ with \\?\ to match rawinput_devices paths */ -+ if (info->Name.Length > 1 && info->Name.Buffer[0] == '\\' && info->Name.Buffer[1] == '?') -+ info->Name.Buffer[1] = '\\'; -+ -+ for (i = 0; i < rawinput_devices_count; ++i) -+ { -+ if (!wcscmp(rawinput_devices[i].path, info->Name.Buffer)) -+ { -+ rawinput_devices[i].handle = device; -+ return &rawinput_devices[i]; -+ } -+ } -+ -+ return NULL; -+} -+ - static void find_devices(void) - { - static ULONGLONG last_check; -@@ -326,6 +362,22 @@ BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_ms - rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message; - rawinput->data.keyboard.ExtraInformation = msg_data->info; - } -+ else if (msg_data->rawinput.type == RIM_TYPEHID) -+ { -+ if (sizeof(*rawinput) + msg_data->rawinput.hid.length > RAWINPUT_BUFFER_SIZE) -+ { -+ ERR("unexpectedly large hardware message dropped\n"); -+ return FALSE; -+ } -+ -+ rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data.hid.bRawData) + msg_data->rawinput.hid.length; -+ rawinput->header.hDevice = rawinput_handle_from_device_handle(wine_server_ptr_handle(msg_data->rawinput.hid.device)); -+ rawinput->header.wParam = 0; -+ -+ rawinput->data.hid.dwSizeHid = msg_data->rawinput.hid.length; -+ rawinput->data.hid.dwCount = 1; -+ memcpy(rawinput->data.hid.bRawData, msg_data + 1, msg_data->rawinput.hid.length); -+ } - else - { - FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type); -@@ -524,7 +576,7 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, - struct hardware_msg_data *msg_data; - struct rawinput_thread_data *thread_data; - RAWINPUT *rawinput; -- UINT count = 0, rawinput_size, next_size, overhead; -+ UINT count = 0, rawinput_size, msg_size, next_size, overhead; - BOOL is_wow64; - int i; - -@@ -584,7 +636,10 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, - data->header.dwSize - sizeof(RAWINPUTHEADER)); - data->header.dwSize += overhead; - data = NEXTRAWINPUTBLOCK(data); -- msg_data++; -+ msg_size = sizeof(*msg_data); -+ if (msg_data->rawinput.type == RIM_TYPEHID) -+ msg_size += msg_data->rawinput.hid.length; -+ msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_size); - } - - if (count == 0 && next_size == 0) *data_size = 0; -@@ -657,6 +712,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT - handle, command, data, data_size); - - if (!data_size) return ~0U; -+ if (!device) return ~0U; - - /* each case below must set: - * *data_size: length (meaning defined by command) of data we want to copy -diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h -index 7761a1ceb4f..bf13e81762a 100644 ---- a/dlls/user32/user_private.h -+++ b/dlls/user32/user_private.h -@@ -391,4 +391,6 @@ static inline WCHAR *heap_strdupW(const WCHAR *src) - return dst; - } - -+extern HANDLE rawinput_handle_from_device_handle(HANDLE device); -+ - #endif /* __WINE_USER_PRIVATE_H */ -diff --git a/server/protocol.def b/server/protocol.def -index 140d94ea036..a032f9aa507 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -312,6 +312,13 @@ struct hardware_msg_data - int y; /* y coordinate */ - unsigned int data; /* mouse data */ - } mouse; -+ struct -+ { -+ int type; /* RIM_TYPEHID */ -+ obj_handle_t device; -+ unsigned int length; /* HID report length */ -+ /* followed by length bytes of HID report data */ -+ } hid; - } rawinput; - }; - -@@ -335,7 +342,7 @@ typedef union - int type; - struct - { -- int type; /* INPUT_KEYBOARD */ -+ int type; /* HW_INPUT_KEYBOARD */ - unsigned short vkey; /* virtual key code */ - unsigned short scan; /* scan code */ - unsigned int flags; /* event flags */ -@@ -344,7 +351,7 @@ typedef union - } kbd; - struct - { -- int type; /* INPUT_MOUSE */ -+ int type; /* HW_INPUT_MOUSE */ - int x; /* coordinates */ - int y; - unsigned int data; /* mouse data */ -@@ -354,11 +361,23 @@ typedef union - } mouse; - struct - { -- int type; /* INPUT_HARDWARE */ -+ int type; /* HW_INPUT_HARDWARE */ - unsigned int msg; /* message code */ - lparam_t lparam; /* message param */ - } hw; -+ struct -+ { -+ int type; /* HW_INPUT_HID */ -+ obj_handle_t device; -+ unsigned char usage_page; -+ unsigned char usage; -+ unsigned int length; -+ } hid; - } hw_input_t; -+#define HW_INPUT_MOUSE 0 -+#define HW_INPUT_KEYBOARD 1 -+#define HW_INPUT_HARDWARE 2 -+#define HW_INPUT_HID 3 - - typedef union - { -@@ -2044,6 +2063,7 @@ enum message_type - user_handle_t win; /* window handle */ - hw_input_t input; /* input data */ - unsigned int flags; /* flags (see below) */ -+ VARARG(data,bytes); /* hid report data */ - @REPLY - int wait; /* do we need to wait for a reply? */ - int prev_x; /* previous cursor position */ -diff --git a/server/queue.c b/server/queue.c -index f39cf19ecd7..1b9d66b847e 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -1608,7 +1608,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa - struct msg_queue *queue; - struct message *msg; - timeout_t timeout = 2000 * -10000; /* FIXME: load from registry */ -- int id = (input->type == INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL; -+ int id = (input->type == HW_INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL; - - if (!(hook_thread = get_first_global_hook( id ))) return 0; - if (!(queue = hook_thread->queue)) return 0; -@@ -1626,7 +1626,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa - msg->data_size = hardware_msg->data_size; - msg->result = NULL; - -- if (input->type == INPUT_KEYBOARD) -+ if (input->type == HW_INPUT_KEYBOARD) - { - unsigned short vkey = input->kbd.vkey; - if (input->kbd.flags & KEYEVENTF_UNICODE) vkey = VK_PACKET; -@@ -1662,6 +1662,8 @@ struct rawinput_message - struct desktop *desktop; - struct hw_msg_source source; - unsigned int time; -+ unsigned char usage_page; -+ unsigned char usage; - struct hardware_msg_data data; - const void *extra; - data_size_t extra_len; -@@ -1671,6 +1673,7 @@ struct rawinput_message - static int queue_rawinput_message( struct process* process, void *arg ) - { - const struct rawinput_message* raw_msg = arg; -+ const struct rawinput_device_entry *entry; - const struct rawinput_device *device = NULL; - struct desktop *target_desktop = NULL, *desktop = NULL; - struct thread *target_thread = NULL, *foreground = NULL; -@@ -1682,6 +1685,8 @@ static int queue_rawinput_message( struct process* process, void *arg ) - device = process->rawinput_mouse; - else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD) - device = process->rawinput_kbd; -+ else if ((entry = find_rawinput_device( process, raw_msg->usage_page, raw_msg->usage ))) -+ device = &entry->device; - if (!device) return 0; - - if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop ); -@@ -2000,6 +2005,37 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ - queue_hardware_message( desktop, msg, 1 ); - } - -+/* queue a hardware message for an hid event */ -+static void queue_hid_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, -+ unsigned int origin, struct msg_queue *sender, unsigned int req_flags, -+ const void *report, data_size_t report_len ) -+{ -+ struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; -+ struct hardware_msg_data *msg_data; -+ struct rawinput_message raw_msg; -+ -+ if (!(req_flags & SEND_HWMSG_RAWINPUT)) -+ return; -+ -+ /* send to all desktops */ -+ raw_msg.foreground = NULL; -+ raw_msg.desktop = NULL; -+ raw_msg.source = source; -+ raw_msg.time = get_tick_count(); -+ raw_msg.usage_page = input->hid.usage_page; -+ raw_msg.usage = input->hid.usage; -+ raw_msg.extra = report; -+ raw_msg.extra_len = report_len; -+ -+ msg_data = &raw_msg.data; -+ msg_data->flags = 0; -+ msg_data->rawinput.type = RIM_TYPEHID; -+ msg_data->rawinput.hid.device = input->hid.device; -+ msg_data->rawinput.hid.length = report_len; -+ -+ enum_processes( queue_rawinput_message, &raw_msg ); -+} -+ - /* check message filter for a hardware message */ - static int check_hw_message_filter( user_handle_t win, unsigned int msg_code, - user_handle_t filter_win, unsigned int first, unsigned int last ) -@@ -2505,15 +2541,18 @@ DECL_HANDLER(send_hardware_message) - - switch (req->input.type) - { -- case INPUT_MOUSE: -+ case HW_INPUT_MOUSE: - reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags ); - break; -- case INPUT_KEYBOARD: -+ case HW_INPUT_KEYBOARD: - reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags ); - break; -- case INPUT_HARDWARE: -+ case HW_INPUT_HARDWARE: - queue_custom_hardware_message( desktop, req->win, origin, &req->input ); - break; -+ case HW_INPUT_HID: -+ queue_hid_message( desktop, req->win, &req->input, origin, sender, req->flags, get_req_data(), get_req_data_size() ); -+ break; - default: - set_error( STATUS_INVALID_PARAMETER ); - } -@@ -3295,14 +3334,17 @@ DECL_HANDLER(get_rawinput_buffer) - { - struct message *msg = LIST_ENTRY( ptr, struct message, entry ); - struct hardware_msg_data *data = msg->data; -+ data_size_t msg_size = sizeof(*data); -+ if (data->rawinput.type == RIM_TYPEHID) -+ msg_size += data->rawinput.hid.length; - - ptr = list_next( &input->msg_list, ptr ); - if (msg->msg != WM_INPUT) continue; - - next_size = req->rawinput_size; - if (size + next_size > req->buffer_size) break; -- if (cur + sizeof(*data) > buf + get_reply_max_size()) break; -- if (cur + sizeof(*data) > buf + buf_size) -+ if (cur + msg_size > buf + get_reply_max_size()) break; -+ if (cur + msg_size > buf + buf_size) - { - buf_size += buf_size / 2; - if (!(tmp = realloc( buf, buf_size ))) -@@ -3314,12 +3356,12 @@ DECL_HANDLER(get_rawinput_buffer) - buf = tmp; - } - -- memcpy(cur, data, sizeof(*data)); -+ memcpy(cur, data, msg_size); - list_remove( &msg->entry ); - free_message( msg ); - - size += next_size; -- cur += sizeof(*data); -+ cur += msg_size; - count++; - } - -diff --git a/server/trace.c b/server/trace.c -index c6ef3fb9773..4434bb1893f 100644 ---- a/server/trace.c -+++ b/server/trace.c -@@ -398,24 +398,28 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input ) - { - switch (input->type) - { -- case INPUT_MOUSE: -+ case HW_INPUT_MOUSE: - fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x,flags=%08x,time=%u", - prefix, input->mouse.x, input->mouse.y, input->mouse.data, input->mouse.flags, - input->mouse.time ); - dump_uint64( ",info=", &input->mouse.info ); - fputc( '}', stderr ); - break; -- case INPUT_KEYBOARD: -+ case HW_INPUT_KEYBOARD: - fprintf( stderr, "%s{type=KEYBOARD,vkey=%04hx,scan=%04hx,flags=%08x,time=%u", - prefix, input->kbd.vkey, input->kbd.scan, input->kbd.flags, input->kbd.time ); - dump_uint64( ",info=", &input->kbd.info ); - fputc( '}', stderr ); - break; -- case INPUT_HARDWARE: -+ case HW_INPUT_HARDWARE: - fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg ); - dump_uint64( ",lparam=", &input->hw.lparam ); - fputc( '}', stderr ); - break; -+ case HW_INPUT_HID: -+ fprintf( stderr, "%s{type=HID,device=%04x,usage_page=%02x,usage=%02x,length=%04x}", -+ prefix, input->hid.device, input->hid.usage_page, input->hid.usage, input->hid.length ); -+ break; - default: - fprintf( stderr, "%s{type=%04x}", prefix, input->type ); - break; --- -2.20.1 - diff --git a/patches/user32-rawinput-hid/0005-hidclass.sys-Send-input-message-to-server-when-HID-r.patch b/patches/user32-rawinput-hid/0005-hidclass.sys-Send-input-message-to-server-when-HID-r.patch deleted file mode 100644 index f3ebe7da..00000000 --- a/patches/user32-rawinput-hid/0005-hidclass.sys-Send-input-message-to-server-when-HID-r.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 8f7a0c92c370cb4bf1ee6e6d7c51a3d90fe4cd48 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Wed, 18 Sep 2019 21:04:25 +0200 -Subject: [PATCH] hidclass.sys: Send input message to server when HID report is - received. - ---- - dlls/hidclass.sys/device.c | 30 ++++++++++++++++++++++++++++++ - dlls/hidclass.sys/hid.h | 1 + - dlls/hidclass.sys/pnp.c | 16 ++++++++++++++++ - 3 files changed, 47 insertions(+) - -diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c -index 0e905c8322f..369d847e3c1 100644 ---- a/dlls/hidclass.sys/device.c -+++ b/dlls/hidclass.sys/device.c -@@ -26,9 +26,11 @@ - #include "winuser.h" - #include "setupapi.h" - -+#include "wine/server.h" - #include "wine/debug.h" - #include "ddk/hidsdi.h" - #include "ddk/hidtypes.h" -+#include "ddk/ntifs.h" - #include "ddk/wdm.h" - - #include "initguid.h" -@@ -123,6 +125,8 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device) - return status; - } - -+ ext->link_handle = INVALID_HANDLE_VALUE; -+ - /* FIXME: This should probably be done in mouhid.sys. */ - if (ext->preparseData->caps.UsagePage == HID_USAGE_PAGE_GENERIC - && ext->preparseData->caps.Usage == HID_USAGE_GENERIC_MOUSE) -@@ -207,6 +211,8 @@ void HID_DeleteDevice(DEVICE_OBJECT *device) - IoCompleteRequest(irp, IO_NO_INCREMENT); - } - -+ CloseHandle(ext->link_handle); -+ - TRACE("Delete device(%p) %s\n", device, debugstr_w(ext->device_name)); - HeapFree(GetProcessHeap(), 0, ext->device_name); - RtlFreeUnicodeString(&ext->link_name); -@@ -241,6 +247,28 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U - return STATUS_BUFFER_OVERFLOW; - } - -+static void HID_Device_sendRawInput(DEVICE_OBJECT *device, HID_XFER_PACKET *packet) -+{ -+ BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; -+ -+ if (ext->link_handle == INVALID_HANDLE_VALUE) -+ return; -+ -+ SERVER_START_REQ(send_hardware_message) -+ { -+ req->win = 0; -+ req->flags = SEND_HWMSG_RAWINPUT; -+ req->input.type = HW_INPUT_HID; -+ req->input.hid.device = wine_server_obj_handle(ext->link_handle); -+ req->input.hid.usage_page = ext->preparseData->caps.UsagePage; -+ req->input.hid.usage = ext->preparseData->caps.Usage; -+ req->input.hid.length = packet->reportBufferLen; -+ wine_server_add_data(req, packet->reportBuffer, packet->reportBufferLen); -+ wine_server_call(req); -+ } -+ SERVER_END_REQ; -+} -+ - static void HID_Device_processQueue(DEVICE_OBJECT *device) - { - IRP *irp; -@@ -324,6 +352,7 @@ static DWORD CALLBACK hid_device_thread(void *args) - if (irp->IoStatus.u.Status == STATUS_SUCCESS) - { - RingBuffer_Write(ext->ring_buffer, packet); -+ HID_Device_sendRawInput(device, packet); - HID_Device_processQueue(device); - } - -@@ -370,6 +399,7 @@ static DWORD CALLBACK hid_device_thread(void *args) - else - packet->reportId = 0; - RingBuffer_Write(ext->ring_buffer, packet); -+ HID_Device_sendRawInput(device, packet); - HID_Device_processQueue(device); - } - -diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h -index 36d13c009d7..f12e04d7898 100644 ---- a/dlls/hidclass.sys/hid.h -+++ b/dlls/hidclass.sys/hid.h -@@ -46,6 +46,7 @@ typedef struct _BASE_DEVICE_EXTENSION { - ULONG poll_interval; - WCHAR *device_name; - UNICODE_STRING link_name; -+ HANDLE link_handle; - WCHAR device_id[MAX_DEVICE_ID_LEN]; - WCHAR instance_id[MAX_DEVICE_ID_LEN]; - struct ReportRingBuffer *ring_buffer; -diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c -index 1c130e8dd80..b84a358dba4 100644 ---- a/dlls/hidclass.sys/pnp.c -+++ b/dlls/hidclass.sys/pnp.c -@@ -299,12 +299,28 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp) - case IRP_MN_START_DEVICE: - { - BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; -+ OBJECT_ATTRIBUTES attr; - - rc = minidriver->PNPDispatch(device, irp); - - IoSetDeviceInterfaceState(&ext->link_name, TRUE); - if (ext->is_mouse) - IoSetDeviceInterfaceState(&ext->mouse_link_name, TRUE); -+ -+ attr.Length = sizeof(attr); -+ attr.RootDirectory = 0; -+ attr.Attributes = OBJ_CASE_INSENSITIVE; -+ attr.ObjectName = &ext->link_name; -+ attr.SecurityDescriptor = NULL; -+ attr.SecurityQualityOfService = NULL; -+ NtOpenSymbolicLinkObject(&ext->link_handle, SYMBOLIC_LINK_QUERY, &attr); -+ ext->link_handle = ConvertToGlobalHandle(ext->link_handle); -+ -+ if (ext->link_handle == INVALID_HANDLE_VALUE) -+ ERR("Failed to open link %s, error %u.\n", debugstr_w(ext->link_name.Buffer), GetLastError()); -+ else -+ TRACE("Opened link handle: %p for %s\n", ext->link_handle, debugstr_w(ext->link_name.Buffer)); -+ - return rc; - } - case IRP_MN_REMOVE_DEVICE: --- -2.27.0 - diff --git a/patches/user32-rawinput-hid/0005-hidclass.sys-Use-__wine_send_input-to-send-device-no.patch b/patches/user32-rawinput-hid/0005-hidclass.sys-Use-__wine_send_input-to-send-device-no.patch new file mode 100644 index 00000000..e8b39bb9 --- /dev/null +++ b/patches/user32-rawinput-hid/0005-hidclass.sys-Use-__wine_send_input-to-send-device-no.patch @@ -0,0 +1,118 @@ +From 4b24ceb11c3b77ecd1e00d7145be370f7192bbbb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Fri, 19 Mar 2021 14:16:16 +0100 +Subject: [PATCH] hidclass.sys: Use __wine_send_input to send device + notifications. + +This currently does nothing, because winedevice.exe isn't associated +with any desktop, and the INPUT_HARDWARE messages are dropped. + +In this specific case, when INPUT type is INPUT_HARDWARE and hi.uMsg is +WM_INPUT_DEVICE_CHANGE, the RAWINPUT structure usage is a non-standard +extension for Wine internal usage: + +* header.wParam contains the message GIDC_ARRIVAL / GIDC_REMOVAL wparam, + +* hid.bRawData contains two bytes, which are the HID device UsagePage + and Usage bytes, instead of a real HID report. + +This will let us use the same entry point and structures to send device +notifications as for the HID reports in the future (which will be sent +with INPUT_HARDWARE type / WM_INPUT uMsg instead). + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/hidclass.sys/Makefile.in | 2 +- + dlls/hidclass.sys/pnp.c | 36 +++++++++++++++++++++++++++++++++++ + 2 files changed, 37 insertions(+), 1 deletion(-) + +diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in +index be4af747853..2f9f30f8bef 100644 +--- a/dlls/hidclass.sys/Makefile.in ++++ b/dlls/hidclass.sys/Makefile.in +@@ -1,6 +1,6 @@ + MODULE = hidclass.sys + IMPORTLIB = hidclass +-IMPORTS = hal ntoskrnl ++IMPORTS = hal ntoskrnl user32 + DELAYIMPORTS = setupapi hid + + EXTRADLLFLAGS = -mno-cygwin +diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c +index a499aec93bb..8e539dfe6b7 100644 +--- a/dlls/hidclass.sys/pnp.c ++++ b/dlls/hidclass.sys/pnp.c +@@ -25,6 +25,7 @@ + #include "ddk/hidtypes.h" + #include "ddk/wdm.h" + #include "regstr.h" ++#include "winuser.h" + #include "wine/debug.h" + #include "wine/list.h" + +@@ -69,6 +70,9 @@ static NTSTATUS get_device_id(DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCH + return status; + } + ++/* make sure bRawData can hold two bytes without requiring additional allocation */ ++C_ASSERT(offsetof(RAWINPUT, data.hid.bRawData[2]) < sizeof(RAWINPUT)); ++ + NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO) + { + WCHAR device_id[MAX_DEVICE_ID_LEN], instance_id[MAX_DEVICE_ID_LEN]; +@@ -79,6 +83,8 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO) + BASE_DEVICE_EXTENSION *ext = NULL; + HID_DESCRIPTOR descriptor; + BYTE *reportDescriptor; ++ RAWINPUT rawinput; ++ INPUT input; + INT i; + + if ((status = get_device_id(PDO, BusQueryDeviceID, device_id))) +@@ -187,6 +193,21 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO) + + HID_StartDeviceThread(device); + ++ rawinput.header.dwType = RIM_TYPEHID; ++ rawinput.header.dwSize = offsetof(RAWINPUT, data.hid.bRawData[2]); ++ rawinput.header.hDevice = ULongToHandle(ext->rawinput_handle); ++ rawinput.header.wParam = GIDC_ARRIVAL; ++ rawinput.data.hid.dwCount = 1; ++ rawinput.data.hid.dwSizeHid = 2; ++ rawinput.data.hid.bRawData[0] = ext->preparseData->caps.UsagePage; ++ rawinput.data.hid.bRawData[1] = ext->preparseData->caps.Usage; ++ ++ input.type = INPUT_HARDWARE; ++ input.u.hi.uMsg = WM_INPUT_DEVICE_CHANGE; ++ input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16); ++ input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0); ++ __wine_send_input(0, &input, &rawinput); ++ + return STATUS_SUCCESS; + } + +@@ -194,6 +215,21 @@ static NTSTATUS remove_device(minidriver *minidriver, DEVICE_OBJECT *device, IRP + { + BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + NTSTATUS rc = STATUS_NOT_SUPPORTED; ++ RAWINPUT rawinput; ++ INPUT input; ++ ++ rawinput.header.dwType = RIM_TYPEHID; ++ rawinput.header.dwSize = offsetof(RAWINPUT, data.hid.bRawData[0]); ++ rawinput.header.hDevice = ULongToHandle(ext->rawinput_handle); ++ rawinput.header.wParam = GIDC_REMOVAL; ++ rawinput.data.hid.dwCount = 0; ++ rawinput.data.hid.dwSizeHid = 0; ++ ++ input.type = INPUT_HARDWARE; ++ input.u.hi.uMsg = WM_INPUT_DEVICE_CHANGE; ++ input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16); ++ input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0); ++ __wine_send_input(0, &input, &rawinput); + + rc = IoSetDeviceInterfaceState(&ext->link_name, FALSE); + if (rc) +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0006-server-Implement-desktop-broadcast-in-queue_rawinput.patch b/patches/user32-rawinput-hid/0006-server-Implement-desktop-broadcast-in-queue_rawinput.patch new file mode 100644 index 00000000..d74e6184 --- /dev/null +++ b/patches/user32-rawinput-hid/0006-server-Implement-desktop-broadcast-in-queue_rawinput.patch @@ -0,0 +1,140 @@ +From 84aab96026febc4d222733b5ecc2919047ac549b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 22 Mar 2021 22:46:36 +0100 +Subject: [PATCH] server: Implement desktop broadcast in + queue_rawinput_message. + +HID rawinput hardware messages will be sent from winedevice.exe, which +is not attached to any desktop. We need to broadcast the messages to all +desktops in that case. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + server/queue.c | 45 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 31 insertions(+), 14 deletions(-) + +diff --git a/server/queue.c b/server/queue.c +index b026c03e13d..ca2f898492b 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -1670,8 +1670,8 @@ static int queue_rawinput_message( struct process* process, void *arg ) + { + const struct rawinput_message* raw_msg = arg; + const struct rawinput_device *device = NULL; +- struct desktop *target_desktop = NULL; +- struct thread *target_thread = NULL; ++ struct desktop *target_desktop = NULL, *desktop = NULL; ++ struct thread *target_thread = NULL, *foreground = NULL; + struct message *msg; + int wparam = RIM_INPUT; + +@@ -1681,12 +1681,18 @@ static int queue_rawinput_message( struct process* process, void *arg ) + device = process->rawinput_kbd; + if (!device) return 0; + +- if (process != raw_msg->foreground->process) ++ if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop ); ++ else if (!(desktop = get_desktop_obj( process, process->desktop, 0 ))) goto done; ++ ++ if (raw_msg->foreground) foreground = (struct thread *)grab_object( raw_msg->foreground ); ++ else if (!(foreground = get_foreground_thread( desktop, 0 ))) goto done; ++ ++ if (process != foreground->process) + { + if (!(device->flags & RIDEV_INPUTSINK)) goto done; + if (!(target_thread = get_window_thread( device->target ))) goto done; + if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done; +- if (target_desktop != raw_msg->desktop) goto done; ++ if (target_desktop != desktop) goto done; + wparam = RIM_INPUTSINK; + } + +@@ -1699,11 +1705,13 @@ static int queue_rawinput_message( struct process* process, void *arg ) + msg->lparam = 0; + memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) ); + +- queue_hardware_message( raw_msg->desktop, msg, 1 ); ++ queue_hardware_message( desktop, msg, 1 ); + + done: + if (target_thread) release_object( target_thread ); + if (target_desktop) release_object( target_desktop ); ++ if (foreground) release_object( foreground ); ++ if (desktop) release_object( desktop ); + return 0; + } + +@@ -1961,6 +1969,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; + struct message *msg; + ++ if (!desktop) return; + if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return; + + msg->win = get_user_full_handle( win ); +@@ -2455,15 +2464,14 @@ DECL_HANDLER(send_message) + DECL_HANDLER(send_hardware_message) + { + struct thread *thread = NULL; +- struct desktop *desktop; ++ struct desktop *desktop = get_thread_desktop( current, 0 ); + unsigned int origin = (req->flags & SEND_HWMSG_INJECTED ? IMO_INJECTED : IMO_HARDWARE); + struct msg_queue *sender = get_current_queue(); + data_size_t size = min( 256, get_reply_max_size() ); + +- if (!(desktop = get_thread_desktop( current, 0 ))) return; +- + if (req->win) + { ++ if (!desktop) return; + if (!(thread = get_window_thread( req->win ))) return; + if (desktop != thread->queue->input->desktop) + { +@@ -2473,18 +2481,24 @@ DECL_HANDLER(send_hardware_message) + } + } + +- reply->prev_x = desktop->cursor.x; +- reply->prev_y = desktop->cursor.y; ++ if (desktop) ++ { ++ reply->prev_x = desktop->cursor.x; ++ reply->prev_y = desktop->cursor.y; ++ } + + switch (req->input.type) + { + case INPUT_MOUSE: ++ if (!desktop) return; + reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender ); + break; + case INPUT_KEYBOARD: ++ if (!desktop) return; + reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender ); + break; + case INPUT_HARDWARE: ++ if (!desktop) set_error( STATUS_SUCCESS ); + queue_custom_hardware_message( desktop, req->win, origin, &req->input ); + break; + default: +@@ -2492,10 +2506,13 @@ DECL_HANDLER(send_hardware_message) + } + if (thread) release_object( thread ); + +- reply->new_x = desktop->cursor.x; +- reply->new_y = desktop->cursor.y; +- set_reply_data( desktop->keystate, size ); +- release_object( desktop ); ++ if (desktop) ++ { ++ reply->new_x = desktop->cursor.x; ++ reply->new_y = desktop->cursor.y; ++ set_reply_data( desktop->keystate, size ); ++ release_object( desktop ); ++ } + } + + /* post a quit message to the current queue */ +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0007-server-Add-rawinput-union-to-hw_input_t-INPUT_HARDWA.patch b/patches/user32-rawinput-hid/0007-server-Add-rawinput-union-to-hw_input_t-INPUT_HARDWA.patch new file mode 100644 index 00000000..0cb9ec66 --- /dev/null +++ b/patches/user32-rawinput-hid/0007-server-Add-rawinput-union-to-hw_input_t-INPUT_HARDWA.patch @@ -0,0 +1,123 @@ +From 281b7628ea550071eab3b0c933b02ff67a3b215d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 22 Mar 2021 17:55:50 +0100 +Subject: [PATCH] server: Add rawinput union to hw_input_t / INPUT_HARDWARE. + +When msg is WM_INPUT_DEVICE_CHANGE. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + server/protocol.def | 42 ++++++++++++++++++++++++------------------ + server/trace.c | 23 +++++++++++++++++++++++ + 2 files changed, 47 insertions(+), 18 deletions(-) + +diff --git a/server/protocol.def b/server/protocol.def +index 617818f622d..9539169f1ff 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -289,30 +289,32 @@ struct hw_msg_source + unsigned int origin; /* source origin (IMO_* values) */ + }; + ++union rawinput ++{ ++ int type; ++ struct ++ { ++ int type; /* RIM_TYPEKEYBOARD */ ++ unsigned int message; /* message generated by this rawinput event */ ++ unsigned short vkey; /* virtual key code */ ++ unsigned short scan; /* scan code */ ++ } kbd; ++ struct ++ { ++ int type; /* RIM_TYPEMOUSE */ ++ int x; /* x coordinate */ ++ int y; /* y coordinate */ ++ unsigned int data; /* mouse data */ ++ } mouse; ++}; ++ + struct hardware_msg_data + { + lparam_t info; /* extra info */ + unsigned int hw_id; /* unique id */ + unsigned int flags; /* hook flags */ + struct hw_msg_source source; /* message source */ +- union +- { +- int type; +- struct +- { +- int type; /* RIM_TYPEKEYBOARD */ +- unsigned int message; /* message generated by this rawinput event */ +- unsigned short vkey; /* virtual key code */ +- unsigned short scan; /* scan code */ +- } kbd; +- struct +- { +- int type; /* RIM_TYPEMOUSE */ +- int x; /* x coordinate */ +- int y; /* y coordinate */ +- unsigned int data; /* mouse data */ +- } mouse; +- } rawinput; ++ union rawinput rawinput; /* rawinput message data */ + }; + + struct callback_msg_data +@@ -357,6 +359,10 @@ typedef union + int type; /* INPUT_HARDWARE */ + unsigned int msg; /* message code */ + lparam_t lparam; /* message param */ ++ union ++ { ++ union rawinput rawinput; /* WM_INPUT_DEVICE_CHANGE msg */ ++ } data; + } hw; + } hw_input_t; + +diff --git a/server/trace.c b/server/trace.c +index 44bc8d8ee6f..ce21ae4fe4f 100644 +--- a/server/trace.c ++++ b/server/trace.c +@@ -409,6 +409,24 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data ) + } + } + ++static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) ++{ ++ switch (rawinput->type) ++ { ++ case RIM_TYPEMOUSE: ++ fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x}", prefix, rawinput->mouse.x, ++ rawinput->mouse.y, rawinput->mouse.data ); ++ break; ++ case RIM_TYPEKEYBOARD: ++ fprintf( stderr, "%s{type=KEYBOARD,message=%04x,vkey=%04hx,scan=%04hx}", prefix, ++ rawinput->kbd.message, rawinput->kbd.vkey, rawinput->kbd.scan ); ++ break; ++ default: ++ fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type ); ++ break; ++ } ++} ++ + static void dump_hw_input( const char *prefix, const hw_input_t *input ) + { + switch (input->type) +@@ -429,6 +447,11 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input ) + case INPUT_HARDWARE: + fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg ); + dump_uint64( ",lparam=", &input->hw.lparam ); ++ switch (input->hw.msg) ++ { ++ case WM_INPUT_DEVICE_CHANGE: ++ dump_rawinput( ",rawinput=", &input->hw.data.rawinput ); ++ } + fputc( '}', stderr ); + break; + default: +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0008-server-Add-RIM_TYPEHID-type-hid-member-to-rawinput-u.patch b/patches/user32-rawinput-hid/0008-server-Add-RIM_TYPEHID-type-hid-member-to-rawinput-u.patch new file mode 100644 index 00000000..369d07f6 --- /dev/null +++ b/patches/user32-rawinput-hid/0008-server-Add-RIM_TYPEHID-type-hid-member-to-rawinput-u.patch @@ -0,0 +1,96 @@ +From 6b794622488eb83f6ede9d62a14f413660a2623a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 22 Mar 2021 18:28:38 +0100 +Subject: [PATCH] server: Add RIM_TYPEHID type / hid member to rawinput union. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + server/protocol.def | 8 ++++++++ + server/trace.c | 38 ++++++++++++++++++++++---------------- + 2 files changed, 30 insertions(+), 16 deletions(-) + +diff --git a/server/protocol.def b/server/protocol.def +index 9539169f1ff..f97b966719c 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -306,6 +306,14 @@ union rawinput + int y; /* y coordinate */ + unsigned int data; /* mouse data */ + } mouse; ++ struct ++ { ++ int type; /* RIM_TYPEHID */ ++ unsigned int device; /* rawinput device index */ ++ unsigned int param; /* rawinput message param */ ++ unsigned int length; /* HID report length */ ++ /* followed by length bytes of HID report data */ ++ } hid; + }; + + struct hardware_msg_data +diff --git a/server/trace.c b/server/trace.c +index ce21ae4fe4f..3d24cec0133 100644 +--- a/server/trace.c ++++ b/server/trace.c +@@ -409,6 +409,22 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data ) + } + } + ++static void dump_varargs_bytes( const char *prefix, data_size_t size ) ++{ ++ const unsigned char *data = cur_data; ++ data_size_t len = min( 1024, size ); ++ ++ fprintf( stderr, "%s{", prefix ); ++ while (len > 0) ++ { ++ fprintf( stderr, "%02x", *data++ ); ++ if (--len) fputc( ',', stderr ); ++ } ++ if (size > 1024) fprintf( stderr, "...(total %u)", size ); ++ fputc( '}', stderr ); ++ remove_data( size ); ++} ++ + static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) + { + switch (rawinput->type) +@@ -421,6 +437,12 @@ static void dump_rawinput( const char *prefix, const union rawinput *rawinput ) + fprintf( stderr, "%s{type=KEYBOARD,message=%04x,vkey=%04hx,scan=%04hx}", prefix, + rawinput->kbd.message, rawinput->kbd.vkey, rawinput->kbd.scan ); + break; ++ case RIM_TYPEHID: ++ fprintf( stderr, "%s{type=HID,device=%04x,param=%04x,length=%u", prefix, ++ rawinput->hid.device, rawinput->hid.param, rawinput->hid.length ); ++ dump_varargs_bytes( ",report=", rawinput->hid.length ); ++ fputc( '}', stderr ); ++ break; + default: + fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type ); + break; +@@ -580,22 +602,6 @@ static void dump_varargs_user_handles( const char *prefix, data_size_t size ) + remove_data( size ); + } + +-static void dump_varargs_bytes( const char *prefix, data_size_t size ) +-{ +- const unsigned char *data = cur_data; +- data_size_t len = min( 1024, size ); +- +- fprintf( stderr,"%s{", prefix ); +- while (len > 0) +- { +- fprintf( stderr, "%02x", *data++ ); +- if (--len) fputc( ',', stderr ); +- } +- if (size > 1024) fprintf( stderr, "...(total %u)", size ); +- fputc( '}', stderr ); +- remove_data( size ); +-} +- + static void dump_varargs_string( const char *prefix, data_size_t size ) + { + fprintf( stderr, "%s\"%.*s\"", prefix, (int)size, (const char *)cur_data ); +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0009-user32-Send-WM_INPUT_DEVICE_CHANGE-RAWINPUT-to-the-s.patch b/patches/user32-rawinput-hid/0009-user32-Send-WM_INPUT_DEVICE_CHANGE-RAWINPUT-to-the-s.patch new file mode 100644 index 00000000..040fb3a5 --- /dev/null +++ b/patches/user32-rawinput-hid/0009-user32-Send-WM_INPUT_DEVICE_CHANGE-RAWINPUT-to-the-s.patch @@ -0,0 +1,47 @@ +From dcd1d9ab1462b49093465e3e4117419b63778799 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 22 Mar 2021 18:11:27 +0100 +Subject: [PATCH] user32: Send WM_INPUT_DEVICE_CHANGE / RAWINPUT to the server. + +Expect INPUT/INPUT_HARDWARE to be followed with RAWINPUT, when uMsg is +WM_INPUT_DEVICE_CHANGE. This is for internal __wine_send_input calls +only, as we ignore INPUT_HARDWARE in SendInput. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/user32/message.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index f87ef9fb3af..f11aaa4144d 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -3267,6 +3267,25 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r + case INPUT_HARDWARE: + req->input.hw.msg = input->u.hi.uMsg; + req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH ); ++ switch (input->u.hi.uMsg) ++ { ++ case WM_INPUT_DEVICE_CHANGE: ++ req->input.hw.data.rawinput.type = rawinput->header.dwType; ++ switch (rawinput->header.dwType) ++ { ++ case RIM_TYPEHID: ++ assert( rawinput->data.hid.dwCount <= 1 ); ++ req->input.hw.data.rawinput.hid.device = HandleToUlong( rawinput->header.hDevice ); ++ req->input.hw.data.rawinput.hid.param = rawinput->header.wParam; ++ req->input.hw.data.rawinput.hid.length = rawinput->data.hid.dwSizeHid; ++ if (rawinput->data.hid.dwSizeHid) ++ wine_server_add_data( req, rawinput->data.hid.bRawData, rawinput->data.hid.dwSizeHid ); ++ break; ++ default: ++ assert( 0 ); ++ break; ++ } ++ } + break; + } + if (key_state_info) wine_server_set_reply( req, key_state_info->state, +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0010-server-Track-known-HID-rawinput-devices-on-addition-.patch b/patches/user32-rawinput-hid/0010-server-Track-known-HID-rawinput-devices-on-addition-.patch new file mode 100644 index 00000000..be826173 --- /dev/null +++ b/patches/user32-rawinput-hid/0010-server-Track-known-HID-rawinput-devices-on-addition-.patch @@ -0,0 +1,83 @@ +From cb2f3ed7057e769dda746b65464b364edb447c32 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 7 Apr 2021 12:17:09 +0200 +Subject: [PATCH] server: Track known HID rawinput devices on addition and + removal. + +To track their usage page and usage bytes. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + server/queue.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/server/queue.c b/server/queue.c +index ca2f898492b..033e4e30b66 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -1656,6 +1656,42 @@ static struct thread *get_foreground_thread( struct desktop *desktop, user_handl + return NULL; + } + ++static struct rawinput_device *hid_rawinput_devices; ++static unsigned int hid_rawinput_device_count; ++ ++static void insert_hid_rawinput_device( unsigned int index, const char *data, unsigned int data_len ) ++{ ++ unsigned int new_count; ++ ++ if (data_len < 2) return; ++ ++ if (!hid_rawinput_device_count) ++ { ++ hid_rawinput_device_count = 64; ++ while (hid_rawinput_device_count < index) hid_rawinput_device_count *= 2; ++ hid_rawinput_devices = mem_alloc( hid_rawinput_device_count * sizeof(*hid_rawinput_devices) ); ++ memset( hid_rawinput_devices, 0, hid_rawinput_device_count * sizeof(*hid_rawinput_devices) ); ++ } ++ else if (hid_rawinput_device_count < index) ++ { ++ new_count = hid_rawinput_device_count; ++ while (new_count < index) new_count *= 2; ++ hid_rawinput_devices = realloc( hid_rawinput_devices, new_count * sizeof(*hid_rawinput_devices) ); ++ memset( hid_rawinput_devices + hid_rawinput_device_count, 0, (new_count - hid_rawinput_device_count) * sizeof(*hid_rawinput_devices) ); ++ hid_rawinput_device_count = new_count; ++ } ++ ++ hid_rawinput_devices[index].usage_page = data[0]; ++ hid_rawinput_devices[index].usage = data[1]; ++} ++ ++static void remove_hid_rawinput_device( unsigned int index ) ++{ ++ if (hid_rawinput_device_count < index) return; ++ hid_rawinput_devices[index].usage_page = 0; ++ hid_rawinput_devices[index].usage = 0; ++} ++ + struct rawinput_message + { + struct thread *foreground; +@@ -1969,6 +2005,19 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; + struct message *msg; + ++ switch (input->hw.msg) ++ { ++ case WM_INPUT_DEVICE_CHANGE: ++ if (input->hw.data.rawinput.type == RIM_TYPEHID && ++ input->hw.data.rawinput.hid.param == GIDC_ARRIVAL) ++ insert_hid_rawinput_device( input->hw.data.rawinput.hid.device, get_req_data(), get_req_data_size() ); ++ ++ if (input->hw.data.rawinput.type == RIM_TYPEHID && ++ input->hw.data.rawinput.hid.param == GIDC_REMOVAL) ++ remove_hid_rawinput_device( input->hw.data.rawinput.hid.device ); ++ return; ++ } ++ + if (!desktop) return; + if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return; + +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0001-server-Add-process-argument-to-find_rawinput_device.patch b/patches/user32-rawinput-hid/0011-server-Add-process-argument-to-find_rawinput_device.patch similarity index 82% rename from patches/user32-rawinput-hid/0001-server-Add-process-argument-to-find_rawinput_device.patch rename to patches/user32-rawinput-hid/0011-server-Add-process-argument-to-find_rawinput_device.patch index 1f0ccc14..2a749459 100644 --- a/patches/user32-rawinput-hid/0001-server-Add-process-argument-to-find_rawinput_device.patch +++ b/patches/user32-rawinput-hid/0011-server-Add-process-argument-to-find_rawinput_device.patch @@ -1,19 +1,21 @@ -From 1851c55f41d14e03c927b0e5220f9c00b1d05f6e Mon Sep 17 00:00:00 2001 +From 3c71ae18955c39a1e85532175de76068597010d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Thu, 12 Sep 2019 14:14:08 +0200 +Date: Wed, 10 Feb 2021 13:23:31 +0100 Subject: [PATCH] server: Add process argument to find_rawinput_device. We need to be able to iterate all registered rawinput devices for foreign processes, not only the current one. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 --- server/queue.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/queue.c b/server/queue.c -index 46ace52f004..810612c5167 100644 +index 033e4e30b66..e71d9207e1a 100644 --- a/server/queue.c +++ b/server/queue.c -@@ -1490,11 +1490,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru +@@ -1489,11 +1489,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru return win; } @@ -27,7 +29,7 @@ index 46ace52f004..810612c5167 100644 { if (e->device.usage_page != usage_page || e->device.usage != usage) continue; return e; -@@ -1507,7 +1507,7 @@ static void update_rawinput_device(const struct rawinput_device *device) +@@ -1506,7 +1506,7 @@ static void update_rawinput_device(const struct rawinput_device *device) { struct rawinput_device_entry *e; @@ -36,7 +38,7 @@ index 46ace52f004..810612c5167 100644 { if (!(e = mem_alloc( sizeof(*e) ))) return; list_add_tail( ¤t->process->rawinput_devices, &e->entry ); -@@ -3286,9 +3286,9 @@ DECL_HANDLER(update_rawinput_devices) +@@ -3362,9 +3362,9 @@ DECL_HANDLER(update_rawinput_devices) update_rawinput_device(&devices[i]); } @@ -49,5 +51,5 @@ index 46ace52f004..810612c5167 100644 } -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-hid/0012-server-Implement-WM_INPUT_DEVICE_CHANGE-message-disp.patch b/patches/user32-rawinput-hid/0012-server-Implement-WM_INPUT_DEVICE_CHANGE-message-disp.patch new file mode 100644 index 00000000..bb709889 --- /dev/null +++ b/patches/user32-rawinput-hid/0012-server-Implement-WM_INPUT_DEVICE_CHANGE-message-disp.patch @@ -0,0 +1,225 @@ +From aec62828c1b4daee79e452e749eb215deb40425a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 7 Apr 2021 12:17:40 +0200 +Subject: [PATCH] server: Implement WM_INPUT_DEVICE_CHANGE message dispatch. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/user32/message.c | 13 +++++++---- + dlls/user32/rawinput.c | 2 +- + server/queue.c | 53 +++++++++++++++++++++++++++++++++++++----- + 3 files changed, 56 insertions(+), 12 deletions(-) + +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index f11aaa4144d..54fcdc4588c 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -2288,11 +2288,14 @@ static void accept_hardware_message( UINT hw_id ) + static BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) + { + struct rawinput_thread_data *thread_data = rawinput_thread_data(); +- if (!rawinput_from_hardware_message( thread_data->buffer, msg_data )) +- return FALSE; + +- thread_data->hw_id = hw_id; +- msg->lParam = (LPARAM)hw_id; ++ if (msg->message == WM_INPUT) ++ { ++ if (!rawinput_from_hardware_message( thread_data->buffer, msg_data )) return FALSE; ++ thread_data->hw_id = hw_id; ++ msg->lParam = (LPARAM)hw_id; ++ } ++ + msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); + return TRUE; + } +@@ -2612,7 +2615,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar + /* hardware messages are always in physical coords */ + context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ); + +- if (msg->message == WM_INPUT) ++ if (msg->message == WM_INPUT || msg->message == WM_INPUT_DEVICE_CHANGE) + ret = process_rawinput_message( msg, hw_id, msg_data ); + else if (is_keyboard_message( msg->message )) + ret = process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove ); +diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c +index ba11a121bc5..99481ffae3d 100644 +--- a/dlls/user32/rawinput.c ++++ b/dlls/user32/rawinput.c +@@ -428,7 +428,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U + TRACE("device %u: page %#x, usage %#x, flags %#x, target %p.\n", + i, devices[i].usUsagePage, devices[i].usUsage, + devices[i].dwFlags, devices[i].hwndTarget); +- if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK)) ++ if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK|RIDEV_DEVNOTIFY)) + FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i); + + d[i].usage_page = devices[i].usUsagePage; +diff --git a/server/queue.c b/server/queue.c +index e71d9207e1a..9fe009b5cfe 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -1464,7 +1464,7 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru + + *thread = NULL; + *msg_code = msg->msg; +- if (msg->msg == WM_INPUT) ++ if (msg->msg == WM_INPUT || msg->msg == WM_INPUT_DEVICE_CHANGE) + { + if (!(win = msg->win) && input) win = input->focus; + } +@@ -1553,7 +1553,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg + if (msg->wparam == VK_SHIFT || msg->wparam == VK_LSHIFT || msg->wparam == VK_RSHIFT) + msg->lparam &= ~(KF_EXTENDED << 16); + } +- else if (msg->msg != WM_INPUT) ++ else if (msg->msg != WM_INPUT && msg->msg != WM_INPUT_DEVICE_CHANGE) + { + if (msg->msg == WM_MOUSEMOVE) + { +@@ -1651,7 +1651,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa + static struct thread *get_foreground_thread( struct desktop *desktop, user_handle_t window ) + { + /* if desktop has no foreground process, assume the receiving window is */ +- if (desktop->foreground_input) return get_window_thread( desktop->foreground_input->focus ); ++ if (desktop && desktop->foreground_input) return get_window_thread( desktop->foreground_input->focus ); + if (window) return get_window_thread( window ); + return NULL; + } +@@ -1692,12 +1692,23 @@ static void remove_hid_rawinput_device( unsigned int index ) + hid_rawinput_devices[index].usage = 0; + } + ++static struct rawinput_device_entry *find_hid_rawinput_device( struct process *process, const union rawinput *rawinput ) ++{ ++ unsigned int index; ++ if (rawinput->type != RIM_TYPEHID) return NULL; ++ if (!(index = rawinput->hid.device)) return NULL; ++ if (hid_rawinput_device_count < index) return NULL; ++ if (!hid_rawinput_devices[index].usage_page) return NULL; ++ return find_rawinput_device( process, hid_rawinput_devices[index].usage_page, hid_rawinput_devices[index].usage ); ++} ++ + struct rawinput_message + { + struct thread *foreground; + struct desktop *desktop; + struct hw_msg_source source; + unsigned int time; ++ unsigned int message; + struct hardware_msg_data data; + }; + +@@ -1705,6 +1716,7 @@ struct rawinput_message + static int queue_rawinput_message( struct process* process, void *arg ) + { + const struct rawinput_message* raw_msg = arg; ++ const struct rawinput_device_entry *entry; + const struct rawinput_device *device = NULL; + struct desktop *target_desktop = NULL, *desktop = NULL; + struct thread *target_thread = NULL, *foreground = NULL; +@@ -1715,8 +1727,12 @@ static int queue_rawinput_message( struct process* process, void *arg ) + device = process->rawinput_mouse; + else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD) + device = process->rawinput_kbd; ++ else if ((entry = find_hid_rawinput_device( process, &raw_msg->data.rawinput ))) ++ device = &entry->device; + if (!device) return 0; + ++ if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && !(device->flags & RIDEV_DEVNOTIFY)) return 0; ++ + if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop ); + else if (!(desktop = get_desktop_obj( process, process->desktop, 0 ))) goto done; + +@@ -1725,7 +1741,7 @@ static int queue_rawinput_message( struct process* process, void *arg ) + + if (process != foreground->process) + { +- if (!(device->flags & RIDEV_INPUTSINK)) goto done; ++ if (raw_msg->message == WM_INPUT && !(device->flags & RIDEV_INPUTSINK)) goto done; + if (!(target_thread = get_window_thread( device->target ))) goto done; + if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done; + if (target_desktop != desktop) goto done; +@@ -1736,11 +1752,17 @@ static int queue_rawinput_message( struct process* process, void *arg ) + goto done; + + msg->win = device->target; +- msg->msg = WM_INPUT; ++ msg->msg = raw_msg->message; + msg->wparam = wparam; + msg->lparam = 0; + memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) ); + ++ if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->data.rawinput.type == RIM_TYPEHID) ++ { ++ msg->wparam = raw_msg->data.rawinput.hid.param; ++ msg->lparam = raw_msg->data.rawinput.hid.device; ++ } ++ + queue_hardware_message( desktop, msg, 1 ); + + done: +@@ -1814,6 +1836,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons + raw_msg.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time; ++ raw_msg.message = WM_INPUT; + + msg_data = &raw_msg.data; + msg_data->info = input->mouse.info; +@@ -1948,6 +1971,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c + raw_msg.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time; ++ raw_msg.message = WM_INPUT; + + msg_data = &raw_msg.data; + msg_data->info = input->kbd.info; +@@ -2003,18 +2027,35 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + unsigned int origin, const hw_input_t *input ) + { + struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; ++ struct hardware_msg_data *msg_data; ++ struct rawinput_message raw_msg; + struct message *msg; + + switch (input->hw.msg) + { + case WM_INPUT_DEVICE_CHANGE: ++ raw_msg.foreground = get_foreground_thread( desktop, win ); ++ raw_msg.desktop = desktop; ++ raw_msg.source = source; ++ raw_msg.time = get_tick_count(); ++ raw_msg.message = input->hw.msg; ++ ++ msg_data = &raw_msg.data; ++ msg_data->info = 0; ++ msg_data->flags = 0; ++ msg_data->rawinput = input->hw.data.rawinput; ++ + if (input->hw.data.rawinput.type == RIM_TYPEHID && + input->hw.data.rawinput.hid.param == GIDC_ARRIVAL) + insert_hid_rawinput_device( input->hw.data.rawinput.hid.device, get_req_data(), get_req_data_size() ); + ++ enum_processes( queue_rawinput_message, &raw_msg ); ++ + if (input->hw.data.rawinput.type == RIM_TYPEHID && + input->hw.data.rawinput.hid.param == GIDC_REMOVAL) + remove_hid_rawinput_device( input->hw.data.rawinput.hid.device ); ++ ++ if (raw_msg.foreground) release_object( raw_msg.foreground ); + return; + } + +@@ -2151,7 +2192,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user + + data->hw_id = msg->unique_id; + set_reply_data( msg->data, msg->data_size ); +- if (msg->msg == WM_INPUT && (flags & PM_REMOVE)) ++ if ((msg->msg == WM_INPUT || msg->msg == WM_INPUT_DEVICE_CHANGE) && (flags & PM_REMOVE)) + release_hardware_message( current->queue, data->hw_id ); + return 1; + } +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0013-hidclass.sys-Send-rawinput-messages-with-HID-report.patch b/patches/user32-rawinput-hid/0013-hidclass.sys-Send-rawinput-messages-with-HID-report.patch new file mode 100644 index 00000000..f5415a08 --- /dev/null +++ b/patches/user32-rawinput-hid/0013-hidclass.sys-Send-rawinput-messages-with-HID-report.patch @@ -0,0 +1,73 @@ +From 7819fe251e3f12eda8ee615aa735b1870a49e3b9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Fri, 5 Mar 2021 10:41:20 +0100 +Subject: [PATCH] hidclass.sys: Send rawinput messages with HID report. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/hidclass.sys/device.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c +index 9a3c92b3576..551816aa4fe 100644 +--- a/dlls/hidclass.sys/device.c ++++ b/dlls/hidclass.sys/device.c +@@ -254,6 +254,39 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U + return STATUS_BUFFER_OVERFLOW; + } + ++static void HID_Device_sendRawInput(DEVICE_OBJECT *device, HID_XFER_PACKET *packet) ++{ ++ BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; ++ RAWINPUT *rawinput; ++ UCHAR *report, id; ++ ULONG data_size; ++ INPUT input; ++ ++ data_size = offsetof(RAWINPUT, data.hid.bRawData) + packet->reportBufferLen; ++ if (!(id = ext->preparseData->reports[0].reportID)) data_size += 1; ++ ++ rawinput = HeapAlloc(GetProcessHeap(), 0, data_size); ++ ++ rawinput->header.dwType = RIM_TYPEHID; ++ rawinput->header.dwSize = data_size; ++ rawinput->header.hDevice = ULongToHandle(ext->rawinput_handle); ++ rawinput->header.wParam = RIM_INPUT; ++ rawinput->data.hid.dwCount = 1; ++ rawinput->data.hid.dwSizeHid = data_size - offsetof(RAWINPUT, data.hid.bRawData); ++ ++ report = rawinput->data.hid.bRawData; ++ if (!id) *report++ = 0; ++ memcpy(report, packet->reportBuffer, packet->reportBufferLen); ++ ++ input.type = INPUT_HARDWARE; ++ input.u.hi.uMsg = WM_INPUT; ++ input.u.hi.wParamH = (WORD)(rawinput->header.dwSize >> 16); ++ input.u.hi.wParamL = (WORD)(rawinput->header.dwSize >> 0); ++ __wine_send_input(0, &input, rawinput); ++ ++ HeapFree(GetProcessHeap(), 0, rawinput); ++} ++ + static void HID_Device_processQueue(DEVICE_OBJECT *device) + { + IRP *irp; +@@ -337,6 +370,7 @@ static DWORD CALLBACK hid_device_thread(void *args) + if (irp->IoStatus.u.Status == STATUS_SUCCESS) + { + RingBuffer_Write(ext->ring_buffer, packet); ++ HID_Device_sendRawInput(device, packet); + HID_Device_processQueue(device); + } + +@@ -383,6 +417,7 @@ static DWORD CALLBACK hid_device_thread(void *args) + else + packet->reportId = 0; + RingBuffer_Write(ext->ring_buffer, packet); ++ HID_Device_sendRawInput(device, packet); + HID_Device_processQueue(device); + } + +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0002-server-Allow-extra-data-for-hardware_msg_data-messag.patch b/patches/user32-rawinput-hid/0014-server-Add-extra-data-to-hardware_msg_data.patch similarity index 69% rename from patches/user32-rawinput-hid/0002-server-Allow-extra-data-for-hardware_msg_data-messag.patch rename to patches/user32-rawinput-hid/0014-server-Add-extra-data-to-hardware_msg_data.patch index 018fb128..36636786 100644 --- a/patches/user32-rawinput-hid/0002-server-Allow-extra-data-for-hardware_msg_data-messag.patch +++ b/patches/user32-rawinput-hid/0014-server-Add-extra-data-to-hardware_msg_data.patch @@ -1,19 +1,21 @@ -From ea854d200d2fb243dc898a1ef4e2a1a6f127a329 Mon Sep 17 00:00:00 2001 +From 9b9134b94879a1e501d0337cdf6f607ebe2ff84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Thu, 19 Sep 2019 09:20:44 +0200 -Subject: [PATCH] server: Allow extra data for hardware_msg_data message. +Date: Tue, 23 Mar 2021 10:11:07 +0100 +Subject: [PATCH] server: Add extra data to hardware_msg_data. The RIM_TYPEHID messages will have to carry the variable length HID report. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 --- - server/queue.c | 31 +++++++++++++++++++++---------- - 1 file changed, 21 insertions(+), 10 deletions(-) + server/queue.c | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/server/queue.c b/server/queue.c -index 810612c5167..f5d19031485 100644 +index 9fe009b5cfe..248157ca7da 100644 --- a/server/queue.c +++ b/server/queue.c -@@ -343,13 +343,13 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_ +@@ -348,13 +348,13 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_ /* allocate a hardware message and its data */ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_source source, @@ -29,7 +31,7 @@ index 810612c5167..f5d19031485 100644 { free( msg ); return NULL; -@@ -358,9 +358,9 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour +@@ -363,9 +363,9 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour msg->type = MSG_HARDWARE; msg->time = time; msg->data = msg_data; @@ -41,7 +43,7 @@ index 810612c5167..f5d19031485 100644 msg_data->info = info; msg_data->source = source; return msg; -@@ -393,7 +393,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y ) +@@ -398,7 +398,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y ) return; } @@ -50,24 +52,24 @@ index 810612c5167..f5d19031485 100644 msg->msg = WM_MOUSEMOVE; msg->x = x; -@@ -1649,6 +1649,8 @@ struct rawinput_message - struct hw_msg_source source; +@@ -1710,6 +1710,8 @@ struct rawinput_message unsigned int time; + unsigned int message; struct hardware_msg_data data; + const void *extra; + data_size_t extra_len; }; /* check if process is supposed to receive a WM_INPUT message and eventually queue it */ -@@ -1659,6 +1661,7 @@ static int queue_rawinput_message( struct process* process, void *arg ) - struct desktop *target_desktop = NULL; - struct thread *target_thread = NULL; +@@ -1721,6 +1723,7 @@ static int queue_rawinput_message( struct process* process, void *arg ) + struct desktop *target_desktop = NULL, *desktop = NULL; + struct thread *target_thread = NULL, *foreground = NULL; struct message *msg; + struct hardware_msg_data *msg_data; int wparam = RIM_INPUT; if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE) -@@ -1676,14 +1679,18 @@ static int queue_rawinput_message( struct process* process, void *arg ) +@@ -1748,14 +1751,18 @@ static int queue_rawinput_message( struct process* process, void *arg ) wparam = RIM_INPUTSINK; } @@ -77,7 +79,7 @@ index 810612c5167..f5d19031485 100644 + msg_data = msg->data; msg->win = device->target; - msg->msg = WM_INPUT; + msg->msg = raw_msg->message; msg->wparam = wparam; msg->lparam = 0; - memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) ); @@ -86,18 +88,18 @@ index 810612c5167..f5d19031485 100644 + if (raw_msg->extra_len && raw_msg->extra) + memcpy( msg_data + 1, raw_msg->extra, raw_msg->extra_len ); - queue_hardware_message( raw_msg->desktop, msg, 1 ); - -@@ -1756,6 +1763,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons - raw_msg.desktop = desktop; + if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->data.rawinput.type == RIM_TYPEHID) + { +@@ -1837,6 +1844,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons raw_msg.source = source; raw_msg.time = time; + raw_msg.message = WM_INPUT; + raw_msg.extra = NULL; + raw_msg.extra_len = 0; msg_data = &raw_msg.data; msg_data->info = input->mouse.info; -@@ -1785,7 +1794,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons +@@ -1862,7 +1871,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons if (!(flags & (1 << i))) continue; flags &= ~(1 << i); @@ -106,33 +108,42 @@ index 810612c5167..f5d19031485 100644 msg_data = msg->data; msg->win = get_user_full_handle( win ); -@@ -1894,6 +1903,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c - raw_msg.desktop = desktop; +@@ -1972,6 +1981,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c raw_msg.source = source; raw_msg.time = time; + raw_msg.message = WM_INPUT; + raw_msg.extra = NULL; + raw_msg.extra_len = 0; msg_data = &raw_msg.data; msg_data->info = input->kbd.info; -@@ -1917,7 +1928,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c - if (!(req_flags & SEND_HWMSG_WINDOW)) +@@ -1991,7 +2002,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c return 0; + } - if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; + if (!(msg = alloc_hardware_message( input->kbd.info, source, time, 0 ))) return 0; msg_data = msg->data; msg->win = get_user_full_handle( win ); -@@ -1955,7 +1966,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ - struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; - struct message *msg; +@@ -2039,6 +2050,8 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + raw_msg.source = source; + raw_msg.time = get_tick_count(); + raw_msg.message = input->hw.msg; ++ raw_msg.extra = NULL; ++ raw_msg.extra_len = 0; + msg_data = &raw_msg.data; + msg_data->info = 0; +@@ -2060,7 +2073,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + } + + if (!desktop) return; - if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return; + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return; msg->win = get_user_full_handle( win ); msg->msg = input->hw.msg; -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-hid/0015-server-Implement-WM_INPUT-RIM_TYPEHID-message-dispat.patch b/patches/user32-rawinput-hid/0015-server-Implement-WM_INPUT-RIM_TYPEHID-message-dispat.patch new file mode 100644 index 00000000..0d4d8c5b --- /dev/null +++ b/patches/user32-rawinput-hid/0015-server-Implement-WM_INPUT-RIM_TYPEHID-message-dispat.patch @@ -0,0 +1,185 @@ +From d394cc092108c710ad2cccbcec1919a084037910 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Tue, 23 Mar 2021 10:42:07 +0100 +Subject: [PATCH] server: Implement WM_INPUT / RIM_TYPEHID message dispatch. + +The messages are of variable size and carry the corresponding HID report +data after each RAWINPUT struct. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506 +--- + dlls/user32/message.c | 1 + + dlls/user32/rawinput.c | 23 +++++++++++++++++++++-- + server/protocol.def | 2 +- + server/queue.c | 25 ++++++++++++++++++------- + server/trace.c | 1 + + 5 files changed, 42 insertions(+), 10 deletions(-) + +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index 54fcdc4588c..f986b71953a 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -3272,6 +3272,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r + req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH ); + switch (input->u.hi.uMsg) + { ++ case WM_INPUT: + case WM_INPUT_DEVICE_CHANGE: + req->input.hw.data.rawinput.type = rawinput->header.dwType; + switch (rawinput->header.dwType) +diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c +index 99481ffae3d..c69393d9ed2 100644 +--- a/dlls/user32/rawinput.c ++++ b/dlls/user32/rawinput.c +@@ -326,6 +326,22 @@ BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_ms + rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message; + rawinput->data.keyboard.ExtraInformation = msg_data->info; + } ++ else if (msg_data->rawinput.type == RIM_TYPEHID) ++ { ++ if (sizeof(*rawinput) + msg_data->rawinput.hid.length > RAWINPUT_BUFFER_SIZE) ++ { ++ ERR( "unexpectedly large hardware message dropped\n" ); ++ return FALSE; ++ } ++ ++ rawinput->header.dwSize = FIELD_OFFSET( RAWINPUT, data.hid.bRawData ) + msg_data->rawinput.hid.length; ++ rawinput->header.hDevice = ULongToHandle( msg_data->rawinput.hid.device ); ++ rawinput->header.wParam = 0; ++ ++ rawinput->data.hid.dwSizeHid = msg_data->rawinput.hid.length; ++ rawinput->data.hid.dwCount = 1; ++ memcpy( rawinput->data.hid.bRawData, msg_data + 1, msg_data->rawinput.hid.length ); ++ } + else + { + FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type); +@@ -524,7 +540,7 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, + struct hardware_msg_data *msg_data; + struct rawinput_thread_data *thread_data; + RAWINPUT *rawinput; +- UINT count = 0, rawinput_size, next_size, overhead; ++ UINT count = 0, rawinput_size, msg_size, next_size, overhead; + BOOL is_wow64; + int i; + +@@ -584,7 +600,9 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, + data->header.dwSize - sizeof(RAWINPUTHEADER)); + data->header.dwSize += overhead; + data = NEXTRAWINPUTBLOCK(data); +- msg_data++; ++ msg_size = sizeof(*msg_data); ++ if (msg_data->rawinput.type == RIM_TYPEHID) msg_size += msg_data->rawinput.hid.length; ++ msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_size); + } + + if (count == 0 && next_size == 0) *data_size = 0; +@@ -657,6 +675,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT + handle, command, data, data_size); + + if (!data_size) return ~0U; ++ if (!device) return ~0U; + + /* each case below must set: + * *data_size: length (meaning defined by command) of data we want to copy +diff --git a/server/protocol.def b/server/protocol.def +index f97b966719c..829216b58c1 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -369,7 +369,7 @@ typedef union + lparam_t lparam; /* message param */ + union + { +- union rawinput rawinput; /* WM_INPUT_DEVICE_CHANGE msg */ ++ union rawinput rawinput; /* WM_INPUT and WM_INPUT_DEVICE_CHANGE msg */ + } data; + } hw; + } hw_input_t; +diff --git a/server/queue.c b/server/queue.c +index 248157ca7da..a411d0af8d2 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -2044,6 +2044,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + + switch (input->hw.msg) + { ++ case WM_INPUT: + case WM_INPUT_DEVICE_CHANGE: + raw_msg.foreground = get_foreground_thread( desktop, win ); + raw_msg.desktop = desktop; +@@ -2053,18 +2054,26 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + raw_msg.extra = NULL; + raw_msg.extra_len = 0; + ++ if (input->hw.msg == WM_INPUT) ++ { ++ raw_msg.extra = get_req_data(); ++ raw_msg.extra_len = get_req_data_size(); ++ } ++ + msg_data = &raw_msg.data; + msg_data->info = 0; + msg_data->flags = 0; + msg_data->rawinput = input->hw.data.rawinput; + +- if (input->hw.data.rawinput.type == RIM_TYPEHID && ++ if (input->hw.msg == WM_INPUT_DEVICE_CHANGE && ++ input->hw.data.rawinput.type == RIM_TYPEHID && + input->hw.data.rawinput.hid.param == GIDC_ARRIVAL) + insert_hid_rawinput_device( input->hw.data.rawinput.hid.device, get_req_data(), get_req_data_size() ); + + enum_processes( queue_rawinput_message, &raw_msg ); + +- if (input->hw.data.rawinput.type == RIM_TYPEHID && ++ if (input->hw.msg == WM_INPUT_DEVICE_CHANGE && ++ input->hw.data.rawinput.type == RIM_TYPEHID && + input->hw.data.rawinput.hid.param == GIDC_REMOVAL) + remove_hid_rawinput_device( input->hw.data.rawinput.hid.device ); + +@@ -3371,16 +3380,18 @@ DECL_HANDLER(get_rawinput_buffer) + { + struct message *msg = LIST_ENTRY( ptr, struct message, entry ); + struct hardware_msg_data *data = msg->data; ++ data_size_t hid_size = data->rawinput.type != RIM_TYPEHID ? 0 : data->rawinput.hid.length; ++ data_size_t data_size = sizeof(*data) + hid_size; + + ptr = list_next( &input->msg_list, ptr ); + if (msg->msg != WM_INPUT) continue; + +- next_size = req->rawinput_size; ++ next_size = req->rawinput_size + hid_size; + if (size + next_size > req->buffer_size) break; +- if (cur + sizeof(*data) > buf + get_reply_max_size()) break; +- if (cur + sizeof(*data) > buf + buf_size) ++ if (cur + data_size > buf + get_reply_max_size()) break; ++ if (cur + data_size > buf + buf_size) + { +- buf_size += buf_size / 2; ++ buf_size += buf_size / 2 + hid_size; + if (!(tmp = realloc( buf, buf_size ))) + { + set_error( STATUS_NO_MEMORY ); +@@ -3390,7 +3401,7 @@ DECL_HANDLER(get_rawinput_buffer) + buf = tmp; + } + +- memcpy(cur, data, sizeof(*data)); ++ memcpy( cur, data, data_size ); + list_remove( &msg->entry ); + free_message( msg ); + +diff --git a/server/trace.c b/server/trace.c +index 3d24cec0133..f50a0367683 100644 +--- a/server/trace.c ++++ b/server/trace.c +@@ -471,6 +471,7 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input ) + dump_uint64( ",lparam=", &input->hw.lparam ); + switch (input->hw.msg) + { ++ case WM_INPUT: + case WM_INPUT_DEVICE_CHANGE: + dump_rawinput( ",rawinput=", &input->hw.data.rawinput ); + } +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0016-ntoskrnl-Implement-IoSetDevicePropertyData.patch b/patches/user32-rawinput-hid/0016-ntoskrnl-Implement-IoSetDevicePropertyData.patch new file mode 100644 index 00000000..c2717a48 --- /dev/null +++ b/patches/user32-rawinput-hid/0016-ntoskrnl-Implement-IoSetDevicePropertyData.patch @@ -0,0 +1,124 @@ +From 2e8dd5065ba659d6f5f5c5bedadbec4e06a98a6a Mon Sep 17 00:00:00 2001 +From: Arkadiusz Hiler +Date: Tue, 23 Feb 2021 14:41:58 +0200 +Subject: [PATCH] ntoskrnl: Implement IoSetDevicePropertyData(). + +--- + dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 + + dlls/ntoskrnl.exe/pnp.c | 51 +++++++++++++++++++++++++++++ + include/ddk/wdm.h | 4 +++ + 3 files changed, 56 insertions(+) + +diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +index 2e5e2e6e11b..4eb08faec2e 100644 +--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec ++++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +@@ -465,6 +465,7 @@ + @ stdcall IoReuseIrp(ptr long) + @ stub IoSetCompletionRoutineEx + @ stdcall IoSetDeviceInterfaceState(ptr long) ++@ stdcall IoSetDevicePropertyData(ptr ptr long long long long ptr) + @ stub IoSetDeviceToVerify + @ stub IoSetFileOrigin + @ stub IoSetHardErrorOrVerifyDevice +diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c +index 7994a8b85b9..0d5d0d721d4 100644 +--- a/dlls/ntoskrnl.exe/pnp.c ++++ b/dlls/ntoskrnl.exe/pnp.c +@@ -38,6 +38,12 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); + + WINE_DEFAULT_DEBUG_CHANNEL(plugplay); + ++static inline const char *debugstr_propkey( const DEVPROPKEY *id ) ++{ ++ if (!id) return "(null)"; ++ return wine_dbg_sprintf( "{%s,%04x}", wine_dbgstr_guid( &id->fmtid ), id->pid ); ++} ++ + #define MAX_SERVICE_NAME 260 + + struct device_interface +@@ -770,6 +776,51 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable + return ret; + } + ++/*********************************************************************** ++ * IoSetDevicePropertyData (NTOSKRNL.EXE.@) ++ */ ++NTSTATUS WINAPI IoSetDevicePropertyData( DEVICE_OBJECT *device, const DEVPROPKEY *property_key, LCID lcid, ++ ULONG flags, DEVPROPTYPE type, ULONG size, void *data ) ++{ ++ SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; ++ WCHAR device_instance_id[MAX_DEVICE_ID_LEN]; ++ NTSTATUS status; ++ HDEVINFO set; ++ ++ TRACE( "device %p, property_key %s, lcid %#x, flags %#x, type %#x, size %u, data %p.\n", ++ device, debugstr_propkey(property_key), lcid, flags, type, size, data ); ++ ++ /* flags is always treated as PLUGPLAY_PROPERTY_PERSISTENT starting with Win 8 / 2012 */ ++ ++ if (lcid != LOCALE_NEUTRAL) FIXME( "only LOCALE_NEUTRAL is supported\n" ); ++ ++ if ((status = get_device_instance_id( device, device_instance_id ))) return status; ++ ++ if ((set = SetupDiCreateDeviceInfoList( &GUID_NULL, NULL )) == INVALID_HANDLE_VALUE) ++ { ++ ERR( "Failed to create device list, error %#x.\n", GetLastError() ); ++ return GetLastError(); ++ } ++ ++ if (!SetupDiOpenDeviceInfoW( set, device_instance_id, NULL, 0, &sp_device )) ++ { ++ ERR( "Failed to open device, error %#x.\n", GetLastError() ); ++ SetupDiDestroyDeviceInfoList( set ); ++ return GetLastError(); ++ } ++ ++ if (!SetupDiSetDevicePropertyW( set, &sp_device, property_key, type, data, size, 0 )) ++ { ++ ERR( "Failed to set property, error %#x.\n", GetLastError() ); ++ SetupDiDestroyDeviceInfoList( set ); ++ return GetLastError(); ++ } ++ ++ SetupDiDestroyDeviceInfoList( set ); ++ ++ return STATUS_SUCCESS; ++} ++ + /*********************************************************************** + * IoRegisterDeviceInterface (NTOSKRNL.EXE.@) + */ +diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h +index 3b9af7d52b2..3d0f810c2f0 100644 +--- a/include/ddk/wdm.h ++++ b/include/ddk/wdm.h +@@ -21,6 +21,7 @@ + #define _NTDDK_ + + #include ++#include + + #ifdef _WIN64 + #define POINTER_ALIGNMENT DECLSPEC_ALIGN(8) +@@ -1677,6 +1678,8 @@ void WINAPI ExReleaseResourceForThreadLite(ERESOURCE*,ERESOURCE_THREAD); + ULONG WINAPI ExSetTimerResolution(ULONG,BOOLEAN); + void WINAPI ExUnregisterCallback(void*); + ++#define PLUGPLAY_PROPERTY_PERSISTENT 0x0001 ++ + void WINAPI IoAcquireCancelSpinLock(KIRQL*); + NTSTATUS WINAPI IoAcquireRemoveLockEx(IO_REMOVE_LOCK*,void*,const char*,ULONG, ULONG); + NTSTATUS WINAPI IoAllocateDriverObjectExtension(PDRIVER_OBJECT,PVOID,ULONG,PVOID*); +@@ -1724,6 +1727,7 @@ void WINAPI IoReleaseRemoveLockAndWaitEx(IO_REMOVE_LOCK*,void*,ULONG); + void WINAPI IoReleaseRemoveLockEx(IO_REMOVE_LOCK*,void*,ULONG); + void WINAPI IoReuseIrp(IRP*,NTSTATUS); + NTSTATUS WINAPI IoSetDeviceInterfaceState(UNICODE_STRING*,BOOLEAN); ++NTSTATUS WINAPI IoSetDevicePropertyData(DEVICE_OBJECT*,const DEVPROPKEY*,LCID,ULONG,DEVPROPTYPE,ULONG,void*); + NTSTATUS WINAPI IoWMIRegistrationControl(PDEVICE_OBJECT,ULONG); + + void FASTCALL KeAcquireInStackQueuedSpinLockAtDpcLevel(KSPIN_LOCK*,KLOCK_QUEUE_HANDLE*); +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0017-hidclass.sys-Assign-rawinput-handles-through-device-.patch b/patches/user32-rawinput-hid/0017-hidclass.sys-Assign-rawinput-handles-through-device-.patch new file mode 100644 index 00000000..34bf736b --- /dev/null +++ b/patches/user32-rawinput-hid/0017-hidclass.sys-Assign-rawinput-handles-through-device-.patch @@ -0,0 +1,48 @@ +From 613004e02a06a93598c45f323fe5b4cd9c989194 Mon Sep 17 00:00:00 2001 +From: Arkadiusz Hiler +Date: Wed, 10 Feb 2021 13:23:33 +0100 +Subject: [PATCH] hidclass.sys: Assign rawinput handles through device + properties. + +--- + dlls/hidclass.sys/device.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c +index 551816aa4fe..fb571bea314 100644 +--- a/dlls/hidclass.sys/device.c ++++ b/dlls/hidclass.sys/device.c +@@ -33,11 +33,14 @@ + + #include "initguid.h" + #include "devguid.h" ++#include "devpkey.h" + #include "ntddmou.h" + + WINE_DEFAULT_DEBUG_CHANNEL(hid); + WINE_DECLARE_DEBUG_CHANNEL(hid_report); + ++DEFINE_DEVPROPKEY(DEVPROPKEY_HID_HANDLE, 0xbc62e415, 0xf4fe, 0x405c, 0x8e, 0xda, 0x63, 0x6f, 0xb5, 0x9f, 0x08, 0x98, 2); ++ + NTSTATUS HID_CreateDevice(DEVICE_OBJECT *native_device, HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT **device) + { + WCHAR dev_name[255]; +@@ -144,6 +147,15 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device) + else + ext->rawinput_handle = alloc_rawinput_handle(); + ++ status = IoSetDevicePropertyData(device, &DEVPROPKEY_HID_HANDLE, LOCALE_NEUTRAL, ++ PLUGPLAY_PROPERTY_PERSISTENT, DEVPROP_TYPE_UINT32, ++ sizeof(ext->rawinput_handle), &ext->rawinput_handle); ++ if (status != STATUS_SUCCESS) ++ { ++ FIXME("failed to set device property %x\n", status); ++ return status; ++ } ++ + return STATUS_SUCCESS; + + error: +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0018-user32-Enumerate-mouse-rawinput-device-before-HID-de.patch b/patches/user32-rawinput-hid/0018-user32-Enumerate-mouse-rawinput-device-before-HID-de.patch new file mode 100644 index 00000000..f9177b02 --- /dev/null +++ b/patches/user32-rawinput-hid/0018-user32-Enumerate-mouse-rawinput-device-before-HID-de.patch @@ -0,0 +1,61 @@ +From c28c0feaa804d97e3d105d402f12430e6cee054e Mon Sep 17 00:00:00 2001 +From: Arkadiusz Hiler +Date: Mon, 22 Feb 2021 15:41:46 +0200 +Subject: [PATCH] user32: Enumerate mouse rawinput device before HID devices. + +--- + dlls/user32/rawinput.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c +index c69393d9ed2..ea8d15ac97b 100644 +--- a/dlls/user32/rawinput.c ++++ b/dlls/user32/rawinput.c +@@ -175,6 +175,22 @@ static void find_devices(void) + } + rawinput_devices_count = 0; + ++ set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MOUSE, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); ++ ++ /* add mice first so we won't add the duplicated HID devices */ ++ for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_MOUSE, idx, &iface); ++idx) ++ { ++ static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE}; ++ ++ if (!(device = add_device(set, &iface))) ++ continue; ++ ++ device->info.dwType = RIM_TYPEMOUSE; ++ device->info.u.mouse = mouse_info; ++ } ++ ++ SetupDiDestroyDeviceInfoList(set); ++ + set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + + for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &hid_guid, idx, &iface); ++idx) +@@ -203,21 +219,6 @@ static void find_devices(void) + + SetupDiDestroyDeviceInfoList(set); + +- set = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MOUSE, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); +- +- for (idx = 0; SetupDiEnumDeviceInterfaces(set, NULL, &GUID_DEVINTERFACE_MOUSE, idx, &iface); ++idx) +- { +- static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE}; +- +- if (!(device = add_device(set, &iface))) +- continue; +- +- device->info.dwType = RIM_TYPEMOUSE; +- device->info.u.mouse = mouse_info; +- } +- +- SetupDiDestroyDeviceInfoList(set); +- + LeaveCriticalSection(&rawinput_devices_cs); + } + +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/0019-user32-Use-device-handles-assigned-by-hidclass.sys.patch b/patches/user32-rawinput-hid/0019-user32-Use-device-handles-assigned-by-hidclass.sys.patch new file mode 100644 index 00000000..34055315 --- /dev/null +++ b/patches/user32-rawinput-hid/0019-user32-Use-device-handles-assigned-by-hidclass.sys.patch @@ -0,0 +1,153 @@ +From f7bb329873ec91a2ed7adbca8b5fac5f774e324d Mon Sep 17 00:00:00 2001 +From: Arkadiusz Hiler +Date: Mon, 22 Feb 2021 15:41:46 +0200 +Subject: [PATCH] user32: Use device handles assigned by hidclass.sys. + +This allows us to avoid racy handle mapping for messages from the WM_INPUT +family. +--- + dlls/user32/rawinput.c | 61 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 51 insertions(+), 10 deletions(-) + +diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c +index ea8d15ac97b..91315692ac5 100644 +--- a/dlls/user32/rawinput.c ++++ b/dlls/user32/rawinput.c +@@ -38,14 +38,18 @@ + #include "user_private.h" + + #include "initguid.h" ++#include "devpkey.h" + #include "ntddmou.h" + + WINE_DEFAULT_DEBUG_CHANNEL(rawinput); + ++DEFINE_DEVPROPKEY(DEVPROPKEY_HID_HANDLE, 0xbc62e415, 0xf4fe, 0x405c, 0x8e, 0xda, 0x63, 0x6f, 0xb5, 0x9f, 0x08, 0x98, 2); ++ + struct device + { + WCHAR *path; + HANDLE file; ++ HANDLE handle; + RID_DEVICE_INFO info; + PHIDP_PREPARSED_DATA data; + }; +@@ -91,11 +95,13 @@ static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int + + static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) + { ++ SP_DEVINFO_DATA device_data = {sizeof(device_data)}; + SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail; ++ UINT32 handle; + struct device *device; + HANDLE file; + WCHAR *path; +- DWORD size; ++ DWORD idx, size, type; + + SetupDiGetDeviceInterfaceDetailW(set, iface, NULL, 0, &size, NULL); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) +@@ -109,7 +115,27 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) + return FALSE; + } + detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); +- SetupDiGetDeviceInterfaceDetailW(set, iface, detail, size, NULL, NULL); ++ SetupDiGetDeviceInterfaceDetailW(set, iface, detail, size, NULL, &device_data); ++ ++ if (!SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_HID_HANDLE, &type, (BYTE *)&handle, sizeof(handle), NULL, 0)) ++ { ++ ERR("Failed to get handle for %s, skipping HID device.\n", debugstr_w(detail->DevicePath)); ++ heap_free(detail); ++ return NULL; ++ } ++ ++ if (type != DEVPROP_TYPE_UINT32) ++ ERR("Wrong prop type for HANDLE.\n"); ++ ++ for (idx = 0; idx < rawinput_devices_count; ++idx) ++ { ++ if (rawinput_devices[idx].handle == ULongToHandle(handle)) ++ { ++ TRACE("Discarding %s as it's a duplicate of %s.\n", debugstr_w(detail->DevicePath), debugstr_w(rawinput_devices[idx].path)); ++ heap_free(detail); ++ return NULL; ++ } ++ } + + TRACE("Found HID device %s.\n", debugstr_w(detail->DevicePath)); + +@@ -143,14 +169,13 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface) + device->path = path; + device->file = file; + device->info.cbSize = sizeof(RID_DEVICE_INFO); ++ device->handle = ULongToHandle(handle); + + return device; + } + + static void find_devices(void) + { +- static ULONGLONG last_check; +- + SP_DEVICE_INTERFACE_DATA iface = { sizeof(iface) }; + struct device *device; + HIDD_ATTRIBUTES attr; +@@ -159,10 +184,6 @@ static void find_devices(void) + HDEVINFO set; + DWORD idx; + +- if (GetTickCount64() - last_check < 2000) +- return; +- last_check = GetTickCount64(); +- + HidD_GetHidGuid(&hid_guid); + + EnterCriticalSection(&rawinput_devices_cs); +@@ -223,6 +244,26 @@ static void find_devices(void) + } + + ++static struct device *rawinput_device_from_handle(HANDLE handle) ++{ ++ unsigned int i; ++ ++ if (!handle) return NULL; ++ ++ for (i = 0; i < rawinput_devices_count; ++i) ++ if (rawinput_devices[i].handle == handle) ++ return &rawinput_devices[i]; ++ ++ find_devices(); ++ ++ for (i = 0; i < rawinput_devices_count; ++i) ++ if (rawinput_devices[i].handle == handle) ++ return &rawinput_devices[i]; ++ ++ return NULL; ++} ++ ++ + struct rawinput_thread_data *rawinput_thread_data(void) + { + struct user_thread_info *thread_info = get_user_thread_info(); +@@ -396,7 +437,7 @@ UINT WINAPI GetRawInputDeviceList(RAWINPUTDEVICELIST *devices, UINT *device_coun + + for (i = 0; i < rawinput_devices_count; ++i) + { +- devices[2 + i].hDevice = &rawinput_devices[i]; ++ devices[2 + i].hDevice = rawinput_devices[i].handle; + devices[2 + i].dwType = rawinput_devices[i].info.dwType; + } + +@@ -668,7 +709,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT + static const RID_DEVICE_INFO_MOUSE mouse_info = {1, 5, 0, FALSE}; + + RID_DEVICE_INFO info; +- struct device *device = handle; ++ struct device *device = rawinput_device_from_handle(handle); + const void *to_copy; + UINT to_copy_bytes, avail_bytes; + +-- +2.30.2 + diff --git a/patches/user32-rawinput-hid/definition b/patches/user32-rawinput-hid/definition index ead6aab3..d39ee187 100644 --- a/patches/user32-rawinput-hid/definition +++ b/patches/user32-rawinput-hid/definition @@ -1,2 +1,2 @@ -# Depends: user32-rawinput-mouse -Disabled: true +Fixes: [50506] WM_INPUT messages are not received for HID devices registered with RegisterRawInputDevices +Depends: loader-KeyboardLayouts diff --git a/patches/user32-rawinput-mouse-experimental/0001-winex11.drv-Add-support-for-absolute-RawMotion-event.patch b/patches/user32-rawinput-mouse-experimental/0001-winex11.drv-Add-support-for-absolute-RawMotion-event.patch index 999b472b..4f4a3521 100644 --- a/patches/user32-rawinput-mouse-experimental/0001-winex11.drv-Add-support-for-absolute-RawMotion-event.patch +++ b/patches/user32-rawinput-mouse-experimental/0001-winex11.drv-Add-support-for-absolute-RawMotion-event.patch @@ -1,4 +1,4 @@ -From 45bb2783e35fd9d20acc88bac151af3a57662edf Mon Sep 17 00:00:00 2001 +From c6fffd9e7e10b3ac95aed8165ecffd1e1da30f61 Mon Sep 17 00:00:00 2001 From: Derek Lesho Date: Tue, 25 Jun 2019 22:37:34 -0400 Subject: [PATCH] winex11.drv: Add support for absolute RawMotion events. @@ -20,16 +20,17 @@ and absolute position events. --- dlls/user32/rawinput.c | 7 ++- dlls/winex11.drv/mouse.c | 96 +++++++++++++++++++++------------- + dlls/winex11.drv/window.c | 3 +- dlls/winex11.drv/x11drv.h | 18 +++---- dlls/winex11.drv/x11drv_main.c | 2 + server/queue.c | 4 +- - 5 files changed, 79 insertions(+), 48 deletions(-) + 6 files changed, 81 insertions(+), 49 deletions(-) diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c -index 90dc911397d..d6dc377ddc3 100644 +index 91315692ac5..2e3f4301a4d 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c -@@ -289,7 +289,12 @@ BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_ms +@@ -296,7 +296,12 @@ BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_ms rawinput->header.hDevice = WINE_MOUSE_HANDLE; rawinput->header.wParam = 0; @@ -44,7 +45,7 @@ index 90dc911397d..d6dc377ddc3 100644 rawinput->data.mouse.u.s.usButtonData = 0; for (i = 1; i < ARRAY_SIZE(button_flags); ++i) diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index ded877a140f..84a47f1e522 100644 +index 0558467a805..dcc9fe82fd1 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -331,32 +331,40 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator @@ -78,16 +79,17 @@ index ded877a140f..84a47f1e522 100644 - { - valuator_data = &thread_data->y_rel_valuator; - } -+ class->label == x11drv_atom( Abs_Y ) || -+ (!class->label && class->number == 1)) -+ thread_data->y_pos_valuator = *class; -+ } - +- - if (valuator_data) { - valuator_data->number = class->number; - valuator_data->min = class->min; - valuator_data->max = class->max; - } ++ class->label == x11drv_atom( Abs_Y ) || ++ (!class->label && class->number == 1)) ++ thread_data->y_pos_valuator = *class; + } ++ + if (thread_data->x_pos_valuator.number < 0 || thread_data->y_pos_valuator.number < 0) + { + WARN("Only one X/Y axis found, ignoring RawMotion events\n"); @@ -97,7 +99,7 @@ index ded877a140f..84a47f1e522 100644 + WARN("Relative/Absolute mismatch between X/Y axis, ignoring RawMotion events\n"); + thread_data->y_pos_valuator.number = -1; + thread_data->y_pos_valuator.number = -1; - } ++ } + + if (thread_data->x_pos_valuator.min >= thread_data->x_pos_valuator.max) + thread_data->x_pos_valuator.min = thread_data->x_pos_valuator.max = 0; @@ -106,18 +108,18 @@ index ded877a140f..84a47f1e522 100644 } #endif -@@ -441,8 +449,8 @@ void X11DRV_XInput2_Disable(void) - mask.deviceid = XIAllMasterDevices; +@@ -478,8 +486,8 @@ void x11drv_xinput_disable( Display *display, Window window, long event_mask ) + pXISelectEvents( display, DefaultRootWindow( display ), &mask, 1 ); - pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 ); + if (!data) return; - data->x_rel_valuator.number = -1; - data->y_rel_valuator.number = -1; + data->x_pos_valuator.number = -1; + data->y_pos_valuator.number = -1; data->xi2_core_pointer = 0; + data->xi2_state = xi_disabled; #endif - } -@@ -1893,16 +1901,22 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1950,16 +1958,22 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) INPUT input; int i; double dx = 0, dy = 0, val; @@ -144,19 +146,18 @@ index ded877a140f..84a47f1e522 100644 input.type = INPUT_MOUSE; input.u.mi.mouseData = 0; -@@ -1913,24 +1927,34 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1970,24 +1984,34 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) input.u.mi.dy = 0; virtual_rect = get_virtual_screen_rect(); -- -- for (i = 0; i <= max ( x_rel->number, y_rel->number ); i++) + if (x_pos->min < x_pos->max) + x_scale = (x_pos->mode == XIModeAbsolute ? 65535 : (virtual_rect.right - virtual_rect.left)) / + (x_pos->max - x_pos->min); + if (y_pos->min < y_pos->max) + y_scale = (y_pos->mode == XIModeAbsolute ? 65535 : (virtual_rect.bottom - virtual_rect.top)) / + (y_pos->max - y_pos->min); -+ + +- for (i = 0; i <= max ( x_rel->number, y_rel->number ); i++) + for (i = 0; i <= max( x_pos->number, y_pos->number ); i++) { if (!XIMaskIsSet( event->valuators.mask, i )) continue; @@ -191,8 +192,29 @@ index ded877a140f..84a47f1e522 100644 } } +diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c +index 4005e3df387..13ab69ec0ef 100644 +--- a/dlls/winex11.drv/window.c ++++ b/dlls/winex11.drv/window.c +@@ -37,6 +37,8 @@ + #include + #endif /* HAVE_LIBXSHAPE */ + ++#include "x11drv.h" ++ + /* avoid conflict with field names in included win32 headers */ + #undef Status + #include "windef.h" +@@ -45,7 +47,6 @@ + #include "winuser.h" + #include "wine/unicode.h" + +-#include "x11drv.h" + #include "wine/debug.h" + #include "wine/server.h" + #include "mwm.h" diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 6febdc18b0a..396056464a7 100644 +index 910a6c6cc18..3155d23baf0 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -32,6 +32,9 @@ @@ -205,7 +227,7 @@ index 6febdc18b0a..396056464a7 100644 #define BOOL X_BOOL #define BYTE X_BYTE -@@ -318,13 +321,6 @@ struct x11drv_escape_flush_gl_drawable +@@ -319,13 +322,6 @@ struct x11drv_escape_flush_gl_drawable * X11 USER driver */ @@ -216,15 +238,15 @@ index 6febdc18b0a..396056464a7 100644 - int number; -}; - - struct x11drv_thread_data + enum xi2_state { - Display *display; -@@ -340,11 +336,13 @@ struct x11drv_thread_data + xi_unavailable = -1, +@@ -349,11 +345,13 @@ struct x11drv_thread_data HWND clip_hwnd; /* message window stored in desktop while clipping is active */ DWORD clip_reset; /* time when clipping was last reset */ HKL kbd_layout; /* active keyboard layout */ +#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H - enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */ + enum xi2_state xi2_state; /* XInput2 state */ - struct x11drv_valuator_data x_rel_valuator; - struct x11drv_valuator_data y_rel_valuator; + XIValuatorClassInfo x_pos_valuator; @@ -235,7 +257,7 @@ index 6febdc18b0a..396056464a7 100644 }; extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN; -@@ -429,6 +427,8 @@ enum x11drv_atoms +@@ -438,6 +436,8 @@ enum x11drv_atoms XATOM_RAW_CAP_HEIGHT, XATOM_Rel_X, XATOM_Rel_Y, @@ -245,7 +267,7 @@ index 6febdc18b0a..396056464a7 100644 XATOM_WM_DELETE_WINDOW, XATOM_WM_STATE, diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c -index 4eaedd1c556..f08ac92e36f 100644 +index d8576949aea..5a1c672b143 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -142,6 +142,8 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = @@ -258,10 +280,10 @@ index 4eaedd1c556..f08ac92e36f 100644 "WM_DELETE_WINDOW", "WM_STATE", diff --git a/server/queue.c b/server/queue.c -index fbed47d6951..161b48e888f 100644 +index 9008f8e90ff..4c68da8f737 100644 --- a/server/queue.c +++ b/server/queue.c -@@ -1783,8 +1783,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons +@@ -1851,8 +1851,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons msg_data->info = input->mouse.info; msg_data->flags = flags; msg_data->rawinput.type = RIM_TYPEMOUSE; @@ -271,7 +293,7 @@ index fbed47d6951..161b48e888f 100644 + msg_data->rawinput.mouse.y = input->mouse.y; msg_data->rawinput.mouse.data = input->mouse.data; - if ((req_flags & SEND_HWMSG_RAWINPUT)) + enum_processes( queue_rawinput_message, &raw_msg ); -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-mouse-experimental/0002-winex11.drv-Send-relative-RawMotion-events-unprocess.patch b/patches/user32-rawinput-mouse-experimental/0002-winex11.drv-Send-relative-RawMotion-events-unprocess.patch index da0a99a8..071f1f76 100644 --- a/patches/user32-rawinput-mouse-experimental/0002-winex11.drv-Send-relative-RawMotion-events-unprocess.patch +++ b/patches/user32-rawinput-mouse-experimental/0002-winex11.drv-Send-relative-RawMotion-events-unprocess.patch @@ -1,4 +1,4 @@ -From ddb1995ab864885e9ab683a16f3594e712efa669 Mon Sep 17 00:00:00 2001 +From fff35d809015ea53a7195122482e80a2dd366b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Tue, 10 Sep 2019 12:24:22 +0200 Subject: [PATCH] winex11.drv: Send relative RawMotion events unprocessed. @@ -9,19 +9,20 @@ virtual desktop space, and cursor speed is meaningless in this case. This does not support mixed relative/absolute X/Y axis. --- - dlls/winex11.drv/mouse.c | 19 +++++++++++++------ - 1 file changed, 13 insertions(+), 6 deletions(-) + dlls/winex11.drv/mouse.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index 84a47f1e522..2fcacaee95c 100644 +index dcc9fe82fd1..44e9786cd9f 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c -@@ -1897,20 +1897,17 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1953,21 +1953,18 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) { XIRawEvent *event = xev->data; const double *values = event->valuators.values; + const double *raw_values = event->raw_values; RECT virtual_rect; + RAWINPUT rawinput; INPUT input; int i; double dx = 0, dy = 0, val; @@ -39,7 +40,7 @@ index 84a47f1e522..2fcacaee95c 100644 if (!event->valuators.mask_len) return FALSE; if (thread_data->xi2_state != xi_enabled) return FALSE; if (event->deviceid != thread_data->xi2_core_pointer) return FALSE; -@@ -1938,9 +1935,11 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1995,9 +1992,11 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) { if (!XIMaskIsSet( event->valuators.mask, i )) continue; val = *values++; @@ -51,7 +52,7 @@ index 84a47f1e522..2fcacaee95c 100644 input.u.mi.dwFlags |= (x_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0); if (x_pos->mode == XIModeAbsolute) input.u.mi.dx = (dx - x_pos->min) * x_scale; -@@ -1950,6 +1949,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -2007,6 +2006,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) if (i == y_pos->number) { dy = val; @@ -59,28 +60,19 @@ index 84a47f1e522..2fcacaee95c 100644 input.u.mi.dwFlags |= (y_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0); if (y_pos->mode == XIModeAbsolute) input.u.mi.dy = (dy - y_pos->min) * y_scale; -@@ -1964,13 +1964,20 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) - return FALSE; - } - -- if (!thread_data->xi2_rawinput_only) -+ if (x_pos->mode == XIModeAbsolute) -+ { -+ TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); -+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT ); -+ } -+ else if (!thread_data->xi2_rawinput_only) - { - TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); - __wine_send_input( 0, &input, SEND_HWMSG_WINDOW ); +@@ -2028,6 +2028,12 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) } else { -+ input.u.mi.dx = raw_dx; -+ input.u.mi.dy = raw_dy; ++ if (x_pos->mode != XIModeAbsolute) ++ { ++ input.u.mi.dx = raw_dx; ++ input.u.mi.dy = raw_dy; ++ } ++ TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); - __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT ); - } + + rawinput.header.dwType = RIM_TYPEMOUSE; -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-mouse-experimental/0003-winex11.drv-Accumulate-mouse-movement-to-avoid-round.patch b/patches/user32-rawinput-mouse-experimental/0003-winex11.drv-Accumulate-mouse-movement-to-avoid-round.patch index 5001b2eb..093587d7 100644 --- a/patches/user32-rawinput-mouse-experimental/0003-winex11.drv-Accumulate-mouse-movement-to-avoid-round.patch +++ b/patches/user32-rawinput-mouse-experimental/0003-winex11.drv-Accumulate-mouse-movement-to-avoid-round.patch @@ -1,6 +1,6 @@ -From fd61f237db287d30a26fc6724103c871cff57bd2 Mon Sep 17 00:00:00 2001 -From: Jordan Galby -Date: Tue, 16 Jul 2019 00:34:38 -0400 +From 8ec7d7199eb28051e8403867a16257f8974414f0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Thu, 25 Mar 2021 14:40:26 +0100 Subject: [PATCH] winex11.drv: Accumulate mouse movement to avoid rounding losses. @@ -11,7 +11,7 @@ From: Jordan Galby 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index 2fcacaee95c..e3c5f8d122e 100644 +index 44e9786cd9f..0e1559a88f3 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -365,6 +365,9 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator @@ -24,7 +24,7 @@ index 2fcacaee95c..e3c5f8d122e 100644 } #endif -@@ -1904,6 +1907,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1961,6 +1964,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) double dx = 0, dy = 0, val; double raw_dx = 0, raw_dy = 0, raw_val; double x_scale = 1, y_scale = 1; @@ -32,7 +32,7 @@ index 2fcacaee95c..e3c5f8d122e 100644 struct x11drv_thread_data *thread_data = x11drv_thread_data(); XIValuatorClassInfo *x_pos, *y_pos; -@@ -1915,6 +1919,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1972,6 +1976,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) x_pos = &thread_data->x_pos_valuator; y_pos = &thread_data->y_pos_valuator; @@ -42,7 +42,7 @@ index 2fcacaee95c..e3c5f8d122e 100644 input.type = INPUT_MOUSE; input.u.mi.mouseData = 0; input.u.mi.dwFlags = MOUSEEVENTF_MOVE; -@@ -1942,9 +1949,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1999,9 +2006,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) raw_dx = raw_val; input.u.mi.dwFlags |= (x_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0); if (x_pos->mode == XIModeAbsolute) @@ -54,7 +54,7 @@ index 2fcacaee95c..e3c5f8d122e 100644 } if (i == y_pos->number) { -@@ -1952,18 +1959,30 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -2009,22 +2016,41 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) raw_dy = raw_val; input.u.mi.dwFlags |= (y_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0); if (y_pos->mode == XIModeAbsolute) @@ -84,15 +84,10 @@ index 2fcacaee95c..e3c5f8d122e 100644 + x_pos->value = x_accum - input.u.mi.dx; + y_pos->value = y_accum - input.u.mi.dy; + - if (x_pos->mode == XIModeAbsolute) - { - TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); -@@ -1971,14 +1990,21 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) - } - else if (!thread_data->xi2_rawinput_only) + if (!thread_data->xi2_rawinput_only) { - TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); -- __wine_send_input( 0, &input, SEND_HWMSG_WINDOW ); +- __wine_send_input( 0, &input, NULL ); + if ((dy || dy) && !(input.u.mi.dx || input.u.mi.dy)) + { + TRACE( "accumulating raw motion (event %f,%f accum %f,%f)\n", dx, dy, x_pos->value, y_pos->value ); @@ -100,18 +95,20 @@ index 2fcacaee95c..e3c5f8d122e 100644 + else + { + TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); -+ __wine_send_input( 0, &input, SEND_HWMSG_WINDOW ); ++ __wine_send_input( 0, &input, NULL ); + } } else { - input.u.mi.dx = raw_dx; - input.u.mi.dy = raw_dy; +@@ -2034,7 +2060,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) + input.u.mi.dy = raw_dy; + } + - TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); + TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, raw_dx, raw_dy ); - __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT ); - } - return TRUE; + + rawinput.header.dwType = RIM_TYPEMOUSE; + rawinput.header.dwSize = offsetof(RAWINPUT, data) + sizeof(RAWMOUSE); -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-mouse-experimental/definition b/patches/user32-rawinput-mouse-experimental/definition index c3a3b748..fe2d8d5e 100644 --- a/patches/user32-rawinput-mouse-experimental/definition +++ b/patches/user32-rawinput-mouse-experimental/definition @@ -1,3 +1,2 @@ Fixes: [45882] - Raw Input should use untransformed mouse values (affects Overwatch, several Source games). -# Depends: user32-rawinput-mouse -Disabled: true +Depends: user32-rawinput-mouse diff --git a/patches/user32-rawinput-mouse/0001-winex11.drv-Split-XInput2-thread-initialization.patch b/patches/user32-rawinput-mouse/0001-winex11.drv-Split-XInput2-thread-initialization.patch new file mode 100644 index 00000000..21bccfa9 --- /dev/null +++ b/patches/user32-rawinput-mouse/0001-winex11.drv-Split-XInput2-thread-initialization.patch @@ -0,0 +1,133 @@ +From 8016a35cf5771858b2b6245ee22e60c23a1bafd6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Fri, 17 Jan 2020 16:33:11 +0100 +Subject: [PATCH] winex11.drv: Split XInput2 thread initialization. + +And rename the library and function loader to x11drv_xinput_load. +--- + dlls/winex11.drv/mouse.c | 46 +++++++++++++++++++++++----------- + dlls/winex11.drv/x11drv.h | 3 ++- + dlls/winex11.drv/x11drv_main.c | 4 ++- + 3 files changed, 36 insertions(+), 17 deletions(-) + +diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c +index 42bac332664..ce77c7e5985 100644 +--- a/dlls/winex11.drv/mouse.c ++++ b/dlls/winex11.drv/mouse.c +@@ -286,6 +286,32 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator + #endif + + ++/*********************************************************************** ++ * x11drv_xinput_init ++ */ ++void x11drv_xinput_init(void) ++{ ++#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H ++ struct x11drv_thread_data *data = x11drv_thread_data(); ++ int major = 2, minor = 0; ++ ++ if (data->xi2_state != xi_unknown) return; ++ ++ if (xinput2_available && ++ !pXIQueryVersion( data->display, &major, &minor )) ++ { ++ TRACE( "XInput2 %d.%d available\n", major, minor ); ++ data->xi2_state = xi_disabled; ++ } ++ else ++ { ++ data->xi2_state = xi_unavailable; ++ WARN( "XInput 2.0 not available\n" ); ++ } ++#endif ++} ++ ++ + /*********************************************************************** + * enable_xinput2 + */ +@@ -298,19 +324,9 @@ static void enable_xinput2(void) + unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)]; + int count; + +- if (!xinput2_available) return; ++ TRACE( "state:%d\n", data->xi2_state ); ++ if (data->xi2_state != xi_disabled) return; + +- if (data->xi2_state == xi_unknown) +- { +- int major = 2, minor = 0; +- if (!pXIQueryVersion( data->display, &major, &minor )) data->xi2_state = xi_disabled; +- else +- { +- data->xi2_state = xi_unavailable; +- WARN( "X Input 2 not available\n" ); +- } +- } +- if (data->xi2_state == xi_unavailable) return; + if (!pXIGetClientPointer( data->display, None, &data->xi2_core_pointer )) return; + + mask.mask = mask_bits; +@@ -350,9 +366,9 @@ static void disable_xinput2(void) + struct x11drv_thread_data *data = x11drv_thread_data(); + XIEventMask mask; + ++ TRACE( "state:%d\n", data->xi2_state ); + if (data->xi2_state != xi_enabled) return; + +- TRACE( "disabling\n" ); + data->xi2_state = xi_disabled; + + mask.mask = NULL; +@@ -1908,9 +1924,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) + + + /*********************************************************************** +- * X11DRV_XInput2_Init ++ * x11drv_xinput_load + */ +-void X11DRV_XInput2_Init(void) ++void x11drv_xinput_load(void) + { + #if defined(SONAME_LIBXI) && defined(HAVE_X11_EXTENSIONS_XINPUT2_H) + int event, error; +diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h +index 45855976607..16a8a6be2be 100644 +--- a/dlls/winex11.drv/x11drv.h ++++ b/dlls/winex11.drv/x11drv.h +@@ -195,7 +195,8 @@ extern BOOL CDECL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN; + /* X11 driver internal functions */ + + extern void X11DRV_Xcursor_Init(void) DECLSPEC_HIDDEN; +-extern void X11DRV_XInput2_Init(void) DECLSPEC_HIDDEN; ++extern void x11drv_xinput_load(void) DECLSPEC_HIDDEN; ++extern void x11drv_xinput_init(void) DECLSPEC_HIDDEN; + + extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, + const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits, +diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c +index 9ec4c7a98f6..43c30ab369c 100644 +--- a/dlls/winex11.drv/x11drv_main.c ++++ b/dlls/winex11.drv/x11drv_main.c +@@ -610,7 +610,7 @@ static BOOL process_attach(void) + #ifdef SONAME_LIBXCOMPOSITE + X11DRV_XComposite_Init(); + #endif +- X11DRV_XInput2_Init(); ++ x11drv_xinput_load(); + + #ifdef HAVE_XKB + if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL ); +@@ -702,6 +702,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) + + if (use_xim) X11DRV_SetupXIM(); + ++ x11drv_xinput_init(); ++ + return data; + } + +-- +2.30.2 + diff --git a/patches/user32-rawinput-mouse/0002-winex11.drv-Support-XInput2-events-for-individual-wi.patch b/patches/user32-rawinput-mouse/0002-winex11.drv-Support-XInput2-events-for-individual-wi.patch new file mode 100644 index 00000000..c5fef640 --- /dev/null +++ b/patches/user32-rawinput-mouse/0002-winex11.drv-Support-XInput2-events-for-individual-wi.patch @@ -0,0 +1,254 @@ +From a5bff960bdb07ad110189c2ea7394370ac28b512 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Thu, 23 Jan 2020 11:00:19 +0100 +Subject: [PATCH] winex11.drv: Support XInput2 events for individual windows. + +This will allow us to listen to the XInput version of several events, +which can bring additional information. +--- + dlls/winex11.drv/desktop.c | 1 + + dlls/winex11.drv/event.c | 7 +++++ + dlls/winex11.drv/mouse.c | 59 +++++++++++++++++++++++++++----------- + dlls/winex11.drv/window.c | 3 ++ + dlls/winex11.drv/x11drv.h | 12 +++++++- + 5 files changed, 65 insertions(+), 17 deletions(-) + +diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c +index b517e44e150..6f46ef505c9 100644 +--- a/dlls/winex11.drv/desktop.c ++++ b/dlls/winex11.drv/desktop.c +@@ -356,6 +356,7 @@ BOOL CDECL X11DRV_create_desktop( UINT width, UINT height ) + 0, 0, width, height, 0, default_visual.depth, InputOutput, default_visual.visual, + CWEventMask | CWCursor | CWColormap, &win_attr ); + if (!win) return FALSE; ++ x11drv_xinput_enable( display, win, win_attr.event_mask ); + if (!create_desktop_win_data( win )) return FALSE; + + X11DRV_init_desktop( win, width, height ); +diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c +index 99943478729..217c1eca857 100644 +--- a/dlls/winex11.drv/event.c ++++ b/dlls/winex11.drv/event.c +@@ -245,6 +245,13 @@ static Bool filter_event( Display *display, XEvent *event, char *arg ) + return (mask & QS_MOUSEBUTTON) != 0; + #ifdef GenericEvent + case GenericEvent: ++#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H ++ if (event->xcookie.extension == xinput2_opcode && ++ (event->xcookie.evtype == XI_RawMotion || ++ event->xcookie.evtype == XI_DeviceChanged)) ++ return (mask & QS_MOUSEMOVE) != 0; ++#endif ++ return (mask & QS_SENDMESSAGE) != 0; + #endif + case MotionNotify: + case EnterNotify: +diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c +index ce77c7e5985..2550af3cb9c 100644 +--- a/dlls/winex11.drv/mouse.c ++++ b/dlls/winex11.drv/mouse.c +@@ -313,21 +313,33 @@ void x11drv_xinput_init(void) + + + /*********************************************************************** +- * enable_xinput2 ++ * x11drv_xinput_enable + */ +-static void enable_xinput2(void) ++void x11drv_xinput_enable( Display *display, Window window, long event_mask ) + { + #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + struct x11drv_thread_data *data = x11drv_thread_data(); + XIEventMask mask; + XIDeviceInfo *pointer_info; + unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)]; ++ enum xi2_state xi2_state = data ? data->xi2_state : xi_unknown; + int count; + +- TRACE( "state:%d\n", data->xi2_state ); +- if (data->xi2_state != xi_disabled) return; ++ TRACE( "state:%d window:%lx event_mask:%lx\n", xi2_state, window, event_mask ); + +- if (!pXIGetClientPointer( data->display, None, &data->xi2_core_pointer )) return; ++ if (xi2_state == xi_unavailable) return; ++ ++ if (window != DefaultRootWindow( display )) ++ { ++ mask.mask = mask_bits; ++ mask.mask_len = sizeof(mask_bits); ++ mask.deviceid = XIAllMasterDevices; ++ memset( mask_bits, 0, sizeof(mask_bits) ); ++ ++ pXISelectEvents( display, window, &mask, 1 ); ++ XSelectInput( display, window, event_mask ); ++ return; ++ } + + mask.mask = mask_bits; + mask.mask_len = sizeof(mask_bits); +@@ -337,8 +349,9 @@ static void enable_xinput2(void) + XISetMask( mask_bits, XI_RawMotion ); + XISetMask( mask_bits, XI_ButtonPress ); + +- pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 ); ++ pXISelectEvents( display, DefaultRootWindow( display ), &mask, 1 ); + ++ if (!data || !pXIGetClientPointer( data->display, None, &data->xi2_core_pointer )) return; + pointer_info = pXIQueryDevice( data->display, data->xi2_core_pointer, &count ); + update_relative_valuators( pointer_info->classes, pointer_info->num_classes ); + pXIFreeDeviceInfo( pointer_info ); +@@ -347,7 +360,7 @@ static void enable_xinput2(void) + * no XI_DeviceChanged events happened. If any hierarchy change occurred that + * might be relevant here (eg. user switching mice after (un)plugging), a + * XI_DeviceChanged event will point us to the right slave. So this list is +- * safe to be obtained statically at enable_xinput2() time. ++ * safe to be obtained statically at x11drv_xinput_enable() time. + */ + if (data->xi2_devices) pXIFreeDeviceInfo( data->xi2_devices ); + data->xi2_devices = pXIQueryDevice( data->display, XIAllDevices, &data->xi2_device_count ); +@@ -358,30 +371,44 @@ static void enable_xinput2(void) + } + + /*********************************************************************** +- * disable_xinput2 ++ * x11drv_xinput_disable + */ +-static void disable_xinput2(void) ++void x11drv_xinput_disable( Display *display, Window window, long event_mask ) + { + #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + struct x11drv_thread_data *data = x11drv_thread_data(); ++ enum xi2_state xi2_state = data ? data->xi2_state : xi_unknown; + XIEventMask mask; + +- TRACE( "state:%d\n", data->xi2_state ); +- if (data->xi2_state != xi_enabled) return; ++ TRACE( "state:%d window:%lx event_mask:%lx\n", xi2_state, window, event_mask ); + +- data->xi2_state = xi_disabled; ++ if (xi2_state == xi_unavailable) return; ++ ++ if (window != DefaultRootWindow( display )) ++ { ++ mask.mask = NULL; ++ mask.mask_len = 0; ++ mask.deviceid = XIAllMasterDevices; ++ ++ pXISelectEvents( display, window, &mask, 1 ); ++ XSelectInput( display, window, event_mask ); ++ return; ++ } + + mask.mask = NULL; + mask.mask_len = 0; + mask.deviceid = XIAllDevices; + +- pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 ); ++ pXISelectEvents( display, DefaultRootWindow( display ), &mask, 1 ); ++ ++ if (!data) return; + pXIFreeDeviceInfo( data->xi2_devices ); + data->x_rel_valuator.number = -1; + data->y_rel_valuator.number = -1; + data->xi2_devices = NULL; + data->xi2_core_pointer = 0; + data->xi2_current_slave = 0; ++ data->xi2_state = xi_disabled; + #endif + } + +@@ -423,7 +450,7 @@ static BOOL grab_clipping_window( const RECT *clip ) + } + + /* enable XInput2 unless we are already clipping */ +- if (!data->clip_hwnd) enable_xinput2(); ++ if (!data->clip_hwnd) x11drv_xinput_enable( data->display, DefaultRootWindow( data->display ), PointerMotionMask ); + + if (data->xi2_state != xi_enabled) + { +@@ -453,7 +480,7 @@ static BOOL grab_clipping_window( const RECT *clip ) + + if (!clipping_cursor) + { +- disable_xinput2(); ++ x11drv_xinput_disable( data->display, DefaultRootWindow( data->display ), PointerMotionMask ); + DestroyWindow( msg_hwnd ); + return FALSE; + } +@@ -532,7 +559,7 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND prev_clip_hwnd, HWND new_clip_hwnd ) + TRACE( "clip hwnd reset from %p\n", hwnd ); + data->clip_hwnd = 0; + data->clip_reset = GetTickCount(); +- disable_xinput2(); ++ x11drv_xinput_disable( data->display, DefaultRootWindow( data->display ), PointerMotionMask ); + DestroyWindow( hwnd ); + } + else if (prev_clip_hwnd) +diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c +index baaa30d74e3..4005e3df387 100644 +--- a/dlls/winex11.drv/window.c ++++ b/dlls/winex11.drv/window.c +@@ -375,6 +375,7 @@ static void sync_window_style( struct x11drv_win_data *data ) + int mask = get_window_attributes( data, &attr ); + + XChangeWindowAttributes( data->display, data->whole_window, mask, &attr ); ++ x11drv_xinput_enable( data->display, data->whole_window, attr.event_mask ); + } + } + +@@ -1573,6 +1574,7 @@ static void create_whole_window( struct x11drv_win_data *data ) + data->vis.visual, mask, &attr ); + if (!data->whole_window) goto done; + ++ x11drv_xinput_enable( data->display, data->whole_window, attr.event_mask ); + set_initial_wm_hints( data->display, data->whole_window ); + set_wm_hints( data ); + +@@ -1879,6 +1881,7 @@ BOOL CDECL X11DRV_CreateWindow( HWND hwnd ) + data->clip_window = XCreateWindow( data->display, root_window, 0, 0, 1, 1, 0, 0, + InputOnly, default_visual.visual, + CWOverrideRedirect | CWEventMask, &attr ); ++ x11drv_xinput_enable( data->display, data->clip_window, attr.event_mask ); + XFlush( data->display ); + SetPropA( hwnd, clip_window_prop, (HANDLE)data->clip_window ); + X11DRV_InitClipboard(); +diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h +index 16a8a6be2be..7ea60fa495a 100644 +--- a/dlls/winex11.drv/x11drv.h ++++ b/dlls/winex11.drv/x11drv.h +@@ -197,6 +197,8 @@ extern BOOL CDECL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN; + extern void X11DRV_Xcursor_Init(void) DECLSPEC_HIDDEN; + extern void x11drv_xinput_load(void) DECLSPEC_HIDDEN; + extern void x11drv_xinput_init(void) DECLSPEC_HIDDEN; ++extern void x11drv_xinput_enable( Display *display, Window window, long event_mask ) DECLSPEC_HIDDEN; ++extern void x11drv_xinput_disable( Display *display, Window window, long event_mask ) DECLSPEC_HIDDEN; + + extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, + const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits, +@@ -324,6 +326,14 @@ struct x11drv_valuator_data + int number; + }; + ++enum xi2_state ++{ ++ xi_unavailable = -1, ++ xi_unknown, ++ xi_disabled, ++ xi_enabled ++}; ++ + struct x11drv_thread_data + { + Display *display; +@@ -339,7 +349,7 @@ struct x11drv_thread_data + HWND clip_hwnd; /* message window stored in desktop while clipping is active */ + DWORD clip_reset; /* time when clipping was last reset */ + HKL kbd_layout; /* active keyboard layout */ +- enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */ ++ enum xi2_state xi2_state; /* XInput2 state */ + void *xi2_devices; /* list of XInput2 devices (valid when state is enabled) */ + int xi2_device_count; + struct x11drv_valuator_data x_rel_valuator; +-- +2.30.2 + diff --git a/patches/user32-rawinput-mouse/0008-winex11.drv-Advertise-XInput2-version-2.1-support.patch b/patches/user32-rawinput-mouse/0003-winex11.drv-Advertise-XInput2-version-2.1-support.patch similarity index 74% rename from patches/user32-rawinput-mouse/0008-winex11.drv-Advertise-XInput2-version-2.1-support.patch rename to patches/user32-rawinput-mouse/0003-winex11.drv-Advertise-XInput2-version-2.1-support.patch index e31007c6..52801349 100644 --- a/patches/user32-rawinput-mouse/0008-winex11.drv-Advertise-XInput2-version-2.1-support.patch +++ b/patches/user32-rawinput-mouse/0003-winex11.drv-Advertise-XInput2-version-2.1-support.patch @@ -1,4 +1,4 @@ -From 7440b3f974b66631ee71fa9acafc333e39543174 Mon Sep 17 00:00:00 2001 +From 3addef6ede746e418be37c5f288027bb0247f37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Fri, 2 Aug 2019 02:24:32 -0400 Subject: [PATCH] winex11.drv: Advertise XInput2 version 2.1 support. @@ -17,35 +17,33 @@ events from the desktop window thread, even if a mouse grab is active. It is now also possible to simplify the code by listening to master device events only and get rid of slave device id tracking. --- - dlls/winex11.drv/mouse.c | 49 ++++++++------------------------------- + dlls/winex11.drv/mouse.c | 43 +++++---------------------------------- dlls/winex11.drv/x11drv.h | 3 --- - 2 files changed, 10 insertions(+), 42 deletions(-) + 2 files changed, 5 insertions(+), 41 deletions(-) diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index aaa34d8ff0f..3a4b1198829 100644 +index 2550af3cb9c..0d41438c5c7 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c -@@ -302,12 +302,16 @@ static void enable_xinput2(void) +@@ -293,7 +293,7 @@ void x11drv_xinput_init(void) + { + #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + struct x11drv_thread_data *data = x11drv_thread_data(); +- int major = 2, minor = 0; ++ int major = 2, minor = 1; - if (data->xi2_state == xi_unknown) + if (data->xi2_state != xi_unknown) return; + +@@ -306,7 +306,7 @@ void x11drv_xinput_init(void) + else { -- int major = 2, minor = 0; -- if (!pXIQueryVersion( data->display, &major, &minor )) data->xi2_state = xi_disabled; -+ int major = 2, minor = 1; -+ if (!pXIQueryVersion( data->display, &major, &minor ) && major == 2 && minor > 0) -+ { -+ TRACE( "XInput2 v%d.%d available\n", major, minor ); -+ data->xi2_state = xi_disabled; -+ } - else - { - data->xi2_state = xi_unavailable; -- WARN( "X Input 2 not available\n" ); -+ WARN( "XInput v2.1 not available\n" ); - } + data->xi2_state = xi_unavailable; +- WARN( "XInput 2.0 not available\n" ); ++ WARN( "XInput 2.1 not available\n" ); } - if (data->xi2_state == xi_unavailable) return; -@@ -315,7 +319,7 @@ static void enable_xinput2(void) + #endif + } +@@ -343,7 +343,7 @@ void x11drv_xinput_enable( Display *display, Window window, long event_mask ) mask.mask = mask_bits; mask.mask_len = sizeof(mask_bits); @@ -54,7 +52,7 @@ index aaa34d8ff0f..3a4b1198829 100644 memset( mask_bits, 0, sizeof(mask_bits) ); XISetMask( mask_bits, XI_DeviceChanged ); XISetMask( mask_bits, XI_RawMotion ); -@@ -327,16 +331,6 @@ static void enable_xinput2(void) +@@ -356,16 +356,6 @@ void x11drv_xinput_enable( Display *display, Window window, long event_mask ) update_relative_valuators( pointer_info->classes, pointer_info->num_classes ); pXIFreeDeviceInfo( pointer_info ); @@ -62,7 +60,7 @@ index aaa34d8ff0f..3a4b1198829 100644 - * no XI_DeviceChanged events happened. If any hierarchy change occurred that - * might be relevant here (eg. user switching mice after (un)plugging), a - * XI_DeviceChanged event will point us to the right slave. So this list is -- * safe to be obtained statically at enable_xinput2() time. +- * safe to be obtained statically at x11drv_xinput_enable() time. - */ - if (data->xi2_devices) pXIFreeDeviceInfo( data->xi2_devices ); - data->xi2_devices = pXIQueryDevice( data->display, XIAllDevices, &data->xi2_device_count ); @@ -71,24 +69,26 @@ index aaa34d8ff0f..3a4b1198829 100644 data->xi2_state = xi_enabled; #endif } -@@ -357,15 +351,12 @@ static void disable_xinput2(void) +@@ -397,17 +387,14 @@ void x11drv_xinput_disable( Display *display, Window window, long event_mask ) mask.mask = NULL; mask.mask_len = 0; - mask.deviceid = XIAllDevices; + mask.deviceid = XIAllMasterDevices; - pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 ); + pXISelectEvents( display, DefaultRootWindow( display ), &mask, 1 ); + + if (!data) return; - pXIFreeDeviceInfo( data->xi2_devices ); data->x_rel_valuator.number = -1; data->y_rel_valuator.number = -1; - data->xi2_devices = NULL; data->xi2_core_pointer = 0; - data->xi2_current_slave = 0; + data->xi2_state = xi_disabled; #endif } - -@@ -1799,7 +1790,6 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev ) +@@ -1860,7 +1847,6 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev ) if (event->reason != XISlaveSwitch) return FALSE; update_relative_valuators( event->classes, event->num_classes ); @@ -96,7 +96,7 @@ index aaa34d8ff0f..3a4b1198829 100644 return TRUE; } -@@ -1820,26 +1810,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1881,26 +1867,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) if (thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) return FALSE; if (!event->valuators.mask_len) return FALSE; if (thread_data->xi2_state != xi_enabled) return FALSE; @@ -125,13 +125,13 @@ index aaa34d8ff0f..3a4b1198829 100644 x_rel = &thread_data->x_rel_valuator; y_rel = &thread_data->y_rel_valuator; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index cfce09bf11d..8a02a6ebf94 100644 +index 7ea60fa495a..df8a53bb228 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h -@@ -339,12 +339,9 @@ struct x11drv_thread_data +@@ -350,12 +350,9 @@ struct x11drv_thread_data DWORD clip_reset; /* time when clipping was last reset */ HKL kbd_layout; /* active keyboard layout */ - enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */ + enum xi2_state xi2_state; /* XInput2 state */ - void *xi2_devices; /* list of XInput2 devices (valid when state is enabled) */ - int xi2_device_count; struct x11drv_valuator_data x_rel_valuator; @@ -142,5 +142,5 @@ index cfce09bf11d..8a02a6ebf94 100644 extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN; -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-mouse/0009-winex11.drv-Keep-track-of-pointer-and-device-button-.patch b/patches/user32-rawinput-mouse/0004-winex11.drv-Keep-track-of-pointer-and-device-button-.patch similarity index 90% rename from patches/user32-rawinput-mouse/0009-winex11.drv-Keep-track-of-pointer-and-device-button-.patch rename to patches/user32-rawinput-mouse/0004-winex11.drv-Keep-track-of-pointer-and-device-button-.patch index 6d76cbad..7dbdae3b 100644 --- a/patches/user32-rawinput-mouse/0009-winex11.drv-Keep-track-of-pointer-and-device-button-.patch +++ b/patches/user32-rawinput-mouse/0004-winex11.drv-Keep-track-of-pointer-and-device-button-.patch @@ -1,4 +1,4 @@ -From e0245cae5151eddb30eeaed3116697257ce65f22 Mon Sep 17 00:00:00 2001 +From a88aed6df65592b55fde5ecee55b090149c362bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 19 Dec 2019 22:34:44 +0100 Subject: [PATCH] winex11.drv: Keep track of pointer and device button @@ -16,10 +16,10 @@ Original patch by Andrew Eikum . 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c -index 2a3bed787ab..37c96c926f4 100644 +index 01620c5e4a4..272f728def9 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c -@@ -1977,13 +1977,24 @@ BOOL X11DRV_MappingNotify( HWND dummy, XEvent *event ) +@@ -1976,13 +1976,24 @@ BOOL X11DRV_MappingNotify( HWND dummy, XEvent *event ) { HWND hwnd; @@ -51,7 +51,7 @@ index 2a3bed787ab..37c96c926f4 100644 } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index 3a4b1198829..26e8b4eea92 100644 +index 0d41438c5c7..fc5fd29d7b6 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -25,6 +25,9 @@ @@ -150,7 +150,7 @@ index 3a4b1198829..26e8b4eea92 100644 #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H /*********************************************************************** * update_relative_valuators -@@ -1790,6 +1865,8 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev ) +@@ -1847,6 +1922,8 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev ) if (event->reason != XISlaveSwitch) return FALSE; update_relative_valuators( event->classes, event->num_classes ); @@ -159,22 +159,22 @@ index 3a4b1198829..26e8b4eea92 100644 return TRUE; } -@@ -1859,13 +1936,12 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) +@@ -1916,13 +1993,12 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) #endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */ - /*********************************************************************** - * X11DRV_XInput2_Init + * x11drv_xinput_load */ - void X11DRV_XInput2_Init(void) + void x11drv_xinput_load(void) { -#if defined(SONAME_LIBXI) && defined(HAVE_X11_EXTENSIONS_XINPUT2_H) +#if defined(SONAME_LIBXI) int event, error; void *libxi_handle = dlopen( SONAME_LIBXI, RTLD_NOW ); -@@ -1881,11 +1957,20 @@ void X11DRV_XInput2_Init(void) +@@ -1938,11 +2014,20 @@ void x11drv_xinput_load(void) return; \ } @@ -196,10 +196,10 @@ index 3a4b1198829..26e8b4eea92 100644 xinput2_available = XQueryExtension( gdi_display, "XInputExtension", &xinput2_opcode, &event, &error ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 8a02a6ebf94..73b1e90f12e 100644 +index df8a53bb228..afa990b7e68 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h -@@ -629,6 +629,7 @@ extern void retry_grab_clipping_window(void) DECLSPEC_HIDDEN; +@@ -643,6 +643,7 @@ extern void retry_grab_clipping_window(void) DECLSPEC_HIDDEN; extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) DECLSPEC_HIDDEN; extern void move_resize_window( HWND hwnd, int dir ) DECLSPEC_HIDDEN; extern void X11DRV_InitKeyboard( Display *display ) DECLSPEC_HIDDEN; @@ -208,10 +208,10 @@ index 8a02a6ebf94..73b1e90f12e 100644 DWORD mask, DWORD flags ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c -index e6e61e801e1..20e829ba64f 100644 +index 43c30ab369c..d8576949aea 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c -@@ -615,6 +615,7 @@ static BOOL process_attach(void) +@@ -616,6 +616,7 @@ static BOOL process_attach(void) if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL ); #endif X11DRV_InitKeyboard( gdi_display ); @@ -220,5 +220,5 @@ index e6e61e801e1..20e829ba64f 100644 X11DRV_DisplayDevices_Init(FALSE); -- -2.27.0 +2.30.2 diff --git a/patches/user32-rawinput-mouse/0005-server-Add-send_hardware_message-flags-for-rawinput-.patch b/patches/user32-rawinput-mouse/0005-server-Add-send_hardware_message-flags-for-rawinput-.patch new file mode 100644 index 00000000..1d26687b --- /dev/null +++ b/patches/user32-rawinput-mouse/0005-server-Add-send_hardware_message-flags-for-rawinput-.patch @@ -0,0 +1,101 @@ +From ce3b572e3b0ac1b19e9d032039435044e51929de Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Mon, 26 Aug 2019 14:37:20 +0200 +Subject: [PATCH] server: Add send_hardware_message flags for rawinput + translation. + +--- + dlls/user32/message.c | 2 ++ + server/protocol.def | 1 + + server/queue.c | 12 ++++++------ + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index f986b71953a..98f6c2730e0 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -3259,6 +3259,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r + req->input.mouse.flags = input->u.mi.dwFlags; + req->input.mouse.time = input->u.mi.time; + req->input.mouse.info = input->u.mi.dwExtraInfo; ++ req->flags |= SEND_HWMSG_RAWINPUT; + break; + case INPUT_KEYBOARD: + req->input.kbd.vkey = input->u.ki.wVk; +@@ -3266,6 +3267,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r + req->input.kbd.flags = input->u.ki.dwFlags; + req->input.kbd.time = input->u.ki.time; + req->input.kbd.info = input->u.ki.dwExtraInfo; ++ req->flags |= SEND_HWMSG_RAWINPUT; + break; + case INPUT_HARDWARE: + req->input.hw.msg = input->u.hi.uMsg; +diff --git a/server/protocol.def b/server/protocol.def +index 829216b58c1..90379955ecd 100644 +--- a/server/protocol.def ++++ b/server/protocol.def +@@ -2054,6 +2054,7 @@ enum message_type + VARARG(keystate,bytes); /* global state array for all the keys */ + @END + #define SEND_HWMSG_INJECTED 0x01 ++#define SEND_HWMSG_RAWINPUT 0x02 + + + /* Get a message from the current queue */ +diff --git a/server/queue.c b/server/queue.c +index a411d0af8d2..a928f4d7fad 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -1782,7 +1782,7 @@ done: + + /* queue a hardware message for a mouse event */ + static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, +- unsigned int origin, struct msg_queue *sender ) ++ unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) + { + const struct rawinput_device *device; + struct hardware_msg_data *msg_data; +@@ -1837,7 +1837,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons + y = desktop->cursor.y; + } + +- if ((foreground = get_foreground_thread( desktop, win ))) ++ if ((req_flags & SEND_HWMSG_RAWINPUT) && (foreground = get_foreground_thread( desktop, win ))) + { + raw_msg.foreground = foreground; + raw_msg.desktop = desktop; +@@ -1896,7 +1896,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons + + /* queue a hardware message for a keyboard event */ + static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, +- unsigned int origin, struct msg_queue *sender ) ++ unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) + { + struct hw_msg_source source = { IMDT_KEYBOARD, origin }; + const struct rawinput_device *device; +@@ -1974,7 +1974,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c + break; + } + +- if ((foreground = get_foreground_thread( desktop, win ))) ++ if ((req_flags & SEND_HWMSG_RAWINPUT) && (foreground = get_foreground_thread( desktop, win ))) + { + raw_msg.foreground = foreground; + raw_msg.desktop = desktop; +@@ -2603,11 +2603,11 @@ DECL_HANDLER(send_hardware_message) + { + case INPUT_MOUSE: + if (!desktop) return; +- reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender ); ++ reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags ); + break; + case INPUT_KEYBOARD: + if (!desktop) return; +- reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender ); ++ reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags ); + break; + case INPUT_HARDWARE: + if (!desktop) set_error( STATUS_SUCCESS ); +-- +2.30.2 + diff --git a/patches/user32-rawinput-mouse/0006-server-Add-send_hardware_message-flags-for-rawinput-.patch b/patches/user32-rawinput-mouse/0006-server-Add-send_hardware_message-flags-for-rawinput-.patch deleted file mode 100644 index 9b32acea..00000000 --- a/patches/user32-rawinput-mouse/0006-server-Add-send_hardware_message-flags-for-rawinput-.patch +++ /dev/null @@ -1,128 +0,0 @@ -From 7a3a5195d932de5bc6291458f15fa5400c9777f0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Mon, 26 Aug 2019 14:37:20 +0200 -Subject: [PATCH] server: Add send_hardware_message flags for rawinput - translation. - ---- - dlls/user32/input.c | 6 +++--- - server/protocol.def | 2 ++ - server/queue.c | 20 ++++++++++++++------ - 3 files changed, 19 insertions(+), 9 deletions(-) - -diff --git a/dlls/user32/input.c b/dlls/user32/input.c -index 1dd43a36a11..f0b95c7fc6c 100644 ---- a/dlls/user32/input.c -+++ b/dlls/user32/input.c -@@ -125,7 +125,7 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) - */ - BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input ) - { -- NTSTATUS status = send_hardware_message( hwnd, input, 0 ); -+ NTSTATUS status = send_hardware_message( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); - if (status) SetLastError( RtlNtStatusToDosError(status) ); - return !status; - } -@@ -193,9 +193,9 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) - /* we need to update the coordinates to what the server expects */ - INPUT input = inputs[i]; - update_mouse_coords( &input ); -- status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED ); -+ status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED|SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); - } -- else status = send_hardware_message( 0, &inputs[i], SEND_HWMSG_INJECTED ); -+ else status = send_hardware_message( 0, &inputs[i], SEND_HWMSG_INJECTED|SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); - - if (status) - { -diff --git a/server/protocol.def b/server/protocol.def -index 56fda14932d..21de849e5d8 100644 ---- a/server/protocol.def -+++ b/server/protocol.def -@@ -2339,6 +2339,8 @@ enum message_type - VARARG(keystate,bytes); /* global state array for all the keys */ - @END - #define SEND_HWMSG_INJECTED 0x01 -+#define SEND_HWMSG_RAWINPUT 0x02 -+#define SEND_HWMSG_WINDOW 0x04 - - - /* Get a message from the current queue */ -diff --git a/server/queue.c b/server/queue.c -index ff9e703d1ff..46ace52f004 100644 ---- a/server/queue.c -+++ b/server/queue.c -@@ -1695,7 +1695,7 @@ done: - - /* queue a hardware message for a mouse event */ - static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, -- unsigned int origin, struct msg_queue *sender ) -+ unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) - { - const struct rawinput_device *device; - struct hardware_msg_data *msg_data; -@@ -1765,7 +1765,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons - msg_data->rawinput.mouse.y = y - desktop->cursor.y; - msg_data->rawinput.mouse.data = input->mouse.data; - -- enum_processes( queue_rawinput_message, &raw_msg ); -+ if ((req_flags & SEND_HWMSG_RAWINPUT)) -+ enum_processes( queue_rawinput_message, &raw_msg ); - release_object( foreground ); - } - -@@ -1775,6 +1776,9 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons - return 0; - } - -+ if (!(req_flags & SEND_HWMSG_WINDOW)) -+ return 0; -+ - for (i = 0; i < ARRAY_SIZE( messages ); i++) - { - if (!messages[i]) continue; -@@ -1806,7 +1810,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons - - /* queue a hardware message for a keyboard event */ - static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, -- unsigned int origin, struct msg_queue *sender ) -+ unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) - { - struct hw_msg_source source = { IMDT_KEYBOARD, origin }; - const struct rawinput_device *device; -@@ -1899,7 +1903,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c - msg_data->rawinput.kbd.vkey = vkey; - msg_data->rawinput.kbd.scan = input->kbd.scan; - -- enum_processes( queue_rawinput_message, &raw_msg ); -+ if ((req_flags & SEND_HWMSG_RAWINPUT)) -+ enum_processes( queue_rawinput_message, &raw_msg ); - release_object( foreground ); - } - -@@ -1909,6 +1914,9 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c - return 0; - } - -+ if (!(req_flags & SEND_HWMSG_WINDOW)) -+ return 0; -+ - if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; - msg_data = msg->data; - -@@ -2465,10 +2473,10 @@ DECL_HANDLER(send_hardware_message) - switch (req->input.type) - { - case INPUT_MOUSE: -- reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender ); -+ reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags ); - break; - case INPUT_KEYBOARD: -- reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender ); -+ reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags ); - break; - case INPUT_HARDWARE: - queue_custom_hardware_message( desktop, req->win, origin, &req->input ); --- -2.27.0 - diff --git a/patches/user32-rawinput-mouse/0006-user32-Set-SEND_HWMSG_RAWINPUT-flags-only-when-RAWIN.patch b/patches/user32-rawinput-mouse/0006-user32-Set-SEND_HWMSG_RAWINPUT-flags-only-when-RAWIN.patch new file mode 100644 index 00000000..6fb04e0b --- /dev/null +++ b/patches/user32-rawinput-mouse/0006-user32-Set-SEND_HWMSG_RAWINPUT-flags-only-when-RAWIN.patch @@ -0,0 +1,278 @@ +From acd309726a5ca6ac94a7ea13c92382ae637e21ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Wed, 24 Mar 2021 23:29:28 +0100 +Subject: [PATCH] user32: Set SEND_HWMSG_RAWINPUT flags only when RAWINPUT is + set. + +So we can generate legacy messages only by calling __wine_send_input +with NULL rawinput, and generate WM_INPUT messages only by calling +__wine_send_input with INPUT_HARDWARE input type and a rawinput. +--- + dlls/user32/input.c | 3 ++- + dlls/user32/message.c | 4 ++-- + dlls/wineandroid.drv/keyboard.c | 3 ++- + dlls/wineandroid.drv/window.c | 5 +++-- + dlls/winemac.drv/ime.c | 6 ++++-- + dlls/winemac.drv/keyboard.c | 3 ++- + dlls/winemac.drv/mouse.c | 3 ++- + dlls/winex11.drv/keyboard.c | 3 ++- + dlls/winex11.drv/mouse.c | 11 +++++++---- + 9 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/dlls/user32/input.c b/dlls/user32/input.c +index 3fc818a2510..af1ad797102 100644 +--- a/dlls/user32/input.c ++++ b/dlls/user32/input.c +@@ -181,6 +181,7 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) + { + UINT i; + NTSTATUS status = STATUS_SUCCESS; ++ RAWINPUT rawinput; + + if (size != sizeof(INPUT)) + { +@@ -210,7 +211,7 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size ) + update_mouse_coords( &input ); + /* fallthrough */ + case INPUT_KEYBOARD: +- status = send_hardware_message( 0, &input, NULL, SEND_HWMSG_INJECTED ); ++ status = send_hardware_message( 0, &input, &rawinput, SEND_HWMSG_INJECTED ); + break; + #ifdef _WIN64 + case INPUT_HARDWARE: +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index 98f6c2730e0..43c6adad033 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -3259,7 +3259,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r + req->input.mouse.flags = input->u.mi.dwFlags; + req->input.mouse.time = input->u.mi.time; + req->input.mouse.info = input->u.mi.dwExtraInfo; +- req->flags |= SEND_HWMSG_RAWINPUT; ++ if (rawinput) req->flags |= SEND_HWMSG_RAWINPUT; + break; + case INPUT_KEYBOARD: + req->input.kbd.vkey = input->u.ki.wVk; +@@ -3267,7 +3267,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r + req->input.kbd.flags = input->u.ki.dwFlags; + req->input.kbd.time = input->u.ki.time; + req->input.kbd.info = input->u.ki.dwExtraInfo; +- req->flags |= SEND_HWMSG_RAWINPUT; ++ if (rawinput) req->flags |= SEND_HWMSG_RAWINPUT; + break; + case INPUT_HARDWARE: + req->input.hw.msg = input->u.hi.uMsg; +diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c +index 0a6ede0ec5f..df85188fbbb 100644 +--- a/dlls/wineandroid.drv/keyboard.c ++++ b/dlls/wineandroid.drv/keyboard.c +@@ -671,6 +671,7 @@ static BOOL get_async_key_state( BYTE state[256] ) + + static void send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD flags ) + { ++ RAWINPUT rawinput; + INPUT input; + + input.type = INPUT_KEYBOARD; +@@ -680,7 +681,7 @@ static void send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD flags ) + input.u.ki.time = 0; + input.u.ki.dwExtraInfo = 0; + +- __wine_send_input( hwnd, &input, NULL ); ++ __wine_send_input( hwnd, &input, &rawinput ); + } + + /*********************************************************************** +diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c +index 1cb1bbbadc9..92a1c5012a0 100644 +--- a/dlls/wineandroid.drv/window.c ++++ b/dlls/wineandroid.drv/window.c +@@ -428,6 +428,7 @@ static int process_events( DWORD mask ) + DPI_AWARENESS_CONTEXT context; + struct java_event *event, *next, *previous; + unsigned int count = 0; ++ RAWINPUT rawinput; + + assert( GetCurrentThreadId() == desktop_tid ); + +@@ -521,7 +522,7 @@ static int process_events( DWORD mask ) + } + SERVER_END_REQ; + } +- __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, NULL ); ++ __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, &rawinput ); + } + break; + +@@ -535,7 +536,7 @@ static int process_events( DWORD mask ) + event->data.kbd.input.u.ki.wVk, event->data.kbd.input.u.ki.wVk, + event->data.kbd.input.u.ki.wScan ); + update_keyboard_lock_state( event->data.kbd.input.u.ki.wVk, event->data.kbd.lock_state ); +- __wine_send_input( 0, &event->data.kbd.input, NULL ); ++ __wine_send_input( 0, &event->data.kbd.input, &rawinput ); + break; + + default: +diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c +index f2368c10743..89f6d9c617d 100644 +--- a/dlls/winemac.drv/ime.c ++++ b/dlls/winemac.drv/ime.c +@@ -42,6 +42,7 @@ + #include "winuser.h" + #include "imm.h" + #include "ddk/imm.h" ++#include "wine/server.h" + + WINE_DEFAULT_DEBUG_CHANNEL(imm); + +@@ -1415,6 +1416,7 @@ void macdrv_im_set_text(const macdrv_event *event) + event->im_set_text.cursor_pos, !event->im_set_text.complete); + else + { ++ RAWINPUT rawinput; + INPUT input; + CFIndex i; + +@@ -1427,10 +1429,10 @@ void macdrv_im_set_text(const macdrv_event *event) + { + input.ki.wScan = chars[i]; + input.ki.dwFlags = KEYEVENTF_UNICODE; +- __wine_send_input(hwnd, &input, NULL); ++ __wine_send_input(hwnd, &input, &rawinput); + + input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; +- __wine_send_input(hwnd, &input, NULL); ++ __wine_send_input(hwnd, &input, &rawinput); + } + } + +diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c +index 1ea15f59341..b4d50058d4e 100644 +--- a/dlls/winemac.drv/keyboard.c ++++ b/dlls/winemac.drv/keyboard.c +@@ -918,6 +918,7 @@ void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_data) + */ + static void macdrv_send_keyboard_input(HWND hwnd, WORD vkey, WORD scan, DWORD flags, DWORD time) + { ++ RAWINPUT rawinput; + INPUT input; + + TRACE_(key)("hwnd %p vkey=%04x scan=%04x flags=%04x\n", hwnd, vkey, scan, flags); +@@ -929,7 +930,7 @@ static void macdrv_send_keyboard_input(HWND hwnd, WORD vkey, WORD scan, DWORD fl + input.ki.time = time; + input.ki.dwExtraInfo = 0; + +- __wine_send_input(hwnd, &input, NULL); ++ __wine_send_input(hwnd, &input, &rawinput); + } + + +diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c +index d2278ae0e4c..d6598617456 100644 +--- a/dlls/winemac.drv/mouse.c ++++ b/dlls/winemac.drv/mouse.c +@@ -136,6 +136,7 @@ static const CFStringRef cocoa_cursor_names[] = + static void send_mouse_input(HWND hwnd, macdrv_window cocoa_window, UINT flags, int x, int y, + DWORD mouse_data, BOOL drag, unsigned long time) + { ++ RAWINPUT rawinput; + INPUT input; + HWND top_level_hwnd; + +@@ -165,7 +166,7 @@ static void send_mouse_input(HWND hwnd, macdrv_window cocoa_window, UINT flags, + input.mi.time = time; + input.mi.dwExtraInfo = 0; + +- __wine_send_input(top_level_hwnd, &input, NULL); ++ __wine_send_input(top_level_hwnd, &input, &rawinput); + } + + +diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c +index 272f728def9..2e87eeede99 100644 +--- a/dlls/winex11.drv/keyboard.c ++++ b/dlls/winex11.drv/keyboard.c +@@ -1137,6 +1137,7 @@ static WORD EVENT_event_to_vkey( XIC xic, XKeyEvent *e) + */ + static void X11DRV_send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD flags, DWORD time ) + { ++ RAWINPUT rawinput; + INPUT input; + + TRACE_(key)( "hwnd %p vkey=%04x scan=%04x flags=%04x\n", hwnd, vkey, scan, flags ); +@@ -1148,7 +1149,7 @@ static void X11DRV_send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD f + input.u.ki.time = time; + input.u.ki.dwExtraInfo = 0; + +- __wine_send_input( hwnd, &input, NULL ); ++ __wine_send_input( hwnd, &input, &rawinput ); + } + + +diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c +index fc5fd29d7b6..6b6512521f4 100644 +--- a/dlls/winex11.drv/mouse.c ++++ b/dlls/winex11.drv/mouse.c +@@ -748,6 +748,7 @@ static void map_event_coords( HWND hwnd, Window window, Window event_root, int x + static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPUT *input ) + { + struct x11drv_win_data *data; ++ RAWINPUT rawinput; + + input->type = INPUT_MOUSE; + +@@ -764,7 +765,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU + sync_window_cursor( window ); + last_cursor_change = input->u.mi.time; + } +- __wine_send_input( hwnd, input, NULL ); ++ __wine_send_input( hwnd, input, &rawinput ); + return; + } + +@@ -804,7 +805,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU + SERVER_END_REQ; + } + +- __wine_send_input( hwnd, input, NULL ); ++ __wine_send_input( hwnd, input, &rawinput ); + } + + #ifdef SONAME_LIBXCURSOR +@@ -1759,6 +1760,7 @@ void move_resize_window( HWND hwnd, int dir ) + { + MSG msg; + INPUT input; ++ RAWINPUT rawinput; + int x, y, rootX, rootY; + + if (!XQueryPointer( display, root_window, &root, &child, &rootX, &rootY, &x, &y, &xstate )) break; +@@ -1774,7 +1776,7 @@ void move_resize_window( HWND hwnd, int dir ) + input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; + input.u.mi.time = GetTickCount(); + input.u.mi.dwExtraInfo = 0; +- __wine_send_input( hwnd, &input, NULL ); ++ __wine_send_input( hwnd, &input, &rawinput ); + } + + while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) +@@ -1935,6 +1937,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) + XIRawEvent *event = xev->data; + const double *values = event->valuators.values; + RECT virtual_rect; ++ RAWINPUT rawinput; + INPUT input; + int i; + double dx = 0, dy = 0, val; +@@ -1987,7 +1990,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) + TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); + + input.type = INPUT_MOUSE; +- __wine_send_input( 0, &input, NULL ); ++ __wine_send_input( 0, &input, &rawinput ); + return TRUE; + } + +-- +2.30.2 + diff --git a/patches/user32-rawinput-mouse/0007-user32-Support-sending-RIM_TYPEMOUSE-through-__wine_.patch b/patches/user32-rawinput-mouse/0007-user32-Support-sending-RIM_TYPEMOUSE-through-__wine_.patch new file mode 100644 index 00000000..af8168d5 --- /dev/null +++ b/patches/user32-rawinput-mouse/0007-user32-Support-sending-RIM_TYPEMOUSE-through-__wine_.patch @@ -0,0 +1,54 @@ +From ba34a1671d177a18391e3bf8619cea68eead6e34 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Thu, 25 Mar 2021 14:26:35 +0100 +Subject: [PATCH] user32: Support sending RIM_TYPEMOUSE through + __wine_send_input. + +--- + dlls/user32/message.c | 6 ++++++ + server/queue.c | 5 ++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index 43c6adad033..d62da5de16f 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -3279,6 +3279,12 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r + req->input.hw.data.rawinput.type = rawinput->header.dwType; + switch (rawinput->header.dwType) + { ++ case RIM_TYPEMOUSE: ++ req->input.hw.data.rawinput.mouse.x = rawinput->data.mouse.lLastX; ++ req->input.hw.data.rawinput.mouse.y = rawinput->data.mouse.lLastY; ++ req->input.hw.data.rawinput.mouse.data = rawinput->data.mouse.u.ulButtons; ++ req->input.hw.lparam = rawinput->data.mouse.ulRawButtons; ++ break; + case RIM_TYPEHID: + assert( rawinput->data.hid.dwCount <= 1 ); + req->input.hw.data.rawinput.hid.device = HandleToUlong( rawinput->header.hDevice ); +diff --git a/server/queue.c b/server/queue.c +index a928f4d7fad..9008f8e90ff 100644 +--- a/server/queue.c ++++ b/server/queue.c +@@ -2054,7 +2054,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + raw_msg.extra = NULL; + raw_msg.extra_len = 0; + +- if (input->hw.msg == WM_INPUT) ++ if (input->hw.msg == WM_INPUT && input->hw.data.rawinput.type == RIM_TYPEHID) + { + raw_msg.extra = get_req_data(); + raw_msg.extra_len = get_req_data_size(); +@@ -2065,6 +2065,9 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ + msg_data->flags = 0; + msg_data->rawinput = input->hw.data.rawinput; + ++ if (input->hw.msg == WM_INPUT && input->hw.data.rawinput.type == RIM_TYPEMOUSE) ++ msg_data->flags = input->hw.lparam; ++ + if (input->hw.msg == WM_INPUT_DEVICE_CHANGE && + input->hw.data.rawinput.type == RIM_TYPEHID && + input->hw.data.rawinput.hid.param == GIDC_ARRIVAL) +-- +2.30.2 + diff --git a/patches/user32-rawinput-mouse/0008-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch b/patches/user32-rawinput-mouse/0008-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch new file mode 100644 index 00000000..23157598 --- /dev/null +++ b/patches/user32-rawinput-mouse/0008-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch @@ -0,0 +1,244 @@ +From a385e325b7fda81327d4e4d41363d20e98b3171f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?R=C3=A9mi=20Bernon?= +Date: Thu, 25 Mar 2021 16:12:58 +0100 +Subject: [PATCH] winex11.drv: Listen to RawMotion and RawButton* events in the + desktop thread. + +We still need to send "normal" input from the clipping window thread +to trigger low-level hooks callbacks when clipping cursor. This is for +instance used in our dinput implementation. +--- + dlls/winex11.drv/event.c | 10 +++- + dlls/winex11.drv/mouse.c | 107 ++++++++++++++++++++++++++++++++++---- + dlls/winex11.drv/x11drv.h | 1 + + 3 files changed, 107 insertions(+), 11 deletions(-) + +diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c +index 217c1eca857..8685ce9536b 100644 +--- a/dlls/winex11.drv/event.c ++++ b/dlls/winex11.drv/event.c +@@ -328,6 +328,10 @@ static enum event_merge_action merge_raw_motion_events( XIRawEvent *prev, XIRawE + */ + static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) + { ++#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H ++ struct x11drv_thread_data *thread_data = x11drv_thread_data(); ++#endif ++ + switch (prev->type) + { + case ConfigureNotify: +@@ -359,19 +363,21 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) + case GenericEvent: + if (next->xcookie.extension != xinput2_opcode) break; + if (next->xcookie.evtype != XI_RawMotion) break; +- if (x11drv_thread_data()->warp_serial) break; ++ if (thread_data->xi2_rawinput_only) break; ++ if (thread_data->warp_serial) break; + return MERGE_KEEP; + } + break; + case GenericEvent: + if (prev->xcookie.extension != xinput2_opcode) break; + if (prev->xcookie.evtype != XI_RawMotion) break; ++ if (thread_data->xi2_rawinput_only) break; + switch (next->type) + { + case GenericEvent: + if (next->xcookie.extension != xinput2_opcode) break; + if (next->xcookie.evtype != XI_RawMotion) break; +- if (x11drv_thread_data()->warp_serial) break; ++ if (thread_data->warp_serial) break; + return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data ); + #endif + } +diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c +index 6b6512521f4..0558467a805 100644 +--- a/dlls/winex11.drv/mouse.c ++++ b/dlls/winex11.drv/mouse.c +@@ -422,7 +422,18 @@ void x11drv_xinput_enable( Display *display, Window window, long event_mask ) + memset( mask_bits, 0, sizeof(mask_bits) ); + XISetMask( mask_bits, XI_DeviceChanged ); + XISetMask( mask_bits, XI_RawMotion ); +- XISetMask( mask_bits, XI_ButtonPress ); ++ ++ if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) ++ { ++ XISetMask( mask_bits, XI_RawButtonPress ); ++ XISetMask( mask_bits, XI_RawButtonRelease ); ++ data->xi2_rawinput_only = TRUE; ++ } ++ else ++ { ++ XISetMask( mask_bits, XI_ButtonPress ); ++ data->xi2_rawinput_only = FALSE; ++ } + + pXISelectEvents( display, DefaultRootWindow( display ), &mask, 1 ); + +@@ -748,7 +759,6 @@ static void map_event_coords( HWND hwnd, Window window, Window event_root, int x + static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPUT *input ) + { + struct x11drv_win_data *data; +- RAWINPUT rawinput; + + input->type = INPUT_MOUSE; + +@@ -765,7 +775,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU + sync_window_cursor( window ); + last_cursor_change = input->u.mi.time; + } +- __wine_send_input( hwnd, input, &rawinput ); ++ __wine_send_input( hwnd, input, NULL ); + return; + } + +@@ -805,7 +815,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU + SERVER_END_REQ; + } + +- __wine_send_input( hwnd, input, &rawinput ); ++ __wine_send_input( hwnd, input, NULL ); + } + + #ifdef SONAME_LIBXCURSOR +@@ -1760,7 +1770,6 @@ void move_resize_window( HWND hwnd, int dir ) + { + MSG msg; + INPUT input; +- RAWINPUT rawinput; + int x, y, rootX, rootY; + + if (!XQueryPointer( display, root_window, &root, &child, &rootX, &rootY, &x, &y, &xstate )) break; +@@ -1776,7 +1785,7 @@ void move_resize_window( HWND hwnd, int dir ) + input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; + input.u.mi.time = GetTickCount(); + input.u.mi.dwExtraInfo = 0; +- __wine_send_input( hwnd, &input, &rawinput ); ++ __wine_send_input( hwnd, &input, NULL ); + } + + while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) +@@ -1952,6 +1961,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) + x_rel = &thread_data->x_rel_valuator; + y_rel = &thread_data->y_rel_valuator; + ++ input.type = INPUT_MOUSE; + input.u.mi.mouseData = 0; + input.u.mi.dwFlags = MOUSEEVENTF_MOVE; + input.u.mi.time = EVENT_x11_time_to_win32_time( event->time ); +@@ -1987,10 +1997,85 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) + return FALSE; + } + +- TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); ++ if (!thread_data->xi2_rawinput_only) ++ { ++ TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); ++ __wine_send_input( 0, &input, NULL ); ++ } ++ else ++ { ++ TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); + +- input.type = INPUT_MOUSE; +- __wine_send_input( 0, &input, &rawinput ); ++ rawinput.header.dwType = RIM_TYPEMOUSE; ++ rawinput.header.dwSize = offsetof(RAWINPUT, data) + sizeof(RAWMOUSE); ++ rawinput.header.hDevice = ULongToHandle(1); /* WINE_MOUSE_HANDLE */ ++ rawinput.header.wParam = RIM_INPUT; ++ rawinput.data.mouse.ulRawButtons = input.u.mi.dwFlags; ++ rawinput.data.mouse.u.ulButtons = input.u.mi.mouseData; ++ rawinput.data.mouse.lLastX = input.u.mi.dx; ++ rawinput.data.mouse.lLastY = input.u.mi.dy; ++ rawinput.data.mouse.ulExtraInformation = 0; ++ ++ input.type = INPUT_HARDWARE; ++ input.u.hi.uMsg = WM_INPUT; ++ input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16); ++ input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0); ++ if (rawinput.data.mouse.lLastX || rawinput.data.mouse.lLastY) ++ __wine_send_input( 0, &input, &rawinput ); ++ } ++ return TRUE; ++} ++ ++/*********************************************************************** ++ * X11DRV_RawButtonEvent ++ */ ++static BOOL X11DRV_RawButtonEvent( XGenericEventCookie *cookie ) ++{ ++ struct x11drv_thread_data *thread_data = x11drv_thread_data(); ++ XIRawEvent *event = cookie->data; ++ int button = event->detail - 1; ++ RAWINPUT rawinput; ++ INPUT input; ++ ++ if (!device_mapping || device_mapping->deviceid != event->sourceid) ++ update_device_mapping( event->display, event->sourceid ); ++ ++ if (button >= 0 && device_mapping) ++ button = device_mapping->buttons[button] - 1; ++ ++ if (button >= 0 && pointer_mapping) ++ button = pointer_mapping->buttons[button] - 1; ++ ++ if (button < 0 || button >= NB_BUTTONS) return FALSE; ++ if (thread_data->xi2_state != xi_enabled) return FALSE; ++ if (event->deviceid != thread_data->xi2_core_pointer) return FALSE; ++ ++ TRACE( "raw button %u (raw: %u) %s\n", button, event->detail, event->evtype == XI_RawButtonRelease ? "up" : "down" ); ++ ++ rawinput.header.dwType = RIM_TYPEMOUSE; ++ rawinput.header.dwSize = offsetof(RAWINPUT, data) + sizeof(RAWMOUSE); ++ rawinput.header.hDevice = ULongToHandle(1); /* WINE_MOUSE_HANDLE */ ++ rawinput.header.wParam = RIM_INPUT; ++ if (event->evtype == XI_RawButtonRelease) ++ { ++ rawinput.data.mouse.ulRawButtons = button_up_flags[button]; ++ rawinput.data.mouse.u.ulButtons = button_up_data[button]; ++ } ++ else ++ { ++ rawinput.data.mouse.ulRawButtons = button_down_flags[button]; ++ rawinput.data.mouse.u.ulButtons = button_down_data[button]; ++ } ++ rawinput.data.mouse.lLastX = 0; ++ rawinput.data.mouse.lLastY = 0; ++ rawinput.data.mouse.ulExtraInformation = 0; ++ ++ input.type = INPUT_HARDWARE; ++ input.u.hi.uMsg = WM_INPUT; ++ input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16); ++ input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0); ++ if (rawinput.data.mouse.ulRawButtons || rawinput.data.mouse.u.ulButtons) ++ __wine_send_input( 0, &input, &rawinput ); + return TRUE; + } + +@@ -2066,6 +2151,10 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev ) + case XI_RawMotion: + ret = X11DRV_RawMotion( event ); + break; ++ case XI_RawButtonPress: ++ case XI_RawButtonRelease: ++ ret = X11DRV_RawButtonEvent( event ); ++ break; + + default: + TRACE( "Unhandled event %#x\n", event->evtype ); +diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h +index afa990b7e68..910a6c6cc18 100644 +--- a/dlls/winex11.drv/x11drv.h ++++ b/dlls/winex11.drv/x11drv.h +@@ -353,6 +353,7 @@ struct x11drv_thread_data + struct x11drv_valuator_data x_rel_valuator; + struct x11drv_valuator_data y_rel_valuator; + int xi2_core_pointer; /* XInput2 core pointer id */ ++ int xi2_rawinput_only; + }; + + extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN; +-- +2.30.2 + diff --git a/patches/user32-rawinput-mouse/0010-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch b/patches/user32-rawinput-mouse/0010-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch deleted file mode 100644 index 0da5a50f..00000000 --- a/patches/user32-rawinput-mouse/0010-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch +++ /dev/null @@ -1,282 +0,0 @@ -From b1139be0f5b7cc4c682f382655a6b58e5087a711 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?R=C3=A9mi=20Bernon?= -Date: Wed, 11 Sep 2019 10:15:20 +0200 -Subject: [PATCH] winex11.drv: Listen to RawMotion and RawButton* events in the - desktop thread. - -We still need to send "normal" input from the clipping window thread -to trigger low-level hooks callbacks when clipping cursor. This is for -instance used in our dinput implementation. ---- - dlls/winex11.drv/event.c | 10 +++- - dlls/winex11.drv/mouse.c | 88 ++++++++++++++++++++++++++++------ - dlls/winex11.drv/x11drv.h | 3 ++ - dlls/winex11.drv/x11drv_main.c | 4 ++ - 4 files changed, 89 insertions(+), 16 deletions(-) - -diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c -index 07f7a1ad502..d722ba9d7cc 100644 ---- a/dlls/winex11.drv/event.c -+++ b/dlls/winex11.drv/event.c -@@ -321,6 +321,10 @@ static enum event_merge_action merge_raw_motion_events( XIRawEvent *prev, XIRawE - */ - static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) - { -+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H -+ struct x11drv_thread_data *thread_data = x11drv_thread_data(); -+#endif -+ - switch (prev->type) - { - case ConfigureNotify: -@@ -352,19 +356,21 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) - case GenericEvent: - if (next->xcookie.extension != xinput2_opcode) break; - if (next->xcookie.evtype != XI_RawMotion) break; -- if (x11drv_thread_data()->warp_serial) break; -+ if (thread_data->xi2_rawinput_only) break; -+ if (thread_data->warp_serial) break; - return MERGE_KEEP; - } - break; - case GenericEvent: - if (prev->xcookie.extension != xinput2_opcode) break; - if (prev->xcookie.evtype != XI_RawMotion) break; -+ if (thread_data->xi2_rawinput_only) break; - switch (next->type) - { - case GenericEvent: - if (next->xcookie.extension != xinput2_opcode) break; - if (next->xcookie.evtype != XI_RawMotion) break; -- if (x11drv_thread_data()->warp_serial) break; -+ if (thread_data->warp_serial) break; - return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data ); - #endif - } -diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c -index a1f2d4262e1..74598a3a85b 100644 ---- a/dlls/winex11.drv/mouse.c -+++ b/dlls/winex11.drv/mouse.c -@@ -362,9 +362,9 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator - - - /*********************************************************************** -- * enable_xinput2 -+ * X11DRV_XInput2_Enable - */ --static void enable_xinput2(void) -+void X11DRV_XInput2_Enable(void) - { - #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H - struct x11drv_thread_data *data = x11drv_thread_data(); -@@ -396,9 +396,21 @@ static void enable_xinput2(void) - mask.mask_len = sizeof(mask_bits); - mask.deviceid = XIAllMasterDevices; - memset( mask_bits, 0, sizeof(mask_bits) ); -+ - XISetMask( mask_bits, XI_DeviceChanged ); - XISetMask( mask_bits, XI_RawMotion ); -- XISetMask( mask_bits, XI_ButtonPress ); -+ -+ if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) -+ { -+ XISetMask( mask_bits, XI_RawButtonPress ); -+ XISetMask( mask_bits, XI_RawButtonRelease ); -+ data->xi2_rawinput_only = TRUE; -+ } -+ else -+ { -+ XISetMask( mask_bits, XI_ButtonPress ); -+ data->xi2_rawinput_only = FALSE; -+ } - - pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 ); - -@@ -411,9 +423,9 @@ static void enable_xinput2(void) - } - - /*********************************************************************** -- * disable_xinput2 -+ * X11DRV_XInput2_Disable - */ --static void disable_xinput2(void) -+void X11DRV_XInput2_Disable(void) - { - #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H - struct x11drv_thread_data *data = x11drv_thread_data(); -@@ -473,7 +485,7 @@ static BOOL grab_clipping_window( const RECT *clip ) - } - - /* enable XInput2 unless we are already clipping */ -- if (!data->clip_hwnd) enable_xinput2(); -+ if (!data->clip_hwnd) X11DRV_XInput2_Enable(); - - if (data->xi2_state != xi_enabled) - { -@@ -503,7 +515,7 @@ static BOOL grab_clipping_window( const RECT *clip ) - - if (!clipping_cursor) - { -- disable_xinput2(); -+ X11DRV_XInput2_Disable(); - DestroyWindow( msg_hwnd ); - return FALSE; - } -@@ -582,7 +594,7 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND prev_clip_hwnd, HWND new_clip_hwnd ) - TRACE( "clip hwnd reset from %p\n", hwnd ); - data->clip_hwnd = 0; - data->clip_reset = GetTickCount(); -- disable_xinput2(); -+ X11DRV_XInput2_Disable(); - DestroyWindow( hwnd ); - } - else if (prev_clip_hwnd) -@@ -719,7 +731,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU - } - input->u.mi.dx += clip_rect.left; - input->u.mi.dy += clip_rect.top; -- __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); -+ __wine_send_input( hwnd, input, SEND_HWMSG_WINDOW ); - return; - } - -@@ -759,7 +771,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU - SERVER_END_REQ; - } - -- __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); -+ __wine_send_input( hwnd, input, SEND_HWMSG_WINDOW ); - } - - #ifdef SONAME_LIBXCURSOR -@@ -1729,7 +1741,7 @@ void move_resize_window( HWND hwnd, int dir ) - input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; - input.u.mi.time = GetTickCount(); - input.u.mi.dwExtraInfo = 0; -- __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); -+ __wine_send_input( hwnd, &input, SEND_HWMSG_WINDOW ); - } - - while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) -@@ -1912,6 +1924,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) - x_rel = &thread_data->x_rel_valuator; - y_rel = &thread_data->y_rel_valuator; - -+ input.type = INPUT_MOUSE; - input.u.mi.mouseData = 0; - input.u.mi.dwFlags = MOUSEEVENTF_MOVE; - input.u.mi.time = EVENT_x11_time_to_win32_time( event->time ); -@@ -1947,10 +1960,53 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) - return FALSE; - } - -- TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); -+ if (!thread_data->xi2_rawinput_only) -+ { -+ TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); -+ __wine_send_input( 0, &input, SEND_HWMSG_WINDOW ); -+ } -+ else -+ { -+ TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); -+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT ); -+ } -+ return TRUE; -+} - -- input.type = INPUT_MOUSE; -- __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW ); -+/*********************************************************************** -+ * X11DRV_RawButtonEvent -+ */ -+static BOOL X11DRV_RawButtonEvent( XGenericEventCookie *cookie ) -+{ -+ struct x11drv_thread_data *thread_data = x11drv_thread_data(); -+ XIRawEvent *event = cookie->data; -+ int button = event->detail - 1; -+ INPUT input; -+ -+ if (!device_mapping || device_mapping->deviceid != event->sourceid) -+ update_device_mapping( event->display, event->sourceid ); -+ -+ if (button >= 0 && device_mapping) -+ button = device_mapping->buttons[button] - 1; -+ -+ if (button >= 0 && pointer_mapping) -+ button = pointer_mapping->buttons[button] - 1; -+ -+ if (button < 0 || button >= NB_BUTTONS) return FALSE; -+ if (thread_data->xi2_state != xi_enabled) return FALSE; -+ if (event->deviceid != thread_data->xi2_core_pointer) return FALSE; -+ -+ TRACE( "raw button %u (raw: %u) %s\n", button, event->detail, event->evtype == XI_RawButtonRelease ? "up" : "down" ); -+ -+ input.type = INPUT_MOUSE; -+ input.u.mi.dx = 0; -+ input.u.mi.dy = 0; -+ input.u.mi.mouseData = event->evtype == XI_RawButtonRelease ? button_up_data[button] : button_down_data[button]; -+ input.u.mi.dwFlags = event->evtype == XI_RawButtonRelease ? button_up_flags[button] : button_down_flags[button]; -+ input.u.mi.time = EVENT_x11_time_to_win32_time(event->time); -+ input.u.mi.dwExtraInfo = 0; -+ -+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT ); - return TRUE; - } - -@@ -2026,6 +2082,10 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev ) - case XI_RawMotion: - ret = X11DRV_RawMotion( event ); - break; -+ case XI_RawButtonPress: -+ case XI_RawButtonRelease: -+ ret = X11DRV_RawButtonEvent( event ); -+ break; - - default: - TRACE( "Unhandled event %#x\n", event->evtype ); -diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h -index 6c2a8978eb5..92bd23c93ea 100644 ---- a/dlls/winex11.drv/x11drv.h -+++ b/dlls/winex11.drv/x11drv.h -@@ -196,6 +196,8 @@ extern BOOL CDECL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN; - - extern void X11DRV_Xcursor_Init(void) DECLSPEC_HIDDEN; - extern void X11DRV_XInput2_Init(void) DECLSPEC_HIDDEN; -+extern void X11DRV_XInput2_Enable(void) DECLSPEC_HIDDEN; -+extern void X11DRV_XInput2_Disable(void) DECLSPEC_HIDDEN; - - extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, - const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits, -@@ -343,6 +345,7 @@ struct x11drv_thread_data - struct x11drv_valuator_data x_rel_valuator; - struct x11drv_valuator_data y_rel_valuator; - int xi2_core_pointer; /* XInput2 core pointer id */ -+ int xi2_rawinput_only; - }; - - extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN; -diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c -index 6b32f3fd118..a7855a3245b 100644 ---- a/dlls/winex11.drv/x11drv_main.c -+++ b/dlls/winex11.drv/x11drv_main.c -@@ -633,6 +633,8 @@ void CDECL X11DRV_ThreadDetach(void) - - if (data) - { -+ if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) -+ X11DRV_XInput2_Disable(); - if (data->xim) XCloseIM( data->xim ); - if (data->font_set) XFreeFontSet( data->display, data->font_set ); - XCloseDisplay( data->display ); -@@ -702,6 +704,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) - TlsSetValue( thread_data_tls_index, data ); - - if (use_xim) X11DRV_SetupXIM(); -+ if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) -+ X11DRV_XInput2_Enable(); - - return data; - } --- -2.28.0 - diff --git a/patches/user32-rawinput-mouse/0011-winex11.drv-Move-header-order.patch b/patches/user32-rawinput-mouse/0011-winex11.drv-Move-header-order.patch deleted file mode 100644 index 471ee827..00000000 --- a/patches/user32-rawinput-mouse/0011-winex11.drv-Move-header-order.patch +++ /dev/null @@ -1,36 +0,0 @@ -From b8cfcfa8e3b7694102462b6d3d59ee7919897a00 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 1 Dec 2020 10:19:00 +1100 -Subject: [PATCH] winex11.drv: Move header order - -The HAVE_X11_EXTENSIONS_XINPUT2_H needs to be moved into each of the files -to avoid a compile error with Status being undefined. ---- - dlls/winex11.drv/window.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c -index 1e9d63ae808..22a330b3f88 100644 ---- a/dlls/winex11.drv/window.c -+++ b/dlls/winex11.drv/window.c -@@ -37,6 +37,8 @@ - #include - #endif /* HAVE_LIBXSHAPE */ - -+#include "x11drv.h" -+ - /* avoid conflict with field names in included win32 headers */ - #undef Status - #include "windef.h" -@@ -45,7 +47,7 @@ - #include "winuser.h" - #include "wine/unicode.h" - --#include "x11drv.h" -+ - #include "wine/debug.h" - #include "wine/server.h" - #include "mwm.h" --- -2.29.2 - diff --git a/patches/user32-rawinput-mouse/definition b/patches/user32-rawinput-mouse/definition index a5e9550e..79417ded 100644 --- a/patches/user32-rawinput-mouse/definition +++ b/patches/user32-rawinput-mouse/definition @@ -1,4 +1,3 @@ Fixes: [42631] Mouse drift, jump or don't react to small slow movements in Unity-engine games and Fallout 4 (partly fixed in Unity games, have walkaround in Fallout4 ) Fixes: [42675] Overwatch: Phantom mouse input / view pulled up to ceiling -# In the process of upstreaming. -Disabled: true +Depends: user32-rawinput-hid