Add patch that contain Mali fixes.
[deb_xorg-server.git] / composite / compalloc.c
1 /*
2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Copyright © 2003 Keith Packard
24 *
25 * Permission to use, copy, modify, distribute, and sell this software and its
26 * documentation for any purpose is hereby granted without fee, provided that
27 * the above copyright notice appear in all copies and that both that
28 * copyright notice and this permission notice appear in supporting
29 * documentation, and that the name of Keith Packard not be used in
30 * advertising or publicity pertaining to distribution of the software without
31 * specific, written prior permission. Keith Packard makes no
32 * representations about the suitability of this software for any purpose. It
33 * is provided "as is" without express or implied warranty.
34 *
35 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
36 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
37 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
39 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
40 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
41 * PERFORMANCE OF THIS SOFTWARE.
42 */
43
44 #ifdef HAVE_DIX_CONFIG_H
45 #include <dix-config.h>
46 #endif
47
48 #include "compint.h"
49
50 static void
51 compScreenUpdate(ScreenPtr pScreen)
52 {
53 compCheckTree(pScreen);
54 compPaintChildrenToWindow(pScreen->root);
55 }
56
57 static void
58 compBlockHandler(ScreenPtr pScreen, pointer pTimeout, pointer pReadmask)
59 {
60 CompScreenPtr cs = GetCompScreen(pScreen);
61
62 pScreen->BlockHandler = cs->BlockHandler;
63 compScreenUpdate(pScreen);
64 (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
65
66 /* Next damage will restore the block handler */
67 cs->BlockHandler = NULL;
68 }
69
70 static void
71 compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
72 {
73 WindowPtr pWin = (WindowPtr) closure;
74 ScreenPtr pScreen = pWin->drawable.pScreen;
75 CompScreenPtr cs = GetCompScreen(pScreen);
76 CompWindowPtr cw = GetCompWindow(pWin);
77
78 if (!cs->BlockHandler) {
79 cs->BlockHandler = pScreen->BlockHandler;
80 pScreen->BlockHandler = compBlockHandler;
81 }
82 cw->damaged = TRUE;
83
84 /* Mark the ancestors */
85 pWin = pWin->parent;
86 while (pWin) {
87 if (pWin->damagedDescendants)
88 break;
89 pWin->damagedDescendants = TRUE;
90 pWin = pWin->parent;
91 }
92 }
93
94 static void
95 compDestroyDamage(DamagePtr pDamage, void *closure)
96 {
97 WindowPtr pWin = (WindowPtr) closure;
98 CompWindowPtr cw = GetCompWindow(pWin);
99
100 cw->damage = 0;
101 }
102
103 static Bool
104 compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin)
105 {
106 ScreenPtr pScreen = pWin->drawable.pScreen;
107 WindowPtr pLayerWin = pWin;
108
109 if (!pWin->viewable)
110 return FALSE;
111
112 (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
113 (*pScreen->MarkWindow) (pLayerWin->parent);
114
115 *ppLayerWin = pLayerWin;
116
117 return TRUE;
118 }
119
120 static void
121 compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin)
122 {
123 ScreenPtr pScreen = pWin->drawable.pScreen;
124
125 (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
126 (*pScreen->HandleExposures) (pLayerWin->parent);
127 if (pScreen->PostValidateTree)
128 (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
129 }
130
131 /*
132 * Redirect one window for one client
133 */
134 int
135 compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
136 {
137 CompWindowPtr cw = GetCompWindow(pWin);
138 CompClientWindowPtr ccw;
139 CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
140 WindowPtr pLayerWin;
141 Bool anyMarked = FALSE;
142
143 if (pWin == cs->pOverlayWin) {
144 return Success;
145 }
146
147 if (!pWin->parent)
148 return BadMatch;
149
150 /*
151 * Only one Manual update is allowed
152 */
153 if (cw && update == CompositeRedirectManual)
154 for (ccw = cw->clients; ccw; ccw = ccw->next)
155 if (ccw->update == CompositeRedirectManual)
156 return BadAccess;
157
158 /*
159 * Allocate per-client per-window structure
160 * The client *could* allocate multiple, but while supported,
161 * it is not expected to be common
162 */
163 ccw = malloc(sizeof(CompClientWindowRec));
164 if (!ccw)
165 return BadAlloc;
166 ccw->id = FakeClientID(pClient->index);
167 ccw->update = update;
168 /*
169 * Now make sure there's a per-window structure to hang this from
170 */
171 if (!cw) {
172 cw = malloc(sizeof(CompWindowRec));
173 if (!cw) {
174 free(ccw);
175 return BadAlloc;
176 }
177 cw->damage = DamageCreate(compReportDamage,
178 compDestroyDamage,
179 DamageReportNonEmpty,
180 FALSE, pWin->drawable.pScreen, pWin);
181 if (!cw->damage) {
182 free(ccw);
183 free(cw);
184 return BadAlloc;
185 }
186
187 anyMarked = compMarkWindows(pWin, &pLayerWin);
188
189 RegionNull(&cw->borderClip);
190 cw->update = CompositeRedirectAutomatic;
191 cw->clients = 0;
192 cw->oldx = COMP_ORIGIN_INVALID;
193 cw->oldy = COMP_ORIGIN_INVALID;
194 cw->damageRegistered = FALSE;
195 cw->damaged = FALSE;
196 cw->pOldPixmap = NullPixmap;
197 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
198 }
199 ccw->next = cw->clients;
200 cw->clients = ccw;
201 if (!AddResource(ccw->id, CompositeClientWindowType, pWin))
202 return BadAlloc;
203 if (ccw->update == CompositeRedirectManual) {
204 if (!anyMarked)
205 anyMarked = compMarkWindows(pWin, &pLayerWin);
206
207 if (cw->damageRegistered) {
208 DamageUnregister(cw->damage);
209 cw->damageRegistered = FALSE;
210 }
211 cw->update = CompositeRedirectManual;
212 }
213 else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) {
214 if (!anyMarked)
215 anyMarked = compMarkWindows(pWin, &pLayerWin);
216 }
217
218 if (!compCheckRedirect(pWin)) {
219 FreeResource(ccw->id, RT_NONE);
220 return BadAlloc;
221 }
222
223 if (anyMarked)
224 compHandleMarkedWindows(pWin, pLayerWin);
225
226 return Success;
227 }
228
229 void
230 compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap)
231 {
232 ScreenPtr pScreen = pWin->drawable.pScreen;
233 WindowPtr pParent = pWin->parent;
234
235 if (pParent->drawable.depth == pWin->drawable.depth) {
236 GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
237 int bw = (int) pWin->borderWidth;
238 int x = bw;
239 int y = bw;
240 int w = pWin->drawable.width;
241 int h = pWin->drawable.height;
242
243 if (pGC) {
244 ChangeGCVal val;
245
246 val.val = IncludeInferiors;
247 ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
248 ValidateGC(&pWin->drawable, pGC);
249 (*pGC->ops->CopyArea) (&pPixmap->drawable,
250 &pWin->drawable, pGC, x, y, w, h, 0, 0);
251 FreeScratchGC(pGC);
252 }
253 }
254 }
255
256 /*
257 * Free one of the per-client per-window resources, clearing
258 * redirect and the per-window pointer as appropriate
259 */
260 void
261 compFreeClientWindow(WindowPtr pWin, XID id)
262 {
263 ScreenPtr pScreen = pWin->drawable.pScreen;
264 CompWindowPtr cw = GetCompWindow(pWin);
265 CompClientWindowPtr ccw, *prev;
266 Bool anyMarked = FALSE;
267 WindowPtr pLayerWin;
268 PixmapPtr pPixmap = NULL;
269
270 if (!cw)
271 return;
272 for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) {
273 if (ccw->id == id) {
274 *prev = ccw->next;
275 if (ccw->update == CompositeRedirectManual)
276 cw->update = CompositeRedirectAutomatic;
277 free(ccw);
278 break;
279 }
280 }
281 if (!cw->clients) {
282 anyMarked = compMarkWindows(pWin, &pLayerWin);
283
284 if (pWin->redirectDraw != RedirectDrawNone) {
285 pPixmap = (*pScreen->GetWindowPixmap) (pWin);
286 compSetParentPixmap(pWin);
287 }
288
289 if (cw->damage)
290 DamageDestroy(cw->damage);
291
292 RegionUninit(&cw->borderClip);
293
294 dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
295 free(cw);
296 }
297 else if (cw->update == CompositeRedirectAutomatic &&
298 !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) {
299 anyMarked = compMarkWindows(pWin, &pLayerWin);
300
301 DamageRegister(&pWin->drawable, cw->damage);
302 cw->damageRegistered = TRUE;
303 pWin->redirectDraw = RedirectDrawAutomatic;
304 DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
305 }
306
307 if (anyMarked)
308 compHandleMarkedWindows(pWin, pLayerWin);
309
310 if (pPixmap) {
311 compRestoreWindow(pWin, pPixmap);
312 (*pScreen->DestroyPixmap) (pPixmap);
313 }
314 }
315
316 /*
317 * This is easy, just free the appropriate resource.
318 */
319
320 int
321 compUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
322 {
323 CompWindowPtr cw = GetCompWindow(pWin);
324 CompClientWindowPtr ccw;
325
326 if (!cw)
327 return BadValue;
328
329 for (ccw = cw->clients; ccw; ccw = ccw->next)
330 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
331 FreeResource(ccw->id, RT_NONE);
332 return Success;
333 }
334 return BadValue;
335 }
336
337 /*
338 * Redirect all subwindows for one client
339 */
340
341 int
342 compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
343 {
344 CompSubwindowsPtr csw = GetCompSubwindows(pWin);
345 CompClientWindowPtr ccw;
346 WindowPtr pChild;
347
348 /*
349 * Only one Manual update is allowed
350 */
351 if (csw && update == CompositeRedirectManual)
352 for (ccw = csw->clients; ccw; ccw = ccw->next)
353 if (ccw->update == CompositeRedirectManual)
354 return BadAccess;
355 /*
356 * Allocate per-client per-window structure
357 * The client *could* allocate multiple, but while supported,
358 * it is not expected to be common
359 */
360 ccw = malloc(sizeof(CompClientWindowRec));
361 if (!ccw)
362 return BadAlloc;
363 ccw->id = FakeClientID(pClient->index);
364 ccw->update = update;
365 /*
366 * Now make sure there's a per-window structure to hang this from
367 */
368 if (!csw) {
369 csw = malloc(sizeof(CompSubwindowsRec));
370 if (!csw) {
371 free(ccw);
372 return BadAlloc;
373 }
374 csw->update = CompositeRedirectAutomatic;
375 csw->clients = 0;
376 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
377 }
378 /*
379 * Redirect all existing windows
380 */
381 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) {
382 int ret = compRedirectWindow(pClient, pChild, update);
383
384 if (ret != Success) {
385 for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
386 (void) compUnredirectWindow(pClient, pChild, update);
387 if (!csw->clients) {
388 free(csw);
389 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
390 }
391 free(ccw);
392 return ret;
393 }
394 }
395 /*
396 * Hook into subwindows list
397 */
398 ccw->next = csw->clients;
399 csw->clients = ccw;
400 if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin))
401 return BadAlloc;
402 if (ccw->update == CompositeRedirectManual) {
403 csw->update = CompositeRedirectManual;
404 /*
405 * tell damage extension that damage events for this client are
406 * critical output
407 */
408 DamageExtSetCritical(pClient, TRUE);
409 pWin->inhibitBGPaint = TRUE;
410 }
411 return Success;
412 }
413
414 /*
415 * Free one of the per-client per-subwindows resources,
416 * which frees one redirect per subwindow
417 */
418 void
419 compFreeClientSubwindows(WindowPtr pWin, XID id)
420 {
421 CompSubwindowsPtr csw = GetCompSubwindows(pWin);
422 CompClientWindowPtr ccw, *prev;
423 WindowPtr pChild;
424
425 if (!csw)
426 return;
427 for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) {
428 if (ccw->id == id) {
429 ClientPtr pClient = clients[CLIENT_ID(id)];
430
431 *prev = ccw->next;
432 if (ccw->update == CompositeRedirectManual) {
433 /*
434 * tell damage extension that damage events for this client are
435 * critical output
436 */
437 DamageExtSetCritical(pClient, FALSE);
438 csw->update = CompositeRedirectAutomatic;
439 pWin->inhibitBGPaint = FALSE;
440 if (pWin->mapped)
441 (*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0,
442 0, TRUE);
443 }
444
445 /*
446 * Unredirect all existing subwindows
447 */
448 for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
449 (void) compUnredirectWindow(pClient, pChild, ccw->update);
450
451 free(ccw);
452 break;
453 }
454 }
455
456 /*
457 * Check if all of the per-client records are gone
458 */
459 if (!csw->clients) {
460 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
461 free(csw);
462 }
463 }
464
465 /*
466 * This is easy, just free the appropriate resource.
467 */
468
469 int
470 compUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
471 {
472 CompSubwindowsPtr csw = GetCompSubwindows(pWin);
473 CompClientWindowPtr ccw;
474
475 if (!csw)
476 return BadValue;
477 for (ccw = csw->clients; ccw; ccw = ccw->next)
478 if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
479 FreeResource(ccw->id, RT_NONE);
480 return Success;
481 }
482 return BadValue;
483 }
484
485 /*
486 * Add redirection information for one subwindow (during reparent)
487 */
488
489 int
490 compRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
491 {
492 CompSubwindowsPtr csw = GetCompSubwindows(pParent);
493 CompClientWindowPtr ccw;
494
495 if (!csw)
496 return Success;
497 for (ccw = csw->clients; ccw; ccw = ccw->next) {
498 int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)],
499 pWin, ccw->update);
500
501 if (ret != Success)
502 return ret;
503 }
504 return Success;
505 }
506
507 /*
508 * Remove redirection information for one subwindow (during reparent)
509 */
510
511 int
512 compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
513 {
514 CompSubwindowsPtr csw = GetCompSubwindows(pParent);
515 CompClientWindowPtr ccw;
516
517 if (!csw)
518 return Success;
519 for (ccw = csw->clients; ccw; ccw = ccw->next) {
520 int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)],
521 pWin, ccw->update);
522
523 if (ret != Success)
524 return ret;
525 }
526 return Success;
527 }
528
529 static PixmapPtr
530 compNewPixmap(WindowPtr pWin, int x, int y, int w, int h)
531 {
532 ScreenPtr pScreen = pWin->drawable.pScreen;
533 WindowPtr pParent = pWin->parent;
534 PixmapPtr pPixmap;
535
536 pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
537 CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
538
539 if (!pPixmap)
540 return 0;
541
542 pPixmap->screen_x = x;
543 pPixmap->screen_y = y;
544
545 if (pParent->drawable.depth == pWin->drawable.depth) {
546 GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
547
548 if (pGC) {
549 ChangeGCVal val;
550
551 val.val = IncludeInferiors;
552 ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
553 ValidateGC(&pPixmap->drawable, pGC);
554 (*pGC->ops->CopyArea) (&pParent->drawable,
555 &pPixmap->drawable,
556 pGC,
557 x - pParent->drawable.x,
558 y - pParent->drawable.y, w, h, 0, 0);
559 FreeScratchGC(pGC);
560 }
561 }
562 else {
563 PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
564 PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
565 XID inferiors = IncludeInferiors;
566 int error;
567
568 PicturePtr pSrcPicture = CreatePicture(None,
569 &pParent->drawable,
570 pSrcFormat,
571 CPSubwindowMode,
572 &inferiors,
573 serverClient, &error);
574
575 PicturePtr pDstPicture = CreatePicture(None,
576 &pPixmap->drawable,
577 pDstFormat,
578 0, 0,
579 serverClient, &error);
580
581 if (pSrcPicture && pDstPicture) {
582 CompositePicture(PictOpSrc,
583 pSrcPicture,
584 NULL,
585 pDstPicture,
586 x - pParent->drawable.x,
587 y - pParent->drawable.y, 0, 0, 0, 0, w, h);
588 }
589 if (pSrcPicture)
590 FreePicture(pSrcPicture, 0);
591 if (pDstPicture)
592 FreePicture(pDstPicture, 0);
593 }
594 return pPixmap;
595 }
596
597 Bool
598 compAllocPixmap(WindowPtr pWin)
599 {
600 int bw = (int) pWin->borderWidth;
601 int x = pWin->drawable.x - bw;
602 int y = pWin->drawable.y - bw;
603 int w = pWin->drawable.width + (bw << 1);
604 int h = pWin->drawable.height + (bw << 1);
605 PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h);
606 CompWindowPtr cw = GetCompWindow(pWin);
607
608 if (!pPixmap)
609 return FALSE;
610 if (cw->update == CompositeRedirectAutomatic)
611 pWin->redirectDraw = RedirectDrawAutomatic;
612 else
613 pWin->redirectDraw = RedirectDrawManual;
614
615 compSetPixmap(pWin, pPixmap);
616 cw->oldx = COMP_ORIGIN_INVALID;
617 cw->oldy = COMP_ORIGIN_INVALID;
618 cw->damageRegistered = FALSE;
619 if (cw->update == CompositeRedirectAutomatic) {
620 DamageRegister(&pWin->drawable, cw->damage);
621 cw->damageRegistered = TRUE;
622 }
623
624 /* Make sure our borderClip is up to date */
625 RegionUninit(&cw->borderClip);
626 RegionCopy(&cw->borderClip, &pWin->borderClip);
627 cw->borderClipX = pWin->drawable.x;
628 cw->borderClipY = pWin->drawable.y;
629
630 return TRUE;
631 }
632
633 void
634 compSetParentPixmap(WindowPtr pWin)
635 {
636 ScreenPtr pScreen = pWin->drawable.pScreen;
637 PixmapPtr pParentPixmap;
638 CompWindowPtr cw = GetCompWindow(pWin);
639
640 if (cw->damageRegistered) {
641 DamageUnregister(cw->damage);
642 cw->damageRegistered = FALSE;
643 DamageEmpty(cw->damage);
644 }
645 /*
646 * Move the parent-constrained border clip region back into
647 * the window so that ValidateTree will handle the unmap
648 * case correctly. Unmap adds the window borderClip to the
649 * parent exposed area; regions beyond the parent cause crashes
650 */
651 RegionCopy(&pWin->borderClip, &cw->borderClip);
652 pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
653 pWin->redirectDraw = RedirectDrawNone;
654 compSetPixmap(pWin, pParentPixmap);
655 }
656
657 /*
658 * Make sure the pixmap is the right size and offset. Allocate a new
659 * pixmap to change size, adjust origin to change offset, leaving the
660 * old pixmap in cw->pOldPixmap so bits can be recovered
661 */
662 Bool
663 compReallocPixmap(WindowPtr pWin, int draw_x, int draw_y,
664 unsigned int w, unsigned int h, int bw)
665 {
666 ScreenPtr pScreen = pWin->drawable.pScreen;
667 PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
668 PixmapPtr pNew;
669 CompWindowPtr cw = GetCompWindow(pWin);
670 int pix_x, pix_y;
671 int pix_w, pix_h;
672
673 assert(cw && pWin->redirectDraw != RedirectDrawNone);
674 cw->oldx = pOld->screen_x;
675 cw->oldy = pOld->screen_y;
676 pix_x = draw_x - bw;
677 pix_y = draw_y - bw;
678 pix_w = w + (bw << 1);
679 pix_h = h + (bw << 1);
680 if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) {
681 pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h);
682 if (!pNew)
683 return FALSE;
684 cw->pOldPixmap = pOld;
685 compSetPixmap(pWin, pNew);
686 }
687 else {
688 pNew = pOld;
689 cw->pOldPixmap = 0;
690 }
691 pNew->screen_x = pix_x;
692 pNew->screen_y = pix_y;
693 return TRUE;
694 }