File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / server / ddx / mi / mivaltree.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

/*
 * mivaltree.c --
 *	Functions for recalculating window clip lists. Main function
 *	is miValidateTree.
 *
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
 * and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
 * 
 *                         All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute this software and its 
 * documentation for any purpose and without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in 
 * supporting documentation, and that the names of Digital or MIT not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  
 * 
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 * 
 ******************************************************************/

 /* 
  * Aug '86: Susan Angebranndt -- original code
  * July '87: Adam de Boor -- substantially modified and commented
  */

#ifndef lint
static char rcsid[] =
"$Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/server/ddx/mi/mivaltree.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $ SPRITE (Berkeley)";
#endif lint

#include    "X.h"
#include    "scrnintstr.h"
#include    "windowstr.h"
#include    "mi.h"
#include    "region.h"

static RegionPtr	exposed = NullRegion;

/*-
 *-----------------------------------------------------------------------
 * miComputeClips --
 *	Recompute the clipList, borderClip, exposed and borderExposed
 *	regions for pParent and its children. Only viewable windows are
 *	taken into account.
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	clipList, borderClip, exposed and borderExposed are altered.
 *	A VisibilityNotify event may be generated on the parent window.
 *
 *-----------------------------------------------------------------------
 */
static void
miComputeClips (pParent, pScreen, universe)
    register WindowPtr	pParent;
    register ScreenPtr	pScreen;
    register RegionPtr	universe;
{
    int			dx,
			dy;
    RegionPtr		childUniverse;
    register WindowPtr	pChild;
    int     	  	oldVis;
    BoxPtr  	  	borderSize;
    
    
    childUniverse = (RegionPtr)NULL;

    /*
     * Figure out the new visibility of this window.
     * The extent of the universe should be the same as the extent of
     * the borderSize region. If the window is unobscured, this rectangle
     * will be completely inside the universe (the universe will cover it
     * completely). If the window is completely obscured, none of the
     * universe will cover the rectangle.
     */
    borderSize = (* pScreen->RegionExtents) (pParent->borderSize);
    
    oldVis = pParent->visibility;
    switch ((* pScreen->RectIn) (universe, borderSize)) 
    {
	case rgnIN:
	    pParent->visibility = VisibilityUnobscured;
	    break;
	case rgnPART:
	    pParent->visibility = VisibilityPartiallyObscured;
	    break;
	default:
	    pParent->visibility = VisibilityFullyObscured;
	    break;
    }
    if (oldVis != pParent->visibility)
	SendVisibilityNotify(pParent);

    /*
     * To calculate exposures correctly, we have to translate the old
     * borderClip and clipList regions to the window's new location so there
     * is a correspondence between pieces of the new and old clipping regions.
     */
    dx = pParent->absCorner.x - pParent->oldAbsCorner.x;
    dy = pParent->absCorner.y - pParent->oldAbsCorner.y;

    if (dx || dy) 
    {
	/*
	 * If the window has moved, the border will *not* be copied, so we
	 * empty the old border clip to force exposure of the whole thing.
	 * We translate the old clipList because that will be exposed or copied
	 * if gravity is right.
	 */
	(* pScreen->RegionEmpty) (pParent->borderClip);
	(* pScreen->TranslateRegion) (pParent->clipList, dx, dy);
	pParent->oldAbsCorner = pParent->absCorner;
    } 
    else if (pParent->borderWidth) 
    {
	/*
	 * If the window has shrunk, we have to be careful about figuring the
	 * exposure of the right and bottom borders -- they should be exposed
	 * if the window shrank on that side and they aren't being obscured
	 * by a sibling -- so we add those edges to the borderExposed region.
	 * This is all necessary because sometimes what was the internal window
	 * in the old borderClip will overlap the new border and cause the
	 * right and bottom edges of the new border not to appear in the
	 * borderExposed region and it's a royal pain to figure out what to
	 * remove from the old borderClip.
	 * XXX: Isn't there a nicer way to do this?
	 */
	BoxPtr	oldExtents;
	BoxPtr	newExtents;
	BoxPtr	windowExtents;
	
	oldExtents = (* pScreen->RegionExtents) (pParent->borderClip);
	newExtents = (* pScreen->RegionExtents) (universe);
	windowExtents = (* pScreen->RegionExtents) (pParent->borderSize);

	if ((* pScreen->RegionNotEmpty) (universe) &&
	    (* pScreen->RegionNotEmpty) (pParent->borderClip) &&
	    ((newExtents->x2 < oldExtents->x2) ||
	     (newExtents->y2 < oldExtents->y2))) 
        {
	    BoxRec 	borderBox;
	    RegionPtr 	borderRegion;

	    borderRegion = (* pScreen->RegionCreate) (NULL, 1);

	    if (newExtents->x2 < oldExtents->x2) 
            {
		/*
		 * Add the right edge.
		 */
		borderBox.x1 = windowExtents->x2 - pParent->borderWidth;
		borderBox.y1 = windowExtents->y1;
		borderBox.x2 = windowExtents->x2;
		borderBox.y2 = windowExtents->y2;
		(* pScreen->RegionReset) (borderRegion, &borderBox);
		(* pScreen->Union) (pParent->borderExposed,
				    pParent->borderExposed,
				    borderRegion);
	    }
	    if (newExtents->y2 < oldExtents->y2) 
            {
		/*
		 * Add the bottom edge.
		 */
		borderBox.x1 = windowExtents->x1;
		borderBox.y1 = windowExtents->y2 - pParent->borderWidth;
		borderBox.x2 = windowExtents->x2;
		borderBox.y2 = windowExtents->y2;
		(* pScreen->RegionReset) (borderRegion, &borderBox);
		(* pScreen->Union) (pParent->borderExposed,
				    pParent->borderExposed,
				    borderRegion);
	    }
	    (* pScreen->RegionDestroy) (borderRegion);

	    /*
	     * To make sure we don't expose a border that's supposed to
	     * be clipped, clip the regions we just added to borderExposed...
	     */
	    (* pScreen->Intersect) (pParent->borderExposed, universe,
				    pParent->borderExposed);
	}
    }

    /*
     * Since the borderClip must not be clipped by the children, we do
     * the border exposure first...
     *
     * 'universe' is the window's borderClip. To figure the exposures, remove
     * the area that used to be exposed (the old borderClip) from the new.
     * This leaves a region of pieces that weren't exposed before. Border
     * exposures accumulate until they're taken care of.
     */
    (* pScreen->Subtract) (exposed, universe, pParent->borderClip);
    (* pScreen->Subtract) (exposed, exposed, pParent->winSize);

    (* pScreen->Union) (pParent->borderExposed, pParent->borderExposed,
			exposed);

    (* pScreen->RegionCopy) (pParent->borderClip, universe);

    /*
     * To get the right clipList for the parent, and to make doubly sure
     * that no child overlaps the parent's border, we remove the parent's
     * border from the universe before proceeding.
     */
    (* pScreen->Intersect) (universe, universe, pParent->winSize);
    
    for (pChild = pParent->firstChild; pChild; pChild = pChild->nextSib) 
    {
	if (pChild->viewable)
        {
	    /*
	     * If the child is viewable, we want to remove its extents from
	     * the current universe, but we only re-clip it if it's been
	     * marked.
	     */
	    if (pChild->marked) 
            {
		/*
		 * Figure out the new universe from the child's perspective and
		 * recurse.
		 */
		if (childUniverse == NullRegion) 
                {
		    childUniverse = (* pScreen->RegionCreate) (NULL, 1);
		}
		(* pScreen->Intersect) (childUniverse, universe,
					pChild->borderSize);
		miComputeClips (pChild, pScreen, childUniverse);
	    }
	    /*
	     * Once the child has been processed, we remove its extents from
	     * the current universe, thus denying its space to any other
	     * sibling.
	     */
	    (* pScreen->Subtract) (universe, universe, pChild->borderSize);
	} 
        else 
        {
	    pChild->marked = 0;
	    if ((* pScreen->RegionNotEmpty) (pChild->borderClip)) 
            {
		/*
		 * If the child isn't viewable, it has no business taking up
		 * clipping space, so we nuke all its clipping regions. There
		 * was a problem with UnmapGravity where the clipList wouldn't
		 * get nuked, so drawing operations succeeded while the window
		 * was unmapped...
		 */
		(* pScreen->RegionEmpty) (pChild->borderClip);
		(* pScreen->RegionEmpty) (pChild->clipList);
		(* pScreen->RegionEmpty) (pChild->exposed);
		(* pScreen->RegionEmpty) (pChild->borderExposed);
		pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
	    }
	}
    }

    /*
     * 'universe' now contains the new clipList for the parent window.
     *
     * To figure the exposure of the window we subtract the old clip from the
     * new, just as for the border. Again, exposures accumulate.
     */
    (* pScreen->Subtract) (exposed, universe, pParent->clipList);
    
    (* pScreen->Union) (pParent->exposed, pParent->exposed, exposed);

    /*
     * One last thing: backing storage. We have to find out what parts of
     * the window are about to be obscured. We can just subtract the universe
     * from the old clipList and get the areas that were in the old but aren't
     * in the new and, hence, are about to be obscured.
     */
    if (pParent->backStorage && (pParent->backingStore != NotUseful)) 
    {
	(* pScreen->Subtract) (exposed, pParent->clipList, universe);
	(* pScreen->Union) (pParent->backStorage->obscured,
			    pParent->backStorage->obscured,
			    exposed);
    }
    
    (* pScreen->RegionCopy) (pParent->clipList, universe);

    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    pParent->marked = 0;

    if (childUniverse) 
	(* pScreen->RegionDestroy) (childUniverse);
}

