Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/user32/input.c | 254 -----------------------------------
dlls/user32/scroll.c | 8 +-
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 1 -
dlls/user32/user_private.h | 1 -
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/input.c | 218 ++++++++++++++++++++++++++++++
dlls/win32u/message.c | 3 +-
dlls/win32u/ntuser_private.h | 1 -
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 2 +
dlls/win32u/wrappers.c | 6 +
include/ntuser.h | 1 +
13 files changed, 235 insertions(+), 265 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 4ef33ab2838..dcb46df22b5 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -49,32 +49,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
WINE_DECLARE_DEBUG_CHANNEL(keyboard);
-/***********************************************************************
- * get_key_state
- */
-static WORD get_key_state(void)
-{
- WORD ret = 0;
-
- if (GetSystemMetrics( SM_SWAPBUTTON ))
- {
- if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON;
- if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON;
- }
- else
- {
- if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON;
- if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON;
- }
- if (NtUserGetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON;
- if (NtUserGetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT;
- if (NtUserGetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL;
- if (NtUserGetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1;
- if (NtUserGetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2;
- return ret;
-}
-
-
/***********************************************************************
* get_locale_kbd_layout
*/
@@ -520,234 +494,6 @@ BOOL WINAPI UnloadKeyboardLayout( HKL layout )
return FALSE;
}
-typedef struct __TRACKINGLIST {
- TRACKMOUSEEVENT tme;
- POINT pos; /* center of hover rectangle */
-} _TRACKINGLIST;
-
-/* FIXME: move tracking stuff into a per thread data */
-static _TRACKINGLIST tracking_info;
-
-static void check_mouse_leave(HWND hwnd, int hittest)
-{
- if (tracking_info.tme.hwndTrack != hwnd)
- {
- if (tracking_info.tme.dwFlags & TME_NONCLIENT)
- PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0);
- else
- PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
-
- /* remove the TME_LEAVE flag */
- tracking_info.tme.dwFlags &= ~TME_LEAVE;
- }
- else
- {
- if (hittest == HTCLIENT)
- {
- if (tracking_info.tme.dwFlags & TME_NONCLIENT)
- {
- PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSELEAVE, 0, 0);
- /* remove the TME_LEAVE flag */
- tracking_info.tme.dwFlags &= ~TME_LEAVE;
- }
- }
- else
- {
- if (!(tracking_info.tme.dwFlags & TME_NONCLIENT))
- {
- PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
- /* remove the TME_LEAVE flag */
- tracking_info.tme.dwFlags &= ~TME_LEAVE;
- }
- }
- }
-}
-
-void CDECL update_mouse_tracking_info( HWND hwnd )
-{
- POINT pos;
- INT hoverwidth = 0, hoverheight = 0, hittest;
-
- TRACE( "hwnd %p\n", hwnd );
-
- GetCursorPos(&pos);
- hwnd = WINPOS_WindowFromPoint(hwnd, pos, &hittest);
-
- TRACE("point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest);
-
- SystemParametersInfoW(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
- SystemParametersInfoW(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
-
- TRACE("tracked pos %s, current pos %s, hover width %d, hover height %d\n",
- wine_dbgstr_point(&tracking_info.pos), wine_dbgstr_point(&pos),
- hoverwidth, hoverheight);
-
- /* see if this tracking event is looking for TME_LEAVE and that the */
- /* mouse has left the window */
- if (tracking_info.tme.dwFlags & TME_LEAVE)
- {
- check_mouse_leave(hwnd, hittest);
- }
-
- if (tracking_info.tme.hwndTrack != hwnd)
- {
- /* mouse is gone, stop tracking mouse hover */
- tracking_info.tme.dwFlags &= ~TME_HOVER;
- }
-
- /* see if we are tracking hovering for this hwnd */
- if (tracking_info.tme.dwFlags & TME_HOVER)
- {
- /* has the cursor moved outside the rectangle centered around pos? */
- if ((abs(pos.x - tracking_info.pos.x) > (hoverwidth / 2)) ||
- (abs(pos.y - tracking_info.pos.y) > (hoverheight / 2)))
- {
- /* record this new position as the current position */
- tracking_info.pos = pos;
- }
- else
- {
- if (hittest == HTCLIENT)
- {
- ScreenToClient(hwnd, &pos);
- TRACE("client cursor pos %s\n", wine_dbgstr_point(&pos));
-
- PostMessageW(tracking_info.tme.hwndTrack, WM_MOUSEHOVER,
- get_key_state(), MAKELPARAM( pos.x, pos.y ));
- }
- else
- {
- if (tracking_info.tme.dwFlags & TME_NONCLIENT)
- PostMessageW(tracking_info.tme.hwndTrack, WM_NCMOUSEHOVER,
- hittest, MAKELPARAM( pos.x, pos.y ));
- }
-
- /* stop tracking mouse hover */
- tracking_info.tme.dwFlags &= ~TME_HOVER;
- }
- }
-
- /* stop the timer if the tracking list is empty */
- if (!(tracking_info.tme.dwFlags & (TME_HOVER | TME_LEAVE)))
- {
- KillSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
- tracking_info.tme.hwndTrack = 0;
- tracking_info.tme.dwFlags = 0;
- tracking_info.tme.dwHoverTime = 0;
- }
-}
-
-
-/***********************************************************************
- * TrackMouseEvent [USER32]
- *
- * Requests notification of mouse events
- *
- * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
- * to the hwnd specified in the ptme structure. After the event message
- * is posted to the hwnd, the entry in the queue is removed.
- *
- * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
- * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
- * immediately and the TME_LEAVE flag being ignored.
- *
- * PARAMS
- * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
- *
- * RETURNS
- * Success: non-zero
- * Failure: zero
- *
- */
-
-BOOL WINAPI
-TrackMouseEvent (TRACKMOUSEEVENT *ptme)
-{
- HWND hwnd;
- POINT pos;
- DWORD hover_time;
- INT hittest;
-
- TRACE("%x, %x, %p, %u\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
-
- if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
- WARN("wrong TRACKMOUSEEVENT size from app\n");
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
- if (ptme->dwFlags & TME_QUERY )
- {
- *ptme = tracking_info.tme;
- /* set cbSize in the case it's not initialized yet */
- ptme->cbSize = sizeof(TRACKMOUSEEVENT);
-
- return TRUE; /* return here, TME_QUERY is retrieving information */
- }
-
- if (!IsWindow(ptme->hwndTrack))
- {
- SetLastError(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
- }
-
- hover_time = (ptme->dwFlags & TME_HOVER) ? ptme->dwHoverTime : HOVER_DEFAULT;
-
- /* if HOVER_DEFAULT was specified replace this with the system's current value.
- * TME_LEAVE doesn't need to specify hover time so use default */
- if (hover_time == HOVER_DEFAULT || hover_time == 0)
- SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0);
-
- GetCursorPos(&pos);
- hwnd = WINPOS_WindowFromPoint(ptme->hwndTrack, pos, &hittest);
- TRACE("point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest);
-
- if (ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT))
- FIXME("Unknown flag(s) %08x\n", ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT));
-
- if (ptme->dwFlags & TME_CANCEL)
- {
- if (tracking_info.tme.hwndTrack == ptme->hwndTrack)
- {
- tracking_info.tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
-
- /* if we aren't tracking on hover or leave remove this entry */
- if (!(tracking_info.tme.dwFlags & (TME_HOVER | TME_LEAVE)))
- {
- KillSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
- tracking_info.tme.hwndTrack = 0;
- tracking_info.tme.dwFlags = 0;
- tracking_info.tme.dwHoverTime = 0;
- }
- }
- } else {
- /* In our implementation it's possible that another window will receive a
- * WM_MOUSEMOVE and call TrackMouseEvent before TrackMouseEventProc is
- * called. In such a situation post the WM_MOUSELEAVE now */
- if (tracking_info.tme.dwFlags & TME_LEAVE && tracking_info.tme.hwndTrack != NULL)
- check_mouse_leave(hwnd, hittest);
-
- KillSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
- tracking_info.tme.hwndTrack = 0;
- tracking_info.tme.dwFlags = 0;
- tracking_info.tme.dwHoverTime = 0;
-
- if (ptme->hwndTrack == hwnd)
- {
- /* Adding new mouse event to the tracking list */
- tracking_info.tme = *ptme;
- tracking_info.tme.dwHoverTime = hover_time;
-
- /* Initialize HoverInfo variables even if not hover tracking */
- tracking_info.pos = pos;
-
- NtUserSetSystemTimer( tracking_info.tme.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE, hover_time );
- }
- }
-
- return TRUE;
-}
/***********************************************************************
* EnableMouseInPointer (USER32.@)
diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c
index 45980b75b2c..8f085364dab 100644
--- a/dlls/user32/scroll.c
+++ b/dlls/user32/scroll.c
@@ -864,12 +864,12 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_QUERY;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
if (!(tme.dwFlags & TME_LEAVE) || tme.hwndTrack != hwnd)
{
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hwnd;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
}
break;
@@ -883,12 +883,12 @@ void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_QUERY;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
if (((tme.dwFlags & (TME_NONCLIENT | TME_LEAVE)) != (TME_NONCLIENT | TME_LEAVE)) || tme.hwndTrack != hwnd)
{
tme.dwFlags = TME_NONCLIENT | TME_LEAVE;
tme.hwndTrack = hwnd;
- TrackMouseEvent( &tme );
+ NtUserTrackMouseEvent( &tme );
}
break;
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index a7b2f7e0681..f7f41621812 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -762,7 +762,7 @@
@ stdcall ToAsciiEx(long long ptr ptr long long)
@ stdcall ToUnicode(long long ptr ptr long long)
@ stdcall ToUnicodeEx(long long ptr ptr long long long) NtUserToUnicodeEx
-@ stdcall TrackMouseEvent(ptr)
+@ stdcall TrackMouseEvent(ptr) NtUserTrackMouseEvent
@ stdcall TrackPopupMenu(long long long long long long ptr)
@ stdcall TrackPopupMenuEx(long long long long long ptr)
@ stdcall TranslateAccelerator(long long ptr) TranslateAcceleratorA
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 08f2833ee3f..6e0722e4750 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -179,7 +179,6 @@ static const struct user_callbacks user_funcs =
SCROLL_SetStandardScrollPainted,
toggle_caret,
unpack_dde_message,
- update_mouse_tracking_info,
register_imm,
unregister_imm,
};
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 54b11f2a8ef..96c47a71753 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -100,7 +100,6 @@ extern void SYSPARAMS_Init(void) DECLSPEC_HIDDEN;
extern void USER_CheckNotLock(void) DECLSPEC_HIDDEN;
extern BOOL USER_IsExitingThread( DWORD tid ) DECLSPEC_HIDDEN;
extern void CDECL toggle_caret( HWND hwnd ) DECLSPEC_HIDDEN;
-extern void CDECL update_mouse_tracking_info( HWND hwnd ) DECLSPEC_HIDDEN;
typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
LRESULT *result, void *arg );
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index fbaf61a52f6..ed483d8f205 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1213,6 +1213,7 @@ static struct unix_funcs unix_funcs =
NtUserSystemParametersInfo,
NtUserSystemParametersInfoForDpi,
NtUserToUnicodeEx,
+ NtUserTrackMouseEvent,
NtUserTranslateMessage,
NtUserUnregisterClass,
NtUserUnregisterHotKey,
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index dd28170b1f0..61de034d7c8 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -1171,6 +1171,224 @@ int WINAPI NtUserGetMouseMovePointsEx( UINT size, MOUSEMOVEPOINT *ptin, MOUSEMOV
return copied;
}
+static WORD get_key_state(void)
+{
+ WORD ret = 0;
+
+ if (get_system_metrics( SM_SWAPBUTTON ))
+ {
+ if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON;
+ if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON;
+ }
+ else
+ {
+ if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON;
+ if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON;
+ }
+ if (NtUserGetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON;
+ if (NtUserGetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT;
+ if (NtUserGetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL;
+ if (NtUserGetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1;
+ if (NtUserGetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2;
+ return ret;
+}
+
+struct tracking_list
+{
+ TRACKMOUSEEVENT info;
+ POINT pos; /* center of hover rectangle */
+};
+
+/* FIXME: move tracking stuff into per-thread data */
+static struct tracking_list tracking_info;
+
+static void check_mouse_leave( HWND hwnd, int hittest )
+{
+ if (tracking_info.info.hwndTrack != hwnd)
+ {
+ if (tracking_info.info.dwFlags & TME_NONCLIENT)
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_NCMOUSELEAVE, 0, 0 );
+ else
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_MOUSELEAVE, 0, 0 );
+
+ tracking_info.info.dwFlags &= ~TME_LEAVE;
+ }
+ else
+ {
+ if (hittest == HTCLIENT)
+ {
+ if (tracking_info.info.dwFlags & TME_NONCLIENT)
+ {
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_NCMOUSELEAVE, 0, 0 );
+ tracking_info.info.dwFlags &= ~TME_LEAVE;
+ }
+ }
+ else
+ {
+ if (!(tracking_info.info.dwFlags & TME_NONCLIENT))
+ {
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_MOUSELEAVE, 0, 0 );
+ tracking_info.info.dwFlags &= ~TME_LEAVE;
+ }
+ }
+ }
+}
+
+void update_mouse_tracking_info( HWND hwnd )
+{
+ int hover_width = 0, hover_height = 0, hittest;
+ POINT pos;
+
+ TRACE( "hwnd %p\n", hwnd );
+
+ get_cursor_pos( &pos );
+ hwnd = window_from_point( hwnd, pos, &hittest );
+
+ TRACE( "point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest );
+
+ NtUserSystemParametersInfo( SPI_GETMOUSEHOVERWIDTH, 0, &hover_width, 0 );
+ NtUserSystemParametersInfo( SPI_GETMOUSEHOVERHEIGHT, 0, &hover_height, 0 );
+
+ TRACE( "tracked pos %s, current pos %s, hover width %d, hover height %d\n",
+ wine_dbgstr_point(&tracking_info.pos), wine_dbgstr_point(&pos),
+ hover_width, hover_height );
+
+ if (tracking_info.info.dwFlags & TME_LEAVE)
+ check_mouse_leave(hwnd, hittest);
+
+ if (tracking_info.info.hwndTrack != hwnd)
+ tracking_info.info.dwFlags &= ~TME_HOVER;
+
+ if (tracking_info.info.dwFlags & TME_HOVER)
+ {
+ /* has the cursor moved outside the rectangle centered around pos? */
+ if ((abs( pos.x - tracking_info.pos.x ) > (hover_width / 2)) ||
+ (abs( pos.y - tracking_info.pos.y ) > (hover_height / 2)))
+ {
+ tracking_info.pos = pos;
+ }
+ else
+ {
+ if (hittest == HTCLIENT)
+ {
+ screen_to_client(hwnd, &pos);
+ TRACE( "client cursor pos %s\n", wine_dbgstr_point(&pos) );
+
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_MOUSEHOVER,
+ get_key_state(), MAKELPARAM( pos.x, pos.y ) );
+ }
+ else
+ {
+ if (tracking_info.info.dwFlags & TME_NONCLIENT)
+ NtUserPostMessage( tracking_info.info.hwndTrack, WM_NCMOUSEHOVER,
+ hittest, MAKELPARAM( pos.x, pos.y ) );
+ }
+
+ /* stop tracking mouse hover */
+ tracking_info.info.dwFlags &= ~TME_HOVER;
+ }
+ }
+
+ /* stop the timer if the tracking list is empty */
+ if (!(tracking_info.info.dwFlags & (TME_HOVER | TME_LEAVE)))
+ {
+ kill_system_timer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
+ tracking_info.info.hwndTrack = 0;
+ tracking_info.info.dwFlags = 0;
+ tracking_info.info.dwHoverTime = 0;
+ }
+}
+
+/***********************************************************************
+ * NtUserTrackMouseEvent (win32u.@)
+ */
+BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info )
+{
+ DWORD hover_time;
+ int hittest;
+ HWND hwnd;
+ POINT pos;
+
+ TRACE( "size %u, flags %#x, hwnd %p, time %u\n",
+ info->cbSize, info->dwFlags, info->hwndTrack, info->dwHoverTime );
+
+ if (info->cbSize != sizeof(TRACKMOUSEEVENT))
+ {
+ WARN( "wrong size %u\n", info->cbSize );
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if (info->dwFlags & TME_QUERY)
+ {
+ *info = tracking_info.info;
+ info->cbSize = sizeof(TRACKMOUSEEVENT);
+ return TRUE;
+ }
+
+ if (!is_window( info->hwndTrack ))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return FALSE;
+ }
+
+ hover_time = (info->dwFlags & TME_HOVER) ? info->dwHoverTime : HOVER_DEFAULT;
+
+ if (hover_time == HOVER_DEFAULT || hover_time == 0)
+ NtUserSystemParametersInfo( SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0 );
+
+ get_cursor_pos( &pos );
+ hwnd = window_from_point( info->hwndTrack, pos, &hittest );
+ 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))
+ FIXME( "ignoring flags %#x\n", info->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT) );
+
+ if (info->dwFlags & TME_CANCEL)
+ {
+ if (tracking_info.info.hwndTrack == info->hwndTrack)
+ {
+ tracking_info.info.dwFlags &= ~(info->dwFlags & ~TME_CANCEL);
+
+ /* if we aren't tracking on hover or leave remove this entry */
+ if (!(tracking_info.info.dwFlags & (TME_HOVER | TME_LEAVE)))
+ {
+ kill_system_timer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
+ tracking_info.info.hwndTrack = 0;
+ tracking_info.info.dwFlags = 0;
+ tracking_info.info.dwHoverTime = 0;
+ }
+ }
+ }
+ else
+ {
+ /* In our implementation, it's possible that another window will receive
+ * WM_MOUSEMOVE and call TrackMouseEvent before TrackMouseEventProc is
+ * called. In such a situation, post the WM_MOUSELEAVE now. */
+ if ((tracking_info.info.dwFlags & TME_LEAVE) && tracking_info.info.hwndTrack != NULL)
+ check_mouse_leave(hwnd, hittest);
+
+ kill_system_timer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE );
+ tracking_info.info.hwndTrack = 0;
+ tracking_info.info.dwFlags = 0;
+ tracking_info.info.dwHoverTime = 0;
+
+ if (info->hwndTrack == hwnd)
+ {
+ /* Adding new mouse event to the tracking list */
+ tracking_info.info = *info;
+ tracking_info.info.dwHoverTime = hover_time;
+
+ /* Initialize HoverInfo variables even if not hover tracking */
+ tracking_info.pos = pos;
+
+ NtUserSetSystemTimer( tracking_info.info.hwndTrack, SYSTEM_TIMER_TRACK_MOUSE, hover_time );
+ }
+ }
+
+ return TRUE;
+}
+
/**********************************************************************
* set_capture_window
*/
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c
index 02644e71929..8ad4a0271b3 100644
--- a/dlls/win32u/message.c
+++ b/dlls/win32u/message.c
@@ -2479,8 +2479,7 @@ LRESULT dispatch_message( const MSG *msg, BOOL ansi )
return 0;
case SYSTEM_TIMER_TRACK_MOUSE:
- if (!user_callbacks) break;
- user_callbacks->update_mouse_tracking_info( msg->hwnd );
+ update_mouse_tracking_info( msg->hwnd );
return 0;
}
}
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 604817708c7..cad038dbff6 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -54,7 +54,6 @@ struct user_callbacks
void (CDECL *toggle_caret)( HWND hwnd );
BOOL (CDECL *unpack_dde_message)( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
void **buffer, size_t size );
- void (CDECL *update_mouse_tracking_info)( HWND hwnd );
BOOL (WINAPI *register_imm)( HWND hwnd );
void (WINAPI *unregister_imm)( HWND hwnd );
};
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index aa40be5f652..265e2ca808b 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1277,7 +1277,7 @@
@ stdcall -syscall NtUserThunkedMenuInfo(long ptr)
@ stub NtUserThunkedMenuItemInfo
@ stdcall NtUserToUnicodeEx(long long ptr ptr long long long)
-@ stub NtUserTrackMouseEvent
+@ stdcall NtUserTrackMouseEvent(ptr)
@ stub NtUserTrackPopupMenuEx
@ stub NtUserTransformPoint
@ stub NtUserTransformRect
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 4c1b0a7b45b..d13958e8449 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -287,6 +287,7 @@ struct unix_funcs
UINT winini, UINT dpi );
INT (WINAPI *pNtUserToUnicodeEx)( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
+ BOOL (WINAPI *pNtUserTrackMouseEvent)( TRACKMOUSEEVENT *info );
BOOL (WINAPI *pNtUserTranslateMessage)( const MSG *msg, UINT flags );
BOOL (WINAPI *pNtUserUnregisterClass)( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name );
@@ -357,6 +358,7 @@ extern DWORD get_input_state(void) DECLSPEC_HIDDEN;
extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ) DECLSPEC_HIDDEN;
+extern void update_mouse_tracking_info( HWND hwnd ) DECLSPEC_HIDDEN;
/* menu.c */
extern HMENU create_menu( BOOL is_popup ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index d3497d29f03..8ac82139dd0 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1210,6 +1210,12 @@ INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
return unix_funcs->pNtUserToUnicodeEx( virt, scan, state, str, size, flags, layout );
}
+BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserTrackMouseEvent( info );
+}
+
BOOL WINAPI NtUserTranslateMessage( const MSG *msg, UINT flags )
{
if (!unix_funcs) return 0;
diff --git a/include/ntuser.h b/include/ntuser.h
index d06b76ab605..aa2683fc451 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -586,6 +586,7 @@ BOOL WINAPI NtUserSystemParametersInfoForDpi( UINT action, UINT val, PVOID pt
BOOL WINAPI NtUserThunkedMenuInfo( HMENU menu, const MENUINFO *info );
INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
+BOOL WINAPI NtUserTrackMouseEvent( TRACKMOUSEEVENT *info );
INT WINAPI NtUserTranslateAccelerator( HWND hwnd, HACCEL accel, MSG *msg );
BOOL WINAPI NtUserTranslateMessage( const MSG *msg, UINT flags );
BOOL WINAPI NtUserUnhookWinEvent( HWINEVENTHOOK hEventHook );
--
2.35.1