This patch removes the cursor location from the window station object and always uses it in the GDIDEVICE. Patch by tinus. Fixes bug #484

svn path=/trunk/; revision=13333
This commit is contained in:
Thomas Bluemel 2005-01-27 00:49:24 +00:00
parent f99bb4b97d
commit a84129a69e
8 changed files with 100 additions and 61 deletions

View file

@ -124,9 +124,6 @@ typedef struct _GDIPOINTER /* should stay private to ENG */
RECTL Exclude; /* required publicly for SPS_ACCEPT_EXCLUDE */
PGD_MOVEPOINTER MovePointer;
ULONG Status;
UINT SafetyRemoveLevel; /* at what level was the cursor removed?
0 for not removed */
UINT SafetyRemoveCount;
} GDIPOINTER, *PGDIPOINTER;
typedef struct
@ -141,6 +138,11 @@ typedef struct
PFILE_OBJECT VideoFileObject;
GDIPOINTER Pointer;
/* Stuff to keep track of software cursors; win32k gdi part */
UINT SafetyRemoveLevel; /* at what level was the cursor removed?
0 for not removed */
UINT SafetyRemoveCount;
} GDIDEVICE;
/* Internal functions */

View file

@ -68,9 +68,9 @@ MouseSafetyOnDrawStart(SURFOBJ *SurfObj, LONG HazardX1,
tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
}
pgp->SafetyRemoveCount++;
ppdev->SafetyRemoveCount++;
if (pgp->SafetyRemoveLevel)
if (ppdev->SafetyRemoveLevel)
{
/* already hidden */
return FALSE;
@ -81,7 +81,7 @@ MouseSafetyOnDrawStart(SURFOBJ *SurfObj, LONG HazardX1,
&& pgp->Exclude.bottom >= HazardY1
&& pgp->Exclude.top <= HazardY2)
{
pgp->SafetyRemoveLevel = pgp->SafetyRemoveCount;
ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
if (pgp->MovePointer)
pgp->MovePointer(SurfObj, -1, -1, NULL);
else
@ -100,6 +100,8 @@ MouseSafetyOnDrawEnd(SURFOBJ *SurfObj)
GDIDEVICE *ppdev;
GDIPOINTER *pgp;
ASSERT(WinSta);
ASSERT(SurfObj != NULL);
ppdev = GDIDEV(SurfObj);
@ -117,22 +119,16 @@ MouseSafetyOnDrawEnd(SURFOBJ *SurfObj)
return FALSE;
}
if (--pgp->SafetyRemoveCount >= pgp->SafetyRemoveLevel)
if (--ppdev->SafetyRemoveCount >= ppdev->SafetyRemoveLevel)
{
return FALSE;
}
/* FIXME - this is wrong!!!!!! we must NOT access pgp->Pos from here, it's
a private field for ENG/driver. This will paint the cursor to the
wrong screen coordinates when a driver overrides DrvMovePointer()!
We should store the coordinates before calling Drv/EngMovePointer()
and Drv/EngSetPointerShape() separately in the GDIDEVICE structure
or somewhere where ntuser can access it! */
if (pgp->MovePointer)
pgp->MovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude);
else
EngMovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude);
pgp->SafetyRemoveLevel = 0;
ppdev->SafetyRemoveLevel = 0;
return(TRUE);
}
@ -368,6 +364,8 @@ EngSetPointerShape(
pgp->HotSpot.x = xHot;
pgp->HotSpot.y = yHot;
/* Actually this should be set by 'the other side', but it would be
* done right after this. It helps IntShowMousePointer. */
if (x != -1)
{
pgp->Pos.x = x;
@ -472,14 +470,13 @@ EngSetPointerShape(
if (prcl != NULL)
{
prcl->left = pgp->Pos.x - pgp->HotSpot.x;
prcl->top = pgp->Pos.y - pgp->HotSpot.x;
prcl->left = x - pgp->HotSpot.x;
prcl->top = y - pgp->HotSpot.x;
prcl->right = prcl->left + pgp->Size.cx;
prcl->bottom = prcl->top + pgp->Size.cy;
}
}
/* FIXME - touch prcl when x == -1? */
} else if (prcl != NULL)
prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
return SPS_ACCEPT_EXCLUDE;
}
@ -509,19 +506,21 @@ EngMovePointer(
IntHideMousePointer(ppdev, pso);
if (x != -1)
{
/* Actually this should be set by 'the other side', but it would be
* done right after this. It helps IntShowMousePointer. */
pgp->Pos.x = x;
pgp->Pos.y = y;
IntShowMousePointer(ppdev, pso);
if (prcl != NULL)
{
prcl->left = pgp->Pos.x - pgp->HotSpot.x;
prcl->top = pgp->Pos.y - pgp->HotSpot.x;
prcl->left = x - pgp->HotSpot.x;
prcl->top = y - pgp->HotSpot.x;
prcl->right = prcl->left + pgp->Size.cx;
prcl->bottom = prcl->top + pgp->Size.cy;
}
}
} else if (prcl != NULL)
prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
/* FIXME - touch prcl when x == -1? */
}
/* EOF */

