misprite.c revision 9ace9065
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 {
566747b715Smrg    CursorPtr	    pCursor;
576747b715Smrg    int		    x;			/* cursor hotspot */
586747b715Smrg    int		    y;
596747b715Smrg    BoxRec	    saved;		/* saved area from the screen */
606747b715Smrg    Bool	    isUp;		/* cursor in frame buffer */
616747b715Smrg    Bool	    shouldBeUp;		/* cursor should be displayed */
626747b715Smrg    WindowPtr	    pCacheWin;		/* window the cursor last seen in */
636747b715Smrg    Bool	    isInCacheWin;
646747b715Smrg    Bool	    checkPixels;	/* check colormap collision */
656747b715Smrg    ScreenPtr       pScreen;
666747b715Smrg} miCursorInfoRec, *miCursorInfoPtr;
676747b715Smrg
686747b715Smrg/*
696747b715Smrg * per screen information
706747b715Smrg */
716747b715Smrg
726747b715Smrgtypedef struct {
736747b715Smrg    /* screen procedures */
746747b715Smrg    CloseScreenProcPtr			CloseScreen;
756747b715Smrg    GetImageProcPtr			GetImage;
766747b715Smrg    GetSpansProcPtr			GetSpans;
776747b715Smrg    SourceValidateProcPtr		SourceValidate;
786747b715Smrg
796747b715Smrg    /* window procedures */
806747b715Smrg    CopyWindowProcPtr			CopyWindow;
816747b715Smrg
826747b715Smrg    /* colormap procedures */
836747b715Smrg    InstallColormapProcPtr		InstallColormap;
846747b715Smrg    StoreColorsProcPtr			StoreColors;
856747b715Smrg
866747b715Smrg    /* os layer procedures */
876747b715Smrg    ScreenBlockHandlerProcPtr		BlockHandler;
886747b715Smrg
896747b715Smrg    /* device cursor procedures */
906747b715Smrg    DeviceCursorInitializeProcPtr       DeviceCursorInitialize;
916747b715Smrg    DeviceCursorCleanupProcPtr          DeviceCursorCleanup;
926747b715Smrg
936747b715Smrg    xColorItem	    colors[2];
946747b715Smrg    ColormapPtr     pInstalledMap;
956747b715Smrg    ColormapPtr     pColormap;
966747b715Smrg    VisualPtr	    pVisual;
976747b715Smrg    DamagePtr	    pDamage;		/* damage tracking structure */
986747b715Smrg    Bool            damageRegistered;
999ace9065Smrg    int             numberOfCursors;
1006747b715Smrg} miSpriteScreenRec, *miSpriteScreenPtr;
1016747b715Smrg
1026747b715Smrg#define SOURCE_COLOR	0
1036747b715Smrg#define MASK_COLOR	1
1046747b715Smrg
1056747b715Smrg/*
1066747b715Smrg * Overlap BoxPtr and Box elements
1076747b715Smrg */
1086747b715Smrg#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
1096747b715Smrg 	(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
1106747b715Smrg	 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
1116747b715Smrg
1126747b715Smrg/*
1136747b715Smrg * Overlap BoxPtr, origins, and rectangle
1146747b715Smrg */
1156747b715Smrg#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
1166747b715Smrg    BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
1176747b715Smrg
1186747b715Smrg/*
1196747b715Smrg * Overlap BoxPtr, origins and RectPtr
1206747b715Smrg */
1216747b715Smrg#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
1226747b715Smrg    ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
1236747b715Smrg		(int)((pRect)->width), (int)((pRect)->height))
1246747b715Smrg/*
1256747b715Smrg * Overlap BoxPtr and horizontal span
1266747b715Smrg */
1276747b715Smrg#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
12805b261ecSmrg
1296747b715Smrg#define LINE_SORT(x1,y1,x2,y2) \
1306747b715Smrg{ int _t; \
1316747b715Smrg  if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
1326747b715Smrg  if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
1336747b715Smrg
1346747b715Smrg#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
1356747b715Smrg    BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
1364642e01fSmrg
1374642e01fSmrg
13805b261ecSmrg#define SPRITE_DEBUG_ENABLE 0
13905b261ecSmrg#if SPRITE_DEBUG_ENABLE
14005b261ecSmrg#define SPRITE_DEBUG(x)	ErrorF x
14105b261ecSmrg#else
14205b261ecSmrg#define SPRITE_DEBUG(x)
14305b261ecSmrg#endif
14405b261ecSmrg
1454642e01fSmrg#define MISPRITE(dev) \
1466747b715Smrg    ((!IsMaster(dev) && !dev->u.master) ? \
1474642e01fSmrg       (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
1486747b715Smrg       (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
1494642e01fSmrg
1504642e01fSmrgstatic void
1514642e01fSmrgmiSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1524642e01fSmrg{
1536747b715Smrg    if (pScreenPriv->damageRegistered) {
1544642e01fSmrg	DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
1554642e01fSmrg			  pScreenPriv->pDamage);
1566747b715Smrg	pScreenPriv->damageRegistered = 0;
1574642e01fSmrg    }
1584642e01fSmrg}
1594642e01fSmrg
1604642e01fSmrgstatic void
1614642e01fSmrgmiSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1624642e01fSmrg{
1636747b715Smrg    if (!pScreenPriv->damageRegistered) {
1646747b715Smrg	pScreenPriv->damageRegistered = 1;
1654642e01fSmrg	DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
1664642e01fSmrg			pScreenPriv->pDamage);
1674642e01fSmrg    }
1684642e01fSmrg}
1694642e01fSmrg
1704642e01fSmrgstatic void
1714642e01fSmrgmiSpriteIsUp(miCursorInfoPtr pDevCursor)
1724642e01fSmrg{
1734642e01fSmrg    pDevCursor->isUp = TRUE;
1744642e01fSmrg}
1754642e01fSmrg
1764642e01fSmrgstatic void
1774642e01fSmrgmiSpriteIsDown(miCursorInfoPtr pDevCursor)
1784642e01fSmrg{
1794642e01fSmrg    pDevCursor->isUp = FALSE;
1804642e01fSmrg}
1814642e01fSmrg
18205b261ecSmrg/*
18305b261ecSmrg * screen wrappers
18405b261ecSmrg */
18505b261ecSmrg
1866747b715Smrgstatic DevPrivateKeyRec miSpriteScreenKeyRec;
1876747b715Smrg#define miSpriteScreenKey (&miSpriteScreenKeyRec)
1889ace9065Smrg#define GetSpriteScreen(pScreen) \
1899ace9065Smrg	(dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey))
1906747b715Smrgstatic DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
1916747b715Smrg#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
19205b261ecSmrg
19305b261ecSmrgstatic Bool	    miSpriteCloseScreen(int i, ScreenPtr pScreen);
19405b261ecSmrgstatic void	    miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
19505b261ecSmrg				     int w, int h, unsigned int format,
19605b261ecSmrg				     unsigned long planemask, char *pdstLine);
19705b261ecSmrgstatic void	    miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
19805b261ecSmrg				     DDXPointPtr ppt, int *pwidth, int nspans,
19905b261ecSmrg				     char *pdstStart);
20005b261ecSmrgstatic void	    miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
2019ace9065Smrg					   int width, int height,
2029ace9065Smrg					   unsigned int subWindowMode);
20305b261ecSmrgstatic void	    miSpriteCopyWindow (WindowPtr pWindow,
20405b261ecSmrg					DDXPointRec ptOldOrg,
20505b261ecSmrg					RegionPtr prgnSrc);
20605b261ecSmrgstatic void	    miSpriteBlockHandler(int i, pointer blockData,
20705b261ecSmrg					 pointer pTimeout,
20805b261ecSmrg					 pointer pReadMask);
20905b261ecSmrgstatic void	    miSpriteInstallColormap(ColormapPtr pMap);
21005b261ecSmrgstatic void	    miSpriteStoreColors(ColormapPtr pMap, int ndef,
21105b261ecSmrg					xColorItem *pdef);
21205b261ecSmrg
2134642e01fSmrgstatic void	    miSpriteComputeSaved(DeviceIntPtr pDev,
2144642e01fSmrg                                         ScreenPtr pScreen);
21505b261ecSmrg
2164642e01fSmrgstatic Bool         miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
2174642e01fSmrg                                                   ScreenPtr pScreen);
2184642e01fSmrgstatic void         miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,
2194642e01fSmrg                                                ScreenPtr pScreen);
22005b261ecSmrg
2219ace9065Smrg#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
2229ace9065Smrg   (pPriv)->field)
2239ace9065Smrg#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
2249ace9065Smrg    ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
22505b261ecSmrg
22605b261ecSmrg/*
22705b261ecSmrg * pointer-sprite method table
22805b261ecSmrg */
22905b261ecSmrg
2304642e01fSmrgstatic Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2314642e01fSmrg                                  CursorPtr pCursor);
2324642e01fSmrgstatic Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2334642e01fSmrg                                    CursorPtr pCursor);
2344642e01fSmrgstatic void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2354642e01fSmrg                              CursorPtr pCursor, int x, int y);
2364642e01fSmrgstatic void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2374642e01fSmrg                               int x, int y);
23805b261ecSmrg
2396747b715SmrgmiPointerSpriteFuncRec miSpritePointerFuncs = {
24005b261ecSmrg    miSpriteRealizeCursor,
24105b261ecSmrg    miSpriteUnrealizeCursor,
24205b261ecSmrg    miSpriteSetCursor,
24305b261ecSmrg    miSpriteMoveCursor,
2444642e01fSmrg    miSpriteDeviceCursorInitialize,
2454642e01fSmrg    miSpriteDeviceCursorCleanup,
24605b261ecSmrg};
24705b261ecSmrg
24805b261ecSmrg/*
24905b261ecSmrg * other misc functions
25005b261ecSmrg */
25105b261ecSmrg
2524642e01fSmrgstatic void miSpriteRemoveCursor(DeviceIntPtr pDev,
2534642e01fSmrg                                 ScreenPtr pScreen);
2544642e01fSmrgstatic void miSpriteSaveUnderCursor(DeviceIntPtr pDev,
2554642e01fSmrg                                 ScreenPtr pScreen);
2564642e01fSmrgstatic void miSpriteRestoreCursor(DeviceIntPtr pDev,
2574642e01fSmrg                                 ScreenPtr pScreen);
25805b261ecSmrg
2599ace9065Smrgstatic void
2609ace9065SmrgmiSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
2619ace9065Smrg{
2629ace9065Smrg    if (!pScreenPriv->BlockHandler) {
2639ace9065Smrg        pScreenPriv->BlockHandler = pScreen->BlockHandler;
2649ace9065Smrg        pScreen->BlockHandler = miSpriteBlockHandler;
2659ace9065Smrg    }
2669ace9065Smrg}
2679ace9065Smrg
26805b261ecSmrgstatic void
26905b261ecSmrgmiSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
27005b261ecSmrg{
27105b261ecSmrg    ScreenPtr		    pScreen = closure;
2724642e01fSmrg    miCursorInfoPtr         pCursorInfo;
2734642e01fSmrg    DeviceIntPtr            pDev;
2744642e01fSmrg
2754642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
27605b261ecSmrg    {
2774642e01fSmrg        if (DevHasCursor(pDev))
2784642e01fSmrg        {
2794642e01fSmrg            pCursorInfo = MISPRITE(pDev);
2804642e01fSmrg
2814642e01fSmrg            if (pCursorInfo->isUp &&
2824642e01fSmrg                pCursorInfo->pScreen == pScreen &&
2836747b715Smrg                RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT)
2844642e01fSmrg            {
2854642e01fSmrg                SPRITE_DEBUG(("Damage remove\n"));
2864642e01fSmrg                miSpriteRemoveCursor (pDev, pScreen);
2874642e01fSmrg            }
2884642e01fSmrg        }
28905b261ecSmrg    }
29005b261ecSmrg}
29105b261ecSmrg
29205b261ecSmrg/*
29305b261ecSmrg * miSpriteInitialize -- called from device-dependent screen
29405b261ecSmrg * initialization proc after all of the function pointers have
29505b261ecSmrg * been stored in the screen structure.
29605b261ecSmrg */
29705b261ecSmrg
29805b261ecSmrgBool
2994642e01fSmrgmiSpriteInitialize (ScreenPtr               pScreen,
3004642e01fSmrg                    miPointerScreenFuncPtr  screenFuncs)
30105b261ecSmrg{
30205b261ecSmrg    miSpriteScreenPtr	pScreenPriv;
30305b261ecSmrg    VisualPtr		pVisual;
3044642e01fSmrg
30505b261ecSmrg    if (!DamageSetup (pScreen))
30605b261ecSmrg	return FALSE;
30705b261ecSmrg
3086747b715Smrg    if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
3096747b715Smrg	return FALSE;
3106747b715Smrg
3116747b715Smrg    if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0))
3126747b715Smrg	return FALSE;
3136747b715Smrg
3146747b715Smrg    pScreenPriv = malloc(sizeof (miSpriteScreenRec));
31505b261ecSmrg    if (!pScreenPriv)
31605b261ecSmrg	return FALSE;
3174642e01fSmrg
31805b261ecSmrg    pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
3196747b715Smrg					 NULL,
32005b261ecSmrg					 DamageReportRawRegion,
32105b261ecSmrg					 TRUE,
32205b261ecSmrg					 pScreen,
3236747b715Smrg					 pScreen);
32405b261ecSmrg
32505b261ecSmrg    if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
32605b261ecSmrg    {
3276747b715Smrg	free(pScreenPriv);
32805b261ecSmrg	return FALSE;
32905b261ecSmrg    }
33005b261ecSmrg    for (pVisual = pScreen->visuals;
33105b261ecSmrg	 pVisual->vid != pScreen->rootVisual;
33205b261ecSmrg	 pVisual++)
33305b261ecSmrg	;
33405b261ecSmrg    pScreenPriv->pVisual = pVisual;
33505b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
33605b261ecSmrg    pScreenPriv->GetImage = pScreen->GetImage;
33705b261ecSmrg    pScreenPriv->GetSpans = pScreen->GetSpans;
33805b261ecSmrg    pScreenPriv->SourceValidate = pScreen->SourceValidate;
33905b261ecSmrg
34005b261ecSmrg    pScreenPriv->CopyWindow = pScreen->CopyWindow;
3414642e01fSmrg
34205b261ecSmrg    pScreenPriv->InstallColormap = pScreen->InstallColormap;
34305b261ecSmrg    pScreenPriv->StoreColors = pScreen->StoreColors;
3444642e01fSmrg
3459ace9065Smrg    pScreenPriv->BlockHandler = NULL;
3464642e01fSmrg
3474642e01fSmrg    pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
3484642e01fSmrg    pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
3494642e01fSmrg
35005b261ecSmrg    pScreenPriv->pInstalledMap = NULL;
35105b261ecSmrg    pScreenPriv->pColormap = NULL;
35205b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].red = 0;
35305b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].green = 0;
35405b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
35505b261ecSmrg    pScreenPriv->colors[MASK_COLOR].red = 0;
35605b261ecSmrg    pScreenPriv->colors[MASK_COLOR].green = 0;
35705b261ecSmrg    pScreenPriv->colors[MASK_COLOR].blue = 0;
3586747b715Smrg    pScreenPriv->damageRegistered = 0;
3599ace9065Smrg    pScreenPriv->numberOfCursors = 0;
3606747b715Smrg
3614642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
3624642e01fSmrg
36305b261ecSmrg    pScreen->CloseScreen = miSpriteCloseScreen;
36405b261ecSmrg    pScreen->GetImage = miSpriteGetImage;
36505b261ecSmrg    pScreen->GetSpans = miSpriteGetSpans;
36605b261ecSmrg    pScreen->SourceValidate = miSpriteSourceValidate;
3674642e01fSmrg
36805b261ecSmrg    pScreen->CopyWindow = miSpriteCopyWindow;
36905b261ecSmrg    pScreen->InstallColormap = miSpriteInstallColormap;
37005b261ecSmrg    pScreen->StoreColors = miSpriteStoreColors;
37105b261ecSmrg
37205b261ecSmrg    return TRUE;
37305b261ecSmrg}
37405b261ecSmrg
37505b261ecSmrg/*
37605b261ecSmrg * Screen wrappers
37705b261ecSmrg */
37805b261ecSmrg
37905b261ecSmrg/*
38005b261ecSmrg * CloseScreen wrapper -- unwrap everything, free the private data
38105b261ecSmrg * and call the wrapped function
38205b261ecSmrg */
38305b261ecSmrg
38405b261ecSmrgstatic Bool
3854642e01fSmrgmiSpriteCloseScreen (int i, ScreenPtr pScreen)
38605b261ecSmrg{
3879ace9065Smrg    miSpriteScreenPtr   pScreenPriv = GetSpriteScreen(pScreen);
38805b261ecSmrg
38905b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
39005b261ecSmrg    pScreen->GetImage = pScreenPriv->GetImage;
39105b261ecSmrg    pScreen->GetSpans = pScreenPriv->GetSpans;
39205b261ecSmrg    pScreen->SourceValidate = pScreenPriv->SourceValidate;
39305b261ecSmrg    pScreen->InstallColormap = pScreenPriv->InstallColormap;
39405b261ecSmrg    pScreen->StoreColors = pScreenPriv->StoreColors;
39505b261ecSmrg
39605b261ecSmrg    DamageDestroy (pScreenPriv->pDamage);
3974642e01fSmrg
3986747b715Smrg    free(pScreenPriv);
39905b261ecSmrg
40005b261ecSmrg    return (*pScreen->CloseScreen) (i, pScreen);
40105b261ecSmrg}
40205b261ecSmrg
40305b261ecSmrgstatic void
4044642e01fSmrgmiSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
4054642e01fSmrg                  unsigned int format, unsigned long planemask,
4064642e01fSmrg                  char *pdstLine)
40705b261ecSmrg{
4089ace9065Smrg    ScreenPtr           pScreen = pDrawable->pScreen;
4099ace9065Smrg    DeviceIntPtr        pDev;
4109ace9065Smrg    miCursorInfoPtr     pCursorInfo;
4119ace9065Smrg    miSpriteScreenPtr   pPriv = GetSpriteScreen(pScreen);
41205b261ecSmrg
4139ace9065Smrg    SCREEN_PROLOGUE (pPriv, pScreen, GetImage);
41405b261ecSmrg
4156747b715Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
41605b261ecSmrg    {
4176747b715Smrg        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
4184642e01fSmrg        {
4196747b715Smrg            if (DevHasCursor(pDev))
4206747b715Smrg            {
4216747b715Smrg                 pCursorInfo = MISPRITE(pDev);
4226747b715Smrg                 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
4236747b715Smrg                      ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y,
4246747b715Smrg                                  sx, sy, w, h))
4256747b715Smrg                 {
4266747b715Smrg                     SPRITE_DEBUG (("GetImage remove\n"));
4276747b715Smrg                     miSpriteRemoveCursor (pDev, pScreen);
4286747b715Smrg                 }
4296747b715Smrg            }
4304642e01fSmrg        }
43105b261ecSmrg    }
43205b261ecSmrg
43305b261ecSmrg    (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
43405b261ecSmrg			  format, planemask, pdstLine);
43505b261ecSmrg
4369ace9065Smrg    SCREEN_EPILOGUE (pPriv, pScreen, GetImage);
43705b261ecSmrg}
43805b261ecSmrg
43905b261ecSmrgstatic void
4404642e01fSmrgmiSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
4414642e01fSmrg                  int *pwidth, int nspans, char *pdstStart)
44205b261ecSmrg{
44305b261ecSmrg    ScreenPtr		    pScreen = pDrawable->pScreen;
4446747b715Smrg    DeviceIntPtr            pDev;
4454642e01fSmrg    miCursorInfoPtr         pCursorInfo;
4469ace9065Smrg    miSpriteScreenPtr       pPriv = GetSpriteScreen(pScreen);
4474642e01fSmrg
4489ace9065Smrg    SCREEN_PROLOGUE (pPriv, pScreen, GetSpans);
44905b261ecSmrg
4506747b715Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
45105b261ecSmrg    {
4526747b715Smrg        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
4534642e01fSmrg        {
4546747b715Smrg            if (DevHasCursor(pDev))
4554642e01fSmrg            {
4566747b715Smrg                pCursorInfo = MISPRITE(pDev);
4576747b715Smrg
4586747b715Smrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
4594642e01fSmrg                {
4606747b715Smrg                    DDXPointPtr    pts;
4616747b715Smrg                    int    	       *widths;
4626747b715Smrg                    int    	       nPts;
4636747b715Smrg                    int    	       xorg,
4646747b715Smrg                                   yorg;
4656747b715Smrg
4666747b715Smrg                    xorg = pDrawable->x;
4676747b715Smrg                    yorg = pDrawable->y;
4686747b715Smrg
4696747b715Smrg                    for (pts = ppt, widths = pwidth, nPts = nspans;
4706747b715Smrg                            nPts--;
4716747b715Smrg                            pts++, widths++)
4724642e01fSmrg                    {
4736747b715Smrg                        if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
4746747b715Smrg                                    pts->x+xorg,*widths))
4756747b715Smrg                        {
4766747b715Smrg                            SPRITE_DEBUG (("GetSpans remove\n"));
4776747b715Smrg                            miSpriteRemoveCursor (pDev, pScreen);
4786747b715Smrg                            break;
4796747b715Smrg                        }
4804642e01fSmrg                    }
4814642e01fSmrg                }
4824642e01fSmrg            }
4834642e01fSmrg        }
48405b261ecSmrg    }
48505b261ecSmrg
48605b261ecSmrg    (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
48705b261ecSmrg
4889ace9065Smrg    SCREEN_EPILOGUE (pPriv, pScreen, GetSpans);
48905b261ecSmrg}
49005b261ecSmrg
49105b261ecSmrgstatic void
4924642e01fSmrgmiSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
4939ace9065Smrg                        int height, unsigned int subWindowMode)
49405b261ecSmrg{
49505b261ecSmrg    ScreenPtr		    pScreen = pDrawable->pScreen;
4966747b715Smrg    DeviceIntPtr            pDev;
4974642e01fSmrg    miCursorInfoPtr         pCursorInfo;
4989ace9065Smrg    miSpriteScreenPtr       pPriv = GetSpriteScreen(pScreen);
4994642e01fSmrg
5009ace9065Smrg    SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate);
50105b261ecSmrg
5026747b715Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
50305b261ecSmrg    {
5046747b715Smrg	for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
5056747b715Smrg	{
5066747b715Smrg	    if (DevHasCursor(pDev))
5076747b715Smrg	    {
5086747b715Smrg		pCursorInfo = MISPRITE(pDev);
5096747b715Smrg		if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
5106747b715Smrg		    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
5116747b715Smrg				x, y, width, height))
5126747b715Smrg		{
5136747b715Smrg		    SPRITE_DEBUG (("SourceValidate remove\n"));
5146747b715Smrg		    miSpriteRemoveCursor (pDev, pScreen);
5156747b715Smrg		}
5166747b715Smrg	    }
5176747b715Smrg	}
51805b261ecSmrg    }
51905b261ecSmrg
52005b261ecSmrg    if (pScreen->SourceValidate)
5219ace9065Smrg	(*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode);
52205b261ecSmrg
5239ace9065Smrg    SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate);
52405b261ecSmrg}
52505b261ecSmrg
52605b261ecSmrgstatic void
52705b261ecSmrgmiSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
52805b261ecSmrg{
52905b261ecSmrg    ScreenPtr	pScreen = pWindow->drawable.pScreen;
5306747b715Smrg    DeviceIntPtr            pDev;
5314642e01fSmrg    miCursorInfoPtr         pCursorInfo;
5329ace9065Smrg    miSpriteScreenPtr       pPriv = GetSpriteScreen(pScreen);
5334642e01fSmrg
5349ace9065Smrg    SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow);
53505b261ecSmrg
5364642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
53705b261ecSmrg    {
5384642e01fSmrg        if (DevHasCursor(pDev))
5394642e01fSmrg        {
5404642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5414642e01fSmrg            /*
5424642e01fSmrg             * Damage will take care of destination check
5434642e01fSmrg             */
5444642e01fSmrg            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
5456747b715Smrg                    RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT)
5464642e01fSmrg            {
5474642e01fSmrg                SPRITE_DEBUG (("CopyWindow remove\n"));
5484642e01fSmrg                miSpriteRemoveCursor (pDev, pScreen);
5494642e01fSmrg            }
5504642e01fSmrg        }
55105b261ecSmrg    }
55205b261ecSmrg
55305b261ecSmrg    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
5549ace9065Smrg    SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow);
55505b261ecSmrg}
55605b261ecSmrg
55705b261ecSmrgstatic void
5584642e01fSmrgmiSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
5594642e01fSmrg                      pointer pReadmask)
56005b261ecSmrg{
56105b261ecSmrg    ScreenPtr		pScreen = screenInfo.screens[i];
5629ace9065Smrg    miSpriteScreenPtr	pPriv = GetSpriteScreen(pScreen);
5636747b715Smrg    DeviceIntPtr            pDev;
5644642e01fSmrg    miCursorInfoPtr         pCursorInfo;
5659ace9065Smrg    Bool                WorkToDo = FALSE;
56605b261ecSmrg
5674642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
5684642e01fSmrg    {
5694642e01fSmrg        if (DevHasCursor(pDev))
5704642e01fSmrg        {
5714642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5724642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp
5734642e01fSmrg                    && pCursorInfo->pScreen == pScreen
5744642e01fSmrg                    && pCursorInfo->shouldBeUp)
5754642e01fSmrg            {
5768223e2f2Smrg                SPRITE_DEBUG (("BlockHandler save"));
5774642e01fSmrg                miSpriteSaveUnderCursor (pDev, pScreen);
5784642e01fSmrg            }
5794642e01fSmrg        }
5804642e01fSmrg    }
5814642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
58205b261ecSmrg    {
5834642e01fSmrg        if (DevHasCursor(pDev))
5844642e01fSmrg        {
5854642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5864642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp &&
5874642e01fSmrg                    pCursorInfo->pScreen == pScreen &&
5884642e01fSmrg                    pCursorInfo->shouldBeUp)
5894642e01fSmrg            {
5904642e01fSmrg                SPRITE_DEBUG (("BlockHandler restore\n"));
5914642e01fSmrg                miSpriteRestoreCursor (pDev, pScreen);
5929ace9065Smrg                if (!pCursorInfo->isUp)
5939ace9065Smrg                    WorkToDo = TRUE;
5944642e01fSmrg            }
5954642e01fSmrg        }
59605b261ecSmrg    }
5979ace9065Smrg
5989ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
5999ace9065Smrg
6009ace9065Smrg    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
6019ace9065Smrg
6029ace9065Smrg    if (WorkToDo)
6039ace9065Smrg        SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
6049ace9065Smrg    else
6059ace9065Smrg        pPriv->BlockHandler = NULL;
60605b261ecSmrg}
60705b261ecSmrg
60805b261ecSmrgstatic void
6094642e01fSmrgmiSpriteInstallColormap (ColormapPtr pMap)
61005b261ecSmrg{
61105b261ecSmrg    ScreenPtr		pScreen = pMap->pScreen;
6129ace9065Smrg    miSpriteScreenPtr	pPriv = GetSpriteScreen(pScreen);
61305b261ecSmrg
6149ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
6154642e01fSmrg
61605b261ecSmrg    (*pScreen->InstallColormap) (pMap);
61705b261ecSmrg
6189ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
61905b261ecSmrg
6204642e01fSmrg    /* InstallColormap can be called before devices are initialized. */
62105b261ecSmrg    pPriv->pInstalledMap = pMap;
62205b261ecSmrg    if (pPriv->pColormap != pMap)
62305b261ecSmrg    {
6244642e01fSmrg        DeviceIntPtr pDev;
6254642e01fSmrg        miCursorInfoPtr     pCursorInfo;
6264642e01fSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
6274642e01fSmrg        {
6284642e01fSmrg            if (DevHasCursor(pDev))
6294642e01fSmrg            {
6304642e01fSmrg                pCursorInfo = MISPRITE(pDev);
6314642e01fSmrg                pCursorInfo->checkPixels = TRUE;
6324642e01fSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
6334642e01fSmrg                    miSpriteRemoveCursor(pDev, pScreen);
6344642e01fSmrg            }
6354642e01fSmrg        }
6364642e01fSmrg
63705b261ecSmrg    }
63805b261ecSmrg}
63905b261ecSmrg
64005b261ecSmrgstatic void
6414642e01fSmrgmiSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
64205b261ecSmrg{
64305b261ecSmrg    ScreenPtr		pScreen = pMap->pScreen;
6449ace9065Smrg    miSpriteScreenPtr	pPriv = GetSpriteScreen(pScreen);
64505b261ecSmrg    int			i;
64605b261ecSmrg    int			updated;
64705b261ecSmrg    VisualPtr		pVisual;
6486747b715Smrg    DeviceIntPtr        pDev;
6494642e01fSmrg    miCursorInfoPtr     pCursorInfo;
65005b261ecSmrg
6519ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
6524642e01fSmrg
65305b261ecSmrg    (*pScreen->StoreColors) (pMap, ndef, pdef);
65405b261ecSmrg
6559ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
65605b261ecSmrg
65705b261ecSmrg    if (pPriv->pColormap == pMap)
65805b261ecSmrg    {
6594642e01fSmrg        updated = 0;
6604642e01fSmrg        pVisual = pMap->pVisual;
6614642e01fSmrg        if (pVisual->class == DirectColor)
6624642e01fSmrg        {
6634642e01fSmrg            /* Direct color - match on any of the subfields */
66405b261ecSmrg
66505b261ecSmrg#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
66605b261ecSmrg
6674642e01fSmrg#define UpdateDAC(dev, plane,dac,mask) {\
6684642e01fSmrg    if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
6694642e01fSmrg	dev->colors[plane].dac = pdef[i].dac; \
67005b261ecSmrg	updated = 1; \
67105b261ecSmrg    } \
67205b261ecSmrg}
67305b261ecSmrg
6744642e01fSmrg#define CheckDirect(dev, plane) \
6754642e01fSmrg	    UpdateDAC(dev, plane,red,redMask) \
6764642e01fSmrg	    UpdateDAC(dev, plane,green,greenMask) \
6774642e01fSmrg	    UpdateDAC(dev, plane,blue,blueMask)
6784642e01fSmrg
6794642e01fSmrg            for (i = 0; i < ndef; i++)
6804642e01fSmrg            {
6814642e01fSmrg                CheckDirect (pPriv, SOURCE_COLOR)
6824642e01fSmrg                CheckDirect (pPriv, MASK_COLOR)
6834642e01fSmrg            }
6844642e01fSmrg        }
6854642e01fSmrg        else
6864642e01fSmrg        {
6874642e01fSmrg            /* PseudoColor/GrayScale - match on exact pixel */
6884642e01fSmrg            for (i = 0; i < ndef; i++)
6894642e01fSmrg            {
6904642e01fSmrg                if (pdef[i].pixel ==
6914642e01fSmrg                        pPriv->colors[SOURCE_COLOR].pixel)
6924642e01fSmrg                {
6934642e01fSmrg                    pPriv->colors[SOURCE_COLOR] = pdef[i];
6944642e01fSmrg                    if (++updated == 2)
6954642e01fSmrg                        break;
6964642e01fSmrg                }
6974642e01fSmrg                if (pdef[i].pixel ==
6984642e01fSmrg                        pPriv->colors[MASK_COLOR].pixel)
6994642e01fSmrg                {
7004642e01fSmrg                    pPriv->colors[MASK_COLOR] = pdef[i];
7014642e01fSmrg                    if (++updated == 2)
7024642e01fSmrg                        break;
7034642e01fSmrg                }
7044642e01fSmrg            }
7054642e01fSmrg        }
7064642e01fSmrg        if (updated)
7074642e01fSmrg        {
7084642e01fSmrg            for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
7094642e01fSmrg            {
7104642e01fSmrg                if (DevHasCursor(pDev))
7114642e01fSmrg                {
7124642e01fSmrg                    pCursorInfo = MISPRITE(pDev);
7134642e01fSmrg                    pCursorInfo->checkPixels = TRUE;
7144642e01fSmrg                    if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
7154642e01fSmrg                        miSpriteRemoveCursor (pDev, pScreen);
7164642e01fSmrg                }
7174642e01fSmrg            }
7184642e01fSmrg        }
71905b261ecSmrg    }
72005b261ecSmrg}
72105b261ecSmrg
72205b261ecSmrgstatic void
7234642e01fSmrgmiSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
72405b261ecSmrg{
7259ace9065Smrg    miSpriteScreenPtr	pScreenPriv = GetSpriteScreen(pScreen);
72605b261ecSmrg    CursorPtr		pCursor;
72705b261ecSmrg    xColorItem		*sourceColor, *maskColor;
72805b261ecSmrg
7294642e01fSmrg    pCursor = pDevCursor->pCursor;
73005b261ecSmrg    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
73105b261ecSmrg    maskColor = &pScreenPriv->colors[MASK_COLOR];
73205b261ecSmrg    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
73305b261ecSmrg	!(pCursor->foreRed == sourceColor->red &&
73405b261ecSmrg	  pCursor->foreGreen == sourceColor->green &&
73505b261ecSmrg          pCursor->foreBlue == sourceColor->blue &&
73605b261ecSmrg	  pCursor->backRed == maskColor->red &&
73705b261ecSmrg	  pCursor->backGreen == maskColor->green &&
73805b261ecSmrg	  pCursor->backBlue == maskColor->blue))
73905b261ecSmrg    {
74005b261ecSmrg	pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
74105b261ecSmrg	sourceColor->red = pCursor->foreRed;
74205b261ecSmrg	sourceColor->green = pCursor->foreGreen;
74305b261ecSmrg	sourceColor->blue = pCursor->foreBlue;
74405b261ecSmrg	FakeAllocColor (pScreenPriv->pColormap, sourceColor);
74505b261ecSmrg	maskColor->red = pCursor->backRed;
74605b261ecSmrg	maskColor->green = pCursor->backGreen;
74705b261ecSmrg	maskColor->blue = pCursor->backBlue;
74805b261ecSmrg	FakeAllocColor (pScreenPriv->pColormap, maskColor);
74905b261ecSmrg	/* "free" the pixels right away, don't let this confuse you */
75005b261ecSmrg	FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
75105b261ecSmrg	FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
75205b261ecSmrg    }
75305b261ecSmrg
7544642e01fSmrg    pDevCursor->checkPixels = FALSE;
75505b261ecSmrg
75605b261ecSmrg}
75705b261ecSmrg
75805b261ecSmrg/*
75905b261ecSmrg * miPointer interface routines
76005b261ecSmrg */
76105b261ecSmrg
76205b261ecSmrg#define SPRITE_PAD  8
76305b261ecSmrg
76405b261ecSmrgstatic Bool
7654642e01fSmrgmiSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
76605b261ecSmrg{
7674642e01fSmrg    miCursorInfoPtr pCursorInfo;
7684642e01fSmrg
7696747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
7704642e01fSmrg        return FALSE;
7716747b715Smrg
7724642e01fSmrg    pCursorInfo = MISPRITE(pDev);
7734642e01fSmrg
7744642e01fSmrg    if (pCursor == pCursorInfo->pCursor)
7754642e01fSmrg	pCursorInfo->checkPixels = TRUE;
77605b261ecSmrg
7776747b715Smrg    return miDCRealizeCursor(pScreen, pCursor);
77805b261ecSmrg}
77905b261ecSmrg
78005b261ecSmrgstatic Bool
7814642e01fSmrgmiSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
78205b261ecSmrg{
7836747b715Smrg    return miDCUnrealizeCursor(pScreen, pCursor);
78405b261ecSmrg}
78505b261ecSmrg
78605b261ecSmrgstatic void
7874642e01fSmrgmiSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
7884642e01fSmrg                   CursorPtr pCursor, int x, int y)
78905b261ecSmrg{
7909ace9065Smrg    miCursorInfoPtr     pPointer;
7919ace9065Smrg    miSpriteScreenPtr   pScreenPriv;
7924642e01fSmrg
7936747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
7944642e01fSmrg        return;
7956747b715Smrg
7964642e01fSmrg    pPointer = MISPRITE(pDev);
7979ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
7984642e01fSmrg
79905b261ecSmrg    if (!pCursor)
80005b261ecSmrg    {
8019ace9065Smrg	if (pPointer->shouldBeUp)
8029ace9065Smrg	    --pScreenPriv->numberOfCursors;
8034642e01fSmrg    	pPointer->shouldBeUp = FALSE;
8044642e01fSmrg    	if (pPointer->isUp)
8054642e01fSmrg	    miSpriteRemoveCursor (pDev, pScreen);
8069ace9065Smrg	if (pScreenPriv->numberOfCursors == 0)
8079ace9065Smrg	    miSpriteDisableDamage(pScreen, pScreenPriv);
8084642e01fSmrg	pPointer->pCursor = 0;
80905b261ecSmrg	return;
81005b261ecSmrg    }
8119ace9065Smrg    if (!pPointer->shouldBeUp)
8129ace9065Smrg	pScreenPriv->numberOfCursors++;
8134642e01fSmrg    pPointer->shouldBeUp = TRUE;
8149ace9065Smrg    if (!pPointer->isUp)
8159ace9065Smrg	miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
8164642e01fSmrg    if (pPointer->x == x &&
8174642e01fSmrg	pPointer->y == y &&
8184642e01fSmrg	pPointer->pCursor == pCursor &&
8194642e01fSmrg	!pPointer->checkPixels)
82005b261ecSmrg    {
82105b261ecSmrg	return;
82205b261ecSmrg    }
8234642e01fSmrg    pPointer->x = x;
8244642e01fSmrg    pPointer->y = y;
8254642e01fSmrg    pPointer->pCacheWin = NullWindow;
8264642e01fSmrg    if (pPointer->checkPixels || pPointer->pCursor != pCursor)
82705b261ecSmrg    {
8284642e01fSmrg	pPointer->pCursor = pCursor;
8294642e01fSmrg	miSpriteFindColors (pPointer, pScreen);
83005b261ecSmrg    }
8314642e01fSmrg    if (pPointer->isUp) {
8326747b715Smrg	/* TODO: reimplement flicker-free MoveCursor */
8336747b715Smrg	SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id));
8346747b715Smrg	miSpriteRemoveCursor (pDev, pScreen);
83505b261ecSmrg    }
8364642e01fSmrg
8374642e01fSmrg    if (!pPointer->isUp && pPointer->pCursor)
83805b261ecSmrg    {
8394642e01fSmrg	SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id));
8404642e01fSmrg        miSpriteSaveUnderCursor(pDev, pScreen);
8414642e01fSmrg	miSpriteRestoreCursor (pDev, pScreen);
84205b261ecSmrg    }
8434642e01fSmrg
84405b261ecSmrg}
84505b261ecSmrg
84605b261ecSmrgstatic void
8474642e01fSmrgmiSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
84805b261ecSmrg{
8494642e01fSmrg    CursorPtr pCursor;
85005b261ecSmrg
8516747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
8524642e01fSmrg        return;
8536747b715Smrg
8544642e01fSmrg    pCursor = MISPRITE(pDev)->pCursor;
8554642e01fSmrg
8564642e01fSmrg    miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
8574642e01fSmrg}
8584642e01fSmrg
8594642e01fSmrg
8604642e01fSmrgstatic Bool
8614642e01fSmrgmiSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
8624642e01fSmrg{
8634642e01fSmrg    miCursorInfoPtr pCursorInfo;
8644642e01fSmrg    int ret = FALSE;
8654642e01fSmrg
8666747b715Smrg    pCursorInfo = malloc(sizeof(miCursorInfoRec));
8674642e01fSmrg    if (!pCursorInfo)
8684642e01fSmrg        return FALSE;
8694642e01fSmrg
8704642e01fSmrg    pCursorInfo->pCursor = NULL;
8714642e01fSmrg    pCursorInfo->x = 0;
8724642e01fSmrg    pCursorInfo->y = 0;
8734642e01fSmrg    pCursorInfo->isUp = FALSE;
8744642e01fSmrg    pCursorInfo->shouldBeUp = FALSE;
8754642e01fSmrg    pCursorInfo->pCacheWin = NullWindow;
8764642e01fSmrg    pCursorInfo->isInCacheWin = FALSE;
8774642e01fSmrg    pCursorInfo->checkPixels = TRUE;
8784642e01fSmrg    pCursorInfo->pScreen = FALSE;
8794642e01fSmrg
8806747b715Smrg    ret = miDCDeviceInitialize(pDev, pScreen);
8814642e01fSmrg    if (!ret)
8824642e01fSmrg    {
8836747b715Smrg        free(pCursorInfo);
8844642e01fSmrg        pCursorInfo = NULL;
8854642e01fSmrg    }
8864642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo);
8874642e01fSmrg    return ret;
8884642e01fSmrg}
8894642e01fSmrg
8904642e01fSmrgstatic void
8914642e01fSmrgmiSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
8924642e01fSmrg{
8934642e01fSmrg    if (DevHasCursor(pDev))
8946747b715Smrg        miDCDeviceCleanup(pDev, pScreen);
89505b261ecSmrg}
89605b261ecSmrg
89705b261ecSmrg/*
89805b261ecSmrg * undraw/draw cursor
89905b261ecSmrg */
90005b261ecSmrg
90105b261ecSmrgstatic void
9024642e01fSmrgmiSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
90305b261ecSmrg{
90405b261ecSmrg    miSpriteScreenPtr   pScreenPriv;
9054642e01fSmrg    miCursorInfoPtr     pCursorInfo;
9064642e01fSmrg
90705b261ecSmrg
9086747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
9094642e01fSmrg        return;
9106747b715Smrg
91105b261ecSmrg    DamageDrawInternal (pScreen, TRUE);
9129ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
9134642e01fSmrg    pCursorInfo = MISPRITE(pDev);
9144642e01fSmrg
9154642e01fSmrg    miSpriteIsDown(pCursorInfo);
9169ace9065Smrg    miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
9174642e01fSmrg    pCursorInfo->pCacheWin = NullWindow;
9184642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
9196747b715Smrg    if (!miDCRestoreUnderCursor(pDev,
9206747b715Smrg                                pScreen,
9216747b715Smrg                                pCursorInfo->saved.x1,
9226747b715Smrg                                pCursorInfo->saved.y1,
9236747b715Smrg                                pCursorInfo->saved.x2 -
9246747b715Smrg                                pCursorInfo->saved.x1,
9256747b715Smrg                                pCursorInfo->saved.y2 -
9266747b715Smrg                                pCursorInfo->saved.y1))
92705b261ecSmrg    {
9286747b715Smrg        miSpriteIsUp(pCursorInfo);
92905b261ecSmrg    }
9304642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
93105b261ecSmrg    DamageDrawInternal (pScreen, FALSE);
93205b261ecSmrg}
93305b261ecSmrg
9344642e01fSmrg/*
9354642e01fSmrg * Called from the block handler, saves area under cursor
9364642e01fSmrg * before waiting for something to do.
9374642e01fSmrg */
9384642e01fSmrg
9394642e01fSmrgstatic void
9404642e01fSmrgmiSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
9414642e01fSmrg{
9424642e01fSmrg    miSpriteScreenPtr   pScreenPriv;
9434642e01fSmrg    int			x, y;
9444642e01fSmrg    CursorPtr		pCursor;
9454642e01fSmrg    miCursorInfoPtr     pCursorInfo;
9464642e01fSmrg
9476747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
9484642e01fSmrg        return;
9496747b715Smrg
9504642e01fSmrg    DamageDrawInternal (pScreen, TRUE);
9519ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
9524642e01fSmrg    pCursorInfo = MISPRITE(pDev);
9534642e01fSmrg
9544642e01fSmrg    miSpriteComputeSaved (pDev, pScreen);
9554642e01fSmrg    pCursor = pCursorInfo->pCursor;
9564642e01fSmrg
9574642e01fSmrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
9584642e01fSmrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
9594642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
9604642e01fSmrg
9616747b715Smrg    miDCSaveUnderCursor(pDev,
9626747b715Smrg                        pScreen,
9636747b715Smrg                        pCursorInfo->saved.x1,
9646747b715Smrg                        pCursorInfo->saved.y1,
9656747b715Smrg                        pCursorInfo->saved.x2 -
9666747b715Smrg                        pCursorInfo->saved.x1,
9676747b715Smrg                        pCursorInfo->saved.y2 -
9686747b715Smrg                        pCursorInfo->saved.y1);
9694642e01fSmrg    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
9704642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
9714642e01fSmrg    DamageDrawInternal (pScreen, FALSE);
9724642e01fSmrg}
9734642e01fSmrg
9744642e01fSmrg
97505b261ecSmrg/*
97605b261ecSmrg * Called from the block handler, restores the cursor
97705b261ecSmrg * before waiting for something to do.
97805b261ecSmrg */
97905b261ecSmrg
98005b261ecSmrgstatic void
9814642e01fSmrgmiSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
98205b261ecSmrg{
98305b261ecSmrg    miSpriteScreenPtr   pScreenPriv;
98405b261ecSmrg    int			x, y;
98505b261ecSmrg    CursorPtr		pCursor;
9864642e01fSmrg    miCursorInfoPtr     pCursorInfo;
9874642e01fSmrg
9886747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
9894642e01fSmrg        return;
99005b261ecSmrg
99105b261ecSmrg    DamageDrawInternal (pScreen, TRUE);
9929ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
9934642e01fSmrg    pCursorInfo = MISPRITE(pDev);
9944642e01fSmrg
9954642e01fSmrg    miSpriteComputeSaved (pDev, pScreen);
9964642e01fSmrg    pCursor = pCursorInfo->pCursor;
9974642e01fSmrg
9984642e01fSmrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
9994642e01fSmrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
10004642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
10014642e01fSmrg    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
10024642e01fSmrg    if (pCursorInfo->checkPixels)
10034642e01fSmrg        miSpriteFindColors (pCursorInfo, pScreen);
10046747b715Smrg    if (miDCPutUpCursor(pDev, pScreen,
10054642e01fSmrg                pCursor, x, y,
10064642e01fSmrg                pScreenPriv->colors[SOURCE_COLOR].pixel,
10074642e01fSmrg                pScreenPriv->colors[MASK_COLOR].pixel))
100805b261ecSmrg    {
10094642e01fSmrg        miSpriteIsUp(pCursorInfo);
10104642e01fSmrg        pCursorInfo->pScreen = pScreen;
101105b261ecSmrg    }
10124642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
101305b261ecSmrg    DamageDrawInternal (pScreen, FALSE);
101405b261ecSmrg}
101505b261ecSmrg
101605b261ecSmrg/*
101705b261ecSmrg * compute the desired area of the screen to save
101805b261ecSmrg */
101905b261ecSmrg
102005b261ecSmrgstatic void
10214642e01fSmrgmiSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
102205b261ecSmrg{
102305b261ecSmrg    int		    x, y, w, h;
102405b261ecSmrg    int		    wpad, hpad;
102505b261ecSmrg    CursorPtr	    pCursor;
10264642e01fSmrg    miCursorInfoPtr pCursorInfo;
102705b261ecSmrg
10286747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
10294642e01fSmrg        return;
10306747b715Smrg
10314642e01fSmrg    pCursorInfo = MISPRITE(pDev);
10324642e01fSmrg
10334642e01fSmrg    pCursor = pCursorInfo->pCursor;
10344642e01fSmrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
10354642e01fSmrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
103605b261ecSmrg    w = pCursor->bits->width;
103705b261ecSmrg    h = pCursor->bits->height;
103805b261ecSmrg    wpad = SPRITE_PAD;
103905b261ecSmrg    hpad = SPRITE_PAD;
10404642e01fSmrg    pCursorInfo->saved.x1 = x - wpad;
10414642e01fSmrg    pCursorInfo->saved.y1 = y - hpad;
10424642e01fSmrg    pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
10434642e01fSmrg    pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
104405b261ecSmrg}
10454642e01fSmrg
1046