misprite.c revision 8223e2f2
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;
996747b715Smrg} miSpriteScreenRec, *miSpriteScreenPtr;
1006747b715Smrg
1016747b715Smrg#define SOURCE_COLOR	0
1026747b715Smrg#define MASK_COLOR	1
1036747b715Smrg
1046747b715Smrg/*
1056747b715Smrg * Overlap BoxPtr and Box elements
1066747b715Smrg */
1076747b715Smrg#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
1086747b715Smrg 	(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
1096747b715Smrg	 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
1106747b715Smrg
1116747b715Smrg/*
1126747b715Smrg * Overlap BoxPtr, origins, and rectangle
1136747b715Smrg */
1146747b715Smrg#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
1156747b715Smrg    BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
1166747b715Smrg
1176747b715Smrg/*
1186747b715Smrg * Overlap BoxPtr, origins and RectPtr
1196747b715Smrg */
1206747b715Smrg#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
1216747b715Smrg    ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
1226747b715Smrg		(int)((pRect)->width), (int)((pRect)->height))
1236747b715Smrg/*
1246747b715Smrg * Overlap BoxPtr and horizontal span
1256747b715Smrg */
1266747b715Smrg#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
12705b261ecSmrg
1286747b715Smrg#define LINE_SORT(x1,y1,x2,y2) \
1296747b715Smrg{ int _t; \
1306747b715Smrg  if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
1316747b715Smrg  if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
1326747b715Smrg
1336747b715Smrg#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
1346747b715Smrg    BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
1354642e01fSmrg
1364642e01fSmrg
13705b261ecSmrg#define SPRITE_DEBUG_ENABLE 0
13805b261ecSmrg#if SPRITE_DEBUG_ENABLE
13905b261ecSmrg#define SPRITE_DEBUG(x)	ErrorF x
14005b261ecSmrg#else
14105b261ecSmrg#define SPRITE_DEBUG(x)
14205b261ecSmrg#endif
14305b261ecSmrg
1444642e01fSmrg#define MISPRITE(dev) \
1456747b715Smrg    ((!IsMaster(dev) && !dev->u.master) ? \
1464642e01fSmrg       (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
1476747b715Smrg       (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
1484642e01fSmrg
1494642e01fSmrgstatic void
1504642e01fSmrgmiSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1514642e01fSmrg{
1526747b715Smrg    if (pScreenPriv->damageRegistered) {
1534642e01fSmrg	DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
1544642e01fSmrg			  pScreenPriv->pDamage);
1556747b715Smrg	pScreenPriv->damageRegistered = 0;
1564642e01fSmrg    }
1574642e01fSmrg}
1584642e01fSmrg
1594642e01fSmrgstatic void
1604642e01fSmrgmiSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1614642e01fSmrg{
1626747b715Smrg    if (!pScreenPriv->damageRegistered) {
1636747b715Smrg	pScreenPriv->damageRegistered = 1;
1644642e01fSmrg	DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
1654642e01fSmrg			pScreenPriv->pDamage);
1664642e01fSmrg    }
1674642e01fSmrg}
1684642e01fSmrg
1694642e01fSmrgstatic void
1704642e01fSmrgmiSpriteIsUp(miCursorInfoPtr pDevCursor)
1714642e01fSmrg{
1724642e01fSmrg    pDevCursor->isUp = TRUE;
1734642e01fSmrg}
1744642e01fSmrg
1754642e01fSmrgstatic void
1764642e01fSmrgmiSpriteIsDown(miCursorInfoPtr pDevCursor)
1774642e01fSmrg{
1784642e01fSmrg    pDevCursor->isUp = FALSE;
1794642e01fSmrg}
1804642e01fSmrg
18105b261ecSmrg/*
18205b261ecSmrg * screen wrappers
18305b261ecSmrg */
18405b261ecSmrg
1856747b715Smrgstatic DevPrivateKeyRec miSpriteScreenKeyRec;
1866747b715Smrg#define miSpriteScreenKey (&miSpriteScreenKeyRec)
1876747b715Smrgstatic DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
1886747b715Smrg#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
18905b261ecSmrg
19005b261ecSmrgstatic Bool	    miSpriteCloseScreen(int i, ScreenPtr pScreen);
19105b261ecSmrgstatic void	    miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
19205b261ecSmrg				     int w, int h, unsigned int format,
19305b261ecSmrg				     unsigned long planemask, char *pdstLine);
19405b261ecSmrgstatic void	    miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
19505b261ecSmrg				     DDXPointPtr ppt, int *pwidth, int nspans,
19605b261ecSmrg				     char *pdstStart);
19705b261ecSmrgstatic void	    miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
19805b261ecSmrg					   int width, int height);
19905b261ecSmrgstatic void	    miSpriteCopyWindow (WindowPtr pWindow,
20005b261ecSmrg					DDXPointRec ptOldOrg,
20105b261ecSmrg					RegionPtr prgnSrc);
20205b261ecSmrgstatic void	    miSpriteBlockHandler(int i, pointer blockData,
20305b261ecSmrg					 pointer pTimeout,
20405b261ecSmrg					 pointer pReadMask);
20505b261ecSmrgstatic void	    miSpriteInstallColormap(ColormapPtr pMap);
20605b261ecSmrgstatic void	    miSpriteStoreColors(ColormapPtr pMap, int ndef,
20705b261ecSmrg					xColorItem *pdef);
20805b261ecSmrg
2094642e01fSmrgstatic void	    miSpriteComputeSaved(DeviceIntPtr pDev,
2104642e01fSmrg                                         ScreenPtr pScreen);
21105b261ecSmrg
2124642e01fSmrgstatic Bool         miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
2134642e01fSmrg                                                   ScreenPtr pScreen);
2144642e01fSmrgstatic void         miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,
2154642e01fSmrg                                                ScreenPtr pScreen);
21605b261ecSmrg
2174642e01fSmrg#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
2184642e01fSmrg   ((miSpriteScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \
2194642e01fSmrg					miSpriteScreenKey))->field)
22005b261ecSmrg#define SCREEN_EPILOGUE(pScreen, field)\
22105b261ecSmrg    ((pScreen)->field = miSprite##field)
22205b261ecSmrg
22305b261ecSmrg/*
22405b261ecSmrg * pointer-sprite method table
22505b261ecSmrg */
22605b261ecSmrg
2274642e01fSmrgstatic Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2284642e01fSmrg                                  CursorPtr pCursor);
2294642e01fSmrgstatic Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2304642e01fSmrg                                    CursorPtr pCursor);
2314642e01fSmrgstatic void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2324642e01fSmrg                              CursorPtr pCursor, int x, int y);
2334642e01fSmrgstatic void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2344642e01fSmrg                               int x, int y);
23505b261ecSmrg
2366747b715SmrgmiPointerSpriteFuncRec miSpritePointerFuncs = {
23705b261ecSmrg    miSpriteRealizeCursor,
23805b261ecSmrg    miSpriteUnrealizeCursor,
23905b261ecSmrg    miSpriteSetCursor,
24005b261ecSmrg    miSpriteMoveCursor,
2414642e01fSmrg    miSpriteDeviceCursorInitialize,
2424642e01fSmrg    miSpriteDeviceCursorCleanup,
24305b261ecSmrg};
24405b261ecSmrg
24505b261ecSmrg/*
24605b261ecSmrg * other misc functions
24705b261ecSmrg */
24805b261ecSmrg
2494642e01fSmrgstatic void miSpriteRemoveCursor(DeviceIntPtr pDev,
2504642e01fSmrg                                 ScreenPtr pScreen);
2514642e01fSmrgstatic void miSpriteSaveUnderCursor(DeviceIntPtr pDev,
2524642e01fSmrg                                 ScreenPtr pScreen);
2534642e01fSmrgstatic void miSpriteRestoreCursor(DeviceIntPtr pDev,
2544642e01fSmrg                                 ScreenPtr pScreen);
25505b261ecSmrg
25605b261ecSmrgstatic void
25705b261ecSmrgmiSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
25805b261ecSmrg{
25905b261ecSmrg    ScreenPtr		    pScreen = closure;
2604642e01fSmrg    miCursorInfoPtr         pCursorInfo;
2614642e01fSmrg    DeviceIntPtr            pDev;
2624642e01fSmrg
2634642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
26405b261ecSmrg    {
2654642e01fSmrg        if (DevHasCursor(pDev))
2664642e01fSmrg        {
2674642e01fSmrg            pCursorInfo = MISPRITE(pDev);
2684642e01fSmrg
2694642e01fSmrg            if (pCursorInfo->isUp &&
2704642e01fSmrg                pCursorInfo->pScreen == pScreen &&
2716747b715Smrg                RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT)
2724642e01fSmrg            {
2734642e01fSmrg                SPRITE_DEBUG(("Damage remove\n"));
2744642e01fSmrg                miSpriteRemoveCursor (pDev, pScreen);
2754642e01fSmrg            }
2764642e01fSmrg        }
27705b261ecSmrg    }
27805b261ecSmrg}
27905b261ecSmrg
28005b261ecSmrg/*
28105b261ecSmrg * miSpriteInitialize -- called from device-dependent screen
28205b261ecSmrg * initialization proc after all of the function pointers have
28305b261ecSmrg * been stored in the screen structure.
28405b261ecSmrg */
28505b261ecSmrg
28605b261ecSmrgBool
2874642e01fSmrgmiSpriteInitialize (ScreenPtr               pScreen,
2884642e01fSmrg                    miPointerScreenFuncPtr  screenFuncs)
28905b261ecSmrg{
29005b261ecSmrg    miSpriteScreenPtr	pScreenPriv;
29105b261ecSmrg    VisualPtr		pVisual;
2924642e01fSmrg
29305b261ecSmrg    if (!DamageSetup (pScreen))
29405b261ecSmrg	return FALSE;
29505b261ecSmrg
2966747b715Smrg    if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
2976747b715Smrg	return FALSE;
2986747b715Smrg
2996747b715Smrg    if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0))
3006747b715Smrg	return FALSE;
3016747b715Smrg
3026747b715Smrg    pScreenPriv = malloc(sizeof (miSpriteScreenRec));
30305b261ecSmrg    if (!pScreenPriv)
30405b261ecSmrg	return FALSE;
3054642e01fSmrg
30605b261ecSmrg    pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
3076747b715Smrg					 NULL,
30805b261ecSmrg					 DamageReportRawRegion,
30905b261ecSmrg					 TRUE,
31005b261ecSmrg					 pScreen,
3116747b715Smrg					 pScreen);
31205b261ecSmrg
31305b261ecSmrg    if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
31405b261ecSmrg    {
3156747b715Smrg	free(pScreenPriv);
31605b261ecSmrg	return FALSE;
31705b261ecSmrg    }
31805b261ecSmrg    for (pVisual = pScreen->visuals;
31905b261ecSmrg	 pVisual->vid != pScreen->rootVisual;
32005b261ecSmrg	 pVisual++)
32105b261ecSmrg	;
32205b261ecSmrg    pScreenPriv->pVisual = pVisual;
32305b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
32405b261ecSmrg    pScreenPriv->GetImage = pScreen->GetImage;
32505b261ecSmrg    pScreenPriv->GetSpans = pScreen->GetSpans;
32605b261ecSmrg    pScreenPriv->SourceValidate = pScreen->SourceValidate;
32705b261ecSmrg
32805b261ecSmrg    pScreenPriv->CopyWindow = pScreen->CopyWindow;
3294642e01fSmrg
33005b261ecSmrg    pScreenPriv->InstallColormap = pScreen->InstallColormap;
33105b261ecSmrg    pScreenPriv->StoreColors = pScreen->StoreColors;
3324642e01fSmrg
33305b261ecSmrg    pScreenPriv->BlockHandler = pScreen->BlockHandler;
3344642e01fSmrg
3354642e01fSmrg    pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
3364642e01fSmrg    pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
3374642e01fSmrg
33805b261ecSmrg    pScreenPriv->pInstalledMap = NULL;
33905b261ecSmrg    pScreenPriv->pColormap = NULL;
34005b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].red = 0;
34105b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].green = 0;
34205b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
34305b261ecSmrg    pScreenPriv->colors[MASK_COLOR].red = 0;
34405b261ecSmrg    pScreenPriv->colors[MASK_COLOR].green = 0;
34505b261ecSmrg    pScreenPriv->colors[MASK_COLOR].blue = 0;
3466747b715Smrg    pScreenPriv->damageRegistered = 0;
3476747b715Smrg
3484642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
3494642e01fSmrg
35005b261ecSmrg    pScreen->CloseScreen = miSpriteCloseScreen;
35105b261ecSmrg    pScreen->GetImage = miSpriteGetImage;
35205b261ecSmrg    pScreen->GetSpans = miSpriteGetSpans;
35305b261ecSmrg    pScreen->SourceValidate = miSpriteSourceValidate;
3544642e01fSmrg
35505b261ecSmrg    pScreen->CopyWindow = miSpriteCopyWindow;
35605b261ecSmrg    pScreen->InstallColormap = miSpriteInstallColormap;
35705b261ecSmrg    pScreen->StoreColors = miSpriteStoreColors;
35805b261ecSmrg
35905b261ecSmrg    pScreen->BlockHandler = miSpriteBlockHandler;
3604642e01fSmrg
36105b261ecSmrg    return TRUE;
36205b261ecSmrg}
36305b261ecSmrg
36405b261ecSmrg/*
36505b261ecSmrg * Screen wrappers
36605b261ecSmrg */
36705b261ecSmrg
36805b261ecSmrg/*
36905b261ecSmrg * CloseScreen wrapper -- unwrap everything, free the private data
37005b261ecSmrg * and call the wrapped function
37105b261ecSmrg */
37205b261ecSmrg
37305b261ecSmrgstatic Bool
3744642e01fSmrgmiSpriteCloseScreen (int i, ScreenPtr pScreen)
37505b261ecSmrg{
37605b261ecSmrg    miSpriteScreenPtr   pScreenPriv;
37705b261ecSmrg
3786747b715Smrg    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
37905b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
38005b261ecSmrg    pScreen->GetImage = pScreenPriv->GetImage;
38105b261ecSmrg    pScreen->GetSpans = pScreenPriv->GetSpans;
38205b261ecSmrg    pScreen->SourceValidate = pScreenPriv->SourceValidate;
38305b261ecSmrg    pScreen->BlockHandler = pScreenPriv->BlockHandler;
38405b261ecSmrg    pScreen->InstallColormap = pScreenPriv->InstallColormap;
38505b261ecSmrg    pScreen->StoreColors = pScreenPriv->StoreColors;
38605b261ecSmrg
38705b261ecSmrg    DamageDestroy (pScreenPriv->pDamage);
3884642e01fSmrg
3896747b715Smrg    free(pScreenPriv);
39005b261ecSmrg
39105b261ecSmrg    return (*pScreen->CloseScreen) (i, pScreen);
39205b261ecSmrg}
39305b261ecSmrg
39405b261ecSmrgstatic void
3954642e01fSmrgmiSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
3964642e01fSmrg                  unsigned int format, unsigned long planemask,
3974642e01fSmrg                  char *pdstLine)
39805b261ecSmrg{
39905b261ecSmrg    ScreenPtr	    pScreen = pDrawable->pScreen;
4006747b715Smrg    DeviceIntPtr    pDev;
4014642e01fSmrg    miCursorInfoPtr pCursorInfo;
40205b261ecSmrg
4034642e01fSmrg    SCREEN_PROLOGUE (pScreen, GetImage);
40405b261ecSmrg
4056747b715Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
40605b261ecSmrg    {
4076747b715Smrg        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
4084642e01fSmrg        {
4096747b715Smrg            if (DevHasCursor(pDev))
4106747b715Smrg            {
4116747b715Smrg                 pCursorInfo = MISPRITE(pDev);
4126747b715Smrg                 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
4136747b715Smrg                      ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y,
4146747b715Smrg                                  sx, sy, w, h))
4156747b715Smrg                 {
4166747b715Smrg                     SPRITE_DEBUG (("GetImage remove\n"));
4176747b715Smrg                     miSpriteRemoveCursor (pDev, pScreen);
4186747b715Smrg                 }
4196747b715Smrg            }
4204642e01fSmrg        }
42105b261ecSmrg    }
42205b261ecSmrg
42305b261ecSmrg    (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
42405b261ecSmrg			  format, planemask, pdstLine);
42505b261ecSmrg
42605b261ecSmrg    SCREEN_EPILOGUE (pScreen, GetImage);
42705b261ecSmrg}
42805b261ecSmrg
42905b261ecSmrgstatic void
4304642e01fSmrgmiSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
4314642e01fSmrg                  int *pwidth, int nspans, char *pdstStart)
43205b261ecSmrg{
43305b261ecSmrg    ScreenPtr		    pScreen = pDrawable->pScreen;
4346747b715Smrg    DeviceIntPtr            pDev;
4354642e01fSmrg    miCursorInfoPtr         pCursorInfo;
4364642e01fSmrg
43705b261ecSmrg    SCREEN_PROLOGUE (pScreen, GetSpans);
43805b261ecSmrg
4396747b715Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
44005b261ecSmrg    {
4416747b715Smrg        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
4424642e01fSmrg        {
4436747b715Smrg            if (DevHasCursor(pDev))
4444642e01fSmrg            {
4456747b715Smrg                pCursorInfo = MISPRITE(pDev);
4466747b715Smrg
4476747b715Smrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
4484642e01fSmrg                {
4496747b715Smrg                    DDXPointPtr    pts;
4506747b715Smrg                    int    	       *widths;
4516747b715Smrg                    int    	       nPts;
4526747b715Smrg                    int    	       xorg,
4536747b715Smrg                                   yorg;
4546747b715Smrg
4556747b715Smrg                    xorg = pDrawable->x;
4566747b715Smrg                    yorg = pDrawable->y;
4576747b715Smrg
4586747b715Smrg                    for (pts = ppt, widths = pwidth, nPts = nspans;
4596747b715Smrg                            nPts--;
4606747b715Smrg                            pts++, widths++)
4614642e01fSmrg                    {
4626747b715Smrg                        if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
4636747b715Smrg                                    pts->x+xorg,*widths))
4646747b715Smrg                        {
4656747b715Smrg                            SPRITE_DEBUG (("GetSpans remove\n"));
4666747b715Smrg                            miSpriteRemoveCursor (pDev, pScreen);
4676747b715Smrg                            break;
4686747b715Smrg                        }
4694642e01fSmrg                    }
4704642e01fSmrg                }
4714642e01fSmrg            }
4724642e01fSmrg        }
47305b261ecSmrg    }
47405b261ecSmrg
47505b261ecSmrg    (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
47605b261ecSmrg
47705b261ecSmrg    SCREEN_EPILOGUE (pScreen, GetSpans);
47805b261ecSmrg}
47905b261ecSmrg
48005b261ecSmrgstatic void
4814642e01fSmrgmiSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
4824642e01fSmrg                        int height)
48305b261ecSmrg{
48405b261ecSmrg    ScreenPtr		    pScreen = pDrawable->pScreen;
4856747b715Smrg    DeviceIntPtr            pDev;
4864642e01fSmrg    miCursorInfoPtr         pCursorInfo;
4874642e01fSmrg
48805b261ecSmrg    SCREEN_PROLOGUE (pScreen, SourceValidate);
48905b261ecSmrg
4906747b715Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
49105b261ecSmrg    {
4926747b715Smrg	for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
4936747b715Smrg	{
4946747b715Smrg	    if (DevHasCursor(pDev))
4956747b715Smrg	    {
4966747b715Smrg		pCursorInfo = MISPRITE(pDev);
4976747b715Smrg		if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
4986747b715Smrg		    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
4996747b715Smrg				x, y, width, height))
5006747b715Smrg		{
5016747b715Smrg		    SPRITE_DEBUG (("SourceValidate remove\n"));
5026747b715Smrg		    miSpriteRemoveCursor (pDev, pScreen);
5036747b715Smrg		}
5046747b715Smrg	    }
5056747b715Smrg	}
50605b261ecSmrg    }
50705b261ecSmrg
50805b261ecSmrg    if (pScreen->SourceValidate)
50905b261ecSmrg	(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
51005b261ecSmrg
51105b261ecSmrg    SCREEN_EPILOGUE (pScreen, SourceValidate);
51205b261ecSmrg}
51305b261ecSmrg
51405b261ecSmrgstatic void
51505b261ecSmrgmiSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
51605b261ecSmrg{
51705b261ecSmrg    ScreenPtr	pScreen = pWindow->drawable.pScreen;
5186747b715Smrg    DeviceIntPtr            pDev;
5194642e01fSmrg    miCursorInfoPtr         pCursorInfo;
5204642e01fSmrg
52105b261ecSmrg    SCREEN_PROLOGUE (pScreen, CopyWindow);
52205b261ecSmrg
5234642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
52405b261ecSmrg    {
5254642e01fSmrg        if (DevHasCursor(pDev))
5264642e01fSmrg        {
5274642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5284642e01fSmrg            /*
5294642e01fSmrg             * Damage will take care of destination check
5304642e01fSmrg             */
5314642e01fSmrg            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
5326747b715Smrg                    RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT)
5334642e01fSmrg            {
5344642e01fSmrg                SPRITE_DEBUG (("CopyWindow remove\n"));
5354642e01fSmrg                miSpriteRemoveCursor (pDev, pScreen);
5364642e01fSmrg            }
5374642e01fSmrg        }
53805b261ecSmrg    }
53905b261ecSmrg
54005b261ecSmrg    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
54105b261ecSmrg    SCREEN_EPILOGUE (pScreen, CopyWindow);
54205b261ecSmrg}
54305b261ecSmrg
54405b261ecSmrgstatic void
5454642e01fSmrgmiSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
5464642e01fSmrg                      pointer pReadmask)
54705b261ecSmrg{
54805b261ecSmrg    ScreenPtr		pScreen = screenInfo.screens[i];
54905b261ecSmrg    miSpriteScreenPtr	pPriv;
5506747b715Smrg    DeviceIntPtr            pDev;
5514642e01fSmrg    miCursorInfoPtr         pCursorInfo;
55205b261ecSmrg
5536747b715Smrg    pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
55405b261ecSmrg    SCREEN_PROLOGUE(pScreen, BlockHandler);
5554642e01fSmrg
55605b261ecSmrg    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
55705b261ecSmrg
55805b261ecSmrg    SCREEN_EPILOGUE(pScreen, BlockHandler);
55905b261ecSmrg
5604642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
5614642e01fSmrg    {
5624642e01fSmrg        if (DevHasCursor(pDev))
5634642e01fSmrg        {
5644642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5654642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp
5664642e01fSmrg                    && pCursorInfo->pScreen == pScreen
5674642e01fSmrg                    && pCursorInfo->shouldBeUp)
5684642e01fSmrg            {
5698223e2f2Smrg                SPRITE_DEBUG (("BlockHandler save"));
5704642e01fSmrg                miSpriteSaveUnderCursor (pDev, pScreen);
5714642e01fSmrg            }
5724642e01fSmrg        }
5734642e01fSmrg    }
5744642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
57505b261ecSmrg    {
5764642e01fSmrg        if (DevHasCursor(pDev))
5774642e01fSmrg        {
5784642e01fSmrg            pCursorInfo = MISPRITE(pDev);
5794642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp &&
5804642e01fSmrg                    pCursorInfo->pScreen == pScreen &&
5814642e01fSmrg                    pCursorInfo->shouldBeUp)
5824642e01fSmrg            {
5834642e01fSmrg                SPRITE_DEBUG (("BlockHandler restore\n"));
5844642e01fSmrg                miSpriteRestoreCursor (pDev, pScreen);
5854642e01fSmrg            }
5864642e01fSmrg        }
58705b261ecSmrg    }
58805b261ecSmrg}
58905b261ecSmrg
59005b261ecSmrgstatic void
5914642e01fSmrgmiSpriteInstallColormap (ColormapPtr pMap)
59205b261ecSmrg{
59305b261ecSmrg    ScreenPtr		pScreen = pMap->pScreen;
59405b261ecSmrg    miSpriteScreenPtr	pPriv;
59505b261ecSmrg
5966747b715Smrg    pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
59705b261ecSmrg    SCREEN_PROLOGUE(pScreen, InstallColormap);
5984642e01fSmrg
59905b261ecSmrg    (*pScreen->InstallColormap) (pMap);
60005b261ecSmrg
60105b261ecSmrg    SCREEN_EPILOGUE(pScreen, InstallColormap);
60205b261ecSmrg
6034642e01fSmrg    /* InstallColormap can be called before devices are initialized. */
60405b261ecSmrg    pPriv->pInstalledMap = pMap;
60505b261ecSmrg    if (pPriv->pColormap != pMap)
60605b261ecSmrg    {
6074642e01fSmrg        DeviceIntPtr pDev;
6084642e01fSmrg        miCursorInfoPtr     pCursorInfo;
6094642e01fSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
6104642e01fSmrg        {
6114642e01fSmrg            if (DevHasCursor(pDev))
6124642e01fSmrg            {
6134642e01fSmrg                pCursorInfo = MISPRITE(pDev);
6144642e01fSmrg                pCursorInfo->checkPixels = TRUE;
6154642e01fSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
6164642e01fSmrg                    miSpriteRemoveCursor(pDev, pScreen);
6174642e01fSmrg            }
6184642e01fSmrg        }
6194642e01fSmrg
62005b261ecSmrg    }
62105b261ecSmrg}
62205b261ecSmrg
62305b261ecSmrgstatic void
6244642e01fSmrgmiSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
62505b261ecSmrg{
62605b261ecSmrg    ScreenPtr		pScreen = pMap->pScreen;
62705b261ecSmrg    miSpriteScreenPtr	pPriv;
62805b261ecSmrg    int			i;
62905b261ecSmrg    int			updated;
63005b261ecSmrg    VisualPtr		pVisual;
6316747b715Smrg    DeviceIntPtr        pDev;
6324642e01fSmrg    miCursorInfoPtr     pCursorInfo;
63305b261ecSmrg
6346747b715Smrg    pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
63505b261ecSmrg    SCREEN_PROLOGUE(pScreen, StoreColors);
6364642e01fSmrg
63705b261ecSmrg    (*pScreen->StoreColors) (pMap, ndef, pdef);
63805b261ecSmrg
63905b261ecSmrg    SCREEN_EPILOGUE(pScreen, StoreColors);
64005b261ecSmrg
64105b261ecSmrg    if (pPriv->pColormap == pMap)
64205b261ecSmrg    {
6434642e01fSmrg        updated = 0;
6444642e01fSmrg        pVisual = pMap->pVisual;
6454642e01fSmrg        if (pVisual->class == DirectColor)
6464642e01fSmrg        {
6474642e01fSmrg            /* Direct color - match on any of the subfields */
64805b261ecSmrg
64905b261ecSmrg#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
65005b261ecSmrg
6514642e01fSmrg#define UpdateDAC(dev, plane,dac,mask) {\
6524642e01fSmrg    if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
6534642e01fSmrg	dev->colors[plane].dac = pdef[i].dac; \
65405b261ecSmrg	updated = 1; \
65505b261ecSmrg    } \
65605b261ecSmrg}
65705b261ecSmrg
6584642e01fSmrg#define CheckDirect(dev, plane) \
6594642e01fSmrg	    UpdateDAC(dev, plane,red,redMask) \
6604642e01fSmrg	    UpdateDAC(dev, plane,green,greenMask) \
6614642e01fSmrg	    UpdateDAC(dev, plane,blue,blueMask)
6624642e01fSmrg
6634642e01fSmrg            for (i = 0; i < ndef; i++)
6644642e01fSmrg            {
6654642e01fSmrg                CheckDirect (pPriv, SOURCE_COLOR)
6664642e01fSmrg                CheckDirect (pPriv, MASK_COLOR)
6674642e01fSmrg            }
6684642e01fSmrg        }
6694642e01fSmrg        else
6704642e01fSmrg        {
6714642e01fSmrg            /* PseudoColor/GrayScale - match on exact pixel */
6724642e01fSmrg            for (i = 0; i < ndef; i++)
6734642e01fSmrg            {
6744642e01fSmrg                if (pdef[i].pixel ==
6754642e01fSmrg                        pPriv->colors[SOURCE_COLOR].pixel)
6764642e01fSmrg                {
6774642e01fSmrg                    pPriv->colors[SOURCE_COLOR] = pdef[i];
6784642e01fSmrg                    if (++updated == 2)
6794642e01fSmrg                        break;
6804642e01fSmrg                }
6814642e01fSmrg                if (pdef[i].pixel ==
6824642e01fSmrg                        pPriv->colors[MASK_COLOR].pixel)
6834642e01fSmrg                {
6844642e01fSmrg                    pPriv->colors[MASK_COLOR] = pdef[i];
6854642e01fSmrg                    if (++updated == 2)
6864642e01fSmrg                        break;
6874642e01fSmrg                }
6884642e01fSmrg            }
6894642e01fSmrg        }
6904642e01fSmrg        if (updated)
6914642e01fSmrg        {
6924642e01fSmrg            for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
6934642e01fSmrg            {
6944642e01fSmrg                if (DevHasCursor(pDev))
6954642e01fSmrg                {
6964642e01fSmrg                    pCursorInfo = MISPRITE(pDev);
6974642e01fSmrg                    pCursorInfo->checkPixels = TRUE;
6984642e01fSmrg                    if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
6994642e01fSmrg                        miSpriteRemoveCursor (pDev, pScreen);
7004642e01fSmrg                }
7014642e01fSmrg            }
7024642e01fSmrg        }
70305b261ecSmrg    }
70405b261ecSmrg}
70505b261ecSmrg
70605b261ecSmrgstatic void
7074642e01fSmrgmiSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
70805b261ecSmrg{
7096747b715Smrg    miSpriteScreenPtr   pScreenPriv =
7104642e01fSmrg	dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
71105b261ecSmrg    CursorPtr		pCursor;
71205b261ecSmrg    xColorItem		*sourceColor, *maskColor;
71305b261ecSmrg
7144642e01fSmrg    pCursor = pDevCursor->pCursor;
71505b261ecSmrg    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
71605b261ecSmrg    maskColor = &pScreenPriv->colors[MASK_COLOR];
71705b261ecSmrg    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
71805b261ecSmrg	!(pCursor->foreRed == sourceColor->red &&
71905b261ecSmrg	  pCursor->foreGreen == sourceColor->green &&
72005b261ecSmrg          pCursor->foreBlue == sourceColor->blue &&
72105b261ecSmrg	  pCursor->backRed == maskColor->red &&
72205b261ecSmrg	  pCursor->backGreen == maskColor->green &&
72305b261ecSmrg	  pCursor->backBlue == maskColor->blue))
72405b261ecSmrg    {
72505b261ecSmrg	pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
72605b261ecSmrg	sourceColor->red = pCursor->foreRed;
72705b261ecSmrg	sourceColor->green = pCursor->foreGreen;
72805b261ecSmrg	sourceColor->blue = pCursor->foreBlue;
72905b261ecSmrg	FakeAllocColor (pScreenPriv->pColormap, sourceColor);
73005b261ecSmrg	maskColor->red = pCursor->backRed;
73105b261ecSmrg	maskColor->green = pCursor->backGreen;
73205b261ecSmrg	maskColor->blue = pCursor->backBlue;
73305b261ecSmrg	FakeAllocColor (pScreenPriv->pColormap, maskColor);
73405b261ecSmrg	/* "free" the pixels right away, don't let this confuse you */
73505b261ecSmrg	FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
73605b261ecSmrg	FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
73705b261ecSmrg    }
73805b261ecSmrg
7394642e01fSmrg    pDevCursor->checkPixels = FALSE;
74005b261ecSmrg
74105b261ecSmrg}
74205b261ecSmrg
74305b261ecSmrg/*
74405b261ecSmrg * miPointer interface routines
74505b261ecSmrg */
74605b261ecSmrg
74705b261ecSmrg#define SPRITE_PAD  8
74805b261ecSmrg
74905b261ecSmrgstatic Bool
7504642e01fSmrgmiSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
75105b261ecSmrg{
7524642e01fSmrg    miCursorInfoPtr pCursorInfo;
7534642e01fSmrg
7546747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
7554642e01fSmrg        return FALSE;
7566747b715Smrg
7574642e01fSmrg    pCursorInfo = MISPRITE(pDev);
7584642e01fSmrg
7594642e01fSmrg    if (pCursor == pCursorInfo->pCursor)
7604642e01fSmrg	pCursorInfo->checkPixels = TRUE;
76105b261ecSmrg
7626747b715Smrg    return miDCRealizeCursor(pScreen, pCursor);
76305b261ecSmrg}
76405b261ecSmrg
76505b261ecSmrgstatic Bool
7664642e01fSmrgmiSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
76705b261ecSmrg{
7686747b715Smrg    return miDCUnrealizeCursor(pScreen, pCursor);
76905b261ecSmrg}
77005b261ecSmrg
77105b261ecSmrgstatic void
7724642e01fSmrgmiSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
7734642e01fSmrg                   CursorPtr pCursor, int x, int y)
77405b261ecSmrg{
7754642e01fSmrg    miCursorInfoPtr pPointer;
7764642e01fSmrg
7776747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
7784642e01fSmrg        return;
7796747b715Smrg
7804642e01fSmrg    pPointer = MISPRITE(pDev);
7814642e01fSmrg
78205b261ecSmrg    if (!pCursor)
78305b261ecSmrg    {
7844642e01fSmrg    	pPointer->shouldBeUp = FALSE;
7854642e01fSmrg    	if (pPointer->isUp)
7864642e01fSmrg	    miSpriteRemoveCursor (pDev, pScreen);
7874642e01fSmrg	pPointer->pCursor = 0;
78805b261ecSmrg	return;
78905b261ecSmrg    }
7904642e01fSmrg    pPointer->shouldBeUp = TRUE;
7914642e01fSmrg    if (pPointer->x == x &&
7924642e01fSmrg	pPointer->y == y &&
7934642e01fSmrg	pPointer->pCursor == pCursor &&
7944642e01fSmrg	!pPointer->checkPixels)
79505b261ecSmrg    {
79605b261ecSmrg	return;
79705b261ecSmrg    }
7984642e01fSmrg    pPointer->x = x;
7994642e01fSmrg    pPointer->y = y;
8004642e01fSmrg    pPointer->pCacheWin = NullWindow;
8014642e01fSmrg    if (pPointer->checkPixels || pPointer->pCursor != pCursor)
80205b261ecSmrg    {
8034642e01fSmrg	pPointer->pCursor = pCursor;
8044642e01fSmrg	miSpriteFindColors (pPointer, pScreen);
80505b261ecSmrg    }
8064642e01fSmrg    if (pPointer->isUp) {
8076747b715Smrg	/* TODO: reimplement flicker-free MoveCursor */
8086747b715Smrg	SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id));
8096747b715Smrg	miSpriteRemoveCursor (pDev, pScreen);
81005b261ecSmrg    }
8114642e01fSmrg
8124642e01fSmrg    if (!pPointer->isUp && pPointer->pCursor)
81305b261ecSmrg    {
8144642e01fSmrg	SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id));
8154642e01fSmrg        miSpriteSaveUnderCursor(pDev, pScreen);
8164642e01fSmrg	miSpriteRestoreCursor (pDev, pScreen);
81705b261ecSmrg    }
8184642e01fSmrg
81905b261ecSmrg}
82005b261ecSmrg
82105b261ecSmrgstatic void
8224642e01fSmrgmiSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
82305b261ecSmrg{
8244642e01fSmrg    CursorPtr pCursor;
82505b261ecSmrg
8266747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
8274642e01fSmrg        return;
8286747b715Smrg
8294642e01fSmrg    pCursor = MISPRITE(pDev)->pCursor;
8304642e01fSmrg
8314642e01fSmrg    miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
8324642e01fSmrg}
8334642e01fSmrg
8344642e01fSmrg
8354642e01fSmrgstatic Bool
8364642e01fSmrgmiSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
8374642e01fSmrg{
8384642e01fSmrg    miCursorInfoPtr pCursorInfo;
8394642e01fSmrg    int ret = FALSE;
8404642e01fSmrg
8416747b715Smrg    pCursorInfo = malloc(sizeof(miCursorInfoRec));
8424642e01fSmrg    if (!pCursorInfo)
8434642e01fSmrg        return FALSE;
8444642e01fSmrg
8454642e01fSmrg    pCursorInfo->pCursor = NULL;
8464642e01fSmrg    pCursorInfo->x = 0;
8474642e01fSmrg    pCursorInfo->y = 0;
8484642e01fSmrg    pCursorInfo->isUp = FALSE;
8494642e01fSmrg    pCursorInfo->shouldBeUp = FALSE;
8504642e01fSmrg    pCursorInfo->pCacheWin = NullWindow;
8514642e01fSmrg    pCursorInfo->isInCacheWin = FALSE;
8524642e01fSmrg    pCursorInfo->checkPixels = TRUE;
8534642e01fSmrg    pCursorInfo->pScreen = FALSE;
8544642e01fSmrg
8556747b715Smrg    ret = miDCDeviceInitialize(pDev, pScreen);
8564642e01fSmrg    if (!ret)
8574642e01fSmrg    {
8586747b715Smrg        free(pCursorInfo);
8594642e01fSmrg        pCursorInfo = NULL;
8604642e01fSmrg    }
8614642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo);
8624642e01fSmrg    return ret;
8634642e01fSmrg}
8644642e01fSmrg
8654642e01fSmrgstatic void
8664642e01fSmrgmiSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
8674642e01fSmrg{
8684642e01fSmrg    if (DevHasCursor(pDev))
8696747b715Smrg        miDCDeviceCleanup(pDev, pScreen);
87005b261ecSmrg}
87105b261ecSmrg
87205b261ecSmrg/*
87305b261ecSmrg * undraw/draw cursor
87405b261ecSmrg */
87505b261ecSmrg
87605b261ecSmrgstatic void
8774642e01fSmrgmiSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
87805b261ecSmrg{
87905b261ecSmrg    miSpriteScreenPtr   pScreenPriv;
8804642e01fSmrg    miCursorInfoPtr     pCursorInfo;
8814642e01fSmrg
88205b261ecSmrg
8836747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
8844642e01fSmrg        return;
8856747b715Smrg
88605b261ecSmrg    DamageDrawInternal (pScreen, TRUE);
8876747b715Smrg    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
8884642e01fSmrg    pCursorInfo = MISPRITE(pDev);
8894642e01fSmrg
8904642e01fSmrg    miSpriteIsDown(pCursorInfo);
8914642e01fSmrg    pCursorInfo->pCacheWin = NullWindow;
8924642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
8936747b715Smrg    if (!miDCRestoreUnderCursor(pDev,
8946747b715Smrg                                pScreen,
8956747b715Smrg                                pCursorInfo->saved.x1,
8966747b715Smrg                                pCursorInfo->saved.y1,
8976747b715Smrg                                pCursorInfo->saved.x2 -
8986747b715Smrg                                pCursorInfo->saved.x1,
8996747b715Smrg                                pCursorInfo->saved.y2 -
9006747b715Smrg                                pCursorInfo->saved.y1))
90105b261ecSmrg    {
9026747b715Smrg        miSpriteIsUp(pCursorInfo);
90305b261ecSmrg    }
9044642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
90505b261ecSmrg    DamageDrawInternal (pScreen, FALSE);
90605b261ecSmrg}
90705b261ecSmrg
9084642e01fSmrg/*
9094642e01fSmrg * Called from the block handler, saves area under cursor
9104642e01fSmrg * before waiting for something to do.
9114642e01fSmrg */
9124642e01fSmrg
9134642e01fSmrgstatic void
9144642e01fSmrgmiSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
9154642e01fSmrg{
9164642e01fSmrg    miSpriteScreenPtr   pScreenPriv;
9174642e01fSmrg    int			x, y;
9184642e01fSmrg    CursorPtr		pCursor;
9194642e01fSmrg    miCursorInfoPtr     pCursorInfo;
9204642e01fSmrg
9216747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
9224642e01fSmrg        return;
9236747b715Smrg
9244642e01fSmrg    DamageDrawInternal (pScreen, TRUE);
9256747b715Smrg    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
9264642e01fSmrg    pCursorInfo = MISPRITE(pDev);
9274642e01fSmrg
9284642e01fSmrg    miSpriteComputeSaved (pDev, pScreen);
9294642e01fSmrg    pCursor = pCursorInfo->pCursor;
9304642e01fSmrg
9314642e01fSmrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
9324642e01fSmrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
9334642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
9344642e01fSmrg
9356747b715Smrg    miDCSaveUnderCursor(pDev,
9366747b715Smrg                        pScreen,
9376747b715Smrg                        pCursorInfo->saved.x1,
9386747b715Smrg                        pCursorInfo->saved.y1,
9396747b715Smrg                        pCursorInfo->saved.x2 -
9406747b715Smrg                        pCursorInfo->saved.x1,
9416747b715Smrg                        pCursorInfo->saved.y2 -
9426747b715Smrg                        pCursorInfo->saved.y1);
9434642e01fSmrg    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
9444642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
9454642e01fSmrg    DamageDrawInternal (pScreen, FALSE);
9464642e01fSmrg}
9474642e01fSmrg
9484642e01fSmrg
94905b261ecSmrg/*
95005b261ecSmrg * Called from the block handler, restores the cursor
95105b261ecSmrg * before waiting for something to do.
95205b261ecSmrg */
95305b261ecSmrg
95405b261ecSmrgstatic void
9554642e01fSmrgmiSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
95605b261ecSmrg{
95705b261ecSmrg    miSpriteScreenPtr   pScreenPriv;
95805b261ecSmrg    int			x, y;
95905b261ecSmrg    CursorPtr		pCursor;
9604642e01fSmrg    miCursorInfoPtr     pCursorInfo;
9614642e01fSmrg
9626747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
9634642e01fSmrg        return;
96405b261ecSmrg
96505b261ecSmrg    DamageDrawInternal (pScreen, TRUE);
9666747b715Smrg    pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
9674642e01fSmrg    pCursorInfo = MISPRITE(pDev);
9684642e01fSmrg
9694642e01fSmrg    miSpriteComputeSaved (pDev, pScreen);
9704642e01fSmrg    pCursor = pCursorInfo->pCursor;
9714642e01fSmrg
9724642e01fSmrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
9734642e01fSmrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
9744642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
9754642e01fSmrg    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
9764642e01fSmrg    if (pCursorInfo->checkPixels)
9774642e01fSmrg        miSpriteFindColors (pCursorInfo, pScreen);
9786747b715Smrg    if (miDCPutUpCursor(pDev, pScreen,
9794642e01fSmrg                pCursor, x, y,
9804642e01fSmrg                pScreenPriv->colors[SOURCE_COLOR].pixel,
9814642e01fSmrg                pScreenPriv->colors[MASK_COLOR].pixel))
98205b261ecSmrg    {
9834642e01fSmrg        miSpriteIsUp(pCursorInfo);
9844642e01fSmrg        pCursorInfo->pScreen = pScreen;
98505b261ecSmrg    }
9864642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
98705b261ecSmrg    DamageDrawInternal (pScreen, FALSE);
98805b261ecSmrg}
98905b261ecSmrg
99005b261ecSmrg/*
99105b261ecSmrg * compute the desired area of the screen to save
99205b261ecSmrg */
99305b261ecSmrg
99405b261ecSmrgstatic void
9954642e01fSmrgmiSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
99605b261ecSmrg{
99705b261ecSmrg    int		    x, y, w, h;
99805b261ecSmrg    int		    wpad, hpad;
99905b261ecSmrg    CursorPtr	    pCursor;
10004642e01fSmrg    miCursorInfoPtr pCursorInfo;
100105b261ecSmrg
10026747b715Smrg    if (!IsMaster(pDev) && !pDev->u.master)
10034642e01fSmrg        return;
10046747b715Smrg
10054642e01fSmrg    pCursorInfo = MISPRITE(pDev);
10064642e01fSmrg
10074642e01fSmrg    pCursor = pCursorInfo->pCursor;
10084642e01fSmrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
10094642e01fSmrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
101005b261ecSmrg    w = pCursor->bits->width;
101105b261ecSmrg    h = pCursor->bits->height;
101205b261ecSmrg    wpad = SPRITE_PAD;
101305b261ecSmrg    hpad = SPRITE_PAD;
10144642e01fSmrg    pCursorInfo->saved.x1 = x - wpad;
10154642e01fSmrg    pCursorInfo->saved.y1 = y - hpad;
10164642e01fSmrg    pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
10174642e01fSmrg    pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
101805b261ecSmrg}
10194642e01fSmrg
1020