support for mouse wheels and 4th and 5th mouse button (WM_MOUSEWHEEL, WM_XBUTTON*)
[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.43 2003/09/28 00:26:13 weiden 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/win32k.h>
34 #include <win32k/dc.h>
35 #include "objects.h"
36 #include "include/msgqueue.h"
37 #include "include/object.h"
38 #include "include/winsta.h"
39 #include <include/mouse.h>
40
41 #define NDEBUG
42 #include <debug.h>
43
44
45 #define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
46
47 /* GLOBALS *******************************************************************/
48
49 static ULONG PointerStatus;
50
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,
84
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};
117
118 /* FUNCTIONS *****************************************************************/
119
120 BOOL FASTCALL
121 IntCheckClipCursor(LONG *x, LONG *y, PSYSTEM_CURSORINFO CurInfo)
122 {
123 if(CurInfo->CursorClipInfo.IsClipped)
124 {
125 if(*x > CurInfo->CursorClipInfo.Right)
126 *x = CurInfo->CursorClipInfo.Right;
127 if(*x < CurInfo->CursorClipInfo.Left)
128 *x = CurInfo->CursorClipInfo.Left;
129 if(*y > CurInfo->CursorClipInfo.Bottom)
130 *y = CurInfo->CursorClipInfo.Bottom;
131 if(*y < CurInfo->CursorClipInfo.Top)
132 *y = CurInfo->CursorClipInfo.Top;
133 return TRUE;
134 }
135 return TRUE;
136 }
137
138 BOOL FASTCALL
139 IntDetectDblClick(PSYSTEM_CURSORINFO CurInfo, DWORD TickCount)
140 {
141 LONG dX, dY;
142 BOOL res = ((TickCount - CurInfo->LastBtnDown) < CurInfo->DblClickSpeed);
143 if(res)
144 {
145 /* check if the second click is within the DblClickWidth and DblClickHeight values */
146 dX = CurInfo->LastBtnDownX - CurInfo->x;
147 dY = CurInfo->LastBtnDownY - CurInfo->y;
148 if(dX < 0) dX = -dX;
149 if(dY < 0) dY = -dY;
150
151 res = (dX <= CurInfo->DblClickWidth) &&
152 (dY <= CurInfo->DblClickHeight);
153
154 if(res)
155 {
156 CurInfo->LastBtnDown = 0; /* prevent sending 2 or more DBLCLK messages */
157 CurInfo->LastBtnDownX = CurInfo->x;
158 CurInfo->LastBtnDownY = CurInfo->y;
159 }
160 else
161 {
162 CurInfo->LastBtnDown = TickCount;
163 CurInfo->LastBtnDownX = CurInfo->x;
164 CurInfo->LastBtnDownY = CurInfo->y;
165 }
166 }
167 else
168 {
169 CurInfo->LastBtnDown = TickCount;
170 CurInfo->LastBtnDownX = CurInfo->x;
171 CurInfo->LastBtnDownY = CurInfo->y;
172 }
173 return res;
174 }
175
176 BOOL FASTCALL
177 IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject, BOOL Swap)
178 {
179 BOOL res = WinStaObject->SystemCursor.SwapButtons;
180 WinStaObject->SystemCursor.SwapButtons = Swap;
181 return res;
182 }
183
184 INT STDCALL
185 MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
186 LONG HazardY1, LONG HazardX2, LONG HazardY2)
187 /*
188 * FUNCTION: Notify the mouse driver that drawing is about to begin in
189 * a rectangle on a particular surface.
190 */
191 {
192 RECTL MouseRect;
193 LONG tmp;
194 PSYSTEM_CURSORINFO CurInfo;
195 PSYSCURSOR SysCursor;
196 BOOL MouseEnabled = FALSE;
197
198
199 /* Mouse is not allowed to move if GDI is busy drawing */
200
201 if(IntGetWindowStationObject(InputWindowStation))
202 {
203 CurInfo = &InputWindowStation->SystemCursor;
204
205 SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
206 MouseEnabled = CurInfo->Enabled && SysCursor->hCursor;
207 }
208 else
209 return FALSE;
210
211 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
212 CurInfo->SafetySwitch2 = TRUE;
213 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
214
215 if (SurfObj == NULL)
216 {
217 ObDereferenceObject(InputWindowStation);
218 return(FALSE);
219 }
220
221
222 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
223 {
224 ObDereferenceObject(InputWindowStation);
225 return(FALSE);
226 }
227
228 if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
229 {
230 /* Hardware cursor, no need to remove it */
231 ObDereferenceObject(InputWindowStation);
232 return(FALSE);
233 }
234
235 if (HazardX1 > HazardX2)
236 {
237 tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
238 }
239 if (HazardY1 > HazardY2)
240 {
241 tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
242 }
243
244 if (((CurInfo->x + SysCursor->cx) >= HazardX1) && (CurInfo->x <= HazardX2) &&
245 ((CurInfo->y + SysCursor->cy) >= HazardY1) && (CurInfo->y <= HazardY2))
246 {
247 /* Mouse is not allowed to move if GDI is busy drawing */
248 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
249 CurInfo->SafetySwitch = TRUE;
250 SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect);
251 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
252 }
253
254 ObDereferenceObject(InputWindowStation);
255 return(TRUE);
256 }
257
258 INT FASTCALL
259 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI)
260 /*
261 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
262 */
263 {
264 RECTL MouseRect;
265 PSYSTEM_CURSORINFO CurInfo;
266 PSYSCURSOR SysCursor;
267 BOOL MouseEnabled = FALSE;
268
269 if(IntGetWindowStationObject(InputWindowStation))
270 {
271 CurInfo = &InputWindowStation->SystemCursor;
272 }
273 else
274 return FALSE;
275
276 if(SurfObj == NULL)
277 {
278 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
279 CurInfo->SafetySwitch2 = FALSE;
280 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
281 ObDereferenceObject(InputWindowStation);
282 return FALSE;
283 }
284
285 SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
286 MouseEnabled = CurInfo->Enabled && SysCursor->hCursor;
287
288 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
289 {
290 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
291 CurInfo->SafetySwitch2 = FALSE;
292 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
293 ObDereferenceObject(InputWindowStation);
294 return(FALSE);
295 }
296
297 if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
298 {
299 /* Hardware cursor, it wasn't removed so need to restore it */
300 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
301 CurInfo->SafetySwitch2 = FALSE;
302 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
303 ObDereferenceObject(InputWindowStation);
304 return(FALSE);
305 }
306
307 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
308 if (CurInfo->SafetySwitch)
309 {
310 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
311 CurInfo->SafetySwitch = FALSE;
312 CurInfo->SafetySwitch2 = FALSE;
313 }
314 else
315 {
316 CurInfo->SafetySwitch2 = FALSE;
317 }
318 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
319 ObDereferenceObject(InputWindowStation);
320 return(TRUE);
321 }
322
323 BOOL FASTCALL
324 MouseMoveCursor(LONG X, LONG Y)
325 {
326 HDC hDC;
327 PDC dc;
328 RECTL MouseRect;
329 BOOL res = FALSE;
330 PSURFOBJ SurfObj;
331 PSURFGDI SurfGDI;
332 PSYSTEM_CURSORINFO CurInfo;
333 MSG Msg;
334 LARGE_INTEGER LargeTickCount;
335 ULONG TickCount;
336
337 if(!InputWindowStation)
338 return FALSE;
339
340 if(IntGetWindowStationObject(InputWindowStation))
341 {
342 CurInfo = &InputWindowStation->SystemCursor;
343 if(!CurInfo->Enabled)
344 {
345 ObDereferenceObject(InputWindowStation);
346 return FALSE;
347 }
348 hDC = IntGetScreenDC();
349 if(!hDC)
350 {
351 ObDereferenceObject(InputWindowStation);
352 return FALSE;
353 }
354 dc = DC_LockDc(hDC);
355 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
356 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
357 DC_UnlockDc( hDC );
358 IntCheckClipCursor(&X, &Y, CurInfo);
359 if((X != CurInfo->x) || (Y != CurInfo->y))
360 {
361 /* send MOUSEMOVE message */
362 KeQueryTickCount(&LargeTickCount);
363 TickCount = LargeTickCount.u.LowPart;
364 Msg.wParam = CurInfo->ButtonsDown;
365 Msg.lParam = MAKELPARAM(X, Y);
366 Msg.message = WM_MOUSEMOVE;
367 Msg.time = TickCount;
368 Msg.pt.x = X;
369 Msg.pt.y = Y;
370 MsqInsertSystemMessage(&Msg, TRUE);
371 /* move cursor */
372 CurInfo->x = X;
373 CurInfo->y = Y;
374 if(CurInfo->Enabled)
375 {
376 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
377 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
378 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
379 }
380 res = TRUE;
381 }
382
383 ObDereferenceObject(InputWindowStation);
384 return res;
385 }
386 else
387 return FALSE;
388 }
389
390 VOID /* STDCALL */
391 MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
392 /*
393 * FUNCTION: Call by the mouse driver when input events occur.
394 */
395 {
396 ULONG i;
397 PSYSTEM_CURSORINFO CurInfo;
398 PSYSCURSOR SysCursor;
399 BOOL MouseEnabled = FALSE;
400 BOOL MouseMoveAdded = FALSE;
401 BOOL Moved = FALSE;
402 LONG mouse_ox, mouse_oy;
403 LONG mouse_cx = 0, mouse_cy = 0;
404 LONG dScroll = 0;
405 HDC hDC;
406 PDC dc;
407 PSURFOBJ SurfObj;
408 PSURFGDI SurfGDI;
409 RECTL MouseRect;
410 WORD wp;
411 MSG Msg;
412 LARGE_INTEGER LargeTickCount;
413 ULONG TickCount;
414
415 hDC = IntGetScreenDC();
416
417 if(!hDC || !InputWindowStation)
418 return;
419
420 if(IntGetWindowStationObject(InputWindowStation))
421 {
422 CurInfo = &InputWindowStation->SystemCursor;
423 SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
424 MouseEnabled = CurInfo->Enabled;
425 if(!MouseEnabled)
426 {
427 ObDereferenceObject(InputWindowStation);
428 return;
429 }
430 mouse_ox = CurInfo->x;
431 mouse_oy = CurInfo->y;
432 }
433 else
434 return;
435
436 dc = DC_LockDc(hDC);
437 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
438 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
439 DC_UnlockDc( hDC );
440
441 /* Compile the total mouse movement change and dispatch button events. */
442 for (i = 0; i < InputCount; i++)
443 {
444 mouse_cx += Data[i].LastX;
445 mouse_cy += Data[i].LastY;
446
447 CurInfo->x += Data[i].LastX;
448 CurInfo->y += Data[i].LastY;
449
450 CurInfo->x = max(CurInfo->x, 0);
451 CurInfo->y = max(CurInfo->y, 0);
452 CurInfo->x = min(CurInfo->x, SurfObj->sizlBitmap.cx - 1);
453 CurInfo->y = min(CurInfo->y, SurfObj->sizlBitmap.cy - 1);
454
455 IntCheckClipCursor(&CurInfo->x, &CurInfo->y, CurInfo);
456
457 KeQueryTickCount(&LargeTickCount);
458 TickCount = LargeTickCount.u.LowPart;
459
460 Msg.wParam = CurInfo->ButtonsDown;
461 Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
462 Msg.message = WM_MOUSEMOVE;
463 Msg.time = TickCount;
464 Msg.pt.x = CurInfo->x;
465 Msg.pt.y = CurInfo->y;
466
467 MouseMoveAdded = FALSE;
468
469 //PrintInputData(i, Data[i]);
470
471 if (Data[i].ButtonFlags != 0)
472 {
473 wp = 0;
474 if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) > 0)
475 {
476 /* insert WM_MOUSEMOVE messages before Button down messages */
477 if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
478 {
479 MsqInsertSystemMessage(&Msg, FALSE);
480 MouseMoveAdded = TRUE;
481 }
482 CurInfo->ButtonsDown |= CurInfo->SwapButtons ? MK_RBUTTON : MK_LBUTTON;
483 if(IntDetectDblClick(CurInfo, TickCount))
484 Msg.message = CurInfo->SwapButtons ? WM_RBUTTONDBLCLK : WM_LBUTTONDBLCLK;
485 else
486 Msg.message = CurInfo->SwapButtons ? WM_RBUTTONDOWN : WM_LBUTTONDOWN;
487 }
488 if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) > 0)
489 {
490 /* insert WM_MOUSEMOVE messages before Button down messages */
491 if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
492 {
493 MsqInsertSystemMessage(&Msg, FALSE);
494 MouseMoveAdded = TRUE;
495 }
496 CurInfo->ButtonsDown |= MK_MBUTTON;
497 if(IntDetectDblClick(CurInfo, TickCount))
498 Msg.message = WM_MBUTTONDBLCLK;
499 else
500 Msg.message = WM_MBUTTONDOWN;
501 }
502 if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) > 0)
503 {
504 /* insert WM_MOUSEMOVE messages before Button down messages */
505 if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
506 {
507 MsqInsertSystemMessage(&Msg, FALSE);
508 MouseMoveAdded = TRUE;
509 }
510 CurInfo->ButtonsDown |= CurInfo->SwapButtons ? MK_LBUTTON : MK_RBUTTON;
511 if(IntDetectDblClick(CurInfo, TickCount))
512 Msg.message = CurInfo->SwapButtons ? WM_LBUTTONDBLCLK : WM_RBUTTONDBLCLK;
513 else
514 Msg.message = CurInfo->SwapButtons ? WM_LBUTTONDOWN : WM_RBUTTONDOWN;
515 }
516
517 if ((Data[i].ButtonFlags & MOUSE_BUTTON_4_DOWN) > 0)
518 {
519 /* insert WM_MOUSEMOVE messages before Button down messages */
520 if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
521 {
522 MsqInsertSystemMessage(&Msg, FALSE);
523 MouseMoveAdded = TRUE;
524 }
525 CurInfo->ButtonsDown |= MK_XBUTTON1;
526 if(IntDetectDblClick(CurInfo, TickCount))
527 {
528 Msg.message = WM_XBUTTONDBLCLK;
529 wp = XBUTTON1;
530 }
531 else
532 Msg.message = WM_XBUTTONDOWN;
533 }
534 if ((Data[i].ButtonFlags & MOUSE_BUTTON_5_DOWN) > 0)
535 {
536 /* insert WM_MOUSEMOVE messages before Button down messages */
537 if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
538 {
539 MsqInsertSystemMessage(&Msg, FALSE);
540 MouseMoveAdded = TRUE;
541 }
542 CurInfo->ButtonsDown |= MK_XBUTTON2;
543 if(IntDetectDblClick(CurInfo, TickCount))
544 {
545 Msg.message = WM_XBUTTONDBLCLK;
546 wp = XBUTTON2;
547 }
548 else
549 Msg.message = WM_XBUTTONDOWN;
550 }
551
552 if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_UP) > 0)
553 {
554 CurInfo->ButtonsDown &= CurInfo->SwapButtons ? ~MK_RBUTTON : ~MK_LBUTTON;
555 Msg.message = CurInfo->SwapButtons ? WM_RBUTTONUP : WM_LBUTTONUP;
556 }
557 if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) > 0)
558 {
559 CurInfo->ButtonsDown &= ~MK_MBUTTON;
560 Msg.message = WM_MBUTTONUP;
561 }
562 if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_UP) > 0)
563 {
564 CurInfo->ButtonsDown &= CurInfo->SwapButtons ? ~MK_LBUTTON : ~MK_RBUTTON;
565 Msg.message = CurInfo->SwapButtons ? WM_LBUTTONUP : WM_RBUTTONUP;
566 }
567 if ((Data[i].ButtonFlags & MOUSE_BUTTON_4_UP) > 0)
568 {
569 CurInfo->ButtonsDown &= ~MK_XBUTTON1;
570 Msg.message = WM_XBUTTONUP;
571 }
572 if ((Data[i].ButtonFlags & MOUSE_BUTTON_5_UP) > 0)
573 {
574 CurInfo->ButtonsDown &= ~MK_XBUTTON2;
575 Msg.message = WM_XBUTTONUP;
576 }
577 if ((Data[i].ButtonFlags & MOUSE_WHEEL) > 0)
578 {
579 dScroll += (LONG)Data[i].ButtonData;
580 }
581
582 if (Data[i].ButtonFlags != MOUSE_WHEEL)
583 {
584 Moved = (0 != mouse_cx) || (0 != mouse_cy);
585 if(Moved && MouseEnabled)
586 {
587 if (!CurInfo->SafetySwitch && !CurInfo->SafetySwitch2 &&
588 ((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
589 {
590 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
591 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
592 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
593 mouse_cx = 0;
594 mouse_cy = 0;
595 }
596 }
597
598 Msg.wParam = CurInfo->ButtonsDown;
599 MsqInsertSystemMessage(&Msg, FALSE);
600
601 /* insert WM_MOUSEMOVE messages after Button up messages */
602 if(!MouseMoveAdded && Moved)
603 {
604 Msg.message = WM_MOUSEMOVE;
605 MsqInsertSystemMessage(&Msg, FALSE);
606 MouseMoveAdded = TRUE;
607 }
608 }
609 }
610 }
611
612 KeQueryTickCount(&LargeTickCount);
613 TickCount = LargeTickCount.u.LowPart;
614
615 /* If the mouse moved then move the pointer. */
616 if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled)
617 {
618
619 if(!MouseMoveAdded)
620 {
621 Msg.wParam = CurInfo->ButtonsDown;
622 Msg.message = WM_MOUSEMOVE;
623 Msg.pt.x = CurInfo->x;
624 Msg.pt.y = CurInfo->y;
625 Msg.time = TickCount;
626 Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
627 MsqInsertSystemMessage(&Msg, TRUE);
628 }
629
630 if (!CurInfo->SafetySwitch && !CurInfo->SafetySwitch2 &&
631 ((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
632 {
633 ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
634 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
635 ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
636 }
637 }
638
639 /* send WM_MOUSEWHEEL message */
640 if(dScroll && MouseEnabled)
641 {
642 Msg.message = WM_MOUSEWHEEL;
643 Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, dScroll);
644 Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
645 Msg.time = TickCount;
646 Msg.pt.x = CurInfo->x;
647 Msg.pt.y = CurInfo->y;
648 MsqInsertSystemMessage(&Msg, FALSE);
649 }
650
651 ObDereferenceObject(InputWindowStation);
652 }
653
654 VOID FASTCALL
655 EnableMouse(HDC hDisplayDC)
656 {
657 PDC dc;
658 PSURFOBJ SurfObj;
659 PSURFGDI SurfGDI;
660 HBITMAP hMouseSurf;
661 PSURFOBJ MouseSurf;
662 SIZEL MouseSize;
663 RECTL MouseRect;
664 PSYSTEM_CURSORINFO CurInfo;
665 PSYSCURSOR SysCursor;
666
667 if( hDisplayDC && InputWindowStation)
668 {
669 if(!IntGetWindowStationObject(InputWindowStation))
670 {
671 InputWindowStation->SystemCursor.Enabled = FALSE;
672 return;
673 }
674
675 CurInfo = &InputWindowStation->SystemCursor;
676 SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
677
678 dc = DC_LockDc(hDisplayDC);
679 SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
680 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
681 DC_UnlockDc( hDisplayDC );
682
683 /* Tell the display driver to set the pointer shape. */
684 CurInfo->x = SurfObj->sizlBitmap.cx / 2;
685 CurInfo->y = SurfObj->sizlBitmap.cy / 2;
686
687 /* Create the default mouse cursor. */
688 MouseSize.cx = SysCursor->cx;
689 MouseSize.cy = SysCursor->cy * 2;
690 hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, BMF_TOPDOWN, DefaultCursor);
691 MouseSurf = (PSURFOBJ)AccessUserObject((ULONG) hMouseSurf);
692
693 DPRINT("Setting Cursor up at 0x%x, 0x%x\n", CurInfo->x, CurInfo->y);
694 IntCheckClipCursor(&CurInfo->x,
695 &CurInfo->y,
696 CurInfo);
697
698 PointerStatus = SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL,
699 SysCursor->hx,
700 SysCursor->hy,
701 CurInfo->x,
702 CurInfo->y,
703 &MouseRect,
704 SPS_CHANGE);
705
706 InputWindowStation->SystemCursor.Enabled = (SPS_ACCEPT_EXCLUDE == PointerStatus ||
707 SPS_ACCEPT_NOEXCLUDE == PointerStatus);
708
709 EngDeleteSurface(hMouseSurf);
710 ObDereferenceObject(InputWindowStation);
711
712 }
713 else
714 {
715 if(IntGetWindowStationObject(InputWindowStation))
716 {
717 InputWindowStation->SystemCursor.Enabled = FALSE;
718 InputWindowStation->SystemCursor.CursorClipInfo.IsClipped = FALSE;
719 ObDereferenceObject(InputWindowStation);
720 return;
721 }
722 }
723 }
724 /* EOF */