View file

@ -37,7 +37,6 @@ typedef struct _SYSTEM_CURSORINFO
BOOL Enabled;
BOOL SwapButtons;
UINT ButtonsDown;
LONG x, y;
FAST_MUTEX CursorMutex;
CURSORCLIP_INFO CursorClipInfo;
PCURICON_OBJECT CurrentCursorObject;
@ -57,6 +56,8 @@ PCURICON_OBJECT FASTCALL IntGetCurIconObject(PWINSTATION_OBJECT WinStaObject, HA
PCURICON_OBJECT FASTCALL IntCreateCurIconHandle(PWINSTATION_OBJECT WinStaObject);
VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PW32PROCESS Win32Process);
BOOL FASTCALL IntGetCursorLocation(PWINSTATION_OBJECT WinStaObject, POINT *loc);
#define IntGetSysCursorInfo(WinStaObj) \
(PSYSTEM_CURSORINFO)((WinStaObj)->SystemCursor)

View file

@ -42,6 +42,40 @@ static PAGED_LOOKASIDE_LIST ProcessLookasideList;
static LIST_ENTRY CurIconList;
static FAST_MUTEX CurIconListLock;
/* Look up the location of the cursor in the GDIDEVICE structure
* when all we know is the window station object
* Actually doesn't use the window station, but should... */
BOOL FASTCALL
IntGetCursorLocation(PWINSTATION_OBJECT WinStaObject, POINT *loc)
{
HDC hDC;
PDC dc;
HBITMAP hBitmap;
BITMAPOBJ *BitmapObj;
SURFOBJ *SurfObj;
#if 1
/* FIXME - get the screen dc from the window station or desktop */
if (!(hDC = IntGetScreenDC()))
return FALSE;
#endif
if (!(dc = DC_LockDc(hDC)))
return FALSE;
hBitmap = dc->w.hBitmap;
DC_UnlockDc(hDC);
if (!(BitmapObj = BITMAPOBJ_LockBitmap(hBitmap)))
return FALSE;
SurfObj = &BitmapObj->SurfObj;
loc->x = GDIDEV(SurfObj)->Pointer.Pos.x;
loc->y = GDIDEV(SurfObj)->Pointer.Pos.y;
BITMAPOBJ_UnlockBitmap(hBitmap);
return TRUE;
}
PCURICON_OBJECT FASTCALL
IntGetCurIconObject(PWINSTATION_OBJECT WinStaObject, HANDLE Handle)
{
@ -116,10 +150,9 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor,
{
/* Remove the cursor if it was displayed */
if (GDIDEV(SurfObj)->Pointer.MovePointer)
GDIDEV(SurfObj)->Pointer.MovePointer(SurfObj, -1, -1, NULL);
GDIDEV(SurfObj)->Pointer.MovePointer(SurfObj, -1, -1, &GDIDEV(SurfObj)->Pointer.Exclude);
else
EngMovePointer(SurfObj, -1, -1, NULL);
GDIDEV(SurfObj)->Pointer.Exclude.right = -1;
EngMovePointer(SurfObj, -1, -1, &GDIDEV(SurfObj)->Pointer.Exclude);
}
GDIDEV(SurfObj)->Pointer.Status = SPS_ACCEPT_NOEXCLUDE;
@ -218,8 +251,8 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor,
SurfObj, soMask, soColor, XlateObj,
NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot,
CurInfo->x,
CurInfo->y,
GDIDEV(SurfObj)->Pointer.Pos.x,
GDIDEV(SurfObj)->Pointer.Pos.y,
&(GDIDEV(SurfObj)->Pointer.Exclude),
SPS_CHANGE);
DPRINT("SetCursor: DrvSetPointerShape() returned %x\n",
@ -236,8 +269,8 @@ IntSetCursor(PWINSTATION_OBJECT WinStaObject, PCURICON_OBJECT NewCursor,
SurfObj, soMask, soColor, XlateObj,
NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot,
CurInfo->x,
CurInfo->y,
GDIDEV(SurfObj)->Pointer.Pos.x,
GDIDEV(SurfObj)->Pointer.Pos.y,
&(GDIDEV(SurfObj)->Pointer.Exclude),
SPS_CHANGE);
GDIDEV(SurfObj)->Pointer.MovePointer = EngMovePointer;
@ -760,6 +793,16 @@ NtUserGetCursorInfo(
PWINSTATION_OBJECT WinStaObject;
NTSTATUS Status;
PCURICON_OBJECT CursorObject;
#if 1
HDC hDC;
/* FIXME - get the screen dc from the window station or desktop */
if (!(hDC = IntGetScreenDC()))
{
return FALSE;
}
#endif
Status = MmCopyFromCaller(&SafeCi.cbSize, pci, sizeof(DWORD));
if(!NT_SUCCESS(Status))
@ -785,9 +828,9 @@ NtUserGetCursorInfo(
SafeCi.flags = ((CurInfo->ShowingCursor && CursorObject) ? CURSOR_SHOWING : 0);
SafeCi.hCursor = (CursorObject ? (HCURSOR)CursorObject->Self : (HCURSOR)0);
SafeCi.ptScreenPos.x = CurInfo->x;
SafeCi.ptScreenPos.y = CurInfo->y;
IntGetCursorLocation(WinStaObject, &SafeCi.ptScreenPos);
Status = MmCopyToCaller(pci, &SafeCi, sizeof(CURSORINFO));
if(!NT_SUCCESS(Status))
{
@ -815,6 +858,7 @@ NtUserClipCursor(
PSYSTEM_CURSORINFO CurInfo;
RECT Rect;
PWINDOW_OBJECT DesktopWindow = NULL;
POINT MousePos;
WinStaObject = IntGetWinStaObj();
if (WinStaObject == NULL)
@ -830,6 +874,8 @@ NtUserClipCursor(
}
CurInfo = IntGetSysCursorInfo(WinStaObject);
IntGetCursorLocation(WinStaObject, &MousePos);
if(WinStaObject->ActiveDesktop)
DesktopWindow = IntGetWindowObject(WinStaObject->ActiveDesktop->DesktopWindow);
@ -845,8 +891,8 @@ NtUserClipCursor(
CurInfo->CursorClipInfo.Bottom = min(Rect.bottom - 1, DesktopWindow->WindowRect.bottom - 1);
IntReleaseWindowObject(DesktopWindow);
mi.dx = CurInfo->x;
mi.dy = CurInfo->y;
mi.dx = MousePos.x;
mi.dy = MousePos.y;
mi.mouseData = 0;
mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
mi.time = 0;

View file

@ -540,7 +540,7 @@ IntMouseInput(MOUSEINPUT *mi)
const UINT SwapBtnMsg[2][2] = {{WM_LBUTTONDOWN, WM_RBUTTONDOWN},
{WM_LBUTTONUP, WM_RBUTTONUP}};
const WPARAM SwapBtn[2] = {MK_LBUTTON, MK_RBUTTON};
POINT MousePos;
POINT MousePos, OrgPos;
PSYSTEM_CURSORINFO CurInfo;
PWINSTATION_OBJECT WinSta;
BOOL DoMove, SwapButtons;
@ -586,8 +586,10 @@ IntMouseInput(MOUSEINPUT *mi)
DoMove = FALSE;
ExAcquireFastMutex(&CurInfo->CursorMutex);
MousePos.x = CurInfo->x;
MousePos.y = CurInfo->y;
IntGetCursorLocation(WinSta, &MousePos);
OrgPos.x = MousePos.x;
OrgPos.y = MousePos.y;
if(mi->dwFlags & MOUSEEVENTF_MOVE)
{
if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
@ -631,12 +633,7 @@ IntMouseInput(MOUSEINPUT *mi)
MousePos.y = (LONG)CurInfo->CursorClipInfo.Top;
}
DoMove = (MousePos.x != CurInfo->x || MousePos.y != CurInfo->y);
if(DoMove)
{
CurInfo->x = MousePos.x;
CurInfo->y = MousePos.y;
}
DoMove = (MousePos.x != OrgPos.x || MousePos.y != OrgPos.y);
}
ExReleaseFastMutex(&CurInfo->CursorMutex);
@ -657,12 +654,13 @@ IntMouseInput(MOUSEINPUT *mi)
if (GDIDEV(SurfObj)->Pointer.MovePointer)
{
GDIDEV(SurfObj)->Pointer.MovePointer(SurfObj, MousePos.x, MousePos.y, &(GDIDEV(SurfObj)->Pointer.Exclude));
}
/* FIXME - That's a bad thing! We should't access private gdi pointer fields
from here. However it is required so MouseSafetyOnDrawEnd() can
properly paint the mouse cursor to the screen again. See the
comment in MouseSafetyOnDrawEnd() to fix this problem! */
GDIDEV(SurfObj)->Pointer.Pos = MousePos;
} else {
EngMovePointer(SurfObj, MousePos.x, MousePos.y, &(GDIDEV(SurfObj)->Pointer.Exclude));
}
/* Only now, update the info in the GDIDEVICE, so EngMovePointer can
* use the old values to move the pointer image */
GDIDEV(SurfObj)->Pointer.Pos.x = MousePos.x;
GDIDEV(SurfObj)->Pointer.Pos.y = MousePos.y;
BITMAPOBJ_UnlockBitmap(hBitmap);
}

View file

@ -1123,7 +1123,6 @@ NtUserPostMessage(HWND Wnd,
}
else
{
PSYSTEM_CURSORINFO CurInfo;
Window = IntGetWindowObject(Wnd);
if (NULL == Window)
{
@ -1149,9 +1148,8 @@ NtUserPostMessage(HWND Wnd,
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
CurInfo = IntGetSysCursorInfo(PsGetWin32Thread()->Desktop->WindowStation);
KernelModeMsg.pt.x = CurInfo->x;
KernelModeMsg.pt.y = CurInfo->y;
IntGetCursorLocation(PsGetWin32Thread()->Desktop->WindowStation,
&KernelModeMsg.pt);
KeQueryTickCount(&LargeTickCount);
KernelModeMsg.time = LargeTickCount.u.LowPart;
MsqPostMessage(Window->MessageQueue, &KernelModeMsg,

View file

@ -263,7 +263,6 @@ NtUserCallOneParam(
case ONEPARAM_ROUTINE_GETCURSORPOSITION:
{
PSYSTEM_CURSORINFO CurInfo;
PWINSTATION_OBJECT WinStaObject;
NTSTATUS Status;
POINT Pos;
@ -277,10 +276,8 @@ NtUserCallOneParam(
if (!NT_SUCCESS(Status))
return (DWORD)FALSE;
CurInfo = IntGetSysCursorInfo(WinStaObject);
/* FIXME - check if process has WINSTA_READATTRIBUTES */
Pos.x = CurInfo->x;
Pos.y = CurInfo->y;
IntGetCursorLocation(WinStaObject, &Pos);
Status = MmCopyToCaller((PPOINT)Param, &Pos, sizeof(POINT));
if(!NT_SUCCESS(Status))

View file

@ -389,8 +389,6 @@ NtUserCreateWindowStation(
ExInitializeFastMutex(&CurInfo->CursorMutex);
CurInfo->Enabled = FALSE;
CurInfo->ButtonsDown = 0;
CurInfo->x = (LONG)0;
CurInfo->y = (LONG)0;
CurInfo->CursorClipInfo.IsClipped = FALSE;
CurInfo->LastBtnDown = 0;
CurInfo->CurrentCursorObject = NULL;