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