From: Paul Gofman pgofman@codeweavers.com
--- dlls/user32/tests/msg.c | 8 +------- dlls/win32u/input.c | 39 ++++++++++++++++++++++++++++++------ dlls/win32u/message.c | 5 +++-- dlls/win32u/win32u_private.h | 3 ++- dlls/win32u/window.c | 6 +++--- 5 files changed, 42 insertions(+), 19 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 2b54e5087ec..a68508ae8f4 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; @@ -15187,7 +15181,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 c718bd1cbbc..a07cfd18d33 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1663,6 +1663,16 @@ struct tracking_list
/* FIXME: move tracking stuff into per-thread data */ static struct tracking_list tracking_info; +static HWND last_mouse_message_hwnd; +static int last_mouse_message_hittest; +static POINT last_mouse_message_pos; + +void update_current_mouse_window( HWND hwnd, INT hittest, POINT pos ) +{ + last_mouse_message_hwnd = hwnd; + last_mouse_message_hittest = hittest; + last_mouse_message_pos = pos; +}
static void check_mouse_leave( HWND hwnd, int hittest ) { @@ -1696,6 +1706,27 @@ static void check_mouse_leave( HWND hwnd, int hittest ) } }
+static HWND get_mouse_window( HWND hwnd, INT *hittest, POINT *ret_pos ) +{ + POINT pos; + HWND ret; + + NtUserGetCursorPos( &pos ); + ret = window_from_point( hwnd, pos, hittest, FALSE ); + if (ret == last_mouse_message_hwnd) + { + *hittest = last_mouse_message_hittest; + *ret_pos = last_mouse_message_pos; + } + else + { + 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 ) { int hover_width = 0, hover_height = 0, hittest; @@ -1703,10 +1734,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 );
NtUserSystemParametersInfo( SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0 ); NtUserSystemParametersInfo( SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0 ); @@ -1799,8 +1827,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 ); 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 d3ef83785bb..14000da9918 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2555,16 +2555,17 @@ 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 ); } } + update_current_mouse_window( msg->hwnd, hittest, msg->pt );
if (!msg->hwnd || !is_current_thread_window( msg->hwnd )) { 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 ); }
/*******************************************************************