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.15 2002/11/01 11:29:57 dwelch 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 <win32k/dc.h>
33 #include "../../drivers/input/include/mouse.h"
35 #include "include/msgqueue.h"
37 /* GLOBALS *******************************************************************/
39 static BOOLEAN SafetySwitch
= FALSE
;
40 static BOOLEAN SafetySwitch2
= FALSE
;
41 static BOOLEAN MouseEnabled
= FALSE
;
42 static LONG mouse_x
, mouse_y
;
43 static UINT mouse_width
= 0, mouse_height
= 0;
45 static UCHAR DefaultCursor
[256] = {
46 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00,
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, 0xC0, 0x00, 0x00,
60 0x00, 0xC0, 0x00, 0x00,
61 0x01, 0x80, 0x00, 0x00,
62 0x01, 0x80, 0x00, 0x00,
63 0x03, 0x00, 0x00, 0x00,
64 0x43, 0x00, 0x00, 0x00,
65 0x66, 0x00, 0x00, 0x00,
66 0x76, 0x00, 0x00, 0x00,
67 0x7E, 0x00, 0x00, 0x00,
68 0x7F, 0xC0, 0x00, 0x00,
69 0x7F, 0x80, 0x00, 0x00,
70 0x7F, 0x00, 0x00, 0x00,
71 0x7E, 0x00, 0x00, 0x00,
72 0x7C, 0x00, 0x00, 0x00,
73 0x78, 0x00, 0x00, 0x00,
74 0x70, 0x00, 0x00, 0x00,
75 0x60, 0x00, 0x00, 0x00,
76 0x40, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00,
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 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, 0x3F, 0xFF, 0xFF,
92 0xFE, 0x1F, 0xFF, 0xFF,
93 0xFE, 0x1F, 0xFF, 0xFF,
94 0xFC, 0x3F, 0xFF, 0xFF,
95 0x7C, 0x3F, 0xFF, 0xFF,
96 0x38, 0x7F, 0xFF, 0xFF,
97 0x18, 0x7F, 0xFF, 0xFF,
98 0x00, 0xFF, 0xFF, 0xFF,
99 0x00, 0xFF, 0xFF, 0xFF,
100 0x00, 0x0F, 0xFF, 0xFF,
101 0x00, 0x1F, 0xFF, 0xFF,
102 0x00, 0x3F, 0xFF, 0xFF,
103 0x00, 0x7F, 0xFF, 0xFF,
104 0x00, 0xFF, 0xFF, 0xFF,
105 0x01, 0xFF, 0xFF, 0xFF,
106 0x03, 0xFF, 0xFF, 0xFF,
107 0x07, 0xFF, 0xFF, 0xFF,
108 0x0F, 0xFF, 0xFF, 0xFF,
109 0x1F, 0xFF, 0xFF, 0xFF,
110 0x3F, 0xFF, 0xFF, 0xFF};
112 /* FUNCTIONS *****************************************************************/
115 MouseSafetyOnDrawStart(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
, LONG HazardX1
,
116 LONG HazardY1
, LONG HazardX2
, LONG HazardY2
)
118 * FUNCTION: Notify the mouse driver that drawing is about to begin in
119 * a rectangle on a particular surface.
130 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
135 if (HazardX1
> HazardX2
)
137 tmp
= HazardX2
; HazardX2
= HazardX1
; HazardX1
= tmp
;
139 if (HazardY1
> HazardY2
)
141 tmp
= HazardY2
; HazardY2
= HazardY1
; HazardY1
= tmp
;
144 if (((mouse_x
+ mouse_width
) >= HazardX1
) && (mouse_x
<= HazardX2
) &&
145 ((mouse_y
+ mouse_height
) >= HazardY1
) && (mouse_y
<= HazardY2
))
147 SurfGDI
->MovePointer(SurfObj
, -1, -1, &MouseRect
);
151 /* Mouse is not allowed to move if GDI is busy drawing */
152 SafetySwitch2
= TRUE
;
158 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj
, PSURFGDI SurfGDI
)
160 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
170 if (SurfObj
->iType
!= STYPE_DEVICE
|| MouseEnabled
== FALSE
)
177 SurfGDI
->MovePointer(SurfObj
, mouse_x
, mouse_y
, &MouseRect
);
178 SafetySwitch
= FALSE
;
181 SafetySwitch2
= FALSE
;
187 MouseGDICallBack(PMOUSE_INPUT_DATA Data
, ULONG InputCount
)
189 * FUNCTION: Call by the mouse driver when input events occur.
193 LONG mouse_cx
= 0, mouse_cy
= 0;
194 HDC hDC
= W32kGetScreenDC();
201 LARGE_INTEGER LargeTickCount
;
203 static ULONG ButtonsDown
= 0;
204 const UINT MouseButtonDownMessage
[3] =
205 {WM_RBUTTONDOWN
, WM_MBUTTONDOWN
, WM_LBUTTONDOWN
};
206 const UINT MouseButtonUpMessage
[3] =
207 {WM_RBUTTONUP
, WM_MBUTTONUP
, WM_LBUTTONUP
};
208 const ULONG MouseButtonFlag
[3] = {MK_RBUTTON
, MK_MBUTTON
, MK_LBUTTON
};
210 KeQueryTickCount(&LargeTickCount
);
211 TickCount
= LargeTickCount
.u
.LowPart
;
218 dc
= DC_HandleToPtr(hDC
);
219 SurfObj
= (PSURFOBJ
)AccessUserObject(dc
->Surface
);
220 SurfGDI
= (PSURFGDI
)AccessInternalObject(dc
->Surface
);
222 /* Compile the total mouse movement change and dispatch button events. */
223 for (i
= 0; i
< InputCount
; i
++)
225 mouse_cx
+= Data
[i
].LastX
;
226 mouse_cy
+= Data
[i
].LastY
;
228 Msg
.wParam
= ButtonsDown
;
229 Msg
.lParam
= MAKELPARAM(mouse_x
+ mouse_cx
, mouse_y
+ mouse_cy
);
230 Msg
.message
= WM_MOUSEMOVE
;
231 Msg
.time
= TickCount
;
232 Msg
.pt
.x
= mouse_x
+ mouse_cx
;
233 Msg
.pt
.y
= mouse_y
+ mouse_cy
;
234 MsqInsertSystemMessage(&Msg
);
236 for (j
= 0; j
< 3; j
++)
238 ULONG Flag
= MouseButtonFlag
[j
];
239 if (Data
[i
].ButtonData
& (1 << j
) && !(ButtonsDown
& Flag
))
243 Msg
.wParam
= ButtonsDown
;
244 Msg
.message
= MouseButtonDownMessage
[j
];
245 MsqInsertSystemMessage(&Msg
);
247 if (!(Data
[i
].ButtonData
& (1 << j
)) && (ButtonsDown
& Flag
))
249 ButtonsDown
&= ~Flag
;
251 Msg
.wParam
= ButtonsDown
;
252 Msg
.message
= MouseButtonUpMessage
[j
];
253 MsqInsertSystemMessage(&Msg
);
258 /* If the mouse moved then move the pointer. */
259 if (mouse_cx
!= 0 || mouse_cy
!= 0)
264 mouse_x
= max(mouse_x
, 0);
265 mouse_y
= max(mouse_y
, 0);
266 mouse_x
= min(mouse_x
, 620);
267 mouse_y
= min(mouse_y
, 460);
269 if (SafetySwitch
== FALSE
&& SafetySwitch2
== FALSE
)
271 SurfGDI
->MovePointer(SurfObj
, mouse_x
, mouse_y
, &MouseRect
);
277 EnableMouse(HDC hDisplayDC
)
279 PDC dc
= DC_HandleToPtr(hDisplayDC
);
280 PSURFOBJ SurfObj
= (PSURFOBJ
)AccessUserObject(dc
->Surface
);
281 PSURFGDI SurfGDI
= (PSURFGDI
)AccessInternalObject(dc
->Surface
);
287 /* Create the default mouse cursor. */
292 hMouseSurf
= EngCreateBitmap(MouseSize
, 4, BMF_1BPP
, 0, DefaultCursor
);
293 MouseSurf
= (PSURFOBJ
)AccessUserObject(hMouseSurf
);
295 /* Tell the display driver to set the pointer shape. */
296 SurfGDI
->SetPointerShape(SurfObj
, MouseSurf
, NULL
, NULL
, 0, 0, 320, 240,