5d60ea0e6369327485e26b90aa8fdc49695ac0e8
[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.24 2003/05/18 19:21:24 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 /* STDCALL */
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
307 if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
308 {
309 #if 1
310 SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
311 #else
312 DbgPrint("WIN32K.%s: call SurfGDI->MovePointer()\n",__FUNCTION__);
313 #endif
314 }
315 }
316 }
317
318 VOID FASTCALL
319 EnableMouse(HDC hDisplayDC)
320 {
321 PDC dc;
322 PSURFOBJ SurfObj;
323 PSURFGDI SurfGDI;
324 HBITMAP hMouseSurf;
325 PSURFOBJ MouseSurf;
326 SIZEL MouseSize;
327 RECTL MouseRect;
328
329 if( hDisplayDC )
330 {
331 dc = DC_HandleToPtr(hDisplayDC);
332 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
333 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
334 DC_ReleasePtr( hDisplayDC );
335
336 /* Create the default mouse cursor. */
337 mouse_width = 32;
338 mouse_height = 32;
339 MouseSize.cx = 32;
340 MouseSize.cy = 64;
341 hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, BMF_TOPDOWN, DefaultCursor);
342 MouseSurf = (PSURFOBJ)AccessUserObject((ULONG) hMouseSurf);
343
344 /* Tell the display driver to set the pointer shape. */
345 #if 0
346 mouse_x = SurfObj->sizlBitmap.cx / 2;
347 mouse_y = SurfObj->sizlBitmap.cy / 2;
348 #else
349 mouse_x = 320;
350 mouse_y = 240;
351 #endif
352 PointerStatus = SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL,
353 0, 0, mouse_x, mouse_y, &MouseRect,
354 SPS_CHANGE);
355
356 MouseEnabled = (SPS_ACCEPT_EXCLUDE == PointerStatus ||
357 SPS_ACCEPT_NOEXCLUDE == PointerStatus);
358
359 EngDeleteSurface(hMouseSurf);
360 }
361 else
362 {
363 MouseEnabled = FALSE;
364 }
365 }
366 /* EOF */