1706f2543Smrg/*
2706f2543Smrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
3706f2543Smrg *
4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5706f2543Smrg * copy of this software and associated documentation files (the "Software"),
6706f2543Smrg * to deal in the Software without restriction, including without limitation
7706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
9706f2543Smrg * Software is furnished to do so, subject to the following conditions:
10706f2543Smrg *
11706f2543Smrg * The above copyright notice and this permission notice (including the next
12706f2543Smrg * paragraph) shall be included in all copies or substantial portions of the
13706f2543Smrg * Software.
14706f2543Smrg *
15706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18706f2543Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19706f2543Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20706f2543Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21706f2543Smrg * DEALINGS IN THE SOFTWARE.
22706f2543Smrg *
23706f2543Smrg * Copyright © 2003 Keith Packard
24706f2543Smrg *
25706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
26706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
27706f2543Smrg * the above copyright notice appear in all copies and that both that
28706f2543Smrg * copyright notice and this permission notice appear in supporting
29706f2543Smrg * documentation, and that the name of Keith Packard not be used in
30706f2543Smrg * advertising or publicity pertaining to distribution of the software without
31706f2543Smrg * specific, written prior permission.  Keith Packard makes no
32706f2543Smrg * representations about the suitability of this software for any purpose.  It
33706f2543Smrg * is provided "as is" without express or implied warranty.
34706f2543Smrg *
35706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
36706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
37706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
38706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
39706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
40706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
41706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
42706f2543Smrg */
43706f2543Smrg
44706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
45706f2543Smrg#include <dix-config.h>
46706f2543Smrg#endif
47706f2543Smrg
48706f2543Smrg#include "compint.h"
49706f2543Smrg
50706f2543Smrg#ifdef PANORAMIX
51706f2543Smrg#include "panoramiXsrv.h"
52706f2543Smrg#endif
53706f2543Smrg
54706f2543Smrg#ifdef COMPOSITE_DEBUG
55706f2543Smrgstatic int
56706f2543SmrgcompCheckWindow (WindowPtr pWin, pointer data)
57706f2543Smrg{
58706f2543Smrg    ScreenPtr	pScreen = pWin->drawable.pScreen;
59706f2543Smrg    PixmapPtr	pWinPixmap = (*pScreen->GetWindowPixmap) (pWin);
60706f2543Smrg    PixmapPtr	pParentPixmap = pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0;
61706f2543Smrg    PixmapPtr	pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
62706f2543Smrg
63706f2543Smrg    if (!pWin->parent)
64706f2543Smrg    {
65706f2543Smrg	assert (pWin->redirectDraw == RedirectDrawNone);
66706f2543Smrg	assert (pWinPixmap == pScreenPixmap);
67706f2543Smrg    }
68706f2543Smrg    else if (pWin->redirectDraw != RedirectDrawNone)
69706f2543Smrg    {
70706f2543Smrg	assert (pWinPixmap != pParentPixmap);
71706f2543Smrg	assert (pWinPixmap != pScreenPixmap);
72706f2543Smrg    }
73706f2543Smrg    else
74706f2543Smrg    {
75706f2543Smrg	assert (pWinPixmap == pParentPixmap);
76706f2543Smrg    }
77706f2543Smrg    assert (0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3);
78706f2543Smrg    assert (0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3);
79706f2543Smrg    if (pParentPixmap)
80706f2543Smrg	assert (0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3);
81706f2543Smrg    return WT_WALKCHILDREN;
82706f2543Smrg}
83706f2543Smrg
84706f2543Smrgvoid
85706f2543SmrgcompCheckTree (ScreenPtr pScreen)
86706f2543Smrg{
87706f2543Smrg    WalkTree (pScreen, compCheckWindow, 0);
88706f2543Smrg}
89706f2543Smrg#endif
90706f2543Smrg
91706f2543Smrgtypedef struct _compPixmapVisit {
92706f2543Smrg    WindowPtr	pWindow;
93706f2543Smrg    PixmapPtr	pPixmap;
94706f2543Smrg} CompPixmapVisitRec, *CompPixmapVisitPtr;
95706f2543Smrg
96706f2543Smrgstatic Bool
97706f2543SmrgcompRepaintBorder (ClientPtr pClient, pointer closure)
98706f2543Smrg{
99706f2543Smrg    WindowPtr pWindow;
100706f2543Smrg    int rc = dixLookupWindow(&pWindow, (XID)(intptr_t)closure, pClient, DixWriteAccess);
101706f2543Smrg
102706f2543Smrg    if (rc == Success) {
103706f2543Smrg	RegionRec exposed;
104706f2543Smrg
105706f2543Smrg	RegionNull(&exposed);
106706f2543Smrg	RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
107706f2543Smrg	miPaintWindow(pWindow, &exposed, PW_BORDER);
108706f2543Smrg	RegionUninit(&exposed);
109706f2543Smrg    }
110706f2543Smrg    return TRUE;
111706f2543Smrg}
112706f2543Smrg
113706f2543Smrgstatic int
114706f2543SmrgcompSetPixmapVisitWindow (WindowPtr pWindow, pointer data)
115706f2543Smrg{
116706f2543Smrg    CompPixmapVisitPtr	pVisit = (CompPixmapVisitPtr) data;
117706f2543Smrg    ScreenPtr		pScreen = pWindow->drawable.pScreen;
118706f2543Smrg
119706f2543Smrg    if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone)
120706f2543Smrg	return WT_DONTWALKCHILDREN;
121706f2543Smrg    (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap);
122706f2543Smrg    /*
123706f2543Smrg     * Recompute winSize and borderSize.  This is duplicate effort
124706f2543Smrg     * when resizing pixmaps, but necessary when changing redirection.
125706f2543Smrg     * Might be nice to fix this.
126706f2543Smrg     */
127706f2543Smrg    SetWinSize (pWindow);
128706f2543Smrg    SetBorderSize (pWindow);
129706f2543Smrg    if (HasBorder (pWindow))
130706f2543Smrg	QueueWorkProc (compRepaintBorder, serverClient,
131706f2543Smrg		       (pointer)(intptr_t) pWindow->drawable.id);
132706f2543Smrg    return WT_WALKCHILDREN;
133706f2543Smrg}
134706f2543Smrg
135706f2543Smrgvoid
136706f2543SmrgcompSetPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
137706f2543Smrg{
138706f2543Smrg    CompPixmapVisitRec	visitRec;
139706f2543Smrg
140706f2543Smrg    visitRec.pWindow = pWindow;
141706f2543Smrg    visitRec.pPixmap = pPixmap;
142706f2543Smrg    TraverseTree (pWindow, compSetPixmapVisitWindow, (pointer) &visitRec);
143706f2543Smrg    compCheckTree (pWindow->drawable.pScreen);
144706f2543Smrg}
145706f2543Smrg
146706f2543SmrgBool
147706f2543SmrgcompCheckRedirect (WindowPtr pWin)
148706f2543Smrg{
149706f2543Smrg    CompWindowPtr   cw = GetCompWindow (pWin);
150706f2543Smrg    CompScreenPtr   cs = GetCompScreen(pWin->drawable.pScreen);
151706f2543Smrg    Bool	    should;
152706f2543Smrg
153706f2543Smrg    should = pWin->realized && (pWin->drawable.class != InputOnly) &&
154706f2543Smrg	     (cw != NULL) && (pWin->parent != NULL);
155706f2543Smrg
156706f2543Smrg    /* Never redirect the overlay window */
157706f2543Smrg    if (cs->pOverlayWin != NULL) {
158706f2543Smrg	if (pWin == cs->pOverlayWin) {
159706f2543Smrg	    should = FALSE;
160706f2543Smrg	}
161706f2543Smrg    }
162706f2543Smrg
163706f2543Smrg    if (should != (pWin->redirectDraw != RedirectDrawNone))
164706f2543Smrg    {
165706f2543Smrg	if (should)
166706f2543Smrg	    return compAllocPixmap (pWin);
167706f2543Smrg	else
168706f2543Smrg	    compFreePixmap (pWin);
169706f2543Smrg    }
170706f2543Smrg    return TRUE;
171706f2543Smrg}
172706f2543Smrg
173706f2543Smrgstatic int
174706f2543SmrgupdateOverlayWindow(ScreenPtr pScreen)
175706f2543Smrg{
176706f2543Smrg	CompScreenPtr cs;
177706f2543Smrg	WindowPtr pWin; /* overlay window */
178706f2543Smrg	XID vlist[2];
179706f2543Smrg	int w = pScreen->width;
180706f2543Smrg	int h = pScreen->height;
181706f2543Smrg
182706f2543Smrg#ifdef PANORAMIX
183706f2543Smrg	if (!noPanoramiXExtension)
184706f2543Smrg	{
185706f2543Smrg	    w = PanoramiXPixWidth;
186706f2543Smrg	    h = PanoramiXPixHeight;
187706f2543Smrg	}
188706f2543Smrg#endif
189706f2543Smrg
190706f2543Smrg	cs = GetCompScreen(pScreen);
191706f2543Smrg	if ((pWin = cs->pOverlayWin) != NULL) {
192706f2543Smrg		if ((pWin->drawable.width == w) &&
193706f2543Smrg			(pWin->drawable.height == h))
194706f2543Smrg			return Success;
195706f2543Smrg
196706f2543Smrg		/* Let's resize the overlay window. */
197706f2543Smrg		vlist[0] = w;
198706f2543Smrg		vlist[1] = h;
199706f2543Smrg		return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin));
200706f2543Smrg	}
201706f2543Smrg
202706f2543Smrg	/* Let's be on the safe side and not assume an overlay window is always allocated. */
203706f2543Smrg	return Success;
204706f2543Smrg}
205706f2543Smrg
206706f2543SmrgBool
207706f2543SmrgcompPositionWindow (WindowPtr pWin, int x, int y)
208706f2543Smrg{
209706f2543Smrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
210706f2543Smrg    CompScreenPtr   cs = GetCompScreen (pScreen);
211706f2543Smrg    Bool	    ret = TRUE;
212706f2543Smrg
213706f2543Smrg    pScreen->PositionWindow = cs->PositionWindow;
214706f2543Smrg    /*
215706f2543Smrg     * "Shouldn't need this as all possible places should be wrapped
216706f2543Smrg     *
217706f2543Smrg    compCheckRedirect (pWin);
218706f2543Smrg     */
219706f2543Smrg#ifdef COMPOSITE_DEBUG
220706f2543Smrg    if ((pWin->redirectDraw != RedirectDrawNone) !=
221706f2543Smrg	(pWin->viewable && (GetCompWindow(pWin) != NULL)))
222706f2543Smrg	OsAbort ();
223706f2543Smrg#endif
224706f2543Smrg    if (pWin->redirectDraw != RedirectDrawNone)
225706f2543Smrg    {
226706f2543Smrg	PixmapPtr   pPixmap = (*pScreen->GetWindowPixmap) (pWin);
227706f2543Smrg	int	    bw = wBorderWidth (pWin);
228706f2543Smrg	int	    nx = pWin->drawable.x - bw;
229706f2543Smrg	int	    ny = pWin->drawable.y - bw;
230706f2543Smrg
231706f2543Smrg	if (pPixmap->screen_x != nx || pPixmap->screen_y != ny)
232706f2543Smrg	{
233706f2543Smrg	    pPixmap->screen_x = nx;
234706f2543Smrg	    pPixmap->screen_y = ny;
235706f2543Smrg	    pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
236706f2543Smrg	}
237706f2543Smrg    }
238706f2543Smrg
239706f2543Smrg    if (!(*pScreen->PositionWindow) (pWin, x, y))
240706f2543Smrg	ret = FALSE;
241706f2543Smrg    cs->PositionWindow = pScreen->PositionWindow;
242706f2543Smrg    pScreen->PositionWindow = compPositionWindow;
243706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
244706f2543Smrg    if (updateOverlayWindow(pScreen) != Success)
245706f2543Smrg	ret = FALSE;
246706f2543Smrg    return ret;
247706f2543Smrg}
248706f2543Smrg
249706f2543SmrgBool
250706f2543SmrgcompRealizeWindow (WindowPtr pWin)
251706f2543Smrg{
252706f2543Smrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
253706f2543Smrg    CompScreenPtr   cs = GetCompScreen (pScreen);
254706f2543Smrg    Bool	    ret = TRUE;
255706f2543Smrg
256706f2543Smrg    pScreen->RealizeWindow = cs->RealizeWindow;
257706f2543Smrg    compCheckRedirect (pWin);
258706f2543Smrg    if (!(*pScreen->RealizeWindow) (pWin))
259706f2543Smrg	ret = FALSE;
260706f2543Smrg    cs->RealizeWindow = pScreen->RealizeWindow;
261706f2543Smrg    pScreen->RealizeWindow = compRealizeWindow;
262706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
263706f2543Smrg    return ret;
264706f2543Smrg}
265706f2543Smrg
266706f2543SmrgBool
267706f2543SmrgcompUnrealizeWindow (WindowPtr pWin)
268706f2543Smrg{
269706f2543Smrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
270706f2543Smrg    CompScreenPtr   cs = GetCompScreen (pScreen);
271706f2543Smrg    Bool	    ret = TRUE;
272706f2543Smrg
273706f2543Smrg    pScreen->UnrealizeWindow = cs->UnrealizeWindow;
274706f2543Smrg    compCheckRedirect (pWin);
275706f2543Smrg    if (!(*pScreen->UnrealizeWindow) (pWin))
276706f2543Smrg	ret = FALSE;
277706f2543Smrg    cs->UnrealizeWindow = pScreen->UnrealizeWindow;
278706f2543Smrg    pScreen->UnrealizeWindow = compUnrealizeWindow;
279706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
280706f2543Smrg    return ret;
281706f2543Smrg}
282706f2543Smrg
283706f2543Smrg/*
284706f2543Smrg * Called after the borderClip for the window has settled down
285706f2543Smrg * We use this to make sure our extra borderClip has the right origin
286706f2543Smrg */
287706f2543Smrg
288706f2543Smrgvoid
289706f2543SmrgcompClipNotify (WindowPtr pWin, int dx, int dy)
290706f2543Smrg{
291706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
292706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
293706f2543Smrg    CompWindowPtr	cw = GetCompWindow (pWin);
294706f2543Smrg
295706f2543Smrg    if (cw)
296706f2543Smrg    {
297706f2543Smrg	if (cw->borderClipX != pWin->drawable.x ||
298706f2543Smrg	    cw->borderClipY != pWin->drawable.y)
299706f2543Smrg	{
300706f2543Smrg	    RegionTranslate(&cw->borderClip,
301706f2543Smrg			      pWin->drawable.x - cw->borderClipX,
302706f2543Smrg			      pWin->drawable.y - cw->borderClipY);
303706f2543Smrg	    cw->borderClipX = pWin->drawable.x;
304706f2543Smrg	    cw->borderClipY = pWin->drawable.y;
305706f2543Smrg	}
306706f2543Smrg    }
307706f2543Smrg    if (cs->ClipNotify)
308706f2543Smrg    {
309706f2543Smrg	pScreen->ClipNotify = cs->ClipNotify;
310706f2543Smrg	(*pScreen->ClipNotify) (pWin, dx, dy);
311706f2543Smrg	cs->ClipNotify = pScreen->ClipNotify;
312706f2543Smrg	pScreen->ClipNotify = compClipNotify;
313706f2543Smrg    }
314706f2543Smrg}
315706f2543Smrg
316706f2543Smrg/*
317706f2543Smrg * Returns TRUE if the window needs server-provided automatic redirect,
318706f2543Smrg * which is true if the child and parent aren't both regular or ARGB visuals
319706f2543Smrg */
320706f2543Smrg
321706f2543Smrgstatic Bool
322706f2543SmrgcompIsAlternateVisual (ScreenPtr    pScreen,
323706f2543Smrg		       XID	    visual)
324706f2543Smrg{
325706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
326706f2543Smrg    int			i;
327706f2543Smrg
328706f2543Smrg    for (i = 0; i < cs->numAlternateVisuals; i++)
329706f2543Smrg	if (cs->alternateVisuals[i] == visual)
330706f2543Smrg	    return TRUE;
331706f2543Smrg    return FALSE;
332706f2543Smrg}
333706f2543Smrg
334706f2543Smrgstatic Bool
335706f2543SmrgcompImplicitRedirect (WindowPtr pWin, WindowPtr pParent)
336706f2543Smrg{
337706f2543Smrg    if (pParent)
338706f2543Smrg    {
339706f2543Smrg	ScreenPtr	pScreen = pWin->drawable.pScreen;
340706f2543Smrg	XID		winVisual = wVisual (pWin);
341706f2543Smrg	XID		parentVisual = wVisual (pParent);
342706f2543Smrg
343706f2543Smrg	if (winVisual != parentVisual &&
344706f2543Smrg	    (compIsAlternateVisual (pScreen, winVisual) ||
345706f2543Smrg	     compIsAlternateVisual (pScreen, parentVisual)))
346706f2543Smrg	    return TRUE;
347706f2543Smrg    }
348706f2543Smrg    return FALSE;
349706f2543Smrg}
350706f2543Smrg
351706f2543Smrgstatic void compFreeOldPixmap(WindowPtr pWin)
352706f2543Smrg{
353706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
354706f2543Smrg    if (pWin->redirectDraw != RedirectDrawNone)
355706f2543Smrg    {
356706f2543Smrg	CompWindowPtr	cw = GetCompWindow (pWin);
357706f2543Smrg	if (cw->pOldPixmap)
358706f2543Smrg	{
359706f2543Smrg	    (*pScreen->DestroyPixmap) (cw->pOldPixmap);
360706f2543Smrg	    cw->pOldPixmap = NullPixmap;
361706f2543Smrg	}
362706f2543Smrg    }
363706f2543Smrg}
364706f2543Smrgvoid
365706f2543SmrgcompMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
366706f2543Smrg{
367706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
368706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
369706f2543Smrg
370706f2543Smrg    pScreen->MoveWindow = cs->MoveWindow;
371706f2543Smrg    (*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
372706f2543Smrg    cs->MoveWindow = pScreen->MoveWindow;
373706f2543Smrg    pScreen->MoveWindow = compMoveWindow;
374706f2543Smrg
375706f2543Smrg    compFreeOldPixmap(pWin);
376706f2543Smrg    compCheckTree (pScreen);
377706f2543Smrg}
378706f2543Smrg
379706f2543Smrgvoid
380706f2543SmrgcompResizeWindow (WindowPtr pWin, int x, int y,
381706f2543Smrg		  unsigned int w, unsigned int h, WindowPtr pSib)
382706f2543Smrg{
383706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
384706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
385706f2543Smrg
386706f2543Smrg    pScreen->ResizeWindow = cs->ResizeWindow;
387706f2543Smrg    (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
388706f2543Smrg    cs->ResizeWindow = pScreen->ResizeWindow;
389706f2543Smrg    pScreen->ResizeWindow = compResizeWindow;
390706f2543Smrg
391706f2543Smrg    compFreeOldPixmap(pWin);
392706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
393706f2543Smrg}
394706f2543Smrg
395706f2543Smrgvoid
396706f2543SmrgcompChangeBorderWidth (WindowPtr pWin, unsigned int bw)
397706f2543Smrg{
398706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
399706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
400706f2543Smrg
401706f2543Smrg    pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
402706f2543Smrg    (*pScreen->ChangeBorderWidth) (pWin, bw);
403706f2543Smrg    cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
404706f2543Smrg    pScreen->ChangeBorderWidth = compChangeBorderWidth;
405706f2543Smrg
406706f2543Smrg    compFreeOldPixmap(pWin);
407706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
408706f2543Smrg}
409706f2543Smrg
410706f2543Smrgvoid
411706f2543SmrgcompReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
412706f2543Smrg{
413706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
414706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
415706f2543Smrg
416706f2543Smrg    pScreen->ReparentWindow = cs->ReparentWindow;
417706f2543Smrg    /*
418706f2543Smrg     * Remove any implicit redirect due to synthesized visual
419706f2543Smrg     */
420706f2543Smrg    if (compImplicitRedirect (pWin, pPriorParent))
421706f2543Smrg	compUnredirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
422706f2543Smrg    /*
423706f2543Smrg     * Handle subwindows redirection
424706f2543Smrg     */
425706f2543Smrg    compUnredirectOneSubwindow (pPriorParent, pWin);
426706f2543Smrg    compRedirectOneSubwindow (pWin->parent, pWin);
427706f2543Smrg    /*
428706f2543Smrg     * Add any implict redirect due to synthesized visual
429706f2543Smrg     */
430706f2543Smrg    if (compImplicitRedirect (pWin, pWin->parent))
431706f2543Smrg	compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
432706f2543Smrg
433706f2543Smrg    /*
434706f2543Smrg     * Allocate any necessary redirect pixmap
435706f2543Smrg     * (this actually should never be true; pWin is always unmapped)
436706f2543Smrg     */
437706f2543Smrg    compCheckRedirect (pWin);
438706f2543Smrg
439706f2543Smrg    /*
440706f2543Smrg     * Reset pixmap pointers as appropriate
441706f2543Smrg     */
442706f2543Smrg    if (pWin->parent && pWin->redirectDraw == RedirectDrawNone)
443706f2543Smrg	compSetPixmap (pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
444706f2543Smrg    /*
445706f2543Smrg     * Call down to next function
446706f2543Smrg     */
447706f2543Smrg    if (pScreen->ReparentWindow)
448706f2543Smrg	(*pScreen->ReparentWindow) (pWin, pPriorParent);
449706f2543Smrg    cs->ReparentWindow = pScreen->ReparentWindow;
450706f2543Smrg    pScreen->ReparentWindow = compReparentWindow;
451706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
452706f2543Smrg}
453706f2543Smrg
454706f2543Smrgvoid
455706f2543SmrgcompCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
456706f2543Smrg{
457706f2543Smrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
458706f2543Smrg    CompScreenPtr   cs = GetCompScreen (pScreen);
459706f2543Smrg    int		    dx = 0, dy = 0;
460706f2543Smrg
461706f2543Smrg    if (pWin->redirectDraw != RedirectDrawNone)
462706f2543Smrg    {
463706f2543Smrg	PixmapPtr	pPixmap = (*pScreen->GetWindowPixmap) (pWin);
464706f2543Smrg	CompWindowPtr	cw = GetCompWindow (pWin);
465706f2543Smrg
466706f2543Smrg	assert (cw->oldx != COMP_ORIGIN_INVALID);
467706f2543Smrg	assert (cw->oldy != COMP_ORIGIN_INVALID);
468706f2543Smrg	if (cw->pOldPixmap)
469706f2543Smrg	{
470706f2543Smrg	    /*
471706f2543Smrg	     * Ok, the old bits are available in pOldPixmap and
472706f2543Smrg	     * need to be copied to pNewPixmap.
473706f2543Smrg	     */
474706f2543Smrg	    RegionRec	rgnDst;
475706f2543Smrg	    PixmapPtr	pPixmap = (*pScreen->GetWindowPixmap) (pWin);
476706f2543Smrg	    GCPtr	pGC;
477706f2543Smrg
478706f2543Smrg	    dx = ptOldOrg.x - pWin->drawable.x;
479706f2543Smrg	    dy = ptOldOrg.y - pWin->drawable.y;
480706f2543Smrg	    RegionTranslate(prgnSrc, -dx, -dy);
481706f2543Smrg
482706f2543Smrg	    RegionNull(&rgnDst);
483706f2543Smrg
484706f2543Smrg	    RegionIntersect(&rgnDst,
485706f2543Smrg			     &pWin->borderClip, prgnSrc);
486706f2543Smrg
487706f2543Smrg	    RegionTranslate(&rgnDst,
488706f2543Smrg			      -pPixmap->screen_x, -pPixmap->screen_y);
489706f2543Smrg
490706f2543Smrg	    dx = dx + pPixmap->screen_x - cw->oldx;
491706f2543Smrg	    dy = dy + pPixmap->screen_y - cw->oldy;
492706f2543Smrg	    pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
493706f2543Smrg	    if (pGC)
494706f2543Smrg	    {
495706f2543Smrg		BoxPtr	pBox = RegionRects (&rgnDst);
496706f2543Smrg		int	nBox = RegionNumRects (&rgnDst);
497706f2543Smrg
498706f2543Smrg		ValidateGC(&pPixmap->drawable, pGC);
499706f2543Smrg		while (nBox--)
500706f2543Smrg		{
501706f2543Smrg		    (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
502706f2543Smrg						  &pPixmap->drawable,
503706f2543Smrg						  pGC,
504706f2543Smrg						  pBox->x1 + dx, pBox->y1 + dy,
505706f2543Smrg						  pBox->x2 - pBox->x1,
506706f2543Smrg						  pBox->y2 - pBox->y1,
507706f2543Smrg						  pBox->x1, pBox->y1);
508706f2543Smrg		    pBox++;
509706f2543Smrg		}
510706f2543Smrg		FreeScratchGC (pGC);
511706f2543Smrg	    }
512706f2543Smrg	    return;
513706f2543Smrg	}
514706f2543Smrg	dx = pPixmap->screen_x - cw->oldx;
515706f2543Smrg	dy = pPixmap->screen_y - cw->oldy;
516706f2543Smrg	ptOldOrg.x += dx;
517706f2543Smrg	ptOldOrg.y += dy;
518706f2543Smrg    }
519706f2543Smrg
520706f2543Smrg    pScreen->CopyWindow = cs->CopyWindow;
521706f2543Smrg    if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y)
522706f2543Smrg    {
523706f2543Smrg	if (dx || dy)
524706f2543Smrg	    RegionTranslate(prgnSrc, dx, dy);
525706f2543Smrg	(*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
526706f2543Smrg	if (dx || dy)
527706f2543Smrg	    RegionTranslate(prgnSrc, -dx, -dy);
528706f2543Smrg    }
529706f2543Smrg    else
530706f2543Smrg    {
531706f2543Smrg	ptOldOrg.x -= dx;
532706f2543Smrg	ptOldOrg.y -= dy;
533706f2543Smrg	RegionTranslate(prgnSrc,
534706f2543Smrg			  pWin->drawable.x - ptOldOrg.x,
535706f2543Smrg			  pWin->drawable.y - ptOldOrg.y);
536706f2543Smrg	DamageDamageRegion(&pWin->drawable, prgnSrc);
537706f2543Smrg    }
538706f2543Smrg    cs->CopyWindow = pScreen->CopyWindow;
539706f2543Smrg    pScreen->CopyWindow = compCopyWindow;
540706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
541706f2543Smrg}
542706f2543Smrg
543706f2543SmrgBool
544706f2543SmrgcompCreateWindow (WindowPtr pWin)
545706f2543Smrg{
546706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
547706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
548706f2543Smrg    Bool		ret;
549706f2543Smrg
550706f2543Smrg    pScreen->CreateWindow = cs->CreateWindow;
551706f2543Smrg    ret = (*pScreen->CreateWindow) (pWin);
552706f2543Smrg    if (pWin->parent && ret)
553706f2543Smrg    {
554706f2543Smrg	CompSubwindowsPtr	csw = GetCompSubwindows (pWin->parent);
555706f2543Smrg        CompClientWindowPtr	ccw;
556706f2543Smrg
557706f2543Smrg	(*pScreen->SetWindowPixmap) (pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
558706f2543Smrg	if (csw)
559706f2543Smrg	    for (ccw = csw->clients; ccw; ccw = ccw->next)
560706f2543Smrg		compRedirectWindow (clients[CLIENT_ID(ccw->id)],
561706f2543Smrg				    pWin, ccw->update);
562706f2543Smrg	if (compImplicitRedirect (pWin, pWin->parent))
563706f2543Smrg	    compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
564706f2543Smrg    }
565706f2543Smrg    cs->CreateWindow = pScreen->CreateWindow;
566706f2543Smrg    pScreen->CreateWindow = compCreateWindow;
567706f2543Smrg    compCheckTree (pWin->drawable.pScreen);
568706f2543Smrg    return ret;
569706f2543Smrg}
570706f2543Smrg
571706f2543SmrgBool
572706f2543SmrgcompDestroyWindow (WindowPtr pWin)
573706f2543Smrg{
574706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
575706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
576706f2543Smrg    CompWindowPtr	cw;
577706f2543Smrg    CompSubwindowsPtr	csw;
578706f2543Smrg    Bool		ret;
579706f2543Smrg
580706f2543Smrg    pScreen->DestroyWindow = cs->DestroyWindow;
581706f2543Smrg    while ((cw = GetCompWindow (pWin)))
582706f2543Smrg	FreeResource (cw->clients->id, RT_NONE);
583706f2543Smrg    while ((csw = GetCompSubwindows (pWin)))
584706f2543Smrg	FreeResource (csw->clients->id, RT_NONE);
585706f2543Smrg
586706f2543Smrg    if (pWin->redirectDraw != RedirectDrawNone)
587706f2543Smrg	compFreePixmap (pWin);
588706f2543Smrg    ret = (*pScreen->DestroyWindow) (pWin);
589706f2543Smrg    cs->DestroyWindow = pScreen->DestroyWindow;
590706f2543Smrg    pScreen->DestroyWindow = compDestroyWindow;
59184795101Smrg
59284795101Smrg    /* Did we just destroy the overlay window? */
59384795101Smrg    if (pWin == cs->pOverlayWin)
59484795101Smrg        cs->pOverlayWin = NULL;
59584795101Smrg
596706f2543Smrg/*    compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
597706f2543Smrg    return ret;
598706f2543Smrg}
599706f2543Smrg
600706f2543Smrgvoid
601706f2543SmrgcompSetRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion)
602706f2543Smrg{
603706f2543Smrg    CompWindowPtr   cw = GetCompWindow (pWin);
604706f2543Smrg    RegionRec	    damage;
605706f2543Smrg
606706f2543Smrg    RegionNull(&damage);
607706f2543Smrg    /*
608706f2543Smrg     * Align old border clip with new border clip
609706f2543Smrg     */
610706f2543Smrg    RegionTranslate(&cw->borderClip,
611706f2543Smrg		      pWin->drawable.x - cw->borderClipX,
612706f2543Smrg		      pWin->drawable.y - cw->borderClipY);
613706f2543Smrg    /*
614706f2543Smrg     * Compute newly visible portion of window for repaint
615706f2543Smrg     */
616706f2543Smrg    RegionSubtract(&damage, pRegion, &cw->borderClip);
617706f2543Smrg    /*
618706f2543Smrg     * Report that as damaged so it will be redrawn
619706f2543Smrg     */
620706f2543Smrg    DamageDamageRegion(&pWin->drawable, &damage);
621706f2543Smrg    RegionUninit(&damage);
622706f2543Smrg    /*
623706f2543Smrg     * Save the new border clip region
624706f2543Smrg     */
625706f2543Smrg    RegionCopy(&cw->borderClip, pRegion);
626706f2543Smrg    cw->borderClipX = pWin->drawable.x;
627706f2543Smrg    cw->borderClipY = pWin->drawable.y;
628706f2543Smrg}
629706f2543Smrg
630706f2543SmrgRegionPtr
631706f2543SmrgcompGetRedirectBorderClip (WindowPtr pWin)
632706f2543Smrg{
633706f2543Smrg    CompWindowPtr   cw = GetCompWindow (pWin);
634706f2543Smrg
635706f2543Smrg    return &cw->borderClip;
636706f2543Smrg}
637706f2543Smrg
638706f2543Smrgstatic VisualPtr
639706f2543SmrgcompGetWindowVisual (WindowPtr pWin)
640706f2543Smrg{
641706f2543Smrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
642706f2543Smrg    VisualID	    vid = wVisual (pWin);
643706f2543Smrg    int		    i;
644706f2543Smrg
645706f2543Smrg    for (i = 0; i < pScreen->numVisuals; i++)
646706f2543Smrg	if (pScreen->visuals[i].vid == vid)
647706f2543Smrg	    return &pScreen->visuals[i];
648706f2543Smrg    return 0;
649706f2543Smrg}
650706f2543Smrg
651706f2543SmrgPictFormatPtr
652706f2543SmrgcompWindowFormat (WindowPtr pWin)
653706f2543Smrg{
654706f2543Smrg    ScreenPtr	pScreen = pWin->drawable.pScreen;
655706f2543Smrg
656706f2543Smrg    return PictureMatchVisual (pScreen, pWin->drawable.depth,
657706f2543Smrg			       compGetWindowVisual (pWin));
658706f2543Smrg}
659706f2543Smrg
660706f2543Smrgstatic void
661706f2543SmrgcompWindowUpdateAutomatic (WindowPtr pWin)
662706f2543Smrg{
663706f2543Smrg    CompWindowPtr   cw = GetCompWindow (pWin);
664706f2543Smrg    ScreenPtr	    pScreen = pWin->drawable.pScreen;
665706f2543Smrg    WindowPtr	    pParent = pWin->parent;
666706f2543Smrg    PixmapPtr	    pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
667706f2543Smrg    PictFormatPtr   pSrcFormat = compWindowFormat (pWin);
668706f2543Smrg    PictFormatPtr   pDstFormat = compWindowFormat (pWin->parent);
669706f2543Smrg    int		    error;
670706f2543Smrg    RegionPtr	    pRegion = DamageRegion (cw->damage);
671706f2543Smrg    PicturePtr	    pSrcPicture = CreatePicture (0, &pSrcPixmap->drawable,
672706f2543Smrg						 pSrcFormat,
673706f2543Smrg						 0, 0,
674706f2543Smrg						 serverClient,
675706f2543Smrg						 &error);
676706f2543Smrg    XID		    subwindowMode = IncludeInferiors;
677706f2543Smrg    PicturePtr	    pDstPicture = CreatePicture (0, &pParent->drawable,
678706f2543Smrg						 pDstFormat,
679706f2543Smrg						 CPSubwindowMode,
680706f2543Smrg						 &subwindowMode,
681706f2543Smrg						 serverClient,
682706f2543Smrg						 &error);
683706f2543Smrg
684706f2543Smrg    /*
685706f2543Smrg     * First move the region from window to screen coordinates
686706f2543Smrg     */
687706f2543Smrg    RegionTranslate(pRegion,
688706f2543Smrg		      pWin->drawable.x, pWin->drawable.y);
689706f2543Smrg
690706f2543Smrg    /*
691706f2543Smrg     * Clip against the "real" border clip
692706f2543Smrg     */
693706f2543Smrg    RegionIntersect(pRegion, pRegion, &cw->borderClip);
694706f2543Smrg
695706f2543Smrg    /*
696706f2543Smrg     * Now translate from screen to dest coordinates
697706f2543Smrg     */
698706f2543Smrg    RegionTranslate(pRegion,
699706f2543Smrg		      -pParent->drawable.x, -pParent->drawable.y);
700706f2543Smrg
701706f2543Smrg    /*
702706f2543Smrg     * Clip the picture
703706f2543Smrg     */
704706f2543Smrg    SetPictureClipRegion (pDstPicture, 0, 0, pRegion);
705706f2543Smrg
706706f2543Smrg    /*
707706f2543Smrg     * And paint
708706f2543Smrg     */
709706f2543Smrg    CompositePicture (PictOpSrc,
710706f2543Smrg		      pSrcPicture,
711706f2543Smrg		      0,
712706f2543Smrg		      pDstPicture,
713706f2543Smrg		      0, 0, /* src_x, src_y */
714706f2543Smrg		      0, 0, /* msk_x, msk_y */
715706f2543Smrg		      pSrcPixmap->screen_x - pParent->drawable.x,
716706f2543Smrg		      pSrcPixmap->screen_y - pParent->drawable.y,
717706f2543Smrg		      pSrcPixmap->drawable.width,
718706f2543Smrg		      pSrcPixmap->drawable.height);
719706f2543Smrg    FreePicture (pSrcPicture, 0);
720706f2543Smrg    FreePicture (pDstPicture, 0);
721706f2543Smrg    /*
722706f2543Smrg     * Empty the damage region.  This has the nice effect of
723706f2543Smrg     * rendering the translations above harmless
724706f2543Smrg     */
725706f2543Smrg    DamageEmpty (cw->damage);
726706f2543Smrg}
727706f2543Smrg
728706f2543Smrgstatic void
729706f2543SmrgcompPaintWindowToParent (WindowPtr pWin)
730706f2543Smrg{
731706f2543Smrg    compPaintChildrenToWindow (pWin);
732706f2543Smrg
733706f2543Smrg    if (pWin->redirectDraw != RedirectDrawNone)
734706f2543Smrg    {
735706f2543Smrg	CompWindowPtr	cw = GetCompWindow(pWin);
736706f2543Smrg
737706f2543Smrg	if (cw->damaged)
738706f2543Smrg	{
739706f2543Smrg	    compWindowUpdateAutomatic (pWin);
740706f2543Smrg	    cw->damaged = FALSE;
741706f2543Smrg	}
742706f2543Smrg    }
743706f2543Smrg}
744706f2543Smrg
745706f2543Smrgvoid
746706f2543SmrgcompPaintChildrenToWindow (WindowPtr pWin)
747706f2543Smrg{
748706f2543Smrg    WindowPtr pChild;
749706f2543Smrg
750706f2543Smrg    if (!pWin->damagedDescendants)
751706f2543Smrg	return;
752706f2543Smrg
753706f2543Smrg    for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
754706f2543Smrg	compPaintWindowToParent (pChild);
755706f2543Smrg
756706f2543Smrg    pWin->damagedDescendants = FALSE;
757706f2543Smrg}
758706f2543Smrg
759706f2543SmrgWindowPtr
760706f2543SmrgCompositeRealChildHead (WindowPtr pWin)
761706f2543Smrg{
762706f2543Smrg    WindowPtr pChild, pChildBefore;
763706f2543Smrg    CompScreenPtr cs;
764706f2543Smrg
765706f2543Smrg    if (!pWin->parent &&
766706f2543Smrg	(screenIsSaved == SCREEN_SAVER_ON) &&
767706f2543Smrg	(HasSaverWindow (pWin->drawable.pScreen))) {
768706f2543Smrg
769706f2543Smrg	/* First child is the screen saver; see if next child is the overlay */
770706f2543Smrg	pChildBefore = pWin->firstChild;
771706f2543Smrg	pChild = pChildBefore->nextSib;
772706f2543Smrg
773706f2543Smrg    } else {
774706f2543Smrg	pChildBefore = NullWindow;
775706f2543Smrg	pChild = pWin->firstChild;
776706f2543Smrg    }
777706f2543Smrg
778706f2543Smrg    if (!pChild) {
779706f2543Smrg	return NullWindow;
780706f2543Smrg    }
781706f2543Smrg
782706f2543Smrg    cs = GetCompScreen(pWin->drawable.pScreen);
783706f2543Smrg    if (pChild == cs->pOverlayWin) {
784706f2543Smrg	return pChild;
785706f2543Smrg    } else {
786706f2543Smrg	return pChildBefore;
787706f2543Smrg    }
788706f2543Smrg}
789706f2543Smrg
790706f2543Smrgint
791706f2543SmrgcompConfigNotify(WindowPtr pWin, int x, int y, int w, int h,
792706f2543Smrg		 int bw, WindowPtr pSib)
793706f2543Smrg{
794706f2543Smrg    ScreenPtr		pScreen = pWin->drawable.pScreen;
795706f2543Smrg    CompScreenPtr	cs = GetCompScreen (pScreen);
796706f2543Smrg    Bool                ret = 0;
797706f2543Smrg    WindowPtr		pParent = pWin->parent;
798706f2543Smrg    int			draw_x, draw_y;
799706f2543Smrg    Bool alloc_ret;
800706f2543Smrg
801706f2543Smrg    if (cs->ConfigNotify)
802706f2543Smrg    {
803706f2543Smrg	pScreen->ConfigNotify = cs->ConfigNotify;
804706f2543Smrg	ret = (*pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib);
805706f2543Smrg	cs->ConfigNotify = pScreen->ConfigNotify;
806706f2543Smrg	pScreen->ConfigNotify = compConfigNotify;
807706f2543Smrg
808706f2543Smrg	if (ret)
809706f2543Smrg	    return ret;
810706f2543Smrg    }
811706f2543Smrg
812706f2543Smrg    if (pWin->redirectDraw == RedirectDrawNone)
813706f2543Smrg	return Success;
814706f2543Smrg
815706f2543Smrg    compCheckTree (pScreen);
816706f2543Smrg
817706f2543Smrg    draw_x = pParent->drawable.x + x + bw;
818706f2543Smrg    draw_y = pParent->drawable.y + y + bw;
819706f2543Smrg    alloc_ret = compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
820706f2543Smrg
821706f2543Smrg    if (alloc_ret == FALSE)
822706f2543Smrg	return BadAlloc;
823706f2543Smrg    return Success;
824706f2543Smrg}
825