mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
162de4a0d8
Otherwise, use software pointer functions. This fixes graphical glitches on cursor change, when the display driver provides accelerated pointer functions (DrvSetPointerShape/DrvMovePointer), but refuses to handle a certain cursor. These graphical glitches may be reproduced: - by using Voodoo driver SFFT 1.9 - by using framebuf_new.dll instead of framebuf.dll - by using the panning driver (setting DefaultSettings.XPanning and DefaultSettings.YPanning in registry)
847 lines
22 KiB
C
847 lines
22 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS win32 subsystem
|
|
* PURPOSE: Mouse pointer functions
|
|
* FILE: win32ss/gdi/eng/mouse.c
|
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
* Timo Kreuzer (timo.kreuzer@reactos.org)
|
|
*/
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <win32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
__drv_preferredFunction("(see documentation)", "Obsolete, always returns false. ")
|
|
BOOL
|
|
APIENTRY
|
|
EngSetPointerTag(
|
|
_In_ HDEV hdev,
|
|
_In_opt_ SURFOBJ *psoMask,
|
|
_In_opt_ SURFOBJ *psoColor,
|
|
_Reserved_ 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.
|
|
*/
|
|
_Requires_lock_held_(*ppdev->hsemDevLock)
|
|
BOOL
|
|
NTAPI
|
|
MouseSafetyOnDrawStart(
|
|
_Inout_ PPDEVOBJ ppdev,
|
|
_In_ LONG HazardX1,
|
|
_In_ LONG HazardY1,
|
|
_In_ LONG HazardX2,
|
|
_In_ LONG HazardY2)
|
|
{
|
|
LONG tmp;
|
|
GDIPOINTER *pgp;
|
|
|
|
ASSERT(ppdev != NULL);
|
|
ASSERT(ppdev->pSurface != NULL);
|
|
|
|
pgp = &ppdev->Pointer;
|
|
|
|
if (pgp->Exclude.right == -1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ppdev->SafetyRemoveCount++;
|
|
|
|
if (ppdev->SafetyRemoveLevel != 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (HazardX1 > HazardX2)
|
|
{
|
|
tmp = HazardX2;
|
|
HazardX2 = HazardX1;
|
|
HazardX1 = tmp;
|
|
}
|
|
if (HazardY1 > HazardY2)
|
|
{
|
|
tmp = HazardY2;
|
|
HazardY2 = HazardY1;
|
|
HazardY1 = tmp;
|
|
}
|
|
|
|
if (pgp->Exclude.right >= HazardX1
|
|
&& pgp->Exclude.left <= HazardX2
|
|
&& pgp->Exclude.bottom >= HazardY1
|
|
&& pgp->Exclude.top <= HazardY2)
|
|
{
|
|
ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
|
|
if (ppdev->flFlags & PDEV_HARDWARE_POINTER)
|
|
ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj, -1, -1, NULL);
|
|
else if (ppdev->flFlags & PDEV_SOFTWARE_POINTER)
|
|
EngMovePointer(&ppdev->pSurface->SurfObj, -1, -1, NULL);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: Notify the mouse driver that drawing has finished on a surface.
|
|
*/
|
|
_Requires_lock_held_(*ppdev->hsemDevLock)
|
|
BOOL
|
|
NTAPI
|
|
MouseSafetyOnDrawEnd(
|
|
_Inout_ PPDEVOBJ ppdev)
|
|
{
|
|
GDIPOINTER *pgp;
|
|
|
|
ASSERT(ppdev != NULL);
|
|
ASSERT(ppdev->pSurface != NULL);
|
|
|
|
pgp = &ppdev->Pointer;
|
|
|
|
if (pgp->Exclude.right == -1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (--ppdev->SafetyRemoveCount >= ppdev->SafetyRemoveLevel)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (ppdev->flFlags & PDEV_HARDWARE_POINTER)
|
|
ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj,
|
|
gpsi->ptCursor.x,
|
|
gpsi->ptCursor.y,
|
|
&pgp->Exclude);
|
|
else if (ppdev->flFlags & PDEV_SOFTWARE_POINTER)
|
|
EngMovePointer(&ppdev->pSurface->SurfObj,
|
|
gpsi->ptCursor.x,
|
|
gpsi->ptCursor.y,
|
|
&pgp->Exclude);
|
|
|
|
ppdev->SafetyRemoveLevel = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
|
|
|
|
VOID
|
|
NTAPI
|
|
IntHideMousePointer(
|
|
_Inout_ PDEVOBJ *ppdev,
|
|
_Inout_ SURFOBJ *psoDest)
|
|
{
|
|
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)
|
|
{
|
|
DPRINT("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,
|
|
ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
IntShowMousePointer(
|
|
_Inout_ PDEVOBJ *ppdev,
|
|
_Inout_ SURFOBJ *psoDest)
|
|
{
|
|
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,
|
|
ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
|
|
|
|
/* Blt the pointer on the screen. */
|
|
if (pgp->psurfColor)
|
|
{
|
|
if(!(pgp->flags & SPS_ALPHA))
|
|
{
|
|
IntEngBitBlt(psoDest,
|
|
&pgp->psurfMask->SurfObj,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&rclSurf,
|
|
(POINTL*)&rclPointer,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
ROP4_SRCAND);
|
|
|
|
IntEngBitBlt(psoDest,
|
|
&pgp->psurfColor->SurfObj,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&rclSurf,
|
|
(POINTL*)&rclPointer,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
ROP4_SRCINVERT);
|
|
}
|
|
else
|
|
{
|
|
BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
|
|
EXLATEOBJ exlo;
|
|
EXLATEOBJ_vInitialize(&exlo,
|
|
&gpalRGB,
|
|
ppdev->ppalSurf,
|
|
0, 0, 0);
|
|
IntEngAlphaBlend(psoDest,
|
|
&pgp->psurfColor->SurfObj,
|
|
NULL,
|
|
&exlo.xlo,
|
|
&rclSurf,
|
|
&rclPointer,
|
|
&blendobj);
|
|
EXLATEOBJ_vCleanup(&exlo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IntEngBitBlt(psoDest,
|
|
&pgp->psurfMask->SurfObj,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&rclSurf,
|
|
(POINTL*)&rclPointer,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
ROP4_FROM_INDEX(R3_OPINDEX_SRCAND));
|
|
|
|
rclPointer.top += pgp->Size.cy;
|
|
|
|
IntEngBitBlt(psoDest,
|
|
&pgp->psurfMask->SurfObj,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&rclSurf,
|
|
(POINTL*)&rclPointer,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG
|
|
APIENTRY
|
|
EngSetPointerShape(
|
|
_In_ SURFOBJ *pso,
|
|
_In_opt_ SURFOBJ *psoMask,
|
|
_In_opt_ SURFOBJ *psoColor,
|
|
_In_opt_ 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;
|
|
|
|
/* Handle the case where we have no XLATEOBJ */
|
|
if (pxlo == NULL)
|
|
pxlo = &gexloTrivial.xlo;
|
|
|
|
/* Do we have any bitmap at all? */
|
|
if (psoColor || psoMask)
|
|
{
|
|
/* Get the size of the new pointer */
|
|
if (psoColor)
|
|
{
|
|
sizel.cx = psoColor->sizlBitmap.cx;
|
|
sizel.cy = psoColor->sizlBitmap.cy;
|
|
}
|
|
else// if (psoMask)
|
|
{
|
|
sizel.cx = psoMask->sizlBitmap.cx;
|
|
sizel.cy = psoMask->sizlBitmap.cy / 2;
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (fl & SPS_ALPHA)
|
|
{
|
|
/* Always store the alpha cursor in RGB. */
|
|
EXLATEOBJ exloSrcRGB;
|
|
PEXLATEOBJ pexlo;
|
|
|
|
pexlo = CONTAINING_RECORD(pxlo, EXLATEOBJ, xlo);
|
|
EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);
|
|
|
|
hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
|
|
WIDTH_BYTES_ALIGN32(sizel.cx, 32),
|
|
BMF_32BPP,
|
|
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,
|
|
&exloSrcRGB.xlo,
|
|
&rectl,
|
|
(POINTL*)&rectl);
|
|
|
|
EXLATEOBJ_vCleanup(&exloSrcRGB);
|
|
}
|
|
else
|
|
{
|
|
/* Color bitmap must have the same format as the dest surface */
|
|
if (psoColor->iBitmapFormat != pso->iBitmapFormat)
|
|
{
|
|
DPRINT1("Screen surface and cursor color bitmap format don't match!.\n");
|
|
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;
|
|
|
|
lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, BitsPerFormat(pso->iBitmapFormat));
|
|
|
|
/* 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_ShareLockPalette(ppdev->devinfo.hpalDefault);
|
|
EXLATEOBJ_vInitialize(&exlo,
|
|
gppalMono,
|
|
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_ShareUnlockPalette(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;
|
|
pgp->flags = fl;
|
|
|
|
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((HSURF)hbmMask);
|
|
if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
|
|
if (hbmColor) EngDeleteSurface((HSURF)hbmColor);
|
|
if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
|
|
if (hbmSave) EngDeleteSurface((HSURF)hbmSave);
|
|
if (psurfSave) SURFACE_ShareUnlockSurface(psurfSave);
|
|
|
|
return SPS_ERROR;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
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
|
|
NTAPI
|
|
IntEngSetPointerShape(
|
|
_In_ SURFOBJ *pso,
|
|
_In_opt_ SURFOBJ *psoMask,
|
|
_In_opt_ SURFOBJ *psoColor,
|
|
_In_opt_ XLATEOBJ *pxlo,
|
|
_In_ LONG xHot,
|
|
_In_ LONG yHot,
|
|
_In_ LONG x,
|
|
_In_ LONG y,
|
|
_In_ RECTL *prcl,
|
|
_In_ FLONG fl)
|
|
{
|
|
ULONG ulResult = SPS_DECLINE;
|
|
PFN_DrvSetPointerShape pfnSetPointerShape;
|
|
PPDEVOBJ ppdev = GDIDEV(pso);
|
|
BOOL bHardwarePointer = FALSE;
|
|
BOOL bSoftwarePointer = TRUE;
|
|
|
|
pfnSetPointerShape = GDIDEVFUNCS(pso).SetPointerShape;
|
|
|
|
if (pfnSetPointerShape)
|
|
{
|
|
/* Drivers expect to get an XLATEOBJ */
|
|
if (pxlo == NULL)
|
|
pxlo = &gexloTrivial.xlo;
|
|
|
|
/* Call the driver */
|
|
ulResult = pfnSetPointerShape(pso,
|
|
psoMask,
|
|
psoColor,
|
|
pxlo,
|
|
xHot,
|
|
yHot,
|
|
x,
|
|
y,
|
|
prcl,
|
|
fl);
|
|
|
|
/* Check if the driver accepted it */
|
|
if (ulResult == SPS_ACCEPT_NOEXCLUDE)
|
|
bHardwarePointer = TRUE;
|
|
|
|
bSoftwarePointer = !bHardwarePointer;
|
|
}
|
|
|
|
if (bSoftwarePointer)
|
|
{
|
|
/* Set software pointer */
|
|
ulResult = EngSetPointerShape(pso,
|
|
psoMask,
|
|
psoColor,
|
|
pxlo,
|
|
xHot,
|
|
yHot,
|
|
x,
|
|
y,
|
|
prcl,
|
|
fl);
|
|
}
|
|
|
|
if (!bSoftwarePointer && ppdev->flFlags & PDEV_SOFTWARE_POINTER)
|
|
{
|
|
/* Disable software pointer */
|
|
EngMovePointer(pso, -1, -1, NULL);
|
|
}
|
|
|
|
if (!bHardwarePointer && ppdev->flFlags & PDEV_HARDWARE_POINTER)
|
|
{
|
|
/* Disable hardware pointer */
|
|
ppdev->pfnMovePointer(pso, -1, -1, NULL);
|
|
}
|
|
|
|
/* Update flags */
|
|
if (bSoftwarePointer)
|
|
ppdev->flFlags |= PDEV_SOFTWARE_POINTER;
|
|
else
|
|
ppdev->flFlags &= ~PDEV_SOFTWARE_POINTER;
|
|
|
|
if (bHardwarePointer)
|
|
ppdev->flFlags |= PDEV_HARDWARE_POINTER;
|
|
else
|
|
ppdev->flFlags &= ~PDEV_HARDWARE_POINTER;
|
|
|
|
return ulResult;
|
|
}
|
|
|
|
ULONG
|
|
NTAPI
|
|
GreSetPointerShape(
|
|
_In_ HDC hdc,
|
|
_In_opt_ HBITMAP hbmMask,
|
|
_In_opt_ HBITMAP hbmColor,
|
|
_In_ LONG xHot,
|
|
_In_ LONG yHot,
|
|
_In_ LONG x,
|
|
_In_ LONG y,
|
|
_In_ FLONG fl)
|
|
{
|
|
PDC pdc;
|
|
PSURFACE psurf, psurfMask, psurfColor;
|
|
EXLATEOBJ exlo;
|
|
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
|
|
{
|
|
//ASSERT(fl & SPS_ALPHA);
|
|
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;
|
|
|
|
/* We must have a valid surface in case of alpha bitmap */
|
|
ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA));
|
|
|
|
/* 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
|
|
NTAPI
|
|
GreMovePointer(
|
|
_In_ HDC hdc,
|
|
_In_ LONG x,
|
|
_In_ LONG y)
|
|
{
|
|
PDC pdc;
|
|
PRECTL prcl;
|
|
|
|
/* Lock the DC */
|
|
pdc = DC_LockDc(hdc);
|
|
if (!pdc)
|
|
{
|
|
DPRINT1("Failed to lock the DC.\n");
|
|
return;
|
|
}
|
|
ASSERT(pdc->dctype == DCTYPE_DIRECT);
|
|
|
|
/* Acquire PDEV lock */
|
|
EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
|
|
|
|
/* Check if we need to move it */
|
|
if(pdc->ppdev->SafetyRemoveLevel == 0)
|
|
{
|
|
SURFOBJ* pso = &pdc->ppdev->pSurface->SurfObj;
|
|
|
|
/* Store the cursor exclude position in the PDEV */
|
|
prcl = &pdc->ppdev->Pointer.Exclude;
|
|
|
|
/* Send new position of the hot spot of the pointer (will likely redraw cursor) */
|
|
if (pdc->ppdev->flFlags & PDEV_HARDWARE_POINTER)
|
|
pdc->ppdev->pfnMovePointer(pso, x, y, prcl);
|
|
else if (pdc->ppdev->flFlags & PDEV_SOFTWARE_POINTER)
|
|
EngMovePointer(pso, x, y, prcl);
|
|
|
|
/* If panning device, and we're not hiding the cursor, notify cursor's current position.
|
|
* (driver may already have been called if it also supports hardware pointers) */
|
|
if (pdc->ppdev->devinfo.flGraphicsCaps & GCAPS_PANNING && y >= 0)
|
|
pdc->ppdev->pfnMovePointer(pso, x, y - pso->sizlBitmap.cy, NULL);
|
|
}
|
|
|
|
/* Release PDEV lock */
|
|
EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
|
|
|
|
/* Unlock the DC */
|
|
DC_UnlockDc(pdc);
|
|
}
|
|
|
|
|
|
/* EOF */
|