You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
831 lines
23 KiB
831 lines
23 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: cursor.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* This module contains code for dealing with cursors.
|
|
*
|
|
* History:
|
|
* 03-Dec-1990 DavidPe Created.
|
|
* 01-Feb-1991 MikeKe Added Revalidation code (None)
|
|
* 12-Feb-1991 JimA Added access checks
|
|
* 21-Jan-1992 IanJa ANSI/Unicode neutralized (null op)
|
|
* 02-Aug-1992 DarrinM Added animated cursor code
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
/***************************************************************************\
|
|
* zzzSetCursor (API)
|
|
*
|
|
* This API sets the cursor image for the current thread.
|
|
*
|
|
* History:
|
|
* 12-03-90 DavidPe Created.
|
|
\***************************************************************************/
|
|
|
|
PCURSOR zzzSetCursor(
|
|
PCURSOR pcur)
|
|
{
|
|
PQ pq;
|
|
PCURSOR pcurPrev;
|
|
PTHREADINFO ptiCurrent = PtiCurrent();
|
|
|
|
pq = ptiCurrent->pq;
|
|
|
|
pcurPrev = pq->spcurCurrent;
|
|
|
|
if (pq->spcurCurrent != pcur) {
|
|
|
|
/*
|
|
* Lock() returns pobjOld - if it is still valid. Don't want to
|
|
* return a pcurPrev that is an invalid pointer.
|
|
*/
|
|
pcurPrev = LockQCursor(pq, pcur);
|
|
|
|
/*
|
|
* If no thread 'owns' the cursor, we must be in initialization
|
|
* so go ahead and assign it to ourself.
|
|
*/
|
|
if (gpqCursor == NULL)
|
|
gpqCursor = pq;
|
|
|
|
/*
|
|
* If we're changing the local-cursor for the thread currently
|
|
* representing the global-cursor, update the cursor image now.
|
|
*/
|
|
if (pq == gpqCursor) {
|
|
TL tlpcur;
|
|
ThreadLockWithPti(ptiCurrent, pcurPrev, &tlpcur);
|
|
zzzUpdateCursorImage();
|
|
pcurPrev = ThreadUnlock(&tlpcur);
|
|
}
|
|
}
|
|
|
|
return pcurPrev;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* zzzSetCursorPos (API)
|
|
*
|
|
* This API sets the cursor position.
|
|
*
|
|
* History:
|
|
* 03-Dec-1990 DavidPe Created.
|
|
* 12-Feb-1991 JimA Added access check
|
|
* 16-May-1991 mikeke Changed to return BOOL
|
|
\***************************************************************************/
|
|
|
|
BOOL zzzSetCursorPos(
|
|
int x,
|
|
int y)
|
|
{
|
|
/*
|
|
* Blow it off if the caller doesn't have the proper access rights
|
|
*/
|
|
if (!CheckWinstaWriteAttributesAccess()) {
|
|
return FALSE;
|
|
}
|
|
|
|
zzzInternalSetCursorPos(x, y);
|
|
|
|
/*
|
|
* Save the absolute coordinates in the global array
|
|
* for GetMouseMovePointsEx.
|
|
*/
|
|
SAVEPOINT(x, y,
|
|
SYSMET(CXVIRTUALSCREEN) - 1,
|
|
SYSMET(CYVIRTUALSCREEN) - 1,
|
|
NtGetTickCount(), 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* zzzInternalSetCursorPos
|
|
*
|
|
* This function is used whenever the server needs to set the cursor
|
|
* position, regardless of the caller's access rights.
|
|
*
|
|
* History:
|
|
* 12-Feb-1991 JimA Created.
|
|
\***************************************************************************/
|
|
VOID zzzInternalSetCursorPos(
|
|
int x,
|
|
int y
|
|
)
|
|
{
|
|
|
|
gptCursorAsync.x = x;
|
|
gptCursorAsync.y = y;
|
|
|
|
BoundCursor(&gptCursorAsync);
|
|
|
|
gpsi->ptCursor = gptCursorAsync;
|
|
/*
|
|
* Pass MP_PROCEDURAL as the last parameter so that in the
|
|
* remote case we send an updated mouse position to the client
|
|
*/
|
|
GreMovePointer(gpDispInfo->hDev, gpsi->ptCursor.x, gpsi->ptCursor.y,
|
|
MP_PROCEDURAL);
|
|
|
|
/*
|
|
* Cursor has changed position, so generate a mouse event so the
|
|
* window underneath the new location knows it's there and sets the
|
|
* shape accordingly.
|
|
*/
|
|
zzzSetFMouseMoved();
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* IncCursorLevel
|
|
* DecCursorLevel
|
|
*
|
|
* Keeps track of this thread show/hide cursor level as well as the queue
|
|
* it is associated with. Thread levels are done so that when
|
|
* AttachThreadInput() is called we can do exact level calculations in the
|
|
* new queue.
|
|
*
|
|
* 15-Jan-1993 ScottLu Created.
|
|
\***************************************************************************/
|
|
|
|
VOID IncCursorLevel(
|
|
PTHREADINFO pti)
|
|
{
|
|
pti->iCursorLevel++;
|
|
pti->pq->iCursorLevel++;
|
|
}
|
|
|
|
VOID DecCursorLevel(
|
|
PTHREADINFO pti)
|
|
{
|
|
pti->iCursorLevel--;
|
|
pti->pq->iCursorLevel--;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* zzzShowCursor (API)
|
|
*
|
|
* This API allows the application to hide or show the cursor image.
|
|
*
|
|
* History:
|
|
* 03-Dec-1990 JimA Implemented for fake cursor stuff
|
|
\***************************************************************************/
|
|
|
|
int zzzShowCursor(
|
|
BOOL fShow)
|
|
{
|
|
PTHREADINFO pti = PtiCurrent();
|
|
PQ pq;
|
|
int iCursorLevel;
|
|
|
|
pq = pti->pq;
|
|
/*
|
|
* To preserve pq
|
|
*/
|
|
DeferWinEventNotify();
|
|
|
|
if (fShow) {
|
|
|
|
IncCursorLevel(pti);
|
|
|
|
if ((pq == gpqCursor) && (pq->iCursorLevel == 0))
|
|
zzzUpdateCursorImage();
|
|
|
|
} else {
|
|
|
|
DecCursorLevel(pti);
|
|
|
|
if ((pq == gpqCursor) && (pq->iCursorLevel == -1))
|
|
zzzUpdateCursorImage();
|
|
}
|
|
|
|
iCursorLevel = pq->iCursorLevel;
|
|
zzzEndDeferWinEventNotify();
|
|
|
|
return iCursorLevel;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* zzzClipCursor (API)
|
|
*
|
|
* This API sets the cursor clipping rectangle which restricts where the
|
|
* cursor can go. If prcClip is NULL, the clipping rectangle will be the
|
|
* screen.
|
|
*
|
|
* History:
|
|
* 03-Dec-1990 DavidPe Created.
|
|
* 16-May-1991 MikeKe Changed to return BOOL
|
|
\***************************************************************************/
|
|
|
|
BOOL zzzClipCursor(
|
|
LPCRECT prcClip)
|
|
{
|
|
PEPROCESS Process = PsGetCurrentProcess();
|
|
|
|
/*
|
|
* Don't let this happen if it doesn't have access.
|
|
*/
|
|
if (Process != gpepCSRSS && !CheckWinstaWriteAttributesAccess()) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* The comment from NT 3.51:
|
|
* Non-foreground threads can only set the clipping rectangle
|
|
* if it was empty, or if they are restoring it to the whole screen.
|
|
*
|
|
* But the code from NT 3.51 says "IsRectEmpty" instead of
|
|
* "!IsRectEmpty", as would follow from the comment. We leave
|
|
* the code as it was, as following the comment appears to
|
|
* break apps.
|
|
*
|
|
* CONSIDER: Removing this test altogether after NT4.0 ships.
|
|
*/
|
|
if ( PtiCurrent()->pq != gpqForeground &&
|
|
prcClip != NULL &&
|
|
IsRectEmpty(&grcCursorClip)) {
|
|
RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, "Access denied in _ClipCursor");
|
|
return FALSE;
|
|
}
|
|
|
|
if (prcClip == NULL) {
|
|
|
|
grcCursorClip = gpDispInfo->rcScreen;
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Never let our cursor leave the screen. Can't use IntersectRect()
|
|
* because it doesn't allow rects with 0 width or height.
|
|
*/
|
|
grcCursorClip.left = max(gpDispInfo->rcScreen.left , prcClip->left);
|
|
grcCursorClip.right = min(gpDispInfo->rcScreen.right , prcClip->right);
|
|
grcCursorClip.top = max(gpDispInfo->rcScreen.top , prcClip->top);
|
|
grcCursorClip.bottom = min(gpDispInfo->rcScreen.bottom, prcClip->bottom);
|
|
|
|
/*
|
|
* Check for invalid clip rect.
|
|
*/
|
|
if (grcCursorClip.left > grcCursorClip.right ||
|
|
grcCursorClip.top > grcCursorClip.bottom) {
|
|
|
|
grcCursorClip = gpDispInfo->rcScreen;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Update the cursor position if it's currently outside the
|
|
* cursor clip-rect.
|
|
*/
|
|
if (!PtInRect(&grcCursorClip, gpsi->ptCursor)) {
|
|
zzzInternalSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* BoundCursor
|
|
*
|
|
* This rountine 'clips' gptCursorAsync to be within rcCursorClip. This
|
|
* routine treats rcCursorClip as non-inclusive so the bottom and right sides
|
|
* get bound to rcCursorClip.bottom/right - 1.
|
|
*
|
|
* Is called in OR out of the USER critical section!! IANJA
|
|
*
|
|
* History:
|
|
* 03-Dec-1990 DavidPe Created.
|
|
\***************************************************************************/
|
|
#ifdef LOCK_MOUSE_CODE
|
|
#pragma alloc_text(MOUSE, BoundCursor)
|
|
#endif
|
|
|
|
VOID BoundCursor(
|
|
LPPOINT lppt)
|
|
{
|
|
if (TEST_PUDF(PUDF_VDMBOUNDSACTIVE) && gspwndFullScreen != NULL) {
|
|
|
|
if (lppt->x < grcVDMCursorBounds.left) {
|
|
lppt->x = grcVDMCursorBounds.left;
|
|
} else if (lppt->x >= grcVDMCursorBounds.right) {
|
|
lppt->x = grcVDMCursorBounds.right - 1;
|
|
}
|
|
|
|
if (lppt->y < grcVDMCursorBounds.top) {
|
|
lppt->y = grcVDMCursorBounds.top;
|
|
} else if (lppt->y >= grcVDMCursorBounds.bottom) {
|
|
lppt->y = grcVDMCursorBounds.bottom - 1;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (lppt->x < grcCursorClip.left) {
|
|
lppt->x = grcCursorClip.left;
|
|
} else if (lppt->x >= grcCursorClip.right) {
|
|
lppt->x = grcCursorClip.right - 1;
|
|
}
|
|
|
|
if (lppt->y < grcCursorClip.top) {
|
|
lppt->y = grcCursorClip.top;
|
|
} else if (lppt->y >= grcCursorClip.bottom) {
|
|
lppt->y = grcCursorClip.bottom - 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If we have more than one monitor, then we need to clip the
|
|
* cursor to a point on the desktop.
|
|
*/
|
|
if (!gpDispInfo->fDesktopIsRect) {
|
|
ClipPointToDesktop(lppt);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* SetVDMCursorBounds
|
|
*
|
|
* This routine is needed so when a vdm is running, the mouse is not bounded
|
|
* by the screen. This is so the vdm can correctly virtualize the DOS mouse
|
|
* device driver. It can't deal with user always bounding to the screen,
|
|
* so it sets wide open bounds.
|
|
*
|
|
* 20-May-1993 ScottLu Created.
|
|
\***************************************************************************/
|
|
|
|
VOID SetVDMCursorBounds(
|
|
LPRECT lprc)
|
|
{
|
|
if (lprc != NULL) {
|
|
|
|
/*
|
|
* Set grcVDMCursorBounds before TEST_PUDF(PUDF_VDMBOUNDSACTIVE), because
|
|
* MoveEvent() calls BoundCursor() from outside the USER CritSect!
|
|
*/
|
|
grcVDMCursorBounds = *lprc;
|
|
Win32MemoryBarrier(); // Ensure grcVDMCursorBounds is updated first.
|
|
SET_PUDF(PUDF_VDMBOUNDSACTIVE);
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Turn vdm bounds off.
|
|
*/
|
|
CLEAR_PUDF(PUDF_VDMBOUNDSACTIVE);
|
|
}
|
|
|
|
/*
|
|
* Before returning from this function,
|
|
* make sure the write instructions are all retired.
|
|
*/
|
|
Win32MemoryBarrier();
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* zzzAnimateCursor
|
|
*
|
|
* When an animated cursor is loaded and the wait cursor is up this routine
|
|
* gets called to maintain the cursor animation.
|
|
*
|
|
* Should only be called by the cursor animation timer.
|
|
*
|
|
* History:
|
|
* 02-Oct-1991 DarrinM Created.
|
|
* 03-Aug-1994 SanfordS Calibrated.
|
|
\***************************************************************************/
|
|
|
|
#if defined (_M_IX86) && (_MSC_VER <= 1100)
|
|
#pragma optimize("s", off)
|
|
#endif
|
|
|
|
VOID zzzAnimateCursor(
|
|
PWND pwndDummy,
|
|
UINT message,
|
|
UINT_PTR nID,
|
|
LPARAM lParam)
|
|
{
|
|
int iicur;
|
|
PACON pacon;
|
|
TL tlpacon;
|
|
int LostTime;
|
|
int tTime;
|
|
|
|
pacon = (PACON)gpcurLogCurrent;
|
|
|
|
if (pacon == NULL || !(pacon->CURSORF_flags & CURSORF_ACON)) {
|
|
gdwLastAniTick = 0;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Find out actual time loss since last update.
|
|
*/
|
|
if (gdwLastAniTick) {
|
|
|
|
LostTime = NtGetTickCount() - gdwLastAniTick -
|
|
(pacon->ajifRate[pacon->iicur] * 100 / 6);
|
|
|
|
if (LostTime < 0)
|
|
LostTime = 0;
|
|
|
|
} else {
|
|
|
|
LostTime = 0;
|
|
}
|
|
|
|
/*
|
|
* Increment the animation index.
|
|
*/
|
|
iicur = pacon->iicur + 1;
|
|
if (iicur >= pacon->cicur)
|
|
iicur = 0;
|
|
|
|
pacon->iicur = iicur;
|
|
|
|
/*
|
|
* This forces the new cursor to be drawn.
|
|
*/
|
|
ThreadLockAlways(pacon, &tlpacon);
|
|
zzzUpdateCursorImage();
|
|
|
|
tTime = pacon->ajifRate[iicur] * 100 / 6;
|
|
|
|
while (tTime < LostTime) {
|
|
|
|
/*
|
|
* Animation is outrunning our ability to render it - skip frames
|
|
* to catch up.
|
|
*/
|
|
LostTime -= tTime;
|
|
|
|
/*
|
|
* Increment the animation index.
|
|
*/
|
|
iicur = pacon->iicur + 1;
|
|
if (iicur >= pacon->cicur)
|
|
iicur = 0;
|
|
|
|
pacon->iicur = iicur;
|
|
|
|
tTime = pacon->ajifRate[iicur] * 100 / 6;
|
|
}
|
|
ThreadUnlock(&tlpacon);
|
|
|
|
gdwLastAniTick = NtGetTickCount() - LostTime;
|
|
gidCursorTimer = InternalSetTimer(NULL, gidCursorTimer, tTime - LostTime, zzzAnimateCursor, TMRF_RIT | TMRF_ONESHOT);
|
|
|
|
return;
|
|
|
|
|
|
DBG_UNREFERENCED_PARAMETER(pwndDummy);
|
|
DBG_UNREFERENCED_PARAMETER(message);
|
|
DBG_UNREFERENCED_PARAMETER(nID);
|
|
DBG_UNREFERENCED_PARAMETER(lParam);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* FCursorShadowed
|
|
*
|
|
\**************************************************************************/
|
|
|
|
__inline FCursorShadowed(PCURSINFO pci)
|
|
{
|
|
return (TestALPHA(CURSORSHADOW) && (pci->CURSORF_flags & CURSORF_SYSTEM));
|
|
}
|
|
|
|
#if defined (_M_IX86) && (_MSC_VER <= 1100)
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
/**************************************************************************\
|
|
* zzzUpdateCursorImage
|
|
*
|
|
* History:
|
|
* 14-Jan-1992 DavidPe Created.
|
|
* 09-Aug-1992 DarrinM Added animated cursor code.
|
|
* 01-Oct-2000 JasonSch Added autorun cursor code.
|
|
\**************************************************************************/
|
|
VOID zzzUpdateCursorImage()
|
|
{
|
|
PCURSOR pcurLogNew;
|
|
PCURSOR pcurPhysNew;
|
|
PACON pacon;
|
|
PCURSOR pcurPhysOld;
|
|
DWORD event;
|
|
|
|
#ifdef GENERIC_INPUT
|
|
/*
|
|
* WindowsBug 298252
|
|
* Even though the mouse pointer is outside
|
|
* the GenericInput aware app, allow it to hide
|
|
* the mouse cursor if mouse is captured.
|
|
* i.e. use gpqForeground instead of gpqCursor.
|
|
*/
|
|
if (gpqForeground) {
|
|
PTHREADINFO ptiMouse = PtiMouseFromQ(gpqForeground);
|
|
|
|
if (TestRawInputMode(ptiMouse, CaptureMouse)) {
|
|
if (gpqForeground->iCursorLevel < 0) {
|
|
pcurLogNew = NULL;
|
|
goto force_setnull;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (gpqCursor == NULL)
|
|
return;
|
|
|
|
if ((gpqCursor->iCursorLevel < 0) || (gpqCursor->spcurCurrent == NULL)) {
|
|
|
|
pcurLogNew = NULL;
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Assume we're using the current cursor.
|
|
*/
|
|
pcurLogNew = gpqCursor->spcurCurrent;
|
|
|
|
/*
|
|
* Check to see if we should use the "app starting" or the "autorun"
|
|
* cursor.
|
|
*/
|
|
if (gtimeStartCursorHide != 0
|
|
#ifdef AUTORUN_CURSOR
|
|
|| gtmridAutorunCursor != 0
|
|
#endif // AUTORUN_CURSOR
|
|
) {
|
|
|
|
if (gpqCursor->spcurCurrent == SYSCUR(ARROW) ||
|
|
#ifdef AUTORUN_CURSOR
|
|
gpqCursor->spcurCurrent == SYSCUR(AUTORUN) ||
|
|
#endif // AUTORUN_CURSOR
|
|
gpqCursor->spcurCurrent == SYSCUR(APPSTARTING)) {
|
|
|
|
#ifdef AUTORUN_CURSOR
|
|
if (gtmridAutorunCursor != 0) {
|
|
pcurLogNew = SYSCUR(AUTORUN);
|
|
} else {
|
|
#endif // AUTORUN_CURSOR
|
|
pcurLogNew = SYSCUR(APPSTARTING);
|
|
#ifdef AUTORUN_CURSOR
|
|
}
|
|
#endif // AUTORUN_CURSOR
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef GENERIC_INPUT
|
|
force_setnull:
|
|
#endif
|
|
|
|
/*
|
|
* If the logical cursor is changing then start/stop the cursor
|
|
* animation timer as appropriate.
|
|
*/
|
|
if (pcurLogNew != gpcurLogCurrent) {
|
|
|
|
/*
|
|
* If the old cursor was animating, shut off the animation timer.
|
|
*/
|
|
if (gtmridAniCursor != 0) {
|
|
/*
|
|
* Disable animation.
|
|
*/
|
|
KILLRITTIMER(NULL, gtmridAniCursor);
|
|
gtmridAniCursor = 0;
|
|
}
|
|
|
|
/*
|
|
* If the new cursor is animated, start the animation timer.
|
|
*/
|
|
if ((pcurLogNew != NULL) && (pcurLogNew->CURSORF_flags & CURSORF_ACON)) {
|
|
|
|
/*
|
|
* Start the animation over from the beginning.
|
|
*/
|
|
pacon = (PACON)pcurLogNew;
|
|
pacon->iicur = 0;
|
|
|
|
gdwLastAniTick = NtGetTickCount();
|
|
|
|
/*
|
|
* Use the rate table to keep the timer on track.
|
|
* 1 Jiffy = 1/60 sec = 100/6 ms
|
|
*/
|
|
gtmridAniCursor = InternalSetTimer(NULL,
|
|
gtmridAniCursor,
|
|
pacon->ajifRate[0] * 100 / 6,
|
|
zzzAnimateCursor,
|
|
TMRF_RIT | TMRF_ONESHOT);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If this is an animated cursor, find and use the current frame
|
|
* of the animation. NOTE: this is done AFTER the AppStarting
|
|
* business so the AppStarting cursor itself can be animated.
|
|
*/
|
|
if (pcurLogNew != NULL && pcurLogNew->CURSORF_flags & CURSORF_ACON) {
|
|
|
|
pcurPhysNew = ((PACON)pcurLogNew)->aspcur[((PACON)pcurLogNew)->
|
|
aicur[((PACON)pcurLogNew)->iicur]];
|
|
} else {
|
|
|
|
pcurPhysNew = pcurLogNew;
|
|
}
|
|
|
|
/*
|
|
* Remember the new logical cursor.
|
|
*/
|
|
gpcurLogCurrent = pcurLogNew;
|
|
|
|
/*
|
|
* If the physical cursor is changing then update screen.
|
|
*/
|
|
if (pcurPhysNew != gpcurPhysCurrent) {
|
|
|
|
pcurPhysOld = gpcurPhysCurrent;
|
|
|
|
gpcurPhysCurrent = pcurPhysNew;
|
|
|
|
if (pcurPhysNew == NULL) {
|
|
|
|
SetPointer(FALSE);
|
|
|
|
} else {
|
|
ULONG fl = 0;
|
|
|
|
if (pcurLogNew->CURSORF_flags & CURSORF_ACON) {
|
|
fl |= SPS_ANIMATEUPDATE;
|
|
}
|
|
if (FCursorShadowed(GETPCI(pcurLogNew))) {
|
|
fl |= SPS_ALPHA;
|
|
}
|
|
GreSetPointer(gpDispInfo->hDev, GETPCI(pcurPhysNew), fl, GETMOUSETRAILS(), MOUSE_TRAILS_FREQ);
|
|
}
|
|
|
|
/*
|
|
* Notify anyone who cares about the change
|
|
* This can happen on the RIT, so we need to pass on the real
|
|
* thread/process ID. Hence we use hwndCursor.
|
|
* This comment is from WIn'95 so it may not be true - IanJa.
|
|
*
|
|
* These are the events we send:
|
|
* hcurPhys now NULL -> EVENT_OBJECT_HIDE
|
|
* hcurPhys was NULL -> EVENT_OBJECT_SHOW
|
|
* hcurPhys changing -> EVENT_OBJECT_NAMECHANGE
|
|
* Since we only go through this code if hcurPhys is actually
|
|
* changing, these checks are simple.
|
|
*/
|
|
if (!pcurPhysNew) {
|
|
event = EVENT_OBJECT_HIDE;
|
|
} else if (!pcurPhysOld) {
|
|
event = EVENT_OBJECT_SHOW;
|
|
} else {
|
|
event = EVENT_OBJECT_NAMECHANGE;
|
|
}
|
|
|
|
zzzWindowEvent(event, NULL, OBJID_CURSOR, INDEXID_CONTAINER, WEF_USEPWNDTHREAD);
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
|
|
/***************************************************************************\
|
|
* DbgLockQCursor
|
|
*
|
|
* Special routine to lock cursors into a queue. Besides a pointer
|
|
* to the cursor, the handle is also saved.
|
|
* Returns the pointer to the previous current cursor for that queue.
|
|
*
|
|
* History:
|
|
* 26-Jan-1993 JimA Created.
|
|
\***************************************************************************/
|
|
|
|
PCURSOR DbgLockQCursor(
|
|
PQ pq,
|
|
PCURSOR pcur)
|
|
{
|
|
/*
|
|
* See if the queue is marked for destuction. If so, we should not
|
|
* be trying to lock a cursor.
|
|
*/
|
|
UserAssertMsg0(!(pq->QF_flags & QF_INDESTROY),
|
|
"LockQCursor: Attempting to lock cursor to freed queue");
|
|
|
|
return Lock(&pq->spcurCurrent, pcur);
|
|
}
|
|
|
|
#endif // DBG
|
|
|
|
/***************************************************************************\
|
|
* SetPointer
|
|
*
|
|
* 29-Mar-1998 vadimg created
|
|
\***************************************************************************/
|
|
|
|
void SetPointer(BOOL fSet)
|
|
{
|
|
if (fSet) {
|
|
#ifdef GENERIC_INPUT
|
|
if (gpqForeground) {
|
|
PTHREADINFO ptiMouse = PtiMouseFromQ(gpqForeground);
|
|
|
|
if (gpqForeground->iCursorLevel < 0 && TestRawInputMode(ptiMouse, CaptureMouse)) {
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
if (gpqCursor != NULL && gpqCursor->iCursorLevel >= 0 &&
|
|
gpqCursor->spcurCurrent != NULL &&
|
|
SYSMET(MOUSEPRESENT)) {
|
|
|
|
PCURSINFO pci = GETPCI(gpqCursor->spcurCurrent);
|
|
ULONG fl = FCursorShadowed(pci) ? SPS_ALPHA : 0;
|
|
|
|
GreSetPointer(gpDispInfo->hDev, pci, fl, GETMOUSETRAILS(), MOUSE_TRAILS_FREQ);
|
|
}
|
|
} else {
|
|
GreSetPointer(gpDispInfo->hDev, NULL, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* HideCursorNoCapture
|
|
*
|
|
* Set the cursor to NULL if the mouse is not captured
|
|
*
|
|
* 20-May-1998 MCostea created
|
|
\***************************************************************************/
|
|
VOID zzzHideCursorNoCapture()
|
|
{
|
|
PTHREADINFO ptiCurrent = PtiCurrentShared();
|
|
|
|
if (!ptiCurrent->pq->spwndCapture &&
|
|
((GetAppCompatFlags2(VER40) & GACF2_EDITNOMOUSEHIDE) == 0) &&
|
|
TestEffectUP(MOUSEVANISH)) {
|
|
|
|
zzzSetCursor(NULL);
|
|
}
|
|
}
|
|
|
|
#ifdef AUTORUN_CURSOR
|
|
/***************************************************************************\
|
|
* ShowAutorunCursor
|
|
*
|
|
* Kicks off a system timer that will fire when it's time to hide the autorun
|
|
* cursor and calls zzzUpdateCursorImage to change the current cursor to the
|
|
* autorun guy.
|
|
*
|
|
* 02-Oct-2000 JasonSch created
|
|
\***************************************************************************/
|
|
VOID ShowAutorunCursor(
|
|
ULONG ulTimeout)
|
|
{
|
|
EnterCrit();
|
|
|
|
/*
|
|
* Create/reset the timer. If we're already set it and it hasn't yet gone
|
|
* off, this will reset the time to whatever we specify (which is the
|
|
* behavior we want).
|
|
*/
|
|
gtmridAutorunCursor = InternalSetTimer(NULL,
|
|
gtmridAutorunCursor,
|
|
ulTimeout,
|
|
HideAutorunCursor,
|
|
TMRF_RIT | TMRF_ONESHOT);
|
|
LeaveCrit();
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* HideAutorunCursor
|
|
*
|
|
* Destroys the autorun cursor timer and resets the cursor itself.
|
|
*
|
|
* 02-Oct-2000 JasonSch created
|
|
\***************************************************************************/
|
|
VOID HideAutorunCursor(
|
|
PWND pwnd,
|
|
UINT message,
|
|
UINT_PTR nID,
|
|
LPARAM lParam)
|
|
{
|
|
CheckCritIn();
|
|
|
|
/*
|
|
* Calling zzzUpdateCursorImage with a NULL gtmridAutorunCursor will cause
|
|
* the cursor to change to whatever is should be (e.g., app starting, if
|
|
* appropriate).
|
|
*/
|
|
KILLRITTIMER(NULL, gtmridAutorunCursor);
|
|
gtmridAutorunCursor = 0;
|
|
zzzUpdateCursorImage();
|
|
|
|
UNREFERENCED_PARAMETER(pwnd);
|
|
UNREFERENCED_PARAMETER(message);
|
|
UNREFERENCED_PARAMETER(nID);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
}
|
|
#endif // AUTORUN_CURSOR
|