Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / win32ss / drivers / displays / framebuf / pointer.c
diff --git a/win32ss/drivers/displays/framebuf/pointer.c b/win32ss/drivers/displays/framebuf/pointer.c
new file mode 100644 (file)
index 0000000..e3a6ed6
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * ReactOS Generic Framebuffer display driver
+ *
+ * Copyright (C) 2004 Filip Navara
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "framebuf.h"
+
+#ifndef EXPERIMENTAL_MOUSE_CURSOR_SUPPORT
+
+/*
+ * DrvSetPointerShape
+ *
+ * Sets the new pointer shape.
+ *
+ * Status
+ *    @unimplemented
+ */
+
+ULONG APIENTRY
+DrvSetPointerShape(
+   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)
+{
+/*   return SPS_DECLINE;*/
+   return EngSetPointerShape(pso, psoMask, psoColor, pxlo, xHot, yHot, x, y, prcl, fl);
+}
+
+/*
+ * DrvMovePointer
+ *
+ * Moves the pointer to a new position and ensures that GDI does not interfere
+ * with the display of the pointer.
+ *
+ * Status
+ *    @unimplemented
+ */
+
+VOID APIENTRY
+DrvMovePointer(
+   IN SURFOBJ *pso,
+   IN LONG x,
+   IN LONG y,
+   IN RECTL *prcl)
+{
+   EngMovePointer(pso, x, y, prcl);
+}
+
+#else
+
+VOID FASTCALL
+IntHideMousePointer(PPDEV ppdev, SURFOBJ *DestSurface)
+{
+   if (ppdev->PointerAttributes.Enable == FALSE)
+   {
+      return;
+   }
+
+   ppdev->PointerAttributes.Enable = FALSE;
+   if (ppdev->PointerSaveSurface != NULL)
+   {
+      RECTL DestRect;
+      POINTL SrcPoint;
+      SURFOBJ *SaveSurface;
+      SURFOBJ *MaskSurface;
+
+      DestRect.left = max(ppdev->PointerAttributes.Column, 0);
+      DestRect.top = max(ppdev->PointerAttributes.Row, 0);
+      DestRect.right = min(
+         ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
+         ppdev->ScreenWidth - 1);
+      DestRect.bottom = min(
+         ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
+         ppdev->ScreenHeight - 1);
+
+      SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
+      SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
+
+      SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
+      MaskSurface = EngLockSurface(ppdev->PointerMaskSurface);
+      EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
+                &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY);
+      EngUnlockSurface(MaskSurface);
+      EngUnlockSurface(SaveSurface);
+   }
+}
+
+VOID FASTCALL
+IntShowMousePointer(PPDEV ppdev, SURFOBJ *DestSurface)
+{
+   if (ppdev->PointerAttributes.Enable)
+   {
+      return;
+   }
+
+   ppdev->PointerAttributes.Enable = TRUE;
+
+   /*
+    * Copy the pixels under the cursor to temporary surface.
+    */
+
+   if (ppdev->PointerSaveSurface != NULL)
+   {
+      RECTL DestRect;
+      POINTL SrcPoint;
+      SURFOBJ *SaveSurface;
+
+      SrcPoint.x = max(ppdev->PointerAttributes.Column, 0);
+      SrcPoint.y = max(ppdev->PointerAttributes.Row, 0);
+
+      DestRect.left = SrcPoint.x - ppdev->PointerAttributes.Column;
+      DestRect.top = SrcPoint.y - ppdev->PointerAttributes.Row;
+      DestRect.right = min(
+         ppdev->PointerAttributes.Width,
+         ppdev->ScreenWidth - ppdev->PointerAttributes.Column - 1);
+      DestRect.bottom = min(
+         ppdev->PointerAttributes.Height,
+         ppdev->ScreenHeight - ppdev->PointerAttributes.Row - 1);
+
+      SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
+      EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL,
+                &DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY);
+      EngUnlockSurface(SaveSurface);
+   }
+
+   /*
+    * Blit the cursor on the screen.
+    */
+
+   {
+      RECTL DestRect;
+      POINTL SrcPoint;
+      SURFOBJ *ColorSurf;
+      SURFOBJ *MaskSurf;
+
+      DestRect.left = max(ppdev->PointerAttributes.Column, 0);
+      DestRect.top = max(ppdev->PointerAttributes.Row, 0);
+      DestRect.right = min(
+         ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
+         ppdev->ScreenWidth - 1);
+      DestRect.bottom = min(
+         ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
+         ppdev->ScreenHeight - 1);
+
+      SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
+      SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
+
+      MaskSurf = EngLockSurface(ppdev->PointerMaskSurface);
+      if (ppdev->PointerColorSurface != NULL)
+      {
+         ColorSurf = EngLockSurface(ppdev->PointerColorSurface);
+         EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, ppdev->PointerXlateObject,
+                   &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC);
+         EngUnlockSurface(ColorSurf);
+      }
+      else
+      {
+         /* FIXME */
+         EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
+                   &DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND);
+         SrcPoint.y += ppdev->PointerAttributes.Height;
+         EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
+                   &DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT);
+      }
+      EngUnlockSurface(MaskSurf);
+   }
+}
+
+/*
+ * DrvSetPointerShape
+ *
+ * Sets the new pointer shape.
+ *
+ * Status
+ *    @implemented
+ */
+
+ULONG APIENTRY
+DrvSetPointerShape(
+   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)
+{
+   PPDEV ppdev = (PPDEV)pso->dhpdev;
+   SURFOBJ *TempSurfObj;
+
+   IntHideMousePointer(ppdev, pso);
+
+   if (ppdev->PointerColorSurface != NULL)
+   {
+      /* FIXME: Is this really needed? */
+      TempSurfObj = EngLockSurface(ppdev->PointerColorSurface);
+      EngFreeMem(TempSurfObj->pvBits);
+      TempSurfObj->pvBits = 0;
+      EngUnlockSurface(TempSurfObj);
+
+      EngDeleteSurface(ppdev->PointerColorSurface);
+      ppdev->PointerMaskSurface = NULL;
+   }
+
+   if (ppdev->PointerMaskSurface != NULL)
+   {
+      /* FIXME: Is this really needed? */
+      TempSurfObj = EngLockSurface(ppdev->PointerMaskSurface);
+      EngFreeMem(TempSurfObj->pvBits);
+      TempSurfObj->pvBits = 0;
+      EngUnlockSurface(TempSurfObj);
+
+      EngDeleteSurface(ppdev->PointerMaskSurface);
+      ppdev->PointerMaskSurface = NULL;
+   }
+
+   if (ppdev->PointerSaveSurface != NULL)
+   {
+      EngDeleteSurface(ppdev->PointerSaveSurface);
+      ppdev->PointerSaveSurface = NULL;
+   }
+
+   /*
+    * See if we are being asked to hide the pointer.
+    */
+
+   if (psoMask == NULL)
+   {
+      return SPS_ACCEPT_EXCLUDE;
+   }
+
+   ppdev->PointerHotSpot.x = xHot;
+   ppdev->PointerHotSpot.y = yHot;
+
+   ppdev->PointerXlateObject = pxlo;
+   ppdev->PointerAttributes.Column = x - xHot;
+   ppdev->PointerAttributes.Row = y - yHot;
+   ppdev->PointerAttributes.Width = psoMask->lDelta << 3;
+   ppdev->PointerAttributes.Height = (psoMask->cjBits / psoMask->lDelta) >> 1;
+
+   if (psoColor != NULL)
+   {
+      SIZEL Size;
+      PBYTE Bits;
+
+      Size.cx = ppdev->PointerAttributes.Width;
+      Size.cy = ppdev->PointerAttributes.Height;
+      Bits = EngAllocMem(0, psoColor->cjBits, ALLOC_TAG);
+      memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
+
+      ppdev->PointerColorSurface = (HSURF)EngCreateBitmap(Size,
+         psoColor->lDelta, psoColor->iBitmapFormat, 0, Bits);
+   }
+   else
+   {
+      ppdev->PointerColorSurface = NULL;
+   }
+
+   if (psoMask != NULL)
+   {
+      SIZEL Size;
+      PBYTE Bits;
+
+      Size.cx = ppdev->PointerAttributes.Width;
+      Size.cy = ppdev->PointerAttributes.Height << 1;
+      Bits = EngAllocMem(0, psoMask->cjBits, ALLOC_TAG);
+      memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
+
+      ppdev->PointerMaskSurface = (HSURF)EngCreateBitmap(Size,
+         psoMask->lDelta, psoMask->iBitmapFormat, 0, Bits);
+   }
+   else
+   {
+      ppdev->PointerMaskSurface = NULL;
+   }
+
+   /*
+    * Create surface for saving the pixels under the cursor.
+    */
+
+   {
+      SIZEL Size;
+      LONG lDelta;
+
+      Size.cx = ppdev->PointerAttributes.Width;
+      Size.cy = ppdev->PointerAttributes.Height;
+
+      switch (pso->iBitmapFormat)
+      {
+         case BMF_8BPP: lDelta = Size.cx; break;
+         case BMF_16BPP: lDelta = Size.cx << 1; break;
+         case BMF_24BPP: lDelta = Size.cx * 3; break;
+         case BMF_32BPP: lDelta = Size.cx << 2; break;
+      }
+
+      ppdev->PointerSaveSurface = (HSURF)EngCreateBitmap(
+         Size, lDelta, pso->iBitmapFormat, BMF_NOZEROINIT, NULL);
+   }
+
+   IntShowMousePointer(ppdev, pso);
+
+   return SPS_ACCEPT_EXCLUDE;
+}
+
+/*
+ * DrvMovePointer
+ *
+ * Moves the pointer to a new position and ensures that GDI does not interfere
+ * with the display of the pointer.
+ *
+ * Status
+ *    @implemented
+ */
+
+VOID APIENTRY
+DrvMovePointer(
+   IN SURFOBJ *pso,
+   IN LONG x,
+   IN LONG y,
+   IN RECTL *prcl)
+{
+   PPDEV ppdev = (PPDEV)pso->dhpdev;
+   BOOL WasVisible;
+
+   WasVisible = ppdev->PointerAttributes.Enable;
+   if (WasVisible)
+   {
+      IntHideMousePointer(ppdev, pso);
+   }
+
+   if (x == -1)
+   {
+      return;
+   }
+
+   ppdev->PointerAttributes.Column = x - ppdev->PointerHotSpot.x;
+   ppdev->PointerAttributes.Row = y - ppdev->PointerHotSpot.y;
+
+   if (WasVisible)
+   {
+      IntShowMousePointer(ppdev, pso);
+   }
+}
+
+#endif