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 BOOL bHardwarePointer = FALSE; 622 BOOL bSoftwarePointer = TRUE; 623 624 pfnSetPointerShape = GDIDEVFUNCS(pso).SetPointerShape; 625 626 if (pfnSetPointerShape) 627 { 628 /* Drivers expect to get an XLATEOBJ */ 629 if (pxlo == NULL) 630 pxlo = &gexloTrivial.xlo; 631 632 /* Call the driver */ 633 ulResult = pfnSetPointerShape(pso, 634 psoMask, 635 psoColor, 636 pxlo, 637 xHot, 638 yHot, 639 x, 640 y, 641 prcl, 642 fl); 643 644 /* Check if the driver accepted it */ 645 if (ulResult == SPS_ACCEPT_NOEXCLUDE) 646 bHardwarePointer = TRUE; 647 648 bSoftwarePointer = !bHardwarePointer; 649 } 650 651 if (bSoftwarePointer) 652 { 653 /* Set software pointer */ 654 ulResult = EngSetPointerShape(pso, 655 psoMask, 656 psoColor, 657 pxlo, 658 xHot, 659 yHot, 660 x, 661 y, 662 prcl, 663 fl); 664 } 665 666 if (!bSoftwarePointer && ppdev->flFlags & PDEV_SOFTWARE_POINTER) 667 { 668 /* Disable software pointer */ 669 EngMovePointer(pso, -1, -1, NULL); 670 } 671 672 if (!bHardwarePointer && ppdev->flFlags & PDEV_HARDWARE_POINTER) 673 { 674 /* Disable hardware pointer */ 675 ppdev->pfnMovePointer(pso, -1, -1, NULL); 676 } 677 678 /* Update flags */ 679 if (bSoftwarePointer) 680 ppdev->flFlags |= PDEV_SOFTWARE_POINTER; 681 else 682 ppdev->flFlags &= ~PDEV_SOFTWARE_POINTER; 683 684 if (bHardwarePointer) 685 ppdev->flFlags |= PDEV_HARDWARE_POINTER; 686 else 687 ppdev->flFlags &= ~PDEV_HARDWARE_POINTER; 688 689 return ulResult; 690 } 691 692 ULONG 693 NTAPI 694 GreSetPointerShape( 695 _In_ HDC hdc, 696 _In_opt_ HBITMAP hbmMask, 697 _In_opt_ HBITMAP hbmColor, 698 _In_ LONG xHot, 699 _In_ LONG yHot, 700 _In_ LONG x, 701 _In_ LONG y, 702 _In_ FLONG fl) 703 { 704 PDC pdc; 705 PSURFACE psurf, psurfMask, psurfColor; 706 EXLATEOBJ exlo; 707 ULONG ulResult = 0; 708 709 pdc = DC_LockDc(hdc); 710 if (!pdc) 711 { 712 DPRINT1("Failed to lock the DC.\n"); 713 return 0; 714 } 715 716 ASSERT(pdc->dctype == DCTYPE_DIRECT); 717 EngAcquireSemaphore(pdc->ppdev->hsemDevLock); 718 /* We're not sure DC surface is the good one */ 719 psurf = pdc->ppdev->pSurface; 720 if (!psurf) 721 { 722 DPRINT1("DC has no surface.\n"); 723 EngReleaseSemaphore(pdc->ppdev->hsemDevLock); 724 DC_UnlockDc(pdc); 725 return 0; 726 } 727 728 /* Lock the mask bitmap */ 729 if (hbmMask) 730 { 731 psurfMask = SURFACE_ShareLockSurface(hbmMask); 732 } 733 else 734 { 735 //ASSERT(fl & SPS_ALPHA); 736 psurfMask = NULL; 737 } 738 739 /* Check for color bitmap */ 740 if (hbmColor) 741 { 742 /* We have one, lock it */ 743 psurfColor = SURFACE_ShareLockSurface(hbmColor); 744 745 if (psurfColor) 746 { 747 /* Create an XLATEOBJ, no mono support */ 748 EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurf->ppal, 0, 0, 0); 749 } 750 } 751 else 752 psurfColor = NULL; 753 754 /* We must have a valid surface in case of alpha bitmap */ 755 ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA)); 756 757 /* Call the driver or eng function */ 758 ulResult = IntEngSetPointerShape(&psurf->SurfObj, 759 psurfMask ? &psurfMask->SurfObj : NULL, 760 psurfColor ? &psurfColor->SurfObj : NULL, 761 psurfColor ? &exlo.xlo : NULL, 762 xHot, 763 yHot, 764 x, 765 y, 766 &pdc->ppdev->Pointer.Exclude, 767 fl | SPS_CHANGE); 768 769 /* Cleanup */ 770 if (psurfColor) 771 { 772 EXLATEOBJ_vCleanup(&exlo); 773 SURFACE_ShareUnlockSurface(psurfColor); 774 } 775 776 if (psurfMask) 777 SURFACE_ShareUnlockSurface(psurfMask); 778 779 EngReleaseSemaphore(pdc->ppdev->hsemDevLock); 780 781 /* Unlock the DC */ 782 DC_UnlockDc(pdc); 783 784 /* Return result */ 785 return ulResult; 786 } 787 788 VOID 789 NTAPI 790 GreMovePointer( 791 _In_ HDC hdc, 792 _In_ LONG x, 793 _In_ LONG y) 794 { 795 PDC pdc; 796 PRECTL prcl; 797 798 /* Lock the DC */ 799 pdc = DC_LockDc(hdc); 800 if (!pdc) 801 { 802 DPRINT1("Failed to lock the DC.\n"); 803 return; 804 } 805 ASSERT(pdc->dctype == DCTYPE_DIRECT); 806 807 /* Acquire PDEV lock */ 808 EngAcquireSemaphore(pdc->ppdev->hsemDevLock); 809 810 /* Check if we need to move it */ 811 if(pdc->ppdev->SafetyRemoveLevel == 0) 812 { 813 SURFOBJ* pso = &pdc->ppdev->pSurface->SurfObj; 814 815 /* Store the cursor exclude position in the PDEV */ 816 prcl = &pdc->ppdev->Pointer.Exclude; 817 818 /* Send new position of the hot spot of the pointer (will likely redraw cursor) */ 819 if (pdc->ppdev->flFlags & PDEV_HARDWARE_POINTER) 820 pdc->ppdev->pfnMovePointer(pso, x, y, prcl); 821 else if (pdc->ppdev->flFlags & PDEV_SOFTWARE_POINTER) 822 EngMovePointer(pso, x, y, prcl); 823 824 /* If panning device, and we're not hiding the cursor, notify cursor's current position. 825 * (driver may already have been called if it also supports hardware pointers) */ 826 if (pdc->ppdev->devinfo.flGraphicsCaps & GCAPS_PANNING && y >= 0) 827 pdc->ppdev->pfnMovePointer(pso, x, y - pso->sizlBitmap.cy, NULL); 828 } 829 830 /* Release PDEV lock */ 831 EngReleaseSemaphore(pdc->ppdev->hsemDevLock); 832 833 /* Unlock the DC */ 834 DC_UnlockDc(pdc); 835 } 836 837 838 /* EOF */ 839