e3499c7514234491f7fe69a381b241c2cc863481
[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.16 2003/01/24 23:25:34 ei 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 /* GLOBALS *******************************************************************/
38
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;
44
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,
78
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};
111
112 /* FUNCTIONS *****************************************************************/
113
114 INT
115 MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
116 LONG HazardY1, LONG HazardX2, LONG HazardY2)
117 /*
118 * FUNCTION: Notify the mouse driver that drawing is about to begin in
119 * a rectangle on a particular surface.
120 */
121 {
122 RECTL MouseRect;
123 LONG tmp;
124
125 if (SurfObj == NULL)
126 {
127 return(FALSE);
128 }
129
130 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
131 {
132 return(FALSE);
133 }
134
135 if (HazardX1 > HazardX2)
136 {
137 tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
138 }
139 if (HazardY1 > HazardY2)
140 {
141 tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
142 }
143
144 if (((mouse_x + mouse_width) >= HazardX1) && (mouse_x <= HazardX2) &&
145 ((mouse_y + mouse_height) >= HazardY1) && (mouse_y <= HazardY2))
146 {
147 SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect);
148 SafetySwitch = TRUE;
149 }
150
151 /* Mouse is not allowed to move if GDI is busy drawing */
152 SafetySwitch2 = TRUE;
153
154 return(TRUE);
155 }
156
157 INT
158 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI)
159 /*
160 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
161 */
162 {
163 RECTL MouseRect;
164
165 if (SurfObj == NULL)
166 {
167 return(FALSE);
168 }
169
170 if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
171 {
172 return(FALSE);
173 }
174
175 if (SafetySwitch)
176 {
177 SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
178 SafetySwitch = FALSE;
179 }
180
181 SafetySwitch2 = FALSE;
182
183 return(TRUE);
184 }
185
186 VOID
187 MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
188 /*
189 * FUNCTION: Call by the mouse driver when input events occur.
190 */
191 {
192 ULONG i;
193 LONG mouse_cx = 0, mouse_cy = 0;
194 HDC hDC = W32kGetScreenDC();
195 PDC dc;
196 PSURFOBJ SurfObj;
197 PSURFGDI SurfGDI;
198 RECTL MouseRect;
199 MSG Msg;
200 ULONG j;
201 LARGE_INTEGER LargeTickCount;
202 ULONG TickCount;
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};
209
210 KeQueryTickCount(&LargeTickCount);
211 TickCount = LargeTickCount.u.LowPart;
212
213 if (hDC == 0)
214 {
215 return;
216 }
217
218 dc = DC_HandleToPtr(hDC);
219 SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface);
220 SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface);
221 DC_ReleasePtr( hDC );
222
223 /* Compile the total mouse movement change and dispatch button events. */
224 for (i = 0; i < InputCount; i++)
225 {
226 mouse_cx += Data[i].LastX;
227 mouse_cy += Data[i].LastY;
228
229 Msg.wParam = ButtonsDown;
230 Msg.lParam = MAKELPARAM(mouse_x + mouse_cx, mouse_y + mouse_cy);
231 Msg.message = WM_MOUSEMOVE;
232 Msg.time = TickCount;
233 Msg.pt.x = mouse_x + mouse_cx;
234 Msg.pt.y = mouse_y + mouse_cy;
235 MsqInsertSystemMessage(&Msg);
236
237 for (j = 0; j < 3; j++)
238 {
239 ULONG Flag = MouseButtonFlag[j];
240 if (Data[i].ButtonData & (1 << j) && !(ButtonsDown & Flag))
241 {
242 ButtonsDown |= Flag;
243
244 Msg.wParam = ButtonsDown;
245 Msg.message = MouseButtonDownMessage[j];
246 MsqInsertSystemMessage(&Msg);
247 }
248 if (!(Data[i].ButtonData & (1 << j)) && (ButtonsDown & Flag))
249 {
250 ButtonsDown &= ~Flag;
251
252 Msg.wParam = ButtonsDown;
253 Msg.message = MouseButtonUpMessage[j];
254 MsqInsertSystemMessage(&Msg);
255 }
256 }
257 }
258
259 /* If the mouse moved then move the pointer. */
260 if (mouse_cx != 0 || mouse_cy != 0)
261 {
262 mouse_x += mouse_cx;
263 mouse_y += mouse_cy;
264
265 mouse_x = max(mouse_x, 0);
266 mouse_y = max(mouse_y, 0);
267 mouse_x = min(mouse_x, 620);
268 mouse_y = min(mouse_y, 460);
269
270 if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
271 {
272 SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect);
273 }
274 }
275 }
276
277 VOID
278 EnableMouse(HDC hDisplayDC)
279 {
280 PDC dc;
281 PSURFOBJ SurfObj;
282 PSURFGDI SurfGDI;
283 HBITMAP hMouseSurf;
284 PSURFOBJ MouseSurf;
285 SIZEL MouseSize;
286 RECTL MouseRect;
287
288 dc = DC_HandleToPtr(hDisplayDC);
289 if( dc ){
290 SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface);
291 SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface);
292 DC_ReleasePtr( hDisplayDC );
293
294 /* Create the default mouse cursor. */
295 mouse_width = 32;
296 mouse_height = 32;
297 MouseSize.cx = 32;
298 MouseSize.cy = 64;
299 hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, 0, DefaultCursor);
300 MouseSurf = (PSURFOBJ)AccessUserObject(hMouseSurf);
301
302 /* Tell the display driver to set the pointer shape. */
303 SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL, 0, 0, 320, 240,
304 &MouseRect, 0);
305
306 mouse_x = 320;
307 mouse_y = 240;
308 MouseEnabled = TRUE;
309 }
310 else{
311 MouseEnabled = FALSE;
312 }
313 }
314