From: navi <navi@vlhl.dev> --- dlls/mouhid.sys/main.c | 14 ++++++++------ dlls/win32u/input.c | 14 ++++++++++++++ dlls/win32u/message.c | 4 ++++ dlls/win32u/win32u_private.h | 1 + dlls/winex11.drv/mouse.c | 36 +++++++++++++++++++++++++++++++++++- include/ntuser.h | 1 + server/protocol.def | 5 +++++ server/queue.c | 8 ++++++++ 8 files changed, 76 insertions(+), 7 deletions(-) diff --git a/dlls/mouhid.sys/main.c b/dlls/mouhid.sys/main.c index 0ed4d5c0344..23e731ae674 100644 --- a/dlls/mouhid.sys/main.c +++ b/dlls/mouhid.sys/main.c @@ -40,7 +40,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(hid); struct contact { struct list entry; - ULONG id; + UINT id; + ULONG hid_id; POINT pos; }; @@ -118,7 +119,7 @@ static void add_contact( struct device *impl, struct list *old_contacts, ULONG i struct contact *contact; LIST_FOR_EACH_ENTRY( contact, old_contacts, struct contact, entry ) - if (contact->id == id) break; + if (contact->hid_id == id) break; if (&contact->entry != old_contacts) { @@ -127,17 +128,18 @@ static void add_contact( struct device *impl, struct list *old_contacts, ULONG i contact->pos.x = x; contact->pos.y = y; - TRACE( "updating contact %#lx, pos %s\n", contact->id, wine_dbgstr_point( &contact->pos ) ); + TRACE( "updating contact %#lx, pos %s\n", contact->hid_id, wine_dbgstr_point( &contact->pos ) ); } else if ((contact = calloc( 1, sizeof(*contact) ))) { msg = WM_POINTERDOWN; flags |= POINTER_MESSAGE_FLAG_NEW; - contact->id = id; + NtUserMessageCall(0, 0, 0, 0, &contact->id, NtUserAllocatePointer, FALSE); + contact->hid_id = id; contact->pos.x = x; contact->pos.y = y; - TRACE( "new contact %#lx, pos %s\n", contact->id, wine_dbgstr_point( &contact->pos ) ); + TRACE( "new contact %#lx, pos %s\n", contact->hid_id, wine_dbgstr_point( &contact->pos ) ); } else { @@ -165,7 +167,7 @@ static void release_contacts( struct list *contacts ) ULONG flags = POINTER_MESSAGE_FLAG_CONFIDENCE; POINTER_INFO *info = &pointer.pointerInfo; - TRACE( "releasing contact %#lx, pos %s\n", contact->id, wine_dbgstr_point( &contact->pos ) ); + TRACE( "releasing contact %#lx, pos %s\n", contact->hid_id, wine_dbgstr_point( &contact->pos ) ); info->pointerId = contact->id; info->pointerFlags = flags; diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 3b9d5e05db7..2640fce0bf7 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2969,6 +2969,20 @@ static struct pointer *pointer_create( UINT32 id, POINTER_INPUT_TYPE type ) return pointer; } +W32KAPI UINT allocate_pointer_id( void ) +{ + UINT pointerid; + + SERVER_START_REQ( allocate_pointer_id ) + { + wine_server_call( req ); + pointerid = reply->id; + } + SERVER_END_REQ; + + return pointerid; +} + static struct pointer *find_pointer( UINT32 id ) { struct user_thread_info *thread_info = get_user_thread_info(); diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index e56fcf28ac7..21e15637ede 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -4821,6 +4821,10 @@ LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa case NtUserInjectPointer: return send_pointer_message( msg, result_info ); + case NtUserAllocatePointer: + *(UINT *)result_info = allocate_pointer_id(); + return 0; + default: FIXME( "%p %x %lx %lx %p %x %x\n", hwnd, msg, (long)wparam, lparam, result_info, type, ansi ); } diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 69693f98f0a..c6288a3c2f9 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -114,6 +114,7 @@ extern USHORT map_scan_to_kbd_vkey( USHORT scan, HKL layout, UINT *mapped ); extern void destroy_thread_pointers(void); extern BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ); extern NTSTATUS send_pointer_message( UINT msg, const POINTER_TYPE_INFO *info ); +extern UINT allocate_pointer_id( void ); extern void update_pointer_from_msg( POINTER_INPUT_TYPE type, const MSG *msg ); extern NTSTATUS send_hardware_input( HWND hwnd, UINT flags, const INPUT *input, LPARAM lparam ); diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 62cbc983931..742f60eb315 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -121,6 +121,14 @@ static const UINT button_up_data[NB_BUTTONS] = XContext cursor_context = 0; +struct pointer +{ + UINT detail, id; + struct list entry; +}; + +static struct list pointers = LIST_INIT( pointers ); + static RECT clip_rect; static Cursor create_cursor( HANDLE handle ); @@ -1672,6 +1680,24 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) return TRUE; } +static struct pointer *pointer_get(UINT detail) +{ + struct pointer *pointer; + + LIST_FOR_EACH_ENTRY( pointer, &pointers, struct pointer, entry ) + if (pointer->detail == detail) + return pointer; + + if (!(pointer = calloc( 1, sizeof( *pointer )))) + return NULL; + + pointer->detail = detail; + NtUserMessageCall(0, 0, 0, 0, &pointer->id, NtUserAllocatePointer, FALSE); + list_add_tail( &pointers, &pointer->entry ); + + return pointer; +} + static BOOL X11DRV_TouchEvent( HWND hwnd, XGenericEventCookie *xev ) { RECT virtual = NtUserGetVirtualScreenRect( MDT_RAW_DPI ); @@ -1679,14 +1705,20 @@ static BOOL X11DRV_TouchEvent( HWND hwnd, XGenericEventCookie *xev ) POINTER_INFO *info = &pointer_info.pointerInfo; XIDeviceEvent *event = xev->data; POINT pt = { event->event_x, event->event_y }, root = { event->root_x, event->root_y }; + struct pointer *pointer; POINT pos; + UINT id; + + if (!(pointer = pointer_get(event->detail))) + return FALSE; pt = map_event_coords( hwnd, event->event, event->root, root, pt ); pos.x = pt.x * 65535 / (virtual.right - virtual.left); pos.y = pt.y * 65535 / (virtual.bottom - virtual.top); + id = pointer->id; info->ptPixelLocation = pos; - info->pointerId = event->detail; + info->pointerId = id; info->pointerFlags = POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT; switch (event->evtype) @@ -1703,6 +1735,8 @@ static BOOL X11DRV_TouchEvent( HWND hwnd, XGenericEventCookie *xev ) NtUserMessageCall( hwnd, WM_POINTERUP, 0, 0, &pointer_info, NtUserInjectPointer, FALSE ); NtUserMessageCall( hwnd, WM_POINTERLEAVE, 0, 0, &pointer_info, NtUserInjectPointer, FALSE ); + list_remove( &pointer->entry ); + free( pointer ); break; case XI_TouchUpdate: TRACE("XI_TouchUpdate detail %u pos %dx%d, flags %#x\n", event->detail, pos.x, pos.y, info->pointerFlags); diff --git a/include/ntuser.h b/include/ntuser.h index 45153724d27..f3c16befbbb 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -418,6 +418,7 @@ enum NtUserPostDdeCall = 0x0308, NtUserWintabDriverCall = 0x0309, NtUserInjectPointer = 0x030a, + NtUserAllocatePointer = 0x030b, }; /* NtUserWintabDriverCall codes */ diff --git a/server/protocol.def b/server/protocol.def index 63c2a9f65c8..a20b7058e67 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2441,6 +2441,11 @@ enum message_type VARARG(data,bytes); @END +@REQ(allocate_pointer_id) +@REPLY + unsigned int id; +@END + /* Get a message from the current queue */ @REQ(get_message) unsigned int flags; /* PM_* flags */ diff --git a/server/queue.c b/server/queue.c index 928f78ba5c1..d150a9cdb04 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2467,6 +2467,9 @@ struct pointer }; static unsigned int pointer_frame = 1; +/* pointer id 1 is always hardcoded to PT_MOUSE */ +static unsigned int last_pointer_id = 2; + static void queue_pointer_message( UINT message, struct pointer *pointer, int repeated ); static void pointer_message_timeout( void *private ) @@ -3248,6 +3251,11 @@ DECL_HANDLER(send_pointer_message) return; } +DECL_HANDLER(allocate_pointer_id) +{ + reply->id = last_pointer_id++; +} + /* post a quit message to the current queue */ DECL_HANDLER(post_quit_message) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11693