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 ******************************************************************/
35 /* FUNCTIONS *****************************************************************/
38 MouseSafetyOnDrawStart(SURFOBJ
*SurfObj
, LONG HazardX1
,
39 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
41 * FUNCTION: Notify the mouse driver that drawing is about to begin in
42 * a rectangle on a particular surface.
49 ASSERT(SurfObj
!= NULL
);
51 ppdev
= GDIDEV(SurfObj
);
58 pgp
= &ppdev
->Pointer
;
60 if (SPS_ACCEPT_NOEXCLUDE
== pgp
->Status
||
61 pgp
->Exclude
.right
== -1)
66 if (HazardX1
> HazardX2
)
68 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
70 if (HazardY1
> HazardY2
)
72 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
75 if (ppdev
->SafetyRemoveLevel
!= 0)
77 ppdev
->SafetyRemoveCount
++;
81 ppdev
->SafetyRemoveCount
++;
83 if (pgp
->Exclude
.right
>= HazardX1
84 && pgp
->Exclude
.left
<= HazardX2
85 && pgp
->Exclude
.bottom
>= HazardY1
86 && pgp
->Exclude
.top
<= HazardY2
)
88 ppdev
->SafetyRemoveLevel
= ppdev
->SafetyRemoveCount
;
90 pgp
->MovePointer(SurfObj
, -1, -1, NULL
);
92 EngMovePointer(SurfObj
, -1, -1, NULL
);
99 MouseSafetyOnDrawEnd(SURFOBJ
*SurfObj
)
101 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
107 ASSERT(SurfObj
!= NULL
);
109 ppdev
= GDIDEV(SurfObj
);
116 pgp
= &ppdev
->Pointer
;
118 if(SPS_ACCEPT_NOEXCLUDE
== pgp
->Status
||
119 pgp
->Exclude
.right
== -1)
124 if (--ppdev
->SafetyRemoveCount
>= ppdev
->SafetyRemoveLevel
)
128 if (pgp
->MovePointer
)
129 pgp
->MovePointer(SurfObj
, pgp
->Pos
.x
, pgp
->Pos
.y
, &pgp
->Exclude
);
131 EngMovePointer(SurfObj
, pgp
->Pos
.x
, pgp
->Pos
.y
, &pgp
->Exclude
);
133 ppdev
->SafetyRemoveLevel
= 0;
138 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
141 IntHideMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
149 pgp
= &ppdev
->Pointer
;
158 pgp
->Enabled
= FALSE
;
161 * The mouse is hide from ShowCours and it is frist ??
163 if (pgp
->ShowPointer
< 0)
172 pt
.x
= pgp
->Pos
.x
- pgp
->HotSpot
.x
;
173 pt
.y
= pgp
->Pos
.y
- pgp
->HotSpot
.y
;
176 if (pgp
->SaveSurface
!= NULL
)
180 SURFOBJ
*SaveSurface
;
181 SURFOBJ
*MaskSurface
;
183 DestRect
.left
= max(pt
.x
, 0);
184 DestRect
.top
= max(pt
.y
, 0);
185 DestRect
.right
= min(
187 DestSurface
->sizlBitmap
.cx
);
188 DestRect
.bottom
= min(
190 DestSurface
->sizlBitmap
.cy
);
192 SrcPoint
.x
= max(-pt
.x
, 0);
193 SrcPoint
.y
= max(-pt
.y
, 0);
195 if((SaveSurface
= EngLockSurface(pgp
->SaveSurface
)))
197 if((MaskSurface
= EngLockSurface(pgp
->MaskSurface
)))
199 IntEngBitBltEx(DestSurface
, SaveSurface
, MaskSurface
, NULL
, NULL
,
200 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
,
201 ROP3_TO_ROP4(SRCCOPY
), FALSE
);
202 EngUnlockSurface(MaskSurface
);
204 EngUnlockSurface(SaveSurface
);
210 IntShowMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
213 SURFOBJ
*SaveSurface
;
219 pgp
= &ppdev
->Pointer
;
229 * Do not blt the mouse if it in hide
231 if (pgp
->ShowPointer
< 0)
236 pt
.x
= pgp
->Pos
.x
- pgp
->HotSpot
.x
;
237 pt
.y
= pgp
->Pos
.y
- pgp
->HotSpot
.y
;
240 * Copy the pixels under the cursor to temporary surface.
243 if (pgp
->SaveSurface
!= NULL
&&
244 (SaveSurface
= EngLockSurface(pgp
->SaveSurface
)))
249 SrcPoint
.x
= max(pt
.x
, 0);
250 SrcPoint
.y
= max(pt
.y
, 0);
252 DestRect
.left
= SrcPoint
.x
- pt
.x
;
253 DestRect
.top
= SrcPoint
.y
- pt
.y
;
254 DestRect
.right
= min(
256 DestSurface
->sizlBitmap
.cx
- pt
.x
);
257 DestRect
.bottom
= min(
259 DestSurface
->sizlBitmap
.cy
- pt
.y
);
261 IntEngBitBltEx(SaveSurface
, DestSurface
, NULL
, NULL
, NULL
,
262 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
,
263 ROP3_TO_ROP4(SRCCOPY
), FALSE
);
264 EngUnlockSurface(SaveSurface
);
269 * Blit the cursor on the screen.
276 SURFOBJ
*MaskSurf
= NULL
;
278 DestRect
.left
= max(pt
.x
, 0);
279 DestRect
.top
= max(pt
.y
, 0);
280 DestRect
.right
= min(
282 DestSurface
->sizlBitmap
.cx
);
283 DestRect
.bottom
= min(
285 DestSurface
->sizlBitmap
.cy
);
287 SrcPoint
.x
= max(-pt
.x
, 0);
288 SrcPoint
.y
= max(-pt
.y
, 0);
291 if (pgp
->MaskSurface
)
292 MaskSurf
= EngLockSurface(pgp
->MaskSurface
);
294 if (MaskSurf
!= NULL
)
296 if (pgp
->ColorSurface
!= NULL
)
298 if((ColorSurf
= EngLockSurface(pgp
->ColorSurface
)))
300 IntEngBitBltEx(DestSurface
, ColorSurf
, MaskSurf
, NULL
,
301 pgp
->XlateObject
, &DestRect
, &SrcPoint
, &SrcPoint
,
302 NULL
, NULL
, R4_MASK
, FALSE
);
303 EngUnlockSurface(ColorSurf
);
308 IntEngBitBltEx(DestSurface
, MaskSurf
, NULL
, NULL
, pgp
->XlateObject
,
309 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
,
310 ROP3_TO_ROP4(SRCAND
), FALSE
);
311 SrcPoint
.y
+= pgp
->Size
.cy
;
312 IntEngBitBltEx(DestSurface
, MaskSurf
, NULL
, NULL
, pgp
->XlateObject
,
313 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
,
314 ROP3_TO_ROP4(SRCINVERT
), FALSE
);
316 EngUnlockSurface(MaskSurf
);
329 IN SURFOBJ
*psoColor
,
339 SURFOBJ
*TempSurfObj
;
345 pgp
= &ppdev
->Pointer
;
347 IntHideMousePointer(ppdev
, pso
);
349 if (pgp
->ColorSurface
!= NULL
)
351 /* FIXME: Is this really needed? */
352 if((TempSurfObj
= EngLockSurface(pgp
->ColorSurface
)))
354 EngFreeMem(TempSurfObj
->pvBits
);
355 TempSurfObj
->pvBits
= 0;
356 EngUnlockSurface(TempSurfObj
);
359 EngDeleteSurface(pgp
->ColorSurface
);
360 pgp
->MaskSurface
= NULL
;
363 if (pgp
->MaskSurface
!= NULL
)
365 /* FIXME: Is this really needed? */
366 if((TempSurfObj
= EngLockSurface(pgp
->MaskSurface
)))
368 EngFreeMem(TempSurfObj
->pvBits
);
369 TempSurfObj
->pvBits
= 0;
370 EngUnlockSurface(TempSurfObj
);
373 EngDeleteSurface(pgp
->MaskSurface
);
374 pgp
->MaskSurface
= NULL
;
377 if (pgp
->SaveSurface
!= NULL
)
379 EngDeleteSurface(pgp
->SaveSurface
);
380 pgp
->SaveSurface
= NULL
;
383 if (pgp
->XlateObject
!= NULL
)
385 EngDeleteXlate(pgp
->XlateObject
);
386 pgp
->XlateObject
= NULL
;
390 * See if we are being asked to hide the pointer.
395 return SPS_ACCEPT_NOEXCLUDE
;
398 pgp
->HotSpot
.x
= xHot
;
399 pgp
->HotSpot
.y
= yHot
;
401 /* Actually this should be set by 'the other side', but it would be
402 * done right after this. It helps IntShowMousePointer. */
409 pgp
->Size
.cx
= abs(psoMask
->lDelta
) << 3;
410 pgp
->Size
.cy
= (psoMask
->cjBits
/ abs(psoMask
->lDelta
)) >> 1;
412 if (psoColor
!= NULL
)
416 Bits
= EngAllocMem(0, psoColor
->cjBits
, TAG_MOUSE
);
422 memcpy(Bits
, psoColor
->pvBits
, psoColor
->cjBits
);
424 pgp
->ColorSurface
= (HSURF
)EngCreateBitmap(pgp
->Size
,
425 psoColor
->lDelta
, psoColor
->iBitmapFormat
,
426 psoColor
->lDelta
< 0 ? 0 : BMF_TOPDOWN
, Bits
);
430 pgp
->ColorSurface
= NULL
;
437 Size
.cx
= pgp
->Size
.cx
;
438 Size
.cy
= pgp
->Size
.cy
<< 1;
439 Bits
= EngAllocMem(0, psoMask
->cjBits
, TAG_MOUSE
);
445 memcpy(Bits
, psoMask
->pvBits
, psoMask
->cjBits
);
447 pgp
->MaskSurface
= (HSURF
)EngCreateBitmap(Size
,
448 psoMask
->lDelta
, psoMask
->iBitmapFormat
,
449 psoMask
->lDelta
< 0 ? 0 : BMF_TOPDOWN
, Bits
);
453 * Create an XLATEOBJ that will be used for drawing masks.
454 * FIXME: We should get this in pxlo parameter!
459 HPALETTE BWPalette
, DestPalette
;
460 ULONG BWColors
[] = {0, 0xFFFFFF};
462 BWPalette
= EngCreatePalette(PAL_INDEXED
, sizeof(BWColors
) / sizeof(ULONG
),
465 DestPalette
= ppdev
->DevInfo
.hpalDefault
;
466 pgp
->XlateObject
= IntEngCreateXlate(0, PAL_INDEXED
,
467 DestPalette
, BWPalette
);
468 EngDeletePalette(BWPalette
);
472 pgp
->XlateObject
= pxlo
;
476 * Create surface for saving the pixels under the cursor.
482 switch (pso
->iBitmapFormat
)
485 lDelta
= pgp
->Size
.cx
>> 3;
488 lDelta
= pgp
->Size
.cx
>> 1;
491 lDelta
= pgp
->Size
.cx
;
494 lDelta
= pgp
->Size
.cx
<< 1;
497 lDelta
= pgp
->Size
.cx
* 3;
500 lDelta
= pgp
->Size
.cx
<< 2;
507 pgp
->SaveSurface
= (HSURF
)EngCreateBitmap(
508 pgp
->Size
, lDelta
, pso
->iBitmapFormat
, BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
513 IntShowMousePointer(ppdev
, pso
);
517 prcl
->left
= x
- pgp
->HotSpot
.x
;
518 prcl
->top
= y
- pgp
->HotSpot
.x
;
519 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
520 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
522 } else if (prcl
!= NULL
)
523 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
525 return SPS_ACCEPT_EXCLUDE
;
548 pgp
= &ppdev
->Pointer
;
550 IntHideMousePointer(ppdev
, pso
);
553 /* Actually this should be set by 'the other side', but it would be
554 * done right after this. It helps IntShowMousePointer. */
557 IntShowMousePointer(ppdev
, pso
);
560 prcl
->left
= x
- pgp
->HotSpot
.x
;
561 prcl
->top
= y
- pgp
->HotSpot
.x
;
562 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
563 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
565 } else if (prcl
!= NULL
)
566 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
577 BITMAPOBJ
*BitmapObj
= CONTAINING_RECORD(SurfObj
, BITMAPOBJ
, SurfObj
);
579 BITMAPOBJ_LockBitmapBits(BitmapObj
);
580 if (GDIDEV(SurfObj
)->Pointer
.MovePointer
)
582 GDIDEV(SurfObj
)->Pointer
.MovePointer(SurfObj
, x
, y
, prcl
);
586 EngMovePointer(SurfObj
, x
, y
, prcl
);
588 BITMAPOBJ_UnlockBitmapBits(BitmapObj
);