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