/** * Union the window's accum-dirty and prev-accum-dirty regions with the * incoming region. * Called by crHashtableWalk() via vncspuGetScreenRects(). */ static void WindowDirtyUnionCB(unsigned long key, void *windowData, void *regionData) { WindowInfo *window = (WindowInfo *) windowData; RegionPtr regionUnion = (RegionPtr) regionData; RegionRec accumScrn; /* accumulated region, in screen coords */ Bool overlap; miRegionInit(&accumScrn, NULL, 0); /* init local var */ CRASSERT(miValidRegion(&window->accumDirtyRegion)); CRASSERT(miValidRegion(&window->prevAccumDirtyRegion)); /* crDebug("accum area: %d prev accum: %d", miRegionArea(&window->accumDirtyRegion), miRegionArea(&window->prevAccumDirtyRegion)); */ /* at first, accumScrn region is in window coords */ REGION_UNION(&accumScrn, &window->accumDirtyRegion, &window->prevAccumDirtyRegion); /* intersect with window bounds */ REGION_INTERSECT(&accumScrn, &accumScrn, &window->clipRegion); REGION_VALIDATE(&accumScrn, &overlap); /* change y=0=bottom to y=0=top */ InvertRegion(&accumScrn, window->height ? window->height : 1); if (REGION_NUM_RECTS(&accumScrn) == 1 && accumScrn.extents.x1 == 0 && accumScrn.extents.y1 == 0 && accumScrn.extents.x2 == 1 && accumScrn.extents.y2 == 1) { /* empty / sentinal region */ } else { /* add window offset */ miTranslateRegion(&accumScrn, window->xPos, window->yPos); } /* now, accumScrn region is in screen coords */ REGION_UNION(regionUnion, regionUnion, &accumScrn); REGION_UNINIT(&accumScrn); /* done with local var */ }
static Bool localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen) { FBManagerPtr offman; FBLinkPtr pLink, tmp, pPrev = NULL; RegionRec FreedRegion; Bool anyUsed = FALSE; offman = pScreen->devPrivates[xf86FBScreenIndex].ptr; pLink = offman->UsedAreas; if(!pLink) return TRUE; while(pLink) { if(pLink->area.RemoveAreaCallback) { (*pLink->area.RemoveAreaCallback)(&pLink->area); REGION_INIT(pScreen, &FreedRegion, &(pLink->area.box), 1); REGION_APPEND(pScreen, offman->FreeBoxes, &FreedRegion); REGION_UNINIT(pScreen, &FreedRegion); if(pPrev) pPrev->next = pLink->next; else offman->UsedAreas = pLink->next; tmp = pLink; pLink = pLink->next; xfree(tmp); offman->NumUsedAreas--; anyUsed = TRUE; } else { pPrev = pLink; pLink = pLink->next; } } if(anyUsed) { REGION_VALIDATE(pScreen, offman->FreeBoxes, &anyUsed); SendCallFreeBoxCallbacks(offman); } return TRUE; }
/* *----------------------------------------------------------------------- * RootlessComputeClips -- * 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 RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, RegionPtr universe, VTKind kind, RegionPtr exposed) { int dx, dy; RegionRec childUniverse; register WindowPtr pChild; int oldVis, newVis; BoxRec borderSize; RegionRec childUnion; Bool overlap; RegionPtr borderVisible; Bool resized; /* * 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; oldVis = pParent->visibility; switch (RECT_IN_REGION( pScreen, universe, &borderSize)) { case rgnIN: newVis = VisibilityUnobscured; break; case rgnPART: newVis = VisibilityPartiallyObscured; { RegionPtr pBounding; if ((pBounding = wBoundingShape (pParent))) { switch (RootlessShapedWindowIn (pScreen, 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) { REGION_TRANSLATE( pScreen, &pChild->borderClip, dx, dy); REGION_TRANSLATE( pScreen, &pChild->clipList, dx, dy); pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; if (pScreen->ClipNotify) (* pScreen->ClipNotify) (pChild, dx, dy); } if (pChild->valdata) { REGION_NULL(pScreen, &pChild->valdata->after.borderExposed); if (HasParentRelativeBorder(pChild)) { REGION_SUBTRACT(pScreen, &pChild->valdata->after.borderExposed, &pChild->borderClip, &pChild->winSize); } REGION_NULL(pScreen, &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. */ REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy); REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy); } break; case VTBroken: REGION_EMPTY (pScreen, &pParent->borderClip); REGION_EMPTY (pScreen, &pParent->clipList); break; } borderVisible = pParent->valdata->before.borderVisible; resized = pParent->valdata->before.resized; REGION_NULL(pScreen, &pParent->valdata->after.borderExposed); REGION_NULL(pScreen, &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 */ REGION_SUBTRACT( pScreen, exposed, universe, borderVisible); REGION_DESTROY( pScreen, borderVisible); } else { REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip); } if (HasParentRelativeBorder(pParent) && (dx || dy)) { REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, universe, &pParent->winSize); } else { REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, exposed, &pParent->winSize); } REGION_COPY( pScreen, &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. */ REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize); } else REGION_COPY( pScreen, &pParent->borderClip, universe); if ((pChild = pParent->firstChild) && pParent->mapped) { REGION_NULL(pScreen, &childUniverse); REGION_NULL(pScreen, &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) REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); } } else { for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) { if (pChild->viewable) REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); } } REGION_VALIDATE( pScreen, &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. */ REGION_INTERSECT( pScreen, &childUniverse, universe, &pChild->borderSize); RootlessComputeClips (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) REGION_SUBTRACT( pScreen, universe, universe, &pChild->borderSize); } } if (!overlap) REGION_SUBTRACT( pScreen, universe, universe, &childUnion); REGION_UNINIT( pScreen, &childUnion); REGION_UNINIT( pScreen, &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) { REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe); } else if (newVis != VisibilityFullyObscured && newVis != VisibilityNotViewable) { REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed, universe, &pParent->clipList); } /* * One last thing: backing storage. We have to try to save 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 && !resized) { REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe); (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy); } /* HACK ALERT - copying contents of regions, instead of regions */ { RegionRec tmp; tmp = pParent->clipList; pParent->clipList = *universe; *universe = tmp; } #ifdef NOTDEF REGION_COPY( pScreen, &pParent->clipList, universe); #endif pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; if (pScreen->ClipNotify) (* pScreen->ClipNotify) (pParent, dx, dy); }