misprite.c revision ed6184df
1/* 2 * misprite.c 3 * 4 * machine independent software sprite routines 5 */ 6 7/* 8 9Copyright 1989, 1998 The Open Group 10 11Permission to use, copy, modify, distribute, and sell this software and its 12documentation for any purpose is hereby granted without fee, provided that 13the above copyright notice appear in all copies and that both that 14copyright notice and this permission notice appear in supporting 15documentation. 16 17The above copyright notice and this permission notice shall be included in 18all copies or substantial portions of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 24AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27Except as contained in this notice, the name of The Open Group shall not be 28used in advertising or otherwise to promote the sale, use or other dealings 29in this Software without prior written authorization from The Open Group. 30*/ 31 32#ifdef HAVE_DIX_CONFIG_H 33#include <dix-config.h> 34#endif 35 36#include <X11/X.h> 37#include <X11/Xproto.h> 38#include "misc.h" 39#include "pixmapstr.h" 40#include "input.h" 41#include "mi.h" 42#include "cursorstr.h" 43#include <X11/fonts/font.h> 44#include "scrnintstr.h" 45#include "colormapst.h" 46#include "windowstr.h" 47#include "gcstruct.h" 48#include "mipointer.h" 49#include "misprite.h" 50#include "dixfontstr.h" 51#include <X11/fonts/fontstruct.h> 52#include "inputstr.h" 53#include "damage.h" 54 55typedef struct { 56 CursorPtr pCursor; 57 int x; /* cursor hotspot */ 58 int y; 59 BoxRec saved; /* saved area from the screen */ 60 Bool isUp; /* cursor in frame buffer */ 61 Bool shouldBeUp; /* cursor should be displayed */ 62 Bool checkPixels; /* check colormap collision */ 63 ScreenPtr pScreen; 64} miCursorInfoRec, *miCursorInfoPtr; 65 66/* 67 * per screen information 68 */ 69 70typedef struct { 71 /* screen procedures */ 72 CloseScreenProcPtr CloseScreen; 73 SourceValidateProcPtr SourceValidate; 74 75 /* window procedures */ 76 CopyWindowProcPtr CopyWindow; 77 78 /* colormap procedures */ 79 InstallColormapProcPtr InstallColormap; 80 StoreColorsProcPtr StoreColors; 81 82 /* os layer procedures */ 83 ScreenBlockHandlerProcPtr BlockHandler; 84 85 xColorItem colors[2]; 86 ColormapPtr pInstalledMap; 87 ColormapPtr pColormap; 88 VisualPtr pVisual; 89 DamagePtr pDamage; /* damage tracking structure */ 90 Bool damageRegistered; 91 int numberOfCursors; 92} miSpriteScreenRec, *miSpriteScreenPtr; 93 94#define SOURCE_COLOR 0 95#define MASK_COLOR 1 96 97/* 98 * Overlap BoxPtr and Box elements 99 */ 100#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ 101 (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ 102 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) 103 104/* 105 * Overlap BoxPtr, origins, and rectangle 106 */ 107#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ 108 BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) 109 110/* 111 * Overlap BoxPtr, origins and RectPtr 112 */ 113#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ 114 ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ 115 (int)((pRect)->width), (int)((pRect)->height)) 116/* 117 * Overlap BoxPtr and horizontal span 118 */ 119#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) 120 121#define LINE_SORT(x1,y1,x2,y2) \ 122{ int _t; \ 123 if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ 124 if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } 125 126#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ 127 BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) 128 129#define SPRITE_DEBUG_ENABLE 0 130#if SPRITE_DEBUG_ENABLE 131#define SPRITE_DEBUG(x) ErrorF x 132#else 133#define SPRITE_DEBUG(x) 134#endif 135 136static DevPrivateKeyRec miSpriteScreenKeyRec; 137static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; 138 139static miSpriteScreenPtr 140GetSpriteScreen(ScreenPtr pScreen) 141{ 142 return dixLookupPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec); 143} 144 145static miCursorInfoPtr 146GetSprite(DeviceIntPtr dev) 147{ 148 if (IsFloating(dev)) 149 return dixLookupPrivate(&dev->devPrivates, &miSpriteDevPrivatesKeyRec); 150 151 return dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, 152 &miSpriteDevPrivatesKeyRec); 153} 154 155static void 156miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) 157{ 158 if (pScreenPriv->damageRegistered) { 159 DamageUnregister(pScreenPriv->pDamage); 160 pScreenPriv->damageRegistered = 0; 161 } 162} 163 164static void 165miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) 166{ 167 if (!pScreenPriv->damageRegistered) { 168 pScreenPriv->damageRegistered = 1; 169 DamageRegister(&(pScreen->GetScreenPixmap(pScreen)->drawable), 170 pScreenPriv->pDamage); 171 } 172} 173 174static void 175miSpriteIsUp(miCursorInfoPtr pDevCursor) 176{ 177 pDevCursor->isUp = TRUE; 178} 179 180static void 181miSpriteIsDown(miCursorInfoPtr pDevCursor) 182{ 183 pDevCursor->isUp = FALSE; 184} 185 186/* 187 * screen wrappers 188 */ 189 190static Bool miSpriteCloseScreen(ScreenPtr pScreen); 191static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, 192 int width, int height, 193 unsigned int subWindowMode); 194static void miSpriteCopyWindow(WindowPtr pWindow, 195 DDXPointRec ptOldOrg, RegionPtr prgnSrc); 196static void miSpriteBlockHandler(ScreenPtr pScreen, void *timeout); 197static void miSpriteInstallColormap(ColormapPtr pMap); 198static void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef); 199 200static void miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen); 201 202static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, 203 ScreenPtr pScreen); 204static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); 205 206#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ 207 (pPriv)->field) 208#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ 209 ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) 210 211/* 212 * pointer-sprite method table 213 */ 214 215static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 216 CursorPtr pCursor); 217static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 218 CursorPtr pCursor); 219static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 220 CursorPtr pCursor, int x, int y); 221static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 222 int x, int y); 223 224miPointerSpriteFuncRec miSpritePointerFuncs = { 225 miSpriteRealizeCursor, 226 miSpriteUnrealizeCursor, 227 miSpriteSetCursor, 228 miSpriteMoveCursor, 229 miSpriteDeviceCursorInitialize, 230 miSpriteDeviceCursorCleanup, 231}; 232 233/* 234 * other misc functions 235 */ 236 237static void miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen); 238static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen); 239static void miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen); 240 241static void 242miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) 243{ 244 if (!pScreenPriv->BlockHandler) { 245 pScreenPriv->BlockHandler = pScreen->BlockHandler; 246 pScreen->BlockHandler = miSpriteBlockHandler; 247 } 248} 249 250static void 251miSpriteReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure) 252{ 253 ScreenPtr pScreen = closure; 254 miCursorInfoPtr pCursorInfo; 255 DeviceIntPtr pDev; 256 257 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 258 if (DevHasCursor(pDev)) { 259 pCursorInfo = GetSprite(pDev); 260 261 if (pCursorInfo->isUp && 262 pCursorInfo->pScreen == pScreen && 263 RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) { 264 SPRITE_DEBUG(("Damage remove\n")); 265 miSpriteRemoveCursor(pDev, pScreen); 266 } 267 } 268 } 269} 270 271/* 272 * miSpriteInitialize -- called from device-dependent screen 273 * initialization proc after all of the function pointers have 274 * been stored in the screen structure. 275 */ 276 277Bool 278miSpriteInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) 279{ 280 miSpriteScreenPtr pScreenPriv; 281 VisualPtr pVisual; 282 283 if (!DamageSetup(pScreen)) 284 return FALSE; 285 286 if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) 287 return FALSE; 288 289 if (!dixRegisterPrivateKey 290 (&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec))) 291 return FALSE; 292 293 pScreenPriv = malloc(sizeof(miSpriteScreenRec)); 294 if (!pScreenPriv) 295 return FALSE; 296 297 pScreenPriv->pDamage = DamageCreate(miSpriteReportDamage, 298 NULL, 299 DamageReportRawRegion, 300 TRUE, pScreen, pScreen); 301 302 if (!miPointerInitialize(pScreen, &miSpritePointerFuncs, screenFuncs, TRUE)) { 303 free(pScreenPriv); 304 return FALSE; 305 } 306 for (pVisual = pScreen->visuals; 307 pVisual->vid != pScreen->rootVisual; pVisual++); 308 pScreenPriv->pVisual = pVisual; 309 pScreenPriv->CloseScreen = pScreen->CloseScreen; 310 pScreenPriv->SourceValidate = pScreen->SourceValidate; 311 312 pScreenPriv->CopyWindow = pScreen->CopyWindow; 313 314 pScreenPriv->InstallColormap = pScreen->InstallColormap; 315 pScreenPriv->StoreColors = pScreen->StoreColors; 316 317 pScreenPriv->BlockHandler = NULL; 318 319 pScreenPriv->pInstalledMap = NULL; 320 pScreenPriv->pColormap = NULL; 321 pScreenPriv->colors[SOURCE_COLOR].red = 0; 322 pScreenPriv->colors[SOURCE_COLOR].green = 0; 323 pScreenPriv->colors[SOURCE_COLOR].blue = 0; 324 pScreenPriv->colors[MASK_COLOR].red = 0; 325 pScreenPriv->colors[MASK_COLOR].green = 0; 326 pScreenPriv->colors[MASK_COLOR].blue = 0; 327 pScreenPriv->damageRegistered = 0; 328 pScreenPriv->numberOfCursors = 0; 329 330 dixSetPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec, pScreenPriv); 331 332 pScreen->CloseScreen = miSpriteCloseScreen; 333 pScreen->SourceValidate = miSpriteSourceValidate; 334 335 pScreen->CopyWindow = miSpriteCopyWindow; 336 pScreen->InstallColormap = miSpriteInstallColormap; 337 pScreen->StoreColors = miSpriteStoreColors; 338 339 return TRUE; 340} 341 342/* 343 * Screen wrappers 344 */ 345 346/* 347 * CloseScreen wrapper -- unwrap everything, free the private data 348 * and call the wrapped function 349 */ 350 351static Bool 352miSpriteCloseScreen(ScreenPtr pScreen) 353{ 354 miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); 355 356 pScreen->CloseScreen = pScreenPriv->CloseScreen; 357 pScreen->SourceValidate = pScreenPriv->SourceValidate; 358 pScreen->InstallColormap = pScreenPriv->InstallColormap; 359 pScreen->StoreColors = pScreenPriv->StoreColors; 360 361 DamageDestroy(pScreenPriv->pDamage); 362 363 free(pScreenPriv); 364 365 return (*pScreen->CloseScreen) (pScreen); 366} 367 368static void 369miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, int width, 370 int height, unsigned int subWindowMode) 371{ 372 ScreenPtr pScreen = pDrawable->pScreen; 373 DeviceIntPtr pDev; 374 miCursorInfoPtr pCursorInfo; 375 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 376 377 SCREEN_PROLOGUE(pPriv, pScreen, SourceValidate); 378 379 if (pDrawable->type == DRAWABLE_WINDOW) { 380 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 381 if (DevHasCursor(pDev)) { 382 pCursorInfo = GetSprite(pDev); 383 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && 384 ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, 385 x, y, width, height)) { 386 SPRITE_DEBUG(("SourceValidate remove\n")); 387 miSpriteRemoveCursor(pDev, pScreen); 388 } 389 } 390 } 391 } 392 393 (*pScreen->SourceValidate) (pDrawable, x, y, width, height, 394 subWindowMode); 395 396 SCREEN_EPILOGUE(pPriv, pScreen, SourceValidate); 397} 398 399static void 400miSpriteCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 401{ 402 ScreenPtr pScreen = pWindow->drawable.pScreen; 403 DeviceIntPtr pDev; 404 miCursorInfoPtr pCursorInfo; 405 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 406 407 SCREEN_PROLOGUE(pPriv, pScreen, CopyWindow); 408 409 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 410 if (DevHasCursor(pDev)) { 411 pCursorInfo = GetSprite(pDev); 412 /* 413 * Damage will take care of destination check 414 */ 415 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && 416 RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) { 417 SPRITE_DEBUG(("CopyWindow remove\n")); 418 miSpriteRemoveCursor(pDev, pScreen); 419 } 420 } 421 } 422 423 (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); 424 SCREEN_EPILOGUE(pPriv, pScreen, CopyWindow); 425} 426 427static void 428miSpriteBlockHandler(ScreenPtr pScreen, void *timeout) 429{ 430 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 431 DeviceIntPtr pDev; 432 miCursorInfoPtr pCursorInfo; 433 Bool WorkToDo = FALSE; 434 435 SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); 436 437 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 438 if (DevHasCursor(pDev)) { 439 pCursorInfo = GetSprite(pDev); 440 if (pCursorInfo && !pCursorInfo->isUp 441 && pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) { 442 SPRITE_DEBUG(("BlockHandler save")); 443 miSpriteSaveUnderCursor(pDev, pScreen); 444 } 445 } 446 } 447 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 448 if (DevHasCursor(pDev)) { 449 pCursorInfo = GetSprite(pDev); 450 if (pCursorInfo && !pCursorInfo->isUp && 451 pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) { 452 SPRITE_DEBUG(("BlockHandler restore\n")); 453 miSpriteRestoreCursor(pDev, pScreen); 454 if (!pCursorInfo->isUp) 455 WorkToDo = TRUE; 456 } 457 } 458 } 459 460 (*pScreen->BlockHandler) (pScreen, timeout); 461 462 if (WorkToDo) 463 SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); 464 else 465 pPriv->BlockHandler = NULL; 466} 467 468static void 469miSpriteInstallColormap(ColormapPtr pMap) 470{ 471 ScreenPtr pScreen = pMap->pScreen; 472 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 473 474 SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); 475 476 (*pScreen->InstallColormap) (pMap); 477 478 SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); 479 480 /* InstallColormap can be called before devices are initialized. */ 481 pPriv->pInstalledMap = pMap; 482 if (pPriv->pColormap != pMap) { 483 DeviceIntPtr pDev; 484 miCursorInfoPtr pCursorInfo; 485 486 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 487 if (DevHasCursor(pDev)) { 488 pCursorInfo = GetSprite(pDev); 489 pCursorInfo->checkPixels = TRUE; 490 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) 491 miSpriteRemoveCursor(pDev, pScreen); 492 } 493 } 494 495 } 496} 497 498static void 499miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef) 500{ 501 ScreenPtr pScreen = pMap->pScreen; 502 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 503 int i; 504 int updated; 505 VisualPtr pVisual; 506 DeviceIntPtr pDev; 507 miCursorInfoPtr pCursorInfo; 508 509 SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); 510 511 (*pScreen->StoreColors) (pMap, ndef, pdef); 512 513 SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); 514 515 if (pPriv->pColormap == pMap) { 516 updated = 0; 517 pVisual = pMap->pVisual; 518 if (pVisual->class == DirectColor) { 519 /* Direct color - match on any of the subfields */ 520 521#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) 522 523#define UpdateDAC(dev, plane,dac,mask) {\ 524 if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ 525 dev->colors[plane].dac = pdef[i].dac; \ 526 updated = 1; \ 527 } \ 528} 529 530#define CheckDirect(dev, plane) \ 531 UpdateDAC(dev, plane,red,redMask) \ 532 UpdateDAC(dev, plane,green,greenMask) \ 533 UpdateDAC(dev, plane,blue,blueMask) 534 535 for (i = 0; i < ndef; i++) { 536 CheckDirect(pPriv, SOURCE_COLOR) 537 CheckDirect(pPriv, MASK_COLOR) 538 } 539 } 540 else { 541 /* PseudoColor/GrayScale - match on exact pixel */ 542 for (i = 0; i < ndef; i++) { 543 if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) { 544 pPriv->colors[SOURCE_COLOR] = pdef[i]; 545 if (++updated == 2) 546 break; 547 } 548 if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) { 549 pPriv->colors[MASK_COLOR] = pdef[i]; 550 if (++updated == 2) 551 break; 552 } 553 } 554 } 555 if (updated) { 556 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 557 if (DevHasCursor(pDev)) { 558 pCursorInfo = GetSprite(pDev); 559 pCursorInfo->checkPixels = TRUE; 560 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) 561 miSpriteRemoveCursor(pDev, pScreen); 562 } 563 } 564 } 565 } 566} 567 568static void 569miSpriteFindColors(miCursorInfoPtr pDevCursor, ScreenPtr pScreen) 570{ 571 miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); 572 CursorPtr pCursor; 573 xColorItem *sourceColor, *maskColor; 574 575 pCursor = pDevCursor->pCursor; 576 sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; 577 maskColor = &pScreenPriv->colors[MASK_COLOR]; 578 if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || 579 !(pCursor->foreRed == sourceColor->red && 580 pCursor->foreGreen == sourceColor->green && 581 pCursor->foreBlue == sourceColor->blue && 582 pCursor->backRed == maskColor->red && 583 pCursor->backGreen == maskColor->green && 584 pCursor->backBlue == maskColor->blue)) { 585 pScreenPriv->pColormap = pScreenPriv->pInstalledMap; 586 sourceColor->red = pCursor->foreRed; 587 sourceColor->green = pCursor->foreGreen; 588 sourceColor->blue = pCursor->foreBlue; 589 FakeAllocColor(pScreenPriv->pColormap, sourceColor); 590 maskColor->red = pCursor->backRed; 591 maskColor->green = pCursor->backGreen; 592 maskColor->blue = pCursor->backBlue; 593 FakeAllocColor(pScreenPriv->pColormap, maskColor); 594 /* "free" the pixels right away, don't let this confuse you */ 595 FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); 596 FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); 597 } 598 599 pDevCursor->checkPixels = FALSE; 600 601} 602 603/* 604 * miPointer interface routines 605 */ 606 607#define SPRITE_PAD 8 608 609static Bool 610miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 611{ 612 miCursorInfoPtr pCursorInfo; 613 614 if (IsFloating(pDev)) 615 return FALSE; 616 617 pCursorInfo = GetSprite(pDev); 618 619 if (pCursor == pCursorInfo->pCursor) 620 pCursorInfo->checkPixels = TRUE; 621 622 return miDCRealizeCursor(pScreen, pCursor); 623} 624 625static Bool 626miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 627{ 628 return miDCUnrealizeCursor(pScreen, pCursor); 629} 630 631static void 632miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 633 CursorPtr pCursor, int x, int y) 634{ 635 miCursorInfoPtr pPointer; 636 miSpriteScreenPtr pScreenPriv; 637 638 if (IsFloating(pDev)) 639 return; 640 641 pPointer = GetSprite(pDev); 642 pScreenPriv = GetSpriteScreen(pScreen); 643 644 if (!pCursor) { 645 if (pPointer->shouldBeUp) 646 --pScreenPriv->numberOfCursors; 647 pPointer->shouldBeUp = FALSE; 648 if (pPointer->isUp) 649 miSpriteRemoveCursor(pDev, pScreen); 650 if (pScreenPriv->numberOfCursors == 0) 651 miSpriteDisableDamage(pScreen, pScreenPriv); 652 pPointer->pCursor = 0; 653 return; 654 } 655 if (!pPointer->shouldBeUp) 656 pScreenPriv->numberOfCursors++; 657 pPointer->shouldBeUp = TRUE; 658 if (!pPointer->isUp) 659 miSpriteRegisterBlockHandler(pScreen, pScreenPriv); 660 if (pPointer->x == x && 661 pPointer->y == y && 662 pPointer->pCursor == pCursor && !pPointer->checkPixels) { 663 return; 664 } 665 pPointer->x = x; 666 pPointer->y = y; 667 if (pPointer->checkPixels || pPointer->pCursor != pCursor) { 668 pPointer->pCursor = pCursor; 669 miSpriteFindColors(pPointer, pScreen); 670 } 671 if (pPointer->isUp) { 672 /* TODO: reimplement flicker-free MoveCursor */ 673 SPRITE_DEBUG(("SetCursor remove %d\n", pDev->id)); 674 miSpriteRemoveCursor(pDev, pScreen); 675 } 676 677 if (!pPointer->isUp && pPointer->pCursor) { 678 SPRITE_DEBUG(("SetCursor restore %d\n", pDev->id)); 679 miSpriteSaveUnderCursor(pDev, pScreen); 680 miSpriteRestoreCursor(pDev, pScreen); 681 } 682 683} 684 685static void 686miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 687{ 688 CursorPtr pCursor; 689 690 if (IsFloating(pDev)) 691 return; 692 693 pCursor = GetSprite(pDev)->pCursor; 694 695 miSpriteSetCursor(pDev, pScreen, pCursor, x, y); 696} 697 698static Bool 699miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) 700{ 701 int ret = miDCDeviceInitialize(pDev, pScreen); 702 703 if (ret) { 704 miCursorInfoPtr pCursorInfo; 705 706 pCursorInfo = 707 dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec); 708 pCursorInfo->pCursor = NULL; 709 pCursorInfo->x = 0; 710 pCursorInfo->y = 0; 711 pCursorInfo->isUp = FALSE; 712 pCursorInfo->shouldBeUp = FALSE; 713 pCursorInfo->checkPixels = TRUE; 714 pCursorInfo->pScreen = FALSE; 715 } 716 717 return ret; 718} 719 720static void 721miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) 722{ 723 miCursorInfoPtr pCursorInfo = 724 dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec); 725 726 if (DevHasCursor(pDev)) 727 miDCDeviceCleanup(pDev, pScreen); 728 729 memset(pCursorInfo, 0, sizeof(miCursorInfoRec)); 730} 731 732/* 733 * undraw/draw cursor 734 */ 735 736static void 737miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen) 738{ 739 miSpriteScreenPtr pScreenPriv; 740 miCursorInfoPtr pCursorInfo; 741 742 if (IsFloating(pDev)) 743 return; 744 745 DamageDrawInternal(pScreen, TRUE); 746 pScreenPriv = GetSpriteScreen(pScreen); 747 pCursorInfo = GetSprite(pDev); 748 749 miSpriteIsDown(pCursorInfo); 750 miSpriteRegisterBlockHandler(pScreen, pScreenPriv); 751 miSpriteDisableDamage(pScreen, pScreenPriv); 752 if (!miDCRestoreUnderCursor(pDev, 753 pScreen, 754 pCursorInfo->saved.x1, 755 pCursorInfo->saved.y1, 756 pCursorInfo->saved.x2 - 757 pCursorInfo->saved.x1, 758 pCursorInfo->saved.y2 - 759 pCursorInfo->saved.y1)) { 760 miSpriteIsUp(pCursorInfo); 761 } 762 miSpriteEnableDamage(pScreen, pScreenPriv); 763 DamageDrawInternal(pScreen, FALSE); 764} 765 766/* 767 * Called from the block handler, saves area under cursor 768 * before waiting for something to do. 769 */ 770 771static void 772miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) 773{ 774 miSpriteScreenPtr pScreenPriv; 775 miCursorInfoPtr pCursorInfo; 776 777 if (IsFloating(pDev)) 778 return; 779 780 DamageDrawInternal(pScreen, TRUE); 781 pScreenPriv = GetSpriteScreen(pScreen); 782 pCursorInfo = GetSprite(pDev); 783 784 miSpriteComputeSaved(pDev, pScreen); 785 786 miSpriteDisableDamage(pScreen, pScreenPriv); 787 788 miDCSaveUnderCursor(pDev, 789 pScreen, 790 pCursorInfo->saved.x1, 791 pCursorInfo->saved.y1, 792 pCursorInfo->saved.x2 - 793 pCursorInfo->saved.x1, 794 pCursorInfo->saved.y2 - pCursorInfo->saved.y1); 795 SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); 796 miSpriteEnableDamage(pScreen, pScreenPriv); 797 DamageDrawInternal(pScreen, FALSE); 798} 799 800/* 801 * Called from the block handler, restores the cursor 802 * before waiting for something to do. 803 */ 804 805static void 806miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen) 807{ 808 miSpriteScreenPtr pScreenPriv; 809 int x, y; 810 CursorPtr pCursor; 811 miCursorInfoPtr pCursorInfo; 812 813 if (IsFloating(pDev)) 814 return; 815 816 DamageDrawInternal(pScreen, TRUE); 817 pScreenPriv = GetSpriteScreen(pScreen); 818 pCursorInfo = GetSprite(pDev); 819 820 miSpriteComputeSaved(pDev, pScreen); 821 pCursor = pCursorInfo->pCursor; 822 823 x = pCursorInfo->x - (int) pCursor->bits->xhot; 824 y = pCursorInfo->y - (int) pCursor->bits->yhot; 825 miSpriteDisableDamage(pScreen, pScreenPriv); 826 SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); 827 if (pCursorInfo->checkPixels) 828 miSpriteFindColors(pCursorInfo, pScreen); 829 if (miDCPutUpCursor(pDev, pScreen, 830 pCursor, x, y, 831 pScreenPriv->colors[SOURCE_COLOR].pixel, 832 pScreenPriv->colors[MASK_COLOR].pixel)) { 833 miSpriteIsUp(pCursorInfo); 834 pCursorInfo->pScreen = pScreen; 835 } 836 miSpriteEnableDamage(pScreen, pScreenPriv); 837 DamageDrawInternal(pScreen, FALSE); 838} 839 840/* 841 * compute the desired area of the screen to save 842 */ 843 844static void 845miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen) 846{ 847 int x, y, w, h; 848 int wpad, hpad; 849 CursorPtr pCursor; 850 miCursorInfoPtr pCursorInfo; 851 852 if (IsFloating(pDev)) 853 return; 854 855 pCursorInfo = GetSprite(pDev); 856 857 pCursor = pCursorInfo->pCursor; 858 x = pCursorInfo->x - (int) pCursor->bits->xhot; 859 y = pCursorInfo->y - (int) pCursor->bits->yhot; 860 w = pCursor->bits->width; 861 h = pCursor->bits->height; 862 wpad = SPRITE_PAD; 863 hpad = SPRITE_PAD; 864 pCursorInfo->saved.x1 = x - wpad; 865 pCursorInfo->saved.y1 = y - hpad; 866 pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; 867 pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; 868} 869