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