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