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.56 2004/01/17 15:20:25 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/mouse.h>
48 #define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
50 /* FUNCTIONS *****************************************************************/
53 IntCheckClipCursor(LONG
*x
, LONG
*y
, PSYSTEM_CURSORINFO CurInfo
)
55 if(CurInfo
->CursorClipInfo
.IsClipped
)
57 if(*x
> CurInfo
->CursorClipInfo
.Right
)
58 *x
= CurInfo
->CursorClipInfo
.Right
;
59 if(*x
< CurInfo
->CursorClipInfo
.Left
)
60 *x
= CurInfo
->CursorClipInfo
.Left
;
61 if(*y
> CurInfo
->CursorClipInfo
.Bottom
)
62 *y
= CurInfo
->CursorClipInfo
.Bottom
;
63 if(*y
< CurInfo
->CursorClipInfo
.Top
)
64 *y
= CurInfo
->CursorClipInfo
.Top
;
71 IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject
, BOOL Swap
)
73 BOOL res
= WinStaObject
->SystemCursor
.SwapButtons
;
74 WinStaObject
->SystemCursor
.SwapButtons
= Swap
;
79 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
80 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
82 * FUNCTION: Notify the mouse driver that drawing is about to begin in
83 * a rectangle on a particular surface.
87 PSYSTEM_CURSORINFO CurInfo
;
88 BOOL MouseEnabled
= FALSE
;
89 PCURICON_OBJECT Cursor
;
92 /* Mouse is not allowed to move if GDI is busy drawing */
94 if(IntGetWindowStationObject(InputWindowStation
))
96 CurInfo
= &InputWindowStation
->SystemCursor
;
98 MouseEnabled
= CurInfo
->Enabled
&& CurInfo
->ShowingCursor
;
105 ObDereferenceObject(InputWindowStation
);
110 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
112 ObDereferenceObject(InputWindowStation
);
116 if (SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
)
118 /* Hardware cursor, no need to remove it */
119 ObDereferenceObject(InputWindowStation
);
123 if(!(Cursor
= CurInfo
->CurrentCursorObject
))
125 ObDereferenceObject(InputWindowStation
);
129 if (HazardX1
> HazardX2
)
131 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
133 if (HazardY1
> HazardY2
)
135 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
138 if (CurInfo
->PointerRectRight
>= HazardX1
139 && CurInfo
->PointerRectLeft
<= HazardX2
140 && CurInfo
->PointerRectBottom
>= HazardY1
141 && CurInfo
->PointerRectTop
<= HazardY2
)
143 /* Mouse is not allowed to move if GDI is busy drawing */
144 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
145 if (0 != CurInfo
->SafetyRemoveCount
++)
147 /* Was already removed */
148 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
149 ObDereferenceObject(InputWindowStation
);
152 CurInfo
->SafetySwitch
= TRUE
;
153 ExAcquireFastMutex(SurfGDI
->DriverLock
);
154 SurfGDI
->MovePointer(SurfObj
, -1, -1, NULL
);
155 ExReleaseFastMutex(SurfGDI
->DriverLock
);
156 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
159 ObDereferenceObject(InputWindowStation
);
164 SetPointerRect(PSYSTEM_CURSORINFO CurInfo
, PRECTL PointerRect
)
166 CurInfo
->PointerRectLeft
= PointerRect
->left
;
167 CurInfo
->PointerRectRight
= PointerRect
->right
;
168 CurInfo
->PointerRectTop
= PointerRect
->top
;
169 CurInfo
->PointerRectBottom
= PointerRect
->bottom
;
173 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
175 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
178 PSYSTEM_CURSORINFO CurInfo
;
179 BOOL MouseEnabled
= FALSE
;
182 if(IntGetWindowStationObject(InputWindowStation
))
184 CurInfo
= &InputWindowStation
->SystemCursor
;
189 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
192 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
193 ObDereferenceObject(InputWindowStation
);
197 MouseEnabled
= CurInfo
->Enabled
&& CurInfo
->ShowingCursor
;
199 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
201 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
202 ObDereferenceObject(InputWindowStation
);
206 if (SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
)
208 /* Hardware cursor, it wasn't removed so need to restore it */
209 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
210 ObDereferenceObject(InputWindowStation
);
214 if (CurInfo
->SafetySwitch
)
216 if (1 < CurInfo
->SafetyRemoveCount
--)
218 /* Someone else removed it too, let them restore it */
219 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
220 ObDereferenceObject(InputWindowStation
);
223 ExAcquireFastMutex(SurfGDI
->DriverLock
);
224 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
225 ExReleaseFastMutex(SurfGDI
->DriverLock
);
226 SetPointerRect(CurInfo
, &PointerRect
);
227 CurInfo
->SafetySwitch
= FALSE
;
230 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
231 ObDereferenceObject(InputWindowStation
);
236 MouseMoveCursor(LONG X
, LONG Y
)
243 PSYSTEM_CURSORINFO CurInfo
;
245 LARGE_INTEGER LargeTickCount
;
249 if(!InputWindowStation
)
252 if(IntGetWindowStationObject(InputWindowStation
))
254 CurInfo
= &InputWindowStation
->SystemCursor
;
255 if(!CurInfo
->Enabled
)
257 ObDereferenceObject(InputWindowStation
);
260 hDC
= IntGetScreenDC();
263 ObDereferenceObject(InputWindowStation
);
267 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
268 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
270 IntCheckClipCursor(&X
, &Y
, CurInfo
);
271 if((X
!= CurInfo
->x
) || (Y
!= CurInfo
->y
))
278 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
279 ExAcquireFastMutex(SurfGDI
->DriverLock
);
280 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
281 ExReleaseFastMutex(SurfGDI
->DriverLock
);
282 SetPointerRect(CurInfo
, &PointerRect
);
283 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
285 /* send MOUSEMOVE message */
286 KeQueryTickCount(&LargeTickCount
);
287 TickCount
= LargeTickCount
.u
.LowPart
;
288 Msg
.wParam
= CurInfo
->ButtonsDown
;
289 Msg
.lParam
= MAKELPARAM(X
, Y
);
290 Msg
.message
= WM_MOUSEMOVE
;
291 Msg
.time
= TickCount
;
294 MsqInsertSystemMessage(&Msg
, TRUE
);
298 ObDereferenceObject(InputWindowStation
);
306 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
308 * FUNCTION: Call by the mouse driver when input events occur.
312 PSYSTEM_CURSORINFO CurInfo
;
313 BOOL MouseEnabled
= FALSE
;
315 LONG mouse_ox
, mouse_oy
;
316 LONG mouse_cx
= 0, mouse_cy
= 0;
325 hDC
= IntGetScreenDC();
327 if(!hDC
|| !InputWindowStation
)
330 if(IntGetWindowStationObject(InputWindowStation
))
332 CurInfo
= &InputWindowStation
->SystemCursor
;
333 MouseEnabled
= CurInfo
->Enabled
;
336 ObDereferenceObject(InputWindowStation
);
339 mouse_ox
= CurInfo
->x
;
340 mouse_oy
= CurInfo
->y
;
346 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
347 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
350 /* Compile the total mouse movement change and dispatch button events. */
351 for (i
= 0; i
< InputCount
; i
++)
353 mouse_cx
+= Data
[i
].LastX
;
354 mouse_cy
+= Data
[i
].LastY
;
356 CurInfo
->x
+= Data
[i
].LastX
;
357 CurInfo
->y
+= Data
[i
].LastY
;
359 CurInfo
->x
= max(CurInfo
->x
, 0);
360 CurInfo
->y
= max(CurInfo
->y
, 0);
361 CurInfo
->x
= min(CurInfo
->x
, SurfObj
->sizlBitmap
.cx
- 1);
362 CurInfo
->y
= min(CurInfo
->y
, SurfObj
->sizlBitmap
.cy
- 1);
364 IntCheckClipCursor(&CurInfo
->x
, &CurInfo
->y
, CurInfo
);
366 Msg
.wParam
= CurInfo
->ButtonsDown
;
367 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
368 Msg
.message
= WM_MOUSEMOVE
;
369 Msg
.pt
.x
= CurInfo
->x
;
370 Msg
.pt
.y
= CurInfo
->y
;
372 if (Data
[i
].ButtonFlags
!= 0)
374 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
376 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_RBUTTON
: MK_LBUTTON
);
377 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONDOWN
: WM_LBUTTONDOWN
);
379 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
381 CurInfo
->ButtonsDown
|= MK_MBUTTON
;
382 Msg
.message
= WM_MBUTTONDOWN
;
384 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
386 CurInfo
->ButtonsDown
|= (CurInfo
->SwapButtons
? MK_LBUTTON
: MK_RBUTTON
);
387 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONDOWN
: WM_RBUTTONDOWN
);
390 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_DOWN
) > 0)
392 CurInfo
->ButtonsDown
|= MK_XBUTTON1
;
393 Msg
.message
= WM_XBUTTONDOWN
;
395 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_DOWN
) > 0)
397 CurInfo
->ButtonsDown
|= MK_XBUTTON2
;
398 Msg
.message
= WM_XBUTTONDOWN
;
401 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
403 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_RBUTTON
: ~MK_LBUTTON
);
404 Msg
.message
= (CurInfo
->SwapButtons
? WM_RBUTTONUP
: WM_LBUTTONUP
);
406 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
408 CurInfo
->ButtonsDown
&= ~MK_MBUTTON
;
409 Msg
.message
= WM_MBUTTONUP
;
411 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
413 CurInfo
->ButtonsDown
&= (CurInfo
->SwapButtons
? ~MK_LBUTTON
: ~MK_RBUTTON
);
414 Msg
.message
= (CurInfo
->SwapButtons
? WM_LBUTTONUP
: WM_RBUTTONUP
);
416 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_4_UP
) > 0)
418 CurInfo
->ButtonsDown
&= ~MK_XBUTTON1
;
419 Msg
.message
= WM_XBUTTONUP
;
421 if ((Data
[i
].ButtonFlags
& MOUSE_BUTTON_5_UP
) > 0)
423 CurInfo
->ButtonsDown
&= ~MK_XBUTTON2
;
424 Msg
.message
= WM_XBUTTONUP
;
426 if ((Data
[i
].ButtonFlags
& MOUSE_WHEEL
) > 0)
428 dScroll
+= (LONG
)Data
[i
].ButtonData
;
431 if (Data
[i
].ButtonFlags
!= MOUSE_WHEEL
)
433 Moved
= (0 != mouse_cx
) || (0 != mouse_cy
);
434 if(Moved
&& MouseEnabled
)
436 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
437 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
439 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
440 ExAcquireFastMutex(SurfGDI
->DriverLock
);
441 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
442 ExReleaseFastMutex(SurfGDI
->DriverLock
);
443 SetPointerRect(CurInfo
, &PointerRect
);
444 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
450 Msg
.wParam
= CurInfo
->ButtonsDown
;
451 MsqInsertSystemMessage(&Msg
, FALSE
);
456 /* If the mouse moved then move the pointer. */
457 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
459 Msg
.wParam
= CurInfo
->ButtonsDown
;
460 Msg
.message
= WM_MOUSEMOVE
;
461 Msg
.pt
.x
= CurInfo
->x
;
462 Msg
.pt
.y
= CurInfo
->y
;
463 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
464 MsqInsertSystemMessage(&Msg
, TRUE
);
466 if (!CurInfo
->SafetySwitch
&& 0 == CurInfo
->SafetyRemoveCount
&&
467 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
469 ExAcquireFastMutex(&CurInfo
->CursorMutex
);
470 ExAcquireFastMutex(SurfGDI
->DriverLock
);
471 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &PointerRect
);
472 ExReleaseFastMutex(SurfGDI
->DriverLock
);
473 SetPointerRect(CurInfo
, &PointerRect
);
474 ExReleaseFastMutex(&CurInfo
->CursorMutex
);
478 /* send WM_MOUSEWHEEL message */
479 if(dScroll
&& MouseEnabled
)
481 Msg
.message
= WM_MOUSEWHEEL
;
482 Msg
.wParam
= MAKEWPARAM(CurInfo
->ButtonsDown
, dScroll
);
483 Msg
.lParam
= MAKELPARAM(CurInfo
->x
, CurInfo
->y
);
484 Msg
.pt
.x
= CurInfo
->x
;
485 Msg
.pt
.y
= CurInfo
->y
;
486 MsqInsertSystemMessage(&Msg
, FALSE
);
489 ObDereferenceObject(InputWindowStation
);
493 EnableMouse(HDC hDisplayDC
)
499 if( hDisplayDC
&& InputWindowStation
)
501 if(!IntGetWindowStationObject(InputWindowStation
))
503 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
507 dc
= DC_LockDc(hDisplayDC
);
508 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
509 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
510 DC_UnlockDc( hDisplayDC
);
512 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
514 InputWindowStation
->SystemCursor
.Enabled
= (SPS_ACCEPT_EXCLUDE
== SurfGDI
->PointerStatus
||
515 SPS_ACCEPT_NOEXCLUDE
== SurfGDI
->PointerStatus
);
517 /* Move the cursor to the screen center */
518 DPRINT("Setting Cursor up at 0x%x, 0x%x\n", SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
519 MouseMoveCursor(SurfObj
->sizlBitmap
.cx
/ 2, SurfObj
->sizlBitmap
.cy
/ 2);
521 ObDereferenceObject(InputWindowStation
);
525 if(IntGetWindowStationObject(InputWindowStation
))
527 IntSetCursor(InputWindowStation
, NULL
, TRUE
);
528 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
529 InputWindowStation
->SystemCursor
.CursorClipInfo
.IsClipped
= FALSE
;
530 ObDereferenceObject(InputWindowStation
);
541 IN SURFOBJ
*psoColor
,
551 // www.osr.com/ddk/graphics/gdifncs_1y5j.htm
568 // www.osr.com/ddk/graphics/gdifncs_8wfb.htm