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