update for HEAD-2002110401
[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 <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   
222   /* Compile the total mouse movement change and dispatch button events. */
223   for (i = 0; i < InputCount; i++)
224     {
225       mouse_cx += Data[i].LastX;
226       mouse_cy += Data[i].LastY;
227
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);
235       
236       for (j = 0; j < 3; j++)
237         {
238           ULONG Flag = MouseButtonFlag[j];
239           if (Data[i].ButtonData & (1 << j) && !(ButtonsDown & Flag))
240             {
241               ButtonsDown |= Flag;
242
243               Msg.wParam = ButtonsDown;
244               Msg.message = MouseButtonDownMessage[j];
245               MsqInsertSystemMessage(&Msg);
246             }
247           if (!(Data[i].ButtonData & (1 << j)) && (ButtonsDown & Flag))
248             {         
249               ButtonsDown &= ~Flag;        
250
251               Msg.wParam = ButtonsDown;
252               Msg.message = MouseButtonUpMessage[j];
253               MsqInsertSystemMessage(&Msg);
254             }
255         }
256     }
257
258   /* If the mouse moved then move the pointer. */
259   if (mouse_cx != 0 || mouse_cy != 0)
260     {     
261       mouse_x += mouse_cx;
262       mouse_y += mouse_cy;      
263
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);
268
269       if (SafetySwitch == FALSE && SafetySwitch2 == FALSE)
270         {
271           SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); 
272         }
273     }
274 }
275
276 VOID 
277 EnableMouse(HDC hDisplayDC)
278 {
279   PDC dc = DC_HandleToPtr(hDisplayDC);
280   PSURFOBJ SurfObj = (PSURFOBJ)AccessUserObject(dc->Surface);
281   PSURFGDI SurfGDI = (PSURFGDI)AccessInternalObject(dc->Surface);
282   HBITMAP hMouseSurf;
283   PSURFOBJ MouseSurf;
284   SIZEL MouseSize;
285   RECTL MouseRect;
286
287   /* Create the default mouse cursor. */
288   mouse_width = 32;
289   mouse_height = 32;
290   MouseSize.cx = 32;
291   MouseSize.cy = 64;
292   hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, 0, DefaultCursor);
293   MouseSurf = (PSURFOBJ)AccessUserObject(hMouseSurf);
294
295   /* Tell the display driver to set the pointer shape. */
296   SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL, 0, 0, 320, 240, 
297                            &MouseRect, 0);
298
299   mouse_x = 320;
300   mouse_y = 240;
301   MouseEnabled = TRUE;
302 }
303