WIN32K code cleanup.
[reactos.git] / reactos / subsys / win32k / eng / mouse.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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.23 2003/05/18 17:16:17 ea 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 <ddk/ntddmou.h>
33 #include <win32k/dc.h>
34 #include "objects.h"
35 #include "include/msgqueue.h"
36 #include "include/object.h"
37 #include "include/winsta.h"
38 #include <include/mouse.h>
39
40 #define NDEBUG
41 #include <debug.h>
42
43 /* GLOBALS *******************************************************************/
44
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;
51
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,
85
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};
118
119 /* FUNCTIONS *****************************************************************/
120
121 INT STDCALL
122 MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
123 LONG HazardY1, LONG HazardX2, LONG HazardY2)
124 /*
125 * FUNCTION: Notify the mouse driver that drawing is about to begin in
126 * a rectangle on a particular surface.
127 */
128 {
129 RECTL MouseRect;
130 LONG tmp;
131
132
133 /* Mouse is not allowed to move if GDI is busy drawing */
134 SafetySwitch2 = TRUE;
135
136 if (SurfObj == NULL)
137 {
138 return(FALSE);
139 }
140
141 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
142 {
143 return(FALSE);
144 }
145
146 if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
147 {
148 /* Hardware cursor, no need to remove it */
149 return(FALSE);
150 }
151
152 if (HazardX1 > HazardX2)
153 {
154 tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
155 }
156 if (HazardY1 > HazardY2)
157 {
158 tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
159 }
160
161 if (((mouse_x + mouse_width) >= HazardX1) && (mouse_x <= HazardX2) &&
162 ((mouse_y + mouse_height) >= HazardY1) && (mouse_y <= HazardY2))
163 {
164 SafetySwitch = TRUE;
165 SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect);
166 }
167
168 return(TRUE);
169 }
170
171 INT FASTCALL
172 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI)
173 /*
174 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
175 */
176 {
177 RECTL MouseRect;
178
179 if (SurfObj == NULL)
180 {
181 SafetySwitch2 = FALSE;
182 return(FALSE);
183 }
184
185 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
186 {
187 SafetySwitch2 = FALSE;
188 return(FALSE);
189 }
190
191 if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
192 {
193 /* Hardware cursor, it wasn't removed so need to restore it */
194 SafetySwitch2 = FALSE;
195 return(FALSE);
196 }
197
198 if (SafetySwitch)
199 {
200 SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
201 SafetySwitch = FALSE;
202 }
203
204 SafetySwitch2 = FALSE;
205
206 return(TRUE);
207 }
208
209 VOID FASTCALL
210 MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
211 /*
212 * FUNCTION: Call by the mouse driver when input events occur.
213 */
214 {
215 ULONG i;
216 LONG mouse_cx = 0, mouse_cy = 0;
217 HDC hDC = W32kGetScreenDC();
218 PDC dc;
219 PSURFOBJ SurfObj;
220 PSURFGDI SurfGDI;
221 RECTL MouseRect;
222 MSG Msg;
223 LARGE_INTEGER LargeTickCount;
224 ULONG TickCount;
225 static ULONG ButtonsDown = 0;
226
227 KeQueryTickCount(&LargeTickCount);
228 TickCount = LargeTickCount.u.LowPart;
229
230 if (hDC == 0)
231 {
232 return;
233 }
234
235 dc = DC_HandleToPtr(hDC);
236 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
237 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
238 DC_ReleasePtr( hDC );
239
240 /* Compile the total mouse movement change and dispatch button events. */
241 for (i = 0; i < InputCount; i++)
242 {
243 mouse_cx += Data[i].LastX;
244 mouse_cy += Data[i].LastY;
245
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))
253 {
254 MsqInsertSystemMessage(&Msg);
255 }
256
257 if (Data[i].ButtonFlags != 0)
258 {
259 if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) > 0)
260 {
261 Msg.wParam = MK_LBUTTON;
262 Msg.message = WM_LBUTTONDOWN;
263 }
264 if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) > 0)
265 {
266 Msg.wParam = MK_MBUTTON;
267 Msg.message = WM_MBUTTONDOWN;
268 }
269 if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) > 0)
270 {
271 Msg.wParam = MK_RBUTTON;
272 Msg.message = WM_RBUTTONDOWN;
273 }
274
275 if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_UP) > 0)
276 {
277 Msg.wParam = MK_LBUTTON;
278 Msg.message = WM_LBUTTONUP;
279 }
280 if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) > 0)
281 {
282 Msg.wParam = MK_MBUTTON;
283 Msg.message = WM_MBUTTONUP;
284 }
285 if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_UP) > 0)
286 {
287 Msg.wParam = MK_RBUTTON;
288 Msg.message = WM_RBUTTONUP;
289 }
290
291 MsqInsertSystemMessage(&Msg);
292 }
293 }
294
295 /* If the mouse moved then move the pointer. */
296 if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled)
297 {
298 mouse_x += mouse_cx;
299 mouse_y += mouse_cy;
300
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);
305
306 if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
307 {
308 SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
309 }
310 }
311 }
312
313 VOID FASTCALL
314 EnableMouse(HDC hDisplayDC)
315 {
316 PDC dc;
317 PSURFOBJ SurfObj;
318 PSURFGDI SurfGDI;
319 HBITMAP hMouseSurf;
320 PSURFOBJ MouseSurf;
321 SIZEL MouseSize;
322 RECTL MouseRect;
323
324 if( hDisplayDC )
325 {
326 dc = DC_HandleToPtr(hDisplayDC);
327 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
328 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
329 DC_ReleasePtr( hDisplayDC );
330
331 /* Create the default mouse cursor. */
332 mouse_width = 32;
333 mouse_height = 32;
334 MouseSize.cx = 32;
335 MouseSize.cy = 64;
336 hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, BMF_TOPDOWN, DefaultCursor);
337 MouseSurf = (PSURFOBJ)AccessUserObject((ULONG) hMouseSurf);
338
339 /* Tell the display driver to set the pointer shape. */
340 #if 0
341 mouse_x = SurfObj->sizlBitmap.cx / 2;
342 mouse_y = SurfObj->sizlBitmap.cy / 2;
343 #else
344 mouse_x = 320;
345 mouse_y = 240;
346 #endif
347 PointerStatus = SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL,
348 0, 0, mouse_x, mouse_y, &MouseRect,
349 SPS_CHANGE);
350
351 MouseEnabled = (SPS_ACCEPT_EXCLUDE == PointerStatus ||
352 SPS_ACCEPT_NOEXCLUDE == PointerStatus);
353
354 EngDeleteSurface(hMouseSurf);
355 }
356 else
357 {
358 MouseEnabled = FALSE;
359 }
360 }
361 /* EOF */