Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/mivaltree.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.