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