Author: gadamopoulos Date: Mon Nov 22 20:10:56 2010 New Revision: 49710
URL: http://svn.reactos.org/svn/reactos?rev=49710&view=rev Log: [win32k] - Fix one of the greatest hacks in message handling: do not wake up every message queue when there is mouse or keyboard input ( wake only the thread that must take input) - rewrite co_WinPosWindowFromPoint, co_MsqInsertMouseMessage and co_MsqPeekHardwareMessage - port co_IntProcessMouseMessage and MsqSendParentNotify from wine - call co_IntProcessHardwareMessage from co_MsqPeekHardwareMessage, and not from co_IntPeekMessage - move co_IntProcessHardwareMessage, co_IntProcessKeyboardMessage and co_IntProcessMouseMessage to msgqueue.c
Modified: trunk/reactos/subsystems/win32/win32k/include/msgqueue.h trunk/reactos/subsystems/win32/win32k/include/winpos.h trunk/reactos/subsystems/win32/win32k/ntuser/message.c trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c trunk/reactos/subsystems/win32/win32k/ntuser/window.c trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c
Modified: trunk/reactos/subsystems/win32/win32k/include/msgqueue.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] Mon Nov 22 20:10:56 2010 @@ -58,8 +58,12 @@ LIST_ENTRY HardwareMessagesListHead; /* Lock for the hardware message list. */ KMUTEX HardwareLock; - /* Pointer to the current WM_MOUSEMOVE message */ - PUSER_MESSAGE MouseMoveMsg; + /* True if a WM_MOUSEMOVE is pending */ + BOOLEAN MouseMoved; + /* Current WM_MOUSEMOVE message */ + MSG MouseMoveMsg; + /* Last click message for translating double clicks */ + MSG msgDblClk; /* True if a WM_QUIT message is pending. */ BOOLEAN QuitPosted; /* The quit exit code. */ @@ -122,18 +126,25 @@ MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode); BOOLEAN APIENTRY MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, - IN BOOLEAN Remove, - IN PWND Window, - IN UINT MsgFilterLow, - IN UINT MsgFilterHigh, - OUT PMSG Message); + IN BOOLEAN Remove, + IN PWND Window, + IN UINT MsgFilterLow, + IN UINT MsgFilterHigh, + OUT PMSG Message); BOOL APIENTRY co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, - IN BOOL Remove, - IN PWND Window, - IN UINT MsgFilterLow, - IN UINT MsgFilterHigh, - OUT MSG* pMsg); + IN BOOL Remove, + IN PWND Window, + IN UINT MsgFilterLow, + IN UINT MsgFilterHigh, + OUT MSG* pMsg); +BOOL APIENTRY +co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue, + IN BOOL Remove, + IN PWND Window, + IN UINT MsgFilterLow, + IN UINT MsgFilterHigh, + OUT MSG* pMsg); BOOLEAN FASTCALL MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQueue); VOID FASTCALL
Modified: trunk/reactos/subsystems/win32/win32k/include/winpos.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/winpos.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/winpos.h [iso-8859-1] Mon Nov 22 20:10:56 2010 @@ -27,9 +27,8 @@ co_WinPosShowWindow(PWND Window, INT Cmd); void FASTCALL co_WinPosSendSizeMove(PWND Window); -USHORT FASTCALL -co_WinPosWindowFromPoint(PWND ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *WinPoint, - PWND* Window); +PWND FASTCALL +co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest); VOID FASTCALL co_WinPosActivateOtherWindow(PWND Window);
VOID FASTCALL WinPosInitInternalPos(PWND WindowObject,
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] Mon Nov 22 20:10:56 2010 @@ -502,387 +502,6 @@ return retval; }
-VOID FASTCALL -co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg) -{ - if(!Msg->hwnd || ThreadQueue->CaptureWindow) - { - return; - } - - switch(Msg->message) - { - case WM_MOUSEMOVE: - { - co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message)); - break; - } - case WM_NCMOUSEMOVE: - { - co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message)); - break; - } - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_XBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_XBUTTONDBLCLK: - { - WPARAM wParam; - PSYSTEM_CURSORINFO CurInfo; - CurInfo = IntGetSysCursorInfo(); - - wParam = (WPARAM)(CurInfo->ButtonsDown); - - co_IntSendMessage(Msg->hwnd, WM_MOUSEMOVE, wParam, Msg->lParam); - co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message)); - break; - } - case WM_NCLBUTTONDOWN: - case WM_NCMBUTTONDOWN: - case WM_NCRBUTTONDOWN: - case WM_NCXBUTTONDOWN: - case WM_NCLBUTTONDBLCLK: - case WM_NCMBUTTONDBLCLK: - case WM_NCRBUTTONDBLCLK: - case WM_NCXBUTTONDBLCLK: - { - co_IntSendMessage(Msg->hwnd, WM_NCMOUSEMOVE, (WPARAM)Msg->wParam, Msg->lParam); - co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message)); - break; - } - } -} - -BOOL FASTCALL -co_IntActivateWindowMouse( PUSER_MESSAGE_QUEUE ThreadQueue, - LPMSG Msg, - PWND MsgWindow, - USHORT *HitTest) -{ - ULONG Result; - PWND Parent; - - ASSERT_REFS_CO(MsgWindow); - - if(*HitTest == (USHORT)HTTRANSPARENT) - { - /* eat the message, search again! */ - return TRUE; - } - - Parent = IntGetParent(MsgWindow);//fixme: deref retval? - - /* If no parent window, pass MsgWindows HWND as wParam. Fixes bug #3111 */ - Result = co_IntSendMessage(MsgWindow->head.h, - WM_MOUSEACTIVATE, - (WPARAM) (Parent ? Parent->head.h : MsgWindow->head.h), - (LPARAM)MAKELONG(*HitTest, Msg->message) - ); - - switch (Result) - { - case MA_NOACTIVATEANDEAT: - return TRUE; - case MA_NOACTIVATE: - break; - case MA_ACTIVATEANDEAT: - co_IntMouseActivateWindow(MsgWindow); - return TRUE; - default: - /* MA_ACTIVATE */ - co_IntMouseActivateWindow(MsgWindow); - break; - } - - return FALSE; -} - -BOOL FASTCALL -co_IntTranslateMouseMessage( PUSER_MESSAGE_QUEUE ThreadQueue, - LPMSG Msg, - USHORT *HitTest, - BOOL Remove) -{ - PWND Window; - USER_REFERENCE_ENTRY Ref, DesktopRef; - - if(!(Window = UserGetWindowObject(Msg->hwnd))) - { - /* let's just eat the message?! */ - return TRUE; - } - - *HitTest = HTCLIENT; - - UserRefObjectCo(Window, &Ref); - - if ( ThreadQueue == Window->head.pti->MessageQueue && - ThreadQueue->CaptureWindow != Window->head.h) - { - /* only send WM_NCHITTEST messages if we're not capturing the window! */ - if (Remove ) - { - *HitTest = co_IntSendMessage(Window->head.h, WM_NCHITTEST, 0, - MAKELONG(Msg->pt.x, Msg->pt.y)); - } - /* else we are going to see this message again, but then with Remove == TRUE */ - - if (*HitTest == (USHORT)HTTRANSPARENT) - { - PWND DesktopWindow; - HWND hDesktop = IntGetDesktopWindow(); - - if ((DesktopWindow = UserGetWindowObject(hDesktop))) - { - PWND Wnd; - - UserRefObjectCo(DesktopWindow, &DesktopRef); - - co_WinPosWindowFromPoint(DesktopWindow, Window->head.pti->MessageQueue, &Msg->pt, &Wnd); - if (Wnd) - { - if (Wnd != Window) - { - /* post the message to the other window */ - Msg->hwnd = Wnd->head.h; - if(!(Wnd->state & WNDS_DESTROYED)) - { - MsqPostMessage(Wnd->head.pti->MessageQueue, Msg, FALSE, - Msg->message == WM_MOUSEMOVE ? QS_MOUSEMOVE : - QS_MOUSEBUTTON); - } - - /* eat the message */ - UserDereferenceObject(Wnd); - UserDerefObjectCo(DesktopWindow); - UserDerefObjectCo(Window); - return TRUE; - } - UserDereferenceObject(Wnd); - } - - UserDerefObjectCo(DesktopWindow); - } - } - } - - if ( gspv.bMouseClickLock && - ((Msg->message == WM_LBUTTONUP) || - (Msg->message == WM_LBUTTONDOWN) ) ) - { - if (MsqIsClkLck(Msg, Remove)) - { - // FIXME: drop the message, hack: use WM_NULL - Msg->message = WM_NULL; - } - } - - if (IS_BTN_MESSAGE(Msg->message, DOWN)) - { - /* generate double click messages, if necessary */ - if ((((*HitTest) != HTCLIENT) || - (Window->pcls->style & CS_DBLCLKS)) && - MsqIsDblClk(Msg, Remove)) - { - Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN; - } - } - - if(Msg->message != WM_MOUSEWHEEL) - { - - if ((*HitTest) != HTCLIENT) - { - Msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE; - if ( (Msg->message == WM_NCRBUTTONUP) && - (((*HitTest) == HTCAPTION) || ((*HitTest) == HTSYSMENU)) ) - { - Msg->message = WM_CONTEXTMENU; - Msg->wParam = (WPARAM)Window->head.h; - } - else - { - Msg->wParam = *HitTest; - } - Msg->lParam = MAKELONG(Msg->pt.x, Msg->pt.y); - } - else if ( ThreadQueue->MoveSize == NULL && - ThreadQueue->MenuOwner == NULL ) - { - /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */ - Msg->lParam = MAKELONG( - Msg->pt.x - (WORD)Window->rcClient.left, - Msg->pt.y - (WORD)Window->rcClient.top); - } - } - - UserDerefObjectCo(Window); - return FALSE; -} - -BOOL ProcessMouseMessage(MSG* Msg, BOOLEAN RemoveMessages) -{ - MOUSEHOOKSTRUCT MHook; - EVENTMSG Event; - PTHREADINFO pti; - PUSER_MESSAGE_QUEUE ThreadQueue; - USER_REFERENCE_ENTRY Ref; - USHORT HitTest = HTNOWHERE; - - pti = PsGetCurrentThreadWin32Thread(); - ThreadQueue = pti->MessageQueue; - - if(RemoveMessages) - { - PWND MsgWindow = NULL; - - /* Mouse message process */ - - if( Msg->hwnd && - ( MsgWindow = UserGetWindowObject(Msg->hwnd) ) && - Msg->message >= WM_MOUSEFIRST && - Msg->message <= WM_MOUSELAST ) - { - USHORT HitTest; - - UserRefObjectCo(MsgWindow, &Ref); - - if ( co_IntTranslateMouseMessage( ThreadQueue, - Msg, - &HitTest, - TRUE)) - /* FIXME - check message filter again, if the message doesn't match anymore, - search again */ - { - UserDerefObjectCo(MsgWindow); - /* eat the message, search again */ - return FALSE; - } - - if(ThreadQueue->CaptureWindow == NULL) - { - co_IntSendHitTestMessages(ThreadQueue, Msg); - - if ( ( Msg->message != WM_MOUSEMOVE && - Msg->message != WM_NCMOUSEMOVE ) && - IS_BTN_MESSAGE(Msg->message, DOWN) && - co_IntActivateWindowMouse(ThreadQueue, Msg, MsgWindow, &HitTest) ) - { - UserDerefObjectCo(MsgWindow); - /* eat the message, search again */ - return FALSE; - } - } - - UserDerefObjectCo(MsgWindow); - } - else - { - co_IntSendHitTestMessages(ThreadQueue, Msg); - } - - return TRUE; - } - - if ( ( Msg->hwnd && - Msg->message >= WM_MOUSEFIRST && - Msg->message <= WM_MOUSELAST ) && - co_IntTranslateMouseMessage( ThreadQueue, - Msg, - &HitTest, - FALSE) ) - /* FIXME - check message filter again, if the message doesn't match anymore, - search again */ - { - /* eat the message, search again */ - return FALSE; - } - - pti->rpdesk->htEx = HitTest; /* Now set the capture hit. */ - - Event.message = Msg->message; - Event.time = Msg->time; - Event.hwnd = Msg->hwnd; - Event.paramL = Msg->pt.x; - Event.paramH = Msg->pt.y; - co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event); - - - MHook.pt = Msg->pt; - MHook.hwnd = Msg->hwnd; - MHook.wHitTestCode = HitTest; - MHook.dwExtraInfo = 0; - if (co_HOOK_CallHooks( WH_MOUSE, - RemoveMessages ? HC_ACTION : HC_NOREMOVE, - Msg->message, - (LPARAM)&MHook )) - { - MHook.pt = Msg->pt; - MHook.hwnd = Msg->hwnd; - MHook.wHitTestCode = HitTest; - MHook.dwExtraInfo = 0; - co_HOOK_CallHooks( WH_CBT, - HCBT_CLICKSKIPPED, - Msg->message, - (LPARAM)&MHook); - DPRINT1("MouseMessage WH_CBT Call Hook return!\n"); - return FALSE; - } - - return TRUE; -} - -BOOL ProcessKeyboardMessage(MSG* Msg, BOOLEAN RemoveMessages) -{ - EVENTMSG Event; - - Event.message = Msg->message; - Event.hwnd = Msg->hwnd; - Event.time = Msg->time; - Event.paramL = (Msg->wParam & 0xFF) | (HIWORD(Msg->lParam) << 8); - Event.paramH = Msg->lParam & 0x7FFF; - if (HIWORD(Msg->lParam) & 0x0100) Event.paramH |= 0x8000; - co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event); - - if (co_HOOK_CallHooks( WH_KEYBOARD, - RemoveMessages ? HC_ACTION : HC_NOREMOVE, - LOWORD(Msg->wParam), - Msg->lParam)) - { - /* skip this message */ - co_HOOK_CallHooks( WH_CBT, - HCBT_KEYSKIPPED, - LOWORD(Msg->wParam), - Msg->lParam ); - DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n"); - return FALSE; - } - return TRUE; -} - -BOOL ProcessHardwareMessage(MSG* Msg, BOOLEAN RemoveMessages) -{ - if ( IS_MOUSE_MESSAGE(Msg->message)) - { - if (!ProcessMouseMessage(Msg, RemoveMessages)) - { - return FALSE; - } - } - else if ( IS_KBD_MESSAGE(Msg->message)) - { - if(!ProcessKeyboardMessage(Msg, RemoveMessages)) - { - return FALSE; - } - } - - return TRUE; -} /* * Internal version of PeekMessage() doing all the work */ @@ -933,27 +552,33 @@
/* Now check for normal messages. */ if (MsqPeekMessage( ThreadQueue, - RemoveMessages, - Window, - MsgFilterMin, - MsgFilterMax, - Msg )) + RemoveMessages, + Window, + MsgFilterMin, + MsgFilterMax, + Msg )) { return TRUE; }
/* Check for hardware events. */ - if(co_MsqPeekHardwareMessage( ThreadQueue, + if(co_MsqPeekMouseMove(ThreadQueue, + RemoveMessages, + Window, + MsgFilterMin, + MsgFilterMax, + Msg )) + { + return TRUE; + } + + if(co_MsqPeekHardwareMessage(ThreadQueue, RemoveMessages, Window, MsgFilterMin, MsgFilterMax, Msg)) { - - if(!ProcessHardwareMessage(Msg, RemoveMessages)) - continue; - return TRUE; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] Mon Nov 22 20:10:56 2010 @@ -22,6 +22,8 @@ * PURPOSE: Message queues * FILE: subsystems/win32/win32k/ntuser/msgqueue.c * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + Alexandre Julliard + Maarten Lankhorst * REVISION HISTORY: * 06-06-2001 CSH Created */ @@ -35,30 +37,7 @@
/* GLOBALS *******************************************************************/
-#define SYSTEM_MESSAGE_QUEUE_SIZE (256) - -static MSG SystemMessageQueue[SYSTEM_MESSAGE_QUEUE_SIZE]; -static ULONG SystemMessageQueueHead = 0; -static ULONG SystemMessageQueueTail = 0; -static ULONG SystemMessageQueueCount = 0; -static KSPIN_LOCK SystemMessageQueueLock; - -static ULONG volatile HardwareMessageQueueStamp = 0; -static LIST_ENTRY HardwareMessageQueueHead; -static KMUTANT HardwareMessageQueueLock; - -static KEVENT HardwareMessageEvent; - static PAGED_LOOKASIDE_LIST MessageLookasideList; - -#define IntLockSystemMessageQueue(OldIrql) \ - KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql) - -#define IntUnLockSystemMessageQueue(OldIrql) \ - KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql) - -#define IntUnLockSystemHardwareMessageQueueLock(Wait) \ - KeReleaseMutant(&HardwareMessageQueueLock, IO_NO_INCREMENT, FALSE, Wait)
/* FUNCTIONS *****************************************************************/
@@ -135,12 +114,6 @@ NTAPI MsqInitializeImpl(VOID) { - /*CurrentFocusMessageQueue = NULL;*/ - InitializeListHead(&HardwareMessageQueueHead); - KeInitializeEvent(&HardwareMessageEvent, NotificationEvent, 0); - KeInitializeSpinLock(&SystemMessageQueueLock); - KeInitializeMutant(&HardwareMessageQueueLock, 0); - ExInitializePagedLookasideList(&MessageLookasideList, NULL, NULL, @@ -153,12 +126,19 @@ }
VOID FASTCALL +MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg) +{ + MessageQueue->MouseMoveMsg = *Msg; + MessageQueue->MouseMoved = TRUE; + MsqWakeQueue(MessageQueue, QS_MOUSEMOVE); +} + +VOID FASTCALL co_MsqInsertMouseMessage(MSG* Msg) { LARGE_INTEGER LargeTickCount; - KIRQL OldIrql; - ULONG Prev; MSLLHOOKSTRUCT MouseHookData; + PWND pwnd, pwndDesktop;
KeQueryTickCount(&LargeTickCount); Msg->time = MsqCalculateMessageTime(&LargeTickCount); @@ -191,556 +171,47 @@ if (co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION, Msg->message, (LPARAM) &MouseHookData)) return;
- /* - * If we got WM_MOUSEMOVE and there are already messages in the - * system message queue, check if the last message is mouse move - * and if it is then just overwrite it. - */ - IntLockSystemMessageQueue(OldIrql); - - /* - * Bail out if the queue is full. FIXME: We should handle this case - * more gracefully. - */ - - if (SystemMessageQueueCount == SYSTEM_MESSAGE_QUEUE_SIZE) - { - IntUnLockSystemMessageQueue(OldIrql); - return; - } - - if (Msg->message == WM_MOUSEMOVE && SystemMessageQueueCount) - { - if (SystemMessageQueueTail == 0) - Prev = SYSTEM_MESSAGE_QUEUE_SIZE - 1; - else - Prev = SystemMessageQueueTail - 1; - if (SystemMessageQueue[Prev].message == WM_MOUSEMOVE) - { - SystemMessageQueueTail = Prev; - SystemMessageQueueCount--; - } - } - - /* - * Actually insert the message into the system message queue. - */ - - SystemMessageQueue[SystemMessageQueueTail] = *Msg; - SystemMessageQueueTail = - (SystemMessageQueueTail + 1) % SYSTEM_MESSAGE_QUEUE_SIZE; - SystemMessageQueueCount++; - - IntUnLockSystemMessageQueue(OldIrql); - - KeSetEvent(&HardwareMessageEvent, IO_NO_INCREMENT, FALSE); -} - -BOOL FASTCALL -MsqIsClkLck(LPMSG Msg, BOOL Remove) -{ - PTHREADINFO pti; - PSYSTEM_CURSORINFO CurInfo; - BOOL Res = FALSE; - - pti = PsGetCurrentThreadWin32Thread(); - if (pti->rpdesk == NULL) - { - return FALSE; - } - - CurInfo = IntGetSysCursorInfo(); - - switch (Msg->message) - { - case WM_LBUTTONUP: - Res = ((Msg->time - CurInfo->ClickLockTime) >= gspv.dwMouseClickLockTime); - if (Res && (!CurInfo->ClickLockActive)) + /* Get the desktop window */ + pwndDesktop = UserGetDesktopWindow(); + if(!pwndDesktop) + return; + + /* Check if the mouse is captured */ + Msg->hwnd = IntGetCaptureWindow(); + if(Msg->hwnd != NULL) + { + pwnd = UserGetWindowObject(Msg->hwnd); + } + else + { + /* Loop all top level windows to find which one should receive input */ + for( pwnd = pwndDesktop->spwndChild; + pwnd != NULL; + pwnd = pwnd->spwndNext ) { - CurInfo->ClickLockActive = TRUE; + if((pwnd->style & WS_VISIBLE) && + IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y)) + { + Msg->hwnd = pwnd->head.h; + break; + } } - break; - case WM_LBUTTONDOWN: - if (CurInfo->ClickLockActive) + } + + /* Check if we found a window */ + if(Msg->hwnd != NULL && pwnd != NULL) + { + if(Msg->message == WM_MOUSEMOVE) { - Res = TRUE; - CurInfo->ClickLockActive = FALSE; - CurInfo->ClickLockTime = 0; + /* Mouse move is a special case*/ + MsqPostMouseMove(pwnd->head.pti->MessageQueue, Msg); } else { - CurInfo->ClickLockTime = Msg->time; + DPRINT("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd)); + MsqPostMessage(pwnd->head.pti->MessageQueue, Msg, TRUE, QS_MOUSEBUTTON); } - break; - } - return Res; -} - -BOOL FASTCALL -MsqIsDblClk(LPMSG Msg, BOOL Remove) -{ - PTHREADINFO pti; - PSYSTEM_CURSORINFO CurInfo; - LONG dX, dY; - BOOL Res; - - pti = PsGetCurrentThreadWin32Thread(); - if (pti->rpdesk == NULL) - { - return FALSE; - } - - CurInfo = IntGetSysCursorInfo(); - Res = (Msg->hwnd == (HWND)CurInfo->LastClkWnd) && - ((Msg->time - CurInfo->LastBtnDown) < gspv.iDblClickTime); - if(Res) - { - - dX = CurInfo->LastBtnDownX - Msg->pt.x; - dY = CurInfo->LastBtnDownY - Msg->pt.y; - if(dX < 0) - dX = -dX; - if(dY < 0) - dY = -dY; - - Res = (dX <= gspv.iDblClickWidth) && - (dY <= gspv.iDblClickHeight); - - if(Res) - { - if(CurInfo->ButtonsDown) - Res = (CurInfo->ButtonsDown == Msg->message); - } - } - - if(Remove) - { - CurInfo->LastBtnDownX = Msg->pt.x; - CurInfo->LastBtnDownY = Msg->pt.y; - CurInfo->ButtonsDown = Msg->message; - if (Res) - { - CurInfo->LastBtnDown = 0; - CurInfo->LastClkWnd = NULL; - } - else - { - CurInfo->LastClkWnd = (HANDLE)Msg->hwnd; - CurInfo->LastBtnDown = Msg->time; - } - } - - return Res; -} - -static BOOL APIENTRY -co_MsqTranslateMouseMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWND Window, UINT FilterLow, UINT FilterHigh, - PUSER_MESSAGE Message, BOOL Remove, PBOOL Freed, - PWND ScopeWin, PPOINT ScreenPoint, BOOL FromGlobalQueue, PLIST_ENTRY *Next) -{ - USHORT Msg = Message->Msg.message; - PWND CaptureWindow = NULL; - HWND hCaptureWin; - - /* FIXME: Mouse message can be sent before the Desktop is up and running in which case ScopeWin (Desktop) is 0. - Is this the best fix? */ - if (ScopeWin == 0) return FALSE; - - ASSERT_REFS_CO(ScopeWin); - - /* - co_WinPosWindowFromPoint can return a Window, and in that case - that window has a ref that we need to deref. Thats why we add "dummy" - refs in all other cases. - */ - - hCaptureWin = IntGetCaptureWindow(); - if (hCaptureWin == NULL) - { - if (Msg == WM_MOUSEWHEEL) - { - CaptureWindow = UserGetWindowObject(IntGetFocusWindow()); - if (CaptureWindow) UserReferenceObject(CaptureWindow); - } - else - { - co_WinPosWindowFromPoint(ScopeWin, NULL, &Message->Msg.pt, &CaptureWindow); - if(CaptureWindow == NULL) - { - CaptureWindow = ScopeWin; - if (CaptureWindow) UserReferenceObject(CaptureWindow); - } - else - { - /* this is the one case where we dont add a ref, since the returned - window is already referenced */ - } - } - } - else - { - /* FIXME - window messages should go to the right window if no buttons are - pressed */ - CaptureWindow = UserGetWindowObject(hCaptureWin); - if (CaptureWindow) UserReferenceObject(CaptureWindow); - } - - - - if (CaptureWindow == NULL) - { - if(!FromGlobalQueue) - { - RemoveEntryList(&Message->ListEntry); - if(MessageQueue->MouseMoveMsg == Message) - { - MessageQueue->MouseMoveMsg = NULL; - } - } - // when FromGlobalQueue is true, the caller has already removed the Message - ExFreePool(Message); - *Freed = TRUE; - return(FALSE); - } - - if (CaptureWindow->head.pti->MessageQueue != MessageQueue) - { - if (! FromGlobalQueue) - { - DPRINT("Moving msg between private queues\n"); - /* This message is already queued in a private queue, but we need - * to move it to a different queue, perhaps because a new window - * was created which now covers the screen area previously taken - * by another window. To move it, we need to take it out of the - * old queue. Note that we're already holding the lock mutexes of the - * old queue */ - RemoveEntryList(&Message->ListEntry); - - /* remove the pointer for the current WM_MOUSEMOVE message in case we - just removed it */ - if(MessageQueue->MouseMoveMsg == Message) - { - MessageQueue->MouseMoveMsg = NULL; - } - } - - /* lock the destination message queue, so we don't get in trouble with other - threads, messing with it at the same time */ - IntLockHardwareMessageQueue(CaptureWindow->head.pti->MessageQueue); - InsertTailList(&CaptureWindow->head.pti->MessageQueue->HardwareMessagesListHead, - &Message->ListEntry); - if(Message->Msg.message == WM_MOUSEMOVE) - { - if(CaptureWindow->head.pti->MessageQueue->MouseMoveMsg) - { - /* remove the old WM_MOUSEMOVE message, we're processing a more recent - one */ - RemoveEntryList(&CaptureWindow->head.pti->MessageQueue->MouseMoveMsg->ListEntry); - ExFreePool(CaptureWindow->head.pti->MessageQueue->MouseMoveMsg); - } - /* save the pointer to the WM_MOUSEMOVE message in the new queue */ - CaptureWindow->head.pti->MessageQueue->MouseMoveMsg = Message; - - MsqWakeQueue(CaptureWindow->head.pti->MessageQueue, QS_MOUSEMOVE); - } - else - { - MsqWakeQueue(CaptureWindow->head.pti->MessageQueue, QS_MOUSEBUTTON); - } - IntUnLockHardwareMessageQueue(CaptureWindow->head.pti->MessageQueue); - - *Freed = FALSE; - UserDereferenceObject(CaptureWindow); - return(FALSE); - } - - /* From here on, we're in the same message queue as the caller! */ - - *ScreenPoint = Message->Msg.pt; - - if((Window != NULL && PtrToInt(Window) != 1 && CaptureWindow->head.h != Window->head.h) || - ((FilterLow != 0 || FilterHigh != 0) && (Msg < FilterLow || Msg > FilterHigh))) - { - /* Reject the message because it doesn't match the filter */ - - if(FromGlobalQueue) - { - /* Lock the message queue so no other thread can mess with it. - Our own message queue is not locked while fetching from the global - queue, so we have to make sure nothing interferes! */ - IntLockHardwareMessageQueue(CaptureWindow->head.pti->MessageQueue); - /* if we're from the global queue, we need to add our message to our - private queue so we don't loose it! */ - InsertTailList(&CaptureWindow->head.pti->MessageQueue->HardwareMessagesListHead, - &Message->ListEntry); - } - - if (Message->Msg.message == WM_MOUSEMOVE) - { - if(CaptureWindow->head.pti->MessageQueue->MouseMoveMsg && - (CaptureWindow->head.pti->MessageQueue->MouseMoveMsg != Message)) - { - /* delete the old message */ - RemoveEntryList(&CaptureWindow->head.pti->MessageQueue->MouseMoveMsg->ListEntry); - ExFreePool(CaptureWindow->head.pti->MessageQueue->MouseMoveMsg); - if (!FromGlobalQueue) - { - // We might have deleted the next one in our queue, so fix next - *Next = Message->ListEntry.Flink; - } - } - /* always save a pointer to this WM_MOUSEMOVE message here because we're - sure that the message is in the private queue */ - CaptureWindow->head.pti->MessageQueue->MouseMoveMsg = Message; - } - if(FromGlobalQueue) - { - IntUnLockHardwareMessageQueue(CaptureWindow->head.pti->MessageQueue); - } - - UserDereferenceObject(CaptureWindow); - *Freed = FALSE; - return(FALSE); - } - - /* FIXME - only assign if removing? */ - Message->Msg.hwnd = CaptureWindow->head.h; - Message->Msg.message = Msg; - Message->Msg.lParam = MAKELONG(Message->Msg.pt.x, Message->Msg.pt.y); - - /* remove the reference to the current WM_(NC)MOUSEMOVE message, if this message - is it */ - if (Message->Msg.message == WM_MOUSEMOVE || - Message->Msg.message == WM_NCMOUSEMOVE) - { - if(FromGlobalQueue) - { - /* Lock the message queue so no other thread can mess with it. - Our own message queue is not locked while fetching from the global - queue, so we have to make sure nothing interferes! */ - IntLockHardwareMessageQueue(CaptureWindow->head.pti->MessageQueue); - if(CaptureWindow->head.pti->MessageQueue->MouseMoveMsg) - { - /* delete the WM_(NC)MOUSEMOVE message in the private queue, we're dealing - with one that's been sent later */ - RemoveEntryList(&CaptureWindow->head.pti->MessageQueue->MouseMoveMsg->ListEntry); - ExFreePool(CaptureWindow->head.pti->MessageQueue->MouseMoveMsg); - /* our message is not in the private queue so we can remove the pointer - instead of setting it to the current message we're processing */ - CaptureWindow->head.pti->MessageQueue->MouseMoveMsg = NULL; - } - IntUnLockHardwareMessageQueue(CaptureWindow->head.pti->MessageQueue); - } - else if (CaptureWindow->head.pti->MessageQueue->MouseMoveMsg == Message) - { - CaptureWindow->head.pti->MessageQueue->MouseMoveMsg = NULL; - } - } - - UserDereferenceObject(CaptureWindow); - *Freed = FALSE; - return(TRUE); -} - -BOOL APIENTRY -co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, - IN BOOL Remove, - IN PWND Window, - IN UINT FilterLow, - IN UINT FilterHigh, - OUT PMSG Message) -{ - KIRQL OldIrql; - POINT ScreenPoint; - BOOL Accept, Freed; - PLIST_ENTRY CurrentEntry; - PWND DesktopWindow = NULL; - PVOID WaitObjects[2]; - NTSTATUS WaitStatus; - DECLARE_RETURN(BOOL); - USER_REFERENCE_ENTRY Ref; - PDESKTOPINFO Desk = NULL; - - WaitObjects[1] = MessageQueue->NewMessages; - WaitObjects[0] = &HardwareMessageQueueLock; - do - { - UserLeaveCo(); - - WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest, - UserMode, FALSE, NULL, NULL); - - UserEnterCo(); - } - while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 != WaitStatus); - - DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()); - - if (DesktopWindow) - { - UserRefObjectCo(DesktopWindow, &Ref); - Desk = DesktopWindow->head.pti->pDeskInfo; - } - - /* Process messages in the message queue itself. */ - IntLockHardwareMessageQueue(MessageQueue); - CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink; - while (CurrentEntry != &MessageQueue->HardwareMessagesListHead) - { - PUSER_MESSAGE Current = - CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); - CurrentEntry = CurrentEntry->Flink; - if (Current->Msg.message >= WM_MOUSEFIRST && - Current->Msg.message <= WM_MOUSELAST) - { - - - Accept = co_MsqTranslateMouseMessage(MessageQueue, Window, FilterLow, FilterHigh, - Current, Remove, &Freed, - DesktopWindow, &ScreenPoint, FALSE, &CurrentEntry); - if (Accept) - { - *Message = Current->Msg; - if (Remove) - { - RemoveEntryList(&Current->ListEntry); - MsqDestroyMessage(Current); - } - IntUnLockHardwareMessageQueue(MessageQueue); - IntUnLockSystemHardwareMessageQueueLock(FALSE); - - if (Desk) - Desk->LastInputWasKbd = FALSE; - - RETURN(TRUE); - } - - } - else - { - *Message = Current->Msg; - if (Remove) - { - RemoveEntryList(&Current->ListEntry); - MsqDestroyMessage(Current); - } - IntUnLockHardwareMessageQueue(MessageQueue); - IntUnLockSystemHardwareMessageQueueLock(FALSE); - - RETURN(TRUE); - } - } - IntUnLockHardwareMessageQueue(MessageQueue); - - /* Now try the global queue. */ - - /* Transfer all messages from the DPC accessible queue to the main queue. */ - IntLockSystemMessageQueue(OldIrql); - while (SystemMessageQueueCount > 0) - { - PUSER_MESSAGE UserMsg; - MSG Msg; - - ASSERT(SystemMessageQueueHead < SYSTEM_MESSAGE_QUEUE_SIZE); - Msg = SystemMessageQueue[SystemMessageQueueHead]; - SystemMessageQueueHead = - (SystemMessageQueueHead + 1) % SYSTEM_MESSAGE_QUEUE_SIZE; - SystemMessageQueueCount--; - IntUnLockSystemMessageQueue(OldIrql); - - UserMsg = ExAllocateFromPagedLookasideList(&MessageLookasideList); - /* What to do if out of memory? For now we just panic a bit in debug */ - ASSERT(UserMsg); - UserMsg->Msg = Msg; - InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry); - - IntLockSystemMessageQueue(OldIrql); - } - HardwareMessageQueueStamp++; - IntUnLockSystemMessageQueue(OldIrql); - - /* Process messages in the queue until we find one to return. */ - CurrentEntry = HardwareMessageQueueHead.Flink; - while (CurrentEntry != &HardwareMessageQueueHead) - { - PUSER_MESSAGE Current = - CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry); - CurrentEntry = CurrentEntry->Flink; - RemoveEntryList(&Current->ListEntry); - HardwareMessageQueueStamp++; - if (Current->Msg.message >= WM_MOUSEFIRST && - Current->Msg.message <= WM_MOUSELAST) - { - const ULONG ActiveStamp = HardwareMessageQueueStamp; - /* Translate the message. */ - Accept = co_MsqTranslateMouseMessage(MessageQueue, Window, FilterLow, FilterHigh, - Current, Remove, &Freed, - DesktopWindow, &ScreenPoint, TRUE, NULL); - if (Accept) - { - /* Check for no more messages in the system queue. */ - IntLockSystemMessageQueue(OldIrql); - if (SystemMessageQueueCount == 0 && - IsListEmpty(&HardwareMessageQueueHead)) - { - KeClearEvent(&HardwareMessageEvent); - } - IntUnLockSystemMessageQueue(OldIrql); - - /* - If we aren't removing the message then add it to the private - queue. - */ - if (!Remove) - { - IntLockHardwareMessageQueue(MessageQueue); - if(Current->Msg.message == WM_MOUSEMOVE) - { - if(MessageQueue->MouseMoveMsg) - { - RemoveEntryList(&MessageQueue->MouseMoveMsg->ListEntry); - ExFreePool(MessageQueue->MouseMoveMsg); - } - MessageQueue->MouseMoveMsg = Current; - } - InsertTailList(&MessageQueue->HardwareMessagesListHead, - &Current->ListEntry); - IntUnLockHardwareMessageQueue(MessageQueue); - } - IntUnLockSystemHardwareMessageQueueLock(FALSE); - *Message = Current->Msg; - - if (Remove) - { - MsqDestroyMessage(Current); - } - - RETURN(TRUE); - } - /* If the contents of the queue changed then restart processing. */ - if (HardwareMessageQueueStamp != ActiveStamp) - { - CurrentEntry = HardwareMessageQueueHead.Flink; - continue; - } - } - } - - /* Check if the system message queue is now empty. */ - IntLockSystemMessageQueue(OldIrql); - if (SystemMessageQueueCount == 0 && IsListEmpty(&HardwareMessageQueueHead)) - { - KeClearEvent(&HardwareMessageEvent); - } - IntUnLockSystemMessageQueue(OldIrql); - IntUnLockSystemHardwareMessageQueueLock(FALSE); - - RETURN(FALSE); - -CLEANUP: - if (DesktopWindow) UserDerefObjectCo(DesktopWindow); - - END_CLEANUP; + } }
// @@ -1323,6 +794,420 @@ MsqWakeQueue(MessageQueue, QS_POSTMESSAGE); }
+/*********************************************************************** + * MsqSendParentNotify + * + * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless + * the window has the WS_EX_NOPARENTNOTIFY style. + */ +static void MsqSendParentNotify( PWND pwnd, WORD event, WORD idChild, POINT pt ) +{ + PWND pwndDesktop = UserGetWindowObject(IntGetDesktopWindow()); + + /* pt has to be in the client coordinates of the parent window */ + pt.x += pwndDesktop->rcClient.left - pwnd->rcClient.left; + pt.y += pwndDesktop->rcClient.top - pwnd->rcClient.top; + + for (;;) + { + PWND pwndParent; + + if (!(pwnd->style & WS_CHILD)) break; + if (pwnd->ExStyle & WS_EX_NOPARENTNOTIFY) break; + if (!(pwndParent = IntGetParent(pwnd))) break; + if (pwndParent == pwndDesktop) break; + pt.x += pwnd->rcClient.left - pwndParent->rcClient.left; + pt.y += pwnd->rcClient.top - pwndParent->rcClient.top; + + pwnd = pwndParent; + co_IntSendMessage( UserHMGetHandle(pwnd), WM_PARENTNOTIFY, + MAKEWPARAM( event, idChild ), MAKELPARAM( pt.x, pt.y ) ); + } +} + +BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT last) +{ + MSG clk_msg; + POINT pt; + UINT message; + USHORT hittest; + EVENTMSG event; + MOUSEHOOKSTRUCT hook; + BOOL eatMsg; + + PWND pwndMsg, pwndDesktop; + PUSER_MESSAGE_QUEUE MessageQueue; + PTHREADINFO pti; + PSYSTEM_CURSORINFO CurInfo; + DECLARE_RETURN(BOOL); + + pti = PsGetCurrentThreadWin32Thread(); + pwndDesktop = UserGetDesktopWindow(); + MessageQueue = pti->MessageQueue; + CurInfo = IntGetSysCursorInfo(); + pwndMsg = UserGetWindowObject(msg->hwnd); + clk_msg = MessageQueue->msgDblClk; + + /* find the window to dispatch this mouse message to */ + if (MessageQueue->CaptureWindow) + { + hittest = HTCLIENT; + pwndMsg = IntGetWindowObject(MessageQueue->CaptureWindow); + } + else + { + pwndMsg = co_WinPosWindowFromPoint(pwndMsg, &msg->pt, &hittest); + } + + DPRINT("Got mouse message for 0x%x, hittest: 0x%x\n", msg->hwnd, hittest ); + + if (pwndMsg == NULL || pwndMsg->head.pti != pti) + { + /* Remove and ignore the message */ + *RemoveMessages = TRUE; + RETURN(FALSE); + } + + msg->hwnd = UserHMGetHandle(pwndMsg); + + /* FIXME: is this really the right place for this hook? */ + event.message = msg->message; + event.time = msg->time; + event.hwnd = msg->hwnd; + event.paramL = msg->pt.x; + event.paramH = msg->pt.y; + co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&event ); + +#if 0 + if (!check_hwnd_filter( msg, hwnd_filter )) RETURN(FALSE); +#endif + + pt = msg->pt; + message = msg->message; + /* Note: windows has no concept of a non-client wheel message */ + if (message != WM_MOUSEWHEEL) + { + if (hittest != HTCLIENT) + { + message += WM_NCMOUSEMOVE - WM_MOUSEMOVE; + msg->wParam = hittest; + } + else + { + /* coordinates don't get translated while tracking a menu */ + /* FIXME: should differentiate popups and top-level menus */ + if (!(MessageQueue->MenuOwner)) + { + pt.x += pwndDesktop->rcClient.left - pwndMsg->rcClient.left; + pt.y += pwndDesktop->rcClient.top - pwndMsg->rcClient.top; + } + } + } + msg->lParam = MAKELONG( pt.x, pt.y ); + + /* translate double clicks */ + + if ((msg->message == WM_LBUTTONDOWN) || + (msg->message == WM_RBUTTONDOWN) || + (msg->message == WM_MBUTTONDOWN) || + (msg->message == WM_XBUTTONDOWN)) + { + BOOL update = *RemoveMessages; + + /* translate double clicks - + * note that ...MOUSEMOVEs can slip in between + * ...BUTTONDOWN and ...BUTTONDBLCLK messages */ + + if ((MessageQueue->MenuOwner || MessageQueue->MoveSize) || + hittest != HTCLIENT || + (pwndMsg->pcls->style & CS_DBLCLKS)) + { + if ((msg->message == clk_msg.message) && + (msg->hwnd == clk_msg.hwnd) && + (msg->wParam == clk_msg.wParam) && + (msg->time - clk_msg.time < gspv.iDblClickTime) && + (abs(msg->pt.x - clk_msg.pt.x) < UserGetSystemMetrics(SM_CXDOUBLECLK)/2) && + (abs(msg->pt.y - clk_msg.pt.y) < UserGetSystemMetrics(SM_CYDOUBLECLK)/2)) + { + message += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); + if (update) + { + MessageQueue->msgDblClk.message = 0; /* clear the double click conditions */ + update = FALSE; + } + } + } + + if (!((first == 0 && last == 0) || (message >= first || message <= last))) + { + DPRINT("Message out of range!!!\n"); + RETURN(FALSE); + } + + /* update static double click conditions */ + if (update) MessageQueue->msgDblClk = *msg; + } + else + { + if (!((first == 0 && last == 0) || (message >= first || message <= last))) + { + DPRINT("Message out of range!!!\n"); + RETURN(FALSE); + } + } + + if(gspv.bMouseClickLock) + { + BOOL IsClkLck = FALSE; + + if(msg->message == WM_LBUTTONUP) + { + IsClkLck = ((msg->time - CurInfo->ClickLockTime) >= gspv.dwMouseClickLockTime); + if (IsClkLck && (!CurInfo->ClickLockActive)) + { + CurInfo->ClickLockActive = TRUE; + } + } + else if (msg->message == WM_LBUTTONDOWN) + { + if (CurInfo->ClickLockActive) + { + IsClkLck = TRUE; + CurInfo->ClickLockActive = FALSE; + } + + CurInfo->ClickLockTime = msg->time; + } + + if(IsClkLck) + { + /* Remove and ignore the message */ + *RemoveMessages = TRUE; + RETURN(FALSE); + } + } + + /* message is accepted now (but may still get dropped) */ + + hook.pt = msg->pt; + hook.hwnd = msg->hwnd; + hook.wHitTestCode = hittest; + hook.dwExtraInfo = 0/*extra_info*/; + if (co_HOOK_CallHooks( WH_MOUSE, *RemoveMessages ? HC_ACTION : HC_NOREMOVE, + message, (LPARAM)&hook )) + { + hook.pt = msg->pt; + hook.hwnd = msg->hwnd; + hook.wHitTestCode = hittest; + hook.dwExtraInfo = 0/*extra_info*/; + co_HOOK_CallHooks( WH_CBT, HCBT_CLICKSKIPPED, message, (LPARAM)&hook ); + + DPRINT1("WH_MOUSE dorpped mouse message!\n"); + + /* Remove and skip message */ + *RemoveMessages = TRUE; + RETURN(FALSE); + } + + if ((hittest == HTERROR) || (hittest == HTNOWHERE)) + { + co_IntSendMessage( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd, + MAKELONG( hittest, msg->message )); + + /* Remove and skip message */ + *RemoveMessages = TRUE; + RETURN(FALSE); + } + + if ((*RemoveMessages == FALSE) || MessageQueue->CaptureWindow) + { + /* Accept the message */ + msg->message = message; + RETURN(TRUE); + } + + eatMsg = FALSE; + + if ((msg->message == WM_LBUTTONDOWN) || + (msg->message == WM_RBUTTONDOWN) || + (msg->message == WM_MBUTTONDOWN) || + (msg->message == WM_XBUTTONDOWN)) + { + /* Send the WM_PARENTNOTIFY, + * note that even for double/nonclient clicks + * notification message is still WM_L/M/RBUTTONDOWN. + */ + MsqSendParentNotify(pwndMsg, msg->message, 0, msg->pt ); + + /* Activate the window if needed */ + + if (msg->hwnd != MessageQueue->ActiveWindow) + { + PWND pwndTop = pwndMsg; + while (pwndTop) + { + if ((pwndTop->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) break; + pwndTop = IntGetParent( pwndTop ); + } + + if (pwndTop && pwndTop != pwndDesktop) + { + LONG ret = co_IntSendMessage( msg->hwnd, + WM_MOUSEACTIVATE, + (WPARAM)UserHMGetHandle(pwndTop), + MAKELONG( hittest, msg->message)); + switch(ret) + { + case MA_NOACTIVATEANDEAT: + eatMsg = TRUE; + /* fall through */ + case MA_NOACTIVATE: + break; + case MA_ACTIVATEANDEAT: + eatMsg = TRUE; + /* fall through */ + case MA_ACTIVATE: + case 0: + if(!co_IntMouseActivateWindow(pwndMsg)) eatMsg = TRUE; + break; + default: + DPRINT1( "unknown WM_MOUSEACTIVATE code %d\n", ret ); + break; + } + } + } + } + + /* send the WM_SETCURSOR message */ + + /* Windows sends the normal mouse message as the message parameter + in the WM_SETCURSOR message even if it's non-client mouse message */ + co_IntSendMessage( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd, MAKELONG( hittest, msg->message )); + + msg->message = message; + RETURN(!eatMsg); + +CLEANUP: + if(pwndMsg) + UserDereferenceObject(pwndMsg); + + END_CLEANUP; +} + +BOOL co_IntProcessKeyboardMessage(MSG* Msg, BOOL* RemoveMessages) +{ + EVENTMSG Event; + + Event.message = Msg->message; + Event.hwnd = Msg->hwnd; + Event.time = Msg->time; + Event.paramL = (Msg->wParam & 0xFF) | (HIWORD(Msg->lParam) << 8); + Event.paramH = Msg->lParam & 0x7FFF; + if (HIWORD(Msg->lParam) & 0x0100) Event.paramH |= 0x8000; + co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event); + + if (co_HOOK_CallHooks( WH_KEYBOARD, + *RemoveMessages ? HC_ACTION : HC_NOREMOVE, + LOWORD(Msg->wParam), + Msg->lParam)) + { + /* skip this message */ + co_HOOK_CallHooks( WH_CBT, + HCBT_KEYSKIPPED, + LOWORD(Msg->wParam), + Msg->lParam ); + DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n"); + return FALSE; + } + return TRUE; +} + +BOOL co_IntProcessHardwareMessage(MSG* Msg, BOOL* RemoveMessages, UINT first, UINT last) +{ + if ( IS_MOUSE_MESSAGE(Msg->message)) + { + return co_IntProcessMouseMessage(Msg, RemoveMessages, first, last); + } + else if ( IS_KBD_MESSAGE(Msg->message)) + { + return co_IntProcessKeyboardMessage(Msg, RemoveMessages); + } + + return TRUE; +} + +BOOL APIENTRY +co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue, + IN BOOL Remove, + IN PWND Window, + IN UINT MsgFilterLow, + IN UINT MsgFilterHigh, + OUT MSG* pMsg) +{ + BOOL AcceptMessage; + MSG msg; + + if(!(MessageQueue->MouseMoved)) + return FALSE; + + msg = MessageQueue->MouseMoveMsg; + + AcceptMessage = co_IntProcessMouseMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh); + + if(AcceptMessage) + *pMsg = msg; + + if(Remove) + MessageQueue->MouseMoved = FALSE; + + return AcceptMessage; +} + +BOOL APIENTRY +co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, + IN BOOL Remove, + IN PWND Window, + IN UINT MsgFilterLow, + IN UINT MsgFilterHigh, + OUT MSG* pMsg) +{ + + BOOL AcceptMessage; + PUSER_MESSAGE CurrentMessage; + PLIST_ENTRY ListHead, CurrentEntry = NULL; + MSG msg; + + ListHead = &MessageQueue->HardwareMessagesListHead; + CurrentEntry = ListHead->Flink; + + while(CurrentEntry != ListHead) + { + CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, + ListEntry); + + msg = CurrentMessage->Msg; + + AcceptMessage = co_IntProcessHardwareMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh); + + CurrentEntry = CurrentMessage->ListEntry.Flink; + + if (Remove) + { + RemoveEntryList(&CurrentMessage->ListEntry); + MsqDestroyMessage(CurrentMessage); + } + + if(AcceptMessage) + { + *pMsg = msg; + return TRUE; + } + + } + + return FALSE; +} + BOOLEAN APIENTRY MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, IN BOOLEAN Remove, @@ -1368,19 +1253,14 @@ co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, PWND WndFilter, UINT MsgFilterMin, UINT MsgFilterMax) { - PVOID WaitObjects[2] = {MessageQueue->NewMessages, &HardwareMessageEvent}; NTSTATUS ret;
UserLeaveCo(); - - ret = KeWaitForMultipleObjects(2, - WaitObjects, - WaitAny, - Executive, - UserMode, - FALSE, - NULL, - NULL); + ret = KeWaitForSingleObject(MessageQueue->NewMessages, + Executive, + UserMode, + FALSE, + NULL); UserEnterCo(); return ret; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c [iso-8859-1] Mon Nov 22 20:10:56 2010 @@ -4424,6 +4424,7 @@ POINT pt; HWND Ret; PWND DesktopWindow = NULL, Window = NULL; + USHORT hittest; DECLARE_RETURN(HWND); USER_REFERENCE_ENTRY Ref;
@@ -4442,7 +4443,7 @@ UserRefObjectCo(DesktopWindow, &Ref);
pti = PsGetCurrentThreadWin32Thread(); - co_WinPosWindowFromPoint(DesktopWindow, pti->MessageQueue, &pt, &Window); + Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest);
if(Window) {
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/winpos.c [iso-8859-1] Mon Nov 22 20:10:56 2010 @@ -1578,162 +1578,99 @@ return(WasVisible); }
- -#if 0 - -/* find child of 'parent' that contains the given point (in parent-relative coords) */ -PWND child_window_from_point(PWND parent, int x, int y ) -{ - PWND Wnd;// = parent->spwndChild; - -// LIST_FOR_EACH_ENTRY( Wnd, &parent->children, struct window, entry ) - for (Wnd = parent->spwndChild; Wnd; Wnd = Wnd->spwndNext) - { - if (!IntPtInWindow( Wnd, x, y )) continue; /* skip it */ - - /* if window is minimized or disabled, return at once */ - if (Wnd->style & (WS_MINIMIZE|WS_DISABLED)) return Wnd; - - /* if point is not in client area, return at once */ - if (x < Wnd->rcClient.left || x >= Wnd->rcClient.right || - y < Wnd->rcClient.top || y >= Wnd->rcClient.bottom) - return Wnd; - - return child_window_from_point( Wnd, x - Wnd->rcClient.left, y - Wnd->rcClient.top ); - } - return parent; /* not found any child */ -} -#endif - -/* wine server: child_window_from_point - -Caller must dereference the "returned" Window -*/ static -VOID FASTCALL +PWND FASTCALL co_WinPosSearchChildren( PWND ScopeWin, - PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *Point, - PWND* Window, USHORT *HitTest ) { - PWND Current; - HWND *List, *phWnd; + PWND pwndChild; + HWND *List, *phWnd; + + if (!(ScopeWin->style & WS_VISIBLE)) + { + return NULL; + } + + if ((ScopeWin->style & WS_DISABLED)) + { + return NULL; + } + + if (!IntPtInWindow(ScopeWin, Point->x, Point->y)) + { + return NULL; + } + + UserReferenceObject(ScopeWin); + + if (Point->x - ScopeWin->rcClient.left < ScopeWin->rcClient.right && + Point->y - ScopeWin->rcClient.top < ScopeWin->rcClient.bottom ) + { + List = IntWinListChildren(ScopeWin); + if(List) + { + for (phWnd = List; *phWnd; ++phWnd) + { + if (!(pwndChild = UserGetWindowObject(*phWnd))) + { + continue; + } + + pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest); + + if(pwndChild != NULL) + { + /* We found a window. Don't send any more WM_NCHITTEST messages */ + UserDereferenceObject(ScopeWin); + return pwndChild; + } + } + } + + ExFreePool(List); + } + + *HitTest = co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, + MAKELONG(Point->x, Point->y)); + if ((*HitTest) == (USHORT)HTTRANSPARENT) + { + UserDereferenceObject(ScopeWin); + return NULL; + } + + return ScopeWin; +} + +PWND FASTCALL +co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest) +{ + PWND Window; + POINT Point = *WinPoint; USER_REFERENCE_ENTRY Ref;
+ if( ScopeWin == NULL ) + { + ScopeWin = UserGetDesktopWindow(); + if(ScopeWin == NULL) + return NULL; + } + + *HitTest = HTNOWHERE; + ASSERT_REFS_CO(ScopeWin); - - if ((List = IntWinListChildren(ScopeWin))) - { - for (phWnd = List; *phWnd; ++phWnd) - { - if (!(Current = UserGetWindowObject(*phWnd))) - continue; - - if (!(Current->style & WS_VISIBLE)) - { - continue; - } - - if ((Current->style & (WS_POPUP | WS_CHILD | WS_DISABLED)) == - (WS_CHILD | WS_DISABLED)) - { - continue; - } - - if (!IntPtInWindow(Current, Point->x, Point->y)) - { - continue; - } - - if (*Window) UserDereferenceObject(*Window); - *Window = Current; - UserReferenceObject(*Window); - - if (Current->style & WS_MINIMIZE) - { - *HitTest = HTCAPTION; - break; - } - - if (Current->style & WS_DISABLED) - { - *HitTest = HTERROR; - break; - } - - UserRefObjectCo(Current, &Ref); - - if (OnlyHitTests && (Current->head.pti->MessageQueue == OnlyHitTests)) - { - *HitTest = co_IntSendMessage(Current->head.h, WM_NCHITTEST, 0, - MAKELONG(Point->x, Point->y)); - if ((*HitTest) == (USHORT)HTTRANSPARENT) - { - UserDerefObjectCo(Current); - continue; - } - } - else - *HitTest = HTCLIENT; - - if (Point->x >= Current->rcClient.left && - Point->x < Current->rcClient.right && - Point->y >= Current->rcClient.top && - Point->y < Current->rcClient.bottom) - { - co_WinPosSearchChildren(Current, OnlyHitTests, Point, Window, HitTest); - } - - UserDerefObjectCo(Current); - - break; - } - ExFreePool(List); - } -} - -/* wine: WINPOS_WindowFromPoint */ -USHORT FASTCALL -co_WinPosWindowFromPoint(PWND ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *WinPoint, - PWND* Window) -{ - HWND DesktopWindowHandle; - PWND DesktopWindow; - POINT Point = *WinPoint; - USHORT HitTest; - + UserRefObjectCo(ScopeWin, &Ref); + + Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest); + + UserDerefObjectCo(ScopeWin); + if(Window) + ASSERT_REFS_CO(Window); ASSERT_REFS_CO(ScopeWin);
- *Window = NULL; - - if(!ScopeWin) - { - DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n"); - return(HTERROR); - } - - if (ScopeWin->style & WS_DISABLED) - { - return(HTERROR); - } - - /* Translate the point to the space of the scope window. */ - DesktopWindowHandle = IntGetDesktopWindow(); - if((DesktopWindowHandle != ScopeWin->head.h) && - (DesktopWindow = UserGetWindowObject(DesktopWindowHandle))) - { - Point.x += ScopeWin->rcClient.left - DesktopWindow->rcClient.left; - Point.y += ScopeWin->rcClient.top - DesktopWindow->rcClient.top; - } - - HitTest = HTNOWHERE; - - co_WinPosSearchChildren(ScopeWin, OnlyHitTests, &Point, Window, &HitTest); - - return ((*Window) ? HitTest : HTNOWHERE); + return Window; }
BOOL