1868 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1868 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C
		
	
	
	
| 
 | |
| #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(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);
 | |
| 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(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) (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;
 | |
|     WindowExposuresProcPtr WindowExposures;
 | |
| 
 | |
|     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)) {
 | |
|                         pScreen->PaintWindow(pTree->pWin, &mival->borderExposed,
 | |
|                                              PW_BORDER);
 | |
|                     }
 | |
|                     RegionUninit(&mival->borderExposed);
 | |
| 
 | |
|                     (*WindowExposures) (pTree->pWin, &mival->exposed);
 | |
|                     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)) {
 | |
|                     pScreen->PaintWindow(pChild, &val->after.borderExposed,
 | |
|                                          PW_BORDER);
 | |
|                 }
 | |
|                 (*WindowExposures) (pChild, &val->after.exposed);
 | |
|             }
 | |
|             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 exposures = prgn;
 | |
|     ScreenPtr pScreen = pWin->drawable.pScreen;
 | |
| 
 | |
|     if (prgn && !RegionNil(prgn)) {
 | |
|         RegionRec expRec;
 | |
|         int clientInterested =
 | |
|             (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask;
 | |
|         if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) {
 | |
|             miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
 | |
|             BoxRec box;
 | |
| 
 | |
|             box = *RegionExtents(prgn);
 | |
|             exposures = &expRec;
 | |
|             RegionInit(exposures, &box, 1);
 | |
|             RegionReset(prgn, &box);
 | |
|             /* 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);
 | |
|         }
 | |
|         pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND);
 | |
|         if (clientInterested)
 | |
|             miSendExposures(pWin, exposures,
 | |
|                             pWin->drawable.x, pWin->drawable.y);
 | |
|         if (exposures == &expRec)
 | |
|             RegionUninit(exposures);
 | |
|         RegionEmpty(prgn);
 | |
|     }
 | |
| }
 | |
| 
 | |
| typedef struct {
 | |
|     RegionPtr over;
 | |
|     RegionPtr under;
 | |
| } miOverlayTwoRegions;
 | |
| 
 | |
| static int
 | |
| miOverlayRecomputeExposures(WindowPtr pWin, void *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,
 | |
|                              (void *) (&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);
 | |
|             (*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;
 | |
|     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, ®);
 | |
|     else if (pWin->backgroundState != None)
 | |
|         pScreen->PaintWindow(pWin, ®, PW_BACKGROUND);
 | |
|     RegionUninit(®);
 | |
| }
 | |
| 
 | |
| /****************************************************************/
 | |
| 
 | |
| /* 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->clientClip) {
 | |
|         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;
 | |
| }
 |