Support for VMware video drivers
[reactos.git] / reactos / subsys / win32k / eng / mouse.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: mouse.c,v 1.17 2003/02/15 19:16:33 gvg Exp $
20 *
21 * PROJECT: ReactOS kernel
22 * PURPOSE: Mouse
23 * FILE: subsys/win32k/eng/mouse.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * REVISION HISTORY:
26 * 06-06-2001 CSH Created
27 */
28 /* INCLUDES ******************************************************************/
29
30 #include <windows.h>
31 #include <ddk/ntddk.h>
32 #include <win32k/dc.h>
33 #include "../../drivers/input/include/mouse.h"
34 #include "objects.h"
35 #include "include/msgqueue.h"
36
37 #define NDEBUG
38 #include <debug.h>
39
40 /* GLOBALS *******************************************************************/
41
42 static BOOLEAN SafetySwitch = FALSE;
43 static BOOLEAN SafetySwitch2 = FALSE;
44 static BOOLEAN MouseEnabled = FALSE;
45 static LONG mouse_x, mouse_y;
46 static UINT mouse_width = 0, mouse_height = 0;
47
48 static UCHAR DefaultCursor[256] = {
49 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00,
62 0x00, 0xC0, 0x00, 0x00,
63 0x00, 0xC0, 0x00, 0x00,
64 0x01, 0x80, 0x00, 0x00,
65 0x01, 0x80, 0x00, 0x00,
66 0x03, 0x00, 0x00, 0x00,
67 0x43, 0x00, 0x00, 0x00,
68 0x66, 0x00, 0x00, 0x00,
69 0x76, 0x00, 0x00, 0x00,
70 0x7E, 0x00, 0x00, 0x00,
71 0x7F, 0xC0, 0x00, 0x00,
72 0x7F, 0x80, 0x00, 0x00,
73 0x7F, 0x00, 0x00, 0x00,
74 0x7E, 0x00, 0x00, 0x00,
75 0x7C, 0x00, 0x00, 0x00,
76 0x78, 0x00, 0x00, 0x00,
77 0x70, 0x00, 0x00, 0x00,
78 0x60, 0x00, 0x00, 0x00,
79 0x40, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00,
81
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,
88 0xFF, 0xFF, 0xFF, 0xFF,
89 0xFF, 0xFF, 0xFF, 0xFF,
90 0xFF, 0xFF, 0xFF, 0xFF,
91 0xFF, 0xFF, 0xFF, 0xFF,
92 0xFF, 0xFF, 0xFF, 0xFF,
93 0xFF, 0xFF, 0xFF, 0xFF,
94 0xFF, 0x3F, 0xFF, 0xFF,
95 0xFE, 0x1F, 0xFF, 0xFF,
96 0xFE, 0x1F, 0xFF, 0xFF,
97 0xFC, 0x3F, 0xFF, 0xFF,
98 0x7C, 0x3F, 0xFF, 0xFF,
99 0x38, 0x7F, 0xFF, 0xFF,
100 0x18, 0x7F, 0xFF, 0xFF,
101 0x00, 0xFF, 0xFF, 0xFF,
102 0x00, 0xFF, 0xFF, 0xFF,
103 0x00, 0x0F, 0xFF, 0xFF,
104 0x00, 0x1F, 0xFF, 0xFF,
105 0x00, 0x3F, 0xFF, 0xFF,
106 0x00, 0x7F, 0xFF, 0xFF,
107 0x00, 0xFF, 0xFF, 0xFF,
108 0x01, 0xFF, 0xFF, 0xFF,
109 0x03, 0xFF, 0xFF, 0xFF,
110 0x07, 0xFF, 0xFF, 0xFF,
111 0x0F, 0xFF, 0xFF, 0xFF,
112 0x1F, 0xFF, 0xFF, 0xFF,
113 0x3F, 0xFF, 0xFF, 0xFF};
114
115 /* FUNCTIONS *****************************************************************/
116
117 INT
118 MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
119 LONG HazardY1, LONG HazardX2, LONG HazardY2)
120 /*
121 * FUNCTION: Notify the mouse driver that drawing is about to begin in
122 * a rectangle on a particular surface.
123 */
124 {
125 RECTL MouseRect;
126 LONG tmp;
127
128 /* Mouse is not allowed to move if GDI is busy drawing */
129 SafetySwitch2 = TRUE;
130
131 if (SurfObj == NULL)
132 {
133 return(FALSE);
134 }
135
136 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
137 {
138 return(FALSE);
139 }
140
141 if (HazardX1 > HazardX2)
142 {
143 tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
144 }
145 if (HazardY1 > HazardY2)
146 {
147 tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
148 }
149
150 if (((mouse_x + mouse_width) >= HazardX1) && (mouse_x <= HazardX2) &&
151 ((mouse_y + mouse_height) >= HazardY1) && (mouse_y <= HazardY2))
152 {
153 SafetySwitch = TRUE;
154 SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect);
155 }
156
157 return(TRUE);
158 }
159
160 INT
161 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI)
162 /*
163 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
164 */
165 {
166 RECTL MouseRect;
167
168 if (SurfObj == NULL)
169 {
170 return(FALSE);
171 }
172
173 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
174 {
175 return(FALSE);
176 }
177
178 if (SafetySwitch)
179 {
180 SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
181 SafetySwitch = FALSE;
182 }
183
184 SafetySwitch2 = FALSE;
185
186 return(TRUE);
187 }
188
189 VOID
190 MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
191 /*
192 * FUNCTION: Call by the mouse driver when input events occur.
193 */
194 {
195 ULONG i;
196 LONG mouse_cx = 0, mouse_cy = 0;
197 HDC hDC = W32kGetScreenDC();
198 PDC dc;
199 PSURFOBJ SurfObj;
200 PSURFGDI SurfGDI;
201 RECTL MouseRect;
202 MSG Msg;
203 ULONG j;
204 LARGE_INTEGER LargeTickCount;
205 ULONG TickCount;
206 static ULONG ButtonsDown = 0;
207 const UINT MouseButtonDownMessage[3] =
208 {WM_RBUTTONDOWN, WM_MBUTTONDOWN, WM_LBUTTONDOWN};
209 const UINT MouseButtonUpMessage[3] =
210 {WM_RBUTTONUP, WM_MBUTTONUP, WM_LBUTTONUP};
211 const ULONG MouseButtonFlag[3] = {MK_RBUTTON, MK_MBUTTON, MK_LBUTTON};
212
213 KeQueryTickCount(&LargeTickCount);
214 TickCount = LargeTickCount.u.LowPart;
215
216 if (hDC == 0)
217 {
218 return;
219 }
220
221 dc = DC_HandleToPtr(hDC);
222 SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface);
223 SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface);
224 DC_ReleasePtr( hDC );
225
226 /* Compile the total mouse movement change and dispatch button events. */
227 for (i = 0; i < InputCount; i++)
228 {
229 mouse_cx += Data[i].LastX;
230 mouse_cy += Data[i].LastY;
231
232 Msg.wParam = ButtonsDown;
233 Msg.lParam = MAKELPARAM(mouse_x + mouse_cx, mouse_y + mouse_cy);
234 Msg.message = WM_MOUSEMOVE;
235 Msg.time = TickCount;
236 Msg.pt.x = mouse_x + mouse_cx;
237 Msg.pt.y = mouse_y + mouse_cy;
238 MsqInsertSystemMessage(&Msg);
239
240 for (j = 0; j < 3; j++)
241 {
242 ULONG Flag = MouseButtonFlag[j];
243 if (Data[i].ButtonData & (1 << j) && !(ButtonsDown & Flag))
244 {
245 ButtonsDown |= Flag;
246
247 Msg.wParam = ButtonsDown;
248 Msg.message = MouseButtonDownMessage[j];
249 MsqInsertSystemMessage(&Msg);
250 }
251 if (!(Data[i].ButtonData & (1 << j)) && (ButtonsDown & Flag))
252 {
253 ButtonsDown &= ~Flag;
254
255 Msg.wParam = ButtonsDown;
256 Msg.message = MouseButtonUpMessage[j];
257 MsqInsertSystemMessage(&Msg);
258 }
259 }
260 }
261
262 /* If the mouse moved then move the pointer. */
263 if (mouse_cx != 0 || mouse_cy != 0)
264 {
265 mouse_x += mouse_cx;
266 mouse_y += mouse_cy;
267
268 mouse_x = max(mouse_x, 0);
269 mouse_y = max(mouse_y, 0);
270 mouse_x = min(mouse_x, 620);
271 mouse_y = min(mouse_y, 460);
272
273 if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
274 {
275 SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
276 }
277 }
278 }
279
280 VOID
281 EnableMouse(HDC hDisplayDC)
282 {
283 PDC dc;
284 PSURFOBJ SurfObj;
285 PSURFGDI SurfGDI;
286 HBITMAP hMouseSurf;
287 PSURFOBJ MouseSurf;
288 SIZEL MouseSize;
289 RECTL MouseRect;
290
291 dc = DC_HandleToPtr(hDisplayDC);
292 if( dc ){
293 SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface);
294 SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface);
295 DC_ReleasePtr( hDisplayDC );
296
297 /* Create the default mouse cursor. */
298 mouse_width = 32;
299 mouse_height = 32;
300 MouseSize.cx = 32;
301 MouseSize.cy = 64;
302 hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, 0, DefaultCursor);
303 MouseSurf = (PSURFOBJ)AccessUserObject(hMouseSurf);
304
305 /* Tell the display driver to set the pointer shape. */
306 SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL, 0, 0, 320, 240,
307 &MouseRect, 0);
308
309 mouse_x = 320;
310 mouse_y = 240;
311 MouseEnabled = TRUE;
312 }
313 else{
314 MouseEnabled = FALSE;
315 }
316 }
317