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.61 2004/02/19 21:12:09 weiden 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 IntCheckClipCursor(LONG
*x
, LONG
*y
, PSYSTEM_CURSORINFO CurInfo
)
59 if(CurInfo
->CursorClipInfo
.IsClipped
)
61 if(*x
> CurInfo
->CursorClipInfo
.Right
)
62 *x
= CurInfo
->CursorClipInfo
.Right
;
63 if(*x
< CurInfo
->CursorClipInfo
.Left
)
64 *x
= CurInfo
->CursorClipInfo
.Left
;
65 if(*y
> CurInfo
->CursorClipInfo
.Bottom
)
66 *y
= CurInfo
->CursorClipInfo
.Bottom
;
67 if(*y
< CurInfo
->CursorClipInfo
.Top
)
68 *y
= CurInfo
->CursorClipInfo
.Top
;
75 IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject
, BOOL Swap
)
77 BOOL res
= WinStaObject
->SystemCursor
.SwapButtons
;
78 WinStaObject
->SystemCursor
.SwapButtons
= Swap
;
83 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
84 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
86 * FUNCTION: Notify the mouse driver that drawing is about to begin in
87 * a rectangle on a particular surface.
91 PSYSTEM_CURSORINFO CurInfo
;
92 BOOL MouseEnabled
= FALSE
;
93 PCURICON_OBJECT Cursor
;
96 /* Mouse is not allowed to move if GDI is busy drawing */
98 if(IntGetWindowStationObject(InputWindowStation
))
100 CurInfo
= &InputWindowStation
->SystemCursor
;
102 MouseEnabled
= CurInfo
->Enabled
&& CurInfo
->ShowingCursor
;
109 ObDereferenceObject(InputWindowStation
);
114 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
116 ObDereferenceObject(InputWindowStation
);
120 if (SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
)
122 /* Hardware cursor, no need to remove it */
123 ObDereferenceObject(InputWindowStation
);
127 if(!(Cursor
= CurInfo
->CurrentCursorObject
))
129 ObDereferenceObject(InputWindowStation
);
133 if (HazardX1
> HazardX2
)
135 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
137 if (HazardY1
> HazardY2
)
139 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
142 if (CurInfo
->PointerRectRight
>= HazardX1
143 && CurInfo
->PointerRectLeft
<= HazardX2
144 && CurInfo
->PointerRectBottom
>= HazardY1
145 && CurInfo
->PointerRectTop
<= HazardY2
)
147 /* Mouse is not allowed to move if GDI is busy drawing */
148 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
149 if (0 != CurInfo
->SafetyRemoveCount
++)
151 /* Was already removed */
152 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
153 ObDereferenceObject(InputWindowStation
);
156 CurInfo
->SafetySwitch
= TRUE
;
157 ExAcquireFastMutex(SurfGDI
->DriverLock
);
158 SurfGDI
->MovePointer(SurfObj
, -1, -1, NULL
);
159 ExReleaseFastMutex(SurfGDI
->DriverLock
);
160 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
163 ObDereferenceObject(InputWindowStation
);
168 SetPointerRect(PSYSTEM_CURSORINFO CurInfo
, PRECTL PointerRect
)
170 CurInfo
->PointerRectLeft
= PointerRect
->left
;
171 CurInfo
->PointerRectRight
= PointerRect
->right
;
172 CurInfo
->PointerRectTop
= PointerRect
->top
;
173 CurInfo
->PointerRectBottom
= PointerRect
->bottom
;
177 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
179 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
182 PSYSTEM_CURSORINFO CurInfo
;
183 BOOL MouseEnabled
= FALSE
;
186 if(IntGetWindowStationObject(InputWindowStation
))
188 CurInfo
= &InputWindowStation
->SystemCursor
;
193 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
196 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
197 ObDereferenceObject(InputWindowStation
);
201 MouseEnabled
= CurInfo
->Enabled
&& CurInfo
->ShowingCursor
;
203 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
205 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
206 ObDereferenceObject(InputWindowStation
);
210 if (SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
)
212 /* Hardware cursor, it wasn't removed so need to restore it */
213 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
214 ObDereferenceObject(InputWindowStation
);
218 if (CurInfo
->SafetySwitch
)
220 if (1 < CurInfo
->SafetyRemoveCount
--)
222 /* Someone else removed it too, let them restore it */
223 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
224 ObDereferenceObject(InputWindowStation
);
227 ExAcquireFastMutex(SurfGDI
->DriverLock
);
228 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
229 ExReleaseFastMutex(SurfGDI
->DriverLock
);
230 SetPointerRect(CurInfo
, &PointerRect
);
231 CurInfo
->SafetySwitch
= FALSE
;
234 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
235 ObDereferenceObject(InputWindowStation
);
240 MouseMoveCursor(LONG X
, LONG Y
)
247 PSYSTEM_CURSORINFO CurInfo
;
249 LARGE_INTEGER LargeTickCount
;
253 if(!InputWindowStation
)
256 if(IntGetWindowStationObject(InputWindowStation
))
258 CurInfo
= &InputWindowStation
->SystemCursor
;
259 if(!CurInfo
->Enabled
)
261 ObDereferenceObject(InputWindowStation
);
264 hDC
= IntGetScreenDC();
267 ObDereferenceObject(InputWindowStation
);
271 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
272 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
274 IntCheckClipCursor(&X
, &Y
, CurInfo
);
275 if((X
!= CurInfo
->x
) || (Y
!= CurInfo
->y
))
282 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
283 ExAcquireFastMutex(SurfGDI
->DriverLock
);
284 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
285 ExReleaseFastMutex(SurfGDI
->DriverLock
);
286 SetPointerRect(CurInfo
, &PointerRect
);
287 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
289 /* send MOUSEMOVE message */
290 KeQueryTickCount(&LargeTickCount
);
291 TickCount
= LargeTickCount
.u
.LowPart
;
292 Msg
.wParam
= CurInfo
->ButtonsDown
;
293 Msg
.lParam
= MAKELPARAM(X
, Y
);
294 Msg
.message
= WM_MOUSEMOVE
;
295 Msg
.time
= TickCount
;
298 MsqInsertSystemMessage(&Msg
, TRUE
);
302 ObDereferenceObject(InputWindowStation
);
310 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
312 * FUNCTION: Call by the mouse driver when input events occur.
316 PSYSTEM_CURSORINFO CurInfo
;
317 BOOL MouseEnabled
= FALSE
;
319 LONG mouse_ox
, mouse_oy
;
320 LONG mouse_cx
= 0, mouse_cy
= 0;
329 hDC
= IntGetScreenDC();
331 if(!hDC
|| !InputWindowStation
)
334 if(IntGetWindowStationObject(InputWindowStation
))
336 CurInfo
= &InputWindowStation
->SystemCursor
;
337 MouseEnabled
= CurInfo
->Enabled
;
340 ObDereferenceObject(InputWindowStation
);
343 mouse_ox
= CurInfo
->x
;
344 mouse_oy
= CurInfo
->y
;
350 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
351 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
354 /* Compile the total mouse movement change and dispatch button events. */
355 for (i
= 0; i
< InputCount
; i
++)
357 mouse_cx
+= Data
[i
].LastX
;
358 mouse_cy
+= Data
[i
].LastY
;
360 CurInfo
->x
+= Data
[i
].LastX
;
361 CurInfo
->y
+= Data
[i
].LastY
;
363 CurInfo
->x
= max(CurInfo
->x
, 0);
364 CurInfo
->y
= max(CurInfo
->y
, 0);
365 CurInfo
->x
= min(CurInfo
->x
, SurfObj
->sizlBitmap
.cx
- 1);
366 CurInfo
->y
= min(CurInfo
->y
, SurfObj
->sizlBitmap
.cy
- 1);
368 IntCheckClipCursor(&CurInfo
->x
, &CurInfo
->y
, CurInfo
);
370 Msg
.wParam
= CurInfo
->ButtonsDown
;
371 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
372 Msg
.message
= WM_MOUSEMOVE
;
373 Msg
.pt
.x
= CurInfo
->x
;
374 Msg
.pt
.y
= CurInfo
->y
;
376 if (Data
[i
].ButtonFlags
!= 0)
378 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
380 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_RBUTTON
: MK_LBUTTON
);
381 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONDOWN
: WM_LBUTTONDOWN
);
383 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
385 CurInfo
->ButtonsDown
|= MK_MBUTTON
;
386 Msg
.message
= WM_MBUTTONDOWN
;
388 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
390 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_LBUTTON
: MK_RBUTTON
);
391 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONDOWN
: WM_RBUTTONDOWN
);
394 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_DOWN
) > 0)
396 CurInfo
->ButtonsDown
|= MK_XBUTTON1
;
397 Msg
.message
= WM_XBUTTONDOWN
;
399 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_DOWN
) > 0)
401 CurInfo
->ButtonsDown
|= MK_XBUTTON2
;
402 Msg
.message
= WM_XBUTTONDOWN
;
405 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
407 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_RBUTTON
: ~MK_LBUTTON
);
408 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONUP
: WM_LBUTTONUP
);
410 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
412 CurInfo
->ButtonsDown
&= ~MK_MBUTTON
;
413 Msg
.message
= WM_MBUTTONUP
;
415 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
417 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_LBUTTON
: ~MK_RBUTTON
);
418 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONUP
: WM_RBUTTONUP
);
420 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_UP
) > 0)
422 CurInfo
->ButtonsDown
&= ~MK_XBUTTON1
;
423 Msg
.message
= WM_XBUTTONUP
;
425 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_UP
) > 0)
427 CurInfo
->ButtonsDown
&= ~MK_XBUTTON2
;
428 Msg
.message
= WM_XBUTTONUP
;
430 if ((Data
[i
].ButtonFlags
& MOUSE_WHEEL
) > 0)
432 dScroll
+= (LONG
)Data
[i
].ButtonData
;
435 if (Data
[i
].ButtonFlags
!= MOUSE_WHEEL
)
437 Moved
= (0 != mouse_cx
) || (0 != mouse_cy
);
438 if(Moved
&& MouseEnabled
)
440 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
441 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
443 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
444 ExAcquireFastMutex(SurfGDI
->DriverLock
);
445 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
446 ExReleaseFastMutex(SurfGDI
->DriverLock
);
447 SetPointerRect(CurInfo
, &PointerRect
);
448 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
454 Msg
.wParam
= CurInfo
->ButtonsDown
;
455 MsqInsertSystemMessage(&Msg
, FALSE
);
460 /* If the mouse moved then move the pointer. */
461 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
463 Msg
.wParam
= CurInfo
->ButtonsDown
;
464 Msg
.message
= WM_MOUSEMOVE
;
465 Msg
.pt
.x
= CurInfo
->x
;
466 Msg
.pt
.y
= CurInfo
->y
;
467 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
468 MsqInsertSystemMessage(&Msg
, TRUE
);
470 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
471 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
473 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
474 ExAcquireFastMutex(SurfGDI
->DriverLock
);
475 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
476 ExReleaseFastMutex(SurfGDI
->DriverLock
);
477 SetPointerRect(CurInfo
, &PointerRect
);
478 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
482 /* send WM_MOUSEWHEEL message */
483 if(dScroll
&& MouseEnabled
)
485 Msg
.message
= WM_MOUSEWHEEL
;
486 Msg
.wParam
= MAKEWPARAM(CurInfo
->ButtonsDown
, dScroll
);
487 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
488 Msg
.pt
.x
= CurInfo
->x
;
489 Msg
.pt
.y
= CurInfo
->y
;
490 MsqInsertSystemMessage(&Msg
, FALSE
);
493 ObDereferenceObject(InputWindowStation
);
497 EnableMouse(HDC hDisplayDC
)
503 if( hDisplayDC
&& InputWindowStation
)
505 if(!IntGetWindowStationObject(InputWindowStation
))
507 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
511 dc
= DC_LockDc(hDisplayDC
);
512 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
513 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
514 DC_UnlockDc( hDisplayDC
);
516 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
518 InputWindowStation
->SystemCursor
.Enabled
= (SPS_ACCEPT_EXCLUDE
== SurfGDI
->PointerStatus
||
519 SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
);
521 /* Move the cursor to the screen center */
522 DPRINT("Setting Cursor up at 0x%x, 0x%x\n", SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
523 MouseMoveCursor(SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
525 ObDereferenceObject(InputWindowStation
);
529 if(IntGetWindowStationObject(InputWindowStation
))
531 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
532 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
533 InputWindowStation
->SystemCursor
.CursorClipInfo
.IsClipped
= FALSE
;
534 ObDereferenceObject(InputWindowStation
);
540 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
543 IntHideMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
545 if (ppdev
->PointerAttributes
.Enable
== FALSE
)
550 ppdev
->PointerAttributes
.Enable
= FALSE
;
552 if (ppdev
->PointerAttributes
.Column
+ ppdev
->PointerHotSpot
.x
== -1)
557 if (ppdev
->PointerSaveSurface
!= NULL
)
561 SURFOBJ
*SaveSurface
;
562 SURFOBJ
*MaskSurface
;
564 DestRect
.left
= max(ppdev
->PointerAttributes
.Column
, 0);
565 DestRect
.top
= max(ppdev
->PointerAttributes
.Row
, 0);
566 DestRect
.right
= min(
567 ppdev
->PointerAttributes
.Column
+ ppdev
->PointerAttributes
.Width
,
568 DestSurface
->sizlBitmap
.cx
);
569 DestRect
.bottom
= min(
570 ppdev
->PointerAttributes
.Row
+ ppdev
->PointerAttributes
.Height
,
571 DestSurface
->sizlBitmap
.cy
);
573 SrcPoint
.x
= max(-ppdev
->PointerAttributes
.Column
, 0);
574 SrcPoint
.y
= max(-ppdev
->PointerAttributes
.Row
, 0);
576 SaveSurface
= EngLockSurface(ppdev
->PointerSaveSurface
);
577 MaskSurface
= EngLockSurface(ppdev
->PointerMaskSurface
);
578 EngBitBlt(DestSurface
, SaveSurface
, MaskSurface
, NULL
, NULL
,
579 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, SRCCOPY
);
580 EngUnlockSurface(MaskSurface
);
581 EngUnlockSurface(SaveSurface
);
586 IntShowMousePointer(GDIDEVICE
*ppdev
, SURFOBJ
*DestSurface
)
588 if (ppdev
->PointerAttributes
.Enable
== TRUE
)
593 ppdev
->PointerAttributes
.Enable
= TRUE
;
596 * Copy the pixels under the cursor to temporary surface.
599 if (ppdev
->PointerSaveSurface
!= NULL
)
603 SURFOBJ
*SaveSurface
;
605 SrcPoint
.x
= max(ppdev
->PointerAttributes
.Column
, 0);
606 SrcPoint
.y
= max(ppdev
->PointerAttributes
.Row
, 0);
608 DestRect
.left
= SrcPoint
.x
- ppdev
->PointerAttributes
.Column
;
609 DestRect
.top
= SrcPoint
.y
- ppdev
->PointerAttributes
.Row
;
610 DestRect
.right
= min(
611 ppdev
->PointerAttributes
.Width
,
612 DestSurface
->sizlBitmap
.cx
- ppdev
->PointerAttributes
.Column
);
613 DestRect
.bottom
= min(
614 ppdev
->PointerAttributes
.Height
,
615 DestSurface
->sizlBitmap
.cy
- ppdev
->PointerAttributes
.Row
);
617 SaveSurface
= EngLockSurface(ppdev
->PointerSaveSurface
);
618 EngBitBlt(SaveSurface
, DestSurface
, NULL
, NULL
, NULL
,
619 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCCOPY
);
620 EngUnlockSurface(SaveSurface
);
624 * Blit the cursor on the screen.
633 DestRect
.left
= max(ppdev
->PointerAttributes
.Column
, 0);
634 DestRect
.top
= max(ppdev
->PointerAttributes
.Row
, 0);
635 DestRect
.right
= min(
636 ppdev
->PointerAttributes
.Column
+ ppdev
->PointerAttributes
.Width
,
637 DestSurface
->sizlBitmap
.cx
);
638 DestRect
.bottom
= min(
639 ppdev
->PointerAttributes
.Row
+ ppdev
->PointerAttributes
.Height
,
640 DestSurface
->sizlBitmap
.cy
);
642 SrcPoint
.x
= max(-ppdev
->PointerAttributes
.Column
, 0);
643 SrcPoint
.y
= max(-ppdev
->PointerAttributes
.Row
, 0);
645 MaskSurf
= EngLockSurface(ppdev
->PointerMaskSurface
);
646 if (ppdev
->PointerColorSurface
!= NULL
)
648 ColorSurf
= EngLockSurface(ppdev
->PointerColorSurface
);
649 EngBitBlt(DestSurface
, ColorSurf
, MaskSurf
, NULL
, ppdev
->PointerXlateObject
,
650 &DestRect
, &SrcPoint
, &SrcPoint
, NULL
, NULL
, 0xAACC);
651 EngUnlockSurface(ColorSurf
);
655 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, ppdev
->PointerXlateObject
,
656 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCAND
);
657 SrcPoint
.y
+= ppdev
->PointerAttributes
.Height
;
658 EngBitBlt(DestSurface
, MaskSurf
, NULL
, NULL
, ppdev
->PointerXlateObject
,
659 &DestRect
, &SrcPoint
, NULL
, NULL
, NULL
, SRCINVERT
);
661 EngUnlockSurface(MaskSurf
);
673 IN SURFOBJ
*psoColor
,
682 GDIDEVICE
*ppdev
= (GDIDEVICE
*)pso
->hdev
;
683 SURFOBJ
*TempSurfObj
;
685 IntHideMousePointer(ppdev
, pso
);
687 if (ppdev
->PointerColorSurface
!= NULL
)
689 /* FIXME: Is this really needed? */
690 TempSurfObj
= EngLockSurface(ppdev
->PointerColorSurface
);
691 EngFreeMem(TempSurfObj
->pvBits
);
692 TempSurfObj
->pvBits
= 0;
693 EngUnlockSurface(TempSurfObj
);
695 EngDeleteSurface(ppdev
->PointerColorSurface
);
696 ppdev
->PointerMaskSurface
= NULL
;
699 if (ppdev
->PointerMaskSurface
!= NULL
)
701 /* FIXME: Is this really needed? */
702 TempSurfObj
= EngLockSurface(ppdev
->PointerMaskSurface
);
703 EngFreeMem(TempSurfObj
->pvBits
);
704 TempSurfObj
->pvBits
= 0;
705 EngUnlockSurface(TempSurfObj
);
707 EngDeleteSurface(ppdev
->PointerMaskSurface
);
708 ppdev
->PointerMaskSurface
= NULL
;
711 if (ppdev
->PointerSaveSurface
!= NULL
)
713 EngDeleteSurface(ppdev
->PointerSaveSurface
);
714 ppdev
->PointerSaveSurface
= NULL
;
717 if (ppdev
->PointerXlateObject
!= NULL
)
719 EngDeleteXlate(ppdev
->PointerXlateObject
);
720 ppdev
->PointerXlateObject
= NULL
;
724 * See if we are being asked to hide the pointer.
729 return SPS_ACCEPT_NOEXCLUDE
;
732 ppdev
->PointerHotSpot
.x
= xHot
;
733 ppdev
->PointerHotSpot
.y
= yHot
;
735 ppdev
->PointerAttributes
.Column
= x
- xHot
;
736 ppdev
->PointerAttributes
.Row
= y
- yHot
;
737 ppdev
->PointerAttributes
.Width
= psoMask
->lDelta
<< 3;
738 ppdev
->PointerAttributes
.Height
= (psoMask
->cjBits
/ psoMask
->lDelta
) >> 1;
742 prcl
->left
= ppdev
->PointerAttributes
.Column
;
743 prcl
->top
= ppdev
->PointerAttributes
.Row
;
744 prcl
->right
= prcl
->left
+ ppdev
->PointerAttributes
.Width
;
745 prcl
->bottom
= prcl
->top
+ ppdev
->PointerAttributes
.Height
;
748 if (psoColor
!= NULL
)
753 Size
.cx
= ppdev
->PointerAttributes
.Width
;
754 Size
.cy
= ppdev
->PointerAttributes
.Height
;
755 Bits
= EngAllocMem(0, psoColor
->cjBits
, TAG_MOUSE
);
756 memcpy(Bits
, psoColor
->pvBits
, psoColor
->cjBits
);
758 ppdev
->PointerColorSurface
= (HSURF
)EngCreateBitmap(Size
,
759 psoColor
->lDelta
, psoColor
->iBitmapFormat
, 0, Bits
);
763 ppdev
->PointerColorSurface
= NULL
;
770 Size
.cx
= ppdev
->PointerAttributes
.Width
;
771 Size
.cy
= ppdev
->PointerAttributes
.Height
<< 1;
772 Bits
= EngAllocMem(0, psoMask
->cjBits
, TAG_MOUSE
);
773 memcpy(Bits
, psoMask
->pvBits
, psoMask
->cjBits
);
775 ppdev
->PointerMaskSurface
= (HSURF
)EngCreateBitmap(Size
,
776 psoMask
->lDelta
, psoMask
->iBitmapFormat
, 0, Bits
);
780 * Create and XLATEOBJ that will be used for drawing masks.
781 * FIXME: We should get this in pxlo parameter!
786 HPALETTE BWPalette
, DestPalette
;
787 ULONG BWColors
[] = {0, 0xFFFFFF};
792 BWPalette
= EngCreatePalette(PAL_INDEXED
, sizeof(BWColors
) / sizeof(ULONG
),
794 Dc
= DC_LockDc(IntGetScreenDC());
795 DestPalette
= Dc
->w
.hPalette
;
796 PalObj
= PALETTE_LockPalette(DestPalette
);
797 DestMode
= PalObj
->Mode
;
798 PALETTE_UnlockPalette(DestPalette
);
799 DC_UnlockDc(IntGetScreenDC());
800 ppdev
->PointerXlateObject
= IntEngCreateXlate(DestMode
, PAL_INDEXED
,
801 DestPalette
, BWPalette
);
802 EngDeletePalette(BWPalette
);
806 ppdev
->PointerXlateObject
= pxlo
;
810 * Create surface for saving the pixels under the cursor.
817 Size
.cx
= ppdev
->PointerAttributes
.Width
;
818 Size
.cy
= ppdev
->PointerAttributes
.Height
;
820 switch (pso
->iBitmapFormat
)
822 case BMF_1BPP
: lDelta
= Size
.cx
>> 3; break;
823 case BMF_4BPP
: lDelta
= Size
.cx
>> 1; break;
824 case BMF_8BPP
: lDelta
= Size
.cx
; break;
825 case BMF_16BPP
: lDelta
= Size
.cx
<< 1; break;
826 case BMF_24BPP
: lDelta
= Size
.cx
* 3; break;
827 case BMF_32BPP
: lDelta
= Size
.cx
<< 2; break;
830 ppdev
->PointerSaveSurface
= (HSURF
)EngCreateBitmap(
831 Size
, lDelta
, pso
->iBitmapFormat
, BMF_NOZEROINIT
, NULL
);
834 IntShowMousePointer(ppdev
, pso
);
836 return SPS_ACCEPT_EXCLUDE
;
850 GDIDEVICE
*ppdev
= (GDIDEVICE
*)pso
->hdev
;
851 PSURFGDI SurfGDI
= AccessInternalObjectFromUserObject(pso
);
854 * Prevent GDI from trying to remve the mouse cursor,
855 * because it would cause unexpected reentrancy effects.
858 SurfGDI
->PointerStatus
= SPS_ACCEPT_NOEXCLUDE
;
860 IntHideMousePointer(ppdev
, pso
);
861 ppdev
->PointerAttributes
.Column
= x
- ppdev
->PointerHotSpot
.x
;
862 ppdev
->PointerAttributes
.Row
= y
- ppdev
->PointerHotSpot
.y
;
865 IntShowMousePointer(ppdev
, pso
);
870 prcl
->left
= ppdev
->PointerAttributes
.Column
;
871 prcl
->top
= ppdev
->PointerAttributes
.Row
;
872 prcl
->right
= prcl
->left
+ ppdev
->PointerAttributes
.Width
;
873 prcl
->bottom
= prcl
->top
+ ppdev
->PointerAttributes
.Height
;
876 SurfGDI
->PointerStatus
= SPS_ACCEPT_EXCLUDE
;