[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / eng / mouse.c
index 9a89616..b2db0e6 100644 (file)
 /*
- *  ReactOS W32 Subsystem
- *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- *
- * PROJECT:          ReactOS kernel
- * PURPOSE:          Mouse
- * FILE:             subsys/win32k/eng/mouse.c
+ * PROJECT:          ReactOS win32 subsystem
+ * PURPOSE:          Mouse pointer functions
+ * FILE:             subsystems/win32k/eng/mouse.c
  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *                   Timo Kreuzer (timo.kreuzer@reactos.org)
  * REVISION HISTORY:
  *       06-06-2001  CSH  Created
  */
 /* INCLUDES ******************************************************************/
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
 
-INT INTERNAL_CALL
-MouseSafetyOnDrawStart(SURFOBJ *SurfObj, LONG HazardX1,
-                      LONG HazardY1, LONG HazardX2, LONG HazardY2)
+BOOL
+APIENTRY
+EngSetPointerTag(
+       IN HDEV hdev,
+       IN SURFOBJ *psoMask,
+       IN SURFOBJ *psoColor,
+       IN XLATEOBJ *pxlo,
+       IN FLONG fl)
+{
+    // This function is obsolete for Windows 2000 and later.
+    // This function is still supported, but always returns FALSE.
+    // www.osr.com/ddk/graphics/gdifncs_4yav.htm
+    return FALSE;
+}
+
 /*
  * FUNCTION: Notify the mouse driver that drawing is about to begin in
  * a rectangle on a particular surface.
  */
+INT INTERNAL_CALL
+MouseSafetyOnDrawStart(
+    PPDEVOBJ ppdev,
+    LONG HazardX1,
+    LONG HazardY1,
+    LONG HazardX2,
+    LONG HazardY2)
 {
-  LONG tmp;
-  GDIDEVICE *ppdev;
-  GDIPOINTER *pgp;
+    LONG tmp;
+    GDIPOINTER *pgp;
 
-  ASSERT(SurfObj != NULL);
+    ASSERT(ppdev != NULL);
+    ASSERT(ppdev->pSurface != NULL);
 
-  ppdev = GDIDEV(SurfObj);
+    pgp = &ppdev->Pointer;
 
-  if(ppdev == NULL)
+    if (pgp->Exclude.right == -1)
     {
-      return(FALSE);
+        return FALSE;
     }
 
-  pgp = &ppdev->Pointer;
+    ppdev->SafetyRemoveCount++;
 
-  if (SPS_ACCEPT_NOEXCLUDE == pgp->Status ||
-      pgp->Exclude.right == -1)
+    if (ppdev->SafetyRemoveLevel != 0)
     {
-      return(FALSE);
+        return FALSE;
     }
 
-  if (HazardX1 > HazardX2)
+    if (HazardX1 > HazardX2)
     {
-      tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
+        tmp = HazardX2;
+        HazardX2 = HazardX1;
+        HazardX1 = tmp;
     }
-  if (HazardY1 > HazardY2)
+    if (HazardY1 > HazardY2)
     {
-      tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
+        tmp = HazardY2;
+        HazardY2 = HazardY1;
+        HazardY1 = tmp;
     }
 
-  if (ppdev->SafetyRemoveLevel != 0)
+    if (pgp->Exclude.right >= HazardX1
+        && pgp->Exclude.left <= HazardX2
+        && pgp->Exclude.bottom >= HazardY1
+        && pgp->Exclude.top <= HazardY2)
     {
-      ppdev->SafetyRemoveCount++;
-      return FALSE;
+        ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
+        ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj, -1, -1, NULL);
     }
 
- ppdev->SafetyRemoveCount++;
-
-  if (pgp->Exclude.right >= HazardX1
-      && pgp->Exclude.left <= HazardX2
-      && pgp->Exclude.bottom >= HazardY1
-      && pgp->Exclude.top <= HazardY2)
-    {
-      ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
-      if (pgp->MovePointer)
-        pgp->MovePointer(SurfObj, -1, -1, NULL);
-      else
-        EngMovePointer(SurfObj, -1, -1, NULL);
-    }
-
-  return(TRUE);
+    return(TRUE);
 }
 
-INT INTERNAL_CALL
-MouseSafetyOnDrawEnd(SURFOBJ *SurfObj)
 /*
  * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
  */
