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(
58 pgp
= &ppdev
->Pointer
;
60 if (pgp
->Exclude
.right
== -1)
65 ppdev
->SafetyRemoveCount
++;
67 if (ppdev
->SafetyRemoveLevel
!= 0)
72 if (HazardX1
> HazardX2
)
78 if (HazardY1
> HazardY2
)
85 if (pgp
->Exclude
.right
>= HazardX1
86 && pgp
->Exclude
.left
<= HazardX2
87 && pgp
->Exclude
.bottom
>= HazardY1
88 && pgp
->Exclude
.top
<= HazardY2
)
90 ppdev
->SafetyRemoveLevel
= ppdev
->SafetyRemoveCount
;
91 ppdev
->pfnMovePointer(pso
, -1, -1, NULL
);
98 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
101 MouseSafetyOnDrawEnd(
109 ppdev
= (PDEVOBJ
*)pso
->hdev
;
116 pgp
= &ppdev
->Pointer
;
118 if (pgp
->Exclude
.right
== -1)
123 if (--ppdev
->SafetyRemoveCount
>= ppdev
->SafetyRemoveLevel
)
128 ppdev
->pfnMovePointer(pso
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
, &pgp
->Exclude
);
130 ppdev
->SafetyRemoveLevel
= 0;
135 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
151 pgp
= &ppdev
->Pointer
;
158 pgp
->Enabled
= FALSE
;
162 DPRINT1("No SaveSurface!\n");
166 /* Calculate cursor coordinates */
167 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
168 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
170 rclDest
.left
= max(pt
.x
, 0);
171 rclDest
.top
= max(pt
.y
, 0);
172 rclDest
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
173 rclDest
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
175 ptlSave
.x
= rclDest
.left
- pt
.x
;
176 ptlSave
.y
= rclDest
.top
- pt
.y
;
178 IntEngBitBltEx(psoDest
,
179 &pgp
->psurfSave
->SurfObj
,
188 ROP3_TO_ROP4(SRCCOPY
),
194 IntShowMousePointer(PDEVOBJ
*ppdev
, SURFOBJ
*psoDest
)
198 RECTL rclSurf
, rclPointer
;
203 pgp
= &ppdev
->Pointer
;
212 /* Check if we have any mouse pointer */
213 if (!pgp
->psurfSave
) return;
215 /* Calculate pointer coordinates */
216 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
217 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
219 /* Calculate the rect on the surface */
220 rclSurf
.left
= max(pt
.x
, 0);
221 rclSurf
.top
= max(pt
.y
, 0);
222 rclSurf
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
223 rclSurf
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
225 /* Calculate the rect in the pointer bitmap */
226 rclPointer
.left
= rclSurf
.left
- pt
.x
;
227 rclPointer
.top
= rclSurf
.top
- pt
.y
;
228 rclPointer
.right
= min(pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
- pt
.x
);
229 rclPointer
.bottom
= min(pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
- pt
.y
);
231 /* Copy the pixels under the cursor to temporary surface. */
232 IntEngBitBltEx(&pgp
->psurfSave
->SurfObj
,
242 ROP3_TO_ROP4(SRCCOPY
),
245 /* Blt the pointer on the screen. */
248 IntEngBitBltEx(psoDest
,
249 &pgp
->psurfMask
->SurfObj
,
254 (POINTL
*)&rclPointer
,
258 ROP3_TO_ROP4(SRCAND
),
261 IntEngBitBltEx(psoDest
,
262 &pgp
->psurfColor
->SurfObj
,
267 (POINTL
*)&rclPointer
,
271 ROP3_TO_ROP4(SRCINVERT
),
276 IntEngBitBltEx(psoDest
,
277 &pgp
->psurfMask
->SurfObj
,
282 (POINTL
*)&rclPointer
,
286 ROP3_TO_ROP4(SRCAND
),
289 rclPointer
.top
+= pgp
->Size
.cy
;
291 IntEngBitBltEx(psoDest
,
292 &pgp
->psurfMask
->SurfObj
,
297 (POINTL
*)&rclPointer
,
301 ROP3_TO_ROP4(SRCINVERT
),
313 IN SURFOBJ
*psoColor
,
325 HBITMAP hbmSave
= NULL
, hbmColor
= NULL
, hbmMask
= NULL
;
326 PSURFACE psurfSave
= NULL
, psurfColor
= NULL
, psurfMask
= NULL
;
328 SIZEL sizel
= {0, 0};
333 pgp
= &ppdev
->Pointer
;
335 /* Do we have any bitmap at all? */
336 if (psoColor
|| psoMask
)
338 /* Get the size of the new pointer */
341 sizel
.cx
= psoColor
->sizlBitmap
.cx
;
342 sizel
.cy
= psoColor
->sizlBitmap
.cy
;
346 sizel
.cx
= psoMask
->sizlBitmap
.cx
;
347 sizel
.cy
= psoMask
->sizlBitmap
.cy
/ 2;
352 rectl
.right
= sizel
.cx
;
353 rectl
.bottom
= sizel
.cy
;
355 /* Calculate lDelta for our surfaces. */
356 lDelta
= DIB_GetDIBWidthBytes(sizel
.cx
,
357 BitsPerFormat(pso
->iBitmapFormat
));
359 /* Create a bitmap for saving the pixels under the cursor. */
360 hbmSave
= EngCreateBitmap(sizel
,
363 BMF_TOPDOWN
| BMF_NOZEROINIT
,
365 psurfSave
= SURFACE_ShareLockSurface(hbmSave
);
366 if (!psurfSave
) goto failure
;
371 /* Color bitmap must have the same format as the dest surface */
372 if (psoColor
->iBitmapFormat
!= pso
->iBitmapFormat
) goto failure
;
374 /* Create a bitmap to copy the color bitmap to */
375 hbmColor
= EngCreateBitmap(psoColor
->sizlBitmap
,
378 BMF_TOPDOWN
| BMF_NOZEROINIT
,
380 psurfColor
= SURFACE_ShareLockSurface(hbmColor
);
381 if (!psurfColor
) goto failure
;
383 /* Now copy the given bitmap */
384 rectl
.bottom
= psoColor
->sizlBitmap
.cy
;
385 IntEngCopyBits(&psurfColor
->SurfObj
,
393 /* Create a mask surface */
399 /* Create a bitmap for the mask */
400 hbmMask
= EngCreateBitmap(psoMask
->sizlBitmap
,
403 BMF_TOPDOWN
| BMF_NOZEROINIT
,
405 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
406 if (!psurfMask
) goto failure
;
408 /* Initialize an EXLATEOBJ */
409 ppal
= PALETTE_LockPalette(ppdev
->devinfo
.hpalDefault
);
410 EXLATEOBJ_vInitialize(&exlo
,
417 /* Copy the mask bitmap */
418 rectl
.bottom
= psoMask
->sizlBitmap
.cy
;
419 IntEngCopyBits(&psurfMask
->SurfObj
,
427 EXLATEOBJ_vCleanup(&exlo
);
428 if (ppal
) PALETTE_UnlockPalette(ppal
);
431 /* Hide mouse pointer */
432 IntHideMousePointer(ppdev
, pso
);
434 /* Free old color bitmap */
437 EngDeleteSurface(pgp
->psurfColor
->BaseObject
.hHmgr
);
438 SURFACE_ShareUnlockSurface(pgp
->psurfColor
);
439 pgp
->psurfColor
= NULL
;
442 /* Free old mask bitmap */
445 EngDeleteSurface(pgp
->psurfMask
->BaseObject
.hHmgr
);
446 SURFACE_ShareUnlockSurface(pgp
->psurfMask
);
447 pgp
->psurfMask
= NULL
;
450 /* Free old save bitmap */
453 EngDeleteSurface(pgp
->psurfSave
->BaseObject
.hHmgr
);
454 SURFACE_ShareUnlockSurface(pgp
->psurfSave
);
455 pgp
->psurfSave
= NULL
;
458 /* See if we are being asked to hide the pointer. */
459 if (psoMask
== NULL
&& psoColor
== NULL
)
462 return SPS_ACCEPT_NOEXCLUDE
;
465 /* Now set the new cursor */
466 pgp
->psurfColor
= psurfColor
;
467 pgp
->psurfMask
= psurfMask
;
468 pgp
->psurfSave
= psurfSave
;
469 pgp
->HotSpot
.x
= xHot
;
470 pgp
->HotSpot
.y
= yHot
;
475 ppdev
->ptlPointer
.x
= x
;
476 ppdev
->ptlPointer
.y
= y
;
478 IntShowMousePointer(ppdev
, pso
);
482 prcl
->left
= x
- pgp
->HotSpot
.x
;
483 prcl
->top
= y
- pgp
->HotSpot
.x
;
484 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
485 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
488 else if (prcl
!= NULL
)
490 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
493 return SPS_ACCEPT_NOEXCLUDE
;
496 /* Cleanup surfaces */
497 if (hbmMask
) EngDeleteSurface(hbmMask
);
498 if (psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
499 if (hbmColor
) EngDeleteSurface(hbmColor
);
500 if (psurfColor
) SURFACE_ShareUnlockSurface(psurfColor
);
501 if (hbmSave
) EngDeleteSurface(hbmSave
);
502 if (psurfSave
) SURFACE_ShareUnlockSurface(psurfSave
);
526 pgp
= &ppdev
->Pointer
;
528 IntHideMousePointer(ppdev
, pso
);
530 ppdev
->ptlPointer
.x
= x
;
531 ppdev
->ptlPointer
.y
= y
;
535 IntShowMousePointer(ppdev
, pso
);
538 prcl
->left
= x
- pgp
->HotSpot
.x
;
539 prcl
->top
= y
- pgp
->HotSpot
.y
;
540 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
541 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
544 else if (prcl
!= NULL
)
546 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
557 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
558 PPDEVOBJ ppdev
= (PPDEVOBJ
)pso
->hdev
;
560 SURFACE_LockBitmapBits(psurf
);
561 ppdev
->pfnMovePointer(pso
, x
, y
, prcl
);
562 SURFACE_UnlockBitmapBits(psurf
);
566 IntEngSetPointerShape(
569 IN SURFOBJ
*psoColor
,
578 ULONG ulResult
= SPS_DECLINE
;
579 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
580 PFN_DrvSetPointerShape pfnSetPointerShape
;
581 PPDEVOBJ ppdev
= GDIDEV(pso
);
583 pfnSetPointerShape
= GDIDEVFUNCS(pso
).SetPointerShape
;
585 SURFACE_LockBitmapBits(psurf
);
586 if (pfnSetPointerShape
)
588 ulResult
= pfnSetPointerShape(pso
,
600 /* Check if the driver accepted it */
601 if (ulResult
== SPS_ACCEPT_NOEXCLUDE
)
603 /* Set MovePointer to the driver function */
604 ppdev
->pfnMovePointer
= GDIDEVFUNCS(pso
).MovePointer
;
608 /* Set software pointer */
609 ulResult
= EngSetPointerShape(pso
,
619 /* Set MovePointer to the eng function */
620 ppdev
->pfnMovePointer
= EngMovePointer
;
623 SURFACE_UnlockBitmapBits(psurf
);
640 PSURFACE psurf
, psurfMask
, psurfColor
;
645 pdc
= DC_LockDc(hdc
);
648 DPRINT1("Failed to lock the DC.\n");
652 psurf
= pdc
->dclevel
.pSurface
;
655 DPRINT1("DC has no surface.\n");
660 /* Lock the mask bitmap */
662 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
666 /* Check for color bitmap */
669 /* We have one, lock it */
670 psurfColor
= SURFACE_ShareLockSurface(hbmColor
);
674 /* Create an XLATEOBJ, no mono support */
675 EXLATEOBJ_vInitialize(&exlo
, psurfColor
->ppal
, psurf
->ppal
, 0, 0, 0);
681 /* Call the driver or eng function */
682 ulResult
= IntEngSetPointerShape(&psurf
->SurfObj
,
683 psurfMask
? &psurfMask
->SurfObj
: NULL
,
684 psurfColor
? &psurfColor
->SurfObj
: NULL
,
685 psurfColor
? &exlo
.xlo
: NULL
,
690 &pdc
->ppdev
->Pointer
.Exclude
,
696 EXLATEOBJ_vCleanup(&exlo
);
697 SURFACE_ShareUnlockSurface(psurfColor
);
701 SURFACE_ShareUnlockSurface(psurfMask
);
721 pdc
= DC_LockDc(hdc
);
724 DPRINT1("Failed to lock the DC.\n");
728 /* Store the cursor exclude position in the PDEV */
729 prcl
= &pdc
->ppdev
->Pointer
.Exclude
;
731 /* Call Eng/Drv function */
732 IntEngMovePointer(&pdc
->dclevel
.pSurface
->SurfObj
, x
, y
, prcl
);