From: Paul Gofman pgofman@codeweavers.com
--- dlls/user32/tests/msg.c | 8 +------- dlls/win32u/input.c | 38 ++++++++++++++++++++++++++++++------ dlls/win32u/message.c | 5 +++-- dlls/win32u/ntuser_private.h | 3 +++ dlls/win32u/win32u_private.h | 3 ++- dlls/win32u/window.c | 6 +++--- 6 files changed, 44 insertions(+), 19 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index cdae4c7d37a..a5124d96a3e 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -14936,12 +14936,6 @@ static const struct message WmMouseLeaveSeq[] = { 0 } };
-static const struct message TrackMouseEventCallSeq[] = -{ - { WM_NCHITTEST, sent | wine_only, 0, 0 }, - { 0 } -}; - static void pump_msg_loop_timeout(DWORD timeout, BOOL inject_mouse_move) { MSG msg; @@ -15206,7 +15200,7 @@ static void test_TrackMouseEvent(void) ok(ret, "TrackMouseEvent(TME_LEAVE) failed, error %ld\n", GetLastError()); flush_events(); ignore_WM_NCHITTEST = TRUE; - ok_sequence(TrackMouseEventCallSeq, "TrackMouseEventCallSeq", FALSE); + ok_sequence(WmEmptySeq, "TrackMouseEventCallSeq", FALSE); SetCursorPos(old_pt.x, old_pt.y); DestroyWindow(hwnd2);
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index a46d898758d..23b6a3e3462 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1663,6 +1663,15 @@ static struct mouse_tracking_info *get_mouse_tracking_info(void) return thread_info->mouse_tracking_info; }
+void update_current_mouse_window( HWND hwnd, INT hittest, POINT pos ) +{ + struct mouse_tracking_info *tracking = get_mouse_tracking_info(); + + tracking->last_mouse_message_hwnd = hwnd; + tracking->last_mouse_message_hittest = hittest; + tracking->last_mouse_message_pos = pos; +} + static void check_mouse_leave( HWND hwnd, int hittest, struct mouse_tracking_info *tracking ) { if (tracking->info.hwndTrack != hwnd) @@ -1695,6 +1704,27 @@ static void check_mouse_leave( HWND hwnd, int hittest, struct mouse_tracking_inf } }
+static HWND get_mouse_window( HWND hwnd, INT *hittest, POINT *ret_pos, struct mouse_tracking_info *tracking ) +{ + POINT pos; + HWND ret; + + NtUserGetCursorPos( &pos ); + ret = window_from_point( hwnd, pos, hittest, FALSE ); + if (ret && ret == tracking->last_mouse_message_hwnd) + { + *hittest = tracking->last_mouse_message_hittest; + *ret_pos = tracking->last_mouse_message_pos; + } + else + { + tracking->last_mouse_message_hwnd = NULL; + *ret_pos = pos; + } + TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), ret, *hittest ); + return ret; +} + void update_mouse_tracking_info( HWND hwnd ) { struct mouse_tracking_info *tracking = get_mouse_tracking_info(); @@ -1703,10 +1733,7 @@ void update_mouse_tracking_info( HWND hwnd )
TRACE( "hwnd %p\n", hwnd );
- NtUserGetCursorPos( &pos ); - hwnd = window_from_point( hwnd, pos, &hittest ); - - TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest ); + hwnd = get_mouse_window( hwnd, &hittest, &pos, tracking );
NtUserSystemParametersInfo( SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0 ); NtUserSystemParametersInfo( SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0 ); @@ -1803,8 +1830,7 @@ BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info ) if (hover_time == HOVER_DEFAULT || hover_time == 0) NtUserSystemParametersInfo( SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0 );
- NtUserGetCursorPos( &pos ); - hwnd = window_from_point( info->hwndTrack, pos, &hittest ); + hwnd = get_mouse_window( info->hwndTrack, &hittest, &pos, tracking ); TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest );
if (info->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT)) diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 3a587199d13..3b93b4c97b2 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2565,14 +2565,14 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H { HWND orig = msg->hwnd;
- msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest ); + msg->hwnd = window_from_point( msg->hwnd, msg->pt, &hittest, TRUE ); if (!msg->hwnd) /* As a heuristic, try the next window if it's the owner of orig */ { HWND next = get_window_relative( orig, GW_HWNDNEXT );
if (next && get_window_relative( orig, GW_OWNER ) == next && is_current_thread_window( next )) - msg->hwnd = window_from_point( next, msg->pt, &hittest ); + msg->hwnd = window_from_point( next, msg->pt, &hittest, TRUE ); } }
@@ -2581,6 +2581,7 @@ static BOOL process_mouse_message( MSG *msg, UINT hw_id, ULONG_PTR extra_info, H accept_hardware_message( hw_id ); return FALSE; } + update_current_mouse_window( msg->hwnd, hittest, msg->pt );
msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); set_thread_dpi_awareness_context( get_window_dpi_awareness_context( msg->hwnd )); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 03a4e43f949..481816729b7 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -100,6 +100,9 @@ struct mouse_tracking_info { TRACKMOUSEEVENT info; POINT pos; /* center of hover rectangle */ + HWND last_mouse_message_hwnd; + int last_mouse_message_hittest; + POINT last_mouse_message_pos; };
/* this is the structure stored in TEB->Win32ClientInfo */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 69d7b5b5257..a9b39de6471 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -100,6 +100,7 @@ extern BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus, DW extern BOOL set_ime_composition_rect( HWND hwnd, RECT rect ); extern void toggle_caret( HWND hwnd ); extern void update_mouse_tracking_info( HWND hwnd ); +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 ); @@ -282,7 +283,7 @@ extern LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newv extern BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ); extern UINT set_window_style_bits( HWND hwnd, UINT set_bits, UINT clear_bits ); extern void update_window_state( HWND hwnd ); -extern HWND window_from_point( HWND hwnd, POINT pt, INT *hittest ); +extern HWND window_from_point( HWND hwnd, POINT pt, INT *hittest, BOOL send_nchittest ); extern HWND get_shell_window(void); extern HWND get_progman_window(void); extern HWND get_taskman_window(void); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 0363a00541f..07d53339a5e 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2628,7 +2628,7 @@ static HWND *list_children_from_point( HWND hwnd, POINT pt, UINT dpi ) * * Find the window and hittest for a given point. */ -HWND window_from_point( HWND hwnd, POINT pt, INT *hittest ) +HWND window_from_point( HWND hwnd, POINT pt, INT *hittest, BOOL send_nchittest ) { int i, res; HWND ret, *list; @@ -2655,7 +2655,7 @@ HWND window_from_point( HWND hwnd, POINT pt, INT *hittest ) break; } /* Send WM_NCCHITTEST (if same thread) */ - if (!is_current_thread_window( list[i] )) + if (!send_nchittest || !is_current_thread_window( list[i] )) { *hittest = HTCLIENT; break; @@ -2682,7 +2682,7 @@ HWND WINAPI NtUserWindowFromPoint( LONG x, LONG y ) { POINT pt = { .x = x, .y = y }; INT hittest; - return window_from_point( 0, pt, &hittest ); + return window_from_point( 0, pt, &hittest, TRUE ); }
/*******************************************************************