misprite.c revision 1b5d61b8
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    Bool checkPixels;           /* check colormap collision */
6335c4bbdfSmrg    ScreenPtr pScreen;
646747b715Smrg} miCursorInfoRec, *miCursorInfoPtr;
656747b715Smrg
666747b715Smrg/*
676747b715Smrg * per screen information
686747b715Smrg */
696747b715Smrg
706747b715Smrgtypedef struct {
716747b715Smrg    /* screen procedures */
7235c4bbdfSmrg    CloseScreenProcPtr CloseScreen;
7335c4bbdfSmrg    GetImageProcPtr GetImage;
7435c4bbdfSmrg    GetSpansProcPtr GetSpans;
7535c4bbdfSmrg    SourceValidateProcPtr SourceValidate;
7635c4bbdfSmrg
776747b715Smrg    /* window procedures */
7835c4bbdfSmrg    CopyWindowProcPtr CopyWindow;
7935c4bbdfSmrg
806747b715Smrg    /* colormap procedures */
8135c4bbdfSmrg    InstallColormapProcPtr InstallColormap;
8235c4bbdfSmrg    StoreColorsProcPtr StoreColors;
8335c4bbdfSmrg
846747b715Smrg    /* os layer procedures */
8535c4bbdfSmrg    ScreenBlockHandlerProcPtr BlockHandler;
8635c4bbdfSmrg
8735c4bbdfSmrg    xColorItem colors[2];
8835c4bbdfSmrg    ColormapPtr pInstalledMap;
8935c4bbdfSmrg    ColormapPtr pColormap;
9035c4bbdfSmrg    VisualPtr pVisual;
9135c4bbdfSmrg    DamagePtr pDamage;          /* damage tracking structure */
9235c4bbdfSmrg    Bool damageRegistered;
9335c4bbdfSmrg    int numberOfCursors;
946747b715Smrg} miSpriteScreenRec, *miSpriteScreenPtr;
956747b715Smrg
966747b715Smrg#define SOURCE_COLOR	0
976747b715Smrg#define MASK_COLOR	1
986747b715Smrg
996747b715Smrg/*
1006747b715Smrg * Overlap BoxPtr and Box elements
1016747b715Smrg */
1026747b715Smrg#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
1036747b715Smrg 	(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
1046747b715Smrg	 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
1056747b715Smrg
1066747b715Smrg/*
1076747b715Smrg * Overlap BoxPtr, origins, and rectangle
1086747b715Smrg */
1096747b715Smrg#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
1106747b715Smrg    BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
1116747b715Smrg
1126747b715Smrg/*
1136747b715Smrg * Overlap BoxPtr, origins and RectPtr
1146747b715Smrg */
1156747b715Smrg#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
1166747b715Smrg    ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
1176747b715Smrg		(int)((pRect)->width), (int)((pRect)->height))
1186747b715Smrg/*
1196747b715Smrg * Overlap BoxPtr and horizontal span
1206747b715Smrg */
1216747b715Smrg#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
12205b261ecSmrg
1236747b715Smrg#define LINE_SORT(x1,y1,x2,y2) \
1246747b715Smrg{ int _t; \
1256747b715Smrg  if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
1266747b715Smrg  if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
1276747b715Smrg
1286747b715Smrg#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
1296747b715Smrg    BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
1304642e01fSmrg
13105b261ecSmrg#define SPRITE_DEBUG_ENABLE 0
13205b261ecSmrg#if SPRITE_DEBUG_ENABLE
13305b261ecSmrg#define SPRITE_DEBUG(x)	ErrorF x
13405b261ecSmrg#else
13505b261ecSmrg#define SPRITE_DEBUG(x)
13605b261ecSmrg#endif
13705b261ecSmrg
1381b5d61b8Smrgstatic DevPrivateKeyRec miSpriteScreenKeyRec;
1391b5d61b8Smrgstatic DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
1401b5d61b8Smrg
1411b5d61b8Smrgstatic miSpriteScreenPtr
1421b5d61b8SmrgGetSpriteScreen(ScreenPtr pScreen)
1431b5d61b8Smrg{
1441b5d61b8Smrg    return dixLookupPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec);
1451b5d61b8Smrg}
1461b5d61b8Smrg
1471b5d61b8Smrgstatic miCursorInfoPtr
1481b5d61b8SmrgGetSprite(DeviceIntPtr dev)
1491b5d61b8Smrg{
1501b5d61b8Smrg    if (IsFloating(dev))
1511b5d61b8Smrg       return dixLookupPrivate(&dev->devPrivates, &miSpriteDevPrivatesKeyRec);
1521b5d61b8Smrg
1531b5d61b8Smrg    return dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates,
1541b5d61b8Smrg                            &miSpriteDevPrivatesKeyRec);
1551b5d61b8Smrg}
1564642e01fSmrg
1574642e01fSmrgstatic void
1584642e01fSmrgmiSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1594642e01fSmrg{
1606747b715Smrg    if (pScreenPriv->damageRegistered) {
16135c4bbdfSmrg        DamageUnregister(pScreenPriv->pDamage);
16235c4bbdfSmrg        pScreenPriv->damageRegistered = 0;
1634642e01fSmrg    }
1644642e01fSmrg}
1654642e01fSmrg
1664642e01fSmrgstatic void
1674642e01fSmrgmiSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1684642e01fSmrg{
1696747b715Smrg    if (!pScreenPriv->damageRegistered) {
17035c4bbdfSmrg        pScreenPriv->damageRegistered = 1;
17135c4bbdfSmrg        DamageRegister(&(pScreen->GetScreenPixmap(pScreen)->drawable),
17235c4bbdfSmrg                       pScreenPriv->pDamage);
1734642e01fSmrg    }
1744642e01fSmrg}
1754642e01fSmrg
1764642e01fSmrgstatic void
1774642e01fSmrgmiSpriteIsUp(miCursorInfoPtr pDevCursor)
1784642e01fSmrg{
1794642e01fSmrg    pDevCursor->isUp = TRUE;
1804642e01fSmrg}
1814642e01fSmrg
1824642e01fSmrgstatic void
1834642e01fSmrgmiSpriteIsDown(miCursorInfoPtr pDevCursor)
1844642e01fSmrg{
1854642e01fSmrg    pDevCursor->isUp = FALSE;
1864642e01fSmrg}
1874642e01fSmrg
18805b261ecSmrg/*
18905b261ecSmrg * screen wrappers
19005b261ecSmrg */
19105b261ecSmrg
19235c4bbdfSmrgstatic Bool miSpriteCloseScreen(ScreenPtr pScreen);
19335c4bbdfSmrgstatic void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
19435c4bbdfSmrg                             int w, int h, unsigned int format,
19535c4bbdfSmrg                             unsigned long planemask, char *pdstLine);
19635c4bbdfSmrgstatic void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
19735c4bbdfSmrg                             DDXPointPtr ppt, int *pwidth, int nspans,
19835c4bbdfSmrg                             char *pdstStart);
19935c4bbdfSmrgstatic void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
20035c4bbdfSmrg                                   int width, int height,
20135c4bbdfSmrg                                   unsigned int subWindowMode);
20235c4bbdfSmrgstatic void miSpriteCopyWindow(WindowPtr pWindow,
20335c4bbdfSmrg                               DDXPointRec ptOldOrg, RegionPtr prgnSrc);
2041b5d61b8Smrgstatic void miSpriteBlockHandler(ScreenPtr pScreen, void *timeout);
20535c4bbdfSmrgstatic void miSpriteInstallColormap(ColormapPtr pMap);
20635c4bbdfSmrgstatic void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef);
20735c4bbdfSmrg
20835c4bbdfSmrgstatic void miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen);
20935c4bbdfSmrg
21035c4bbdfSmrgstatic Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
21135c4bbdfSmrg                                           ScreenPtr pScreen);
21235c4bbdfSmrgstatic void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
21305b261ecSmrg
2149ace9065Smrg#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
2159ace9065Smrg   (pPriv)->field)
2169ace9065Smrg#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
2179ace9065Smrg    ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
21805b261ecSmrg
21905b261ecSmrg/*
22005b261ecSmrg * pointer-sprite method table
22105b261ecSmrg */
22205b261ecSmrg
2234642e01fSmrgstatic Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2244642e01fSmrg                                  CursorPtr pCursor);
2254642e01fSmrgstatic Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2264642e01fSmrg                                    CursorPtr pCursor);
2274642e01fSmrgstatic void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2284642e01fSmrg                              CursorPtr pCursor, int x, int y);
2294642e01fSmrgstatic void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2304642e01fSmrg                               int x, int y);
23105b261ecSmrg
2326747b715SmrgmiPointerSpriteFuncRec miSpritePointerFuncs = {
23305b261ecSmrg    miSpriteRealizeCursor,
23405b261ecSmrg    miSpriteUnrealizeCursor,
23505b261ecSmrg    miSpriteSetCursor,
23605b261ecSmrg    miSpriteMoveCursor,
2374642e01fSmrg    miSpriteDeviceCursorInitialize,
2384642e01fSmrg    miSpriteDeviceCursorCleanup,
23905b261ecSmrg};
24005b261ecSmrg
24105b261ecSmrg/*
24205b261ecSmrg * other misc functions
24305b261ecSmrg */
24405b261ecSmrg
24535c4bbdfSmrgstatic void miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
24635c4bbdfSmrgstatic void miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
24735c4bbdfSmrgstatic void miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
24805b261ecSmrg
2499ace9065Smrgstatic void
2509ace9065SmrgmiSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
2519ace9065Smrg{
2529ace9065Smrg    if (!pScreenPriv->BlockHandler) {
2539ace9065Smrg        pScreenPriv->BlockHandler = pScreen->BlockHandler;
2549ace9065Smrg        pScreen->BlockHandler = miSpriteBlockHandler;
2559ace9065Smrg    }
2569ace9065Smrg}
2579ace9065Smrg
25805b261ecSmrgstatic void
25935c4bbdfSmrgmiSpriteReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
26005b261ecSmrg{
26135c4bbdfSmrg    ScreenPtr pScreen = closure;
26235c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
26335c4bbdfSmrg    DeviceIntPtr pDev;
26435c4bbdfSmrg
26535c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
26635c4bbdfSmrg        if (DevHasCursor(pDev)) {
2671b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
2684642e01fSmrg
2694642e01fSmrg            if (pCursorInfo->isUp &&
2704642e01fSmrg                pCursorInfo->pScreen == pScreen &&
27135c4bbdfSmrg                RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) {
2724642e01fSmrg                SPRITE_DEBUG(("Damage remove\n"));
27335c4bbdfSmrg                miSpriteRemoveCursor(pDev, pScreen);
2744642e01fSmrg            }
2754642e01fSmrg        }
27605b261ecSmrg    }
27705b261ecSmrg}
27805b261ecSmrg
27905b261ecSmrg/*
28005b261ecSmrg * miSpriteInitialize -- called from device-dependent screen
28105b261ecSmrg * initialization proc after all of the function pointers have
28205b261ecSmrg * been stored in the screen structure.
28305b261ecSmrg */
28405b261ecSmrg
28505b261ecSmrgBool
28635c4bbdfSmrgmiSpriteInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
28705b261ecSmrg{
28835c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
28935c4bbdfSmrg    VisualPtr pVisual;
2904642e01fSmrg
29135c4bbdfSmrg    if (!DamageSetup(pScreen))
29235c4bbdfSmrg        return FALSE;
29305b261ecSmrg
2946747b715Smrg    if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
29535c4bbdfSmrg        return FALSE;
2966747b715Smrg
29735c4bbdfSmrg    if (!dixRegisterPrivateKey
29835c4bbdfSmrg        (&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec)))
29935c4bbdfSmrg        return FALSE;
3006747b715Smrg
30135c4bbdfSmrg    pScreenPriv = malloc(sizeof(miSpriteScreenRec));
30205b261ecSmrg    if (!pScreenPriv)
30335c4bbdfSmrg        return FALSE;
30435c4bbdfSmrg
30535c4bbdfSmrg    pScreenPriv->pDamage = DamageCreate(miSpriteReportDamage,
30635c4bbdfSmrg                                        NULL,
30735c4bbdfSmrg                                        DamageReportRawRegion,
30835c4bbdfSmrg                                        TRUE, pScreen, pScreen);
30935c4bbdfSmrg
31035c4bbdfSmrg    if (!miPointerInitialize(pScreen, &miSpritePointerFuncs, screenFuncs, TRUE)) {
31135c4bbdfSmrg        free(pScreenPriv);
31235c4bbdfSmrg        return FALSE;
31305b261ecSmrg    }
31405b261ecSmrg    for (pVisual = pScreen->visuals;
31535c4bbdfSmrg         pVisual->vid != pScreen->rootVisual; pVisual++);
31605b261ecSmrg    pScreenPriv->pVisual = pVisual;
31705b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
31805b261ecSmrg    pScreenPriv->GetImage = pScreen->GetImage;
31905b261ecSmrg    pScreenPriv->GetSpans = pScreen->GetSpans;
32005b261ecSmrg    pScreenPriv->SourceValidate = pScreen->SourceValidate;
32105b261ecSmrg
32205b261ecSmrg    pScreenPriv->CopyWindow = pScreen->CopyWindow;
3234642e01fSmrg
32405b261ecSmrg    pScreenPriv->InstallColormap = pScreen->InstallColormap;
32505b261ecSmrg    pScreenPriv->StoreColors = pScreen->StoreColors;
3264642e01fSmrg
3279ace9065Smrg    pScreenPriv->BlockHandler = NULL;
3284642e01fSmrg
32905b261ecSmrg    pScreenPriv->pInstalledMap = NULL;
33005b261ecSmrg    pScreenPriv->pColormap = NULL;
33105b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].red = 0;
33205b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].green = 0;
33305b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
33405b261ecSmrg    pScreenPriv->colors[MASK_COLOR].red = 0;
33505b261ecSmrg    pScreenPriv->colors[MASK_COLOR].green = 0;
33605b261ecSmrg    pScreenPriv->colors[MASK_COLOR].blue = 0;
3376747b715Smrg    pScreenPriv->damageRegistered = 0;
3389ace9065Smrg    pScreenPriv->numberOfCursors = 0;
3396747b715Smrg
3401b5d61b8Smrg    dixSetPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec, pScreenPriv);
3414642e01fSmrg
34205b261ecSmrg    pScreen->CloseScreen = miSpriteCloseScreen;
34305b261ecSmrg    pScreen->GetImage = miSpriteGetImage;
34405b261ecSmrg    pScreen->GetSpans = miSpriteGetSpans;
34505b261ecSmrg    pScreen->SourceValidate = miSpriteSourceValidate;
3464642e01fSmrg
34705b261ecSmrg    pScreen->CopyWindow = miSpriteCopyWindow;
34805b261ecSmrg    pScreen->InstallColormap = miSpriteInstallColormap;
34905b261ecSmrg    pScreen->StoreColors = miSpriteStoreColors;
35005b261ecSmrg
35105b261ecSmrg    return TRUE;
35205b261ecSmrg}
35305b261ecSmrg
35405b261ecSmrg/*
35505b261ecSmrg * Screen wrappers
35605b261ecSmrg */
35705b261ecSmrg
35805b261ecSmrg/*
35905b261ecSmrg * CloseScreen wrapper -- unwrap everything, free the private data
36005b261ecSmrg * and call the wrapped function
36105b261ecSmrg */
36205b261ecSmrg
36305b261ecSmrgstatic Bool
36435c4bbdfSmrgmiSpriteCloseScreen(ScreenPtr pScreen)
36505b261ecSmrg{
36635c4bbdfSmrg    miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
36705b261ecSmrg
36805b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
36905b261ecSmrg    pScreen->GetImage = pScreenPriv->GetImage;
37005b261ecSmrg    pScreen->GetSpans = pScreenPriv->GetSpans;
37105b261ecSmrg    pScreen->SourceValidate = pScreenPriv->SourceValidate;
37205b261ecSmrg    pScreen->InstallColormap = pScreenPriv->InstallColormap;
37305b261ecSmrg    pScreen->StoreColors = pScreenPriv->StoreColors;
37405b261ecSmrg
37535c4bbdfSmrg    DamageDestroy(pScreenPriv->pDamage);
3764642e01fSmrg
3776747b715Smrg    free(pScreenPriv);
37805b261ecSmrg
37935c4bbdfSmrg    return (*pScreen->CloseScreen) (pScreen);
38005b261ecSmrg}
38105b261ecSmrg
38205b261ecSmrgstatic void
38335c4bbdfSmrgmiSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
38435c4bbdfSmrg                 unsigned int format, unsigned long planemask, char *pdstLine)
38505b261ecSmrg{
38635c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
38735c4bbdfSmrg    DeviceIntPtr pDev;
38835c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
38935c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
39035c4bbdfSmrg
39135c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, GetImage);
39235c4bbdfSmrg
39335c4bbdfSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
39435c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
39535c4bbdfSmrg            if (DevHasCursor(pDev)) {
3961b5d61b8Smrg                pCursorInfo = GetSprite(pDev);
39735c4bbdfSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
39835c4bbdfSmrg                    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
39935c4bbdfSmrg                                sx, sy, w, h)) {
40035c4bbdfSmrg                    SPRITE_DEBUG(("GetImage remove\n"));
40135c4bbdfSmrg                    miSpriteRemoveCursor(pDev, pScreen);
40235c4bbdfSmrg                }
4036747b715Smrg            }
4044642e01fSmrg        }
40505b261ecSmrg    }
40605b261ecSmrg
40735c4bbdfSmrg    (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine);
40805b261ecSmrg
40935c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, GetImage);
41005b261ecSmrg}
41105b261ecSmrg
41205b261ecSmrgstatic void
41335c4bbdfSmrgmiSpriteGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
41435c4bbdfSmrg                 int *pwidth, int nspans, char *pdstStart)
41505b261ecSmrg{
41635c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
41735c4bbdfSmrg    DeviceIntPtr pDev;
41835c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
41935c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
42035c4bbdfSmrg
42135c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, GetSpans);
42235c4bbdfSmrg
42335c4bbdfSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
42435c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
42535c4bbdfSmrg            if (DevHasCursor(pDev)) {
4261b5d61b8Smrg                pCursorInfo = GetSprite(pDev);
4276747b715Smrg
42835c4bbdfSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) {
42935c4bbdfSmrg                    DDXPointPtr pts;
43035c4bbdfSmrg                    int *widths;
43135c4bbdfSmrg                    int nPts;
43235c4bbdfSmrg                    int xorg, yorg;
4336747b715Smrg
4346747b715Smrg                    xorg = pDrawable->x;
4356747b715Smrg                    yorg = pDrawable->y;
4366747b715Smrg
4376747b715Smrg                    for (pts = ppt, widths = pwidth, nPts = nspans;
43835c4bbdfSmrg                         nPts--; pts++, widths++) {
43935c4bbdfSmrg                        if (SPN_OVERLAP(&pCursorInfo->saved, pts->y + yorg,
44035c4bbdfSmrg                                        pts->x + xorg, *widths)) {
44135c4bbdfSmrg                            SPRITE_DEBUG(("GetSpans remove\n"));
44235c4bbdfSmrg                            miSpriteRemoveCursor(pDev, pScreen);
4436747b715Smrg                            break;
4446747b715Smrg                        }
4454642e01fSmrg                    }
4464642e01fSmrg                }
4474642e01fSmrg            }
4484642e01fSmrg        }
44905b261ecSmrg    }
45005b261ecSmrg
45105b261ecSmrg    (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
45205b261ecSmrg
45335c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, GetSpans);
45405b261ecSmrg}
45505b261ecSmrg
45605b261ecSmrgstatic void
45735c4bbdfSmrgmiSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, int width,
45835c4bbdfSmrg                       int height, unsigned int subWindowMode)
45905b261ecSmrg{
46035c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
46135c4bbdfSmrg    DeviceIntPtr pDev;
46235c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
46335c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
46435c4bbdfSmrg
46535c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, SourceValidate);
46635c4bbdfSmrg
46735c4bbdfSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
46835c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
46935c4bbdfSmrg            if (DevHasCursor(pDev)) {
4701b5d61b8Smrg                pCursorInfo = GetSprite(pDev);
47135c4bbdfSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
47235c4bbdfSmrg                    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
47335c4bbdfSmrg                                x, y, width, height)) {
47435c4bbdfSmrg                    SPRITE_DEBUG(("SourceValidate remove\n"));
47535c4bbdfSmrg                    miSpriteRemoveCursor(pDev, pScreen);
47635c4bbdfSmrg                }
47735c4bbdfSmrg            }
47835c4bbdfSmrg        }
47905b261ecSmrg    }
48005b261ecSmrg
48105b261ecSmrg    if (pScreen->SourceValidate)
48235c4bbdfSmrg        (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
48335c4bbdfSmrg                                    subWindowMode);
48405b261ecSmrg
48535c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, SourceValidate);
48605b261ecSmrg}
48705b261ecSmrg
48805b261ecSmrgstatic void
48935c4bbdfSmrgmiSpriteCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
49005b261ecSmrg{
49135c4bbdfSmrg    ScreenPtr pScreen = pWindow->drawable.pScreen;
49235c4bbdfSmrg    DeviceIntPtr pDev;
49335c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
49435c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
4954642e01fSmrg
49635c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, CopyWindow);
49705b261ecSmrg
49835c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
49935c4bbdfSmrg        if (DevHasCursor(pDev)) {
5001b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
5014642e01fSmrg            /*
5024642e01fSmrg             * Damage will take care of destination check
5034642e01fSmrg             */
5044642e01fSmrg            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
50535c4bbdfSmrg                RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) {
50635c4bbdfSmrg                SPRITE_DEBUG(("CopyWindow remove\n"));
50735c4bbdfSmrg                miSpriteRemoveCursor(pDev, pScreen);
5084642e01fSmrg            }
5094642e01fSmrg        }
51005b261ecSmrg    }
51105b261ecSmrg
51205b261ecSmrg    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
51335c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, CopyWindow);
51405b261ecSmrg}
51505b261ecSmrg
51605b261ecSmrgstatic void
5171b5d61b8SmrgmiSpriteBlockHandler(ScreenPtr pScreen, void *timeout)
51805b261ecSmrg{
51935c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
52035c4bbdfSmrg    DeviceIntPtr pDev;
52135c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
52235c4bbdfSmrg    Bool WorkToDo = FALSE;
52335c4bbdfSmrg
52435c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
52535c4bbdfSmrg
52635c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
52735c4bbdfSmrg        if (DevHasCursor(pDev)) {
5281b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
5294642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp
53035c4bbdfSmrg                && pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
53135c4bbdfSmrg                SPRITE_DEBUG(("BlockHandler save"));
53235c4bbdfSmrg                miSpriteSaveUnderCursor(pDev, pScreen);
5334642e01fSmrg            }
5344642e01fSmrg        }
5354642e01fSmrg    }
53635c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
53735c4bbdfSmrg        if (DevHasCursor(pDev)) {
5381b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
5394642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp &&
54035c4bbdfSmrg                pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
54135c4bbdfSmrg                SPRITE_DEBUG(("BlockHandler restore\n"));
54235c4bbdfSmrg                miSpriteRestoreCursor(pDev, pScreen);
5439ace9065Smrg                if (!pCursorInfo->isUp)
5449ace9065Smrg                    WorkToDo = TRUE;
5454642e01fSmrg            }
5464642e01fSmrg        }
54705b261ecSmrg    }
5489ace9065Smrg
5491b5d61b8Smrg    (*pScreen->BlockHandler) (pScreen, timeout);
5509ace9065Smrg
5519ace9065Smrg    if (WorkToDo)
5529ace9065Smrg        SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
5539ace9065Smrg    else
5549ace9065Smrg        pPriv->BlockHandler = NULL;
55505b261ecSmrg}
55605b261ecSmrg
55705b261ecSmrgstatic void
55835c4bbdfSmrgmiSpriteInstallColormap(ColormapPtr pMap)
55905b261ecSmrg{
56035c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
56135c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
56205b261ecSmrg
5639ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
5644642e01fSmrg
56505b261ecSmrg    (*pScreen->InstallColormap) (pMap);
56605b261ecSmrg
5679ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
56805b261ecSmrg
5694642e01fSmrg    /* InstallColormap can be called before devices are initialized. */
57005b261ecSmrg    pPriv->pInstalledMap = pMap;
57135c4bbdfSmrg    if (pPriv->pColormap != pMap) {
5724642e01fSmrg        DeviceIntPtr pDev;
57335c4bbdfSmrg        miCursorInfoPtr pCursorInfo;
57435c4bbdfSmrg
57535c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
57635c4bbdfSmrg            if (DevHasCursor(pDev)) {
5771b5d61b8Smrg                pCursorInfo = GetSprite(pDev);
5784642e01fSmrg                pCursorInfo->checkPixels = TRUE;
5794642e01fSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
5804642e01fSmrg                    miSpriteRemoveCursor(pDev, pScreen);
5814642e01fSmrg            }
5824642e01fSmrg        }
5834642e01fSmrg
58405b261ecSmrg    }
58505b261ecSmrg}
58605b261ecSmrg
58705b261ecSmrgstatic void
58835c4bbdfSmrgmiSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef)
58905b261ecSmrg{
59035c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
59135c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
59235c4bbdfSmrg    int i;
59335c4bbdfSmrg    int updated;
59435c4bbdfSmrg    VisualPtr pVisual;
59535c4bbdfSmrg    DeviceIntPtr pDev;
59635c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
59705b261ecSmrg
5989ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
5994642e01fSmrg
60005b261ecSmrg    (*pScreen->StoreColors) (pMap, ndef, pdef);
60105b261ecSmrg
6029ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
60305b261ecSmrg
60435c4bbdfSmrg    if (pPriv->pColormap == pMap) {
6054642e01fSmrg        updated = 0;
6064642e01fSmrg        pVisual = pMap->pVisual;
60735c4bbdfSmrg        if (pVisual->class == DirectColor) {
6084642e01fSmrg            /* Direct color - match on any of the subfields */
60905b261ecSmrg
61005b261ecSmrg#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
61105b261ecSmrg
6124642e01fSmrg#define UpdateDAC(dev, plane,dac,mask) {\
6134642e01fSmrg    if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
6144642e01fSmrg	dev->colors[plane].dac = pdef[i].dac; \
61505b261ecSmrg	updated = 1; \
61605b261ecSmrg    } \
61705b261ecSmrg}
61805b261ecSmrg
6194642e01fSmrg#define CheckDirect(dev, plane) \
6204642e01fSmrg	    UpdateDAC(dev, plane,red,redMask) \
6214642e01fSmrg	    UpdateDAC(dev, plane,green,greenMask) \
6224642e01fSmrg	    UpdateDAC(dev, plane,blue,blueMask)
6234642e01fSmrg
62435c4bbdfSmrg            for (i = 0; i < ndef; i++) {
62535c4bbdfSmrg                CheckDirect(pPriv, SOURCE_COLOR)
62635c4bbdfSmrg                    CheckDirect(pPriv, MASK_COLOR)
6274642e01fSmrg            }
6284642e01fSmrg        }
62935c4bbdfSmrg        else {
6304642e01fSmrg            /* PseudoColor/GrayScale - match on exact pixel */
63135c4bbdfSmrg            for (i = 0; i < ndef; i++) {
63235c4bbdfSmrg                if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) {
6334642e01fSmrg                    pPriv->colors[SOURCE_COLOR] = pdef[i];
6344642e01fSmrg                    if (++updated == 2)
6354642e01fSmrg                        break;
6364642e01fSmrg                }
63735c4bbdfSmrg                if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) {
6384642e01fSmrg                    pPriv->colors[MASK_COLOR] = pdef[i];
6394642e01fSmrg                    if (++updated == 2)
6404642e01fSmrg                        break;
6414642e01fSmrg                }
6424642e01fSmrg            }
6434642e01fSmrg        }
64435c4bbdfSmrg        if (updated) {
64535c4bbdfSmrg            for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
64635c4bbdfSmrg                if (DevHasCursor(pDev)) {
6471b5d61b8Smrg                    pCursorInfo = GetSprite(pDev);
6484642e01fSmrg                    pCursorInfo->checkPixels = TRUE;
6494642e01fSmrg                    if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
65035c4bbdfSmrg                        miSpriteRemoveCursor(pDev, pScreen);
6514642e01fSmrg                }
6524642e01fSmrg            }
6534642e01fSmrg        }
65405b261ecSmrg    }
65505b261ecSmrg}
65605b261ecSmrg
65705b261ecSmrgstatic void
65835c4bbdfSmrgmiSpriteFindColors(miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
65905b261ecSmrg{
66035c4bbdfSmrg    miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
66135c4bbdfSmrg    CursorPtr pCursor;
66235c4bbdfSmrg    xColorItem *sourceColor, *maskColor;
66305b261ecSmrg
6644642e01fSmrg    pCursor = pDevCursor->pCursor;
66505b261ecSmrg    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
66605b261ecSmrg    maskColor = &pScreenPriv->colors[MASK_COLOR];
66705b261ecSmrg    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
66835c4bbdfSmrg        !(pCursor->foreRed == sourceColor->red &&
66935c4bbdfSmrg          pCursor->foreGreen == sourceColor->green &&
67005b261ecSmrg          pCursor->foreBlue == sourceColor->blue &&
67135c4bbdfSmrg          pCursor->backRed == maskColor->red &&
67235c4bbdfSmrg          pCursor->backGreen == maskColor->green &&
67335c4bbdfSmrg          pCursor->backBlue == maskColor->blue)) {
67435c4bbdfSmrg        pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
67535c4bbdfSmrg        sourceColor->red = pCursor->foreRed;
67635c4bbdfSmrg        sourceColor->green = pCursor->foreGreen;
67735c4bbdfSmrg        sourceColor->blue = pCursor->foreBlue;
67835c4bbdfSmrg        FakeAllocColor(pScreenPriv->pColormap, sourceColor);
67935c4bbdfSmrg        maskColor->red = pCursor->backRed;
68035c4bbdfSmrg        maskColor->green = pCursor->backGreen;
68135c4bbdfSmrg        maskColor->blue = pCursor->backBlue;
68235c4bbdfSmrg        FakeAllocColor(pScreenPriv->pColormap, maskColor);
68335c4bbdfSmrg        /* "free" the pixels right away, don't let this confuse you */
68435c4bbdfSmrg        FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
68535c4bbdfSmrg        FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
68605b261ecSmrg    }
68705b261ecSmrg
6884642e01fSmrg    pDevCursor->checkPixels = FALSE;
68905b261ecSmrg
69005b261ecSmrg}
69105b261ecSmrg
69205b261ecSmrg/*
69305b261ecSmrg * miPointer interface routines
69405b261ecSmrg */
69505b261ecSmrg
69605b261ecSmrg#define SPRITE_PAD  8
69705b261ecSmrg
69805b261ecSmrgstatic Bool
69935c4bbdfSmrgmiSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
70005b261ecSmrg{
7014642e01fSmrg    miCursorInfoPtr pCursorInfo;
7024642e01fSmrg
70335c4bbdfSmrg    if (IsFloating(pDev))
7044642e01fSmrg        return FALSE;
7056747b715Smrg
7061b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
7074642e01fSmrg
7084642e01fSmrg    if (pCursor == pCursorInfo->pCursor)
70935c4bbdfSmrg        pCursorInfo->checkPixels = TRUE;
71005b261ecSmrg
7116747b715Smrg    return miDCRealizeCursor(pScreen, pCursor);
71205b261ecSmrg}
71305b261ecSmrg
71405b261ecSmrgstatic Bool
7154642e01fSmrgmiSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
71605b261ecSmrg{
7176747b715Smrg    return miDCUnrealizeCursor(pScreen, pCursor);
71805b261ecSmrg}
71905b261ecSmrg
72005b261ecSmrgstatic void
72135c4bbdfSmrgmiSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
72235c4bbdfSmrg                  CursorPtr pCursor, int x, int y)
72305b261ecSmrg{
72435c4bbdfSmrg    miCursorInfoPtr pPointer;
72535c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
7264642e01fSmrg
72735c4bbdfSmrg    if (IsFloating(pDev))
7284642e01fSmrg        return;
7296747b715Smrg
7301b5d61b8Smrg    pPointer = GetSprite(pDev);
7319ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
7324642e01fSmrg
73335c4bbdfSmrg    if (!pCursor) {
73435c4bbdfSmrg        if (pPointer->shouldBeUp)
73535c4bbdfSmrg            --pScreenPriv->numberOfCursors;
73635c4bbdfSmrg        pPointer->shouldBeUp = FALSE;
73735c4bbdfSmrg        if (pPointer->isUp)
73835c4bbdfSmrg            miSpriteRemoveCursor(pDev, pScreen);
73935c4bbdfSmrg        if (pScreenPriv->numberOfCursors == 0)
74035c4bbdfSmrg            miSpriteDisableDamage(pScreen, pScreenPriv);
74135c4bbdfSmrg        pPointer->pCursor = 0;
74235c4bbdfSmrg        return;
74305b261ecSmrg    }
7449ace9065Smrg    if (!pPointer->shouldBeUp)
74535c4bbdfSmrg        pScreenPriv->numberOfCursors++;
7464642e01fSmrg    pPointer->shouldBeUp = TRUE;
7479ace9065Smrg    if (!pPointer->isUp)
74835c4bbdfSmrg        miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
7494642e01fSmrg    if (pPointer->x == x &&
75035c4bbdfSmrg        pPointer->y == y &&
75135c4bbdfSmrg        pPointer->pCursor == pCursor && !pPointer->checkPixels) {
75235c4bbdfSmrg        return;
75305b261ecSmrg    }
7544642e01fSmrg    pPointer->x = x;
7554642e01fSmrg    pPointer->y = y;
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
7821b5d61b8Smrg    pCursor = GetSprite(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 =
7961b5d61b8Smrg            dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec);
79735c4bbdfSmrg        pCursorInfo->pCursor = NULL;
79835c4bbdfSmrg        pCursorInfo->x = 0;
79935c4bbdfSmrg        pCursorInfo->y = 0;
80035c4bbdfSmrg        pCursorInfo->isUp = FALSE;
80135c4bbdfSmrg        pCursorInfo->shouldBeUp = FALSE;
80235c4bbdfSmrg        pCursorInfo->checkPixels = TRUE;
80335c4bbdfSmrg        pCursorInfo->pScreen = FALSE;
8044642e01fSmrg    }
80535c4bbdfSmrg
8064642e01fSmrg    return ret;
8074642e01fSmrg}
8084642e01fSmrg
8094642e01fSmrgstatic void
8104642e01fSmrgmiSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
8114642e01fSmrg{
81235c4bbdfSmrg    miCursorInfoPtr pCursorInfo =
8131b5d61b8Smrg        dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec);
81435c4bbdfSmrg
8154642e01fSmrg    if (DevHasCursor(pDev))
8166747b715Smrg        miDCDeviceCleanup(pDev, pScreen);
81735c4bbdfSmrg
81835c4bbdfSmrg    memset(pCursorInfo, 0, sizeof(miCursorInfoRec));
81905b261ecSmrg}
82005b261ecSmrg
82105b261ecSmrg/*
82205b261ecSmrg * undraw/draw cursor
82305b261ecSmrg */
82405b261ecSmrg
82505b261ecSmrgstatic void
82635c4bbdfSmrgmiSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
82705b261ecSmrg{
82835c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
82935c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
83005b261ecSmrg
83135c4bbdfSmrg    if (IsFloating(pDev))
8324642e01fSmrg        return;
8336747b715Smrg
83435c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
8359ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
8361b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
8374642e01fSmrg
8384642e01fSmrg    miSpriteIsDown(pCursorInfo);
8399ace9065Smrg    miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
8404642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
8416747b715Smrg    if (!miDCRestoreUnderCursor(pDev,
8426747b715Smrg                                pScreen,
8436747b715Smrg                                pCursorInfo->saved.x1,
8446747b715Smrg                                pCursorInfo->saved.y1,
8456747b715Smrg                                pCursorInfo->saved.x2 -
8466747b715Smrg                                pCursorInfo->saved.x1,
8476747b715Smrg                                pCursorInfo->saved.y2 -
84835c4bbdfSmrg                                pCursorInfo->saved.y1)) {
8496747b715Smrg        miSpriteIsUp(pCursorInfo);
85005b261ecSmrg    }
8514642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
85235c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
85305b261ecSmrg}
85405b261ecSmrg
8554642e01fSmrg/*
8564642e01fSmrg * Called from the block handler, saves area under cursor
8574642e01fSmrg * before waiting for something to do.
8584642e01fSmrg */
8594642e01fSmrg
8604642e01fSmrgstatic void
8614642e01fSmrgmiSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
8624642e01fSmrg{
86335c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
86435c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
8654642e01fSmrg
86635c4bbdfSmrg    if (IsFloating(pDev))
8674642e01fSmrg        return;
8686747b715Smrg
86935c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
8709ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
8711b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
8724642e01fSmrg
87335c4bbdfSmrg    miSpriteComputeSaved(pDev, pScreen);
8744642e01fSmrg
8754642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
8764642e01fSmrg
8776747b715Smrg    miDCSaveUnderCursor(pDev,
8786747b715Smrg                        pScreen,
8796747b715Smrg                        pCursorInfo->saved.x1,
8806747b715Smrg                        pCursorInfo->saved.y1,
8816747b715Smrg                        pCursorInfo->saved.x2 -
8826747b715Smrg                        pCursorInfo->saved.x1,
88335c4bbdfSmrg                        pCursorInfo->saved.y2 - pCursorInfo->saved.y1);
8844642e01fSmrg    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
8854642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
88635c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
8874642e01fSmrg}
8884642e01fSmrg
88905b261ecSmrg/*
89005b261ecSmrg * Called from the block handler, restores the cursor
89105b261ecSmrg * before waiting for something to do.
89205b261ecSmrg */
89305b261ecSmrg
89405b261ecSmrgstatic void
89535c4bbdfSmrgmiSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
89605b261ecSmrg{
89735c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
89835c4bbdfSmrg    int x, y;
89935c4bbdfSmrg    CursorPtr pCursor;
90035c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
9014642e01fSmrg
90235c4bbdfSmrg    if (IsFloating(pDev))
9034642e01fSmrg        return;
90405b261ecSmrg
90535c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
9069ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
9071b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
9084642e01fSmrg
90935c4bbdfSmrg    miSpriteComputeSaved(pDev, pScreen);
9104642e01fSmrg    pCursor = pCursorInfo->pCursor;
9114642e01fSmrg
91235c4bbdfSmrg    x = pCursorInfo->x - (int) pCursor->bits->xhot;
91335c4bbdfSmrg    y = pCursorInfo->y - (int) pCursor->bits->yhot;
9144642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
9154642e01fSmrg    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
9164642e01fSmrg    if (pCursorInfo->checkPixels)
91735c4bbdfSmrg        miSpriteFindColors(pCursorInfo, pScreen);
9186747b715Smrg    if (miDCPutUpCursor(pDev, pScreen,
91935c4bbdfSmrg                        pCursor, x, y,
92035c4bbdfSmrg                        pScreenPriv->colors[SOURCE_COLOR].pixel,
92135c4bbdfSmrg                        pScreenPriv->colors[MASK_COLOR].pixel)) {
9224642e01fSmrg        miSpriteIsUp(pCursorInfo);
9234642e01fSmrg        pCursorInfo->pScreen = pScreen;
92405b261ecSmrg    }
9254642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
92635c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
92705b261ecSmrg}
92805b261ecSmrg
92905b261ecSmrg/*
93005b261ecSmrg * compute the desired area of the screen to save
93105b261ecSmrg */
93205b261ecSmrg
93305b261ecSmrgstatic void
93435c4bbdfSmrgmiSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen)
93505b261ecSmrg{
93635c4bbdfSmrg    int x, y, w, h;
93735c4bbdfSmrg    int wpad, hpad;
93835c4bbdfSmrg    CursorPtr pCursor;
9394642e01fSmrg    miCursorInfoPtr pCursorInfo;
94005b261ecSmrg
94135c4bbdfSmrg    if (IsFloating(pDev))
9424642e01fSmrg        return;
9436747b715Smrg
9441b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
9454642e01fSmrg
9464642e01fSmrg    pCursor = pCursorInfo->pCursor;
94735c4bbdfSmrg    x = pCursorInfo->x - (int) pCursor->bits->xhot;
94835c4bbdfSmrg    y = pCursorInfo->y - (int) pCursor->bits->yhot;
94905b261ecSmrg    w = pCursor->bits->width;
95005b261ecSmrg    h = pCursor->bits->height;
95105b261ecSmrg    wpad = SPRITE_PAD;
95205b261ecSmrg    hpad = SPRITE_PAD;
9534642e01fSmrg    pCursorInfo->saved.x1 = x - wpad;
9544642e01fSmrg    pCursorInfo->saved.y1 = y - hpad;
9554642e01fSmrg    pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
9564642e01fSmrg    pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
95705b261ecSmrg}
958