1 /*
2  * midispcur.c
3  *
4  * machine independent cursor display routines
5  */
6 
7 /* $XConsortium: midispcur.c,v 5.14 94/04/17 20:27:28 dpw Exp $ */
8 
9 /*
10 
11 Copyright (c) 1989  X Consortium
12 
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19 
20 The above copyright notice and this permission notice shall be included in
21 all copies or substantial portions of the Software.
22 
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
27 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 
30 Except as contained in this notice, the name of the X Consortium shall not be
31 used in advertising or otherwise to promote the sale, use or other dealings
32 in this Software without prior written authorization from the X Consortium.
33 */
34 
35 #define NEED_EVENTS
36 # include   "X.h"
37 # include   "misc.h"
38 # include   "input.h"
39 # include   "cursorstr.h"
40 # include   "windowstr.h"
41 # include   "regionstr.h"
42 # include   "dixstruct.h"
43 # include   "scrnintstr.h"
44 # include   "servermd.h"
45 # include   "mipointer.h"
46 # include   "misprite.h"
47 # include   "gcstruct.h"
48 
49 extern WindowPtr    *WindowTable;
50 
51 /* per-screen private data */
52 
53 static int	miDCScreenIndex;
54 static unsigned long miDCGeneration = 0;
55 
56 static Bool	miDCCloseScreen();
57 
58 typedef struct {
59     GCPtr	    pSourceGC, pMaskGC;
60     GCPtr	    pSaveGC, pRestoreGC;
61     GCPtr	    pMoveGC;
62     GCPtr	    pPixSourceGC, pPixMaskGC;
63     CloseScreenProcPtr CloseScreen;
64     PixmapPtr	    pSave, pTemp;
65 } miDCScreenRec, *miDCScreenPtr;
66 
67 /* per-cursor per-screen private data */
68 typedef struct {
69     PixmapPtr		sourceBits;	    /* source bits */
70     PixmapPtr		maskBits;	    /* mask bits */
71 } miDCCursorRec, *miDCCursorPtr;
72 
73 /*
74  * sprite/cursor method table
75  */
76 
77 static Bool	miDCRealizeCursor(),	    miDCUnrealizeCursor();
78 static Bool	miDCPutUpCursor(),	    miDCSaveUnderCursor();
79 static Bool	miDCRestoreUnderCursor(),   miDCMoveCursor();
80 static Bool	miDCChangeSave();
81 
82 static miSpriteCursorFuncRec miDCFuncs = {
83     miDCRealizeCursor,
84     miDCUnrealizeCursor,
85     miDCPutUpCursor,
86     miDCSaveUnderCursor,
87     miDCRestoreUnderCursor,
88     miDCMoveCursor,
89     miDCChangeSave,
90 };
91 
92 Bool
miDCInitialize(pScreen,screenFuncs)93 miDCInitialize (pScreen, screenFuncs)
94     ScreenPtr		    pScreen;
95     miPointerScreenFuncPtr  screenFuncs;
96 {
97     miDCScreenPtr   pScreenPriv;
98 
99     if (miDCGeneration != serverGeneration)
100     {
101 	miDCScreenIndex = AllocateScreenPrivateIndex ();
102 	if (miDCScreenIndex < 0)
103 	    return FALSE;
104 	miDCGeneration = serverGeneration;
105     }
106     pScreenPriv = (miDCScreenPtr) xalloc (sizeof (miDCScreenRec));
107     if (!pScreenPriv)
108 	return FALSE;
109 
110     /*
111      * initialize the entire private structure to zeros
112      */
113 
114     pScreenPriv->pSourceGC =
115 	pScreenPriv->pMaskGC =
116 	pScreenPriv->pSaveGC =
117  	pScreenPriv->pRestoreGC =
118  	pScreenPriv->pMoveGC =
119  	pScreenPriv->pPixSourceGC =
120 	pScreenPriv->pPixMaskGC = NULL;
121 
122     pScreenPriv->pSave = pScreenPriv->pTemp = NULL;
123 
124     pScreenPriv->CloseScreen = pScreen->CloseScreen;
125     pScreen->CloseScreen = miDCCloseScreen;
126 
127     pScreen->devPrivates[miDCScreenIndex].ptr = (pointer) pScreenPriv;
128 
129     if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
130     {
131 	xfree ((pointer) pScreenPriv);
132 	return FALSE;
133     }
134     return TRUE;
135 }
136 
137 #define tossGC(gc)  (gc ? FreeGC (gc, (GContext) 0) : 0)
138 #define tossPix(pix)	(pix ? (*pScreen->DestroyPixmap) (pix) : TRUE)
139 
140 static Bool
miDCCloseScreen(index,pScreen)141 miDCCloseScreen (index, pScreen)
142     ScreenPtr	pScreen;
143 {
144     miDCScreenPtr   pScreenPriv;
145 
146     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
147     pScreen->CloseScreen = pScreenPriv->CloseScreen;
148     tossGC (pScreenPriv->pSourceGC);
149     tossGC (pScreenPriv->pMaskGC);
150     tossGC (pScreenPriv->pSaveGC);
151     tossGC (pScreenPriv->pRestoreGC);
152     tossGC (pScreenPriv->pMoveGC);
153     tossGC (pScreenPriv->pPixSourceGC);
154     tossGC (pScreenPriv->pPixMaskGC);
155     tossPix (pScreenPriv->pSave);
156     tossPix (pScreenPriv->pTemp);
157     xfree ((pointer) pScreenPriv);
158     return (*pScreen->CloseScreen) (index, pScreen);
159 }
160 
161 static Bool
miDCRealizeCursor(pScreen,pCursor)162 miDCRealizeCursor (pScreen, pCursor)
163     ScreenPtr	pScreen;
164     CursorPtr	pCursor;
165 {
166     if (pCursor->bits->refcnt <= 1)
167 	pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL;
168     return TRUE;
169 }
170 
171 static miDCCursorPtr
miDCRealize(pScreen,pCursor)172 miDCRealize (pScreen, pCursor)
173     ScreenPtr	pScreen;
174     CursorPtr	pCursor;
175 {
176     miDCCursorPtr   pPriv;
177     GCPtr	    pGC;
178     XID		    gcvals[3];
179 
180     pPriv = (miDCCursorPtr) xalloc (sizeof (miDCCursorRec));
181     if (!pPriv)
182 	return (miDCCursorPtr)NULL;
183     pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1);
184     if (!pPriv->sourceBits)
185     {
186 	xfree ((pointer) pPriv);
187 	return (miDCCursorPtr)NULL;
188     }
189     pPriv->maskBits =  (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1);
190     if (!pPriv->maskBits)
191     {
192 	(*pScreen->DestroyPixmap) (pPriv->sourceBits);
193 	xfree ((pointer) pPriv);
194 	return (miDCCursorPtr)NULL;
195     }
196     pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv;
197 
198     /* create the two sets of bits, clipping as appropriate */
199 
200     pGC = GetScratchGC (1, pScreen);
201     if (!pGC)
202     {
203 	(void) miDCUnrealizeCursor (pScreen, pCursor);
204 	return (miDCCursorPtr)NULL;
205     }
206 
207     ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
208     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
209 			   0, 0, pCursor->bits->width, pCursor->bits->height,
210  			   0, XYPixmap, (char *)pCursor->bits->source);
211     gcvals[0] = GXand;
212     ChangeGC (pGC, GCFunction, gcvals);
213     ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
214     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
215 			   0, 0, pCursor->bits->width, pCursor->bits->height,
216  			   0, XYPixmap, (char *)pCursor->bits->mask);
217 
218     /* mask bits -- pCursor->mask & ~pCursor->source */
219     gcvals[0] = GXcopy;
220     ChangeGC (pGC, GCFunction, gcvals);
221     ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
222     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
223 			   0, 0, pCursor->bits->width, pCursor->bits->height,
224  			   0, XYPixmap, (char *)pCursor->bits->mask);
225     gcvals[0] = GXandInverted;
226     ChangeGC (pGC, GCFunction, gcvals);
227     ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
228     (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
229 			   0, 0, pCursor->bits->width, pCursor->bits->height,
230  			   0, XYPixmap, (char *)pCursor->bits->source);
231     FreeScratchGC (pGC);
232     return pPriv;
233 }
234 
235 static Bool
miDCUnrealizeCursor(pScreen,pCursor)236 miDCUnrealizeCursor (pScreen, pCursor)
237     ScreenPtr	pScreen;
238     CursorPtr	pCursor;
239 {
240     miDCCursorPtr   pPriv;
241 
242     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
243     if (pPriv && (pCursor->bits->refcnt <= 1))
244     {
245 	(*pScreen->DestroyPixmap) (pPriv->sourceBits);
246 	(*pScreen->DestroyPixmap) (pPriv->maskBits);
247 	xfree ((pointer) pPriv);
248 	pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL;
249     }
250     return TRUE;
251 }
252 
253 static void
miDCPutBits(pDrawable,pPriv,sourceGC,maskGC,x,y,w,h,source,mask)254 miDCPutBits (pDrawable, pPriv, sourceGC, maskGC, x, y, w, h, source, mask)
255     DrawablePtr	    pDrawable;
256     GCPtr	    sourceGC, maskGC;
257     int             x, y;
258     unsigned        w, h;
259     miDCCursorPtr   pPriv;
260     unsigned long   source, mask;
261 {
262     XID	    gcvals[1];
263 
264     if (sourceGC->fgPixel != source)
265     {
266 	gcvals[0] = source;
267 	DoChangeGC (sourceGC, GCForeground, gcvals, 0);
268     }
269     if (sourceGC->serialNumber != pDrawable->serialNumber)
270 	ValidateGC (pDrawable, sourceGC);
271     (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
272     if (maskGC->fgPixel != mask)
273     {
274 	gcvals[0] = mask;
275 	DoChangeGC (maskGC, GCForeground, gcvals, 0);
276     }
277     if (maskGC->serialNumber != pDrawable->serialNumber)
278 	ValidateGC (pDrawable, maskGC);
279     (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
280 }
281 
282 #define EnsureGC(gc,win) (gc || miDCMakeGC(&gc, win))
283 
284 static GCPtr
miDCMakeGC(ppGC,pWin)285 miDCMakeGC(ppGC, pWin)
286     GCPtr	*ppGC;
287     WindowPtr	pWin;
288 {
289     GCPtr pGC;
290     int   status;
291     XID   gcvals[2];
292 
293     gcvals[0] = IncludeInferiors;
294     gcvals[1] = FALSE;
295     pGC = CreateGC((DrawablePtr)pWin,
296 		   GCSubwindowMode|GCGraphicsExposures, gcvals, &status);
297     if (pGC)
298 	(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
299     *ppGC = pGC;
300     return pGC;
301 }
302 
303 static Bool
miDCPutUpCursor(pScreen,pCursor,x,y,source,mask)304 miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
305     ScreenPtr	    pScreen;
306     CursorPtr	    pCursor;
307     int		    x, y;
308     unsigned long   source, mask;
309 {
310     miDCScreenPtr   pScreenPriv;
311     miDCCursorPtr   pPriv;
312     WindowPtr	    pWin;
313 
314     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
315     if (!pPriv)
316     {
317 	pPriv = miDCRealize(pScreen, pCursor);
318 	if (!pPriv)
319 	    return FALSE;
320     }
321     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
322     pWin = WindowTable[pScreen->myNum];
323     if (!EnsureGC(pScreenPriv->pSourceGC, pWin))
324 	return FALSE;
325     if (!EnsureGC(pScreenPriv->pMaskGC, pWin))
326     {
327 	FreeGC (pScreenPriv->pSourceGC, (GContext) 0);
328 	pScreenPriv->pSourceGC = 0;
329 	return FALSE;
330     }
331     miDCPutBits ((DrawablePtr)pWin, pPriv,
332 		 pScreenPriv->pSourceGC, pScreenPriv->pMaskGC,
333 		 x, y, pCursor->bits->width, pCursor->bits->height,
334 		 source, mask);
335     return TRUE;
336 }
337 
338 static Bool
miDCSaveUnderCursor(pScreen,x,y,w,h)339 miDCSaveUnderCursor (pScreen, x, y, w, h)
340     ScreenPtr	pScreen;
341     int		x, y, w, h;
342 {
343     miDCScreenPtr   pScreenPriv;
344     PixmapPtr	    pSave;
345     WindowPtr	    pWin;
346     GCPtr	    pGC;
347 
348     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
349     pSave = pScreenPriv->pSave;
350     pWin = WindowTable[pScreen->myNum];
351     if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
352     {
353 	if (pSave)
354 	    (*pScreen->DestroyPixmap) (pSave);
355 	pScreenPriv->pSave = pSave =
356 		(*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth);
357 	if (!pSave)
358 	    return FALSE;
359     }
360     if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
361 	return FALSE;
362     pGC = pScreenPriv->pSaveGC;
363     if (pSave->drawable.serialNumber != pGC->serialNumber)
364 	ValidateGC ((DrawablePtr) pSave, pGC);
365     (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
366 			    x, y, w, h, 0, 0);
367     return TRUE;
368 }
369 
370 static Bool
miDCRestoreUnderCursor(pScreen,x,y,w,h)371 miDCRestoreUnderCursor (pScreen, x, y, w, h)
372     ScreenPtr	pScreen;
373     int		x, y, w, h;
374 {
375     miDCScreenPtr   pScreenPriv;
376     PixmapPtr	    pSave;
377     WindowPtr	    pWin;
378     GCPtr	    pGC;
379 
380     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
381     pSave = pScreenPriv->pSave;
382     pWin = WindowTable[pScreen->myNum];
383     if (!pSave)
384 	return FALSE;
385     if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
386 	return FALSE;
387     pGC = pScreenPriv->pRestoreGC;
388     if (pWin->drawable.serialNumber != pGC->serialNumber)
389 	ValidateGC ((DrawablePtr) pWin, pGC);
390     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
391 			    0, 0, w, h, x, y);
392     return TRUE;
393 }
394 
395 static Bool
miDCChangeSave(pScreen,x,y,w,h,dx,dy)396 miDCChangeSave (pScreen, x, y, w, h, dx, dy)
397     ScreenPtr	    pScreen;
398     int		    x, y, w, h, dx, dy;
399 {
400     miDCScreenPtr   pScreenPriv;
401     PixmapPtr	    pSave;
402     WindowPtr	    pWin;
403     GCPtr	    pGC;
404     int		    sourcex, sourcey, destx, desty, copyw, copyh;
405 
406     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
407     pSave = pScreenPriv->pSave;
408     pWin = WindowTable[pScreen->myNum];
409     /*
410      * restore the bits which are about to get trashed
411      */
412     if (!pSave)
413 	return FALSE;
414     if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
415 	return FALSE;
416     pGC = pScreenPriv->pRestoreGC;
417     if (pWin->drawable.serialNumber != pGC->serialNumber)
418 	ValidateGC ((DrawablePtr) pWin, pGC);
419     /*
420      * copy the old bits to the screen.
421      */
422     if (dy > 0)
423     {
424 	(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
425 			       0, h - dy, w, dy, x + dx, y + h);
426     }
427     else if (dy < 0)
428     {
429 	(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
430 			       0, 0, w, -dy, x + dx, y + dy);
431     }
432     if (dy >= 0)
433     {
434 	desty = y + dy;
435 	sourcey = 0;
436 	copyh = h - dy;
437     }
438     else
439     {
440 	desty = y;
441 	sourcey = - dy;
442 	copyh = h + dy;
443     }
444     if (dx > 0)
445     {
446 	(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
447 			       w - dx, sourcey, dx, copyh, x + w, desty);
448     }
449     else if (dx < 0)
450     {
451 	(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
452 			       0, sourcey, -dx, copyh, x + dx, desty);
453     }
454     if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
455 	return FALSE;
456     pGC = pScreenPriv->pSaveGC;
457     if (pSave->drawable.serialNumber != pGC->serialNumber)
458 	ValidateGC ((DrawablePtr) pSave, pGC);
459     /*
460      * move the bits that are still valid within the pixmap
461      */
462     if (dx >= 0)
463     {
464 	sourcex = 0;
465 	destx = dx;
466 	copyw = w - dx;
467     }
468     else
469     {
470 	destx = 0;
471 	sourcex = - dx;
472 	copyw = w + dx;
473     }
474     if (dy >= 0)
475     {
476 	sourcey = 0;
477 	desty = dy;
478 	copyh = h - dy;
479     }
480     else
481     {
482 	desty = 0;
483 	sourcey = -dy;
484 	copyh = h + dy;
485     }
486     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC,
487 			   sourcex, sourcey, copyw, copyh, destx, desty);
488     /*
489      * copy the new bits from the screen into the remaining areas of the
490      * pixmap
491      */
492     if (dy > 0)
493     {
494 	(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
495 			       x, y, w, dy, 0, 0);
496     }
497     else if (dy < 0)
498     {
499 	(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
500 			       x, y + h + dy, w, -dy, 0, h + dy);
501     }
502     if (dy >= 0)
503     {
504 	desty = dy;
505 	sourcey = y + dy;
506 	copyh = h - dy;
507     }
508     else
509     {
510 	desty = 0;
511 	sourcey = y;
512 	copyh = h + dy;
513     }
514     if (dx > 0)
515     {
516 	(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
517 			       x, sourcey, dx, copyh, 0, desty);
518     }
519     else if (dx < 0)
520     {
521 	(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
522 			       x + w + dx, sourcey, -dx, copyh, w + dx, desty);
523     }
524     return TRUE;
525 }
526 
527 static Bool
miDCMoveCursor(pScreen,pCursor,x,y,w,h,dx,dy,source,mask)528 miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
529     ScreenPtr	    pScreen;
530     CursorPtr	    pCursor;
531     int		    x, y, w, h, dx, dy;
532     unsigned long   source, mask;
533 {
534     miDCCursorPtr   pPriv;
535     miDCScreenPtr   pScreenPriv;
536     int		    status;
537     WindowPtr	    pWin;
538     GCPtr	    pGC;
539     XID		    gcval = FALSE;
540     PixmapPtr	    pTemp;
541 
542     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
543     if (!pPriv)
544     {
545 	pPriv = miDCRealize(pScreen, pCursor);
546 	if (!pPriv)
547 	    return FALSE;
548     }
549     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
550     pWin = WindowTable[pScreen->myNum];
551     pTemp = pScreenPriv->pTemp;
552     if (!pTemp ||
553 	pTemp->drawable.width != pScreenPriv->pSave->drawable.width ||
554 	pTemp->drawable.height != pScreenPriv->pSave->drawable.height)
555     {
556 	if (pTemp)
557 	    (*pScreen->DestroyPixmap) (pTemp);
558 	pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap)
559 	    (pScreen, w, h, pScreenPriv->pSave->drawable.depth);
560 	if (!pTemp)
561 	    return FALSE;
562     }
563     if (!pScreenPriv->pMoveGC)
564     {
565 	pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp,
566 	    GCGraphicsExposures, &gcval, &status);
567 	if (!pScreenPriv->pMoveGC)
568 	    return FALSE;
569     }
570     /*
571      * copy the saved area to a temporary pixmap
572      */
573     pGC = pScreenPriv->pMoveGC;
574     if (pGC->serialNumber != pTemp->drawable.serialNumber)
575 	ValidateGC ((DrawablePtr) pTemp, pGC);
576     (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave,
577 			  (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
578 
579     /*
580      * draw the cursor in the temporary pixmap
581      */
582     if (!pScreenPriv->pPixSourceGC)
583     {
584 	pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
585 	    GCGraphicsExposures, &gcval, &status);
586 	if (!pScreenPriv->pPixSourceGC)
587 	    return FALSE;
588     }
589     if (!pScreenPriv->pPixMaskGC)
590     {
591 	pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
592 	    GCGraphicsExposures, &gcval, &status);
593 	if (!pScreenPriv->pPixMaskGC)
594 	    return FALSE;
595     }
596     miDCPutBits ((DrawablePtr)pTemp, pPriv,
597 		 pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC,
598  		 dx, dy, pCursor->bits->width, pCursor->bits->height,
599 		 source, mask);
600 
601     /*
602      * copy the temporary pixmap onto the screen
603      */
604 
605     if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
606 	return FALSE;
607     pGC = pScreenPriv->pRestoreGC;
608     if (pWin->drawable.serialNumber != pGC->serialNumber)
609 	ValidateGC ((DrawablePtr) pWin, pGC);
610 
611     (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin,
612 			    pGC,
613 			    0, 0, w, h, x, y);
614     return TRUE;
615 }
616