2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/eng/mouse.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH Created
28 /* INCLUDES ******************************************************************/
31 /* FUNCTIONS *****************************************************************/
34 MouseSafetyOnDrawStart(SURFOBJ
*SurfObj
, LONG HazardX1
,
35 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
37 * FUNCTION: Notify the mouse driver that drawing is about to begin in
38 * a rectangle on a particular surface.
45 ASSERT(SurfObj
!= NULL
);
47 ppdev
= GDIDEV(SurfObj
);
54 pgp
= &ppdev
->Pointer
;
56 if (SPS_ACCEPT_NOEXCLUDE
== pgp
->Status
||
57 pgp
->Exclude
.right
== -1)
62 if (HazardX1
> HazardX2
)
64 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
66 if (HazardY1
> HazardY2
)
68 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
71 ppdev
->SafetyRemoveCount
++;
73 if (ppdev
->SafetyRemoveLevel
)
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
;
86 pgp
->MovePointer(SurfObj
, -1, -1, NULL
);
88 EngMovePointer(SurfObj
, -1, -1, NULL
);
95 MouseSafetyOnDrawEnd(SURFOBJ
*SurfObj
)
97 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
103 ASSERT(SurfObj
!= NULL
);
105 ppdev
= GDIDEV(SurfObj
);
112 pgp
= &ppdev
->Pointer
;
114 if(SPS_ACCEPT_NOEXCLUDE
== pgp
->Status
||
115 pgp
->Exclude
.right
== -1)
120 if (--ppdev
->SafetyRemoveCount
>= ppdev
->SafetyRemoveLevel
)
124 if (pgp
->MovePointer
)
125 pgp
->MovePointer(SurfObj
, pgp
->Pos
.x
, pgp
->Pos
.y
, &pgp
->Exclude
);
127 EngMovePointer(SurfObj
, pgp
->Pos
.x
, pgp
->Pos
.y
, &pgp
->Exclude
);
129 ppdev
->SafetyRemoveLevel
= 0;
134 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
137 IntHideMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
145 pgp
= &ppdev
->Pointer
;
152 pgp
->Enabled
= FALSE
;
154 pt
.x
= pgp
->Pos
.x
- pgp
->HotSpot
.x
;
155 pt
.y
= pgp
->Pos
.y
- pgp
->HotSpot
.y
;
157 if (pgp
->SaveSurface
!= NULL
)
161 SURFOBJ
*SaveSurface
;
162 SURFOBJ
*MaskSurface
;
164 DestRect
.left
= max(pt
.x
, 0);
165 DestRect
.top
= max(pt
.y
, 0);
166 DestRect
.right
= min(
168 DestSurface
->sizlBitmap
.cx
);
169 DestRect
.bottom
= min(
171 DestSurface
->sizlBitmap
.cy
);
173 SrcPoint
.x
= max(-pt
.x
, 0);
174 SrcPoint
.y
= max(-pt
.y
, 0);
176 if((SaveSurface
= EngLockSurface(pgp
->SaveSurface
)))
178 if((MaskSurface
= EngLockSurface(pgp
->MaskSurface
)))
180 EngBitBlt(DestSurface
, SaveSurface
, MaskSurface
, NULL
, NULL
,
181 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, ROP3_TO_ROP4(SRCCOPY
));
182 EngUnlockSurface(MaskSurface
);
184 EngUnlockSurface(SaveSurface
);
190 IntShowMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
193 SURFOBJ
*SaveSurface
;
199 pgp
= &ppdev
->Pointer
;
208 pt
.x
= pgp
->Pos
.x
- pgp
->HotSpot
.x
;
209 pt
.y
= pgp
->Pos
.y
- pgp
->HotSpot
.y
;
212 * Copy the pixels under the cursor to temporary surface.
215 if (pgp
->SaveSurface
!= NULL
&&
216 (SaveSurface
= EngLockSurface(pgp
->SaveSurface
)))
221 SrcPoint
.x
= max(pt
.x
, 0);
222 SrcPoint
.y
= max(pt
.y
, 0);
224 DestRect
.left
= SrcPoint
.x
- pt
.x
;
225 DestRect
.top
= SrcPoint
.y
- pt
.y
;
226 DestRect
.right
= min(
228 DestSurface
->sizlBitmap
.cx
- pt
.x
);
229 DestRect
.bottom
= min(
231 DestSurface
->sizlBitmap
.cy
- pt
.y
);
233 EngBitBlt(SaveSurface
, DestSurface
, NULL
, NULL
, NULL
,
234 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, ROP3_TO_ROP4(SRCCOPY
));
235 EngUnlockSurface(SaveSurface
);
239 * Blit the cursor on the screen.
246 SURFOBJ
*MaskSurf
= NULL
;
248 DestRect
.left
= max(pt
.x
, 0);
249 DestRect
.top
= max(pt
.y
, 0);
250 DestRect
.right
= min(
252 DestSurface
->sizlBitmap
.cx
);
253 DestRect
.bottom
= min(
255 DestSurface
->sizlBitmap
.cy
);
257 SrcPoint
.x
= max(-pt
.x
, 0);
258 SrcPoint
.y
= max(-pt
.y
, 0);
260 if (pgp
->MaskSurface
)
261 MaskSurf
= EngLockSurface(pgp
->MaskSurface
);
263 if (MaskSurf
!= NULL
)
265 if (pgp
->ColorSurface
!= NULL
)
267 if((ColorSurf
= EngLockSurface(pgp
->ColorSurface
)))
269 EngBitBlt(DestSurface
, ColorSurf
, MaskSurf
, NULL
, pgp
->XlateObject
,
270 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, R4_MASK
);
271 EngUnlockSurface(ColorSurf
);
276 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, pgp
->XlateObject
,
277 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, ROP3_TO_ROP4(SRCAND
));
278 SrcPoint
.y
+= pgp
->Size
.cy
;
279 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, pgp
->XlateObject
,
280 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, ROP3_TO_ROP4(SRCINVERT
));
282 EngUnlockSurface(MaskSurf
);
295 IN SURFOBJ
*psoColor
,
305 SURFOBJ
*TempSurfObj
;
311 pgp
= &ppdev
->Pointer
;
313 IntHideMousePointer(ppdev
, pso
);
315 if (pgp
->ColorSurface
!= NULL
)
317 /* FIXME: Is this really needed? */
318 if((TempSurfObj
= EngLockSurface(pgp
->ColorSurface
)))
320 EngFreeMem(TempSurfObj
->pvBits
);
321 TempSurfObj
->pvBits
= 0;
322 EngUnlockSurface(TempSurfObj
);
325 EngDeleteSurface(pgp
->ColorSurface
);
326 pgp
->MaskSurface
= NULL
;
329 if (pgp
->MaskSurface
!= NULL
)
331 /* FIXME: Is this really needed? */
332 if((TempSurfObj
= EngLockSurface(pgp
->MaskSurface
)))
334 EngFreeMem(TempSurfObj
->pvBits
);
335 TempSurfObj
->pvBits
= 0;
336 EngUnlockSurface(TempSurfObj
);
339 EngDeleteSurface(pgp
->MaskSurface
);
340 pgp
->MaskSurface
= NULL
;
343 if (pgp
->SaveSurface
!= NULL
)
345 EngDeleteSurface(pgp
->SaveSurface
);
346 pgp
->SaveSurface
= NULL
;
349 if (pgp
->XlateObject
!= NULL
)
351 EngDeleteXlate(pgp
->XlateObject
);
352 pgp
->XlateObject
= NULL
;
356 * See if we are being asked to hide the pointer.
361 return SPS_ACCEPT_NOEXCLUDE
;
364 pgp
->HotSpot
.x
= xHot
;
365 pgp
->HotSpot
.y
= yHot
;
367 /* Actually this should be set by 'the other side', but it would be
368 * done right after this. It helps IntShowMousePointer. */
375 pgp
->Size
.cx
= abs(psoMask
->lDelta
) << 3;
376 pgp
->Size
.cy
= (psoMask
->cjBits
/ abs(psoMask
->lDelta
)) >> 1;
378 if (psoColor
!= NULL
)
382 Bits
= EngAllocMem(0, psoColor
->cjBits
, TAG_MOUSE
);
383 memcpy(Bits
, psoColor
->pvBits
, psoColor
->cjBits
);
385 pgp
->ColorSurface
= (HSURF
)EngCreateBitmap(pgp
->Size
,
386 psoColor
->lDelta
, psoColor
->iBitmapFormat
,
387 psoColor
->lDelta
< 0 ? 0 : BMF_TOPDOWN
, Bits
);
391 pgp
->ColorSurface
= NULL
;
398 Size
.cx
= pgp
->Size
.cx
;
399 Size
.cy
= pgp
->Size
.cy
<< 1;
400 Bits
= EngAllocMem(0, psoMask
->cjBits
, TAG_MOUSE
);
401 memcpy(Bits
, psoMask
->pvBits
, psoMask
->cjBits
);
403 pgp
->MaskSurface
= (HSURF
)EngCreateBitmap(Size
,
404 psoMask
->lDelta
, psoMask
->iBitmapFormat
,
405 psoMask
->lDelta
< 0 ? 0 : BMF_TOPDOWN
, Bits
);
409 * Create an XLATEOBJ that will be used for drawing masks.
410 * FIXME: We should get this in pxlo parameter!
415 HPALETTE BWPalette
, DestPalette
;
416 ULONG BWColors
[] = {0, 0xFFFFFF};
418 BWPalette
= EngCreatePalette(PAL_INDEXED
, sizeof(BWColors
) / sizeof(ULONG
),
421 DestPalette
= ppdev
->DevInfo
.hpalDefault
;
422 pgp
->XlateObject
= IntEngCreateXlate(0, PAL_INDEXED
,
423 DestPalette
, BWPalette
);
424 EngDeletePalette(BWPalette
);
428 pgp
->XlateObject
= pxlo
;
432 * Create surface for saving the pixels under the cursor.
438 switch (pso
->iBitmapFormat
)
441 lDelta
= pgp
->Size
.cx
>> 3;
444 lDelta
= pgp
->Size
.cx
>> 1;
447 lDelta
= pgp
->Size
.cx
;
450 lDelta
= pgp
->Size
.cx
<< 1;
453 lDelta
= pgp
->Size
.cx
* 3;
456 lDelta
= pgp
->Size
.cx
<< 2;
463 pgp
->SaveSurface
= (HSURF
)EngCreateBitmap(
464 pgp
->Size
, lDelta
, pso
->iBitmapFormat
, BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
469 IntShowMousePointer(ppdev
, pso
);
473 prcl
->left
= x
- pgp
->HotSpot
.x
;
474 prcl
->top
= y
- pgp
->HotSpot
.x
;
475 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
476 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
478 } else if (prcl
!= NULL
)
479 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
481 return SPS_ACCEPT_EXCLUDE
;
504 pgp
= &ppdev
->Pointer
;
506 IntHideMousePointer(ppdev
, pso
);
509 /* Actually this should be set by 'the other side', but it would be
510 * done right after this. It helps IntShowMousePointer. */
513 IntShowMousePointer(ppdev
, pso
);
516 prcl
->left
= x
- pgp
->HotSpot
.x
;
517 prcl
->top
= y
- pgp
->HotSpot
.x
;
518 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
519 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
521 } else if (prcl
!= NULL
)
522 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;