fixed major bugs in the message queue

svn path=/trunk/; revision=9139
This commit is contained in:
Thomas Bluemel 2004-04-14 17:19:38 +00:00
parent b325c3fecb
commit 81a46fb20d
4 changed files with 143 additions and 110 deletions

View file

@ -29,7 +29,7 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
BOOLEAN FASTCALL
WinPosShowWindow(HWND Wnd, INT Cmd);
USHORT FASTCALL
WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, BOOL SendHitTestMessage, POINT *WinPoint,
WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *WinPoint,
PWINDOW_OBJECT* Window);
VOID FASTCALL WinPosActivateOtherWindow(PWINDOW_OBJECT Window);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: msgqueue.c,v 1.83 2004/04/13 13:50:31 weiden Exp $
/* $Id: msgqueue.c,v 1.84 2004/04/14 17:19:38 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -249,65 +249,73 @@ MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh,
PWINDOW_OBJECT Window = NULL;
HWND CaptureWin;
POINT Point;
ThreadQueue = PsGetWin32Thread()->MessageQueue;
if (Msg == WM_LBUTTONDOWN ||
Msg == WM_MBUTTONDOWN ||
Msg == WM_RBUTTONDOWN ||
Msg == WM_XBUTTONDOWN)
{
*HitTest = WinPosWindowFromPoint(ScopeWin, !FromGlobalQueue, &Message->Msg.pt, &Window);
if(Window && FromGlobalQueue && (PsGetWin32Thread()->MessageQueue == Window->MessageQueue))
{
*HitTest = IntSendMessage(Window->Self, WM_NCHITTEST, 0,
MAKELONG(Message->Msg.pt.x, Message->Msg.pt.y));
}
*HitTest = WinPosWindowFromPoint(ScopeWin, ThreadQueue, &Message->Msg.pt, &Window);
/*
**Make sure that we have a window that is not already in focus
*/
if (Window)
if (Window && (Window->Self != IntGetFocusWindow()))
{
if(Window->Self != IntGetFocusWindow())
if(ThreadQueue == Window->MessageQueue)
{
/* only get a more detailed hit-test if the window is in the same thread! */
*HitTest = IntSendMessage(Window->Self, WM_NCHITTEST, 0,
MAKELONG(Message->Msg.pt.x, Message->Msg.pt.y));
}
if(*HitTest != (USHORT)HTTRANSPARENT)
{
LRESULT Result;
if(*HitTest != (USHORT)HTTRANSPARENT)
{
LRESULT Result;
/* Sending a message to another thread might lock up our own when it's
hung, so just send messages to our own thread */
if(Window->MessageQueue == ThreadQueue)
Result = IntSendMessage(Window->Self, WM_MOUSEACTIVATE, (WPARAM)NtUserGetParent(Window->Self), (LPARAM)MAKELONG(*HitTest, Msg));
switch (Result)
{
case MA_NOACTIVATEANDEAT:
*Freed = FALSE;
IntReleaseWindowObject(Window);
return TRUE;
case MA_NOACTIVATE:
break;
case MA_ACTIVATEANDEAT:
IntMouseActivateWindow(Window);
IntReleaseWindowObject(Window);
*Freed = FALSE;
return TRUE;
/* case MA_ACTIVATE:
case 0:*/
default:
IntMouseActivateWindow(Window);
break;
}
}
else
{
IntReleaseWindowObject(Window);
if(RemoveWhenFreed)
{
RemoveEntryList(&Message->ListEntry);
}
ExFreePool(Message);
*Freed = TRUE;
return(FALSE);
/* just post WM_MOUSEACTIVATE to the other thread */
NtUserPostMessage(Window->Self, WM_MOUSEACTIVATE, (WPARAM)NtUserGetParent(Window->Self), (LPARAM)MAKELONG(*HitTest, Msg));
/* and assume that windows of other threads should always be activated. */
Result = MA_ACTIVATE;
}
switch (Result)
{
case MA_NOACTIVATEANDEAT:
*Freed = FALSE;
IntReleaseWindowObject(Window);
return TRUE;
case MA_NOACTIVATE:
break;
case MA_ACTIVATEANDEAT:
IntMouseActivateWindow(Window);
IntReleaseWindowObject(Window);
*Freed = FALSE;
return TRUE;
default:
/* MA_ACTIVATE */
IntMouseActivateWindow(Window);
break;
}
}
else
{
IntReleaseWindowObject(Window);
if(RemoveWhenFreed)
{
RemoveEntryList(&Message->ListEntry);
}
ExFreePool(Message);
*Freed = TRUE;
return(FALSE);
}
}
}
CaptureWin = IntGetCaptureWindow();
@ -325,8 +333,8 @@ MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh,
{
if(!Window)
{
*HitTest = WinPosWindowFromPoint(ScopeWin, !FromGlobalQueue, &Message->Msg.pt, &Window);
if(Window && FromGlobalQueue && (PsGetWin32Thread()->MessageQueue == Window->MessageQueue))
*HitTest = WinPosWindowFromPoint(ScopeWin, ThreadQueue, &Message->Msg.pt, &Window);
if(Window && (ThreadQueue == Window->MessageQueue))
{
*HitTest = IntSendMessage(Window->Self, WM_NCHITTEST, 0,
MAKELONG(Message->Msg.pt.x, Message->Msg.pt.y));
@ -358,7 +366,6 @@ MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh,
return(FALSE);
}
ThreadQueue = PsGetWin32Thread()->MessageQueue;
if (Window->MessageQueue != ThreadQueue)
{
if (! FromGlobalQueue)
@ -379,70 +386,33 @@ MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh,
ThreadQueue->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(Window->MessageQueue);
if((Message->Msg.message == WM_MOUSEMOVE) && Window->MessageQueue->MouseMoveMsg)
InsertTailList(&Window->MessageQueue->HardwareMessagesListHead,
&Message->ListEntry);
if(Message->Msg.message == WM_MOUSEMOVE)
{
/* we do not hold more than one WM_MOUSEMOVE message in the queue */
Window->MessageQueue->MouseMoveMsg->Msg = Message->Msg;
if(RemoveWhenFreed && FromGlobalQueue)
if(Window->MessageQueue->MouseMoveMsg)
{
RemoveEntryList(&Message->ListEntry);
/* remove the old WM_MOUSEMOVE message, we're processing a more recent
one */
RemoveEntryList(&Window->MessageQueue->MouseMoveMsg->ListEntry);
ExFreePool(Window->MessageQueue->MouseMoveMsg);
}
*Freed = TRUE;
}
else
{
InsertTailList(&Window->MessageQueue->HardwareMessagesListHead,
&Message->ListEntry);
if(Message->Msg.message == WM_MOUSEMOVE)
{
Window->MessageQueue->MouseMoveMsg = Message;
}
*Freed = FALSE;
/* save the pointer to the WM_MOUSEMOVE message in the new queue */
Window->MessageQueue->MouseMoveMsg = Message;
}
IntUnLockHardwareMessageQueue(Window->MessageQueue);
if(*Freed)
{
ExFreePool(Message);
}
KeSetEvent(&Window->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
*Freed = FALSE;
IntReleaseWindowObject(Window);
return(FALSE);
}
if (hWnd != NULL && Window->Self != hWnd &&
!IntIsChildWindow(hWnd, Window->Self))
{
IntLockHardwareMessageQueue(Window->MessageQueue);
if((Message->Msg.message == WM_MOUSEMOVE) && Window->MessageQueue->MouseMoveMsg)
{
/* we do not hold more than one WM_MOUSEMOVE message in the queue */
Window->MessageQueue->MouseMoveMsg->Msg = Message->Msg;
if(RemoveWhenFreed)
{
RemoveEntryList(&Message->ListEntry);
}
*Freed = TRUE;
}
else
{
InsertTailList(&Window->MessageQueue->HardwareMessagesListHead,
&Message->ListEntry);
if(Message->Msg.message == WM_MOUSEMOVE)
{
Window->MessageQueue->MouseMoveMsg = Message;
}
*Freed = FALSE;
}
IntUnLockHardwareMessageQueue(Window->MessageQueue);
if(*Freed)
{
ExFreePool(Message);
}
KeSetEvent(&Window->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
IntReleaseWindowObject(Window);
return(FALSE);
}
/* From here on, we're in the same message queue as the caller! */
switch (Msg)
{
@ -487,7 +457,43 @@ MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh,
}
}
/* FIXME: Check message filter. */
if(hWnd != NULL && Window->Self != hWnd)
{
/* 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(Window->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(&Window->MessageQueue->HardwareMessagesListHead,
&Message->ListEntry);
}
if (Message->Msg.message == WM_MOUSEMOVE)
{
if(Window->MessageQueue->MouseMoveMsg)
{
/* delete the old message */
RemoveEntryList(&Window->MessageQueue->MouseMoveMsg->ListEntry);
ExFreePool(Window->MessageQueue->MouseMoveMsg);
}
/* always save a pointer to this WM_MOUSEMOVE message here because we're
sure that the message is in the private queue */
Window->MessageQueue->MouseMoveMsg = Message;
}
if(FromGlobalQueue)
{
IntUnLockHardwareMessageQueue(Window->MessageQueue);
}
IntReleaseWindowObject(Window);
*Freed = FALSE;
return(FALSE);
}
if (Remove)
{
@ -496,6 +502,34 @@ MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh,
Message->Msg.lParam = MAKELONG(Point.x, Point.y);
}
/* remove the reference to the current WM_MOUSEMOVE message, if this message
is it */
if (Message->Msg.message == WM_MOUSEMOVE)
{
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(Window->MessageQueue);
if(Window->MessageQueue->MouseMoveMsg)
{
/* delete the WM_MOUSEMOVE message in the private queue, we're dealing
with one that's been sent later */
RemoveEntryList(&Window->MessageQueue->MouseMoveMsg->ListEntry);
ExFreePool(Window->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 */
Window->MessageQueue->MouseMoveMsg = NULL;
}
IntUnLockHardwareMessageQueue(Window->MessageQueue);
}
else if(Window->MessageQueue->MouseMoveMsg == Message)
{
Window->MessageQueue->MouseMoveMsg = NULL;
}
}
IntReleaseWindowObject(Window);
*Freed = FALSE;
return(TRUE);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: window.c,v 1.216 2004/04/13 23:25:54 weiden Exp $
/* $Id: window.c,v 1.217 2004/04/14 17:19:38 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -3715,7 +3715,7 @@ NtUserWindowFromPoint(LONG X, LONG Y)
pt.x = X;
pt.y = Y;
Hit = WinPosWindowFromPoint(DesktopWindow, TRUE, &pt, &Window);
Hit = WinPosWindowFromPoint(DesktopWindow, PsGetWin32Thread()->MessageQueue, &pt, &Window);
if(Window)
{

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: winpos.c,v 1.110 2004/04/13 23:12:30 weiden Exp $
/* $Id: winpos.c,v 1.111 2004/04/14 17:19:38 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -1368,7 +1368,7 @@ WinPosShowWindow(HWND Wnd, INT Cmd)
}
VOID STATIC FASTCALL
WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, BOOL SendHitTestMessage, POINT *Point,
WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *Point,
PWINDOW_OBJECT* Window, USHORT *HitTest)
{
PWINDOW_OBJECT Current;
@ -1400,8 +1400,7 @@ WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, BOOL SendHitTestMessage, POINT *Po
return;
}
if(SendHitTestMessage &&
(Current->MessageQueue == PsGetWin32Thread()->MessageQueue))
if(OnlyHitTests && (Current->MessageQueue == OnlyHitTests))
{
*HitTest = IntSendMessage(Current->Self, WM_NCHITTEST, 0,
MAKELONG(Point->x, Point->y));
@ -1420,7 +1419,7 @@ WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, BOOL SendHitTestMessage, POINT *Po
Point->y >= Current->ClientRect.top &&
Point->y < Current->ClientRect.bottom)
{
WinPosSearchChildren(Current, SendHitTestMessage, Point, Window, HitTest);
WinPosSearchChildren(Current, OnlyHitTests, Point, Window, HitTest);
ExFreePool(List);
return;
}
@ -1435,7 +1434,7 @@ WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, BOOL SendHitTestMessage, POINT *Po
}
USHORT FASTCALL
WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, BOOL SendHitTestMessage, POINT *WinPoint,
WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *WinPoint,
PWINDOW_OBJECT* Window)
{
HWND DesktopWindowHandle;
@ -1468,7 +1467,7 @@ WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, BOOL SendHitTestMessage, POINT *W
HitTest = HTNOWHERE;
WinPosSearchChildren(ScopeWin, SendHitTestMessage, &Point, Window, &HitTest);
WinPosSearchChildren(ScopeWin, OnlyHitTests, &Point, Window, &HitTest);
return ((*Window) ? HitTest : HTNOWHERE);
}