[PATCH 0/2] MR10120: win32u: Implement NtUserEnableMouseInPointer semi-stub.
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/tests/input.c | 95 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 7915a8416d3..8d32ea31989 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -5408,6 +5408,7 @@ static DWORD CALLBACK test_GetPointerInfo_thread( void *arg ) hwnd = CreateWindowW( L"test", L"test name", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, NULL, 0 ); + empty_message_queue(); memset( &pointer_info, 0xcd, sizeof(pointer_info) ); ret = pGetPointerInfo( 1, &pointer_info ); @@ -5419,8 +5420,51 @@ static DWORD CALLBACK test_GetPointerInfo_thread( void *arg ) return 0; } +static BOOL accept_pointer_messages( UINT msg ) +{ + if (is_mouse_message( msg )) return TRUE; + return msg >= WM_TOUCH && msg <= WM_POINTERROUTEDRELEASED; +} + static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) { +#define WIN_MSG(m, h, w, l, ...) {.func = MSG_TEST_WIN, .message = {.msg = m, .hwnd = h, .wparam = w, .lparam = l}, ## __VA_ARGS__} + UINT down_flags = POINTER_MESSAGE_FLAG_FIRSTBUTTON|POINTER_MESSAGE_FLAG_INCONTACT; + struct user_call button_down_seq[] = + { + WIN_MSG(WM_LBUTTONDOWN, 0, 1, 0/*rel*/), + {0}, + }; + struct user_call pointer_down_seq[] = + { + WIN_MSG(WM_POINTERDOWN, 0, MAKELONG(1, POINTER_MESSAGE_FLAG_PRIMARY|POINTER_MESSAGE_FLAG_INRANGE|down_flags), 0/*abs*/), + WIN_MSG(WM_LBUTTONDOWN, 0, 1, 0/*rel*/), + {0}, + }; + struct user_call button_up_seq[] = + { + WIN_MSG(WM_LBUTTONUP, 0, 0, 0/*rel*/), + {0}, + }; + struct user_call pointer_up_seq[] = + { + WIN_MSG(WM_POINTERUP, 0, MAKELONG(1, POINTER_MESSAGE_FLAG_INRANGE), 0/*abs*/), + WIN_MSG(WM_LBUTTONUP, 0, 0, 0/*rel*/), + {0}, + }; + struct user_call mouse_move_seq[] = + { + WIN_MSG(WM_MOUSEMOVE, 0, 0, 0/*rel*/), + {0}, + }; + struct user_call pointer_move_seq[] = + { + WIN_MSG(WM_POINTERUPDATE, 0, MAKELONG(1, POINTER_MESSAGE_FLAG_PRIMARY|POINTER_MESSAGE_FLAG_INRANGE), 0/*abs*/), + WIN_MSG(WM_MOUSEMOVE, 0, 0, 0/*rel*/), + {0}, + }; +#undef WIN_MSG + POINTER_INFO pointer_info[4], expect_pointer; void *invalid_ptr = (void *)0xdeadbeef; UINT32 entry_count, pointer_count; @@ -5432,10 +5476,12 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) .hbrBackground = GetStockObject( WHITE_BRUSH ), .lpszClassName = L"test", }; + LONG_PTR old_proc; HANDLE thread; ATOM class; DWORD res; HWND hwnd; + POINT pt; BOOL ret; if (!pGetPointerType) @@ -5482,7 +5528,7 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) SetCursorPos( 500, 500 ); /* avoid generating mouse message on window creation */ - hwnd = CreateWindowW( L"test", L"test name", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, + hwnd = CreateWindowW( L"test", L"test name", WS_POPUP | WS_VISIBLE, 100, 100, 200, 200, 0, 0, NULL, 0 ); empty_message_queue(); @@ -5492,13 +5538,50 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); SetCursorPos( 200, 200 ); - empty_message_queue(); + wait_messages( 100, FALSE ); + ok_seq( empty_sequence ); + + old_proc = SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)append_message_wndproc ); + ok_ne( 0, old_proc, LONG_PTR, "%#Ix" ); + p_accept_message = accept_pointer_messages; + mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 ); - empty_message_queue(); + wait_messages( 100, FALSE ); + + /* fixup flaky windows mouse position */ + GetCursorPos( &pt ); + button_down_seq[0].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); + pointer_down_seq[0].message.lparam = MAKELONG(pt.x, pt.y); + pointer_down_seq[1].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); + + if (mouse_in_pointer_enabled) todo_wine ok_seq( pointer_down_seq ); + else ok_seq( button_down_seq ); + mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); - empty_message_queue(); - mouse_event( MOUSEEVENTF_MOVE, 10, 10, 0, 0 ); - empty_message_queue(); + wait_messages( 100, FALSE ); + + /* fixup flaky windows mouse position */ + GetCursorPos( &pt ); + button_up_seq[0].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); + pointer_up_seq[0].message.lparam = MAKELONG(pt.x, pt.y); + pointer_up_seq[1].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); + + if (mouse_in_pointer_enabled) todo_wine ok_seq( pointer_up_seq ); + else ok_seq( button_up_seq ); + + mouse_event( MOUSEEVENTF_MOVE, 20, 20, 0, 0 ); + wait_messages( 100, FALSE ); + + /* fixup flaky windows mouse position */ + GetCursorPos( &pt ); + mouse_move_seq[0].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); + pointer_move_seq[0].message.lparam = MAKELONG(pt.x, pt.y); + pointer_move_seq[1].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); + + if (mouse_in_pointer_enabled) todo_wine ok_seq( pointer_move_seq ); + else ok_seq( mouse_move_seq ); + + p_accept_message = NULL; memset( pointer_info, 0xcd, sizeof(pointer_info) ); ret = pGetPointerInfo( 0xdead, pointer_info ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10120
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/tests/input.c | 11 +++------ dlls/win32u/input.c | 27 ++++++++++++++++------ dlls/win32u/message.c | 45 ++++++++++++++++++++++++++++++++++++ dlls/win32u/win32u_private.h | 1 + 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 8d32ea31989..35f56edafe8 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -5554,7 +5554,7 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) pointer_down_seq[0].message.lparam = MAKELONG(pt.x, pt.y); pointer_down_seq[1].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); - if (mouse_in_pointer_enabled) todo_wine ok_seq( pointer_down_seq ); + if (mouse_in_pointer_enabled) ok_seq( pointer_down_seq ); else ok_seq( button_down_seq ); mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 ); @@ -5566,7 +5566,7 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) pointer_up_seq[0].message.lparam = MAKELONG(pt.x, pt.y); pointer_up_seq[1].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); - if (mouse_in_pointer_enabled) todo_wine ok_seq( pointer_up_seq ); + if (mouse_in_pointer_enabled) ok_seq( pointer_up_seq ); else ok_seq( button_up_seq ); mouse_event( MOUSEEVENTF_MOVE, 20, 20, 0, 0 ); @@ -5578,7 +5578,7 @@ static void test_GetPointerInfo( BOOL mouse_in_pointer_enabled ) pointer_move_seq[0].message.lparam = MAKELONG(pt.x, pt.y); pointer_move_seq[1].message.lparam = MAKELONG(pt.x - 100, pt.y - 100); - if (mouse_in_pointer_enabled) todo_wine ok_seq( pointer_move_seq ); + if (mouse_in_pointer_enabled) ok_seq( pointer_move_seq ); else ok_seq( mouse_move_seq ); p_accept_message = NULL; @@ -5683,23 +5683,18 @@ static void test_EnableMouseInPointer( const char *arg ) winetest_push_context( "enable %lu", enable ); ret = pEnableMouseInPointer( enable ); - todo_wine ok( ret, "EnableMouseInPointer failed, error %lu\n", GetLastError() ); SetLastError( 0xdeadbeef ); ret = pEnableMouseInPointer( !enable ); ok( !ret, "EnableMouseInPointer succeeded\n" ); - todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError() ); ret = pIsMouseInPointerEnabled(); - todo_wine_if(enable) ok( ret == enable, "IsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() ); ret = pEnableMouseInPointer( enable ); - todo_wine ok( ret, "EnableMouseInPointer failed, error %lu\n", GetLastError() ); ret = pIsMouseInPointerEnabled(); - todo_wine_if(enable) ok( ret == enable, "IsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() ); test_GetPointerInfo( enable ); diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index c86a357ab14..5736d56cecc 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -405,6 +405,7 @@ static const KBDTABLES kbdus_tables = }; static LONG clipping_cursor; /* clipping thread counter */ +static LONG enable_mouse_in_pointer = -1; BOOL grab_pointer = TRUE; BOOL grab_fullscreen = FALSE; @@ -2608,15 +2609,22 @@ void toggle_caret( HWND hwnd ) if (ret && !hidden) display_caret( hwnd, &r ); } - /********************************************************************** * NtUserEnableMouseInPointer (win32u.@) */ BOOL WINAPI NtUserEnableMouseInPointer( BOOL enable ) { - FIXME( "enable %u stub!\n", enable ); - RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + LONG prev; + + TRACE( "enable %u\n", enable ); + + if ((prev = InterlockedCompareExchange( &enable_mouse_in_pointer, !!enable, -1 )) != -1 && prev != enable) + { + RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); + return FALSE; + } + + return TRUE; } /********************************************************************** @@ -2634,9 +2642,14 @@ BOOL WINAPI NtUserEnableMouseInPointerForThread( void ) */ BOOL WINAPI NtUserIsMouseInPointerEnabled(void) { - FIXME( "stub!\n" ); - RtlSetLastWin32Error( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + BOOL ret = ReadNoFence( &enable_mouse_in_pointer ) == 1; + TRACE( "-> %d.\n", ret ); + return ret; +} + +BOOL is_mouse_in_pointer_enabled( HWND hwnd ) +{ + return ReadNoFence( &enable_mouse_in_pointer ) == 1; } static BOOL is_captured_by_system(void) diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 58eeb046a94..b5d0a542ad0 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2605,6 +2605,51 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); set_thread_dpi_awareness_context( get_window_dpi_awareness_context( msg->hwnd )); + if ((extra_info & 0xffffff00) != 0xff515700 && is_mouse_in_pointer_enabled( msg->hwnd )) + { + WORD flags = POINTER_MESSAGE_FLAG_INRANGE; + DWORD message = 0; + + switch (msg->message) + { + case WM_MOUSEMOVE: + message = WM_POINTERUPDATE; + flags |= POINTER_MESSAGE_FLAG_PRIMARY; + break; + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_XBUTTONDOWN: + message = WM_POINTERDOWN; + flags |= POINTER_MESSAGE_FLAG_PRIMARY|POINTER_MESSAGE_FLAG_INCONTACT; + if (msg->message == WM_LBUTTONDOWN) flags |= POINTER_MESSAGE_FLAG_FIRSTBUTTON; + if (msg->message == WM_RBUTTONDOWN) flags |= POINTER_MESSAGE_FLAG_SECONDBUTTON; + if (msg->message == WM_MBUTTONDOWN) flags |= POINTER_MESSAGE_FLAG_THIRDBUTTON; + if (msg->message == WM_XBUTTONDOWN && LOWORD( msg->wParam ) == MK_LBUTTON) flags |= POINTER_MESSAGE_FLAG_FIRSTBUTTON; + if (msg->message == WM_XBUTTONDOWN && LOWORD( msg->wParam ) == MK_RBUTTON) flags |= POINTER_MESSAGE_FLAG_SECONDBUTTON; + if (msg->message == WM_XBUTTONDOWN && LOWORD( msg->wParam ) == MK_MBUTTON) flags |= POINTER_MESSAGE_FLAG_THIRDBUTTON; + if (msg->message == WM_XBUTTONDOWN && LOWORD( msg->wParam ) == MK_XBUTTON1) flags |= POINTER_MESSAGE_FLAG_FOURTHBUTTON; + if (msg->message == WM_XBUTTONDOWN && LOWORD( msg->wParam ) == MK_XBUTTON2) flags |= POINTER_MESSAGE_FLAG_FIFTHBUTTON; + break; + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + case WM_XBUTTONUP: + message = WM_POINTERUP; + break; + case WM_MOUSEWHEEL: + message = WM_POINTERWHEEL; + flags = HIWORD( msg->wParam ); + break; + case WM_MOUSEHWHEEL: + message = WM_POINTERHWHEEL; + flags = HIWORD( msg->wParam ); + break; + } + + if (message) send_message( msg->hwnd, message, MAKELONG( 1, flags ), MAKELONG( msg->pt.x, msg->pt.y ) ); + } + /* FIXME: is this really the right place for this hook? */ event.message = msg->message; event.time = msg->time; diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 1024fb71c26..22d376839b3 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -93,6 +93,7 @@ extern void unregister_imm_window( HWND hwnd ); /* input.c */ extern BOOL grab_pointer; extern BOOL grab_fullscreen; +extern BOOL is_mouse_in_pointer_enabled( HWND hwnd ); extern HWND get_active_window(void); extern HWND get_capture(void); extern HWND get_focus(void); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10120
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)