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.32 2003/08/24 23:52:29 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/dc.h>
35 #include "include/msgqueue.h"
36 #include "include/object.h"
37 #include "include/winsta.h"
38 #include <include/mouse.h>
44 #define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
46 /* GLOBALS *******************************************************************/
48 //static BOOLEAN SafetySwitch = FALSE;
49 //static BOOLEAN SafetySwitch2 = FALSE;
50 //static BOOLEAN MouseEnabled = FALSE;
51 //static LONG mouse_x, mouse_y;
52 //static LONG mouse_width = 0, mouse_height = 0;
53 static ULONG PointerStatus
;
55 static UCHAR DefaultCursor
[256] = {
56 0x3F, 0xFF, 0xFF, 0xFF,
57 0x1F, 0xFF, 0xFF, 0xFF,
58 0x0F, 0xFF, 0xFF, 0xFF,
59 0x07, 0xFF, 0xFF, 0xFF,
60 0x03, 0xFF, 0xFF, 0xFF,
61 0x01, 0xFF, 0xFF, 0xFF,
62 0x00, 0xFF, 0xFF, 0xFF,
63 0x00, 0x7F, 0xFF, 0xFF,
64 0x00, 0x3F, 0xFF, 0xFF,
65 0x00, 0x1F, 0xFF, 0xFF,
66 0x00, 0x0F, 0xFF, 0xFF,
67 0x00, 0xFF, 0xFF, 0xFF,
68 0x00, 0xFF, 0xFF, 0xFF,
69 0x18, 0x7F, 0xFF, 0xFF,
70 0x38, 0x7F, 0xFF, 0xFF,
71 0x7C, 0x3F, 0xFF, 0xFF,
72 0xFC, 0x3F, 0xFF, 0xFF,
73 0xFE, 0x1F, 0xFF, 0xFF,
74 0xFE, 0x1F, 0xFF, 0xFF,
75 0xFF, 0x3F, 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,
84 0xFF, 0xFF, 0xFF, 0xFF,
85 0xFF, 0xFF, 0xFF, 0xFF,
86 0xFF, 0xFF, 0xFF, 0xFF,
87 0xFF, 0xFF, 0xFF, 0xFF,
89 0x00, 0x00, 0x00, 0x00,
90 0x40, 0x00, 0x00, 0x00,
91 0x60, 0x00, 0x00, 0x00,
92 0x70, 0x00, 0x00, 0x00,
93 0x78, 0x00, 0x00, 0x00,
94 0x7C, 0x00, 0x00, 0x00,
95 0x7E, 0x00, 0x00, 0x00,
96 0x7F, 0x00, 0x00, 0x00,
97 0x7F, 0x80, 0x00, 0x00,
98 0x7F, 0xC0, 0x00, 0x00,
99 0x7E, 0x00, 0x00, 0x00,
100 0x76, 0x00, 0x00, 0x00,
101 0x76, 0x00, 0x00, 0x00,
102 0x43, 0x00, 0x00, 0x00,
103 0x03, 0x00, 0x00, 0x00,
104 0x01, 0x80, 0x00, 0x00,
105 0x01, 0x80, 0x00, 0x00,
106 0x00, 0xC0, 0x00, 0x00,
107 0x00, 0xC0, 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,
117 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00};
122 /* FUNCTIONS *****************************************************************/
125 CheckClipCursor(LONG
*x
, LONG
*y
, PSYSTEM_CURSORINFO CurInfo
)
127 if(CurInfo
->CursorClipInfo
.IsClipped
)
129 if(*x
> CurInfo
->CursorClipInfo
.Right
)
130 *x
= CurInfo
->CursorClipInfo
.Right
;
131 if(*x
< CurInfo
->CursorClipInfo
.Left
)
132 *x
= CurInfo
->CursorClipInfo
.Left
;
133 if(*y
> CurInfo
->CursorClipInfo
.Bottom
)
134 *y
= CurInfo
->CursorClipInfo
.Bottom
;
135 if(*y
< CurInfo
->CursorClipInfo
.Top
)
136 *y
= CurInfo
->CursorClipInfo
.Top
;
143 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
144 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
146 * FUNCTION: Notify the mouse driver that drawing is about to begin in
147 * a rectangle on a particular surface.
152 PSYSTEM_CURSORINFO CurInfo
;
153 PSYSCURSOR SysCursor
;
154 BOOL MouseEnabled
= FALSE
;
157 /* Mouse is not allowed to move if GDI is busy drawing */
159 if(IntGetWindowStationObject(InputWindowStation
))
161 CurInfo
= &InputWindowStation
->SystemCursor
;
163 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
164 MouseEnabled
= CurInfo
->Enabled
&& SysCursor
->hCursor
;
169 CurInfo
->SafetySwitch2
= TRUE
;
173 ObDereferenceObject(InputWindowStation
);
178 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
180 ObDereferenceObject(InputWindowStation
);
184 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
186 /* Hardware cursor, no need to remove it */
187 ObDereferenceObject(InputWindowStation
);
191 if (HazardX1
> HazardX2
)
193 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
195 if (HazardY1
> HazardY2
)
197 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
200 if (((CurInfo
->x
+ SysCursor
->cx
) >= HazardX1
) && (CurInfo
->x
<= HazardX2
) &&
201 ((CurInfo
->y
+ SysCursor
->cy
) >= HazardY1
) && (CurInfo
->y
<= HazardY2
))
203 /* Mouse is not allowed to move if GDI is busy drawing */
204 CurInfo
->SafetySwitch
= TRUE
;
205 SurfGDI
->MovePointer(SurfObj
, -1, -1, &MouseRect
);
208 ObDereferenceObject(InputWindowStation
);
213 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
215 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
219 PSYSTEM_CURSORINFO CurInfo
;
220 PSYSCURSOR SysCursor
;
221 BOOL MouseEnabled
= FALSE
;
223 if(IntGetWindowStationObject(InputWindowStation
))
225 CurInfo
= &InputWindowStation
->SystemCursor
;
232 CurInfo
->SafetySwitch2
= FALSE
;
233 ObDereferenceObject(InputWindowStation
);
237 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
238 MouseEnabled
= CurInfo
->Enabled
&& SysCursor
->hCursor
;
240 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
242 CurInfo
->SafetySwitch2
= FALSE
;
243 ObDereferenceObject(InputWindowStation
);
247 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
249 /* Hardware cursor, it wasn't removed so need to restore it */
250 CurInfo
->SafetySwitch2
= FALSE
;
251 ObDereferenceObject(InputWindowStation
);
255 if (CurInfo
->SafetySwitch
)
257 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &MouseRect
);
258 CurInfo
->SafetySwitch
= FALSE
;
261 CurInfo
->SafetySwitch2
= FALSE
;
262 ObDereferenceObject(InputWindowStation
);
267 MouseMoveCursor(LONG X
, LONG Y
)
275 PSYSTEM_CURSORINFO CurInfo
;
277 LARGE_INTEGER LargeTickCount
;
280 hDC
= IntGetScreenDC();
282 if(!hDC
|| !InputWindowStation
)
285 if(IntGetWindowStationObject(InputWindowStation
))
288 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
289 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
291 CurInfo
= &InputWindowStation
->SystemCursor
;
292 CheckClipCursor(&X
, &X
, CurInfo
);
293 if((X
!= CurInfo
->x
) || (Y
!= CurInfo
->y
))
295 /* send MOUSEMOVE message */
296 KeQueryTickCount(&LargeTickCount
);
297 TickCount
= LargeTickCount
.u
.LowPart
;
299 Msg
.lParam
= MAKELPARAM(X
, Y
);
300 Msg
.message
= WM_MOUSEMOVE
;
301 Msg
.time
= TickCount
;
304 MsqInsertSystemMessage(&Msg
);
308 if(!CurInfo
->SafetySwitch
&& !CurInfo
->SafetySwitch2
&& CurInfo
->Enabled
)
310 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &MouseRect
);
315 ObDereferenceObject(InputWindowStation
);
323 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
325 * FUNCTION: Call by the mouse driver when input events occur.
329 PSYSTEM_CURSORINFO CurInfo
;
330 PSYSCURSOR SysCursor
;
331 BOOL MouseEnabled
= FALSE
;
332 LONG mouse_ox
, mouse_oy
;
333 LONG mouse_cx
= 0, mouse_cy
= 0;
340 LARGE_INTEGER LargeTickCount
;
342 static ULONG ButtonsDown
= 0;
344 hDC
= IntGetScreenDC();
346 if(!hDC
|| !InputWindowStation
)
349 if(IntGetWindowStationObject(InputWindowStation
))
351 CurInfo
= &InputWindowStation
->SystemCursor
;
352 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
353 MouseEnabled
= CurInfo
->Enabled
;
354 mouse_ox
= CurInfo
->x
;
355 mouse_oy
= CurInfo
->y
;
360 KeQueryTickCount(&LargeTickCount
);
361 TickCount
= LargeTickCount
.u
.LowPart
;
364 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
365 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
368 /* Compile the total mouse movement change and dispatch button events. */
369 for (i
= 0; i
< InputCount
; i
++)
371 mouse_cx
+= Data
[i
].LastX
;
372 mouse_cy
+= Data
[i
].LastY
;
374 Msg
.wParam
= ButtonsDown
;
375 Msg
.lParam
= MAKELPARAM(CurInfo
->x
+ mouse_cx
, CurInfo
->y
+ mouse_cy
);
376 Msg
.message
= WM_MOUSEMOVE
;
377 Msg
.time
= TickCount
;
378 Msg
.pt
.x
= CurInfo
->x
+ mouse_cx
;
379 Msg
.pt
.y
= CurInfo
->y
+ mouse_cy
;
381 CheckClipCursor(&Msg
.pt
.x
, &Msg
.pt
.y
, CurInfo
);
383 if ((0 != Data
[i
].LastX
) || (0 != Data
[i
].LastY
))
385 MsqInsertSystemMessage(&Msg
);
388 if (Data
[i
].ButtonFlags
!= 0)
390 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
392 Msg
.wParam
= MK_LBUTTON
;
393 Msg
.message
= WM_LBUTTONDOWN
;
395 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
397 Msg
.wParam
= MK_MBUTTON
;
398 Msg
.message
= WM_MBUTTONDOWN
;
400 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
402 Msg
.wParam
= MK_RBUTTON
;
403 Msg
.message
= WM_RBUTTONDOWN
;
406 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
408 Msg
.wParam
= MK_LBUTTON
;
409 Msg
.message
= WM_LBUTTONUP
;
411 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
413 Msg
.wParam
= MK_MBUTTON
;
414 Msg
.message
= WM_MBUTTONUP
;
416 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
418 Msg
.wParam
= MK_RBUTTON
;
419 Msg
.message
= WM_RBUTTONUP
;
422 MsqInsertSystemMessage(&Msg
);
426 /* If the mouse moved then move the pointer. */
427 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
429 CurInfo
->x
+= mouse_cx
;
430 CurInfo
->y
+= mouse_cy
;
432 CurInfo
->x
= max(CurInfo
->x
, 0);
433 CurInfo
->y
= max(CurInfo
->y
, 0);
434 CurInfo
->x
= min(CurInfo
->x
, SurfObj
->sizlBitmap
.cx
- 20);
435 CurInfo
->y
= min(CurInfo
->y
, SurfObj
->sizlBitmap
.cy
- 20);
437 CheckClipCursor(&CurInfo
->x
, &CurInfo
->y
, CurInfo
);
439 if (!CurInfo
->SafetySwitch
&& !CurInfo
->SafetySwitch2
&&
440 ((mouse_ox
!= CurInfo
->x
) || (mouse_oy
!= CurInfo
->y
)))
442 SurfGDI
->MovePointer(SurfObj
, CurInfo
->x
, CurInfo
->y
, &MouseRect
);
446 ObDereferenceObject(InputWindowStation
);
450 EnableMouse(HDC hDisplayDC
)
459 PSYSTEM_CURSORINFO CurInfo
;
460 PSYSCURSOR SysCursor
;
462 if( hDisplayDC
&& InputWindowStation
)
464 if(!IntGetWindowStationObject(InputWindowStation
))
466 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
469 CurInfo
= &InputWindowStation
->SystemCursor
;
470 SysCursor
= &CurInfo
->SystemCursors
[CurInfo
->CurrentCursor
];
472 dc
= DC_LockDc(hDisplayDC
);
473 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
474 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
475 DC_UnlockDc( hDisplayDC
);
477 /* Tell the display driver to set the pointer shape. */
479 CurInfo
->x
= SurfObj
->sizlBitmap
.cx
/ 2;
480 CurInfo
->y
= SurfObj
->sizlBitmap
.cy
/ 2;
486 /* Create the default mouse cursor. */
487 MouseSize
.cx
= SysCursor
->cx
;
488 MouseSize
.cy
= SysCursor
->cy
* 2;
489 hMouseSurf
= EngCreateBitmap(MouseSize
, 4, BMF_1BPP
, BMF_TOPDOWN
, DefaultCursor
);
490 MouseSurf
= (PSURFOBJ
)AccessUserObject((ULONG
) hMouseSurf
);
492 DbgPrint("Setting Cursor up at 0x%x, 0x%x\n", CurInfo
->x
, CurInfo
->y
);
493 CheckClipCursor(&CurInfo
->x
,
497 PointerStatus
= SurfGDI
->SetPointerShape(SurfObj
, MouseSurf
, NULL
, NULL
,
504 InputWindowStation
->SystemCursor
.Enabled
= (SPS_ACCEPT_EXCLUDE
== PointerStatus
||
505 SPS_ACCEPT_NOEXCLUDE
== PointerStatus
);
507 EngDeleteSurface(hMouseSurf
);
508 ObDereferenceObject(InputWindowStation
);
513 if(IntGetWindowStationObject(InputWindowStation
))
515 InputWindowStation
->SystemCursor
.Enabled
= FALSE
;
516 InputWindowStation
->SystemCursor
.CursorClipInfo
.IsClipped
= FALSE
;
517 ObDereferenceObject(InputWindowStation
);