diff options
Diffstat (limited to 'xorg-server/mi/mioverlay.c')
-rw-r--r-- | xorg-server/mi/mioverlay.c | 3846 |
1 files changed, 1900 insertions, 1946 deletions
diff --git a/xorg-server/mi/mioverlay.c b/xorg-server/mi/mioverlay.c index 76484c275..f72159e73 100644 --- a/xorg-server/mi/mioverlay.c +++ b/xorg-server/mi/mioverlay.c @@ -1,1946 +1,1900 @@ -
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include "scrnintstr.h"
-#include <X11/extensions/shapeproto.h>
-#include "validate.h"
-#include "windowstr.h"
-#include "mi.h"
-#include "gcstruct.h"
-#include "regionstr.h"
-#include "privates.h"
-#include "mivalidate.h"
-#include "mioverlay.h"
-#include "migc.h"
-
-#include "globals.h"
-
-
-typedef struct {
- RegionRec exposed;
- RegionRec borderExposed;
- RegionPtr borderVisible;
- DDXPointRec oldAbsCorner;
-} miOverlayValDataRec, *miOverlayValDataPtr;
-
-typedef struct _TreeRec {
- WindowPtr pWin;
- struct _TreeRec *parent;
- struct _TreeRec *firstChild;
- struct _TreeRec *lastChild;
- struct _TreeRec *prevSib;
- struct _TreeRec *nextSib;
- RegionRec borderClip;
- RegionRec clipList;
- unsigned visibility;
- miOverlayValDataPtr valdata;
-} miOverlayTreeRec, *miOverlayTreePtr;
-
-typedef struct {
- miOverlayTreePtr tree;
-} miOverlayWindowRec, *miOverlayWindowPtr;
-
-typedef struct {
- CloseScreenProcPtr CloseScreen;
- CreateWindowProcPtr CreateWindow;
- DestroyWindowProcPtr DestroyWindow;
- UnrealizeWindowProcPtr UnrealizeWindow;
- RealizeWindowProcPtr RealizeWindow;
- miOverlayTransFunc MakeTransparent;
- miOverlayInOverlayFunc InOverlay;
- Bool underlayMarked;
- Bool copyUnderlay;
-} miOverlayScreenRec, *miOverlayScreenPtr;
-
-static DevPrivateKeyRec miOverlayWindowKeyRec;
-#define miOverlayWindowKey (&miOverlayWindowKeyRec)
-static DevPrivateKeyRec miOverlayScreenKeyRec;
-#define miOverlayScreenKey (&miOverlayScreenKeyRec)
-
-static void RebuildTree(WindowPtr);
-static Bool HasUnderlayChildren(WindowPtr);
-static void MarkUnderlayWindow(WindowPtr);
-static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr);
-
-static Bool miOverlayCloseScreen(int, ScreenPtr);
-static Bool miOverlayCreateWindow(WindowPtr);
-static Bool miOverlayDestroyWindow(WindowPtr);
-static Bool miOverlayUnrealizeWindow(WindowPtr);
-static Bool miOverlayRealizeWindow(WindowPtr);
-static void miOverlayMarkWindow(WindowPtr);
-static void miOverlayReparentWindow(WindowPtr, WindowPtr);
-static void miOverlayRestackWindow(WindowPtr, WindowPtr);
-static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr*);
-static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool);
-static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind);
-static void miOverlayHandleExposures(WindowPtr);
-static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind);
-static void miOverlayWindowExposures(WindowPtr, RegionPtr, RegionPtr);
-static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int,
- unsigned int, WindowPtr);
-static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool);
-
-static void miOverlaySetShape(WindowPtr, int);
-static void miOverlayChangeBorderWidth(WindowPtr, unsigned int);
-
-#define MIOVERLAY_GET_SCREEN_PRIVATE(pScreen) ((miOverlayScreenPtr) \
- dixLookupPrivate(&(pScreen)->devPrivates, miOverlayScreenKey))
-#define MIOVERLAY_GET_WINDOW_PRIVATE(pWin) ((miOverlayWindowPtr) \
- dixLookupPrivate(&(pWin)->devPrivates, miOverlayWindowKey))
-#define MIOVERLAY_GET_WINDOW_TREE(pWin) \
- (MIOVERLAY_GET_WINDOW_PRIVATE(pWin)->tree)
-
-#define IN_UNDERLAY(w) MIOVERLAY_GET_WINDOW_TREE(w)
-#define IN_OVERLAY(w) !MIOVERLAY_GET_WINDOW_TREE(w)
-
-#define MARK_OVERLAY(w) miMarkWindow(w)
-#define MARK_UNDERLAY(w) MarkUnderlayWindow(w)
-
-#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
- HasBorder(w) && \
- (w)->backgroundState == ParentRelative)
-
-Bool
-miInitOverlay(
- ScreenPtr pScreen,
- miOverlayInOverlayFunc inOverlayFunc,
- miOverlayTransFunc transFunc
-){
- miOverlayScreenPtr pScreenPriv;
-
- if(!inOverlayFunc || !transFunc) return FALSE;
-
- if(!dixRegisterPrivateKey(&miOverlayWindowKeyRec, PRIVATE_WINDOW, sizeof(miOverlayWindowRec)))
- return FALSE;
-
- if(!dixRegisterPrivateKey(&miOverlayScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if(!(pScreenPriv = malloc(sizeof(miOverlayScreenRec))))
- return FALSE;
-
- dixSetPrivate(&pScreen->devPrivates, miOverlayScreenKey, pScreenPriv);
-
- pScreenPriv->InOverlay = inOverlayFunc;
- pScreenPriv->MakeTransparent = transFunc;
- pScreenPriv->underlayMarked = FALSE;
-
-
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreenPriv->CreateWindow = pScreen->CreateWindow;
- pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
- pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow;
- pScreenPriv->RealizeWindow = pScreen->RealizeWindow;
-
- pScreen->CloseScreen = miOverlayCloseScreen;
- pScreen->CreateWindow = miOverlayCreateWindow;
- pScreen->DestroyWindow = miOverlayDestroyWindow;
- pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
- pScreen->RealizeWindow = miOverlayRealizeWindow;
-
- pScreen->ReparentWindow = miOverlayReparentWindow;
- pScreen->RestackWindow = miOverlayRestackWindow;
- pScreen->MarkOverlappedWindows = miOverlayMarkOverlappedWindows;
- pScreen->MarkUnrealizedWindow = miOverlayMarkUnrealizedWindow;
- pScreen->ValidateTree = miOverlayValidateTree;
- pScreen->HandleExposures = miOverlayHandleExposures;
- pScreen->MoveWindow = miOverlayMoveWindow;
- pScreen->WindowExposures = miOverlayWindowExposures;
- pScreen->ResizeWindow = miOverlayResizeWindow;
- pScreen->MarkWindow = miOverlayMarkWindow;
- pScreen->ClearToBackground = miOverlayClearToBackground;
- pScreen->SetShape = miOverlaySetShape;
- pScreen->ChangeBorderWidth = miOverlayChangeBorderWidth;
-
- return TRUE;
-}
-
-
-static Bool
-miOverlayCloseScreen(int i, ScreenPtr pScreen)
-{
- miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
-
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- pScreen->CreateWindow = pScreenPriv->CreateWindow;
- pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
- pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
- pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
-
- free(pScreenPriv);
-
- return (*pScreen->CloseScreen)(i, pScreen);
-}
-
-
-static Bool
-miOverlayCreateWindow(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- miOverlayWindowPtr pWinPriv = MIOVERLAY_GET_WINDOW_PRIVATE(pWin);
- miOverlayTreePtr pTree = NULL;
- Bool result = TRUE;
-
- pWinPriv->tree = NULL;
-
- if(!pWin->parent || !((*pScreenPriv->InOverlay)(pWin))) {
- if(!(pTree = (miOverlayTreePtr)calloc(1, sizeof(miOverlayTreeRec))))
- return FALSE;
- }
-
- if(pScreenPriv->CreateWindow) {
- pScreen->CreateWindow = pScreenPriv->CreateWindow;
- result = (*pScreen->CreateWindow)(pWin);
- pScreen->CreateWindow = miOverlayCreateWindow;
- }
-
- if (pTree) {
- if(result) {
- pTree->pWin = pWin;
- pTree->visibility = VisibilityNotViewable;
- pWinPriv->tree = pTree;
- if(pWin->parent) {
- RegionNull(&(pTree->borderClip));
- RegionNull(&(pTree->clipList));
- RebuildTree(pWin);
- } else {
- BoxRec fullBox;
- fullBox.x1 = 0;
- fullBox.y1 = 0;
- fullBox.x2 = pScreen->width;
- fullBox.y2 = pScreen->height;
- RegionInit(&(pTree->borderClip), &fullBox, 1);
- RegionInit(&(pTree->clipList), &fullBox, 1);
- }
- } else free(pTree);
- }
-
- return TRUE;
-}
-
-
-static Bool
-miOverlayDestroyWindow(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- Bool result = TRUE;
-
- if (pTree) {
- if(pTree->prevSib)
- pTree->prevSib->nextSib = pTree->nextSib;
- else if(pTree->parent)
- pTree->parent->firstChild = pTree->nextSib;
-
- if(pTree->nextSib)
- pTree->nextSib->prevSib = pTree->prevSib;
- else if(pTree->parent)
- pTree->parent->lastChild = pTree->prevSib;
-
- RegionUninit(&(pTree->borderClip));
- RegionUninit(&(pTree->clipList));
- free(pTree);
- }
-
- if(pScreenPriv->DestroyWindow) {
- pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
- result = (*pScreen->DestroyWindow)(pWin);
- pScreen->DestroyWindow = miOverlayDestroyWindow;
- }
-
- return result;
-}
-
-static Bool
-miOverlayUnrealizeWindow(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- Bool result = TRUE;
-
- if(pTree) pTree->visibility = VisibilityNotViewable;
-
- if(pScreenPriv->UnrealizeWindow) {
- pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
- result = (*pScreen->UnrealizeWindow)(pWin);
- pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
- }
-
- return result;
-}
-
-
-static Bool
-miOverlayRealizeWindow(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- Bool result = TRUE;
-
- if(pScreenPriv->RealizeWindow) {
- pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
- result = (*pScreen->RealizeWindow)(pWin);
- pScreen->RealizeWindow = miOverlayRealizeWindow;
- }
-
- /* we only need to catch the root window realization */
-
- if(result && !pWin->parent && !((*pScreenPriv->InOverlay)(pWin)))
- {
- BoxRec box;
- box.x1 = box.y1 = 0;
- box.x2 = pWin->drawable.width;
- box.y2 = pWin->drawable.height;
- (*pScreenPriv->MakeTransparent)(pScreen, 1, &box);
- }
-
- return result;
-}
-
-
-static void
-miOverlayReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
-{
- if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
- /* This could probably be more optimal */
- RebuildTree(pWin->drawable.pScreen->root->firstChild);
- }
-}
-
-static void
-miOverlayRestackWindow(WindowPtr pWin, WindowPtr oldNextSib)
-{
- if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
- /* This could probably be more optimal */
- RebuildTree(pWin);
- }
-}
-
-
-static Bool
-miOverlayMarkOverlappedWindows(
- WindowPtr pWin,
- WindowPtr pFirst,
- WindowPtr *pLayerWin
-){
- WindowPtr pChild, pLast;
- Bool overMarked, underMarked, doUnderlay, markAll;
- miOverlayTreePtr pTree = NULL, tLast, tChild;
- BoxPtr box;
-
- overMarked = underMarked = markAll = FALSE;
-
- if(pLayerWin) *pLayerWin = pWin; /* hah! */
-
- doUnderlay = (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin));
-
- box = RegionExtents(&pWin->borderSize);
-
- if((pChild = pFirst)) {
- pLast = pChild->parent->lastChild;
- while (1) {
- if (pChild == pWin) markAll = TRUE;
-
- if(doUnderlay && IN_UNDERLAY(pChild))
- pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
-
- if(pChild->viewable) {
- if (RegionBroken(&pChild->winSize))
- SetWinSize (pChild);
- if (RegionBroken(&pChild->borderSize))
- SetBorderSize (pChild);
-
- if (markAll ||
- RegionContainsRect(&pChild->borderSize, box))
- {
- MARK_OVERLAY(pChild);
- overMarked = TRUE;
- if(doUnderlay && IN_UNDERLAY(pChild)) {
- MARK_UNDERLAY(pChild);
- underMarked = TRUE;
- }
- if (pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
- }
- }
- while (!pChild->nextSib && (pChild != pLast)) {
- pChild = pChild->parent;
- if(doUnderlay && IN_UNDERLAY(pChild))
- pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
- }
-
- if(pChild == pWin) markAll = FALSE;
-
- if (pChild == pLast) break;
-
- pChild = pChild->nextSib;
- }
- if(overMarked)
- MARK_OVERLAY(pWin->parent);
- }
-
- if(doUnderlay && !pTree) {
- if(!(pTree = MIOVERLAY_GET_WINDOW_TREE(pWin))) {
- pChild = pWin->lastChild;
- while(1) {
- if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild)))
- break;
-
- if(pChild->lastChild) {
- pChild = pChild->lastChild;
- continue;
- }
-
- while(!pChild->prevSib) pChild = pChild->parent;
-
- pChild = pChild->prevSib;
- }
- }
- }
-
- if(pTree && pTree->nextSib) {
- tChild = pTree->parent->lastChild;
- tLast = pTree->nextSib;
-
- while(1) {
- if(tChild->pWin->viewable) {
- if (RegionBroken(&tChild->pWin->winSize))
- SetWinSize (tChild->pWin);
- if (RegionBroken(&tChild->pWin->borderSize))
- SetBorderSize (tChild->pWin);
-
- if(RegionContainsRect(&(tChild->pWin->borderSize), box))
- {
- MARK_UNDERLAY(tChild->pWin);
- underMarked = TRUE;
- }
- }
-
- if(tChild->lastChild) {
- tChild = tChild->lastChild;
- continue;
- }
-
- while(!tChild->prevSib && (tChild != tLast))
- tChild = tChild->parent;
-
- if(tChild == tLast) break;
-
- tChild = tChild->prevSib;
- }
- }
-
- if(underMarked) {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- MARK_UNDERLAY(pTree->parent->pWin);
- MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->underlayMarked = TRUE;
- }
-
- return underMarked || overMarked;
-}
-
-
-static void
-miOverlayComputeClips(
- WindowPtr pParent,
- RegionPtr universe,
- VTKind kind,
- RegionPtr exposed
-){
- ScreenPtr pScreen = pParent->drawable.pScreen;
- int oldVis, newVis, dx, dy;
- BoxRec borderSize;
- RegionPtr borderVisible;
- RegionRec childUniverse, childUnion;
- miOverlayTreePtr tParent = MIOVERLAY_GET_WINDOW_TREE(pParent);
- miOverlayTreePtr tChild;
- Bool overlap;
-
- 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 = tParent->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;
- }
- tParent->visibility = newVis;
-
- dx = pParent->drawable.x - tParent->valdata->oldAbsCorner.x;
- dy = pParent->drawable.y - tParent->valdata->oldAbsCorner.y;
-
- switch (kind) {
- case VTMap:
- case VTStack:
- case VTUnmap:
- break;
- case VTMove:
- if ((oldVis == newVis) &&
- ((oldVis == VisibilityFullyObscured) ||
- (oldVis == VisibilityUnobscured)))
- {
- tChild = tParent;
- while (1) {
- if (tChild->pWin->viewable) {
- if (tChild->visibility != VisibilityFullyObscured) {
- RegionTranslate(&tChild->borderClip, dx, dy);
- RegionTranslate(&tChild->clipList, dx, dy);
-
- tChild->pWin->drawable.serialNumber =
- NEXT_SERIAL_NUMBER;
- if (pScreen->ClipNotify)
- (* pScreen->ClipNotify) (tChild->pWin, dx, dy);
- }
- if (tChild->valdata) {
- RegionNull(&tChild->valdata->borderExposed);
- if (HasParentRelativeBorder(tChild->pWin)){
- RegionSubtract(&tChild->valdata->borderExposed,
- &tChild->borderClip,
- &tChild->pWin->winSize);
- }
- RegionNull(&tChild->valdata->exposed);
- }
- if (tChild->firstChild) {
- tChild = tChild->firstChild;
- continue;
- }
- }
- while (!tChild->nextSib && (tChild != tParent))
- tChild = tChild->parent;
- if (tChild == tParent)
- break;
- tChild = tChild->nextSib;
- }
- return;
- }
- /* fall through */
- default:
- if (dx || dy) {
- RegionTranslate(&tParent->borderClip, dx, dy);
- RegionTranslate(&tParent->clipList, dx, dy);
- }
- break;
- case VTBroken:
- RegionEmpty(&tParent->borderClip);
- RegionEmpty(&tParent->clipList);
- break;
- }
-
- borderVisible = tParent->valdata->borderVisible;
- RegionNull(&tParent->valdata->borderExposed);
- RegionNull(&tParent->valdata->exposed);
-
- if (HasBorder (pParent)) {
- if (borderVisible) {
- RegionSubtract(exposed, universe, borderVisible);
- RegionDestroy(borderVisible);
- } else
- RegionSubtract(exposed, universe, &tParent->borderClip);
-
- if (HasParentRelativeBorder(pParent) && (dx || dy))
- RegionSubtract(&tParent->valdata->borderExposed,
- universe, &pParent->winSize);
- else
- RegionSubtract(&tParent->valdata->borderExposed,
- exposed, &pParent->winSize);
-
- RegionCopy(&tParent->borderClip, universe);
- RegionIntersect(universe, universe, &pParent->winSize);
- }
- else
- RegionCopy(&tParent->borderClip, universe);
-
- if ((tChild = tParent->firstChild) && pParent->mapped) {
- RegionNull(&childUniverse);
- RegionNull(&childUnion);
-
- for (; tChild; tChild = tChild->nextSib) {
- if (tChild->pWin->viewable)
- RegionAppend(&childUnion, &tChild->pWin->borderSize);
- }
-
- RegionValidate(&childUnion, &overlap);
-
- for (tChild = tParent->firstChild;
- tChild;
- tChild = tChild->nextSib)
- {
- if (tChild->pWin->viewable) {
- if (tChild->valdata) {
- RegionIntersect(&childUniverse, universe,
- &tChild->pWin->borderSize);
- miOverlayComputeClips (tChild->pWin, &childUniverse,
- kind, exposed);
- }
- if (overlap)
- RegionSubtract(universe, universe,
- &tChild->pWin->borderSize);
- }
- }
- if (!overlap)
- RegionSubtract(universe, universe, &childUnion);
- RegionUninit(&childUnion);
- RegionUninit(&childUniverse);
- }
-
- if (oldVis == VisibilityFullyObscured ||
- oldVis == VisibilityNotViewable)
- {
- RegionCopy(&tParent->valdata->exposed, universe);
- }
- else if (newVis != VisibilityFullyObscured &&
- newVis != VisibilityNotViewable)
- {
- RegionSubtract(&tParent->valdata->exposed,
- universe, &tParent->clipList);
- }
-
- /* HACK ALERT - copying contents of regions, instead of regions */
- {
- RegionRec tmp;
-
- tmp = tParent->clipList;
- tParent->clipList = *universe;
- *universe = tmp;
- }
-
- pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
-
- if (pScreen->ClipNotify)
- (* pScreen->ClipNotify) (pParent, dx, dy);
-}
-
-
-static void
-miOverlayMarkWindow(WindowPtr pWin)
-{
- miOverlayTreePtr pTree = NULL;
- WindowPtr pChild, pGrandChild;
-
- miMarkWindow(pWin);
-
- /* look for UnmapValdata among immediate children */
-
- if(!(pChild = pWin->firstChild)) return;
-
- for( ; pChild; pChild = pChild->nextSib) {
- if(pChild->valdata == UnmapValData) {
- if(IN_UNDERLAY(pChild)) {
- pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
- pTree->valdata = (miOverlayValDataPtr)UnmapValData;
- continue;
- } else {
- if(!(pGrandChild = pChild->firstChild))
- continue;
-
- while(1) {
- if(IN_UNDERLAY(pGrandChild)) {
- pTree = MIOVERLAY_GET_WINDOW_TREE(pGrandChild);
- pTree->valdata = (miOverlayValDataPtr)UnmapValData;
- } else if(pGrandChild->firstChild) {
- pGrandChild = pGrandChild->firstChild;
- continue;
- }
-
- while(!pGrandChild->nextSib && (pGrandChild != pChild))
- pGrandChild = pGrandChild->parent;
-
- if(pChild == pGrandChild) break;
-
- pGrandChild = pGrandChild->nextSib;
- }
- }
- }
- }
-
- if(pTree) {
- MARK_UNDERLAY(pTree->parent->pWin);
- MIOVERLAY_GET_SCREEN_PRIVATE(
- pWin->drawable.pScreen)->underlayMarked = TRUE;
- }
-}
-
-static void
-miOverlayMarkUnrealizedWindow(
- WindowPtr pChild,
- WindowPtr pWin,
- Bool fromConfigure
-){
- if ((pChild != pWin) || fromConfigure) {
- miOverlayTreePtr pTree;
-
- RegionEmpty(&pChild->clipList);
- if (pChild->drawable.pScreen->ClipNotify)
- (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
- RegionEmpty(&pChild->borderClip);
- if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
- if(pTree->valdata != (miOverlayValDataPtr)UnmapValData) {
- RegionEmpty(&pTree->clipList);
- RegionEmpty(&pTree->borderClip);
- }
- }
- }
-}
-
-
-static int
-miOverlayValidateTree(
- WindowPtr pParent,
- WindowPtr pChild, /* first child effected */
- VTKind kind
-){
- ScreenPtr pScreen = pParent->drawable.pScreen;
- miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- RegionRec totalClip, childClip, exposed;
- miOverlayTreePtr tParent, tChild, tWin;
- Bool overlap;
- WindowPtr newParent;
-
- if(!pPriv->underlayMarked)
- goto SKIP_UNDERLAY;
-
- if (!pChild) pChild = pParent->firstChild;
-
- RegionNull(&totalClip);
- RegionNull(&childClip);
- RegionNull(&exposed);
-
- newParent = pParent;
-
- while(IN_OVERLAY(newParent))
- newParent = newParent->parent;
-
- tParent = MIOVERLAY_GET_WINDOW_TREE(newParent);
-
- if(IN_UNDERLAY(pChild))
- tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
- else
- tChild = tParent->firstChild;
-
- if (RegionBroken(&tParent->clipList) &&
- !RegionBroken(&tParent->borderClip))
- {
- kind = VTBroken;
- RegionCopy(&totalClip, &tParent->borderClip);
- RegionIntersect(&totalClip, &totalClip,
- &tParent->pWin->winSize);
-
- for (tWin = tParent->firstChild; tWin != tChild; tWin = tWin->nextSib) {
- if (tWin->pWin->viewable)
- RegionSubtract(&totalClip, &totalClip,
- &tWin->pWin->borderSize);
- }
- RegionEmpty(&tParent->clipList);
- } else {
- for(tWin = tChild; tWin; tWin = tWin->nextSib) {
- if(tWin->valdata)
- RegionAppend(&totalClip, &tWin->borderClip);
- }
- RegionValidate(&totalClip, &overlap);
- }
-
- if(kind != VTStack)
- RegionUnion(&totalClip, &totalClip, &tParent->clipList);
-
- for(tWin = tChild; tWin; tWin = tWin->nextSib) {
- if(tWin->valdata) {
- if(tWin->pWin->viewable) {
- RegionIntersect(&childClip, &totalClip,
- &tWin->pWin->borderSize);
- miOverlayComputeClips(tWin->pWin, &childClip, kind, &exposed);
- RegionSubtract(&totalClip, &totalClip,
- &tWin->pWin->borderSize);
- } else { /* Means we are unmapping */
- RegionEmpty(&tWin->clipList);
- RegionEmpty(&tWin->borderClip);
- tWin->valdata = NULL;
- }
- }
- }
-
- RegionUninit(&childClip);
-
- if(!((*pPriv->InOverlay)(newParent))) {
- RegionNull(&tParent->valdata->exposed);
- RegionNull(&tParent->valdata->borderExposed);
- }
-
- switch (kind) {
- case VTStack:
- break;
- default:
- if(!((*pPriv->InOverlay)(newParent)))
- RegionSubtract(&tParent->valdata->exposed, &totalClip,
- &tParent->clipList);
- /* fall through */
- case VTMap:
- RegionCopy(&tParent->clipList, &totalClip);
- if(!((*pPriv->InOverlay)(newParent)))
- newParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
- break;
- }
-
- RegionUninit(&totalClip);
- RegionUninit(&exposed);
-
-SKIP_UNDERLAY:
-
- miValidateTree(pParent, pChild, kind);
-
- return 1;
-}
-
-
-static void
-miOverlayHandleExposures(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- WindowPtr pChild;
- ValidatePtr val;
- void (* WindowExposures)(WindowPtr, RegionPtr, RegionPtr);
-
- WindowExposures = pWin->drawable.pScreen->WindowExposures;
- if(pPriv->underlayMarked) {
- miOverlayTreePtr pTree;
- miOverlayValDataPtr mival;
-
- pChild = pWin;
- while(IN_OVERLAY(pChild))
- pChild = pChild->parent;
-
- pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
-
- while (1) {
- if((mival = pTree->valdata)) {
- if(!((*pPriv->InOverlay)(pTree->pWin))) {
- if (RegionNotEmpty(&mival->borderExposed)) {
- miPaintWindow(pTree->pWin, &mival->borderExposed,
- PW_BORDER);
- }
- RegionUninit(&mival->borderExposed);
-
- (*WindowExposures)(pTree->pWin,&mival->exposed,NullRegion);
- RegionUninit(&mival->exposed);
- }
- free(mival);
- pTree->valdata = NULL;
- if (pTree->firstChild) {
- pTree = pTree->firstChild;
- continue;
- }
- }
- while (!pTree->nextSib && (pTree->pWin != pChild))
- pTree = pTree->parent;
- if (pTree->pWin == pChild)
- break;
- pTree = pTree->nextSib;
- }
- pPriv->underlayMarked = FALSE;
- }
-
- pChild = pWin;
- while (1) {
- if ( (val = pChild->valdata) ) {
- if(!((*pPriv->InOverlay)(pChild))) {
- RegionUnion(&val->after.exposed, &val->after.exposed,
- &val->after.borderExposed);
-
- if (RegionNotEmpty(&val->after.exposed)) {
- (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent))(
- pScreen,
- RegionNumRects(&val->after.exposed),
- RegionRects(&val->after.exposed));
- }
- } else {
- if (RegionNotEmpty(&val->after.borderExposed)) {
- miPaintWindow(pChild, &val->after.borderExposed,
- PW_BORDER);
- }
- (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
- }
- RegionUninit(&val->after.borderExposed);
- RegionUninit(&val->after.exposed);
- free(val);
- pChild->valdata = NULL;
- if (pChild->firstChild)
- {
- pChild = pChild->firstChild;
- continue;
- }
- }
- while (!pChild->nextSib && (pChild != pWin))
- pChild = pChild->parent;
- if (pChild == pWin)
- break;
- pChild = pChild->nextSib;
- }
-}
-
-
-static void
-miOverlayMoveWindow(
- WindowPtr pWin,
- int x,
- int y,
- WindowPtr pNextSib,
- VTKind kind
-){
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- WindowPtr pParent, windowToValidate;
- Bool WasViewable = (Bool)(pWin->viewable);
- short bw;
- RegionRec overReg, underReg;
- DDXPointRec oldpt;
-
- if (!(pParent = pWin->parent))
- return ;
- bw = wBorderWidth (pWin);
-
- oldpt.x = pWin->drawable.x;
- oldpt.y = pWin->drawable.y;
- if (WasViewable) {
- RegionNull(&overReg);
- RegionNull(&underReg);
- if(pTree) {
- RegionCopy(&overReg, &pWin->borderClip);
- RegionCopy(&underReg, &pTree->borderClip);
- } else {
- RegionCopy(&overReg, &pWin->borderClip);
- CollectUnderlayChildrenRegions(pWin, &underReg);
- }
- (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
- }
- pWin->origin.x = x + (int)bw;
- pWin->origin.y = y + (int)bw;
- x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
- y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
-
- SetWinSize (pWin);
- SetBorderSize (pWin);
-
- (*pScreen->PositionWindow)(pWin, x, y);
-
- windowToValidate = MoveWindowInStack(pWin, pNextSib);
-
- ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
-
- if (WasViewable) {
- miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- (*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL);
-
-
- (*pScreen->ValidateTree)(pWin->parent, NullWindow, kind);
- if(RegionNotEmpty(&underReg)) {
- pPriv->copyUnderlay = TRUE;
- (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &underReg);
- }
- RegionUninit(&underReg);
- if(RegionNotEmpty(&overReg)) {
- pPriv->copyUnderlay = FALSE;
- (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &overReg);
- }
- RegionUninit(&overReg);
- (*pScreen->HandleExposures)(pWin->parent);
-
- if (pScreen->PostValidateTree)
- (*pScreen->PostValidateTree)(pWin->parent, NullWindow, kind);
- }
- if (pWin->realized)
- WindowsRestructured ();
-}
-
-#ifndef RECTLIMIT
-#define RECTLIMIT 25
-#endif
-
-static void
-miOverlayWindowExposures(
- WindowPtr pWin,
- RegionPtr prgn,
- RegionPtr other_exposed
-){
- RegionPtr exposures = prgn;
-
- if ((prgn && !RegionNil(prgn)) ||
- (exposures && !RegionNil(exposures)) || other_exposed)
- {
- RegionRec expRec;
- int clientInterested;
-
- clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) &
- ExposureMask;
- if (other_exposed) {
- if (exposures) {
- RegionUnion(other_exposed, exposures, other_exposed);
- if (exposures != prgn)
- RegionDestroy(exposures);
- }
- exposures = other_exposed;
- }
- if (clientInterested && exposures &&
- (RegionNumRects(exposures) > RECTLIMIT))
- {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- BoxRec box;
-
- box = *RegionExtents(exposures);
- if (exposures == prgn) {
- exposures = &expRec;
- RegionInit(exposures, &box, 1);
- RegionReset(prgn, &box);
- } else {
- RegionReset(exposures, &box);
- RegionUnion(prgn, prgn, exposures);
- }
- /* This is the only reason why we are replacing mi's version
- of this file */
-
- if(!((*pPriv->InOverlay)(pWin))) {
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- RegionIntersect(prgn, prgn, &pTree->clipList);
- } else
- RegionIntersect(prgn, prgn, &pWin->clipList);
- }
- if (prgn && !RegionNil(prgn))
- miPaintWindow(pWin, prgn, PW_BACKGROUND);
- if (clientInterested && exposures && !RegionNil(exposures))
- miSendExposures(pWin, exposures,
- pWin->drawable.x, pWin->drawable.y);
- if (exposures == &expRec) {
- RegionUninit(exposures);
- }
- else if (exposures && exposures != prgn && exposures != other_exposed)
- RegionDestroy(exposures);
- if (prgn)
- RegionEmpty(prgn);
- }
- else if (exposures && exposures != prgn)
- RegionDestroy(exposures);
-}
-
-
-typedef struct {
- RegionPtr over;
- RegionPtr under;
-} miOverlayTwoRegions;
-
-static int
-miOverlayRecomputeExposures (
- WindowPtr pWin,
- pointer value
-){
- miOverlayTwoRegions *pValid = (miOverlayTwoRegions*)value;
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
-
- if (pWin->valdata) {
- /*
- * compute exposed regions of this window
- */
- RegionSubtract(&pWin->valdata->after.exposed,
- &pWin->clipList, pValid->over);
- /*
- * compute exposed regions of the border
- */
- RegionSubtract(&pWin->valdata->after.borderExposed,
- &pWin->borderClip, &pWin->winSize);
- RegionSubtract(&pWin->valdata->after.borderExposed,
- &pWin->valdata->after.borderExposed, pValid->over);
- }
-
- if(pTree && pTree->valdata) {
- RegionSubtract(&pTree->valdata->exposed,
- &pTree->clipList, pValid->under);
- RegionSubtract(&pTree->valdata->borderExposed,
- &pTree->borderClip, &pWin->winSize);
- RegionSubtract(&pTree->valdata->borderExposed,
- &pTree->valdata->borderExposed, pValid->under);
- } else if (!pWin->valdata)
- return WT_NOMATCH;
-
- return WT_WALKCHILDREN;
-}
-
-static void
-miOverlayResizeWindow(
- WindowPtr pWin,
- int x, int y,
- unsigned int w, unsigned int h,
- WindowPtr pSib
-){
- ScreenPtr pScreen = pWin->drawable.pScreen;
- WindowPtr pParent;
- miOverlayTreePtr tChild, pTree;
- Bool WasViewable = (Bool)(pWin->viewable);
- unsigned short width = pWin->drawable.width;
- unsigned short height = pWin->drawable.height;
- short oldx = pWin->drawable.x;
- short oldy = pWin->drawable.y;
- int bw = wBorderWidth (pWin);
- short dw, dh;
- DDXPointRec oldpt;
- RegionPtr oldRegion = NULL, oldRegion2 = NULL;
- WindowPtr pFirstChange;
- WindowPtr pChild;
- RegionPtr gravitate[StaticGravity + 1];
- RegionPtr gravitate2[StaticGravity + 1];
- unsigned g;
- int nx, ny; /* destination x,y */
- int newx, newy; /* new inner window position */
- RegionPtr pRegion = NULL;
- RegionPtr destClip, destClip2;
- RegionPtr oldWinClip = NULL, oldWinClip2 = NULL;
- RegionPtr borderVisible = NullRegion;
- RegionPtr borderVisible2 = NullRegion;
- Bool shrunk = FALSE; /* shrunk in an inner dimension */
- Bool moved = FALSE; /* window position changed */
- Bool doUnderlay;
-
- /* if this is a root window, can't be resized */
- if (!(pParent = pWin->parent))
- return ;
-
- pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- doUnderlay = ((pTree) || HasUnderlayChildren(pWin));
- newx = pParent->drawable.x + x + bw;
- newy = pParent->drawable.y + y + bw;
- if (WasViewable)
- {
- /*
- * save the visible region of the window
- */
- oldRegion = RegionCreate(NullBox, 1);
- RegionCopy(oldRegion, &pWin->winSize);
- if(doUnderlay) {
- oldRegion2 = RegionCreate(NullBox, 1);
- RegionCopy(oldRegion2, &pWin->winSize);
- }
-
- /*
- * categorize child windows into regions to be moved
- */
- for (g = 0; g <= StaticGravity; g++)
- gravitate[g] = gravitate2[g] = NULL;
- for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
- g = pChild->winGravity;
- if (g != UnmapGravity) {
- if (!gravitate[g])
- gravitate[g] = RegionCreate(NullBox, 1);
- RegionUnion(gravitate[g],
- gravitate[g], &pChild->borderClip);
-
- if(doUnderlay) {
- if (!gravitate2[g])
- gravitate2[g] = RegionCreate(NullBox, 0);
-
- if((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
- RegionUnion(gravitate2[g],
- gravitate2[g], &tChild->borderClip);
- } else
- CollectUnderlayChildrenRegions(pChild, gravitate2[g]);
- }
- } else {
- UnmapWindow(pChild, TRUE);
- }
- }
- (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
-
-
- oldWinClip = oldWinClip2 = NULL;
- if (pWin->bitGravity != ForgetGravity) {
- oldWinClip = RegionCreate(NullBox, 1);
- RegionCopy(oldWinClip, &pWin->clipList);
- if(pTree) {
- oldWinClip2 = RegionCreate(NullBox, 1);
- RegionCopy(oldWinClip2, &pTree->clipList);
- }
- }
- /*
- * if the window is changing size, borderExposed
- * can't be computed correctly without some help.
- */
- if (pWin->drawable.height > h || pWin->drawable.width > w)
- shrunk = TRUE;
-
- if (newx != oldx || newy != oldy)
- moved = TRUE;
-
- if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
- HasBorder (pWin))
- {
- borderVisible = RegionCreate(NullBox, 1);
- if(pTree)
- borderVisible2 = RegionCreate(NullBox, 1);
- /* for tiled borders, we punt and draw the whole thing */
- if (pWin->borderIsPixel || !moved)
- {
- if (shrunk || moved)
- RegionSubtract(borderVisible,
- &pWin->borderClip,
- &pWin->winSize);
- else
- RegionCopy(borderVisible,
- &pWin->borderClip);
- if(pTree) {
- if (shrunk || moved)
- RegionSubtract(borderVisible,
- &pTree->borderClip,
- &pWin->winSize);
- else
- RegionCopy(borderVisible,
- &pTree->borderClip);
- }
- }
- }
- }
- pWin->origin.x = x + bw;
- pWin->origin.y = y + bw;
- pWin->drawable.height = h;
- pWin->drawable.width = w;
-
- x = pWin->drawable.x = newx;
- y = pWin->drawable.y = newy;
-
- SetWinSize (pWin);
- SetBorderSize (pWin);
-
- dw = (int)w - (int)width;
- dh = (int)h - (int)height;
- ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
-
- /* let the hardware adjust background and border pixmaps, if any */
- (*pScreen->PositionWindow)(pWin, x, y);
-
- pFirstChange = MoveWindowInStack(pWin, pSib);
-
- if (WasViewable) {
- pRegion = RegionCreate(NullBox, 1);
-
- (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, NULL);
-
- pWin->valdata->before.resized = TRUE;
- pWin->valdata->before.borderVisible = borderVisible;
- if(pTree)
- pTree->valdata->borderVisible = borderVisible2;
-
-
- (*pScreen->ValidateTree)(pWin->parent, pFirstChange, VTOther);
- /*
- * the entire window is trashed unless bitGravity
- * recovers portions of it
- */
- RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
- if(pTree)
- RegionCopy(&pTree->valdata->exposed, &pTree->clipList);
- }
-
- GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
-
- if (WasViewable) {
- miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- miOverlayTwoRegions TwoRegions;
-
- /* avoid the border */
- if (HasBorder (pWin)) {
- int offx, offy, dx, dy;
-
- /* kruft to avoid double translates for each gravity */
- offx = 0;
- offy = 0;
- for (g = 0; g <= StaticGravity; g++) {
- if (!gravitate[g] && !gravitate2[g])
- continue;
-
- /* align winSize to gravitate[g].
- * winSize is in new coordinates,
- * gravitate[g] is still in old coordinates */
- GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
-
- dx = (oldx - nx) - offx;
- dy = (oldy - ny) - offy;
- if (dx || dy) {
- RegionTranslate(&pWin->winSize, dx, dy);
- offx += dx;
- offy += dy;
- }
- if(gravitate[g])
- RegionIntersect(gravitate[g], gravitate[g],
- &pWin->winSize);
- if(gravitate2[g])
- RegionIntersect(gravitate2[g], gravitate2[g],
- &pWin->winSize);
- }
- /* get winSize back where it belongs */
- if (offx || offy)
- RegionTranslate(&pWin->winSize, -offx, -offy);
- }
- /*
- * add screen bits to the appropriate bucket
- */
-
- if (oldWinClip2)
- {
- RegionCopy(pRegion, oldWinClip2);
- RegionTranslate(pRegion, nx - oldx, ny - oldy);
- RegionIntersect(oldWinClip2, pRegion, &pTree->clipList);
-
- for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
- if (gravitate2[g])
- RegionSubtract(oldWinClip2, oldWinClip2,
- gravitate2[g]);
- }
- RegionTranslate(oldWinClip2, oldx - nx, oldy - ny);
- g = pWin->bitGravity;
- if (!gravitate2[g])
- gravitate2[g] = oldWinClip2;
- else {
- RegionUnion(gravitate2[g],gravitate2[g],oldWinClip2);
- RegionDestroy(oldWinClip2);
- }
- }
-
- if (oldWinClip)
- {
- /*
- * clip to new clipList
- */
- RegionCopy(pRegion, oldWinClip);
- RegionTranslate(pRegion, nx - oldx, ny - oldy);
- RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
- /*
- * don't step on any gravity bits which will be copied after this
- * region. Note -- this assumes that the regions will be copied
- * in gravity order.
- */
- for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
- if (gravitate[g])
- RegionSubtract(oldWinClip, oldWinClip,
- gravitate[g]);
- }
- RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
- g = pWin->bitGravity;
- if (!gravitate[g])
- gravitate[g] = oldWinClip;
- else {
- RegionUnion(gravitate[g], gravitate[g], oldWinClip);
- RegionDestroy(oldWinClip);
- }
- }
-
- /*
- * move the bits on the screen
- */
-
- destClip = destClip2 = NULL;
-
- for (g = 0; g <= StaticGravity; g++) {
- if (!gravitate[g] && !gravitate2[g])
- continue;
-
- GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
-
- oldpt.x = oldx + (x - nx);
- oldpt.y = oldy + (y - ny);
-
- /* Note that gravitate[g] is *translated* by CopyWindow */
-
- /* only copy the remaining useful bits */
-
- if(gravitate[g])
- RegionIntersect(gravitate[g],
- gravitate[g], oldRegion);
- if(gravitate2[g])
- RegionIntersect(gravitate2[g],
- gravitate2[g], oldRegion2);
-
- /* clip to not overwrite already copied areas */
-
- if (destClip && gravitate[g]) {
- RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
- RegionSubtract(gravitate[g], gravitate[g], destClip);
- RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
- }
- if (destClip2 && gravitate2[g]) {
- RegionTranslate(destClip2, oldpt.x - x, oldpt.y - y);
- RegionSubtract(gravitate2[g],gravitate2[g],destClip2);
- RegionTranslate(destClip2, x - oldpt.x, y - oldpt.y);
- }
-
- /* and move those bits */
-
- if (oldpt.x != x || oldpt.y != y) {
- if(gravitate2[g]) {
- pPriv->copyUnderlay = TRUE;
- (*pScreen->CopyWindow)(pWin, oldpt, gravitate2[g]);
- }
- if(gravitate[g]) {
- pPriv->copyUnderlay = FALSE;
- (*pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
- }
- }
-
- /* remove any overwritten bits from the remaining useful bits */
-
- if(gravitate[g])
- RegionSubtract(oldRegion, oldRegion, gravitate[g]);
- if(gravitate2[g])
- RegionSubtract(oldRegion2, oldRegion2, gravitate2[g]);
-
- /*
- * recompute exposed regions of child windows
- */
-
-
- for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
- if (pChild->winGravity != g)
- continue;
-
- TwoRegions.over = gravitate[g];
- TwoRegions.under = gravitate2[g];
-
- TraverseTree (pChild, miOverlayRecomputeExposures,
- (pointer)(&TwoRegions));
- }
-
- /*
- * remove the successfully copied regions of the
- * window from its exposed region
- */
-
- if (g == pWin->bitGravity) {
- if(gravitate[g])
- RegionSubtract(&pWin->valdata->after.exposed,
- &pWin->valdata->after.exposed, gravitate[g]);
- if(gravitate2[g] && pTree)
- RegionSubtract(&pTree->valdata->exposed,
- &pTree->valdata->exposed, gravitate2[g]);
- }
- if(gravitate[g]) {
- if (!destClip)
- destClip = gravitate[g];
- else {
- RegionUnion(destClip, destClip, gravitate[g]);
- RegionDestroy(gravitate[g]);
- }
- }
- if(gravitate2[g]) {
- if (!destClip2)
- destClip2 = gravitate2[g];
- else {
- RegionUnion(destClip2, destClip2, gravitate2[g]);
- RegionDestroy(gravitate2[g]);
- }
- }
- }
-
- RegionDestroy(pRegion);
- RegionDestroy(oldRegion);
- if(doUnderlay)
- RegionDestroy(oldRegion2);
- if (destClip)
- RegionDestroy(destClip);
- if (destClip2)
- RegionDestroy(destClip2);
- (*pScreen->HandleExposures)(pWin->parent);
- if (pScreen->PostValidateTree)
- (*pScreen->PostValidateTree)(pWin->parent, pFirstChange, VTOther);
- }
- if (pWin->realized)
- WindowsRestructured ();
-}
-
-
-static void
-miOverlaySetShape(WindowPtr pWin, int kind)
-{
- Bool WasViewable = (Bool)(pWin->viewable);
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- if (kind != ShapeInput) {
- if (WasViewable) {
- (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
-
- if (HasBorder (pWin)) {
- RegionPtr borderVisible;
-
- borderVisible = RegionCreate(NullBox, 1);
- RegionSubtract(borderVisible,
- &pWin->borderClip, &pWin->winSize);
- pWin->valdata->before.borderVisible = borderVisible;
- pWin->valdata->before.resized = TRUE;
- if(IN_UNDERLAY(pWin)) {
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- RegionPtr borderVisible2;
-
- borderVisible2 = RegionCreate(NULL, 1);
- RegionSubtract(borderVisible2,
- &pTree->borderClip, &pWin->winSize);
- pTree->valdata->borderVisible = borderVisible2;
- }
- }
- }
-
- SetWinSize (pWin);
- SetBorderSize (pWin);
-
- ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
-
- if (WasViewable) {
- (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
-
-
- (*pScreen->ValidateTree)(pWin->parent, NullWindow, VTOther);
- }
-
- if (WasViewable) {
- (*pScreen->HandleExposures)(pWin->parent);
- if (pScreen->PostValidateTree)
- (*pScreen->PostValidateTree)(pWin->parent, NullWindow, VTOther);
- }
- }
- if (pWin->realized)
- WindowsRestructured ();
- CheckCursorConfinement(pWin);
-}
-
-
-
-static void
-miOverlayChangeBorderWidth(
- WindowPtr pWin,
- unsigned int width
-){
- int oldwidth;
- ScreenPtr pScreen;
- Bool WasViewable = (Bool)(pWin->viewable);
- Bool HadBorder;
-
- oldwidth = wBorderWidth (pWin);
- if (oldwidth == width)
- return;
- HadBorder = HasBorder(pWin);
- pScreen = pWin->drawable.pScreen;
- if (WasViewable && (width < oldwidth))
- (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
-
- pWin->borderWidth = width;
- SetBorderSize (pWin);
-
- if (WasViewable) {
- if (width > oldwidth) {
- (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
-
- if (HadBorder) {
- RegionPtr borderVisible;
- borderVisible = RegionCreate(NULL, 1);
- RegionSubtract(borderVisible,
- &pWin->borderClip, &pWin->winSize);
- pWin->valdata->before.borderVisible = borderVisible;
- if(IN_UNDERLAY(pWin)) {
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- RegionPtr borderVisible2;
-
- borderVisible2 = RegionCreate(NULL, 1);
- RegionSubtract(borderVisible2,
- &pTree->borderClip, &pWin->winSize);
- pTree->valdata->borderVisible = borderVisible2;
- }
- }
- }
- (*pScreen->ValidateTree)(pWin->parent, pWin, VTOther);
- (*pScreen->HandleExposures)(pWin->parent);
-
- if (pScreen->PostValidateTree)
- (*pScreen->PostValidateTree)(pWin->parent, pWin, VTOther);
- }
- if (pWin->realized)
- WindowsRestructured ();
-}
-
-/* We need this as an addition since the xf86 common code doesn't
- know about the second tree which is static to this file. */
-
-void
-miOverlaySetRootClip(ScreenPtr pScreen, Bool enable)
-{
- WindowPtr pRoot = pScreen->root;
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot);
-
- MARK_UNDERLAY(pRoot);
-
- if(enable) {
- BoxRec box;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
-
- RegionReset(&pTree->borderClip, &box);
- } else
- RegionEmpty(&pTree->borderClip);
-
- RegionBreak(&pTree->clipList);
-}
-
-static void
-miOverlayClearToBackground(
- WindowPtr pWin,
- int x, int y,
- int w, int h,
- Bool generateExposures
-)
-{
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- BoxRec box;
- RegionRec reg;
- RegionPtr pBSReg = NullRegion;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
- RegionPtr clipList;
- BoxPtr extents;
- int x1, y1, x2, y2;
-
- x1 = pWin->drawable.x + x;
- y1 = pWin->drawable.y + y;
- if (w)
- x2 = x1 + (int) w;
- else
- x2 = x1 + (int) pWin->drawable.width - (int) x;
- if (h)
- y2 = y1 + h;
- else
- y2 = y1 + (int) pWin->drawable.height - (int) y;
-
- clipList = ((*pScreenPriv->InOverlay)(pWin)) ? &pWin->clipList :
- &pTree->clipList;
-
- extents = RegionExtents(clipList);
-
- if (x1 < extents->x1) x1 = extents->x1;
- if (x2 > extents->x2) x2 = extents->x2;
- if (y1 < extents->y1) y1 = extents->y1;
- if (y2 > extents->y2) y2 = extents->y2;
-
- if (x2 <= x1 || y2 <= y1)
- x2 = x1 = y2 = y1 = 0;
-
- box.x1 = x1; box.x2 = x2;
- box.y1 = y1; box.y2 = y2;
-
- RegionInit(®, &box, 1);
-
- RegionIntersect(®, ®, clipList);
- if (generateExposures)
- (*pScreen->WindowExposures)(pWin, ®, pBSReg);
- else if (pWin->backgroundState != None)
- miPaintWindow(pWin, ®, PW_BACKGROUND);
- RegionUninit(®);
- if (pBSReg)
- RegionDestroy(pBSReg);
-}
-
-
-/****************************************************************/
-
-/* not used */
-Bool
-miOverlayGetPrivateClips(
- WindowPtr pWin,
- RegionPtr *borderClip,
- RegionPtr *clipList
-){
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
-
- if(pTree) {
- *borderClip = &(pTree->borderClip);
- *clipList = &(pTree->clipList);
- return TRUE;
- }
-
- *borderClip = *clipList = NULL;
-
- return FALSE;
-}
-
-void
-miOverlaySetTransFunction (
- ScreenPtr pScreen,
- miOverlayTransFunc transFunc
-){
- MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc;
-}
-
-Bool
-miOverlayCopyUnderlay(ScreenPtr pScreen)
-{
- return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay;
-}
-
-void
-miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin)
-{
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
- RegionPtr pregWin;
- Bool freeTmpClip, freeCompClip;
-
- if(!pTree) {
- miComputeCompositeClip(pGC, &pWin->drawable);
- return;
- }
-
- if (pGC->subWindowMode == IncludeInferiors) {
- pregWin = RegionCreate(NullBox, 1);
- freeTmpClip = TRUE;
- if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) ||
- !HasSaverWindow (pGC->pScreen))
- {
- RegionIntersect(pregWin,&pTree->borderClip,&pWin->winSize);
- }
- } else {
- pregWin = &pTree->clipList;
- freeTmpClip = FALSE;
- }
- freeCompClip = pGC->freeCompClip;
- if (pGC->clientClipType == CT_NONE) {
- if (freeCompClip)
- RegionDestroy(pGC->pCompositeClip);
- pGC->pCompositeClip = pregWin;
- pGC->freeCompClip = freeTmpClip;
- } else {
- RegionTranslate(pGC->clientClip,
- pWin->drawable.x + pGC->clipOrg.x,
- pWin->drawable.y + pGC->clipOrg.y);
-
- if (freeCompClip) {
- RegionIntersect(pGC->pCompositeClip,
- pregWin, pGC->clientClip);
- if (freeTmpClip)
- RegionDestroy(pregWin);
- } else if (freeTmpClip) {
- RegionIntersect(pregWin, pregWin, pGC->clientClip);
- pGC->pCompositeClip = pregWin;
- } else {
- pGC->pCompositeClip = RegionCreate(NullBox, 0);
- RegionIntersect(pGC->pCompositeClip,
- pregWin, pGC->clientClip);
- }
- pGC->freeCompClip = TRUE;
- RegionTranslate(pGC->clientClip,
- -(pWin->drawable.x + pGC->clipOrg.x),
- -(pWin->drawable.y + pGC->clipOrg.y));
- }
-}
-
-Bool
-miOverlayCollectUnderlayRegions(
- WindowPtr pWin,
- RegionPtr *region
-){
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
-
- if(pTree) {
- *region = &pTree->borderClip;
- return FALSE;
- }
-
- *region = RegionCreate(NullBox, 0);
-
- CollectUnderlayChildrenRegions(pWin, *region);
-
- return TRUE;
-}
-
-
-static miOverlayTreePtr
-DoLeaf(
- WindowPtr pWin,
- miOverlayTreePtr parent,
- miOverlayTreePtr prevSib
-){
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
-
- pTree->parent = parent;
- pTree->firstChild = NULL;
- pTree->lastChild = NULL;
- pTree->prevSib = prevSib;
- pTree->nextSib = NULL;
-
- if(prevSib)
- prevSib->nextSib = pTree;
-
- if(!parent->firstChild)
- parent->firstChild = parent->lastChild = pTree;
- else if(parent->lastChild == prevSib)
- parent->lastChild = pTree;
-
- return pTree;
-}
-
-static void
-RebuildTree(WindowPtr pWin)
-{
- miOverlayTreePtr parent, prevSib, tChild;
- WindowPtr pChild;
-
- prevSib = tChild = NULL;
-
- pWin = pWin->parent;
-
- while(IN_OVERLAY(pWin))
- pWin = pWin->parent;
-
- parent = MIOVERLAY_GET_WINDOW_TREE(pWin);
-
- pChild = pWin->firstChild;
- parent->firstChild = parent->lastChild = NULL;
-
- while(1) {
- if(IN_UNDERLAY(pChild))
- prevSib = tChild = DoLeaf(pChild, parent, prevSib);
-
- if(pChild->firstChild) {
- if(IN_UNDERLAY(pChild)) {
- parent = tChild;
- prevSib = NULL;
- }
- pChild = pChild->firstChild;
- continue;
- }
-
- while(!pChild->nextSib) {
- pChild = pChild->parent;
- if(pChild == pWin) return;
- if(IN_UNDERLAY(pChild)) {
- prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
- parent = tChild->parent;
- }
- }
-
- pChild = pChild->nextSib;
- }
-}
-
-
-static Bool
-HasUnderlayChildren(WindowPtr pWin)
-{
- WindowPtr pChild;
-
- if(!(pChild = pWin->firstChild))
- return FALSE;
-
- while(1) {
- if(IN_UNDERLAY(pChild))
- return TRUE;
-
- if(pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
-
- while(!pChild->nextSib && (pWin != pChild))
- pChild = pChild->parent;
-
- if(pChild == pWin) break;
-
- pChild = pChild->nextSib;
- }
-
- return FALSE;
-}
-
-
-static Bool
-CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg)
-{
- WindowPtr pChild;
- miOverlayTreePtr pTree;
- Bool hasUnderlay;
-
- if(!(pChild = pWin->firstChild))
- return FALSE;
-
- hasUnderlay = FALSE;
-
- while(1) {
- if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
- RegionAppend(pReg, &pTree->borderClip);
- hasUnderlay = TRUE;
- } else
- if(pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
-
- while(!pChild->nextSib && (pWin != pChild))
- pChild = pChild->parent;
-
- if(pChild == pWin) break;
-
- pChild = pChild->nextSib;
- }
-
- if(hasUnderlay) {
- Bool overlap;
- RegionValidate(pReg, &overlap);
- }
-
- return hasUnderlay;
-}
-
-
-static void
-MarkUnderlayWindow(WindowPtr pWin)
-{
- miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
-
- if(pTree->valdata) return;
- pTree->valdata = (miOverlayValDataPtr)xnfalloc(sizeof(miOverlayValDataRec));
- pTree->valdata->oldAbsCorner.x = pWin->drawable.x;
- pTree->valdata->oldAbsCorner.y = pWin->drawable.y;
- pTree->valdata->borderVisible = NullRegion;
-}
+ +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include "scrnintstr.h" +#include <X11/extensions/shapeproto.h> +#include "validate.h" +#include "windowstr.h" +#include "mi.h" +#include "gcstruct.h" +#include "regionstr.h" +#include "privates.h" +#include "mivalidate.h" +#include "mioverlay.h" +#include "migc.h" + +#include "globals.h" + +typedef struct { + RegionRec exposed; + RegionRec borderExposed; + RegionPtr borderVisible; + DDXPointRec oldAbsCorner; +} miOverlayValDataRec, *miOverlayValDataPtr; + +typedef struct _TreeRec { + WindowPtr pWin; + struct _TreeRec *parent; + struct _TreeRec *firstChild; + struct _TreeRec *lastChild; + struct _TreeRec *prevSib; + struct _TreeRec *nextSib; + RegionRec borderClip; + RegionRec clipList; + unsigned visibility; + miOverlayValDataPtr valdata; +} miOverlayTreeRec, *miOverlayTreePtr; + +typedef struct { + miOverlayTreePtr tree; +} miOverlayWindowRec, *miOverlayWindowPtr; + +typedef struct { + CloseScreenProcPtr CloseScreen; + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + RealizeWindowProcPtr RealizeWindow; + miOverlayTransFunc MakeTransparent; + miOverlayInOverlayFunc InOverlay; + Bool underlayMarked; + Bool copyUnderlay; +} miOverlayScreenRec, *miOverlayScreenPtr; + +static DevPrivateKeyRec miOverlayWindowKeyRec; + +#define miOverlayWindowKey (&miOverlayWindowKeyRec) +static DevPrivateKeyRec miOverlayScreenKeyRec; + +#define miOverlayScreenKey (&miOverlayScreenKeyRec) + +static void RebuildTree(WindowPtr); +static Bool HasUnderlayChildren(WindowPtr); +static void MarkUnderlayWindow(WindowPtr); +static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr); + +static Bool miOverlayCloseScreen(int, ScreenPtr); +static Bool miOverlayCreateWindow(WindowPtr); +static Bool miOverlayDestroyWindow(WindowPtr); +static Bool miOverlayUnrealizeWindow(WindowPtr); +static Bool miOverlayRealizeWindow(WindowPtr); +static void miOverlayMarkWindow(WindowPtr); +static void miOverlayReparentWindow(WindowPtr, WindowPtr); +static void miOverlayRestackWindow(WindowPtr, WindowPtr); +static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr *); +static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool); +static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind); +static void miOverlayHandleExposures(WindowPtr); +static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind); +static void miOverlayWindowExposures(WindowPtr, RegionPtr, RegionPtr); +static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int, + unsigned int, WindowPtr); +static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool); + +static void miOverlaySetShape(WindowPtr, int); +static void miOverlayChangeBorderWidth(WindowPtr, unsigned int); + +#define MIOVERLAY_GET_SCREEN_PRIVATE(pScreen) ((miOverlayScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, miOverlayScreenKey)) +#define MIOVERLAY_GET_WINDOW_PRIVATE(pWin) ((miOverlayWindowPtr) \ + dixLookupPrivate(&(pWin)->devPrivates, miOverlayWindowKey)) +#define MIOVERLAY_GET_WINDOW_TREE(pWin) \ + (MIOVERLAY_GET_WINDOW_PRIVATE(pWin)->tree) + +#define IN_UNDERLAY(w) MIOVERLAY_GET_WINDOW_TREE(w) +#define IN_OVERLAY(w) !MIOVERLAY_GET_WINDOW_TREE(w) + +#define MARK_OVERLAY(w) miMarkWindow(w) +#define MARK_UNDERLAY(w) MarkUnderlayWindow(w) + +#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ + HasBorder(w) && \ + (w)->backgroundState == ParentRelative) + +Bool +miInitOverlay(ScreenPtr pScreen, + miOverlayInOverlayFunc inOverlayFunc, + miOverlayTransFunc transFunc) +{ + miOverlayScreenPtr pScreenPriv; + + if (!inOverlayFunc || !transFunc) + return FALSE; + + if (!dixRegisterPrivateKey + (&miOverlayWindowKeyRec, PRIVATE_WINDOW, sizeof(miOverlayWindowRec))) + return FALSE; + + if (!dixRegisterPrivateKey(&miOverlayScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!(pScreenPriv = malloc(sizeof(miOverlayScreenRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, miOverlayScreenKey, pScreenPriv); + + pScreenPriv->InOverlay = inOverlayFunc; + pScreenPriv->MakeTransparent = transFunc; + pScreenPriv->underlayMarked = FALSE; + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->CreateWindow = pScreen->CreateWindow; + pScreenPriv->DestroyWindow = pScreen->DestroyWindow; + pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow; + pScreenPriv->RealizeWindow = pScreen->RealizeWindow; + + pScreen->CloseScreen = miOverlayCloseScreen; + pScreen->CreateWindow = miOverlayCreateWindow; + pScreen->DestroyWindow = miOverlayDestroyWindow; + pScreen->UnrealizeWindow = miOverlayUnrealizeWindow; + pScreen->RealizeWindow = miOverlayRealizeWindow; + + pScreen->ReparentWindow = miOverlayReparentWindow; + pScreen->RestackWindow = miOverlayRestackWindow; + pScreen->MarkOverlappedWindows = miOverlayMarkOverlappedWindows; + pScreen->MarkUnrealizedWindow = miOverlayMarkUnrealizedWindow; + pScreen->ValidateTree = miOverlayValidateTree; + pScreen->HandleExposures = miOverlayHandleExposures; + pScreen->MoveWindow = miOverlayMoveWindow; + pScreen->WindowExposures = miOverlayWindowExposures; + pScreen->ResizeWindow = miOverlayResizeWindow; + pScreen->MarkWindow = miOverlayMarkWindow; + pScreen->ClearToBackground = miOverlayClearToBackground; + pScreen->SetShape = miOverlaySetShape; + pScreen->ChangeBorderWidth = miOverlayChangeBorderWidth; + + return TRUE; +} + +static Bool +miOverlayCloseScreen(int i, ScreenPtr pScreen) +{ + miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->CreateWindow = pScreenPriv->CreateWindow; + pScreen->DestroyWindow = pScreenPriv->DestroyWindow; + pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow; + pScreen->RealizeWindow = pScreenPriv->RealizeWindow; + + free(pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static Bool +miOverlayCreateWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + miOverlayWindowPtr pWinPriv = MIOVERLAY_GET_WINDOW_PRIVATE(pWin); + miOverlayTreePtr pTree = NULL; + Bool result = TRUE; + + pWinPriv->tree = NULL; + + if (!pWin->parent || !((*pScreenPriv->InOverlay) (pWin))) { + if (!(pTree = (miOverlayTreePtr) calloc(1, sizeof(miOverlayTreeRec)))) + return FALSE; + } + + if (pScreenPriv->CreateWindow) { + pScreen->CreateWindow = pScreenPriv->CreateWindow; + result = (*pScreen->CreateWindow) (pWin); + pScreen->CreateWindow = miOverlayCreateWindow; + } + + if (pTree) { + if (result) { + pTree->pWin = pWin; + pTree->visibility = VisibilityNotViewable; + pWinPriv->tree = pTree; + if (pWin->parent) { + RegionNull(&(pTree->borderClip)); + RegionNull(&(pTree->clipList)); + RebuildTree(pWin); + } + else { + BoxRec fullBox; + + fullBox.x1 = 0; + fullBox.y1 = 0; + fullBox.x2 = pScreen->width; + fullBox.y2 = pScreen->height; + RegionInit(&(pTree->borderClip), &fullBox, 1); + RegionInit(&(pTree->clipList), &fullBox, 1); + } + } + else + free(pTree); + } + + return TRUE; +} + +static Bool +miOverlayDestroyWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + Bool result = TRUE; + + if (pTree) { + if (pTree->prevSib) + pTree->prevSib->nextSib = pTree->nextSib; + else if (pTree->parent) + pTree->parent->firstChild = pTree->nextSib; + + if (pTree->nextSib) + pTree->nextSib->prevSib = pTree->prevSib; + else if (pTree->parent) + pTree->parent->lastChild = pTree->prevSib; + + RegionUninit(&(pTree->borderClip)); + RegionUninit(&(pTree->clipList)); + free(pTree); + } + + if (pScreenPriv->DestroyWindow) { + pScreen->DestroyWindow = pScreenPriv->DestroyWindow; + result = (*pScreen->DestroyWindow) (pWin); + pScreen->DestroyWindow = miOverlayDestroyWindow; + } + + return result; +} + +static Bool +miOverlayUnrealizeWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + Bool result = TRUE; + + if (pTree) + pTree->visibility = VisibilityNotViewable; + + if (pScreenPriv->UnrealizeWindow) { + pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow; + result = (*pScreen->UnrealizeWindow) (pWin); + pScreen->UnrealizeWindow = miOverlayUnrealizeWindow; + } + + return result; +} + +static Bool +miOverlayRealizeWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + Bool result = TRUE; + + if (pScreenPriv->RealizeWindow) { + pScreen->RealizeWindow = pScreenPriv->RealizeWindow; + result = (*pScreen->RealizeWindow) (pWin); + pScreen->RealizeWindow = miOverlayRealizeWindow; + } + + /* we only need to catch the root window realization */ + + if (result && !pWin->parent && !((*pScreenPriv->InOverlay) (pWin))) { + BoxRec box; + + box.x1 = box.y1 = 0; + box.x2 = pWin->drawable.width; + box.y2 = pWin->drawable.height; + (*pScreenPriv->MakeTransparent) (pScreen, 1, &box); + } + + return result; +} + +static void +miOverlayReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) +{ + if (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) { + /* This could probably be more optimal */ + RebuildTree(pWin->drawable.pScreen->root->firstChild); + } +} + +static void +miOverlayRestackWindow(WindowPtr pWin, WindowPtr oldNextSib) +{ + if (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) { + /* This could probably be more optimal */ + RebuildTree(pWin); + } +} + +static Bool +miOverlayMarkOverlappedWindows(WindowPtr pWin, + WindowPtr pFirst, WindowPtr *pLayerWin) +{ + WindowPtr pChild, pLast; + Bool overMarked, underMarked, doUnderlay, markAll; + miOverlayTreePtr pTree = NULL, tLast, tChild; + BoxPtr box; + + overMarked = underMarked = markAll = FALSE; + + if (pLayerWin) + *pLayerWin = pWin; /* hah! */ + + doUnderlay = (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)); + + box = RegionExtents(&pWin->borderSize); + + if ((pChild = pFirst)) { + pLast = pChild->parent->lastChild; + while (1) { + if (pChild == pWin) + markAll = TRUE; + + if (doUnderlay && IN_UNDERLAY(pChild)) + pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); + + if (pChild->viewable) { + if (RegionBroken(&pChild->winSize)) + SetWinSize(pChild); + if (RegionBroken(&pChild->borderSize)) + SetBorderSize(pChild); + + if (markAll || RegionContainsRect(&pChild->borderSize, box)) { + MARK_OVERLAY(pChild); + overMarked = TRUE; + if (doUnderlay && IN_UNDERLAY(pChild)) { + MARK_UNDERLAY(pChild); + underMarked = TRUE; + } + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + } + } + while (!pChild->nextSib && (pChild != pLast)) { + pChild = pChild->parent; + if (doUnderlay && IN_UNDERLAY(pChild)) + pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); + } + + if (pChild == pWin) + markAll = FALSE; + + if (pChild == pLast) + break; + + pChild = pChild->nextSib; + } + if (overMarked) + MARK_OVERLAY(pWin->parent); + } + + if (doUnderlay && !pTree) { + if (!(pTree = MIOVERLAY_GET_WINDOW_TREE(pWin))) { + pChild = pWin->lastChild; + while (1) { + if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) + break; + + if (pChild->lastChild) { + pChild = pChild->lastChild; + continue; + } + + while (!pChild->prevSib) + pChild = pChild->parent; + + pChild = pChild->prevSib; + } + } + } + + if (pTree && pTree->nextSib) { + tChild = pTree->parent->lastChild; + tLast = pTree->nextSib; + + while (1) { + if (tChild->pWin->viewable) { + if (RegionBroken(&tChild->pWin->winSize)) + SetWinSize(tChild->pWin); + if (RegionBroken(&tChild->pWin->borderSize)) + SetBorderSize(tChild->pWin); + + if (RegionContainsRect(&(tChild->pWin->borderSize), box)) { + MARK_UNDERLAY(tChild->pWin); + underMarked = TRUE; + } + } + + if (tChild->lastChild) { + tChild = tChild->lastChild; + continue; + } + + while (!tChild->prevSib && (tChild != tLast)) + tChild = tChild->parent; + + if (tChild == tLast) + break; + + tChild = tChild->prevSib; + } + } + + if (underMarked) { + ScreenPtr pScreen = pWin->drawable.pScreen; + + MARK_UNDERLAY(pTree->parent->pWin); + MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->underlayMarked = TRUE; + } + + return underMarked || overMarked; +} + +static void +miOverlayComputeClips(WindowPtr pParent, + RegionPtr universe, VTKind kind, RegionPtr exposed) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + int oldVis, newVis, dx, dy; + BoxRec borderSize; + RegionPtr borderVisible; + RegionRec childUniverse, childUnion; + miOverlayTreePtr tParent = MIOVERLAY_GET_WINDOW_TREE(pParent); + miOverlayTreePtr tChild; + Bool overlap; + + 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 = tParent->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; + } + tParent->visibility = newVis; + + dx = pParent->drawable.x - tParent->valdata->oldAbsCorner.x; + dy = pParent->drawable.y - tParent->valdata->oldAbsCorner.y; + + switch (kind) { + case VTMap: + case VTStack: + case VTUnmap: + break; + case VTMove: + if ((oldVis == newVis) && + ((oldVis == VisibilityFullyObscured) || + (oldVis == VisibilityUnobscured))) { + tChild = tParent; + while (1) { + if (tChild->pWin->viewable) { + if (tChild->visibility != VisibilityFullyObscured) { + RegionTranslate(&tChild->borderClip, dx, dy); + RegionTranslate(&tChild->clipList, dx, dy); + + tChild->pWin->drawable.serialNumber = + NEXT_SERIAL_NUMBER; + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (tChild->pWin, dx, dy); + } + if (tChild->valdata) { + RegionNull(&tChild->valdata->borderExposed); + if (HasParentRelativeBorder(tChild->pWin)) { + RegionSubtract(&tChild->valdata->borderExposed, + &tChild->borderClip, + &tChild->pWin->winSize); + } + RegionNull(&tChild->valdata->exposed); + } + if (tChild->firstChild) { + tChild = tChild->firstChild; + continue; + } + } + while (!tChild->nextSib && (tChild != tParent)) + tChild = tChild->parent; + if (tChild == tParent) + break; + tChild = tChild->nextSib; + } + return; + } + /* fall through */ + default: + if (dx || dy) { + RegionTranslate(&tParent->borderClip, dx, dy); + RegionTranslate(&tParent->clipList, dx, dy); + } + break; + case VTBroken: + RegionEmpty(&tParent->borderClip); + RegionEmpty(&tParent->clipList); + break; + } + + borderVisible = tParent->valdata->borderVisible; + RegionNull(&tParent->valdata->borderExposed); + RegionNull(&tParent->valdata->exposed); + + if (HasBorder(pParent)) { + if (borderVisible) { + RegionSubtract(exposed, universe, borderVisible); + RegionDestroy(borderVisible); + } + else + RegionSubtract(exposed, universe, &tParent->borderClip); + + if (HasParentRelativeBorder(pParent) && (dx || dy)) + RegionSubtract(&tParent->valdata->borderExposed, + universe, &pParent->winSize); + else + RegionSubtract(&tParent->valdata->borderExposed, + exposed, &pParent->winSize); + + RegionCopy(&tParent->borderClip, universe); + RegionIntersect(universe, universe, &pParent->winSize); + } + else + RegionCopy(&tParent->borderClip, universe); + + if ((tChild = tParent->firstChild) && pParent->mapped) { + RegionNull(&childUniverse); + RegionNull(&childUnion); + + for (; tChild; tChild = tChild->nextSib) { + if (tChild->pWin->viewable) + RegionAppend(&childUnion, &tChild->pWin->borderSize); + } + + RegionValidate(&childUnion, &overlap); + + for (tChild = tParent->firstChild; tChild; tChild = tChild->nextSib) { + if (tChild->pWin->viewable) { + if (tChild->valdata) { + RegionIntersect(&childUniverse, universe, + &tChild->pWin->borderSize); + miOverlayComputeClips(tChild->pWin, &childUniverse, + kind, exposed); + } + if (overlap) + RegionSubtract(universe, universe, + &tChild->pWin->borderSize); + } + } + if (!overlap) + RegionSubtract(universe, universe, &childUnion); + RegionUninit(&childUnion); + RegionUninit(&childUniverse); + } + + if (oldVis == VisibilityFullyObscured || oldVis == VisibilityNotViewable) { + RegionCopy(&tParent->valdata->exposed, universe); + } + else if (newVis != VisibilityFullyObscured && + newVis != VisibilityNotViewable) { + RegionSubtract(&tParent->valdata->exposed, + universe, &tParent->clipList); + } + + /* HACK ALERT - copying contents of regions, instead of regions */ + { + RegionRec tmp; + + tmp = tParent->clipList; + tParent->clipList = *universe; + *universe = tmp; + } + + pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pParent, dx, dy); +} + +static void +miOverlayMarkWindow(WindowPtr pWin) +{ + miOverlayTreePtr pTree = NULL; + WindowPtr pChild, pGrandChild; + + miMarkWindow(pWin); + + /* look for UnmapValdata among immediate children */ + + if (!(pChild = pWin->firstChild)) + return; + + for (; pChild; pChild = pChild->nextSib) { + if (pChild->valdata == UnmapValData) { + if (IN_UNDERLAY(pChild)) { + pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); + pTree->valdata = (miOverlayValDataPtr) UnmapValData; + continue; + } + else { + if (!(pGrandChild = pChild->firstChild)) + continue; + + while (1) { + if (IN_UNDERLAY(pGrandChild)) { + pTree = MIOVERLAY_GET_WINDOW_TREE(pGrandChild); + pTree->valdata = (miOverlayValDataPtr) UnmapValData; + } + else if (pGrandChild->firstChild) { + pGrandChild = pGrandChild->firstChild; + continue; + } + + while (!pGrandChild->nextSib && (pGrandChild != pChild)) + pGrandChild = pGrandChild->parent; + + if (pChild == pGrandChild) + break; + + pGrandChild = pGrandChild->nextSib; + } + } + } + } + + if (pTree) { + MARK_UNDERLAY(pTree->parent->pWin); + MIOVERLAY_GET_SCREEN_PRIVATE(pWin->drawable.pScreen)->underlayMarked = + TRUE; + } +} + +static void +miOverlayMarkUnrealizedWindow(WindowPtr pChild, + WindowPtr pWin, Bool fromConfigure) +{ + if ((pChild != pWin) || fromConfigure) { + miOverlayTreePtr pTree; + + RegionEmpty(&pChild->clipList); + if (pChild->drawable.pScreen->ClipNotify) + (*pChild->drawable.pScreen->ClipNotify) (pChild, 0, 0); + RegionEmpty(&pChild->borderClip); + if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) { + if (pTree->valdata != (miOverlayValDataPtr) UnmapValData) { + RegionEmpty(&pTree->clipList); + RegionEmpty(&pTree->borderClip); + } + } + } +} + +static int +miOverlayValidateTree(WindowPtr pParent, WindowPtr pChild, /* first child effected */ + VTKind kind) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + RegionRec totalClip, childClip, exposed; + miOverlayTreePtr tParent, tChild, tWin; + Bool overlap; + WindowPtr newParent; + + if (!pPriv->underlayMarked) + goto SKIP_UNDERLAY; + + if (!pChild) + pChild = pParent->firstChild; + + RegionNull(&totalClip); + RegionNull(&childClip); + RegionNull(&exposed); + + newParent = pParent; + + while (IN_OVERLAY(newParent)) + newParent = newParent->parent; + + tParent = MIOVERLAY_GET_WINDOW_TREE(newParent); + + if (IN_UNDERLAY(pChild)) + tChild = MIOVERLAY_GET_WINDOW_TREE(pChild); + else + tChild = tParent->firstChild; + + if (RegionBroken(&tParent->clipList) && !RegionBroken(&tParent->borderClip)) { + kind = VTBroken; + RegionCopy(&totalClip, &tParent->borderClip); + RegionIntersect(&totalClip, &totalClip, &tParent->pWin->winSize); + + for (tWin = tParent->firstChild; tWin != tChild; tWin = tWin->nextSib) { + if (tWin->pWin->viewable) + RegionSubtract(&totalClip, &totalClip, &tWin->pWin->borderSize); + } + RegionEmpty(&tParent->clipList); + } + else { + for (tWin = tChild; tWin; tWin = tWin->nextSib) { + if (tWin->valdata) + RegionAppend(&totalClip, &tWin->borderClip); + } + RegionValidate(&totalClip, &overlap); + } + + if (kind != VTStack) + RegionUnion(&totalClip, &totalClip, &tParent->clipList); + + for (tWin = tChild; tWin; tWin = tWin->nextSib) { + if (tWin->valdata) { + if (tWin->pWin->viewable) { + RegionIntersect(&childClip, &totalClip, + &tWin->pWin->borderSize); + miOverlayComputeClips(tWin->pWin, &childClip, kind, &exposed); + RegionSubtract(&totalClip, &totalClip, &tWin->pWin->borderSize); + } + else { /* Means we are unmapping */ + RegionEmpty(&tWin->clipList); + RegionEmpty(&tWin->borderClip); + tWin->valdata = NULL; + } + } + } + + RegionUninit(&childClip); + + if (!((*pPriv->InOverlay) (newParent))) { + RegionNull(&tParent->valdata->exposed); + RegionNull(&tParent->valdata->borderExposed); + } + + switch (kind) { + case VTStack: + break; + default: + if (!((*pPriv->InOverlay) (newParent))) + RegionSubtract(&tParent->valdata->exposed, &totalClip, + &tParent->clipList); + /* fall through */ + case VTMap: + RegionCopy(&tParent->clipList, &totalClip); + if (!((*pPriv->InOverlay) (newParent))) + newParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; + break; + } + + RegionUninit(&totalClip); + RegionUninit(&exposed); + + SKIP_UNDERLAY: + + miValidateTree(pParent, pChild, kind); + + return 1; +} + +static void +miOverlayHandleExposures(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + WindowPtr pChild; + ValidatePtr val; + void (*WindowExposures) (WindowPtr, RegionPtr, RegionPtr); + + WindowExposures = pWin->drawable.pScreen->WindowExposures; + if (pPriv->underlayMarked) { + miOverlayTreePtr pTree; + miOverlayValDataPtr mival; + + pChild = pWin; + while (IN_OVERLAY(pChild)) + pChild = pChild->parent; + + pTree = MIOVERLAY_GET_WINDOW_TREE(pChild); + + while (1) { + if ((mival = pTree->valdata)) { + if (!((*pPriv->InOverlay) (pTree->pWin))) { + if (RegionNotEmpty(&mival->borderExposed)) { + miPaintWindow(pTree->pWin, &mival->borderExposed, + PW_BORDER); + } + RegionUninit(&mival->borderExposed); + + (*WindowExposures) (pTree->pWin, &mival->exposed, + NullRegion); + RegionUninit(&mival->exposed); + } + free(mival); + pTree->valdata = NULL; + if (pTree->firstChild) { + pTree = pTree->firstChild; + continue; + } + } + while (!pTree->nextSib && (pTree->pWin != pChild)) + pTree = pTree->parent; + if (pTree->pWin == pChild) + break; + pTree = pTree->nextSib; + } + pPriv->underlayMarked = FALSE; + } + + pChild = pWin; + while (1) { + if ((val = pChild->valdata)) { + if (!((*pPriv->InOverlay) (pChild))) { + RegionUnion(&val->after.exposed, &val->after.exposed, + &val->after.borderExposed); + + if (RegionNotEmpty(&val->after.exposed)) { + (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent)) + (pScreen, RegionNumRects(&val->after.exposed), + RegionRects(&val->after.exposed)); + } + } + else { + if (RegionNotEmpty(&val->after.borderExposed)) { + miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER); + } + (*WindowExposures) (pChild, &val->after.exposed, NullRegion); + } + RegionUninit(&val->after.borderExposed); + RegionUninit(&val->after.exposed); + free(val); + pChild->valdata = NULL; + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } +} + +static void +miOverlayMoveWindow(WindowPtr pWin, + int x, int y, WindowPtr pNextSib, VTKind kind) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + WindowPtr pParent, windowToValidate; + Bool WasViewable = (Bool) (pWin->viewable); + short bw; + RegionRec overReg, underReg; + DDXPointRec oldpt; + + if (!(pParent = pWin->parent)) + return; + bw = wBorderWidth(pWin); + + oldpt.x = pWin->drawable.x; + oldpt.y = pWin->drawable.y; + if (WasViewable) { + RegionNull(&overReg); + RegionNull(&underReg); + if (pTree) { + RegionCopy(&overReg, &pWin->borderClip); + RegionCopy(&underReg, &pTree->borderClip); + } + else { + RegionCopy(&overReg, &pWin->borderClip); + CollectUnderlayChildrenRegions(pWin, &underReg); + } + (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); + } + pWin->origin.x = x + (int) bw; + pWin->origin.y = y + (int) bw; + x = pWin->drawable.x = pParent->drawable.x + x + (int) bw; + y = pWin->drawable.y = pParent->drawable.y + y + (int) bw; + + SetWinSize(pWin); + SetBorderSize(pWin); + + (*pScreen->PositionWindow) (pWin, x, y); + + windowToValidate = MoveWindowInStack(pWin, pNextSib); + + ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0); + + if (WasViewable) { + miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + + (*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL); + + (*pScreen->ValidateTree) (pWin->parent, NullWindow, kind); + if (RegionNotEmpty(&underReg)) { + pPriv->copyUnderlay = TRUE; + (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, &underReg); + } + RegionUninit(&underReg); + if (RegionNotEmpty(&overReg)) { + pPriv->copyUnderlay = FALSE; + (*pWin->drawable.pScreen->CopyWindow) (pWin, oldpt, &overReg); + } + RegionUninit(&overReg); + (*pScreen->HandleExposures) (pWin->parent); + + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pWin->parent, NullWindow, kind); + } + if (pWin->realized) + WindowsRestructured(); +} + +#ifndef RECTLIMIT +#define RECTLIMIT 25 +#endif + +static void +miOverlayWindowExposures(WindowPtr pWin, + RegionPtr prgn, RegionPtr other_exposed) +{ + RegionPtr exposures = prgn; + + if ((prgn && !RegionNil(prgn)) || + (exposures && !RegionNil(exposures)) || other_exposed) { + RegionRec expRec; + int clientInterested; + + clientInterested = (pWin->eventMask | wOtherEventMasks(pWin)) & + ExposureMask; + if (other_exposed) { + if (exposures) { + RegionUnion(other_exposed, exposures, other_exposed); + if (exposures != prgn) + RegionDestroy(exposures); + } + exposures = other_exposed; + } + if (clientInterested && exposures && + (RegionNumRects(exposures) > RECTLIMIT)) { + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + BoxRec box; + + box = *RegionExtents(exposures); + if (exposures == prgn) { + exposures = &expRec; + RegionInit(exposures, &box, 1); + RegionReset(prgn, &box); + } + else { + RegionReset(exposures, &box); + RegionUnion(prgn, prgn, exposures); + } + /* This is the only reason why we are replacing mi's version + of this file */ + + if (!((*pPriv->InOverlay) (pWin))) { + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + + RegionIntersect(prgn, prgn, &pTree->clipList); + } + else + RegionIntersect(prgn, prgn, &pWin->clipList); + } + if (prgn && !RegionNil(prgn)) + miPaintWindow(pWin, prgn, PW_BACKGROUND); + if (clientInterested && exposures && !RegionNil(exposures)) + miSendExposures(pWin, exposures, + pWin->drawable.x, pWin->drawable.y); + if (exposures == &expRec) { + RegionUninit(exposures); + } + else if (exposures && exposures != prgn && exposures != other_exposed) + RegionDestroy(exposures); + if (prgn) + RegionEmpty(prgn); + } + else if (exposures && exposures != prgn) + RegionDestroy(exposures); +} + +typedef struct { + RegionPtr over; + RegionPtr under; +} miOverlayTwoRegions; + +static int +miOverlayRecomputeExposures(WindowPtr pWin, pointer value) +{ + miOverlayTwoRegions *pValid = (miOverlayTwoRegions *) value; + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + + if (pWin->valdata) { + /* + * compute exposed regions of this window + */ + RegionSubtract(&pWin->valdata->after.exposed, + &pWin->clipList, pValid->over); + /* + * compute exposed regions of the border + */ + RegionSubtract(&pWin->valdata->after.borderExposed, + &pWin->borderClip, &pWin->winSize); + RegionSubtract(&pWin->valdata->after.borderExposed, + &pWin->valdata->after.borderExposed, pValid->over); + } + + if (pTree && pTree->valdata) { + RegionSubtract(&pTree->valdata->exposed, + &pTree->clipList, pValid->under); + RegionSubtract(&pTree->valdata->borderExposed, + &pTree->borderClip, &pWin->winSize); + RegionSubtract(&pTree->valdata->borderExposed, + &pTree->valdata->borderExposed, pValid->under); + } + else if (!pWin->valdata) + return WT_NOMATCH; + + return WT_WALKCHILDREN; +} + +static void +miOverlayResizeWindow(WindowPtr pWin, + int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent; + miOverlayTreePtr tChild, pTree; + Bool WasViewable = (Bool) (pWin->viewable); + unsigned short width = pWin->drawable.width; + unsigned short height = pWin->drawable.height; + short oldx = pWin->drawable.x; + short oldy = pWin->drawable.y; + int bw = wBorderWidth(pWin); + short dw, dh; + DDXPointRec oldpt; + RegionPtr oldRegion = NULL, oldRegion2 = NULL; + WindowPtr pFirstChange; + WindowPtr pChild; + RegionPtr gravitate[StaticGravity + 1]; + RegionPtr gravitate2[StaticGravity + 1]; + unsigned g; + int nx, ny; /* destination x,y */ + int newx, newy; /* new inner window position */ + RegionPtr pRegion = NULL; + RegionPtr destClip, destClip2; + RegionPtr oldWinClip = NULL, oldWinClip2 = NULL; + RegionPtr borderVisible = NullRegion; + RegionPtr borderVisible2 = NullRegion; + Bool shrunk = FALSE; /* shrunk in an inner dimension */ + Bool moved = FALSE; /* window position changed */ + Bool doUnderlay; + + /* if this is a root window, can't be resized */ + if (!(pParent = pWin->parent)) + return; + + pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + doUnderlay = ((pTree) || HasUnderlayChildren(pWin)); + newx = pParent->drawable.x + x + bw; + newy = pParent->drawable.y + y + bw; + if (WasViewable) { + /* + * save the visible region of the window + */ + oldRegion = RegionCreate(NullBox, 1); + RegionCopy(oldRegion, &pWin->winSize); + if (doUnderlay) { + oldRegion2 = RegionCreate(NullBox, 1); + RegionCopy(oldRegion2, &pWin->winSize); + } + + /* + * categorize child windows into regions to be moved + */ + for (g = 0; g <= StaticGravity; g++) + gravitate[g] = gravitate2[g] = NULL; + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + g = pChild->winGravity; + if (g != UnmapGravity) { + if (!gravitate[g]) + gravitate[g] = RegionCreate(NullBox, 1); + RegionUnion(gravitate[g], gravitate[g], &pChild->borderClip); + + if (doUnderlay) { + if (!gravitate2[g]) + gravitate2[g] = RegionCreate(NullBox, 0); + + if ((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) { + RegionUnion(gravitate2[g], + gravitate2[g], &tChild->borderClip); + } + else + CollectUnderlayChildrenRegions(pChild, gravitate2[g]); + } + } + else { + UnmapWindow(pChild, TRUE); + } + } + (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); + + oldWinClip = oldWinClip2 = NULL; + if (pWin->bitGravity != ForgetGravity) { + oldWinClip = RegionCreate(NullBox, 1); + RegionCopy(oldWinClip, &pWin->clipList); + if (pTree) { + oldWinClip2 = RegionCreate(NullBox, 1); + RegionCopy(oldWinClip2, &pTree->clipList); + } + } + /* + * if the window is changing size, borderExposed + * can't be computed correctly without some help. + */ + if (pWin->drawable.height > h || pWin->drawable.width > w) + shrunk = TRUE; + + if (newx != oldx || newy != oldy) + moved = TRUE; + + if ((pWin->drawable.height != h || pWin->drawable.width != w) && + HasBorder(pWin)) { + borderVisible = RegionCreate(NullBox, 1); + if (pTree) + borderVisible2 = RegionCreate(NullBox, 1); + /* for tiled borders, we punt and draw the whole thing */ + if (pWin->borderIsPixel || !moved) { + if (shrunk || moved) + RegionSubtract(borderVisible, + &pWin->borderClip, &pWin->winSize); + else + RegionCopy(borderVisible, &pWin->borderClip); + if (pTree) { + if (shrunk || moved) + RegionSubtract(borderVisible, + &pTree->borderClip, &pWin->winSize); + else + RegionCopy(borderVisible, &pTree->borderClip); + } + } + } + } + pWin->origin.x = x + bw; + pWin->origin.y = y + bw; + pWin->drawable.height = h; + pWin->drawable.width = w; + + x = pWin->drawable.x = newx; + y = pWin->drawable.y = newy; + + SetWinSize(pWin); + SetBorderSize(pWin); + + dw = (int) w - (int) width; + dh = (int) h - (int) height; + ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh); + + /* let the hardware adjust background and border pixmaps, if any */ + (*pScreen->PositionWindow) (pWin, x, y); + + pFirstChange = MoveWindowInStack(pWin, pSib); + + if (WasViewable) { + pRegion = RegionCreate(NullBox, 1); + + (*pScreen->MarkOverlappedWindows) (pWin, pFirstChange, NULL); + + pWin->valdata->before.resized = TRUE; + pWin->valdata->before.borderVisible = borderVisible; + if (pTree) + pTree->valdata->borderVisible = borderVisible2; + + (*pScreen->ValidateTree) (pWin->parent, pFirstChange, VTOther); + /* + * the entire window is trashed unless bitGravity + * recovers portions of it + */ + RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList); + if (pTree) + RegionCopy(&pTree->valdata->exposed, &pTree->clipList); + } + + GravityTranslate(x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny); + + if (WasViewable) { + miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + miOverlayTwoRegions TwoRegions; + + /* avoid the border */ + if (HasBorder(pWin)) { + int offx, offy, dx, dy; + + /* kruft to avoid double translates for each gravity */ + offx = 0; + offy = 0; + for (g = 0; g <= StaticGravity; g++) { + if (!gravitate[g] && !gravitate2[g]) + continue; + + /* align winSize to gravitate[g]. + * winSize is in new coordinates, + * gravitate[g] is still in old coordinates */ + GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + dx = (oldx - nx) - offx; + dy = (oldy - ny) - offy; + if (dx || dy) { + RegionTranslate(&pWin->winSize, dx, dy); + offx += dx; + offy += dy; + } + if (gravitate[g]) + RegionIntersect(gravitate[g], gravitate[g], &pWin->winSize); + if (gravitate2[g]) + RegionIntersect(gravitate2[g], gravitate2[g], + &pWin->winSize); + } + /* get winSize back where it belongs */ + if (offx || offy) + RegionTranslate(&pWin->winSize, -offx, -offy); + } + /* + * add screen bits to the appropriate bucket + */ + + if (oldWinClip2) { + RegionCopy(pRegion, oldWinClip2); + RegionTranslate(pRegion, nx - oldx, ny - oldy); + RegionIntersect(oldWinClip2, pRegion, &pTree->clipList); + + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { + if (gravitate2[g]) + RegionSubtract(oldWinClip2, oldWinClip2, gravitate2[g]); + } + RegionTranslate(oldWinClip2, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate2[g]) + gravitate2[g] = oldWinClip2; + else { + RegionUnion(gravitate2[g], gravitate2[g], oldWinClip2); + RegionDestroy(oldWinClip2); + } + } + + if (oldWinClip) { + /* + * clip to new clipList + */ + RegionCopy(pRegion, oldWinClip); + RegionTranslate(pRegion, nx - oldx, ny - oldy); + RegionIntersect(oldWinClip, pRegion, &pWin->clipList); + /* + * don't step on any gravity bits which will be copied after this + * region. Note -- this assumes that the regions will be copied + * in gravity order. + */ + for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) { + if (gravitate[g]) + RegionSubtract(oldWinClip, oldWinClip, gravitate[g]); + } + RegionTranslate(oldWinClip, oldx - nx, oldy - ny); + g = pWin->bitGravity; + if (!gravitate[g]) + gravitate[g] = oldWinClip; + else { + RegionUnion(gravitate[g], gravitate[g], oldWinClip); + RegionDestroy(oldWinClip); + } + } + + /* + * move the bits on the screen + */ + + destClip = destClip2 = NULL; + + for (g = 0; g <= StaticGravity; g++) { + if (!gravitate[g] && !gravitate2[g]) + continue; + + GravityTranslate(x, y, oldx, oldy, dw, dh, g, &nx, &ny); + + oldpt.x = oldx + (x - nx); + oldpt.y = oldy + (y - ny); + + /* Note that gravitate[g] is *translated* by CopyWindow */ + + /* only copy the remaining useful bits */ + + if (gravitate[g]) + RegionIntersect(gravitate[g], gravitate[g], oldRegion); + if (gravitate2[g]) + RegionIntersect(gravitate2[g], gravitate2[g], oldRegion2); + + /* clip to not overwrite already copied areas */ + + if (destClip && gravitate[g]) { + RegionTranslate(destClip, oldpt.x - x, oldpt.y - y); + RegionSubtract(gravitate[g], gravitate[g], destClip); + RegionTranslate(destClip, x - oldpt.x, y - oldpt.y); + } + if (destClip2 && gravitate2[g]) { + RegionTranslate(destClip2, oldpt.x - x, oldpt.y - y); + RegionSubtract(gravitate2[g], gravitate2[g], destClip2); + RegionTranslate(destClip2, x - oldpt.x, y - oldpt.y); + } + + /* and move those bits */ + + if (oldpt.x != x || oldpt.y != y) { + if (gravitate2[g]) { + pPriv->copyUnderlay = TRUE; + (*pScreen->CopyWindow) (pWin, oldpt, gravitate2[g]); + } + if (gravitate[g]) { + pPriv->copyUnderlay = FALSE; + (*pScreen->CopyWindow) (pWin, oldpt, gravitate[g]); + } + } + + /* remove any overwritten bits from the remaining useful bits */ + + if (gravitate[g]) + RegionSubtract(oldRegion, oldRegion, gravitate[g]); + if (gravitate2[g]) + RegionSubtract(oldRegion2, oldRegion2, gravitate2[g]); + + /* + * recompute exposed regions of child windows + */ + + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + if (pChild->winGravity != g) + continue; + + TwoRegions.over = gravitate[g]; + TwoRegions.under = gravitate2[g]; + + TraverseTree(pChild, miOverlayRecomputeExposures, + (pointer) (&TwoRegions)); + } + + /* + * remove the successfully copied regions of the + * window from its exposed region + */ + + if (g == pWin->bitGravity) { + if (gravitate[g]) + RegionSubtract(&pWin->valdata->after.exposed, + &pWin->valdata->after.exposed, gravitate[g]); + if (gravitate2[g] && pTree) + RegionSubtract(&pTree->valdata->exposed, + &pTree->valdata->exposed, gravitate2[g]); + } + if (gravitate[g]) { + if (!destClip) + destClip = gravitate[g]; + else { + RegionUnion(destClip, destClip, gravitate[g]); + RegionDestroy(gravitate[g]); + } + } + if (gravitate2[g]) { + if (!destClip2) + destClip2 = gravitate2[g]; + else { + RegionUnion(destClip2, destClip2, gravitate2[g]); + RegionDestroy(gravitate2[g]); + } + } + } + + RegionDestroy(pRegion); + RegionDestroy(oldRegion); + if (doUnderlay) + RegionDestroy(oldRegion2); + if (destClip) + RegionDestroy(destClip); + if (destClip2) + RegionDestroy(destClip2); + (*pScreen->HandleExposures) (pWin->parent); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pWin->parent, pFirstChange, VTOther); + } + if (pWin->realized) + WindowsRestructured(); +} + +static void +miOverlaySetShape(WindowPtr pWin, int kind) +{ + Bool WasViewable = (Bool) (pWin->viewable); + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (kind != ShapeInput) { + if (WasViewable) { + (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); + + if (HasBorder(pWin)) { + RegionPtr borderVisible; + + borderVisible = RegionCreate(NullBox, 1); + RegionSubtract(borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + pWin->valdata->before.resized = TRUE; + if (IN_UNDERLAY(pWin)) { + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + RegionPtr borderVisible2; + + borderVisible2 = RegionCreate(NULL, 1); + RegionSubtract(borderVisible2, + &pTree->borderClip, &pWin->winSize); + pTree->valdata->borderVisible = borderVisible2; + } + } + } + + SetWinSize(pWin); + SetBorderSize(pWin); + + ResizeChildrenWinSize(pWin, 0, 0, 0, 0); + + if (WasViewable) { + (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); + + (*pScreen->ValidateTree) (pWin->parent, NullWindow, VTOther); + } + + if (WasViewable) { + (*pScreen->HandleExposures) (pWin->parent); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pWin->parent, NullWindow, + VTOther); + } + } + if (pWin->realized) + WindowsRestructured(); + CheckCursorConfinement(pWin); +} + +static void +miOverlayChangeBorderWidth(WindowPtr pWin, unsigned int width) +{ + int oldwidth; + ScreenPtr pScreen; + Bool WasViewable = (Bool) (pWin->viewable); + Bool HadBorder; + + oldwidth = wBorderWidth(pWin); + if (oldwidth == width) + return; + HadBorder = HasBorder(pWin); + pScreen = pWin->drawable.pScreen; + if (WasViewable && (width < oldwidth)) + (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); + + pWin->borderWidth = width; + SetBorderSize(pWin); + + if (WasViewable) { + if (width > oldwidth) { + (*pScreen->MarkOverlappedWindows) (pWin, pWin, NULL); + + if (HadBorder) { + RegionPtr borderVisible; + + borderVisible = RegionCreate(NULL, 1); + RegionSubtract(borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + if (IN_UNDERLAY(pWin)) { + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + RegionPtr borderVisible2; + + borderVisible2 = RegionCreate(NULL, 1); + RegionSubtract(borderVisible2, + &pTree->borderClip, &pWin->winSize); + pTree->valdata->borderVisible = borderVisible2; + } + } + } + (*pScreen->ValidateTree) (pWin->parent, pWin, VTOther); + (*pScreen->HandleExposures) (pWin->parent); + + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pWin->parent, pWin, VTOther); + } + if (pWin->realized) + WindowsRestructured(); +} + +/* We need this as an addition since the xf86 common code doesn't + know about the second tree which is static to this file. */ + +void +miOverlaySetRootClip(ScreenPtr pScreen, Bool enable) +{ + WindowPtr pRoot = pScreen->root; + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot); + + MARK_UNDERLAY(pRoot); + + if (enable) { + BoxRec box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + + RegionReset(&pTree->borderClip, &box); + } + else + RegionEmpty(&pTree->borderClip); + + RegionBreak(&pTree->clipList); +} + +static void +miOverlayClearToBackground(WindowPtr pWin, + int x, int y, int w, int h, Bool generateExposures) +{ + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + BoxRec box; + RegionRec reg; + RegionPtr pBSReg = NullRegion; + ScreenPtr pScreen = pWin->drawable.pScreen; + miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen); + RegionPtr clipList; + BoxPtr extents; + int x1, y1, x2, y2; + + x1 = pWin->drawable.x + x; + y1 = pWin->drawable.y + y; + if (w) + x2 = x1 + (int) w; + else + x2 = x1 + (int) pWin->drawable.width - (int) x; + if (h) + y2 = y1 + h; + else + y2 = y1 + (int) pWin->drawable.height - (int) y; + + clipList = ((*pScreenPriv->InOverlay) (pWin)) ? &pWin->clipList : + &pTree->clipList; + + extents = RegionExtents(clipList); + + if (x1 < extents->x1) + x1 = extents->x1; + if (x2 > extents->x2) + x2 = extents->x2; + if (y1 < extents->y1) + y1 = extents->y1; + if (y2 > extents->y2) + y2 = extents->y2; + + if (x2 <= x1 || y2 <= y1) + x2 = x1 = y2 = y1 = 0; + + box.x1 = x1; + box.x2 = x2; + box.y1 = y1; + box.y2 = y2; + + RegionInit(®, &box, 1); + + RegionIntersect(®, ®, clipList); + if (generateExposures) + (*pScreen->WindowExposures) (pWin, ®, pBSReg); + else if (pWin->backgroundState != None) + miPaintWindow(pWin, ®, PW_BACKGROUND); + RegionUninit(®); + if (pBSReg) + RegionDestroy(pBSReg); +} + +/****************************************************************/ + +/* not used */ +Bool +miOverlayGetPrivateClips(WindowPtr pWin, + RegionPtr *borderClip, RegionPtr *clipList) +{ + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + + if (pTree) { + *borderClip = &(pTree->borderClip); + *clipList = &(pTree->clipList); + return TRUE; + } + + *borderClip = *clipList = NULL; + + return FALSE; +} + +void +miOverlaySetTransFunction(ScreenPtr pScreen, miOverlayTransFunc transFunc) +{ + MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc; +} + +Bool +miOverlayCopyUnderlay(ScreenPtr pScreen) +{ + return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay; +} + +void +miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin) +{ + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + RegionPtr pregWin; + Bool freeTmpClip, freeCompClip; + + if (!pTree) { + miComputeCompositeClip(pGC, &pWin->drawable); + return; + } + + if (pGC->subWindowMode == IncludeInferiors) { + pregWin = RegionCreate(NullBox, 1); + freeTmpClip = TRUE; + if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) || + !HasSaverWindow(pGC->pScreen)) { + RegionIntersect(pregWin, &pTree->borderClip, &pWin->winSize); + } + } + else { + pregWin = &pTree->clipList; + freeTmpClip = FALSE; + } + freeCompClip = pGC->freeCompClip; + if (pGC->clientClipType == CT_NONE) { + if (freeCompClip) + RegionDestroy(pGC->pCompositeClip); + pGC->pCompositeClip = pregWin; + pGC->freeCompClip = freeTmpClip; + } + else { + RegionTranslate(pGC->clientClip, + pWin->drawable.x + pGC->clipOrg.x, + pWin->drawable.y + pGC->clipOrg.y); + + if (freeCompClip) { + RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip); + if (freeTmpClip) + RegionDestroy(pregWin); + } + else if (freeTmpClip) { + RegionIntersect(pregWin, pregWin, pGC->clientClip); + pGC->pCompositeClip = pregWin; + } + else { + pGC->pCompositeClip = RegionCreate(NullBox, 0); + RegionIntersect(pGC->pCompositeClip, pregWin, pGC->clientClip); + } + pGC->freeCompClip = TRUE; + RegionTranslate(pGC->clientClip, + -(pWin->drawable.x + pGC->clipOrg.x), + -(pWin->drawable.y + pGC->clipOrg.y)); + } +} + +Bool +miOverlayCollectUnderlayRegions(WindowPtr pWin, RegionPtr *region) +{ + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + + if (pTree) { + *region = &pTree->borderClip; + return FALSE; + } + + *region = RegionCreate(NullBox, 0); + + CollectUnderlayChildrenRegions(pWin, *region); + + return TRUE; +} + +static miOverlayTreePtr +DoLeaf(WindowPtr pWin, miOverlayTreePtr parent, miOverlayTreePtr prevSib) +{ + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + + pTree->parent = parent; + pTree->firstChild = NULL; + pTree->lastChild = NULL; + pTree->prevSib = prevSib; + pTree->nextSib = NULL; + + if (prevSib) + prevSib->nextSib = pTree; + + if (!parent->firstChild) + parent->firstChild = parent->lastChild = pTree; + else if (parent->lastChild == prevSib) + parent->lastChild = pTree; + + return pTree; +} + +static void +RebuildTree(WindowPtr pWin) +{ + miOverlayTreePtr parent, prevSib, tChild; + WindowPtr pChild; + + prevSib = tChild = NULL; + + pWin = pWin->parent; + + while (IN_OVERLAY(pWin)) + pWin = pWin->parent; + + parent = MIOVERLAY_GET_WINDOW_TREE(pWin); + + pChild = pWin->firstChild; + parent->firstChild = parent->lastChild = NULL; + + while (1) { + if (IN_UNDERLAY(pChild)) + prevSib = tChild = DoLeaf(pChild, parent, prevSib); + + if (pChild->firstChild) { + if (IN_UNDERLAY(pChild)) { + parent = tChild; + prevSib = NULL; + } + pChild = pChild->firstChild; + continue; + } + + while (!pChild->nextSib) { + pChild = pChild->parent; + if (pChild == pWin) + return; + if (IN_UNDERLAY(pChild)) { + prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild); + parent = tChild->parent; + } + } + + pChild = pChild->nextSib; + } +} + +static Bool +HasUnderlayChildren(WindowPtr pWin) +{ + WindowPtr pChild; + + if (!(pChild = pWin->firstChild)) + return FALSE; + + while (1) { + if (IN_UNDERLAY(pChild)) + return TRUE; + + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + + while (!pChild->nextSib && (pWin != pChild)) + pChild = pChild->parent; + + if (pChild == pWin) + break; + + pChild = pChild->nextSib; + } + + return FALSE; +} + +static Bool +CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg) +{ + WindowPtr pChild; + miOverlayTreePtr pTree; + Bool hasUnderlay; + + if (!(pChild = pWin->firstChild)) + return FALSE; + + hasUnderlay = FALSE; + + while (1) { + if ((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) { + RegionAppend(pReg, &pTree->borderClip); + hasUnderlay = TRUE; + } + else if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + + while (!pChild->nextSib && (pWin != pChild)) + pChild = pChild->parent; + + if (pChild == pWin) + break; + + pChild = pChild->nextSib; + } + + if (hasUnderlay) { + Bool overlap; + + RegionValidate(pReg, &overlap); + } + + return hasUnderlay; +} + +static void +MarkUnderlayWindow(WindowPtr pWin) +{ + miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin); + + if (pTree->valdata) + return; + pTree->valdata = + (miOverlayValDataPtr) xnfalloc(sizeof(miOverlayValDataRec)); + pTree->valdata->oldAbsCorner.x = pWin->drawable.x; + pTree->valdata->oldAbsCorner.y = pWin->drawable.y; + pTree->valdata->borderVisible = NullRegion; +} |