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