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