Annotation of researchv9/X11/src/X.V11R1/server/ddx/mi/mivaltree.c, revision 1.1.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.