|
|
1.1 ! root 1: /* ! 2: * mivaltree.c -- ! 3: * Functions for recalculating window clip lists. Main function ! 4: * is miValidateTree. ! 5: * ! 6: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, ! 7: * and the Massachusetts Institute of Technology, Cambridge, Massachusetts. ! 8: * ! 9: * All Rights Reserved ! 10: * ! 11: * Permission to use, copy, modify, and distribute this software and its ! 12: * documentation for any purpose and without fee is hereby granted, ! 13: * provided that the above copyright notice appear in all copies and that ! 14: * both that copyright notice and this permission notice appear in ! 15: * supporting documentation, and that the names of Digital or MIT not be ! 16: * used in advertising or publicity pertaining to distribution of the ! 17: * software without specific, written prior permission. ! 18: * ! 19: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 20: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 21: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 22: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 23: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 24: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 25: * SOFTWARE. ! 26: * ! 27: ******************************************************************/ ! 28: ! 29: /* ! 30: * Aug '86: Susan Angebranndt -- original code ! 31: * July '87: Adam de Boor -- substantially modified and commented ! 32: */ ! 33: ! 34: #ifndef lint ! 35: static char rcsid[] = ! 36: "$Header: mivaltree.c,v 1.36 87/09/11 07:20:34 toddb Exp $ SPRITE (Berkeley)"; ! 37: #endif lint ! 38: ! 39: #include "X.h" ! 40: #include "scrnintstr.h" ! 41: #include "windowstr.h" ! 42: #include "mi.h" ! 43: #include "region.h" ! 44: ! 45: static RegionPtr exposed = NullRegion; ! 46: ! 47: /*- ! 48: *----------------------------------------------------------------------- ! 49: * miComputeClips -- ! 50: * Recompute the clipList, borderClip, exposed and borderExposed ! 51: * regions for pParent and its children. Only viewable windows are ! 52: * taken into account. ! 53: * ! 54: * Results: ! 55: * None. ! 56: * ! 57: * Side Effects: ! 58: * clipList, borderClip, exposed and borderExposed are altered. ! 59: * A VisibilityNotify event may be generated on the parent window. ! 60: * ! 61: *----------------------------------------------------------------------- ! 62: */ ! 63: static void ! 64: miComputeClips (pParent, pScreen, universe) ! 65: register WindowPtr pParent; ! 66: register ScreenPtr pScreen; ! 67: register RegionPtr universe; ! 68: { ! 69: int dx, ! 70: dy; ! 71: RegionPtr childUniverse; ! 72: register WindowPtr pChild; ! 73: int oldVis; ! 74: BoxPtr borderSize; ! 75: ! 76: ! 77: childUniverse = (RegionPtr)NULL; ! 78: ! 79: /* ! 80: * Figure out the new visibility of this window. ! 81: * The extent of the universe should be the same as the extent of ! 82: * the borderSize region. If the window is unobscured, this rectangle ! 83: * will be completely inside the universe (the universe will cover it ! 84: * completely). If the window is completely obscured, none of the ! 85: * universe will cover the rectangle. ! 86: */ ! 87: borderSize = (* pScreen->RegionExtents) (pParent->borderSize); ! 88: ! 89: oldVis = pParent->visibility; ! 90: switch ((* pScreen->RectIn) (universe, borderSize)) ! 91: { ! 92: case rgnIN: ! 93: pParent->visibility = VisibilityUnobscured; ! 94: break; ! 95: case rgnPART: ! 96: pParent->visibility = VisibilityPartiallyObscured; ! 97: break; ! 98: default: ! 99: pParent->visibility = VisibilityFullyObscured; ! 100: break; ! 101: } ! 102: if (oldVis != pParent->visibility) ! 103: SendVisibilityNotify(pParent); ! 104: ! 105: /* ! 106: * To calculate exposures correctly, we have to translate the old ! 107: * borderClip and clipList regions to the window's new location so there ! 108: * is a correspondence between pieces of the new and old clipping regions. ! 109: */ ! 110: dx = pParent->absCorner.x - pParent->oldAbsCorner.x; ! 111: dy = pParent->absCorner.y - pParent->oldAbsCorner.y; ! 112: ! 113: if (dx || dy) ! 114: { ! 115: /* ! 116: * If the window has moved, the border will *not* be copied, so we ! 117: * empty the old border clip to force exposure of the whole thing. ! 118: * We translate the old clipList because that will be exposed or copied ! 119: * if gravity is right. ! 120: */ ! 121: (* pScreen->RegionEmpty) (pParent->borderClip); ! 122: (* pScreen->TranslateRegion) (pParent->clipList, dx, dy); ! 123: pParent->oldAbsCorner = pParent->absCorner; ! 124: } ! 125: else if (pParent->borderWidth) ! 126: { ! 127: /* ! 128: * If the window has shrunk, we have to be careful about figuring the ! 129: * exposure of the right and bottom borders -- they should be exposed ! 130: * if the window shrank on that side and they aren't being obscured ! 131: * by a sibling -- so we add those edges to the borderExposed region. ! 132: * This is all necessary because sometimes what was the internal window ! 133: * in the old borderClip will overlap the new border and cause the ! 134: * right and bottom edges of the new border not to appear in the ! 135: * borderExposed region and it's a royal pain to figure out what to ! 136: * remove from the old borderClip. ! 137: * XXX: Isn't there a nicer way to do this? ! 138: */ ! 139: BoxPtr oldExtents; ! 140: BoxPtr newExtents; ! 141: BoxPtr windowExtents; ! 142: ! 143: oldExtents = (* pScreen->RegionExtents) (pParent->borderClip); ! 144: newExtents = (* pScreen->RegionExtents) (universe); ! 145: windowExtents = (* pScreen->RegionExtents) (pParent->borderSize); ! 146: ! 147: if ((* pScreen->RegionNotEmpty) (universe) && ! 148: (* pScreen->RegionNotEmpty) (pParent->borderClip) && ! 149: ((newExtents->x2 < oldExtents->x2) || ! 150: (newExtents->y2 < oldExtents->y2))) ! 151: { ! 152: BoxRec borderBox; ! 153: RegionPtr borderRegion; ! 154: ! 155: borderRegion = (* pScreen->RegionCreate) (NULL, 1); ! 156: ! 157: if (newExtents->x2 < oldExtents->x2) ! 158: { ! 159: /* ! 160: * Add the right edge. ! 161: */ ! 162: borderBox.x1 = windowExtents->x2 - pParent->borderWidth; ! 163: borderBox.y1 = windowExtents->y1; ! 164: borderBox.x2 = windowExtents->x2; ! 165: borderBox.y2 = windowExtents->y2; ! 166: (* pScreen->RegionReset) (borderRegion, &borderBox); ! 167: (* pScreen->Union) (pParent->borderExposed, ! 168: pParent->borderExposed, ! 169: borderRegion); ! 170: } ! 171: if (newExtents->y2 < oldExtents->y2) ! 172: { ! 173: /* ! 174: * Add the bottom edge. ! 175: */ ! 176: borderBox.x1 = windowExtents->x1; ! 177: borderBox.y1 = windowExtents->y2 - pParent->borderWidth; ! 178: borderBox.x2 = windowExtents->x2; ! 179: borderBox.y2 = windowExtents->y2; ! 180: (* pScreen->RegionReset) (borderRegion, &borderBox); ! 181: (* pScreen->Union) (pParent->borderExposed, ! 182: pParent->borderExposed, ! 183: borderRegion); ! 184: } ! 185: (* pScreen->RegionDestroy) (borderRegion); ! 186: ! 187: /* ! 188: * To make sure we don't expose a border that's supposed to ! 189: * be clipped, clip the regions we just added to borderExposed... ! 190: */ ! 191: (* pScreen->Intersect) (pParent->borderExposed, universe, ! 192: pParent->borderExposed); ! 193: } ! 194: } ! 195: ! 196: /* ! 197: * Since the borderClip must not be clipped by the children, we do ! 198: * the border exposure first... ! 199: * ! 200: * 'universe' is the window's borderClip. To figure the exposures, remove ! 201: * the area that used to be exposed (the old borderClip) from the new. ! 202: * This leaves a region of pieces that weren't exposed before. Border ! 203: * exposures accumulate until they're taken care of. ! 204: */ ! 205: (* pScreen->Subtract) (exposed, universe, pParent->borderClip); ! 206: (* pScreen->Subtract) (exposed, exposed, pParent->winSize); ! 207: ! 208: (* pScreen->Union) (pParent->borderExposed, pParent->borderExposed, ! 209: exposed); ! 210: ! 211: (* pScreen->RegionCopy) (pParent->borderClip, universe); ! 212: ! 213: /* ! 214: * To get the right clipList for the parent, and to make doubly sure ! 215: * that no child overlaps the parent's border, we remove the parent's ! 216: * border from the universe before proceeding. ! 217: */ ! 218: (* pScreen->Intersect) (universe, universe, pParent->winSize); ! 219: ! 220: for (pChild = pParent->firstChild; pChild; pChild = pChild->nextSib) ! 221: { ! 222: if (pChild->viewable) ! 223: { ! 224: /* ! 225: * If the child is viewable, we want to remove its extents from ! 226: * the current universe, but we only re-clip it if it's been ! 227: * marked. ! 228: */ ! 229: if (pChild->marked) ! 230: { ! 231: /* ! 232: * Figure out the new universe from the child's perspective and ! 233: * recurse. ! 234: */ ! 235: if (childUniverse == NullRegion) ! 236: { ! 237: childUniverse = (* pScreen->RegionCreate) (NULL, 1); ! 238: } ! 239: (* pScreen->Intersect) (childUniverse, universe, ! 240: pChild->borderSize); ! 241: miComputeClips (pChild, pScreen, childUniverse); ! 242: } ! 243: /* ! 244: * Once the child has been processed, we remove its extents from ! 245: * the current universe, thus denying its space to any other ! 246: * sibling. ! 247: */ ! 248: (* pScreen->Subtract) (universe, universe, pChild->borderSize); ! 249: } ! 250: else ! 251: { ! 252: pChild->marked = 0; ! 253: if ((* pScreen->RegionNotEmpty) (pChild->borderClip)) ! 254: { ! 255: /* ! 256: * If the child isn't viewable, it has no business taking up ! 257: * clipping space, so we nuke all its clipping regions. There ! 258: * was a problem with UnmapGravity where the clipList wouldn't ! 259: * get nuked, so drawing operations succeeded while the window ! 260: * was unmapped... ! 261: */ ! 262: (* pScreen->RegionEmpty) (pChild->borderClip); ! 263: (* pScreen->RegionEmpty) (pChild->clipList); ! 264: (* pScreen->RegionEmpty) (pChild->exposed); ! 265: (* pScreen->RegionEmpty) (pChild->borderExposed); ! 266: pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; ! 267: } ! 268: } ! 269: } ! 270: ! 271: /* ! 272: * 'universe' now contains the new clipList for the parent window. ! 273: * ! 274: * To figure the exposure of the window we subtract the old clip from the ! 275: * new, just as for the border. Again, exposures accumulate. ! 276: */ ! 277: (* pScreen->Subtract) (exposed, universe, pParent->clipList); ! 278: ! 279: (* pScreen->Union) (pParent->exposed, pParent->exposed, exposed); ! 280: ! 281: /* ! 282: * One last thing: backing storage. We have to find out what parts of ! 283: * the window are about to be obscured. We can just subtract the universe ! 284: * from the old clipList and get the areas that were in the old but aren't ! 285: * in the new and, hence, are about to be obscured. ! 286: */ ! 287: if (pParent->backStorage && (pParent->backingStore != NotUseful)) ! 288: { ! 289: (* pScreen->Subtract) (exposed, pParent->clipList, universe); ! 290: (* pScreen->Union) (pParent->backStorage->obscured, ! 291: pParent->backStorage->obscured, ! 292: exposed); ! 293: } ! 294: ! 295: (* pScreen->RegionCopy) (pParent->clipList, universe); ! 296: ! 297: pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; ! 298: pParent->marked = 0; ! 299: ! 300: if (childUniverse) ! 301: (* pScreen->RegionDestroy) (childUniverse); ! 302: } ! 303: ! 304: /*- ! 305: *----------------------------------------------------------------------- ! 306: * miValidateTree -- ! 307: * Recomputes the clip list for pParent and all its inferiors. ! 308: * ! 309: * Results: ! 310: * Always returns 1. ! 311: * ! 312: * Side Effects: ! 313: * The clipList, borderClip, exposed, and borderExposed regions for ! 314: * each marked window are altered. ! 315: * ! 316: * Notes: ! 317: * This routine assumes that all affected windows have had their ! 318: * marked fields set true and their winSize and borderSize regions ! 319: * adjusted to correspond to their new positions. The borderClip and ! 320: * clipList regions should not have been touched. ! 321: * ! 322: * The top-most level is treated differently from all lower levels ! 323: * because pParent is unchanged. For the top level, we merge the ! 324: * regions taken up by the marked children back into the clipList ! 325: * for pParent, thus forming a region from which the marked children ! 326: * can claim their areas. For lower levels, where the old clipList ! 327: * and borderClip are invalid, we can't do this and have to do the ! 328: * extra operations done in miComputeClips, but this is much faster ! 329: * e.g. when only one child has moved... ! 330: * ! 331: *----------------------------------------------------------------------- ! 332: */ ! 333: /*ARGSUSED*/ ! 334: int ! 335: miValidateTree (pParent, pChild, top, anyMarked) ! 336: WindowPtr pParent; /* Parent to validate */ ! 337: WindowPtr pChild; /* First child of pParent that was ! 338: * affected */ ! 339: Bool top; /* TRUE if at top level. UNUSED */ ! 340: Bool anyMarked; /* TRUE if any windows were marked. */ ! 341: { ! 342: RegionPtr totalClip; /* Total clipping region available to ! 343: * the marked children. pParent's clipList ! 344: * merged with the borderClips of all ! 345: * the marked children. */ ! 346: RegionPtr childClip; /* The new borderClip for the current ! 347: * child */ ! 348: register ScreenPtr pScreen; ! 349: register WindowPtr pWin; ! 350: ! 351: if (!anyMarked) ! 352: { ! 353: return (1); ! 354: } ! 355: pScreen = pParent->drawable.pScreen; ! 356: ! 357: if (exposed == NullRegion) ! 358: { ! 359: exposed = (* pScreen->RegionCreate) (NULL, 1); ! 360: } ! 361: ! 362: totalClip = (* pScreen->RegionCreate) (NULL, 1); ! 363: childClip = (* pScreen->RegionCreate) (NULL, 1); ! 364: ! 365: /* ! 366: * Preserve the parent's old clipList to make calculating exposures ! 367: * easier. ! 368: */ ! 369: (* pScreen->RegionCopy) (totalClip, pParent->clipList); ! 370: ! 371: if (pChild == NullWindow) ! 372: { ! 373: pChild = pParent->firstChild; ! 374: } ! 375: ! 376: /* ! 377: * First merge in the child windows at their old places. ! 378: */ ! 379: for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) ! 380: { ! 381: if (pWin->marked) ! 382: { ! 383: (* pScreen->Union) (totalClip, totalClip, pWin->borderClip); ! 384: } ! 385: } ! 386: ! 387: /* ! 388: * Now go through the children of the root and figure their new ! 389: * borderClips from the totalClip, passing that off to miComputeClips ! 390: * to handle recursively. Once that's done, we remove the child ! 391: * from the totalClip to clip any siblings below it. ! 392: */ ! 393: for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) ! 394: { ! 395: if (pWin->viewable) ! 396: { ! 397: if (pWin->marked) ! 398: { ! 399: (* pScreen->Intersect) (childClip, totalClip, pWin->borderSize); ! 400: miComputeClips (pWin, pScreen, childClip); ! 401: (* pScreen->Subtract) (totalClip, totalClip, pWin->borderSize); ! 402: } ! 403: } ! 404: else ! 405: { ! 406: /* ! 407: * Make sure the child is no longer marked (Windows being unmapped ! 408: * are marked but unviewable...) ! 409: */ ! 410: pWin->marked = 0; ! 411: if ((* pScreen->RegionNotEmpty) (pWin->borderClip)) ! 412: { ! 413: /* ! 414: * If the child isn't viewable, it has no business taking up ! 415: * clipping space, so we nuke all its clipping regions. There ! 416: * was a problem with UnmapGravity where the clipList wouldn't ! 417: * get nuked, so drawing operations succeeded while the window ! 418: * was unmapped... ! 419: */ ! 420: (* pScreen->RegionEmpty) (pChild->borderClip); ! 421: (* pScreen->RegionEmpty) (pChild->clipList); ! 422: (* pScreen->RegionEmpty) (pChild->exposed); ! 423: (* pScreen->RegionEmpty) (pChild->borderExposed); ! 424: pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; ! 425: } ! 426: } ! 427: } ! 428: ! 429: /* ! 430: * totalClip contains the new clipList for the parent. Figure out ! 431: * exposures and obscures as per miComputeClips and reset the parent's ! 432: * clipList. ! 433: */ ! 434: (* pScreen->Subtract) (exposed, totalClip, pParent->clipList); ! 435: (* pScreen->Union) (pParent->exposed, pParent->exposed, exposed); ! 436: ! 437: if (pParent->backStorage && (pParent->backingStore != NotUseful)) ! 438: { ! 439: (* pScreen->Subtract) (exposed, pParent->clipList, totalClip); ! 440: (* pScreen->Union) (pParent->backStorage->obscured, ! 441: pParent->backStorage->obscured, ! 442: exposed); ! 443: } ! 444: ! 445: (* pScreen->RegionCopy) (pParent->clipList, totalClip); ! 446: pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; ! 447: pParent->marked = 0; ! 448: ! 449: (* pScreen->RegionDestroy) (childClip); ! 450: ! 451: WindowsRestructured(); ! 452: ! 453: (* pScreen->RegionDestroy) (totalClip); ! 454: ! 455: return (1); ! 456: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.