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/in…
==============================================================================
--- 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/in…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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(a)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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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