diff --git a/reactos/subsystems/win32/win32k/eng/mouse.c b/reactos/subsystems/win32/win32k/eng/mouse.c index 7ee6d3ea1f8..d3b67f81072 100644 --- a/reactos/subsystems/win32/win32k/eng/mouse.c +++ b/reactos/subsystems/win32/win32k/eng/mouse.c @@ -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 */ diff --git a/reactos/subsystems/win32/win32k/include/cursoricon.h b/reactos/subsystems/win32/win32k/include/cursoricon.h index a3464ba887f..5e31b1fc414 100644 --- a/reactos/subsystems/win32/win32k/include/cursoricon.h +++ b/reactos/subsystems/win32/win32k/include/cursoricon.h @@ -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 */ diff --git a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c index 4e1802c9d26..56cce86a84b 100644 --- a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c +++ b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c @@ -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) {