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.43 2003/09/28 00:26:13 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/mouse.h>
45 #define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
47 /* GLOBALS *******************************************************************/
49 static ULONG PointerStatus
;
51 static UCHAR DefaultCursor
[256] = {
52 0x3F, 0xFF, 0xFF, 0xFF,
53 0x1F, 0xFF, 0xFF, 0xFF,
54 0x0F, 0xFF, 0xFF, 0xFF,
55 0x07, 0xFF, 0xFF, 0xFF,
56 0x03, 0xFF, 0xFF, 0xFF,
57 0x01, 0xFF, 0xFF, 0xFF,
58 0x00, 0xFF, 0xFF, 0xFF,
59 0x00, 0x7F, 0xFF, 0xFF,
60 0x00, 0x3F, 0xFF, 0xFF,
61 0x00, 0x1F, 0xFF, 0xFF,
62 0x00, 0x0F, 0xFF, 0xFF,
63 0x00, 0xFF, 0xFF, 0xFF,
64 0x00, 0xFF, 0xFF, 0xFF,
65 0x18, 0x7F, 0xFF, 0xFF,
66 0x38, 0x7F, 0xFF, 0xFF,
67 0x7C, 0x3F, 0xFF, 0xFF,
68 0xFC, 0x3F, 0xFF, 0xFF,
69 0xFE, 0x1F, 0xFF, 0xFF,
70 0xFE, 0x1F, 0xFF, 0xFF,
71 0xFF, 0x3F, 0xFF, 0xFF,
72 0xFF, 0xFF, 0xFF, 0xFF,
73 0xFF, 0xFF, 0xFF, 0xFF,
74 0xFF, 0xFF, 0xFF, 0xFF,
75 0xFF, 0xFF, 0xFF, 0xFF,
76 0xFF, 0xFF, 0xFF, 0xFF,
77 0xFF, 0xFF, 0xFF, 0xFF,
78 0xFF, 0xFF, 0xFF, 0xFF,
79 0xFF, 0xFF, 0xFF, 0xFF,
80 0xFF, 0xFF, 0xFF, 0xFF,
81 0xFF, 0xFF, 0xFF, 0xFF,
82 0xFF, 0xFF, 0xFF, 0xFF,
83 0xFF, 0xFF, 0xFF, 0xFF,
85 0x00, 0x00, 0x00, 0x00,
86 0x40, 0x00, 0x00, 0x00,
87 0x60, 0x00, 0x00, 0x00,
88 0x70, 0x00, 0x00, 0x00,
89 0x78, 0x00, 0x00, 0x00,
90 0x7C, 0x00, 0x00, 0x00,
91 0x7E, 0x00, 0x00, 0x00,
92 0x7F, 0x00, 0x00, 0x00,
93 0x7F, 0x80, 0x00, 0x00,
94 0x7F, 0xC0, 0x00, 0x00,
95 0x7E, 0x00, 0x00, 0x00,
96 0x76, 0x00, 0x00, 0x00,
97 0x76, 0x00, 0x00, 0x00,
98 0x43, 0x00, 0x00, 0x00,
99 0x03, 0x00, 0x00, 0x00,
100 0x01, 0x80, 0x00, 0x00,
101 0x01, 0x80, 0x00, 0x00,
102 0x00, 0xC0, 0x00, 0x00,
103 0x00, 0xC0, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00};
118 /* FUNCTIONS *****************************************************************/
121 IntCheckClipCursor(LONG
*x
, LONG
*y
, PSYSTEM_CURSORINFO CurInfo
)
123 if(CurInfo
->CursorClipInfo
.IsClipped
)
125 if(*x
> CurInfo
->CursorClipInfo
.Right
)
126 *x
= CurInfo
->CursorClipInfo
.Right
;
127 if(*x
< CurInfo
->CursorClipInfo
.Left
)
128 *x
= CurInfo
->CursorClipInfo
.Left
;
129 if(*y
> CurInfo
->CursorClipInfo
.Bottom
)
130 *y
= CurInfo
->CursorClipInfo
.Bottom
;
131 if(*y
< CurInfo
->CursorClipInfo
.Top
)
132 *y
= CurInfo
->CursorClipInfo
.Top
;
139 IntDetectDblClick(PSYSTEM_CURSORINFO CurInfo
, DWORD TickCount
)
142 BOOL res
= ((TickCount
- CurInfo
->LastBtnDown
) < CurInfo
->DblClickSpeed
);
145 /* check if the second click is within the DblClickWidth and DblClickHeight values */
146 dX
= CurInfo
->LastBtnDownX
- CurInfo
->x
;
147 dY
= CurInfo
->LastBtnDownY
- CurInfo
->y
;
151 res
= (dX
<= CurInfo
->DblClickWidth
) &&
152 (dY
<= CurInfo
->DblClickHeight
);
156 CurInfo
->LastBtnDown
= 0; /* prevent sending 2 or more DBLCLK messages */
157 CurInfo
->LastBtnDownX
= CurInfo
->x
;
158 CurInfo
->LastBtnDownY
= CurInfo
->y
;
162 CurInfo
->LastBtnDown
= TickCount
;
163 CurInfo
->LastBtnDownX
= CurInfo
->x
;
164 CurInfo
->LastBtnDownY
= CurInfo
->y
;
169 CurInfo
->LastBtnDown
= TickCount
;
170 CurInfo
->LastBtnDownX
= CurInfo
->x
;
171 CurInfo
->LastBtnDownY
= CurInfo
->y
;
177 IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject
, BOOL Swap
)
179 BOOL res
= WinStaObject
->SystemCursor
.SwapButtons
;
180 WinStaObject
->SystemCursor
.SwapButtons
= Swap
;
185 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
186 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
188 * FUNCTION: Notify the mouse driver that drawing is about to begin in
189 * a rectangle on a particular surface.
194 PSYSTEM_CURSORINFO CurInfo
;
195 PSYSCURSOR SysCursor
;
196 BOOL MouseEnabled
= FALSE
;
199 /* Mouse is not allowed to move if GDI is busy drawing */
201 if(IntGetWindowStationObject(InputWindowStation
))
203 CurInfo
= &InputWindowStation
->SystemCursor
;
205 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
206 MouseEnabled
= CurInfo
->Enabled
&& SysCursor
->hCursor
;
211 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
212 CurInfo
->SafetySwitch2
= TRUE
;
213 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
217 ObDereferenceObject(InputWindowStation
);
222 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
224 ObDereferenceObject(InputWindowStation
);
228 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
230 /* Hardware cursor, no need to remove it */
231 ObDereferenceObject(InputWindowStation
);
235 if (HazardX1
> HazardX2
)
237 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
239 if (HazardY1
> HazardY2
)
241 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
244 if (((CurInfo
->x
+ SysCursor
->cx
) >= HazardX1
) && (CurInfo
->x
<= HazardX2
) &&
245 ((CurInfo
->y
+ SysCursor
->cy
) >= HazardY1
) && (CurInfo
->y
<= HazardY2
))
247 /* Mouse is not allowed to move if GDI is busy drawing */
248 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
249 CurInfo
->SafetySwitch
= TRUE
;
250 SurfGDI
->MovePointer(SurfObj
, -1, -1, &MouseRect
);
251 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
254 ObDereferenceObject(InputWindowStation
);
259 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
261 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
265 PSYSTEM_CURSORINFO CurInfo
;
266 PSYSCURSOR SysCursor
;
267 BOOL MouseEnabled
= FALSE
;
269 if(IntGetWindowStationObject(InputWindowStation
))
271 CurInfo
= &InputWindowStation
->SystemCursor
;
278 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
279 CurInfo
->SafetySwitch2
= FALSE
;
280 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
281 ObDereferenceObject(InputWindowStation
);
285 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
286 MouseEnabled
= CurInfo
->Enabled
&& SysCursor
->hCursor
;
288 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
290 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
291 CurInfo
->SafetySwitch2
= FALSE
;
292 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
293 ObDereferenceObject(InputWindowStation
);
297 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
299 /* Hardware cursor, it wasn't removed so need to restore it */
300 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
301 CurInfo
->SafetySwitch2
= FALSE
;
302 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
303 ObDereferenceObject(InputWindowStation
);
307 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
308 if (CurInfo
->SafetySwitch
)
310 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &MouseRect
);
311 CurInfo
->SafetySwitch
= FALSE
;
312 CurInfo
->SafetySwitch2
= FALSE
;
316 CurInfo
->SafetySwitch2
= FALSE
;
318 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
319 ObDereferenceObject(InputWindowStation
);
324 MouseMoveCursor(LONG X
, LONG Y
)
332 PSYSTEM_CURSORINFO CurInfo
;
334 LARGE_INTEGER LargeTickCount
;
337 if(!InputWindowStation
)
340 if(IntGetWindowStationObject(InputWindowStation
))
342 CurInfo
= &InputWindowStation
->SystemCursor
;
343 if(!CurInfo
->Enabled
)
345 ObDereferenceObject(InputWindowStation
);
348 hDC
= IntGetScreenDC();
351 ObDereferenceObject(InputWindowStation
);
355 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
356 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
358 IntCheckClipCursor(&X
, &Y
, CurInfo
);
359 if((X
!= CurInfo
->x
) || (Y
!= CurInfo
->y
))
361 /* send MOUSEMOVE message */
362 KeQueryTickCount(&LargeTickCount
);
363 TickCount
= LargeTickCount
.u
.LowPart
;
364 Msg
.wParam
= CurInfo
->ButtonsDown
;
365 Msg
.lParam
= MAKELPARAM(X
, Y
);
366 Msg
.message
= WM_MOUSEMOVE
;
367 Msg
.time
= TickCount
;
370 MsqInsertSystemMessage(&Msg
, TRUE
);
376 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
377 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &MouseRect
);
378 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
383 ObDereferenceObject(InputWindowStation
);
391 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
393 * FUNCTION: Call by the mouse driver when input events occur.
397 PSYSTEM_CURSORINFO CurInfo
;
398 PSYSCURSOR SysCursor
;
399 BOOL MouseEnabled
= FALSE
;
400 BOOL MouseMoveAdded
= FALSE
;
402 LONG mouse_ox
, mouse_oy
;
403 LONG mouse_cx
= 0, mouse_cy
= 0;
412 LARGE_INTEGER LargeTickCount
;
415 hDC
= IntGetScreenDC();
417 if(!hDC
|| !InputWindowStation
)
420 if(IntGetWindowStationObject(InputWindowStation
))
422 CurInfo
= &InputWindowStation
->SystemCursor
;
423 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
424 MouseEnabled
= CurInfo
->Enabled
;
427 ObDereferenceObject(InputWindowStation
);
430 mouse_ox
= CurInfo
->x
;
431 mouse_oy
= CurInfo
->y
;
437 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
438 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
441 /* Compile the total mouse movement change and dispatch button events. */
442 for (i
= 0; i
< InputCount
; i
++)
444 mouse_cx
+= Data
[i
].LastX
;
445 mouse_cy
+= Data
[i
].LastY
;
447 CurInfo
->x
+= Data
[i
].LastX
;
448 CurInfo
->y
+= Data
[i
].LastY
;
450 CurInfo
->x
= max(CurInfo
->x
, 0);
451 CurInfo
->y
= max(CurInfo
->y
, 0);
452 CurInfo
->x
= min(CurInfo
->x
, SurfObj
->sizlBitmap
.cx
- 1);
453 CurInfo
->y
= min(CurInfo
->y
, SurfObj
->sizlBitmap
.cy
- 1);
455 IntCheckClipCursor(&CurInfo
->x
, &CurInfo
->y
, CurInfo
);
457 KeQueryTickCount(&LargeTickCount
);
458 TickCount
= LargeTickCount
.u
.LowPart
;
460 Msg
.wParam
= CurInfo
->ButtonsDown
;
461 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
462 Msg
.message
= WM_MOUSEMOVE
;
463 Msg
.time
= TickCount
;
464 Msg
.pt
.x
= CurInfo
->x
;
465 Msg
.pt
.y
= CurInfo
->y
;
467 MouseMoveAdded
= FALSE
;
469 //PrintInputData(i, Data[i]);
471 if (Data
[i
].ButtonFlags
!= 0)
474 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
476 /* insert WM_MOUSEMOVE messages before Button down messages */
477 if ((0 != Data
[i
].LastX
) || (0 != Data
[i
].LastY
))
479 MsqInsertSystemMessage(&Msg
, FALSE
);
480 MouseMoveAdded
= TRUE
;
482 CurInfo
->ButtonsDown
|= CurInfo
->SwapButtons
? MK_RBUTTON
: MK_LBUTTON
;
483 if(IntDetectDblClick(CurInfo
, TickCount
))
484 Msg
.message
= CurInfo
->SwapButtons
? WM_RBUTTONDBLCLK
: WM_LBUTTONDBLCLK
;
486 Msg
.message
= CurInfo
->SwapButtons
? WM_RBUTTONDOWN
: WM_LBUTTONDOWN
;
488 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
490 /* insert WM_MOUSEMOVE messages before Button down messages */
491 if ((0 != Data
[i
].LastX
) || (0 != Data
[i
].LastY
))
493 MsqInsertSystemMessage(&Msg
, FALSE
);
494 MouseMoveAdded
= TRUE
;
496 CurInfo
->ButtonsDown
|= MK_MBUTTON
;
497 if(IntDetectDblClick(CurInfo
, TickCount
))
498 Msg
.message
= WM_MBUTTONDBLCLK
;
500 Msg
.message
= WM_MBUTTONDOWN
;
502 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
504 /* insert WM_MOUSEMOVE messages before Button down messages */
505 if ((0 != Data
[i
].LastX
) || (0 != Data
[i
].LastY
))
507 MsqInsertSystemMessage(&Msg
, FALSE
);
508 MouseMoveAdded
= TRUE
;
510 CurInfo
->ButtonsDown
|= CurInfo
->SwapButtons
? MK_LBUTTON
: MK_RBUTTON
;
511 if(IntDetectDblClick(CurInfo
, TickCount
))
512 Msg
.message
= CurInfo
->SwapButtons
? WM_LBUTTONDBLCLK
: WM_RBUTTONDBLCLK
;
514 Msg
.message
= CurInfo
->SwapButtons
? WM_LBUTTONDOWN
: WM_RBUTTONDOWN
;
517 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_DOWN
) > 0)
519 /* insert WM_MOUSEMOVE messages before Button down messages */
520 if ((0 != Data
[i
].LastX
) || (0 != Data
[i
].LastY
))
522 MsqInsertSystemMessage(&Msg
, FALSE
);
523 MouseMoveAdded
= TRUE
;
525 CurInfo
->ButtonsDown
|= MK_XBUTTON1
;
526 if(IntDetectDblClick(CurInfo
, TickCount
))
528 Msg
.message
= WM_XBUTTONDBLCLK
;
532 Msg
.message
= WM_XBUTTONDOWN
;
534 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_DOWN
) > 0)
536 /* insert WM_MOUSEMOVE messages before Button down messages */
537 if ((0 != Data
[i
].LastX
) || (0 != Data
[i
].LastY
))
539 MsqInsertSystemMessage(&Msg
, FALSE
);
540 MouseMoveAdded
= TRUE
;
542 CurInfo
->ButtonsDown
|= MK_XBUTTON2
;
543 if(IntDetectDblClick(CurInfo
, TickCount
))
545 Msg
.message
= WM_XBUTTONDBLCLK
;
549 Msg
.message
= WM_XBUTTONDOWN
;
552 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
554 CurInfo
->ButtonsDown
&= CurInfo
->SwapButtons
? ~MK_RBUTTON
: ~MK_LBUTTON
;
555 Msg
.message
= CurInfo
->SwapButtons
? WM_RBUTTONUP
: WM_LBUTTONUP
;
557 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
559 CurInfo
->ButtonsDown
&= ~MK_MBUTTON
;
560 Msg
.message
= WM_MBUTTONUP
;
562 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
564 CurInfo
->ButtonsDown
&= CurInfo
->SwapButtons
? ~MK_LBUTTON
: ~MK_RBUTTON
;
565 Msg
.message
= CurInfo
->SwapButtons
? WM_LBUTTONUP
: WM_RBUTTONUP
;
567 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_UP
) > 0)
569 CurInfo
->ButtonsDown
&= ~MK_XBUTTON1
;
570 Msg
.message
= WM_XBUTTONUP
;
572 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_UP
) > 0)
574 CurInfo
->ButtonsDown
&= ~MK_XBUTTON2
;
575 Msg
.message
= WM_XBUTTONUP
;
577 if ((Data
[i
].ButtonFlags
& MOUSE_WHEEL
) > 0)
579 dScroll
+= (LONG
)Data
[i
].ButtonData
;
582 if (Data
[i
].ButtonFlags
!= MOUSE_WHEEL
)
584 Moved
= (0 != mouse_cx
) || (0 != mouse_cy
);
585 if(Moved
&& MouseEnabled
)
587 if (!CurInfo
->SafetySwitch
&& !CurInfo
->SafetySwitch2
&&
588 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
590 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
591 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &MouseRect
);
592 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
598 Msg
.wParam
= CurInfo
->ButtonsDown
;
599 MsqInsertSystemMessage(&Msg
, FALSE
);
601 /* insert WM_MOUSEMOVE messages after Button up messages */
602 if(!MouseMoveAdded
&& Moved
)
604 Msg
.message
= WM_MOUSEMOVE
;
605 MsqInsertSystemMessage(&Msg
, FALSE
);
606 MouseMoveAdded
= TRUE
;
612 KeQueryTickCount(&LargeTickCount
);
613 TickCount
= LargeTickCount
.u
.LowPart
;
615 /* If the mouse moved then move the pointer. */
616 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
621 Msg
.wParam
= CurInfo
->ButtonsDown
;
622 Msg
.message
= WM_MOUSEMOVE
;
623 Msg
.pt
.x
= CurInfo
->x
;
624 Msg
.pt
.y
= CurInfo
->y
;
625 Msg
.time
= TickCount
;
626 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
627 MsqInsertSystemMessage(&Msg
, TRUE
);
630 if (!CurInfo
->SafetySwitch
&& !CurInfo
->SafetySwitch2
&&
631 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
633 ExAcquireFastMutexUnsafe(&CurInfo
->CursorMutex
);
634 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &MouseRect
);
635 ExReleaseFastMutexUnsafe(&CurInfo
->CursorMutex
);
639 /* send WM_MOUSEWHEEL message */
640 if(dScroll
&& MouseEnabled
)
642 Msg
.message
= WM_MOUSEWHEEL
;
643 Msg
.wParam
= MAKEWPARAM(CurInfo
->ButtonsDown
, dScroll
);
644 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
645 Msg
.time
= TickCount
;
646 Msg
.pt
.x
= CurInfo
->x
;
647 Msg
.pt
.y
= CurInfo
->y
;
648 MsqInsertSystemMessage(&Msg
, FALSE
);
651 ObDereferenceObject(InputWindowStation
);
655 EnableMouse(HDC hDisplayDC
)
664 PSYSTEM_CURSORINFO CurInfo
;
665 PSYSCURSOR SysCursor
;
667 if( hDisplayDC
&& InputWindowStation
)
669 if(!IntGetWindowStationObject(InputWindowStation
))
671 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
675 CurInfo
= &InputWindowStation
->SystemCursor
;
676 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
678 dc
= DC_LockDc(hDisplayDC
);
679 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
680 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
681 DC_UnlockDc( hDisplayDC
);
683 /* Tell the display driver to set the pointer shape. */
684 CurInfo
->x
= SurfObj
->sizlBitmap
.cx
/ 2;
685 CurInfo
->y
= SurfObj
->sizlBitmap
.cy
/ 2;
687 /* Create the default mouse cursor. */
688 MouseSize
.cx
= SysCursor
->cx
;
689 MouseSize
.cy
= SysCursor
->cy
* 2;
690 hMouseSurf
= EngCreateBitmap(MouseSize
, 4, BMF_1BPP
, BMF_TOPDOWN
, DefaultCursor
);
691 MouseSurf
= (PSURFOBJ
)AccessUserObject((ULONG
) hMouseSurf
);
693 DPRINT("Setting Cursor up at 0x%x, 0x%x\n", CurInfo
->x
, CurInfo
->y
);
694 IntCheckClipCursor(&CurInfo
->x
,
698 PointerStatus
= SurfGDI
->SetPointerShape(SurfObj
, MouseSurf
, NULL
, NULL
,
706 InputWindowStation
->SystemCursor
.Enabled
= (SPS_ACCEPT_EXCLUDE
== PointerStatus
||
707 SPS_ACCEPT_NOEXCLUDE
== PointerStatus
);
709 EngDeleteSurface(hMouseSurf
);
710 ObDereferenceObject(InputWindowStation
);
715 if(IntGetWindowStationObject(InputWindowStation
))
717 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
718 InputWindowStation
->SystemCursor
.CursorClipInfo
.IsClipped
= FALSE
;
719 ObDereferenceObject(InputWindowStation
);