+INT INTERNAL_CALL
+MouseSafetyOnDrawEnd(
+    PPDEVOBJ ppdev)
 {
-  GDIDEVICE *ppdev;
-  GDIPOINTER *pgp;
+    GDIPOINTER *pgp;
 
-  ASSERT(SurfObj != NULL);
+    ASSERT(ppdev != NULL);
+    ASSERT(ppdev->pSurface != NULL);
 
-  ppdev = GDIDEV(SurfObj);
+    pgp = &ppdev->Pointer;
 
-  if(ppdev == NULL)
+    if (pgp->Exclude.right == -1)
     {
-      return(FALSE);
+        return FALSE;
     }
 
-  pgp = &ppdev->Pointer;
-
-  if(SPS_ACCEPT_NOEXCLUDE == pgp->Status ||
-     pgp->Exclude.right == -1)
-  {
-    return FALSE;
-  }
+    if (--ppdev->SafetyRemoveCount >= ppdev->SafetyRemoveLevel)
+    {
+        return FALSE;
+    }
 
-  if (--ppdev->SafetyRemoveCount >= ppdev->SafetyRemoveLevel)
-   {
-      return FALSE;
-   }
-  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);
+    ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj,
+                          gpsi->ptCursor.x,
+                          gpsi->ptCursor.y,
+                          &pgp->Exclude);
 
-  ppdev->SafetyRemoveLevel = 0;
+    ppdev->SafetyRemoveLevel = 0;
 
-  return(TRUE);
+    return(TRUE);
 }
 
 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
 
-VOID INTERNAL_CALL
-IntHideMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
+VOID
+INTERNAL_CALL
+IntHideMousePointer(
+    PDEVOBJ *ppdev,
+    SURFOBJ *psoDest)
 {
-   GDIPOINTER *pgp;
-   POINTL pt;
-
-   ASSERT(ppdev);
-   ASSERT(DestSurface);
-
-   pgp = &ppdev->Pointer;
-
-   if (!pgp->Enabled)
-   {
-      return;
-   }
-
-      
-
-   pgp->Enabled = FALSE;
-   
-   /*
-    * The mouse is hide from ShowCours and it is frist ?? 
-    */
-   if (pgp->ShowPointer < 0)
-   {
-     return ;
-   }
-   
-
-  /*
-   *  Hide the cours
-   */
-   pt.x = pgp->Pos.x - pgp->HotSpot.x;
-   pt.y = pgp->Pos.y - pgp->HotSpot.y;
-   
-
-   if (pgp->SaveSurface != NULL)
-   {
-      RECTL DestRect;
-      POINTL SrcPoint;
-      SURFOBJ *SaveSurface;
-      SURFOBJ *MaskSurface;
-
-      DestRect.left = max(pt.x, 0);
-      DestRect.top = max(pt.y, 0);
-      DestRect.right = min(
-         pt.x + pgp->Size.cx,
-         DestSurface->sizlBitmap.cx);
-      DestRect.bottom = min(
-         pt.y + pgp->Size.cy,
-         DestSurface->sizlBitmap.cy);
-
-      SrcPoint.x = max(-pt.x, 0);
-      SrcPoint.y = max(-pt.y, 0);
-
-      if((SaveSurface = EngLockSurface(pgp->SaveSurface)))
-      {
-        if((MaskSurface = EngLockSurface(pgp->MaskSurface)))
-        {
-          IntEngBitBltEx(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
-                         &DestRect, &SrcPoint, &SrcPoint, NULL, NULL,
-                         ROP3_TO_ROP4(SRCCOPY), FALSE);
-          EngUnlockSurface(MaskSurface);
-        }
-        EngUnlockSurface(SaveSurface);
-      }
-   }
+    GDIPOINTER *pgp;
+    POINTL pt;
+    RECTL rclDest;
+    POINTL ptlSave;
+
+    ASSERT(ppdev);
+    ASSERT(psoDest);
+
+    pgp = &ppdev->Pointer;
+
+    if (!pgp->Enabled)
+    {
+        return;
+    }
+
+    pgp->Enabled = FALSE;
+
+    if (!pgp->psurfSave)
+    {
+        DPRINT1("No SaveSurface!\n");
+        return;
+    }
+
+    /* Calculate cursor coordinates */
+    pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x;
+    pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y;
+
+    rclDest.left = max(pt.x, 0);
+    rclDest.top = max(pt.y, 0);
+    rclDest.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx);
+    rclDest.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy);
+
+    ptlSave.x = rclDest.left - pt.x;
+    ptlSave.y = rclDest.top - pt.y;
+
+    IntEngBitBlt(psoDest,
+                 &pgp->psurfSave->SurfObj,
+                 NULL,
+                 NULL,
+                 NULL,
+                 &rclDest,
+                 &ptlSave,
+                 &ptlSave,
+                 NULL,
+                 NULL,
+                 ROP3_TO_ROP4(SRCCOPY));
 }
 
