This patch removes the cursor location from the window station object and always uses it in the GDIDEVICE. Patch by tinus. Fixes bug #484 Modified: trunk/reactos/include/win32k/dc.h Modified: trunk/reactos/subsys/win32k/eng/mouse.c Modified: trunk/reactos/subsys/win32k/include/cursoricon.h Modified: trunk/reactos/subsys/win32k/ntuser/cursoricon.c Modified: trunk/reactos/subsys/win32k/ntuser/input.c Modified: trunk/reactos/subsys/win32k/ntuser/message.c Modified: trunk/reactos/subsys/win32k/ntuser/misc.c Modified: trunk/reactos/subsys/win32k/ntuser/winsta.c _____
Modified: trunk/reactos/include/win32k/dc.h --- trunk/reactos/include/win32k/dc.h 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/include/win32k/dc.h 2005-01-27 00:49:24 UTC (rev 13333) @@ -124,9 +124,6 @@
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 @@ 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 */ _____
Modified: trunk/reactos/subsys/win32k/eng/mouse.c --- trunk/reactos/subsys/win32k/eng/mouse.c 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/subsys/win32k/eng/mouse.c 2005-01-27 00:49:24 UTC (rev 13333) @@ -68,9 +68,9 @@
tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp; }
- pgp->SafetyRemoveCount++; + ppdev->SafetyRemoveCount++;
- if (pgp->SafetyRemoveLevel) + if (ppdev->SafetyRemoveLevel) { /* already hidden */ return FALSE; @@ -81,7 +81,7 @@ && 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 @@ GDIDEVICE *ppdev; GDIPOINTER *pgp;
+ ASSERT(WinSta); + ASSERT(SurfObj != NULL);
ppdev = GDIDEV(SurfObj); @@ -117,22 +119,16 @@ 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 @@ 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 @@
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 @@ 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 */ _____
Modified: trunk/reactos/subsys/win32k/include/cursoricon.h --- trunk/reactos/subsys/win32k/include/cursoricon.h 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/subsys/win32k/include/cursoricon.h 2005-01-27 00:49:24 UTC (rev 13333) @@ -37,7 +37,6 @@
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 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)
_____
Modified: trunk/reactos/subsys/win32k/ntuser/cursoricon.c --- trunk/reactos/subsys/win32k/ntuser/cursoricon.c 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/subsys/win32k/ntuser/cursoricon.c 2005-01-27 00:49:24 UTC (rev 13333) @@ -42,6 +42,40 @@
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 @@ { /* 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 @@ 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 @@ 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 @@ 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 @@
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 @@ PSYSTEM_CURSORINFO CurInfo; RECT Rect; PWINDOW_OBJECT DesktopWindow = NULL; + POINT MousePos;
WinStaObject = IntGetWinStaObj(); if (WinStaObject == NULL) @@ -830,6 +874,8 @@ }
CurInfo = IntGetSysCursorInfo(WinStaObject); + IntGetCursorLocation(WinStaObject, &MousePos); + if(WinStaObject->ActiveDesktop) DesktopWindow = IntGetWindowObject(WinStaObject->ActiveDesktop->DesktopWindow);
@@ -845,8 +891,8 @@ 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; _____
Modified: trunk/reactos/subsys/win32k/ntuser/input.c --- trunk/reactos/subsys/win32k/ntuser/input.c 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/subsys/win32k/ntuser/input.c 2005-01-27 00:49:24 UTC (rev 13333) @@ -540,7 +540,7 @@
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 @@ 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 @@ 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 @@ 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); } _____
Modified: trunk/reactos/subsys/win32k/ntuser/message.c --- trunk/reactos/subsys/win32k/ntuser/message.c 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/subsys/win32k/ntuser/message.c 2005-01-27 00:49:24 UTC (rev 13333) @@ -1123,7 +1123,6 @@
} else { - PSYSTEM_CURSORINFO CurInfo; Window = IntGetWindowObject(Wnd); if (NULL == Window) { @@ -1149,9 +1148,8 @@ 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, _____
Modified: trunk/reactos/subsys/win32k/ntuser/misc.c --- trunk/reactos/subsys/win32k/ntuser/misc.c 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/subsys/win32k/ntuser/misc.c 2005-01-27 00:49:24 UTC (rev 13333) @@ -263,7 +263,6 @@
case ONEPARAM_ROUTINE_GETCURSORPOSITION: { - PSYSTEM_CURSORINFO CurInfo; PWINSTATION_OBJECT WinStaObject; NTSTATUS Status; POINT Pos; @@ -277,10 +276,8 @@ 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)) _____
Modified: trunk/reactos/subsys/win32k/ntuser/winsta.c --- trunk/reactos/subsys/win32k/ntuser/winsta.c 2005-01-27 00:33:11 UTC (rev 13332) +++ trunk/reactos/subsys/win32k/ntuser/winsta.c 2005-01-27 00:49:24 UTC (rev 13333) @@ -389,8 +389,6 @@
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;