2
* Calculate window clip lists for rootless mode
4
* This file is very closely based on mivaltree.c.
6
/* $XFree86: xc/programs/Xserver/miext/rootless/rootlessValTree.c,v 1.1tsi Exp $ */
10
* Functions for recalculating window clip lists. Main function
14
Copyright 1987, 1988, 1989, 1998 The Open Group
18
The above copyright notice and this permission notice shall be included in
19
all copies or substantial portions of the Software.
21
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
Except as contained in this notice, the name of The Open Group shall not be
29
used in advertising or otherwise to promote the sale, use or other dealings
30
in this Software without prior written authorization from The Open Group.
33
* Copyright 1987, 1988, 1989 by
34
* Digital Equipment Corporation, Maynard, Massachusetts,
38
* Permission to use, copy, modify, and distribute this software and its
39
* documentation for any purpose and without fee is hereby granted,
40
* provided that the above copyright notice appear in all copies and that
41
* both that copyright notice and this permission notice appear in
42
* supporting documentation, and that the name of Digital not be
43
* used in advertising or publicity pertaining to distribution of the
44
* software without specific, written prior permission.
46
* DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
47
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
48
* DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
49
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
50
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
51
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54
******************************************************************/
56
/* The panoramix components contained the following notice */
57
/*****************************************************************
59
Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
61
Permission is hereby granted, free of charge, to any person obtaining a copy
62
of this software and associated documentation files (the "Software"), to deal
63
in the Software without restriction, including without limitation the rights
64
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
65
copies of the Software.
67
The above copyright notice and this permission notice shall be included in
68
all copies or substantial portions of the Software.
70
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
73
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
74
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
75
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
76
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
78
Except as contained in this notice, the name of Digital Equipment Corporation
79
shall not be used in advertising or otherwise to promote the sale, use or other
80
dealings in this Software without prior written authorization from Digital
81
Equipment Corporation.
83
******************************************************************/
85
* Aug '86: Susan Angebranndt -- original code
86
* July '87: Adam de Boor -- substantially modified and commented
87
* Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
88
* In particular, much improved code for window mapping and
90
* Bob Scheifler -- avoid miComputeClips for unmapped windows,
93
#ifdef HAVE_DIX_CONFIG_H
94
#include <dix-config.h>
98
#include "scrnintstr.h"
100
#include "windowstr.h"
102
#include "regionstr.h"
103
#include "mivalidate.h"
109
* Compute the visibility of a shaped window
112
RootlessShapedWindowIn (pScreen, universe, bounding, rect, x, y)
114
RegionPtr universe, bounding;
119
register BoxPtr boundBox;
121
Bool someIn, someOut;
122
register int t, x1, y1, x2, y2;
124
nbox = REGION_NUM_RECTS (bounding);
125
boundBox = REGION_RECTS (bounding);
126
someIn = someOut = FALSE;
133
if ((t = boundBox->x1 + x) < x1)
136
if ((t = boundBox->y1 + y) < y1)
139
if ((t = boundBox->x2 + x) > x2)
142
if ((t = boundBox->y2 + y) > y2)
149
switch (RECT_IN_REGION(pScreen, universe, &box))
172
#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
174
(w)->backgroundState == ParentRelative)
178
*-----------------------------------------------------------------------
179
* RootlessComputeClips --
180
* Recompute the clipList, borderClip, exposed and borderExposed
181
* regions for pParent and its children. Only viewable windows are
182
* taken into account.
188
* clipList, borderClip, exposed and borderExposed are altered.
189
* A VisibilityNotify event may be generated on the parent window.
191
*-----------------------------------------------------------------------
194
RootlessComputeClips (pParent, pScreen, universe, kind, exposed)
195
register WindowPtr pParent;
196
register ScreenPtr pScreen;
197
register RegionPtr universe;
199
RegionPtr exposed; /* for intermediate calculations */
203
RegionRec childUniverse;
204
register WindowPtr pChild;
207
RegionRec childUnion;
209
RegionPtr borderVisible;
212
* Figure out the new visibility of this window.
213
* The extent of the universe should be the same as the extent of
214
* the borderSize region. If the window is unobscured, this rectangle
215
* will be completely inside the universe (the universe will cover it
216
* completely). If the window is completely obscured, none of the
217
* universe will cover the rectangle.
219
borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
220
borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
221
dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
225
dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
230
oldVis = pParent->visibility;
231
switch (RECT_IN_REGION( pScreen, universe, &borderSize))
234
newVis = VisibilityUnobscured;
237
newVis = VisibilityPartiallyObscured;
242
if ((pBounding = wBoundingShape (pParent)))
244
switch (RootlessShapedWindowIn (pScreen, universe,
245
pBounding, &borderSize,
247
pParent->drawable.y))
250
newVis = VisibilityUnobscured;
253
newVis = VisibilityFullyObscured;
261
newVis = VisibilityFullyObscured;
265
pParent->visibility = newVis;
266
if (oldVis != newVis &&
267
((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
268
SendVisibilityNotify(pParent);
270
dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
271
dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
274
* avoid computations when dealing with simple operations
283
if ((oldVis == newVis) &&
284
((oldVis == VisibilityFullyObscured) ||
285
(oldVis == VisibilityUnobscured)))
290
if (pChild->viewable)
292
if (pChild->visibility != VisibilityFullyObscured)
294
REGION_TRANSLATE( pScreen, &pChild->borderClip,
296
REGION_TRANSLATE( pScreen, &pChild->clipList,
298
pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
299
if (pScreen->ClipNotify)
300
(* pScreen->ClipNotify) (pChild, dx, dy);
306
&pChild->valdata->after.borderExposed);
307
if (HasParentRelativeBorder(pChild))
309
REGION_SUBTRACT(pScreen,
310
&pChild->valdata->after.borderExposed,
314
REGION_NULL(pScreen, &pChild->valdata->after.exposed);
316
if (pChild->firstChild)
318
pChild = pChild->firstChild;
322
while (!pChild->nextSib && (pChild != pParent))
323
pChild = pChild->parent;
324
if (pChild == pParent)
326
pChild = pChild->nextSib;
333
* To calculate exposures correctly, we have to translate the old
334
* borderClip and clipList regions to the window's new location so there
335
* is a correspondence between pieces of the new and old clipping regions.
340
* We translate the old clipList because that will be exposed or copied
341
* if gravity is right.
343
REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
344
REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
348
REGION_EMPTY (pScreen, &pParent->borderClip);
349
REGION_EMPTY (pScreen, &pParent->clipList);
353
borderVisible = pParent->valdata->before.borderVisible;
354
resized = pParent->valdata->before.resized;
355
REGION_NULL(pScreen, &pParent->valdata->after.borderExposed);
356
REGION_NULL(pScreen, &pParent->valdata->after.exposed);
359
* Since the borderClip must not be clipped by the children, we do
360
* the border exposure first...
362
* 'universe' is the window's borderClip. To figure the exposures, remove
363
* the area that used to be exposed from the new.
364
* This leaves a region of pieces that weren't exposed before.
367
if (HasBorder (pParent))
372
* when the border changes shape, the old visible portions
373
* of the border will be saved by DIX in borderVisible --
374
* use that region and destroy it
376
REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
377
REGION_DESTROY( pScreen, borderVisible);
381
REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
383
if (HasParentRelativeBorder(pParent) && (dx || dy)) {
384
REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
388
REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
389
exposed, &pParent->winSize);
392
REGION_COPY( pScreen, &pParent->borderClip, universe);
395
* To get the right clipList for the parent, and to make doubly sure
396
* that no child overlaps the parent's border, we remove the parent's
397
* border from the universe before proceeding.
400
REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
403
REGION_COPY( pScreen, &pParent->borderClip, universe);
405
if ((pChild = pParent->firstChild) && pParent->mapped)
407
REGION_NULL(pScreen, &childUniverse);
408
REGION_NULL(pScreen, &childUnion);
409
if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
410
((pChild->drawable.y == pParent->lastChild->drawable.y) &&
411
(pChild->drawable.x < pParent->lastChild->drawable.x)))
413
for (; pChild; pChild = pChild->nextSib)
415
if (pChild->viewable)
416
REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
421
for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
423
if (pChild->viewable)
424
REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
427
REGION_VALIDATE( pScreen, &childUnion, &overlap);
429
for (pChild = pParent->firstChild;
431
pChild = pChild->nextSib)
433
if (pChild->viewable) {
435
* If the child is viewable, we want to remove its extents
436
* from the current universe, but we only re-clip it if
439
if (pChild->valdata) {
441
* Figure out the new universe from the child's
442
* perspective and recurse.
444
REGION_INTERSECT( pScreen, &childUniverse,
446
&pChild->borderSize);
447
RootlessComputeClips (pChild, pScreen, &childUniverse,
451
* Once the child has been processed, we remove its extents
452
* from the current universe, thus denying its space to any
456
REGION_SUBTRACT( pScreen, universe, universe,
457
&pChild->borderSize);
461
REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
462
REGION_UNINIT( pScreen, &childUnion);
463
REGION_UNINIT( pScreen, &childUniverse);
464
} /* if any children */
467
* 'universe' now contains the new clipList for the parent window.
469
* To figure the exposure of the window we subtract the old clip from the
470
* new, just as for the border.
473
if (oldVis == VisibilityFullyObscured ||
474
oldVis == VisibilityNotViewable)
476
REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
478
else if (newVis != VisibilityFullyObscured &&
479
newVis != VisibilityNotViewable)
481
REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
482
universe, &pParent->clipList);
486
* One last thing: backing storage. We have to try to save what parts of
487
* the window are about to be obscured. We can just subtract the universe
488
* from the old clipList and get the areas that were in the old but aren't
489
* in the new and, hence, are about to be obscured.
491
if (pParent->backStorage && !resized)
493
REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe);
494
(* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
497
/* HACK ALERT - copying contents of regions, instead of regions */
501
tmp = pParent->clipList;
502
pParent->clipList = *universe;
507
REGION_COPY( pScreen, &pParent->clipList, universe);
510
pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
512
if (pScreen->ClipNotify)
513
(* pScreen->ClipNotify) (pParent, dx, dy);
517
RootlessTreeObscured(pParent)
518
register WindowPtr pParent;
520
register WindowPtr pChild;
526
if (pChild->viewable)
528
oldVis = pChild->visibility;
529
if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
530
((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
531
SendVisibilityNotify(pChild);
532
if (pChild->firstChild)
534
pChild = pChild->firstChild;
538
while (!pChild->nextSib && (pChild != pParent))
539
pChild = pChild->parent;
540
if (pChild == pParent)
542
pChild = pChild->nextSib;
547
*-----------------------------------------------------------------------
548
* RootlessMiValidateTree --
549
* Recomputes the clip list for pParent and all its inferiors.
555
* The clipList, borderClip, exposed, and borderExposed regions for
556
* each marked window are altered.
559
* This routine assumes that all affected windows have been marked
560
* (valdata created) and their winSize and borderSize regions
561
* adjusted to correspond to their new positions. The borderClip and
562
* clipList regions should not have been touched.
564
* The top-most level is treated differently from all lower levels
565
* because pParent is unchanged. For the top level, we merge the
566
* regions taken up by the marked children back into the clipList
567
* for pParent, thus forming a region from which the marked children
568
* can claim their areas. For lower levels, where the old clipList
569
* and borderClip are invalid, we can't do this and have to do the
570
* extra operations done in miComputeClips, but this is much faster
571
* e.g. when only one child has moved...
573
*-----------------------------------------------------------------------
576
Quartz version: used for validate from root in rootless mode.
577
We need to make sure top-level windows don't clip each other,
578
and that top-level windows aren't clipped to the root window.
581
// fixme this is ugly
582
// Xprint/ValTree.c doesn't work, but maybe that method can?
584
RootlessMiValidateTree (pRoot, pChild, kind)
585
WindowPtr pRoot; /* Parent to validate */
586
WindowPtr pChild; /* First child of pRoot that was
588
VTKind kind; /* What kind of configuration caused call */
590
RegionRec childClip; /* The new borderClip for the current
592
RegionRec exposed; /* For intermediate calculations */
593
register ScreenPtr pScreen;
594
register WindowPtr pWin;
596
pScreen = pRoot->drawable.pScreen;
597
if (pChild == NullWindow)
598
pChild = pRoot->firstChild;
600
REGION_NULL(pScreen, &childClip);
601
REGION_NULL(pScreen, &exposed);
603
if (REGION_BROKEN (pScreen, &pRoot->clipList) &&
604
!REGION_BROKEN (pScreen, &pRoot->borderClip))
606
// fixme this might not work, but hopefully doesn't happen anyway.
608
REGION_EMPTY (pScreen, &pRoot->clipList);
609
ErrorF("ValidateTree: BUSTED!\n");
613
* Recursively compute the clips for all children of the root.
614
* They don't clip against each other or the root itself, so
615
* childClip is always reset to that child's size.
620
pWin = pWin->nextSib)
622
if (pWin->viewable) {
624
REGION_COPY( pScreen, &childClip, &pWin->borderSize);
625
RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
626
} else if (pWin->visibility == VisibilityNotViewable) {
627
RootlessTreeObscured(pWin);
631
REGION_EMPTY( pScreen, &pWin->clipList);
632
if (pScreen->ClipNotify)
633
(* pScreen->ClipNotify) (pWin, 0, 0);
634
REGION_EMPTY( pScreen, &pWin->borderClip);
635
pWin->valdata = (ValidatePtr)NULL;
640
REGION_UNINIT(pScreen, &childClip);
642
/* The root is never clipped by its children, so nothing on the root
643
is ever exposed by moving or mapping its children. */
644
REGION_NULL(pScreen, &pRoot->valdata->after.exposed);
645
REGION_NULL(pScreen, &pRoot->valdata->after.borderExposed);