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