midispcur.c revision 05b261ec
1/* 2 * midispcur.c 3 * 4 * machine independent cursor display routines 5 */ 6 7 8/* 9 10Copyright 1989, 1998 The Open Group 11 12Permission to use, copy, modify, distribute, and sell this software and its 13documentation for any purpose is hereby granted without fee, provided that 14the above copyright notice appear in all copies and that both that 15copyright notice and this permission notice appear in supporting 16documentation. 17 18The above copyright notice and this permission notice shall be included in 19all copies or substantial portions of the Software. 20 21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28Except as contained in this notice, the name of The Open Group shall not be 29used in advertising or otherwise to promote the sale, use or other dealings 30in this Software without prior written authorization from The Open Group. 31*/ 32 33#ifdef HAVE_DIX_CONFIG_H 34#include <dix-config.h> 35#endif 36 37#define NEED_EVENTS 38# include <X11/X.h> 39# include "misc.h" 40# include "input.h" 41# include "cursorstr.h" 42# include "windowstr.h" 43# include "regionstr.h" 44# include "dixstruct.h" 45# include "scrnintstr.h" 46# include "servermd.h" 47# include "mipointer.h" 48# include "misprite.h" 49# include "gcstruct.h" 50 51#ifdef ARGB_CURSOR 52# include "picturestr.h" 53#endif 54 55/* per-screen private data */ 56 57static int miDCScreenIndex; 58static unsigned long miDCGeneration = 0; 59 60static Bool miDCCloseScreen(int index, ScreenPtr pScreen); 61 62typedef struct { 63 GCPtr pSourceGC, pMaskGC; 64 GCPtr pSaveGC, pRestoreGC; 65 GCPtr pMoveGC; 66 GCPtr pPixSourceGC, pPixMaskGC; 67 CloseScreenProcPtr CloseScreen; 68 PixmapPtr pSave, pTemp; 69#ifdef ARGB_CURSOR 70 PicturePtr pRootPicture; 71 PicturePtr pTempPicture; 72#endif 73} miDCScreenRec, *miDCScreenPtr; 74 75/* per-cursor per-screen private data */ 76typedef struct { 77 PixmapPtr sourceBits; /* source bits */ 78 PixmapPtr maskBits; /* mask bits */ 79#ifdef ARGB_CURSOR 80 PicturePtr pPicture; 81#endif 82} miDCCursorRec, *miDCCursorPtr; 83 84/* 85 * sprite/cursor method table 86 */ 87 88static Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); 89static Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); 90static Bool miDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor, 91 int x, int y, unsigned long source, 92 unsigned long mask); 93static Bool miDCSaveUnderCursor(ScreenPtr pScreen, int x, int y, 94 int w, int h); 95static Bool miDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y, 96 int w, int h); 97static Bool miDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor, 98 int x, int y, int w, int h, int dx, int dy, 99 unsigned long source, unsigned long mask); 100static Bool miDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h, 101 int dx, int dy); 102 103static miSpriteCursorFuncRec miDCFuncs = { 104 miDCRealizeCursor, 105 miDCUnrealizeCursor, 106 miDCPutUpCursor, 107 miDCSaveUnderCursor, 108 miDCRestoreUnderCursor, 109 miDCMoveCursor, 110 miDCChangeSave, 111}; 112 113_X_EXPORT Bool 114miDCInitialize (pScreen, screenFuncs) 115 ScreenPtr pScreen; 116 miPointerScreenFuncPtr screenFuncs; 117{ 118 miDCScreenPtr pScreenPriv; 119 120 if (miDCGeneration != serverGeneration) 121 { 122 miDCScreenIndex = AllocateScreenPrivateIndex (); 123 if (miDCScreenIndex < 0) 124 return FALSE; 125 miDCGeneration = serverGeneration; 126 } 127 pScreenPriv = (miDCScreenPtr) xalloc (sizeof (miDCScreenRec)); 128 if (!pScreenPriv) 129 return FALSE; 130 131 /* 132 * initialize the entire private structure to zeros 133 */ 134 135 pScreenPriv->pSourceGC = 136 pScreenPriv->pMaskGC = 137 pScreenPriv->pSaveGC = 138 pScreenPriv->pRestoreGC = 139 pScreenPriv->pMoveGC = 140 pScreenPriv->pPixSourceGC = 141 pScreenPriv->pPixMaskGC = NULL; 142#ifdef ARGB_CURSOR 143 pScreenPriv->pRootPicture = NULL; 144 pScreenPriv->pTempPicture = NULL; 145#endif 146 147 pScreenPriv->pSave = pScreenPriv->pTemp = NULL; 148 149 pScreenPriv->CloseScreen = pScreen->CloseScreen; 150 pScreen->CloseScreen = miDCCloseScreen; 151 152 pScreen->devPrivates[miDCScreenIndex].ptr = (pointer) pScreenPriv; 153 154 if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs)) 155 { 156 xfree ((pointer) pScreenPriv); 157 return FALSE; 158 } 159 return TRUE; 160} 161 162#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0) 163#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE) 164#define tossPict(pict) (pict ? FreePicture (pict, 0) : 0) 165 166static Bool 167miDCCloseScreen (index, pScreen) 168 int index; 169 ScreenPtr pScreen; 170{ 171 miDCScreenPtr pScreenPriv; 172 173 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; 174 pScreen->CloseScreen = pScreenPriv->CloseScreen; 175 tossGC (pScreenPriv->pSourceGC); 176 tossGC (pScreenPriv->pMaskGC); 177 tossGC (pScreenPriv->pSaveGC); 178 tossGC (pScreenPriv->pRestoreGC); 179 tossGC (pScreenPriv->pMoveGC); 180 tossGC (pScreenPriv->pPixSourceGC); 181 tossGC (pScreenPriv->pPixMaskGC); 182 tossPix (pScreenPriv->pSave); 183 tossPix (pScreenPriv->pTemp); 184#ifdef ARGB_CURSOR 185#if 0 /* This has been free()d before */ 186 tossPict (pScreenPriv->pRootPicture); 187#endif 188 tossPict (pScreenPriv->pTempPicture); 189#endif 190 xfree ((pointer) pScreenPriv); 191 return (*pScreen->CloseScreen) (index, pScreen); 192} 193 194static Bool 195miDCRealizeCursor (pScreen, pCursor) 196 ScreenPtr pScreen; 197 CursorPtr pCursor; 198{ 199 if (pCursor->bits->refcnt <= 1) 200 pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; 201 return TRUE; 202} 203 204#ifdef ARGB_CURSOR 205#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win)) 206 207static VisualPtr 208miDCGetWindowVisual (WindowPtr pWin) 209{ 210 ScreenPtr pScreen = pWin->drawable.pScreen; 211 VisualID vid = wVisual (pWin); 212 int i; 213 214 for (i = 0; i < pScreen->numVisuals; i++) 215 if (pScreen->visuals[i].vid == vid) 216 return &pScreen->visuals[i]; 217 return 0; 218} 219 220static PicturePtr 221miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin) 222{ 223 ScreenPtr pScreen = pDraw->pScreen; 224 VisualPtr pVisual; 225 PictFormatPtr pFormat; 226 XID subwindow_mode = IncludeInferiors; 227 PicturePtr pPicture; 228 int error; 229 230 pVisual = miDCGetWindowVisual (pWin); 231 if (!pVisual) 232 return 0; 233 pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual); 234 if (!pFormat) 235 return 0; 236 pPicture = CreatePicture (0, pDraw, pFormat, 237 CPSubwindowMode, &subwindow_mode, 238 serverClient, &error); 239 *ppPicture = pPicture; 240 return pPicture; 241} 242#endif 243 244static miDCCursorPtr 245miDCRealize ( 246 ScreenPtr pScreen, 247 CursorPtr pCursor) 248{ 249 miDCCursorPtr pPriv; 250 GCPtr pGC; 251 XID gcvals[3]; 252 253 pPriv = (miDCCursorPtr) xalloc (sizeof (miDCCursorRec)); 254 if (!pPriv) 255 return (miDCCursorPtr)NULL; 256#ifdef ARGB_CURSOR 257 if (pCursor->bits->argb) 258 { 259 PixmapPtr pPixmap; 260 PictFormatPtr pFormat; 261 int error; 262 263 pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); 264 if (!pFormat) 265 { 266 xfree ((pointer) pPriv); 267 return (miDCCursorPtr)NULL; 268 } 269 270 pPriv->sourceBits = 0; 271 pPriv->maskBits = 0; 272 pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, 273 pCursor->bits->height, 32); 274 if (!pPixmap) 275 { 276 xfree ((pointer) pPriv); 277 return (miDCCursorPtr)NULL; 278 } 279 pGC = GetScratchGC (32, pScreen); 280 if (!pGC) 281 { 282 (*pScreen->DestroyPixmap) (pPixmap); 283 xfree ((pointer) pPriv); 284 return (miDCCursorPtr)NULL; 285 } 286 ValidateGC (&pPixmap->drawable, pGC); 287 (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, 288 0, 0, pCursor->bits->width, 289 pCursor->bits->height, 290 0, ZPixmap, (char *) pCursor->bits->argb); 291 FreeScratchGC (pGC); 292 pPriv->pPicture = CreatePicture (0, &pPixmap->drawable, 293 pFormat, 0, 0, serverClient, &error); 294 (*pScreen->DestroyPixmap) (pPixmap); 295 if (!pPriv->pPicture) 296 { 297 xfree ((pointer) pPriv); 298 return (miDCCursorPtr)NULL; 299 } 300 pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; 301 return pPriv; 302 } 303 pPriv->pPicture = 0; 304#endif 305 pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); 306 if (!pPriv->sourceBits) 307 { 308 xfree ((pointer) pPriv); 309 return (miDCCursorPtr)NULL; 310 } 311 pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1); 312 if (!pPriv->maskBits) 313 { 314 (*pScreen->DestroyPixmap) (pPriv->sourceBits); 315 xfree ((pointer) pPriv); 316 return (miDCCursorPtr)NULL; 317 } 318 pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv; 319 320 /* create the two sets of bits, clipping as appropriate */ 321 322 pGC = GetScratchGC (1, pScreen); 323 if (!pGC) 324 { 325 (void) miDCUnrealizeCursor (pScreen, pCursor); 326 return (miDCCursorPtr)NULL; 327 } 328 329 ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); 330 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, 331 0, 0, pCursor->bits->width, pCursor->bits->height, 332 0, XYPixmap, (char *)pCursor->bits->source); 333 gcvals[0] = GXand; 334 ChangeGC (pGC, GCFunction, gcvals); 335 ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); 336 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, 337 0, 0, pCursor->bits->width, pCursor->bits->height, 338 0, XYPixmap, (char *)pCursor->bits->mask); 339 340 /* mask bits -- pCursor->mask & ~pCursor->source */ 341 gcvals[0] = GXcopy; 342 ChangeGC (pGC, GCFunction, gcvals); 343 ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); 344 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, 345 0, 0, pCursor->bits->width, pCursor->bits->height, 346 0, XYPixmap, (char *)pCursor->bits->mask); 347 gcvals[0] = GXandInverted; 348 ChangeGC (pGC, GCFunction, gcvals); 349 ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); 350 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, 351 0, 0, pCursor->bits->width, pCursor->bits->height, 352 0, XYPixmap, (char *)pCursor->bits->source); 353 FreeScratchGC (pGC); 354 return pPriv; 355} 356 357static Bool 358miDCUnrealizeCursor (pScreen, pCursor) 359 ScreenPtr pScreen; 360 CursorPtr pCursor; 361{ 362 miDCCursorPtr pPriv; 363 364 pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; 365 if (pPriv && (pCursor->bits->refcnt <= 1)) 366 { 367 if (pPriv->sourceBits) 368 (*pScreen->DestroyPixmap) (pPriv->sourceBits); 369 if (pPriv->maskBits) 370 (*pScreen->DestroyPixmap) (pPriv->maskBits); 371#ifdef ARGB_CURSOR 372 if (pPriv->pPicture) 373 FreePicture (pPriv->pPicture, 0); 374#endif 375 xfree ((pointer) pPriv); 376 pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL; 377 } 378 return TRUE; 379} 380 381static void 382miDCPutBits ( 383 DrawablePtr pDrawable, 384 miDCCursorPtr pPriv, 385 GCPtr sourceGC, 386 GCPtr maskGC, 387 int x_org, 388 int y_org, 389 unsigned w, 390 unsigned h, 391 unsigned long source, 392 unsigned long mask) 393{ 394 XID gcvals[1]; 395 int x, y; 396 397 if (sourceGC->fgPixel != source) 398 { 399 gcvals[0] = source; 400 DoChangeGC (sourceGC, GCForeground, gcvals, 0); 401 } 402 if (sourceGC->serialNumber != pDrawable->serialNumber) 403 ValidateGC (pDrawable, sourceGC); 404 405 if(sourceGC->miTranslate) 406 { 407 x = pDrawable->x + x_org; 408 y = pDrawable->y + y_org; 409 } 410 else 411 { 412 x = x_org; 413 y = y_org; 414 } 415 416 (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); 417 if (maskGC->fgPixel != mask) 418 { 419 gcvals[0] = mask; 420 DoChangeGC (maskGC, GCForeground, gcvals, 0); 421 } 422 if (maskGC->serialNumber != pDrawable->serialNumber) 423 ValidateGC (pDrawable, maskGC); 424 425 if(maskGC->miTranslate) 426 { 427 x = pDrawable->x + x_org; 428 y = pDrawable->y + y_org; 429 } 430 else 431 { 432 x = x_org; 433 y = y_org; 434 } 435 436 (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); 437} 438 439#define EnsureGC(gc,win) (gc || miDCMakeGC(&gc, win)) 440 441static GCPtr 442miDCMakeGC( 443 GCPtr *ppGC, 444 WindowPtr pWin) 445{ 446 GCPtr pGC; 447 int status; 448 XID gcvals[2]; 449 450 gcvals[0] = IncludeInferiors; 451 gcvals[1] = FALSE; 452 pGC = CreateGC((DrawablePtr)pWin, 453 GCSubwindowMode|GCGraphicsExposures, gcvals, &status); 454 if (pGC && pWin->drawable.pScreen->DrawGuarantee) 455 (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack); 456 *ppGC = pGC; 457 return pGC; 458} 459 460 461static Bool 462miDCPutUpCursor (pScreen, pCursor, x, y, source, mask) 463 ScreenPtr pScreen; 464 CursorPtr pCursor; 465 int x, y; 466 unsigned long source, mask; 467{ 468 miDCScreenPtr pScreenPriv; 469 miDCCursorPtr pPriv; 470 WindowPtr pWin; 471 472 pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; 473 if (!pPriv) 474 { 475 pPriv = miDCRealize(pScreen, pCursor); 476 if (!pPriv) 477 return FALSE; 478 } 479 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; 480 pWin = WindowTable[pScreen->myNum]; 481#ifdef ARGB_CURSOR 482 if (pPriv->pPicture) 483 { 484 if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin)) 485 return FALSE; 486 CompositePicture (PictOpOver, 487 pPriv->pPicture, 488 NULL, 489 pScreenPriv->pRootPicture, 490 0, 0, 0, 0, 491 x, y, 492 pCursor->bits->width, 493 pCursor->bits->height); 494 } 495 else 496#endif 497 { 498 if (!EnsureGC(pScreenPriv->pSourceGC, pWin)) 499 return FALSE; 500 if (!EnsureGC(pScreenPriv->pMaskGC, pWin)) 501 { 502 FreeGC (pScreenPriv->pSourceGC, (GContext) 0); 503 pScreenPriv->pSourceGC = 0; 504 return FALSE; 505 } 506 miDCPutBits ((DrawablePtr)pWin, pPriv, 507 pScreenPriv->pSourceGC, pScreenPriv->pMaskGC, 508 x, y, pCursor->bits->width, pCursor->bits->height, 509 source, mask); 510 } 511 return TRUE; 512} 513 514static Bool 515miDCSaveUnderCursor (pScreen, x, y, w, h) 516 ScreenPtr pScreen; 517 int x, y, w, h; 518{ 519 miDCScreenPtr pScreenPriv; 520 PixmapPtr pSave; 521 WindowPtr pWin; 522 GCPtr pGC; 523 524 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; 525 pSave = pScreenPriv->pSave; 526 pWin = WindowTable[pScreen->myNum]; 527 if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) 528 { 529 if (pSave) 530 (*pScreen->DestroyPixmap) (pSave); 531 pScreenPriv->pSave = pSave = 532 (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth); 533 if (!pSave) 534 return FALSE; 535 } 536 if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) 537 return FALSE; 538 pGC = pScreenPriv->pSaveGC; 539 if (pSave->drawable.serialNumber != pGC->serialNumber) 540 ValidateGC ((DrawablePtr) pSave, pGC); 541 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, 542 x, y, w, h, 0, 0); 543 return TRUE; 544} 545 546static Bool 547miDCRestoreUnderCursor (pScreen, x, y, w, h) 548 ScreenPtr pScreen; 549 int x, y, w, h; 550{ 551 miDCScreenPtr pScreenPriv; 552 PixmapPtr pSave; 553 WindowPtr pWin; 554 GCPtr pGC; 555 556 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; 557 pSave = pScreenPriv->pSave; 558 pWin = WindowTable[pScreen->myNum]; 559 if (!pSave) 560 return FALSE; 561 if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) 562 return FALSE; 563 pGC = pScreenPriv->pRestoreGC; 564 if (pWin->drawable.serialNumber != pGC->serialNumber) 565 ValidateGC ((DrawablePtr) pWin, pGC); 566 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, 567 0, 0, w, h, x, y); 568 return TRUE; 569} 570 571static Bool 572miDCChangeSave (pScreen, x, y, w, h, dx, dy) 573 ScreenPtr pScreen; 574 int x, y, w, h, dx, dy; 575{ 576 miDCScreenPtr pScreenPriv; 577 PixmapPtr pSave; 578 WindowPtr pWin; 579 GCPtr pGC; 580 int sourcex, sourcey, destx, desty, copyw, copyh; 581 582 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; 583 pSave = pScreenPriv->pSave; 584 pWin = WindowTable[pScreen->myNum]; 585 /* 586 * restore the bits which are about to get trashed 587 */ 588 if (!pSave) 589 return FALSE; 590 if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) 591 return FALSE; 592 pGC = pScreenPriv->pRestoreGC; 593 if (pWin->drawable.serialNumber != pGC->serialNumber) 594 ValidateGC ((DrawablePtr) pWin, pGC); 595 /* 596 * copy the old bits to the screen. 597 */ 598 if (dy > 0) 599 { 600 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, 601 0, h - dy, w, dy, x + dx, y + h); 602 } 603 else if (dy < 0) 604 { 605 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, 606 0, 0, w, -dy, x + dx, y + dy); 607 } 608 if (dy >= 0) 609 { 610 desty = y + dy; 611 sourcey = 0; 612 copyh = h - dy; 613 } 614 else 615 { 616 desty = y; 617 sourcey = - dy; 618 copyh = h + dy; 619 } 620 if (dx > 0) 621 { 622 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, 623 w - dx, sourcey, dx, copyh, x + w, desty); 624 } 625 else if (dx < 0) 626 { 627 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, 628 0, sourcey, -dx, copyh, x + dx, desty); 629 } 630 if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) 631 return FALSE; 632 pGC = pScreenPriv->pSaveGC; 633 if (pSave->drawable.serialNumber != pGC->serialNumber) 634 ValidateGC ((DrawablePtr) pSave, pGC); 635 /* 636 * move the bits that are still valid within the pixmap 637 */ 638 if (dx >= 0) 639 { 640 sourcex = 0; 641 destx = dx; 642 copyw = w - dx; 643 } 644 else 645 { 646 destx = 0; 647 sourcex = - dx; 648 copyw = w + dx; 649 } 650 if (dy >= 0) 651 { 652 sourcey = 0; 653 desty = dy; 654 copyh = h - dy; 655 } 656 else 657 { 658 desty = 0; 659 sourcey = -dy; 660 copyh = h + dy; 661 } 662 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC, 663 sourcex, sourcey, copyw, copyh, destx, desty); 664 /* 665 * copy the new bits from the screen into the remaining areas of the 666 * pixmap 667 */ 668 if (dy > 0) 669 { 670 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, 671 x, y, w, dy, 0, 0); 672 } 673 else if (dy < 0) 674 { 675 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, 676 x, y + h + dy, w, -dy, 0, h + dy); 677 } 678 if (dy >= 0) 679 { 680 desty = dy; 681 sourcey = y + dy; 682 copyh = h - dy; 683 } 684 else 685 { 686 desty = 0; 687 sourcey = y; 688 copyh = h + dy; 689 } 690 if (dx > 0) 691 { 692 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, 693 x, sourcey, dx, copyh, 0, desty); 694 } 695 else if (dx < 0) 696 { 697 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, 698 x + w + dx, sourcey, -dx, copyh, w + dx, desty); 699 } 700 return TRUE; 701} 702 703static Bool 704miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) 705 ScreenPtr pScreen; 706 CursorPtr pCursor; 707 int x, y, w, h, dx, dy; 708 unsigned long source, mask; 709{ 710 miDCCursorPtr pPriv; 711 miDCScreenPtr pScreenPriv; 712 int status; 713 WindowPtr pWin; 714 GCPtr pGC; 715 XID gcval = FALSE; 716 PixmapPtr pTemp; 717 718 pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum]; 719 if (!pPriv) 720 { 721 pPriv = miDCRealize(pScreen, pCursor); 722 if (!pPriv) 723 return FALSE; 724 } 725 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr; 726 pWin = WindowTable[pScreen->myNum]; 727 pTemp = pScreenPriv->pTemp; 728 if (!pTemp || 729 pTemp->drawable.width != pScreenPriv->pSave->drawable.width || 730 pTemp->drawable.height != pScreenPriv->pSave->drawable.height) 731 { 732 if (pTemp) 733 (*pScreen->DestroyPixmap) (pTemp); 734#ifdef ARGB_CURSOR 735 if (pScreenPriv->pTempPicture) 736 { 737 FreePicture (pScreenPriv->pTempPicture, 0); 738 pScreenPriv->pTempPicture = 0; 739 } 740#endif 741 pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap) 742 (pScreen, w, h, pScreenPriv->pSave->drawable.depth); 743 if (!pTemp) 744 return FALSE; 745 } 746 if (!pScreenPriv->pMoveGC) 747 { 748 pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp, 749 GCGraphicsExposures, &gcval, &status); 750 if (!pScreenPriv->pMoveGC) 751 return FALSE; 752 } 753 /* 754 * copy the saved area to a temporary pixmap 755 */ 756 pGC = pScreenPriv->pMoveGC; 757 if (pGC->serialNumber != pTemp->drawable.serialNumber) 758 ValidateGC ((DrawablePtr) pTemp, pGC); 759 (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave, 760 (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0); 761 762 /* 763 * draw the cursor in the temporary pixmap 764 */ 765#ifdef ARGB_CURSOR 766 if (pPriv->pPicture) 767 { 768 if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin)) 769 return FALSE; 770 CompositePicture (PictOpOver, 771 pPriv->pPicture, 772 NULL, 773 pScreenPriv->pTempPicture, 774 0, 0, 0, 0, 775 dx, dy, 776 pCursor->bits->width, 777 pCursor->bits->height); 778 } 779 else 780#endif 781 { 782 if (!pScreenPriv->pPixSourceGC) 783 { 784 pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, 785 GCGraphicsExposures, &gcval, &status); 786 if (!pScreenPriv->pPixSourceGC) 787 return FALSE; 788 } 789 if (!pScreenPriv->pPixMaskGC) 790 { 791 pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, 792 GCGraphicsExposures, &gcval, &status); 793 if (!pScreenPriv->pPixMaskGC) 794 return FALSE; 795 } 796 miDCPutBits ((DrawablePtr)pTemp, pPriv, 797 pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC, 798 dx, dy, pCursor->bits->width, pCursor->bits->height, 799 source, mask); 800 } 801 802 /* 803 * copy the temporary pixmap onto the screen 804 */ 805 806 if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) 807 return FALSE; 808 pGC = pScreenPriv->pRestoreGC; 809 if (pWin->drawable.serialNumber != pGC->serialNumber) 810 ValidateGC ((DrawablePtr) pWin, pGC); 811 812 (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin, 813 pGC, 814 0, 0, w, h, x, y); 815 return TRUE; 816} 817