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 /* Calculate pointer coordinates */
213 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
214 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
216 /* Calculate the rect on the surface */
217 rclSurf
.left
= max(pt
.x
, 0);
218 rclSurf
.top
= max(pt
.y
, 0);
219 rclSurf
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
220 rclSurf
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
222 /* Calculate the rect in the pointer bitmap */
223 rclPointer
.left
= rclSurf
.left
- pt
.x
;
224 rclPointer
.top
= rclSurf
.top
- pt
.y
;
225 rclPointer
.right
= min(pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
- pt
.x
);
226 rclPointer
.bottom
= min(pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
- pt
.y
);
228 /* Copy the pixels under the cursor to temporary surface. */
229 IntEngBitBltEx(&pgp
->psurfSave
->SurfObj
,
239 ROP3_TO_ROP4(SRCCOPY
),
242 /* Blt the pointer on the screen. */
245 IntEngBitBltEx(psoDest
,
246 &pgp
->psurfMask
->SurfObj
,
251 (POINTL
*)&rclPointer
,
255 ROP3_TO_ROP4(SRCAND
),
258 IntEngBitBltEx(psoDest
,
259 &pgp
->psurfColor
->SurfObj
,
264 (POINTL
*)&rclPointer
,
268 ROP3_TO_ROP4(SRCINVERT
),
273 IntEngBitBltEx(psoDest
,
274 &pgp
->psurfMask
->SurfObj
,
279 (POINTL
*)&rclPointer
,
283 ROP3_TO_ROP4(SRCAND
),
286 rclPointer
.top
+= pgp
->Size
.cy
;
288 IntEngBitBltEx(psoDest
,
289 &pgp
->psurfMask
->SurfObj
,
294 (POINTL
*)&rclPointer
,
298 ROP3_TO_ROP4(SRCINVERT
),
310 IN SURFOBJ
*psoColor
,
328 pgp
= &ppdev
->Pointer
;
332 pgp
->Size
.cx
= psoColor
->sizlBitmap
.cx
;
333 pgp
->Size
.cy
= psoColor
->sizlBitmap
.cy
;
336 // CHECKME: Is this really required? if we have a color surface,
337 // we only need the AND part of the mask.
338 /* Check if the sizes match as they should */
339 if (psoMask
->sizlBitmap
.cx
!= psoColor
->sizlBitmap
.cx
||
340 psoMask
->sizlBitmap
.cy
!= psoColor
->sizlBitmap
.cy
* 2)
342 DPRINT("Sizes of mask (%ld,%ld) and color (%ld,%ld) don't match\n",
343 psoMask
->sizlBitmap
.cx
, psoMask
->sizlBitmap
.cy
,
344 psoColor
->sizlBitmap
.cx
, psoColor
->sizlBitmap
.cy
);
351 pgp
->Size
.cx
= psoMask
->sizlBitmap
.cx
;
352 pgp
->Size
.cy
= psoMask
->sizlBitmap
.cy
/ 2;
355 IntHideMousePointer(ppdev
, pso
);
359 EngDeleteSurface(pgp
->psurfColor
->BaseObject
.hHmgr
);
360 SURFACE_ShareUnlockSurface(pgp
->psurfColor
);
361 pgp
->psurfColor
= NULL
;
366 EngDeleteSurface(pgp
->psurfMask
->BaseObject
.hHmgr
);
367 SURFACE_ShareUnlockSurface(pgp
->psurfMask
);
368 pgp
->psurfMask
= NULL
;
371 if (pgp
->psurfSave
!= NULL
)
373 EngDeleteSurface(pgp
->psurfSave
->BaseObject
.hHmgr
);
374 SURFACE_ShareUnlockSurface(pgp
->psurfSave
);
375 pgp
->psurfSave
= NULL
;
378 /* See if we are being asked to hide the pointer. */
379 if (psoMask
== NULL
&& psoColor
== NULL
)
381 return SPS_ACCEPT_NOEXCLUDE
;
384 pgp
->HotSpot
.x
= xHot
;
385 pgp
->HotSpot
.y
= yHot
;
387 /* Calculate lDelta for our surfaces. */
388 lDelta
= DIB_GetDIBWidthBytes(pgp
->Size
.cx
,
389 BitsPerFormat(pso
->iBitmapFormat
));
393 rcl
.right
= pgp
->Size
.cx
;
394 rcl
.bottom
= pgp
->Size
.cy
;
396 /* Create surface for saving the pixels under the cursor. */
397 hbmp
= EngCreateBitmap(pgp
->Size
,
400 BMF_TOPDOWN
| BMF_NOZEROINIT
,
402 pgp
->psurfSave
= SURFACE_ShareLockSurface(hbmp
);
404 /* Create a mask surface */
410 hbmp
= EngCreateBitmap(psoMask
->sizlBitmap
,
413 BMF_TOPDOWN
| BMF_NOZEROINIT
,
415 pgp
->psurfMask
= SURFACE_ShareLockSurface(hbmp
);
419 ppal
= PALETTE_LockPalette(ppdev
->devinfo
.hpalDefault
);
420 EXLATEOBJ_vInitialize(&exlo
,
427 rcl
.bottom
= psoMask
->sizlBitmap
.cy
;
428 IntEngCopyBits(&pgp
->psurfMask
->SurfObj
,
435 EXLATEOBJ_vCleanup(&exlo
);
437 PALETTE_UnlockPalette(ppal
);
442 pgp
->psurfMask
= NULL
;
445 /* Create a color surface */
448 hbmp
= EngCreateBitmap(psoColor
->sizlBitmap
,
451 BMF_TOPDOWN
| BMF_NOZEROINIT
,
453 pgp
->psurfColor
= SURFACE_ShareLockSurface(hbmp
);
456 rcl
.bottom
= psoColor
->sizlBitmap
.cy
;
457 IntEngCopyBits(&pgp
->psurfColor
->SurfObj
,
467 pgp
->psurfColor
= NULL
;
472 ppdev
->ptlPointer
.x
= x
;
473 ppdev
->ptlPointer
.y
= y
;
475 IntShowMousePointer(ppdev
, pso
);
479 prcl
->left
= x
- pgp
->HotSpot
.x
;
480 prcl
->top
= y
- pgp
->HotSpot
.x
;
481 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
482 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
485 else if (prcl
!= NULL
)
487 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
490 return SPS_ACCEPT_NOEXCLUDE
;
512 pgp
= &ppdev
->Pointer
;
514 IntHideMousePointer(ppdev
, pso
);
516 ppdev
->ptlPointer
.x
= x
;
517 ppdev
->ptlPointer
.y
= y
;
521 IntShowMousePointer(ppdev
, pso
);
524 prcl
->left
= x
- pgp
->HotSpot
.x
;
525 prcl
->top
= y
- pgp
->HotSpot
.y
;
526 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
527 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
530 else if (prcl
!= NULL
)
532 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
543 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
544 PPDEVOBJ ppdev
= (PPDEVOBJ
)pso
->hdev
;
546 SURFACE_LockBitmapBits(psurf
);
547 ppdev
->pfnMovePointer(pso
, x
, y
, prcl
);
548 SURFACE_UnlockBitmapBits(psurf
);
552 IntEngSetPointerShape(
555 IN SURFOBJ
*psoColor
,
564 ULONG ulResult
= SPS_DECLINE
;
565 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
566 PFN_DrvSetPointerShape pfnSetPointerShape
;
567 PPDEVOBJ ppdev
= GDIDEV(pso
);
569 pfnSetPointerShape
= GDIDEVFUNCS(pso
).SetPointerShape
;
571 SURFACE_LockBitmapBits(psurf
);
572 if (pfnSetPointerShape
)
574 ulResult
= pfnSetPointerShape(pso
,
586 /* Check if the driver accepted it */
587 if (ulResult
== SPS_ACCEPT_NOEXCLUDE
)
589 /* Set MovePointer to the driver function */
590 ppdev
->pfnMovePointer
= GDIDEVFUNCS(pso
).MovePointer
;
594 /* Set software pointer */
595 ulResult
= EngSetPointerShape(pso
,
605 /* Set MovePointer to the eng function */
606 ppdev
->pfnMovePointer
= EngMovePointer
;
609 SURFACE_UnlockBitmapBits(psurf
);
626 PSURFACE psurf
, psurfMask
, psurfColor
;
631 pdc
= DC_LockDc(hdc
);
634 DPRINT1("Failed to lock the DC.\n");
638 psurf
= pdc
->dclevel
.pSurface
;
641 DPRINT1("DC has no surface.\n");
646 /* Lock the mask bitmap */
648 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
652 /* Check for color bitmap */
655 /* We have one, lock it */
656 psurfColor
= SURFACE_ShareLockSurface(hbmColor
);
660 /* Create an XLATEOBJ, no mono support */
661 EXLATEOBJ_vInitialize(&exlo
, psurfColor
->ppal
, psurf
->ppal
, 0, 0, 0);
667 /* Call the driver or eng function */
668 ulResult
= IntEngSetPointerShape(&psurf
->SurfObj
,
669 psurfMask
? &psurfMask
->SurfObj
: NULL
,
670 psurfColor
? &psurfColor
->SurfObj
: NULL
,
671 psurfColor
? &exlo
.xlo
: NULL
,
676 &pdc
->ppdev
->Pointer
.Exclude
,
682 EXLATEOBJ_vCleanup(&exlo
);
683 SURFACE_ShareUnlockSurface(psurfColor
);
687 SURFACE_ShareUnlockSurface(psurfMask
);
707 pdc
= DC_LockDc(hdc
);
710 DPRINT1("Failed to lock the DC.\n");
714 /* Store the cursor exclude position in the PDEV */
715 prcl
= &pdc
->ppdev
->Pointer
.Exclude
;
717 /* Call Eng/Drv function */
718 IntEngMovePointer(&pdc
->dclevel
.pSurface
->SurfObj
, x
, y
, prcl
);