branch update for HEAD-2003021201
[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   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