1901 lines
59 KiB
C
1901 lines
59 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, 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;
|
|
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;
|
|
}
|