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