From db0f9b9ba4195b0bfc456312f356877b455ffb3a Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 24 Jan 2004 17:42:56 +0000 Subject: [PATCH] Work on mouse pointer implementation. svn path=/trunk/; revision=7864 --- .../drivers/video/displays/framebuf/enable.c | 2 +- .../video/displays/framebuf/framebuf.h | 12 + .../drivers/video/displays/framebuf/pointer.c | 312 ++++++++++++++++++ .../drivers/video/displays/framebuf/surface.c | 22 +- 4 files changed, 345 insertions(+), 3 deletions(-) diff --git a/reactos/drivers/video/displays/framebuf/enable.c b/reactos/drivers/video/displays/framebuf/enable.c index 3c8a24a9d80..05d1b1bda5b 100644 --- a/reactos/drivers/video/displays/framebuf/enable.c +++ b/reactos/drivers/video/displays/framebuf/enable.c @@ -31,7 +31,7 @@ static DRVFN DrvFunctionTable[] = {INDEX_DrvGetModes, (PFN)DrvGetModes}, {INDEX_DrvSetPalette, (PFN)DrvSetPalette}, {INDEX_DrvSetPointerShape, (PFN)DrvSetPointerShape}, - {INDEX_DrvMovePointer, (PFN)DrvMovePointer}, + {INDEX_DrvMovePointer, (PFN)DrvMovePointer} }; /* diff --git a/reactos/drivers/video/displays/framebuf/framebuf.h b/reactos/drivers/video/displays/framebuf/framebuf.h index 41353de0ef5..bc044387628 100644 --- a/reactos/drivers/video/displays/framebuf/framebuf.h +++ b/reactos/drivers/video/displays/framebuf/framebuf.h @@ -26,6 +26,8 @@ #include #include +#define EXPERIMENTAL_MOUSE_CURSOR_SUPPORT + typedef struct _PDEV { HANDLE hDriver; @@ -43,6 +45,16 @@ typedef struct _PDEV PVOID ScreenPtr; HPALETTE DefaultPalette; PALETTEENTRY *PaletteEntries; + +#ifdef EXPERIMENTAL_MOUSE_CURSOR_SUPPORT + VIDEO_POINTER_ATTRIBUTES PointerAttributes; + HSURF PointerColorSurface; + HSURF PointerMaskSurface; + HSURF PointerSaveSurface; + XLATEOBJ *XlateObject; + POINTL HotSpot; + CLIPOBJ *ScreenClipObj; +#endif } PDEV, *PPDEV; #define DEVICE_NAME L"framebuf" diff --git a/reactos/drivers/video/displays/framebuf/pointer.c b/reactos/drivers/video/displays/framebuf/pointer.c index 61078ffde5d..c930270d396 100644 --- a/reactos/drivers/video/displays/framebuf/pointer.c +++ b/reactos/drivers/video/displays/framebuf/pointer.c @@ -20,6 +20,8 @@ #include "framebuf.h" +#ifndef EXPERIMENTAL_MOUSE_CURSOR_SUPPORT + /* * DrvSetPointerShape * @@ -64,3 +66,313 @@ DrvMovePointer( { } + +#else + +VOID FASTCALL +IntHideMousePointer(PPDEV ppdev) +{ + if (ppdev->PointerAttributes.Enable == FALSE) + { + return; + } + + ppdev->PointerAttributes.Enable = FALSE; + if (ppdev->PointerSaveSurface != NULL) + { + RECTL DestRect; + POINTL SrcPoint; + SURFOBJ *SaveSurface; + SURFOBJ *DestSurface; + 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); + DestSurface = EngLockSurface(ppdev->hSurfEng); + MaskSurface = EngLockSurface(ppdev->PointerMaskSurface); + EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL, + &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY); + EngUnlockSurface(MaskSurface); + EngUnlockSurface(DestSurface); + EngUnlockSurface(SaveSurface); + } +} + +VOID FASTCALL +IntShowMousePointer(PPDEV ppdev) +{ + if (ppdev->PointerAttributes.Enable == TRUE) + { + return; + } + + ppdev->PointerAttributes.Enable = TRUE; + + /* + * Copy the pixels under the cursor to temporary surface. + */ + + if (ppdev->PointerSaveSurface != NULL) + { + RECTL DestRect; + POINTL SrcPoint; + SURFOBJ *SaveSurface; + SURFOBJ *DestSurface; + + 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); + DestSurface = EngLockSurface(ppdev->hSurfEng); + EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL, + &DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY); + EngUnlockSurface(DestSurface); + EngUnlockSurface(SaveSurface); + } + + /* + * Blit the cursor on the screen. + */ + + { + RECTL DestRect; + POINTL SrcPoint; + SURFOBJ *DestSurf; + 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); + + DestSurf = EngLockSurface(ppdev->hSurfEng); + MaskSurf = EngLockSurface(ppdev->PointerMaskSurface); + if (ppdev->PointerColorSurface != NULL) + { + ColorSurf = EngLockSurface(ppdev->PointerColorSurface); + EngBitBlt(DestSurf, ColorSurf, MaskSurf, NULL, ppdev->XlateObject, + &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC); + EngUnlockSurface(ColorSurf); + } + else + { + /* FIXME */ + EngBitBlt(DestSurf, MaskSurf, NULL, NULL, NULL, + &DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND); + SrcPoint.y += ppdev->PointerAttributes.Height; + EngBitBlt(DestSurf, MaskSurf, NULL, NULL, NULL, + &DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT); + } + EngUnlockSurface(MaskSurf); + EngUnlockSurface(DestSurf); + } +} + +/* + * DrvSetPointerShape + * + * Sets the new pointer shape. + * + * Status + * @implemented + */ + +ULONG DDKAPI +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); + + 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->HotSpot.x = xHot; + ppdev->HotSpot.y = yHot; + + ppdev->XlateObject = 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); + + 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 DDKAPI +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); + } + + if (x == -1) + { + return; + } + + ppdev->PointerAttributes.Column = x - ppdev->HotSpot.x; + ppdev->PointerAttributes.Row = y - ppdev->HotSpot.y; + + if (WasVisible) + { + IntShowMousePointer(ppdev); + } +} + +#endif diff --git a/reactos/drivers/video/displays/framebuf/surface.c b/reactos/drivers/video/displays/framebuf/surface.c index 8d02d5860a1..7698ef5b9ed 100644 --- a/reactos/drivers/video/displays/framebuf/surface.c +++ b/reactos/drivers/video/displays/framebuf/surface.c @@ -111,6 +111,15 @@ DrvEnableSurface( ppdev->hSurfEng = hSurface; +#ifdef EXPERIMENTAL_MOUSE_CURSOR_SUPPORT + ppdev->ScreenClipObj = EngCreateClip(); + ppdev->ScreenClipObj->iDComplexity = DC_RECT; + ppdev->ScreenClipObj->rclBounds.left = 0; + ppdev->ScreenClipObj->rclBounds.top = 0; + ppdev->ScreenClipObj->rclBounds.right = ppdev->ScreenWidth; + ppdev->ScreenClipObj->rclBounds.bottom = ppdev->ScreenHeight; +#endif + return hSurface; } @@ -130,9 +139,18 @@ DrvDisableSurface( { DWORD ulTemp; VIDEO_MEMORY VideoMemory; + PPDEV ppdev = (PPDEV)dhpdev; - EngDeleteSurface(((PPDEV)dhpdev)->hSurfEng); - ((PPDEV)dhpdev)->hSurfEng = NULL; + EngDeleteSurface(ppdev->hSurfEng); + ppdev->hSurfEng = NULL; + +#ifdef EXPERIMENTAL_MOUSE_CURSOR_SUPPORT + EngDeleteClip(ppdev->ScreenClipObj); + ppdev->ScreenClipObj = NULL; + + /* Clear all mouse pointer surfaces. */ + DrvSetPointerShape(NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0); +#endif /* * Unmap the framebuffer.