3bc769cd3152eee162440f8e560f7f8a62b2baa7
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
;
160 pt
.x
= pgp
->Pos
.x
- pgp
->HotSpot
.x
;
161 pt
.y
= pgp
->Pos
.y
- pgp
->HotSpot
.y
;
164 if (pgp
->SaveSurface
!= NULL
)
168 SURFOBJ
*SaveSurface
;
169 SURFOBJ
*MaskSurface
;
171 DestRect
.left
= max(pt
.x
, 0);
172 DestRect
.top
= max(pt
.y
, 0);
173 DestRect
.right
= min(
175 DestSurface
->sizlBitmap
.cx
);
176 DestRect
.bottom
= min(
178 DestSurface
->sizlBitmap
.cy
);
180 SrcPoint
.x
= max(-pt
.x
, 0);
181 SrcPoint
.y
= max(-pt
.y
, 0);
183 if((SaveSurface
= EngLockSurface(pgp
->SaveSurface
)))
185 if((MaskSurface
= EngLockSurface(pgp
->MaskSurface
)))
187 IntEngBitBltEx(DestSurface
, SaveSurface
, MaskSurface
, NULL
, NULL
,
188 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
,
189 ROP3_TO_ROP4(SRCCOPY
), FALSE
);
190 EngUnlockSurface(MaskSurface
);
192 EngUnlockSurface(SaveSurface
);
198 IntShowMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
201 SURFOBJ
*SaveSurface
;
207 pgp
= &ppdev
->Pointer
;
214 if (pgp
->ShowPointer
== 1)
222 pt
.x
= pgp
->Pos
.x
- pgp
->HotSpot
.x
;
223 pt
.y
= pgp
->Pos
.y
- pgp
->HotSpot
.y
;
226 * Copy the pixels under the cursor to temporary surface.
229 if (pgp
->SaveSurface
!= NULL
&&
230 (SaveSurface
= EngLockSurface(pgp
->SaveSurface
)))
235 SrcPoint
.x
= max(pt
.x
, 0);
236 SrcPoint
.y
= max(pt
.y
, 0);
238 DestRect
.left
= SrcPoint
.x
- pt
.x
;
239 DestRect
.top
= SrcPoint
.y
- pt
.y
;
240 DestRect
.right
= min(
242 DestSurface
->sizlBitmap
.cx
- pt
.x
);
243 DestRect
.bottom
= min(
245 DestSurface
->sizlBitmap
.cy
- pt
.y
);
247 IntEngBitBltEx(SaveSurface
, DestSurface
, NULL
, NULL
, NULL
,
248 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
,
249 ROP3_TO_ROP4(SRCCOPY
), FALSE
);
250 EngUnlockSurface(SaveSurface
);
254 * Blit the cursor on the screen.
261 SURFOBJ
*MaskSurf
= NULL
;
263 DestRect
.left
= max(pt
.x
, 0);
264 DestRect
.top
= max(pt
.y
, 0);
265 DestRect
.right
= min(
267 DestSurface
->sizlBitmap
.cx
);
268 DestRect
.bottom
= min(
270 DestSurface
->sizlBitmap
.cy
);
272 SrcPoint
.x
= max(-pt
.x
, 0);
273 SrcPoint
.y
= max(-pt
.y
, 0);
275 if (pgp
->MaskSurface
)
276 MaskSurf
= EngLockSurface(pgp
->MaskSurface
);
278 if (MaskSurf
!= NULL
)
280 if (pgp
->ColorSurface
!= NULL
)
282 if((ColorSurf
= EngLockSurface(pgp
->ColorSurface
)))
284 IntEngBitBltEx(DestSurface
, ColorSurf
, MaskSurf
, NULL
,
285 pgp
->XlateObject
, &DestRect
, &SrcPoint
, &SrcPoint
,
286 NULL
, NULL
, R4_MASK
, FALSE
);
287 EngUnlockSurface(ColorSurf
);
292 IntEngBitBltEx(DestSurface
, MaskSurf
, NULL
, NULL
, pgp
->XlateObject
,
293 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
,
294 ROP3_TO_ROP4(SRCAND
), FALSE
);
295 SrcPoint
.y
+= pgp
->Size
.cy
;
296 IntEngBitBltEx(DestSurface
, MaskSurf
, NULL
, NULL
, pgp
->XlateObject
,
297 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
,
298 ROP3_TO_ROP4(SRCINVERT
), FALSE
);
300 EngUnlockSurface(MaskSurf
);
313 IN SURFOBJ
*psoColor
,
323 SURFOBJ
*TempSurfObj
;
329 pgp
= &ppdev
->Pointer
;
331 IntHideMousePointer(ppdev
, pso
);
333 if (pgp
->ColorSurface
!= NULL
)
335 /* FIXME: Is this really needed? */
336 if((TempSurfObj
= EngLockSurface(pgp
->ColorSurface
)))
338 EngFreeMem(TempSurfObj
->pvBits
);
339 TempSurfObj
->pvBits
= 0;
340 EngUnlockSurface(TempSurfObj
);
343 EngDeleteSurface(pgp
->ColorSurface
);
344 pgp
->MaskSurface
= NULL
;
347 if (pgp
->MaskSurface
!= NULL
)
349 /* FIXME: Is this really needed? */
350 if((TempSurfObj
= EngLockSurface(pgp
->MaskSurface
)))
352 EngFreeMem(TempSurfObj
->pvBits
);
353 TempSurfObj
->pvBits
= 0;
354 EngUnlockSurface(TempSurfObj
);
357 EngDeleteSurface(pgp
->MaskSurface
);
358 pgp
->MaskSurface
= NULL
;
361 if (pgp
->SaveSurface
!= NULL
)
363 EngDeleteSurface(pgp
->SaveSurface
);
364 pgp
->SaveSurface
= NULL
;
367 if (pgp
->XlateObject
!= NULL
)
369 EngDeleteXlate(pgp
->XlateObject
);
370 pgp
->XlateObject
= NULL
;
374 * See if we are being asked to hide the pointer.
379 return SPS_ACCEPT_NOEXCLUDE
;
382 pgp
->HotSpot
.x
= xHot
;
383 pgp
->HotSpot
.y
= yHot
;
385 /* Actually this should be set by 'the other side', but it would be
386 * done right after this. It helps IntShowMousePointer. */
393 pgp
->Size
.cx
= abs(psoMask
->lDelta
) << 3;
394 pgp
->Size
.cy
= (psoMask
->cjBits
/ abs(psoMask
->lDelta
)) >> 1;
396 if (psoColor
!= NULL
)
400 Bits
= EngAllocMem(0, psoColor
->cjBits
, TAG_MOUSE
);
406 memcpy(Bits
, psoColor
->pvBits
, psoColor
->cjBits
);
408 pgp
->ColorSurface
= (HSURF
)EngCreateBitmap(pgp
->Size
,
409 psoColor
->lDelta
, psoColor
->iBitmapFormat
,
410 psoColor
->lDelta
< 0 ? 0 : BMF_TOPDOWN
, Bits
);
414 pgp
->ColorSurface
= NULL
;
421 Size
.cx
= pgp
->Size
.cx
;
422 Size
.cy
= pgp
->Size
.cy
<< 1;
423 Bits
= EngAllocMem(0, psoMask
->cjBits
, TAG_MOUSE
);
429 memcpy(Bits
, psoMask
->pvBits
, psoMask
->cjBits
);
431 pgp
->MaskSurface
= (HSURF
)EngCreateBitmap(Size
,
432 psoMask
->lDelta
, psoMask
->iBitmapFormat
,
433 psoMask
->lDelta
< 0 ? 0 : BMF_TOPDOWN
, Bits
);
437 * Create an XLATEOBJ that will be used for drawing masks.
438 * FIXME: We should get this in pxlo parameter!
443 HPALETTE BWPalette
, DestPalette
;
444 ULONG BWColors
[] = {0, 0xFFFFFF};
446 BWPalette
= EngCreatePalette(PAL_INDEXED
, sizeof(BWColors
) / sizeof(ULONG
),
449 DestPalette
= ppdev
->DevInfo
.hpalDefault
;
450 pgp
->XlateObject
= IntEngCreateXlate(0, PAL_INDEXED
,
451 DestPalette
, BWPalette
);
452 EngDeletePalette(BWPalette
);
456 pgp
->XlateObject
= pxlo
;
460 * Create surface for saving the pixels under the cursor.
466 switch (pso
->iBitmapFormat
)
469 lDelta
= pgp
->Size
.cx
>> 3;
472 lDelta
= pgp
->Size
.cx
>> 1;
475 lDelta
= pgp
->Size
.cx
;
478 lDelta
= pgp
->Size
.cx
<< 1;
481 lDelta
= pgp
->Size
.cx
* 3;
484 lDelta
= pgp
->Size
.cx
<< 2;
491 pgp
->SaveSurface
= (HSURF
)EngCreateBitmap(
492 pgp
->Size
, lDelta
, pso
->iBitmapFormat
, BMF_TOPDOWN
| BMF_NOZEROINIT
, NULL
);
497 IntShowMousePointer(ppdev
, pso
);
501 prcl
->left
= x
- pgp
->HotSpot
.x
;
502 prcl
->top
= y
- pgp
->HotSpot
.x
;
503 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
504 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
506 } else if (prcl
!= NULL
)
507 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
509 return SPS_ACCEPT_EXCLUDE
;
532 pgp
= &ppdev
->Pointer
;
534 IntHideMousePointer(ppdev
, pso
);
537 /* Actually this should be set by 'the other side', but it would be
538 * done right after this. It helps IntShowMousePointer. */
541 IntShowMousePointer(ppdev
, pso
);
544 prcl
->left
= x
- pgp
->HotSpot
.x
;
545 prcl
->top
= y
- pgp
->HotSpot
.x
;
546 prcl
->right
= prcl
->left
+ pgp
->Size
.cx
;
547 prcl
->bottom
= prcl
->top
+ pgp
->Size
.cy
;
549 } else if (prcl
!= NULL
)
550 prcl
->left
= prcl
->top
= prcl
->right
= prcl
->bottom
= -1;
561 BITMAPOBJ
*BitmapObj
= CONTAINING_RECORD(SurfObj
, BITMAPOBJ
, SurfObj
);
563 BITMAPOBJ_LockBitmapBits(BitmapObj
);
564 if (GDIDEV(SurfObj
)->Pointer
.MovePointer
)
566 GDIDEV(SurfObj
)->Pointer
.MovePointer(SurfObj
, x
, y
, prcl
);
570 EngMovePointer(SurfObj
, x
, y
, prcl
);
572 BITMAPOBJ_UnlockBitmapBits(BitmapObj
);