misprite.c revision 35c4bbdf
105b261ecSmrg/*
205b261ecSmrg * misprite.c
305b261ecSmrg *
405b261ecSmrg * machine independent software sprite routines
505b261ecSmrg */
605b261ecSmrg
705b261ecSmrg/*
805b261ecSmrg
905b261ecSmrgCopyright 1989, 1998  The Open Group
1005b261ecSmrg
1105b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
1205b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
1305b261ecSmrgthe above copyright notice appear in all copies and that both that
1405b261ecSmrgcopyright notice and this permission notice appear in supporting
1505b261ecSmrgdocumentation.
1605b261ecSmrg
1705b261ecSmrgThe above copyright notice and this permission notice shall be included in
1805b261ecSmrgall copies or substantial portions of the Software.
1905b261ecSmrg
2005b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2105b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2205b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2305b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2405b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2505b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2605b261ecSmrg
2705b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2805b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2905b261ecSmrgin this Software without prior written authorization from The Open Group.
3005b261ecSmrg*/
3105b261ecSmrg
3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3305b261ecSmrg#include <dix-config.h>
3405b261ecSmrg#endif
3505b261ecSmrg
366747b715Smrg#include   <X11/X.h>
376747b715Smrg#include   <X11/Xproto.h>
386747b715Smrg#include   "misc.h"
396747b715Smrg#include   "pixmapstr.h"
406747b715Smrg#include   "input.h"
416747b715Smrg#include   "mi.h"
426747b715Smrg#include   "cursorstr.h"
436747b715Smrg#include   <X11/fonts/font.h>
446747b715Smrg#include   "scrnintstr.h"
456747b715Smrg#include   "colormapst.h"
466747b715Smrg#include   "windowstr.h"
476747b715Smrg#include   "gcstruct.h"
486747b715Smrg#include   "mipointer.h"
496747b715Smrg#include   "misprite.h"
506747b715Smrg#include   "dixfontstr.h"
516747b715Smrg#include   <X11/fonts/fontstruct.h>
526747b715Smrg#include   "inputstr.h"
536747b715Smrg#include   "damage.h"
546747b715Smrg
556747b715Smrgtypedef struct {
5635c4bbdfSmrg    CursorPtr pCursor;
5735c4bbdfSmrg    int x;                      /* cursor hotspot */
5835c4bbdfSmrg    int y;
5935c4bbdfSmrg    BoxRec saved;               /* saved area from the screen */
6035c4bbdfSmrg    Bool isUp;                  /* cursor in frame buffer */
6135c4bbdfSmrg    Bool shouldBeUp;            /* cursor should be displayed */
6235c4bbdfSmrg    WindowPtr pCacheWin;        /* window the cursor last seen in */
6335c4bbdfSmrg    Bool isInCacheWin;
6435c4bbdfSmrg    Bool checkPixels;           /* check colormap collision */
6535c4bbdfSmrg    ScreenPtr pScreen;
666747b715Smrg} miCursorInfoRec, *miCursorInfoPtr;
676747b715Smrg
686747b715Smrg/*
696747b715Smrg * per screen information
706747b715Smrg */
716747b715Smrg
726747b715Smrgtypedef struct {
736747b715Smrg    /* screen procedures */
7435c4bbdfSmrg    CloseScreenProcPtr CloseScreen;
7535c4bbdfSmrg    GetImageProcPtr GetImage;
7635c4bbdfSmrg    GetSpansProcPtr GetSpans;
7735c4bbdfSmrg    SourceValidateProcPtr SourceValidate;
7835c4bbdfSmrg
796747b715Smrg    /* window procedures */
8035c4bbdfSmrg    CopyWindowProcPtr CopyWindow;
8135c4bbdfSmrg
826747b715Smrg    /* colormap procedures */
8335c4bbdfSmrg    InstallColormapProcPtr InstallColormap;
8435c4bbdfSmrg    StoreColorsProcPtr StoreColors;
8535c4bbdfSmrg
866747b715Smrg    /* os layer procedures */
8735c4bbdfSmrg    ScreenBlockHandlerProcPtr BlockHandler;
8835c4bbdfSmrg
8935c4bbdfSmrg    xColorItem colors[2];
9035c4bbdfSmrg    ColormapPtr pInstalledMap;
9135c4bbdfSmrg    ColormapPtr pColormap;
9235c4bbdfSmrg    VisualPtr pVisual;
9335c4bbdfSmrg    DamagePtr pDamage;          /* damage tracking structure */
9435c4bbdfSmrg    Bool damageRegistered;
9535c4bbdfSmrg    int numberOfCursors;
966747b715Smrg} miSpriteScreenRec, *miSpriteScreenPtr;
976747b715Smrg
986747b715Smrg#define SOURCE_COLOR	0
996747b715Smrg#define MASK_COLOR	1
1006747b715Smrg
1016747b715Smrg/*
1026747b715Smrg * Overlap BoxPtr and Box elements
1036747b715Smrg */
1046747b715Smrg#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
1056747b715Smrg 	(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
1066747b715Smrg	 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
1076747b715Smrg
1086747b715Smrg/*
1096747b715Smrg * Overlap BoxPtr, origins, and rectangle
1106747b715Smrg */
1116747b715Smrg#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
1126747b715Smrg    BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
1136747b715Smrg
1146747b715Smrg/*
1156747b715Smrg * Overlap BoxPtr, origins and RectPtr
1166747b715Smrg */
1176747b715Smrg#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
1186747b715Smrg    ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
1196747b715Smrg		(int)((pRect)->width), (int)((pRect)->height))
1206747b715Smrg/*
1216747b715Smrg * Overlap BoxPtr and horizontal span
1226747b715Smrg */
1236747b715Smrg#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
12405b261ecSmrg
1256747b715Smrg#define LINE_SORT(x1,y1,x2,y2) \
1266747b715Smrg{ int _t; \
1276747b715Smrg  if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
1286747b715Smrg  if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
1296747b715Smrg
1306747b715Smrg#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
1316747b715Smrg    BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
1324642e01fSmrg
13305b261ecSmrg#define SPRITE_DEBUG_ENABLE 0
13405b261ecSmrg#if SPRITE_DEBUG_ENABLE
13505b261ecSmrg#define SPRITE_DEBUG(x)	ErrorF x
13605b261ecSmrg#else
13705b261ecSmrg#define SPRITE_DEBUG(x)
13805b261ecSmrg#endif
13905b261ecSmrg
1404642e01fSmrg#define MISPRITE(dev) \
14135c4bbdfSmrg    (IsFloating(dev) ? \
1424642e01fSmrg       (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
1436747b715Smrg       (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
1444642e01fSmrg
1454642e01fSmrgstatic void
1464642e01fSmrgmiSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1474642e01fSmrg{
1486747b715Smrg    if (pScreenPriv->damageRegistered) {
14935c4bbdfSmrg        DamageUnregister(pScreenPriv->pDamage);
15035c4bbdfSmrg        pScreenPriv->damageRegistered = 0;
1514642e01fSmrg    }
1524642e01fSmrg}
1534642e01fSmrg
1544642e01fSmrgstatic void
1554642e01fSmrgmiSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1564642e01fSmrg{
1576747b715Smrg    if (!pScreenPriv->damageRegistered) {
15835c4bbdfSmrg        pScreenPriv->damageRegistered = 1;
15935c4bbdfSmrg        DamageRegister(&(pScreen->GetScreenPixmap(pScreen)->drawable),
16035c4bbdfSmrg                       pScreenPriv->pDamage);
1614642e01fSmrg    }
1624642e01fSmrg}
1634642e01fSmrg
1644642e01fSmrgstatic void
1654642e01fSmrgmiSpriteIsUp(miCursorInfoPtr pDevCursor)
1664642e01fSmrg{
1674642e01fSmrg    pDevCursor->isUp = TRUE;
1684642e01fSmrg}
1694642e01fSmrg
1704642e01fSmrgstatic void
1714642e01fSmrgmiSpriteIsDown(miCursorInfoPtr pDevCursor)
1724642e01fSmrg{
1734642e01fSmrg    pDevCursor->isUp = FALSE;
1744642e01fSmrg}
1754642e01fSmrg
17605b261ecSmrg/*
17705b261ecSmrg * screen wrappers
17805b261ecSmrg */
17905b261ecSmrg
1806747b715Smrgstatic DevPrivateKeyRec miSpriteScreenKeyRec;
18135c4bbdfSmrg
1826747b715Smrg#define miSpriteScreenKey (&miSpriteScreenKeyRec)
1839ace9065Smrg#define GetSpriteScreen(pScreen) \
1849ace9065Smrg	(dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey))
1856747b715Smrgstatic DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
18635c4bbdfSmrg
1876747b715Smrg#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
18805b261ecSmrg
18935c4bbdfSmrgstatic Bool miSpriteCloseScreen(ScreenPtr pScreen);
19035c4bbdfSmrgstatic void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
19135c4bbdfSmrg                             int w, int h, unsigned int format,
19235c4bbdfSmrg                             unsigned long planemask, char *pdstLine);
19335c4bbdfSmrgstatic void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
19435c4bbdfSmrg                             DDXPointPtr ppt, int *pwidth, int nspans,
19535c4bbdfSmrg                             char *pdstStart);
19635c4bbdfSmrgstatic void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
19735c4bbdfSmrg                                   int width, int height,
19835c4bbdfSmrg                                   unsigned int subWindowMode);
19935c4bbdfSmrgstatic void miSpriteCopyWindow(WindowPtr pWindow,
20035c4bbdfSmrg                               DDXPointRec ptOldOrg, RegionPtr prgnSrc);
20135c4bbdfSmrgstatic void miSpriteBlockHandler(ScreenPtr pScreen,
20235c4bbdfSmrg                                 void *pTimeout, void *pReadMask);
20335c4bbdfSmrgstatic void miSpriteInstallColormap(ColormapPtr pMap);
20435c4bbdfSmrgstatic void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef);
20535c4bbdfSmrg
20635c4bbdfSmrgstatic void miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen);
20735c4bbdfSmrg
20835c4bbdfSmrgstatic Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
20935c4bbdfSmrg                                           ScreenPtr pScreen);
21035c4bbdfSmrgstatic void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
21105b261ecSmrg
2129ace9065Smrg#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
2139ace9065Smrg   (pPriv)->field)
2149ace9065Smrg#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
2159ace9065Smrg    ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
21605b261ecSmrg
21705b261ecSmrg/*
21805b261ecSmrg * pointer-sprite method table
21905b261ecSmrg */
22005b261ecSmrg
2214642e01fSmrgstatic Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2224642e01fSmrg                                  CursorPtr pCursor);
2234642e01fSmrgstatic Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2244642e01fSmrg                                    CursorPtr pCursor);
2254642e01fSmrgstatic void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2264642e01fSmrg                              CursorPtr pCursor, int x, int y);
2274642e01fSmrgstatic void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2284642e01fSmrg                               int x, int y);
22905b261ecSmrg
2306747b715SmrgmiPointerSpriteFuncRec miSpritePointerFuncs = {
23105b261ecSmrg    miSpriteRealizeCursor,
23205b261ecSmrg    miSpriteUnrealizeCursor,
23305b261ecSmrg    miSpriteSetCursor,
23405b261ecSmrg    miSpriteMoveCursor,
2354642e01fSmrg    miSpriteDeviceCursorInitialize,
2364642e01fSmrg    miSpriteDeviceCursorCleanup,
23705b261ecSmrg};
23805b261ecSmrg
23905b261ecSmrg/*
24005b261ecSmrg * other misc functions
24105b261ecSmrg */
24205b261ecSmrg
24335c4bbdfSmrgstatic void miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
24435c4bbdfSmrgstatic void miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
24535c4bbdfSmrgstatic void miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
24605b261ecSmrg
2479ace9065Smrgstatic void
2489ace9065SmrgmiSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
2499ace9065Smrg{
2509ace9065Smrg    if (!pScreenPriv->BlockHandler) {
2519ace9065Smrg        pScreenPriv->BlockHandler = pScreen->BlockHandler;
2529ace9065Smrg        pScreen->BlockHandler = miSpriteBlockHandler;
2539ace9065Smrg    }
2549ace9065Smrg}
2559ace9065Smrg
25605b261ecSmrgstatic void
25735c4bbdfSmrgmiSpriteReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
25805b261ecSmrg{
25935c4bbdfSmrg    ScreenPtr pScreen = closure;
26035c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
26135c4bbdfSmrg    DeviceIntPtr pDev;
26235c4bbdfSmrg
26335c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
26435c4bbdfSmrg        if (DevHasCursor(pDev)) {
2654642e01fSmrg            pCursorInfo = MISPRITE(pDev);
2664642e01fSmrg
2674642e01fSmrg            if (pCursorInfo->isUp &&
2684642e01fSmrg                pCursorInfo->pScreen == pScreen &&
26935c4bbdfSmrg                RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) {
2704642e01fSmrg                SPRITE_DEBUG(("Damage remove\n"));
27135c4bbdfSmrg                miSpriteRemoveCursor(pDev, pScreen);
2724642e01fSmrg            }
2734642e01fSmrg        }
27405b261ecSmrg    }
27505b261ecSmrg}
27605b261ecSmrg
27705b261ecSmrg/*
27805b261ecSmrg * miSpriteInitialize -- called from device-dependent screen
27905b261ecSmrg * initialization proc after all of the function pointers have
28005b261ecSmrg * been stored in the screen structure.
28105b261ecSmrg */
28205b261ecSmrg
28305b261ecSmrgBool
28435c4bbdfSmrgmiSpriteInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
28505b261ecSmrg{
28635c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
28735c4bbdfSmrg    VisualPtr pVisual;
2884642e01fSmrg
28935c4bbdfSmrg    if (!DamageSetup(pScreen))
29035c4bbdfSmrg        return FALSE;
29105b261ecSmrg
2926747b715Smrg    if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
29335c4bbdfSmrg        return FALSE;
2946747b715Smrg
29535c4bbdfSmrg    if (!dixRegisterPrivateKey
29635c4bbdfSmrg        (&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec)))
29735c4bbdfSmrg        return FALSE;
2986747b715Smrg
29935c4bbdfSmrg    pScreenPriv = malloc(sizeof(miSpriteScreenRec));
30005b261ecSmrg    if (!pScreenPriv)
30135c4bbdfSmrg        return FALSE;
30235c4bbdfSmrg
30335c4bbdfSmrg    pScreenPriv->pDamage = DamageCreate(miSpriteReportDamage,
30435c4bbdfSmrg                                        NULL,
30535c4bbdfSmrg                                        DamageReportRawRegion,
30635c4bbdfSmrg                                        TRUE, pScreen, pScreen);
30735c4bbdfSmrg
30835c4bbdfSmrg    if (!miPointerInitialize(pScreen, &miSpritePointerFuncs, screenFuncs, TRUE)) {
30935c4bbdfSmrg        free(pScreenPriv);
31035c4bbdfSmrg        return FALSE;
31105b261ecSmrg    }
31205b261ecSmrg    for (pVisual = pScreen->visuals;
31335c4bbdfSmrg         pVisual->vid != pScreen->rootVisual; pVisual++);
31405b261ecSmrg    pScreenPriv->pVisual = pVisual;
31505b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
31605b261ecSmrg    pScreenPriv->GetImage = pScreen->GetImage;
31705b261ecSmrg    pScreenPriv->GetSpans = pScreen->GetSpans;
31805b261ecSmrg    pScreenPriv->SourceValidate = pScreen->SourceValidate;
31905b261ecSmrg
32005b261ecSmrg    pScreenPriv->CopyWindow = pScreen->CopyWindow;
3214642e01fSmrg
32205b261ecSmrg    pScreenPriv->InstallColormap = pScreen->InstallColormap;
32305b261ecSmrg    pScreenPriv->StoreColors = pScreen->StoreColors;
3244642e01fSmrg
3259ace9065Smrg    pScreenPriv->BlockHandler = NULL;
3264642e01fSmrg
32705b261ecSmrg    pScreenPriv->pInstalledMap = NULL;
32805b261ecSmrg    pScreenPriv->pColormap = NULL;
32905b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].red = 0;
33005b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].green = 0;
33105b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
33205b261ecSmrg    pScreenPriv->colors[MASK_COLOR].red = 0;
33305b261ecSmrg    pScreenPriv->colors[MASK_COLOR].green = 0;
33405b261ecSmrg    pScreenPriv->colors[MASK_COLOR].blue = 0;
3356747b715Smrg    pScreenPriv->damageRegistered = 0;
3369ace9065Smrg    pScreenPriv->numberOfCursors = 0;
3376747b715Smrg
3384642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
3394642e01fSmrg
34005b261ecSmrg    pScreen->CloseScreen = miSpriteCloseScreen;
34105b261ecSmrg    pScreen->GetImage = miSpriteGetImage;
34205b261ecSmrg    pScreen->GetSpans = miSpriteGetSpans;
34305b261ecSmrg    pScreen->SourceValidate = miSpriteSourceValidate;
3444642e01fSmrg
34505b261ecSmrg    pScreen->CopyWindow = miSpriteCopyWindow;
34605b261ecSmrg    pScreen->InstallColormap = miSpriteInstallColormap;
34705b261ecSmrg    pScreen->StoreColors = miSpriteStoreColors;
34805b261ecSmrg
34905b261ecSmrg    return TRUE;
35005b261ecSmrg}
35105b261ecSmrg
35205b261ecSmrg/*
35305b261ecSmrg * Screen wrappers
35405b261ecSmrg */
35505b261ecSmrg
35605b261ecSmrg/*
35705b261ecSmrg * CloseScreen wrapper -- unwrap everything, free the private data
35805b261ecSmrg * and call the wrapped function
35905b261ecSmrg */
36005b261ecSmrg
36105b261ecSmrgstatic Bool
36235c4bbdfSmrgmiSpriteCloseScreen(ScreenPtr pScreen)
36305b261ecSmrg{
36435c4bbdfSmrg    miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
36505b261ecSmrg
36605b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
36705b261ecSmrg    pScreen->GetImage = pScreenPriv->GetImage;
36805b261ecSmrg    pScreen->GetSpans = pScreenPriv->GetSpans;
36905b261ecSmrg    pScreen->SourceValidate = pScreenPriv->SourceValidate;
37005b261ecSmrg    pScreen->InstallColormap = pScreenPriv->InstallColormap;
37105b261ecSmrg    pScreen->StoreColors = pScreenPriv->StoreColors;
37205b261ecSmrg
37335c4bbdfSmrg    DamageDestroy(pScreenPriv->pDamage);
3744642e01fSmrg
3756747b715Smrg    free(pScreenPriv);
37605b261ecSmrg
37735c4bbdfSmrg    return (*pScreen->CloseScreen) (pScreen);
37805b261ecSmrg}
37905b261ecSmrg
38005b261ecSmrgstatic void
38135c4bbdfSmrgmiSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
38235c4bbdfSmrg                 unsigned int format, unsigned long planemask, char *pdstLine)
38305b261ecSmrg{
38435c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
38535c4bbdfSmrg    DeviceIntPtr pDev;
38635c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
38735c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
38835c4bbdfSmrg
38935c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, GetImage);
39035c4bbdfSmrg
39135c4bbdfSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
39235c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
39335c4bbdfSmrg            if (DevHasCursor(pDev)) {
39435c4bbdfSmrg                pCursorInfo = MISPRITE(pDev);
39535c4bbdfSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
39635c4bbdfSmrg                    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
39735c4bbdfSmrg                                sx, sy, w, h)) {
39835c4bbdfSmrg                    SPRITE_DEBUG(("GetImage remove\n"));
39935c4bbdfSmrg                    miSpriteRemoveCursor(pDev, pScreen);
40035c4bbdfSmrg                }
4016747b715Smrg            }
4024642e01fSmrg        }
40305b261ecSmrg    }
40405b261ecSmrg
40535c4bbdfSmrg    (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine);
40605b261ecSmrg
40735c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, GetImage);
40805b261ecSmrg}
40905b261ecSmrg
41005b261ecSmrgstatic void
41135c4bbdfSmrgmiSpriteGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
41235c4bbdfSmrg                 int *pwidth, int nspans, char *pdstStart)
41305b261ecSmrg{
41435c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
41535c4bbdfSmrg    DeviceIntPtr pDev;
41635c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
41735c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
41835c4bbdfSmrg
41935c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, GetSpans);
42035c4bbdfSmrg
42135c4bbdfSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
42235c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
42335c4bbdfSmrg            if (DevHasCursor(pDev)) {
4246747b715Smrg                pCursorInfo = MISPRITE(pDev);
4256747b715Smrg
42635c4bbdfSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) {
42735c4bbdfSmrg                    DDXPointPtr pts;
42835c4bbdfSmrg                    int *widths;
42935c4bbdfSmrg                    int nPts;
43035c4bbdfSmrg                    int xorg, yorg;
4316747b715Smrg
4326747b715Smrg                    xorg = pDrawable->x;
4336747b715Smrg                    yorg = pDrawable->y;
4346747b715Smrg
4356747b715Smrg                    for (pts = ppt, widths = pwidth, nPts = nspans;
43635c4bbdfSmrg                         nPts--; pts++, widths++) {
43735c4bbdfSmrg                        if (SPN_OVERLAP(&pCursorInfo->saved, pts->y + yorg,
43835c4bbdfSmrg                                        pts->x + xorg, *widths)) {
43935c4bbdfSmrg                            SPRITE_DEBUG(("GetSpans remove\n"));
44035c4bbdfSmrg                            miSpriteRemoveCursor(pDev, pScreen);
4416747b715Smrg                            break;
4426747b715Smrg                        }
4434642e01fSmrg                    }
4444642e01fSmrg                }
4454642e01fSmrg            }
4464642e01fSmrg        }
44705b261ecSmrg    }
44805b261ecSmrg
44905b261ecSmrg    (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
45005b261ecSmrg
45135c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, GetSpans);
45205b261ecSmrg}
45305b261ecSmrg
45405b261ecSmrgstatic void
45535c4bbdfSmrgmiSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, int width,
45635c4bbdfSmrg                       int height, unsigned int subWindowMode)
45705b261ecSmrg{
45835c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
45935c4bbdfSmrg    DeviceIntPtr pDev;
46035c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
46135c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
46235c4bbdfSmrg
46335c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, SourceValidate);
46435c4bbdfSmrg
46535c4bbdfSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
46635c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
46735c4bbdfSmrg            if (DevHasCursor(pDev)) {
46835c4bbdfSmrg                pCursorInfo = MISPRITE(pDev);
46935c4bbdfSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
47035c4bbdfSmrg                    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
47135c4bbdfSmrg                                x, y, width, height)) {
47235c4bbdfSmrg                    SPRITE_DEBUG(("SourceValidate remove\n"));
47335c4bbdfSmrg                    miSpriteRemoveCursor(pDev, pScreen);
47435c4bbdfSmrg                }
47535c4bbdfSmrg            }
47635c4bbdfSmrg        }
47705b261ecSmrg    }
47805b261ecSmrg
47905b261ecSmrg    if (pScreen->SourceValidate)
48035c4bbdfSmrg        (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
48135c4bbdfSmrg                                    subWindowMode);
48205b261ecSmrg
48335c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, SourceValidate);
48405b261ecSmrg}
48505b261ecSmrg
48605b261ecSmrgstatic void
48735c4bbdfSmrgmiSpriteCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
48805b261ecSmrg{
48935c4bbdfSmrg    ScreenPtr pScreen = pWindow->drawable.pScreen;
49035c4bbdfSmrg    DeviceIntPtr pDev;
49135c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
49235c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
4934642e01fSmrg
49435c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, CopyWindow);
49505b261ecSmrg
49635c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
49735c4bbdfSmrg        if (DevHasCursor(pDev)) {
4984642e01fSmrg            pCursorInfo = MISPRITE(pDev);
4994642e01fSmrg            /*
5004642e01fSmrg             * Damage will take care of destination check
5014642e01fSmrg             */
5024642e01fSmrg            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
50335c4bbdfSmrg                RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) {
50435c4bbdfSmrg                SPRITE_DEBUG(("CopyWindow remove\n"));
50535c4bbdfSmrg                miSpriteRemoveCursor(pDev, pScreen);
5064642e01fSmrg            }
5074642e01fSmrg        }
50805b261ecSmrg    }
50905b261ecSmrg
51005b261ecSmrg    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
51135c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, CopyWindow);
51205b261ecSmrg}
51305b261ecSmrg
51405b261ecSmrgstatic void
51535c4bbdfSmrgmiSpriteBlockHandler(ScreenPtr pScreen, void *pTimeout,
51635c4bbdfSmrg                     void *pReadmask)
51705b261ecSmrg{
51835c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
51935c4bbdfSmrg    DeviceIntPtr pDev;
52035c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
52135c4bbdfSmrg    Bool WorkToDo = FALSE;
52235c4bbdfSmrg
52335c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
52435c4bbdfSmrg
52535c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
52635c4bbdfSmrg        if (DevHasCursor(pDev)) {
5274642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5284642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp
52935c4bbdfSmrg                && pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
53035c4bbdfSmrg                SPRITE_DEBUG(("BlockHandler save"));
53135c4bbdfSmrg                miSpriteSaveUnderCursor(pDev, pScreen);
5324642e01fSmrg            }
5334642e01fSmrg        }
5344642e01fSmrg    }
53535c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
53635c4bbdfSmrg        if (DevHasCursor(pDev)) {
5374642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5384642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp &&
53935c4bbdfSmrg                pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
54035c4bbdfSmrg                SPRITE_DEBUG(("BlockHandler restore\n"));
54135c4bbdfSmrg                miSpriteRestoreCursor(pDev, pScreen);
5429ace9065Smrg                if (!pCursorInfo->isUp)
5439ace9065Smrg                    WorkToDo = TRUE;
5444642e01fSmrg            }
5454642e01fSmrg        }
54605b261ecSmrg    }
5479ace9065Smrg
54835c4bbdfSmrg    (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
5499ace9065Smrg
5509ace9065Smrg    if (WorkToDo)
5519ace9065Smrg        SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
5529ace9065Smrg    else
5539ace9065Smrg        pPriv->BlockHandler = NULL;
55405b261ecSmrg}
55505b261ecSmrg
55605b261ecSmrgstatic void
55735c4bbdfSmrgmiSpriteInstallColormap(ColormapPtr pMap)
55805b261ecSmrg{
55935c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
56035c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
56105b261ecSmrg
5629ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
5634642e01fSmrg
56405b261ecSmrg    (*pScreen->InstallColormap) (pMap);
56505b261ecSmrg
5669ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
56705b261ecSmrg
5684642e01fSmrg    /* InstallColormap can be called before devices are initialized. */
56905b261ecSmrg    pPriv->pInstalledMap = pMap;
57035c4bbdfSmrg    if (pPriv->pColormap != pMap) {
5714642e01fSmrg        DeviceIntPtr pDev;
57235c4bbdfSmrg        miCursorInfoPtr pCursorInfo;
57335c4bbdfSmrg
57435c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
57535c4bbdfSmrg            if (DevHasCursor(pDev)) {
5764642e01fSmrg                pCursorInfo = MISPRITE(pDev);
5774642e01fSmrg                pCursorInfo->checkPixels = TRUE;
5784642e01fSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
5794642e01fSmrg                    miSpriteRemoveCursor(pDev, pScreen);
5804642e01fSmrg            }
5814642e01fSmrg        }
5824642e01fSmrg
58305b261ecSmrg    }
58405b261ecSmrg}
58505b261ecSmrg
58605b261ecSmrgstatic void
58735c4bbdfSmrgmiSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef)
58805b261ecSmrg{
58935c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
59035c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
59135c4bbdfSmrg    int i;
59235c4bbdfSmrg    int updated;
59335c4bbdfSmrg    VisualPtr pVisual;
59435c4bbdfSmrg    DeviceIntPtr pDev;
59535c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
59605b261ecSmrg
5979ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
5984642e01fSmrg
59905b261ecSmrg    (*pScreen->StoreColors) (pMap, ndef, pdef);
60005b261ecSmrg
6019ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
60205b261ecSmrg
60335c4bbdfSmrg    if (pPriv->pColormap == pMap) {
6044642e01fSmrg        updated = 0;
6054642e01fSmrg        pVisual = pMap->pVisual;
60635c4bbdfSmrg        if (pVisual->class == DirectColor) {
6074642e01fSmrg            /* Direct color - match on any of the subfields */
60805b261ecSmrg
60905b261ecSmrg#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
61005b261ecSmrg
6114642e01fSmrg#define UpdateDAC(dev, plane,dac,mask) {\
6124642e01fSmrg    if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
6134642e01fSmrg	dev->colors[plane].dac = pdef[i].dac; \
61405b261ecSmrg	updated = 1; \
61505b261ecSmrg    } \
61605b261ecSmrg}
61705b261ecSmrg
6184642e01fSmrg#define CheckDirect(dev, plane) \
6194642e01fSmrg	    UpdateDAC(dev, plane,red,redMask) \
6204642e01fSmrg	    UpdateDAC(dev, plane,green,greenMask) \
6214642e01fSmrg	    UpdateDAC(dev, plane,blue,blueMask)
6224642e01fSmrg
62335c4bbdfSmrg            for (i = 0; i < ndef; i++) {
62435c4bbdfSmrg                CheckDirect(pPriv, SOURCE_COLOR)
62535c4bbdfSmrg                    CheckDirect(pPriv, MASK_COLOR)
6264642e01fSmrg            }
6274642e01fSmrg        }
62835c4bbdfSmrg        else {
6294642e01fSmrg            /* PseudoColor/GrayScale - match on exact pixel */
63035c4bbdfSmrg            for (i = 0; i < ndef; i++) {
63135c4bbdfSmrg                if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) {
6324642e01fSmrg                    pPriv->colors[SOURCE_COLOR] = pdef[i];
6334642e01fSmrg                    if (++updated == 2)
6344642e01fSmrg                        break;
6354642e01fSmrg                }
63635c4bbdfSmrg                if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) {
6374642e01fSmrg                    pPriv->colors[MASK_COLOR] = pdef[i];
6384642e01fSmrg                    if (++updated == 2)
6394642e01fSmrg                        break;
6404642e01fSmrg                }
6414642e01fSmrg            }
6424642e01fSmrg        }
64335c4bbdfSmrg        if (updated) {
64435c4bbdfSmrg            for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
64535c4bbdfSmrg                if (DevHasCursor(pDev)) {
6464642e01fSmrg                    pCursorInfo = MISPRITE(pDev);
6474642e01fSmrg                    pCursorInfo->checkPixels = TRUE;
6484642e01fSmrg                    if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
64935c4bbdfSmrg                        miSpriteRemoveCursor(pDev, pScreen);
6504642e01fSmrg                }
6514642e01fSmrg            }
6524642e01fSmrg        }
65305b261ecSmrg    }
65405b261ecSmrg}
65505b261ecSmrg
65605b261ecSmrgstatic void
65735c4bbdfSmrgmiSpriteFindColors(miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
65805b261ecSmrg{
65935c4bbdfSmrg    miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
66035c4bbdfSmrg    CursorPtr pCursor;
66135c4bbdfSmrg    xColorItem *sourceColor, *maskColor;
66205b261ecSmrg
6634642e01fSmrg    pCursor = pDevCursor->pCursor;
66405b261ecSmrg    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
66505b261ecSmrg    maskColor = &pScreenPriv->colors[MASK_COLOR];
66605b261ecSmrg    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
66735c4bbdfSmrg        !(pCursor->foreRed == sourceColor->red &&
66835c4bbdfSmrg          pCursor->foreGreen == sourceColor->green &&
66905b261ecSmrg          pCursor->foreBlue == sourceColor->blue &&
67035c4bbdfSmrg          pCursor->backRed == maskColor->red &&
67135c4bbdfSmrg          pCursor->backGreen == maskColor->green &&
67235c4bbdfSmrg          pCursor->backBlue == maskColor->blue)) {
67335c4bbdfSmrg        pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
67435c4bbdfSmrg        sourceColor->red = pCursor->foreRed;
67535c4bbdfSmrg        sourceColor->green = pCursor->foreGreen;
67635c4bbdfSmrg        sourceColor->blue = pCursor->foreBlue;
67735c4bbdfSmrg        FakeAllocColor(pScreenPriv->pColormap, sourceColor);
67835c4bbdfSmrg        maskColor->red = pCursor->backRed;
67935c4bbdfSmrg        maskColor->green = pCursor->backGreen;
68035c4bbdfSmrg        maskColor->blue = pCursor->backBlue;
68135c4bbdfSmrg        FakeAllocColor(pScreenPriv->pColormap, maskColor);
68235c4bbdfSmrg        /* "free" the pixels right away, don't let this confuse you */
68335c4bbdfSmrg        FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
68435c4bbdfSmrg        FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
68505b261ecSmrg    }
68605b261ecSmrg
6874642e01fSmrg    pDevCursor->checkPixels = FALSE;
68805b261ecSmrg
68905b261ecSmrg}
69005b261ecSmrg
69105b261ecSmrg/*
69205b261ecSmrg * miPointer interface routines
69305b261ecSmrg */
69405b261ecSmrg
69505b261ecSmrg#define SPRITE_PAD  8
69605b261ecSmrg
69705b261ecSmrgstatic Bool
69835c4bbdfSmrgmiSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
69905b261ecSmrg{
7004642e01fSmrg    miCursorInfoPtr pCursorInfo;
7014642e01fSmrg
70235c4bbdfSmrg    if (IsFloating(pDev))
7034642e01fSmrg        return FALSE;
7046747b715Smrg
7054642e01fSmrg    pCursorInfo = MISPRITE(pDev);
7064642e01fSmrg
7074642e01fSmrg    if (pCursor == pCursorInfo->pCursor)
70835c4bbdfSmrg        pCursorInfo->checkPixels = TRUE;
70905b261ecSmrg
7106747b715Smrg    return miDCRealizeCursor(pScreen, pCursor);
71105b261ecSmrg}
71205b261ecSmrg
71305b261ecSmrgstatic Bool
7144642e01fSmrgmiSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
71505b261ecSmrg{
7166747b715Smrg    return miDCUnrealizeCursor(pScreen, pCursor);
71705b261ecSmrg}
71805b261ecSmrg
71905b261ecSmrgstatic void
72035c4bbdfSmrgmiSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
72135c4bbdfSmrg                  CursorPtr pCursor, int x, int y)
72205b261ecSmrg{
72335c4bbdfSmrg    miCursorInfoPtr pPointer;
72435c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
7254642e01fSmrg
72635c4bbdfSmrg    if (IsFloating(pDev))
7274642e01fSmrg        return;
7286747b715Smrg
7294642e01fSmrg    pPointer = MISPRITE(pDev);
7309ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
7314642e01fSmrg
73235c4bbdfSmrg    if (!pCursor) {
73335c4bbdfSmrg        if (pPointer->shouldBeUp)
73435c4bbdfSmrg            --pScreenPriv->numberOfCursors;
73535c4bbdfSmrg        pPointer->shouldBeUp = FALSE;
73635c4bbdfSmrg        if (pPointer->isUp)
73735c4bbdfSmrg            miSpriteRemoveCursor(pDev, pScreen);
73835c4bbdfSmrg        if (pScreenPriv->numberOfCursors == 0)
73935c4bbdfSmrg            miSpriteDisableDamage(pScreen, pScreenPriv);
74035c4bbdfSmrg        pPointer->pCursor = 0;
74135c4bbdfSmrg        return;
74205b261ecSmrg    }
7439ace9065Smrg    if (!pPointer->shouldBeUp)
74435c4bbdfSmrg        pScreenPriv->numberOfCursors++;
7454642e01fSmrg    pPointer->shouldBeUp = TRUE;
7469ace9065Smrg    if (!pPointer->isUp)
74735c4bbdfSmrg        miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
7484642e01fSmrg    if (pPointer->x == x &&
74935c4bbdfSmrg        pPointer->y == y &&
75035c4bbdfSmrg        pPointer->pCursor == pCursor && !pPointer->checkPixels) {
75135c4bbdfSmrg        return;
75205b261ecSmrg    }
7534642e01fSmrg    pPointer->x = x;
7544642e01fSmrg    pPointer->y = y;
7554642e01fSmrg    pPointer->pCacheWin = NullWindow;
75635c4bbdfSmrg    if (pPointer->checkPixels || pPointer->pCursor != pCursor) {
75735c4bbdfSmrg        pPointer->pCursor = pCursor;
75835c4bbdfSmrg        miSpriteFindColors(pPointer, pScreen);
75905b261ecSmrg    }
7604642e01fSmrg    if (pPointer->isUp) {
76135c4bbdfSmrg        /* TODO: reimplement flicker-free MoveCursor */
76235c4bbdfSmrg        SPRITE_DEBUG(("SetCursor remove %d\n", pDev->id));
76335c4bbdfSmrg        miSpriteRemoveCursor(pDev, pScreen);
76405b261ecSmrg    }
7654642e01fSmrg
76635c4bbdfSmrg    if (!pPointer->isUp && pPointer->pCursor) {
76735c4bbdfSmrg        SPRITE_DEBUG(("SetCursor restore %d\n", pDev->id));
7684642e01fSmrg        miSpriteSaveUnderCursor(pDev, pScreen);
76935c4bbdfSmrg        miSpriteRestoreCursor(pDev, pScreen);
77005b261ecSmrg    }
7714642e01fSmrg
77205b261ecSmrg}
77305b261ecSmrg
77405b261ecSmrgstatic void
77535c4bbdfSmrgmiSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
77605b261ecSmrg{
7774642e01fSmrg    CursorPtr pCursor;
77805b261ecSmrg
77935c4bbdfSmrg    if (IsFloating(pDev))
7804642e01fSmrg        return;
7816747b715Smrg
7824642e01fSmrg    pCursor = MISPRITE(pDev)->pCursor;
7834642e01fSmrg
78435c4bbdfSmrg    miSpriteSetCursor(pDev, pScreen, pCursor, x, y);
7854642e01fSmrg}
7864642e01fSmrg
7874642e01fSmrgstatic Bool
7884642e01fSmrgmiSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
7894642e01fSmrg{
79035c4bbdfSmrg    int ret = miDCDeviceInitialize(pDev, pScreen);
79135c4bbdfSmrg
79235c4bbdfSmrg    if (ret) {
79335c4bbdfSmrg        miCursorInfoPtr pCursorInfo;
79435c4bbdfSmrg
79535c4bbdfSmrg        pCursorInfo =
79635c4bbdfSmrg            dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey);
79735c4bbdfSmrg        pCursorInfo->pCursor = NULL;
79835c4bbdfSmrg        pCursorInfo->x = 0;
79935c4bbdfSmrg        pCursorInfo->y = 0;
80035c4bbdfSmrg        pCursorInfo->isUp = FALSE;
80135c4bbdfSmrg        pCursorInfo->shouldBeUp = FALSE;
80235c4bbdfSmrg        pCursorInfo->pCacheWin = NullWindow;
80335c4bbdfSmrg        pCursorInfo->isInCacheWin = FALSE;
80435c4bbdfSmrg        pCursorInfo->checkPixels = TRUE;
80535c4bbdfSmrg        pCursorInfo->pScreen = FALSE;
8064642e01fSmrg    }
80735c4bbdfSmrg
8084642e01fSmrg    return ret;
8094642e01fSmrg}
8104642e01fSmrg
8114642e01fSmrgstatic void
8124642e01fSmrgmiSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
8134642e01fSmrg{
81435c4bbdfSmrg    miCursorInfoPtr pCursorInfo =
81535c4bbdfSmrg        dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey);
81635c4bbdfSmrg
8174642e01fSmrg    if (DevHasCursor(pDev))
8186747b715Smrg        miDCDeviceCleanup(pDev, pScreen);
81935c4bbdfSmrg
82035c4bbdfSmrg    memset(pCursorInfo, 0, sizeof(miCursorInfoRec));
82105b261ecSmrg}
82205b261ecSmrg
82305b261ecSmrg/*
82405b261ecSmrg * undraw/draw cursor
82505b261ecSmrg */
82605b261ecSmrg
82705b261ecSmrgstatic void
82835c4bbdfSmrgmiSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
82905b261ecSmrg{
83035c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
83135c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
83205b261ecSmrg
83335c4bbdfSmrg    if (IsFloating(pDev))
8344642e01fSmrg        return;
8356747b715Smrg
83635c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
8379ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
8384642e01fSmrg    pCursorInfo = MISPRITE(pDev);
8394642e01fSmrg
8404642e01fSmrg    miSpriteIsDown(pCursorInfo);
8419ace9065Smrg    miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
8424642e01fSmrg    pCursorInfo->pCacheWin = NullWindow;
8434642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
8446747b715Smrg    if (!miDCRestoreUnderCursor(pDev,
8456747b715Smrg                                pScreen,
8466747b715Smrg                                pCursorInfo->saved.x1,
8476747b715Smrg                                pCursorInfo->saved.y1,
8486747b715Smrg                                pCursorInfo->saved.x2 -
8496747b715Smrg                                pCursorInfo->saved.x1,
8506747b715Smrg                                pCursorInfo->saved.y2 -
85135c4bbdfSmrg                                pCursorInfo->saved.y1)) {
8526747b715Smrg        miSpriteIsUp(pCursorInfo);
85305b261ecSmrg    }
8544642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
85535c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
85605b261ecSmrg}
85705b261ecSmrg
8584642e01fSmrg/*
8594642e01fSmrg * Called from the block handler, saves area under cursor
8604642e01fSmrg * before waiting for something to do.
8614642e01fSmrg */
8624642e01fSmrg
8634642e01fSmrgstatic void
8644642e01fSmrgmiSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
8654642e01fSmrg{
86635c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
86735c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
8684642e01fSmrg
86935c4bbdfSmrg    if (IsFloating(pDev))
8704642e01fSmrg        return;
8716747b715Smrg
87235c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
8739ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
8744642e01fSmrg    pCursorInfo = MISPRITE(pDev);
8754642e01fSmrg
87635c4bbdfSmrg    miSpriteComputeSaved(pDev, pScreen);
8774642e01fSmrg
8784642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
8794642e01fSmrg
8806747b715Smrg    miDCSaveUnderCursor(pDev,
8816747b715Smrg                        pScreen,
8826747b715Smrg                        pCursorInfo->saved.x1,
8836747b715Smrg                        pCursorInfo->saved.y1,
8846747b715Smrg                        pCursorInfo->saved.x2 -
8856747b715Smrg                        pCursorInfo->saved.x1,
88635c4bbdfSmrg                        pCursorInfo->saved.y2 - pCursorInfo->saved.y1);
8874642e01fSmrg    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
8884642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
88935c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
8904642e01fSmrg}
8914642e01fSmrg
89205b261ecSmrg/*
89305b261ecSmrg * Called from the block handler, restores the cursor
89405b261ecSmrg * before waiting for something to do.
89505b261ecSmrg */
89605b261ecSmrg
89705b261ecSmrgstatic void
89835c4bbdfSmrgmiSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
89905b261ecSmrg{
90035c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
90135c4bbdfSmrg    int x, y;
90235c4bbdfSmrg    CursorPtr pCursor;
90335c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
9044642e01fSmrg
90535c4bbdfSmrg    if (IsFloating(pDev))
9064642e01fSmrg        return;
90705b261ecSmrg
90835c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
9099ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
9104642e01fSmrg    pCursorInfo = MISPRITE(pDev);
9114642e01fSmrg
91235c4bbdfSmrg    miSpriteComputeSaved(pDev, pScreen);
9134642e01fSmrg    pCursor = pCursorInfo->pCursor;
9144642e01fSmrg
91535c4bbdfSmrg    x = pCursorInfo->x - (int) pCursor->bits->xhot;
91635c4bbdfSmrg    y = pCursorInfo->y - (int) pCursor->bits->yhot;
9174642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
9184642e01fSmrg    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
9194642e01fSmrg    if (pCursorInfo->checkPixels)
92035c4bbdfSmrg        miSpriteFindColors(pCursorInfo, pScreen);
9216747b715Smrg    if (miDCPutUpCursor(pDev, pScreen,
92235c4bbdfSmrg                        pCursor, x, y,
92335c4bbdfSmrg                        pScreenPriv->colors[SOURCE_COLOR].pixel,
92435c4bbdfSmrg                        pScreenPriv->colors[MASK_COLOR].pixel)) {
9254642e01fSmrg        miSpriteIsUp(pCursorInfo);
9264642e01fSmrg        pCursorInfo->pScreen = pScreen;
92705b261ecSmrg    }
9284642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
92935c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
93005b261ecSmrg}
93105b261ecSmrg
93205b261ecSmrg/*
93305b261ecSmrg * compute the desired area of the screen to save
93405b261ecSmrg */
93505b261ecSmrg
93605b261ecSmrgstatic void
93735c4bbdfSmrgmiSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen)
93805b261ecSmrg{
93935c4bbdfSmrg    int x, y, w, h;
94035c4bbdfSmrg    int wpad, hpad;
94135c4bbdfSmrg    CursorPtr pCursor;
9424642e01fSmrg    miCursorInfoPtr pCursorInfo;
94305b261ecSmrg
94435c4bbdfSmrg    if (IsFloating(pDev))
9454642e01fSmrg        return;
9466747b715Smrg
9474642e01fSmrg    pCursorInfo = MISPRITE(pDev);
9484642e01fSmrg
9494642e01fSmrg    pCursor = pCursorInfo->pCursor;
95035c4bbdfSmrg    x = pCursorInfo->x - (int) pCursor->bits->xhot;
95135c4bbdfSmrg    y = pCursorInfo->y - (int) pCursor->bits->yhot;
95205b261ecSmrg    w = pCursor->bits->width;
95305b261ecSmrg    h = pCursor->bits->height;
95405b261ecSmrg    wpad = SPRITE_PAD;
95505b261ecSmrg    hpad = SPRITE_PAD;
9564642e01fSmrg    pCursorInfo->saved.x1 = x - wpad;
9574642e01fSmrg    pCursorInfo->saved.y1 = y - hpad;
9584642e01fSmrg    pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
9594642e01fSmrg    pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
96005b261ecSmrg}
961