2 * PROJECT: ReactOS win32 subsystem
3 * PURPOSE: Mouse pointer functions
4 * FILE: subsystems/win32k/eng/mouse.c
5 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * Timo Kreuzer (timo.kreuzer@reactos.org)
8 * 06-06-2001 CSH Created
10 /* INCLUDES ******************************************************************/
17 /* FUNCTIONS *****************************************************************/
28 // This function is obsolete for Windows 2000 and later.
29 // This function is still supported, but always returns FALSE.
30 // www.osr.com/ddk/graphics/gdifncs_4yav.htm
35 * FUNCTION: Notify the mouse driver that drawing is about to begin in
36 * a rectangle on a particular surface.
39 MouseSafetyOnDrawStart(
49 ASSERT(ppdev
!= NULL
);
50 ASSERT(ppdev
->pSurface
!= NULL
);
52 pgp
= &ppdev
->Pointer
;
54 if (pgp
->Exclude
.right
== -1)
59 ppdev
->SafetyRemoveCount
++;
61 if (ppdev
->SafetyRemoveLevel
!= 0)
66 if (HazardX1
> HazardX2
)
72 if (HazardY1
> HazardY2
)
79 if (pgp
->Exclude
.right
>= HazardX1
80 && pgp
->Exclude
.left
<= HazardX2
81 && pgp
->Exclude
.bottom
>= HazardY1
82 && pgp
->Exclude
.top
<= HazardY2
)
84 ppdev
->SafetyRemoveLevel
= ppdev
->SafetyRemoveCount
;
85 ppdev
->pfnMovePointer(&ppdev
->pSurface
->SurfObj
, -1, -1, NULL
);
92 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
100 ASSERT(ppdev
!= NULL
);
101 ASSERT(ppdev
->pSurface
!= NULL
);
103 pgp
= &ppdev
->Pointer
;
105 if (pgp
->Exclude
.right
== -1)
110 if (--ppdev
->SafetyRemoveCount
>= ppdev
->SafetyRemoveLevel
)
115 ppdev
->pfnMovePointer(&ppdev
->pSurface
->SurfObj
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
, &pgp
->Exclude
);
117 ppdev
->SafetyRemoveLevel
= 0;
122 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
138 pgp
= &ppdev
->Pointer
;
145 pgp
->Enabled
= FALSE
;
149 DPRINT1("No SaveSurface!\n");
153 /* Calculate cursor coordinates */
154 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
155 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
157 rclDest
.left
= max(pt
.x
, 0);
158 rclDest
.top
= max(pt
.y
, 0);
159 rclDest
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
160 rclDest
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
162 ptlSave
.x
= rclDest
.left
- pt
.x
;
163 ptlSave
.y
= rclDest
.top
- pt
.y
;
165 IntEngBitBltEx(psoDest
,
166 &pgp
->psurfSave
->SurfObj
,
175 ROP3_TO_ROP4(SRCCOPY
),
181 IntShowMousePointer(PDEVOBJ
*ppdev
, SURFOBJ
*psoDest
)
185 RECTL rclSurf
, rclPointer
;
190 pgp
= &ppdev
->Pointer
;
199 /* Calculate pointer coordinates */
200 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
201 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
203 /* Calculate the rect on the surface */
204 rclSurf
.left
= max(pt
.x
, 0);
205 rclSurf
.top
= max(pt
.y
, 0);
206 rclSurf
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
207 rclSurf
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
209 /* Calculate the rect in the pointer bitmap */
210 rclPointer
.left
= rclSurf
.left
- pt
.x
;
211 rclPointer
.top
= rclSurf
.top
- pt
.y
;
212 rclPointer
.right
= min(pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
- pt
.x
);
213 rclPointer
.bottom
= min(pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
- pt
.y
);
215 /* Copy the pixels under the cursor to temporary surface. */
216 IntEngBitBltEx(&pgp
->psurfSave
->SurfObj
,
226 ROP3_TO_ROP4(SRCCOPY
),
229 /* Blt the pointer on the screen. */
232 IntEngBitBltEx(psoDest
,
233 &pgp
->psurfMask
->SurfObj
,
238 (POINTL
*)&rclPointer
,
242 ROP3_TO_ROP4(SRCAND
),
245 IntEngBitBltEx(psoDest
,
246 &pgp
->psurfColor
->SurfObj
,
251 (POINTL
*)&rclPointer
,
255 ROP3_TO_ROP4(SRCINVERT
),
260 IntEngBitBltEx(psoDest
,
261 &pgp
->psurfMask
->SurfObj
,
266 (POINTL
*)&rclPointer
,
270 ROP3_TO_ROP4(SRCAND
),
273 rclPointer
.top
+= pgp
->Size
.cy
;
275 IntEngBitBltEx(psoDest
,
276 &pgp
->psurfMask
->SurfObj
,
281 (POINTL
*)&rclPointer
,
285 ROP3_TO_ROP4(SRCINVERT
),
297 IN SURFOBJ
*psoColor
,
315 pgp
= &ppdev
->Pointer
;
319 pgp
->Size
.cx
= psoColor
->sizlBitmap
.cx
;
320 pgp
->Size
.cy
= psoColor
->sizlBitmap
.cy
;
323 // CHECKME: Is this really required? if we have a color surface,
324 // we only need the AND part of the mask.
325 /* Check if the sizes match as they should */
326 if (psoMask
->sizlBitmap
.cx
!= psoColor
->sizlBitmap
.cx
||
327 psoMask
->sizlBitmap
.cy
!= psoColor
->sizlBitmap
.cy
* 2)
329 DPRINT("Sizes of mask (%ld,%ld) and color (%ld,%ld) don't match\n",
330 psoMask
->sizlBitmap
.cx
, psoMask
->sizlBitmap
.cy
,
331 psoColor
->sizlBitmap
.cx
, psoColor
->sizlBitmap
.cy
);
338 pgp
->Size
.cx
= psoMask
->sizlBitmap
.cx
;
339 pgp
->Size
.cy
= psoMask
->sizlBitmap
.cy
/ 2;
342 IntHideMousePointer(ppdev
, pso
);
346 EngDeleteSurface(pgp
->psurfColor
->BaseObject
.hHmgr
);
347 SURFACE_ShareUnlockSurface(pgp
->psurfColor
);
348 pgp
->psurfColor
= NULL
;
353 EngDeleteSurface(pgp
->psurfMask
->BaseObject
.hHmgr
);
354 SURFACE_ShareUnlockSurface(pgp
->psurfMask
);
355 pgp
->psurfMask
= NULL
;
358 if (pgp
->psurfSave
!= NULL
)
360 EngDeleteSurface(pgp
->psurfSave
->BaseObject
.hHmgr
);
361 SURFACE_ShareUnlockSurface(pgp
->psurfSave
);
362 pgp
->psurfSave
= NULL
;
365 /* See if we are being asked to hide the pointer. */
366 if (psoMask
== NULL
&& psoColor
== NULL
)
368 return SPS_ACCEPT_NOEXCLUDE
;
371 pgp
->HotSpot
.x
= xHot
;
372 pgp
->HotSpot
.y
= yHot
;
374 /* Calculate lDelta for our surfaces. */
375 lDelta
= DIB_GetDIBWidthBytes(pgp
->Size
.cx
,
376 BitsPerFormat(pso
->iBitmapFormat
));
380 rcl
.right
= pgp
->Size
.cx
;
381 rcl
.bottom
= pgp
->Size
.cy
;
383 /* Create surface for saving the pixels under the cursor. */
384 hbmp
= EngCreateBitmap(pgp
->Size
,
387 BMF_TOPDOWN
| BMF_NOZEROINIT
,
389 pgp
->psurfSave
= SURFACE_ShareLockSurface(hbmp
);
391 /* Create a mask surface */
397 hbmp
= EngCreateBitmap(psoMask
->sizlBitmap
,
400 BMF_TOPDOWN
| BMF_NOZEROINIT
,
402 pgp
->psurfMask
= SURFACE_ShareLockSurface(hbmp
);
406 ppal
= PALETTE_LockPalette(ppdev
->devinfo
.hpalDefault
);
407 EXLATEOBJ_vInitialize(&exlo
,
414 rcl
.bottom
= psoMask
->sizlBitmap
.cy
;
415 IntEngCopyBits(&pgp
->psurfMask
->SurfObj
,
422 EXLATEOBJ_vCleanup(&exlo
);
424 PALETTE_UnlockPalette(ppal
);
429 pgp
->psurfMask
= NULL
;
432 /* Create a color surface */
435 hbmp
= EngCreateBitmap(psoColor
->sizlBitmap
,
438 BMF_TOPDOWN
| BMF_NOZEROINIT
,
440 pgp
->psurfColor
= SURFACE_ShareLockSurface(hbmp
);
443 rcl
.bottom
= psoColor
->sizlBitmap
.cy
;
444 IntEngCopyBits(&pgp
->psurfColor
->SurfObj
,
454 pgp
->psurfColor
= NULL
;
459 ppdev
->ptlPointer
.x
= x
;
460 ppdev
->ptlPointer
.y
= y
;
462 IntShowMousePointer(ppdev
, pso
);
466 prcl
->left
= x
- pgp
->HotSpot
.x
;
467 prcl
->top
= y
- pgp
->HotSpot
.x
;
468 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
469 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
472 else if (prcl
!= NULL
)
474 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
477 return SPS_ACCEPT_NOEXCLUDE
;
499 pgp
= &ppdev
->Pointer
;
501 IntHideMousePointer(ppdev
, pso
);
503 ppdev
->ptlPointer
.x
= x
;
504 ppdev
->ptlPointer
.y
= y
;
508 IntShowMousePointer(ppdev
, pso
);
511 prcl
->left
= x
- pgp
->HotSpot
.x
;
512 prcl
->top
= y
- pgp
->HotSpot
.y
;
513 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
514 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
517 else if (prcl
!= NULL
)
519 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
530 PPDEVOBJ ppdev
= (PPDEVOBJ
)pso
->hdev
;
531 if(ppdev
->SafetyRemoveLevel
)
534 EngAcquireSemaphore(ppdev
->hsemDevLock
);
535 ppdev
->pfnMovePointer(pso
, x
, y
, prcl
);
536 EngReleaseSemaphore(ppdev
->hsemDevLock
);
540 IntEngSetPointerShape(
543 IN SURFOBJ
*psoColor
,
552 ULONG ulResult
= SPS_DECLINE
;
553 PFN_DrvSetPointerShape pfnSetPointerShape
;
554 PPDEVOBJ ppdev
= GDIDEV(pso
);
556 pfnSetPointerShape
= GDIDEVFUNCS(pso
).SetPointerShape
;
558 EngAcquireSemaphore(ppdev
->hsemDevLock
);
559 if (pfnSetPointerShape
)
561 ulResult
= pfnSetPointerShape(pso
,
573 /* Check if the driver accepted it */
574 if (ulResult
== SPS_ACCEPT_NOEXCLUDE
)
576 /* Set MovePointer to the driver function */
577 ppdev
->pfnMovePointer
= GDIDEVFUNCS(pso
).MovePointer
;
581 /* Set software pointer */
582 ulResult
= EngSetPointerShape(pso
,
592 /* Set MovePointer to the eng function */
593 ppdev
->pfnMovePointer
= EngMovePointer
;
596 EngReleaseSemaphore(ppdev
->hsemDevLock
);
613 PSURFACE psurf
, psurfMask
, psurfColor
;
618 pdc
= DC_LockDc(hdc
);
621 DPRINT1("Failed to lock the DC.\n");
625 ASSERT(pdc
->dctype
== DCTYPE_DIRECT
);
626 /* We're not sure DC surface is the good one */
627 psurf
= pdc
->ppdev
->pSurface
;
630 DPRINT1("DC has no surface.\n");
635 /* Lock the mask bitmap */
637 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
641 /* Check for color bitmap */
644 /* We have one, lock it */
645 psurfColor
= SURFACE_ShareLockSurface(hbmColor
);
649 /* Create an XLATEOBJ, no mono support */
650 EXLATEOBJ_vInitialize(&exlo
, psurfColor
->ppal
, psurf
->ppal
, 0, 0, 0);
656 /* Call the driver or eng function */
657 ulResult
= IntEngSetPointerShape(&psurf
->SurfObj
,
658 psurfMask
? &psurfMask
->SurfObj
: NULL
,
659 psurfColor
? &psurfColor
->SurfObj
: NULL
,
660 psurfColor
? &exlo
.xlo
: NULL
,
665 &pdc
->ppdev
->Pointer
.Exclude
,
671 EXLATEOBJ_vCleanup(&exlo
);
672 SURFACE_ShareUnlockSurface(psurfColor
);
676 SURFACE_ShareUnlockSurface(psurfMask
);
696 pdc
= DC_LockDc(hdc
);
699 DPRINT1("Failed to lock the DC.\n");
702 ASSERT(pdc
->dctype
== DCTYPE_DIRECT
);
704 /* Store the cursor exclude position in the PDEV */
705 prcl
= &pdc
->ppdev
->Pointer
.Exclude
;
707 /* Call Eng/Drv function */
708 IntEngMovePointer(&pdc
->ppdev
->pSurface
->SurfObj
, x
, y
, prcl
);