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
;
160 /* The mouse is hide from ShowCours and it is frist ?? */
161 if (pgp
->ShowPointer
< 0)
168 DPRINT1("No SaveSurface!\n");
172 /* Calculate cursor coordinates */
173 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
174 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
176 rclDest
.left
= max(pt
.x
, 0);
177 rclDest
.top
= max(pt
.y
, 0);
178 rclDest
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
179 rclDest
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
181 ptlSave
.x
= rclDest
.left
- pt
.x
;
182 ptlSave
.y
= rclDest
.top
- pt
.y
;
184 IntEngBitBltEx(psoDest
,
185 &pgp
->psurfSave
->SurfObj
,
194 ROP3_TO_ROP4(SRCCOPY
),
200 IntShowMousePointer(PDEVOBJ
*ppdev
, SURFOBJ
*psoDest
)
204 RECTL rclSurf
, rclPointer
;
209 pgp
= &ppdev
->Pointer
;
218 /* Do not blt the pointer, if it is hidden */
219 if (pgp
->ShowPointer
< 0)
224 /* Calculate pointer coordinates */
225 pt
.x
= ppdev
->ptlPointer
.x
- pgp
->HotSpot
.x
;
226 pt
.y
= ppdev
->ptlPointer
.y
- pgp
->HotSpot
.y
;
228 /* Calculate the rect on the surface */
229 rclSurf
.left
= max(pt
.x
, 0);
230 rclSurf
.top
= max(pt
.y
, 0);
231 rclSurf
.right
= min(pt
.x
+ pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
);
232 rclSurf
.bottom
= min(pt
.y
+ pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
);
234 /* Calculate the rect in the pointer bitmap */
235 rclPointer
.left
= rclSurf
.left
- pt
.x
;
236 rclPointer
.top
= rclSurf
.top
- pt
.y
;
237 rclPointer
.right
= min(pgp
->Size
.cx
, psoDest
->sizlBitmap
.cx
- pt
.x
);
238 rclPointer
.bottom
= min(pgp
->Size
.cy
, psoDest
->sizlBitmap
.cy
- pt
.y
);
240 /* Copy the pixels under the cursor to temporary surface. */
241 IntEngBitBltEx(&pgp
->psurfSave
->SurfObj
,
251 ROP3_TO_ROP4(SRCCOPY
),
254 /* Blt the pointer on the screen. */
257 IntEngBitBltEx(psoDest
,
258 &pgp
->psurfMask
->SurfObj
,
263 (POINTL
*)&rclPointer
,
267 ROP3_TO_ROP4(SRCAND
),
270 IntEngBitBltEx(psoDest
,
271 &pgp
->psurfColor
->SurfObj
,
276 (POINTL
*)&rclPointer
,
280 ROP3_TO_ROP4(SRCINVERT
),
285 IntEngBitBltEx(psoDest
,
286 &pgp
->psurfMask
->SurfObj
,
291 (POINTL
*)&rclPointer
,
295 ROP3_TO_ROP4(SRCAND
),
298 rclPointer
.top
+= pgp
->Size
.cy
;
300 IntEngBitBltEx(psoDest
,
301 &pgp
->psurfMask
->SurfObj
,
306 (POINTL
*)&rclPointer
,
310 ROP3_TO_ROP4(SRCINVERT
),
322 IN SURFOBJ
*psoColor
,
340 pgp
= &ppdev
->Pointer
;
344 pgp
->Size
.cx
= psoColor
->sizlBitmap
.cx
;
345 pgp
->Size
.cy
= psoColor
->sizlBitmap
.cy
;
348 // CHECKME: Is this really required? if we have a color surface,
349 // we only need the AND part of the mask.
350 /* Check if the sizes match as they should */
351 if (psoMask
->sizlBitmap
.cx
!= psoColor
->sizlBitmap
.cx
||
352 psoMask
->sizlBitmap
.cy
!= psoColor
->sizlBitmap
.cy
* 2)
354 DPRINT("Sizes of mask (%ld,%ld) and color (%ld,%ld) don't match\n",
355 psoMask
->sizlBitmap
.cx
, psoMask
->sizlBitmap
.cy
,
356 psoColor
->sizlBitmap
.cx
, psoColor
->sizlBitmap
.cy
);
363 pgp
->Size
.cx
= psoMask
->sizlBitmap
.cx
;
364 pgp
->Size
.cy
= psoMask
->sizlBitmap
.cy
/ 2;
367 IntHideMousePointer(ppdev
, pso
);
371 EngDeleteSurface(pgp
->psurfColor
->BaseObject
.hHmgr
);
372 SURFACE_ShareUnlockSurface(pgp
->psurfColor
);
373 pgp
->psurfColor
= NULL
;
378 EngDeleteSurface(pgp
->psurfMask
->BaseObject
.hHmgr
);
379 SURFACE_ShareUnlockSurface(pgp
->psurfMask
);
380 pgp
->psurfMask
= NULL
;
383 if (pgp
->psurfSave
!= NULL
)
385 EngDeleteSurface(pgp
->psurfSave
->BaseObject
.hHmgr
);
386 SURFACE_ShareUnlockSurface(pgp
->psurfSave
);
387 pgp
->psurfSave
= NULL
;
390 /* See if we are being asked to hide the pointer. */
391 if (psoMask
== NULL
&& psoColor
== NULL
)
393 return SPS_ACCEPT_NOEXCLUDE
;
396 pgp
->HotSpot
.x
= xHot
;
397 pgp
->HotSpot
.y
= yHot
;
399 /* Calculate lDelta for our surfaces. */
400 lDelta
= DIB_GetDIBWidthBytes(pgp
->Size
.cx
,
401 BitsPerFormat(pso
->iBitmapFormat
));
405 rcl
.right
= pgp
->Size
.cx
;
406 rcl
.bottom
= pgp
->Size
.cy
;
408 /* Create surface for saving the pixels under the cursor. */
409 hbmp
= EngCreateBitmap(pgp
->Size
,
412 BMF_TOPDOWN
| BMF_NOZEROINIT
,
414 pgp
->psurfSave
= SURFACE_ShareLockSurface(hbmp
);
416 /* Create a mask surface */
422 hbmp
= EngCreateBitmap(psoMask
->sizlBitmap
,
425 BMF_TOPDOWN
| BMF_NOZEROINIT
,
427 pgp
->psurfMask
= SURFACE_ShareLockSurface(hbmp
);
431 ppal
= PALETTE_LockPalette(ppdev
->devinfo
.hpalDefault
);
432 EXLATEOBJ_vInitialize(&exlo
,
439 rcl
.bottom
= psoMask
->sizlBitmap
.cy
;
440 IntEngCopyBits(&pgp
->psurfMask
->SurfObj
,
447 EXLATEOBJ_vCleanup(&exlo
);
449 PALETTE_UnlockPalette(ppal
);
454 pgp
->psurfMask
= NULL
;
457 /* Create a color surface */
460 hbmp
= EngCreateBitmap(psoColor
->sizlBitmap
,
463 BMF_TOPDOWN
| BMF_NOZEROINIT
,
465 pgp
->psurfColor
= SURFACE_ShareLockSurface(hbmp
);
468 rcl
.bottom
= psoColor
->sizlBitmap
.cy
;
469 IntEngCopyBits(&pgp
->psurfColor
->SurfObj
,
479 pgp
->psurfColor
= NULL
;
484 ppdev
->ptlPointer
.x
= x
;
485 ppdev
->ptlPointer
.y
= y
;
487 IntShowMousePointer(ppdev
, pso
);
491 prcl
->left
= x
- pgp
->HotSpot
.x
;
492 prcl
->top
= y
- pgp
->HotSpot
.x
;
493 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
494 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
497 else if (prcl
!= NULL
)
499 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
502 return SPS_ACCEPT_NOEXCLUDE
;
524 pgp
= &ppdev
->Pointer
;
526 IntHideMousePointer(ppdev
, pso
);
528 ppdev
->ptlPointer
.x
= x
;
529 ppdev
->ptlPointer
.y
= y
;
533 IntShowMousePointer(ppdev
, pso
);
536 prcl
->left
= x
- pgp
->HotSpot
.x
;
537 prcl
->top
= y
- pgp
->HotSpot
.y
;
538 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
539 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
541 } else if (prcl
!= NULL
)
542 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
552 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
553 PPDEVOBJ ppdev
= (PPDEVOBJ
)pso
->hdev
;
555 SURFACE_LockBitmapBits(psurf
);
556 ppdev
->pfnMovePointer(pso
, x
, y
, prcl
);
557 SURFACE_UnlockBitmapBits(psurf
);
561 IntEngSetPointerShape(
564 IN SURFOBJ
*psoColor
,
573 ULONG ulResult
= SPS_DECLINE
;
574 SURFACE
*psurf
= CONTAINING_RECORD(pso
, SURFACE
, SurfObj
);
575 PFN_DrvSetPointerShape pfnSetPointerShape
;
576 PPDEVOBJ ppdev
= GDIDEV(pso
);
578 pfnSetPointerShape
= GDIDEVFUNCS(pso
).SetPointerShape
;
580 SURFACE_LockBitmapBits(psurf
);
581 if (pfnSetPointerShape
)
583 ulResult
= pfnSetPointerShape(pso
,
595 /* Check if the driver accepted it */
596 if (ulResult
== SPS_ACCEPT_NOEXCLUDE
)
598 /* Set MovePointer to the driver function */
599 ppdev
->pfnMovePointer
= GDIDEVFUNCS(pso
).MovePointer
;
603 /* Set software pointer */
604 ulResult
= EngSetPointerShape(pso
,
614 /* Set MovePointer to the eng function */
615 ppdev
->pfnMovePointer
= EngMovePointer
;
618 SURFACE_UnlockBitmapBits(psurf
);
635 PSURFACE psurf
, psurfMask
, psurfColor
;
640 pdc
= DC_LockDc(hdc
);
643 DPRINT1("Failed to lock the DC.\n");
647 psurf
= pdc
->dclevel
.pSurface
;
650 DPRINT1("DC has no surface.\n");
655 /* Lock the mask bitmap */
657 psurfMask
= SURFACE_ShareLockSurface(hbmMask
);
661 /* Check for color bitmap */
664 /* We have one, lock it */
665 psurfColor
= SURFACE_ShareLockSurface(hbmColor
);
669 /* Create an XLATEOBJ, no mono support */
670 EXLATEOBJ_vInitialize(&exlo
, psurfColor
->ppal
, psurf
->ppal
, 0, 0, 0);
676 /* Call the driver or eng function */
677 ulResult
= IntEngSetPointerShape(&psurf
->SurfObj
,
678 psurfMask
? &psurfMask
->SurfObj
: NULL
,
679 psurfColor
? &psurfColor
->SurfObj
: NULL
,
680 psurfColor
? &exlo
.xlo
: NULL
,
685 &pdc
->ppdev
->Pointer
.Exclude
,
691 EXLATEOBJ_vCleanup(&exlo
);
692 SURFACE_ShareUnlockSurface(psurfColor
);
696 SURFACE_ShareUnlockSurface(psurfMask
);
716 pdc
= DC_LockDc(hdc
);
719 DPRINT1("Failed to lock the DC.\n");
723 /* Store the cursor exclude position in the PDEV */
724 prcl
= &pdc
->ppdev
->Pointer
.Exclude
;
726 /* Call Eng/Drv function */
727 IntEngMovePointer(&pdc
->dclevel
.pSurface
->SurfObj
, x
, y
, prcl
);