Implement GreMovePointer and GreSetPointerShape, calling the eng functions and use them instead of the former mess in IntSetCursor. Fix IntShowMousePointer, EngSetPointerShape to properly handle the color bitmap. We now have support for colored mouse cursors, like used by our paint.

svn path=/trunk/; revision=42447
This commit is contained in:
Timo Kreuzer 2009-08-07 01:44:38 +00:00
parent 314fa19276
commit 29c24f700e
3 changed files with 254 additions and 196 deletions

View file

@ -240,16 +240,29 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest)
if (pgp->psurfColor)
{
IntEngBitBltEx(psoDest,
&pgp->psurfColor->SurfObj,
&pgp->psurfMask->SurfObj,
NULL,
NULL,
NULL,
&rclSurf,
(POINTL*)&rclPointer,
NULL,
NULL,
NULL,
ROP3_TO_ROP4(SRCAND),
FALSE);
IntEngBitBltEx(psoDest,
&pgp->psurfColor->SurfObj,
NULL,
NULL,
NULL,
&rclSurf,
(POINTL*)&rclPointer,
NULL,
NULL,
R4_MASK,
NULL,
ROP3_TO_ROP4(SRCINVERT),
FALSE);
}
else
@ -302,7 +315,6 @@ EngSetPointerShape(
{
PDEVOBJ *ppdev;
GDIPOINTER *pgp;
SIZEL Size;
LONG lDelta;
HBITMAP hbmp;
RECTL rcl;
@ -312,6 +324,31 @@ EngSetPointerShape(
ppdev = GDIDEV(pso);
pgp = &ppdev->Pointer;
if (psoColor)
{
pgp->Size.cx = psoColor->sizlBitmap.cx;
pgp->Size.cy = psoColor->sizlBitmap.cy;
if (psoMask)
{
// CHECKME: Is this really required? if we have a color surface,
// we only need the and part of the mask.
/* Check if the sizes match as they should */
if (psoMask->sizlBitmap.cx != psoColor->sizlBitmap.cx ||
psoMask->sizlBitmap.cy != psoColor->sizlBitmap.cy * 2)
{
DPRINT("Sizes of mask (%ld,%ld) and color (%ld,%ld) don't match\n",
psoMask->sizlBitmap.cx, psoMask->sizlBitmap.cy,
psoColor->sizlBitmap.cx, psoColor->sizlBitmap.cy);
// return SPS_ERROR;
}
}
}
else
{
pgp->Size.cx = psoMask->sizlBitmap.cx;
pgp->Size.cy = psoMask->sizlBitmap.cy / 2;
}
IntHideMousePointer(ppdev, pso);
if (pgp->psurfColor)
@ -336,7 +373,7 @@ EngSetPointerShape(
}
/* See if we are being asked to hide the pointer. */
if (psoMask == NULL)
if (psoMask == NULL && psoColor == NULL)
{
return SPS_ACCEPT_NOEXCLUDE;
}
@ -344,23 +381,6 @@ EngSetPointerShape(
pgp->HotSpot.x = xHot;
pgp->HotSpot.y = yHot;
if (x != -1)
{
ppdev->ptlPointer.x = x;
ppdev->ptlPointer.y = y;
}
pgp->Size.cx = abs(psoMask->lDelta) << 3;
pgp->Size.cy = (psoMask->cjBits / abs(psoMask->lDelta)) >> 1;
Size.cx = pgp->Size.cx;
Size.cy = pgp->Size.cy << 1;
rcl.left = 0;
rcl.top = 0;
rcl.right = Size.cx;
rcl.bottom = Size.cy;
/* Calculate lDelta for our surfaces. */
switch (pso->iBitmapFormat)
{
@ -387,6 +407,11 @@ EngSetPointerShape(
break;
}
rcl.left = 0;
rcl.top = 0;
rcl.right = pgp->Size.cx;
rcl.bottom = pgp->Size.cy;
/* Create surface for saving the pixels under the cursor. */
hbmp = EngCreateBitmap(pgp->Size,
lDelta,
@ -401,30 +426,35 @@ EngSetPointerShape(
EXLATEOBJ exlo;
PPALETTE ppal;
ppal = PALETTE_LockPalette(ppdev->DevInfo.hpalDefault);
EXLATEOBJ_vInitialize(&exlo,
&gpalMono,
ppal,
0,
RGB(0xff,0xff,0xff),
RGB(0,0,0));
hbmp = EngCreateBitmap(Size,
hbmp = EngCreateBitmap(psoMask->sizlBitmap,
lDelta,
pso->iBitmapFormat,
0,
NULL);
pgp->psurfMask = SURFACE_ShareLockSurface(hbmp);
IntEngCopyBits(&pgp->psurfMask->SurfObj,
psoMask,
NULL,
&exlo.xlo,
&rcl,
(POINTL*)&rcl);
EXLATEOBJ_vCleanup(&exlo);
if (ppal)
PALETTE_UnlockPalette(ppal);
if(pgp->psurfMask)
{
ppal = PALETTE_LockPalette(ppdev->DevInfo.hpalDefault);
EXLATEOBJ_vInitialize(&exlo,
&gpalMono,
ppal,
0,
RGB(0xff,0xff,0xff),
RGB(0,0,0));
rcl.bottom = pgp->Size.cy * 2;
IntEngCopyBits(&pgp->psurfMask->SurfObj,
psoMask,
NULL,
&exlo.xlo,
&rcl,
(POINTL*)&rcl);
EXLATEOBJ_vCleanup(&exlo);
if (ppal)
PALETTE_UnlockPalette(ppal);
}
}
else
{
@ -434,18 +464,22 @@ EngSetPointerShape(
/* Create a color surface */
if (psoColor)
{
hbmp = EngCreateBitmap(pgp->Size,
hbmp = EngCreateBitmap(psoColor->sizlBitmap,
lDelta,
pso->iBitmapFormat,
BMF_TOPDOWN | BMF_NOZEROINIT,
NULL);
pgp->psurfColor = SURFACE_ShareLockSurface(hbmp);
IntEngCopyBits(&pgp->psurfColor->SurfObj,
psoColor,
NULL,
pxlo,
&rcl,
(POINTL*)&rcl);
if (pgp->psurfColor)
{
rcl.bottom = pgp->Size.cy;
IntEngCopyBits(&pgp->psurfColor->SurfObj,
psoColor,
NULL,
pxlo,
&rcl,
(POINTL*)&rcl);
}
}
else
{
@ -454,6 +488,9 @@ EngSetPointerShape(
if (x != -1)
{
ppdev->ptlPointer.x = x;
ppdev->ptlPointer.y = y;
IntShowMousePointer(ppdev, pso);
if (prcl != NULL)
@ -590,4 +627,115 @@ IntEngSetPointerShape(
return ulResult;
}
ULONG
NTAPI
GreSetPointerShape(
HDC hdc,
HBITMAP hbmMask,
HBITMAP hbmColor,
LONG xHot,
LONG yHot,
LONG x,
LONG y)
{
PDC pdc;
PSURFACE psurf, psurfMask, psurfColor;
EXLATEOBJ exlo;
FLONG fl = 0;
ULONG ulResult = 0;
pdc = DC_LockDc(hdc);
if (!pdc)
{
DPRINT1("Failed to lock the DC.\n");
return 0;
}
psurf = pdc->dclevel.pSurface;
if (!psurf)
{
DPRINT1("DC has no surface.\n");
DC_UnlockDc(pdc);
return 0;
}
/* Lock the mask bitmap */
if (hbmMask)
psurfMask = SURFACE_ShareLockSurface(hbmMask);
else
psurfMask = NULL;
/* Check for color bitmap */
if (hbmColor)
{
/* We have one, lock it */
psurfColor = SURFACE_ShareLockSurface(hbmColor);
if (psurfColor)
{
/* Create an XLATEOBJ, no mono support */
EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurf->ppal, 0, 0, 0);
}
}
else
psurfColor = NULL;
/* Call the driver or eng function */
ulResult = IntEngSetPointerShape(&psurf->SurfObj,
psurfMask ? &psurfMask->SurfObj : NULL,
psurfColor ? &psurfColor->SurfObj : NULL,
psurfColor ? &exlo.xlo : NULL,
xHot,
yHot,
x,
y,
&pdc->ppdev->Pointer.Exclude,
fl);
/* Cleanup */
if (hbmColor)
EXLATEOBJ_vCleanup(&exlo);
if (psurfColor)
SURFACE_ShareUnlockSurface(psurfColor);
if (psurfMask)
SURFACE_ShareUnlockSurface(psurfMask);
/* Unlock the DC */
DC_UnlockDc(pdc);
/* Return result */
return ulResult;
}
VOID
NTAPI
GreMovePointer(
HDC hdc,
LONG x,
LONG y)
{
PDC pdc;
PRECTL prcl;
/* Lock the DC */
pdc = DC_LockDc(hdc);
if (!pdc)
{
DPRINT1("Failed to lock the DC.\n");
return;
}
/* Store the cursor exclude position in the PDEV */
prcl = &pdc->ppdev->Pointer.Exclude;
/* Call Eng/Drv function */
IntEngMovePointer(&pdc->dclevel.pSurface->SurfObj, x, y, prcl);
/* Unlock the DC */
DC_UnlockDc(pdc);
}
/* EOF */

View file

@ -85,6 +85,24 @@ int APIENTRY UserShowCursor(BOOL bShow);
#define IntReleaseCurIconObject(CurIconObj) \
UserDereferenceObject(CurIconObj)
ULONG
NTAPI
GreSetPointerShape(
HDC hdc,
HBITMAP hbmMask,
HBITMAP hbmColor,
LONG xHot,
LONG yHot,
LONG x,
LONG y);
VOID
NTAPI
GreMovePointer(
HDC hdc,
LONG x,
LONG y);
#endif /* _WIN32K_CURSORICON_H */
/* EOF */

View file

@ -78,153 +78,70 @@ PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
#define COLORCURSORS_ALLOWED FALSE
HCURSOR FASTCALL
IntSetCursor(PWINSTATION_OBJECT WinSta, PCURICON_OBJECT NewCursor,
BOOL ForceChange)
HCURSOR
FASTCALL
IntSetCursor(
PWINSTATION_OBJECT WinSta,
PCURICON_OBJECT NewCursor,
BOOL ForceChange)
{
SURFACE *psurf;
SURFOBJ *pso;
PDEVINFO DevInfo;
PSURFACE MaskBmpObj = NULL;
PSYSTEM_CURSORINFO CurInfo;
PCURICON_OBJECT OldCursor;
HCURSOR Ret = (HCURSOR)0;
HBITMAP hMask = 0;
SURFOBJ *soMask = NULL, *soColor = NULL;
XLATEOBJ *XlateObj = NULL;
HDC Screen;
PDC dc;
ULONG Status;
HCURSOR hOldCursor = (HCURSOR)0;
HDC hdcScreen;
BOOL bResult;
CurInfo = IntGetSysCursorInfo(WinSta);
OldCursor = CurInfo->CurrentCursorObject;
if (OldCursor)
{
Ret = (HCURSOR)OldCursor->Self;
hOldCursor = (HCURSOR)OldCursor->Self;
}
if (!ForceChange && OldCursor == NewCursor)
/* Is the new cursor the same as the old cursor? */
if (OldCursor == NewCursor)
{
return Ret;
/* Nothing to to do in this case */
return hOldCursor;
}
if (!(Screen = IntGetScreenDC()))
/* Get the screen DC */
if(!(hdcScreen = IntGetScreenDC()))
{
return (HCURSOR)0;
}
/* FIXME use the desktop's HDC instead of using ScreenDeviceContext */
dc = DC_LockDc(Screen);
if (!dc)
/* Do we have a new cursor? */
if (NewCursor)
{
return Ret;
}
DevInfo = (PDEVINFO)&dc->ppdev->DevInfo;
UserReferenceObject(NewCursor);
psurf = dc->dclevel.pSurface;
if (!psurf)
{
DC_UnlockDc(dc);
return (HCURSOR)0;
}
pso = &psurf->SurfObj;
if (!NewCursor)
{
if (CurInfo->CurrentCursorObject || ForceChange)
{
if (CurInfo->CurrentCursorObject)
{
UserDereferenceObject(CurInfo->CurrentCursorObject);
if (CurInfo->ShowingCursor)
{
DPRINT("Removing pointer!\n");
/* Remove the cursor if it was displayed */
IntEngMovePointer(pso, -1, -1, &GDIDEV(pso)->Pointer.Exclude);
}
}
CurInfo->CurrentCursorObject = NewCursor; /* i.e. CurrentCursorObject = NULL */
CurInfo->ShowingCursor = 0;
}
DC_UnlockDc(dc);
return Ret;
}
/* TODO: Fixme. Logic is screwed above */
MaskBmpObj = SURFACE_LockSurface(NewCursor->IconInfo.hbmMask);
if (MaskBmpObj)
{
const int maskBpp = BitsPerFormat(MaskBmpObj->SurfObj.iBitmapFormat);
SURFACE_UnlockSurface(MaskBmpObj);
if (maskBpp != 1)
{
DPRINT1("SetCursor: The Mask bitmap must have 1BPP!\n");
DC_UnlockDc(dc);
return Ret;
}
if ((DevInfo->flGraphicsCaps2 & GCAPS2_ALPHACURSOR) &&
pso->iBitmapFormat >= BMF_16BPP &&
pso->iBitmapFormat <= BMF_32BPP &&
NewCursor->Shadow && COLORCURSORS_ALLOWED)
{
/* FIXME - Create a color pointer, only 32bit bitmap, set alpha bits!
Do not pass a mask bitmap to DrvSetPointerShape()!
Create a XLATEOBJ that describes the colors of the bitmap. */
DPRINT1("SetCursor: (Colored) alpha cursors are not supported!\n");
}
else
{
if (NewCursor->IconInfo.hbmColor
&& COLORCURSORS_ALLOWED)
{
/* FIXME - Create a color pointer, create only one 32bit bitmap!
Do not pass a mask bitmap to DrvSetPointerShape()!
Create a XLATEOBJ that describes the colors of the bitmap.
(16bit bitmaps are propably allowed) */
DPRINT1("SetCursor: Cursors with colors are not supported!\n");
}
else
{
MaskBmpObj = SURFACE_LockSurface(NewCursor->IconInfo.hbmMask);
if (MaskBmpObj)
{
RECTL DestRect = {0, 0, MaskBmpObj->SurfObj.sizlBitmap.cx, MaskBmpObj->SurfObj.sizlBitmap.cy};
POINTL SourcePoint = {0, 0};
/*
* NOTE: For now we create the cursor in top-down bitmap,
* because VMware driver rejects it otherwise. This should
* be fixed later.
*/
hMask = EngCreateBitmap(
MaskBmpObj->SurfObj.sizlBitmap, abs(MaskBmpObj->SurfObj.lDelta),
MaskBmpObj->SurfObj.iBitmapFormat, BMF_TOPDOWN,
NULL);
if (!hMask)
{
SURFACE_UnlockSurface(MaskBmpObj);
DC_UnlockDc(dc);
return (HCURSOR)0;
}
soMask = EngLockSurface((HSURF)hMask);
IntEngCopyBits(soMask, &MaskBmpObj->SurfObj, NULL, NULL,
&DestRect, &SourcePoint);
SURFACE_UnlockSurface(MaskBmpObj);
}
}
}
CurInfo->ShowingCursor = CURSOR_SHOWING;
CurInfo->CurrentCursorObject = NewCursor;
UserReferenceObject(NewCursor);
/* Call GDI to set the new screen cursor */
bResult = GreSetPointerShape(hdcScreen,
NewCursor->IconInfo.hbmMask,
NewCursor->IconInfo.hbmColor,
NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
}
else
{
CurInfo->ShowingCursor = 0;
/* Check if were diplaying a cursor */
if (OldCursor && CurInfo->ShowingCursor)
{
/* Remove the cursor */
GreMovePointer(hdcScreen, -1, -1);
DPRINT("Removing pointer!\n");
}
CurInfo->CurrentCursorObject = NULL;
CurInfo->ShowingCursor = 0;
}
/* OldCursor is not in use anymore */
@ -233,36 +150,11 @@ IntSetCursor(PWINSTATION_OBJECT WinSta, PCURICON_OBJECT NewCursor,
UserDereferenceObject(OldCursor);
}
Status = IntEngSetPointerShape(pso,
soMask,
soColor,
XlateObj,
NewCursor->IconInfo.xHotspot,
NewCursor->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y,
&(GDIDEV(pso)->Pointer.Exclude),
SPS_CHANGE);
if (Status != SPS_ACCEPT_NOEXCLUDE)
{
DPRINT1("IntEngSetPointerShape returned %lx\n", Status);
}
if (hMask)
{
EngUnlockSurface(soMask);
EngDeleteSurface((HSURF)hMask);
}
if (XlateObj)
{
EngDeleteXlate(XlateObj);
}
DC_UnlockDc(dc);
return Ret;
/* Return handle of the old cursor */
return hOldCursor;
}
BOOL FASTCALL
IntSetupCurIconHandles(PWINSTATION_OBJECT WinSta)
{