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 IntEngBitBlt(psoDest
,
166 &pgp
->psurfSave
->SurfObj
,
175 ROP3_TO_ROP4(SRCCOPY
));
180 IntShowMousePointer(PDEVOBJ
*ppdev
, SURFOBJ
*psoDest
)
184 RECTL rclSurf
, rclPointer
;
189 pgp
= &ppdev
->Pointer
;
198 /* Check if we have any mouse pointer */
199 if (!pgp
->psurfSave
) return;
201 /* Calculate pointer coordinates */
202 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
203 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
205 /* Calculate the rect on the surface */
206 rclSurf
.left
= max(pt
.x
, 0);
207 rclSurf
.top
= max(pt
.y
, 0);
208 rclSurf
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
209 rclSurf
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
211 /* Calculate the rect in the pointer bitmap */
212 rclPointer
.left
= rclSurf
.left
- pt
.x
;
213 rclPointer
.top
= rclSurf
.top
- pt
.y
;
214 rclPointer
.right
= min(pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
- pt
.x
);
215 rclPointer
.bottom
= min(pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
- pt
.y
);
217 /* Copy the pixels under the cursor to temporary surface. */
218 IntEngBitBlt(&pgp
->psurfSave
->SurfObj
,
228 ROP3_TO_ROP4(SRCCOPY
));
230 /* Blt the pointer on the screen. */
233 IntEngBitBlt(psoDest
,
234 &pgp
->psurfMask
->SurfObj
,
239 (POINTL
*)&rclPointer
,
243 ROP3_TO_ROP4(SRCAND
));
245 IntEngBitBlt(psoDest
,
246 &pgp
->psurfColor
->SurfObj
,
251 (POINTL
*)&rclPointer
,
255 ROP3_TO_ROP4(SRCINVERT
));
259 IntEngBitBlt(psoDest
,
260 &pgp
->psurfMask
->SurfObj
,
265 (POINTL
*)&rclPointer
,
269 ROP3_TO_ROP4(SRCAND
));
271 rclPointer
.top
+= pgp
->Size
.cy
;
273 IntEngBitBlt(psoDest
,
274 &pgp
->psurfMask
->SurfObj
,
279 (POINTL
*)&rclPointer
,
283 ROP3_TO_ROP4(SRCINVERT
));
294 IN SURFOBJ
*psoColor
,
306 HBITMAP hbmSave
= NULL
, hbmColor
= NULL
, hbmMask
= NULL
;
307 PSURFACE psurfSave
= NULL
, psurfColor
= NULL
, psurfMask
= NULL
;
309 SIZEL sizel
= {0, 0};
314 pgp
= &ppdev
->Pointer
;
316 /* Do we have any bitmap at all? */
317 if (psoColor
|| psoMask
)
319 /* Get the size of the new pointer */
322 sizel
.cx
= psoColor
->sizlBitmap
.cx
;
323 sizel
.cy
= psoColor
->sizlBitmap
.cy
;
327 sizel
.cx
= psoMask
->sizlBitmap
.cx
;
328 sizel
.cy
= psoMask
->sizlBitmap
.cy
/ 2;
333 rectl
.right
= sizel
.cx
;
334 rectl
.bottom
= sizel
.cy
;
336 /* Calculate lDelta for our surfaces. */
337 lDelta
= DIB_GetDIBWidthBytes(sizel
.cx
,
338 BitsPerFormat(pso
->iBitmapFormat
));
340 /* Create a bitmap for saving the pixels under the cursor. */
341 hbmSave
= EngCreateBitmap(sizel
,
344 BMF_TOPDOWN
| BMF_NOZEROINIT
,
346 psurfSave
= SURFACE_ShareLockSurface(hbmSave
);
347 if (!psurfSave
) goto failure
;
352 /* Color bitmap must have the same format as the dest surface */
353 if (psoColor
->iBitmapFormat
!= pso
->iBitmapFormat
) goto failure
;
355 /* Create a bitmap to copy the color bitmap to */
356 hbmColor
= EngCreateBitmap(psoColor
->sizlBitmap
,
359 BMF_TOPDOWN
| BMF_NOZEROINIT
,
361 psurfColor
= SURFACE_ShareLockSurface(hbmColor
);
362 if (!psurfColor
) goto failure
;
364 /* Now copy the given bitmap */
365 rectl
.bottom
= psoColor
->sizlBitmap
.cy
;
366 IntEngCopyBits(&psurfColor
->SurfObj
,
374 /* Create a mask surface */
380 /* Create a bitmap for the mask */
381 hbmMask
= EngCreateBitmap(psoMask
->sizlBitmap
,
384 BMF_TOPDOWN
| BMF_NOZEROINIT
,
386 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
387 if (!psurfMask
) goto failure
;
389 /* Initialize an EXLATEOBJ */
390 ppal
= PALETTE_LockPalette(ppdev
->devinfo
.hpalDefault
);
391 EXLATEOBJ_vInitialize(&exlo
,
398 /* Copy the mask bitmap */
399 rectl
.bottom
= psoMask
->sizlBitmap
.cy
;
400 IntEngCopyBits(&psurfMask
->SurfObj
,
408 EXLATEOBJ_vCleanup(&exlo
);
409 if (ppal
) PALETTE_UnlockPalette(ppal
);
412 /* Hide mouse pointer */
413 IntHideMousePointer(ppdev
, pso
);
415 /* Free old color bitmap */
418 EngDeleteSurface(pgp
->psurfColor
->BaseObject
.hHmgr
);
419 SURFACE_ShareUnlockSurface(pgp
->psurfColor
);
420 pgp
->psurfColor
= NULL
;
423 /* Free old mask bitmap */
426 EngDeleteSurface(pgp
->psurfMask
->BaseObject
.hHmgr
);
427 SURFACE_ShareUnlockSurface(pgp
->psurfMask
);
428 pgp
->psurfMask
= NULL
;
431 /* Free old save bitmap */
434 EngDeleteSurface(pgp
->psurfSave
->BaseObject
.hHmgr
);
435 SURFACE_ShareUnlockSurface(pgp
->psurfSave
);
436 pgp
->psurfSave
= NULL
;
439 /* See if we are being asked to hide the pointer. */
440 if (psoMask
== NULL
&& psoColor
== NULL
)
443 return SPS_ACCEPT_NOEXCLUDE
;
446 /* Now set the new cursor */
447 pgp
->psurfColor
= psurfColor
;
448 pgp
->psurfMask
= psurfMask
;
449 pgp
->psurfSave
= psurfSave
;
450 pgp
->HotSpot
.x
= xHot
;
451 pgp
->HotSpot
.y
= yHot
;
456 ppdev
->ptlPointer
.x
= x
;
457 ppdev
->ptlPointer
.y
= y
;
459 IntShowMousePointer(ppdev
, pso
);
463 prcl
->left
= x
- pgp
->HotSpot
.x
;
464 prcl
->top
= y
- pgp
->HotSpot
.x
;
465 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
466 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
469 else if (prcl
!= NULL
)
471 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
474 return SPS_ACCEPT_NOEXCLUDE
;
477 /* Cleanup surfaces */
478 if (hbmMask
) EngDeleteSurface(hbmMask
);
479 if (psurfMask
) SURFACE_ShareUnlockSurface(psurfMask
);
480 if (hbmColor
) EngDeleteSurface(hbmColor
);
481 if (psurfColor
) SURFACE_ShareUnlockSurface(psurfColor
);
482 if (hbmSave
) EngDeleteSurface(hbmSave
);
483 if (psurfSave
) SURFACE_ShareUnlockSurface(psurfSave
);
507 pgp
= &ppdev
->Pointer
;
509 IntHideMousePointer(ppdev
, pso
);
511 ppdev
->ptlPointer
.x
= x
;
512 ppdev
->ptlPointer
.y
= y
;
516 IntShowMousePointer(ppdev
, pso
);
519 prcl
->left
= x
- pgp
->HotSpot
.x
;
520 prcl
->top
= y
- pgp
->HotSpot
.y
;
521 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
522 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
525 else if (prcl
!= NULL
)
527 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
532 IntEngSetPointerShape(
535 IN SURFOBJ
*psoColor
,
544 ULONG ulResult
= SPS_DECLINE
;
545 PFN_DrvSetPointerShape pfnSetPointerShape
;
546 PPDEVOBJ ppdev
= GDIDEV(pso
);
548 pfnSetPointerShape
= GDIDEVFUNCS(pso
).SetPointerShape
;
550 if (pfnSetPointerShape
)
552 ulResult
= pfnSetPointerShape(pso
,
564 /* Check if the driver accepted it */
565 if (ulResult
== SPS_ACCEPT_NOEXCLUDE
)
567 /* Set MovePointer to the driver function */
568 ppdev
->pfnMovePointer
= GDIDEVFUNCS(pso
).MovePointer
;
572 /* Set software pointer */
573 ulResult
= EngSetPointerShape(pso
,
583 /* Set MovePointer to the eng function */
584 ppdev
->pfnMovePointer
= EngMovePointer
;
602 PSURFACE psurf
, psurfMask
, psurfColor
;
607 pdc
= DC_LockDc(hdc
);
610 DPRINT1("Failed to lock the DC.\n");
614 ASSERT(pdc
->dctype
== DCTYPE_DIRECT
);
615 EngAcquireSemaphore(pdc
->ppdev
->hsemDevLock
);
616 /* We're not sure DC surface is the good one */
617 psurf
= pdc
->ppdev
->pSurface
;
620 DPRINT1("DC has no surface.\n");
621 EngReleaseSemaphore(pdc
->ppdev
->hsemDevLock
);
626 /* Lock the mask bitmap */
628 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
632 /* Check for color bitmap */
635 /* We have one, lock it */
636 psurfColor
= SURFACE_ShareLockSurface(hbmColor
);
640 /* Create an XLATEOBJ, no mono support */
641 EXLATEOBJ_vInitialize(&exlo
, psurfColor
->ppal
, psurf
->ppal
, 0, 0, 0);
647 /* Call the driver or eng function */
648 ulResult
= IntEngSetPointerShape(&psurf
->SurfObj
,
649 psurfMask
? &psurfMask
->SurfObj
: NULL
,
650 psurfColor
? &psurfColor
->SurfObj
: NULL
,
651 psurfColor
? &exlo
.xlo
: NULL
,
656 &pdc
->ppdev
->Pointer
.Exclude
,
662 EXLATEOBJ_vCleanup(&exlo
);
663 SURFACE_ShareUnlockSurface(psurfColor
);
667 SURFACE_ShareUnlockSurface(psurfMask
);
669 EngReleaseSemaphore(pdc
->ppdev
->hsemDevLock
);
689 pdc
= DC_LockDc(hdc
);
692 DPRINT1("Failed to lock the DC.\n");
695 ASSERT(pdc
->dctype
== DCTYPE_DIRECT
);
697 /* Acquire PDEV lock */
698 EngAcquireSemaphore(pdc
->ppdev
->hsemDevLock
);
700 /* Check if we need to move it */
701 if(pdc
->ppdev
->SafetyRemoveLevel
== 0)
703 /* Store the cursor exclude position in the PDEV */
704 prcl
= &pdc
->ppdev
->Pointer
.Exclude
;
706 /* Call Eng/Drv function */
707 pdc
->ppdev
->pfnMovePointer(&pdc
->ppdev
->pSurface
->SurfObj
, x
, y
, prcl
);
710 /* Release PDEV lock */
711 EngReleaseSemaphore(pdc
->ppdev
->hsemDevLock
);