/* * misprite.c * * machine independent software sprite routines */ /* Copyright 1989, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ #ifdef HAVE_DIX_CONFIG_H #include #endif # include # include # include "misc.h" # include "pixmapstr.h" # include "input.h" # include "mi.h" # include "cursorstr.h" # include # include "scrnintstr.h" # include "colormapst.h" # include "windowstr.h" # include "gcstruct.h" # include "mipointer.h" # include "mispritest.h" # include "dixfontstr.h" # include #ifdef RENDER # include "mipict.h" #endif # include "damage.h" #define SPRITE_DEBUG_ENABLE 0 #if SPRITE_DEBUG_ENABLE #define SPRITE_DEBUG(x) ErrorF x #else #define SPRITE_DEBUG(x) #endif /* * screen wrappers */ static int miSpriteScreenIndex; static unsigned long miSpriteGeneration = 0; static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, unsigned int format, unsigned long planemask, char *pdstLine); static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart); static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, int width, int height); static void miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc); static void miSpriteBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadMask); static void miSpriteInstallColormap(ColormapPtr pMap); static void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem *pdef); static void miSpriteSaveDoomedAreas(WindowPtr pWin, RegionPtr pObscured, int dx, int dy); static void miSpriteComputeSaved(ScreenPtr pScreen); #define SCREEN_PROLOGUE(pScreen, field)\ ((pScreen)->field = \ ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field) #define SCREEN_EPILOGUE(pScreen, field)\ ((pScreen)->field = miSprite##field) /* * pointer-sprite method table */ static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y); static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y); _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = { miSpriteRealizeCursor, miSpriteUnrealizeCursor, miSpriteSetCursor, miSpriteMoveCursor, }; /* * other misc functions */ static void miSpriteRemoveCursor(ScreenPtr pScreen); static void miSpriteRestoreCursor(ScreenPtr pScreen); static void miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) { ScreenPtr pScreen = closure; miSpriteScreenPtr pScreenPriv; pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; if (pScreenPriv->isUp && RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) { SPRITE_DEBUG(("Damage remove\n")); miSpriteRemoveCursor (pScreen); } } /* * miSpriteInitialize -- called from device-dependent screen * initialization proc after all of the function pointers have * been stored in the screen structure. */ Bool miSpriteInitialize (pScreen, cursorFuncs, screenFuncs) ScreenPtr pScreen; miSpriteCursorFuncPtr cursorFuncs; miPointerScreenFuncPtr screenFuncs; { miSpriteScreenPtr pScreenPriv; VisualPtr pVisual; if (!DamageSetup (pScreen)) return FALSE; if (miSpriteGeneration != serverGeneration) { miSpriteScreenIndex = AllocateScreenPrivateIndex (); if (miSpriteScreenIndex < 0) return FALSE; miSpriteGeneration = serverGeneration; } pScreenPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec)); if (!pScreenPriv) return FALSE; pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, (DamageDestroyFunc) 0, DamageReportRawRegion, TRUE, pScreen, (void *) pScreen); if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) { xfree ((pointer) pScreenPriv); return FALSE; } for (pVisual = pScreen->visuals; pVisual->vid != pScreen->rootVisual; pVisual++) ; pScreenPriv->pVisual = pVisual; pScreenPriv->CloseScreen = pScreen->CloseScreen; pScreenPriv->GetImage = pScreen->GetImage; pScreenPriv->GetSpans = pScreen->GetSpans; pScreenPriv->SourceValidate = pScreen->SourceValidate; pScreenPriv->CopyWindow = pScreen->CopyWindow; pScreenPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas; pScreenPriv->InstallColormap = pScreen->InstallColormap; pScreenPriv->StoreColors = pScreen->StoreColors; pScreenPriv->BlockHandler = pScreen->BlockHandler; pScreenPriv->pCursor = NULL; pScreenPriv->x = 0; pScreenPriv->y = 0; pScreenPriv->isUp = FALSE; pScreenPriv->shouldBeUp = FALSE; pScreenPriv->pCacheWin = NullWindow; pScreenPriv->isInCacheWin = FALSE; pScreenPriv->checkPixels = TRUE; pScreenPriv->pInstalledMap = NULL; pScreenPriv->pColormap = NULL; pScreenPriv->funcs = cursorFuncs; pScreenPriv->colors[SOURCE_COLOR].red = 0; pScreenPriv->colors[SOURCE_COLOR].green = 0; pScreenPriv->colors[SOURCE_COLOR].blue = 0; pScreenPriv->colors[MASK_COLOR].red = 0; pScreenPriv->colors[MASK_COLOR].green = 0; pScreenPriv->colors[MASK_COLOR].blue = 0; pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv; pScreen->CloseScreen = miSpriteCloseScreen; pScreen->GetImage = miSpriteGetImage; pScreen->GetSpans = miSpriteGetSpans; pScreen->SourceValidate = miSpriteSourceValidate; pScreen->CopyWindow = miSpriteCopyWindow; pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas; pScreen->InstallColormap = miSpriteInstallColormap; pScreen->StoreColors = miSpriteStoreColors; pScreen->BlockHandler = miSpriteBlockHandler; return TRUE; } /* * Screen wrappers */ /* * CloseScreen wrapper -- unwrap everything, free the private data * and call the wrapped function */ static Bool miSpriteCloseScreen (i, pScreen) int i; ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; pScreen->CloseScreen = pScreenPriv->CloseScreen; pScreen->GetImage = pScreenPriv->GetImage; pScreen->GetSpans = pScreenPriv->GetSpans; pScreen->SourceValidate = pScreenPriv->SourceValidate; pScreen->BlockHandler = pScreenPriv->BlockHandler; pScreen->InstallColormap = pScreenPriv->InstallColormap; pScreen->StoreColors = pScreenPriv->StoreColors; pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas; miSpriteIsUpFALSE (pScreen, pScreenPriv); DamageDestroy (pScreenPriv->pDamage); xfree ((pointer) pScreenPriv); return (*pScreen->CloseScreen) (i, pScreen); } static void miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) DrawablePtr pDrawable; int sx, sy, w, h; unsigned int format; unsigned long planemask; char *pdstLine; { ScreenPtr pScreen = pDrawable->pScreen; miSpriteScreenPtr pScreenPriv; SCREEN_PROLOGUE (pScreen, GetImage); pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp && ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) { SPRITE_DEBUG (("GetImage remove\n")); miSpriteRemoveCursor (pScreen); } (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine); SCREEN_EPILOGUE (pScreen, GetImage); } static void miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) DrawablePtr pDrawable; int wMax; DDXPointPtr ppt; int *pwidth; int nspans; char *pdstStart; { ScreenPtr pScreen = pDrawable->pScreen; miSpriteScreenPtr pScreenPriv; SCREEN_PROLOGUE (pScreen, GetSpans); pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp) { register DDXPointPtr pts; register int *widths; register int nPts; register int xorg, yorg; xorg = pDrawable->x; yorg = pDrawable->y; for (pts = ppt, widths = pwidth, nPts = nspans; nPts--; pts++, widths++) { if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, pts->x+xorg,*widths)) { SPRITE_DEBUG (("GetSpans remove\n")); miSpriteRemoveCursor (pScreen); break; } } } (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); SCREEN_EPILOGUE (pScreen, GetSpans); } static void miSpriteSourceValidate (pDrawable, x, y, width, height) DrawablePtr pDrawable; int x, y, width, height; { ScreenPtr pScreen = pDrawable->pScreen; miSpriteScreenPtr pScreenPriv; SCREEN_PROLOGUE (pScreen, SourceValidate); pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp && ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, x, y, width, height)) { SPRITE_DEBUG (("SourceValidate remove\n")); miSpriteRemoveCursor (pScreen); } if (pScreen->SourceValidate) (*pScreen->SourceValidate) (pDrawable, x, y, width, height); SCREEN_EPILOGUE (pScreen, SourceValidate); } static void miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWindow->drawable.pScreen; miSpriteScreenPtr pScreenPriv; SCREEN_PROLOGUE (pScreen, CopyWindow); pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; /* * Damage will take care of destination check */ if (pScreenPriv->isUp && RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->saved) != rgnOUT) { SPRITE_DEBUG (("CopyWindow remove\n")); miSpriteRemoveCursor (pScreen); } (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); SCREEN_EPILOGUE (pScreen, CopyWindow); } static void miSpriteBlockHandler (i, blockData, pTimeout, pReadmask) int i; pointer blockData; pointer pTimeout; pointer pReadmask; { ScreenPtr pScreen = screenInfo.screens[i]; miSpriteScreenPtr pPriv; pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; SCREEN_PROLOGUE(pScreen, BlockHandler); (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); SCREEN_EPILOGUE(pScreen, BlockHandler); if (!pPriv->isUp && pPriv->shouldBeUp) { SPRITE_DEBUG (("BlockHandler restore\n")); miSpriteRestoreCursor (pScreen); } } static void miSpriteInstallColormap (pMap) ColormapPtr pMap; { ScreenPtr pScreen = pMap->pScreen; miSpriteScreenPtr pPriv; pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; SCREEN_PROLOGUE(pScreen, InstallColormap); (*pScreen->InstallColormap) (pMap); SCREEN_EPILOGUE(pScreen, InstallColormap); pPriv->pInstalledMap = pMap; if (pPriv->pColormap != pMap) { pPriv->checkPixels = TRUE; if (pPriv->isUp) miSpriteRemoveCursor (pScreen); } } static void miSpriteStoreColors (pMap, ndef, pdef) ColormapPtr pMap; int ndef; xColorItem *pdef; { ScreenPtr pScreen = pMap->pScreen; miSpriteScreenPtr pPriv; int i; int updated; VisualPtr pVisual; pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; SCREEN_PROLOGUE(pScreen, StoreColors); (*pScreen->StoreColors) (pMap, ndef, pdef); SCREEN_EPILOGUE(pScreen, StoreColors); if (pPriv->pColormap == pMap) { updated = 0; pVisual = pMap->pVisual; if (pVisual->class == DirectColor) { /* Direct color - match on any of the subfields */ #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) #define UpdateDAC(plane,dac,mask) {\ if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ pPriv->colors[plane].dac = pdef[i].dac; \ updated = 1; \ } \ } #define CheckDirect(plane) \ UpdateDAC(plane,red,redMask) \ UpdateDAC(plane,green,greenMask) \ UpdateDAC(plane,blue,blueMask) for (i = 0; i < ndef; i++) { CheckDirect (SOURCE_COLOR) CheckDirect (MASK_COLOR) } } else { /* PseudoColor/GrayScale - match on exact pixel */ for (i = 0; i < ndef; i++) { if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) { pPriv->colors[SOURCE_COLOR] = pdef[i]; if (++updated == 2) break; } if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) { pPriv->colors[MASK_COLOR] = pdef[i]; if (++updated == 2) break; } } } if (updated) { pPriv->checkPixels = TRUE; if (pPriv->isUp) miSpriteRemoveCursor (pScreen); } } } static void miSpriteFindColors (ScreenPtr pScreen) { miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; CursorPtr pCursor; xColorItem *sourceColor, *maskColor; pCursor = pScreenPriv->pCursor; sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; maskColor = &pScreenPriv->colors[MASK_COLOR]; if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || !(pCursor->foreRed == sourceColor->red && pCursor->foreGreen == sourceColor->green && pCursor->foreBlue == sourceColor->blue && pCursor->backRed == maskColor->red && pCursor->backGreen == maskColor->green && pCursor->backBlue == maskColor->blue)) { pScreenPriv->pColormap = pScreenPriv->pInstalledMap; sourceColor->red = pCursor->foreRed; sourceColor->green = pCursor->foreGreen; sourceColor->blue = pCursor->foreBlue; FakeAllocColor (pScreenPriv->pColormap, sourceColor); maskColor->red = pCursor->backRed; maskColor->green = pCursor->backGreen; maskColor->blue = pCursor->backBlue; FakeAllocColor (pScreenPriv->pColormap, maskColor); /* "free" the pixels right away, don't let this confuse you */ FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); } pScreenPriv->checkPixels = FALSE; } /* * BackingStore wrappers */ static void miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy) WindowPtr pWin; RegionPtr pObscured; int dx, dy; { ScreenPtr pScreen; miSpriteScreenPtr pScreenPriv; BoxRec cursorBox; pScreen = pWin->drawable.pScreen; SCREEN_PROLOGUE (pScreen, SaveDoomedAreas); pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; if (pScreenPriv->isUp) { cursorBox = pScreenPriv->saved; if (dx || dy) { cursorBox.x1 += dx; cursorBox.y1 += dy; cursorBox.x2 += dx; cursorBox.y2 += dy; } if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT) miSpriteRemoveCursor (pScreen); } (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy); SCREEN_EPILOGUE (pScreen, SaveDoomedAreas); } /* * miPointer interface routines */ #define SPRITE_PAD 8 static Bool miSpriteRealizeCursor (pScreen, pCursor) ScreenPtr pScreen; CursorPtr pCursor; { miSpriteScreenPtr pScreenPriv; pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; if (pCursor == pScreenPriv->pCursor) pScreenPriv->checkPixels = TRUE; return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); } static Bool miSpriteUnrealizeCursor (pScreen, pCursor) ScreenPtr pScreen; CursorPtr pCursor; { miSpriteScreenPtr pScreenPriv; pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); } static void miSpriteSetCursor (pScreen, pCursor, x, y) ScreenPtr pScreen; CursorPtr pCursor; int x; int y; { miSpriteScreenPtr pScreenPriv; pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; if (!pCursor) { pScreenPriv->shouldBeUp = FALSE; if (pScreenPriv->isUp) miSpriteRemoveCursor (pScreen); pScreenPriv->pCursor = 0; return; } pScreenPriv->shouldBeUp = TRUE; if (pScreenPriv->x == x && pScreenPriv->y == y && pScreenPriv->pCursor == pCursor && !pScreenPriv->checkPixels) { return; } pScreenPriv->x = x; pScreenPriv->y = y; pScreenPriv->pCacheWin = NullWindow; if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) { pScreenPriv->pCursor = pCursor; miSpriteFindColors (pScreen); } if (pScreenPriv->isUp) { int sx, sy; /* * check to see if the old saved region * encloses the new sprite, in which case we use * the flicker-free MoveCursor primitive. */ sx = pScreenPriv->x - (int)pCursor->bits->xhot; sy = pScreenPriv->y - (int)pCursor->bits->yhot; if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && sx < pScreenPriv->saved.x2 && sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && sy < pScreenPriv->saved.y2 && (int) pCursor->bits->width + (2 * SPRITE_PAD) == pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && (int) pCursor->bits->height + (2 * SPRITE_PAD) == pScreenPriv->saved.y2 - pScreenPriv->saved.y1 ) { DamageDrawInternal (pScreen, TRUE); miSpriteIsUpFALSE (pScreen, pScreenPriv); if (!(sx >= pScreenPriv->saved.x1 && sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && sy >= pScreenPriv->saved.y1 && sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) { int oldx1, oldy1, dx, dy; oldx1 = pScreenPriv->saved.x1; oldy1 = pScreenPriv->saved.y1; dx = oldx1 - (sx - SPRITE_PAD); dy = oldy1 - (sy - SPRITE_PAD); pScreenPriv->saved.x1 -= dx; pScreenPriv->saved.y1 -= dy; pScreenPriv->saved.x2 -= dx; pScreenPriv->saved.y2 -= dy; (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, pScreenPriv->saved.x1, pScreenPriv->saved.y1, pScreenPriv->saved.x2 - pScreenPriv->saved.x1, pScreenPriv->saved.y2 - pScreenPriv->saved.y1, dx, dy); } (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, pScreenPriv->saved.x1, pScreenPriv->saved.y1, pScreenPriv->saved.x2 - pScreenPriv->saved.x1, pScreenPriv->saved.y2 - pScreenPriv->saved.y1, sx - pScreenPriv->saved.x1, sy - pScreenPriv->saved.y1, pScreenPriv->colors[SOURCE_COLOR].pixel, pScreenPriv->colors[MASK_COLOR].pixel); miSpriteIsUpTRUE (pScreen, pScreenPriv); DamageDrawInternal (pScreen, FALSE); } else { SPRITE_DEBUG (("SetCursor remove\n")); miSpriteRemoveCursor (pScreen); } } if (!pScreenPriv->isUp && pScreenPriv->pCursor) { SPRITE_DEBUG (("SetCursor restore\n")); miSpriteRestoreCursor (pScreen); } } static void miSpriteMoveCursor (pScreen, x, y) ScreenPtr pScreen; int x, y; { miSpriteScreenPtr pScreenPriv; pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); } /* * undraw/draw cursor */ static void miSpriteRemoveCursor (pScreen) ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; DamageDrawInternal (pScreen, TRUE); pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; miSpriteIsUpFALSE (pScreen, pScreenPriv); pScreenPriv->pCacheWin = NullWindow; if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, pScreenPriv->saved.x1, pScreenPriv->saved.y1, pScreenPriv->saved.x2 - pScreenPriv->saved.x1, pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) { miSpriteIsUpTRUE (pScreen, pScreenPriv); } DamageDrawInternal (pScreen, FALSE); } /* * Called from the block handler, restores the cursor * before waiting for something to do. */ static void miSpriteRestoreCursor (pScreen) ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; int x, y; CursorPtr pCursor; DamageDrawInternal (pScreen, TRUE); miSpriteComputeSaved (pScreen); pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; pCursor = pScreenPriv->pCursor; x = pScreenPriv->x - (int)pCursor->bits->xhot; y = pScreenPriv->y - (int)pCursor->bits->yhot; if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, pScreenPriv->saved.x1, pScreenPriv->saved.y1, pScreenPriv->saved.x2 - pScreenPriv->saved.x1, pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) { if (pScreenPriv->checkPixels) miSpriteFindColors (pScreen); if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, pScreenPriv->colors[SOURCE_COLOR].pixel, pScreenPriv->colors[MASK_COLOR].pixel)) { miSpriteIsUpTRUE (pScreen, pScreenPriv); } } DamageDrawInternal (pScreen, FALSE); } /* * compute the desired area of the screen to save */ static void miSpriteComputeSaved (pScreen) ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; int x, y, w, h; int wpad, hpad; CursorPtr pCursor; pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; pCursor = pScreenPriv->pCursor; x = pScreenPriv->x - (int)pCursor->bits->xhot; y = pScreenPriv->y - (int)pCursor->bits->yhot; w = pCursor->bits->width; h = pCursor->bits->height; wpad = SPRITE_PAD; hpad = SPRITE_PAD; pScreenPriv->saved.x1 = x - wpad; pScreenPriv->saved.y1 = y - hpad; pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; }