3 * Copyright (C) 1998, 1999, 2000, 2001 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.21 2003/03/24 22:49:54 gvg 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"
42 /* GLOBALS *******************************************************************/
44 static BOOLEAN SafetySwitch
= FALSE
;
45 static BOOLEAN SafetySwitch2
= FALSE
;
46 static BOOLEAN MouseEnabled
= FALSE
;
47 static LONG mouse_x
, mouse_y
;
48 static UINT mouse_width
= 0, mouse_height
= 0;
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 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
122 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
124 * FUNCTION: Notify the mouse driver that drawing is about to begin in
125 * a rectangle on a particular surface.
132 /* Mouse is not allowed to move if GDI is busy drawing */
133 SafetySwitch2
= TRUE
;
140 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
145 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
147 /* Hardware cursor, no need to remove it */
151 if (HazardX1
> HazardX2
)
153 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
155 if (HazardY1
> HazardY2
)
157 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
160 if (((mouse_x
+ mouse_width
) >= HazardX1
) && (mouse_x
<= HazardX2
) &&
161 ((mouse_y
+ mouse_height
) >= HazardY1
) && (mouse_y
<= HazardY2
))
164 SurfGDI
->MovePointer(SurfObj
, -1, -1, &MouseRect
);
171 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
173 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
180 SafetySwitch2
= FALSE
;
184 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
186 SafetySwitch2
= FALSE
;
190 if (SPS_ACCEPT_NOEXCLUDE
== PointerStatus
)
192 /* Hardware cursor, it wasn't removed so need to restore it */
193 SafetySwitch2
= FALSE
;
199 SurfGDI
->MovePointer(SurfObj
, mouse_x
, mouse_y
, &MouseRect
);
200 SafetySwitch
= FALSE
;
203 SafetySwitch2
= FALSE
;
209 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
211 * FUNCTION: Call by the mouse driver when input events occur.
215 LONG mouse_cx
= 0, mouse_cy
= 0;
216 HDC hDC
= W32kGetScreenDC();
222 LARGE_INTEGER LargeTickCount
;
224 static ULONG ButtonsDown
= 0;
226 KeQueryTickCount(&LargeTickCount
);
227 TickCount
= LargeTickCount
.u
.LowPart
;
234 dc
= DC_HandleToPtr(hDC
);
235 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
236 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
237 DC_ReleasePtr( hDC
);
239 /* Compile the total mouse movement change and dispatch button events. */
240 for (i
= 0; i
< InputCount
; i
++)
242 mouse_cx
+= Data
[i
].LastX
;
243 mouse_cy
+= Data
[i
].LastY
;
245 Msg
.wParam
= ButtonsDown
;
246 Msg
.lParam
= MAKELPARAM(mouse_x
+ mouse_cx
, mouse_y
+ mouse_cy
);
247 Msg
.message
= WM_MOUSEMOVE
;
248 Msg
.time
= TickCount
;
249 Msg
.pt
.x
= mouse_x
+ mouse_cx
;
250 Msg
.pt
.y
= mouse_y
+ mouse_cy
;
251 if ((mouse_cx
> 0) || (mouse_cy
> 0))
253 MsqInsertSystemMessage(&Msg
);
256 if (Data
[i
].ButtonFlags
!= 0)
258 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_DOWN
) > 0)
260 Msg
.wParam
= MK_LBUTTON
;
261 Msg
.message
= WM_LBUTTONDOWN
;
263 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_DOWN
) > 0)
265 Msg
.wParam
= MK_MBUTTON
;
266 Msg
.message
= WM_MBUTTONDOWN
;
268 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_DOWN
) > 0)
270 Msg
.wParam
= MK_RBUTTON
;
271 Msg
.message
= WM_RBUTTONDOWN
;
274 if ((Data
[i
].ButtonFlags
& MOUSE_LEFT_BUTTON_UP
) > 0)
276 Msg
.wParam
= MK_LBUTTON
;
277 Msg
.message
= WM_LBUTTONUP
;
279 if ((Data
[i
].ButtonFlags
& MOUSE_MIDDLE_BUTTON_UP
) > 0)
281 Msg
.wParam
= MK_MBUTTON
;
282 Msg
.message
= WM_MBUTTONUP
;
284 if ((Data
[i
].ButtonFlags
& MOUSE_RIGHT_BUTTON_UP
) > 0)
286 Msg
.wParam
= MK_RBUTTON
;
287 Msg
.message
= WM_RBUTTONUP
;
290 MsqInsertSystemMessage(&Msg
);
294 /* If the mouse moved then move the pointer. */
295 if ((mouse_cx
!= 0 || mouse_cy
!= 0) && MouseEnabled
)
300 mouse_x
= max(mouse_x
, 0);
301 mouse_y
= max(mouse_y
, 0);
302 mouse_x
= min(mouse_x
, 620);
303 mouse_y
= min(mouse_y
, 460);
305 if (SafetySwitch
== FALSE
&& SafetySwitch2
== FALSE
)
307 SurfGDI
->MovePointer(SurfObj
, mouse_x
, mouse_y
, &MouseRect
);
313 EnableMouse(HDC hDisplayDC
)
325 dc
= DC_HandleToPtr(hDisplayDC
);
326 SurfObj
= (PSURFOBJ
)AccessUserObject((ULONG
) dc
->Surface
);
327 SurfGDI
= (PSURFGDI
)AccessInternalObject((ULONG
) dc
->Surface
);
328 DC_ReleasePtr( hDisplayDC
);
330 /* Create the default mouse cursor. */
335 hMouseSurf
= EngCreateBitmap(MouseSize
, 4, BMF_1BPP
, BMF_TOPDOWN
, DefaultCursor
);
336 MouseSurf
= (PSURFOBJ
)AccessUserObject((ULONG
) hMouseSurf
);
338 /* Tell the display driver to set the pointer shape. */
340 mouse_x
= SurfObj
->sizlBitmap
.cx
/ 2;
341 mouse_y
= SurfObj
->sizlBitmap
.cy
/ 2;
346 PointerStatus
= SurfGDI
->SetPointerShape(SurfObj
, MouseSurf
, NULL
, NULL
,
347 0, 0, mouse_x
, mouse_y
, &MouseRect
,
350 MouseEnabled
= (SPS_ACCEPT_EXCLUDE
== PointerStatus
||
351 SPS_ACCEPT_NOEXCLUDE
== PointerStatus
);
353 EngDeleteSurface(hMouseSurf
);
357 MouseEnabled
= FALSE
;