1706f2543Smrg
2706f2543Smrg/***********************************************************
3706f2543Smrg
4706f2543SmrgCopyright 1987, 1998  The Open Group
5706f2543Smrg
6706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
7706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
8706f2543Smrgthe above copyright notice appear in all copies and that both that
9706f2543Smrgcopyright notice and this permission notice appear in supporting
10706f2543Smrgdocumentation.
11706f2543Smrg
12706f2543SmrgThe above copyright notice and this permission notice shall be included in
13706f2543Smrgall copies or substantial portions of the Software.
14706f2543Smrg
15706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21706f2543Smrg
22706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
23706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
24706f2543Smrgin this Software without prior written authorization from The Open Group.
25706f2543Smrg
26706f2543Smrg
27706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28706f2543Smrg
29706f2543Smrg                        All Rights Reserved
30706f2543Smrg
31706f2543SmrgPermission to use, copy, modify, and distribute this software and its
32706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
33706f2543Smrgprovided that the above copyright notice appear in all copies and that
34706f2543Smrgboth that copyright notice and this permission notice appear in
35706f2543Smrgsupporting documentation, and that the name of Digital not be
36706f2543Smrgused in advertising or publicity pertaining to distribution of the
37706f2543Smrgsoftware without specific, written prior permission.
38706f2543Smrg
39706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45706f2543SmrgSOFTWARE.
46706f2543Smrg
47706f2543Smrg******************************************************************/
48706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
49706f2543Smrg#include <dix-config.h>
50706f2543Smrg#endif
51706f2543Smrg
52706f2543Smrg#include <X11/X.h>
53706f2543Smrg#include <X11/extensions/shapeconst.h>
54706f2543Smrg#include "regionstr.h"
55706f2543Smrg#include "region.h"
56706f2543Smrg#include "mi.h"
57706f2543Smrg#include "windowstr.h"
58706f2543Smrg#include "scrnintstr.h"
59706f2543Smrg#include "pixmapstr.h"
60706f2543Smrg#include "mivalidate.h"
61706f2543Smrg
62706f2543Smrgvoid
63706f2543SmrgmiClearToBackground(WindowPtr pWin,
64706f2543Smrg                    int x, int y, int w, int h,
65706f2543Smrg                    Bool generateExposures)
66706f2543Smrg{
67706f2543Smrg    BoxRec box;
68706f2543Smrg    RegionRec	reg;
69706f2543Smrg    BoxPtr  extents;
70706f2543Smrg    int	    x1, y1, x2, y2;
71706f2543Smrg
72706f2543Smrg    /* compute everything using ints to avoid overflow */
73706f2543Smrg
74706f2543Smrg    x1 = pWin->drawable.x + x;
75706f2543Smrg    y1 = pWin->drawable.y + y;
76706f2543Smrg    if (w)
77706f2543Smrg        x2 = x1 + (int) w;
78706f2543Smrg    else
79706f2543Smrg        x2 = x1 + (int) pWin->drawable.width - (int) x;
80706f2543Smrg    if (h)
81706f2543Smrg        y2 = y1 + h;
82706f2543Smrg    else
83706f2543Smrg        y2 = y1 + (int) pWin->drawable.height - (int) y;
84706f2543Smrg
85706f2543Smrg    extents = &pWin->clipList.extents;
86706f2543Smrg
87706f2543Smrg    /* clip the resulting rectangle to the window clipList extents.  This
88706f2543Smrg     * makes sure that the result will fit in a box, given that the
89706f2543Smrg     * screen is < 32768 on a side.
90706f2543Smrg     */
91706f2543Smrg
92706f2543Smrg    if (x1 < extents->x1)
93706f2543Smrg	x1 = extents->x1;
94706f2543Smrg    if (x2 > extents->x2)
95706f2543Smrg	x2 = extents->x2;
96706f2543Smrg    if (y1 < extents->y1)
97706f2543Smrg	y1 = extents->y1;
98706f2543Smrg    if (y2 > extents->y2)
99706f2543Smrg	y2 = extents->y2;
100706f2543Smrg
101706f2543Smrg    if (x2 <= x1 || y2 <= y1)
102706f2543Smrg    {
103706f2543Smrg	x2 = x1 = 0;
104706f2543Smrg	y2 = y1 = 0;
105706f2543Smrg    }
106706f2543Smrg
107706f2543Smrg    box.x1 = x1;
108706f2543Smrg    box.x2 = x2;
109706f2543Smrg    box.y1 = y1;
110706f2543Smrg    box.y2 = y2;
111706f2543Smrg
112706f2543Smrg    RegionInit(&reg, &box, 1);
113706f2543Smrg
114706f2543Smrg    RegionIntersect(&reg, &reg, &pWin->clipList);
115706f2543Smrg    if (generateExposures)
116706f2543Smrg	(*pWin->drawable.pScreen->WindowExposures)(pWin, &reg, NULL);
117706f2543Smrg    else if (pWin->backgroundState != None)
118706f2543Smrg	miPaintWindow(pWin, &reg, PW_BACKGROUND);
119706f2543Smrg    RegionUninit(&reg);
120706f2543Smrg}
121706f2543Smrg
122706f2543Smrgvoid
123706f2543SmrgmiMarkWindow(WindowPtr pWin)
124706f2543Smrg{
125706f2543Smrg    ValidatePtr val;
126706f2543Smrg
127706f2543Smrg    if (pWin->valdata)
128706f2543Smrg	return;
129706f2543Smrg    val = (ValidatePtr)xnfalloc(sizeof(ValidateRec));
130706f2543Smrg    val->before.oldAbsCorner.x = pWin->drawable.x;
131706f2543Smrg    val->before.oldAbsCorner.y = pWin->drawable.y;
132706f2543Smrg    val->before.borderVisible = NullRegion;
133706f2543Smrg    val->before.resized = FALSE;
134706f2543Smrg    pWin->valdata = val;
135706f2543Smrg}
136706f2543Smrg
137706f2543SmrgBool
138706f2543SmrgmiMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
139706f2543Smrg{
140706f2543Smrg    BoxPtr box;
141706f2543Smrg    WindowPtr pChild, pLast;
142706f2543Smrg    Bool anyMarked = FALSE;
143706f2543Smrg    MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow;
144706f2543Smrg
145706f2543Smrg    /* single layered systems are easy */
146706f2543Smrg    if (ppLayerWin) *ppLayerWin = pWin;
147706f2543Smrg
148706f2543Smrg    if (pWin == pFirst)
149706f2543Smrg    {
150706f2543Smrg	/* Blindly mark pWin and all of its inferiors.	 This is a slight
151706f2543Smrg	 * overkill if there are mapped windows that outside pWin's border,
152706f2543Smrg	 * but it's better than wasting time on RectIn checks.
153706f2543Smrg	 */
154706f2543Smrg	pChild = pWin;
155706f2543Smrg	while (1)
156706f2543Smrg	{
157706f2543Smrg	    if (pChild->viewable)
158706f2543Smrg	    {
159706f2543Smrg		if (RegionBroken(&pChild->winSize))
160706f2543Smrg		    SetWinSize (pChild);
161706f2543Smrg		if (RegionBroken(&pChild->borderSize))
162706f2543Smrg		    SetBorderSize (pChild);
163706f2543Smrg		(* MarkWindow)(pChild);
164706f2543Smrg		if (pChild->firstChild)
165706f2543Smrg		{
166706f2543Smrg		    pChild = pChild->firstChild;
167706f2543Smrg		    continue;
168706f2543Smrg		}
169706f2543Smrg	    }
170706f2543Smrg	    while (!pChild->nextSib && (pChild != pWin))
171706f2543Smrg		pChild = pChild->parent;
172706f2543Smrg	    if (pChild == pWin)
173706f2543Smrg		break;
174706f2543Smrg	    pChild = pChild->nextSib;
175706f2543Smrg	}
176706f2543Smrg	anyMarked = TRUE;
177706f2543Smrg	pFirst = pFirst->nextSib;
178706f2543Smrg    }
179706f2543Smrg    if ( (pChild = pFirst) )
180706f2543Smrg    {
181706f2543Smrg	box = RegionExtents(&pWin->borderSize);
182706f2543Smrg	pLast = pChild->parent->lastChild;
183706f2543Smrg	while (1)
184706f2543Smrg	{
185706f2543Smrg	    if (pChild->viewable)
186706f2543Smrg	    {
187706f2543Smrg		if (RegionBroken(&pChild->winSize))
188706f2543Smrg		    SetWinSize (pChild);
189706f2543Smrg		if (RegionBroken(&pChild->borderSize))
190706f2543Smrg		    SetBorderSize (pChild);
191706f2543Smrg		if (RegionContainsRect(&pChild->borderSize, box))
192706f2543Smrg		{
193706f2543Smrg		    (* MarkWindow)(pChild);
194706f2543Smrg		    anyMarked = TRUE;
195706f2543Smrg		    if (pChild->firstChild)
196706f2543Smrg		    {
197706f2543Smrg			pChild = pChild->firstChild;
198706f2543Smrg			continue;
199706f2543Smrg		    }
200706f2543Smrg		}
201706f2543Smrg	    }
202706f2543Smrg	    while (!pChild->nextSib && (pChild != pLast))
203706f2543Smrg		pChild = pChild->parent;
204706f2543Smrg	    if (pChild == pLast)
205706f2543Smrg		break;
206706f2543Smrg	    pChild = pChild->nextSib;
207706f2543Smrg	}
208706f2543Smrg    }
209706f2543Smrg    if (anyMarked)
210706f2543Smrg	(* MarkWindow)(pWin->parent);
211706f2543Smrg    return anyMarked;
212706f2543Smrg}
213706f2543Smrg
214706f2543Smrg/*****
215706f2543Smrg *  miHandleValidateExposures(pWin)
216706f2543Smrg *    starting at pWin, draw background in any windows that have exposure
217706f2543Smrg *    regions, translate the regions, restore any backing store,
218706f2543Smrg *    and then send any regions still exposed to the client
219706f2543Smrg *****/
220706f2543Smrgvoid
221706f2543SmrgmiHandleValidateExposures(WindowPtr pWin)
222706f2543Smrg{
223706f2543Smrg    WindowPtr pChild;
224706f2543Smrg    ValidatePtr val;
225706f2543Smrg    WindowExposuresProcPtr WindowExposures;
226706f2543Smrg
227706f2543Smrg    pChild = pWin;
228706f2543Smrg    WindowExposures = pChild->drawable.pScreen->WindowExposures;
229706f2543Smrg    while (1)
230706f2543Smrg    {
231706f2543Smrg	if ( (val = pChild->valdata) )
232706f2543Smrg	{
233706f2543Smrg	    if (RegionNotEmpty(&val->after.borderExposed))
234706f2543Smrg		miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
235706f2543Smrg	    RegionUninit(&val->after.borderExposed);
236706f2543Smrg	    (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
237706f2543Smrg	    RegionUninit(&val->after.exposed);
238706f2543Smrg	    free(val);
239706f2543Smrg	    pChild->valdata = NULL;
240706f2543Smrg	    if (pChild->firstChild)
241706f2543Smrg	    {
242706f2543Smrg		pChild = pChild->firstChild;
243706f2543Smrg		continue;
244706f2543Smrg	    }
245706f2543Smrg	}
246706f2543Smrg	while (!pChild->nextSib && (pChild != pWin))
247706f2543Smrg	    pChild = pChild->parent;
248706f2543Smrg	if (pChild == pWin)
249706f2543Smrg	    break;
250706f2543Smrg	pChild = pChild->nextSib;
251706f2543Smrg    }
252706f2543Smrg}
253706f2543Smrg
254706f2543Smrgvoid
255706f2543SmrgmiMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
256706f2543Smrg{
257706f2543Smrg    WindowPtr pParent;
258706f2543Smrg    Bool WasViewable = (Bool)(pWin->viewable);
259706f2543Smrg    short bw;
260706f2543Smrg    RegionPtr oldRegion = NULL;
261706f2543Smrg    DDXPointRec oldpt;
262706f2543Smrg    Bool anyMarked = FALSE;
263706f2543Smrg    ScreenPtr pScreen;
264706f2543Smrg    WindowPtr windowToValidate;
265706f2543Smrg    WindowPtr pLayerWin;
266706f2543Smrg
267706f2543Smrg    /* if this is a root window, can't be moved */
268706f2543Smrg    if (!(pParent = pWin->parent))
269706f2543Smrg       return ;
270706f2543Smrg    pScreen = pWin->drawable.pScreen;
271706f2543Smrg    bw = wBorderWidth (pWin);
272706f2543Smrg
273706f2543Smrg    oldpt.x = pWin->drawable.x;
274706f2543Smrg    oldpt.y = pWin->drawable.y;
275706f2543Smrg    if (WasViewable)
276706f2543Smrg    {
277706f2543Smrg	oldRegion = RegionCreate(NullBox, 1);
278706f2543Smrg	RegionCopy(oldRegion, &pWin->borderClip);
279706f2543Smrg	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
280706f2543Smrg    }
281706f2543Smrg    pWin->origin.x = x + (int)bw;
282706f2543Smrg    pWin->origin.y = y + (int)bw;
283706f2543Smrg    x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
284706f2543Smrg    y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
285706f2543Smrg
286706f2543Smrg    SetWinSize (pWin);
287706f2543Smrg    SetBorderSize (pWin);
288706f2543Smrg
289706f2543Smrg    (*pScreen->PositionWindow)(pWin, x, y);
290706f2543Smrg
291706f2543Smrg    windowToValidate = MoveWindowInStack(pWin, pNextSib);
292706f2543Smrg
293706f2543Smrg    ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
294706f2543Smrg
295706f2543Smrg    if (WasViewable)
296706f2543Smrg    {
297706f2543Smrg	if (pLayerWin == pWin)
298706f2543Smrg	    anyMarked |= (*pScreen->MarkOverlappedWindows)
299706f2543Smrg				(pWin, windowToValidate, NULL);
300706f2543Smrg	else
301706f2543Smrg	    anyMarked |= (*pScreen->MarkOverlappedWindows)
302706f2543Smrg				(pWin, pLayerWin, NULL);
303706f2543Smrg
304706f2543Smrg
305706f2543Smrg	if (anyMarked)
306706f2543Smrg	{
307706f2543Smrg	    (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind);
308706f2543Smrg	    (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion);
309706f2543Smrg	    RegionDestroy(oldRegion);
310706f2543Smrg	    /* XXX need to retile border if ParentRelative origin */
311706f2543Smrg	    (*pScreen->HandleExposures)(pLayerWin->parent);
312706f2543Smrg	}
313706f2543Smrg	if (anyMarked && pScreen->PostValidateTree)
314706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind);
315706f2543Smrg    }
316706f2543Smrg    if (pWin->realized)
317706f2543Smrg	WindowsRestructured ();
318706f2543Smrg}
319706f2543Smrg
320706f2543Smrg
321706f2543Smrg/*
322706f2543Smrg * pValid is a region of the screen which has been
323706f2543Smrg * successfully copied -- recomputed exposed regions for affected windows
324706f2543Smrg */
325706f2543Smrg
326706f2543Smrgstatic int
327706f2543SmrgmiRecomputeExposures (
328706f2543Smrg    WindowPtr	pWin,
329706f2543Smrg    pointer		value) /* must conform to VisitWindowProcPtr */
330706f2543Smrg{
331706f2543Smrg    RegionPtr	pValid = (RegionPtr)value;
332706f2543Smrg
333706f2543Smrg    if (pWin->valdata)
334706f2543Smrg    {
335706f2543Smrg#ifdef COMPOSITE
336706f2543Smrg	/*
337706f2543Smrg	 * Redirected windows are not affected by parent window
338706f2543Smrg	 * gravity manipulations, so don't recompute their
339706f2543Smrg	 * exposed areas here.
340706f2543Smrg	 */
341706f2543Smrg	if (pWin->redirectDraw != RedirectDrawNone)
342706f2543Smrg	    return WT_DONTWALKCHILDREN;
343706f2543Smrg#endif
344706f2543Smrg	/*
345706f2543Smrg	 * compute exposed regions of this window
346706f2543Smrg	 */
347706f2543Smrg	RegionSubtract(&pWin->valdata->after.exposed,
348706f2543Smrg			&pWin->clipList, pValid);
349706f2543Smrg	/*
350706f2543Smrg	 * compute exposed regions of the border
351706f2543Smrg	 */
352706f2543Smrg	RegionSubtract(&pWin->valdata->after.borderExposed,
353706f2543Smrg			     &pWin->borderClip, &pWin->winSize);
354706f2543Smrg	RegionSubtract(&pWin->valdata->after.borderExposed,
355706f2543Smrg			     &pWin->valdata->after.borderExposed, pValid);
356706f2543Smrg	return WT_WALKCHILDREN;
357706f2543Smrg    }
358706f2543Smrg    return WT_NOMATCH;
359706f2543Smrg}
360706f2543Smrg
361706f2543Smrgvoid
362706f2543SmrgmiSlideAndSizeWindow(WindowPtr pWin,
363706f2543Smrg                     int x, int y,
364706f2543Smrg                     unsigned int w, unsigned int h,
365706f2543Smrg                     WindowPtr pSib)
366706f2543Smrg{
367706f2543Smrg    WindowPtr pParent;
368706f2543Smrg    Bool WasViewable = (Bool)(pWin->viewable);
369706f2543Smrg    unsigned short width = pWin->drawable.width,
370706f2543Smrg		   height = pWin->drawable.height;
371706f2543Smrg    short oldx = pWin->drawable.x,
372706f2543Smrg	  oldy = pWin->drawable.y;
373706f2543Smrg    int bw = wBorderWidth (pWin);
374706f2543Smrg    short dw, dh;
375706f2543Smrg    DDXPointRec oldpt;
376706f2543Smrg    RegionPtr oldRegion = NULL;
377706f2543Smrg    Bool anyMarked = FALSE;
378706f2543Smrg    ScreenPtr pScreen;
379706f2543Smrg    WindowPtr pFirstChange;
380706f2543Smrg    WindowPtr pChild;
381706f2543Smrg    RegionPtr	gravitate[StaticGravity + 1];
382706f2543Smrg    unsigned g;
383706f2543Smrg    int		nx, ny;		/* destination x,y */
384706f2543Smrg    int		newx, newy;	/* new inner window position */
385706f2543Smrg    RegionPtr	pRegion = NULL;
386706f2543Smrg    RegionPtr	destClip;	/* portions of destination already written */
387706f2543Smrg    RegionPtr	oldWinClip = NULL;	/* old clip list for window */
388706f2543Smrg    RegionPtr	borderVisible = NullRegion; /* visible area of the border */
389706f2543Smrg    Bool	shrunk = FALSE; /* shrunk in an inner dimension */
390706f2543Smrg    Bool	moved = FALSE;	/* window position changed */
391706f2543Smrg    WindowPtr  pLayerWin;
392706f2543Smrg
393706f2543Smrg    /* if this is a root window, can't be resized */
394706f2543Smrg    if (!(pParent = pWin->parent))
395706f2543Smrg	return ;
396706f2543Smrg
397706f2543Smrg    pScreen = pWin->drawable.pScreen;
398706f2543Smrg    newx = pParent->drawable.x + x + bw;
399706f2543Smrg    newy = pParent->drawable.y + y + bw;
400706f2543Smrg    if (WasViewable)
401706f2543Smrg    {
402706f2543Smrg	anyMarked = FALSE;
403706f2543Smrg	/*
404706f2543Smrg	 * save the visible region of the window
405706f2543Smrg	 */
406706f2543Smrg	oldRegion = RegionCreate(NullBox, 1);
407706f2543Smrg	RegionCopy(oldRegion, &pWin->winSize);
408706f2543Smrg
409706f2543Smrg	/*
410706f2543Smrg	 * categorize child windows into regions to be moved
411706f2543Smrg	 */
412706f2543Smrg	for (g = 0; g <= StaticGravity; g++)
413706f2543Smrg	    gravitate[g] = (RegionPtr) NULL;
414706f2543Smrg	for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
415706f2543Smrg	{
416706f2543Smrg	    g = pChild->winGravity;
417706f2543Smrg	    if (g != UnmapGravity)
418706f2543Smrg	    {
419706f2543Smrg		if (!gravitate[g])
420706f2543Smrg		    gravitate[g] = RegionCreate(NullBox, 1);
421706f2543Smrg		RegionUnion(gravitate[g],
422706f2543Smrg				   gravitate[g], &pChild->borderClip);
423706f2543Smrg	    }
424706f2543Smrg	    else
425706f2543Smrg	    {
426706f2543Smrg		UnmapWindow(pChild, TRUE);
427706f2543Smrg		anyMarked = TRUE;
428706f2543Smrg	    }
429706f2543Smrg	}
430706f2543Smrg	anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
431706f2543Smrg						       &pLayerWin);
432706f2543Smrg
433706f2543Smrg	oldWinClip = NULL;
434706f2543Smrg	if (pWin->bitGravity != ForgetGravity)
435706f2543Smrg	{
436706f2543Smrg	    oldWinClip = RegionCreate(NullBox, 1);
437706f2543Smrg	    RegionCopy(oldWinClip, &pWin->clipList);
438706f2543Smrg	}
439706f2543Smrg	/*
440706f2543Smrg	 * if the window is changing size, borderExposed
441706f2543Smrg	 * can't be computed correctly without some help.
442706f2543Smrg	 */
443706f2543Smrg	if (pWin->drawable.height > h || pWin->drawable.width > w)
444706f2543Smrg	    shrunk = TRUE;
445706f2543Smrg
446706f2543Smrg	if (newx != oldx || newy != oldy)
447706f2543Smrg	    moved = TRUE;
448706f2543Smrg
449706f2543Smrg	if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
450706f2543Smrg	    HasBorder (pWin))
451706f2543Smrg	{
452706f2543Smrg	    borderVisible = RegionCreate(NullBox, 1);
453706f2543Smrg	    /* for tiled borders, we punt and draw the whole thing */
454706f2543Smrg	    if (pWin->borderIsPixel || !moved)
455706f2543Smrg	    {
456706f2543Smrg		if (shrunk || moved)
457706f2543Smrg		    RegionSubtract(borderVisible,
458706f2543Smrg					  &pWin->borderClip,
459706f2543Smrg					  &pWin->winSize);
460706f2543Smrg		else
461706f2543Smrg		    RegionCopy(borderVisible,
462706f2543Smrg					    &pWin->borderClip);
463706f2543Smrg	    }
464706f2543Smrg	}
465706f2543Smrg    }
466706f2543Smrg    pWin->origin.x = x + bw;
467706f2543Smrg    pWin->origin.y = y + bw;
468706f2543Smrg    pWin->drawable.height = h;
469706f2543Smrg    pWin->drawable.width = w;
470706f2543Smrg
471706f2543Smrg    x = pWin->drawable.x = newx;
472706f2543Smrg    y = pWin->drawable.y = newy;
473706f2543Smrg
474706f2543Smrg    SetWinSize (pWin);
475706f2543Smrg    SetBorderSize (pWin);
476706f2543Smrg
477706f2543Smrg    dw = (int)w - (int)width;
478706f2543Smrg    dh = (int)h - (int)height;
479706f2543Smrg    ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
480706f2543Smrg
481706f2543Smrg    /* let the hardware adjust background and border pixmaps, if any */
482706f2543Smrg    (*pScreen->PositionWindow)(pWin, x, y);
483706f2543Smrg
484706f2543Smrg    pFirstChange = MoveWindowInStack(pWin, pSib);
485706f2543Smrg
486706f2543Smrg    if (WasViewable)
487706f2543Smrg    {
488706f2543Smrg	pRegion = RegionCreate(NullBox, 1);
489706f2543Smrg
490706f2543Smrg	if (pLayerWin == pWin)
491706f2543Smrg	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
492706f2543Smrg						NULL);
493706f2543Smrg	else
494706f2543Smrg	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
495706f2543Smrg						NULL);
496706f2543Smrg
497706f2543Smrg	if (pWin->valdata)
498706f2543Smrg	{
499706f2543Smrg	    pWin->valdata->before.resized = TRUE;
500706f2543Smrg	    pWin->valdata->before.borderVisible = borderVisible;
501706f2543Smrg	}
502706f2543Smrg
503706f2543Smrg
504706f2543Smrg	if (anyMarked)
505706f2543Smrg	    (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther);
506706f2543Smrg	/*
507706f2543Smrg	 * the entire window is trashed unless bitGravity
508706f2543Smrg	 * recovers portions of it
509706f2543Smrg	 */
510706f2543Smrg	RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
511706f2543Smrg    }
512706f2543Smrg
513706f2543Smrg    GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
514706f2543Smrg
515706f2543Smrg    if (WasViewable)
516706f2543Smrg    {
517706f2543Smrg	/* avoid the border */
518706f2543Smrg	if (HasBorder (pWin))
519706f2543Smrg	{
520706f2543Smrg	    int	offx, offy, dx, dy;
521706f2543Smrg
522706f2543Smrg	    /* kruft to avoid double translates for each gravity */
523706f2543Smrg	    offx = 0;
524706f2543Smrg	    offy = 0;
525706f2543Smrg	    for (g = 0; g <= StaticGravity; g++)
526706f2543Smrg	    {
527706f2543Smrg		if (!gravitate[g])
528706f2543Smrg		    continue;
529706f2543Smrg
530706f2543Smrg		/* align winSize to gravitate[g].
531706f2543Smrg		 * winSize is in new coordinates,
532706f2543Smrg		 * gravitate[g] is still in old coordinates */
533706f2543Smrg		GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
534706f2543Smrg
535706f2543Smrg		dx = (oldx - nx) - offx;
536706f2543Smrg		dy = (oldy - ny) - offy;
537706f2543Smrg		if (dx || dy)
538706f2543Smrg		{
539706f2543Smrg		    RegionTranslate(&pWin->winSize, dx, dy);
540706f2543Smrg		    offx += dx;
541706f2543Smrg		    offy += dy;
542706f2543Smrg		}
543706f2543Smrg		RegionIntersect(gravitate[g], gravitate[g],
544706f2543Smrg				 &pWin->winSize);
545706f2543Smrg	    }
546706f2543Smrg	    /* get winSize back where it belongs */
547706f2543Smrg	    if (offx || offy)
548706f2543Smrg		RegionTranslate(&pWin->winSize, -offx, -offy);
549706f2543Smrg	}
550706f2543Smrg	/*
551706f2543Smrg	 * add screen bits to the appropriate bucket
552706f2543Smrg	 */
553706f2543Smrg
554706f2543Smrg	if (oldWinClip)
555706f2543Smrg	{
556706f2543Smrg	    /*
557706f2543Smrg	     * clip to new clipList
558706f2543Smrg	     */
559706f2543Smrg	    RegionCopy(pRegion, oldWinClip);
560706f2543Smrg	    RegionTranslate(pRegion, nx - oldx, ny - oldy);
561706f2543Smrg	    RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
562706f2543Smrg	    /*
563706f2543Smrg	     * don't step on any gravity bits which will be copied after this
564706f2543Smrg	     * region.	Note -- this assumes that the regions will be copied
565706f2543Smrg	     * in gravity order.
566706f2543Smrg	     */
567706f2543Smrg	    for (g = pWin->bitGravity + 1; g <= StaticGravity; g++)
568706f2543Smrg	    {
569706f2543Smrg		if (gravitate[g])
570706f2543Smrg		    RegionSubtract(oldWinClip, oldWinClip,
571706f2543Smrg					gravitate[g]);
572706f2543Smrg	    }
573706f2543Smrg	    RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
574706f2543Smrg	    g = pWin->bitGravity;
575706f2543Smrg	    if (!gravitate[g])
576706f2543Smrg		gravitate[g] = oldWinClip;
577706f2543Smrg	    else
578706f2543Smrg	    {
579706f2543Smrg		RegionUnion(gravitate[g], gravitate[g], oldWinClip);
580706f2543Smrg		RegionDestroy(oldWinClip);
581706f2543Smrg	    }
582706f2543Smrg	}
583706f2543Smrg
584706f2543Smrg	/*
585706f2543Smrg	 * move the bits on the screen
586706f2543Smrg	 */
587706f2543Smrg
588706f2543Smrg	destClip = NULL;
589706f2543Smrg
590706f2543Smrg	for (g = 0; g <= StaticGravity; g++)
591706f2543Smrg	{
592706f2543Smrg	    if (!gravitate[g])
593706f2543Smrg		continue;
594706f2543Smrg
595706f2543Smrg	    GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
596706f2543Smrg
597706f2543Smrg	    oldpt.x = oldx + (x - nx);
598706f2543Smrg	    oldpt.y = oldy + (y - ny);
599706f2543Smrg
600706f2543Smrg	    /* Note that gravitate[g] is *translated* by CopyWindow */
601706f2543Smrg
602706f2543Smrg	    /* only copy the remaining useful bits */
603706f2543Smrg
604706f2543Smrg	    RegionIntersect(gravitate[g], gravitate[g], oldRegion);
605706f2543Smrg
606706f2543Smrg	    /* clip to not overwrite already copied areas */
607706f2543Smrg
608706f2543Smrg	    if (destClip) {
609706f2543Smrg		RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
610706f2543Smrg		RegionSubtract(gravitate[g], gravitate[g], destClip);
611706f2543Smrg		RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
612706f2543Smrg	    }
613706f2543Smrg
614706f2543Smrg	    /* and move those bits */
615706f2543Smrg
616706f2543Smrg	    if (oldpt.x != x || oldpt.y != y
617706f2543Smrg#ifdef COMPOSITE
618706f2543Smrg		|| pWin->redirectDraw
619706f2543Smrg#endif
620706f2543Smrg		)
621706f2543Smrg	    {
622706f2543Smrg		(*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
623706f2543Smrg	    }
624706f2543Smrg
625706f2543Smrg	    /* remove any overwritten bits from the remaining useful bits */
626706f2543Smrg
627706f2543Smrg	    RegionSubtract(oldRegion, oldRegion, gravitate[g]);
628706f2543Smrg
629706f2543Smrg	    /*
630706f2543Smrg	     * recompute exposed regions of child windows
631706f2543Smrg	     */
632706f2543Smrg
633706f2543Smrg	    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
634706f2543Smrg	    {
635706f2543Smrg		if (pChild->winGravity != g)
636706f2543Smrg		    continue;
637706f2543Smrg		RegionIntersect(pRegion,
638706f2543Smrg				       &pChild->borderClip, gravitate[g]);
639706f2543Smrg		TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion);
640706f2543Smrg	    }
641706f2543Smrg
642706f2543Smrg	    /*
643706f2543Smrg	     * remove the successfully copied regions of the
644706f2543Smrg	     * window from its exposed region
645706f2543Smrg	     */
646706f2543Smrg
647706f2543Smrg	    if (g == pWin->bitGravity)
648706f2543Smrg		RegionSubtract(&pWin->valdata->after.exposed,
649706f2543Smrg				     &pWin->valdata->after.exposed, gravitate[g]);
650706f2543Smrg	    if (!destClip)
651706f2543Smrg		destClip = gravitate[g];
652706f2543Smrg	    else
653706f2543Smrg	    {
654706f2543Smrg		RegionUnion(destClip, destClip, gravitate[g]);
655706f2543Smrg		RegionDestroy(gravitate[g]);
656706f2543Smrg	    }
657706f2543Smrg	}
658706f2543Smrg
659706f2543Smrg	RegionDestroy(oldRegion);
660706f2543Smrg	RegionDestroy(pRegion);
661706f2543Smrg	if (destClip)
662706f2543Smrg	    RegionDestroy(destClip);
663706f2543Smrg	if (anyMarked)
664706f2543Smrg	    (*pScreen->HandleExposures)(pLayerWin->parent);
665706f2543Smrg	if (anyMarked && pScreen->PostValidateTree)
666706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange,
667706f2543Smrg					  VTOther);
668706f2543Smrg    }
669706f2543Smrg    if (pWin->realized)
670706f2543Smrg	WindowsRestructured ();
671706f2543Smrg}
672706f2543Smrg
673706f2543SmrgWindowPtr
674706f2543SmrgmiGetLayerWindow(WindowPtr pWin)
675706f2543Smrg{
676706f2543Smrg    return pWin->firstChild;
677706f2543Smrg}
678706f2543Smrg
679706f2543Smrg/******
680706f2543Smrg *
681706f2543Smrg * miSetShape
682706f2543Smrg *    The border/window shape has changed.  Recompute winSize/borderSize
683706f2543Smrg *    and send appropriate exposure events
684706f2543Smrg */
685706f2543Smrg
686706f2543Smrgvoid
687706f2543SmrgmiSetShape(WindowPtr pWin, int kind)
688706f2543Smrg{
689706f2543Smrg    Bool        WasViewable = (Bool)(pWin->viewable);
690706f2543Smrg    ScreenPtr   pScreen = pWin->drawable.pScreen;
691706f2543Smrg    Bool        anyMarked = FALSE;
692706f2543Smrg    WindowPtr   pLayerWin;
693706f2543Smrg
694706f2543Smrg    if (kind != ShapeInput) {
695706f2543Smrg        if (WasViewable)
696706f2543Smrg        {
697706f2543Smrg            anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
698706f2543Smrg                                                          &pLayerWin);
699706f2543Smrg            if (pWin->valdata)
700706f2543Smrg            {
701706f2543Smrg                if (HasBorder (pWin))
702706f2543Smrg                {
703706f2543Smrg                    RegionPtr borderVisible;
704706f2543Smrg
705706f2543Smrg                    borderVisible = RegionCreate(NullBox, 1);
706706f2543Smrg                    RegionSubtract(borderVisible,
707706f2543Smrg                                    &pWin->borderClip, &pWin->winSize);
708706f2543Smrg                    pWin->valdata->before.borderVisible = borderVisible;
709706f2543Smrg                }
710706f2543Smrg                pWin->valdata->before.resized = TRUE;
711706f2543Smrg            }
712706f2543Smrg        }
713706f2543Smrg
714706f2543Smrg        SetWinSize (pWin);
715706f2543Smrg        SetBorderSize (pWin);
716706f2543Smrg
717706f2543Smrg        ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
718706f2543Smrg
719706f2543Smrg        if (WasViewable)
720706f2543Smrg        {
721706f2543Smrg            anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
722706f2543Smrg                                                           NULL);
723706f2543Smrg
724706f2543Smrg            if (anyMarked)
725706f2543Smrg                (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow,
726706f2543Smrg                                         VTOther);
727706f2543Smrg        }
728706f2543Smrg
729706f2543Smrg        if (WasViewable)
730706f2543Smrg        {
731706f2543Smrg            if (anyMarked)
732706f2543Smrg                (*pScreen->HandleExposures)(pLayerWin->parent);
733706f2543Smrg            if (anyMarked && pScreen->PostValidateTree)
734706f2543Smrg                (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow,
735706f2543Smrg                                             VTOther);
736706f2543Smrg        }
737706f2543Smrg    }
738706f2543Smrg    if (pWin->realized)
739706f2543Smrg        WindowsRestructured ();
740706f2543Smrg    CheckCursorConfinement(pWin);
741706f2543Smrg}
742706f2543Smrg
743706f2543Smrg/* Keeps the same inside(!) origin */
744706f2543Smrg
745706f2543Smrgvoid
746706f2543SmrgmiChangeBorderWidth(WindowPtr pWin, unsigned int width)
747706f2543Smrg{
748706f2543Smrg    int oldwidth;
749706f2543Smrg    Bool anyMarked = FALSE;
750706f2543Smrg    ScreenPtr pScreen;
751706f2543Smrg    Bool WasViewable = (Bool)(pWin->viewable);
752706f2543Smrg    Bool HadBorder;
753706f2543Smrg    WindowPtr  pLayerWin;
754706f2543Smrg
755706f2543Smrg    oldwidth = wBorderWidth (pWin);
756706f2543Smrg    if (oldwidth == width)
757706f2543Smrg	return;
758706f2543Smrg    HadBorder = HasBorder(pWin);
759706f2543Smrg    pScreen = pWin->drawable.pScreen;
760706f2543Smrg    if (WasViewable && width < oldwidth)
761706f2543Smrg	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
762706f2543Smrg
763706f2543Smrg    pWin->borderWidth = width;
764706f2543Smrg    SetBorderSize (pWin);
765706f2543Smrg
766706f2543Smrg    if (WasViewable)
767706f2543Smrg    {
768706f2543Smrg	if (width > oldwidth)
769706f2543Smrg	{
770706f2543Smrg	    anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
771706f2543Smrg							  &pLayerWin);
772706f2543Smrg	    /*
773706f2543Smrg	     * save the old border visible region to correctly compute
774706f2543Smrg	     * borderExposed.
775706f2543Smrg	     */
776706f2543Smrg	    if (pWin->valdata && HadBorder)
777706f2543Smrg	    {
778706f2543Smrg		RegionPtr   borderVisible;
779706f2543Smrg		borderVisible = RegionCreate(NULL, 1);
780706f2543Smrg		RegionSubtract(borderVisible,
781706f2543Smrg				      &pWin->borderClip, &pWin->winSize);
782706f2543Smrg		pWin->valdata->before.borderVisible = borderVisible;
783706f2543Smrg	    }
784706f2543Smrg	}
785706f2543Smrg
786706f2543Smrg	if (anyMarked)
787706f2543Smrg	{
788706f2543Smrg	    (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
789706f2543Smrg	    (*pScreen->HandleExposures)(pLayerWin->parent);
790706f2543Smrg	}
791706f2543Smrg	if (anyMarked && pScreen->PostValidateTree)
792706f2543Smrg	    (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin,
793706f2543Smrg					  VTOther);
794706f2543Smrg    }
795706f2543Smrg    if (pWin->realized)
796706f2543Smrg	WindowsRestructured ();
797706f2543Smrg}
798706f2543Smrg
799706f2543Smrgvoid
800706f2543SmrgmiMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
801706f2543Smrg{
802706f2543Smrg    if ((pChild != pWin) || fromConfigure)
803706f2543Smrg    {
804706f2543Smrg	RegionEmpty(&pChild->clipList);
805706f2543Smrg	if (pChild->drawable.pScreen->ClipNotify)
806706f2543Smrg	    (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
807706f2543Smrg	RegionEmpty(&pChild->borderClip);
808706f2543Smrg    }
809706f2543Smrg}
810706f2543Smrg
811706f2543Smrgvoid
812706f2543SmrgmiSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
813706f2543Smrg{
814706f2543Smrg    WindowPtr pChild;
815706f2543Smrg
816706f2543Smrg    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
817706f2543Smrg    {
818706f2543Smrg	if (pChild->drawable.depth == depth)
819706f2543Smrg	    RegionUnion(pReg, pReg, &pChild->borderClip);
820706f2543Smrg
821706f2543Smrg	if (pChild->firstChild)
822706f2543Smrg	    miSegregateChildren(pChild, pReg, depth);
823706f2543Smrg    }
824706f2543Smrg}
825