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.
19 /* $Id: mouse.c,v 1.63 2004/03/05 09:02:41 hbirr Exp $
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 #include <ddk/ntddk.h>
32 #include <ddk/ntddmou.h>
33 #include <win32k/win32k.h>
34 #include <win32k/dc.h>
36 #include "include/msgqueue.h"
37 #include "include/object.h"
38 #include "include/winsta.h"
39 #include "include/desktop.h"
40 #include "include/window.h"
41 #include "include/cursoricon.h"
42 #include "include/callback.h"
43 #include "include/palette.h"
44 #include "include/inteng.h"
45 #include "include/eng.h"
46 #include "include/tags.h"
47 #include <include/mouse.h>
52 #define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
54 /* FUNCTIONS *****************************************************************/
57 IntIsPrimarSurface(PSURFGDI SurfGDI
);
61 IntCheckClipCursor(LONG
*x
, LONG
*y
, PSYSTEM_CURSORINFO CurInfo
)
63 if(CurInfo
->CursorClipInfo
.IsClipped
)
65 if(*x
> CurInfo
->CursorClipInfo
.Right
)
66 *x
= CurInfo
->CursorClipInfo
.Right
;
67 if(*x
< CurInfo
->CursorClipInfo
.Left
)
68 *x
= CurInfo
->CursorClipInfo
.Left
;
69 if(*y
> CurInfo
->CursorClipInfo
.Bottom
)
70 *y
= CurInfo
->CursorClipInfo
.Bottom
;
71 if(*y
< CurInfo
->CursorClipInfo
.Top
)
72 *y
= CurInfo
->CursorClipInfo
.Top
;
79 IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject
, BOOL Swap
)
81 BOOL res
= WinStaObject
->SystemCursor
.SwapButtons
;
82 WinStaObject
->SystemCursor
.SwapButtons
= Swap
;
87 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
88 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
90 * FUNCTION: Notify the mouse driver that drawing is about to begin in
91 * a rectangle on a particular surface.
95 PSYSTEM_CURSORINFO CurInfo
;
96 BOOL MouseEnabled
= FALSE
;
97 PCURICON_OBJECT Cursor
;
100 /* Mouse is not allowed to move if GDI is busy drawing */
102 if(IntGetWindowStationObject(InputWindowStation
))
104 CurInfo
= &InputWindowStation
->SystemCursor
;
106 MouseEnabled
= CurInfo
->Enabled
&& CurInfo
->ShowingCursor
;
113 ObDereferenceObject(InputWindowStation
);
116 if (!IntIsPrimarSurface(SurfGDI
) || MouseEnabled
== FALSE
)
118 ObDereferenceObject(InputWindowStation
);
122 if (SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
)
124 /* Hardware cursor, no need to remove it */
125 ObDereferenceObject(InputWindowStation
);
129 if(!(Cursor
= CurInfo
->CurrentCursorObject
))
131 ObDereferenceObject(InputWindowStation
);
135 if (HazardX1
> HazardX2
)
137 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
139 if (HazardY1
> HazardY2
)
141 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
144 if (CurInfo
->PointerRectRight
>= HazardX1
145 && CurInfo
->PointerRectLeft
<= HazardX2
146 && CurInfo
->PointerRectBottom
>= HazardY1
147 && CurInfo
->PointerRectTop
<= HazardY2
)
149 /* Mouse is not allowed to move if GDI is busy drawing */
150 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
151 if (0 != CurInfo
->SafetyRemoveCount
++)
153 /* Was already removed */
154 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
155 ObDereferenceObject(InputWindowStation
);
158 CurInfo
->SafetySwitch
= TRUE
;
159 IntLockGDIDriver(SurfGDI
);
160 SurfGDI
->MovePointer(SurfObj
, -1, -1, NULL
);
161 IntUnLockGDIDriver(SurfGDI
);
162 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
165 ObDereferenceObject(InputWindowStation
);
170 SetPointerRect(PSYSTEM_CURSORINFO CurInfo
, PRECTL PointerRect
)
172 CurInfo
->PointerRectLeft
= PointerRect
->left
;
173 CurInfo
->PointerRectRight
= PointerRect
->right
;
174 CurInfo
->PointerRectTop
= PointerRect
->top
;
175 CurInfo
->PointerRectBottom
= PointerRect
->bottom
;
179 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
181 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
184 PSYSTEM_CURSORINFO CurInfo
;
185 BOOL MouseEnabled
= FALSE
;
188 if(IntGetWindowStationObject(InputWindowStation
))
190 CurInfo
= &InputWindowStation
->SystemCursor
;
195 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
198 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
199 ObDereferenceObject(InputWindowStation
);
203 MouseEnabled
= CurInfo
->Enabled
&& CurInfo
->ShowingCursor
;
204 if (!IntIsPrimarSurface(SurfGDI
) || MouseEnabled
== FALSE
)
206 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
207 ObDereferenceObject(InputWindowStation
);
211 if (SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
)
213 /* Hardware cursor, it wasn't removed so need to restore it */
214 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
215 ObDereferenceObject(InputWindowStation
);
219 if (CurInfo
->SafetySwitch
)
221 if (1 < CurInfo
->SafetyRemoveCount
--)
223 /* Someone else removed it too, let them restore it */
224 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
225 ObDereferenceObject(InputWindowStation
);
228 IntLockGDIDriver(SurfGDI
);
229 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
230 IntUnLockGDIDriver(SurfGDI
);
231 SetPointerRect(CurInfo
, &PointerRect
);
232 CurInfo
->SafetySwitch
= FALSE
;
235 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
236 ObDereferenceObject(InputWindowStation
);
241 MouseMoveCursor(LONG X
, LONG Y
)
248 PSYSTEM_CURSORINFO CurInfo
;
250 LARGE_INTEGER LargeTickCount
;
254 if(!InputWindowStation
)
257 if(IntGetWindowStationObject(InputWindowStation
))
259 CurInfo
= &InputWindowStation
->SystemCursor
;
260 if(!CurInfo
->Enabled
)
262 ObDereferenceObject(InputWindowStation
);
265 hDC
= IntGetScreenDC();
268 ObDereferenceObject(InputWindowStation
);
272 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
273 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
275 IntCheckClipCursor(&X
, &Y
, CurInfo
);
276 if((X
!= CurInfo
->x
) || (Y
!= CurInfo
->y
))
283 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
284 IntLockGDIDriver(SurfGDI
);
285 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
286 IntUnLockGDIDriver(SurfGDI
);
287 SetPointerRect(CurInfo
, &PointerRect
);
288 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
290 /* send MOUSEMOVE message */
291 KeQueryTickCount(&LargeTickCount
);
292 TickCount
= LargeTickCount
.u
.LowPart
;
293 Msg
.wParam
= CurInfo
->ButtonsDown
;
294 Msg
.lParam
= MAKELPARAM(X
, Y
);
295 Msg
.message
= WM_MOUSEMOVE
;
296 Msg
.time
= TickCount
;
299 MsqInsertSystemMessage(&Msg
, TRUE
);
303 ObDereferenceObject(InputWindowStation
);
311 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
313 * FUNCTION: Call by the mouse driver when input events occur.
317 PSYSTEM_CURSORINFO CurInfo
;
318 BOOL MouseEnabled
= FALSE
;
320 LONG mouse_ox
, mouse_oy
;
321 LONG mouse_cx
= 0, mouse_cy
= 0;
330 hDC
= IntGetScreenDC();
332 if(!hDC
|| !InputWindowStation
)
335 if(IntGetWindowStationObject(InputWindowStation
))
337 CurInfo
= &InputWindowStation
->SystemCursor
;
338 MouseEnabled
= CurInfo
->Enabled
;
341 ObDereferenceObject(InputWindowStation
);
344 mouse_ox
= CurInfo
->x
;
345 mouse_oy
= CurInfo
->y
;
351 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
352 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
355 /* Compile the total mouse movement change and dispatch button events. */
356 for (i
= 0; i
< InputCount
; i
++)
358 mouse_cx
+= Data
[i
].LastX
;
359 mouse_cy
+= Data
[i
].LastY
;
361 CurInfo
->x
+= Data
[i
].LastX
;
362 CurInfo
->y
+= Data
[i
].LastY
;
364 CurInfo
->x
= max(CurInfo
->x
, 0);
365 CurInfo
->y
= max(CurInfo
->y
, 0);
366 CurInfo
->x
= min(CurInfo
->x
, SurfObj
->sizlBitmap
.cx
- 1);
367 CurInfo
->y
= min(CurInfo
->y
, SurfObj
->sizlBitmap
.cy
- 1);
369 IntCheckClipCursor(&CurInfo
->x
, &CurInfo
->y
, CurInfo
);
371 Msg
.wParam
= CurInfo
->ButtonsDown
;
372 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
373 Msg
.message
= WM_MOUSEMOVE
;
374 Msg
.pt
.x
= CurInfo
->x
;
375 Msg
.pt
.y
= CurInfo
->y
;
377 if (Data
[i
].ButtonFlags
!= 0)
379 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
381 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_RBUTTON
: MK_LBUTTON
);
382 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONDOWN
: WM_LBUTTONDOWN
);
384 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
386 CurInfo
->ButtonsDown
|= MK_MBUTTON
;
387 Msg
.message
= WM_MBUTTONDOWN
;
389 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
391 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_LBUTTON
: MK_RBUTTON
);
392 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONDOWN
: WM_RBUTTONDOWN
);
395 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_DOWN
) > 0)
397 CurInfo
->ButtonsDown
|= MK_XBUTTON1
;
398 Msg
.message
= WM_XBUTTONDOWN
;
400 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_DOWN
) > 0)
402 CurInfo
->ButtonsDown
|= MK_XBUTTON2
;
403 Msg
.message
= WM_XBUTTONDOWN
;
406 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
408 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_RBUTTON
: ~MK_LBUTTON
);
409 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONUP
: WM_LBUTTONUP
);
411 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
413 CurInfo
->ButtonsDown
&= ~MK_MBUTTON
;
414 Msg
.message
= WM_MBUTTONUP
;
416 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
418 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_LBUTTON
: ~MK_RBUTTON
);
419 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONUP
: WM_RBUTTONUP
);
421 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_UP
) > 0)
423 CurInfo
->ButtonsDown
&= ~MK_XBUTTON1
;
424 Msg
.message
= WM_XBUTTONUP
;
426 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_UP
) > 0)
428 CurInfo
->ButtonsDown
&= ~MK_XBUTTON2
;
429 Msg
.message
= WM_XBUTTONUP
;
431 if ((Data
[i
].ButtonFlags
& MOUSE_WHEEL
) > 0)
433 dScroll
+= (LONG
)Data
[i
].ButtonData
;
436 if (Data
[i
].ButtonFlags
!= MOUSE_WHEEL
)
438 Moved
= (0 != mouse_cx
) || (0 != mouse_cy
);
439 if(Moved
&& MouseEnabled
)
441 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
442 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
444 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
445 IntLockGDIDriver(SurfGDI
);
446 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
447 IntUnLockGDIDriver(SurfGDI
);
448 SetPointerRect(CurInfo
, &PointerRect
);
449 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
455 Msg
.wParam
= CurInfo
->ButtonsDown
;
456 MsqInsertSystemMessage(&Msg
, FALSE
);
461 /* If the mouse moved then move the pointer. */
462 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
464 Msg
.wParam
= CurInfo
->ButtonsDown
;
465 Msg
.message
= WM_MOUSEMOVE
;
466 Msg
.pt
.x
= CurInfo
->x
;
467 Msg
.pt
.y
= CurInfo
->y
;
468 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
469 MsqInsertSystemMessage(&Msg
, TRUE
);
471 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
472 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
474 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
475 IntLockGDIDriver(SurfGDI
);
476 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
477 IntUnLockGDIDriver(SurfGDI
);
478 SetPointerRect(CurInfo
, &PointerRect
);
479 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
483 /* send WM_MOUSEWHEEL message */
484 if(dScroll
&& MouseEnabled
)
486 Msg
.message
= WM_MOUSEWHEEL
;
487 Msg
.wParam
= MAKEWPARAM(CurInfo
->ButtonsDown
, dScroll
);
488 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
489 Msg
.pt
.x
= CurInfo
->x
;
490 Msg
.pt
.y
= CurInfo
->y
;
491 MsqInsertSystemMessage(&Msg
, FALSE
);
494 ObDereferenceObject(InputWindowStation
);
498 EnableMouse(HDC hDisplayDC
)
504 if( hDisplayDC
&& InputWindowStation
)
506 if(!IntGetWindowStationObject(InputWindowStation
))
508 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
512 dc
= DC_LockDc(hDisplayDC
);
513 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
514 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
515 DC_UnlockDc( hDisplayDC
);
517 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
519 InputWindowStation
->SystemCursor
.Enabled
= (SPS_ACCEPT_EXCLUDE
== SurfGDI
->PointerStatus
||
520 SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
);
522 /* Move the cursor to the screen center */
523 DPRINT("Setting Cursor up at 0x%x, 0x%x\n", SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
524 MouseMoveCursor(SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
526 ObDereferenceObject(InputWindowStation
);
530 if(IntGetWindowStationObject(InputWindowStation
))
532 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
533 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
534 InputWindowStation
->SystemCursor
.CursorClipInfo
.IsClipped
= FALSE
;
535 ObDereferenceObject(InputWindowStation
);
541 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
544 IntHideMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
546 if (ppdev
->PointerAttributes
.Enable
== FALSE
)
551 ppdev
->PointerAttributes
.Enable
= FALSE
;
553 if (ppdev
->PointerAttributes
.Column
+ ppdev
->PointerHotSpot
.x
== -1)
558 if (ppdev
->PointerSaveSurface
!= NULL
)
562 SURFOBJ
*SaveSurface
;
563 SURFOBJ
*MaskSurface
;
565 DestRect
.left
= max(ppdev
->PointerAttributes
.Column
, 0);
566 DestRect
.top
= max(ppdev
->PointerAttributes
.Row
, 0);
567 DestRect
.right
= min(
568 ppdev
->PointerAttributes
.Column
+ ppdev
->PointerAttributes
.Width
,
569 DestSurface
->sizlBitmap
.cx
);
570 DestRect
.bottom
= min(
571 ppdev
->PointerAttributes
.Row
+ ppdev
->PointerAttributes
.Height
,
572 DestSurface
->sizlBitmap
.cy
);
574 SrcPoint
.x
= max(-ppdev
->PointerAttributes
.Column
, 0);
575 SrcPoint
.y
= max(-ppdev
->PointerAttributes
.Row
, 0);
577 SaveSurface
= EngLockSurface(ppdev
->PointerSaveSurface
);
578 MaskSurface
= EngLockSurface(ppdev
->PointerMaskSurface
);
579 EngBitBlt(DestSurface
, SaveSurface
, MaskSurface
, NULL
, NULL
,
580 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, SRCCOPY
);
581 EngUnlockSurface(MaskSurface
);
582 EngUnlockSurface(SaveSurface
);
587 IntShowMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
589 if (ppdev
->PointerAttributes
.Enable
== TRUE
)
594 ppdev
->PointerAttributes
.Enable
= TRUE
;
597 * Copy the pixels under the cursor to temporary surface.
600 if (ppdev
->PointerSaveSurface
!= NULL
)
604 SURFOBJ
*SaveSurface
;
606 SrcPoint
.x
= max(ppdev
->PointerAttributes
.Column
, 0);
607 SrcPoint
.y
= max(ppdev
->PointerAttributes
.Row
, 0);
609 DestRect
.left
= SrcPoint
.x
- ppdev
->PointerAttributes
.Column
;
610 DestRect
.top
= SrcPoint
.y
- ppdev
->PointerAttributes
.Row
;
611 DestRect
.right
= min(
612 ppdev
->PointerAttributes
.Width
,
613 DestSurface
->sizlBitmap
.cx
- ppdev
->PointerAttributes
.Column
);
614 DestRect
.bottom
= min(
615 ppdev
->PointerAttributes
.Height
,
616 DestSurface
->sizlBitmap
.cy
- ppdev
->PointerAttributes
.Row
);
618 SaveSurface
= EngLockSurface(ppdev
->PointerSaveSurface
);
619 EngBitBlt(SaveSurface
, DestSurface
, NULL
, NULL
, NULL
,
620 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCCOPY
);
621 EngUnlockSurface(SaveSurface
);
625 * Blit the cursor on the screen.
634 DestRect
.left
= max(ppdev
->PointerAttributes
.Column
, 0);
635 DestRect
.top
= max(ppdev
->PointerAttributes
.Row
, 0);
636 DestRect
.right
= min(
637 ppdev
->PointerAttributes
.Column
+ ppdev
->PointerAttributes
.Width
,
638 DestSurface
->sizlBitmap
.cx
);
639 DestRect
.bottom
= min(
640 ppdev
->PointerAttributes
.Row
+ ppdev
->PointerAttributes
.Height
,
641 DestSurface
->sizlBitmap
.cy
);
643 SrcPoint
.x
= max(-ppdev
->PointerAttributes
.Column
, 0);
644 SrcPoint
.y
= max(-ppdev
->PointerAttributes
.Row
, 0);
646 MaskSurf
= EngLockSurface(ppdev
->PointerMaskSurface
);
647 if (ppdev
->PointerColorSurface
!= NULL
)
649 ColorSurf
= EngLockSurface(ppdev
->PointerColorSurface
);
650 EngBitBlt(DestSurface
, ColorSurf
, MaskSurf
, NULL
, ppdev
->PointerXlateObject
,
651 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, 0xAACC);
652 EngUnlockSurface(ColorSurf
);
656 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, ppdev
->PointerXlateObject
,
657 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCAND
);
658 SrcPoint
.y
+= ppdev
->PointerAttributes
.Height
;
659 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, ppdev
->PointerXlateObject
,
660 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCINVERT
);
662 EngUnlockSurface(MaskSurf
);
674 IN SURFOBJ
*psoColor
,
683 GDIDEVICE
*ppdev
= (GDIDEVICE
*)pso
->hdev
;
684 SURFOBJ
*TempSurfObj
;
686 IntHideMousePointer(ppdev
, pso
);
688 if (ppdev
->PointerColorSurface
!= NULL
)
690 /* FIXME: Is this really needed? */
691 TempSurfObj
= EngLockSurface(ppdev
->PointerColorSurface
);
692 EngFreeMem(TempSurfObj
->pvBits
);
693 TempSurfObj
->pvBits
= 0;
694 EngUnlockSurface(TempSurfObj
);
696 EngDeleteSurface(ppdev
->PointerColorSurface
);
697 ppdev
->PointerMaskSurface
= NULL
;
700 if (ppdev
->PointerMaskSurface
!= NULL
)
702 /* FIXME: Is this really needed? */
703 TempSurfObj
= EngLockSurface(ppdev
->PointerMaskSurface
);
704 EngFreeMem(TempSurfObj
->pvBits
);
705 TempSurfObj
->pvBits
= 0;
706 EngUnlockSurface(TempSurfObj
);
708 EngDeleteSurface(ppdev
->PointerMaskSurface
);
709 ppdev
->PointerMaskSurface
= NULL
;
712 if (ppdev
->PointerSaveSurface
!= NULL
)
714 EngDeleteSurface(ppdev
->PointerSaveSurface
);
715 ppdev
->PointerSaveSurface
= NULL
;
718 if (ppdev
->PointerXlateObject
!= NULL
)
720 EngDeleteXlate(ppdev
->PointerXlateObject
);
721 ppdev
->PointerXlateObject
= NULL
;
725 * See if we are being asked to hide the pointer.
730 return SPS_ACCEPT_NOEXCLUDE
;
733 ppdev
->PointerHotSpot
.x
= xHot
;
734 ppdev
->PointerHotSpot
.y
= yHot
;
736 ppdev
->PointerAttributes
.Column
= x
- xHot
;
737 ppdev
->PointerAttributes
.Row
= y
- yHot
;
738 ppdev
->PointerAttributes
.Width
= psoMask
->lDelta
<< 3;
739 ppdev
->PointerAttributes
.Height
= (psoMask
->cjBits
/ psoMask
->lDelta
) >> 1;
743 prcl
->left
= ppdev
->PointerAttributes
.Column
;
744 prcl
->top
= ppdev
->PointerAttributes
.Row
;
745 prcl
->right
= prcl
->left
+ ppdev
->PointerAttributes
.Width
;
746 prcl
->bottom
= prcl
->top
+ ppdev
->PointerAttributes
.Height
;
749 if (psoColor
!= NULL
)
754 Size
.cx
= ppdev
->PointerAttributes
.Width
;
755 Size
.cy
= ppdev
->PointerAttributes
.Height
;
756 Bits
= EngAllocMem(0, psoColor
->cjBits
, TAG_MOUSE
);
757 memcpy(Bits
, psoColor
->pvBits
, psoColor
->cjBits
);
759 ppdev
->PointerColorSurface
= (HSURF
)EngCreateBitmap(Size
,
760 psoColor
->lDelta
, psoColor
->iBitmapFormat
, 0, Bits
);
764 ppdev
->PointerColorSurface
= NULL
;
771 Size
.cx
= ppdev
->PointerAttributes
.Width
;
772 Size
.cy
= ppdev
->PointerAttributes
.Height
<< 1;
773 Bits
= EngAllocMem(0, psoMask
->cjBits
, TAG_MOUSE
);
774 memcpy(Bits
, psoMask
->pvBits
, psoMask
->cjBits
);
776 ppdev
->PointerMaskSurface
= (HSURF
)EngCreateBitmap(Size
,
777 psoMask
->lDelta
, psoMask
->iBitmapFormat
, 0, Bits
);
781 * Create and XLATEOBJ that will be used for drawing masks.
782 * FIXME: We should get this in pxlo parameter!
787 HPALETTE BWPalette
, DestPalette
;
788 ULONG BWColors
[] = {0, 0xFFFFFF};
793 BWPalette
= EngCreatePalette(PAL_INDEXED
, sizeof(BWColors
) / sizeof(ULONG
),
795 Dc
= DC_LockDc(IntGetScreenDC());
796 DestPalette
= Dc
->w
.hPalette
;
797 PalObj
= PALETTE_LockPalette(DestPalette
);
798 DestMode
= PalObj
->Mode
;
799 PALETTE_UnlockPalette(DestPalette
);
800 DC_UnlockDc(IntGetScreenDC());
801 ppdev
->PointerXlateObject
= IntEngCreateXlate(DestMode
, PAL_INDEXED
,
802 DestPalette
, BWPalette
);
803 EngDeletePalette(BWPalette
);
807 ppdev
->PointerXlateObject
= pxlo
;
811 * Create surface for saving the pixels under the cursor.
818 Size
.cx
= ppdev
->PointerAttributes
.Width
;
819 Size
.cy
= ppdev
->PointerAttributes
.Height
;
821 switch (pso
->iBitmapFormat
)
823 case BMF_1BPP
: lDelta
= Size
.cx
>> 3; break;
824 case BMF_4BPP
: lDelta
= Size
.cx
>> 1; break;
825 case BMF_8BPP
: lDelta
= Size
.cx
; break;
826 case BMF_16BPP
: lDelta
= Size
.cx
<< 1; break;
827 case BMF_24BPP
: lDelta
= Size
.cx
* 3; break;
828 case BMF_32BPP
: lDelta
= Size
.cx
<< 2; break;
831 ppdev
->PointerSaveSurface
= (HSURF
)EngCreateBitmap(
832 Size
, lDelta
, pso
->iBitmapFormat
, BMF_NOZEROINIT
, NULL
);
835 IntShowMousePointer(ppdev
, pso
);
837 return SPS_ACCEPT_EXCLUDE
;
851 GDIDEVICE
*ppdev
= (GDIDEVICE
*)pso
->hdev
;
852 PSURFGDI SurfGDI
= AccessInternalObjectFromUserObject(pso
);
855 * Prevent GDI from trying to remve the mouse cursor,
856 * because it would cause unexpected reentrancy effects.
859 SurfGDI
->PointerStatus
= SPS_ACCEPT_NOEXCLUDE
;
861 IntHideMousePointer(ppdev
, pso
);
862 ppdev
->PointerAttributes
.Column
= x
- ppdev
->PointerHotSpot
.x
;
863 ppdev
->PointerAttributes
.Row
= y
- ppdev
->PointerHotSpot
.y
;
866 IntShowMousePointer(ppdev
, pso
);
871 prcl
->left
= ppdev
->PointerAttributes
.Column
;
872 prcl
->top
= ppdev
->PointerAttributes
.Row
;
873 prcl
->right
= prcl
->left
+ ppdev
->PointerAttributes
.Width
;
874 prcl
->bottom
= prcl
->top
+ ppdev
->PointerAttributes
.Height
;
877 SurfGDI
->PointerStatus
= SPS_ACCEPT_EXCLUDE
;