misprite.c revision 1b5d61b8
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 GetImageProcPtr GetImage; 74 GetSpansProcPtr GetSpans; 75 SourceValidateProcPtr SourceValidate; 76 77 /* window procedures */ 78 CopyWindowProcPtr CopyWindow; 79 80 /* colormap procedures */ 81 InstallColormapProcPtr InstallColormap; 82 StoreColorsProcPtr StoreColors; 83 84 /* os layer procedures */ 85 ScreenBlockHandlerProcPtr BlockHandler; 86 87 xColorItem colors[2]; 88 ColormapPtr pInstalledMap; 89 ColormapPtr pColormap; 90 VisualPtr pVisual; 91 DamagePtr pDamage; /* damage tracking structure */ 92 Bool damageRegistered; 93 int numberOfCursors; 94} miSpriteScreenRec, *miSpriteScreenPtr; 95 96#define SOURCE_COLOR 0 97#define MASK_COLOR 1 98 99/* 100 * Overlap BoxPtr and Box elements 101 */ 102#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ 103 (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ 104 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) 105 106/* 107 * Overlap BoxPtr, origins, and rectangle 108 */ 109#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ 110 BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) 111 112/* 113 * Overlap BoxPtr, origins and RectPtr 114 */ 115#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ 116 ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ 117 (int)((pRect)->width), (int)((pRect)->height)) 118/* 119 * Overlap BoxPtr and horizontal span 120 */ 121#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) 122 123#define LINE_SORT(x1,y1,x2,y2) \ 124{ int _t; \ 125 if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ 126 if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } 127 128#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ 129 BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) 130 131#define SPRITE_DEBUG_ENABLE 0 132#if SPRITE_DEBUG_ENABLE 133#define SPRITE_DEBUG(x) ErrorF x 134#else 135#define SPRITE_DEBUG(x) 136#endif 137 138static DevPrivateKeyRec miSpriteScreenKeyRec; 139static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; 140 141static miSpriteScreenPtr 142GetSpriteScreen(ScreenPtr pScreen) 143{ 144 return dixLookupPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec); 145} 146 147static miCursorInfoPtr 148GetSprite(DeviceIntPtr dev) 149{ 150 if (IsFloating(dev)) 151 return dixLookupPrivate(&dev->devPrivates, &miSpriteDevPrivatesKeyRec); 152 153 return dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, 154 &miSpriteDevPrivatesKeyRec); 155} 156 157static void 158miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) 159{ 160 if (pScreenPriv->damageRegistered) { 161 DamageUnregister(pScreenPriv->pDamage); 162 pScreenPriv->damageRegistered = 0; 163 } 164} 165 166static void 167miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) 168{ 169 if (!pScreenPriv->damageRegistered) { 170 pScreenPriv->damageRegistered = 1; 171 DamageRegister(&(pScreen->GetScreenPixmap(pScreen)->drawable), 172 pScreenPriv->pDamage); 173 } 174} 175 176static void 177miSpriteIsUp(miCursorInfoPtr pDevCursor) 178{ 179 pDevCursor->isUp = TRUE; 180} 181 182static void 183miSpriteIsDown(miCursorInfoPtr pDevCursor) 184{ 185 pDevCursor->isUp = FALSE; 186} 187 188/* 189 * screen wrappers 190 */ 191 192static Bool miSpriteCloseScreen(ScreenPtr pScreen); 193static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, 194 int w, int h, unsigned int format, 195 unsigned long planemask, char *pdstLine); 196static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, 197 DDXPointPtr ppt, int *pwidth, int nspans, 198 char *pdstStart); 199static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, 200 int width, int height, 201 unsigned int subWindowMode); 202static void miSpriteCopyWindow(WindowPtr pWindow, 203 DDXPointRec ptOldOrg, RegionPtr prgnSrc); 204static void miSpriteBlockHandler(ScreenPtr pScreen, void *timeout); 205static void miSpriteInstallColormap(ColormapPtr pMap); 206static void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef); 207 208static void miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen); 209 210static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, 211 ScreenPtr pScreen); 212static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); 213 214#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ 215 (pPriv)->field) 216#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ 217 ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) 218 219/* 220 * pointer-sprite method table 221 */ 222 223static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 224 CursorPtr pCursor); 225static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 226 CursorPtr pCursor); 227static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 228 CursorPtr pCursor, int x, int y); 229static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 230 int x, int y); 231 232miPointerSpriteFuncRec miSpritePointerFuncs = { 233 miSpriteRealizeCursor, 234 miSpriteUnrealizeCursor, 235 miSpriteSetCursor, 236 miSpriteMoveCursor, 237 miSpriteDeviceCursorInitialize, 238 miSpriteDeviceCursorCleanup, 239}; 240 241/* 242 * other misc functions 243 */ 244 245static void miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen); 246static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen); 247static void miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen); 248 249static void 250miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) 251{ 252 if (!pScreenPriv->BlockHandler) { 253 pScreenPriv->BlockHandler = pScreen->BlockHandler; 254 pScreen->BlockHandler = miSpriteBlockHandler; 255 } 256} 257 258static void 259miSpriteReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure) 260{ 261 ScreenPtr pScreen = closure; 262 miCursorInfoPtr pCursorInfo; 263 DeviceIntPtr pDev; 264 265 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 266 if (DevHasCursor(pDev)) { 267 pCursorInfo = GetSprite(pDev); 268 269 if (pCursorInfo->isUp && 270 pCursorInfo->pScreen == pScreen && 271 RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) { 272 SPRITE_DEBUG(("Damage remove\n")); 273 miSpriteRemoveCursor(pDev, pScreen); 274 } 275 } 276 } 277} 278 279/* 280 * miSpriteInitialize -- called from device-dependent screen 281 * initialization proc after all of the function pointers have 282 * been stored in the screen structure. 283 */ 284 285Bool 286miSpriteInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) 287{ 288 miSpriteScreenPtr pScreenPriv; 289 VisualPtr pVisual; 290 291 if (!DamageSetup(pScreen)) 292 return FALSE; 293 294 if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) 295 return FALSE; 296 297 if (!dixRegisterPrivateKey 298 (&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec))) 299 return FALSE; 300 301 pScreenPriv = malloc(sizeof(miSpriteScreenRec)); 302 if (!pScreenPriv) 303 return FALSE; 304 305 pScreenPriv->pDamage = DamageCreate(miSpriteReportDamage, 306 NULL, 307 DamageReportRawRegion, 308 TRUE, pScreen, pScreen); 309 310 if (!miPointerInitialize(pScreen, &miSpritePointerFuncs, screenFuncs, TRUE)) { 311 free(pScreenPriv); 312 return FALSE; 313 } 314 for (pVisual = pScreen->visuals; 315 pVisual->vid != pScreen->rootVisual; pVisual++); 316 pScreenPriv->pVisual = pVisual; 317 pScreenPriv->CloseScreen = pScreen->CloseScreen; 318 pScreenPriv->GetImage = pScreen->GetImage; 319 pScreenPriv->GetSpans = pScreen->GetSpans; 320 pScreenPriv->SourceValidate = pScreen->SourceValidate; 321 322 pScreenPriv->CopyWindow = pScreen->CopyWindow; 323 324 pScreenPriv->InstallColormap = pScreen->InstallColormap; 325 pScreenPriv->StoreColors = pScreen->StoreColors; 326 327 pScreenPriv->BlockHandler = NULL; 328 329 pScreenPriv->pInstalledMap = NULL; 330 pScreenPriv->pColormap = NULL; 331 pScreenPriv->colors[SOURCE_COLOR].red = 0; 332 pScreenPriv->colors[SOURCE_COLOR].green = 0; 333 pScreenPriv->colors[SOURCE_COLOR].blue = 0; 334 pScreenPriv->colors[MASK_COLOR].red = 0; 335 pScreenPriv->colors[MASK_COLOR].green = 0; 336 pScreenPriv->colors[MASK_COLOR].blue = 0; 337 pScreenPriv->damageRegistered = 0; 338 pScreenPriv->numberOfCursors = 0; 339 340 dixSetPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec, pScreenPriv); 341 342 pScreen->CloseScreen = miSpriteCloseScreen; 343 pScreen->GetImage = miSpriteGetImage; 344 pScreen->GetSpans = miSpriteGetSpans; 345 pScreen->SourceValidate = miSpriteSourceValidate; 346 347 pScreen->CopyWindow = miSpriteCopyWindow; 348 pScreen->InstallColormap = miSpriteInstallColormap; 349 pScreen->StoreColors = miSpriteStoreColors; 350 351 return TRUE; 352} 353 354/* 355 * Screen wrappers 356 */ 357 358/* 359 * CloseScreen wrapper -- unwrap everything, free the private data 360 * and call the wrapped function 361 */ 362 363static Bool 364miSpriteCloseScreen(ScreenPtr pScreen) 365{ 366 miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); 367 368 pScreen->CloseScreen = pScreenPriv->CloseScreen; 369 pScreen->GetImage = pScreenPriv->GetImage; 370 pScreen->GetSpans = pScreenPriv->GetSpans; 371 pScreen->SourceValidate = pScreenPriv->SourceValidate; 372 pScreen->InstallColormap = pScreenPriv->InstallColormap; 373 pScreen->StoreColors = pScreenPriv->StoreColors; 374 375 DamageDestroy(pScreenPriv->pDamage); 376 377 free(pScreenPriv); 378 379 return (*pScreen->CloseScreen) (pScreen); 380} 381 382static void 383miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 384 unsigned int format, unsigned long planemask, char *pdstLine) 385{ 386 ScreenPtr pScreen = pDrawable->pScreen; 387 DeviceIntPtr pDev; 388 miCursorInfoPtr pCursorInfo; 389 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 390 391 SCREEN_PROLOGUE(pPriv, pScreen, GetImage); 392 393 if (pDrawable->type == DRAWABLE_WINDOW) { 394 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 395 if (DevHasCursor(pDev)) { 396 pCursorInfo = GetSprite(pDev); 397 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && 398 ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, 399 sx, sy, w, h)) { 400 SPRITE_DEBUG(("GetImage remove\n")); 401 miSpriteRemoveCursor(pDev, pScreen); 402 } 403 } 404 } 405 } 406 407 (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine); 408 409 SCREEN_EPILOGUE(pPriv, pScreen, GetImage); 410} 411 412static void 413miSpriteGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, 414 int *pwidth, int nspans, char *pdstStart) 415{ 416 ScreenPtr pScreen = pDrawable->pScreen; 417 DeviceIntPtr pDev; 418 miCursorInfoPtr pCursorInfo; 419 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 420 421 SCREEN_PROLOGUE(pPriv, pScreen, GetSpans); 422 423 if (pDrawable->type == DRAWABLE_WINDOW) { 424 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 425 if (DevHasCursor(pDev)) { 426 pCursorInfo = GetSprite(pDev); 427 428 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) { 429 DDXPointPtr pts; 430 int *widths; 431 int nPts; 432 int xorg, yorg; 433 434 xorg = pDrawable->x; 435 yorg = pDrawable->y; 436 437 for (pts = ppt, widths = pwidth, nPts = nspans; 438 nPts--; pts++, widths++) { 439 if (SPN_OVERLAP(&pCursorInfo->saved, pts->y + yorg, 440 pts->x + xorg, *widths)) { 441 SPRITE_DEBUG(("GetSpans remove\n")); 442 miSpriteRemoveCursor(pDev, pScreen); 443 break; 444 } 445 } 446 } 447 } 448 } 449 } 450 451 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 452 453 SCREEN_EPILOGUE(pPriv, pScreen, GetSpans); 454} 455 456static void 457miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, int width, 458 int height, unsigned int subWindowMode) 459{ 460 ScreenPtr pScreen = pDrawable->pScreen; 461 DeviceIntPtr pDev; 462 miCursorInfoPtr pCursorInfo; 463 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 464 465 SCREEN_PROLOGUE(pPriv, pScreen, SourceValidate); 466 467 if (pDrawable->type == DRAWABLE_WINDOW) { 468 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 469 if (DevHasCursor(pDev)) { 470 pCursorInfo = GetSprite(pDev); 471 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && 472 ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, 473 x, y, width, height)) { 474 SPRITE_DEBUG(("SourceValidate remove\n")); 475 miSpriteRemoveCursor(pDev, pScreen); 476 } 477 } 478 } 479 } 480 481 if (pScreen->SourceValidate) 482 (*pScreen->SourceValidate) (pDrawable, x, y, width, height, 483 subWindowMode); 484 485 SCREEN_EPILOGUE(pPriv, pScreen, SourceValidate); 486} 487 488static void 489miSpriteCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 490{ 491 ScreenPtr pScreen = pWindow->drawable.pScreen; 492 DeviceIntPtr pDev; 493 miCursorInfoPtr pCursorInfo; 494 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 495 496 SCREEN_PROLOGUE(pPriv, pScreen, CopyWindow); 497 498 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 499 if (DevHasCursor(pDev)) { 500 pCursorInfo = GetSprite(pDev); 501 /* 502 * Damage will take care of destination check 503 */ 504 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && 505 RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) { 506 SPRITE_DEBUG(("CopyWindow remove\n")); 507 miSpriteRemoveCursor(pDev, pScreen); 508 } 509 } 510 } 511 512 (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); 513 SCREEN_EPILOGUE(pPriv, pScreen, CopyWindow); 514} 515 516static void 517miSpriteBlockHandler(ScreenPtr pScreen, void *timeout) 518{ 519 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 520 DeviceIntPtr pDev; 521 miCursorInfoPtr pCursorInfo; 522 Bool WorkToDo = FALSE; 523 524 SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); 525 526 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 527 if (DevHasCursor(pDev)) { 528 pCursorInfo = GetSprite(pDev); 529 if (pCursorInfo && !pCursorInfo->isUp 530 && pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) { 531 SPRITE_DEBUG(("BlockHandler save")); 532 miSpriteSaveUnderCursor(pDev, pScreen); 533 } 534 } 535 } 536 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 537 if (DevHasCursor(pDev)) { 538 pCursorInfo = GetSprite(pDev); 539 if (pCursorInfo && !pCursorInfo->isUp && 540 pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) { 541 SPRITE_DEBUG(("BlockHandler restore\n")); 542 miSpriteRestoreCursor(pDev, pScreen); 543 if (!pCursorInfo->isUp) 544 WorkToDo = TRUE; 545 } 546 } 547 } 548 549 (*pScreen->BlockHandler) (pScreen, timeout); 550 551 if (WorkToDo) 552 SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); 553 else 554 pPriv->BlockHandler = NULL; 555} 556 557static void 558miSpriteInstallColormap(ColormapPtr pMap) 559{ 560 ScreenPtr pScreen = pMap->pScreen; 561 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 562 563 SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); 564 565 (*pScreen->InstallColormap) (pMap); 566 567 SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); 568 569 /* InstallColormap can be called before devices are initialized. */ 570 pPriv->pInstalledMap = pMap; 571 if (pPriv->pColormap != pMap) { 572 DeviceIntPtr pDev; 573 miCursorInfoPtr pCursorInfo; 574 575 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 576 if (DevHasCursor(pDev)) { 577 pCursorInfo = GetSprite(pDev); 578 pCursorInfo->checkPixels = TRUE; 579 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) 580 miSpriteRemoveCursor(pDev, pScreen); 581 } 582 } 583 584 } 585} 586 587static void 588miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef) 589{ 590 ScreenPtr pScreen = pMap->pScreen; 591 miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); 592 int i; 593 int updated; 594 VisualPtr pVisual; 595 DeviceIntPtr pDev; 596 miCursorInfoPtr pCursorInfo; 597 598 SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); 599 600 (*pScreen->StoreColors) (pMap, ndef, pdef); 601 602 SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); 603 604 if (pPriv->pColormap == pMap) { 605 updated = 0; 606 pVisual = pMap->pVisual; 607 if (pVisual->class == DirectColor) { 608 /* Direct color - match on any of the subfields */ 609 610#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) 611 612#define UpdateDAC(dev, plane,dac,mask) {\ 613 if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ 614 dev->colors[plane].dac = pdef[i].dac; \ 615 updated = 1; \ 616 } \ 617} 618 619#define CheckDirect(dev, plane) \ 620 UpdateDAC(dev, plane,red,redMask) \ 621 UpdateDAC(dev, plane,green,greenMask) \ 622 UpdateDAC(dev, plane,blue,blueMask) 623 624 for (i = 0; i < ndef; i++) { 625 CheckDirect(pPriv, SOURCE_COLOR) 626 CheckDirect(pPriv, MASK_COLOR) 627 } 628 } 629 else { 630 /* PseudoColor/GrayScale - match on exact pixel */ 631 for (i = 0; i < ndef; i++) { 632 if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) { 633 pPriv->colors[SOURCE_COLOR] = pdef[i]; 634 if (++updated == 2) 635 break; 636 } 637 if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) { 638 pPriv->colors[MASK_COLOR] = pdef[i]; 639 if (++updated == 2) 640 break; 641 } 642 } 643 } 644 if (updated) { 645 for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 646 if (DevHasCursor(pDev)) { 647 pCursorInfo = GetSprite(pDev); 648 pCursorInfo->checkPixels = TRUE; 649 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) 650 miSpriteRemoveCursor(pDev, pScreen); 651 } 652 } 653 } 654 } 655} 656 657static void 658miSpriteFindColors(miCursorInfoPtr pDevCursor, ScreenPtr pScreen) 659{ 660 miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); 661 CursorPtr pCursor; 662 xColorItem *sourceColor, *maskColor; 663 664 pCursor = pDevCursor->pCursor; 665 sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; 666 maskColor = &pScreenPriv->colors[MASK_COLOR]; 667 if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || 668 !(pCursor->foreRed == sourceColor->red && 669 pCursor->foreGreen == sourceColor->green && 670 pCursor->foreBlue == sourceColor->blue && 671 pCursor->backRed == maskColor->red && 672 pCursor->backGreen == maskColor->green && 673 pCursor->backBlue == maskColor->blue)) { 674 pScreenPriv->pColormap = pScreenPriv->pInstalledMap; 675 sourceColor->red = pCursor->foreRed; 676 sourceColor->green = pCursor->foreGreen; 677 sourceColor->blue = pCursor->foreBlue; 678 FakeAllocColor(pScreenPriv->pColormap, sourceColor); 679 maskColor->red = pCursor->backRed; 680 maskColor->green = pCursor->backGreen; 681 maskColor->blue = pCursor->backBlue; 682 FakeAllocColor(pScreenPriv->pColormap, maskColor); 683 /* "free" the pixels right away, don't let this confuse you */ 684 FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); 685 FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); 686 } 687 688 pDevCursor->checkPixels = FALSE; 689 690} 691 692/* 693 * miPointer interface routines 694 */ 695 696#define SPRITE_PAD 8 697 698static Bool 699miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 700{ 701 miCursorInfoPtr pCursorInfo; 702 703 if (IsFloating(pDev)) 704 return FALSE; 705 706 pCursorInfo = GetSprite(pDev); 707 708 if (pCursor == pCursorInfo->pCursor) 709 pCursorInfo->checkPixels = TRUE; 710 711 return miDCRealizeCursor(pScreen, pCursor); 712} 713 714static Bool 715miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 716{ 717 return miDCUnrealizeCursor(pScreen, pCursor); 718} 719 720static void 721miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 722 CursorPtr pCursor, int x, int y) 723{ 724 miCursorInfoPtr pPointer; 725 miSpriteScreenPtr pScreenPriv; 726 727 if (IsFloating(pDev)) 728 return; 729 730 pPointer = GetSprite(pDev); 731 pScreenPriv = GetSpriteScreen(pScreen); 732 733 if (!pCursor) { 734 if (pPointer->shouldBeUp) 735 --pScreenPriv->numberOfCursors; 736 pPointer->shouldBeUp = FALSE; 737 if (pPointer->isUp) 738 miSpriteRemoveCursor(pDev, pScreen); 739 if (pScreenPriv->numberOfCursors == 0) 740 miSpriteDisableDamage(pScreen, pScreenPriv); 741 pPointer->pCursor = 0; 742 return; 743 } 744 if (!pPointer->shouldBeUp) 745 pScreenPriv->numberOfCursors++; 746 pPointer->shouldBeUp = TRUE; 747 if (!pPointer->isUp) 748 miSpriteRegisterBlockHandler(pScreen, pScreenPriv); 749 if (pPointer->x == x && 750 pPointer->y == y && 751 pPointer->pCursor == pCursor && !pPointer->checkPixels) { 752 return; 753 } 754 pPointer->x = x; 755 pPointer->y = y; 756 if (pPointer->checkPixels || pPointer->pCursor != pCursor) { 757 pPointer->pCursor = pCursor; 758 miSpriteFindColors(pPointer, pScreen); 759 } 760 if (pPointer->isUp) { 761 /* TODO: reimplement flicker-free MoveCursor */ 762 SPRITE_DEBUG(("SetCursor remove %d\n", pDev->id)); 763 miSpriteRemoveCursor(pDev, pScreen); 764 } 765 766 if (!pPointer->isUp && pPointer->pCursor) { 767 SPRITE_DEBUG(("SetCursor restore %d\n", pDev->id)); 768 miSpriteSaveUnderCursor(pDev, pScreen); 769 miSpriteRestoreCursor(pDev, pScreen); 770 } 771 772} 773 774static void 775miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 776{ 777 CursorPtr pCursor; 778 779 if (IsFloating(pDev)) 780 return; 781 782 pCursor = GetSprite(pDev)->pCursor; 783 784 miSpriteSetCursor(pDev, pScreen, pCursor, x, y); 785} 786 787static Bool 788miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) 789{ 790 int ret = miDCDeviceInitialize(pDev, pScreen); 791 792 if (ret) { 793 miCursorInfoPtr pCursorInfo; 794 795 pCursorInfo = 796 dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec); 797 pCursorInfo->pCursor = NULL; 798 pCursorInfo->x = 0; 799 pCursorInfo->y = 0; 800 pCursorInfo->isUp = FALSE; 801 pCursorInfo->shouldBeUp = FALSE; 802 pCursorInfo->checkPixels = TRUE; 803 pCursorInfo->pScreen = FALSE; 804 } 805 806 return ret; 807} 808 809static void 810miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) 811{ 812 miCursorInfoPtr pCursorInfo = 813 dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec); 814 815 if (DevHasCursor(pDev)) 816 miDCDeviceCleanup(pDev, pScreen); 817 818 memset(pCursorInfo, 0, sizeof(miCursorInfoRec)); 819} 820 821/* 822 * undraw/draw cursor 823 */ 824 825static void 826miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen) 827{ 828 miSpriteScreenPtr pScreenPriv; 829 miCursorInfoPtr pCursorInfo; 830 831 if (IsFloating(pDev)) 832 return; 833 834 DamageDrawInternal(pScreen, TRUE); 835 pScreenPriv = GetSpriteScreen(pScreen); 836 pCursorInfo = GetSprite(pDev); 837 838 miSpriteIsDown(pCursorInfo); 839 miSpriteRegisterBlockHandler(pScreen, pScreenPriv); 840 miSpriteDisableDamage(pScreen, pScreenPriv); 841 if (!miDCRestoreUnderCursor(pDev, 842 pScreen, 843 pCursorInfo->saved.x1, 844 pCursorInfo->saved.y1, 845 pCursorInfo->saved.x2 - 846 pCursorInfo->saved.x1, 847 pCursorInfo->saved.y2 - 848 pCursorInfo->saved.y1)) { 849 miSpriteIsUp(pCursorInfo); 850 } 851 miSpriteEnableDamage(pScreen, pScreenPriv); 852 DamageDrawInternal(pScreen, FALSE); 853} 854 855/* 856 * Called from the block handler, saves area under cursor 857 * before waiting for something to do. 858 */ 859 860static void 861miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) 862{ 863 miSpriteScreenPtr pScreenPriv; 864 miCursorInfoPtr pCursorInfo; 865 866 if (IsFloating(pDev)) 867 return; 868 869 DamageDrawInternal(pScreen, TRUE); 870 pScreenPriv = GetSpriteScreen(pScreen); 871 pCursorInfo = GetSprite(pDev); 872 873 miSpriteComputeSaved(pDev, pScreen); 874 875 miSpriteDisableDamage(pScreen, pScreenPriv); 876 877 miDCSaveUnderCursor(pDev, 878 pScreen, 879 pCursorInfo->saved.x1, 880 pCursorInfo->saved.y1, 881 pCursorInfo->saved.x2 - 882 pCursorInfo->saved.x1, 883 pCursorInfo->saved.y2 - pCursorInfo->saved.y1); 884 SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); 885 miSpriteEnableDamage(pScreen, pScreenPriv); 886 DamageDrawInternal(pScreen, FALSE); 887} 888 889/* 890 * Called from the block handler, restores the cursor 891 * before waiting for something to do. 892 */ 893 894static void 895miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen) 896{ 897 miSpriteScreenPtr pScreenPriv; 898 int x, y; 899 CursorPtr pCursor; 900 miCursorInfoPtr pCursorInfo; 901 902 if (IsFloating(pDev)) 903 return; 904 905 DamageDrawInternal(pScreen, TRUE); 906 pScreenPriv = GetSpriteScreen(pScreen); 907 pCursorInfo = GetSprite(pDev); 908 909 miSpriteComputeSaved(pDev, pScreen); 910 pCursor = pCursorInfo->pCursor; 911 912 x = pCursorInfo->x - (int) pCursor->bits->xhot; 913 y = pCursorInfo->y - (int) pCursor->bits->yhot; 914 miSpriteDisableDamage(pScreen, pScreenPriv); 915 SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); 916 if (pCursorInfo->checkPixels) 917 miSpriteFindColors(pCursorInfo, pScreen); 918 if (miDCPutUpCursor(pDev, pScreen, 919 pCursor, x, y, 920 pScreenPriv->colors[SOURCE_COLOR].pixel, 921 pScreenPriv->colors[MASK_COLOR].pixel)) { 922 miSpriteIsUp(pCursorInfo); 923 pCursorInfo->pScreen = pScreen; 924 } 925 miSpriteEnableDamage(pScreen, pScreenPriv); 926 DamageDrawInternal(pScreen, FALSE); 927} 928 929/* 930 * compute the desired area of the screen to save 931 */ 932 933static void 934miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen) 935{ 936 int x, y, w, h; 937 int wpad, hpad; 938 CursorPtr pCursor; 939 miCursorInfoPtr pCursorInfo; 940 941 if (IsFloating(pDev)) 942 return; 943 944 pCursorInfo = GetSprite(pDev); 945 946 pCursor = pCursorInfo->pCursor; 947 x = pCursorInfo->x - (int) pCursor->bits->xhot; 948 y = pCursorInfo->y - (int) pCursor->bits->yhot; 949 w = pCursor->bits->width; 950 h = pCursor->bits->height; 951 wpad = SPRITE_PAD; 952 hpad = SPRITE_PAD; 953 pCursorInfo->saved.x1 = x - wpad; 954 pCursorInfo->saved.y1 = y - hpad; 955 pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; 956 pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; 957} 958