mirror of
https://github.com/reactos/reactos.git
synced 2025-05-17 16:27:00 +00:00
[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 svn path=/trunk/; revision=49710
This commit is contained in:
parent
8b5175e0ab
commit
9b693d8c69
6 changed files with 573 additions and 1120 deletions
|
@ -58,8 +58,12 @@ typedef struct _USER_MESSAGE_QUEUE
|
|||
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 @@ VOID FASTCALL
|
|||
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
|
||||
|
|
|
@ -27,9 +27,8 @@ BOOLEAN FASTCALL
|
|||
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,
|
||||
|
|
|
@ -502,387 +502,6 @@ IntDispatchMessage(PMSG pMsg)
|
|||
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 @@ co_IntPeekMessage( PMSG Msg,
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4424,6 +4424,7 @@ NtUserWindowFromPoint(LONG X, LONG Y)
|
|||
POINT pt;
|
||||
HWND Ret;
|
||||
PWND DesktopWindow = NULL, Window = NULL;
|
||||
USHORT hittest;
|
||||
DECLARE_RETURN(HWND);
|
||||
USER_REFERENCE_ENTRY Ref;
|
||||
|
||||
|
@ -4442,7 +4443,7 @@ NtUserWindowFromPoint(LONG X, LONG Y)
|
|||
UserRefObjectCo(DesktopWindow, &Ref);
|
||||
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
co_WinPosWindowFromPoint(DesktopWindow, pti->MessageQueue, &pt, &Window);
|
||||
Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest);
|
||||
|
||||
if(Window)
|
||||
{
|
||||
|
|
|
@ -1578,162 +1578,99 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
|
|||
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;
|
||||
USER_REFERENCE_ENTRY Ref;
|
||||
PWND pwndChild;
|
||||
HWND *List, *phWnd;
|
||||
|
||||
ASSERT_REFS_CO(ScopeWin);
|
||||
if (!(ScopeWin->style & WS_VISIBLE))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((List = IntWinListChildren(ScopeWin)))
|
||||
{
|
||||
for (phWnd = List; *phWnd; ++phWnd)
|
||||
{
|
||||
if (!(Current = UserGetWindowObject(*phWnd)))
|
||||
continue;
|
||||
if ((ScopeWin->style & WS_DISABLED))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(Current->style & WS_VISIBLE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!IntPtInWindow(ScopeWin, Point->x, Point->y))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((Current->style & (WS_POPUP | WS_CHILD | WS_DISABLED)) ==
|
||||
(WS_CHILD | WS_DISABLED))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
UserReferenceObject(ScopeWin);
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
UserDerefObjectCo(Current);
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
ExFreePool(List);
|
||||
}
|
||||
|
||||
UserDerefObjectCo(Current);
|
||||
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* wine: WINPOS_WindowFromPoint */
|
||||
USHORT FASTCALL
|
||||
co_WinPosWindowFromPoint(PWND ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *WinPoint,
|
||||
PWND* Window)
|
||||
PWND FASTCALL
|
||||
co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest)
|
||||
{
|
||||
HWND DesktopWindowHandle;
|
||||
PWND DesktopWindow;
|
||||
PWND Window;
|
||||
POINT Point = *WinPoint;
|
||||
USHORT HitTest;
|
||||
USER_REFERENCE_ENTRY Ref;
|
||||
|
||||
if( ScopeWin == NULL )
|
||||
{
|
||||
ScopeWin = UserGetDesktopWindow();
|
||||
if(ScopeWin == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*HitTest = HTNOWHERE;
|
||||
|
||||
ASSERT_REFS_CO(ScopeWin);
|
||||
UserRefObjectCo(ScopeWin, &Ref);
|
||||
|
||||
*Window = NULL;
|
||||
Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest);
|
||||
|
||||
if(!ScopeWin)
|
||||
{
|
||||
DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
|
||||
return(HTERROR);
|
||||
}
|
||||
UserDerefObjectCo(ScopeWin);
|
||||
if(Window)
|
||||
ASSERT_REFS_CO(Window);
|
||||
ASSERT_REFS_CO(ScopeWin);
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue