-- v2: win32u: Add support for sending and receiving WM_POINTER* messages. server: Add support for sending and receiving WM_POINTER* messages. mouhid.sys: Send WM_POINTER* messages on contact updates. dinput/tests: Test the WM_POINTER* message parameter values. win32u: Use a custom struct hid_input for NtUserSendHardwareInput.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/hidclass.sys/device.c | 2 +- dlls/hidclass.sys/pnp.c | 2 +- dlls/win32u/input.c | 12 +----------- dlls/win32u/main.c | 5 ----- dlls/win32u/message.c | 19 +++++++++++++------ dlls/win32u/win32syscalls.h | 6 ++---- dlls/win32u/win32u.spec | 1 - dlls/win32u/win32u_private.h | 3 +-- dlls/win32u/window.c | 6 ++++++ dlls/wineandroid.drv/keyboard.c | 2 +- dlls/wineandroid.drv/window.c | 4 ++-- dlls/winemac.drv/keyboard.c | 2 +- dlls/winemac.drv/mouse.c | 2 +- dlls/winewayland.drv/wayland_keyboard.c | 6 +++--- dlls/winewayland.drv/wayland_pointer.c | 8 ++++---- dlls/winex11.drv/keyboard.c | 2 +- dlls/winex11.drv/mouse.c | 8 ++++---- dlls/wow64win/user.c | 22 ++++++++++++++++------ include/ntuser.h | 14 ++++++++++++++ 19 files changed, 72 insertions(+), 54 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 62dc9f86379..1b5233e84b6 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -252,7 +252,7 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack input.hi.uMsg = WM_INPUT; input.hi.wParamH = 0; input.hi.wParamL = 0; - __wine_send_input( 0, &input, rawinput ); + NtUserSendHardwareInput( 0, 0, &input, (LPARAM)rawinput );
free( rawinput ); } diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index e2bdd82f567..afa217c539f 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -134,7 +134,7 @@ static void send_wm_input_device_change(BASE_DEVICE_EXTENSION *ext, LPARAM param input.hi.uMsg = WM_INPUT_DEVICE_CHANGE; input.hi.wParamH = 0; input.hi.wParamL = 0; - __wine_send_input(0, &input, &rawinput); + NtUserSendHardwareInput(0, 0, &input, (LPARAM)&rawinput); }
static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *bus_pdo) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index ef8d564c264..0f6b9482942 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -604,16 +604,6 @@ BOOL WINAPI NtUserAttachThreadInput( DWORD from, DWORD to, BOOL attach ) return ret; }
-/*********************************************************************** - * __wine_send_input (win32u.@) - * - * Internal SendInput function to allow the graphics driver to inject real events. - */ -BOOL WINAPI __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput ) -{ - return set_ntstatus( send_hardware_message( hwnd, input, rawinput, 0 )); -} - /*********************************************************************** * update_mouse_coords * @@ -693,7 +683,7 @@ UINT WINAPI NtUserSendInput( UINT count, INPUT *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, SEND_HWMSG_INJECTED, &input, 0 ); break; case INPUT_HARDWARE: RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index e06386da693..234120408f0 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -2162,11 +2162,6 @@ BOOL SYSCALL_API __wine_get_icm_profile( HDC hdc, BOOL allow_default, DWORD *siz SYSCALL_FUNC( __wine_get_icm_profile ); }
-BOOL SYSCALL_API __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput ) -{ - SYSCALL_FUNC( __wine_send_input ); -} - #else /* __arm64ec__ */
#ifdef _WIN64 diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 08222fd460f..e0944ca64d8 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3482,7 +3482,7 @@ LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid, /*********************************************************************** * send_hardware_message */ -NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput, UINT flags ) +NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARAM lparam ) { struct send_message_info info; int prev_x, prev_y, new_x, new_y; @@ -3500,18 +3500,22 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r if (input->type == INPUT_MOUSE && (input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_RIGHTDOWN))) clip_fullscreen_window( hwnd, FALSE );
- if (input->type == INPUT_HARDWARE && rawinput->header.dwType == RIM_TYPEHID) + if (input->type == INPUT_HARDWARE) { if (input->hi.uMsg == WM_INPUT_DEVICE_CHANGE) { + const RAWINPUT *rawinput = (const RAWINPUT *)lparam; hid_usage_page = ((USAGE *)rawinput->data.hid.bRawData)[0]; hid_usage = ((USAGE *)rawinput->data.hid.bRawData)[1]; } - if (input->hi.uMsg == WM_INPUT && - !rawinput_device_get_usages( rawinput->header.hDevice, &hid_usage_page, &hid_usage )) + if (input->hi.uMsg == WM_INPUT) { - WARN( "unable to get HID usages for device %p\n", rawinput->header.hDevice ); - return STATUS_INVALID_HANDLE; + const RAWINPUT *rawinput = (const RAWINPUT *)lparam; + if (!rawinput_device_get_usages( rawinput->header.hDevice, &hid_usage_page, &hid_usage )) + { + WARN( "unable to get HID usages for device %p\n", rawinput->header.hDevice ); + return STATUS_INVALID_HANDLE; + } } }
@@ -3549,6 +3553,8 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r { case WM_INPUT: case WM_INPUT_DEVICE_CHANGE: + { + const RAWINPUT *rawinput = (const RAWINPUT *)lparam; switch (rawinput->header.dwType) { case RIM_TYPEHID: @@ -3565,6 +3571,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r break; } } + } break; } ret = wine_server_call( req ); diff --git a/dlls/win32u/win32syscalls.h b/dlls/win32u/win32syscalls.h index da0ba39f771..6dedc3333a2 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -402,8 +402,7 @@ SYSCALL_ENTRY( 0x018e, NtUserWindowFromDC, 4 ) \ SYSCALL_ENTRY( 0x018f, NtUserWindowFromPoint, 8 ) \ SYSCALL_ENTRY( 0x0190, __wine_get_file_outline_text_metric, 16 ) \ - SYSCALL_ENTRY( 0x0191, __wine_get_icm_profile, 16 ) \ - SYSCALL_ENTRY( 0x0192, __wine_send_input, 12 ) + SYSCALL_ENTRY( 0x0191, __wine_get_icm_profile, 16 )
#define ALL_SYSCALLS64 \ SYSCALL_ENTRY( 0x0000, NtGdiAbortDoc, 8 ) \ @@ -807,5 +806,4 @@ SYSCALL_ENTRY( 0x018e, NtUserWindowFromDC, 8 ) \ SYSCALL_ENTRY( 0x018f, NtUserWindowFromPoint, 16 ) \ SYSCALL_ENTRY( 0x0190, __wine_get_file_outline_text_metric, 32 ) \ - SYSCALL_ENTRY( 0x0191, __wine_get_icm_profile, 32 ) \ - SYSCALL_ENTRY( 0x0192, __wine_send_input, 24 ) + SYSCALL_ENTRY( 0x0191, __wine_get_icm_profile, 32 ) diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 8aa241b1e7a..c2f51a014eb 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1322,4 +1322,3 @@
@ stdcall -syscall __wine_get_icm_profile(long long ptr ptr) @ stdcall -syscall __wine_get_file_outline_text_metric(wstr ptr ptr ptr) -@ stdcall -syscall __wine_send_input(long ptr ptr) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index d5f010a8249..eba9a3389eb 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -131,8 +131,7 @@ extern void track_mouse_menu_bar( HWND hwnd, INT ht, int x, int y ); /* message.c */ extern BOOL kill_system_timer( HWND hwnd, UINT_PTR id ); extern BOOL reply_message_result( LRESULT result ); -extern NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput, - UINT flags ); +extern NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARAM lparam ); extern LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid, UINT msg, WPARAM wparam, LPARAM lparam, UINT flags, UINT timeout, PDWORD_PTR res_ptr ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 69dd8caba5d..73a0fa9e896 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5590,6 +5590,12 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) case NtUserCallHwndParam_ShowOwnedPopups: return show_owned_popups( hwnd, param );
+ case NtUserCallHwndParam_SendHardwareInput: + { + struct send_hardware_input_params *params = (void *)param; + return send_hardware_message( hwnd, params->flags, params->input, params->lparam ); + } + /* temporary exports */ case NtUserSetWindowStyle: { diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c index 9f369094949..b0380d147da 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 ) input.ki.time = 0; input.ki.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input, NULL ); + NtUserSendHardwareInput( hwnd, 0, &input, 0 ); }
/*********************************************************************** diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index d62a2c53909..ed7ee808b29 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -514,7 +514,7 @@ static int process_events( DWORD mask ) } SERVER_END_REQ; } - __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, NULL ); + NtUserSendHardwareInput( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, 0, 0 ); } break;
@@ -528,7 +528,7 @@ static int process_events( DWORD mask ) event->data.kbd.input.ki.wVk, event->data.kbd.input.ki.wVk, event->data.kbd.input.ki.wScan ); update_keyboard_lock_state( event->data.kbd.input.ki.wVk, event->data.kbd.lock_state ); - __wine_send_input( 0, &event->data.kbd.input, NULL ); + NtUserSendHardwareInput( 0, 0, &event->data.kbd.input, 0 ); break;
default: diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c index bf1daa7a5df..474ca499961 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -1001,7 +1001,7 @@ static void macdrv_send_keyboard_input(HWND hwnd, WORD vkey, WORD scan, unsigned input.ki.time = time; input.ki.dwExtraInfo = 0;
- __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); }
diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c index 2f05a33a8b5..a87654e9885 100644 --- a/dlls/winemac.drv/mouse.c +++ b/dlls/winemac.drv/mouse.c @@ -158,7 +158,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); + NtUserSendHardwareInput(top_level_hwnd, 0, &input, 0); }
diff --git a/dlls/winewayland.drv/wayland_keyboard.c b/dlls/winewayland.drv/wayland_keyboard.c index a5d01fe1f08..04a1c0a9fc3 100644 --- a/dlls/winewayland.drv/wayland_keyboard.c +++ b/dlls/winewayland.drv/wayland_keyboard.c @@ -642,7 +642,7 @@ static void release_all_keys(HWND hwnd) input.ki.wScan = scan & 0xff; input.ki.dwFlags = KEYEVENTF_KEYUP; if (scan & ~0xff) input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; - __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); } } } @@ -805,7 +805,7 @@ static void send_right_control(HWND hwnd, uint32_t state) input.ki.wVk = VK_RCONTROL; input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; if (state == WL_KEYBOARD_KEY_STATE_RELEASED) input.ki.dwFlags |= KEYEVENTF_KEYUP; - __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); }
static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, @@ -829,7 +829,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard, if (scan & ~0xff) input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
if (state == WL_KEYBOARD_KEY_STATE_RELEASED) input.ki.dwFlags |= KEYEVENTF_KEYUP; - __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); }
static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard, diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 54dd7931b6e..df76a4e9954 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -86,7 +86,7 @@ static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy) hwnd, wl_fixed_to_double(sx), wl_fixed_to_double(sy), (int)screen.x, (int)screen.y);
- __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); }
static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, @@ -185,7 +185,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
TRACE("hwnd=%p button=%#x state=%u\n", hwnd, button, state);
- __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); }
static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, @@ -232,7 +232,7 @@ static void pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_point
TRACE("hwnd=%p axis=%u discrete=%d\n", hwnd, axis, discrete);
- __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); }
static const struct wl_pointer_listener pointer_listener = @@ -317,7 +317,7 @@ static void relative_pointer_v1_relative_motion(void *data, hwnd, wl_fixed_to_double(dx), wl_fixed_to_double(dy), (int)screen.x, (int)screen.y);
- __wine_send_input(hwnd, &input, NULL); + NtUserSendHardwareInput(hwnd, 0, &input, 0); }
static const struct zwp_relative_pointer_v1_listener relative_pointer_v1_listener = diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index dde74303bad..23f07b851a7 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1131,7 +1131,7 @@ static void X11DRV_send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, UINT fl input.ki.time = time; input.ki.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input, NULL ); + NtUserSendHardwareInput( hwnd, 0, &input, 0 ); }
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index bdbd559b107..03c2152b76b 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -524,7 +524,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU { struct x11drv_thread_data *thread_data = x11drv_thread_data(); if (!thread_data->clipping_cursor || thread_data->clip_window != window) return; - __wine_send_input( hwnd, input, NULL ); + NtUserSendHardwareInput( hwnd, 0, input, 0 ); return; }
@@ -551,7 +551,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU SERVER_END_REQ; }
- __wine_send_input( hwnd, input, NULL ); + NtUserSendHardwareInput( hwnd, 0, input, 0 ); }
#ifdef SONAME_LIBXCURSOR @@ -1494,7 +1494,7 @@ void move_resize_window( HWND hwnd, int dir ) input.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; input.mi.time = NtGetTickCount(); input.mi.dwExtraInfo = 0; - __wine_send_input( hwnd, &input, NULL ); + NtUserSendHardwareInput( hwnd, 0, &input, 0 ); }
while (NtUserPeekMessage( &msg, 0, 0, 0, PM_REMOVE )) @@ -1722,7 +1722,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) input.mi.dy = 0; if (!map_raw_event_coords( event, &input )) return FALSE;
- __wine_send_input( 0, &input, NULL ); + NtUserSendHardwareInput( 0, 0, &input, 0 ); return TRUE; }
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index ff3f92c81fe..9a293826ba9 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -1710,6 +1710,22 @@ NTSTATUS WINAPI wow64_NtUserCallHwndParam( UINT *args ) return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, code ); }
+ case NtUserCallHwndParam_SendHardwareInput: + { + struct + { + UINT flags; + ULONG input; + ULONG lparam; + } *params32 = UlongToPtr( param ); + struct send_hardware_input_params params; + + params.flags = params32->flags; + params.input = UlongToPtr( params32->input ); + params.lparam = params32->lparam; + return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, code ); + } + default: return NtUserCallHwndParam( hwnd, param, code ); } @@ -4875,9 +4891,3 @@ NTSTATUS WINAPI wow64_NtUserDisplayConfigGetDeviceInfo( UINT *args )
return NtUserDisplayConfigGetDeviceInfo( packet ); } - -NTSTATUS WINAPI wow64___wine_send_input( UINT *args ) -{ - ERR( "not supported\n" ); - return 0; -} diff --git a/include/ntuser.h b/include/ntuser.h index 9cf23373cdc..eb8c95ac8b4 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1236,6 +1236,7 @@ enum NtUserCallHwndParam_SetMDIClientInfo, NtUserCallHwndParam_SetWindowContextHelpId, NtUserCallHwndParam_ShowOwnedPopups, + NtUserCallHwndParam_SendHardwareInput, /* temporary exports */ NtUserSetWindowStyle, }; @@ -1406,6 +1407,19 @@ static inline BOOL NtUserShowOwnedPopups( HWND hwnd, BOOL show ) return NtUserCallHwndParam( hwnd, show, NtUserCallHwndParam_ShowOwnedPopups ); }
+struct send_hardware_input_params +{ + UINT flags; + const INPUT *input; + LPARAM lparam; /* RAWINPUT pointer for WM_INPUT* messages */ +}; + +static inline BOOL NtUserSendHardwareInput( HWND hwnd, UINT flags, const INPUT *input, LPARAM lparam ) +{ + struct send_hardware_input_params params = {.flags = flags, .input = input, .lparam = lparam}; + return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_SendHardwareInput ); +} + /* Wine extensions */ W32KAPI BOOL WINAPI __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/hidclass.sys/device.c | 37 +++++++++++++++---------------- dlls/hidclass.sys/pnp.c | 23 +++++++------------ dlls/win32u/message.c | 45 +++++++------------------------------- include/ntuser.h | 13 ++++++++++- server/protocol.def | 9 ++------ server/queue.c | 2 +- 6 files changed, 49 insertions(+), 80 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 1b5233e84b6..cb8330b18bb 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -225,7 +225,6 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack struct hid_report *last_report, *report; struct hid_queue *queue; LIST_ENTRY completed, *entry; - RAWINPUT *rawinput; KIRQL irql; IRP *irp;
@@ -233,28 +232,28 @@ static void hid_device_queue_input( DEVICE_OBJECT *device, HID_XFER_PACKET *pack
if (IsEqualGUID( ext->class_guid, &GUID_DEVINTERFACE_HID )) { - size = offsetof( RAWINPUT, data.hid.bRawData[report_len] ); - if (!(rawinput = malloc( size ))) ERR( "Failed to allocate rawinput data!\n" ); + struct hid_input *hid; + + size = offsetof( struct hid_input, data[report_len] ); + if (!(hid = malloc( size ))) ERR( "Failed to allocate rawinput data!\n" ); else { - INPUT input; - - rawinput->header.dwType = RIM_TYPEHID; - rawinput->header.dwSize = size; - rawinput->header.hDevice = ULongToHandle( ext->u.pdo.rawinput_handle ); - rawinput->header.wParam = RIM_INPUT; - rawinput->data.hid.dwCount = 1; - rawinput->data.hid.dwSizeHid = report_len; - memcpy( rawinput->data.hid.bRawData, packet->reportBuffer, packet->reportBufferLen ); - memset( rawinput->data.hid.bRawData + packet->reportBufferLen, 0, report_len - packet->reportBufferLen ); - - input.type = INPUT_HARDWARE; + INPUT input = {.type = INPUT_HARDWARE}; + input.hi.uMsg = WM_INPUT; - input.hi.wParamH = 0; - input.hi.wParamL = 0; - NtUserSendHardwareInput( 0, 0, &input, (LPARAM)rawinput ); + input.hi.wParamH = HIWORD(RIM_INPUT); + input.hi.wParamL = LOWORD(RIM_INPUT); + + hid->device = ext->u.pdo.rawinput_handle; + hid->usage = MAKELONG(desc->Usage, desc->UsagePage); + + hid->count = 1; + hid->length = report_len; + memcpy( hid->data, packet->reportBuffer, packet->reportBufferLen ); + memset( hid->data + packet->reportBufferLen, 0, report_len - packet->reportBufferLen ); + NtUserSendHardwareInput( 0, 0, &input, (LPARAM)hid );
- free( rawinput ); + free( hid ); } }
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index afa217c539f..551635b055e 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -114,27 +114,20 @@ C_ASSERT(offsetof(RAWINPUT, data.hid.bRawData[2 * sizeof(USAGE)]) < sizeof(RAWIN static void send_wm_input_device_change(BASE_DEVICE_EXTENSION *ext, LPARAM param) { HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc; - RAWINPUT rawinput; - INPUT input; + INPUT input = {.type = INPUT_HARDWARE}; + struct hid_input hid = {0};
TRACE("ext %p, lparam %p\n", ext, (void *)param);
if (!IsEqualGUID( ext->class_guid, &GUID_DEVINTERFACE_HID )) return;
- rawinput.header.dwType = RIM_TYPEHID; - rawinput.header.dwSize = offsetof(RAWINPUT, data.hid.bRawData[2 * sizeof(USAGE)]); - rawinput.header.hDevice = ULongToHandle(ext->u.pdo.rawinput_handle); - rawinput.header.wParam = param; - rawinput.data.hid.dwCount = 0; - rawinput.data.hid.dwSizeHid = 0; - ((USAGE *)rawinput.data.hid.bRawData)[0] = desc->UsagePage; - ((USAGE *)rawinput.data.hid.bRawData)[1] = desc->Usage; - - input.type = INPUT_HARDWARE; input.hi.uMsg = WM_INPUT_DEVICE_CHANGE; - input.hi.wParamH = 0; - input.hi.wParamL = 0; - NtUserSendHardwareInput(0, 0, &input, (LPARAM)&rawinput); + input.hi.wParamH = HIWORD(param); + input.hi.wParamL = LOWORD(param); + + hid.device = ext->u.pdo.rawinput_handle; + hid.usage = MAKELONG(desc->Usage, desc->UsagePage); + NtUserSendHardwareInput(0, 0, &input, (LPARAM)&hid); }
static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *bus_pdo) diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index e0944ca64d8..e8d456689b6 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3486,7 +3486,6 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA { struct send_message_info info; int prev_x, prev_y, new_x, new_y; - USAGE hid_usage_page, hid_usage; NTSTATUS ret; BOOL wait, affects_key_state = FALSE;
@@ -3500,25 +3499,6 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA if (input->type == INPUT_MOUSE && (input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_RIGHTDOWN))) clip_fullscreen_window( hwnd, FALSE );
- if (input->type == INPUT_HARDWARE) - { - if (input->hi.uMsg == WM_INPUT_DEVICE_CHANGE) - { - const RAWINPUT *rawinput = (const RAWINPUT *)lparam; - hid_usage_page = ((USAGE *)rawinput->data.hid.bRawData)[0]; - hid_usage = ((USAGE *)rawinput->data.hid.bRawData)[1]; - } - if (input->hi.uMsg == WM_INPUT) - { - const RAWINPUT *rawinput = (const RAWINPUT *)lparam; - if (!rawinput_device_get_usages( rawinput->header.hDevice, &hid_usage_page, &hid_usage )) - { - WARN( "unable to get HID usages for device %p\n", rawinput->header.hDevice ); - return STATUS_INVALID_HANDLE; - } - } - } - SERVER_START_REQ( send_hardware_message ) { req->win = wine_server_user_handle( hwnd ); @@ -3548,29 +3528,20 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA break; case INPUT_HARDWARE: req->input.hw.msg = input->hi.uMsg; - req->input.hw.lparam = MAKELONG( input->hi.wParamL, input->hi.wParamH ); + req->input.hw.wparam = MAKELONG( input->hi.wParamL, input->hi.wParamH ); switch (input->hi.uMsg) { case WM_INPUT: case WM_INPUT_DEVICE_CHANGE: { - const RAWINPUT *rawinput = (const RAWINPUT *)lparam; - switch (rawinput->header.dwType) - { - case RIM_TYPEHID: - req->input.hw.wparam = rawinput->header.wParam; - req->input.hw.hid.device = HandleToUlong( rawinput->header.hDevice ); - req->input.hw.hid.usage = MAKELONG(hid_usage, hid_usage_page); - req->input.hw.hid.count = rawinput->data.hid.dwCount; - req->input.hw.hid.length = rawinput->data.hid.dwSizeHid; - wine_server_add_data( req, rawinput->data.hid.bRawData, - rawinput->data.hid.dwCount * rawinput->data.hid.dwSizeHid ); - break; - default: - assert( 0 ); - break; - } + struct hid_input *hid = (struct hid_input *)lparam; + req->input.hw.hid = *hid; + wine_server_add_data( req, hid->data, hid->count * hid->length ); + break; } + default: + req->input.hw.lparam = lparam; + break; } break; } diff --git a/include/ntuser.h b/include/ntuser.h index eb8c95ac8b4..967936f43f2 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1407,11 +1407,22 @@ static inline BOOL NtUserShowOwnedPopups( HWND hwnd, BOOL show ) return NtUserCallHwndParam( hwnd, show, NtUserCallHwndParam_ShowOwnedPopups ); }
+struct hid_input +{ + UINT device; + UINT usage; + UINT count; + UINT length; + BYTE data[]; +}; + +C_ASSERT(sizeof(struct hid_input) == offsetof(struct hid_input, data[0])); + struct send_hardware_input_params { UINT flags; const INPUT *input; - LPARAM lparam; /* RAWINPUT pointer for WM_INPUT* messages */ + LPARAM lparam; /* struct hid_input pointer for WM_INPUT* messages */ };
static inline BOOL NtUserSendHardwareInput( HWND hwnd, UINT flags, const INPUT *input, LPARAM lparam ) diff --git a/server/protocol.def b/server/protocol.def index fa78e0487f8..7b21aa16636 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -30,6 +30,7 @@
#include <windef.h> #include <winbase.h> +#include <ntuser.h>
typedef unsigned int obj_handle_t; typedef unsigned int user_handle_t; @@ -341,13 +342,7 @@ typedef union unsigned int msg; /* message code */ lparam_t wparam; /* parameters */ lparam_t lparam; /* parameters */ - struct - { - unsigned int device; /* rawinput device index */ - unsigned int usage; /* HID device usage */ - unsigned int count; /* HID report count */ - unsigned int length; /* HID report length */ - } hid; + struct hid_input hid; /* defined in ntuser.h */ } hw; } hw_input_t;
diff --git a/server/queue.c b/server/queue.c index 4373bd71254..ef40d30aedf 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2250,7 +2250,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
msg->win = get_user_full_handle( win ); msg->msg = input->hw.msg; - msg->wparam = 0; + msg->wparam = input->hw.wparam; msg->lparam = input->hw.lparam; msg->x = desktop->cursor.x; msg->y = desktop->cursor.y;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 141 +++++++++++++++++++++++++++++++++--- 1 file changed, 131 insertions(+), 10 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index 2c44bb4c5c6..e6b38ad6cce 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -1767,14 +1767,31 @@ done: static UINT pointer_enter_count; static UINT pointer_up_count; static HANDLE touchdown_event, touchleave_event; +static WPARAM pointer_wparam[16]; +static WPARAM pointer_lparam[16]; +static UINT pointer_count;
static LRESULT CALLBACK touch_screen_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - if (msg == WM_POINTERENTER) pointer_enter_count++; + if (msg == WM_POINTERENTER) + { + pointer_wparam[pointer_count] = wparam; + pointer_lparam[pointer_count] = lparam; + pointer_count++; + pointer_enter_count++; + } if (msg == WM_POINTERDOWN) ReleaseSemaphore( touchdown_event, 1, NULL ); - if (msg == WM_POINTERUP) pointer_up_count++; + + if (msg == WM_POINTERUP) + { + pointer_wparam[pointer_count] = wparam; + pointer_lparam[pointer_count] = lparam; + pointer_count++; + pointer_up_count++; + } if (msg == WM_POINTERLEAVE) ReleaseSemaphore( touchleave_event, 1, NULL ); - return DefWindowProcA( hwnd, msg, wparam, lparam ); + + return DefWindowProcW( hwnd, msg, wparam, lparam ); }
static void test_hid_touch_screen(void) @@ -1909,7 +1926,7 @@ static void test_hid_touch_screen(void) };
RAWINPUTDEVICE rawdevice = {.usUsagePage = HID_USAGE_PAGE_DIGITIZER, .usUsage = HID_USAGE_DIGITIZER_TOUCH_SCREEN}; - UINT rawbuffer_count, rawbuffer_size; + UINT rawbuffer_count, rawbuffer_size, expect_flags, id, width, height; WCHAR device_path[MAX_PATH]; char rawbuffer[1024]; RAWINPUT *rawinput; @@ -1918,6 +1935,9 @@ static void test_hid_touch_screen(void) HWND hwnd; BOOL ret;
+ width = GetSystemMetrics( SM_CXVIRTUALSCREEN ); + height = GetSystemMetrics( SM_CYVIRTUALSCREEN ); + touchdown_event = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); ok( !!touchdown_event, "CreateSemaphoreW failed, error %lu\n", GetLastError() ); touchleave_event = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL ); @@ -1971,7 +1991,9 @@ static void test_hid_touch_screen(void)
/* a single touch is automatically released if we don't send continuous updates */
- pointer_enter_count = pointer_up_count = 0; + pointer_enter_count = pointer_up_count = pointer_count = 0; + memset( pointer_wparam, 0, sizeof(pointer_wparam) ); + memset( pointer_lparam, 0, sizeof(pointer_lparam) ); bus_send_hid_input( file, &desc, &touch_single, sizeof(touch_single) );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); @@ -1981,7 +2003,7 @@ static void test_hid_touch_screen(void) res = msg_wait_for_events( 1, &touchdown_event, 10 ); todo_wine ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); - res = msg_wait_for_events( 1, &touchleave_event, 100 ); + res = msg_wait_for_events( 1, &touchleave_event, 500 ); todo_wine ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); todo_wine @@ -1989,6 +2011,28 @@ static void test_hid_touch_screen(void) todo_wine ok( pointer_up_count == 1, "got pointer_up_count %u\n", pointer_up_count );
+ expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE | + POINTER_MESSAGE_FLAG_FIRSTBUTTON | POINTER_MESSAGE_FLAG_NEW | + POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_INCONTACT; + todo_wine + ok( HIWORD( pointer_wparam[0] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_wparam[0] ) > 0, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_lparam[0] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[0] ); + todo_wine + ok( HIWORD( pointer_lparam[0] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[0] ); + id = LOWORD( pointer_wparam[0] ); + + expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE; + todo_wine + ok( HIWORD( pointer_wparam[1] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[1] ); + ok( LOWORD( pointer_wparam[1] ) == id, "got wparam %#Ix\n", pointer_wparam[1] ); + todo_wine + ok( LOWORD( pointer_lparam[1] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[1] ); + todo_wine + ok( HIWORD( pointer_lparam[1] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[1] ); +
/* test that we receive HID rawinput type with the touchscreen */
@@ -2091,7 +2135,9 @@ static void test_hid_touch_screen(void)
/* now the touch is continuously updated */
- pointer_enter_count = pointer_up_count = 0; + pointer_enter_count = pointer_up_count = pointer_count = 0; + memset( pointer_wparam, 0, sizeof(pointer_wparam) ); + memset( pointer_lparam, 0, sizeof(pointer_lparam) ); bus_send_hid_input( file, &desc, &touch_single, sizeof(touch_single) );
res = msg_wait_for_events( 1, &touchdown_event, 1000 ); @@ -2103,8 +2149,25 @@ static void test_hid_touch_screen(void) ok( pointer_enter_count == 1, "got pointer_enter_count %u\n", pointer_enter_count ); ok( pointer_up_count == 0, "got pointer_up_count %u\n", pointer_up_count );
+ expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE | + POINTER_MESSAGE_FLAG_FIRSTBUTTON | POINTER_MESSAGE_FLAG_NEW | + POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_INCONTACT; + todo_wine + ok( HIWORD( pointer_wparam[0] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_wparam[0] ) > 0, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_lparam[0] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[0] ); + todo_wine + ok( HIWORD( pointer_lparam[0] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[0] ); + ok( pointer_wparam[1] == 0, "got wparam %#Ix\n", pointer_wparam[1] ); + ok( pointer_lparam[1] == 0, "got lparam %#Ix\n", pointer_lparam[1] ); + id = LOWORD( pointer_wparam[0] );
- pointer_enter_count = pointer_up_count = 0; + + pointer_enter_count = pointer_up_count = pointer_count = 0; + memset( pointer_wparam, 0, sizeof(pointer_wparam) ); + memset( pointer_lparam, 0, sizeof(pointer_lparam) ); bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) );
res = msg_wait_for_events( 1, &touchleave_event, 1000 ); @@ -2116,8 +2179,21 @@ static void test_hid_touch_screen(void) todo_wine ok( pointer_up_count == 1, "got pointer_up_count %u\n", pointer_up_count );
+ expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE; + todo_wine + ok( HIWORD( pointer_wparam[0] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[0] ); + ok( LOWORD( pointer_wparam[0] ) == id, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_lparam[0] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[0] ); + todo_wine + ok( HIWORD( pointer_lparam[0] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[0] ); + ok( pointer_wparam[1] == 0, "got wparam %#Ix\n", pointer_wparam[1] ); + ok( pointer_lparam[1] == 0, "got lparam %#Ix\n", pointer_lparam[1] ); +
- pointer_enter_count = pointer_up_count = 0; + pointer_enter_count = pointer_up_count = pointer_count = 0; + memset( pointer_wparam, 0, sizeof(pointer_wparam) ); + memset( pointer_lparam, 0, sizeof(pointer_lparam) ); bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) );
res = msg_wait_for_events( 1, &touchdown_event, 1000 ); @@ -2132,8 +2208,34 @@ static void test_hid_touch_screen(void) ok( pointer_enter_count == 2, "got pointer_enter_count %u\n", pointer_enter_count ); ok( pointer_up_count == 0, "got pointer_up_count %u\n", pointer_up_count );
+ expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE | + POINTER_MESSAGE_FLAG_FIRSTBUTTON | POINTER_MESSAGE_FLAG_NEW | + POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_INCONTACT; + todo_wine + ok( HIWORD( pointer_wparam[0] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_wparam[0] ) > 0, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_lparam[0] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[0] ); + todo_wine + ok( HIWORD( pointer_lparam[0] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[0] ); + id = LOWORD( pointer_wparam[0] ); + + expect_flags = POINTER_MESSAGE_FLAG_CONFIDENCE | POINTER_MESSAGE_FLAG_FIRSTBUTTON | + POINTER_MESSAGE_FLAG_NEW | POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_INCONTACT; + todo_wine + ok( HIWORD( pointer_wparam[1] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[1] ); + todo_wine + ok( LOWORD( pointer_wparam[1] ) == id + 1, "got wparam %#Ix\n", pointer_wparam[1] ); + todo_wine + ok( LOWORD( pointer_lparam[1] ) * 128 / width == 0x18, "got lparam %#Ix\n", pointer_lparam[1] ); + todo_wine + ok( HIWORD( pointer_lparam[1] ) * 128 / height == 0x20, "got lparam %#Ix\n", pointer_lparam[1] ); +
- pointer_enter_count = pointer_up_count = 0; + pointer_enter_count = pointer_up_count = pointer_count = 0; + memset( pointer_wparam, 0, sizeof(pointer_wparam) ); + memset( pointer_lparam, 0, sizeof(pointer_lparam) ); bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) );
res = msg_wait_for_events( 1, &touchleave_event, 1000 ); @@ -2148,6 +2250,25 @@ static void test_hid_touch_screen(void) todo_wine ok( pointer_up_count == 2, "got pointer_up_count %u\n", pointer_up_count );
+ expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE; + todo_wine + ok( HIWORD( pointer_wparam[0] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[0] ); + ok( LOWORD( pointer_wparam[0] ) == id, "got wparam %#Ix\n", pointer_wparam[0] ); + todo_wine + ok( LOWORD( pointer_lparam[0] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[0] ); + todo_wine + ok( HIWORD( pointer_lparam[0] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[0] ); + + expect_flags = POINTER_MESSAGE_FLAG_CONFIDENCE; + todo_wine + ok( HIWORD( pointer_wparam[1] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[1] ); + todo_wine + ok( LOWORD( pointer_wparam[1] ) == id + 1, "got wparam %#Ix\n", pointer_wparam[1] ); + todo_wine + ok( LOWORD( pointer_lparam[1] ) * 128 / width == 0x18, "got lparam %#Ix\n", pointer_lparam[1] ); + todo_wine + ok( HIWORD( pointer_lparam[1] ) * 128 / height == 0x20, "got lparam %#Ix\n", pointer_lparam[1] ); +
DestroyWindow( hwnd );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mouhid.sys/Makefile.in | 2 +- dlls/mouhid.sys/main.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/mouhid.sys/Makefile.in b/dlls/mouhid.sys/Makefile.in index 331486bc104..79bc38a92b4 100644 --- a/dlls/mouhid.sys/Makefile.in +++ b/dlls/mouhid.sys/Makefile.in @@ -1,5 +1,5 @@ MODULE = mouhid.sys -IMPORTS = ntoskrnl hidparse +IMPORTS = ntoskrnl hidparse win32u EXTRADLLFLAGS = -Wl,--subsystem,native
SOURCES = \ diff --git a/dlls/mouhid.sys/main.c b/dlls/mouhid.sys/main.c index c1b4288e1dd..b38299b0fb8 100644 --- a/dlls/mouhid.sys/main.c +++ b/dlls/mouhid.sys/main.c @@ -113,6 +113,8 @@ static NTSTATUS start_device_read( DEVICE_OBJECT *device )
static void add_contact( struct device *impl, struct list *old_contacts, ULONG id, LONG x, LONG y ) { + UINT flags = POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_INCONTACT | POINTER_MESSAGE_FLAG_CONFIDENCE; + INPUT input = {.type = INPUT_HARDWARE}; struct contact *contact;
LIST_FOR_EACH_ENTRY( contact, old_contacts, struct contact, entry ) @@ -120,6 +122,7 @@ static void add_contact( struct device *impl, struct list *old_contacts, ULONG i
if (&contact->entry != old_contacts) { + input.hi.uMsg = WM_POINTERUPDATE; list_remove( &contact->entry );
contact->pos.x = x; @@ -128,6 +131,9 @@ static void add_contact( struct device *impl, struct list *old_contacts, ULONG i } else if ((contact = calloc( 1, sizeof(*contact) ))) { + input.hi.uMsg = WM_POINTERDOWN; + flags |= POINTER_MESSAGE_FLAG_NEW; + contact->id = id; contact->pos.x = x; contact->pos.y = y; @@ -139,6 +145,10 @@ static void add_contact( struct device *impl, struct list *old_contacts, ULONG i return; }
+ input.hi.wParamL = contact->id; + input.hi.wParamH = flags; + NtUserSendHardwareInput( 0, 0, &input, MAKELPARAM(contact->pos.x, contact->pos.y) ); + list_add_tail( &impl->contacts, &contact->entry ); }
@@ -148,7 +158,16 @@ static void release_contacts( struct list *contacts )
LIST_FOR_EACH_ENTRY_SAFE( contact, next, contacts, struct contact, entry ) { + INPUT input = {.type = INPUT_HARDWARE}; + ULONG flags = POINTER_MESSAGE_FLAG_CONFIDENCE; + TRACE( "releasing contact %#lx, pos %s\n", contact->id, wine_dbgstr_point( &contact->pos ) ); + + input.hi.uMsg = WM_POINTERUP; + input.hi.wParamL = contact->id; + input.hi.wParamH = flags; + NtUserSendHardwareInput( 0, 0, &input, MAKELPARAM(contact->pos.x, contact->pos.y) ); + list_remove( &contact->entry ); free( contact ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 4 -- server/queue.c | 85 ++++++++++++++++++++++++++++++++++++- server/user.h | 2 + server/winstation.c | 2 + 4 files changed, 88 insertions(+), 5 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index e6b38ad6cce..5bcab668d6b 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -1997,7 +1997,6 @@ static void test_hid_touch_screen(void) bus_send_hid_input( file, &desc, &touch_single, sizeof(touch_single) );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); - todo_wine ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
res = msg_wait_for_events( 1, &touchdown_event, 10 ); @@ -2047,7 +2046,6 @@ static void test_hid_touch_screen(void) bus_wait_hid_input( file, &desc, 5000 );
res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); - todo_wine ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
memset( rawbuffer, 0, sizeof(rawbuffer) ); @@ -2086,11 +2084,9 @@ static void test_hid_touch_screen(void)
bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) ); res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); - todo_wine ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res ); bus_send_hid_input( file, &desc, &touch_release, sizeof(touch_release) ); res = MsgWaitForMultipleObjects( 0, NULL, FALSE, 500, QS_POINTER ); - todo_wine ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
rawinput = (RAWINPUT *)rawbuffer; diff --git a/server/queue.c b/server/queue.c index ef40d30aedf..0b9430c5f4d 100644 --- a/server/queue.c +++ b/server/queue.c @@ -633,6 +633,7 @@ static inline int filter_contains_hw_range( unsigned int first, unsigned int las /* get the QS_* bit corresponding to a given hardware message */ static inline int get_hardware_msg_bit( unsigned int message ) { + if (message >= WM_POINTERUPDATE && message <= WM_POINTERLEAVE) return QS_POINTER; if (message == WM_INPUT_DEVICE_CHANGE || message == WM_INPUT) return QS_RAWINPUT; if (message == WM_MOUSEMOVE || message == WM_NCMOUSEMOVE) return QS_MOUSEMOVE; if (message >= WM_KEYFIRST && message <= WM_KEYLAST) return QS_KEY; @@ -1614,6 +1615,7 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru *msg_code = msg->msg; switch (get_hardware_msg_bit( msg->msg )) { + case QS_POINTER: case QS_RAWINPUT: if (!(win = msg->win) && input) win = input->focus; break; @@ -2216,12 +2218,72 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c return wait; }
+struct pointer +{ + struct list entry; + struct desktop *desktop; + user_handle_t win; + int primary; + hw_input_t input; +}; + +static void queue_pointer_message( struct pointer *pointer ) +{ + struct hw_msg_source source = { IMDT_UNAVAILABLE, IMDT_TOUCH }; + struct desktop *desktop = pointer->desktop; + const hw_input_t *input = &pointer->input; + unsigned int wparam = input->hw.wparam; + user_handle_t win = pointer->win; + rectangle_t top_rect; + struct message *msg; + int x, y; + + get_top_window_rectangle( desktop, &top_rect ); + x = LOWORD(input->hw.lparam) * (top_rect.right - top_rect.left) / 65535; + y = HIWORD(input->hw.lparam) * (top_rect.bottom - top_rect.top) / 65535; + + if (pointer->primary) wparam |= POINTER_MESSAGE_FLAG_PRIMARY << 16; + + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return; + + msg->win = get_user_full_handle( win ); + msg->msg = input->hw.msg; + msg->wparam = wparam; + msg->lparam = MAKELONG(x, y); + msg->x = desktop->cursor.x; + msg->y = desktop->cursor.y; + + queue_hardware_message( desktop, msg, 1 ); + + if (input->hw.msg == WM_POINTERUP) + { + list_remove( &pointer->entry ); + free( pointer ); + } +} + +static struct pointer *find_pointer_from_id( struct desktop *desktop, unsigned int id ) +{ + struct pointer *pointer; + + LIST_FOR_EACH_ENTRY( pointer, &desktop->pointers, struct pointer, entry ) + if (LOWORD(pointer->input.hw.wparam) == id) return pointer; + + pointer = mem_alloc( sizeof(struct pointer) ); + pointer->desktop = desktop; + pointer->primary = list_empty( &desktop->pointers ); + list_add_tail( &desktop->pointers, &pointer->entry ); + + return pointer; +} + /* queue a hardware message for a custom type of event */ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_t win, unsigned int origin, const hw_input_t *input ) { struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; struct thread *foreground; + struct pointer *pointer; struct message *msg;
switch (input->hw.msg) @@ -2246,6 +2308,16 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ return; }
+ if (input->hw.msg == WM_POINTERDOWN || input->hw.msg == WM_POINTERUP || input->hw.msg == WM_POINTERUPDATE) + { + pointer = find_pointer_from_id( desktop, LOWORD(input->hw.wparam) ); + pointer->input = *input; + pointer->win = win; + + queue_pointer_message( pointer ); + return; + } + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->win = get_user_full_handle( win ); @@ -2394,7 +2466,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 ((get_hardware_msg_bit( msg->msg ) == QS_RAWINPUT && (flags & PM_REMOVE)) || + if ((get_hardware_msg_bit( msg->msg ) & (QS_RAWINPUT | QS_POINTER) && (flags & PM_REMOVE)) || is_internal_hardware_message( msg->msg )) release_hardware_message( current->queue, data->hw_id ); return 1; @@ -2572,6 +2644,17 @@ void post_win_event( struct thread *thread, unsigned int event, } }
+void free_pointers( struct desktop *desktop ) +{ + struct pointer *pointer, *next; + + LIST_FOR_EACH_ENTRY_SAFE( pointer, next, &desktop->pointers, struct pointer, entry ) + { + list_remove( &pointer->entry ); + free( pointer ); + } +} + /* free all hotkeys on a desktop, optionally filtering by window */ void free_hotkeys( struct desktop *desktop, user_handle_t window ) { diff --git a/server/user.h b/server/user.h index b4cf618f87e..309a0966104 100644 --- a/server/user.h +++ b/server/user.h @@ -75,6 +75,7 @@ struct desktop struct window *msg_window; /* HWND_MESSAGE top window */ struct hook_table *global_hooks; /* table of global hooks on this desktop */ struct list hotkeys; /* list of registered hotkeys */ + struct list pointers; /* list of active pointers */ struct timeout_user *close_timeout; /* timeout before closing the desktop */ struct thread_input *foreground_input; /* thread input of foreground thread */ unsigned int users; /* processes and threads using this desktop */ @@ -125,6 +126,7 @@ extern void post_win_event( struct thread *thread, unsigned int event, const WCHAR *module, data_size_t module_size, user_handle_t handle ); extern void free_hotkeys( struct desktop *desktop, user_handle_t window ); +extern void free_pointers( struct desktop *desktop ); extern void set_rawinput_process( struct process *process, int enable );
/* region functions */ diff --git a/server/winstation.c b/server/winstation.c index 373a1f7ba92..4672cf65e56 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -296,6 +296,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned memset( desktop->keystate, 0, sizeof(desktop->keystate) ); list_add_tail( &winstation->desktops, &desktop->entry ); list_init( &desktop->hotkeys ); + list_init( &desktop->pointers ); } else { @@ -357,6 +358,7 @@ static void desktop_destroy( struct object *obj ) }
free_hotkeys( desktop, 0 ); + free_pointers( desktop ); if (desktop->top_window) free_window_handle( desktop->top_window ); if (desktop->msg_window) free_window_handle( desktop->msg_window ); if (desktop->global_hooks) release_object( desktop->global_hooks );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/device8.c | 17 ++--------------- dlls/win32u/message.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index 5bcab668d6b..14098ec39c7 100644 --- a/dlls/dinput/tests/device8.c +++ b/dlls/dinput/tests/device8.c @@ -2000,7 +2000,6 @@ static void test_hid_touch_screen(void) ok( !res, "MsgWaitForMultipleObjects returned %#lx\n", res );
res = msg_wait_for_events( 1, &touchdown_event, 10 ); - todo_wine ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); res = msg_wait_for_events( 1, &touchleave_event, 500 ); todo_wine @@ -2137,7 +2136,6 @@ static void test_hid_touch_screen(void) bus_send_hid_input( file, &desc, &touch_single, sizeof(touch_single) );
res = msg_wait_for_events( 1, &touchdown_event, 1000 ); - todo_wine ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); res = msg_wait_for_events( 1, &touchleave_event, 10 ); ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); @@ -2172,16 +2170,13 @@ static void test_hid_touch_screen(void) res = msg_wait_for_events( 1, &touchdown_event, 10 ); ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); ok( pointer_enter_count == 0, "got pointer_enter_count %u\n", pointer_enter_count ); - todo_wine ok( pointer_up_count == 1, "got pointer_up_count %u\n", pointer_up_count );
expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE; - todo_wine ok( HIWORD( pointer_wparam[0] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[0] ); - ok( LOWORD( pointer_wparam[0] ) == id, "got wparam %#Ix\n", pointer_wparam[0] ); todo_wine + ok( LOWORD( pointer_wparam[0] ) == id, "got wparam %#Ix\n", pointer_wparam[0] ); ok( LOWORD( pointer_lparam[0] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[0] ); - todo_wine ok( HIWORD( pointer_lparam[0] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[0] ); ok( pointer_wparam[1] == 0, "got wparam %#Ix\n", pointer_wparam[1] ); ok( pointer_lparam[1] == 0, "got lparam %#Ix\n", pointer_lparam[1] ); @@ -2193,10 +2188,8 @@ static void test_hid_touch_screen(void) bus_send_hid_input( file, &desc, &touch_multiple, sizeof(touch_multiple) );
res = msg_wait_for_events( 1, &touchdown_event, 1000 ); - todo_wine ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); res = msg_wait_for_events( 1, &touchdown_event, 1000 ); - todo_wine ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); res = msg_wait_for_events( 1, &touchleave_event, 10 ); ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); @@ -2243,26 +2236,20 @@ static void test_hid_touch_screen(void) res = msg_wait_for_events( 1, &touchdown_event, 10 ); ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); ok( pointer_enter_count == 0, "got pointer_enter_count %u\n", pointer_enter_count ); - todo_wine ok( pointer_up_count == 2, "got pointer_up_count %u\n", pointer_up_count );
expect_flags = POINTER_MESSAGE_FLAG_PRIMARY | POINTER_MESSAGE_FLAG_CONFIDENCE; - todo_wine ok( HIWORD( pointer_wparam[0] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[0] ); - ok( LOWORD( pointer_wparam[0] ) == id, "got wparam %#Ix\n", pointer_wparam[0] ); todo_wine + ok( LOWORD( pointer_wparam[0] ) == id, "got wparam %#Ix\n", pointer_wparam[0] ); ok( LOWORD( pointer_lparam[0] ) * 128 / width == 0x08, "got lparam %#Ix\n", pointer_lparam[0] ); - todo_wine ok( HIWORD( pointer_lparam[0] ) * 128 / height == 0x10, "got lparam %#Ix\n", pointer_lparam[0] );
expect_flags = POINTER_MESSAGE_FLAG_CONFIDENCE; - todo_wine ok( HIWORD( pointer_wparam[1] ) == expect_flags, "got wparam %#Ix\n", pointer_wparam[1] ); todo_wine ok( LOWORD( pointer_wparam[1] ) == id + 1, "got wparam %#Ix\n", pointer_wparam[1] ); - todo_wine ok( LOWORD( pointer_lparam[1] ) * 128 / width == 0x18, "got lparam %#Ix\n", pointer_lparam[1] ); - todo_wine ok( HIWORD( pointer_lparam[1] ) * 128 / height == 0x20, "got lparam %#Ix\n", pointer_lparam[1] );
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index e8d456689b6..d3c4047b30a 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2319,6 +2319,16 @@ static void handle_keyboard_repeat_message( HWND hwnd ) NtUserPostMessage( hwnd, msg->message, msg->wParam, msg->lParam ); }
+/*********************************************************************** + * process_pointer_message + * + * returns TRUE if the contents of 'msg' should be passed to the application + */ +static BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) +{ + msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); + return TRUE; +}
/*********************************************************************** * process_keyboard_message @@ -2669,6 +2679,8 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar ret = process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove ); else if (is_mouse_message( msg->message )) ret = process_mouse_message( msg, hw_id, msg_data->info, hwnd_filter, first, last, remove ); + else if (msg->message >= WM_POINTERUPDATE && msg->message <= WM_POINTERLEAVE) + ret = process_pointer_message( msg, hw_id, msg_data ); else if (msg->message == WM_WINE_CLIPCURSOR) process_wine_clipcursor( msg->hwnd, msg->wParam, msg->lParam ); else if (msg->message == WM_WINE_SETCURSOR)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=143561
Your paranoid android.
=== w8 (32 bit report) ===
dinput: device8.c:2027: Test failed: got wparam 0x20000002 device8.c:2176: Test failed: got wparam 0x20000007 device8.c:2242: Test failed: got wparam 0x20000008 device8.c:2249: Test failed: got wparam 0x9
Anything wrong here? The test failures don't look related.
It's causing clang warnings here:
``` In file included from ../wine/dlls/ntoskrnl.exe/sync.c:27: In file included from ../wine/include/wine/server.h:28: ../wine/include/wine/server_protocol.h:2846:21: warning: field 'input' with variable sized type 'hw_input_t' not at the end of a struct or class is a GNU extension [-Wgnu-variable-sized-type-not-at-end] In file included from ../wine/dlls/ntoskrnl.exe/sync.c:27: ../wine/include/wine/server.h:46:7: warning: field 'u' with variable sized type 'union (unnamed union at ../wine/include/wine/server.h:42:5)' not at the end of a struct or class is a GNU extension [-Wgnu-variable-sized-type-not-at-end] ```
Ah, sorry. Would you prefer explicit padding in the hw_input_t union to move that field to the end or instead dropping the flexible array member and make it implicit?
Oh nvm, it's not going to work as it's part of the generic request structure. I guess I'll just drop that flexible array.