[PATCH v14 0/11] MR10649: win32u: Initial implementation for GetPointer{,Frame}Info{,History} and GetPointerDeviceRects
-- v14: win32u: Implement NtUserGetPointerInfoList. win32u: Update pointerid 1 from mouse_in_pointer events. win32u: Implement NtUserGetPointerType. win32u: Keep track of pointer types. win32u: Preallocate pointerId 1 for the mouse pointer. win32u: Keep per-thread list of known pointers. win32u: Move process_pointer_message to input.c. win32u: Implement NtUserGetPointerDeviceRects for INVALID_HANDLE_VALUE. win32u: Add NtUserGetPointerDeviceRects test for INVALID_HANDLE_VALUE. https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/win32u/input.c | 10 ++++++++++ dlls/win32u/main.c | 5 +++++ dlls/win32u/win32syscalls.h | 5 ++--- dlls/win32u/win32u.spec | 2 +- dlls/wow64win/user.c | 8 ++++++++ include/ntuser.h | 1 + 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index ab09c3b7d42..16f9b33ebe5 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2852,3 +2852,13 @@ INT WINAPI NtUserScheduleDispatchNotification( HWND hwnd ) return 0; } + +/********************************************************************** + * NtUserGetPointerType (win32u.@) + */ +BOOL WINAPI NtUserGetPointerType(UINT32 id, POINTER_INPUT_TYPE *type) +{ + FIXME( "(%u, %p) stub!\n", id, type ); + RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; +} diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index 73a6ae32448..80f309474f3 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -1743,6 +1743,11 @@ BOOL SYSCALL_API NtUserGetPointerInfoList( UINT32 id, POINTER_INPUT_TYPE type, U SYSCALL_FUNC( NtUserGetPointerInfoList ); } +BOOL SYSCALL_API NtUserGetPointerType( UINT32 id, POINTER_INPUT_TYPE *type ) +{ + SYSCALL_FUNC( NtUserGetPointerType ); +} + INT SYSCALL_API NtUserGetPriorityClipboardFormat( UINT *list, INT count ) { SYSCALL_FUNC( NtUserGetPriorityClipboardFormat ); diff --git a/dlls/win32u/win32syscalls.h b/dlls/win32u/win32syscalls.h index aa0ceec4072..36e7d5ff116 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -1074,7 +1074,7 @@ SYSCALL_ENTRY( 0x142e, NtUserGetPointerInfoList, 32 ) \ SYSCALL_ENTRY( 0x142f, NtUserGetPointerInputTransform, 0 ) \ SYSCALL_ENTRY( 0x1430, NtUserGetPointerProprietaryId, 0 ) \ - SYSCALL_ENTRY( 0x1431, NtUserGetPointerType, 0 ) \ + SYSCALL_ENTRY( 0x1431, NtUserGetPointerType, 8 ) \ SYSCALL_ENTRY( 0x1432, NtUserGetPrecisionTouchPadConfiguration, 0 ) \ SYSCALL_ENTRY( 0x1433, NtUserGetPriorityClipboardFormat, 8 ) \ SYSCALL_ENTRY( 0x1434, NtUserGetProcessDefaultLayout, 4 ) \ @@ -2616,7 +2616,7 @@ SYSCALL_ENTRY( 0x142e, NtUserGetPointerInfoList, 64 ) \ SYSCALL_ENTRY( 0x142f, NtUserGetPointerInputTransform, 0 ) \ SYSCALL_ENTRY( 0x1430, NtUserGetPointerProprietaryId, 0 ) \ - SYSCALL_ENTRY( 0x1431, NtUserGetPointerType, 0 ) \ + SYSCALL_ENTRY( 0x1431, NtUserGetPointerType, 16 ) \ SYSCALL_ENTRY( 0x1432, NtUserGetPrecisionTouchPadConfiguration, 0 ) \ SYSCALL_ENTRY( 0x1433, NtUserGetPriorityClipboardFormat, 16 ) \ SYSCALL_ENTRY( 0x1434, NtUserGetProcessDefaultLayout, 8 ) \ @@ -3837,7 +3837,6 @@ SYSCALL_STUB( NtUserGetPointerFrameTimes ) \ SYSCALL_STUB( NtUserGetPointerInputTransform ) \ SYSCALL_STUB( NtUserGetPointerProprietaryId ) \ - SYSCALL_STUB( NtUserGetPointerType ) \ SYSCALL_STUB( NtUserGetPrecisionTouchPadConfiguration ) \ SYSCALL_STUB( NtUserGetProcessUIContextInformation ) \ SYSCALL_STUB( NtUserGetProp2 ) \ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 2f657aa854e..965264c8ef6 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1072,7 +1072,7 @@ @ stdcall -syscall NtUserGetPointerInfoList(long long long long long ptr ptr ptr) @ stub -syscall NtUserGetPointerInputTransform @ stub -syscall NtUserGetPointerProprietaryId -@ stub -syscall NtUserGetPointerType +@ stdcall -syscall NtUserGetPointerType(long ptr) @ stub -syscall NtUserGetPrecisionTouchPadConfiguration @ stdcall -syscall NtUserGetPriorityClipboardFormat(ptr long) @ stdcall -syscall NtUserGetProcessDefaultLayout(ptr) diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 0a570d79ff7..ec5f8b6bbd9 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -2853,6 +2853,14 @@ NTSTATUS WINAPI wow64_NtUserGetPointerInfoList( UINT *args ) return NtUserGetPointerInfoList( id, type, unk0, unk1, size, entry_count, pointer_count, pointer_info ); } +NTSTATUS WINAPI wow64_NtUserGetPointerType( UINT *args ) +{ + UINT id = get_ulong( &args ); + POINTER_INPUT_TYPE *type = get_ptr( &args ); + + return NtUserGetPointerType( id, type ); +} + NTSTATUS WINAPI wow64_NtUserGetPriorityClipboardFormat( UINT *args ) { UINT *list = get_ptr( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index 939771c9121..a73066ba29b 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -894,6 +894,7 @@ W32KAPI BOOL WINAPI NtUserGetObjectInformation( HANDLE handle, INT index, voi W32KAPI HWND WINAPI NtUserGetOpenClipboardWindow(void); W32KAPI BOOL WINAPI NtUserGetPointerInfoList( UINT32 id, POINTER_INPUT_TYPE type, UINT_PTR, UINT_PTR, SIZE_T size, UINT32 *entry_count, UINT32 *pointer_count, void *pointer_info ); +W32KAPI BOOL WINAPI NtUserGetPointerType( UINT32 id, POINTER_INPUT_TYPE *type ); W32KAPI INT WINAPI NtUserGetPriorityClipboardFormat( UINT *list, INT count ); W32KAPI BOOL WINAPI NtUserGetProcessDefaultLayout( ULONG *layout ); W32KAPI ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/win32u/input.c | 10 ++++++++++ dlls/win32u/main.c | 5 +++++ dlls/win32u/win32syscalls.h | 5 ++--- dlls/win32u/win32u.spec | 2 +- dlls/wow64win/user.c | 9 +++++++++ include/ntuser.h | 1 + 6 files changed, 28 insertions(+), 4 deletions(-) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 16f9b33ebe5..3ed2ca3a3e1 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2862,3 +2862,13 @@ BOOL WINAPI NtUserGetPointerType(UINT32 id, POINTER_INPUT_TYPE *type) RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); return FALSE; } + +/********************************************************************** + * NtUserGetPointerDeviceRects (win32u.@) + */ +BOOL WINAPI NtUserGetPointerDeviceRects( HANDLE handle, RECT *pointerDeviceRect, RECT *displayRect ) +{ + FIXME( "(%p, %p, %p) stub!\n", handle, pointerDeviceRect, displayRect ); + RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; +} diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index 80f309474f3..08e7c87314d 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -1748,6 +1748,11 @@ BOOL SYSCALL_API NtUserGetPointerType( UINT32 id, POINTER_INPUT_TYPE *type ) SYSCALL_FUNC( NtUserGetPointerType ); } +BOOL SYSCALL_API NtUserGetPointerDeviceRects( HANDLE handle, RECT *pointerDeviceRect, RECT *displayRect ) +{ + SYSCALL_FUNC( NtUserGetPointerDeviceRects ); +} + INT SYSCALL_API NtUserGetPriorityClipboardFormat( UINT *list, INT count ) { SYSCALL_FUNC( NtUserGetPriorityClipboardFormat ); diff --git a/dlls/win32u/win32syscalls.h b/dlls/win32u/win32syscalls.h index 36e7d5ff116..b298d8d4bc9 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -1068,7 +1068,7 @@ SYSCALL_ENTRY( 0x1428, NtUserGetPointerDeviceInputSpace, 0 ) \ SYSCALL_ENTRY( 0x1429, NtUserGetPointerDeviceOrientation, 0 ) \ SYSCALL_ENTRY( 0x142a, NtUserGetPointerDeviceProperties, 0 ) \ - SYSCALL_ENTRY( 0x142b, NtUserGetPointerDeviceRects, 0 ) \ + SYSCALL_ENTRY( 0x142b, NtUserGetPointerDeviceRects, 12 ) \ SYSCALL_ENTRY( 0x142c, NtUserGetPointerDevices, 0 ) \ SYSCALL_ENTRY( 0x142d, NtUserGetPointerFrameTimes, 0 ) \ SYSCALL_ENTRY( 0x142e, NtUserGetPointerInfoList, 32 ) \ @@ -2610,7 +2610,7 @@ SYSCALL_ENTRY( 0x1428, NtUserGetPointerDeviceInputSpace, 0 ) \ SYSCALL_ENTRY( 0x1429, NtUserGetPointerDeviceOrientation, 0 ) \ SYSCALL_ENTRY( 0x142a, NtUserGetPointerDeviceProperties, 0 ) \ - SYSCALL_ENTRY( 0x142b, NtUserGetPointerDeviceRects, 0 ) \ + SYSCALL_ENTRY( 0x142b, NtUserGetPointerDeviceRects, 24 ) \ SYSCALL_ENTRY( 0x142c, NtUserGetPointerDevices, 0 ) \ SYSCALL_ENTRY( 0x142d, NtUserGetPointerFrameTimes, 0 ) \ SYSCALL_ENTRY( 0x142e, NtUserGetPointerInfoList, 64 ) \ @@ -3832,7 +3832,6 @@ SYSCALL_STUB( NtUserGetPointerDeviceInputSpace ) \ SYSCALL_STUB( NtUserGetPointerDeviceOrientation ) \ SYSCALL_STUB( NtUserGetPointerDeviceProperties ) \ - SYSCALL_STUB( NtUserGetPointerDeviceRects ) \ SYSCALL_STUB( NtUserGetPointerDevices ) \ SYSCALL_STUB( NtUserGetPointerFrameTimes ) \ SYSCALL_STUB( NtUserGetPointerInputTransform ) \ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 965264c8ef6..4979bf8dd53 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1066,7 +1066,7 @@ @ stub -syscall NtUserGetPointerDeviceInputSpace @ stub -syscall NtUserGetPointerDeviceOrientation @ stub -syscall NtUserGetPointerDeviceProperties -@ stub -syscall NtUserGetPointerDeviceRects +@ stdcall -syscall NtUserGetPointerDeviceRects(long ptr ptr) @ stub -syscall NtUserGetPointerDevices @ stub -syscall NtUserGetPointerFrameTimes @ stdcall -syscall NtUserGetPointerInfoList(long long long long long ptr ptr ptr) diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index ec5f8b6bbd9..a25aa76c44b 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -2861,6 +2861,15 @@ NTSTATUS WINAPI wow64_NtUserGetPointerType( UINT *args ) return NtUserGetPointerType( id, type ); } +NTSTATUS WINAPI wow64_NtUserGetPointerDeviceRects( UINT *args ) +{ + HANDLE device = get_handle( &args ); + RECT *device_rect = get_ptr( &args ); + RECT *display_rect = get_ptr( &args ); + + return NtUserGetPointerDeviceRects(device, device_rect, display_rect); +} + NTSTATUS WINAPI wow64_NtUserGetPriorityClipboardFormat( UINT *args ) { UINT *list = get_ptr( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index a73066ba29b..aef22700926 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -895,6 +895,7 @@ W32KAPI HWND WINAPI NtUserGetOpenClipboardWindow(void); W32KAPI BOOL WINAPI NtUserGetPointerInfoList( UINT32 id, POINTER_INPUT_TYPE type, UINT_PTR, UINT_PTR, SIZE_T size, UINT32 *entry_count, UINT32 *pointer_count, void *pointer_info ); W32KAPI BOOL WINAPI NtUserGetPointerType( UINT32 id, POINTER_INPUT_TYPE *type ); +W32KAPI BOOL WINAPI NtUserGetPointerDeviceRects( HANDLE handle, RECT *pointerDeviceRect, RECT *displayRect ); W32KAPI INT WINAPI NtUserGetPriorityClipboardFormat( UINT *list, INT count ); W32KAPI BOOL WINAPI NtUserGetProcessDefaultLayout( ULONG *layout ); W32KAPI ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/win32u/tests/win32u.c | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 19c05a97835..07c94fc9b67 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -2949,6 +2949,62 @@ static void test_NtUserRegisterWindowMessage(void) ok( !wcscmp( buf, L"#0xabc" ), "buf = %s\n", debugstr_w(buf) ); } +static BOOL CALLBACK get_virtual_screen_proc( HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM lp ) +{ + RECT *virtual_rect = (RECT *)lp; + UnionRect( virtual_rect, virtual_rect, rect ); + return TRUE; +} + +static RECT get_virtual_screen_rect(void) +{ + RECT rect = {0}; + EnumDisplayMonitors( 0, NULL, get_virtual_screen_proc, (LPARAM)&rect ); + return rect; +} + +void test_NtUserGetPointerDeviceRects( const char *arg ) +{ + RECT screen, himetric_dev = {0}, device = {0}, display = {0}; + DPI_AWARENESS_CONTEXT ctx = 0; + const UINT himetric = 2540; + UINT ret, dpi; + + if (!strcmp( arg, "unaware" )) + ctx = DPI_AWARENESS_CONTEXT_UNAWARE; + else if (!strcmp( arg, "system" )) + ctx = DPI_AWARENESS_CONTEXT_SYSTEM_AWARE; + else if (!strcmp( arg, "monitor" )) + ctx = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE; + + if (ctx) + { + ret = SetProcessDpiAwarenessContext( ctx ); + ok( ret, "SetProcessDpiAwarenessContext failed, error %lu.\n", GetLastError() ); + } + + screen = get_virtual_screen_rect(); + + /* operating on unaware scaled values returns wrong values */ + ctx = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ); + + dpi = GetDpiForSystem(); + himetric_dev.right = GetSystemMetrics( SM_CXVIRTUALSCREEN ) * himetric / dpi; + himetric_dev.bottom = GetSystemMetrics( SM_CYVIRTUALSCREEN ) * himetric / dpi; + + SetThreadDpiAwarenessContext(ctx); + + ret = NtUserGetPointerDeviceRects( INVALID_HANDLE_VALUE, &device, &display ); + todo_wine + { + ok( ret, "NtUserGetPointerDeviceRects failed, error %lu.\n", GetLastError() ); + ok( EqualRect( &device, &himetric_dev ), "device %s, expected %s\n", + wine_dbgstr_rect( &device ), wine_dbgstr_rect( &himetric_dev ) ); + ok( EqualRect( &display, &screen ), "display %s, expected %s\n", + wine_dbgstr_rect( &display ), wine_dbgstr_rect( &screen ) ); + } +} + START_TEST(win32u) { char **argv; @@ -2978,6 +3034,14 @@ START_TEST(win32u) return; } + if (argc > 3 && !strcmp( argv[2], "NtUserGetPointerDeviceRects" )) + { + winetest_push_context( "dpi context %s", argv[3] ); + test_NtUserGetPointerDeviceRects( argv[3] ); + winetest_pop_context(); + return; + } + test_NtUserEnumDisplayDevices(); test_window_props(); test_class(); @@ -3004,6 +3068,10 @@ START_TEST(win32u) run_in_process( argv, "NtUserEnableMouseInPointer 0" ); run_in_process( argv, "NtUserEnableMouseInPointer 1" ); + run_in_process( argv, "NtUserGetPointerDeviceRects unaware" ); + run_in_process( argv, "NtUserGetPointerDeviceRects system" ); + run_in_process( argv, "NtUserGetPointerDeviceRects monitor" ); + run_in_process( argv, "NtUserSetProcessDpiAwarenessContext 0x6010" ); run_in_process( argv, "NtUserSetProcessDpiAwarenessContext 0x11" ); run_in_process( argv, "NtUserSetProcessDpiAwarenessContext 0x12" ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/user32/input.c | 8 -------- dlls/user32/user32.spec | 2 +- dlls/win32u/input.c | 27 ++++++++++++++++++++++++--- dlls/win32u/tests/win32u.c | 13 +++++-------- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 48b38166b75..623fab14d11 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -750,14 +750,6 @@ BOOL WINAPI GetPointerDeviceProperties( HANDLE device, UINT32 *count, return FALSE; } -BOOL WINAPI GetPointerDeviceRects( HANDLE device, RECT *device_rect, RECT *display_rect ) -{ - FIXME( "device %p, device_rect %p, display_rect %p stub!\n", - device, device_rect, display_rect ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; -} - BOOL WINAPI GetPointerPenInfo( UINT32 id, POINTER_PEN_INFO *info ) { FIXME( "id %u, info %p stub!\n", id, info ); diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index b8939646668..80dfa388dd8 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -630,7 +630,7 @@ # @ stub GetPointerDeviceInputSpace # @ stub GetPointerDeviceOrientation @ stdcall GetPointerDeviceProperties(ptr ptr ptr) -@ stdcall GetPointerDeviceRects(ptr ptr ptr) +@ stdcall GetPointerDeviceRects(ptr ptr ptr) NtUserGetPointerDeviceRects @ stdcall GetPointerDevices(ptr ptr) # @ stub GetPointerFrameInfo # @ stub GetPointerFrameInfoHistory diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 3ed2ca3a3e1..3907cc4699d 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -40,6 +40,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); WINE_DECLARE_DEBUG_CHANNEL(keyboard); +#define HIMETRIC 2540 + static const WCHAR keyboard_layouts_keyW[] = { '\\','R','e','g','i','s','t','r','y', @@ -2868,7 +2870,26 @@ BOOL WINAPI NtUserGetPointerType(UINT32 id, POINTER_INPUT_TYPE *type) */ BOOL WINAPI NtUserGetPointerDeviceRects( HANDLE handle, RECT *pointerDeviceRect, RECT *displayRect ) { - FIXME( "(%p, %p, %p) stub!\n", handle, pointerDeviceRect, displayRect ); - RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + UINT ctx, dpi; + + TRACE( "%p, %p, %p\n", handle, pointerDeviceRect, displayRect ); + + if (handle != INVALID_HANDLE_VALUE) + { + FIXME( "Pointer devices are not implemented!\n" ); + RtlSetLastWin32Error( ERROR_NO_DATA ); + return FALSE; + } + + *displayRect = get_virtual_screen_rect( get_thread_dpi(), MDT_RAW_DPI ); + + ctx = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); + + dpi = get_system_dpi(); + pointerDeviceRect->right = get_system_metrics( SM_CXVIRTUALSCREEN ) * HIMETRIC / dpi; + pointerDeviceRect->bottom = get_system_metrics( SM_CYVIRTUALSCREEN ) * HIMETRIC / dpi; + + set_thread_dpi_awareness_context(ctx); + + return TRUE; } diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 07c94fc9b67..4c928f88fc1 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -2995,14 +2995,11 @@ void test_NtUserGetPointerDeviceRects( const char *arg ) SetThreadDpiAwarenessContext(ctx); ret = NtUserGetPointerDeviceRects( INVALID_HANDLE_VALUE, &device, &display ); - todo_wine - { - ok( ret, "NtUserGetPointerDeviceRects failed, error %lu.\n", GetLastError() ); - ok( EqualRect( &device, &himetric_dev ), "device %s, expected %s\n", - wine_dbgstr_rect( &device ), wine_dbgstr_rect( &himetric_dev ) ); - ok( EqualRect( &display, &screen ), "display %s, expected %s\n", - wine_dbgstr_rect( &display ), wine_dbgstr_rect( &screen ) ); - } + ok( ret, "NtUserGetPointerDeviceRects failed, error %lu.\n", GetLastError() ); + ok( EqualRect( &device, &himetric_dev ), "device %s, expected %s\n", + wine_dbgstr_rect( &device ), wine_dbgstr_rect( &himetric_dev ) ); + ok( EqualRect( &display, &screen ), "display %s, expected %s\n", + wine_dbgstr_rect( &display ), wine_dbgstr_rect( &screen ) ); } START_TEST(win32u) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/win32u/input.c | 11 +++++++++++ dlls/win32u/message.c | 11 ----------- dlls/win32u/win32u_private.h | 1 + 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 3907cc4699d..b194b34ce46 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2855,6 +2855,17 @@ INT WINAPI NtUserScheduleDispatchNotification( HWND hwnd ) return 0; } +/*********************************************************************** + * process_pointer_message + g* + * returns TRUE if the contents of 'msg' should be passed to the application + */ +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; +} + /********************************************************************** * NtUserGetPointerType (win32u.@) */ diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index fe0cd2a61fe..62115515fb2 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2456,17 +2456,6 @@ static void send_parent_notify( HWND hwnd, WORD event, WORD idChild, POINT pt ) } } -/*********************************************************************** - * 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 * diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index cab58dfd499..d68cba0dc50 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -110,6 +110,7 @@ extern void update_current_mouse_window( HWND hwnd, INT hittest, POINT pos ); extern BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset ); extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ); extern USHORT map_scan_to_kbd_vkey( USHORT scan, HKL layout ); +extern BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ); /* menu.c */ extern UINT draw_nc_menu_bar( HDC hdc, RECT *rect, HWND hwnd ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/win32u/input.c | 106 +++++++++++++++++++++++++++++++++++ dlls/win32u/ntuser_private.h | 1 + 2 files changed, 107 insertions(+) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index b194b34ce46..0408e15a031 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -407,6 +407,19 @@ static const KBDTABLES kbdus_tables = static LONG clipping_cursor; /* clipping thread counter */ static LONG enable_mouse_in_pointer = -1; +static LONG last_frame = 0; + +struct pointer +{ + UINT32 id; + struct list entry; + POINTER_INFO info; +}; + +struct pointer_thread_data +{ + struct list known_pointers; +}; BOOL grab_pointer = TRUE; BOOL grab_fullscreen = FALSE; @@ -2855,6 +2868,91 @@ INT WINAPI NtUserScheduleDispatchNotification( HWND hwnd ) return 0; } +static struct pointer_thread_data *get_pointer_thread_data(void) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + if (!thread_info->pointer_data && (thread_info->pointer_data = calloc( 1, sizeof(*thread_info->pointer_data) ))) + list_init( &thread_info->pointer_data->known_pointers ); + return thread_info->pointer_data; +}; + +static struct pointer *find_pointerid(UINT32 id) +{ + struct pointer_thread_data *thread_data = get_pointer_thread_data(); + struct pointer *pointer; + + TRACE( "looking for pointer id %d\n", id ); + + if (!thread_data) + return NULL; + + LIST_FOR_EACH_ENTRY(pointer, &thread_data->known_pointers, struct pointer, entry) + if (pointer->id == id) + return pointer; + + TRACE( "allocating pointer id %d\n", id ); + + if (!(pointer = calloc( 1, sizeof(*pointer) ))) + return NULL; + + pointer->id = id; + list_add_tail( &thread_data->known_pointers, &pointer->entry ); + + return pointer; +} + +static POINTER_INFO pointer_info_from_msg( const MSG *msg ) +{ + POINT location = { LOWORD( msg->lParam ), HIWORD( msg->lParam ) }; + LARGE_INTEGER counter; + POINTER_INFO info = { + .pointerId = GET_POINTERID_WPARAM( msg->wParam ), + .sourceDevice = INVALID_HANDLE_VALUE, + .frameId = InterlockedIncrement( &last_frame ), + .hwndTarget = msg->hwnd, + .historyCount = 1, + .dwTime = msg->time, + }; + + info.pointerFlags = HIWORD( msg->wParam ); + switch (msg->message) + { + case WM_POINTERUPDATE: info.pointerFlags |= POINTER_FLAG_UPDATE; break; + case WM_POINTERDOWN: info.pointerFlags |= POINTER_FLAG_DOWN; break; + case WM_POINTERUP: info.pointerFlags |= POINTER_FLAG_UP; break; + } + info.ptPixelLocation = info.ptPixelLocationRaw = location; + info.ptHimetricLocation = info.ptHimetricLocationRaw = map_dpi_point( location, HIMETRIC, get_system_dpi() ); + + NtQueryPerformanceCounter( &counter, NULL ); + info.PerformanceCount = counter.QuadPart; + + return info; +} + +static POINTER_BUTTON_CHANGE_TYPE compare_button( const POINTER_INFO *old, const POINTER_INFO *new ) +{ + POINTER_BUTTON_CHANGE_TYPE change = POINTER_CHANGE_NONE; + static const struct + { + POINTER_FLAGS flag; + POINTER_BUTTON_CHANGE_TYPE down, up; + } map[] = { + { POINTER_FLAG_FIRSTBUTTON, POINTER_CHANGE_FIRSTBUTTON_DOWN, POINTER_CHANGE_FIRSTBUTTON_UP }, + { POINTER_FLAG_SECONDBUTTON, POINTER_CHANGE_SECONDBUTTON_DOWN, POINTER_CHANGE_SECONDBUTTON_UP }, + { POINTER_FLAG_THIRDBUTTON, POINTER_CHANGE_THIRDBUTTON_DOWN, POINTER_CHANGE_THIRDBUTTON_UP }, + { POINTER_FLAG_FOURTHBUTTON, POINTER_CHANGE_FOURTHBUTTON_DOWN, POINTER_CHANGE_FOURTHBUTTON_UP }, + { POINTER_FLAG_FIFTHBUTTON, POINTER_CHANGE_FIFTHBUTTON_DOWN, POINTER_CHANGE_FIFTHBUTTON_UP }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(map); i++) + if (!(old->pointerFlags & map[i].flag) && new->pointerFlags & map[i].flag) + change |= map[i].down; + else if (old->pointerFlags & map[i].flag && !(new->pointerFlags & map[i].flag)) + change |= map[i].up; + return change; +} + /*********************************************************************** * process_pointer_message g* @@ -2862,7 +2960,15 @@ INT WINAPI NtUserScheduleDispatchNotification( HWND hwnd ) */ BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) { + struct pointer *pointer; + POINTER_INFO info; + msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); + if (!(pointer = find_pointerid( GET_POINTERID_WPARAM( msg->wParam ) ))) + return TRUE; + info = pointer_info_from_msg( msg ); + info.ButtonChangeType = compare_button( &pointer->info, &info ); + pointer->info = info; return TRUE; } diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 2f9bc9c2ccc..2fa6944b820 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -130,6 +130,7 @@ struct user_thread_info DWORD clipping_reset; /* time when clipping was last reset */ struct session_thread_data *session_data; /* shared session thread data */ struct mouse_tracking_info *mouse_tracking_info; /* NtUserTrackMouseEvent handling */ + struct pointer_thread_data *pointer_data; /* list of known pointers */ }; C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> Seems like pointerId 1 is always the mouse, regardless of EnableMouseInPointer. --- dlls/win32u/input.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 0408e15a031..8ad0329dd1b 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2868,19 +2868,38 @@ INT WINAPI NtUserScheduleDispatchNotification( HWND hwnd ) return 0; } +static struct pointer *allocate_pointerid( UINT32 id ); + static struct pointer_thread_data *get_pointer_thread_data(void) { struct user_thread_info *thread_info = get_user_thread_info(); if (!thread_info->pointer_data && (thread_info->pointer_data = calloc( 1, sizeof(*thread_info->pointer_data) ))) + { list_init( &thread_info->pointer_data->known_pointers ); + allocate_pointerid( 1 ); + } return thread_info->pointer_data; }; -static struct pointer *find_pointerid(UINT32 id) +static struct pointer *allocate_pointerid( UINT32 id ) { struct pointer_thread_data *thread_data = get_pointer_thread_data(); struct pointer *pointer; + TRACE( "allocating pointer id %d\n", id ); + + if (!thread_data || !(pointer = calloc( 1, sizeof(*pointer) ))) + return NULL; + pointer->id = id; + list_add_tail( &thread_data->known_pointers, &pointer->entry ); + + return pointer; +} + +static struct pointer *find_pointerid( UINT32 id ) { + struct pointer_thread_data *thread_data = get_pointer_thread_data(); + struct pointer *pointer; + TRACE( "looking for pointer id %d\n", id ); if (!thread_data) @@ -2890,15 +2909,7 @@ static struct pointer *find_pointerid(UINT32 id) if (pointer->id == id) return pointer; - TRACE( "allocating pointer id %d\n", id ); - - if (!(pointer = calloc( 1, sizeof(*pointer) ))) - return NULL; - - pointer->id = id; - list_add_tail( &thread_data->known_pointers, &pointer->entry ); - - return pointer; + return allocate_pointerid( id ); } static POINTER_INFO pointer_info_from_msg( const MSG *msg ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/win32u/input.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 8ad0329dd1b..77c0080ce42 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -413,6 +413,7 @@ struct pointer { UINT32 id; struct list entry; + POINTER_INPUT_TYPE type; POINTER_INFO info; }; @@ -2868,7 +2869,7 @@ INT WINAPI NtUserScheduleDispatchNotification( HWND hwnd ) return 0; } -static struct pointer *allocate_pointerid( UINT32 id ); +static struct pointer *allocate_pointerid( UINT32 id, POINTER_INPUT_TYPE type ); static struct pointer_thread_data *get_pointer_thread_data(void) { @@ -2876,27 +2877,29 @@ static struct pointer_thread_data *get_pointer_thread_data(void) if (!thread_info->pointer_data && (thread_info->pointer_data = calloc( 1, sizeof(*thread_info->pointer_data) ))) { list_init( &thread_info->pointer_data->known_pointers ); - allocate_pointerid( 1 ); + allocate_pointerid( 1, PT_MOUSE ); } return thread_info->pointer_data; }; -static struct pointer *allocate_pointerid( UINT32 id ) +static struct pointer *allocate_pointerid( UINT32 id, POINTER_INPUT_TYPE type ) { struct pointer_thread_data *thread_data = get_pointer_thread_data(); struct pointer *pointer; - TRACE( "allocating pointer id %d\n", id ); + TRACE( "allocating pointer id %d, type %#x\n", id, type ); if (!thread_data || !(pointer = calloc( 1, sizeof(*pointer) ))) return NULL; pointer->id = id; + pointer->type = type; list_add_tail( &thread_data->known_pointers, &pointer->entry ); return pointer; } -static struct pointer *find_pointerid( UINT32 id ) { +static struct pointer *find_pointerid( UINT32 id, POINTER_INPUT_TYPE type ) +{ struct pointer_thread_data *thread_data = get_pointer_thread_data(); struct pointer *pointer; @@ -2909,7 +2912,7 @@ static struct pointer *find_pointerid( UINT32 id ) { if (pointer->id == id) return pointer; - return allocate_pointerid( id ); + return allocate_pointerid( id, type ); } static POINTER_INFO pointer_info_from_msg( const MSG *msg ) @@ -2964,6 +2967,18 @@ static POINTER_BUTTON_CHANGE_TYPE compare_button( const POINTER_INFO *old, const return change; } +static POINTER_INPUT_TYPE pointer_type_from_hw( const struct hw_msg_source *source ) +{ + switch (source->origin) + { + case IMDT_PEN: return PT_PEN; + case IMDT_MOUSE: return PT_MOUSE; + case IMDT_TOUCH: + case IMDT_TOUCHPAD: return PT_TOUCH; + default: return PT_POINTER; + } +} + /*********************************************************************** * process_pointer_message g* @@ -2975,11 +2990,12 @@ BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_da POINTER_INFO info; msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); - if (!(pointer = find_pointerid( GET_POINTERID_WPARAM( msg->wParam ) ))) + if (!(pointer = find_pointerid( GET_POINTERID_WPARAM( msg->wParam ), pointer_type_from_hw( &msg_data->source ) ))) return TRUE; info = pointer_info_from_msg( msg ); info.ButtonChangeType = compare_button( &pointer->info, &info ); pointer->info = info; + pointer->info.pointerType = pointer->type; return TRUE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/user32/misc.c | 11 ++--------- dlls/user32/tests/input.c | 2 -- dlls/win32u/input.c | 23 +++++++++++++++++------ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c index 6333fcb48b4..16f02958135 100644 --- a/dlls/user32/misc.c +++ b/dlls/user32/misc.c @@ -512,16 +512,9 @@ LRESULT WINAPI PackTouchHitTestingProximityEvaluation(const TOUCH_HIT_TESTING_IN */ BOOL WINAPI GetPointerType(UINT32 id, POINTER_INPUT_TYPE *type) { - FIXME("(%d %p): stub\n", id, type); + TRACE( "%d %p\n", id, type ); - if(!id || !type) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - *type = PT_MOUSE; - return TRUE; + return NtUserGetPointerType( id, type ); } BOOL WINAPI GetPointerInfo(UINT32 id, POINTER_INFO *info) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 905ff0dd922..d6fb9830d76 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -5527,9 +5527,7 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); SetLastError( 0xdeadbeef ); ret = pGetPointerType( 0xdead, &type ); - todo_wine ok( !ret, "GetPointerType succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); ret = pGetPointerType( 1, &type ); ok( ret, "GetPointerType failed, error %lu\n", GetLastError() ); diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 77c0080ce42..1677cfc293e 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2898,7 +2898,7 @@ static struct pointer *allocate_pointerid( UINT32 id, POINTER_INPUT_TYPE type ) return pointer; } -static struct pointer *find_pointerid( UINT32 id, POINTER_INPUT_TYPE type ) +static struct pointer *find_pointerid( UINT32 id ) { struct pointer_thread_data *thread_data = get_pointer_thread_data(); struct pointer *pointer; @@ -2912,7 +2912,7 @@ static struct pointer *find_pointerid( UINT32 id, POINTER_INPUT_TYPE type ) if (pointer->id == id) return pointer; - return allocate_pointerid( id, type ); + return NULL; } static POINTER_INFO pointer_info_from_msg( const MSG *msg ) @@ -2986,11 +2986,13 @@ static POINTER_INPUT_TYPE pointer_type_from_hw( const struct hw_msg_source *sour */ BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) { + UINT32 pointer_id = GET_POINTERID_WPARAM( msg->wParam ); struct pointer *pointer; POINTER_INFO info; msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); - if (!(pointer = find_pointerid( GET_POINTERID_WPARAM( msg->wParam ), pointer_type_from_hw( &msg_data->source ) ))) + if (!(pointer = find_pointerid( pointer_id )) && + !(pointer = allocate_pointerid( pointer_id, pointer_type_from_hw( &msg_data->source ) ))) return TRUE; info = pointer_info_from_msg( msg ); info.ButtonChangeType = compare_button( &pointer->info, &info ); @@ -3004,9 +3006,18 @@ BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_da */ BOOL WINAPI NtUserGetPointerType(UINT32 id, POINTER_INPUT_TYPE *type) { - FIXME( "(%u, %p) stub!\n", id, type ); - RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + struct pointer *pointer; + + TRACE( "%u, %p\n", id, type ); + + if (!id || !type || !(pointer = find_pointerid( id )) ) + { + RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + *type = pointer->type; + return TRUE; } /********************************************************************** -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/win32u/input.c | 45 +++++++++++++++++++++--------------- dlls/win32u/message.c | 11 ++++++++- dlls/win32u/win32u_private.h | 2 ++ 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 1677cfc293e..5f68a727972 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2915,21 +2915,21 @@ static struct pointer *find_pointerid( UINT32 id ) return NULL; } -static POINTER_INFO pointer_info_from_msg( const MSG *msg ) +POINTER_INFO pointer_info_from_msg( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, DWORD time ) { - POINT location = { LOWORD( msg->lParam ), HIWORD( msg->lParam ) }; + POINT location = { LOWORD( lParam ), HIWORD( lParam ) }; LARGE_INTEGER counter; POINTER_INFO info = { - .pointerId = GET_POINTERID_WPARAM( msg->wParam ), + .pointerId = GET_POINTERID_WPARAM( wParam ), .sourceDevice = INVALID_HANDLE_VALUE, .frameId = InterlockedIncrement( &last_frame ), - .hwndTarget = msg->hwnd, + .hwndTarget = hwnd, .historyCount = 1, - .dwTime = msg->time, + .dwTime = time, }; - info.pointerFlags = HIWORD( msg->wParam ); - switch (msg->message) + info.pointerFlags = HIWORD( wParam ); + switch (msg) { case WM_POINTERUPDATE: info.pointerFlags |= POINTER_FLAG_UPDATE; break; case WM_POINTERDOWN: info.pointerFlags |= POINTER_FLAG_DOWN; break; @@ -2967,6 +2967,23 @@ static POINTER_BUTTON_CHANGE_TYPE compare_button( const POINTER_INFO *old, const return change; } +void pointer_update( UINT32 id, POINTER_INPUT_TYPE type, POINTER_INFO *info ) +{ + POINTER_BUTTON_CHANGE_TYPE buttons; + struct pointer *pointer; + + TRACE( "updating pointer id %d.\n", id ); + + if (!(pointer = find_pointerid( id )) && !(pointer = allocate_pointerid( id, type ))) + return; + + buttons = compare_button(&pointer->info, info); + + pointer->info = *info; + pointer->info.pointerType = pointer->type; + pointer->info.ButtonChangeType = buttons; +} + static POINTER_INPUT_TYPE pointer_type_from_hw( const struct hw_msg_source *source ) { switch (source->origin) @@ -2986,18 +3003,8 @@ static POINTER_INPUT_TYPE pointer_type_from_hw( const struct hw_msg_source *sour */ BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) { - UINT32 pointer_id = GET_POINTERID_WPARAM( msg->wParam ); - struct pointer *pointer; - POINTER_INFO info; - - msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); - if (!(pointer = find_pointerid( pointer_id )) && - !(pointer = allocate_pointerid( pointer_id, pointer_type_from_hw( &msg_data->source ) ))) - return TRUE; - info = pointer_info_from_msg( msg ); - info.ButtonChangeType = compare_button( &pointer->info, &info ); - pointer->info = info; - pointer->info.pointerType = pointer->type; + POINTER_INFO info = pointer_info_from_msg( msg->hwnd, msg->message, msg->wParam, msg->lParam, msg->time ); + pointer_update( GET_POINTERID_WPARAM( msg->wParam ), pointer_type_from_hw( &msg_data->source ), &info ); return TRUE; } diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 62115515fb2..c694e88f77d 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2666,7 +2666,16 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H break; } - if (message) send_message( msg->hwnd, message, MAKELONG( 1, flags ), MAKELONG( msg->pt.x, msg->pt.y ) ); + if (message) + { + LPARAM lParam = MAKELONG( msg->pt.x, msg->pt.y ); + WPARAM wParam = MAKELONG( 1, flags ); + POINTER_INFO info; + + info = pointer_info_from_msg( msg->hwnd, message, wParam, lParam, msg->time ); + pointer_update( 1, PT_MOUSE, &info ); + send_message( msg->hwnd, message, wParam, lParam ); + } } /* FIXME: is this really the right place for this hook? */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index d68cba0dc50..0217f52e5da 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -111,6 +111,8 @@ extern BOOL process_wine_clipcursor( HWND hwnd, UINT flags, BOOL reset ); extern BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ); extern USHORT map_scan_to_kbd_vkey( USHORT scan, HKL layout ); extern BOOL process_pointer_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ); +extern POINTER_INFO pointer_info_from_msg( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, DWORD time ); +extern void pointer_update( UINT32 id, POINTER_INPUT_TYPE type, POINTER_INFO *info ); /* menu.c */ extern UINT draw_nc_menu_bar( HDC hdc, RECT *rect, HWND hwnd ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
From: "Anna (navi) Figueiredo Gomes" <navi@vlhl.dev> --- dlls/user32/input.c | 63 ++++++++++++++++++++++++++++++++------ dlls/user32/misc.c | 32 +++++++++++++++++-- dlls/user32/tests/input.c | 17 ++++------ dlls/user32/user32.spec | 16 +++++----- dlls/win32u/input.c | 62 +++++++++++++++++++++++++++++-------- dlls/win32u/tests/win32u.c | 8 ++--- 6 files changed, 151 insertions(+), 47 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 623fab14d11..051f4e48ec9 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -752,16 +752,20 @@ BOOL WINAPI GetPointerDeviceProperties( HANDLE device, UINT32 *count, BOOL WINAPI GetPointerPenInfo( UINT32 id, POINTER_PEN_INFO *info ) { - FIXME( "id %u, info %p stub!\n", id, info ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + UINT32 count = 1; + + TRACE( "id %u, info %p\n", id, info ); + + return NtUserGetPointerInfoList( id, PT_PEN, 0, 0, sizeof(*info), &count, &count, info ); } BOOL WINAPI GetPointerTouchInfo( UINT32 id, POINTER_TOUCH_INFO *info ) { - FIXME( "id %u, info %p stub!\n", id, info ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + UINT32 count = 1; + + TRACE( "id %u, info %p stub!\n", id, info ); + + return NtUserGetPointerInfoList( id, PT_TOUCH, 0, 0, sizeof(*info), &count, &count, info ); } BOOL WINAPI GetRawPointerDeviceData( UINT32 id, UINT32 hist_count, UINT32 prop_count, @@ -775,9 +779,50 @@ BOOL WINAPI GetRawPointerDeviceData( UINT32 id, UINT32 hist_count, UINT32 prop_c BOOL WINAPI GetPointerTouchInfoHistory( UINT32 id, UINT32 *count, POINTER_TOUCH_INFO *info ) { - FIXME( "id %u, count %p, info %p stub!\n", id, count, info ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + UINT32 pointers = 1; + + TRACE( "id %u, count %p, info %p\n", id, count, info ); + + return NtUserGetPointerInfoList( id, PT_TOUCH, 0, 0, sizeof(*info), count, &pointers, info ); +} + +BOOL WINAPI GetPointerPenInfoHistory( UINT32 id, UINT32 *count, POINTER_PEN_INFO *info ) +{ + UINT32 pointers = 1; + + TRACE( "id %u, count %p, info %p\n", id, count, info ); + + return NtUserGetPointerInfoList( id, PT_PEN, 0, 0, sizeof(*info), count, &pointers, info ); +} + +BOOL WINAPI GetPointerFrameTouchInfo( UINT32 id, UINT32 *count, POINTER_TOUCH_INFO *info ) +{ + UINT32 entries = 1; + + TRACE( "id %u, count %p, info %p\n", id, count, info ); + + return NtUserGetPointerInfoList( id, PT_TOUCH, 0, 0, sizeof(*info), &entries, count, info ); +} + +BOOL WINAPI GetPointerFramePenInfo( UINT32 id, UINT32 *count, POINTER_PEN_INFO *info ) +{ + UINT32 entries = 1; + + TRACE( "id %u, count %p, info %p\n", id, count, info ); + + return NtUserGetPointerInfoList( id, PT_PEN, 0, 0, sizeof(*info), &entries, count, info ); +} + +BOOL WINAPI GetPointerFrameTouchInfoHistory( UINT32 id, UINT32 *entries, UINT32 *pointers, POINTER_TOUCH_INFO *info ) +{ + TRACE( "id %u, entries %p, pointers %p, info %p\n", id, entries, pointers, info ); + return NtUserGetPointerInfoList( id, PT_TOUCH, 0, 0, sizeof(*info), entries, pointers, info ); +} + +BOOL WINAPI GetPointerFramePenInfoHistory( UINT32 id, UINT32 *entries, UINT32 *pointers, POINTER_PEN_INFO *info ) +{ + TRACE( "id %u, entries %p, pointers %p, info %p\n", id, entries, pointers, info ); + return NtUserGetPointerInfoList( id, PT_PEN, 0, 0, sizeof(*info), entries, pointers, info ); } diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c index 16f02958135..764e559df19 100644 --- a/dlls/user32/misc.c +++ b/dlls/user32/misc.c @@ -519,10 +519,36 @@ BOOL WINAPI GetPointerType(UINT32 id, POINTER_INPUT_TYPE *type) BOOL WINAPI GetPointerInfo(UINT32 id, POINTER_INFO *info) { - FIXME("(%d %p): stub\n", id, info); + UINT32 count = 1; - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + TRACE( "id %d, info %p\n", id, info ); + + return NtUserGetPointerInfoList( id, PT_POINTER, 0, 0, sizeof(*info), &count, &count, info ); +} + +BOOL WINAPI GetPointerInfoHistory( UINT32 id, UINT32 *count, POINTER_INFO *info ) +{ + UINT32 pointers = 1; + + TRACE( "id %u, count %p, info %p\n", id, count, info ); + + return NtUserGetPointerInfoList( id, PT_POINTER, 0, 0, sizeof(*info), count, &pointers, info ); +} + +BOOL WINAPI GetPointerFrameInfo( UINT32 id, UINT32 *count, POINTER_INFO *info ) +{ + UINT32 entries = 1; + + TRACE( "id %u, count %p, info %p\n", id, count, info ); + + return NtUserGetPointerInfoList( id, PT_POINTER, 0, 0, sizeof(*info), &entries, count, info ); +} + +BOOL WINAPI GetPointerFrameInfoHistory( UINT32 id, UINT32 *entries, UINT32 *pointers, POINTER_INFO *info ) +{ + TRACE( "id %u, entries %p, pointers %p, info %p\n", id, entries, pointers, info ); + + return NtUserGetPointerInfoList( id, PT_POINTER, 0, 0, sizeof(*info), entries, pointers, info ); } LRESULT WINAPI ImeWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index d6fb9830d76..51bad80e252 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -5416,7 +5416,9 @@ static DWORD CALLBACK test_GetPointerInfo_thread( void *arg ) memset( &pointer_info, 0xcd, sizeof(pointer_info) ); ret = pGetPointerInfo( 1, &pointer_info ); + todo_wine ok( !ret, "GetPointerInfo succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); DestroyWindow( hwnd ); @@ -5545,13 +5547,13 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) ret = pGetPointerInfo( 1, invalid_ptr ); ok( !ret, "GetPointerInfo succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_NOACCESS || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* w10 32bit */, "got error %lu\n", GetLastError() ); memset( pointer_info, 0xcd, sizeof(pointer_info) ); ret = pGetPointerInfo( 1, pointer_info ); ok( !ret, "GetPointerInfo succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); SetCursorPos( 500, 500 ); /* avoid generating mouse message on window creation */ @@ -5563,6 +5565,7 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) memset( pointer_info, 0xcd, sizeof(pointer_info) ); ret = pGetPointerInfo( 1, pointer_info ); ok( !ret, "GetPointerInfo succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); SetCursorPos( 200, 200 ); @@ -5648,30 +5651,26 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) memset( pointer_info, 0xcd, sizeof(pointer_info) ); ret = pGetPointerInfo( 0xdead, pointer_info ); ok( !ret, "GetPointerInfo succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); memset( pointer_info, 0xcd, sizeof(pointer_info) ); ret = pGetPointerInfo( 1, pointer_info ); - todo_wine_if(mouse_in_pointer_enabled) ok( ret == mouse_in_pointer_enabled, "GetPointerInfo failed, error %lu\n", GetLastError() ); if (!mouse_in_pointer_enabled) { + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); return; } - todo_wine ok( pointer_info[0].pointerType == PT_MOUSE, "got pointerType %lu\n", pointer_info[0].pointerType ); - todo_wine ok( pointer_info[0].pointerId == 1, "got pointerId %u\n", pointer_info[0].pointerId ); ok( !!pointer_info[0].frameId, "got frameId %u\n", pointer_info[0].frameId ); - todo_wine ok( pointer_info[0].pointerFlags == (0x40000 | POINTER_MESSAGE_FLAG_INRANGE), "got pointerFlags %#x\n", pointer_info[0].pointerFlags ); - todo_wine ok( pointer_info[0].sourceDevice == INVALID_HANDLE_VALUE || broken(!!pointer_info[0].sourceDevice) /* < w10 & 32bit */, "got sourceDevice %p\n", pointer_info[0].sourceDevice ); - todo_wine ok( pointer_info[0].hwndTarget == hwnd, "got hwndTarget %p\n", pointer_info[0].hwndTarget ); ok( !!pointer_info[0].ptPixelLocation.x, "got ptPixelLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocation ) ); ok( !!pointer_info[0].ptPixelLocation.y, "got ptPixelLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocation ) ); @@ -5682,14 +5681,10 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) ok( !!pointer_info[0].ptHimetricLocationRaw.x, "got ptHimetricLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocationRaw ) ); ok( !!pointer_info[0].ptHimetricLocationRaw.y, "got ptHimetricLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocationRaw ) ); ok( !!pointer_info[0].dwTime, "got dwTime %lu\n", pointer_info[0].dwTime ); - todo_wine ok( pointer_info[0].historyCount == 1, "got historyCount %u\n", pointer_info[0].historyCount ); - todo_wine ok( pointer_info[0].InputData == 0, "got InputData %u\n", pointer_info[0].InputData ); - todo_wine ok( pointer_info[0].dwKeyStates == 0, "got dwKeyStates %lu\n", pointer_info[0].dwKeyStates ); ok( !!pointer_info[0].PerformanceCount, "got PerformanceCount %I64u\n", pointer_info[0].PerformanceCount ); - todo_wine ok( pointer_info[0].ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP, "got ButtonChangeType %u\n", pointer_info[0].ButtonChangeType ); thread = CreateThread( NULL, 0, test_GetPointerInfo_thread, NULL, 0, NULL ); diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 80dfa388dd8..2ae092d696f 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -632,18 +632,18 @@ @ stdcall GetPointerDeviceProperties(ptr ptr ptr) @ stdcall GetPointerDeviceRects(ptr ptr ptr) NtUserGetPointerDeviceRects @ stdcall GetPointerDevices(ptr ptr) -# @ stub GetPointerFrameInfo -# @ stub GetPointerFrameInfoHistory -# @ stub GetPointerFramePenInfo -# @ stub GetPointerFramePenInfoHistory +@ stdcall GetPointerFrameInfo(long ptr ptr) +@ stdcall GetPointerFrameInfoHistory(long ptr ptr ptr) +@ stdcall GetPointerFramePenInfo(long ptr ptr) +@ stdcall GetPointerFramePenInfoHistory(long ptr ptr ptr) # @ stub GetPointerFrameTimes -# @ stub GetPointerFrameTouchInfo -# @ stub GetPointerFrameTouchInfoHistory +@ stdcall GetPointerFrameTouchInfo(long ptr ptr) +@ stdcall GetPointerFrameTouchInfoHistory(long ptr ptr ptr) @ stdcall GetPointerInfo(long ptr) -# @ stub GetPointerInfoHistory +@ stdcall GetPointerInfoHistory(long ptr ptr) # @ stub GetPointerInputTransform @ stdcall GetPointerPenInfo(long ptr) -# @ stub GetPointerPenInfoHistory +@ stdcall GetPointerPenInfoHistory(long ptr ptr) @ stdcall GetPointerTouchInfo(long ptr) @ stdcall GetPointerTouchInfoHistory(long ptr ptr) @ stdcall GetPointerType(long ptr) diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 5f68a727972..5788d85f9a5 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -2735,18 +2735,6 @@ BOOL clip_fullscreen_window( HWND hwnd, BOOL reset ) return ret; } -/********************************************************************** - * NtUserGetPointerInfoList (win32u.@) - */ -BOOL WINAPI NtUserGetPointerInfoList( UINT32 id, POINTER_INPUT_TYPE type, UINT_PTR unk0, UINT_PTR unk1, SIZE_T size, - UINT32 *entry_count, UINT32 *pointer_count, void *pointer_info ) -{ - FIXME( "id %#x, type %#x, unk0 %#lx, unk1 %#lx, size %#lx, entry_count %p, pointer_count %p, pointer_info %p stub!\n", - id, type, (long)unk0, (long)unk1, size, entry_count, pointer_count, pointer_info ); - RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; -} - static BOOL get_clip_cursor( RECT *rect, UINT dpi, MONITOR_DPI_TYPE type ) { struct object_lock lock = OBJECT_LOCK_INIT; @@ -3027,6 +3015,56 @@ BOOL WINAPI NtUserGetPointerType(UINT32 id, POINTER_INPUT_TYPE *type) return TRUE; } +/********************************************************************** + * NtUserGetPointerInfoList (win32u.@) + */ +BOOL WINAPI NtUserGetPointerInfoList( UINT32 id, POINTER_INPUT_TYPE type, UINT_PTR unk0, UINT_PTR unk1, SIZE_T size, + UINT32 *entry_count, UINT32 *pointer_count, void *pointer_info ) +{ + struct pointer *pointer; + size_t target_size = 0; + + TRACE( "id %d, type %#x, unk0 %#lx, unk1 %#lx, size %#lx, entry_count %p, pointer_count %p, pointer_info %p\n", + id, type, (long)unk0, (long)unk1, size, entry_count, pointer_count, pointer_info ); + + switch (type) + { + case PT_MOUSE: + case PT_PEN: target_size = sizeof(POINTER_PEN_INFO); break; + case PT_POINTER: target_size = sizeof(POINTER_INFO); break; + case PT_TOUCHPAD: + case PT_TOUCH: target_size = sizeof(POINTER_TOUCH_INFO); break; + } + + if (type == PT_MOUSE || size != target_size) + { + RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (!(pointer = find_pointerid( id ))) + { + TRACE( "pointer id %d not found.\n", id ); + RtlSetLastWin32Error( ERROR_NOACCESS ); + return FALSE; + } + + if (!pointer->info.pointerId) + { + TRACE( "no info on pointer id %d.\n", id ); + RtlSetLastWin32Error( ERROR_NOACCESS ); + return FALSE; + } + + if (type != PT_POINTER && type != PT_MOUSE) + FIXME( "Pointer type %#x not implemented!", type ); + + *entry_count = 1; + *pointer_count = 1; + *(POINTER_INFO *)pointer_info = pointer->info; + return TRUE; +} + /********************************************************************** * NtUserGetPointerDeviceRects (win32u.@) */ diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 4c928f88fc1..3522c5ecb82 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -1807,9 +1807,13 @@ static DWORD CALLBACK test_NtUserGetPointerInfoList_thread( void *arg ) memset( &pointer_info, 0xcd, sizeof(pointer_info) ); entry_count = pointer_count = 2; ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, pointer_info ); + todo_wine ok( !ret, "NtUserGetPointerInfoList succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); + todo_wine ok( pointer_count == 2, "got pointer_count %u\n", pointer_count ); + todo_wine ok( entry_count == 2, "got entry_count %u\n", entry_count ); DestroyWindow( hwnd ); @@ -1869,17 +1873,14 @@ static void test_NtUserGetPointerInfoList( BOOL mouse_in_pointer_enabled ) entry_count = pointer_count = 2; ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), invalid_ptr, &pointer_count, pointer_info ); ok( !ret, "NtUserGetPointerInfoList succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() ); entry_count = pointer_count = 2; ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, invalid_ptr, pointer_info ); ok( !ret, "NtUserGetPointerInfoList succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() ); entry_count = pointer_count = 2; ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, invalid_ptr ); ok( !ret, "NtUserGetPointerInfoList succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_NOACCESS || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* w10 32bit */, "got error %lu\n", GetLastError() ); memset( pointer_info, 0xcd, sizeof(pointer_info) ); @@ -1918,7 +1919,6 @@ static void test_NtUserGetPointerInfoList( BOOL mouse_in_pointer_enabled ) memset( pointer_info, 0xcd, sizeof(pointer_info) ); entry_count = pointer_count = 2; ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, pointer_info ); - todo_wine_if(mouse_in_pointer_enabled) ok( ret == mouse_in_pointer_enabled, "NtUserGetPointerInfoList failed, error %lu\n", GetLastError() ); if (!ret) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10649
On Fri Apr 17 17:21:13 2026 +0000, navi wrote:
changed this line in [version 12 of the diff](/wine/wine/-/merge_requests/10649/diffs?diff_id=261247&start_sha=60b125e8457bdf1fb487b01d80854f35ede5497f#c0e9abea64045e9b4299dedef42bd12721df8706_3094_3084) on tests i've ran for the himetric pointerDeviceRect, i actually got rounding errors using MulDiv, which worked with manual operations:
device (0,0)-(39264,20760), expected (0,0)-(39264,20761)
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10649#note_138960
On Tue May 5 01:41:16 2026 +0000, navi wrote:
initially i've added simple tests but those didn't hold under certain combinations of dpi/scale and resolutions ~~after being confused for a while, i noticed the ratio between the dpi aware virtual screen pixel dimensions and the pointer device dimensions was always constant everywhere i tried (qemu w/ various output configurations, and a physical laptop)~~ ~~i still can't really find out where from, why, or how that ratio is derived, so i didn't yet update the implementation itself -- would appreciate some suggestions if any~~ nevermind, ci fails and i think qemu and the laptop just had very similar display sizes okay issue was, the resulting value was influenced by the dpi value, but it was always the dpi that was set at boot, which would be applied to the current resolution -- changing the dpi reflected on the displayRect, but would only reflect on the pointerDeviceRect after a reboot
i am much unsure how to test this, it's a very specific quirk that only shows up when scaling is changed at runtime, so should we try to match that behaviour at all? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10649#note_138961
participants (2)
-
Anna (navi) Figueiredo Gomes -
navi (@navi)