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