- Compile Win32k, GDI, USER32 and CSRSS using W32API.
[reactos.git] / reactos / 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: mouse.c,v 1.65 2004/04/09 20:03:16 navaraf 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 <ddk/ntddmou.h>
33 #include <ddk/winddi.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/desktop.h"
40 #include "include/window.h"
41 #include "include/cursoricon.h"
42 #include "include/callback.h"
43 #include "include/palette.h"
44 #include "include/inteng.h"
45 #include "include/eng.h"
46 #include "include/tags.h"
47 #include <include/mouse.h>
48
49 #define NDEBUG
50 #include <debug.h>
51
52 #define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
53
54 /* FUNCTIONS *****************************************************************/
55
56 BOOL FASTCALL
57 IntIsPrimarySurface(PSURFGDI SurfGDI);
58
59
60 BOOL FASTCALL
61 IntCheckClipCursor(LONG *x, LONG *y, PSYSTEM_CURSORINFO CurInfo)
62 {
63 if(CurInfo->CursorClipInfo.IsClipped)
64 {
65 if(*x > CurInfo->CursorClipInfo.Right)
66 *x = CurInfo->CursorClipInfo.Right;
67 if(*x < CurInfo->CursorClipInfo.Left)
68 *x = CurInfo->CursorClipInfo.Left;
69 if(*y > CurInfo->CursorClipInfo.Bottom)
70 *y = CurInfo->CursorClipInfo.Bottom;
71 if(*y < CurInfo->CursorClipInfo.Top)
72 *y = CurInfo->CursorClipInfo.Top;
73 return TRUE;
74 }
75 return TRUE;
76 }
77
78 BOOL FASTCALL
79 IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject, BOOL Swap)
80 {
81 BOOL res = WinStaObject->SystemCursor.SwapButtons;
82 WinStaObject->SystemCursor.SwapButtons = Swap;
83 return res;
84 }
85
86 INT STDCALL
87 MouseSafetyOnDrawStart(SURFOBJ *SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
88 LONG HazardY1, LONG HazardX2, LONG HazardY2)
89 /*
90 * FUNCTION: Notify the mouse driver that drawing is about to begin in
91 * a rectangle on a particular surface.
92 */
93 {
94 LONG tmp;
95 PSYSTEM_CURSORINFO CurInfo;
96 BOOL MouseEnabled = FALSE;
97 PCURICON_OBJECT Cursor;
98
99
100 /* Mouse is not allowed to move if GDI is busy drawing */
101
102 if(IntGetWindowStationObject(InputWindowStation))
103 {
104 CurInfo = &InputWindowStation->SystemCursor;
105
106 MouseEnabled = CurInfo->Enabled && CurInfo->ShowingCursor;
107 }
108 else
109 return FALSE;
110
111 if (SurfObj == NULL)
112 {
113 ObDereferenceObject(InputWindowStation);
114 return(FALSE);
115 }
116 if (!IntIsPrimarySurface(SurfGDI) || MouseEnabled == FALSE)
117 {
118 ObDereferenceObject(InputWindowStation);
119 return(FALSE);
120 }
121
122 if (SPS_ACCEPT_NOEXCLUDE == SurfGDI->PointerStatus)
123 {
124 /* Hardware cursor, no need to remove it */
125 ObDereferenceObject(InputWindowStation);
126 return(FALSE);
127 }
128
129 if(!(Cursor = CurInfo->CurrentCursorObject))
130 {
131 ObDereferenceObject(InputWindowStation);
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 (CurInfo->PointerRectRight >= HazardX1
145 && CurInfo->PointerRectLeft <= HazardX2
146 && CurInfo->PointerRectBottom >= HazardY1
147 && CurInfo->PointerRectTop <= HazardY2)
148 {
149 /* Mouse is not allowed to move if GDI is busy drawing */
150 ExAcquireFastMutex(&CurInfo->CursorMutex);
151 if (0 != CurInfo->SafetyRemoveCount++)
152 {
153 /* Was already removed */
154 ExReleaseFastMutex(&CurInfo->CursorMutex);
155 ObDereferenceObject(InputWindowStation);
156 return FALSE;
157 }
158 CurInfo->SafetySwitch = TRUE;
159 IntLockGDIDriver(SurfGDI);
160 SurfGDI->MovePointer(SurfObj, -1, -1, NULL);
161 IntUnLockGDIDriver(SurfGDI);
162 ExReleaseFastMutex(&CurInfo->CursorMutex);
163 }
164
165 ObDereferenceObject(InputWindowStation);
166 return(TRUE);
167 }
168
169 STATIC VOID FASTCALL
170 SetPointerRect(PSYSTEM_CURSORINFO CurInfo, PRECTL PointerRect)
171 {
172 CurInfo->PointerRectLeft = PointerRect->left;
173 CurInfo->PointerRectRight = PointerRect->right;
174 CurInfo->PointerRectTop = PointerRect->top;
175 CurInfo->PointerRectBottom = PointerRect->bottom;
176 }
177
178 INT FASTCALL
179 MouseSafetyOnDrawEnd(SURFOBJ *SurfObj, SURFGDI *SurfGDI)
180 /*
181 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
182 */
183 {
184 PSYSTEM_CURSORINFO CurInfo;
185 BOOL MouseEnabled = FALSE;
186 RECTL PointerRect;
187
188 if(IntGetWindowStationObject(InputWindowStation))
189 {
190 CurInfo = &InputWindowStation->SystemCursor;
191 }
192 else
193 return FALSE;
194
195 ExAcquireFastMutex(&CurInfo->CursorMutex);
196 if(SurfObj == NULL)
197 {
198 ExReleaseFastMutex(&CurInfo->CursorMutex);
199 ObDereferenceObject(InputWindowStation);
200 return FALSE;
201 }
202
203 MouseEnabled = CurInfo->Enabled && CurInfo->ShowingCursor;
204 if (!IntIsPrimarySurface(SurfGDI) || MouseEnabled == FALSE)
205 {
206 ExReleaseFastMutex(&CurInfo->CursorMutex);
207 ObDereferenceObject(InputWindowStation);
208 return(FALSE);
209 }
210
211 if (SPS_ACCEPT_NOEXCLUDE == SurfGDI->PointerStatus)
212 {
213 /* Hardware cursor, it wasn't removed so need to restore it */
214 ExReleaseFastMutex(&CurInfo->CursorMutex);
215 ObDereferenceObject(InputWindowStation);
216 return(FALSE);
217 }
218
219 if (CurInfo->SafetySwitch)
220 {
221 if (1 < CurInfo->SafetyRemoveCount--)
222 {
223 /* Someone else removed it too, let them restore it */
224 ExReleaseFastMutex(&CurInfo->CursorMutex);
225 ObDereferenceObject(InputWindowStation);
226 return FALSE;
227 }
228 IntLockGDIDriver(SurfGDI);
229 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
230 IntUnLockGDIDriver(SurfGDI);
231 SetPointerRect(CurInfo, &PointerRect);
232 CurInfo->SafetySwitch = FALSE;
233 }
234
235 ExReleaseFastMutex(&CurInfo->CursorMutex);
236 ObDereferenceObject(InputWindowStation);
237 return(TRUE);
238 }
239
240 BOOL FASTCALL
241 MouseMoveCursor(LONG X, LONG Y)
242 {
243 HDC hDC;
244 PDC dc;
245 BOOL res = FALSE;
246 SURFOBJ *SurfObj;
247 PSURFGDI SurfGDI;
248 PSYSTEM_CURSORINFO CurInfo;
249 MSG Msg;
250 LARGE_INTEGER LargeTickCount;
251 ULONG TickCount;
252 RECTL PointerRect;
253
254 if(!InputWindowStation)
255 return FALSE;
256
257 if(IntGetWindowStationObject(InputWindowStation))
258 {
259 CurInfo = &InputWindowStation->SystemCursor;
260 if(!CurInfo->Enabled)
261 {
262 ObDereferenceObject(InputWindowStation);
263 return FALSE;
264 }
265 hDC = IntGetScreenDC();
266 if(!hDC)
267 {
268 ObDereferenceObject(InputWindowStation);
269 return FALSE;
270 }
271 dc = DC_LockDc(hDC);
272 SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
273 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
274 DC_UnlockDc( hDC );
275 IntCheckClipCursor(&X, &Y, CurInfo);
276 if((X != CurInfo->x) || (Y != CurInfo->y))
277 {
278 /* move cursor */
279 CurInfo->x = X;
280 CurInfo->y = Y;
281 if(CurInfo->Enabled)
282 {
283 ExAcquireFastMutex(&CurInfo->CursorMutex);
284 IntLockGDIDriver(SurfGDI);
285 if (SurfGDI->MovePointer != NULL)
286 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
287 IntUnLockGDIDriver(SurfGDI);
288 SetPointerRect(CurInfo, &PointerRect);
289 ExReleaseFastMutex(&CurInfo->CursorMutex);
290 }
291 /* send MOUSEMOVE message */
292 KeQueryTickCount(&LargeTickCount);
293 TickCount = LargeTickCount.u.LowPart;
294 Msg.wParam = CurInfo->ButtonsDown;
295 Msg.lParam = MAKELPARAM(X, Y);
296 Msg.message = WM_MOUSEMOVE;
297 Msg.time = TickCount;
298 Msg.pt.x = X;
299 Msg.pt.y = Y;
300 MsqInsertSystemMessage(&Msg, TRUE);
301 res = TRUE;
302 }
303
304 ObDereferenceObject(InputWindowStation);
305 return res;
306 }
307 else
308 return FALSE;
309 }
310
311 VOID /* STDCALL */
312 MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
313 /*
314 * FUNCTION: Call by the mouse driver when input events occur.
315 */
316 {
317 ULONG i;
318 PSYSTEM_CURSORINFO CurInfo;
319 BOOL MouseEnabled = FALSE;
320 BOOL Moved = FALSE;
321 LONG mouse_ox, mouse_oy;
322 LONG mouse_cx = 0, mouse_cy = 0;
323 LONG dScroll = 0;
324 HDC hDC;
325 PDC dc;
326 SURFOBJ *SurfObj;
327 PSURFGDI SurfGDI;
328 MSG Msg;
329 RECTL PointerRect;
330
331 hDC = IntGetScreenDC();
332
333 if(!hDC || !InputWindowStation)
334 return;
335
336 if(IntGetWindowStationObject(InputWindowStation))
337 {
338 CurInfo = &InputWindowStation->SystemCursor;
339 MouseEnabled = CurInfo->Enabled;
340 if(!MouseEnabled)
341 {
342 ObDereferenceObject(InputWindowStation);
343 return;
344 }
345 mouse_ox = CurInfo->x;
346 mouse_oy = CurInfo->y;
347 }
348 else
349 return;
350
351 dc = DC_LockDc(hDC);
352 SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
353 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
354 DC_UnlockDc( hDC );
355
356 /* Compile the total mouse movement change and dispatch button events. */
357 for (i = 0; i < InputCount; i++)
358 {
359 mouse_cx += Data[i].LastX;
360 mouse_cy += Data[i].LastY;
361
362 CurInfo->x += Data[i].LastX;
363 CurInfo->y += Data[i].LastY;
364
365 CurInfo->x = max(CurInfo->x, 0);
366 CurInfo->y = max(CurInfo->y, 0);
367 CurInfo->x = min(CurInfo->x, SurfObj->sizlBitmap.cx - 1);
368 CurInfo->y = min(CurInfo->y, SurfObj->sizlBitmap.cy - 1);
369
370 IntCheckClipCursor(&CurInfo->x, &CurInfo->y, CurInfo);
371
372 Msg.wParam = CurInfo->ButtonsDown;
373 Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
374 Msg.message = WM_MOUSEMOVE;
375 Msg.pt.x = CurInfo->x;
376 Msg.pt.y = CurInfo->y;
377
378 if (Data[i].ButtonFlags != 0)
379 {
380 if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) > 0)
381 {
382 CurInfo->ButtonsDown |= (CurInfo->SwapButtons ? MK_RBUTTON : MK_LBUTTON);
383 Msg.message = (CurInfo->SwapButtons ? WM_RBUTTONDOWN : WM_LBUTTONDOWN);
384 }
385 if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) > 0)
386 {
387 CurInfo->ButtonsDown |= MK_MBUTTON;
388 Msg.message = WM_MBUTTONDOWN;
389 }
390 if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) > 0)
391 {
392 CurInfo->ButtonsDown |= (CurInfo->SwapButtons ? MK_LBUTTON : MK_RBUTTON);
393 Msg.message = (CurInfo->SwapButtons ? WM_LBUTTONDOWN : WM_RBUTTONDOWN);
394 }
395
396 if ((Data[i].ButtonFlags & MOUSE_BUTTON_4_DOWN) > 0)
397 {
398 CurInfo->ButtonsDown |= MK_XBUTTON1;
399 Msg.message = WM_XBUTTONDOWN;
400 }
401 if ((Data[i].ButtonFlags & MOUSE_BUTTON_5_DOWN) > 0)
402 {
403 CurInfo->ButtonsDown |= MK_XBUTTON2;
404 Msg.message = WM_XBUTTONDOWN;
405 }
406
407 if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_UP) > 0)
408 {
409 CurInfo->ButtonsDown &= (CurInfo->SwapButtons ? ~MK_RBUTTON : ~MK_LBUTTON);
410 Msg.message = (CurInfo->SwapButtons ? WM_RBUTTONUP : WM_LBUTTONUP);
411 }
412 if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) > 0)
413 {
414 CurInfo->ButtonsDown &= ~MK_MBUTTON;
415 Msg.message = WM_MBUTTONUP;
416 }
417 if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_UP) > 0)
418 {
419 CurInfo->ButtonsDown &= (CurInfo->SwapButtons ? ~MK_LBUTTON : ~MK_RBUTTON);
420 Msg.message = (CurInfo->SwapButtons ? WM_LBUTTONUP : WM_RBUTTONUP);
421 }
422 if ((Data[i].ButtonFlags & MOUSE_BUTTON_4_UP) > 0)
423 {
424 CurInfo->ButtonsDown &= ~MK_XBUTTON1;
425 Msg.message = WM_XBUTTONUP;
426 }
427 if ((Data[i].ButtonFlags & MOUSE_BUTTON_5_UP) > 0)
428 {
429 CurInfo->ButtonsDown &= ~MK_XBUTTON2;
430 Msg.message = WM_XBUTTONUP;
431 }
432 if ((Data[i].ButtonFlags & MOUSE_WHEEL) > 0)
433 {
434 dScroll += (LONG)Data[i].ButtonData;
435 }
436
437 if (Data[i].ButtonFlags != MOUSE_WHEEL)
438 {
439 Moved = (0 != mouse_cx) || (0 != mouse_cy);
440 if(Moved && MouseEnabled)
441 {
442 if (!CurInfo->SafetySwitch && 0 == CurInfo->SafetyRemoveCount &&
443 ((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
444 {
445 ExAcquireFastMutex(&CurInfo->CursorMutex);
446 IntLockGDIDriver(SurfGDI);
447 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
448 IntUnLockGDIDriver(SurfGDI);
449 SetPointerRect(CurInfo, &PointerRect);
450 ExReleaseFastMutex(&CurInfo->CursorMutex);
451 mouse_cx = 0;
452 mouse_cy = 0;
453 }
454 }
455
456 Msg.wParam = CurInfo->ButtonsDown;
457 MsqInsertSystemMessage(&Msg, FALSE);
458 }
459 }
460 }
461
462 /* If the mouse moved then move the pointer. */
463 if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled)
464 {
465 Msg.wParam = CurInfo->ButtonsDown;
466 Msg.message = WM_MOUSEMOVE;
467 Msg.pt.x = CurInfo->x;
468 Msg.pt.y = CurInfo->y;
469 Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
470 MsqInsertSystemMessage(&Msg, TRUE);
471
472 if (!CurInfo->SafetySwitch && 0 == CurInfo->SafetyRemoveCount &&
473 ((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
474 {
475 ExAcquireFastMutex(&CurInfo->CursorMutex);
476 IntLockGDIDriver(SurfGDI);
477 SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
478 IntUnLockGDIDriver(SurfGDI);
479 SetPointerRect(CurInfo, &PointerRect);
480 ExReleaseFastMutex(&CurInfo->CursorMutex);
481 }
482 }
483
484 /* send WM_MOUSEWHEEL message */
485 if(dScroll && MouseEnabled)
486 {
487 Msg.message = WM_MOUSEWHEEL;
488 Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, dScroll);
489 Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
490 Msg.pt.x = CurInfo->x;
491 Msg.pt.y = CurInfo->y;
492 MsqInsertSystemMessage(&Msg, FALSE);
493 }
494
495 ObDereferenceObject(InputWindowStation);
496 }
497
498 VOID FASTCALL
499 EnableMouse(HDC hDisplayDC)
500 {
501 PDC dc;
502 SURFOBJ *SurfObj;
503 PSURFGDI SurfGDI;
504
505 if( hDisplayDC && InputWindowStation)
506 {
507 if(!IntGetWindowStationObject(InputWindowStation))
508 {
509 InputWindowStation->SystemCursor.Enabled = FALSE;
510 return;
511 }
512
513 dc = DC_LockDc(hDisplayDC);
514 SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
515 SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
516 DC_UnlockDc( hDisplayDC );
517
518 IntSetCursor(InputWindowStation, NULL, TRUE);
519
520 InputWindowStation->SystemCursor.Enabled = (SPS_ACCEPT_EXCLUDE == SurfGDI->PointerStatus ||
521 SPS_ACCEPT_NOEXCLUDE == SurfGDI->PointerStatus);
522
523 /* Move the cursor to the screen center */
524 DPRINT("Setting Cursor up at 0x%x, 0x%x\n", SurfObj->sizlBitmap.cx / 2, SurfObj->sizlBitmap.cy / 2);
525 MouseMoveCursor(SurfObj->sizlBitmap.cx / 2, SurfObj->sizlBitmap.cy / 2);
526
527 ObDereferenceObject(InputWindowStation);
528 }
529 else
530 {
531 if(IntGetWindowStationObject(InputWindowStation))
532 {
533 IntSetCursor(InputWindowStation, NULL, TRUE);
534 InputWindowStation->SystemCursor.Enabled = FALSE;
535 InputWindowStation->SystemCursor.CursorClipInfo.IsClipped = FALSE;
536 ObDereferenceObject(InputWindowStation);
537 return;
538 }
539 }
540 }
541
542 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
543
544 VOID FASTCALL
545 IntHideMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
546 {
547 if (ppdev->PointerAttributes.Enable == FALSE)
548 {
549 return;
550 }
551
552 ppdev->PointerAttributes.Enable = FALSE;
553
554 if (ppdev->PointerAttributes.Column + ppdev->PointerHotSpot.x == -1)
555 {
556 return;
557 }
558
559 if (ppdev->PointerSaveSurface != NULL)
560 {
561 RECTL DestRect;
562 POINTL SrcPoint;
563 SURFOBJ *SaveSurface;
564 SURFOBJ *MaskSurface;
565
566 DestRect.left = max(ppdev->PointerAttributes.Column, 0);
567 DestRect.top = max(ppdev->PointerAttributes.Row, 0);
568 DestRect.right = min(
569 ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
570 DestSurface->sizlBitmap.cx);
571 DestRect.bottom = min(
572 ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
573 DestSurface->sizlBitmap.cy);
574
575 SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
576 SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
577
578 SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
579 MaskSurface = EngLockSurface(ppdev->PointerMaskSurface);
580 EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
581 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY);
582 EngUnlockSurface(MaskSurface);
583 EngUnlockSurface(SaveSurface);
584 }
585 }
586
587 VOID FASTCALL
588 IntShowMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
589 {
590 if (ppdev->PointerAttributes.Enable == TRUE)
591 {
592 return;
593 }
594
595 ppdev->PointerAttributes.Enable = TRUE;
596
597 /*
598 * Copy the pixels under the cursor to temporary surface.
599 */
600
601 if (ppdev->PointerSaveSurface != NULL)
602 {
603 RECTL DestRect;
604 POINTL SrcPoint;
605 SURFOBJ *SaveSurface;
606
607 SrcPoint.x = max(ppdev->PointerAttributes.Column, 0);
608 SrcPoint.y = max(ppdev->PointerAttributes.Row, 0);
609
610 DestRect.left = SrcPoint.x - ppdev->PointerAttributes.Column;
611 DestRect.top = SrcPoint.y - ppdev->PointerAttributes.Row;
612 DestRect.right = min(
613 ppdev->PointerAttributes.Width,
614 DestSurface->sizlBitmap.cx - ppdev->PointerAttributes.Column);
615 DestRect.bottom = min(
616 ppdev->PointerAttributes.Height,
617 DestSurface->sizlBitmap.cy - ppdev->PointerAttributes.Row);
618
619 SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
620 EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL,
621 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY);
622 EngUnlockSurface(SaveSurface);
623 }
624
625 /*
626 * Blit the cursor on the screen.
627 */
628
629 {
630 RECTL DestRect;
631 POINTL SrcPoint;
632 SURFOBJ *ColorSurf;
633 SURFOBJ *MaskSurf;
634
635 DestRect.left = max(ppdev->PointerAttributes.Column, 0);
636 DestRect.top = max(ppdev->PointerAttributes.Row, 0);
637 DestRect.right = min(
638 ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
639 DestSurface->sizlBitmap.cx);
640 DestRect.bottom = min(
641 ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
642 DestSurface->sizlBitmap.cy);
643
644 SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
645 SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
646
647 MaskSurf = EngLockSurface(ppdev->PointerMaskSurface);
648 if (ppdev->PointerColorSurface != NULL)
649 {
650 ColorSurf = EngLockSurface(ppdev->PointerColorSurface);
651 EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, ppdev->PointerXlateObject,
652 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC);
653 EngUnlockSurface(ColorSurf);
654 }
655 else
656 {
657 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
658 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND);
659 SrcPoint.y += ppdev->PointerAttributes.Height;
660 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
661 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT);
662 }
663 EngUnlockSurface(MaskSurf);
664 }
665 }
666
667 /*
668 * @implemented
669 */
670
671 ULONG STDCALL
672 EngSetPointerShape(
673 IN SURFOBJ *pso,
674 IN SURFOBJ *psoMask,
675 IN SURFOBJ *psoColor,
676 IN XLATEOBJ *pxlo,
677 IN LONG xHot,
678 IN LONG yHot,
679 IN LONG x,
680 IN LONG y,
681 IN RECTL *prcl,
682 IN FLONG fl)
683 {
684 GDIDEVICE *ppdev = (GDIDEVICE *)pso->hdev;
685 SURFOBJ *TempSurfObj;
686
687 IntHideMousePointer(ppdev, pso);
688
689 if (ppdev->PointerColorSurface != NULL)
690 {
691 /* FIXME: Is this really needed? */
692 TempSurfObj = EngLockSurface(ppdev->PointerColorSurface);
693 EngFreeMem(TempSurfObj->pvBits);
694 TempSurfObj->pvBits = 0;
695 EngUnlockSurface(TempSurfObj);
696
697 EngDeleteSurface(ppdev->PointerColorSurface);
698 ppdev->PointerMaskSurface = NULL;
699 }
700
701 if (ppdev->PointerMaskSurface != NULL)
702 {
703 /* FIXME: Is this really needed? */
704 TempSurfObj = EngLockSurface(ppdev->PointerMaskSurface);
705 EngFreeMem(TempSurfObj->pvBits);
706 TempSurfObj->pvBits = 0;
707 EngUnlockSurface(TempSurfObj);
708
709 EngDeleteSurface(ppdev->PointerMaskSurface);
710 ppdev->PointerMaskSurface = NULL;
711 }
712
713 if (ppdev->PointerSaveSurface != NULL)
714 {
715 EngDeleteSurface(ppdev->PointerSaveSurface);
716 ppdev->PointerSaveSurface = NULL;
717 }
718
719 if (ppdev->PointerXlateObject != NULL)
720 {
721 EngDeleteXlate(ppdev->PointerXlateObject);
722 ppdev->PointerXlateObject = NULL;
723 }
724
725 /*
726 * See if we are being asked to hide the pointer.
727 */
728
729 if (psoMask == NULL)
730 {
731 return SPS_ACCEPT_NOEXCLUDE;
732 }
733
734 ppdev->PointerHotSpot.x = xHot;
735 ppdev->PointerHotSpot.y = yHot;
736
737 ppdev->PointerAttributes.Column = x - xHot;
738 ppdev->PointerAttributes.Row = y - yHot;
739 ppdev->PointerAttributes.Width = psoMask->lDelta << 3;
740 ppdev->PointerAttributes.Height = (psoMask->cjBits / psoMask->lDelta) >> 1;
741
742 if (prcl != NULL)
743 {
744 prcl->left = ppdev->PointerAttributes.Column;
745 prcl->top = ppdev->PointerAttributes.Row;
746 prcl->right = prcl->left + ppdev->PointerAttributes.Width;
747 prcl->bottom = prcl->top + ppdev->PointerAttributes.Height;
748 }
749
750 if (psoColor != NULL)
751 {
752 SIZEL Size;
753 PBYTE Bits;
754
755 Size.cx = ppdev->PointerAttributes.Width;
756 Size.cy = ppdev->PointerAttributes.Height;
757 Bits = EngAllocMem(0, psoColor->cjBits, TAG_MOUSE);
758 memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
759
760 ppdev->PointerColorSurface = (HSURF)EngCreateBitmap(Size,
761 psoColor->lDelta, psoColor->iBitmapFormat, 0, Bits);
762 }
763 else
764 {
765 ppdev->PointerColorSurface = NULL;
766 }
767
768 {
769 SIZEL Size;
770 PBYTE Bits;
771
772 Size.cx = ppdev->PointerAttributes.Width;
773 Size.cy = ppdev->PointerAttributes.Height << 1;
774 Bits = EngAllocMem(0, psoMask->cjBits, TAG_MOUSE);
775 memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
776
777 ppdev->PointerMaskSurface = (HSURF)EngCreateBitmap(Size,
778 psoMask->lDelta, psoMask->iBitmapFormat, 0, Bits);
779 }
780
781 /*
782 * Create and XLATEOBJ that will be used for drawing masks.
783 * FIXME: We should get this in pxlo parameter!
784 */
785
786 if (pxlo == NULL)
787 {
788 HPALETTE BWPalette, DestPalette;
789 ULONG BWColors[] = {0, 0xFFFFFF};
790 PDC Dc;
791 PPALGDI PalObj;
792 LONG DestMode;
793
794 BWPalette = EngCreatePalette(PAL_INDEXED, sizeof(BWColors) / sizeof(ULONG),
795 BWColors, 0, 0, 0);
796 Dc = DC_LockDc(IntGetScreenDC());
797 DestPalette = Dc->w.hPalette;
798 PalObj = PALETTE_LockPalette(DestPalette);
799 DestMode = PalObj->Mode;
800 PALETTE_UnlockPalette(DestPalette);
801 DC_UnlockDc(IntGetScreenDC());
802 ppdev->PointerXlateObject = IntEngCreateXlate(DestMode, PAL_INDEXED,
803 DestPalette, BWPalette);
804 EngDeletePalette(BWPalette);
805 }
806 else
807 {
808 ppdev->PointerXlateObject = pxlo;
809 }
810
811 /*
812 * Create surface for saving the pixels under the cursor.
813 */
814
815 {
816 SIZEL Size;
817 LONG lDelta;
818
819 Size.cx = ppdev->PointerAttributes.Width;
820 Size.cy = ppdev->PointerAttributes.Height;
821
822 switch (pso->iBitmapFormat)
823 {
824 case BMF_1BPP: lDelta = Size.cx >> 3; break;
825 case BMF_4BPP: lDelta = Size.cx >> 1; break;
826 case BMF_8BPP: lDelta = Size.cx; break;
827 case BMF_16BPP: lDelta = Size.cx << 1; break;
828 case BMF_24BPP: lDelta = Size.cx * 3; break;
829 case BMF_32BPP: lDelta = Size.cx << 2; break;
830 }
831
832 ppdev->PointerSaveSurface = (HSURF)EngCreateBitmap(
833 Size, lDelta, pso->iBitmapFormat, BMF_NOZEROINIT, NULL);
834 }
835
836 IntShowMousePointer(ppdev, pso);
837
838 return SPS_ACCEPT_EXCLUDE;
839 }
840
841 /*
842 * @implemented
843 */
844
845 VOID STDCALL
846 EngMovePointer(
847 IN SURFOBJ *pso,
848 IN LONG x,
849 IN LONG y,
850 IN RECTL *prcl)
851 {
852 GDIDEVICE *ppdev = (GDIDEVICE *)pso->hdev;
853
854 IntHideMousePointer(ppdev, pso);
855 ppdev->PointerAttributes.Column = x - ppdev->PointerHotSpot.x;
856 ppdev->PointerAttributes.Row = y - ppdev->PointerHotSpot.y;
857 if (x != -1)
858 {
859 IntShowMousePointer(ppdev, pso);
860 }
861
862 if (prcl != NULL)
863 {
864 prcl->left = ppdev->PointerAttributes.Column;
865 prcl->top = ppdev->PointerAttributes.Row;
866 prcl->right = prcl->left + ppdev->PointerAttributes.Width;
867 prcl->bottom = prcl->top + ppdev->PointerAttributes.Height;
868 }
869 }
870
871 /* EOF */