-- v3: 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. win32u: Use NtUserCallHwndParam interface for __wine_send_input.
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 | 18 ++++++++++++++- server/protocol.def | 9 ++------ server/queue.c | 2 +- 6 files changed, 54 insertions(+), 80 deletions(-)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 1b5233e84b6..e6b34077a77 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_packet *hid; + + size = offsetof( struct hid_packet, 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->head.device = ext->u.pdo.rawinput_handle; + hid->head.usage = MAKELONG(desc->Usage, desc->UsagePage); + + hid->head.count = 1; + hid->head.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..ddccffb91e2 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_packet 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.head.device = ext->u.pdo.rawinput_handle; + hid.head.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..79390a7fdc5 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_packet *hid = (struct hid_packet *)lparam; + req->input.hw.hid = hid->head; + wine_server_add_data( req, hid->data, hid->head.count * hid->head.length ); + break; } + default: + req->input.hw.lparam = lparam; + break; } break; } diff --git a/include/ntuser.h b/include/ntuser.h index eb8c95ac8b4..a048aebbb2a 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1407,11 +1407,27 @@ 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; +}; + +struct hid_packet +{ + struct hid_input head; + BYTE data[]; +}; + +C_ASSERT(sizeof(struct hid_packet) == offsetof(struct hid_packet, data[0])); + struct send_hardware_input_params { UINT flags; const INPUT *input; - LPARAM lparam; /* RAWINPUT pointer for WM_INPUT* messages */ + LPARAM lparam; /* struct hid_packet 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 | 151 +++++++++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 10 deletions(-)
diff --git a/dlls/dinput/tests/device8.c b/dlls/dinput/tests/device8.c index 2c44bb4c5c6..caf85fc370f 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,30 @@ 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 || + broken(HIWORD( pointer_wparam[1] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ + "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 +2137,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 +2151,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 +2181,23 @@ 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 || + broken(HIWORD( pointer_wparam[0] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ + "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 +2212,36 @@ 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 || + broken(HIWORD( pointer_wparam[1] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ + "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 +2256,29 @@ 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 || + broken(HIWORD( pointer_wparam[0] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ + "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 || + broken(HIWORD( pointer_wparam[1] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ + "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 caf85fc370f..41e560a7e62 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 ); @@ -2049,7 +2048,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) ); @@ -2088,11 +2086,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 41e560a7e62..8b2a72f5976 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 @@ -2139,7 +2138,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 ); @@ -2174,18 +2172,15 @@ 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 || broken(HIWORD( pointer_wparam[0] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ "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] ); @@ -2197,10 +2192,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 ); @@ -2249,30 +2242,24 @@ 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 || broken(HIWORD( pointer_wparam[0] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ "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 || broken(HIWORD( pointer_wparam[1] ) == (expect_flags & ~POINTER_MESSAGE_FLAG_CONFIDENCE)), /* Win8 32bit */ "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 79390a7fdc5..f7f751ef883 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)
v3: Avoid using a flexible array member inside the server hw_input_t structure. Add a couple of broken results for Win8.