Author: rharabien Date: Tue Jun 7 20:12:56 2011 New Revision: 52136
URL: http://svn.reactos.org/svn/reactos?rev=52136&view=rev Log: - Add ShowingCursor counter and CursorObject to message queue and use them when moving mouse. They are not globally in Windows.
Modified: trunk/reactos/subsystems/win32/win32k/include/cursoricon.h trunk/reactos/subsystems/win32/win32k/include/msgqueue.h trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c trunk/reactos/subsystems/win32/win32k/ntuser/display.c trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c
Modified: trunk/reactos/subsystems/win32/win32k/include/cursoricon.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/cursoricon.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/cursoricon.h [iso-8859-1] Tue Jun 7 20:12:56 2011 @@ -71,8 +71,6 @@
BOOL UserSetCursorPos( INT x, INT y, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook);
-int UserShowCursor(BOOL bShow); - PSYSTEM_CURSORINFO IntGetSysCursorInfo(VOID);
#define IntReleaseCurIconObject(CurIconObj) \
Modified: trunk/reactos/subsystems/win32/win32k/include/msgqueue.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/msgqueue.h [iso-8859-1] Tue Jun 7 20:12:56 2011 @@ -1,6 +1,7 @@ #pragma once
#include "hook.h" +#include "cursoricon.h"
#define MSQ_HUNG 5000 #define MSQ_NORMAL 0 @@ -59,8 +60,6 @@ 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 @@ /* 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 @@ 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 */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c [iso-8859-1] Tue Jun 7 20:12:56 2011 @@ -99,79 +99,13 @@ 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())) { @@ -194,56 +128,17 @@ 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; }
/*
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/display.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/display.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/display.c [iso-8859-1] Tue Jun 7 20:12:56 2011 @@ -634,7 +634,6 @@
BOOL APIENTRY UserClipCursor(RECTL *prcl); VOID APIENTRY UserRedrawDesktop(); -HCURSOR FASTCALL UserSetCursor(PCURICON_OBJECT NewCursor, BOOL ForceChange);
LONG APIENTRY
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] Tue Jun 7 20:12:56 2011 @@ -41,6 +41,151 @@ 256);
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) @@ -307,13 +452,15 @@ 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 @@
/* Get the desktop window */ pwndDesktop = UserGetDesktopWindow(); - if(!pwndDesktop) + if (!pwndDesktop) return;
/* Set hit somewhere on the desktop */ @@ -354,7 +501,7 @@
/* 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,41 +513,66 @@ } 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 ) + 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->message == WM_MOUSEMOVE) + { + PUSER_MESSAGE_QUEUE MessageQueue = pwnd->head.pti->MessageQueue; + + /* Check if cursor should be visible */ + if(hdcScreen && + MessageQueue->CursorObject && + MessageQueue->ShowingCursor >= 0) { - DPRINT("The Window is in DESTROY!\n"); - continue; + /* 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); } - - 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; - } - } - } - - /* Check if we found a window */ - if(Msg->hwnd != NULL && pwnd != NULL) - { - if(Msg->message == WM_MOUSEMOVE) - { - /* Mouse move is a special case*/ - MsqPostMouseMove(pwnd->head.pti->MessageQueue, Msg); + /* 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 { DPRINT("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd)); 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. */ @@ -1601,13 +1773,14 @@ 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 @@ 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 @@ return ret; }
- /* EOF */