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