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    SourceValidateProcPtr SourceValidate;
7435c4bbdfSmrg
756747b715Smrg    /* window procedures */
7635c4bbdfSmrg    CopyWindowProcPtr CopyWindow;
7735c4bbdfSmrg
786747b715Smrg    /* colormap procedures */
7935c4bbdfSmrg    InstallColormapProcPtr InstallColormap;
8035c4bbdfSmrg    StoreColorsProcPtr StoreColors;
8135c4bbdfSmrg
826747b715Smrg    /* os layer procedures */
8335c4bbdfSmrg    ScreenBlockHandlerProcPtr BlockHandler;
8435c4bbdfSmrg
8535c4bbdfSmrg    xColorItem colors[2];
8635c4bbdfSmrg    ColormapPtr pInstalledMap;
8735c4bbdfSmrg    ColormapPtr pColormap;
8835c4bbdfSmrg    VisualPtr pVisual;
8935c4bbdfSmrg    DamagePtr pDamage;          /* damage tracking structure */
9035c4bbdfSmrg    Bool damageRegistered;
9135c4bbdfSmrg    int numberOfCursors;
926747b715Smrg} miSpriteScreenRec, *miSpriteScreenPtr;
936747b715Smrg
946747b715Smrg#define SOURCE_COLOR	0
956747b715Smrg#define MASK_COLOR	1
966747b715Smrg
976747b715Smrg/*
986747b715Smrg * Overlap BoxPtr and Box elements
996747b715Smrg */
1006747b715Smrg#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
1016747b715Smrg 	(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
1026747b715Smrg	 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
1036747b715Smrg
1046747b715Smrg/*
1056747b715Smrg * Overlap BoxPtr, origins, and rectangle
1066747b715Smrg */
1076747b715Smrg#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
1086747b715Smrg    BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
1096747b715Smrg
1106747b715Smrg/*
1116747b715Smrg * Overlap BoxPtr, origins and RectPtr
1126747b715Smrg */
1136747b715Smrg#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
1146747b715Smrg    ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
1156747b715Smrg		(int)((pRect)->width), (int)((pRect)->height))
1166747b715Smrg/*
1176747b715Smrg * Overlap BoxPtr and horizontal span
1186747b715Smrg */
1196747b715Smrg#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
12005b261ecSmrg
1216747b715Smrg#define LINE_SORT(x1,y1,x2,y2) \
1226747b715Smrg{ int _t; \
1236747b715Smrg  if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
1246747b715Smrg  if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
1256747b715Smrg
1266747b715Smrg#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
1276747b715Smrg    BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
1284642e01fSmrg
12905b261ecSmrg#define SPRITE_DEBUG_ENABLE 0
13005b261ecSmrg#if SPRITE_DEBUG_ENABLE
13105b261ecSmrg#define SPRITE_DEBUG(x)	ErrorF x
13205b261ecSmrg#else
13305b261ecSmrg#define SPRITE_DEBUG(x)
13405b261ecSmrg#endif
13505b261ecSmrg
1361b5d61b8Smrgstatic DevPrivateKeyRec miSpriteScreenKeyRec;
1371b5d61b8Smrgstatic DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
1381b5d61b8Smrg
1391b5d61b8Smrgstatic miSpriteScreenPtr
1401b5d61b8SmrgGetSpriteScreen(ScreenPtr pScreen)
1411b5d61b8Smrg{
1421b5d61b8Smrg    return dixLookupPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec);
1431b5d61b8Smrg}
1441b5d61b8Smrg
1451b5d61b8Smrgstatic miCursorInfoPtr
1461b5d61b8SmrgGetSprite(DeviceIntPtr dev)
1471b5d61b8Smrg{
1481b5d61b8Smrg    if (IsFloating(dev))
1491b5d61b8Smrg       return dixLookupPrivate(&dev->devPrivates, &miSpriteDevPrivatesKeyRec);
1501b5d61b8Smrg
1511b5d61b8Smrg    return dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates,
1521b5d61b8Smrg                            &miSpriteDevPrivatesKeyRec);
1531b5d61b8Smrg}
1544642e01fSmrg
1554642e01fSmrgstatic void
1564642e01fSmrgmiSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1574642e01fSmrg{
1586747b715Smrg    if (pScreenPriv->damageRegistered) {
15935c4bbdfSmrg        DamageUnregister(pScreenPriv->pDamage);
16035c4bbdfSmrg        pScreenPriv->damageRegistered = 0;
1614642e01fSmrg    }
1624642e01fSmrg}
1634642e01fSmrg
1644642e01fSmrgstatic void
1654642e01fSmrgmiSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
1664642e01fSmrg{
1676747b715Smrg    if (!pScreenPriv->damageRegistered) {
16835c4bbdfSmrg        pScreenPriv->damageRegistered = 1;
16935c4bbdfSmrg        DamageRegister(&(pScreen->GetScreenPixmap(pScreen)->drawable),
17035c4bbdfSmrg                       pScreenPriv->pDamage);
1714642e01fSmrg    }
1724642e01fSmrg}
1734642e01fSmrg
1744642e01fSmrgstatic void
1754642e01fSmrgmiSpriteIsUp(miCursorInfoPtr pDevCursor)
1764642e01fSmrg{
1774642e01fSmrg    pDevCursor->isUp = TRUE;
1784642e01fSmrg}
1794642e01fSmrg
1804642e01fSmrgstatic void
1814642e01fSmrgmiSpriteIsDown(miCursorInfoPtr pDevCursor)
1824642e01fSmrg{
1834642e01fSmrg    pDevCursor->isUp = FALSE;
1844642e01fSmrg}
1854642e01fSmrg
18605b261ecSmrg/*
18705b261ecSmrg * screen wrappers
18805b261ecSmrg */
18905b261ecSmrg
19035c4bbdfSmrgstatic Bool miSpriteCloseScreen(ScreenPtr pScreen);
19135c4bbdfSmrgstatic void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
19235c4bbdfSmrg                                   int width, int height,
19335c4bbdfSmrg                                   unsigned int subWindowMode);
19435c4bbdfSmrgstatic void miSpriteCopyWindow(WindowPtr pWindow,
19535c4bbdfSmrg                               DDXPointRec ptOldOrg, RegionPtr prgnSrc);
1961b5d61b8Smrgstatic void miSpriteBlockHandler(ScreenPtr pScreen, void *timeout);
19735c4bbdfSmrgstatic void miSpriteInstallColormap(ColormapPtr pMap);
19835c4bbdfSmrgstatic void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef);
19935c4bbdfSmrg
20035c4bbdfSmrgstatic void miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen);
20135c4bbdfSmrg
20235c4bbdfSmrgstatic Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
20335c4bbdfSmrg                                           ScreenPtr pScreen);
20435c4bbdfSmrgstatic void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
20505b261ecSmrg
2069ace9065Smrg#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
2079ace9065Smrg   (pPriv)->field)
2089ace9065Smrg#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
2099ace9065Smrg    ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
21005b261ecSmrg
21105b261ecSmrg/*
21205b261ecSmrg * pointer-sprite method table
21305b261ecSmrg */
21405b261ecSmrg
2154642e01fSmrgstatic Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2164642e01fSmrg                                  CursorPtr pCursor);
2174642e01fSmrgstatic Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2184642e01fSmrg                                    CursorPtr pCursor);
2194642e01fSmrgstatic void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2204642e01fSmrg                              CursorPtr pCursor, int x, int y);
2214642e01fSmrgstatic void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
2224642e01fSmrg                               int x, int y);
22305b261ecSmrg
2246747b715SmrgmiPointerSpriteFuncRec miSpritePointerFuncs = {
22505b261ecSmrg    miSpriteRealizeCursor,
22605b261ecSmrg    miSpriteUnrealizeCursor,
22705b261ecSmrg    miSpriteSetCursor,
22805b261ecSmrg    miSpriteMoveCursor,
2294642e01fSmrg    miSpriteDeviceCursorInitialize,
2304642e01fSmrg    miSpriteDeviceCursorCleanup,
23105b261ecSmrg};
23205b261ecSmrg
23305b261ecSmrg/*
23405b261ecSmrg * other misc functions
23505b261ecSmrg */
23605b261ecSmrg
23735c4bbdfSmrgstatic void miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
23835c4bbdfSmrgstatic void miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
23935c4bbdfSmrgstatic void miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
24005b261ecSmrg
2419ace9065Smrgstatic void
2429ace9065SmrgmiSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
2439ace9065Smrg{
2449ace9065Smrg    if (!pScreenPriv->BlockHandler) {
2459ace9065Smrg        pScreenPriv->BlockHandler = pScreen->BlockHandler;
2469ace9065Smrg        pScreen->BlockHandler = miSpriteBlockHandler;
2479ace9065Smrg    }
2489ace9065Smrg}
2499ace9065Smrg
25005b261ecSmrgstatic void
25135c4bbdfSmrgmiSpriteReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
25205b261ecSmrg{
25335c4bbdfSmrg    ScreenPtr pScreen = closure;
25435c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
25535c4bbdfSmrg    DeviceIntPtr pDev;
25635c4bbdfSmrg
25735c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
25835c4bbdfSmrg        if (DevHasCursor(pDev)) {
2591b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
2604642e01fSmrg
2614642e01fSmrg            if (pCursorInfo->isUp &&
2624642e01fSmrg                pCursorInfo->pScreen == pScreen &&
26335c4bbdfSmrg                RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) {
2644642e01fSmrg                SPRITE_DEBUG(("Damage remove\n"));
26535c4bbdfSmrg                miSpriteRemoveCursor(pDev, pScreen);
2664642e01fSmrg            }
2674642e01fSmrg        }
26805b261ecSmrg    }
26905b261ecSmrg}
27005b261ecSmrg
27105b261ecSmrg/*
27205b261ecSmrg * miSpriteInitialize -- called from device-dependent screen
27305b261ecSmrg * initialization proc after all of the function pointers have
27405b261ecSmrg * been stored in the screen structure.
27505b261ecSmrg */
27605b261ecSmrg
27705b261ecSmrgBool
27835c4bbdfSmrgmiSpriteInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
27905b261ecSmrg{
28035c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
28135c4bbdfSmrg    VisualPtr pVisual;
2824642e01fSmrg
28335c4bbdfSmrg    if (!DamageSetup(pScreen))
28435c4bbdfSmrg        return FALSE;
28505b261ecSmrg
2866747b715Smrg    if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
28735c4bbdfSmrg        return FALSE;
2886747b715Smrg
28935c4bbdfSmrg    if (!dixRegisterPrivateKey
29035c4bbdfSmrg        (&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec)))
29135c4bbdfSmrg        return FALSE;
2926747b715Smrg
29335c4bbdfSmrg    pScreenPriv = malloc(sizeof(miSpriteScreenRec));
29405b261ecSmrg    if (!pScreenPriv)
29535c4bbdfSmrg        return FALSE;
29635c4bbdfSmrg
29735c4bbdfSmrg    pScreenPriv->pDamage = DamageCreate(miSpriteReportDamage,
29835c4bbdfSmrg                                        NULL,
29935c4bbdfSmrg                                        DamageReportRawRegion,
30035c4bbdfSmrg                                        TRUE, pScreen, pScreen);
30135c4bbdfSmrg
30235c4bbdfSmrg    if (!miPointerInitialize(pScreen, &miSpritePointerFuncs, screenFuncs, TRUE)) {
30335c4bbdfSmrg        free(pScreenPriv);
30435c4bbdfSmrg        return FALSE;
30505b261ecSmrg    }
30605b261ecSmrg    for (pVisual = pScreen->visuals;
30735c4bbdfSmrg         pVisual->vid != pScreen->rootVisual; pVisual++);
30805b261ecSmrg    pScreenPriv->pVisual = pVisual;
30905b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
31005b261ecSmrg    pScreenPriv->SourceValidate = pScreen->SourceValidate;
31105b261ecSmrg
31205b261ecSmrg    pScreenPriv->CopyWindow = pScreen->CopyWindow;
3134642e01fSmrg
31405b261ecSmrg    pScreenPriv->InstallColormap = pScreen->InstallColormap;
31505b261ecSmrg    pScreenPriv->StoreColors = pScreen->StoreColors;
3164642e01fSmrg
3179ace9065Smrg    pScreenPriv->BlockHandler = NULL;
3184642e01fSmrg
31905b261ecSmrg    pScreenPriv->pInstalledMap = NULL;
32005b261ecSmrg    pScreenPriv->pColormap = NULL;
32105b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].red = 0;
32205b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].green = 0;
32305b261ecSmrg    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
32405b261ecSmrg    pScreenPriv->colors[MASK_COLOR].red = 0;
32505b261ecSmrg    pScreenPriv->colors[MASK_COLOR].green = 0;
32605b261ecSmrg    pScreenPriv->colors[MASK_COLOR].blue = 0;
3276747b715Smrg    pScreenPriv->damageRegistered = 0;
3289ace9065Smrg    pScreenPriv->numberOfCursors = 0;
3296747b715Smrg
3301b5d61b8Smrg    dixSetPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec, pScreenPriv);
3314642e01fSmrg
33205b261ecSmrg    pScreen->CloseScreen = miSpriteCloseScreen;
33305b261ecSmrg    pScreen->SourceValidate = miSpriteSourceValidate;
3344642e01fSmrg
33505b261ecSmrg    pScreen->CopyWindow = miSpriteCopyWindow;
33605b261ecSmrg    pScreen->InstallColormap = miSpriteInstallColormap;
33705b261ecSmrg    pScreen->StoreColors = miSpriteStoreColors;
33805b261ecSmrg
33905b261ecSmrg    return TRUE;
34005b261ecSmrg}
34105b261ecSmrg
34205b261ecSmrg/*
34305b261ecSmrg * Screen wrappers
34405b261ecSmrg */
34505b261ecSmrg
34605b261ecSmrg/*
34705b261ecSmrg * CloseScreen wrapper -- unwrap everything, free the private data
34805b261ecSmrg * and call the wrapped function
34905b261ecSmrg */
35005b261ecSmrg
35105b261ecSmrgstatic Bool
35235c4bbdfSmrgmiSpriteCloseScreen(ScreenPtr pScreen)
35305b261ecSmrg{
35435c4bbdfSmrg    miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
35505b261ecSmrg
35605b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
35705b261ecSmrg    pScreen->SourceValidate = pScreenPriv->SourceValidate;
35805b261ecSmrg    pScreen->InstallColormap = pScreenPriv->InstallColormap;
35905b261ecSmrg    pScreen->StoreColors = pScreenPriv->StoreColors;
36005b261ecSmrg
36135c4bbdfSmrg    DamageDestroy(pScreenPriv->pDamage);
3624642e01fSmrg
3636747b715Smrg    free(pScreenPriv);
36405b261ecSmrg
36535c4bbdfSmrg    return (*pScreen->CloseScreen) (pScreen);
36605b261ecSmrg}
36705b261ecSmrg
36805b261ecSmrgstatic void
36935c4bbdfSmrgmiSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, int width,
37035c4bbdfSmrg                       int height, unsigned int subWindowMode)
37105b261ecSmrg{
37235c4bbdfSmrg    ScreenPtr pScreen = pDrawable->pScreen;
37335c4bbdfSmrg    DeviceIntPtr pDev;
37435c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
37535c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
37635c4bbdfSmrg
37735c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, SourceValidate);
37835c4bbdfSmrg
37935c4bbdfSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
38035c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
38135c4bbdfSmrg            if (DevHasCursor(pDev)) {
3821b5d61b8Smrg                pCursorInfo = GetSprite(pDev);
38335c4bbdfSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
38435c4bbdfSmrg                    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
38535c4bbdfSmrg                                x, y, width, height)) {
38635c4bbdfSmrg                    SPRITE_DEBUG(("SourceValidate remove\n"));
38735c4bbdfSmrg                    miSpriteRemoveCursor(pDev, pScreen);
38835c4bbdfSmrg                }
38935c4bbdfSmrg            }
39035c4bbdfSmrg        }
39105b261ecSmrg    }
39205b261ecSmrg
393ed6184dfSmrg    (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
394ed6184dfSmrg                                subWindowMode);
39505b261ecSmrg
39635c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, SourceValidate);
39705b261ecSmrg}
39805b261ecSmrg
39905b261ecSmrgstatic void
40035c4bbdfSmrgmiSpriteCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
40105b261ecSmrg{
40235c4bbdfSmrg    ScreenPtr pScreen = pWindow->drawable.pScreen;
40335c4bbdfSmrg    DeviceIntPtr pDev;
40435c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
40535c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
4064642e01fSmrg
40735c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, CopyWindow);
40805b261ecSmrg
40935c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
41035c4bbdfSmrg        if (DevHasCursor(pDev)) {
4111b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
4124642e01fSmrg            /*
4134642e01fSmrg             * Damage will take care of destination check
4144642e01fSmrg             */
4154642e01fSmrg            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
41635c4bbdfSmrg                RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) {
41735c4bbdfSmrg                SPRITE_DEBUG(("CopyWindow remove\n"));
41835c4bbdfSmrg                miSpriteRemoveCursor(pDev, pScreen);
4194642e01fSmrg            }
4204642e01fSmrg        }
42105b261ecSmrg    }
42205b261ecSmrg
42305b261ecSmrg    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
42435c4bbdfSmrg    SCREEN_EPILOGUE(pPriv, pScreen, CopyWindow);
42505b261ecSmrg}
42605b261ecSmrg
42705b261ecSmrgstatic void
4281b5d61b8SmrgmiSpriteBlockHandler(ScreenPtr pScreen, void *timeout)
42905b261ecSmrg{
43035c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
43135c4bbdfSmrg    DeviceIntPtr pDev;
43235c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
43335c4bbdfSmrg    Bool WorkToDo = FALSE;
43435c4bbdfSmrg
43535c4bbdfSmrg    SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
43635c4bbdfSmrg
43735c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
43835c4bbdfSmrg        if (DevHasCursor(pDev)) {
4391b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
4404642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp
44135c4bbdfSmrg                && pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
44235c4bbdfSmrg                SPRITE_DEBUG(("BlockHandler save"));
44335c4bbdfSmrg                miSpriteSaveUnderCursor(pDev, pScreen);
4444642e01fSmrg            }
4454642e01fSmrg        }
4464642e01fSmrg    }
44735c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
44835c4bbdfSmrg        if (DevHasCursor(pDev)) {
4491b5d61b8Smrg            pCursorInfo = GetSprite(pDev);
4504642e01fSmrg            if (pCursorInfo && !pCursorInfo->isUp &&
45135c4bbdfSmrg                pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
45235c4bbdfSmrg                SPRITE_DEBUG(("BlockHandler restore\n"));
45335c4bbdfSmrg                miSpriteRestoreCursor(pDev, pScreen);
4549ace9065Smrg                if (!pCursorInfo->isUp)
4559ace9065Smrg                    WorkToDo = TRUE;
4564642e01fSmrg            }
4574642e01fSmrg        }
45805b261ecSmrg    }
4599ace9065Smrg
4601b5d61b8Smrg    (*pScreen->BlockHandler) (pScreen, timeout);
4619ace9065Smrg
4629ace9065Smrg    if (WorkToDo)
4639ace9065Smrg        SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
4649ace9065Smrg    else
4659ace9065Smrg        pPriv->BlockHandler = NULL;
46605b261ecSmrg}
46705b261ecSmrg
46805b261ecSmrgstatic void
46935c4bbdfSmrgmiSpriteInstallColormap(ColormapPtr pMap)
47005b261ecSmrg{
47135c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
47235c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
47305b261ecSmrg
4749ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
4754642e01fSmrg
47605b261ecSmrg    (*pScreen->InstallColormap) (pMap);
47705b261ecSmrg
4789ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
47905b261ecSmrg
4804642e01fSmrg    /* InstallColormap can be called before devices are initialized. */
48105b261ecSmrg    pPriv->pInstalledMap = pMap;
48235c4bbdfSmrg    if (pPriv->pColormap != pMap) {
4834642e01fSmrg        DeviceIntPtr pDev;
48435c4bbdfSmrg        miCursorInfoPtr pCursorInfo;
48535c4bbdfSmrg
48635c4bbdfSmrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
48735c4bbdfSmrg            if (DevHasCursor(pDev)) {
4881b5d61b8Smrg                pCursorInfo = GetSprite(pDev);
4894642e01fSmrg                pCursorInfo->checkPixels = TRUE;
4904642e01fSmrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
4914642e01fSmrg                    miSpriteRemoveCursor(pDev, pScreen);
4924642e01fSmrg            }
4934642e01fSmrg        }
4944642e01fSmrg
49505b261ecSmrg    }
49605b261ecSmrg}
49705b261ecSmrg
49805b261ecSmrgstatic void
49935c4bbdfSmrgmiSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef)
50005b261ecSmrg{
50135c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
50235c4bbdfSmrg    miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
50335c4bbdfSmrg    int i;
50435c4bbdfSmrg    int updated;
50535c4bbdfSmrg    VisualPtr pVisual;
50635c4bbdfSmrg    DeviceIntPtr pDev;
50735c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
50805b261ecSmrg
5099ace9065Smrg    SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
5104642e01fSmrg
51105b261ecSmrg    (*pScreen->StoreColors) (pMap, ndef, pdef);
51205b261ecSmrg
5139ace9065Smrg    SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
51405b261ecSmrg
51535c4bbdfSmrg    if (pPriv->pColormap == pMap) {
5164642e01fSmrg        updated = 0;
5174642e01fSmrg        pVisual = pMap->pVisual;
51835c4bbdfSmrg        if (pVisual->class == DirectColor) {
5194642e01fSmrg            /* Direct color - match on any of the subfields */
52005b261ecSmrg
52105b261ecSmrg#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
52205b261ecSmrg
5234642e01fSmrg#define UpdateDAC(dev, plane,dac,mask) {\
5244642e01fSmrg    if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
5254642e01fSmrg	dev->colors[plane].dac = pdef[i].dac; \
52605b261ecSmrg	updated = 1; \
52705b261ecSmrg    } \
52805b261ecSmrg}
52905b261ecSmrg
5304642e01fSmrg#define CheckDirect(dev, plane) \
5314642e01fSmrg	    UpdateDAC(dev, plane,red,redMask) \
5324642e01fSmrg	    UpdateDAC(dev, plane,green,greenMask) \
5334642e01fSmrg	    UpdateDAC(dev, plane,blue,blueMask)
5344642e01fSmrg
53535c4bbdfSmrg            for (i = 0; i < ndef; i++) {
53635c4bbdfSmrg                CheckDirect(pPriv, SOURCE_COLOR)
53735c4bbdfSmrg                    CheckDirect(pPriv, MASK_COLOR)
5384642e01fSmrg            }
5394642e01fSmrg        }
54035c4bbdfSmrg        else {
5414642e01fSmrg            /* PseudoColor/GrayScale - match on exact pixel */
54235c4bbdfSmrg            for (i = 0; i < ndef; i++) {
54335c4bbdfSmrg                if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) {
5444642e01fSmrg                    pPriv->colors[SOURCE_COLOR] = pdef[i];
5454642e01fSmrg                    if (++updated == 2)
5464642e01fSmrg                        break;
5474642e01fSmrg                }
54835c4bbdfSmrg                if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) {
5494642e01fSmrg                    pPriv->colors[MASK_COLOR] = pdef[i];
5504642e01fSmrg                    if (++updated == 2)
5514642e01fSmrg                        break;
5524642e01fSmrg                }
5534642e01fSmrg            }
5544642e01fSmrg        }
55535c4bbdfSmrg        if (updated) {
55635c4bbdfSmrg            for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
55735c4bbdfSmrg                if (DevHasCursor(pDev)) {
5581b5d61b8Smrg                    pCursorInfo = GetSprite(pDev);
5594642e01fSmrg                    pCursorInfo->checkPixels = TRUE;
5604642e01fSmrg                    if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
56135c4bbdfSmrg                        miSpriteRemoveCursor(pDev, pScreen);
5624642e01fSmrg                }
5634642e01fSmrg            }
5644642e01fSmrg        }
56505b261ecSmrg    }
56605b261ecSmrg}
56705b261ecSmrg
56805b261ecSmrgstatic void
56935c4bbdfSmrgmiSpriteFindColors(miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
57005b261ecSmrg{
57135c4bbdfSmrg    miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
57235c4bbdfSmrg    CursorPtr pCursor;
57335c4bbdfSmrg    xColorItem *sourceColor, *maskColor;
57405b261ecSmrg
5754642e01fSmrg    pCursor = pDevCursor->pCursor;
57605b261ecSmrg    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
57705b261ecSmrg    maskColor = &pScreenPriv->colors[MASK_COLOR];
57805b261ecSmrg    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
57935c4bbdfSmrg        !(pCursor->foreRed == sourceColor->red &&
58035c4bbdfSmrg          pCursor->foreGreen == sourceColor->green &&
58105b261ecSmrg          pCursor->foreBlue == sourceColor->blue &&
58235c4bbdfSmrg          pCursor->backRed == maskColor->red &&
58335c4bbdfSmrg          pCursor->backGreen == maskColor->green &&
58435c4bbdfSmrg          pCursor->backBlue == maskColor->blue)) {
58535c4bbdfSmrg        pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
58635c4bbdfSmrg        sourceColor->red = pCursor->foreRed;
58735c4bbdfSmrg        sourceColor->green = pCursor->foreGreen;
58835c4bbdfSmrg        sourceColor->blue = pCursor->foreBlue;
58935c4bbdfSmrg        FakeAllocColor(pScreenPriv->pColormap, sourceColor);
59035c4bbdfSmrg        maskColor->red = pCursor->backRed;
59135c4bbdfSmrg        maskColor->green = pCursor->backGreen;
59235c4bbdfSmrg        maskColor->blue = pCursor->backBlue;
59335c4bbdfSmrg        FakeAllocColor(pScreenPriv->pColormap, maskColor);
59435c4bbdfSmrg        /* "free" the pixels right away, don't let this confuse you */
59535c4bbdfSmrg        FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
59635c4bbdfSmrg        FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
59705b261ecSmrg    }
59805b261ecSmrg
5994642e01fSmrg    pDevCursor->checkPixels = FALSE;
60005b261ecSmrg
60105b261ecSmrg}
60205b261ecSmrg
60305b261ecSmrg/*
60405b261ecSmrg * miPointer interface routines
60505b261ecSmrg */
60605b261ecSmrg
60705b261ecSmrg#define SPRITE_PAD  8
60805b261ecSmrg
60905b261ecSmrgstatic Bool
61035c4bbdfSmrgmiSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
61105b261ecSmrg{
6124642e01fSmrg    miCursorInfoPtr pCursorInfo;
6134642e01fSmrg
61435c4bbdfSmrg    if (IsFloating(pDev))
6154642e01fSmrg        return FALSE;
6166747b715Smrg
6171b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
6184642e01fSmrg
6194642e01fSmrg    if (pCursor == pCursorInfo->pCursor)
62035c4bbdfSmrg        pCursorInfo->checkPixels = TRUE;
62105b261ecSmrg
6226747b715Smrg    return miDCRealizeCursor(pScreen, pCursor);
62305b261ecSmrg}
62405b261ecSmrg
62505b261ecSmrgstatic Bool
6264642e01fSmrgmiSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
62705b261ecSmrg{
6286747b715Smrg    return miDCUnrealizeCursor(pScreen, pCursor);
62905b261ecSmrg}
63005b261ecSmrg
63105b261ecSmrgstatic void
63235c4bbdfSmrgmiSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
63335c4bbdfSmrg                  CursorPtr pCursor, int x, int y)
63405b261ecSmrg{
63535c4bbdfSmrg    miCursorInfoPtr pPointer;
63635c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
6374642e01fSmrg
63835c4bbdfSmrg    if (IsFloating(pDev))
6394642e01fSmrg        return;
6406747b715Smrg
6411b5d61b8Smrg    pPointer = GetSprite(pDev);
6429ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
6434642e01fSmrg
64435c4bbdfSmrg    if (!pCursor) {
64535c4bbdfSmrg        if (pPointer->shouldBeUp)
64635c4bbdfSmrg            --pScreenPriv->numberOfCursors;
64735c4bbdfSmrg        pPointer->shouldBeUp = FALSE;
64835c4bbdfSmrg        if (pPointer->isUp)
64935c4bbdfSmrg            miSpriteRemoveCursor(pDev, pScreen);
65035c4bbdfSmrg        if (pScreenPriv->numberOfCursors == 0)
65135c4bbdfSmrg            miSpriteDisableDamage(pScreen, pScreenPriv);
65235c4bbdfSmrg        pPointer->pCursor = 0;
65335c4bbdfSmrg        return;
65405b261ecSmrg    }
6559ace9065Smrg    if (!pPointer->shouldBeUp)
65635c4bbdfSmrg        pScreenPriv->numberOfCursors++;
6574642e01fSmrg    pPointer->shouldBeUp = TRUE;
6589ace9065Smrg    if (!pPointer->isUp)
65935c4bbdfSmrg        miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
6604642e01fSmrg    if (pPointer->x == x &&
66135c4bbdfSmrg        pPointer->y == y &&
66235c4bbdfSmrg        pPointer->pCursor == pCursor && !pPointer->checkPixels) {
66335c4bbdfSmrg        return;
66405b261ecSmrg    }
6654642e01fSmrg    pPointer->x = x;
6664642e01fSmrg    pPointer->y = y;
66735c4bbdfSmrg    if (pPointer->checkPixels || pPointer->pCursor != pCursor) {
66835c4bbdfSmrg        pPointer->pCursor = pCursor;
66935c4bbdfSmrg        miSpriteFindColors(pPointer, pScreen);
67005b261ecSmrg    }
6714642e01fSmrg    if (pPointer->isUp) {
67235c4bbdfSmrg        /* TODO: reimplement flicker-free MoveCursor */
67335c4bbdfSmrg        SPRITE_DEBUG(("SetCursor remove %d\n", pDev->id));
67435c4bbdfSmrg        miSpriteRemoveCursor(pDev, pScreen);
67505b261ecSmrg    }
6764642e01fSmrg
67735c4bbdfSmrg    if (!pPointer->isUp && pPointer->pCursor) {
67835c4bbdfSmrg        SPRITE_DEBUG(("SetCursor restore %d\n", pDev->id));
6794642e01fSmrg        miSpriteSaveUnderCursor(pDev, pScreen);
68035c4bbdfSmrg        miSpriteRestoreCursor(pDev, pScreen);
68105b261ecSmrg    }
6824642e01fSmrg
68305b261ecSmrg}
68405b261ecSmrg
68505b261ecSmrgstatic void
68635c4bbdfSmrgmiSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
68705b261ecSmrg{
6884642e01fSmrg    CursorPtr pCursor;
68905b261ecSmrg
69035c4bbdfSmrg    if (IsFloating(pDev))
6914642e01fSmrg        return;
6926747b715Smrg
6931b5d61b8Smrg    pCursor = GetSprite(pDev)->pCursor;
6944642e01fSmrg
69535c4bbdfSmrg    miSpriteSetCursor(pDev, pScreen, pCursor, x, y);
6964642e01fSmrg}
6974642e01fSmrg
6984642e01fSmrgstatic Bool
6994642e01fSmrgmiSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
7004642e01fSmrg{
70135c4bbdfSmrg    int ret = miDCDeviceInitialize(pDev, pScreen);
70235c4bbdfSmrg
70335c4bbdfSmrg    if (ret) {
70435c4bbdfSmrg        miCursorInfoPtr pCursorInfo;
70535c4bbdfSmrg
70635c4bbdfSmrg        pCursorInfo =
7071b5d61b8Smrg            dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec);
70835c4bbdfSmrg        pCursorInfo->pCursor = NULL;
70935c4bbdfSmrg        pCursorInfo->x = 0;
71035c4bbdfSmrg        pCursorInfo->y = 0;
71135c4bbdfSmrg        pCursorInfo->isUp = FALSE;
71235c4bbdfSmrg        pCursorInfo->shouldBeUp = FALSE;
71335c4bbdfSmrg        pCursorInfo->checkPixels = TRUE;
71435c4bbdfSmrg        pCursorInfo->pScreen = FALSE;
7154642e01fSmrg    }
71635c4bbdfSmrg
7174642e01fSmrg    return ret;
7184642e01fSmrg}
7194642e01fSmrg
7204642e01fSmrgstatic void
7214642e01fSmrgmiSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
7224642e01fSmrg{
72335c4bbdfSmrg    miCursorInfoPtr pCursorInfo =
7241b5d61b8Smrg        dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec);
72535c4bbdfSmrg
7264642e01fSmrg    if (DevHasCursor(pDev))
7276747b715Smrg        miDCDeviceCleanup(pDev, pScreen);
72835c4bbdfSmrg
72935c4bbdfSmrg    memset(pCursorInfo, 0, sizeof(miCursorInfoRec));
73005b261ecSmrg}
73105b261ecSmrg
73205b261ecSmrg/*
73305b261ecSmrg * undraw/draw cursor
73405b261ecSmrg */
73505b261ecSmrg
73605b261ecSmrgstatic void
73735c4bbdfSmrgmiSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
73805b261ecSmrg{
73935c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
74035c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
74105b261ecSmrg
74235c4bbdfSmrg    if (IsFloating(pDev))
7434642e01fSmrg        return;
7446747b715Smrg
74535c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
7469ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
7471b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
7484642e01fSmrg
7494642e01fSmrg    miSpriteIsDown(pCursorInfo);
7509ace9065Smrg    miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
7514642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
7526747b715Smrg    if (!miDCRestoreUnderCursor(pDev,
7536747b715Smrg                                pScreen,
7546747b715Smrg                                pCursorInfo->saved.x1,
7556747b715Smrg                                pCursorInfo->saved.y1,
7566747b715Smrg                                pCursorInfo->saved.x2 -
7576747b715Smrg                                pCursorInfo->saved.x1,
7586747b715Smrg                                pCursorInfo->saved.y2 -
75935c4bbdfSmrg                                pCursorInfo->saved.y1)) {
7606747b715Smrg        miSpriteIsUp(pCursorInfo);
76105b261ecSmrg    }
7624642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
76335c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
76405b261ecSmrg}
76505b261ecSmrg
7664642e01fSmrg/*
7674642e01fSmrg * Called from the block handler, saves area under cursor
7684642e01fSmrg * before waiting for something to do.
7694642e01fSmrg */
7704642e01fSmrg
7714642e01fSmrgstatic void
7724642e01fSmrgmiSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
7734642e01fSmrg{
77435c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
77535c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
7764642e01fSmrg
77735c4bbdfSmrg    if (IsFloating(pDev))
7784642e01fSmrg        return;
7796747b715Smrg
78035c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
7819ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
7821b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
7834642e01fSmrg
78435c4bbdfSmrg    miSpriteComputeSaved(pDev, pScreen);
7854642e01fSmrg
7864642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
7874642e01fSmrg
7886747b715Smrg    miDCSaveUnderCursor(pDev,
7896747b715Smrg                        pScreen,
7906747b715Smrg                        pCursorInfo->saved.x1,
7916747b715Smrg                        pCursorInfo->saved.y1,
7926747b715Smrg                        pCursorInfo->saved.x2 -
7936747b715Smrg                        pCursorInfo->saved.x1,
79435c4bbdfSmrg                        pCursorInfo->saved.y2 - pCursorInfo->saved.y1);
7954642e01fSmrg    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
7964642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
79735c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
7984642e01fSmrg}
7994642e01fSmrg
80005b261ecSmrg/*
80105b261ecSmrg * Called from the block handler, restores the cursor
80205b261ecSmrg * before waiting for something to do.
80305b261ecSmrg */
80405b261ecSmrg
80505b261ecSmrgstatic void
80635c4bbdfSmrgmiSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
80705b261ecSmrg{
80835c4bbdfSmrg    miSpriteScreenPtr pScreenPriv;
80935c4bbdfSmrg    int x, y;
81035c4bbdfSmrg    CursorPtr pCursor;
81135c4bbdfSmrg    miCursorInfoPtr pCursorInfo;
8124642e01fSmrg
81335c4bbdfSmrg    if (IsFloating(pDev))
8144642e01fSmrg        return;
81505b261ecSmrg
81635c4bbdfSmrg    DamageDrawInternal(pScreen, TRUE);
8179ace9065Smrg    pScreenPriv = GetSpriteScreen(pScreen);
8181b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
8194642e01fSmrg
82035c4bbdfSmrg    miSpriteComputeSaved(pDev, pScreen);
8214642e01fSmrg    pCursor = pCursorInfo->pCursor;
8224642e01fSmrg
82335c4bbdfSmrg    x = pCursorInfo->x - (int) pCursor->bits->xhot;
82435c4bbdfSmrg    y = pCursorInfo->y - (int) pCursor->bits->yhot;
8254642e01fSmrg    miSpriteDisableDamage(pScreen, pScreenPriv);
8264642e01fSmrg    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
8274642e01fSmrg    if (pCursorInfo->checkPixels)
82835c4bbdfSmrg        miSpriteFindColors(pCursorInfo, pScreen);
8296747b715Smrg    if (miDCPutUpCursor(pDev, pScreen,
83035c4bbdfSmrg                        pCursor, x, y,
83135c4bbdfSmrg                        pScreenPriv->colors[SOURCE_COLOR].pixel,
83235c4bbdfSmrg                        pScreenPriv->colors[MASK_COLOR].pixel)) {
8334642e01fSmrg        miSpriteIsUp(pCursorInfo);
8344642e01fSmrg        pCursorInfo->pScreen = pScreen;
83505b261ecSmrg    }
8364642e01fSmrg    miSpriteEnableDamage(pScreen, pScreenPriv);
83735c4bbdfSmrg    DamageDrawInternal(pScreen, FALSE);
83805b261ecSmrg}
83905b261ecSmrg
84005b261ecSmrg/*
84105b261ecSmrg * compute the desired area of the screen to save
84205b261ecSmrg */
84305b261ecSmrg
84405b261ecSmrgstatic void
84535c4bbdfSmrgmiSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen)
84605b261ecSmrg{
84735c4bbdfSmrg    int x, y, w, h;
84835c4bbdfSmrg    int wpad, hpad;
84935c4bbdfSmrg    CursorPtr pCursor;
8504642e01fSmrg    miCursorInfoPtr pCursorInfo;
85105b261ecSmrg
85235c4bbdfSmrg    if (IsFloating(pDev))
8534642e01fSmrg        return;
8546747b715Smrg
8551b5d61b8Smrg    pCursorInfo = GetSprite(pDev);
8564642e01fSmrg
8574642e01fSmrg    pCursor = pCursorInfo->pCursor;
85835c4bbdfSmrg    x = pCursorInfo->x - (int) pCursor->bits->xhot;
85935c4bbdfSmrg    y = pCursorInfo->y - (int) pCursor->bits->yhot;
86005b261ecSmrg    w = pCursor->bits->width;
86105b261ecSmrg    h = pCursor->bits->height;
86205b261ecSmrg    wpad = SPRITE_PAD;
86305b261ecSmrg    hpad = SPRITE_PAD;
8644642e01fSmrg    pCursorInfo->saved.x1 = x - wpad;
8654642e01fSmrg    pCursorInfo->saved.y1 = y - hpad;
8664642e01fSmrg    pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
8674642e01fSmrg    pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
86805b261ecSmrg}
869