- Add ShowingCursor counter and CursorObject to message queue and use them when moving mouse. They are not globally in Windows.

svn path=/trunk/; revision=52136
This commit is contained in:
Rafal Harabien
2011-06-07 20:12:56 +00:00
parent a1560e1c82
commit cc329d2fe9
5 changed files with 225 additions and 139 deletions
@@ -71,8 +71,6 @@ PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon);
BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook);
int UserShowCursor(BOOL bShow);
PSYSTEM_CURSORINFO IntGetSysCursorInfo(VOID);
#define IntReleaseCurIconObject(CurIconObj) \
@@ -1,6 +1,7 @@
#pragma once
#include "hook.h"
#include "cursoricon.h"
#define MSQ_HUNG 5000
#define MSQ_NORMAL 0
@@ -59,8 +60,6 @@ typedef struct _USER_MESSAGE_QUEUE
LIST_ENTRY PostedMessagesListHead;
/* Queue for hardware messages for the queue. */
LIST_ENTRY HardwareMessagesListHead;
/* Lock for the hardware message list. */
KMUTEX HardwareLock;
/* True if a WM_MOUSEMOVE is pending */
BOOLEAN MouseMoved;
/* Current WM_MOUSEMOVE message */
@@ -111,6 +110,11 @@ typedef struct _USER_MESSAGE_QUEUE
/* state of each key */
UCHAR KeyState[256];
/* showing cursor counter (value>=0 - cursor visible, value<0 - cursor hidden) */
INT ShowingCursor;
/* cursor object */
PCURICON_OBJECT CursorObject;
/* messages that are currently dispatched by other threads */
LIST_ENTRY DispatchingMessagesHead;
/* messages that are currently dispatched by this message queue, required for cleanup */
@@ -322,4 +326,10 @@ UINT FASTCALL GetWakeMask(UINT, UINT);
VOID FASTCALL MsqWakeQueue(PUSER_MESSAGE_QUEUE,DWORD,BOOL);
VOID FASTCALL ClearMsgBitsMask(PUSER_MESSAGE_QUEUE,UINT);
int UserShowCursor(BOOL bShow);
PCURICON_OBJECT
FASTCALL
UserSetCursor(PCURICON_OBJECT NewCursor,
BOOL ForceChange);
/* EOF */
@@ -99,80 +99,14 @@ PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
return CurIcon;
}
PCURICON_OBJECT
FASTCALL
UserSetCursor(
PCURICON_OBJECT NewCursor,
BOOL ForceChange)
{
PSYSTEM_CURSORINFO CurInfo;
PCURICON_OBJECT OldCursor;
HDC hdcScreen;
CurInfo = IntGetSysCursorInfo();
OldCursor = CurInfo->CurrentCursorObject;
/* Is the new cursor the same as the old cursor? */
if (OldCursor == NewCursor)
{
/* Nothing to to do in this case */
return OldCursor;
}
/* Get the screen DC */
if(!(hdcScreen = IntGetScreenDC()))
{
return (HCURSOR)0;
}
/* Do we have a new cursor? */
if (NewCursor)
{
CurInfo->ShowingCursor = 0;
CurInfo->CurrentCursorObject = NewCursor;
/* Call GDI to set the new screen cursor */
GreSetPointerShape(hdcScreen,
NewCursor->IconInfo.hbmMask,
NewCursor->IconInfo.hbmColor,
NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
}
else
{
/* Check if were diplaying a cursor */
if (OldCursor && CurInfo->ShowingCursor >= 0)
{
/* Remove the cursor */
GreMovePointer(hdcScreen, -1, -1);
DPRINT("Removing pointer!\n");
}
CurInfo->CurrentCursorObject = NULL;
CurInfo->ShowingCursor = -1;
}
/* Return the old cursor */
return OldCursor;
}
BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
{
PWND DesktopWindow;
PSYSTEM_CURSORINFO CurInfo;
HDC hDC;
MSG Msg;
RECTL rcClip;
POINT pt;
if(!(hDC = IntGetScreenDC()))
{
return FALSE;
}
if(!(DesktopWindow = UserGetDesktopWindow()))
{
return FALSE;
@@ -194,58 +128,19 @@ BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Ho
pt.x = x;
pt.y = y;
/* 3. Generate a mouse move message, this sets the htEx and Track Window too. */
/* 1. Generate a mouse move message, this sets the htEx and Track Window too. */
Msg.message = WM_MOUSEMOVE;
Msg.wParam = CurInfo->ButtonsDown;
Msg.lParam = MAKELPARAM(x, y);
Msg.pt = pt;
co_MsqInsertMouseMessage(&Msg, flags, dwExtraInfo, Hook);
/* 1. Store the new cursor position */
/* 2. Store the new cursor position */
gpsi->ptCursor = pt;
/* 2. Move the mouse pointer */
GreMovePointer(hDC, x, y);
return TRUE;
}
/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
* User32 macro NtUserShowCursor */
int UserShowCursor(BOOL bShow)
{
PSYSTEM_CURSORINFO CurInfo = IntGetSysCursorInfo();
HDC hdcScreen;
if (!(hdcScreen = IntGetScreenDC()))
{
return -1; /* No mouse */
}
if (bShow == FALSE)
{
/* Check if were diplaying a cursor */
if (CurInfo->ShowingCursor == 0)
{
/* Remove the pointer */
GreMovePointer(hdcScreen, -1, -1);
DPRINT("Removing pointer!\n");
}
CurInfo->ShowingCursor--;
}
else
{
if (CurInfo->ShowingCursor == -1)
{
/*Show the pointer*/
GreMovePointer(hdcScreen, gpsi->ptCursor.x, gpsi->ptCursor.y);
}
CurInfo->ShowingCursor++;
}
return CurInfo->ShowingCursor;
}
/*
* We have to register that this object is in use by the current
* process. The only way to do that seems to be to walk the list
@@ -634,7 +634,6 @@ NtUserEnumDisplaySettings(
BOOL APIENTRY UserClipCursor(RECTL *prcl);
VOID APIENTRY UserRedrawDesktop();
HCURSOR FASTCALL UserSetCursor(PCURICON_OBJECT NewCursor, BOOL ForceChange);
LONG
APIENTRY
+211 -27
View File
@@ -43,6 +43,151 @@ MsqInitializeImpl(VOID)
return(STATUS_SUCCESS);
}
PWND FASTCALL
IntTopLevelWindowFromPoint(INT x, INT y)
{
PWND pWnd, pwndDesktop;
/* Get the desktop window */
pwndDesktop = UserGetDesktopWindow();
if (!pwndDesktop)
return NULL;
/* Loop all top level windows */
for (pWnd = pwndDesktop->spwndChild;
pWnd != NULL;
pWnd = pWnd->spwndNext)
{
if (pWnd->state2 & WNDS2_INDESTROY || pWnd->state & WNDS_DESTROYED)
{
DPRINT("The Window is in DESTROY!\n");
continue;
}
if ((pWnd->style & WS_VISIBLE) && IntPtInWindow(pWnd, x, y))
return pWnd;
}
/* Window has not been found */
return NULL;
}
PCURICON_OBJECT
FASTCALL
UserSetCursor(
PCURICON_OBJECT NewCursor,
BOOL ForceChange)
{
PCURICON_OBJECT OldCursor;
HDC hdcScreen;
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE MessageQueue;
PWND pWnd;
pti = PsGetCurrentThreadWin32Thread();
MessageQueue = pti->MessageQueue;
/* Get the screen DC */
if(!(hdcScreen = IntGetScreenDC()))
{
return (HCURSOR)0;
}
OldCursor = MessageQueue->CursorObject;
/* Check if cursors are different */
if (OldCursor == NewCursor)
return OldCursor;
/* Update cursor for this message queue */
MessageQueue->CursorObject = NewCursor;
/* If cursor is not visible we have nothing to do */
if (MessageQueue->ShowingCursor < 0)
return OldCursor;
/* Update cursor if this message queue controls it */
pWnd = IntTopLevelWindowFromPoint(gpsi->ptCursor.x, gpsi->ptCursor.y);
if (pWnd && pWnd->head.pti->MessageQueue == MessageQueue)
{
if (NewCursor)
{
/* Call GDI to set the new screen cursor */
GreSetPointerShape(hdcScreen,
NewCursor->IconInfo.hbmMask,
NewCursor->IconInfo.hbmColor,
NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
}
else /* Note: OldCursor != NewCursor so we have to hide cursor */
{
/* Remove the cursor */
GreMovePointer(hdcScreen, -1, -1);
DPRINT1("Removing pointer!\n");
DbgBreakPoint();
}
IntGetSysCursorInfo()->CurrentCursorObject = NewCursor;
}
/* Return the old cursor */
return OldCursor;
}
/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
* User32 macro NtUserShowCursor */
int UserShowCursor(BOOL bShow)
{
HDC hdcScreen;
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE MessageQueue;
PWND pWnd;
if (!(hdcScreen = IntGetScreenDC()))
{
return -1; /* No mouse */
}
pti = PsGetCurrentThreadWin32Thread();
MessageQueue = pti->MessageQueue;
/* Update counter */
MessageQueue->ShowingCursor += bShow ? 1 : -1;
/* Check for trivial cases */
if ((bShow && MessageQueue->ShowingCursor != 0) ||
(!bShow && MessageQueue->ShowingCursor != -1))
{
/* Note: w don't update global info here because it is used only
internally to check if cursor is visible */
return MessageQueue->ShowingCursor;
}
/* Check if cursor is above window owned by this MessageQueue */
pWnd = IntTopLevelWindowFromPoint(gpsi->ptCursor.x, gpsi->ptCursor.y);
if (pWnd && pWnd->head.pti->MessageQueue == MessageQueue)
{
if (bShow)
{
/* Show the pointer */
GreMovePointer(hdcScreen, gpsi->ptCursor.x, gpsi->ptCursor.y);
DPRINT1("Showing pointer!\n");
}
else
{
/* Remove the pointer */
GreMovePointer(hdcScreen, -1, -1);
DPRINT1("Removing pointer!\n");
}
/* Update global info */
IntGetSysCursorInfo()->ShowingCursor = MessageQueue->ShowingCursor;
}
return MessageQueue->ShowingCursor;
}
DWORD FASTCALL UserGetKeyState(DWORD key)
{
DWORD ret = 0;
@@ -307,13 +452,15 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
MSLLHOOKSTRUCT MouseHookData;
PDESKTOP pDesk;
PWND pwnd, pwndDesktop;
HDC hdcScreen;
PSYSTEM_CURSORINFO CurInfo;
KeQueryTickCount(&LargeTickCount);
Msg->time = MsqCalculateMessageTime(&LargeTickCount);
MouseHookData.pt.x = LOWORD(Msg->lParam);
MouseHookData.pt.y = HIWORD(Msg->lParam);
switch(Msg->message)
switch (Msg->message)
{
case WM_MOUSEWHEEL:
MouseHookData.mouseData = MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg->wParam));
@@ -344,7 +491,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
/* Get the desktop window */
pwndDesktop = UserGetDesktopWindow();
if(!pwndDesktop)
if (!pwndDesktop)
return;
/* Set hit somewhere on the desktop */
@@ -354,7 +501,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
/* Check if the mouse is captured */
Msg->hwnd = IntGetCaptureWindow();
if(Msg->hwnd != NULL)
if (Msg->hwnd != NULL)
{
pwnd = UserGetWindowObject(Msg->hwnd);
if ((pwnd->style & WS_VISIBLE) &&
@@ -366,35 +513,54 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
}
else
{
/* Loop all top level windows to find which one should receive input */
for( pwnd = pwndDesktop->spwndChild;
pwnd != NULL;
pwnd = pwnd->spwndNext )
pwnd = IntTopLevelWindowFromPoint(Msg->pt.x, Msg->pt.y);
if (pwnd)
{
if ( pwnd->state2 & WNDS2_INDESTROY || pwnd->state & WNDS_DESTROYED )
{
DPRINT("The Window is in DESTROY!\n");
continue;
}
if((pwnd->style & WS_VISIBLE) &&
IntPtInWindow(pwnd, Msg->pt.x, Msg->pt.y))
{
Msg->hwnd = pwnd->head.h;
pDesk->htEx = HTCLIENT;
pDesk->spwndTrack = pwnd;
break;
}
Msg->hwnd = pwnd->head.h;
pDesk->htEx = HTCLIENT;
pDesk->spwndTrack = pwnd;
}
}
hdcScreen = IntGetScreenDC();
CurInfo = IntGetSysCursorInfo();
/* Check if we found a window */
if(Msg->hwnd != NULL && pwnd != NULL)
if (Msg->hwnd != NULL && pwnd != NULL)
{
if(Msg->message == WM_MOUSEMOVE)
if (Msg->message == WM_MOUSEMOVE)
{
/* Mouse move is a special case*/
MsqPostMouseMove(pwnd->head.pti->MessageQueue, Msg);
PUSER_MESSAGE_QUEUE MessageQueue = pwnd->head.pti->MessageQueue;
/* Check if cursor should be visible */
if(hdcScreen &&
MessageQueue->CursorObject &&
MessageQueue->ShowingCursor >= 0)
{
/* Check if shape has changed */
if(CurInfo->CurrentCursorObject != MessageQueue->CursorObject)
{
/* Call GDI to set the new screen cursor */
GreSetPointerShape(hdcScreen,
MessageQueue->CursorObject->IconInfo.hbmMask,
MessageQueue->CursorObject->IconInfo.hbmColor,
MessageQueue->CursorObject->IconInfo.xHotspot,
MessageQueue->CursorObject->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
} else
GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y);
}
/* Check if w have to hide cursor */
else if (CurInfo->ShowingCursor >= 0)
GreMovePointer(hdcScreen, -1, -1);
/* Update global cursor info */
CurInfo->ShowingCursor = MessageQueue->ShowingCursor;
CurInfo->CurrentCursorObject = MessageQueue->CursorObject;
/* Mouse move is a special case */
MsqPostMouseMove(MessageQueue, Msg);
}
else
{
@@ -402,6 +568,12 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
MsqPostMessage(pwnd->head.pti->MessageQueue, Msg, TRUE, QS_MOUSEBUTTON);
}
}
else if (hdcScreen)
{
/* always show cursor on background; FIXME: set default pointer */
GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y);
CurInfo->ShowingCursor = 0;
}
/* Do GetMouseMovePointsEx FIFO. */
MouseHistoryOfMoves[gcur_count].x = Msg->pt.x;
@@ -1601,13 +1773,14 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu
InitializeListHead(&MessageQueue->HardwareMessagesListHead);
InitializeListHead(&MessageQueue->DispatchingMessagesHead);
InitializeListHead(&MessageQueue->LocalDispatchingMessagesHead);
KeInitializeMutex(&MessageQueue->HardwareLock, 0);
MessageQueue->QuitPosted = FALSE;
MessageQueue->QuitExitCode = 0;
KeQueryTickCount(&LargeTickCount);
MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
MessageQueue->FocusWindow = NULL;
MessageQueue->NewMessagesHandle = NULL;
MessageQueue->ShowingCursor = 0;
MessageQueue->CursorObject = NULL;
Status = ZwCreateEvent(&MessageQueue->NewMessagesHandle, EVENT_ALL_ACCESS,
NULL, SynchronizationEvent, FALSE);
@@ -1763,6 +1936,18 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
MessageQueue->nCntsQBits[QSRosPostMessage] = 0;
MessageQueue->nCntsQBits[QSRosSendMessage] = 0;
MessageQueue->nCntsQBits[QSRosHotKey] = 0;
if (MessageQueue->CursorObject)
{
PCURICON_OBJECT pCursor = MessageQueue->CursorObject;
/* Change to another cursor if we going to dereference current one */
if (IntGetSysCursorInfo()->CurrentCursorObject == pCursor)
UserSetCursor(NULL, TRUE);
UserDereferenceObject(pCursor);
}
}
PUSER_MESSAGE_QUEUE FASTCALL
@@ -1989,5 +2174,4 @@ NtUserSetKeyboardState(LPBYTE lpKeyState)
return ret;
}
/* EOF */