4 * machine independent software sprite routines
9 Copyright 1989, 1998 The Open Group
11 Permission to use, copy, modify, distribute, and sell this software and its
12 documentation for any purpose is hereby granted without fee, provided that
13 the above copyright notice appear in all copies and that both that
14 copyright notice and this permission notice appear in supporting
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 Except as contained in this notice, the name of The Open Group shall not be
28 used in advertising or otherwise to promote the sale, use or other dealings
29 in this Software without prior written authorization from The Open Group.
32 #ifdef HAVE_DIX_CONFIG_H
33 #include <dix-config.h>
37 #include <X11/Xproto.h>
39 #include "pixmapstr.h"
42 #include "cursorstr.h"
43 #include <X11/fonts/font.h>
44 #include "scrnintstr.h"
45 #include "colormapst.h"
46 #include "windowstr.h"
48 #include "mipointer.h"
50 #include "dixfontstr.h"
51 #include <X11/fonts/fontstruct.h>
57 int x
; /* cursor hotspot */
59 BoxRec saved
; /* saved area from the screen */
60 Bool isUp
; /* cursor in frame buffer */
61 Bool shouldBeUp
; /* cursor should be displayed */
62 WindowPtr pCacheWin
; /* window the cursor last seen in */
64 Bool checkPixels
; /* check colormap collision */
66 } miCursorInfoRec
, *miCursorInfoPtr
;
69 * per screen information
73 /* screen procedures */
74 CloseScreenProcPtr CloseScreen
;
75 GetImageProcPtr GetImage
;
76 GetSpansProcPtr GetSpans
;
77 SourceValidateProcPtr SourceValidate
;
79 /* window procedures */
80 CopyWindowProcPtr CopyWindow
;
82 /* colormap procedures */
83 InstallColormapProcPtr InstallColormap
;
84 StoreColorsProcPtr StoreColors
;
86 /* os layer procedures */
87 ScreenBlockHandlerProcPtr BlockHandler
;
90 ColormapPtr pInstalledMap
;
91 ColormapPtr pColormap
;
93 DamagePtr pDamage
; /* damage tracking structure */
94 Bool damageRegistered
;
96 } miSpriteScreenRec
, *miSpriteScreenPtr
;
98 #define SOURCE_COLOR 0
102 * Overlap BoxPtr and Box elements
104 #define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
105 (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
106 ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
109 * Overlap BoxPtr, origins, and rectangle
111 #define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
112 BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
115 * Overlap BoxPtr, origins and RectPtr
117 #define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
118 ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
119 (int)((pRect)->width), (int)((pRect)->height))
121 * Overlap BoxPtr and horizontal span
123 #define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
125 #define LINE_SORT(x1,y1,x2,y2) \
127 if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
128 if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
130 #define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
131 BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
133 #define SPRITE_DEBUG_ENABLE 0
134 #if SPRITE_DEBUG_ENABLE
135 #define SPRITE_DEBUG(x) ErrorF x
137 #define SPRITE_DEBUG(x)
140 #define MISPRITE(dev) \
142 (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
143 (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
146 miSpriteDisableDamage(ScreenPtr pScreen
, miSpriteScreenPtr pScreenPriv
)
148 if (pScreenPriv
->damageRegistered
) {
149 DamageUnregister(pScreenPriv
->pDamage
);
150 pScreenPriv
->damageRegistered
= 0;
155 miSpriteEnableDamage(ScreenPtr pScreen
, miSpriteScreenPtr pScreenPriv
)
157 if (!pScreenPriv
->damageRegistered
) {
158 pScreenPriv
->damageRegistered
= 1;
159 DamageRegister(&(pScreen
->GetScreenPixmap(pScreen
)->drawable
),
160 pScreenPriv
->pDamage
);
165 miSpriteIsUp(miCursorInfoPtr pDevCursor
)
167 pDevCursor
->isUp
= TRUE
;
171 miSpriteIsDown(miCursorInfoPtr pDevCursor
)
173 pDevCursor
->isUp
= FALSE
;
180 static DevPrivateKeyRec miSpriteScreenKeyRec
;
182 #define miSpriteScreenKey (&miSpriteScreenKeyRec)
183 #define GetSpriteScreen(pScreen) \
184 (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey))
185 static DevPrivateKeyRec miSpriteDevPrivatesKeyRec
;
187 #define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
189 static Bool
miSpriteCloseScreen(ScreenPtr pScreen
);
190 static void miSpriteGetImage(DrawablePtr pDrawable
, int sx
, int sy
,
191 int w
, int h
, unsigned int format
,
192 unsigned long planemask
, char *pdstLine
);
193 static void miSpriteGetSpans(DrawablePtr pDrawable
, int wMax
,
194 DDXPointPtr ppt
, int *pwidth
, int nspans
,
196 static void miSpriteSourceValidate(DrawablePtr pDrawable
, int x
, int y
,
197 int width
, int height
,
198 unsigned int subWindowMode
);
199 static void miSpriteCopyWindow(WindowPtr pWindow
,
200 DDXPointRec ptOldOrg
, RegionPtr prgnSrc
);
201 static void miSpriteBlockHandler(ScreenPtr pScreen
,
202 pointer pTimeout
, pointer pReadMask
);
203 static void miSpriteInstallColormap(ColormapPtr pMap
);
204 static void miSpriteStoreColors(ColormapPtr pMap
, int ndef
, xColorItem
* pdef
);
206 static void miSpriteComputeSaved(DeviceIntPtr pDev
, ScreenPtr pScreen
);
208 static Bool
miSpriteDeviceCursorInitialize(DeviceIntPtr pDev
,
210 static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev
, ScreenPtr pScreen
);
212 #define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
214 #define SCREEN_EPILOGUE(pPriv, pScreen, field)\
215 ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
218 * pointer-sprite method table
221 static Bool
miSpriteRealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
223 static Bool
miSpriteUnrealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
225 static void miSpriteSetCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
226 CursorPtr pCursor
, int x
, int y
);
227 static void miSpriteMoveCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
230 miPointerSpriteFuncRec miSpritePointerFuncs
= {
231 miSpriteRealizeCursor
,
232 miSpriteUnrealizeCursor
,
235 miSpriteDeviceCursorInitialize
,
236 miSpriteDeviceCursorCleanup
,
240 * other misc functions
243 static void miSpriteRemoveCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
);
244 static void miSpriteSaveUnderCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
);
245 static void miSpriteRestoreCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
);
248 miSpriteRegisterBlockHandler(ScreenPtr pScreen
, miSpriteScreenPtr pScreenPriv
)
250 if (!pScreenPriv
->BlockHandler
) {
251 pScreenPriv
->BlockHandler
= pScreen
->BlockHandler
;
252 pScreen
->BlockHandler
= miSpriteBlockHandler
;
257 miSpriteReportDamage(DamagePtr pDamage
, RegionPtr pRegion
, void *closure
)
259 ScreenPtr pScreen
= closure
;
260 miCursorInfoPtr pCursorInfo
;
263 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
264 if (DevHasCursor(pDev
)) {
265 pCursorInfo
= MISPRITE(pDev
);
267 if (pCursorInfo
->isUp
&&
268 pCursorInfo
->pScreen
== pScreen
&&
269 RegionContainsRect(pRegion
, &pCursorInfo
->saved
) != rgnOUT
) {
270 SPRITE_DEBUG(("Damage remove\n"));
271 miSpriteRemoveCursor(pDev
, pScreen
);
278 * miSpriteInitialize -- called from device-dependent screen
279 * initialization proc after all of the function pointers have
280 * been stored in the screen structure.
284 miSpriteInitialize(ScreenPtr pScreen
, miPointerScreenFuncPtr screenFuncs
)
286 miSpriteScreenPtr pScreenPriv
;
289 if (!DamageSetup(pScreen
))
292 if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec
, PRIVATE_SCREEN
, 0))
295 if (!dixRegisterPrivateKey
296 (&miSpriteDevPrivatesKeyRec
, PRIVATE_DEVICE
, sizeof(miCursorInfoRec
)))
299 pScreenPriv
= malloc(sizeof(miSpriteScreenRec
));
303 pScreenPriv
->pDamage
= DamageCreate(miSpriteReportDamage
,
305 DamageReportRawRegion
,
306 TRUE
, pScreen
, pScreen
);
308 if (!miPointerInitialize(pScreen
, &miSpritePointerFuncs
, screenFuncs
, TRUE
)) {
312 for (pVisual
= pScreen
->visuals
;
313 pVisual
->vid
!= pScreen
->rootVisual
; pVisual
++);
314 pScreenPriv
->pVisual
= pVisual
;
315 pScreenPriv
->CloseScreen
= pScreen
->CloseScreen
;
316 pScreenPriv
->GetImage
= pScreen
->GetImage
;
317 pScreenPriv
->GetSpans
= pScreen
->GetSpans
;
318 pScreenPriv
->SourceValidate
= pScreen
->SourceValidate
;
320 pScreenPriv
->CopyWindow
= pScreen
->CopyWindow
;
322 pScreenPriv
->InstallColormap
= pScreen
->InstallColormap
;
323 pScreenPriv
->StoreColors
= pScreen
->StoreColors
;
325 pScreenPriv
->BlockHandler
= NULL
;
327 pScreenPriv
->pInstalledMap
= NULL
;
328 pScreenPriv
->pColormap
= NULL
;
329 pScreenPriv
->colors
[SOURCE_COLOR
].red
= 0;
330 pScreenPriv
->colors
[SOURCE_COLOR
].green
= 0;
331 pScreenPriv
->colors
[SOURCE_COLOR
].blue
= 0;
332 pScreenPriv
->colors
[MASK_COLOR
].red
= 0;
333 pScreenPriv
->colors
[MASK_COLOR
].green
= 0;
334 pScreenPriv
->colors
[MASK_COLOR
].blue
= 0;
335 pScreenPriv
->damageRegistered
= 0;
336 pScreenPriv
->numberOfCursors
= 0;
338 dixSetPrivate(&pScreen
->devPrivates
, miSpriteScreenKey
, pScreenPriv
);
340 pScreen
->CloseScreen
= miSpriteCloseScreen
;
341 pScreen
->GetImage
= miSpriteGetImage
;
342 pScreen
->GetSpans
= miSpriteGetSpans
;
343 pScreen
->SourceValidate
= miSpriteSourceValidate
;
345 pScreen
->CopyWindow
= miSpriteCopyWindow
;
346 pScreen
->InstallColormap
= miSpriteInstallColormap
;
347 pScreen
->StoreColors
= miSpriteStoreColors
;
357 * CloseScreen wrapper -- unwrap everything, free the private data
358 * and call the wrapped function
362 miSpriteCloseScreen(ScreenPtr pScreen
)
364 miSpriteScreenPtr pScreenPriv
= GetSpriteScreen(pScreen
);
366 pScreen
->CloseScreen
= pScreenPriv
->CloseScreen
;
367 pScreen
->GetImage
= pScreenPriv
->GetImage
;
368 pScreen
->GetSpans
= pScreenPriv
->GetSpans
;
369 pScreen
->SourceValidate
= pScreenPriv
->SourceValidate
;
370 pScreen
->InstallColormap
= pScreenPriv
->InstallColormap
;
371 pScreen
->StoreColors
= pScreenPriv
->StoreColors
;
373 DamageDestroy(pScreenPriv
->pDamage
);
377 return (*pScreen
->CloseScreen
) (pScreen
);
381 miSpriteGetImage(DrawablePtr pDrawable
, int sx
, int sy
, int w
, int h
,
382 unsigned int format
, unsigned long planemask
, char *pdstLine
)
384 ScreenPtr pScreen
= pDrawable
->pScreen
;
386 miCursorInfoPtr pCursorInfo
;
387 miSpriteScreenPtr pPriv
= GetSpriteScreen(pScreen
);
389 SCREEN_PROLOGUE(pPriv
, pScreen
, GetImage
);
391 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
392 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
393 if (DevHasCursor(pDev
)) {
394 pCursorInfo
= MISPRITE(pDev
);
395 if (pCursorInfo
->isUp
&& pCursorInfo
->pScreen
== pScreen
&&
396 ORG_OVERLAP(&pCursorInfo
->saved
, pDrawable
->x
, pDrawable
->y
,
398 SPRITE_DEBUG(("GetImage remove\n"));
399 miSpriteRemoveCursor(pDev
, pScreen
);
405 (*pScreen
->GetImage
) (pDrawable
, sx
, sy
, w
, h
, format
, planemask
, pdstLine
);
407 SCREEN_EPILOGUE(pPriv
, pScreen
, GetImage
);
411 miSpriteGetSpans(DrawablePtr pDrawable
, int wMax
, DDXPointPtr ppt
,
412 int *pwidth
, int nspans
, char *pdstStart
)
414 ScreenPtr pScreen
= pDrawable
->pScreen
;
416 miCursorInfoPtr pCursorInfo
;
417 miSpriteScreenPtr pPriv
= GetSpriteScreen(pScreen
);
419 SCREEN_PROLOGUE(pPriv
, pScreen
, GetSpans
);
421 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
422 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
423 if (DevHasCursor(pDev
)) {
424 pCursorInfo
= MISPRITE(pDev
);
426 if (pCursorInfo
->isUp
&& pCursorInfo
->pScreen
== pScreen
) {
435 for (pts
= ppt
, widths
= pwidth
, nPts
= nspans
;
436 nPts
--; pts
++, widths
++) {
437 if (SPN_OVERLAP(&pCursorInfo
->saved
, pts
->y
+ yorg
,
438 pts
->x
+ xorg
, *widths
)) {
439 SPRITE_DEBUG(("GetSpans remove\n"));
440 miSpriteRemoveCursor(pDev
, pScreen
);
449 (*pScreen
->GetSpans
) (pDrawable
, wMax
, ppt
, pwidth
, nspans
, pdstStart
);
451 SCREEN_EPILOGUE(pPriv
, pScreen
, GetSpans
);
455 miSpriteSourceValidate(DrawablePtr pDrawable
, int x
, int y
, int width
,
456 int height
, unsigned int subWindowMode
)
458 ScreenPtr pScreen
= pDrawable
->pScreen
;
460 miCursorInfoPtr pCursorInfo
;
461 miSpriteScreenPtr pPriv
= GetSpriteScreen(pScreen
);
463 SCREEN_PROLOGUE(pPriv
, pScreen
, SourceValidate
);
465 if (pDrawable
->type
== DRAWABLE_WINDOW
) {
466 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
467 if (DevHasCursor(pDev
)) {
468 pCursorInfo
= MISPRITE(pDev
);
469 if (pCursorInfo
->isUp
&& pCursorInfo
->pScreen
== pScreen
&&
470 ORG_OVERLAP(&pCursorInfo
->saved
, pDrawable
->x
, pDrawable
->y
,
471 x
, y
, width
, height
)) {
472 SPRITE_DEBUG(("SourceValidate remove\n"));
473 miSpriteRemoveCursor(pDev
, pScreen
);
479 if (pScreen
->SourceValidate
)
480 (*pScreen
->SourceValidate
) (pDrawable
, x
, y
, width
, height
,
483 SCREEN_EPILOGUE(pPriv
, pScreen
, SourceValidate
);
487 miSpriteCopyWindow(WindowPtr pWindow
, DDXPointRec ptOldOrg
, RegionPtr prgnSrc
)
489 ScreenPtr pScreen
= pWindow
->drawable
.pScreen
;
491 miCursorInfoPtr pCursorInfo
;
492 miSpriteScreenPtr pPriv
= GetSpriteScreen(pScreen
);
494 SCREEN_PROLOGUE(pPriv
, pScreen
, CopyWindow
);
496 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
497 if (DevHasCursor(pDev
)) {
498 pCursorInfo
= MISPRITE(pDev
);
500 * Damage will take care of destination check
502 if (pCursorInfo
->isUp
&& pCursorInfo
->pScreen
== pScreen
&&
503 RegionContainsRect(prgnSrc
, &pCursorInfo
->saved
) != rgnOUT
) {
504 SPRITE_DEBUG(("CopyWindow remove\n"));
505 miSpriteRemoveCursor(pDev
, pScreen
);
510 (*pScreen
->CopyWindow
) (pWindow
, ptOldOrg
, prgnSrc
);
511 SCREEN_EPILOGUE(pPriv
, pScreen
, CopyWindow
);
515 miSpriteBlockHandler(ScreenPtr pScreen
, pointer pTimeout
,
518 miSpriteScreenPtr pPriv
= GetSpriteScreen(pScreen
);
520 miCursorInfoPtr pCursorInfo
;
521 Bool WorkToDo
= FALSE
;
523 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
524 if (DevHasCursor(pDev
)) {
525 pCursorInfo
= MISPRITE(pDev
);
526 if (pCursorInfo
&& !pCursorInfo
->isUp
527 && pCursorInfo
->pScreen
== pScreen
&& pCursorInfo
->shouldBeUp
) {
528 SPRITE_DEBUG(("BlockHandler save"));
529 miSpriteSaveUnderCursor(pDev
, pScreen
);
533 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
534 if (DevHasCursor(pDev
)) {
535 pCursorInfo
= MISPRITE(pDev
);
536 if (pCursorInfo
&& !pCursorInfo
->isUp
&&
537 pCursorInfo
->pScreen
== pScreen
&& pCursorInfo
->shouldBeUp
) {
538 SPRITE_DEBUG(("BlockHandler restore\n"));
539 miSpriteRestoreCursor(pDev
, pScreen
);
540 if (!pCursorInfo
->isUp
)
546 SCREEN_PROLOGUE(pPriv
, pScreen
, BlockHandler
);
548 (*pScreen
->BlockHandler
) (pScreen
, pTimeout
, pReadmask
);
551 SCREEN_EPILOGUE(pPriv
, pScreen
, BlockHandler
);
553 pPriv
->BlockHandler
= NULL
;
557 miSpriteInstallColormap(ColormapPtr pMap
)
559 ScreenPtr pScreen
= pMap
->pScreen
;
560 miSpriteScreenPtr pPriv
= GetSpriteScreen(pScreen
);
562 SCREEN_PROLOGUE(pPriv
, pScreen
, InstallColormap
);
564 (*pScreen
->InstallColormap
) (pMap
);
566 SCREEN_EPILOGUE(pPriv
, pScreen
, InstallColormap
);
568 /* InstallColormap can be called before devices are initialized. */
569 pPriv
->pInstalledMap
= pMap
;
570 if (pPriv
->pColormap
!= pMap
) {
572 miCursorInfoPtr pCursorInfo
;
574 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
575 if (DevHasCursor(pDev
)) {
576 pCursorInfo
= MISPRITE(pDev
);
577 pCursorInfo
->checkPixels
= TRUE
;
578 if (pCursorInfo
->isUp
&& pCursorInfo
->pScreen
== pScreen
)
579 miSpriteRemoveCursor(pDev
, pScreen
);
587 miSpriteStoreColors(ColormapPtr pMap
, int ndef
, xColorItem
* pdef
)
589 ScreenPtr pScreen
= pMap
->pScreen
;
590 miSpriteScreenPtr pPriv
= GetSpriteScreen(pScreen
);
595 miCursorInfoPtr pCursorInfo
;
597 SCREEN_PROLOGUE(pPriv
, pScreen
, StoreColors
);
599 (*pScreen
->StoreColors
) (pMap
, ndef
, pdef
);
601 SCREEN_EPILOGUE(pPriv
, pScreen
, StoreColors
);
603 if (pPriv
->pColormap
== pMap
) {
605 pVisual
= pMap
->pVisual
;
606 if (pVisual
->class == DirectColor
) {
607 /* Direct color - match on any of the subfields */
609 #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
611 #define UpdateDAC(dev, plane,dac,mask) {\
612 if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
613 dev->colors[plane].dac = pdef[i].dac; \
618 #define CheckDirect(dev, plane) \
619 UpdateDAC(dev, plane,red,redMask) \
620 UpdateDAC(dev, plane,green,greenMask) \
621 UpdateDAC(dev, plane,blue,blueMask)
623 for (i
= 0; i
< ndef
; i
++) {
624 CheckDirect(pPriv
, SOURCE_COLOR
)
625 CheckDirect(pPriv
, MASK_COLOR
)
629 /* PseudoColor/GrayScale - match on exact pixel */
630 for (i
= 0; i
< ndef
; i
++) {
631 if (pdef
[i
].pixel
== pPriv
->colors
[SOURCE_COLOR
].pixel
) {
632 pPriv
->colors
[SOURCE_COLOR
] = pdef
[i
];
636 if (pdef
[i
].pixel
== pPriv
->colors
[MASK_COLOR
].pixel
) {
637 pPriv
->colors
[MASK_COLOR
] = pdef
[i
];
644 for (pDev
= inputInfo
.devices
; pDev
; pDev
= pDev
->next
) {
645 if (DevHasCursor(pDev
)) {
646 pCursorInfo
= MISPRITE(pDev
);
647 pCursorInfo
->checkPixels
= TRUE
;
648 if (pCursorInfo
->isUp
&& pCursorInfo
->pScreen
== pScreen
)
649 miSpriteRemoveCursor(pDev
, pScreen
);
657 miSpriteFindColors(miCursorInfoPtr pDevCursor
, ScreenPtr pScreen
)
659 miSpriteScreenPtr pScreenPriv
= GetSpriteScreen(pScreen
);
661 xColorItem
*sourceColor
, *maskColor
;
663 pCursor
= pDevCursor
->pCursor
;
664 sourceColor
= &pScreenPriv
->colors
[SOURCE_COLOR
];
665 maskColor
= &pScreenPriv
->colors
[MASK_COLOR
];
666 if (pScreenPriv
->pColormap
!= pScreenPriv
->pInstalledMap
||
667 !(pCursor
->foreRed
== sourceColor
->red
&&
668 pCursor
->foreGreen
== sourceColor
->green
&&
669 pCursor
->foreBlue
== sourceColor
->blue
&&
670 pCursor
->backRed
== maskColor
->red
&&
671 pCursor
->backGreen
== maskColor
->green
&&
672 pCursor
->backBlue
== maskColor
->blue
)) {
673 pScreenPriv
->pColormap
= pScreenPriv
->pInstalledMap
;
674 sourceColor
->red
= pCursor
->foreRed
;
675 sourceColor
->green
= pCursor
->foreGreen
;
676 sourceColor
->blue
= pCursor
->foreBlue
;
677 FakeAllocColor(pScreenPriv
->pColormap
, sourceColor
);
678 maskColor
->red
= pCursor
->backRed
;
679 maskColor
->green
= pCursor
->backGreen
;
680 maskColor
->blue
= pCursor
->backBlue
;
681 FakeAllocColor(pScreenPriv
->pColormap
, maskColor
);
682 /* "free" the pixels right away, don't let this confuse you */
683 FakeFreeColor(pScreenPriv
->pColormap
, sourceColor
->pixel
);
684 FakeFreeColor(pScreenPriv
->pColormap
, maskColor
->pixel
);
687 pDevCursor
->checkPixels
= FALSE
;
692 * miPointer interface routines
698 miSpriteRealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
)
700 miCursorInfoPtr pCursorInfo
;
702 if (IsFloating(pDev
))
705 pCursorInfo
= MISPRITE(pDev
);
707 if (pCursor
== pCursorInfo
->pCursor
)
708 pCursorInfo
->checkPixels
= TRUE
;
710 return miDCRealizeCursor(pScreen
, pCursor
);
714 miSpriteUnrealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
)
716 return miDCUnrealizeCursor(pScreen
, pCursor
);
720 miSpriteSetCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
721 CursorPtr pCursor
, int x
, int y
)
723 miCursorInfoPtr pPointer
;
724 miSpriteScreenPtr pScreenPriv
;
726 if (IsFloating(pDev
))
729 pPointer
= MISPRITE(pDev
);
730 pScreenPriv
= GetSpriteScreen(pScreen
);
733 if (pPointer
->shouldBeUp
)
734 --pScreenPriv
->numberOfCursors
;
735 pPointer
->shouldBeUp
= FALSE
;
737 miSpriteRemoveCursor(pDev
, pScreen
);
738 if (pScreenPriv
->numberOfCursors
== 0)
739 miSpriteDisableDamage(pScreen
, pScreenPriv
);
740 pPointer
->pCursor
= 0;
743 if (!pPointer
->shouldBeUp
)
744 pScreenPriv
->numberOfCursors
++;
745 pPointer
->shouldBeUp
= TRUE
;
747 miSpriteRegisterBlockHandler(pScreen
, pScreenPriv
);
748 if (pPointer
->x
== x
&&
750 pPointer
->pCursor
== pCursor
&& !pPointer
->checkPixels
) {
755 pPointer
->pCacheWin
= NullWindow
;
756 if (pPointer
->checkPixels
|| pPointer
->pCursor
!= pCursor
) {
757 pPointer
->pCursor
= pCursor
;
758 miSpriteFindColors(pPointer
, pScreen
);
760 if (pPointer
->isUp
) {
761 /* TODO: reimplement flicker-free MoveCursor */
762 SPRITE_DEBUG(("SetCursor remove %d\n", pDev
->id
));
763 miSpriteRemoveCursor(pDev
, pScreen
);
766 if (!pPointer
->isUp
&& pPointer
->pCursor
) {
767 SPRITE_DEBUG(("SetCursor restore %d\n", pDev
->id
));
768 miSpriteSaveUnderCursor(pDev
, pScreen
);
769 miSpriteRestoreCursor(pDev
, pScreen
);
775 miSpriteMoveCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, int x
, int y
)
779 if (IsFloating(pDev
))
782 pCursor
= MISPRITE(pDev
)->pCursor
;
784 miSpriteSetCursor(pDev
, pScreen
, pCursor
, x
, y
);
788 miSpriteDeviceCursorInitialize(DeviceIntPtr pDev
, ScreenPtr pScreen
)
790 int ret
= miDCDeviceInitialize(pDev
, pScreen
);
793 miCursorInfoPtr pCursorInfo
;
796 dixLookupPrivate(&pDev
->devPrivates
, miSpriteDevPrivatesKey
);
797 pCursorInfo
->pCursor
= NULL
;
800 pCursorInfo
->isUp
= FALSE
;
801 pCursorInfo
->shouldBeUp
= FALSE
;
802 pCursorInfo
->pCacheWin
= NullWindow
;
803 pCursorInfo
->isInCacheWin
= FALSE
;
804 pCursorInfo
->checkPixels
= TRUE
;
805 pCursorInfo
->pScreen
= FALSE
;
812 miSpriteDeviceCursorCleanup(DeviceIntPtr pDev
, ScreenPtr pScreen
)
814 miCursorInfoPtr pCursorInfo
=
815 dixLookupPrivate(&pDev
->devPrivates
, miSpriteDevPrivatesKey
);
817 if (DevHasCursor(pDev
))
818 miDCDeviceCleanup(pDev
, pScreen
);
820 memset(pCursorInfo
, 0, sizeof(miCursorInfoRec
));
828 miSpriteRemoveCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
)
830 miSpriteScreenPtr pScreenPriv
;
831 miCursorInfoPtr pCursorInfo
;
833 if (IsFloating(pDev
))
836 DamageDrawInternal(pScreen
, TRUE
);
837 pScreenPriv
= GetSpriteScreen(pScreen
);
838 pCursorInfo
= MISPRITE(pDev
);
840 miSpriteIsDown(pCursorInfo
);
841 miSpriteRegisterBlockHandler(pScreen
, pScreenPriv
);
842 pCursorInfo
->pCacheWin
= NullWindow
;
843 miSpriteDisableDamage(pScreen
, pScreenPriv
);
844 if (!miDCRestoreUnderCursor(pDev
,
846 pCursorInfo
->saved
.x1
,
847 pCursorInfo
->saved
.y1
,
848 pCursorInfo
->saved
.x2
-
849 pCursorInfo
->saved
.x1
,
850 pCursorInfo
->saved
.y2
-
851 pCursorInfo
->saved
.y1
)) {
852 miSpriteIsUp(pCursorInfo
);
854 miSpriteEnableDamage(pScreen
, pScreenPriv
);
855 DamageDrawInternal(pScreen
, FALSE
);
859 * Called from the block handler, saves area under cursor
860 * before waiting for something to do.
864 miSpriteSaveUnderCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
)
866 miSpriteScreenPtr pScreenPriv
;
867 miCursorInfoPtr pCursorInfo
;
869 if (IsFloating(pDev
))
872 DamageDrawInternal(pScreen
, TRUE
);
873 pScreenPriv
= GetSpriteScreen(pScreen
);
874 pCursorInfo
= MISPRITE(pDev
);
876 miSpriteComputeSaved(pDev
, pScreen
);
878 miSpriteDisableDamage(pScreen
, pScreenPriv
);
880 miDCSaveUnderCursor(pDev
,
882 pCursorInfo
->saved
.x1
,
883 pCursorInfo
->saved
.y1
,
884 pCursorInfo
->saved
.x2
-
885 pCursorInfo
->saved
.x1
,
886 pCursorInfo
->saved
.y2
- pCursorInfo
->saved
.y1
);
887 SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev
->id
));
888 miSpriteEnableDamage(pScreen
, pScreenPriv
);
889 DamageDrawInternal(pScreen
, FALSE
);
893 * Called from the block handler, restores the cursor
894 * before waiting for something to do.
898 miSpriteRestoreCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
)
900 miSpriteScreenPtr pScreenPriv
;
903 miCursorInfoPtr pCursorInfo
;
905 if (IsFloating(pDev
))
908 DamageDrawInternal(pScreen
, TRUE
);
909 pScreenPriv
= GetSpriteScreen(pScreen
);
910 pCursorInfo
= MISPRITE(pDev
);
912 miSpriteComputeSaved(pDev
, pScreen
);
913 pCursor
= pCursorInfo
->pCursor
;
915 x
= pCursorInfo
->x
- (int) pCursor
->bits
->xhot
;
916 y
= pCursorInfo
->y
- (int) pCursor
->bits
->yhot
;
917 miSpriteDisableDamage(pScreen
, pScreenPriv
);
918 SPRITE_DEBUG(("RestoreCursor %d\n", pDev
->id
));
919 if (pCursorInfo
->checkPixels
)
920 miSpriteFindColors(pCursorInfo
, pScreen
);
921 if (miDCPutUpCursor(pDev
, pScreen
,
923 pScreenPriv
->colors
[SOURCE_COLOR
].pixel
,
924 pScreenPriv
->colors
[MASK_COLOR
].pixel
)) {
925 miSpriteIsUp(pCursorInfo
);
926 pCursorInfo
->pScreen
= pScreen
;
928 miSpriteEnableDamage(pScreen
, pScreenPriv
);
929 DamageDrawInternal(pScreen
, FALSE
);
933 * compute the desired area of the screen to save
937 miSpriteComputeSaved(DeviceIntPtr pDev
, ScreenPtr pScreen
)
942 miCursorInfoPtr pCursorInfo
;
944 if (IsFloating(pDev
))
947 pCursorInfo
= MISPRITE(pDev
);
949 pCursor
= pCursorInfo
->pCursor
;
950 x
= pCursorInfo
->x
- (int) pCursor
->bits
->xhot
;
951 y
= pCursorInfo
->y
- (int) pCursor
->bits
->yhot
;
952 w
= pCursor
->bits
->width
;
953 h
= pCursor
->bits
->height
;
956 pCursorInfo
->saved
.x1
= x
- wpad
;
957 pCursorInfo
->saved
.y1
= y
- hpad
;
958 pCursorInfo
->saved
.x2
= pCursorInfo
->saved
.x1
+ w
+ wpad
* 2;
959 pCursorInfo
->saved
.y2
= pCursorInfo
->saved
.y1
+ h
+ hpad
* 2;