[INTRIN]
[reactos.git] / reactos / win32ss / core / gdi / eng / mouse.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS win32 subsystem
4 * PURPOSE: Mouse pointer functions
5 * FILE: subsystems/win32k/eng/mouse.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Timo Kreuzer (timo.kreuzer@reactos.org)
8 */
9 /* INCLUDES ******************************************************************/
10
11 #include <win32k.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 BOOL
19 APIENTRY
20 EngSetPointerTag(
21 IN HDEV hdev,
22 IN SURFOBJ *psoMask,
23 IN SURFOBJ *psoColor,
24 IN XLATEOBJ *pxlo,
25 IN FLONG fl)
26 {
27 // This function is obsolete for Windows 2000 and later.
28 // This function is still supported, but always returns FALSE.
29 // www.osr.com/ddk/graphics/gdifncs_4yav.htm
30 return FALSE;
31 }
32
33 /*
34 * FUNCTION: Notify the mouse driver that drawing is about to begin in
35 * a rectangle on a particular surface.
36 */
37 INT NTAPI
38 MouseSafetyOnDrawStart(
39 PPDEVOBJ ppdev,
40 LONG HazardX1,
41 LONG HazardY1,
42 LONG HazardX2,
43 LONG HazardY2)
44 {
45 LONG tmp;
46 GDIPOINTER *pgp;
47
48 ASSERT(ppdev != NULL);
49 ASSERT(ppdev->pSurface != NULL);
50
51 pgp = &ppdev->Pointer;
52
53 if (pgp->Exclude.right == -1)
54 {
55 return FALSE;
56 }
57
58 ppdev->SafetyRemoveCount++;
59
60 if (ppdev->SafetyRemoveLevel != 0)
61 {
62 return FALSE;
63 }
64
65 if (HazardX1 > HazardX2)
66 {
67 tmp = HazardX2;
68 HazardX2 = HazardX1;
69 HazardX1 = tmp;
70 }
71 if (HazardY1 > HazardY2)
72 {
73 tmp = HazardY2;
74 HazardY2 = HazardY1;
75 HazardY1 = tmp;
76 }
77
78 if (pgp->Exclude.right >= HazardX1
79 && pgp->Exclude.left <= HazardX2
80 && pgp->Exclude.bottom >= HazardY1
81 && pgp->Exclude.top <= HazardY2)
82 {
83 ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
84 ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj, -1, -1, NULL);
85 }
86
87 return(TRUE);
88 }
89
90 /*
91 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
92 */
93 INT NTAPI
94 MouseSafetyOnDrawEnd(
95 PPDEVOBJ ppdev)
96 {
97 GDIPOINTER *pgp;
98
99 ASSERT(ppdev != NULL);
100 ASSERT(ppdev->pSurface != NULL);
101
102 pgp = &ppdev->Pointer;
103
104 if (pgp->Exclude.right == -1)
105 {
106 return FALSE;
107 }
108
109 if (--ppdev->SafetyRemoveCount >= ppdev->SafetyRemoveLevel)
110 {
111 return FALSE;
112 }
113
114 ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj,
115 gpsi->ptCursor.x,
116 gpsi->ptCursor.y,
117 &pgp->Exclude);
118
119 ppdev->SafetyRemoveLevel = 0;
120
121 return(TRUE);
122 }
123
124 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
125
126 VOID
127 NTAPI
128 IntHideMousePointer(
129 PDEVOBJ *ppdev,
130 SURFOBJ *psoDest)
131 {
132 GDIPOINTER *pgp;
133 POINTL pt;
134 RECTL rclDest;
135 POINTL ptlSave;
136
137 ASSERT(ppdev);
138 ASSERT(psoDest);
139
140 pgp = &ppdev->Pointer;
141
142 if (!pgp->Enabled)
143 {
144 return;
145 }
146
147 pgp->Enabled = FALSE;
148
149 if (!pgp->psurfSave)
150 {
151 DPRINT("No SaveSurface!\n");
152 return;
153 }
154
155 /* Calculate cursor coordinates */
156 pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x;
157 pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y;
158
159 rclDest.left = max(pt.x, 0);
160 rclDest.top = max(pt.y, 0);
161 rclDest.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx);
162 rclDest.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy);
163
164 ptlSave.x = rclDest.left - pt.x;
165 ptlSave.y = rclDest.top - pt.y;
166
167 IntEngBitBlt(psoDest,
168 &pgp->psurfSave->SurfObj,
169 NULL,
170 NULL,
171 NULL,
172 &rclDest,
173 &ptlSave,
174 &ptlSave,
175 NULL,
176 NULL,
177 ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
178 }
179
180 VOID
181 NTAPI
182 IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest)
183 {
184 GDIPOINTER *pgp;
185 POINTL pt;
186 RECTL rclSurf, rclPointer;
187
188 ASSERT(ppdev);
189 ASSERT(psoDest);
190
191 pgp = &ppdev->Pointer;
192
193 if (pgp->Enabled)
194 {
195 return;
196 }
197
198 pgp->Enabled = TRUE;
199
200 /* Check if we have any mouse pointer */
201 if (!pgp->psurfSave) return;
202
203 /* Calculate pointer coordinates */
204 pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x;
205 pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y;
206
207 /* Calculate the rect on the surface */
208 rclSurf.left = max(pt.x, 0);
209 rclSurf.top = max(pt.y, 0);
210 rclSurf.right = min(pt.x + pgp->Size.cx, psoDest->sizlBitmap.cx);
211 rclSurf.bottom = min(pt.y + pgp->Size.cy, psoDest->sizlBitmap.cy);
212
213 /* Calculate the rect in the pointer bitmap */
214 rclPointer.left = rclSurf.left - pt.x;
215 rclPointer.top = rclSurf.top - pt.y;
216 rclPointer.right = min(pgp->Size.cx, psoDest->sizlBitmap.cx - pt.x);
217 rclPointer.bottom = min(pgp->Size.cy, psoDest->sizlBitmap.cy - pt.y);
218
219 /* Copy the pixels under the cursor to temporary surface. */
220 IntEngBitBlt(&pgp->psurfSave->SurfObj,
221 psoDest,
222 NULL,
223 NULL,
224 NULL,
225 &rclPointer,
226 (POINTL*)&rclSurf,
227 NULL,
228 NULL,
229 NULL,
230 ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
231
232 /* Blt the pointer on the screen. */
233 if (pgp->psurfColor)
234 {
235 if(!(pgp->flags & SPS_ALPHA))
236 {
237 IntEngBitBlt(psoDest,
238 &pgp->psurfMask->SurfObj,
239 NULL,
240 NULL,
241 NULL,
242 &rclSurf,
243 (POINTL*)&rclPointer,
244 NULL,
245 NULL,
246 NULL,
247 ROP4_SRCAND);
248
249 IntEngBitBlt(psoDest,
250 &pgp->psurfColor->SurfObj,
251 NULL,
252 NULL,
253 NULL,
254 &rclSurf,
255 (POINTL*)&rclPointer,
256 NULL,
257 NULL,
258 NULL,
259 ROP4_SRCINVERT);
260 }
261 else
262 {
263 BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
264 EXLATEOBJ exlo;
265 EXLATEOBJ_vInitialize(&exlo,
266 &gpalRGB,
267 ppdev->ppalSurf,
268 0, 0, 0);
269 IntEngAlphaBlend(psoDest,
270 &pgp->psurfColor->SurfObj,
271 NULL,
272 &exlo.xlo,
273 &rclSurf,
274 &rclPointer,
275 &blendobj);
276 EXLATEOBJ_vCleanup(&exlo);
277 }
278 }
279 else
280 {
281 IntEngBitBlt(psoDest,
282 &pgp->psurfMask->SurfObj,
283 NULL,
284 NULL,
285 NULL,
286 &rclSurf,
287 (POINTL*)&rclPointer,
288 NULL,
289 NULL,
290 NULL,
291 ROP4_FROM_INDEX(R3_OPINDEX_SRCAND));
292
293 rclPointer.top += pgp->Size.cy;
294
295 IntEngBitBlt(psoDest,
296 &pgp->psurfMask->SurfObj,
297 NULL,
298 NULL,
299 NULL,
300 &rclSurf,
301 (POINTL*)&rclPointer,
302 NULL,
303 NULL,
304 NULL,
305 ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT));
306 }
307 }
308
309 /*
310 * @implemented
311 */
312 ULONG APIENTRY
313 EngSetPointerShape(
314 IN SURFOBJ *pso,
315 IN SURFOBJ *psoMask,
316 IN SURFOBJ *psoColor,
317 IN XLATEOBJ *pxlo,
318 IN LONG xHot,
319 IN LONG yHot,
320 IN LONG x,
321 IN LONG y,
322 IN RECTL *prcl,
323 IN FLONG fl)
324 {
325 PDEVOBJ *ppdev;
326 GDIPOINTER *pgp;
327 LONG lDelta = 0;
328 HBITMAP hbmSave = NULL, hbmColor = NULL, hbmMask = NULL;
329 PSURFACE psurfSave = NULL, psurfColor = NULL, psurfMask = NULL;
330 RECTL rectl;
331 SIZEL sizel = {0, 0};
332
333 ASSERT(pso);
334
335 ppdev = GDIDEV(pso);
336 pgp = &ppdev->Pointer;
337
338 /* Do we have any bitmap at all? */
339 if (psoColor || psoMask)
340 {
341 /* Get the size of the new pointer */
342 if (psoColor)
343 {
344 sizel.cx = psoColor->sizlBitmap.cx;
345 sizel.cy = psoColor->sizlBitmap.cy;
346 }
347 else// if (psoMask)
348 {
349 sizel.cx = psoMask->sizlBitmap.cx;
350 sizel.cy = psoMask->sizlBitmap.cy / 2;
351 }
352
353 rectl.left = 0;
354 rectl.top = 0;
355 rectl.right = sizel.cx;
356 rectl.bottom = sizel.cy;
357
358 /* Calculate lDelta for our surfaces. */
359 lDelta = WIDTH_BYTES_ALIGN32(sizel.cx,
360 BitsPerFormat(pso->iBitmapFormat));
361
362 /* Create a bitmap for saving the pixels under the cursor. */
363 hbmSave = EngCreateBitmap(sizel,
364 lDelta,
365 pso->iBitmapFormat,
366 BMF_TOPDOWN | BMF_NOZEROINIT,
367 NULL);
368 psurfSave = SURFACE_ShareLockSurface(hbmSave);
369 if (!psurfSave) goto failure;
370 }
371
372 if (psoColor)
373 {
374 if (fl & SPS_ALPHA)
375 {
376 /* Always store the alpha cursor in RGB. */
377 EXLATEOBJ exloSrcRGB;
378 PEXLATEOBJ pexlo;
379
380 pexlo = CONTAINING_RECORD(pxlo, EXLATEOBJ, xlo);
381 EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);
382
383 hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
384 WIDTH_BYTES_ALIGN32(sizel.cx, 32),
385 BMF_32BPP,
386 BMF_TOPDOWN | BMF_NOZEROINIT,
387 NULL);
388 psurfColor = SURFACE_ShareLockSurface(hbmColor);
389 if (!psurfColor) goto failure;
390
391 /* Now copy the given bitmap. */
392 rectl.bottom = psoColor->sizlBitmap.cy;
393 IntEngCopyBits(&psurfColor->SurfObj,
394 psoColor,
395 NULL,
396 &exloSrcRGB.xlo,
397 &rectl,
398 (POINTL*)&rectl);
399
400 EXLATEOBJ_vCleanup(&exloSrcRGB);
401 }
402 else
403 {
404 /* Color bitmap must have the same format as the dest surface */
405 if (psoColor->iBitmapFormat != pso->iBitmapFormat)
406 {
407 DPRINT1("Screen surface and cursor color bitmap format don't match!.\n");
408 goto failure;
409 }
410
411 /* Create a bitmap to copy the color bitmap to */
412 hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
413 lDelta,
414 pso->iBitmapFormat,
415 BMF_TOPDOWN | BMF_NOZEROINIT,
416 NULL);
417 psurfColor = SURFACE_ShareLockSurface(hbmColor);
418 if (!psurfColor) goto failure;
419
420 /* Now copy the given bitmap. */
421 rectl.bottom = psoColor->sizlBitmap.cy;
422 IntEngCopyBits(&psurfColor->SurfObj,
423 psoColor,
424 NULL,
425 pxlo,
426 &rectl,
427 (POINTL*)&rectl);
428 }
429
430 }
431
432 /* Create a mask surface */
433 if (psoMask)
434 {
435 EXLATEOBJ exlo;
436 PPALETTE ppal;
437
438 lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, BitsPerFormat(pso->iBitmapFormat));
439
440 /* Create a bitmap for the mask */
441 hbmMask = EngCreateBitmap(psoMask->sizlBitmap,
442 lDelta,
443 pso->iBitmapFormat,
444 BMF_TOPDOWN | BMF_NOZEROINIT,
445 NULL);
446 psurfMask = SURFACE_ShareLockSurface(hbmMask);
447 if (!psurfMask) goto failure;
448
449 /* Initialize an EXLATEOBJ */
450 ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
451 EXLATEOBJ_vInitialize(&exlo,
452 gppalMono,
453 ppal,
454 0,
455 RGB(0xff,0xff,0xff),
456 RGB(0,0,0));
457
458 /* Copy the mask bitmap */
459 rectl.bottom = psoMask->sizlBitmap.cy;
460 IntEngCopyBits(&psurfMask->SurfObj,
461 psoMask,
462 NULL,
463 &exlo.xlo,
464 &rectl,
465 (POINTL*)&rectl);
466
467 /* Cleanup */
468 EXLATEOBJ_vCleanup(&exlo);
469 if (ppal) PALETTE_ShareUnlockPalette(ppal);
470 }
471
472 /* Hide mouse pointer */
473 IntHideMousePointer(ppdev, pso);
474
475 /* Free old color bitmap */
476 if (pgp->psurfColor)
477 {
478 EngDeleteSurface(pgp->psurfColor->BaseObject.hHmgr);
479 SURFACE_ShareUnlockSurface(pgp->psurfColor);
480 pgp->psurfColor = NULL;
481 }
482
483 /* Free old mask bitmap */
484 if (pgp->psurfMask)
485 {
486 EngDeleteSurface(pgp->psurfMask->BaseObject.hHmgr);
487 SURFACE_ShareUnlockSurface(pgp->psurfMask);
488 pgp->psurfMask = NULL;
489 }
490
491 /* Free old save bitmap */
492 if (pgp->psurfSave)
493 {
494 EngDeleteSurface(pgp->psurfSave->BaseObject.hHmgr);
495 SURFACE_ShareUnlockSurface(pgp->psurfSave);
496 pgp->psurfSave = NULL;
497 }
498
499 /* See if we are being asked to hide the pointer. */
500 if (psoMask == NULL && psoColor == NULL)
501 {
502 /* We're done */
503 return SPS_ACCEPT_NOEXCLUDE;
504 }
505
506 /* Now set the new cursor */
507 pgp->psurfColor = psurfColor;
508 pgp->psurfMask = psurfMask;
509 pgp->psurfSave = psurfSave;
510 pgp->HotSpot.x = xHot;
511 pgp->HotSpot.y = yHot;
512 pgp->Size = sizel;
513 pgp->flags = fl;
514
515 if (x != -1)
516 {
517 ppdev->ptlPointer.x = x;
518 ppdev->ptlPointer.y = y;
519
520 IntShowMousePointer(ppdev, pso);
521
522 if (prcl != NULL)
523 {
524 prcl->left = x - pgp->HotSpot.x;
525 prcl->top = y - pgp->HotSpot.x;
526 prcl->right = prcl->left + pgp->Size.cx;
527 prcl->bottom = prcl->top + pgp->Size.cy;
528 }
529 }
530 else if (prcl != NULL)
531 {
532 prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
533 }
534
535 return SPS_ACCEPT_NOEXCLUDE;
536
537 failure:
538 /* Cleanup surfaces */
539 if (hbmMask) EngDeleteSurface((HSURF)hbmMask);
540 if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask);
541 if (hbmColor) EngDeleteSurface((HSURF)hbmColor);
542 if (psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
543 if (hbmSave) EngDeleteSurface((HSURF)hbmSave);
544 if (psurfSave) SURFACE_ShareUnlockSurface(psurfSave);
545
546 return SPS_ERROR;
547 }
548
549 /*
550 * @implemented
551 */
552
553 VOID APIENTRY
554 EngMovePointer(
555 IN SURFOBJ *pso,
556 IN LONG x,
557 IN LONG y,
558 IN RECTL *prcl)
559 {
560 PDEVOBJ *ppdev;
561 GDIPOINTER *pgp;
562
563 ASSERT(pso);
564
565 ppdev = GDIDEV(pso);
566 ASSERT(ppdev);
567
568 pgp = &ppdev->Pointer;
569
570 IntHideMousePointer(ppdev, pso);
571
572 ppdev->ptlPointer.x = x;
573 ppdev->ptlPointer.y = y;
574
575 if (x != -1)
576 {
577 IntShowMousePointer(ppdev, pso);
578 if (prcl != NULL)
579 {
580 prcl->left = x - pgp->HotSpot.x;
581 prcl->top = y - pgp->HotSpot.y;
582 prcl->right = prcl->left + pgp->Size.cx;
583 prcl->bottom = prcl->top + pgp->Size.cy;
584 }
585 }
586 else if (prcl != NULL)
587 {
588 prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
589 }
590 }
591
592 ULONG APIENTRY
593 IntEngSetPointerShape(
594 IN SURFOBJ *pso,
595 IN SURFOBJ *psoMask,
596 IN SURFOBJ *psoColor,
597 IN XLATEOBJ *pxlo,
598 IN LONG xHot,
599 IN LONG yHot,
600 IN LONG x,
601 IN LONG y,
602 IN RECTL *prcl,
603 IN FLONG fl)
604 {
605 ULONG ulResult = SPS_DECLINE;
606 PFN_DrvSetPointerShape pfnSetPointerShape;
607 PPDEVOBJ ppdev = GDIDEV(pso);
608
609 pfnSetPointerShape = GDIDEVFUNCS(pso).SetPointerShape;
610
611 if (pfnSetPointerShape)
612 {
613 ulResult = pfnSetPointerShape(pso,
614 psoMask,
615 psoColor,
616 pxlo,
617 xHot,
618 yHot,
619 x,
620 y,
621 prcl,
622 fl);
623 }
624
625 /* Check if the driver accepted it */
626 if (ulResult == SPS_ACCEPT_NOEXCLUDE)
627 {
628 /* Set MovePointer to the driver function */
629 ppdev->pfnMovePointer = GDIDEVFUNCS(pso).MovePointer;
630 }
631 else
632 {
633 /* Set software pointer */
634 ulResult = EngSetPointerShape(pso,
635 psoMask,
636 psoColor,
637 pxlo,
638 xHot,
639 yHot,
640 x,
641 y,
642 prcl,
643 fl);
644 /* Set MovePointer to the eng function */
645 ppdev->pfnMovePointer = EngMovePointer;
646 }
647
648 return ulResult;
649 }
650
651 ULONG
652 NTAPI
653 GreSetPointerShape(
654 HDC hdc,
655 HBITMAP hbmMask,
656 HBITMAP hbmColor,
657 LONG xHot,
658 LONG yHot,
659 LONG x,
660 LONG y,
661 FLONG fl)
662 {
663 PDC pdc;
664 PSURFACE psurf, psurfMask, psurfColor;
665 EXLATEOBJ exlo;
666 ULONG ulResult = 0;
667
668 pdc = DC_LockDc(hdc);
669 if (!pdc)
670 {
671 DPRINT1("Failed to lock the DC.\n");
672 return 0;
673 }
674
675 ASSERT(pdc->dctype == DCTYPE_DIRECT);
676 EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
677 /* We're not sure DC surface is the good one */
678 psurf = pdc->ppdev->pSurface;
679 if (!psurf)
680 {
681 DPRINT1("DC has no surface.\n");
682 EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
683 DC_UnlockDc(pdc);
684 return 0;
685 }
686
687 /* Lock the mask bitmap */
688 if (hbmMask)
689 psurfMask = SURFACE_ShareLockSurface(hbmMask);
690 else
691 {
692 //ASSERT(fl & SPS_ALPHA);
693 psurfMask = NULL;
694 }
695
696 /* Check for color bitmap */
697 if (hbmColor)
698 {
699 /* We have one, lock it */
700 psurfColor = SURFACE_ShareLockSurface(hbmColor);
701
702 if (psurfColor)
703 {
704 /* Create an XLATEOBJ, no mono support */
705 EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurf->ppal, 0, 0, 0);
706 }
707 }
708 else
709 psurfColor = NULL;
710
711 /* We must have a valid surface in case of alpha bitmap */
712 ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA));
713
714 /* Call the driver or eng function */
715 ulResult = IntEngSetPointerShape(&psurf->SurfObj,
716 psurfMask ? &psurfMask->SurfObj : NULL,
717 psurfColor ? &psurfColor->SurfObj : NULL,
718 psurfColor ? &exlo.xlo : NULL,
719 xHot,
720 yHot,
721 x,
722 y,
723 &pdc->ppdev->Pointer.Exclude,
724 fl | SPS_CHANGE);
725
726 /* Cleanup */
727 if (psurfColor)
728 {
729 EXLATEOBJ_vCleanup(&exlo);
730 SURFACE_ShareUnlockSurface(psurfColor);
731 }
732
733 if (psurfMask)
734 SURFACE_ShareUnlockSurface(psurfMask);
735
736 EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
737
738 /* Unlock the DC */
739 DC_UnlockDc(pdc);
740
741 /* Return result */
742 return ulResult;
743 }
744
745 VOID
746 NTAPI
747 GreMovePointer(
748 HDC hdc,
749 LONG x,
750 LONG y)
751 {
752 PDC pdc;
753 PRECTL prcl;
754
755 /* Lock the DC */
756 pdc = DC_LockDc(hdc);
757 if (!pdc)
758 {
759 DPRINT1("Failed to lock the DC.\n");
760 return;
761 }
762 ASSERT(pdc->dctype == DCTYPE_DIRECT);
763
764 /* Acquire PDEV lock */
765 EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
766
767 /* Check if we need to move it */
768 if(pdc->ppdev->SafetyRemoveLevel == 0)
769 {
770 /* Store the cursor exclude position in the PDEV */
771 prcl = &pdc->ppdev->Pointer.Exclude;
772
773 /* Call Eng/Drv function */
774 pdc->ppdev->pfnMovePointer(&pdc->ppdev->pSurface->SurfObj, x, y, prcl);
775 }
776
777 /* Release PDEV lock */
778 EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
779
780 /* Unlock the DC */
781 DC_UnlockDc(pdc);
782 }
783
784
785 /* EOF */