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 */ 806