#include "layerstr.h"
static LayerListPtr
NewLayerList (ScreenPtr pScreen, LayerPtr pLayer)
{
LayerListPtr pLayList;
pLayList = (LayerListPtr) xalloc (sizeof (LayerListRec));
if (!pLayList)
return 0;
pLayList->pNext = 0;
pLayList->pLayer = pLayer;
pLayList->inheritClip = TRUE;
REGION_NULL (pScreen, &pLayList->clipList);
REGION_NULL (pScreen, &pLayList->borderClip);
return pLayList;
}
static void
FreeLayerList (ScreenPtr pScreen, LayerListPtr pLayList)
{
REGION_UNINIT (pScreen, &pLayList->clipList);
REGION_UNINIT (pScreen, &pLayList->borderClip);
xfree (pLayList);
}
Bool
LayerCreatePixmap (ScreenPtr pScreen, LayerPtr pLayer)
{
LayerKindPtr pKind = pLayer->pKind;
LayerUnwrap (pScreen, pKind, CreatePixmap);
pLayer->pPixmap = (*pScreen->CreatePixmap) (pScreen, pScreen->width,
pScreen->height, pLayer->depth);
LayerWrap (pScreen, pKind, CreatePixmap, layerCreatePixmap);
if (!pLayer->pPixmap)
return FALSE;
if (pLayer->pKind->kind == LAYER_SHADOW)
{
if (!shadowAdd (pScreen, pLayer->pPixmap, pLayer->update,
pLayer->window, pLayer->randr,
pLayer->closure))
return FALSE;
}
return TRUE;
}
void
LayerDestroyPixmap (ScreenPtr pScreen, LayerPtr pLayer)
{
if (pLayer->pPixmap)
{
if (pLayer->pKind->kind == LAYER_SHADOW)
shadowRemove (pScreen, pLayer->pPixmap);
if (pLayer->freePixmap)
{
LayerKindPtr pKind = pLayer->pKind;
LayerUnwrap (pScreen, pKind, DestroyPixmap);
(*pScreen->DestroyPixmap) (pLayer->pPixmap);
LayerWrap (pScreen, pKind, DestroyPixmap, layerDestroyPixmap);
}
pLayer->pPixmap = 0;
}
}
Bool
LayerWindowAdd (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin)
{
layerWinPriv(pWin);
if (pLayer->pPixmap == LAYER_SCREEN_PIXMAP)
pLayer->pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
else if (!pLayer->pPixmap && !LayerCreatePixmap (pScreen, pLayer))
return FALSE;
if (pLayWin->isList || pLayWin->u.pLayer)
{
LayerListPtr pPrev;
LayerListPtr pLayList;
if (!pLayWin->isList)
{
pPrev = NewLayerList (pScreen, pLayWin->u.pLayer);
if (!pPrev)
return FALSE;
}
else
{
for (pPrev = pLayWin->u.pLayList; pPrev->pNext; pPrev = pPrev->pNext)
;
}
pLayList = NewLayerList (pScreen, pLayer);
if (!pLayList)
{
if (!pLayWin->isList)
FreeLayerList (pScreen, pPrev);
return FALSE;
}
pPrev->pNext = pLayList;
if (!pLayWin->isList)
{
pLayWin->isList = TRUE;
pLayWin->u.pLayList = pPrev;
}
}
else
pLayWin->u.pLayer = pLayer;
(*pScreen->SetWindowPixmap) (pWin, pLayer->pPixmap);
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
pLayer->refcnt++;
pLayer->windows++;
return TRUE;
}
void
LayerWindowRemove (ScreenPtr pScreen, LayerPtr pLayer, WindowPtr pWin)
{
layerWinPriv(pWin);
if (pLayWin->isList)
{
LayerListPtr *pPrev;
LayerListPtr pLayList;
for (pPrev = &pLayWin->u.pLayList; (pLayList = *pPrev); pPrev = &pLayList->pNext)
{
if (pLayList->pLayer == pLayer)
{
*pPrev = pLayList->pNext;
FreeLayerList (pScreen, pLayList);
--pLayer->windows;
if (pLayer->windows <= 0)
LayerDestroyPixmap (pScreen, pLayer);
LayerDestroy (pScreen, pLayer);
break;
}
}
pLayList = pLayWin->u.pLayList;
if (!pLayList)
{
pLayWin->isList = FALSE;
pLayWin->u.pLayer = 0;
}
else if (!pLayList->pNext && pLayList->inheritClip)
{
pLayer = pLayList->pLayer;
FreeLayerList (pScreen, pLayList);
pLayWin->isList = FALSE;
pLayWin->u.pLayer = pLayer;
}
}
else
{
if (pLayWin->u.pLayer == pLayer)
{
--pLayer->windows;
if (pLayer->windows <= 0)
LayerDestroyPixmap (pScreen, pLayer);
LayerDestroy (pScreen, pLayer);
pLayWin->u.pLayer = 0;
}
}
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
LayerPtr
LayerWindowFirst (WindowPtr pWin, LayerWinLoopPtr pLoop)
{
layerWinPriv (pWin);
pLoop->pLayWin = pLayWin;
if (!pLayWin->isList)
return pLayWin->u.pLayer;
pLoop->clipList = pWin->clipList;
pLoop->borderClip = pWin->borderClip;
pLoop->pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
pLoop->pLayList = pLayWin->u.pLayList;
return LayerWindowNext (pWin, pLoop);
}
LayerPtr
LayerWindowNext (WindowPtr pWin, LayerWinLoopPtr pLoop)
{
LayerPtr pLayer;
LayerWinPtr pLayWin = pLoop->pLayWin;
LayerListPtr pLayList;
if (!pLayWin->isList)
return 0;
pLayList = pLoop->pLayList;
pLayer = pLayList->pLayer;
(*pWin->drawable.pScreen->SetWindowPixmap) (pWin, pLayer->pPixmap);
if (!pLayList->inheritClip)
{
pWin->clipList = pLayList->clipList;
pWin->borderClip = pLayList->borderClip;
}
pLoop->pLayList = pLayList->pNext;
return pLayer;
}
void
LayerWindowDone (WindowPtr pWin, LayerWinLoopPtr pLoop)
{
LayerWinPtr pLayWin = pLoop->pLayWin;
if (!pLayWin->isList)
return;
pWin->clipList = pLoop->clipList;
pWin->borderClip = pLoop->clipList;
(*pWin->drawable.pScreen->SetWindowPixmap) (pWin, pLoop->pPixmap);
}
Bool
layerCreateWindow (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
layerWinPriv(pWin);
layerScrPriv(pScreen);
LayerPtr pLayer;
Bool ret;
pLayWin->isList = FALSE;
pLayWin->u.pLayer = 0;
if (pWin->drawable.type == UNDRAWABLE_WINDOW)
return TRUE;
for (pLayer = pLayScr->pLayers; pLayer; pLayer = pLayer->pNext)
if (pLayer->depth == pWin->drawable.depth)
break;
ret = TRUE;
if (pLayer)
{
pScreen->CreateWindow = pLayer->pKind->CreateWindow;
ret = (*pScreen->CreateWindow) (pWin);
pLayer->pKind->CreateWindow = pScreen->CreateWindow;
pScreen->CreateWindow = layerCreateWindow;
LayerWindowAdd (pScreen, pLayer, pWin);
}
return ret;
}
Bool
layerDestroyWindow (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
layerWinPriv(pWin);
LayerPtr pLayer;
Bool ret = TRUE;
while ((pLayer = layerWinLayer (pLayWin)))
{
LayerUnwrap (pScreen, pLayer->pKind, DestroyWindow);
ret = (*pScreen->DestroyWindow) (pWin);
LayerWrap (pScreen, pLayer->pKind, DestroyWindow, layerDestroyWindow);
LayerWindowRemove (pWin->drawable.pScreen, pLayer, pWin);
}
return ret;
}
Bool
layerChangeWindowAttributes (WindowPtr pWin, unsigned long mask)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
LayerPtr pLay;
LayerWinLoopRec loop;
Bool ret = TRUE;
for (pLay = LayerWindowFirst (pWin, &loop);
pLay;
pLay = LayerWindowNext (pWin, &loop))
{
LayerUnwrap(pScreen,pLay->pKind,ChangeWindowAttributes);
if (!(*pScreen->ChangeWindowAttributes) (pWin, mask))
ret = FALSE;
LayerWrap(pScreen,pLay->pKind,ChangeWindowAttributes,layerChangeWindowAttributes);
}
LayerWindowDone (pWin, &loop);
return ret;
}
void
layerPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
LayerPtr pLay;
LayerWinLoopRec loop;
for (pLay = LayerWindowFirst (pWin, &loop);
pLay;
pLay = LayerWindowNext (pWin, &loop))
{
LayerUnwrap(pScreen,pLay->pKind,PaintWindowBackground);
(*pScreen->PaintWindowBackground) (pWin, pRegion, what);
LayerWrap(pScreen,pLay->pKind,PaintWindowBackground,layerPaintWindowBackground);
}
LayerWindowDone (pWin, &loop);
}
void
layerPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
LayerPtr pLay;
LayerWinLoopRec loop;
for (pLay = LayerWindowFirst (pWin, &loop);
pLay;
pLay = LayerWindowNext (pWin, &loop))
{
LayerUnwrap(pScreen,pLay->pKind,PaintWindowBorder);
(*pScreen->PaintWindowBorder) (pWin, pRegion, what);
LayerWrap(pScreen,pLay->pKind,PaintWindowBorder,layerPaintWindowBorder);
}
LayerWindowDone (pWin, &loop);
}
void
layerCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
LayerPtr pLay;
LayerWinLoopRec loop;
int dx = 0, dy = 0;
for (pLay = LayerWindowFirst (pWin, &loop);
pLay;
pLay = LayerWindowNext (pWin, &loop))
{
LayerUnwrap(pScreen,pLay->pKind,CopyWindow);
if (dx || dy)
REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy);
(*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
LayerWrap(pScreen,pLay->pKind,CopyWindow,layerCopyWindow);
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
}
LayerWindowDone (pWin, &loop);
}
PixmapPtr
layerCreatePixmap (ScreenPtr pScreen, int width, int height, int depth)
{
layerScrPriv (pScreen);
LayerKindPtr pKind;
PixmapPtr pPixmap;
pKind = &pLayScr->kinds[0];
if (pLayScr->pLayers)
pKind = pLayScr->pLayers->pKind;
LayerUnwrap (pScreen, pKind, CreatePixmap);
pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth);
LayerWrap (pScreen,pKind,CreatePixmap,layerCreatePixmap);
return pPixmap;
}
Bool
layerDestroyPixmap (PixmapPtr pPixmap)
{
ScreenPtr pScreen = pPixmap->drawable.pScreen;
layerScrPriv (pScreen);
LayerKindPtr pKind;
Bool ret;
pKind = &pLayScr->kinds[0];
if (pLayScr->pLayers)
pKind = pLayScr->pLayers->pKind;
LayerUnwrap (pScreen, pKind, DestroyPixmap);
ret = (*pScreen->DestroyPixmap) (pPixmap);
LayerWrap (pScreen,pKind,DestroyPixmap,layerDestroyPixmap);
return ret;
}