Exemple #1
0
static Bool
localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen)
{
    FBManagerPtr offman;
    FBLinkPtr pLink, tmp, pPrev = NULL;
    RegionRec FreedRegion;
    Bool anyUsed = FALSE;

    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);
    pLink = offman->UsedAreas;
    if (!pLink)
        return TRUE;

    while (pLink) {
        if (pLink->area.RemoveAreaCallback) {
            (*pLink->area.RemoveAreaCallback) (&pLink->area);

            RegionInit(&FreedRegion, &(pLink->area.box), 1);
            RegionAppend(offman->FreeBoxes, &FreedRegion);
            RegionUninit(&FreedRegion);

            if (pPrev)
                pPrev->next = pLink->next;
            else
                offman->UsedAreas = pLink->next;

            tmp = pLink;
            pLink = pLink->next;
            free(tmp);
            offman->NumUsedAreas--;
            anyUsed = TRUE;
        }
        else {
            pPrev = pLink;
            pLink = pLink->next;
        }
    }

    if (anyUsed) {
        RegionValidate(offman->FreeBoxes, &anyUsed);
        SendCallFreeBoxCallbacks(offman);
    }

    return TRUE;
}
Exemple #2
0
/*ARGSUSED*/
int
miValidateTree (
    WindowPtr		pParent,    /* Parent to validate */
    WindowPtr		pChild,     /* First child of pParent that was
				     * affected */
    VTKind		kind        /* What kind of configuration caused call */
    )
{
    RegionRec	  	totalClip;  /* Total clipping region available to
				     * the marked children. pParent's clipList
				     * merged with the borderClips of all
				     * the marked children. */
    RegionRec	  	childClip;  /* The new borderClip for the current
				     * child */
    RegionRec		childUnion; /* the space covered by borderSize for
				     * all marked children */
    RegionRec		exposed;    /* For intermediate calculations */
    ScreenPtr		pScreen;
    WindowPtr		pWin;
    Bool		overlap;
    int			viewvals;
    Bool		forward;

    pScreen = pParent->drawable.pScreen;
    if (pChild == NullWindow)
	pChild = pParent->firstChild;

    RegionNull(&childClip);
    RegionNull(&exposed);

    /*
     * compute the area of the parent window occupied
     * by the marked children + the parent itself.  This
     * is the area which can be divied up among the marked
     * children in their new configuration.
     */
    RegionNull(&totalClip);
    viewvals = 0;
    if (RegionBroken(&pParent->clipList) &&
	!RegionBroken(&pParent->borderClip))
    {
	kind = VTBroken;
	/*
	 * When rebuilding clip lists after out of memory,
	 * assume everything is busted.
	 */
	forward = TRUE;
	RegionCopy(&totalClip, &pParent->borderClip);
	RegionIntersect(&totalClip, &totalClip, &pParent->winSize);
	
	for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib)
	{
	    if (pWin->viewable && !TreatAsTransparent (pWin))
		RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
	}
	for (pWin = pChild; pWin; pWin = pWin->nextSib)
	    if (pWin->valdata && pWin->viewable)
		viewvals++;
	
	RegionEmpty(&pParent->clipList);
    }
    else 
    {
	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
	{
	    forward = TRUE;
	    for (pWin = pChild; pWin; pWin = pWin->nextSib)
	    {
		if (pWin->valdata)
		{
		    RegionPtr	pBorderClip = &pWin->borderClip;
#ifdef COMPOSITE
		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
#endif
		    RegionAppend(&totalClip, pBorderClip );
		    if (pWin->viewable)
			viewvals++;
		}
	    }
	}
	else
	{
	    forward = FALSE;
	    pWin = pParent->lastChild;
	    while (1)
	    {
		if (pWin->valdata)
		{
		    RegionPtr	pBorderClip = &pWin->borderClip;
#ifdef COMPOSITE
		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
#endif
		    RegionAppend(&totalClip, pBorderClip );
		    if (pWin->viewable)
			viewvals++;
		}
		if (pWin == pChild)
		    break;
		pWin = pWin->prevSib;
	    }
	}
	RegionValidate(&totalClip, &overlap);
    }

    /*
     * 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.
     */

    overlap = TRUE;
    if (kind != VTStack)
    {
	RegionUnion(&totalClip, &totalClip, &pParent->clipList);
	if (viewvals > 1)
	{
	    /*
	     * precompute childUnion to discover whether any of them
	     * overlap.  This seems redundant, but performance studies
	     * have demonstrated that the cost of this loop is
	     * lower than the cost of multiple Subtracts in the
	     * loop below.
	     */
	    RegionNull(&childUnion);
	    if (forward)
	    {
		for (pWin = pChild; pWin; pWin = pWin->nextSib)
		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
			RegionAppend(&childUnion,
						   &pWin->borderSize);
	    }
	    else
	    {
		pWin = pParent->lastChild;
		while (1)
		{
		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
			RegionAppend(&childUnion,
						   &pWin->borderSize);
		    if (pWin == pChild)
			break;
		    pWin = pWin->prevSib;
		}
	    }
	    RegionValidate(&childUnion, &overlap);
	    if (overlap)
		RegionUninit(&childUnion);
	}
    }

    for (pWin = pChild;
	 pWin != NullWindow;
	 pWin = pWin->nextSib)
    {
	if (pWin->viewable) {
	    if (pWin->valdata) {
		RegionIntersect(&childClip,
					&totalClip,
 					&pWin->borderSize);
		miComputeClips (pWin, pScreen, &childClip, kind, &exposed);
		if (overlap && !TreatAsTransparent (pWin))
		{
		    RegionSubtract(&totalClip,
				       	   &totalClip,
				       	   &pWin->borderSize);
		}
	    } else if (pWin->visibility == VisibilityNotViewable) {
		miTreeObscured(pWin);
	    }
	} else {
	    if (pWin->valdata) {
		RegionEmpty(&pWin->clipList);
		if (pScreen->ClipNotify)
		    (* pScreen->ClipNotify) (pWin, 0, 0);
		RegionEmpty(&pWin->borderClip);
		pWin->valdata = NULL;
	    }
	}
    }

    RegionUninit(&childClip);
    if (!overlap)
    {
	RegionSubtract(&totalClip, &totalClip, &childUnion);
	RegionUninit(&childUnion);
    }

    RegionNull(&pParent->valdata->after.exposed);
    RegionNull(&pParent->valdata->after.borderExposed);

    /*
     * each case below is responsible for updating the
     * clipList and serial number for the parent window
     */

    switch (kind) {
    case VTStack:
	break;
    default:
	/*
	 * totalClip contains the new clipList for the parent. Figure out
	 * exposures and obscures as per miComputeClips and reset the parent's
	 * clipList.
	 */
	RegionSubtract(&pParent->valdata->after.exposed,
			       &totalClip, &pParent->clipList);
	/* fall through */
    case VTMap:
	RegionCopy(&pParent->clipList, &totalClip);
	pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
	break;
    }

    RegionUninit(&totalClip);
    RegionUninit(&exposed);
    if (pScreen->ClipNotify)
	(*pScreen->ClipNotify) (pParent, 0, 0);
    return 1;
}
Exemple #3
0
static Bool
localQueryLargestOffscreenArea(ScreenPtr pScreen,
                               int *width, int *height,
                               int granularity, int preferences, int severity)
{
    FBManagerPtr offman;
    RegionPtr newRegion = NULL;
    BoxPtr pbox;
    int nbox;
    int x, w, h, area, oldArea;

    *width = *height = oldArea = 0;

    if (granularity <= 1)
        granularity = 0;

    if ((preferences < 0) || (preferences > 3))
        return FALSE;

    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);
    if (severity < 0)
        severity = 0;
    if (severity > 2)
        severity = 2;

    switch (severity) {
    case 2:
        if (offman->NumUsedAreas) {
            FBLinkPtr pLink;
            RegionRec tmpRegion;

            newRegion = RegionCreate(NULL, 1);
            RegionCopy(newRegion, offman->InitialBoxes);
            pLink = offman->UsedAreas;

            while (pLink) {
                if (!pLink->area.RemoveAreaCallback) {
                    RegionInit(&tmpRegion, &(pLink->area.box), 1);
                    RegionSubtract(newRegion, newRegion, &tmpRegion);
                    RegionUninit(&tmpRegion);
                }
                pLink = pLink->next;
            }

            nbox = RegionNumRects(newRegion);
            pbox = RegionRects(newRegion);
            break;
        }
    case 1:
        if (offman->NumUsedAreas) {
            FBLinkPtr pLink;
            RegionRec tmpRegion;

            newRegion = RegionCreate(NULL, 1);
            RegionCopy(newRegion, offman->FreeBoxes);
            pLink = offman->UsedAreas;

            while (pLink) {
                if (pLink->area.RemoveAreaCallback) {
                    RegionInit(&tmpRegion, &(pLink->area.box), 1);
                    RegionAppend(newRegion, &tmpRegion);
                    RegionUninit(&tmpRegion);
                }
                pLink = pLink->next;
            }

            nbox = RegionNumRects(newRegion);
            pbox = RegionRects(newRegion);
            break;
        }
    default:
        nbox = RegionNumRects(offman->FreeBoxes);
        pbox = RegionRects(offman->FreeBoxes);
        break;
    }

    while (nbox--) {
        x = pbox->x1;
        if (granularity > 1)
            x = ((x + granularity - 1) / granularity) * granularity;

        w = pbox->x2 - x;
        h = pbox->y2 - pbox->y1;
        area = w * h;

        if (w > 0) {
            Bool gotIt = FALSE;

            switch (preferences) {
            case FAVOR_AREA_THEN_WIDTH:
                if ((area > oldArea) || ((area == oldArea) && (w > *width)))
                    gotIt = TRUE;
                break;
            case FAVOR_AREA_THEN_HEIGHT:
                if ((area > oldArea) || ((area == oldArea) && (h > *height)))
                    gotIt = TRUE;
                break;
            case FAVOR_WIDTH_THEN_AREA:
                if ((w > *width) || ((w == *width) && (area > oldArea)))
                    gotIt = TRUE;
                break;
            case FAVOR_HEIGHT_THEN_AREA:
                if ((h > *height) || ((h == *height) && (area > oldArea)))
                    gotIt = TRUE;
                break;
            }
            if (gotIt) {
                *width = w;
                *height = h;
                oldArea = area;
            }
        }
        pbox++;
    }

    if (newRegion)
        RegionDestroy(newRegion);

    return TRUE;
}
Exemple #4
0
/*
 *-----------------------------------------------------------------------
 * 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 (
    WindowPtr	pParent,
    ScreenPtr	pScreen,
    RegionPtr	universe,
    VTKind		kind,
    RegionPtr		exposed ) /* for intermediate calculations */
{
    int			dx,
			dy;
    RegionRec		childUniverse;
    WindowPtr		pChild;
    int     	  	oldVis, newVis;
    BoxRec		borderSize;
    RegionRec		childUnion;
    Bool		overlap;
    RegionPtr		borderVisible;
    /*
     * 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.x1 = pParent->drawable.x - wBorderWidth(pParent);
    borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
    dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
    if (dx > 32767)
	dx = 32767;
    borderSize.x2 = dx;
    dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
    if (dy > 32767)
	dy = 32767;
    borderSize.y2 = dy;

#ifdef COMPOSITE
    /*
     * In redirected drawing case, reset universe to borderSize
     */
    if (pParent->redirectDraw != RedirectDrawNone)
    {
	if (miSetRedirectBorderClipProc)
	{
	    if (TreatAsTransparent (pParent))
		RegionEmpty(universe);
	    (*miSetRedirectBorderClipProc) (pParent, universe);
	}
	RegionCopy(universe, &pParent->borderSize);
    }
#endif

    oldVis = pParent->visibility;
    switch (RegionContainsRect(universe, &borderSize))
    {
	case rgnIN:
	    newVis = VisibilityUnobscured;
	    break;
	case rgnPART:
	    newVis = VisibilityPartiallyObscured;
	    {
		RegionPtr   pBounding;

		if ((pBounding = wBoundingShape (pParent)))
		{
		    switch (miShapedWindowIn (universe, pBounding,
					      &borderSize,
					      pParent->drawable.x,
 					      pParent->drawable.y))
		    {
		    case rgnIN:
			newVis = VisibilityUnobscured;
			break;
		    case rgnOUT:
			newVis = VisibilityFullyObscured;
			break;
		    }
		}
	    }
	    break;
	default:
	    newVis = VisibilityFullyObscured;
	    break;
    }
    pParent->visibility = newVis;
    if (oldVis != newVis &&
	((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
	SendVisibilityNotify(pParent);

    dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
    dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;

    /*
     * avoid computations when dealing with simple operations
     */

    switch (kind) {
    case VTMap:
    case VTStack:
    case VTUnmap:
	break;
    case VTMove:
	if ((oldVis == newVis) &&
	    ((oldVis == VisibilityFullyObscured) ||
	     (oldVis == VisibilityUnobscured)))
	{
	    pChild = pParent;
	    while (1)
	    {
		if (pChild->viewable)
		{
		    if (pChild->visibility != VisibilityFullyObscured)
		    {
			RegionTranslate(&pChild->borderClip,
						      dx, dy);
			RegionTranslate(&pChild->clipList,
						      dx, dy);
			pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
			if (pScreen->ClipNotify)
			    (* pScreen->ClipNotify) (pChild, dx, dy);

		    }
		    if (pChild->valdata)
		    {
			RegionNull(&pChild->valdata->after.borderExposed);
			if (HasParentRelativeBorder(pChild))
			{
			    RegionSubtract(&pChild->valdata->after.borderExposed,
					   &pChild->borderClip,
					   &pChild->winSize);
			}
			RegionNull(&pChild->valdata->after.exposed);
		    }
		    if (pChild->firstChild)
		    {
			pChild = pChild->firstChild;
			continue;
		    }
		}
		while (!pChild->nextSib && (pChild != pParent))
		    pChild = pChild->parent;
		if (pChild == pParent)
		    break;
		pChild = pChild->nextSib;
	    }
	    return;
	}
	/* fall through */
    default:
    	/*
     	 * 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.
     	 */
    	if (dx || dy) 
    	{
	    /*
	     * We translate the old clipList because that will be exposed or copied
	     * if gravity is right.
	     */
	    RegionTranslate(&pParent->borderClip, dx, dy);
	    RegionTranslate(&pParent->clipList, dx, dy);
    	} 
	break;
    case VTBroken:
	RegionEmpty(&pParent->borderClip);
	RegionEmpty(&pParent->clipList);
	break;
    }

    borderVisible = pParent->valdata->before.borderVisible;
    RegionNull(&pParent->valdata->after.borderExposed);
    RegionNull(&pParent->valdata->after.exposed);

    /*
     * 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 from the new.
     * This leaves a region of pieces that weren't exposed before.
     */

    if (HasBorder (pParent))
    {
    	if (borderVisible)
    	{
	    /*
	     * when the border changes shape, the old visible portions
	     * of the border will be saved by DIX in borderVisible --
	     * use that region and destroy it
	     */
	    RegionSubtract(exposed, universe, borderVisible);
	    RegionDestroy(borderVisible);
    	}
    	else
    	{
	    RegionSubtract(exposed, universe, &pParent->borderClip);
    	}
	if (HasParentRelativeBorder(pParent) && (dx || dy))
	    RegionSubtract(&pParent->valdata->after.borderExposed,
				  universe,
				  &pParent->winSize);
	else
	    RegionSubtract(&pParent->valdata->after.borderExposed,
			       exposed, &pParent->winSize);

	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.
     	 */
    
	RegionIntersect(universe, universe, &pParent->winSize);
    }
    else
	RegionCopy(&pParent->borderClip, universe);
    
    if ((pChild = pParent->firstChild) && pParent->mapped)
    {
	RegionNull(&childUniverse);
	RegionNull(&childUnion);
	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
	{
	    for (; pChild; pChild = pChild->nextSib)
	    {
		if (pChild->viewable && !TreatAsTransparent(pChild))
		    RegionAppend(&childUnion, &pChild->borderSize);
	    }
	}
	else
	{
	    for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
	    {
		if (pChild->viewable && !TreatAsTransparent(pChild))
		    RegionAppend(&childUnion, &pChild->borderSize);
	    }
	}
	RegionValidate(&childUnion, &overlap);

	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->valdata) {
		    /*
		     * Figure out the new universe from the child's
		     * perspective and recurse.
		     */
		    RegionIntersect(&childUniverse,
					    universe,
					    &pChild->borderSize);
		    miComputeClips (pChild, pScreen, &childUniverse, kind,
				    exposed);
		}
		/*
		 * Once the child has been processed, we remove its extents
		 * from the current universe, thus denying its space to any
		 * other sibling.
		 */
		if (overlap && !TreatAsTransparent (pChild))
		    RegionSubtract(universe, universe,
					  &pChild->borderSize);
	    }
	}
	if (!overlap)
	    RegionSubtract(universe, universe, &childUnion);
	RegionUninit(&childUnion);
	RegionUninit(&childUniverse);
    } /* if any children */

    /*
     * '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.
     */

    if (oldVis == VisibilityFullyObscured ||
	oldVis == VisibilityNotViewable)
    {
	RegionCopy(&pParent->valdata->after.exposed, universe);
    }
    else if (newVis != VisibilityFullyObscured &&
	     newVis != VisibilityNotViewable)
    {
	RegionSubtract(&pParent->valdata->after.exposed,
			       universe, &pParent->clipList);
    }

    /* HACK ALERT - copying contents of regions, instead of regions */
    {
	RegionRec   tmp;

	tmp = pParent->clipList;
	pParent->clipList = *universe;
	*universe = tmp;
    }

#ifdef NOTDEF
    RegionCopy(&pParent->clipList, universe);
#endif

    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;

    if (pScreen->ClipNotify)
	(* pScreen->ClipNotify) (pParent, dx, dy);
}