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 #ifdef PANORAMIX
51 #include "panoramiXsrv.h"
52 #endif
53 
54 #ifdef COMPOSITE_DEBUG
55 static int
compCheckWindow(WindowPtr pWin,void * data)56 compCheckWindow(WindowPtr pWin, void *data)
57 {
58     ScreenPtr pScreen = pWin->drawable.pScreen;
59     PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin);
60     PixmapPtr pParentPixmap =
61         pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0;
62     PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
63 
64     if (!pWin->parent) {
65         assert(pWin->redirectDraw == RedirectDrawNone);
66         assert(pWinPixmap == pScreenPixmap);
67     }
68     else if (pWin->redirectDraw != RedirectDrawNone) {
69         assert(pWinPixmap != pParentPixmap);
70         assert(pWinPixmap != pScreenPixmap);
71     }
72     else {
73         assert(pWinPixmap == pParentPixmap);
74     }
75     assert(0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3);
76     assert(0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3);
77     if (pParentPixmap)
78         assert(0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3);
79     return WT_WALKCHILDREN;
80 }
81 
82 void
compCheckTree(ScreenPtr pScreen)83 compCheckTree(ScreenPtr pScreen)
84 {
85     WalkTree(pScreen, compCheckWindow, 0);
86 }
87 #endif
88 
89 typedef struct _compPixmapVisit {
90     WindowPtr pWindow;
91     PixmapPtr pPixmap;
92     int bw;
93 } CompPixmapVisitRec, *CompPixmapVisitPtr;
94 
95 static Bool
compRepaintBorder(ClientPtr pClient,void * closure)96 compRepaintBorder(ClientPtr pClient, void *closure)
97 {
98     WindowPtr pWindow;
99     int rc =
100         dixLookupWindow(&pWindow, (XID) (intptr_t) closure, pClient,
101                         DixWriteAccess);
102 
103     if (rc == Success) {
104         RegionRec exposed;
105 
106         RegionNull(&exposed);
107         RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
108         pWindow->drawable.pScreen->PaintWindow(pWindow, &exposed, PW_BORDER);
109         RegionUninit(&exposed);
110     }
111     return TRUE;
112 }
113 
114 static int
compSetPixmapVisitWindow(WindowPtr pWindow,void * data)115 compSetPixmapVisitWindow(WindowPtr pWindow, void *data)
116 {
117     CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data;
118     ScreenPtr pScreen = pWindow->drawable.pScreen;
119 
120     if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone)
121         return WT_DONTWALKCHILDREN;
122     (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap);
123     /*
124      * Recompute winSize and borderSize.  This is duplicate effort
125      * when resizing pixmaps, but necessary when changing redirection.
126      * Might be nice to fix this.
127      */
128     SetWinSize(pWindow);
129     SetBorderSize(pWindow);
130     if (pVisit->bw)
131         QueueWorkProc(compRepaintBorder, serverClient,
132                       (void *) (intptr_t) pWindow->drawable.id);
133     return WT_WALKCHILDREN;
134 }
135 
136 void
compSetPixmap(WindowPtr pWindow,PixmapPtr pPixmap,int bw)137 compSetPixmap(WindowPtr pWindow, PixmapPtr pPixmap, int bw)
138 {
139     CompPixmapVisitRec visitRec;
140 
141     visitRec.pWindow = pWindow;
142     visitRec.pPixmap = pPixmap;
143     visitRec.bw = bw;
144     TraverseTree(pWindow, compSetPixmapVisitWindow, (void *) &visitRec);
145     compCheckTree(pWindow->drawable.pScreen);
146 }
147 
148 Bool
compCheckRedirect(WindowPtr pWin)149 compCheckRedirect(WindowPtr pWin)
150 {
151     CompWindowPtr cw = GetCompWindow(pWin);
152     CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
153     Bool should;
154 
155     should = pWin->realized && (pWin->drawable.class != InputOnly) &&
156         (cw != NULL) && (pWin->parent != NULL);
157 
158     /* Never redirect the overlay window */
159     if (cs->pOverlayWin != NULL) {
160         if (pWin == cs->pOverlayWin) {
161             should = FALSE;
162         }
163     }
164 
165     if (should != (pWin->redirectDraw != RedirectDrawNone)) {
166         if (should)
167             return compAllocPixmap(pWin);
168         else {
169             ScreenPtr pScreen = pWin->drawable.pScreen;
170             PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
171 
172             compSetParentPixmap(pWin);
173             compRestoreWindow(pWin, pPixmap);
174             (*pScreen->DestroyPixmap) (pPixmap);
175         }
176     }
177     else if (should) {
178         if (cw->update == CompositeRedirectAutomatic)
179             pWin->redirectDraw = RedirectDrawAutomatic;
180         else
181             pWin->redirectDraw = RedirectDrawManual;
182     }
183     return TRUE;
184 }
185 
186 static int
updateOverlayWindow(ScreenPtr pScreen)187 updateOverlayWindow(ScreenPtr pScreen)
188 {
189     CompScreenPtr cs;
190     WindowPtr pWin;             /* overlay window */
191     XID vlist[2];
192     int w = pScreen->width;
193     int h = pScreen->height;
194 
195 #ifdef PANORAMIX
196     if (!noPanoramiXExtension) {
197         w = PanoramiXPixWidth;
198         h = PanoramiXPixHeight;
199     }
200 #endif
201 
202     cs = GetCompScreen(pScreen);
203     if ((pWin = cs->pOverlayWin) != NULL) {
204         if ((pWin->drawable.width == w) && (pWin->drawable.height == h))
205             return Success;
206 
207         /* Let's resize the overlay window. */
208         vlist[0] = w;
209         vlist[1] = h;
210         return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin));
211     }
212 
213     /* Let's be on the safe side and not assume an overlay window is
214        always allocated. */
215     return Success;
216 }
217 
218 Bool
compPositionWindow(WindowPtr pWin,int x,int y)219 compPositionWindow(WindowPtr pWin, int x, int y)
220 {
221     ScreenPtr pScreen = pWin->drawable.pScreen;
222     CompScreenPtr cs = GetCompScreen(pScreen);
223     Bool ret = TRUE;
224 
225     pScreen->PositionWindow = cs->PositionWindow;
226     /*
227      * "Shouldn't need this as all possible places should be wrapped
228      *
229      compCheckRedirect (pWin);
230      */
231 #ifdef COMPOSITE_DEBUG
232     if ((pWin->redirectDraw != RedirectDrawNone) !=
233         (pWin->viewable && (GetCompWindow(pWin) != NULL)))
234         OsAbort();
235 #endif
236     if (pWin->redirectDraw != RedirectDrawNone) {
237         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
238         int bw = wBorderWidth(pWin);
239         int nx = pWin->drawable.x - bw;
240         int ny = pWin->drawable.y - bw;
241 
242         if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) {
243             pPixmap->screen_x = nx;
244             pPixmap->screen_y = ny;
245             pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
246         }
247     }
248 
249     if (!(*pScreen->PositionWindow) (pWin, x, y))
250         ret = FALSE;
251     cs->PositionWindow = pScreen->PositionWindow;
252     pScreen->PositionWindow = compPositionWindow;
253     compCheckTree(pWin->drawable.pScreen);
254     if (updateOverlayWindow(pScreen) != Success)
255         ret = FALSE;
256     return ret;
257 }
258 
259 Bool
compRealizeWindow(WindowPtr pWin)260 compRealizeWindow(WindowPtr pWin)
261 {
262     ScreenPtr pScreen = pWin->drawable.pScreen;
263     CompScreenPtr cs = GetCompScreen(pScreen);
264     Bool ret = TRUE;
265 
266     pScreen->RealizeWindow = cs->RealizeWindow;
267     compCheckRedirect(pWin);
268     if (!(*pScreen->RealizeWindow) (pWin))
269         ret = FALSE;
270     cs->RealizeWindow = pScreen->RealizeWindow;
271     pScreen->RealizeWindow = compRealizeWindow;
272     compCheckTree(pWin->drawable.pScreen);
273     return ret;
274 }
275 
276 Bool
compUnrealizeWindow(WindowPtr pWin)277 compUnrealizeWindow(WindowPtr pWin)
278 {
279     ScreenPtr pScreen = pWin->drawable.pScreen;
280     CompScreenPtr cs = GetCompScreen(pScreen);
281     Bool ret = TRUE;
282 
283     pScreen->UnrealizeWindow = cs->UnrealizeWindow;
284     compCheckRedirect(pWin);
285     if (!(*pScreen->UnrealizeWindow) (pWin))
286         ret = FALSE;
287     cs->UnrealizeWindow = pScreen->UnrealizeWindow;
288     pScreen->UnrealizeWindow = compUnrealizeWindow;
289     compCheckTree(pWin->drawable.pScreen);
290     return ret;
291 }
292 
293 /*
294  * Called after the borderClip for the window has settled down
295  * We use this to make sure our extra borderClip has the right origin
296  */
297 
298 void
compClipNotify(WindowPtr pWin,int dx,int dy)299 compClipNotify(WindowPtr pWin, int dx, int dy)
300 {
301     ScreenPtr pScreen = pWin->drawable.pScreen;
302     CompScreenPtr cs = GetCompScreen(pScreen);
303     CompWindowPtr cw = GetCompWindow(pWin);
304 
305     if (cw) {
306         if (cw->borderClipX != pWin->drawable.x ||
307             cw->borderClipY != pWin->drawable.y) {
308             RegionTranslate(&cw->borderClip,
309                             pWin->drawable.x - cw->borderClipX,
310                             pWin->drawable.y - cw->borderClipY);
311             cw->borderClipX = pWin->drawable.x;
312             cw->borderClipY = pWin->drawable.y;
313         }
314     }
315     if (cs->ClipNotify) {
316         pScreen->ClipNotify = cs->ClipNotify;
317         (*pScreen->ClipNotify) (pWin, dx, dy);
318         cs->ClipNotify = pScreen->ClipNotify;
319         pScreen->ClipNotify = compClipNotify;
320     }
321 }
322 
323 Bool
compIsAlternateVisual(ScreenPtr pScreen,XID visual)324 compIsAlternateVisual(ScreenPtr pScreen, XID visual)
325 {
326     CompScreenPtr cs = GetCompScreen(pScreen);
327     int i;
328 
329     for (i = 0; cs && i < cs->numAlternateVisuals; i++)
330         if (cs->alternateVisuals[i] == visual)
331             return TRUE;
332     return FALSE;
333 }
334 
335 static Bool
compIsImplicitRedirectException(ScreenPtr pScreen,XID parentVisual,XID winVisual)336 compIsImplicitRedirectException(ScreenPtr pScreen,
337                                 XID parentVisual, XID winVisual)
338 {
339     CompScreenPtr cs = GetCompScreen(pScreen);
340     int i;
341 
342     for (i = 0; i < cs->numImplicitRedirectExceptions; i++)
343         if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual &&
344             cs->implicitRedirectExceptions[i].winVisual == winVisual)
345             return TRUE;
346 
347     return FALSE;
348 }
349 
350 static Bool
compImplicitRedirect(WindowPtr pWin,WindowPtr pParent)351 compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
352 {
353     if (pParent) {
354         ScreenPtr pScreen = pWin->drawable.pScreen;
355         XID winVisual = wVisual(pWin);
356         XID parentVisual = wVisual(pParent);
357 
358         if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual))
359             return FALSE;
360 
361         if (winVisual != parentVisual &&
362             (compIsAlternateVisual(pScreen, winVisual) ||
363              compIsAlternateVisual(pScreen, parentVisual)))
364             return TRUE;
365     }
366     return FALSE;
367 }
368 
369 static void
compFreeOldPixmap(WindowPtr pWin)370 compFreeOldPixmap(WindowPtr pWin)
371 {
372     ScreenPtr pScreen = pWin->drawable.pScreen;
373 
374     if (pWin->redirectDraw != RedirectDrawNone) {
375         CompWindowPtr cw = GetCompWindow(pWin);
376 
377         if (cw->pOldPixmap) {
378             (*pScreen->DestroyPixmap) (cw->pOldPixmap);
379             cw->pOldPixmap = NullPixmap;
380         }
381     }
382 }
383 
384 void
compMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind)385 compMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
386 {
387     ScreenPtr pScreen = pWin->drawable.pScreen;
388     CompScreenPtr cs = GetCompScreen(pScreen);
389 
390     pScreen->MoveWindow = cs->MoveWindow;
391     (*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
392     cs->MoveWindow = pScreen->MoveWindow;
393     pScreen->MoveWindow = compMoveWindow;
394 
395     compFreeOldPixmap(pWin);
396     compCheckTree(pScreen);
397 }
398 
399 void
compResizeWindow(WindowPtr pWin,int x,int y,unsigned int w,unsigned int h,WindowPtr pSib)400 compResizeWindow(WindowPtr pWin, int x, int y,
401                  unsigned int w, unsigned int h, WindowPtr pSib)
402 {
403     ScreenPtr pScreen = pWin->drawable.pScreen;
404     CompScreenPtr cs = GetCompScreen(pScreen);
405 
406     pScreen->ResizeWindow = cs->ResizeWindow;
407     (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
408     cs->ResizeWindow = pScreen->ResizeWindow;
409     pScreen->ResizeWindow = compResizeWindow;
410 
411     compFreeOldPixmap(pWin);
412     compCheckTree(pWin->drawable.pScreen);
413 }
414 
415 void
compChangeBorderWidth(WindowPtr pWin,unsigned int bw)416 compChangeBorderWidth(WindowPtr pWin, unsigned int bw)
417 {
418     ScreenPtr pScreen = pWin->drawable.pScreen;
419     CompScreenPtr cs = GetCompScreen(pScreen);
420 
421     pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
422     (*pScreen->ChangeBorderWidth) (pWin, bw);
423     cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
424     pScreen->ChangeBorderWidth = compChangeBorderWidth;
425 
426     compFreeOldPixmap(pWin);
427     compCheckTree(pWin->drawable.pScreen);
428 }
429 
430 void
compReparentWindow(WindowPtr pWin,WindowPtr pPriorParent)431 compReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
432 {
433     ScreenPtr pScreen = pWin->drawable.pScreen;
434     CompScreenPtr cs = GetCompScreen(pScreen);
435     CompWindowPtr cw;
436 
437     pScreen->ReparentWindow = cs->ReparentWindow;
438     /*
439      * Remove any implicit redirect due to synthesized visual
440      */
441     if (compImplicitRedirect(pWin, pPriorParent))
442         compUnredirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
443     /*
444      * Handle subwindows redirection
445      */
446     compUnredirectOneSubwindow(pPriorParent, pWin);
447     compRedirectOneSubwindow(pWin->parent, pWin);
448     /*
449      * Add any implict redirect due to synthesized visual
450      */
451     if (compImplicitRedirect(pWin, pWin->parent))
452         compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
453 
454     /*
455      * Allocate any necessary redirect pixmap
456      * (this actually should never be true; pWin is always unmapped)
457      */
458     compCheckRedirect(pWin);
459 
460     /*
461      * Reset pixmap pointers as appropriate
462      */
463     if (pWin->parent && pWin->redirectDraw == RedirectDrawNone)
464         compSetPixmap(pWin, (*pScreen->GetWindowPixmap) (pWin->parent),
465                       pWin->borderWidth);
466     /*
467      * Call down to next function
468      */
469     if (pScreen->ReparentWindow)
470         (*pScreen->ReparentWindow) (pWin, pPriorParent);
471     cs->ReparentWindow = pScreen->ReparentWindow;
472     pScreen->ReparentWindow = compReparentWindow;
473 
474     cw = GetCompWindow(pWin);
475     if (pWin->damagedDescendants || (cw && cw->damaged))
476         compMarkAncestors(pWin);
477 
478     compCheckTree(pWin->drawable.pScreen);
479 }
480 
481 void
compCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc)482 compCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
483 {
484     ScreenPtr pScreen = pWin->drawable.pScreen;
485     CompScreenPtr cs = GetCompScreen(pScreen);
486     int dx = 0, dy = 0;
487 
488     if (pWin->redirectDraw != RedirectDrawNone) {
489         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
490         CompWindowPtr cw = GetCompWindow(pWin);
491 
492         assert(cw->oldx != COMP_ORIGIN_INVALID);
493         assert(cw->oldy != COMP_ORIGIN_INVALID);
494         if (cw->pOldPixmap) {
495             /*
496              * Ok, the old bits are available in pOldPixmap and
497              * need to be copied to pNewPixmap.
498              */
499             RegionRec rgnDst;
500             GCPtr pGC;
501 
502             dx = ptOldOrg.x - pWin->drawable.x;
503             dy = ptOldOrg.y - pWin->drawable.y;
504             RegionTranslate(prgnSrc, -dx, -dy);
505 
506             RegionNull(&rgnDst);
507 
508             RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
509 
510             RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y);
511 
512             dx = dx + pPixmap->screen_x - cw->oldx;
513             dy = dy + pPixmap->screen_y - cw->oldy;
514             pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
515             if (pGC) {
516                 BoxPtr pBox = RegionRects(&rgnDst);
517                 int nBox = RegionNumRects(&rgnDst);
518 
519                 ValidateGC(&pPixmap->drawable, pGC);
520                 while (nBox--) {
521                     (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
522                                                   &pPixmap->drawable,
523                                                   pGC,
524                                                   pBox->x1 + dx, pBox->y1 + dy,
525                                                   pBox->x2 - pBox->x1,
526                                                   pBox->y2 - pBox->y1,
527                                                   pBox->x1, pBox->y1);
528                     pBox++;
529                 }
530                 FreeScratchGC(pGC);
531             }
532             RegionUninit(&rgnDst);
533             return;
534         }
535         dx = pPixmap->screen_x - cw->oldx;
536         dy = pPixmap->screen_y - cw->oldy;
537         ptOldOrg.x += dx;
538         ptOldOrg.y += dy;
539     }
540 
541     pScreen->CopyWindow = cs->CopyWindow;
542     if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y) {
543         if (dx || dy)
544             RegionTranslate(prgnSrc, dx, dy);
545         (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
546         if (dx || dy)
547             RegionTranslate(prgnSrc, -dx, -dy);
548     }
549     else {
550         ptOldOrg.x -= dx;
551         ptOldOrg.y -= dy;
552         RegionTranslate(prgnSrc,
553                         pWin->drawable.x - ptOldOrg.x,
554                         pWin->drawable.y - ptOldOrg.y);
555         DamageDamageRegion(&pWin->drawable, prgnSrc);
556     }
557     cs->CopyWindow = pScreen->CopyWindow;
558     pScreen->CopyWindow = compCopyWindow;
559     compCheckTree(pWin->drawable.pScreen);
560 }
561 
562 Bool
compCreateWindow(WindowPtr pWin)563 compCreateWindow(WindowPtr pWin)
564 {
565     ScreenPtr pScreen = pWin->drawable.pScreen;
566     CompScreenPtr cs = GetCompScreen(pScreen);
567     Bool ret;
568 
569     pScreen->CreateWindow = cs->CreateWindow;
570     ret = (*pScreen->CreateWindow) (pWin);
571     if (pWin->parent && ret) {
572         CompSubwindowsPtr csw = GetCompSubwindows(pWin->parent);
573         CompClientWindowPtr ccw;
574         PixmapPtr parent_pixmap = (*pScreen->GetWindowPixmap)(pWin->parent);
575         PixmapPtr window_pixmap = (*pScreen->GetWindowPixmap)(pWin);
576 
577         if (window_pixmap != parent_pixmap)
578             (*pScreen->SetWindowPixmap) (pWin, parent_pixmap);
579         if (csw)
580             for (ccw = csw->clients; ccw; ccw = ccw->next)
581                 compRedirectWindow(clients[CLIENT_ID(ccw->id)],
582                                    pWin, ccw->update);
583         if (compImplicitRedirect(pWin, pWin->parent))
584             compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
585     }
586     cs->CreateWindow = pScreen->CreateWindow;
587     pScreen->CreateWindow = compCreateWindow;
588     compCheckTree(pWin->drawable.pScreen);
589     return ret;
590 }
591 
592 Bool
compDestroyWindow(WindowPtr pWin)593 compDestroyWindow(WindowPtr pWin)
594 {
595     ScreenPtr pScreen = pWin->drawable.pScreen;
596     CompScreenPtr cs = GetCompScreen(pScreen);
597     CompWindowPtr cw;
598     CompSubwindowsPtr csw;
599     Bool ret;
600 
601     pScreen->DestroyWindow = cs->DestroyWindow;
602     while ((cw = GetCompWindow(pWin)))
603         FreeResource(cw->clients->id, RT_NONE);
604     while ((csw = GetCompSubwindows(pWin)))
605         FreeResource(csw->clients->id, RT_NONE);
606 
607     if (pWin->redirectDraw != RedirectDrawNone) {
608         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
609 
610         compSetParentPixmap(pWin);
611         (*pScreen->DestroyPixmap) (pPixmap);
612     }
613     ret = (*pScreen->DestroyWindow) (pWin);
614     cs->DestroyWindow = pScreen->DestroyWindow;
615     pScreen->DestroyWindow = compDestroyWindow;
616 /*    compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
617     return ret;
618 }
619 
620 void
compSetRedirectBorderClip(WindowPtr pWin,RegionPtr pRegion)621 compSetRedirectBorderClip(WindowPtr pWin, RegionPtr pRegion)
622 {
623     CompWindowPtr cw = GetCompWindow(pWin);
624     RegionRec damage;
625 
626     RegionNull(&damage);
627     /*
628      * Align old border clip with new border clip
629      */
630     RegionTranslate(&cw->borderClip,
631                     pWin->drawable.x - cw->borderClipX,
632                     pWin->drawable.y - cw->borderClipY);
633     /*
634      * Compute newly visible portion of window for repaint
635      */
636     RegionSubtract(&damage, pRegion, &cw->borderClip);
637     /*
638      * Report that as damaged so it will be redrawn
639      */
640     DamageDamageRegion(&pWin->drawable, &damage);
641     RegionUninit(&damage);
642     /*
643      * Save the new border clip region
644      */
645     RegionCopy(&cw->borderClip, pRegion);
646     cw->borderClipX = pWin->drawable.x;
647     cw->borderClipY = pWin->drawable.y;
648 }
649 
650 RegionPtr
compGetRedirectBorderClip(WindowPtr pWin)651 compGetRedirectBorderClip(WindowPtr pWin)
652 {
653     CompWindowPtr cw = GetCompWindow(pWin);
654 
655     return &cw->borderClip;
656 }
657 
658 static void
compWindowUpdateAutomatic(WindowPtr pWin)659 compWindowUpdateAutomatic(WindowPtr pWin)
660 {
661     CompWindowPtr cw = GetCompWindow(pWin);
662     ScreenPtr pScreen = pWin->drawable.pScreen;
663     WindowPtr pParent = pWin->parent;
664     PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
665     PictFormatPtr pSrcFormat = PictureWindowFormat(pWin);
666     PictFormatPtr pDstFormat = PictureWindowFormat(pWin->parent);
667     int error;
668     RegionPtr pRegion = DamageRegion(cw->damage);
669     PicturePtr pSrcPicture = CreatePicture(0, &pSrcPixmap->drawable,
670                                            pSrcFormat,
671                                            0, 0,
672                                            serverClient,
673                                            &error);
674     XID subwindowMode = IncludeInferiors;
675     PicturePtr pDstPicture = CreatePicture(0, &pParent->drawable,
676                                            pDstFormat,
677                                            CPSubwindowMode,
678                                            &subwindowMode,
679                                            serverClient,
680                                            &error);
681 
682     /*
683      * First move the region from window to screen coordinates
684      */
685     RegionTranslate(pRegion, pWin->drawable.x, pWin->drawable.y);
686 
687     /*
688      * Clip against the "real" border clip
689      */
690     RegionIntersect(pRegion, pRegion, &cw->borderClip);
691 
692     /*
693      * Now translate from screen to dest coordinates
694      */
695     RegionTranslate(pRegion, -pParent->drawable.x, -pParent->drawable.y);
696 
697     /*
698      * Clip the picture
699      */
700     SetPictureClipRegion(pDstPicture, 0, 0, pRegion);
701 
702     /*
703      * And paint
704      */
705     CompositePicture(PictOpSrc, pSrcPicture, 0, pDstPicture,
706                      0, 0,      /* src_x, src_y */
707                      0, 0,      /* msk_x, msk_y */
708                      pSrcPixmap->screen_x - pParent->drawable.x,
709                      pSrcPixmap->screen_y - pParent->drawable.y,
710                      pSrcPixmap->drawable.width, pSrcPixmap->drawable.height);
711     FreePicture(pSrcPicture, 0);
712     FreePicture(pDstPicture, 0);
713     /*
714      * Empty the damage region.  This has the nice effect of
715      * rendering the translations above harmless
716      */
717     DamageEmpty(cw->damage);
718 }
719 
720 static void
compPaintWindowToParent(WindowPtr pWin)721 compPaintWindowToParent(WindowPtr pWin)
722 {
723     compPaintChildrenToWindow(pWin);
724 
725     if (pWin->redirectDraw != RedirectDrawNone) {
726         CompWindowPtr cw = GetCompWindow(pWin);
727 
728         if (cw->damaged) {
729             compWindowUpdateAutomatic(pWin);
730             cw->damaged = FALSE;
731         }
732     }
733 }
734 
735 void
compPaintChildrenToWindow(WindowPtr pWin)736 compPaintChildrenToWindow(WindowPtr pWin)
737 {
738     WindowPtr pChild;
739 
740     if (!pWin->damagedDescendants)
741         return;
742 
743     for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
744         compPaintWindowToParent(pChild);
745 
746     pWin->damagedDescendants = FALSE;
747 }
748 
749 WindowPtr
CompositeRealChildHead(WindowPtr pWin)750 CompositeRealChildHead(WindowPtr pWin)
751 {
752     WindowPtr pChild, pChildBefore;
753     CompScreenPtr cs;
754 
755     if (!pWin->parent &&
756         (screenIsSaved == SCREEN_SAVER_ON) &&
757         (HasSaverWindow(pWin->drawable.pScreen))) {
758 
759         /* First child is the screen saver; see if next child is the overlay */
760         pChildBefore = pWin->firstChild;
761         pChild = pChildBefore->nextSib;
762 
763     }
764     else {
765         pChildBefore = NullWindow;
766         pChild = pWin->firstChild;
767     }
768 
769     if (!pChild) {
770         return NullWindow;
771     }
772 
773     cs = GetCompScreen(pWin->drawable.pScreen);
774     if (pChild == cs->pOverlayWin) {
775         return pChild;
776     }
777     else {
778         return pChildBefore;
779     }
780 }
781 
782 int
compConfigNotify(WindowPtr pWin,int x,int y,int w,int h,int bw,WindowPtr pSib)783 compConfigNotify(WindowPtr pWin, int x, int y, int w, int h,
784                  int bw, WindowPtr pSib)
785 {
786     ScreenPtr pScreen = pWin->drawable.pScreen;
787     CompScreenPtr cs = GetCompScreen(pScreen);
788     Bool ret = 0;
789     WindowPtr pParent = pWin->parent;
790     int draw_x, draw_y;
791     Bool alloc_ret;
792 
793     if (cs->ConfigNotify) {
794         pScreen->ConfigNotify = cs->ConfigNotify;
795         ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib);
796         cs->ConfigNotify = pScreen->ConfigNotify;
797         pScreen->ConfigNotify = compConfigNotify;
798 
799         if (ret)
800             return ret;
801     }
802 
803     if (pWin->redirectDraw == RedirectDrawNone)
804         return Success;
805 
806     compCheckTree(pScreen);
807 
808     draw_x = pParent->drawable.x + x + bw;
809     draw_y = pParent->drawable.y + y + bw;
810     alloc_ret = compReallocPixmap(pWin, draw_x, draw_y, w, h, bw);
811 
812     if (alloc_ret == FALSE)
813         return BadAlloc;
814     return Success;
815 }
816