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.64 2004/03/15 20:21:50 navaraf 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 if (SurfGDI
->MovePointer
!= NULL
)
286 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
287 IntUnLockGDIDriver(SurfGDI
);
288 SetPointerRect(CurInfo
, &PointerRect
);
289 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
291 /* send MOUSEMOVE message */
292 KeQueryTickCount(&LargeTickCount
);
293 TickCount
= LargeTickCount
.u
.LowPart
;
294 Msg
.wParam
= CurInfo
->ButtonsDown
;
295 Msg
.lParam
= MAKELPARAM(X
, Y
);
296 Msg
.message
= WM_MOUSEMOVE
;
297 Msg
.time
= TickCount
;
300 MsqInsertSystemMessage(&Msg
, TRUE
);
304 ObDereferenceObject(InputWindowStation
);
312 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
314 * FUNCTION: Call by the mouse driver when input events occur.
318 PSYSTEM_CURSORINFO CurInfo
;
319 BOOL MouseEnabled
= FALSE
;
321 LONG mouse_ox
, mouse_oy
;
322 LONG mouse_cx
= 0, mouse_cy
= 0;
331 hDC
= IntGetScreenDC();
333 if(!hDC
|| !InputWindowStation
)
336 if(IntGetWindowStationObject(InputWindowStation
))
338 CurInfo
= &InputWindowStation
->SystemCursor
;
339 MouseEnabled
= CurInfo
->Enabled
;
342 ObDereferenceObject(InputWindowStation
);
345 mouse_ox
= CurInfo
->x
;
346 mouse_oy
= CurInfo
->y
;
352 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
353 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
356 /* Compile the total mouse movement change and dispatch button events. */
357 for (i
= 0; i
< InputCount
; i
++)
359 mouse_cx
+= Data
[i
].LastX
;
360 mouse_cy
+= Data
[i
].LastY
;
362 CurInfo
->x
+= Data
[i
].LastX
;
363 CurInfo
->y
+= Data
[i
].LastY
;
365 CurInfo
->x
= max(CurInfo
->x
, 0);
366 CurInfo
->y
= max(CurInfo
->y
, 0);
367 CurInfo
->x
= min(CurInfo
->x
, SurfObj
->sizlBitmap
.cx
- 1);
368 CurInfo
->y
= min(CurInfo
->y
, SurfObj
->sizlBitmap
.cy
- 1);
370 IntCheckClipCursor(&CurInfo
->x
, &CurInfo
->y
, CurInfo
);
372 Msg
.wParam
= CurInfo
->ButtonsDown
;
373 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
374 Msg
.message
= WM_MOUSEMOVE
;
375 Msg
.pt
.x
= CurInfo
->x
;
376 Msg
.pt
.y
= CurInfo
->y
;
378 if (Data
[i
].ButtonFlags
!= 0)
380 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
382 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_RBUTTON
: MK_LBUTTON
);
383 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONDOWN
: WM_LBUTTONDOWN
);
385 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
387 CurInfo
->ButtonsDown
|= MK_MBUTTON
;
388 Msg
.message
= WM_MBUTTONDOWN
;
390 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
392 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_LBUTTON
: MK_RBUTTON
);
393 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONDOWN
: WM_RBUTTONDOWN
);
396 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_DOWN
) > 0)
398 CurInfo
->ButtonsDown
|= MK_XBUTTON1
;
399 Msg
.message
= WM_XBUTTONDOWN
;
401 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_DOWN
) > 0)
403 CurInfo
->ButtonsDown
|= MK_XBUTTON2
;
404 Msg
.message
= WM_XBUTTONDOWN
;
407 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
409 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_RBUTTON
: ~MK_LBUTTON
);
410 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONUP
: WM_LBUTTONUP
);
412 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
414 CurInfo
->ButtonsDown
&= ~MK_MBUTTON
;
415 Msg
.message
= WM_MBUTTONUP
;
417 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
419 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_LBUTTON
: ~MK_RBUTTON
);
420 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONUP
: WM_RBUTTONUP
);
422 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_UP
) > 0)
424 CurInfo
->ButtonsDown
&= ~MK_XBUTTON1
;
425 Msg
.message
= WM_XBUTTONUP
;
427 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_UP
) > 0)
429 CurInfo
->ButtonsDown
&= ~MK_XBUTTON2
;
430 Msg
.message
= WM_XBUTTONUP
;
432 if ((Data
[i
].ButtonFlags
& MOUSE_WHEEL
) > 0)
434 dScroll
+= (LONG
)Data
[i
].ButtonData
;
437 if (Data
[i
].ButtonFlags
!= MOUSE_WHEEL
)
439 Moved
= (0 != mouse_cx
) || (0 != mouse_cy
);
440 if(Moved
&& MouseEnabled
)
442 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
443 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
445 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
446 IntLockGDIDriver(SurfGDI
);
447 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
448 IntUnLockGDIDriver(SurfGDI
);
449 SetPointerRect(CurInfo
, &PointerRect
);
450 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
456 Msg
.wParam
= CurInfo
->ButtonsDown
;
457 MsqInsertSystemMessage(&Msg
, FALSE
);
462 /* If the mouse moved then move the pointer. */
463 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
465 Msg
.wParam
= CurInfo
->ButtonsDown
;
466 Msg
.message
= WM_MOUSEMOVE
;
467 Msg
.pt
.x
= CurInfo
->x
;
468 Msg
.pt
.y
= CurInfo
->y
;
469 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
470 MsqInsertSystemMessage(&Msg
, TRUE
);
472 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
473 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
475 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
476 IntLockGDIDriver(SurfGDI
);
477 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
478 IntUnLockGDIDriver(SurfGDI
);
479 SetPointerRect(CurInfo
, &PointerRect
);
480 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
484 /* send WM_MOUSEWHEEL message */
485 if(dScroll
&& MouseEnabled
)
487 Msg
.message
= WM_MOUSEWHEEL
;
488 Msg
.wParam
= MAKEWPARAM(CurInfo
->ButtonsDown
, dScroll
);
489 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
490 Msg
.pt
.x
= CurInfo
->x
;
491 Msg
.pt
.y
= CurInfo
->y
;
492 MsqInsertSystemMessage(&Msg
, FALSE
);
495 ObDereferenceObject(InputWindowStation
);
499 EnableMouse(HDC hDisplayDC
)
505 if( hDisplayDC
&& InputWindowStation
)
507 if(!IntGetWindowStationObject(InputWindowStation
))
509 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
513 dc
= DC_LockDc(hDisplayDC
);
514 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
515 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
516 DC_UnlockDc( hDisplayDC
);
518 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
520 InputWindowStation
->SystemCursor
.Enabled
= (SPS_ACCEPT_EXCLUDE
== SurfGDI
->PointerStatus
||
521 SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
);
523 /* Move the cursor to the screen center */
524 DPRINT("Setting Cursor up at 0x%x, 0x%x\n", SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
525 MouseMoveCursor(SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
527 ObDereferenceObject(InputWindowStation
);
531 if(IntGetWindowStationObject(InputWindowStation
))
533 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
534 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
535 InputWindowStation
->SystemCursor
.CursorClipInfo
.IsClipped
= FALSE
;
536 ObDereferenceObject(InputWindowStation
);
542 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
545 IntHideMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
547 if (ppdev
->PointerAttributes
.Enable
== FALSE
)
552 ppdev
->PointerAttributes
.Enable
= FALSE
;
554 if (ppdev
->PointerAttributes
.Column
+ ppdev
->PointerHotSpot
.x
== -1)
559 if (ppdev
->PointerSaveSurface
!= NULL
)
563 SURFOBJ
*SaveSurface
;
564 SURFOBJ
*MaskSurface
;
566 DestRect
.left
= max(ppdev
->PointerAttributes
.Column
, 0);
567 DestRect
.top
= max(ppdev
->PointerAttributes
.Row
, 0);
568 DestRect
.right
= min(
569 ppdev
->PointerAttributes
.Column
+ ppdev
->PointerAttributes
.Width
,
570 DestSurface
->sizlBitmap
.cx
);
571 DestRect
.bottom
= min(
572 ppdev
->PointerAttributes
.Row
+ ppdev
->PointerAttributes
.Height
,
573 DestSurface
->sizlBitmap
.cy
);
575 SrcPoint
.x
= max(-ppdev
->PointerAttributes
.Column
, 0);
576 SrcPoint
.y
= max(-ppdev
->PointerAttributes
.Row
, 0);
578 SaveSurface
= EngLockSurface(ppdev
->PointerSaveSurface
);
579 MaskSurface
= EngLockSurface(ppdev
->PointerMaskSurface
);
580 EngBitBlt(DestSurface
, SaveSurface
, MaskSurface
, NULL
, NULL
,
581 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, SRCCOPY
);
582 EngUnlockSurface(MaskSurface
);
583 EngUnlockSurface(SaveSurface
);
588 IntShowMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
590 if (ppdev
->PointerAttributes
.Enable
== TRUE
)
595 ppdev
->PointerAttributes
.Enable
= TRUE
;
598 * Copy the pixels under the cursor to temporary surface.
601 if (ppdev
->PointerSaveSurface
!= NULL
)
605 SURFOBJ
*SaveSurface
;
607 SrcPoint
.x
= max(ppdev
->PointerAttributes
.Column
, 0);
608 SrcPoint
.y
= max(ppdev
->PointerAttributes
.Row
, 0);
610 DestRect
.left
= SrcPoint
.x
- ppdev
->PointerAttributes
.Column
;
611 DestRect
.top
= SrcPoint
.y
- ppdev
->PointerAttributes
.Row
;
612 DestRect
.right
= min(
613 ppdev
->PointerAttributes
.Width
,
614 DestSurface
->sizlBitmap
.cx
- ppdev
->PointerAttributes
.Column
);
615 DestRect
.bottom
= min(
616 ppdev
->PointerAttributes
.Height
,
617 DestSurface
->sizlBitmap
.cy
- ppdev
->PointerAttributes
.Row
);
619 SaveSurface
= EngLockSurface(ppdev
->PointerSaveSurface
);
620 EngBitBlt(SaveSurface
, DestSurface
, NULL
, NULL
, NULL
,
621 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCCOPY
);
622 EngUnlockSurface(SaveSurface
);
626 * Blit the cursor on the screen.
635 DestRect
.left
= max(ppdev
->PointerAttributes
.Column
, 0);
636 DestRect
.top
= max(ppdev
->PointerAttributes
.Row
, 0);
637 DestRect
.right
= min(
638 ppdev
->PointerAttributes
.Column
+ ppdev
->PointerAttributes
.Width
,
639 DestSurface
->sizlBitmap
.cx
);
640 DestRect
.bottom
= min(
641 ppdev
->PointerAttributes
.Row
+ ppdev
->PointerAttributes
.Height
,
642 DestSurface
->sizlBitmap
.cy
);
644 SrcPoint
.x
= max(-ppdev
->PointerAttributes
.Column
, 0);
645 SrcPoint
.y
= max(-ppdev
->PointerAttributes
.Row
, 0);
647 MaskSurf
= EngLockSurface(ppdev
->PointerMaskSurface
);
648 if (ppdev
->PointerColorSurface
!= NULL
)
650 ColorSurf
= EngLockSurface(ppdev
->PointerColorSurface
);
651 EngBitBlt(DestSurface
, ColorSurf
, MaskSurf
, NULL
, ppdev
->PointerXlateObject
,
652 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, 0xAACC);
653 EngUnlockSurface(ColorSurf
);
657 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, ppdev
->PointerXlateObject
,
658 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCAND
);
659 SrcPoint
.y
+= ppdev
->PointerAttributes
.Height
;
660 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, ppdev
->PointerXlateObject
,
661 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCINVERT
);
663 EngUnlockSurface(MaskSurf
);
675 IN SURFOBJ
*psoColor
,
684 GDIDEVICE
*ppdev
= (GDIDEVICE
*)pso
->hdev
;
685 SURFOBJ
*TempSurfObj
;
687 IntHideMousePointer(ppdev
, pso
);
689 if (ppdev
->PointerColorSurface
!= NULL
)
691 /* FIXME: Is this really needed? */
692 TempSurfObj
= EngLockSurface(ppdev
->PointerColorSurface
);
693 EngFreeMem(TempSurfObj
->pvBits
);
694 TempSurfObj
->pvBits
= 0;
695 EngUnlockSurface(TempSurfObj
);
697 EngDeleteSurface(ppdev
->PointerColorSurface
);
698 ppdev
->PointerMaskSurface
= NULL
;
701 if (ppdev
->PointerMaskSurface
!= NULL
)
703 /* FIXME: Is this really needed? */
704 TempSurfObj
= EngLockSurface(ppdev
->PointerMaskSurface
);
705 EngFreeMem(TempSurfObj
->pvBits
);
706 TempSurfObj
->pvBits
= 0;
707 EngUnlockSurface(TempSurfObj
);
709 EngDeleteSurface(ppdev
->PointerMaskSurface
);
710 ppdev
->PointerMaskSurface
= NULL
;
713 if (ppdev
->PointerSaveSurface
!= NULL
)
715 EngDeleteSurface(ppdev
->PointerSaveSurface
);
716 ppdev
->PointerSaveSurface
= NULL
;
719 if (ppdev
->PointerXlateObject
!= NULL
)
721 EngDeleteXlate(ppdev
->PointerXlateObject
);
722 ppdev
->PointerXlateObject
= NULL
;
726 * See if we are being asked to hide the pointer.
731 return SPS_ACCEPT_NOEXCLUDE
;
734 ppdev
->PointerHotSpot
.x
= xHot
;
735 ppdev
->PointerHotSpot
.y
= yHot
;
737 ppdev
->PointerAttributes
.Column
= x
- xHot
;
738 ppdev
->PointerAttributes
.Row
= y
- yHot
;
739 ppdev
->PointerAttributes
.Width
= psoMask
->lDelta
<< 3;
740 ppdev
->PointerAttributes
.Height
= (psoMask
->cjBits
/ psoMask
->lDelta
) >> 1;
744 prcl
->left
= ppdev
->PointerAttributes
.Column
;
745 prcl
->top
= ppdev
->PointerAttributes
.Row
;
746 prcl
->right
= prcl
->left
+ ppdev
->PointerAttributes
.Width
;
747 prcl
->bottom
= prcl
->top
+ ppdev
->PointerAttributes
.Height
;
750 if (psoColor
!= NULL
)
755 Size
.cx
= ppdev
->PointerAttributes
.Width
;
756 Size
.cy
= ppdev
->PointerAttributes
.Height
;
757 Bits
= EngAllocMem(0, psoColor
->cjBits
, TAG_MOUSE
);
758 memcpy(Bits
, psoColor
->pvBits
, psoColor
->cjBits
);
760 ppdev
->PointerColorSurface
= (HSURF
)EngCreateBitmap(Size
,
761 psoColor
->lDelta
, psoColor
->iBitmapFormat
, 0, Bits
);
765 ppdev
->PointerColorSurface
= NULL
;
772 Size
.cx
= ppdev
->PointerAttributes
.Width
;
773 Size
.cy
= ppdev
->PointerAttributes
.Height
<< 1;
774 Bits
= EngAllocMem(0, psoMask
->cjBits
, TAG_MOUSE
);
775 memcpy(Bits
, psoMask
->pvBits
, psoMask
->cjBits
);
777 ppdev
->PointerMaskSurface
= (HSURF
)EngCreateBitmap(Size
,
778 psoMask
->lDelta
, psoMask
->iBitmapFormat
, 0, Bits
);
782 * Create and XLATEOBJ that will be used for drawing masks.
783 * FIXME: We should get this in pxlo parameter!
788 HPALETTE BWPalette
, DestPalette
;
789 ULONG BWColors
[] = {0, 0xFFFFFF};
794 BWPalette
= EngCreatePalette(PAL_INDEXED
, sizeof(BWColors
) / sizeof(ULONG
),
796 Dc
= DC_LockDc(IntGetScreenDC());
797 DestPalette
= Dc
->w
.hPalette
;
798 PalObj
= PALETTE_LockPalette(DestPalette
);
799 DestMode
= PalObj
->Mode
;
800 PALETTE_UnlockPalette(DestPalette
);
801 DC_UnlockDc(IntGetScreenDC());
802 ppdev
->PointerXlateObject
= IntEngCreateXlate(DestMode
, PAL_INDEXED
,
803 DestPalette
, BWPalette
);
804 EngDeletePalette(BWPalette
);
808 ppdev
->PointerXlateObject
= pxlo
;
812 * Create surface for saving the pixels under the cursor.
819 Size
.cx
= ppdev
->PointerAttributes
.Width
;
820 Size
.cy
= ppdev
->PointerAttributes
.Height
;
822 switch (pso
->iBitmapFormat
)
824 case BMF_1BPP
: lDelta
= Size
.cx
>> 3; break;
825 case BMF_4BPP
: lDelta
= Size
.cx
>> 1; break;
826 case BMF_8BPP
: lDelta
= Size
.cx
; break;
827 case BMF_16BPP
: lDelta
= Size
.cx
<< 1; break;
828 case BMF_24BPP
: lDelta
= Size
.cx
* 3; break;
829 case BMF_32BPP
: lDelta
= Size
.cx
<< 2; break;
832 ppdev
->PointerSaveSurface
= (HSURF
)EngCreateBitmap(
833 Size
, lDelta
, pso
->iBitmapFormat
, BMF_NOZEROINIT
, NULL
);
836 IntShowMousePointer(ppdev
, pso
);
838 return SPS_ACCEPT_EXCLUDE
;
852 GDIDEVICE
*ppdev
= (GDIDEVICE
*)pso
->hdev
;
854 IntHideMousePointer(ppdev
, pso
);
855 ppdev
->PointerAttributes
.Column
= x
- ppdev
->PointerHotSpot
.x
;
856 ppdev
->PointerAttributes
.Row
= y
- ppdev
->PointerHotSpot
.y
;
859 IntShowMousePointer(ppdev
, pso
);
864 prcl
->left
= ppdev
->PointerAttributes
.Column
;
865 prcl
->top
= ppdev
->PointerAttributes
.Row
;
866 prcl
->right
= prcl
->left
+ ppdev
->PointerAttributes
.Width
;
867 prcl
->bottom
= prcl
->top
+ ppdev
->PointerAttributes
.Height
;