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.24 2003/05/18 19:21:24 ea 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>
43 /* GLOBALS *******************************************************************/
45 static BOOLEAN SafetySwitch
= FALSE
;
46 static BOOLEAN SafetySwitch2
= FALSE
;
47 static BOOLEAN MouseEnabled
= FALSE
;
48 static LONG mouse_x
, mouse_y
;
49 static UINT mouse_width
= 0, mouse_height
= 0;
50 static ULONG PointerStatus
;
52 static UCHAR DefaultCursor
[256] = {
53 0x3F, 0xFF, 0xFF, 0xFF,
54 0x1F, 0xFF, 0xFF, 0xFF,
55 0x0F, 0xFF, 0xFF, 0xFF,
56 0x07, 0xFF, 0xFF, 0xFF,
57 0x03, 0xFF, 0xFF, 0xFF,
58 0x01, 0xFF, 0xFF, 0xFF,
59 0x00, 0xFF, 0xFF, 0xFF,
60 0x00, 0x7F, 0xFF, 0xFF,
61 0x00, 0x3F, 0xFF, 0xFF,
62 0x00, 0x1F, 0xFF, 0xFF,
63 0x00, 0x0F, 0xFF, 0xFF,
64 0x00, 0xFF, 0xFF, 0xFF,
65 0x00, 0xFF, 0xFF, 0xFF,
66 0x18, 0x7F, 0xFF, 0xFF,
67 0x38, 0x7F, 0xFF, 0xFF,
68 0x7C, 0x3F, 0xFF, 0xFF,
69 0xFC, 0x3F, 0xFF, 0xFF,
70 0xFE, 0x1F, 0xFF, 0xFF,
71 0xFE, 0x1F, 0xFF, 0xFF,
72 0xFF, 0x3F, 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,
84 0xFF, 0xFF, 0xFF, 0xFF,
86 0x00, 0x00, 0x00, 0x00,
87 0x40, 0x00, 0x00, 0x00,
88 0x60, 0x00, 0x00, 0x00,
89 0x70, 0x00, 0x00, 0x00,
90 0x78, 0x00, 0x00, 0x00,
91 0x7C, 0x00, 0x00, 0x00,
92 0x7E, 0x00, 0x00, 0x00,
93 0x7F, 0x00, 0x00, 0x00,
94 0x7F, 0x80, 0x00, 0x00,
95 0x7F, 0xC0, 0x00, 0x00,
96 0x7E, 0x00, 0x00, 0x00,
97 0x76, 0x00, 0x00, 0x00,
98 0x76, 0x00, 0x00, 0x00,
99 0x43, 0x00, 0x00, 0x00,
100 0x03, 0x00, 0x00, 0x00,
101 0x01, 0x80, 0x00, 0x00,
102 0x01, 0x80, 0x00, 0x00,
103 0x00, 0xC0, 0x00, 0x00,
104 0x00, 0xC0, 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,
117 0x00, 0x00, 0x00, 0x00};
119 /* FUNCTIONS *****************************************************************/
122 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
123 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
125 * FUNCTION: Notify the mouse driver that drawing is about to begin in
126 * a rectangle on a particular surface.
133 /* Mouse is not allowed to move if GDI is busy drawing */
134 SafetySwitch2
= TRUE
;
141 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
146 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
148 /* Hardware cursor, no need to remove it */
152 if (HazardX1
> HazardX2
)
154 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
156 if (HazardY1
> HazardY2
)
158 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
161 if (((mouse_x
+ mouse_width
) >= HazardX1
) && (mouse_x
<= HazardX2
) &&
162 ((mouse_y
+ mouse_height
) >= HazardY1
) && (mouse_y
<= HazardY2
))
165 SurfGDI
->MovePointer(SurfObj
, -1, -1, &MouseRect
);
172 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
174 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
181 SafetySwitch2
= FALSE
;
185 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
187 SafetySwitch2
= FALSE
;
191 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
193 /* Hardware cursor, it wasn't removed so need to restore it */
194 SafetySwitch2
= FALSE
;
200 SurfGDI
->MovePointer(SurfObj
, mouse_x
, mouse_y
, &MouseRect
);
201 SafetySwitch
= FALSE
;
204 SafetySwitch2
= FALSE
;
210 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
212 * FUNCTION: Call by the mouse driver when input events occur.
216 LONG mouse_cx
= 0, mouse_cy
= 0;
217 HDC hDC
= W32kGetScreenDC();
223 LARGE_INTEGER LargeTickCount
;
225 static ULONG ButtonsDown
= 0;
227 KeQueryTickCount(&LargeTickCount
);
228 TickCount
= LargeTickCount
.u
.LowPart
;
235 dc
= DC_HandleToPtr(hDC
);
236 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
237 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
238 DC_ReleasePtr( hDC
);
240 /* Compile the total mouse movement change and dispatch button events. */
241 for (i
= 0; i
< InputCount
; i
++)
243 mouse_cx
+= Data
[i
].LastX
;
244 mouse_cy
+= Data
[i
].LastY
;
246 Msg
.wParam
= ButtonsDown
;
247 Msg
.lParam
= MAKELPARAM(mouse_x
+ mouse_cx
, mouse_y
+ mouse_cy
);
248 Msg
.message
= WM_MOUSEMOVE
;
249 Msg
.time
= TickCount
;
250 Msg
.pt
.x
= mouse_x
+ mouse_cx
;
251 Msg
.pt
.y
= mouse_y
+ mouse_cy
;
252 if ((0 != Data
[i
].LastX
) || (0 != Data
[i
].LastY
))
254 MsqInsertSystemMessage(&Msg
);
257 if (Data
[i
].ButtonFlags
!= 0)
259 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
261 Msg
.wParam
= MK_LBUTTON
;
262 Msg
.message
= WM_LBUTTONDOWN
;
264 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
266 Msg
.wParam
= MK_MBUTTON
;
267 Msg
.message
= WM_MBUTTONDOWN
;
269 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
271 Msg
.wParam
= MK_RBUTTON
;
272 Msg
.message
= WM_RBUTTONDOWN
;
275 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
277 Msg
.wParam
= MK_LBUTTON
;
278 Msg
.message
= WM_LBUTTONUP
;
280 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
282 Msg
.wParam
= MK_MBUTTON
;
283 Msg
.message
= WM_MBUTTONUP
;
285 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
287 Msg
.wParam
= MK_RBUTTON
;
288 Msg
.message
= WM_RBUTTONUP
;
291 MsqInsertSystemMessage(&Msg
);
295 /* If the mouse moved then move the pointer. */
296 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
301 mouse_x
= max(mouse_x
, 0);
302 mouse_y
= max(mouse_y
, 0);
303 mouse_x
= min(mouse_x
, 620);
304 mouse_y
= min(mouse_y
, 460);
307 if (SafetySwitch
== FALSE
&& SafetySwitch2
== FALSE
)
310 SurfGDI
->MovePointer(SurfObj
, mouse_x
, mouse_y
, &MouseRect
);
312 DbgPrint("WIN32K.%s: call SurfGDI->MovePointer()\n",__FUNCTION__
);
319 EnableMouse(HDC hDisplayDC
)
331 dc
= DC_HandleToPtr(hDisplayDC
);
332 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
333 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
334 DC_ReleasePtr( hDisplayDC
);
336 /* Create the default mouse cursor. */
341 hMouseSurf
= EngCreateBitmap(MouseSize
, 4, BMF_1BPP
, BMF_TOPDOWN
, DefaultCursor
);
342 MouseSurf
= (PSURFOBJ
)AccessUserObject((ULONG
) hMouseSurf
);
344 /* Tell the display driver to set the pointer shape. */
346 mouse_x
= SurfObj
->sizlBitmap
.cx
/ 2;
347 mouse_y
= SurfObj
->sizlBitmap
.cy
/ 2;
352 PointerStatus
= SurfGDI
->SetPointerShape(SurfObj
, MouseSurf
, NULL
, NULL
,
353 0, 0, mouse_x
, mouse_y
, &MouseRect
,
356 MouseEnabled
= (SPS_ACCEPT_EXCLUDE
== PointerStatus
||
357 SPS_ACCEPT_NOEXCLUDE
== PointerStatus
);
359 EngDeleteSurface(hMouseSurf
);
363 MouseEnabled
= FALSE
;