update for HEAD-2003091401
[reactos.git] / subsys / win32k / eng / mouse.c
1 /*
2  *  ReactOS W32 Subsystem
3  *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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/win32k.h>
34 #include <win32k/dc.h>
35 #include "objects.h"
36 #include "include/msgqueue.h"
37 #include "include/object.h"
38 #include "include/winsta.h"
39 #include <include/mouse.h>
40
41 #define NDEBUG
42 #include <debug.h>
43
44
45 #define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
46
47 /* GLOBALS *******************************************************************/
48
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 BOOL FASTCALL
121 IntCheckClipCursor(LONG *x, LONG *y, PSYSTEM_CURSORINFO CurInfo)
122 {
123   if(CurInfo->CursorClipInfo.IsClipped)
124   {
125     if(*x > CurInfo->CursorClipInfo.Right)
126       *x = CurInfo->CursorClipInfo.Right;
127     if(*x < CurInfo->CursorClipInfo.Left)
128       *x = CurInfo->CursorClipInfo.Left;
129     if(*y > CurInfo->CursorClipInfo.Bottom)
130       *y = CurInfo->CursorClipInfo.Bottom;
131     if(*y < CurInfo->CursorClipInfo.Top)
132       *y = CurInfo->CursorClipInfo.Top;
133     return TRUE;
134   }
135   return TRUE;
136 }
137
138 BOOL FASTCALL
139 IntDetectDblClick(PSYSTEM_CURSORINFO CurInfo, DWORD TickCount)
140 {
141   LONG dX, dY;
142   BOOL res = ((TickCount - CurInfo->LastBtnDown) < CurInfo->DblClickSpeed);
143   if(res)
144   {
145     /* check if the second click is within the DblClickWidth and DblClickHeight values */
146     dX = CurInfo->LastBtnDownX - CurInfo->x;
147     dY = CurInfo->LastBtnDownY - CurInfo->y;
148     if(dX < 0) dX = -dX;
149     if(dY < 0) dY = -dY;
150     
151     res = (dX <= CurInfo->DblClickWidth) &&
152           (dY <= CurInfo->DblClickHeight);
153
154     if(res)
155     {
156       CurInfo->LastBtnDown = 0; /* prevent sending 2 or more DBLCLK messages */
157       CurInfo->LastBtnDownX = CurInfo->x;
158       CurInfo->LastBtnDownY = CurInfo->y;
159     }
160     else
161     {
162       CurInfo->LastBtnDown = TickCount;
163       CurInfo->LastBtnDownX = CurInfo->x;
164       CurInfo->LastBtnDownY = CurInfo->y;
165     }
166   }
167   else
168   {
169     CurInfo->LastBtnDown = TickCount;
170     CurInfo->LastBtnDownX = CurInfo->x;
171     CurInfo->LastBtnDownY = CurInfo->y;
172   }
173   return res;
174 }
175
176 BOOL FASTCALL
177 IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject, BOOL Swap)
178 {
179   BOOL res = WinStaObject->SystemCursor.SwapButtons;
180   WinStaObject->SystemCursor.SwapButtons = Swap;
181   return res;
182 }
183
184 INT STDCALL
185 MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
186                        LONG HazardY1, LONG HazardX2, LONG HazardY2)
187 /*
188  * FUNCTION: Notify the mouse driver that drawing is about to begin in
189  * a rectangle on a particular surface.
190  */
191 {
192   RECTL MouseRect;
193   LONG tmp;
194   PSYSTEM_CURSORINFO CurInfo;
195   PSYSCURSOR SysCursor;
196   BOOL MouseEnabled = FALSE;
197
198
199   /* Mouse is not allowed to move if GDI is busy drawing */
200    
201   if(IntGetWindowStationObject(InputWindowStation))
202   {
203     CurInfo = &InputWindowStation->SystemCursor;
204     
205     SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
206     MouseEnabled = CurInfo->Enabled && SysCursor->hCursor;
207   }
208   else
209     return FALSE;
210     
211   CurInfo->SafetySwitch2 = TRUE;
212     
213   if (SurfObj == NULL)
214     {
215       ObDereferenceObject(InputWindowStation);
216       return(FALSE);
217     }
218
219
220   if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
221     {
222       ObDereferenceObject(InputWindowStation);
223       return(FALSE);
224     }
225
226   if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
227     {
228       /* Hardware cursor, no need to remove it */
229       ObDereferenceObject(InputWindowStation);
230       return(FALSE);
231     }
232
233   if (HazardX1 > HazardX2)
234     {
235       tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
236     }
237   if (HazardY1 > HazardY2)
238     {
239       tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
240     }
241
242   if (((CurInfo->x + SysCursor->cx) >= HazardX1)  && (CurInfo->x <= HazardX2) &&
243       ((CurInfo->y + SysCursor->cy) >= HazardY1) && (CurInfo->y <= HazardY2))
244     {
245       /* Mouse is not allowed to move if GDI is busy drawing */
246       ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
247       CurInfo->SafetySwitch = TRUE;
248       SurfGDI->MovePointer(SurfObj, -1, -1, &MouseRect);
249       ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
250     }
251     
252   ObDereferenceObject(InputWindowStation);
253   return(TRUE);
254 }
255
256 INT FASTCALL
257 MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI)
258 /*
259  * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
260  */
261 {
262   RECTL MouseRect;
263   PSYSTEM_CURSORINFO CurInfo;
264   PSYSCURSOR SysCursor;
265   BOOL MouseEnabled = FALSE;
266     
267   if(IntGetWindowStationObject(InputWindowStation))
268   {
269     CurInfo = &InputWindowStation->SystemCursor;
270   }
271   else
272     return FALSE;
273     
274   if(SurfObj == NULL)
275   {
276     CurInfo->SafetySwitch2 = FALSE;
277     ObDereferenceObject(InputWindowStation);
278     return FALSE;
279   }
280   
281   SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
282   MouseEnabled = CurInfo->Enabled && SysCursor->hCursor;
283
284   if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
285     {
286       CurInfo->SafetySwitch2 = FALSE;
287       ObDereferenceObject(InputWindowStation);
288       return(FALSE);
289     }
290
291   if (SPS_ACCEPT_NOEXCLUDE == PointerStatus)
292     {
293       /* Hardware cursor, it wasn't removed so need to restore it */
294       CurInfo->SafetySwitch2 = FALSE;
295       ObDereferenceObject(InputWindowStation);
296       return(FALSE);
297     }
298
299   if (CurInfo->SafetySwitch)
300     {
301       ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
302       SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
303       CurInfo->SafetySwitch = FALSE;
304       ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
305     }
306   
307   CurInfo->SafetySwitch2 = FALSE;
308   ObDereferenceObject(InputWindowStation);
309   return(TRUE);
310 }
311
312 BOOL FASTCALL
313 MouseMoveCursor(LONG X, LONG Y)
314 {
315   HDC hDC;
316   PDC dc;
317   RECTL MouseRect;
318   BOOL res = FALSE;
319   PSURFOBJ SurfObj;
320   PSURFGDI SurfGDI;
321   PSYSTEM_CURSORINFO CurInfo;
322   MSG Msg;
323   LARGE_INTEGER LargeTickCount;
324   ULONG TickCount;
325   static ULONG ButtonsDown = 0;
326   
327   if(!InputWindowStation)
328     return FALSE;
329   
330   if(IntGetWindowStationObject(InputWindowStation))
331   {
332     CurInfo = &InputWindowStation->SystemCursor;
333     if(!CurInfo->Enabled)
334     {
335       ObDereferenceObject(InputWindowStation);
336       return FALSE;
337     }
338     hDC = IntGetScreenDC();
339     if(!hDC)
340     {
341       ObDereferenceObject(InputWindowStation);
342       return FALSE;
343     }
344     dc = DC_LockDc(hDC);
345     SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
346     SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
347     DC_UnlockDc( hDC );
348     IntCheckClipCursor(&X, &Y, CurInfo);
349     if((X != CurInfo->x) || (Y != CurInfo->y))
350     {
351       /* send MOUSEMOVE message */
352       KeQueryTickCount(&LargeTickCount);
353       TickCount = LargeTickCount.u.LowPart;
354       Msg.wParam = ButtonsDown;
355       Msg.lParam = MAKELPARAM(X, Y);
356       Msg.message = WM_MOUSEMOVE;
357       Msg.time = TickCount;
358       Msg.pt.x = X;
359       Msg.pt.y = Y;
360       MsqInsertSystemMessage(&Msg, TRUE);
361       /* move cursor */
362       CurInfo->x = X;
363       CurInfo->y = Y;
364       if(CurInfo->Enabled)
365       {
366         ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
367         SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
368         ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
369       }
370       res = TRUE;
371     }
372         
373     ObDereferenceObject(InputWindowStation);
374     return res;
375   }
376   else
377     return FALSE;
378 }
379
380 VOID /* STDCALL */
381 MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
382 /*
383  * FUNCTION: Call by the mouse driver when input events occur.
384  */
385 {
386   ULONG i;
387   PSYSTEM_CURSORINFO CurInfo;
388   PSYSCURSOR SysCursor;
389   BOOL MouseEnabled = FALSE;
390   BOOL MouseMoveAdded = FALSE;
391   LONG mouse_ox, mouse_oy;
392   LONG mouse_cx = 0, mouse_cy = 0;
393   HDC hDC;
394   PDC dc;
395   PSURFOBJ SurfObj;
396   PSURFGDI SurfGDI;
397   RECTL MouseRect;
398   MSG Msg;
399   LARGE_INTEGER LargeTickCount;
400   ULONG TickCount;
401   static ULONG ButtonsDown = 0;
402   
403   hDC = IntGetScreenDC();
404   
405   if(!hDC || !InputWindowStation)
406     return;
407
408   if(IntGetWindowStationObject(InputWindowStation))
409   {
410     CurInfo = &InputWindowStation->SystemCursor;
411     SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
412     MouseEnabled = CurInfo->Enabled;
413     if(!MouseEnabled)
414     {
415       ObDereferenceObject(InputWindowStation);
416       return;
417     }
418     mouse_ox = CurInfo->x;
419     mouse_oy = CurInfo->y;
420   }
421   else
422     return;
423
424   dc = DC_LockDc(hDC);
425   SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
426   SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
427   DC_UnlockDc( hDC );
428
429   /* Compile the total mouse movement change and dispatch button events. */
430   for (i = 0; i < InputCount; i++)
431   {
432     mouse_cx += Data[i].LastX;
433     mouse_cy += Data[i].LastY;
434     
435     CurInfo->x += Data[i].LastX;
436     CurInfo->y += Data[i].LastY;
437     
438     CurInfo->x = max(CurInfo->x, 0);
439     CurInfo->y = max(CurInfo->y, 0);
440     CurInfo->x = min(CurInfo->x, SurfObj->sizlBitmap.cx - 1);
441     CurInfo->y = min(CurInfo->y, SurfObj->sizlBitmap.cy - 1);
442     
443     IntCheckClipCursor(&CurInfo->x, &CurInfo->y, CurInfo);
444     
445     KeQueryTickCount(&LargeTickCount);
446     TickCount = LargeTickCount.u.LowPart;
447
448     Msg.wParam = ButtonsDown;
449     Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
450     Msg.message = WM_MOUSEMOVE;
451     Msg.time = TickCount;
452     Msg.pt.x = CurInfo->x;
453     Msg.pt.y = CurInfo->y;
454     
455     MouseMoveAdded = FALSE;
456     
457     if (Data[i].ButtonFlags != 0)
458     {
459
460       if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) > 0)
461       {
462         /* insert WM_MOUSEMOVE messages before Button down messages */
463         if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
464         {
465           MsqInsertSystemMessage(&Msg, FALSE);
466           MouseMoveAdded = TRUE;
467         }
468         Msg.wParam  = CurInfo->SwapButtons ? MK_RBUTTON : MK_LBUTTON;
469         if(IntDetectDblClick(CurInfo, TickCount))
470           Msg.message = CurInfo->SwapButtons ? WM_RBUTTONDBLCLK : WM_LBUTTONDBLCLK;
471         else
472           Msg.message = CurInfo->SwapButtons ? WM_RBUTTONDOWN : WM_LBUTTONDOWN;
473       }
474       if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) > 0)
475       {
476         /* insert WM_MOUSEMOVE messages before Button down messages */
477         if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
478         {
479           MsqInsertSystemMessage(&Msg, FALSE);
480           MouseMoveAdded = TRUE;
481         }
482         Msg.wParam  = MK_MBUTTON;
483         if(IntDetectDblClick(CurInfo, TickCount))
484           Msg.message = WM_MBUTTONDBLCLK;
485         else
486           Msg.message = WM_MBUTTONDOWN;
487       }
488       if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) > 0)
489       {
490         /* insert WM_MOUSEMOVE messages before Button down messages */
491         if ((0 != Data[i].LastX) || (0 != Data[i].LastY))
492         {
493           MsqInsertSystemMessage(&Msg, FALSE);
494           MouseMoveAdded = TRUE;
495         }
496         Msg.wParam  = CurInfo->SwapButtons ? MK_LBUTTON : MK_RBUTTON;
497         if(IntDetectDblClick(CurInfo, TickCount))
498           Msg.message = CurInfo->SwapButtons ? WM_LBUTTONDBLCLK : WM_RBUTTONDBLCLK;
499         else
500           Msg.message = CurInfo->SwapButtons ? WM_LBUTTONDOWN : WM_RBUTTONDOWN;
501       }
502
503       if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_UP) > 0)
504       {
505         Msg.wParam  = CurInfo->SwapButtons ? MK_RBUTTON : MK_LBUTTON;
506         Msg.message = CurInfo->SwapButtons ? WM_RBUTTONUP : WM_LBUTTONUP;
507       }
508       if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) > 0)
509       {
510         Msg.wParam  = MK_MBUTTON;
511         Msg.message = WM_MBUTTONUP;
512       }
513       if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_UP) > 0)
514       {
515         Msg.wParam  = CurInfo->SwapButtons ? MK_LBUTTON : MK_RBUTTON;
516         Msg.message = CurInfo->SwapButtons ? WM_LBUTTONUP : WM_RBUTTONUP;
517       }
518
519       MsqInsertSystemMessage(&Msg, FALSE);
520       
521       /* insert WM_MOUSEMOVE messages after Button up messages */
522       if(!MouseMoveAdded && ((0 != Data[i].LastX) || (0 != Data[i].LastY)))
523       {
524         Msg.wParam = ButtonsDown;
525         Msg.message = WM_MOUSEMOVE;
526         MsqInsertSystemMessage(&Msg, FALSE);
527         MouseMoveAdded = TRUE;
528       }
529     }
530   }
531
532   /* If the mouse moved then move the pointer. */
533   if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled)
534   {
535
536     if(!MouseMoveAdded)
537     {
538      KeQueryTickCount(&LargeTickCount);
539      TickCount = LargeTickCount.u.LowPart;
540       Msg.wParam = ButtonsDown;
541       Msg.message = WM_MOUSEMOVE;
542       Msg.pt.x = CurInfo->x;
543       Msg.pt.y = CurInfo->y;
544       Msg.time = TickCount;
545       Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
546       MsqInsertSystemMessage(&Msg, TRUE);
547     }
548     
549     if (!CurInfo->SafetySwitch && !CurInfo->SafetySwitch2 &&
550         ((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
551     {
552       ExAcquireFastMutexUnsafe(&CurInfo->CursorMutex);
553       SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &MouseRect);
554       ExReleaseFastMutexUnsafe(&CurInfo->CursorMutex);
555     }
556   }
557
558   ObDereferenceObject(InputWindowStation);
559 }
560
561 VOID FASTCALL
562 EnableMouse(HDC hDisplayDC)
563 {
564   PDC dc;
565   PSURFOBJ SurfObj;
566   PSURFGDI SurfGDI;
567   HBITMAP hMouseSurf;
568   PSURFOBJ MouseSurf;
569   SIZEL MouseSize;
570   RECTL MouseRect;
571   PSYSTEM_CURSORINFO CurInfo;
572   PSYSCURSOR SysCursor;
573
574   if( hDisplayDC && InputWindowStation)
575   {
576     if(!IntGetWindowStationObject(InputWindowStation))
577     {
578        InputWindowStation->SystemCursor.Enabled = FALSE;
579        return;
580     }
581     
582     CurInfo = &InputWindowStation->SystemCursor;
583     SysCursor = &CurInfo->SystemCursors[CurInfo->CurrentCursor];
584     
585     dc = DC_LockDc(hDisplayDC);
586     SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
587     SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
588     DC_UnlockDc( hDisplayDC );
589     
590     /* Tell the display driver to set the pointer shape. */
591     CurInfo->x = SurfObj->sizlBitmap.cx / 2;
592     CurInfo->y = SurfObj->sizlBitmap.cy / 2;
593
594     /* Create the default mouse cursor. */
595     MouseSize.cx = SysCursor->cx;
596     MouseSize.cy = SysCursor->cy * 2;
597     hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, BMF_TOPDOWN, DefaultCursor);
598     MouseSurf = (PSURFOBJ)AccessUserObject((ULONG) hMouseSurf);
599
600     DPRINT("Setting Cursor up at 0x%x, 0x%x\n", CurInfo->x, CurInfo->y);
601     IntCheckClipCursor(&CurInfo->x, 
602                        &CurInfo->y,
603                        CurInfo);
604
605     PointerStatus = SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL,
606                                              SysCursor->hx,
607                                              SysCursor->hy, 
608                                              CurInfo->x, 
609                                              CurInfo->y, 
610                                              &MouseRect,
611                                              SPS_CHANGE);
612
613     InputWindowStation->SystemCursor.Enabled = (SPS_ACCEPT_EXCLUDE == PointerStatus ||
614                                                 SPS_ACCEPT_NOEXCLUDE == PointerStatus);
615
616     EngDeleteSurface(hMouseSurf);
617     ObDereferenceObject(InputWindowStation);
618     
619   }
620   else
621   {
622     if(IntGetWindowStationObject(InputWindowStation))
623     {
624        InputWindowStation->SystemCursor.Enabled = FALSE;
625        InputWindowStation->SystemCursor.CursorClipInfo.IsClipped = FALSE;
626            ObDereferenceObject(InputWindowStation);
627        return;
628     }
629   }
630 }
631 /* EOF */