From 9519ff7b1256be73bb6cbec54679c5d09818bfaf Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Sun, 17 Jul 2011 15:30:12 +0000 Subject: [PATCH] [win32k] - Fix TrackMouseEvent. Now hot tracking really works svn path=/branches/GSoC_2011/ThemesSupport/; revision=52716 --- subsystems/win32/win32k/ntuser/input.c | 15 +---- subsystems/win32/win32k/ntuser/msgqueue.c | 78 +++++++++++++++++++---- subsystems/win32/win32k/ntuser/timer.c | 14 +++- 3 files changed, 80 insertions(+), 27 deletions(-) diff --git a/subsystems/win32/win32k/ntuser/input.c b/subsystems/win32/win32k/ntuser/input.c index 48b06297255..bb1f29914c6 100644 --- a/subsystems/win32/win32k/ntuser/input.c +++ b/subsystems/win32/win32k/ntuser/input.c @@ -1612,19 +1612,6 @@ IntTrackMouseEvent( if (!(pWnd = UserGetWindowObject(lpEventTrack->hwndTrack))) return FALSE; - if ( pDesk->spwndTrack != pWnd || - (pDesk->htEx != HTCLIENT) ^ !!(lpEventTrack->dwFlags & TME_NONCLIENT) ) - { - if ( lpEventTrack->dwFlags & TME_LEAVE && !(lpEventTrack->dwFlags & TME_CANCEL) ) - { - UserPostMessage( lpEventTrack->hwndTrack, - lpEventTrack->dwFlags & TME_NONCLIENT ? WM_NCMOUSELEAVE : WM_MOUSELEAVE, - 0, 0); - } - DPRINT("IntTrackMouseEvent spwndTrack 0x%x pwnd 0x%x\n", pDesk->spwndTrack,pWnd); - return TRUE; - } - /* Tracking spwndTrack same as pWnd */ if ( lpEventTrack->dwFlags & TME_CANCEL ) // Canceled mode. { @@ -1642,6 +1629,7 @@ IntTrackMouseEvent( } else // Not Canceled. { + pDesk->spwndTrack = pWnd; if ( lpEventTrack->dwFlags & TME_LEAVE ) pDesk->dwDTFlags |= DF_TME_LEAVE; @@ -1657,6 +1645,7 @@ IntTrackMouseEvent( IntSetTimer( pWnd, ID_EVENT_SYSTIMER_MOUSEHOVER, pDesk->dwMouseHoverTime, SystemTimerProc, TMRF_SYSTEM); // Get windows thread message points. point = pWnd->head.pti->ptLast; + DPRINT1("point: %d, %d\n", point.x, point.y); // Set desktop mouse hover from the system default hover rectangle. RECTL_vSetRect(&pDesk->rcMouseHover, point.x - gspv.iMouseHoverWidth / 2, diff --git a/subsystems/win32/win32k/ntuser/msgqueue.c b/subsystems/win32/win32k/ntuser/msgqueue.c index 42ef2d9b6d3..fce565da96a 100644 --- a/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/subsystems/win32/win32k/ntuser/msgqueue.c @@ -540,22 +540,35 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook if (pwnd) { - PWND pwndTrack = IntChildrenWindowFromPoint(pwnd, Msg->pt.x, Msg->pt.y); - - if ( pDesk->spwndTrack != pwndTrack && pDesk->dwDTFlags & (DF_TME_LEAVE|DF_TME_HOVER) ) + /* If we a re tracking the mouse and it moves to another top level window */ + if(pDesk->spwndTrack && + UserGetAncestor(pDesk->spwndTrack, GA_ROOT) != pwnd) { - if ( pDesk->dwDTFlags & DF_TME_LEAVE ) - UserPostMessage( UserHMGetHandle(pDesk->spwndTrack), - (pDesk->htEx != HTCLIENT) ? WM_NCMOUSELEAVE : WM_MOUSELEAVE, - 0, 0); + /* Generate a WM_MOUSELEAVE message */ + if ( pDesk->dwDTFlags & DF_TME_LEAVE ) + { + MSG msgMouseLeave; - if ( pDesk->dwDTFlags & DF_TME_HOVER ) - IntKillTimer(UserHMGetHandle(pDesk->spwndTrack), ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE); + DPRINT1("co_MsqInsertMouseMessage: generating WM_MOUSELEAVE\n"); - pDesk->dwDTFlags &= ~(DF_TME_LEAVE|DF_TME_HOVER); + msgMouseLeave.hwnd = UserHMGetHandle(pDesk->spwndTrack); + msgMouseLeave.message = WM_MOUSELEAVE; + msgMouseLeave.pt = Msg->pt; + msgMouseLeave.time = Msg->time; + msgMouseLeave.lParam = msgMouseLeave.wParam = 0; + + MsqPostMessage(pwnd->head.pti->MessageQueue, Msg, TRUE, QS_MOUSE); + } + + /* Stop tracking */ + if ( pDesk->dwDTFlags & DF_TME_HOVER ) + { + IntKillTimer(pDesk->spwndTrack, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE); + } + + pDesk->spwndTrack = NULL; + pDesk->htEx = 0; } - pDesk->spwndTrack = pwndTrack; - pDesk->htEx = GetNCHitEx(pDesk->spwndTrack, Msg->pt); } hdcScreen = IntGetScreenDC(); @@ -1287,6 +1300,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT PUSER_MESSAGE_QUEUE MessageQueue; PTHREADINFO pti; PSYSTEM_CURSORINFO CurInfo; + PDESKTOP pDesk; DECLARE_RETURN(BOOL); pti = PsGetCurrentThreadWin32Thread(); @@ -1295,6 +1309,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT CurInfo = IntGetSysCursorInfo(); pwndMsg = UserGetWindowObject(msg->hwnd); clk_msg = MessageQueue->msgDblClk; + pDesk = pwndDesktop->head.rpdesk; /* find the window to dispatch this mouse message to */ if (MessageQueue->CaptureWindow) @@ -1316,6 +1331,45 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT RETURN(FALSE); } + /* If we a re tracking the mouse and it moves to another window */ + if(pDesk->spwndTrack && + pDesk->spwndTrack != pwndMsg && + msg->message != WM_MOUSELEAVE) + { + /* Generate a WM_MOUSELEAVE message */ + if ( pDesk->dwDTFlags & DF_TME_LEAVE ) + { + MSG msgMouseLeave; + + DPRINT1("co_IntProcessMouseMessage: generating WM_MOUSELEAVE\n"); + + msgMouseLeave.hwnd = UserHMGetHandle(pDesk->spwndTrack); + msgMouseLeave.message = WM_MOUSELEAVE; + msgMouseLeave.pt = msg->pt; + msgMouseLeave.time = msg->time; + msgMouseLeave.lParam = msgMouseLeave.wParam = 0; + + MsqPostMessage(pwndMsg->head.pti->MessageQueue, + &msgMouseLeave, + TRUE, + QS_MOUSE); + } + + /* Stop tracking */ + if ( pDesk->dwDTFlags & DF_TME_HOVER ) + { + IntKillTimer(pDesk->spwndTrack, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE); + } + + pDesk->spwndTrack = NULL; + pDesk->htEx = 0; + } + + if(pDesk->spwndTrack) + { + pDesk->htEx = hittest; + } + msg->hwnd = UserHMGetHandle(pwndMsg); #if 0 diff --git a/subsystems/win32/win32k/ntuser/timer.c b/subsystems/win32/win32k/ntuser/timer.c index b7c4a32277b..ecef00cf88f 100644 --- a/subsystems/win32/win32k/ntuser/timer.c +++ b/subsystems/win32/win32k/ntuser/timer.c @@ -320,12 +320,13 @@ SystemTimerProc(HWND hwnd, POINT Point; UINT Msg; WPARAM wParam; - + pDesk = pWnd->head.rpdesk; if ( pDesk->dwDTFlags & DF_TME_HOVER && pWnd == pDesk->spwndTrack ) { - Point = gpsi->ptCursor; + Point = pWnd->head.pti->MessageQueue->MouseMoveMsg.pt; + DPRINT1("point: %d, %d\n", Point.x, Point.y); if ( IntPtInRect(&pDesk->rcMouseHover, Point) ) { if (pDesk->htEx == HTCLIENT) // In a client area. @@ -346,10 +347,19 @@ SystemTimerProc(HWND hwnd, wParam = pDesk->htEx; // Need to support all HTXYZ hits. Msg = WM_NCMOUSEHOVER; } + DPRINT1("Generating WM_NCMOUSEHOVER\n"); UserPostMessage(hwnd, Msg, wParam, MAKELPARAM(Point.x, Point.y)); pDesk->dwDTFlags &= ~DF_TME_HOVER; break; // Kill this timer. } + else + { + RECTL_vSetRect(&pDesk->rcMouseHover, + Point.x - gspv.iMouseHoverWidth / 2, + Point.y - gspv.iMouseHoverHeight / 2, + Point.x + gspv.iMouseHoverWidth / 2, + Point.y + gspv.iMouseHoverHeight / 2); + } } } return; // Not this window so just return.