1706f2543Smrg/*
2706f2543Smrg * misprite.c
3706f2543Smrg *
4706f2543Smrg * machine independent software sprite routines
5706f2543Smrg */
6706f2543Smrg
7706f2543Smrg/*
8706f2543Smrg
9706f2543SmrgCopyright 1989, 1998  The Open Group
10706f2543Smrg
11706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
12706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
13706f2543Smrgthe above copyright notice appear in all copies and that both that
14706f2543Smrgcopyright notice and this permission notice appear in supporting
15706f2543Smrgdocumentation.
16706f2543Smrg
17706f2543SmrgThe above copyright notice and this permission notice shall be included in
18706f2543Smrgall copies or substantial portions of the Software.
19706f2543Smrg
20706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
23706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26706f2543Smrg
27706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
28706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
29706f2543Smrgin this Software without prior written authorization from The Open Group.
30706f2543Smrg*/
31706f2543Smrg
32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
33706f2543Smrg#include <dix-config.h>
34706f2543Smrg#endif
35706f2543Smrg
36706f2543Smrg#include   <X11/X.h>
37706f2543Smrg#include   <X11/Xproto.h>
38706f2543Smrg#include   "misc.h"
39706f2543Smrg#include   "pixmapstr.h"
40706f2543Smrg#include   "input.h"
41706f2543Smrg#include   "mi.h"
42706f2543Smrg#include   "cursorstr.h"
43706f2543Smrg#include   <X11/fonts/font.h>
44706f2543Smrg#include   "scrnintstr.h"
45706f2543Smrg#include   "colormapst.h"
46706f2543Smrg#include   "windowstr.h"
47706f2543Smrg#include   "gcstruct.h"
48706f2543Smrg#include   "mipointer.h"
49706f2543Smrg#include   "misprite.h"
50706f2543Smrg#include   "dixfontstr.h"
51706f2543Smrg#include   <X11/fonts/fontstruct.h>
52706f2543Smrg#include   "inputstr.h"
53706f2543Smrg#include   "damage.h"
54706f2543Smrg
55706f2543Smrgtypedef struct {
56706f2543Smrg    CursorPtr	    pCursor;
57706f2543Smrg    int		    x;			/* cursor hotspot */
58706f2543Smrg    int		    y;
59706f2543Smrg    BoxRec	    saved;		/* saved area from the screen */
60706f2543Smrg    Bool	    isUp;		/* cursor in frame buffer */
61706f2543Smrg    Bool	    shouldBeUp;		/* cursor should be displayed */
62706f2543Smrg    WindowPtr	    pCacheWin;		/* window the cursor last seen in */
63706f2543Smrg    Bool	    isInCacheWin;
64706f2543Smrg    Bool	    checkPixels;	/* check colormap collision */
65706f2543Smrg    ScreenPtr       pScreen;
66706f2543Smrg} miCursorInfoRec, *miCursorInfoPtr;
67706f2543Smrg
68706f2543Smrg/*
69706f2543Smrg * per screen information
70706f2543Smrg */
71706f2543Smrg
72706f2543Smrgtypedef struct {
73706f2543Smrg    /* screen procedures */
74706f2543Smrg    CloseScreenProcPtr			CloseScreen;
75706f2543Smrg    GetImageProcPtr			GetImage;
76706f2543Smrg    GetSpansProcPtr			GetSpans;
77706f2543Smrg    SourceValidateProcPtr		SourceValidate;
78706f2543Smrg
79706f2543Smrg    /* window procedures */
80706f2543Smrg    CopyWindowProcPtr			CopyWindow;
81706f2543Smrg
82706f2543Smrg    /* colormap procedures */
83706f2543Smrg    InstallColormapProcPtr		InstallColormap;
84706f2543Smrg    StoreColorsProcPtr			StoreColors;
85706f2543Smrg
86706f2543Smrg    /* os layer procedures */
87706f2543Smrg    ScreenBlockHandlerProcPtr		BlockHandler;
88706f2543Smrg
89706f2543Smrg    /* device cursor procedures */
90706f2543Smrg    DeviceCursorInitializeProcPtr       DeviceCursorInitialize;
91706f2543Smrg    DeviceCursorCleanupProcPtr          DeviceCursorCleanup;
92706f2543Smrg
93706f2543Smrg    xColorItem	    colors[2];
94706f2543Smrg    ColormapPtr     pInstalledMap;
95706f2543Smrg    ColormapPtr     pColormap;
96706f2543Smrg    VisualPtr	    pVisual;
97706f2543Smrg    DamagePtr	    pDamage;		/* damage tracking structure */
98706f2543Smrg    Bool            damageRegistered;
99706f2543Smrg    int             numberOfCursors;
100706f2543Smrg} miSpriteScreenRec, *miSpriteScreenPtr;
101706f2543Smrg
102706f2543Smrg#define SOURCE_COLOR	0
103706f2543Smrg#define MASK_COLOR	1
104706f2543Smrg
105706f2543Smrg/*
106706f2543Smrg * Overlap BoxPtr and Box elements
107706f2543Smrg */
108706f2543Smrg#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
109706f2543Smrg 	(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
110706f2543Smrg	 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
111706f2543Smrg
112706f2543Smrg/*
113706f2543Smrg * Overlap BoxPtr, origins, and rectangle
114706f2543Smrg */
115706f2543Smrg#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
116706f2543Smrg    BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
117706f2543Smrg
118706f2543Smrg/*
119706f2543Smrg * Overlap BoxPtr, origins and RectPtr
120706f2543Smrg */
121706f2543Smrg#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
122706f2543Smrg    ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
123706f2543Smrg		(int)((pRect)->width), (int)((pRect)->height))
124706f2543Smrg/*
125706f2543Smrg * Overlap BoxPtr and horizontal span
126706f2543Smrg */
127706f2543Smrg#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
128706f2543Smrg
129706f2543Smrg#define LINE_SORT(x1,y1,x2,y2) \
130706f2543Smrg{ int _t; \
131706f2543Smrg  if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
132706f2543Smrg  if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
133706f2543Smrg
134706f2543Smrg#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
135706f2543Smrg    BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
136706f2543Smrg
137706f2543Smrg
138706f2543Smrg#define SPRITE_DEBUG_ENABLE 0
139706f2543Smrg#if SPRITE_DEBUG_ENABLE
140706f2543Smrg#define SPRITE_DEBUG(x)	ErrorF x
141706f2543Smrg#else
142706f2543Smrg#define SPRITE_DEBUG(x)
143706f2543Smrg#endif
144706f2543Smrg
145706f2543Smrg#define MISPRITE(dev) \
146706f2543Smrg    ((!IsMaster(dev) && !dev->u.master) ? \
147706f2543Smrg       (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
148706f2543Smrg       (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
149706f2543Smrg
150706f2543Smrgstatic void
151706f2543SmrgmiSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
152706f2543Smrg{
153706f2543Smrg    if (pScreenPriv->damageRegistered) {
154706f2543Smrg	DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
155706f2543Smrg			  pScreenPriv->pDamage);
156706f2543Smrg	pScreenPriv->damageRegistered = 0;
157706f2543Smrg    }
158706f2543Smrg}
159706f2543Smrg
160706f2543Smrgstatic void
161706f2543SmrgmiSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
162706f2543Smrg{
163706f2543Smrg    if (!pScreenPriv->damageRegistered) {
164706f2543Smrg	pScreenPriv->damageRegistered = 1;
165706f2543Smrg	DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
166706f2543Smrg			pScreenPriv->pDamage);
167706f2543Smrg    }
168706f2543Smrg}
169706f2543Smrg
170706f2543Smrgstatic void
171706f2543SmrgmiSpriteIsUp(miCursorInfoPtr pDevCursor)
172706f2543Smrg{
173706f2543Smrg    pDevCursor->isUp = TRUE;
174706f2543Smrg}
175706f2543Smrg
176706f2543Smrgstatic void
177706f2543SmrgmiSpriteIsDown(miCursorInfoPtr pDevCursor)
178706f2543Smrg{
179706f2543Smrg    pDevCursor->isUp = FALSE;
180706f2543Smrg}
181706f2543Smrg
182706f2543Smrg/*
183706f2543Smrg * screen wrappers
184706f2543Smrg */
185706f2543Smrg
186706f2543Smrgstatic DevPrivateKeyRec miSpriteScreenKeyRec;
187706f2543Smrg#define miSpriteScreenKey (&miSpriteScreenKeyRec)
188706f2543Smrg#define GetSpriteScreen(pScreen) \
189706f2543Smrg	(dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey))
190706f2543Smrgstatic DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
191706f2543Smrg#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
192706f2543Smrg
193706f2543Smrgstatic Bool	    miSpriteCloseScreen(int i, ScreenPtr pScreen);
194706f2543Smrgstatic void	    miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
195706f2543Smrg				     int w, int h, unsigned int format,
196706f2543Smrg				     unsigned long planemask, char *pdstLine);
197706f2543Smrgstatic void	    miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
198706f2543Smrg				     DDXPointPtr ppt, int *pwidth, int nspans,
199706f2543Smrg				     char *pdstStart);
200706f2543Smrgstatic void	    miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
201706f2543Smrg					   int width, int height,
202706f2543Smrg					   unsigned int subWindowMode);
203706f2543Smrgstatic void	    miSpriteCopyWindow (WindowPtr pWindow,
204706f2543Smrg					DDXPointRec ptOldOrg,
205706f2543Smrg					RegionPtr prgnSrc);
206706f2543Smrgstatic void	    miSpriteBlockHandler(int i, pointer blockData,
207706f2543Smrg					 pointer pTimeout,
208706f2543Smrg					 pointer pReadMask);
209706f2543Smrgstatic void	    miSpriteInstallColormap(ColormapPtr pMap);
210706f2543Smrgstatic void	    miSpriteStoreColors(ColormapPtr pMap, int ndef,
211706f2543Smrg					xColorItem *pdef);
212706f2543Smrg
213706f2543Smrgstatic void	    miSpriteComputeSaved(DeviceIntPtr pDev,
214706f2543Smrg                                         ScreenPtr pScreen);
215706f2543Smrg
216706f2543Smrgstatic Bool         miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
217706f2543Smrg                                                   ScreenPtr pScreen);
218706f2543Smrgstatic void         miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,
219706f2543Smrg                                                ScreenPtr pScreen);
220706f2543Smrg
221706f2543Smrg#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
222706f2543Smrg   (pPriv)->field)
223706f2543Smrg#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
224706f2543Smrg    ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
225706f2543Smrg
226706f2543Smrg/*
227706f2543Smrg * pointer-sprite method table
228706f2543Smrg */
229706f2543Smrg
230706f2543Smrgstatic Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
231706f2543Smrg                                  CursorPtr pCursor);
232706f2543Smrgstatic Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
233706f2543Smrg                                    CursorPtr pCursor);
234706f2543Smrgstatic void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
235706f2543Smrg                              CursorPtr pCursor, int x, int y);
236706f2543Smrgstatic void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
237706f2543Smrg                               int x, int y);
238706f2543Smrg
239706f2543SmrgmiPointerSpriteFuncRec miSpritePointerFuncs = {
240706f2543Smrg    miSpriteRealizeCursor,
241706f2543Smrg    miSpriteUnrealizeCursor,
242706f2543Smrg    miSpriteSetCursor,
243706f2543Smrg    miSpriteMoveCursor,
244706f2543Smrg    miSpriteDeviceCursorInitialize,
245706f2543Smrg    miSpriteDeviceCursorCleanup,
246706f2543Smrg};
247706f2543Smrg
248706f2543Smrg/*
249706f2543Smrg * other misc functions
250706f2543Smrg */
251706f2543Smrg
252706f2543Smrgstatic void miSpriteRemoveCursor(DeviceIntPtr pDev,
253706f2543Smrg                                 ScreenPtr pScreen);
254706f2543Smrgstatic void miSpriteSaveUnderCursor(DeviceIntPtr pDev,
255706f2543Smrg                                 ScreenPtr pScreen);
256706f2543Smrgstatic void miSpriteRestoreCursor(DeviceIntPtr pDev,
257706f2543Smrg                                 ScreenPtr pScreen);
258706f2543Smrg
259706f2543Smrgstatic void
260706f2543SmrgmiSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
261706f2543Smrg{
262706f2543Smrg    if (!pScreenPriv->BlockHandler) {
263706f2543Smrg        pScreenPriv->BlockHandler = pScreen->BlockHandler;
264706f2543Smrg        pScreen->BlockHandler = miSpriteBlockHandler;
265706f2543Smrg    }
266706f2543Smrg}
267706f2543Smrg
268706f2543Smrgstatic void
269706f2543SmrgmiSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
270706f2543Smrg{
271706f2543Smrg    ScreenPtr		    pScreen = closure;
272706f2543Smrg    miCursorInfoPtr         pCursorInfo;
273706f2543Smrg    DeviceIntPtr            pDev;
274706f2543Smrg
275706f2543Smrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
276706f2543Smrg    {
277706f2543Smrg        if (DevHasCursor(pDev))
278706f2543Smrg        {
279706f2543Smrg            pCursorInfo = MISPRITE(pDev);
280706f2543Smrg
281706f2543Smrg            if (pCursorInfo->isUp &&
282706f2543Smrg                pCursorInfo->pScreen == pScreen &&
283706f2543Smrg                RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT)
284706f2543Smrg            {
285706f2543Smrg                SPRITE_DEBUG(("Damage remove\n"));
286706f2543Smrg                miSpriteRemoveCursor (pDev, pScreen);
287706f2543Smrg            }
288706f2543Smrg        }
289706f2543Smrg    }
290706f2543Smrg}
291706f2543Smrg
292706f2543Smrg/*
293706f2543Smrg * miSpriteInitialize -- called from device-dependent screen
294706f2543Smrg * initialization proc after all of the function pointers have
295706f2543Smrg * been stored in the screen structure.
296706f2543Smrg */
297706f2543Smrg
298706f2543SmrgBool
299706f2543SmrgmiSpriteInitialize (ScreenPtr               pScreen,
300706f2543Smrg                    miPointerScreenFuncPtr  screenFuncs)
301706f2543Smrg{
302706f2543Smrg    miSpriteScreenPtr	pScreenPriv;
303706f2543Smrg    VisualPtr		pVisual;
304706f2543Smrg
305706f2543Smrg    if (!DamageSetup (pScreen))
306706f2543Smrg	return FALSE;
307706f2543Smrg
308706f2543Smrg    if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
309706f2543Smrg	return FALSE;
310706f2543Smrg
311706f2543Smrg    if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0))
312706f2543Smrg	return FALSE;
313706f2543Smrg
314706f2543Smrg    pScreenPriv = malloc(sizeof (miSpriteScreenRec));
315706f2543Smrg    if (!pScreenPriv)
316706f2543Smrg	return FALSE;
317706f2543Smrg
318706f2543Smrg    pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
319706f2543Smrg					 NULL,
320706f2543Smrg					 DamageReportRawRegion,
321706f2543Smrg					 TRUE,
322706f2543Smrg					 pScreen,
323706f2543Smrg					 pScreen);
324706f2543Smrg
325706f2543Smrg    if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
326706f2543Smrg    {
327706f2543Smrg	free(pScreenPriv);
328706f2543Smrg	return FALSE;
329706f2543Smrg    }
330706f2543Smrg    for (pVisual = pScreen->visuals;
331706f2543Smrg	 pVisual->vid != pScreen->rootVisual;
332706f2543Smrg	 pVisual++)
333706f2543Smrg	;
334706f2543Smrg    pScreenPriv->pVisual = pVisual;
335706f2543Smrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
336706f2543Smrg    pScreenPriv->GetImage = pScreen->GetImage;
337706f2543Smrg    pScreenPriv->GetSpans = pScreen->GetSpans;
338706f2543Smrg    pScreenPriv->SourceValidate = pScreen->SourceValidate;
339706f2543Smrg
340706f2543Smrg    pScreenPriv->CopyWindow = pScreen->CopyWindow;
341706f2543Smrg
342706f2543Smrg    pScreenPriv->InstallColormap = pScreen->InstallColormap;
343706f2543Smrg    pScreenPriv->StoreColors = pScreen->StoreColors;
344706f2543Smrg
345706f2543Smrg    pScreenPriv->BlockHandler = NULL;
346706f2543Smrg
347706f2543Smrg    pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
348706f2543Smrg    pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
349706f2543Smrg
350706f2543Smrg    pScreenPriv->pInstalledMap = NULL;
351706f2543Smrg    pScreenPriv->pColormap = NULL;
352706f2543Smrg    pScreenPriv->colors[SOURCE_COLOR].red = 0;
353706f2543Smrg    pScreenPriv->colors[SOURCE_COLOR].green = 0;
354706f2543Smrg    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
355706f2543Smrg    pScreenPriv->colors[MASK_COLOR].red = 0;
356706f2543Smrg    pScreenPriv->colors[MASK_COLOR].green = 0;
357706f2543Smrg    pScreenPriv->colors[MASK_COLOR].blue = 0;
358706f2543Smrg    pScreenPriv->damageRegistered = 0;
359706f2543Smrg    pScreenPriv->numberOfCursors = 0;
360706f2543Smrg
361706f2543Smrg    dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
362706f2543Smrg
363706f2543Smrg    pScreen->CloseScreen = miSpriteCloseScreen;
364706f2543Smrg    pScreen->GetImage = miSpriteGetImage;
365706f2543Smrg    pScreen->GetSpans = miSpriteGetSpans;
366706f2543Smrg    pScreen->SourceValidate = miSpriteSourceValidate;
367706f2543Smrg
368706f2543Smrg    pScreen->CopyWindow = miSpriteCopyWindow;
369706f2543Smrg    pScreen->InstallColormap = miSpriteInstallColormap;
370706f2543Smrg    pScreen->StoreColors = miSpriteStoreColors;
371706f2543Smrg
372706f2543Smrg    return TRUE;
373706f2543Smrg}
374706f2543Smrg
375706f2543Smrg/*
376706f2543Smrg * Screen wrappers
377706f2543Smrg */
378706f2543Smrg
379706f2543Smrg/*
380706f2543Smrg * CloseScreen wrapper -- unwrap everything, free the private data
381706f2543Smrg * and call the wrapped function
382706f2543Smrg */
383706f2543Smrg
384706f2543Smrgstatic Bool
385706f2543SmrgmiSpriteCloseScreen (int i, ScreenPtr pScreen)
386706f2543Smrg{
387706f2543Smrg    miSpriteScreenPtr   pScreenPriv = GetSpriteScreen(pScreen);
388706f2543Smrg
389706f2543Smrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
390706f2543Smrg    pScreen->GetImage = pScreenPriv->GetImage;
391706f2543Smrg    pScreen->GetSpans = pScreenPriv->GetSpans;
392706f2543Smrg    pScreen->SourceValidate = pScreenPriv->SourceValidate;
393706f2543Smrg    pScreen->InstallColormap = pScreenPriv->InstallColormap;
394706f2543Smrg    pScreen->StoreColors = pScreenPriv->StoreColors;
395706f2543Smrg
396706f2543Smrg    DamageDestroy (pScreenPriv->pDamage);
397706f2543Smrg
398706f2543Smrg    free(pScreenPriv);
399706f2543Smrg
400706f2543Smrg    return (*pScreen->CloseScreen) (i, pScreen);
401706f2543Smrg}
402706f2543Smrg
403706f2543Smrgstatic void
404706f2543SmrgmiSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
405706f2543Smrg                  unsigned int format, unsigned long planemask,
406706f2543Smrg                  char *pdstLine)
407706f2543Smrg{
408706f2543Smrg    ScreenPtr           pScreen = pDrawable->pScreen;
409706f2543Smrg    DeviceIntPtr        pDev;
410706f2543Smrg    miCursorInfoPtr     pCursorInfo;
411706f2543Smrg    miSpriteScreenPtr   pPriv = GetSpriteScreen(pScreen);
412706f2543Smrg
413706f2543Smrg    SCREEN_PROLOGUE (pPriv, pScreen, GetImage);
414706f2543Smrg
415706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
416706f2543Smrg    {
417706f2543Smrg        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
418706f2543Smrg        {
419706f2543Smrg            if (DevHasCursor(pDev))
420706f2543Smrg            {
421706f2543Smrg                 pCursorInfo = MISPRITE(pDev);
422706f2543Smrg                 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
423706f2543Smrg                      ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y,
424706f2543Smrg                                  sx, sy, w, h))
425706f2543Smrg                 {
426706f2543Smrg                     SPRITE_DEBUG (("GetImage remove\n"));
427706f2543Smrg                     miSpriteRemoveCursor (pDev, pScreen);
428706f2543Smrg                 }
429706f2543Smrg            }
430706f2543Smrg        }
431706f2543Smrg    }
432706f2543Smrg
433706f2543Smrg    (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
434706f2543Smrg			  format, planemask, pdstLine);
435706f2543Smrg
436706f2543Smrg    SCREEN_EPILOGUE (pPriv, pScreen, GetImage);
437706f2543Smrg}
438706f2543Smrg
439706f2543Smrgstatic void
440706f2543SmrgmiSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
441706f2543Smrg                  int *pwidth, int nspans, char *pdstStart)
442706f2543Smrg{
443706f2543Smrg    ScreenPtr		    pScreen = pDrawable->pScreen;
444706f2543Smrg    DeviceIntPtr            pDev;
445706f2543Smrg    miCursorInfoPtr         pCursorInfo;
446706f2543Smrg    miSpriteScreenPtr       pPriv = GetSpriteScreen(pScreen);
447706f2543Smrg
448706f2543Smrg    SCREEN_PROLOGUE (pPriv, pScreen, GetSpans);
449706f2543Smrg
450706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
451706f2543Smrg    {
452706f2543Smrg        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
453706f2543Smrg        {
454706f2543Smrg            if (DevHasCursor(pDev))
455706f2543Smrg            {
456706f2543Smrg                pCursorInfo = MISPRITE(pDev);
457706f2543Smrg
458706f2543Smrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
459706f2543Smrg                {
460706f2543Smrg                    DDXPointPtr    pts;
461706f2543Smrg                    int    	       *widths;
462706f2543Smrg                    int    	       nPts;
463706f2543Smrg                    int    	       xorg,
464706f2543Smrg                                   yorg;
465706f2543Smrg
466706f2543Smrg                    xorg = pDrawable->x;
467706f2543Smrg                    yorg = pDrawable->y;
468706f2543Smrg
469706f2543Smrg                    for (pts = ppt, widths = pwidth, nPts = nspans;
470706f2543Smrg                            nPts--;
471706f2543Smrg                            pts++, widths++)
472706f2543Smrg                    {
473706f2543Smrg                        if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
474706f2543Smrg                                    pts->x+xorg,*widths))
475706f2543Smrg                        {
476706f2543Smrg                            SPRITE_DEBUG (("GetSpans remove\n"));
477706f2543Smrg                            miSpriteRemoveCursor (pDev, pScreen);
478706f2543Smrg                            break;
479706f2543Smrg                        }
480706f2543Smrg                    }
481706f2543Smrg                }
482706f2543Smrg            }
483706f2543Smrg        }
484706f2543Smrg    }
485706f2543Smrg
486706f2543Smrg    (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
487706f2543Smrg
488706f2543Smrg    SCREEN_EPILOGUE (pPriv, pScreen, GetSpans);
489706f2543Smrg}
490706f2543Smrg
491706f2543Smrgstatic void
492706f2543SmrgmiSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
493706f2543Smrg                        int height, unsigned int subWindowMode)
494706f2543Smrg{
495706f2543Smrg    ScreenPtr		    pScreen = pDrawable->pScreen;
496706f2543Smrg    DeviceIntPtr            pDev;
497706f2543Smrg    miCursorInfoPtr         pCursorInfo;
498706f2543Smrg    miSpriteScreenPtr       pPriv = GetSpriteScreen(pScreen);
499706f2543Smrg
500706f2543Smrg    SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate);
501706f2543Smrg
502706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW)
503706f2543Smrg    {
504706f2543Smrg	for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
505706f2543Smrg	{
506706f2543Smrg	    if (DevHasCursor(pDev))
507706f2543Smrg	    {
508706f2543Smrg		pCursorInfo = MISPRITE(pDev);
509706f2543Smrg		if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
510706f2543Smrg		    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
511706f2543Smrg				x, y, width, height))
512706f2543Smrg		{
513706f2543Smrg		    SPRITE_DEBUG (("SourceValidate remove\n"));
514706f2543Smrg		    miSpriteRemoveCursor (pDev, pScreen);
515706f2543Smrg		}
516706f2543Smrg	    }
517706f2543Smrg	}
518706f2543Smrg    }
519706f2543Smrg
520706f2543Smrg    if (pScreen->SourceValidate)
521706f2543Smrg	(*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode);
522706f2543Smrg
523706f2543Smrg    SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate);
524706f2543Smrg}
525706f2543Smrg
526706f2543Smrgstatic void
527706f2543SmrgmiSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
528706f2543Smrg{
529706f2543Smrg    ScreenPtr	pScreen = pWindow->drawable.pScreen;
530706f2543Smrg    DeviceIntPtr            pDev;
531706f2543Smrg    miCursorInfoPtr         pCursorInfo;
532706f2543Smrg    miSpriteScreenPtr       pPriv = GetSpriteScreen(pScreen);
533706f2543Smrg
534706f2543Smrg    SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow);
535706f2543Smrg
536706f2543Smrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
537706f2543Smrg    {
538706f2543Smrg        if (DevHasCursor(pDev))
539706f2543Smrg        {
540706f2543Smrg            pCursorInfo = MISPRITE(pDev);
541706f2543Smrg            /*
542706f2543Smrg             * Damage will take care of destination check
543706f2543Smrg             */
544706f2543Smrg            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
545706f2543Smrg                    RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT)
546706f2543Smrg            {
547706f2543Smrg                SPRITE_DEBUG (("CopyWindow remove\n"));
548706f2543Smrg                miSpriteRemoveCursor (pDev, pScreen);
549706f2543Smrg            }
550706f2543Smrg        }
551706f2543Smrg    }
552706f2543Smrg
553706f2543Smrg    (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
554706f2543Smrg    SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow);
555706f2543Smrg}
556706f2543Smrg
557706f2543Smrgstatic void
558706f2543SmrgmiSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
559706f2543Smrg                      pointer pReadmask)
560706f2543Smrg{
561706f2543Smrg    ScreenPtr		pScreen = screenInfo.screens[i];
562706f2543Smrg    miSpriteScreenPtr	pPriv = GetSpriteScreen(pScreen);
563706f2543Smrg    DeviceIntPtr            pDev;
564706f2543Smrg    miCursorInfoPtr         pCursorInfo;
565706f2543Smrg    Bool                WorkToDo = FALSE;
566706f2543Smrg
567706f2543Smrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
568706f2543Smrg    {
569706f2543Smrg        if (DevHasCursor(pDev))
570706f2543Smrg        {
571706f2543Smrg            pCursorInfo = MISPRITE(pDev);
572706f2543Smrg            if (pCursorInfo && !pCursorInfo->isUp
573706f2543Smrg                    && pCursorInfo->pScreen == pScreen
574706f2543Smrg                    && pCursorInfo->shouldBeUp)
575706f2543Smrg            {
576706f2543Smrg                SPRITE_DEBUG (("BlockHandler save"));
577706f2543Smrg                miSpriteSaveUnderCursor (pDev, pScreen);
578706f2543Smrg            }
579706f2543Smrg        }
580706f2543Smrg    }
581706f2543Smrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
582706f2543Smrg    {
583706f2543Smrg        if (DevHasCursor(pDev))
584706f2543Smrg        {
585706f2543Smrg            pCursorInfo = MISPRITE(pDev);
586706f2543Smrg            if (pCursorInfo && !pCursorInfo->isUp &&
587706f2543Smrg                    pCursorInfo->pScreen == pScreen &&
588706f2543Smrg                    pCursorInfo->shouldBeUp)
589706f2543Smrg            {
590706f2543Smrg                SPRITE_DEBUG (("BlockHandler restore\n"));
591706f2543Smrg                miSpriteRestoreCursor (pDev, pScreen);
592706f2543Smrg                if (!pCursorInfo->isUp)
593706f2543Smrg                    WorkToDo = TRUE;
594706f2543Smrg            }
595706f2543Smrg        }
596706f2543Smrg    }
597706f2543Smrg
598706f2543Smrg    SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
599706f2543Smrg
600706f2543Smrg    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
601706f2543Smrg
602706f2543Smrg    if (WorkToDo)
603706f2543Smrg        SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
604706f2543Smrg    else
605706f2543Smrg        pPriv->BlockHandler = NULL;
606706f2543Smrg}
607706f2543Smrg
608706f2543Smrgstatic void
609706f2543SmrgmiSpriteInstallColormap (ColormapPtr pMap)
610706f2543Smrg{
611706f2543Smrg    ScreenPtr		pScreen = pMap->pScreen;
612706f2543Smrg    miSpriteScreenPtr	pPriv = GetSpriteScreen(pScreen);
613706f2543Smrg
614706f2543Smrg    SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
615706f2543Smrg
616706f2543Smrg    (*pScreen->InstallColormap) (pMap);
617706f2543Smrg
618706f2543Smrg    SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
619706f2543Smrg
620706f2543Smrg    /* InstallColormap can be called before devices are initialized. */
621706f2543Smrg    pPriv->pInstalledMap = pMap;
622706f2543Smrg    if (pPriv->pColormap != pMap)
623706f2543Smrg    {
624706f2543Smrg        DeviceIntPtr pDev;
625706f2543Smrg        miCursorInfoPtr     pCursorInfo;
626706f2543Smrg        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
627706f2543Smrg        {
628706f2543Smrg            if (DevHasCursor(pDev))
629706f2543Smrg            {
630706f2543Smrg                pCursorInfo = MISPRITE(pDev);
631706f2543Smrg                pCursorInfo->checkPixels = TRUE;
632706f2543Smrg                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
633706f2543Smrg                    miSpriteRemoveCursor(pDev, pScreen);
634706f2543Smrg            }
635706f2543Smrg        }
636706f2543Smrg
637706f2543Smrg    }
638706f2543Smrg}
639706f2543Smrg
640706f2543Smrgstatic void
641706f2543SmrgmiSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
642706f2543Smrg{
643706f2543Smrg    ScreenPtr		pScreen = pMap->pScreen;
644706f2543Smrg    miSpriteScreenPtr	pPriv = GetSpriteScreen(pScreen);
645706f2543Smrg    int			i;
646706f2543Smrg    int			updated;
647706f2543Smrg    VisualPtr		pVisual;
648706f2543Smrg    DeviceIntPtr        pDev;
649706f2543Smrg    miCursorInfoPtr     pCursorInfo;
650706f2543Smrg
651706f2543Smrg    SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
652706f2543Smrg
653706f2543Smrg    (*pScreen->StoreColors) (pMap, ndef, pdef);
654706f2543Smrg
655706f2543Smrg    SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
656706f2543Smrg
657706f2543Smrg    if (pPriv->pColormap == pMap)
658706f2543Smrg    {
659706f2543Smrg        updated = 0;
660706f2543Smrg        pVisual = pMap->pVisual;
661706f2543Smrg        if (pVisual->class == DirectColor)
662706f2543Smrg        {
663706f2543Smrg            /* Direct color - match on any of the subfields */
664706f2543Smrg
665706f2543Smrg#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
666706f2543Smrg
667706f2543Smrg#define UpdateDAC(dev, plane,dac,mask) {\
668706f2543Smrg    if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
669706f2543Smrg	dev->colors[plane].dac = pdef[i].dac; \
670706f2543Smrg	updated = 1; \
671706f2543Smrg    } \
672706f2543Smrg}
673706f2543Smrg
674706f2543Smrg#define CheckDirect(dev, plane) \
675706f2543Smrg	    UpdateDAC(dev, plane,red,redMask) \
676706f2543Smrg	    UpdateDAC(dev, plane,green,greenMask) \
677706f2543Smrg	    UpdateDAC(dev, plane,blue,blueMask)
678706f2543Smrg
679706f2543Smrg            for (i = 0; i < ndef; i++)
680706f2543Smrg            {
681706f2543Smrg                CheckDirect (pPriv, SOURCE_COLOR)
682706f2543Smrg                CheckDirect (pPriv, MASK_COLOR)
683706f2543Smrg            }
684706f2543Smrg        }
685706f2543Smrg        else
686706f2543Smrg        {
687706f2543Smrg            /* PseudoColor/GrayScale - match on exact pixel */
688706f2543Smrg            for (i = 0; i < ndef; i++)
689706f2543Smrg            {
690706f2543Smrg                if (pdef[i].pixel ==
691706f2543Smrg                        pPriv->colors[SOURCE_COLOR].pixel)
692706f2543Smrg                {
693706f2543Smrg                    pPriv->colors[SOURCE_COLOR] = pdef[i];
694706f2543Smrg                    if (++updated == 2)
695706f2543Smrg                        break;
696706f2543Smrg                }
697706f2543Smrg                if (pdef[i].pixel ==
698706f2543Smrg                        pPriv->colors[MASK_COLOR].pixel)
699706f2543Smrg                {
700706f2543Smrg                    pPriv->colors[MASK_COLOR] = pdef[i];
701706f2543Smrg                    if (++updated == 2)
702706f2543Smrg                        break;
703706f2543Smrg                }
704706f2543Smrg            }
705706f2543Smrg        }
706706f2543Smrg        if (updated)
707706f2543Smrg        {
708706f2543Smrg            for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
709706f2543Smrg            {
710706f2543Smrg                if (DevHasCursor(pDev))
711706f2543Smrg                {
712706f2543Smrg                    pCursorInfo = MISPRITE(pDev);
713706f2543Smrg                    pCursorInfo->checkPixels = TRUE;
714706f2543Smrg                    if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
715706f2543Smrg                        miSpriteRemoveCursor (pDev, pScreen);
716706f2543Smrg                }
717706f2543Smrg            }
718706f2543Smrg        }
719706f2543Smrg    }
720706f2543Smrg}
721706f2543Smrg
722706f2543Smrgstatic void
723706f2543SmrgmiSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
724706f2543Smrg{
725706f2543Smrg    miSpriteScreenPtr	pScreenPriv = GetSpriteScreen(pScreen);
726706f2543Smrg    CursorPtr		pCursor;
727706f2543Smrg    xColorItem		*sourceColor, *maskColor;
728706f2543Smrg
729706f2543Smrg    pCursor = pDevCursor->pCursor;
730706f2543Smrg    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
731706f2543Smrg    maskColor = &pScreenPriv->colors[MASK_COLOR];
732706f2543Smrg    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
733706f2543Smrg	!(pCursor->foreRed == sourceColor->red &&
734706f2543Smrg	  pCursor->foreGreen == sourceColor->green &&
735706f2543Smrg          pCursor->foreBlue == sourceColor->blue &&
736706f2543Smrg	  pCursor->backRed == maskColor->red &&
737706f2543Smrg	  pCursor->backGreen == maskColor->green &&
738706f2543Smrg	  pCursor->backBlue == maskColor->blue))
739706f2543Smrg    {
740706f2543Smrg	pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
741706f2543Smrg	sourceColor->red = pCursor->foreRed;
742706f2543Smrg	sourceColor->green = pCursor->foreGreen;
743706f2543Smrg	sourceColor->blue = pCursor->foreBlue;
744706f2543Smrg	FakeAllocColor (pScreenPriv->pColormap, sourceColor);
745706f2543Smrg	maskColor->red = pCursor->backRed;
746706f2543Smrg	maskColor->green = pCursor->backGreen;
747706f2543Smrg	maskColor->blue = pCursor->backBlue;
748706f2543Smrg	FakeAllocColor (pScreenPriv->pColormap, maskColor);
749706f2543Smrg	/* "free" the pixels right away, don't let this confuse you */
750706f2543Smrg	FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
751706f2543Smrg	FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
752706f2543Smrg    }
753706f2543Smrg
754706f2543Smrg    pDevCursor->checkPixels = FALSE;
755706f2543Smrg
756706f2543Smrg}
757706f2543Smrg
758706f2543Smrg/*
759706f2543Smrg * miPointer interface routines
760706f2543Smrg */
761706f2543Smrg
762706f2543Smrg#define SPRITE_PAD  8
763706f2543Smrg
764706f2543Smrgstatic Bool
765706f2543SmrgmiSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
766706f2543Smrg{
767706f2543Smrg    miCursorInfoPtr pCursorInfo;
768706f2543Smrg
769706f2543Smrg    if (!IsMaster(pDev) && !pDev->u.master)
770706f2543Smrg        return FALSE;
771706f2543Smrg
772706f2543Smrg    pCursorInfo = MISPRITE(pDev);
773706f2543Smrg
774706f2543Smrg    if (pCursor == pCursorInfo->pCursor)
775706f2543Smrg	pCursorInfo->checkPixels = TRUE;
776706f2543Smrg
777706f2543Smrg    return miDCRealizeCursor(pScreen, pCursor);
778706f2543Smrg}
779706f2543Smrg
780706f2543Smrgstatic Bool
781706f2543SmrgmiSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
782706f2543Smrg{
783706f2543Smrg    return miDCUnrealizeCursor(pScreen, pCursor);
784706f2543Smrg}
785706f2543Smrg
786706f2543Smrgstatic void
787706f2543SmrgmiSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
788706f2543Smrg                   CursorPtr pCursor, int x, int y)
789706f2543Smrg{
790706f2543Smrg    miCursorInfoPtr     pPointer;
791706f2543Smrg    miSpriteScreenPtr   pScreenPriv;
792706f2543Smrg
793706f2543Smrg    if (!IsMaster(pDev) && !pDev->u.master)
794706f2543Smrg        return;
795706f2543Smrg
796706f2543Smrg    pPointer = MISPRITE(pDev);
797706f2543Smrg    pScreenPriv = GetSpriteScreen(pScreen);
798706f2543Smrg
799706f2543Smrg    if (!pCursor)
800706f2543Smrg    {
801706f2543Smrg	if (pPointer->shouldBeUp)
802706f2543Smrg	    --pScreenPriv->numberOfCursors;
803706f2543Smrg    	pPointer->shouldBeUp = FALSE;
804706f2543Smrg    	if (pPointer->isUp)
805706f2543Smrg	    miSpriteRemoveCursor (pDev, pScreen);
806706f2543Smrg	if (pScreenPriv->numberOfCursors == 0)
807706f2543Smrg	    miSpriteDisableDamage(pScreen, pScreenPriv);
808706f2543Smrg	pPointer->pCursor = 0;
809706f2543Smrg	return;
810706f2543Smrg    }
811706f2543Smrg    if (!pPointer->shouldBeUp)
812706f2543Smrg	pScreenPriv->numberOfCursors++;
813706f2543Smrg    pPointer->shouldBeUp = TRUE;
814706f2543Smrg    if (!pPointer->isUp)
815706f2543Smrg	miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
816706f2543Smrg    if (pPointer->x == x &&
817706f2543Smrg	pPointer->y == y &&
818706f2543Smrg	pPointer->pCursor == pCursor &&
819706f2543Smrg	!pPointer->checkPixels)
820706f2543Smrg    {
821706f2543Smrg	return;
822706f2543Smrg    }
823706f2543Smrg    pPointer->x = x;
824706f2543Smrg    pPointer->y = y;
825706f2543Smrg    pPointer->pCacheWin = NullWindow;
826706f2543Smrg    if (pPointer->checkPixels || pPointer->pCursor != pCursor)
827706f2543Smrg    {
828706f2543Smrg	pPointer->pCursor = pCursor;
829706f2543Smrg	miSpriteFindColors (pPointer, pScreen);
830706f2543Smrg    }
831706f2543Smrg    if (pPointer->isUp) {
832706f2543Smrg	/* TODO: reimplement flicker-free MoveCursor */
833706f2543Smrg	SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id));
834706f2543Smrg	miSpriteRemoveCursor (pDev, pScreen);
835706f2543Smrg    }
836706f2543Smrg
837706f2543Smrg    if (!pPointer->isUp && pPointer->pCursor)
838706f2543Smrg    {
839706f2543Smrg	SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id));
840706f2543Smrg        miSpriteSaveUnderCursor(pDev, pScreen);
841706f2543Smrg	miSpriteRestoreCursor (pDev, pScreen);
842706f2543Smrg    }
843706f2543Smrg
844706f2543Smrg}
845706f2543Smrg
846706f2543Smrgstatic void
847706f2543SmrgmiSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
848706f2543Smrg{
849706f2543Smrg    CursorPtr pCursor;
850706f2543Smrg
851706f2543Smrg    if (!IsMaster(pDev) && !pDev->u.master)
852706f2543Smrg        return;
853706f2543Smrg
854706f2543Smrg    pCursor = MISPRITE(pDev)->pCursor;
855706f2543Smrg
856706f2543Smrg    miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
857706f2543Smrg}
858706f2543Smrg
859706f2543Smrg
860706f2543Smrgstatic Bool
861706f2543SmrgmiSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
862706f2543Smrg{
863706f2543Smrg    miCursorInfoPtr pCursorInfo;
864706f2543Smrg    int ret = FALSE;
865706f2543Smrg
866706f2543Smrg    pCursorInfo = malloc(sizeof(miCursorInfoRec));
867706f2543Smrg    if (!pCursorInfo)
868706f2543Smrg        return FALSE;
869706f2543Smrg
870706f2543Smrg    pCursorInfo->pCursor = NULL;
871706f2543Smrg    pCursorInfo->x = 0;
872706f2543Smrg    pCursorInfo->y = 0;
873706f2543Smrg    pCursorInfo->isUp = FALSE;
874706f2543Smrg    pCursorInfo->shouldBeUp = FALSE;
875706f2543Smrg    pCursorInfo->pCacheWin = NullWindow;
876706f2543Smrg    pCursorInfo->isInCacheWin = FALSE;
877706f2543Smrg    pCursorInfo->checkPixels = TRUE;
878706f2543Smrg    pCursorInfo->pScreen = FALSE;
879706f2543Smrg
880706f2543Smrg    ret = miDCDeviceInitialize(pDev, pScreen);
881706f2543Smrg    if (!ret)
882706f2543Smrg    {
883706f2543Smrg        free(pCursorInfo);
884706f2543Smrg        pCursorInfo = NULL;
885706f2543Smrg    }
886706f2543Smrg    dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo);
887706f2543Smrg    return ret;
888706f2543Smrg}
889706f2543Smrg
890706f2543Smrgstatic void
891706f2543SmrgmiSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
892706f2543Smrg{
893706f2543Smrg    if (DevHasCursor(pDev))
894706f2543Smrg        miDCDeviceCleanup(pDev, pScreen);
895706f2543Smrg}
896706f2543Smrg
897706f2543Smrg/*
898706f2543Smrg * undraw/draw cursor
899706f2543Smrg */
900706f2543Smrg
901706f2543Smrgstatic void
902706f2543SmrgmiSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
903706f2543Smrg{
904706f2543Smrg    miSpriteScreenPtr   pScreenPriv;
905706f2543Smrg    miCursorInfoPtr     pCursorInfo;
906706f2543Smrg
907706f2543Smrg
908706f2543Smrg    if (!IsMaster(pDev) && !pDev->u.master)
909706f2543Smrg        return;
910706f2543Smrg
911706f2543Smrg    DamageDrawInternal (pScreen, TRUE);
912706f2543Smrg    pScreenPriv = GetSpriteScreen(pScreen);
913706f2543Smrg    pCursorInfo = MISPRITE(pDev);
914706f2543Smrg
915706f2543Smrg    miSpriteIsDown(pCursorInfo);
916706f2543Smrg    miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
917706f2543Smrg    pCursorInfo->pCacheWin = NullWindow;
918706f2543Smrg    miSpriteDisableDamage(pScreen, pScreenPriv);
919706f2543Smrg    if (!miDCRestoreUnderCursor(pDev,
920706f2543Smrg                                pScreen,
921706f2543Smrg                                pCursorInfo->saved.x1,
922706f2543Smrg                                pCursorInfo->saved.y1,
923706f2543Smrg                                pCursorInfo->saved.x2 -
924706f2543Smrg                                pCursorInfo->saved.x1,
925706f2543Smrg                                pCursorInfo->saved.y2 -
926706f2543Smrg                                pCursorInfo->saved.y1))
927706f2543Smrg    {
928706f2543Smrg        miSpriteIsUp(pCursorInfo);
929706f2543Smrg    }
930706f2543Smrg    miSpriteEnableDamage(pScreen, pScreenPriv);
931706f2543Smrg    DamageDrawInternal (pScreen, FALSE);
932706f2543Smrg}
933706f2543Smrg
934706f2543Smrg/*
935706f2543Smrg * Called from the block handler, saves area under cursor
936706f2543Smrg * before waiting for something to do.
937706f2543Smrg */
938706f2543Smrg
939706f2543Smrgstatic void
940706f2543SmrgmiSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
941706f2543Smrg{
942706f2543Smrg    miSpriteScreenPtr   pScreenPriv;
943706f2543Smrg    int			x, y;
944706f2543Smrg    CursorPtr		pCursor;
945706f2543Smrg    miCursorInfoPtr     pCursorInfo;
946706f2543Smrg
947706f2543Smrg    if (!IsMaster(pDev) && !pDev->u.master)
948706f2543Smrg        return;
949706f2543Smrg
950706f2543Smrg    DamageDrawInternal (pScreen, TRUE);
951706f2543Smrg    pScreenPriv = GetSpriteScreen(pScreen);
952706f2543Smrg    pCursorInfo = MISPRITE(pDev);
953706f2543Smrg
954706f2543Smrg    miSpriteComputeSaved (pDev, pScreen);
955706f2543Smrg    pCursor = pCursorInfo->pCursor;
956706f2543Smrg
957706f2543Smrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
958706f2543Smrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
959706f2543Smrg    miSpriteDisableDamage(pScreen, pScreenPriv);
960706f2543Smrg
961706f2543Smrg    miDCSaveUnderCursor(pDev,
962706f2543Smrg                        pScreen,
963706f2543Smrg                        pCursorInfo->saved.x1,
964706f2543Smrg                        pCursorInfo->saved.y1,
965706f2543Smrg                        pCursorInfo->saved.x2 -
966706f2543Smrg                        pCursorInfo->saved.x1,
967706f2543Smrg                        pCursorInfo->saved.y2 -
968706f2543Smrg                        pCursorInfo->saved.y1);
969706f2543Smrg    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
970706f2543Smrg    miSpriteEnableDamage(pScreen, pScreenPriv);
971706f2543Smrg    DamageDrawInternal (pScreen, FALSE);
972706f2543Smrg}
973706f2543Smrg
974706f2543Smrg
975706f2543Smrg/*
976706f2543Smrg * Called from the block handler, restores the cursor
977706f2543Smrg * before waiting for something to do.
978706f2543Smrg */
979706f2543Smrg
980706f2543Smrgstatic void
981706f2543SmrgmiSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
982706f2543Smrg{
983706f2543Smrg    miSpriteScreenPtr   pScreenPriv;
984706f2543Smrg    int			x, y;
985706f2543Smrg    CursorPtr		pCursor;
986706f2543Smrg    miCursorInfoPtr     pCursorInfo;
987706f2543Smrg
988706f2543Smrg    if (!IsMaster(pDev) && !pDev->u.master)
989706f2543Smrg        return;
990706f2543Smrg
991706f2543Smrg    DamageDrawInternal (pScreen, TRUE);
992706f2543Smrg    pScreenPriv = GetSpriteScreen(pScreen);
993706f2543Smrg    pCursorInfo = MISPRITE(pDev);
994706f2543Smrg
995706f2543Smrg    miSpriteComputeSaved (pDev, pScreen);
996706f2543Smrg    pCursor = pCursorInfo->pCursor;
997706f2543Smrg
998706f2543Smrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
999706f2543Smrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
1000706f2543Smrg    miSpriteDisableDamage(pScreen, pScreenPriv);
1001706f2543Smrg    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
1002706f2543Smrg    if (pCursorInfo->checkPixels)
1003706f2543Smrg        miSpriteFindColors (pCursorInfo, pScreen);
1004706f2543Smrg    if (miDCPutUpCursor(pDev, pScreen,
1005706f2543Smrg                pCursor, x, y,
1006706f2543Smrg                pScreenPriv->colors[SOURCE_COLOR].pixel,
1007706f2543Smrg                pScreenPriv->colors[MASK_COLOR].pixel))
1008706f2543Smrg    {
1009706f2543Smrg        miSpriteIsUp(pCursorInfo);
1010706f2543Smrg        pCursorInfo->pScreen = pScreen;
1011706f2543Smrg    }
1012706f2543Smrg    miSpriteEnableDamage(pScreen, pScreenPriv);
1013706f2543Smrg    DamageDrawInternal (pScreen, FALSE);
1014706f2543Smrg}
1015706f2543Smrg
1016706f2543Smrg/*
1017706f2543Smrg * compute the desired area of the screen to save
1018706f2543Smrg */
1019706f2543Smrg
1020706f2543Smrgstatic void
1021706f2543SmrgmiSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
1022706f2543Smrg{
1023706f2543Smrg    int		    x, y, w, h;
1024706f2543Smrg    int		    wpad, hpad;
1025706f2543Smrg    CursorPtr	    pCursor;
1026706f2543Smrg    miCursorInfoPtr pCursorInfo;
1027706f2543Smrg
1028706f2543Smrg    if (!IsMaster(pDev) && !pDev->u.master)
1029706f2543Smrg        return;
1030706f2543Smrg
1031706f2543Smrg    pCursorInfo = MISPRITE(pDev);
1032706f2543Smrg
1033706f2543Smrg    pCursor = pCursorInfo->pCursor;
1034706f2543Smrg    x = pCursorInfo->x - (int)pCursor->bits->xhot;
1035706f2543Smrg    y = pCursorInfo->y - (int)pCursor->bits->yhot;
1036706f2543Smrg    w = pCursor->bits->width;
1037706f2543Smrg    h = pCursor->bits->height;
1038706f2543Smrg    wpad = SPRITE_PAD;
1039706f2543Smrg    hpad = SPRITE_PAD;
1040706f2543Smrg    pCursorInfo->saved.x1 = x - wpad;
1041706f2543Smrg    pCursorInfo->saved.y1 = y - hpad;
1042706f2543Smrg    pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
1043706f2543Smrg    pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
1044706f2543Smrg}
1045706f2543Smrg
1046