-VOID INTERNAL_CALL
-IntShowMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
+VOID
+INTERNAL_CALL
+IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest)
 {
-   GDIPOINTER *pgp;
-   SURFOBJ *SaveSurface;
-   POINTL pt;
-
-   ASSERT(ppdev);
-   ASSERT(DestSurface);
-
-   pgp = &ppdev->Pointer;
-
-   if (pgp->Enabled)
-   {
-      return;
-   }
-     
-   pgp->Enabled = TRUE;
-   
-   /*
-    * Do not blt the mouse if it in hide 
-    */
-   if (pgp->ShowPointer < 0)
-   {
-     return ;
-   }
-   
-   pt.x = pgp->Pos.x - pgp->HotSpot.x;
-   pt.y = pgp->Pos.y - pgp->HotSpot.y;
-
-   /*
-    * Copy the pixels under the cursor to temporary surface.
-    */
-
-   if (pgp->SaveSurface != NULL &&
-       (SaveSurface = EngLockSurface(pgp->SaveSurface)))
-   {
-      RECTL DestRect;
-      POINTL SrcPoint;
-
-      SrcPoint.x = max(pt.x, 0);
-      SrcPoint.y = max(pt.y, 0);
-
-      DestRect.left = SrcPoint.x - pt.x;
-      DestRect.top = SrcPoint.y - pt.y;
-      DestRect.right = min(
-         pgp->Size.cx,
-         DestSurface->sizlBitmap.cx - pt.x);
-      DestRect.bottom = min(
-         pgp->Size.cy,
-         DestSurface->sizlBitmap.cy - pt.y);
-
-      IntEngBitBltEx(SaveSurface, DestSurface, NULL, NULL, NULL,
-                     &DestRect, &SrcPoint, NULL, NULL, NULL,
-                     ROP3_TO_ROP4(SRCCOPY), FALSE);
-      EngUnlockSurface(SaveSurface);
-   }
-
-
-   /*   
-    * Blit the cursor on the screen.
-    */
-
-   {
-      RECTL DestRect;
-      POINTL SrcPoint;
-      SURFOBJ *ColorSurf;
-      SURFOBJ *MaskSurf = NULL;
-
-      DestRect.left = max(pt.x, 0);
-      DestRect.top = max(pt.y, 0);
-      DestRect.right = min(
-         pt.x + pgp->Size.cx,
-         DestSurface->sizlBitmap.cx);
-      DestRect.bottom = min(
-         pt.y + pgp->Size.cy,
-         DestSurface->sizlBitmap.cy);
-
-      SrcPoint.x = max(-pt.x, 0);
-      SrcPoint.y = max(-pt.y, 0);
-
-
-      if (pgp->MaskSurface)
-        MaskSurf = EngLockSurface(pgp->MaskSurface);
-
-      if (MaskSurf != NULL)
-      {
-        if (pgp->ColorSurface != NULL)
+    GDIPOINTER *pgp;
+    POINTL pt;
+    RECTL rclSurf, rclPointer;
+
+    ASSERT(ppdev);
+    ASSERT(psoDest);
+
+    pgp = &ppdev->Pointer;
+
+    if (pgp->Enabled)
+    {
+        return;
+    }
+
+    pgp->Enabled = TRUE;
+
+    /* Check if we have any mouse pointer */
+    if (!pgp->psurfSave) return;
+
+    /* Calculate pointer coordinates */
+    pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x;
+    pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y;
+
+    /* Calculate the rect on the surface */
+    rclSurf.left = max(pt.x, 0);
+    rclSurf.top = max(pt.y, 0);
+    rclSurf.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx);
+    rclSurf.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy);
+
+    /* Calculate the rect in the pointer bitmap */
+    rclPointer.left = rclSurf.left - pt.x;
+    rclPointer.top = rclSurf.top - pt.y;
+    rclPointer.right = min(pgp->Size.cx, psoDest->sizlBitmap.cx - pt.x);
+    rclPointer.bottom = min(pgp->Size.cy, psoDest->sizlBitmap.cy - pt.y);
+
+    /* Copy the pixels under the cursor to temporary surface. */
+    IntEngBitBlt(&pgp->psurfSave->SurfObj,
+                 psoDest,
+                 NULL,
+                 NULL,
+                 NULL,
+                 &rclPointer,
+                 (POINTL*)&rclSurf,
+                 NULL,
+                 NULL,
+                 NULL,
+                 ROP3_TO_ROP4(SRCCOPY));
+
+    /* Blt the pointer on the screen. */
+    if (pgp->psurfColor)
+    {
+        IntEngBitBlt(psoDest,
+                     &pgp->psurfMask->SurfObj,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &rclSurf,
+                     (POINTL*)&rclPointer,
+                     NULL,
+                     NULL,
+                     NULL,
+                     ROP3_TO_ROP4(SRCAND));
+
+        IntEngBitBlt(psoDest,
+                     &pgp->psurfColor->SurfObj,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &rclSurf,
+                     (POINTL*)&rclPointer,
+                     NULL,
+                     NULL,
+                     NULL,
+                     ROP3_TO_ROP4(SRCINVERT));
+    }
+    else
+    {
+        IntEngBitBlt(psoDest,
+                     &pgp->psurfMask->SurfObj,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &rclSurf,
+                     (POINTL*)&rclPointer,
+                     NULL,
+                     NULL,
+                     NULL,
+                     ROP3_TO_ROP4(SRCAND));
+
+        rclPointer.top += pgp->Size.cy;
+
+        IntEngBitBlt(psoDest,
+                     &pgp->psurfMask->SurfObj,
+                     NULL,
+                     NULL,
+                     NULL,
+                     &rclSurf,
+                     (POINTL*)&rclPointer,
+                     NULL,
+                     NULL,
+                     NULL,
+                     ROP3_TO_ROP4(SRCINVERT));
+    }
+}
+
+/*
+ * @implemented
+ */
+ULONG APIENTRY
+EngSetPointerShape(
+    IN SURFOBJ *pso,
+    IN SURFOBJ *psoMask,
+    IN SURFOBJ *psoColor,
+    IN XLATEOBJ *pxlo,
+    IN LONG xHot,
+    IN LONG yHot,
+    IN LONG x,
+    IN LONG y,
+    IN RECTL *prcl,
+    IN FLONG fl)
+{
+    PDEVOBJ *ppdev;
+    GDIPOINTER *pgp;
+    LONG lDelta = 0;
+    HBITMAP hbmSave = NULL, hbmColor = NULL, hbmMask = NULL;
+    PSURFACE psurfSave = NULL, psurfColor = NULL, psurfMask = NULL;
+    RECTL rectl;
+    SIZEL sizel = {0, 0};
+
+    ASSERT(pso);
+
+    ppdev = GDIDEV(pso);
+    pgp = &ppdev->Pointer;
+
+    /* Do we have any bitmap at all? */
+    if (psoColor || psoMask)
+    {
+        /* Get the size of the new pointer */
+        if (psoColor)
         {
-           if((ColorSurf = EngLockSurface(pgp->ColorSurface)))
-           {
-                IntEngBitBltEx(DestSurface, ColorSurf, MaskSurf, NULL,
-                            pgp->XlateObject, &DestRect, &SrcPoint, &SrcPoint,
-                            NULL, NULL, R4_MASK, FALSE);
-                EngUnlockSurface(ColorSurf);
-           }
+            sizel.cx = psoColor->sizlBitmap.cx;
+            sizel.cy = psoColor->sizlBitmap.cy;
         }
-        else
-        {         
-           IntEngBitBltEx(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject,
-                          &DestRect, &SrcPoint, NULL, NULL, NULL,
-                          ROP3_TO_ROP4(SRCAND), FALSE);
-           SrcPoint.y += pgp->Size.cy;
-           IntEngBitBltEx(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject,
-                          &DestRect, &SrcPoint, NULL, NULL, NULL,
-                          ROP3_TO_ROP4(SRCINVERT), FALSE);         
+        else// if (psoMask)
+        {
+            sizel.cx = psoMask->sizlBitmap.cx;
+            sizel.cy = psoMask->sizlBitmap.cy / 2;
         }
-        EngUnlockSurface(MaskSurf);
-      }
-   }
+
+        rectl.left = 0;
+        rectl.top = 0;
+        rectl.right = sizel.cx;
+        rectl.bottom = sizel.cy;
+
+        /* Calculate lDelta for our surfaces. */
+        lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, 
+                                      BitsPerFormat(pso->iBitmapFormat));
+
+        /* Create a bitmap for saving the pixels under the cursor. */
+        hbmSave = EngCreateBitmap(sizel,
+                                  lDelta,
+                                  pso->iBitmapFormat,
+                                  BMF_TOPDOWN | BMF_NOZEROINIT,
+                                  NULL);
+        psurfSave = SURFACE_ShareLockSurface(hbmSave);
+        if (!psurfSave) goto failure;
+    }
+
+    if (psoColor)
+    {
+        /* Color bitmap must have the same format as the dest surface */
+        if (psoColor->iBitmapFormat != pso->iBitmapFormat) goto failure;
+
+        /* Create a bitmap to copy the color bitmap to */
+        hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
+                           lDelta,
+                           pso->iBitmapFormat,
+                           BMF_TOPDOWN | BMF_NOZEROINIT,
+                           NULL);
+        psurfColor = SURFACE_ShareLockSurface(hbmColor);
+        if (!psurfColor) goto failure;
+
+        /* Now copy the given bitmap */
+        rectl.bottom = psoColor->sizlBitmap.cy;
+        IntEngCopyBits(&psurfColor->SurfObj,
+                       psoColor,
+                       NULL,
+                       pxlo,
+                       &rectl,
+                       (POINTL*)&rectl);
+    }
+
+    /* Create a mask surface */
+    if (psoMask)
+    {
+        EXLATEOBJ exlo;
+        PPALETTE ppal;
+
+        /* Create a bitmap for the mask */
+        hbmMask = EngCreateBitmap(psoMask->sizlBitmap,
+                                  lDelta,
+                                  pso->iBitmapFormat,
+                                  BMF_TOPDOWN | BMF_NOZEROINIT,
+                                  NULL);
+        psurfMask = SURFACE_ShareLockSurface(hbmMask);
+        if (!psurfMask) goto failure;
+
+        /* Initialize an EXLATEOBJ */
+        ppal = PALETTE_LockPalette(ppdev->devinfo.hpalDefault);
+        EXLATEOBJ_vInitialize(&exlo,
+                              &gpalMono,
+                              ppal,
+                              0,
+                              RGB(0xff,0xff,0xff),
+                              RGB(0,0,0));
+
+        /* Copy the mask bitmap */
+        rectl.bottom = psoMask->sizlBitmap.cy;
+        IntEngCopyBits(&psurfMask->SurfObj,
+                       psoMask,
+                       NULL,
+                       &exlo.xlo,
+                       &rectl,
+                       (POINTL*)&rectl);
+
+        /* Cleanup */
+        EXLATEOBJ_vCleanup(&exlo);
+        if (ppal) PALETTE_UnlockPalette(ppal);
+    }
+
+    /* Hide mouse pointer */
+    IntHideMousePointer(ppdev, pso);
+
+    /* Free old color bitmap */
+    if (pgp->psurfColor)
+    {
+        EngDeleteSurface(pgp->psurfColor->BaseObject.hHmgr);
+        SURFACE_ShareUnlockSurface(pgp->psurfColor);
+        pgp->psurfColor = NULL;
+    }
+
+    /* Free old mask bitmap */
+    if (pgp->psurfMask)
+    {
+        EngDeleteSurface(pgp->psurfMask->BaseObject.hHmgr);
+        SURFACE_ShareUnlockSurface(pgp->psurfMask);
+        pgp->psurfMask = NULL;
+    }
+
+    /* Free old save bitmap */
+    if (pgp->psurfSave)
+    {
+        EngDeleteSurface(pgp->psurfSave->BaseObject.hHmgr);
+        SURFACE_ShareUnlockSurface(pgp->psurfSave);
+        pgp->psurfSave = NULL;
+    }
+
+    /* See if we are being asked to hide the pointer. */
+    if (psoMask == NULL && psoColor == NULL)
+    {
+        /* We're done */
+        return SPS_ACCEPT_NOEXCLUDE;
+    }
+
+    /* Now set the new cursor */
+    pgp->psurfColor = psurfColor;
+    pgp->psurfMask = psurfMask;
+    pgp->psurfSave = psurfSave;
+    pgp->HotSpot.x = xHot;
+    pgp->HotSpot.y = yHot;
+    pgp->Size = sizel;
+
+    if (x != -1)
+    {
+        ppdev->ptlPointer.x = x;
+        ppdev->ptlPointer.y = y;
+
+        IntShowMousePointer(ppdev, pso);
+
+        if (prcl != NULL)
+        {
+            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;
+    }
+
+    return SPS_ACCEPT_NOEXCLUDE;
+
+failure:
+    /* Cleanup surfaces */
+    if (hbmMask) EngDeleteSurface(hbmMask);
+    if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
+    if (hbmColor) EngDeleteSurface(hbmColor);
+    if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
+    if (hbmSave) EngDeleteSurface(hbmSave);
+    if (psurfSave) SURFACE_ShareUnlockSurface(psurfSave);
+
+    return SPS_ERROR;
 }
 
 /*
  * @implemented
  */
 