/*-
 *-----------------------------------------------------------------------
 * miValidateTree --
 *	Recomputes the clip list for pParent and all its inferiors.
 *
 * Results:
 *	Always returns 1.
 *
 * Side Effects:
 *	The clipList, borderClip, exposed, and borderExposed regions for
 *	each marked window are altered.
 *
 * Notes:
 *	This routine assumes that all affected windows have had their
 *	marked fields set true and their winSize and borderSize regions
 *	adjusted to correspond to their new positions. The borderClip and
 *	clipList regions should not have been touched.
 *
 *	The top-most level is treated differently from all lower levels
 *	because pParent is unchanged. For the top level, we merge the
 *	regions taken up by the marked children back into the clipList
 *	for pParent, thus forming a region from which the marked children
 *	can claim their areas. For lower levels, where the old clipList
 *	and borderClip are invalid, we can't do this and have to do the
 *	extra operations done in miComputeClips, but this is much faster
 *	e.g. when only one child has moved...
 *
 *-----------------------------------------------------------------------
 */
/*ARGSUSED*/
int
miValidateTree (pParent, pChild, top, anyMarked)
    WindowPtr	  	pParent;    /* Parent to validate */
    WindowPtr	  	pChild;     /* First child of pParent that was
				     * affected */
    Bool    	  	top;	    /* TRUE if at top level. UNUSED */
    Bool    	  	anyMarked;  /* TRUE if any windows were marked. */
{
    RegionPtr	  	totalClip;  /* Total clipping region available to
				     * the marked children. pParent's clipList
				     * merged with the borderClips of all
				     * the marked children. */
    RegionPtr	  	childClip;  /* The new borderClip for the current
				     * child */
    register ScreenPtr	pScreen;
    register WindowPtr	pWin;

    if (!anyMarked) 
    {
	return (1);
    }
    pScreen = pParent->drawable.pScreen;

    if (exposed == NullRegion) 
    {
	exposed = (* pScreen->RegionCreate) (NULL, 1);
    }

    totalClip = (* pScreen->RegionCreate) (NULL, 1);
    childClip = (* pScreen->RegionCreate) (NULL, 1);

    /*
     * Preserve the parent's old clipList to make calculating exposures
     * easier.
     */
    (* pScreen->RegionCopy) (totalClip, pParent->clipList);

    if (pChild == NullWindow) 
    {
	pChild = pParent->firstChild;
    }
			       
    /*
     * First merge in the child windows at their old places.
     */
    for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) 
    {
	if (pWin->marked) 
        {
	    (* pScreen->Union) (totalClip, totalClip, pWin->borderClip);
	}
    }

    /*
     * Now go through the children of the root and figure their new
     * borderClips from the totalClip, passing that off to miComputeClips
     * to handle recursively. Once that's done, we remove the child
     * from the totalClip to clip any siblings below it.
     */
    for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) 
    {
	if (pWin->viewable) 
        {
	    if (pWin->marked) 
            {
		(* pScreen->Intersect) (childClip, totalClip, pWin->borderSize);
		miComputeClips (pWin, pScreen, childClip);
		(* pScreen->Subtract) (totalClip, totalClip, pWin->borderSize);
	    }
	} 
        else 
        {
	    /*
	     * Make sure the child is no longer marked (Windows being unmapped
	     * are marked but unviewable...)
	     */
	    pWin->marked = 0;
	    if ((* pScreen->RegionNotEmpty) (pWin->borderClip)) 
            {
		/*
		 * If the child isn't viewable, it has no business taking up
		 * clipping space, so we nuke all its clipping regions. There
		 * was a problem with UnmapGravity where the clipList wouldn't
		 * get nuked, so drawing operations succeeded while the window
		 * was unmapped...
		 */
		(* pScreen->RegionEmpty) (pChild->borderClip);
		(* pScreen->RegionEmpty) (pChild->clipList);
		(* pScreen->RegionEmpty) (pChild->exposed);
		(* pScreen->RegionEmpty) (pChild->borderExposed);
		pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
	    }
	}
    }

    /*
     * totalClip contains the new clipList for the parent. Figure out
     * exposures and obscures as per miComputeClips and reset the parent's
     * clipList.
     */
    (* pScreen->Subtract) (exposed, totalClip, pParent->clipList);
    (* pScreen->Union) (pParent->exposed, pParent->exposed, exposed);

    if (pParent->backStorage && (pParent->backingStore != NotUseful)) 
    {
	(* pScreen->Subtract) (exposed, pParent->clipList, totalClip);
	(* pScreen->Union) (pParent->backStorage->obscured,
			    pParent->backStorage->obscured,
			    exposed);
    }
    
    (* pScreen->RegionCopy) (pParent->clipList, totalClip);
    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    pParent->marked = 0;

    (* pScreen->RegionDestroy) (childClip);

    WindowsRestructured();

    (* pScreen->RegionDestroy) (totalClip);

    return (1);
}

unix.superglobalmegacorp.com

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