From a84129a69ec8030cbfa9fcba57171899cc8193eb Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Thu, 27 Jan 2005 00:49:24 +0000 Subject: [PATCH] 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 --- reactos/include/win32k/dc.h | 8 ++- reactos/subsys/win32k/eng/mouse.c | 39 ++++++------ reactos/subsys/win32k/include/cursoricon.h | 3 +- reactos/subsys/win32k/ntuser/cursoricon.c | 70 ++++++++++++++++++---- reactos/subsys/win32k/ntuser/input.c | 28 ++++----- reactos/subsys/win32k/ntuser/message.c | 6 +- reactos/subsys/win32k/ntuser/misc.c | 5 +- reactos/subsys/win32k/ntuser/winsta.c | 2 - 8 files changed, 100 insertions(+), 61 deletions(-) diff --git a/reactos/include/win32k/dc.h b/reactos/include/win32k/dc.h index 8de7bed3f93..d85424d2c2e 100644 --- a/reactos/include/win32k/dc.h +++ b/reactos/include/win32k/dc.h @@ -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 */ diff --git a/reactos/subsys/win32k/eng/mouse.c b/reactos/subsys/win32k/eng/mouse.c index 0bf3df28977..6ed83be1fbd 100644 --- a/reactos/subsys/win32k/eng/mouse.c +++ b/reactos/subsys/win32k/eng/mouse.c @@ -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 */ diff --git a/reactos/subsys/win32k/include/cursoricon.h b/reactos/subsys/win32k/include/cursoricon.h index 8507630cc96..29dca570731 100644 --- a/reactos/subsys/win32k/include/cursoricon.h +++ b/reactos/subsys/win32k/include/cursoricon.h @@ -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) diff --git a/reactos/subsys/win32k/ntuser/cursoricon.c b/reactos/subsys/win32k/ntuser/cursoricon.c index d7157dc77d7..65fe5467d3b 100644 --- a/reactos/subsys/win32k/ntuser/cursoricon.c +++ b/reactos/subsys/win32k/ntuser/cursoricon.c @@ -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; diff --git a/reactos/subsys/win32k/ntuser/input.c b/reactos/subsys/win32k/ntuser/input.c index 1544141599d..735f789e994 100644 --- a/reactos/subsys/win32k/ntuser/input.c +++ b/reactos/subsys/win32k/ntuser/input.c @@ -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); } diff --git a/reactos/subsys/win32k/ntuser/message.c b/reactos/subsys/win32k/ntuser/message.c index 32248449f6a..3ec02fa815a 100644 --- a/reactos/subsys/win32k/ntuser/message.c +++ b/reactos/subsys/win32k/ntuser/message.c @@ -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, diff --git a/reactos/subsys/win32k/ntuser/misc.c b/reactos/subsys/win32k/ntuser/misc.c index a0d666297d4..b8acc8802d1 100644 --- a/reactos/subsys/win32k/ntuser/misc.c +++ b/reactos/subsys/win32k/ntuser/misc.c @@ -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)) diff --git a/reactos/subsys/win32k/ntuser/winsta.c b/reactos/subsys/win32k/ntuser/winsta.c index 8d87948e2b6..76755d5ff30 100644 --- a/reactos/subsys/win32k/ntuser/winsta.c +++ b/reactos/subsys/win32k/ntuser/winsta.c @@ -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;