-ULONG STDCALL
-EngSetPointerShape(
+VOID APIENTRY
+EngMovePointer(
+    IN SURFOBJ *pso,
+    IN LONG x,
+    IN LONG y,
+    IN RECTL *prcl)
+{
+    PDEVOBJ *ppdev;
+    GDIPOINTER *pgp;
+
+    ASSERT(pso);
+
+    ppdev = GDIDEV(pso);
+    ASSERT(ppdev);
+
+    pgp = &ppdev->Pointer;
+
+    IntHideMousePointer(ppdev, pso);
+
+    ppdev->ptlPointer.x = x;
+    ppdev->ptlPointer.y = y;
+
+    if (x != -1)
+    {
+        IntShowMousePointer(ppdev, pso);
+        if (prcl != NULL)
+        {
+            prcl->left = x - pgp->HotSpot.x;
+            prcl->top = y - pgp->HotSpot.y;
+            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;
+    }
+}
+
+ULONG APIENTRY
+IntEngSetPointerShape(
    IN SURFOBJ *pso,
    IN SURFOBJ *psoMask,
    IN SURFOBJ *psoColor,
@@ -335,257 +544,178 @@ EngSetPointerShape(
    IN RECTL *prcl,
    IN FLONG fl)
 {
-   GDIDEVICE *ppdev;
-   SURFOBJ *TempSurfObj;
-   GDIPOINTER *pgp;
-
-   ASSERT(pso);
-
-   ppdev = GDIDEV(pso);
-   pgp = &ppdev->Pointer;
-
-   IntHideMousePointer(ppdev, pso);
-
-   if (pgp->ColorSurface != NULL)
-   {
-      /* FIXME: Is this really needed? */
-      if((TempSurfObj = EngLockSurface(pgp->ColorSurface)))
-      {
-        EngFreeMem(TempSurfObj->pvBits);
-        TempSurfObj->pvBits = 0;
-        EngUnlockSurface(TempSurfObj);
-      }
-
-      EngDeleteSurface(pgp->ColorSurface);
-      pgp->MaskSurface = NULL;
-   }
-
-   if (pgp->MaskSurface != NULL)
-   {
-      /* FIXME: Is this really needed? */
-      if((TempSurfObj = EngLockSurface(pgp->MaskSurface)))
-      {
-        EngFreeMem(TempSurfObj->pvBits);
-        TempSurfObj->pvBits = 0;
-        EngUnlockSurface(TempSurfObj);
-      }
-
-      EngDeleteSurface(pgp->MaskSurface);
-      pgp->MaskSurface = NULL;
-   }
-
-   if (pgp->SaveSurface != NULL)
-   {
-      EngDeleteSurface(pgp->SaveSurface);
-      pgp->SaveSurface = NULL;
-   }
-
-   if (pgp->XlateObject != NULL)
-   {
-      EngDeleteXlate(pgp->XlateObject);
-      pgp->XlateObject = NULL;
-   }
-
-   /*
-    * See if we are being asked to hide the pointer.
-    */
-
-   if (psoMask == NULL)
-   {
-      return SPS_ACCEPT_NOEXCLUDE;
-   }
-
-   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;
-     pgp->Pos.y = y;
-   }
-
-   pgp->Size.cx = abs(psoMask->lDelta) << 3;
-   pgp->Size.cy = (psoMask->cjBits / abs(psoMask->lDelta)) >> 1;
-
-   if (psoColor != NULL)
-   {
-      PBYTE Bits;
-
-      Bits = EngAllocMem(0, psoColor->cjBits, TAG_MOUSE);
-      if (Bits == NULL)
-      {
-          return SPS_ERROR;
-      }
-      
-      memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
-
-      pgp->ColorSurface = (HSURF)EngCreateBitmap(pgp->Size,
-         psoColor->lDelta, psoColor->iBitmapFormat,
-         psoColor->lDelta < 0 ? 0 : BMF_TOPDOWN, Bits);
-   }
-   else
-   {
-      pgp->ColorSurface = NULL;
-   }
-
-   {
-      SIZEL Size;
-      PBYTE Bits;
-
-      Size.cx = pgp->Size.cx;
-      Size.cy = pgp->Size.cy << 1;
-      Bits = EngAllocMem(0, psoMask->cjBits, TAG_MOUSE);
-      if (Bits == NULL)
-      {
-          return SPS_ERROR;
-      }
-      
-      memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
-
-      pgp->MaskSurface = (HSURF)EngCreateBitmap(Size,
-         psoMask->lDelta, psoMask->iBitmapFormat,
-         psoMask->lDelta < 0 ? 0 : BMF_TOPDOWN, Bits);
-   }
-
-   /*
-    * Create an XLATEOBJ that will be used for drawing masks.
-    * FIXME: We should get this in pxlo parameter!
-    */
-
-   if (pxlo == NULL)
-   {
-      HPALETTE BWPalette, DestPalette;
-      ULONG BWColors[] = {0, 0xFFFFFF};
-
-      BWPalette = EngCreatePalette(PAL_INDEXED, sizeof(BWColors) / sizeof(ULONG),
-         BWColors, 0, 0, 0);
-
-      DestPalette = ppdev->DevInfo.hpalDefault;
-      pgp->XlateObject = IntEngCreateXlate(0, PAL_INDEXED,
-         DestPalette, BWPalette);
-      EngDeletePalette(BWPalette);
-   }
-   else
-   {
-      pgp->XlateObject = pxlo;
-   }
-
-   /*
-    * Create surface for saving the pixels under the cursor.
-    */
-
-   {
-      LONG lDelta;
-
-      switch (pso->iBitmapFormat)
-      {
-         case BMF_1BPP:
-          lDelta = pgp->Size.cx >> 3;
-          break;
-         case BMF_4BPP:
-          lDelta = pgp->Size.cx >> 1;
-          break;
-         case BMF_8BPP:
-          lDelta = pgp->Size.cx;
-          break;
-         case BMF_16BPP:
-          lDelta = pgp->Size.cx << 1;
-          break;
-         case BMF_24BPP:
-          lDelta = pgp->Size.cx * 3;
-          break;
-         case BMF_32BPP:
-          lDelta = pgp->Size.cx << 2;
-          break;
-         default:
-          lDelta = 0;
-          break;
-      }
-
-      pgp->SaveSurface = (HSURF)EngCreateBitmap(
-         pgp->Size, lDelta, pso->iBitmapFormat, BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
-   }
-
-   if(x != -1)
-   {
-     IntShowMousePointer(ppdev, pso);
-
-     if (prcl != NULL)
-     {
-       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;
-
-   return SPS_ACCEPT_EXCLUDE;
-}
+    ULONG ulResult = SPS_DECLINE;
+    PFN_DrvSetPointerShape pfnSetPointerShape;
+    PPDEVOBJ ppdev = GDIDEV(pso);
 
-/*
- * @implemented
- */
+    pfnSetPointerShape = GDIDEVFUNCS(pso).SetPointerShape;
 
-VOID STDCALL
-EngMovePointer(
-   IN SURFOBJ *pso,
-   IN LONG x,
-   IN LONG y,
-   IN RECTL *prcl)
+    if (pfnSetPointerShape)
+    {
+        ulResult = pfnSetPointerShape(pso,
+                                      psoMask,
+                                      psoColor,
+                                      pxlo,
+                                      xHot,
+                                      yHot,
+                                      x,
+                                      y,
+                                      prcl,
+                                      fl);
+    }
+
+    /* Check if the driver accepted it */
+    if (ulResult == SPS_ACCEPT_NOEXCLUDE)
+    {
+        /* Set MovePointer to the driver function */
+        ppdev->pfnMovePointer = GDIDEVFUNCS(pso).MovePointer;
+    }
+    else
+    {
+        /* Set software pointer */
+        ulResult = EngSetPointerShape(pso,
+                                      psoMask,
+                                      psoColor,
+                                      pxlo,
+                                      xHot,
+                                      yHot,
+                                      x,
+                                      y,
+                                      prcl,
+                                      fl);
+        /* Set MovePointer to the eng function */
+        ppdev->pfnMovePointer = EngMovePointer;
+    }
+
+    return ulResult;
+}
+
+ULONG
+NTAPI
+GreSetPointerShape(
+    HDC hdc,
+    HBITMAP hbmMask,
+    HBITMAP hbmColor,
+    LONG xHot,
+    LONG yHot,
+    LONG x,
+    LONG y)
 {
-   GDIDEVICE *ppdev;
-   GDIPOINTER *pgp;
-
-   ASSERT(pso);
-
-   ppdev = GDIDEV(pso);
-
-   ASSERT(ppdev);
-
-   pgp = &ppdev->Pointer;
-
-   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 = 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;
+    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;
+    }
+
+    ASSERT(pdc->dctype == DCTYPE_DIRECT);
+    EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
+    /* We're not sure DC surface is the good one */
+    psurf = pdc->ppdev->pSurface;
+    if (!psurf)
+    {
+        DPRINT1("DC has no surface.\n");
+        EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
+        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 | SPS_CHANGE);
+
+    /* Cleanup */
+    if (psurfColor)
+    {
+        EXLATEOBJ_vCleanup(&exlo);
+        SURFACE_ShareUnlockSurface(psurfColor);
+    }
+
+    if (psurfMask)
+        SURFACE_ShareUnlockSurface(psurfMask);
+
+    EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
 
+    /* Unlock the DC */
+    DC_UnlockDc(pdc);
+
+    /* Return result */
+    return ulResult;
 }
 
-VOID STDCALL
-IntEngMovePointer(
-   IN SURFOBJ *SurfObj,
-   IN LONG x,
-   IN LONG y,
-   IN RECTL *prcl)
+VOID
+NTAPI
+GreMovePointer(
+    HDC hdc,
+    LONG x,
+    LONG y)
 {
-  BITMAPOBJ *BitmapObj = CONTAINING_RECORD(SurfObj, BITMAPOBJ, SurfObj);
+    PDC pdc;
+    PRECTL prcl;
 
-  BITMAPOBJ_LockBitmapBits(BitmapObj);
-  if (GDIDEV(SurfObj)->Pointer.MovePointer)
+    /* Lock the DC */
+    pdc = DC_LockDc(hdc);
+    if (!pdc)
     {
-    GDIDEV(SurfObj)->Pointer.MovePointer(SurfObj, x, y, prcl);
+        DPRINT1("Failed to lock the DC.\n");
+        return;
     }
-  else
+    ASSERT(pdc->dctype == DCTYPE_DIRECT);
+
+    /* Acquire PDEV lock */
+    EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
+
+    /* Check if we need to move it */
+    if(pdc->ppdev->SafetyRemoveLevel == 0)
     {
-    EngMovePointer(SurfObj, x, y, prcl);
+        /* Store the cursor exclude position in the PDEV */
+        prcl = &pdc->ppdev->Pointer.Exclude;
+
+        /* Call Eng/Drv function */
+        pdc->ppdev->pfnMovePointer(&pdc->ppdev->pSurface->SurfObj, x, y, prcl);
     }
-  BITMAPOBJ_UnlockBitmapBits(BitmapObj);
+
+    /* Release PDEV lock */
+    EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
+
+    /* Unlock the DC */
+    DC_UnlockDc(pdc);
 }
 
+
 /* EOF */