xref: /OK3568_Linux_fs/external/xserver/mi/misprite.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * misprite.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * machine independent software sprite routines
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun /*
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun Copyright 1989, 1998  The Open Group
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
12*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
13*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
14*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
15*4882a593Smuzhiyun documentation.
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
18*4882a593Smuzhiyun all copies or substantial portions of the Software.
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
23*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
28*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
29*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
30*4882a593Smuzhiyun */
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
33*4882a593Smuzhiyun #include <dix-config.h>
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #include   <X11/X.h>
37*4882a593Smuzhiyun #include   <X11/Xproto.h>
38*4882a593Smuzhiyun #include   "misc.h"
39*4882a593Smuzhiyun #include   "pixmapstr.h"
40*4882a593Smuzhiyun #include   "input.h"
41*4882a593Smuzhiyun #include   "mi.h"
42*4882a593Smuzhiyun #include   "cursorstr.h"
43*4882a593Smuzhiyun #include   <X11/fonts/font.h>
44*4882a593Smuzhiyun #include   "scrnintstr.h"
45*4882a593Smuzhiyun #include   "colormapst.h"
46*4882a593Smuzhiyun #include   "windowstr.h"
47*4882a593Smuzhiyun #include   "gcstruct.h"
48*4882a593Smuzhiyun #include   "mipointer.h"
49*4882a593Smuzhiyun #include   "misprite.h"
50*4882a593Smuzhiyun #include   "dixfontstr.h"
51*4882a593Smuzhiyun #include   <X11/fonts/fontstruct.h>
52*4882a593Smuzhiyun #include   "inputstr.h"
53*4882a593Smuzhiyun #include   "damage.h"
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun typedef struct {
56*4882a593Smuzhiyun     CursorPtr pCursor;
57*4882a593Smuzhiyun     int x;                      /* cursor hotspot */
58*4882a593Smuzhiyun     int y;
59*4882a593Smuzhiyun     BoxRec saved;               /* saved area from the screen */
60*4882a593Smuzhiyun     Bool isUp;                  /* cursor in frame buffer */
61*4882a593Smuzhiyun     Bool shouldBeUp;            /* cursor should be displayed */
62*4882a593Smuzhiyun     Bool checkPixels;           /* check colormap collision */
63*4882a593Smuzhiyun     ScreenPtr pScreen;
64*4882a593Smuzhiyun } miCursorInfoRec, *miCursorInfoPtr;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun  * per screen information
68*4882a593Smuzhiyun  */
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun typedef struct {
71*4882a593Smuzhiyun     /* screen procedures */
72*4882a593Smuzhiyun     CloseScreenProcPtr CloseScreen;
73*4882a593Smuzhiyun     GetImageProcPtr GetImage;
74*4882a593Smuzhiyun     GetSpansProcPtr GetSpans;
75*4882a593Smuzhiyun     SourceValidateProcPtr SourceValidate;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun     /* window procedures */
78*4882a593Smuzhiyun     CopyWindowProcPtr CopyWindow;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun     /* colormap procedures */
81*4882a593Smuzhiyun     InstallColormapProcPtr InstallColormap;
82*4882a593Smuzhiyun     StoreColorsProcPtr StoreColors;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun     /* os layer procedures */
85*4882a593Smuzhiyun     ScreenBlockHandlerProcPtr BlockHandler;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     xColorItem colors[2];
88*4882a593Smuzhiyun     ColormapPtr pInstalledMap;
89*4882a593Smuzhiyun     ColormapPtr pColormap;
90*4882a593Smuzhiyun     VisualPtr pVisual;
91*4882a593Smuzhiyun     DamagePtr pDamage;          /* damage tracking structure */
92*4882a593Smuzhiyun     Bool damageRegistered;
93*4882a593Smuzhiyun     int numberOfCursors;
94*4882a593Smuzhiyun } miSpriteScreenRec, *miSpriteScreenPtr;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun #define SOURCE_COLOR	0
97*4882a593Smuzhiyun #define MASK_COLOR	1
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun  * Overlap BoxPtr and Box elements
101*4882a593Smuzhiyun  */
102*4882a593Smuzhiyun #define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
103*4882a593Smuzhiyun  	(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
104*4882a593Smuzhiyun 	 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun  * Overlap BoxPtr, origins, and rectangle
108*4882a593Smuzhiyun  */
109*4882a593Smuzhiyun #define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
110*4882a593Smuzhiyun     BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun /*
113*4882a593Smuzhiyun  * Overlap BoxPtr, origins and RectPtr
114*4882a593Smuzhiyun  */
115*4882a593Smuzhiyun #define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
116*4882a593Smuzhiyun     ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
117*4882a593Smuzhiyun 		(int)((pRect)->width), (int)((pRect)->height))
118*4882a593Smuzhiyun /*
119*4882a593Smuzhiyun  * Overlap BoxPtr and horizontal span
120*4882a593Smuzhiyun  */
121*4882a593Smuzhiyun #define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun #define LINE_SORT(x1,y1,x2,y2) \
124*4882a593Smuzhiyun { int _t; \
125*4882a593Smuzhiyun   if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
126*4882a593Smuzhiyun   if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun #define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
129*4882a593Smuzhiyun     BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun #define SPRITE_DEBUG_ENABLE 0
132*4882a593Smuzhiyun #if SPRITE_DEBUG_ENABLE
133*4882a593Smuzhiyun #define SPRITE_DEBUG(x)	ErrorF x
134*4882a593Smuzhiyun #else
135*4882a593Smuzhiyun #define SPRITE_DEBUG(x)
136*4882a593Smuzhiyun #endif
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun static DevPrivateKeyRec miSpriteScreenKeyRec;
139*4882a593Smuzhiyun static DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun static miSpriteScreenPtr
GetSpriteScreen(ScreenPtr pScreen)142*4882a593Smuzhiyun GetSpriteScreen(ScreenPtr pScreen)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun     return dixLookupPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun static miCursorInfoPtr
GetSprite(DeviceIntPtr dev)148*4882a593Smuzhiyun GetSprite(DeviceIntPtr dev)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun     if (IsFloating(dev))
151*4882a593Smuzhiyun        return dixLookupPrivate(&dev->devPrivates, &miSpriteDevPrivatesKeyRec);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun     return dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates,
154*4882a593Smuzhiyun                             &miSpriteDevPrivatesKeyRec);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun static void
miSpriteDisableDamage(ScreenPtr pScreen,miSpriteScreenPtr pScreenPriv)158*4882a593Smuzhiyun miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun     if (pScreenPriv->damageRegistered) {
161*4882a593Smuzhiyun         DamageUnregister(pScreenPriv->pDamage);
162*4882a593Smuzhiyun         pScreenPriv->damageRegistered = 0;
163*4882a593Smuzhiyun     }
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun static void
miSpriteEnableDamage(ScreenPtr pScreen,miSpriteScreenPtr pScreenPriv)167*4882a593Smuzhiyun miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun     if (!pScreenPriv->damageRegistered) {
170*4882a593Smuzhiyun         pScreenPriv->damageRegistered = 1;
171*4882a593Smuzhiyun         DamageRegister(&(pScreen->GetScreenPixmap(pScreen)->drawable),
172*4882a593Smuzhiyun                        pScreenPriv->pDamage);
173*4882a593Smuzhiyun     }
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun static void
miSpriteIsUp(miCursorInfoPtr pDevCursor)177*4882a593Smuzhiyun miSpriteIsUp(miCursorInfoPtr pDevCursor)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun     pDevCursor->isUp = TRUE;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun static void
miSpriteIsDown(miCursorInfoPtr pDevCursor)183*4882a593Smuzhiyun miSpriteIsDown(miCursorInfoPtr pDevCursor)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun     pDevCursor->isUp = FALSE;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun /*
189*4882a593Smuzhiyun  * screen wrappers
190*4882a593Smuzhiyun  */
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static Bool miSpriteCloseScreen(ScreenPtr pScreen);
193*4882a593Smuzhiyun static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
194*4882a593Smuzhiyun                              int w, int h, unsigned int format,
195*4882a593Smuzhiyun                              unsigned long planemask, char *pdstLine);
196*4882a593Smuzhiyun static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
197*4882a593Smuzhiyun                              DDXPointPtr ppt, int *pwidth, int nspans,
198*4882a593Smuzhiyun                              char *pdstStart);
199*4882a593Smuzhiyun static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
200*4882a593Smuzhiyun                                    int width, int height,
201*4882a593Smuzhiyun                                    unsigned int subWindowMode);
202*4882a593Smuzhiyun static void miSpriteCopyWindow(WindowPtr pWindow,
203*4882a593Smuzhiyun                                DDXPointRec ptOldOrg, RegionPtr prgnSrc);
204*4882a593Smuzhiyun static void miSpriteBlockHandler(ScreenPtr pScreen, void *timeout);
205*4882a593Smuzhiyun static void miSpriteInstallColormap(ColormapPtr pMap);
206*4882a593Smuzhiyun static void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun static void miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
211*4882a593Smuzhiyun                                            ScreenPtr pScreen);
212*4882a593Smuzhiyun static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun #define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
215*4882a593Smuzhiyun    (pPriv)->field)
216*4882a593Smuzhiyun #define SCREEN_EPILOGUE(pPriv, pScreen, field)\
217*4882a593Smuzhiyun     ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun /*
220*4882a593Smuzhiyun  * pointer-sprite method table
221*4882a593Smuzhiyun  */
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
224*4882a593Smuzhiyun                                   CursorPtr pCursor);
225*4882a593Smuzhiyun static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
226*4882a593Smuzhiyun                                     CursorPtr pCursor);
227*4882a593Smuzhiyun static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
228*4882a593Smuzhiyun                               CursorPtr pCursor, int x, int y);
229*4882a593Smuzhiyun static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
230*4882a593Smuzhiyun                                int x, int y);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun miPointerSpriteFuncRec miSpritePointerFuncs = {
233*4882a593Smuzhiyun     miSpriteRealizeCursor,
234*4882a593Smuzhiyun     miSpriteUnrealizeCursor,
235*4882a593Smuzhiyun     miSpriteSetCursor,
236*4882a593Smuzhiyun     miSpriteMoveCursor,
237*4882a593Smuzhiyun     miSpriteDeviceCursorInitialize,
238*4882a593Smuzhiyun     miSpriteDeviceCursorCleanup,
239*4882a593Smuzhiyun };
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun /*
242*4882a593Smuzhiyun  * other misc functions
243*4882a593Smuzhiyun  */
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun static void miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
246*4882a593Smuzhiyun static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
247*4882a593Smuzhiyun static void miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun static void
miSpriteRegisterBlockHandler(ScreenPtr pScreen,miSpriteScreenPtr pScreenPriv)250*4882a593Smuzhiyun miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun     if (!pScreenPriv->BlockHandler) {
253*4882a593Smuzhiyun         pScreenPriv->BlockHandler = pScreen->BlockHandler;
254*4882a593Smuzhiyun         pScreen->BlockHandler = miSpriteBlockHandler;
255*4882a593Smuzhiyun     }
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun static void
miSpriteReportDamage(DamagePtr pDamage,RegionPtr pRegion,void * closure)259*4882a593Smuzhiyun miSpriteReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun     ScreenPtr pScreen = closure;
262*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
263*4882a593Smuzhiyun     DeviceIntPtr pDev;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
266*4882a593Smuzhiyun         if (DevHasCursor(pDev)) {
267*4882a593Smuzhiyun             pCursorInfo = GetSprite(pDev);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun             if (pCursorInfo->isUp &&
270*4882a593Smuzhiyun                 pCursorInfo->pScreen == pScreen &&
271*4882a593Smuzhiyun                 RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) {
272*4882a593Smuzhiyun                 SPRITE_DEBUG(("Damage remove\n"));
273*4882a593Smuzhiyun                 miSpriteRemoveCursor(pDev, pScreen);
274*4882a593Smuzhiyun             }
275*4882a593Smuzhiyun         }
276*4882a593Smuzhiyun     }
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun /*
280*4882a593Smuzhiyun  * miSpriteInitialize -- called from device-dependent screen
281*4882a593Smuzhiyun  * initialization proc after all of the function pointers have
282*4882a593Smuzhiyun  * been stored in the screen structure.
283*4882a593Smuzhiyun  */
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun Bool
miSpriteInitialize(ScreenPtr pScreen,miPointerScreenFuncPtr screenFuncs)286*4882a593Smuzhiyun miSpriteInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun     miSpriteScreenPtr pScreenPriv;
289*4882a593Smuzhiyun     VisualPtr pVisual;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun     if (!DamageSetup(pScreen))
292*4882a593Smuzhiyun         return FALSE;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
295*4882a593Smuzhiyun         return FALSE;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     if (!dixRegisterPrivateKey
298*4882a593Smuzhiyun         (&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, sizeof(miCursorInfoRec)))
299*4882a593Smuzhiyun         return FALSE;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     pScreenPriv = malloc(sizeof(miSpriteScreenRec));
302*4882a593Smuzhiyun     if (!pScreenPriv)
303*4882a593Smuzhiyun         return FALSE;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     pScreenPriv->pDamage = DamageCreate(miSpriteReportDamage,
306*4882a593Smuzhiyun                                         NULL,
307*4882a593Smuzhiyun                                         DamageReportRawRegion,
308*4882a593Smuzhiyun                                         TRUE, pScreen, pScreen);
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun     if (!miPointerInitialize(pScreen, &miSpritePointerFuncs, screenFuncs, TRUE)) {
311*4882a593Smuzhiyun         free(pScreenPriv);
312*4882a593Smuzhiyun         return FALSE;
313*4882a593Smuzhiyun     }
314*4882a593Smuzhiyun     for (pVisual = pScreen->visuals;
315*4882a593Smuzhiyun          pVisual->vid != pScreen->rootVisual; pVisual++);
316*4882a593Smuzhiyun     pScreenPriv->pVisual = pVisual;
317*4882a593Smuzhiyun     pScreenPriv->CloseScreen = pScreen->CloseScreen;
318*4882a593Smuzhiyun     pScreenPriv->GetImage = pScreen->GetImage;
319*4882a593Smuzhiyun     pScreenPriv->GetSpans = pScreen->GetSpans;
320*4882a593Smuzhiyun     pScreenPriv->SourceValidate = pScreen->SourceValidate;
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun     pScreenPriv->CopyWindow = pScreen->CopyWindow;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun     pScreenPriv->InstallColormap = pScreen->InstallColormap;
325*4882a593Smuzhiyun     pScreenPriv->StoreColors = pScreen->StoreColors;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun     pScreenPriv->BlockHandler = NULL;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun     pScreenPriv->pInstalledMap = NULL;
330*4882a593Smuzhiyun     pScreenPriv->pColormap = NULL;
331*4882a593Smuzhiyun     pScreenPriv->colors[SOURCE_COLOR].red = 0;
332*4882a593Smuzhiyun     pScreenPriv->colors[SOURCE_COLOR].green = 0;
333*4882a593Smuzhiyun     pScreenPriv->colors[SOURCE_COLOR].blue = 0;
334*4882a593Smuzhiyun     pScreenPriv->colors[MASK_COLOR].red = 0;
335*4882a593Smuzhiyun     pScreenPriv->colors[MASK_COLOR].green = 0;
336*4882a593Smuzhiyun     pScreenPriv->colors[MASK_COLOR].blue = 0;
337*4882a593Smuzhiyun     pScreenPriv->damageRegistered = 0;
338*4882a593Smuzhiyun     pScreenPriv->numberOfCursors = 0;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, &miSpriteScreenKeyRec, pScreenPriv);
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun     pScreen->CloseScreen = miSpriteCloseScreen;
343*4882a593Smuzhiyun     pScreen->GetImage = miSpriteGetImage;
344*4882a593Smuzhiyun     pScreen->GetSpans = miSpriteGetSpans;
345*4882a593Smuzhiyun     pScreen->SourceValidate = miSpriteSourceValidate;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun     pScreen->CopyWindow = miSpriteCopyWindow;
348*4882a593Smuzhiyun     pScreen->InstallColormap = miSpriteInstallColormap;
349*4882a593Smuzhiyun     pScreen->StoreColors = miSpriteStoreColors;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun     return TRUE;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun /*
355*4882a593Smuzhiyun  * Screen wrappers
356*4882a593Smuzhiyun  */
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun /*
359*4882a593Smuzhiyun  * CloseScreen wrapper -- unwrap everything, free the private data
360*4882a593Smuzhiyun  * and call the wrapped function
361*4882a593Smuzhiyun  */
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun static Bool
miSpriteCloseScreen(ScreenPtr pScreen)364*4882a593Smuzhiyun miSpriteCloseScreen(ScreenPtr pScreen)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun     miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun     pScreen->CloseScreen = pScreenPriv->CloseScreen;
369*4882a593Smuzhiyun     pScreen->GetImage = pScreenPriv->GetImage;
370*4882a593Smuzhiyun     pScreen->GetSpans = pScreenPriv->GetSpans;
371*4882a593Smuzhiyun     pScreen->SourceValidate = pScreenPriv->SourceValidate;
372*4882a593Smuzhiyun     pScreen->InstallColormap = pScreenPriv->InstallColormap;
373*4882a593Smuzhiyun     pScreen->StoreColors = pScreenPriv->StoreColors;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun     DamageDestroy(pScreenPriv->pDamage);
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun     free(pScreenPriv);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun     return (*pScreen->CloseScreen) (pScreen);
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun static void
miSpriteGetImage(DrawablePtr pDrawable,int sx,int sy,int w,int h,unsigned int format,unsigned long planemask,char * pdstLine)383*4882a593Smuzhiyun miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
384*4882a593Smuzhiyun                  unsigned int format, unsigned long planemask, char *pdstLine)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun     ScreenPtr pScreen = pDrawable->pScreen;
387*4882a593Smuzhiyun     DeviceIntPtr pDev;
388*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
389*4882a593Smuzhiyun     miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     SCREEN_PROLOGUE(pPriv, pScreen, GetImage);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     if (pDrawable->type == DRAWABLE_WINDOW) {
394*4882a593Smuzhiyun         for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
395*4882a593Smuzhiyun             if (DevHasCursor(pDev)) {
396*4882a593Smuzhiyun                 pCursorInfo = GetSprite(pDev);
397*4882a593Smuzhiyun                 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
398*4882a593Smuzhiyun                     ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
399*4882a593Smuzhiyun                                 sx, sy, w, h)) {
400*4882a593Smuzhiyun                     SPRITE_DEBUG(("GetImage remove\n"));
401*4882a593Smuzhiyun                     miSpriteRemoveCursor(pDev, pScreen);
402*4882a593Smuzhiyun                 }
403*4882a593Smuzhiyun             }
404*4882a593Smuzhiyun         }
405*4882a593Smuzhiyun     }
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun     (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine);
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun     SCREEN_EPILOGUE(pPriv, pScreen, GetImage);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun static void
miSpriteGetSpans(DrawablePtr pDrawable,int wMax,DDXPointPtr ppt,int * pwidth,int nspans,char * pdstStart)413*4882a593Smuzhiyun miSpriteGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
414*4882a593Smuzhiyun                  int *pwidth, int nspans, char *pdstStart)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun     ScreenPtr pScreen = pDrawable->pScreen;
417*4882a593Smuzhiyun     DeviceIntPtr pDev;
418*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
419*4882a593Smuzhiyun     miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun     SCREEN_PROLOGUE(pPriv, pScreen, GetSpans);
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun     if (pDrawable->type == DRAWABLE_WINDOW) {
424*4882a593Smuzhiyun         for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
425*4882a593Smuzhiyun             if (DevHasCursor(pDev)) {
426*4882a593Smuzhiyun                 pCursorInfo = GetSprite(pDev);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun                 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) {
429*4882a593Smuzhiyun                     DDXPointPtr pts;
430*4882a593Smuzhiyun                     int *widths;
431*4882a593Smuzhiyun                     int nPts;
432*4882a593Smuzhiyun                     int xorg, yorg;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun                     xorg = pDrawable->x;
435*4882a593Smuzhiyun                     yorg = pDrawable->y;
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun                     for (pts = ppt, widths = pwidth, nPts = nspans;
438*4882a593Smuzhiyun                          nPts--; pts++, widths++) {
439*4882a593Smuzhiyun                         if (SPN_OVERLAP(&pCursorInfo->saved, pts->y + yorg,
440*4882a593Smuzhiyun                                         pts->x + xorg, *widths)) {
441*4882a593Smuzhiyun                             SPRITE_DEBUG(("GetSpans remove\n"));
442*4882a593Smuzhiyun                             miSpriteRemoveCursor(pDev, pScreen);
443*4882a593Smuzhiyun                             break;
444*4882a593Smuzhiyun                         }
445*4882a593Smuzhiyun                     }
446*4882a593Smuzhiyun                 }
447*4882a593Smuzhiyun             }
448*4882a593Smuzhiyun         }
449*4882a593Smuzhiyun     }
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun     (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun     SCREEN_EPILOGUE(pPriv, pScreen, GetSpans);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun static void
miSpriteSourceValidate(DrawablePtr pDrawable,int x,int y,int width,int height,unsigned int subWindowMode)457*4882a593Smuzhiyun miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, int width,
458*4882a593Smuzhiyun                        int height, unsigned int subWindowMode)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun     ScreenPtr pScreen = pDrawable->pScreen;
461*4882a593Smuzhiyun     DeviceIntPtr pDev;
462*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
463*4882a593Smuzhiyun     miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun     SCREEN_PROLOGUE(pPriv, pScreen, SourceValidate);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun     if (pDrawable->type == DRAWABLE_WINDOW) {
468*4882a593Smuzhiyun         for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
469*4882a593Smuzhiyun             if (DevHasCursor(pDev)) {
470*4882a593Smuzhiyun                 pCursorInfo = GetSprite(pDev);
471*4882a593Smuzhiyun                 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
472*4882a593Smuzhiyun                     ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
473*4882a593Smuzhiyun                                 x, y, width, height)) {
474*4882a593Smuzhiyun                     SPRITE_DEBUG(("SourceValidate remove\n"));
475*4882a593Smuzhiyun                     miSpriteRemoveCursor(pDev, pScreen);
476*4882a593Smuzhiyun                 }
477*4882a593Smuzhiyun             }
478*4882a593Smuzhiyun         }
479*4882a593Smuzhiyun     }
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun     if (pScreen->SourceValidate)
482*4882a593Smuzhiyun         (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
483*4882a593Smuzhiyun                                     subWindowMode);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun     SCREEN_EPILOGUE(pPriv, pScreen, SourceValidate);
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun static void
miSpriteCopyWindow(WindowPtr pWindow,DDXPointRec ptOldOrg,RegionPtr prgnSrc)489*4882a593Smuzhiyun miSpriteCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
490*4882a593Smuzhiyun {
491*4882a593Smuzhiyun     ScreenPtr pScreen = pWindow->drawable.pScreen;
492*4882a593Smuzhiyun     DeviceIntPtr pDev;
493*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
494*4882a593Smuzhiyun     miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun     SCREEN_PROLOGUE(pPriv, pScreen, CopyWindow);
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
499*4882a593Smuzhiyun         if (DevHasCursor(pDev)) {
500*4882a593Smuzhiyun             pCursorInfo = GetSprite(pDev);
501*4882a593Smuzhiyun             /*
502*4882a593Smuzhiyun              * Damage will take care of destination check
503*4882a593Smuzhiyun              */
504*4882a593Smuzhiyun             if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
505*4882a593Smuzhiyun                 RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) {
506*4882a593Smuzhiyun                 SPRITE_DEBUG(("CopyWindow remove\n"));
507*4882a593Smuzhiyun                 miSpriteRemoveCursor(pDev, pScreen);
508*4882a593Smuzhiyun             }
509*4882a593Smuzhiyun         }
510*4882a593Smuzhiyun     }
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun     (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
513*4882a593Smuzhiyun     SCREEN_EPILOGUE(pPriv, pScreen, CopyWindow);
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun static void
miSpriteBlockHandler(ScreenPtr pScreen,void * timeout)517*4882a593Smuzhiyun miSpriteBlockHandler(ScreenPtr pScreen, void *timeout)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun     miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
520*4882a593Smuzhiyun     DeviceIntPtr pDev;
521*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
522*4882a593Smuzhiyun     Bool WorkToDo = FALSE;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun     SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
527*4882a593Smuzhiyun         if (DevHasCursor(pDev)) {
528*4882a593Smuzhiyun             pCursorInfo = GetSprite(pDev);
529*4882a593Smuzhiyun             if (pCursorInfo && !pCursorInfo->isUp
530*4882a593Smuzhiyun                 && pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
531*4882a593Smuzhiyun                 SPRITE_DEBUG(("BlockHandler save"));
532*4882a593Smuzhiyun                 miSpriteSaveUnderCursor(pDev, pScreen);
533*4882a593Smuzhiyun             }
534*4882a593Smuzhiyun         }
535*4882a593Smuzhiyun     }
536*4882a593Smuzhiyun     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
537*4882a593Smuzhiyun         if (DevHasCursor(pDev)) {
538*4882a593Smuzhiyun             pCursorInfo = GetSprite(pDev);
539*4882a593Smuzhiyun             if (pCursorInfo && !pCursorInfo->isUp &&
540*4882a593Smuzhiyun                 pCursorInfo->pScreen == pScreen && pCursorInfo->shouldBeUp) {
541*4882a593Smuzhiyun                 SPRITE_DEBUG(("BlockHandler restore\n"));
542*4882a593Smuzhiyun                 miSpriteRestoreCursor(pDev, pScreen);
543*4882a593Smuzhiyun                 if (!pCursorInfo->isUp)
544*4882a593Smuzhiyun                     WorkToDo = TRUE;
545*4882a593Smuzhiyun             }
546*4882a593Smuzhiyun         }
547*4882a593Smuzhiyun     }
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun     (*pScreen->BlockHandler) (pScreen, timeout);
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun     if (WorkToDo)
552*4882a593Smuzhiyun         SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
553*4882a593Smuzhiyun     else
554*4882a593Smuzhiyun         pPriv->BlockHandler = NULL;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun static void
miSpriteInstallColormap(ColormapPtr pMap)558*4882a593Smuzhiyun miSpriteInstallColormap(ColormapPtr pMap)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun     ScreenPtr pScreen = pMap->pScreen;
561*4882a593Smuzhiyun     miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun     SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun     (*pScreen->InstallColormap) (pMap);
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun     SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun     /* InstallColormap can be called before devices are initialized. */
570*4882a593Smuzhiyun     pPriv->pInstalledMap = pMap;
571*4882a593Smuzhiyun     if (pPriv->pColormap != pMap) {
572*4882a593Smuzhiyun         DeviceIntPtr pDev;
573*4882a593Smuzhiyun         miCursorInfoPtr pCursorInfo;
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun         for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
576*4882a593Smuzhiyun             if (DevHasCursor(pDev)) {
577*4882a593Smuzhiyun                 pCursorInfo = GetSprite(pDev);
578*4882a593Smuzhiyun                 pCursorInfo->checkPixels = TRUE;
579*4882a593Smuzhiyun                 if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
580*4882a593Smuzhiyun                     miSpriteRemoveCursor(pDev, pScreen);
581*4882a593Smuzhiyun             }
582*4882a593Smuzhiyun         }
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun     }
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun static void
miSpriteStoreColors(ColormapPtr pMap,int ndef,xColorItem * pdef)588*4882a593Smuzhiyun miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun     ScreenPtr pScreen = pMap->pScreen;
591*4882a593Smuzhiyun     miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
592*4882a593Smuzhiyun     int i;
593*4882a593Smuzhiyun     int updated;
594*4882a593Smuzhiyun     VisualPtr pVisual;
595*4882a593Smuzhiyun     DeviceIntPtr pDev;
596*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun     SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun     (*pScreen->StoreColors) (pMap, ndef, pdef);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun     SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun     if (pPriv->pColormap == pMap) {
605*4882a593Smuzhiyun         updated = 0;
606*4882a593Smuzhiyun         pVisual = pMap->pVisual;
607*4882a593Smuzhiyun         if (pVisual->class == DirectColor) {
608*4882a593Smuzhiyun             /* Direct color - match on any of the subfields */
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun #define UpdateDAC(dev, plane,dac,mask) {\
613*4882a593Smuzhiyun     if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
614*4882a593Smuzhiyun 	dev->colors[plane].dac = pdef[i].dac; \
615*4882a593Smuzhiyun 	updated = 1; \
616*4882a593Smuzhiyun     } \
617*4882a593Smuzhiyun }
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun #define CheckDirect(dev, plane) \
620*4882a593Smuzhiyun 	    UpdateDAC(dev, plane,red,redMask) \
621*4882a593Smuzhiyun 	    UpdateDAC(dev, plane,green,greenMask) \
622*4882a593Smuzhiyun 	    UpdateDAC(dev, plane,blue,blueMask)
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun             for (i = 0; i < ndef; i++) {
625*4882a593Smuzhiyun                 CheckDirect(pPriv, SOURCE_COLOR)
626*4882a593Smuzhiyun                     CheckDirect(pPriv, MASK_COLOR)
627*4882a593Smuzhiyun             }
628*4882a593Smuzhiyun         }
629*4882a593Smuzhiyun         else {
630*4882a593Smuzhiyun             /* PseudoColor/GrayScale - match on exact pixel */
631*4882a593Smuzhiyun             for (i = 0; i < ndef; i++) {
632*4882a593Smuzhiyun                 if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) {
633*4882a593Smuzhiyun                     pPriv->colors[SOURCE_COLOR] = pdef[i];
634*4882a593Smuzhiyun                     if (++updated == 2)
635*4882a593Smuzhiyun                         break;
636*4882a593Smuzhiyun                 }
637*4882a593Smuzhiyun                 if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) {
638*4882a593Smuzhiyun                     pPriv->colors[MASK_COLOR] = pdef[i];
639*4882a593Smuzhiyun                     if (++updated == 2)
640*4882a593Smuzhiyun                         break;
641*4882a593Smuzhiyun                 }
642*4882a593Smuzhiyun             }
643*4882a593Smuzhiyun         }
644*4882a593Smuzhiyun         if (updated) {
645*4882a593Smuzhiyun             for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
646*4882a593Smuzhiyun                 if (DevHasCursor(pDev)) {
647*4882a593Smuzhiyun                     pCursorInfo = GetSprite(pDev);
648*4882a593Smuzhiyun                     pCursorInfo->checkPixels = TRUE;
649*4882a593Smuzhiyun                     if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
650*4882a593Smuzhiyun                         miSpriteRemoveCursor(pDev, pScreen);
651*4882a593Smuzhiyun                 }
652*4882a593Smuzhiyun             }
653*4882a593Smuzhiyun         }
654*4882a593Smuzhiyun     }
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun static void
miSpriteFindColors(miCursorInfoPtr pDevCursor,ScreenPtr pScreen)658*4882a593Smuzhiyun miSpriteFindColors(miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun     miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
661*4882a593Smuzhiyun     CursorPtr pCursor;
662*4882a593Smuzhiyun     xColorItem *sourceColor, *maskColor;
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun     pCursor = pDevCursor->pCursor;
665*4882a593Smuzhiyun     sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
666*4882a593Smuzhiyun     maskColor = &pScreenPriv->colors[MASK_COLOR];
667*4882a593Smuzhiyun     if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
668*4882a593Smuzhiyun         !(pCursor->foreRed == sourceColor->red &&
669*4882a593Smuzhiyun           pCursor->foreGreen == sourceColor->green &&
670*4882a593Smuzhiyun           pCursor->foreBlue == sourceColor->blue &&
671*4882a593Smuzhiyun           pCursor->backRed == maskColor->red &&
672*4882a593Smuzhiyun           pCursor->backGreen == maskColor->green &&
673*4882a593Smuzhiyun           pCursor->backBlue == maskColor->blue)) {
674*4882a593Smuzhiyun         pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
675*4882a593Smuzhiyun         sourceColor->red = pCursor->foreRed;
676*4882a593Smuzhiyun         sourceColor->green = pCursor->foreGreen;
677*4882a593Smuzhiyun         sourceColor->blue = pCursor->foreBlue;
678*4882a593Smuzhiyun         FakeAllocColor(pScreenPriv->pColormap, sourceColor);
679*4882a593Smuzhiyun         maskColor->red = pCursor->backRed;
680*4882a593Smuzhiyun         maskColor->green = pCursor->backGreen;
681*4882a593Smuzhiyun         maskColor->blue = pCursor->backBlue;
682*4882a593Smuzhiyun         FakeAllocColor(pScreenPriv->pColormap, maskColor);
683*4882a593Smuzhiyun         /* "free" the pixels right away, don't let this confuse you */
684*4882a593Smuzhiyun         FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
685*4882a593Smuzhiyun         FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
686*4882a593Smuzhiyun     }
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun     pDevCursor->checkPixels = FALSE;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun /*
693*4882a593Smuzhiyun  * miPointer interface routines
694*4882a593Smuzhiyun  */
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun #define SPRITE_PAD  8
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun static Bool
miSpriteRealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor)699*4882a593Smuzhiyun miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun     if (IsFloating(pDev))
704*4882a593Smuzhiyun         return FALSE;
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun     pCursorInfo = GetSprite(pDev);
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun     if (pCursor == pCursorInfo->pCursor)
709*4882a593Smuzhiyun         pCursorInfo->checkPixels = TRUE;
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun     return miDCRealizeCursor(pScreen, pCursor);
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun static Bool
miSpriteUnrealizeCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor)715*4882a593Smuzhiyun miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun     return miDCUnrealizeCursor(pScreen, pCursor);
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun static void
miSpriteSetCursor(DeviceIntPtr pDev,ScreenPtr pScreen,CursorPtr pCursor,int x,int y)721*4882a593Smuzhiyun miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
722*4882a593Smuzhiyun                   CursorPtr pCursor, int x, int y)
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun     miCursorInfoPtr pPointer;
725*4882a593Smuzhiyun     miSpriteScreenPtr pScreenPriv;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun     if (IsFloating(pDev))
728*4882a593Smuzhiyun         return;
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun     pPointer = GetSprite(pDev);
731*4882a593Smuzhiyun     pScreenPriv = GetSpriteScreen(pScreen);
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun     if (!pCursor) {
734*4882a593Smuzhiyun         if (pPointer->shouldBeUp)
735*4882a593Smuzhiyun             --pScreenPriv->numberOfCursors;
736*4882a593Smuzhiyun         pPointer->shouldBeUp = FALSE;
737*4882a593Smuzhiyun         if (pPointer->isUp)
738*4882a593Smuzhiyun             miSpriteRemoveCursor(pDev, pScreen);
739*4882a593Smuzhiyun         if (pScreenPriv->numberOfCursors == 0)
740*4882a593Smuzhiyun             miSpriteDisableDamage(pScreen, pScreenPriv);
741*4882a593Smuzhiyun         pPointer->pCursor = 0;
742*4882a593Smuzhiyun         return;
743*4882a593Smuzhiyun     }
744*4882a593Smuzhiyun     if (!pPointer->shouldBeUp)
745*4882a593Smuzhiyun         pScreenPriv->numberOfCursors++;
746*4882a593Smuzhiyun     pPointer->shouldBeUp = TRUE;
747*4882a593Smuzhiyun     if (!pPointer->isUp)
748*4882a593Smuzhiyun         miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
749*4882a593Smuzhiyun     if (pPointer->x == x &&
750*4882a593Smuzhiyun         pPointer->y == y &&
751*4882a593Smuzhiyun         pPointer->pCursor == pCursor && !pPointer->checkPixels) {
752*4882a593Smuzhiyun         return;
753*4882a593Smuzhiyun     }
754*4882a593Smuzhiyun     pPointer->x = x;
755*4882a593Smuzhiyun     pPointer->y = y;
756*4882a593Smuzhiyun     if (pPointer->checkPixels || pPointer->pCursor != pCursor) {
757*4882a593Smuzhiyun         pPointer->pCursor = pCursor;
758*4882a593Smuzhiyun         miSpriteFindColors(pPointer, pScreen);
759*4882a593Smuzhiyun     }
760*4882a593Smuzhiyun     if (pPointer->isUp) {
761*4882a593Smuzhiyun         /* TODO: reimplement flicker-free MoveCursor */
762*4882a593Smuzhiyun         SPRITE_DEBUG(("SetCursor remove %d\n", pDev->id));
763*4882a593Smuzhiyun         miSpriteRemoveCursor(pDev, pScreen);
764*4882a593Smuzhiyun     }
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun     if (!pPointer->isUp && pPointer->pCursor) {
767*4882a593Smuzhiyun         SPRITE_DEBUG(("SetCursor restore %d\n", pDev->id));
768*4882a593Smuzhiyun         miSpriteSaveUnderCursor(pDev, pScreen);
769*4882a593Smuzhiyun         miSpriteRestoreCursor(pDev, pScreen);
770*4882a593Smuzhiyun     }
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun static void
miSpriteMoveCursor(DeviceIntPtr pDev,ScreenPtr pScreen,int x,int y)775*4882a593Smuzhiyun miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun     CursorPtr pCursor;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun     if (IsFloating(pDev))
780*4882a593Smuzhiyun         return;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun     pCursor = GetSprite(pDev)->pCursor;
783*4882a593Smuzhiyun 
784*4882a593Smuzhiyun     miSpriteSetCursor(pDev, pScreen, pCursor, x, y);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun static Bool
miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,ScreenPtr pScreen)788*4882a593Smuzhiyun miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
789*4882a593Smuzhiyun {
790*4882a593Smuzhiyun     int ret = miDCDeviceInitialize(pDev, pScreen);
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun     if (ret) {
793*4882a593Smuzhiyun         miCursorInfoPtr pCursorInfo;
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun         pCursorInfo =
796*4882a593Smuzhiyun             dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec);
797*4882a593Smuzhiyun         pCursorInfo->pCursor = NULL;
798*4882a593Smuzhiyun         pCursorInfo->x = 0;
799*4882a593Smuzhiyun         pCursorInfo->y = 0;
800*4882a593Smuzhiyun         pCursorInfo->isUp = FALSE;
801*4882a593Smuzhiyun         pCursorInfo->shouldBeUp = FALSE;
802*4882a593Smuzhiyun         pCursorInfo->checkPixels = TRUE;
803*4882a593Smuzhiyun         pCursorInfo->pScreen = FALSE;
804*4882a593Smuzhiyun     }
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun     return ret;
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun static void
miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,ScreenPtr pScreen)810*4882a593Smuzhiyun miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
811*4882a593Smuzhiyun {
812*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo =
813*4882a593Smuzhiyun         dixLookupPrivate(&pDev->devPrivates, &miSpriteDevPrivatesKeyRec);
814*4882a593Smuzhiyun 
815*4882a593Smuzhiyun     if (DevHasCursor(pDev))
816*4882a593Smuzhiyun         miDCDeviceCleanup(pDev, pScreen);
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun     memset(pCursorInfo, 0, sizeof(miCursorInfoRec));
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun /*
822*4882a593Smuzhiyun  * undraw/draw cursor
823*4882a593Smuzhiyun  */
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun static void
miSpriteRemoveCursor(DeviceIntPtr pDev,ScreenPtr pScreen)826*4882a593Smuzhiyun miSpriteRemoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun     miSpriteScreenPtr pScreenPriv;
829*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun     if (IsFloating(pDev))
832*4882a593Smuzhiyun         return;
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun     DamageDrawInternal(pScreen, TRUE);
835*4882a593Smuzhiyun     pScreenPriv = GetSpriteScreen(pScreen);
836*4882a593Smuzhiyun     pCursorInfo = GetSprite(pDev);
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun     miSpriteIsDown(pCursorInfo);
839*4882a593Smuzhiyun     miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
840*4882a593Smuzhiyun     miSpriteDisableDamage(pScreen, pScreenPriv);
841*4882a593Smuzhiyun     if (!miDCRestoreUnderCursor(pDev,
842*4882a593Smuzhiyun                                 pScreen,
843*4882a593Smuzhiyun                                 pCursorInfo->saved.x1,
844*4882a593Smuzhiyun                                 pCursorInfo->saved.y1,
845*4882a593Smuzhiyun                                 pCursorInfo->saved.x2 -
846*4882a593Smuzhiyun                                 pCursorInfo->saved.x1,
847*4882a593Smuzhiyun                                 pCursorInfo->saved.y2 -
848*4882a593Smuzhiyun                                 pCursorInfo->saved.y1)) {
849*4882a593Smuzhiyun         miSpriteIsUp(pCursorInfo);
850*4882a593Smuzhiyun     }
851*4882a593Smuzhiyun     miSpriteEnableDamage(pScreen, pScreenPriv);
852*4882a593Smuzhiyun     DamageDrawInternal(pScreen, FALSE);
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun /*
856*4882a593Smuzhiyun  * Called from the block handler, saves area under cursor
857*4882a593Smuzhiyun  * before waiting for something to do.
858*4882a593Smuzhiyun  */
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun static void
miSpriteSaveUnderCursor(DeviceIntPtr pDev,ScreenPtr pScreen)861*4882a593Smuzhiyun miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun     miSpriteScreenPtr pScreenPriv;
864*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun     if (IsFloating(pDev))
867*4882a593Smuzhiyun         return;
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun     DamageDrawInternal(pScreen, TRUE);
870*4882a593Smuzhiyun     pScreenPriv = GetSpriteScreen(pScreen);
871*4882a593Smuzhiyun     pCursorInfo = GetSprite(pDev);
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun     miSpriteComputeSaved(pDev, pScreen);
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun     miSpriteDisableDamage(pScreen, pScreenPriv);
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun     miDCSaveUnderCursor(pDev,
878*4882a593Smuzhiyun                         pScreen,
879*4882a593Smuzhiyun                         pCursorInfo->saved.x1,
880*4882a593Smuzhiyun                         pCursorInfo->saved.y1,
881*4882a593Smuzhiyun                         pCursorInfo->saved.x2 -
882*4882a593Smuzhiyun                         pCursorInfo->saved.x1,
883*4882a593Smuzhiyun                         pCursorInfo->saved.y2 - pCursorInfo->saved.y1);
884*4882a593Smuzhiyun     SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
885*4882a593Smuzhiyun     miSpriteEnableDamage(pScreen, pScreenPriv);
886*4882a593Smuzhiyun     DamageDrawInternal(pScreen, FALSE);
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun /*
890*4882a593Smuzhiyun  * Called from the block handler, restores the cursor
891*4882a593Smuzhiyun  * before waiting for something to do.
892*4882a593Smuzhiyun  */
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun static void
miSpriteRestoreCursor(DeviceIntPtr pDev,ScreenPtr pScreen)895*4882a593Smuzhiyun miSpriteRestoreCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun     miSpriteScreenPtr pScreenPriv;
898*4882a593Smuzhiyun     int x, y;
899*4882a593Smuzhiyun     CursorPtr pCursor;
900*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun     if (IsFloating(pDev))
903*4882a593Smuzhiyun         return;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun     DamageDrawInternal(pScreen, TRUE);
906*4882a593Smuzhiyun     pScreenPriv = GetSpriteScreen(pScreen);
907*4882a593Smuzhiyun     pCursorInfo = GetSprite(pDev);
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun     miSpriteComputeSaved(pDev, pScreen);
910*4882a593Smuzhiyun     pCursor = pCursorInfo->pCursor;
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun     x = pCursorInfo->x - (int) pCursor->bits->xhot;
913*4882a593Smuzhiyun     y = pCursorInfo->y - (int) pCursor->bits->yhot;
914*4882a593Smuzhiyun     miSpriteDisableDamage(pScreen, pScreenPriv);
915*4882a593Smuzhiyun     SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
916*4882a593Smuzhiyun     if (pCursorInfo->checkPixels)
917*4882a593Smuzhiyun         miSpriteFindColors(pCursorInfo, pScreen);
918*4882a593Smuzhiyun     if (miDCPutUpCursor(pDev, pScreen,
919*4882a593Smuzhiyun                         pCursor, x, y,
920*4882a593Smuzhiyun                         pScreenPriv->colors[SOURCE_COLOR].pixel,
921*4882a593Smuzhiyun                         pScreenPriv->colors[MASK_COLOR].pixel)) {
922*4882a593Smuzhiyun         miSpriteIsUp(pCursorInfo);
923*4882a593Smuzhiyun         pCursorInfo->pScreen = pScreen;
924*4882a593Smuzhiyun     }
925*4882a593Smuzhiyun     miSpriteEnableDamage(pScreen, pScreenPriv);
926*4882a593Smuzhiyun     DamageDrawInternal(pScreen, FALSE);
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun 
929*4882a593Smuzhiyun /*
930*4882a593Smuzhiyun  * compute the desired area of the screen to save
931*4882a593Smuzhiyun  */
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun static void
miSpriteComputeSaved(DeviceIntPtr pDev,ScreenPtr pScreen)934*4882a593Smuzhiyun miSpriteComputeSaved(DeviceIntPtr pDev, ScreenPtr pScreen)
935*4882a593Smuzhiyun {
936*4882a593Smuzhiyun     int x, y, w, h;
937*4882a593Smuzhiyun     int wpad, hpad;
938*4882a593Smuzhiyun     CursorPtr pCursor;
939*4882a593Smuzhiyun     miCursorInfoPtr pCursorInfo;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun     if (IsFloating(pDev))
942*4882a593Smuzhiyun         return;
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun     pCursorInfo = GetSprite(pDev);
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun     pCursor = pCursorInfo->pCursor;
947*4882a593Smuzhiyun     x = pCursorInfo->x - (int) pCursor->bits->xhot;
948*4882a593Smuzhiyun     y = pCursorInfo->y - (int) pCursor->bits->yhot;
949*4882a593Smuzhiyun     w = pCursor->bits->width;
950*4882a593Smuzhiyun     h = pCursor->bits->height;
951*4882a593Smuzhiyun     wpad = SPRITE_PAD;
952*4882a593Smuzhiyun     hpad = SPRITE_PAD;
953*4882a593Smuzhiyun     pCursorInfo->saved.x1 = x - wpad;
954*4882a593Smuzhiyun     pCursorInfo->saved.y1 = y - hpad;
955*4882a593Smuzhiyun     pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
956*4882a593Smuzhiyun     pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
957*4882a593Smuzhiyun }
958