#define NEED_REPLIES
#define NEED_EVENTS
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "os.h"
#include "windowstr.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "dixstruct.h"
#include "resource.h"
#include "opaque.h"
#include "dbestruct.h"
#include "midbestr.h"
#include "regionstr.h"
#include "gcstruct.h"
#include "inputstr.h"
#include "midbe.h"
#include "xace.h"
#include <stdio.h>
static int miDbeWindowPrivPrivKeyIndex;
static DevPrivateKey miDbeWindowPrivPrivKey = &miDbeWindowPrivPrivKeyIndex;
static RESTYPE dbeDrawableResType;
static RESTYPE dbeWindowPrivResType;
static int dbeScreenPrivKeyIndex;
static DevPrivateKey dbeScreenPrivKey = &dbeScreenPrivKeyIndex;
static int dbeWindowPrivKeyIndex;
static DevPrivateKey dbeWindowPrivKey = &dbeWindowPrivKeyIndex;
static Bool
miDbeGetVisualInfo(ScreenPtr pScreen, XdbeScreenVisualInfo *pScrVisInfo)
{
register int i, j, k;
register int count;
DepthPtr pDepth;
XdbeVisualInfo *visInfo;
for (i = 0, count = 0; i < pScreen->numDepths; i++)
{
count += pScreen->allowedDepths[i].numVids;
}
if (!(visInfo = (XdbeVisualInfo *)xalloc(count * sizeof(XdbeVisualInfo))))
{
return(FALSE);
}
for (i = 0, k = 0; i < pScreen->numDepths; i++)
{
pDepth = &pScreen->allowedDepths[i];
for (j = 0; j < pDepth->numVids; j++)
{
visInfo[k].visual = pDepth->vids[j];
visInfo[k].depth = pDepth->depth;
visInfo[k].perflevel = 0;
k++;
}
}
pScrVisInfo->count = count;
pScrVisInfo->visinfo = visInfo;
return(TRUE);
}
static int
miDbeAllocBackBufferName(WindowPtr pWin, XID bufId, int swapAction)
{
ScreenPtr pScreen;
DbeWindowPrivPtr pDbeWindowPriv;
MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
DbeScreenPrivPtr pDbeScreenPriv;
GCPtr pGC;
xRectangle clearRect;
int rc;
pScreen = pWin->drawable.pScreen;
pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
if (pDbeWindowPriv->nBufferIDs == 0)
{
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
pDbeWindowPrivPriv->pDbeWindowPriv = pDbeWindowPriv;
if (!(pDbeWindowPrivPriv->pFrontBuffer =
(*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
pDbeWindowPriv->height,
pWin->drawable.depth, 0)))
{
return(BadAlloc);
}
if (!(pDbeWindowPrivPriv->pBackBuffer =
(*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
pDbeWindowPriv->height,
pWin->drawable.depth, 0)))
{
(*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
return(BadAlloc);
}
rc = XaceHook(XACE_RESOURCE_ACCESS, serverClient, bufId,
dbeDrawableResType, pDbeWindowPrivPriv->pBackBuffer,
RT_WINDOW, pWin, DixCreateAccess);
if (rc != Success || !AddResource(bufId, dbeDrawableResType,
pDbeWindowPrivPriv->pBackBuffer))
{
FreeResource(bufId, RT_NONE);
return (rc == Success) ? BadAlloc : rc;
}
dixSetPrivate(&pDbeWindowPriv->devPrivates, miDbeWindowPrivPrivKey,
pDbeWindowPrivPriv);
pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
{
ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC);
clearRect.x = clearRect.y = 0;
clearRect.width = pDbeWindowPrivPriv->pBackBuffer->drawable.width;
clearRect.height = pDbeWindowPrivPriv->pBackBuffer->drawable.height;
(*pGC->ops->PolyFillRect)(
(DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC, 1,
&clearRect);
}
FreeScratchGC(pGC);
}
else
{
pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
if (!AddResource(bufId, dbeDrawableResType,
(pointer)pDbeWindowPrivPriv->pBackBuffer))
{
return(BadAlloc);
}
}
return(Success);
}
static void
miDbeAliasBuffers(DbeWindowPrivPtr pDbeWindowPriv)
{
int i;
MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv =
MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++)
{
ChangeResourceValue(pDbeWindowPriv->IDs[i], dbeDrawableResType,
(pointer)pDbeWindowPrivPriv->pBackBuffer);
}
}
static int
miDbeSwapBuffers(ClientPtr client, int *pNumWindows, DbeSwapInfoPtr swapInfo)
{
DbeScreenPrivPtr pDbeScreenPriv;
GCPtr pGC;
WindowPtr pWin;
MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
PixmapPtr pTmpBuffer;
xRectangle clearRect;
pWin = swapInfo[0].pWindow;
pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin);
pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin);
pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
switch(swapInfo[0].swapAction)
{
case XdbeUndefined:
break;
case XdbeBackground:
break;
case XdbeUntouched:
ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer, pGC);
(*pGC->ops->CopyArea)((DrawablePtr)pWin,
(DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
pGC, 0, 0, pWin->drawable.width,
pWin->drawable.height, 0, 0);
break;
case XdbeCopied:
break;
}
ValidateGC((DrawablePtr)pWin, pGC);
(*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
(DrawablePtr)pWin, pGC, 0, 0,
pWin->drawable.width, pWin->drawable.height,
0, 0);
switch(swapInfo[0].swapAction)
{
case XdbeUndefined:
break;
case XdbeBackground:
if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
{
ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC);
clearRect.x = 0;
clearRect.y = 0;
clearRect.width =
pDbeWindowPrivPriv->pBackBuffer->drawable.width;
clearRect.height =
pDbeWindowPrivPriv->pBackBuffer->drawable.height;
(*pGC->ops->PolyFillRect)(
(DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
pGC, 1, &clearRect);
}
break;
case XdbeUntouched:
pTmpBuffer = pDbeWindowPrivPriv->pBackBuffer;
pDbeWindowPrivPriv->pBackBuffer =
pDbeWindowPrivPriv->pFrontBuffer;
pDbeWindowPrivPriv->pFrontBuffer = pTmpBuffer;
miDbeAliasBuffers(pDbeWindowPrivPriv->pDbeWindowPriv);
break;
case XdbeCopied:
break;
}
if (*pNumWindows > 1)
{
swapInfo[0].pWindow = swapInfo[*pNumWindows - 1].pWindow;
swapInfo[0].swapAction = swapInfo[*pNumWindows - 1].swapAction;
swapInfo[*pNumWindows - 1].pWindow = (WindowPtr)NULL;
swapInfo[*pNumWindows - 1].swapAction = 0;
}
else
{
swapInfo[0].pWindow = (WindowPtr)NULL;
swapInfo[0].swapAction = 0;
}
(*pNumWindows)--;
FreeScratchGC(pGC);
return(Success);
}
static void
miDbeWinPrivDelete(DbeWindowPrivPtr pDbeWindowPriv, XID bufId)
{
MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
if (pDbeWindowPriv->nBufferIDs != 0)
{
return;
}
pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
if (pDbeWindowPrivPriv->pFrontBuffer)
{
(*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
pDbeWindowPrivPriv->pFrontBuffer);
}
if (pDbeWindowPrivPriv->pBackBuffer)
{
(*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
pDbeWindowPrivPriv->pBackBuffer);
}
}
static Bool
miDbePositionWindow(WindowPtr pWin, int x, int y)
{
ScreenPtr pScreen;
DbeScreenPrivPtr pDbeScreenPriv;
DbeWindowPrivPtr pDbeWindowPriv;
int width, height;
int dx, dy, dw, dh;
int sourcex, sourcey;
int destx, desty;
int savewidth, saveheight;
PixmapPtr pFrontBuffer;
PixmapPtr pBackBuffer;
Bool clear;
GCPtr pGC;
xRectangle clearRect;
Bool ret;
pScreen = pWin->drawable.pScreen;
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
ret = (*pScreen->PositionWindow)(pWin, x, y);
pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
pScreen->PositionWindow = miDbePositionWindow;
if (!(pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)))
{
return(ret);
}
if (pDbeWindowPriv->width == pWin->drawable.width &&
pDbeWindowPriv->height == pWin->drawable.height)
{
return(ret);
}
width = pWin->drawable.width;
height = pWin->drawable.height;
dx = pWin->drawable.x - pDbeWindowPriv->x;
dy = pWin->drawable.y - pDbeWindowPriv->y;
dw = width - pDbeWindowPriv->width;
dh = height - pDbeWindowPriv->height;
GravityTranslate (0, 0, -dx, -dy, dw, dh, pWin->bitGravity, &destx, &desty);
clear = ((pDbeWindowPriv->width < (unsigned short)width ) ||
(pDbeWindowPriv->height < (unsigned short)height) ||
(pWin->bitGravity == ForgetGravity));
sourcex = 0;
sourcey = 0;
savewidth = pDbeWindowPriv->width;
saveheight = pDbeWindowPriv->height;
if (destx < 0)
{
savewidth += destx;
sourcex -= destx;
destx = 0;
}
if (destx + savewidth > width)
{
savewidth = width - destx;
}
if (desty < 0)
{
saveheight += desty;
sourcey -= desty;
desty = 0;
}
if (desty + saveheight > height)
{
saveheight = height - desty;
}
pDbeWindowPriv->width = width;
pDbeWindowPriv->height = height;
pDbeWindowPriv->x = pWin->drawable.x;
pDbeWindowPriv->y = pWin->drawable.y;
pGC = GetScratchGC (pWin->drawable.depth, pScreen);
if (clear)
{
if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
{
clearRect.x = 0;
clearRect.y = 0;
clearRect.width = width;
clearRect.height = height;
}
else
{
clear = FALSE;
}
}
pFrontBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
pWin->drawable.depth, 0);
pBackBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
pWin->drawable.depth, 0);
if (!pFrontBuffer || !pBackBuffer)
{
if (pFrontBuffer)
{
(*pScreen->DestroyPixmap)(pFrontBuffer);
}
if (pBackBuffer)
{
(*pScreen->DestroyPixmap)(pBackBuffer);
}
while (pDbeWindowPriv)
{
FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
}
FreeScratchGC(pGC);
return(FALSE);
}
else
{
MiDbeWindowPrivPrivPtr pDbeWindowPrivPriv;
pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
ValidateGC((DrawablePtr)pFrontBuffer, pGC);
if (clear)
{
(*pGC->ops->PolyFillRect)((DrawablePtr)pFrontBuffer, pGC, 1,
&clearRect);
(*pGC->ops->PolyFillRect)((DrawablePtr)pBackBuffer , pGC, 1,
&clearRect);
}
if (pWin->bitGravity != ForgetGravity)
{
(*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
(DrawablePtr)pFrontBuffer, pGC, sourcex,
sourcey, savewidth, saveheight, destx, desty);
(*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
(DrawablePtr)pBackBuffer, pGC, sourcex,
sourcey, savewidth, saveheight, destx, desty);
}
(*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
(*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pBackBuffer);
pDbeWindowPrivPriv->pFrontBuffer = pFrontBuffer;
pDbeWindowPrivPriv->pBackBuffer = pBackBuffer;
miDbeAliasBuffers(pDbeWindowPriv);
FreeScratchGC(pGC);
}
return(ret);
}
static void
miDbeResetProc(ScreenPtr pScreen)
{
DbeScreenPrivPtr pDbeScreenPriv;
pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
}
Bool
miDbeInit(ScreenPtr pScreen, DbeScreenPrivPtr pDbeScreenPriv)
{
dbeDrawableResType = pDbeScreenPriv->dbeDrawableResType;
dbeWindowPrivResType = pDbeScreenPriv->dbeWindowPrivResType;
dbeScreenPrivKey = pDbeScreenPriv->dbeScreenPrivKey;
dbeWindowPrivKey = pDbeScreenPriv->dbeWindowPrivKey;
if (!dixRequestPrivate(miDbeWindowPrivPrivKey,
sizeof(MiDbeWindowPrivPrivRec)))
return(FALSE);
pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
pScreen->PositionWindow = miDbePositionWindow;
pDbeScreenPriv->GetVisualInfo = miDbeGetVisualInfo;
pDbeScreenPriv->AllocBackBufferName = miDbeAllocBackBufferName;
pDbeScreenPriv->SwapBuffers = miDbeSwapBuffers;
pDbeScreenPriv->BeginIdiom = 0;
pDbeScreenPriv->EndIdiom = 0;
pDbeScreenPriv->ResetProc = miDbeResetProc;
pDbeScreenPriv->WinPrivDelete = miDbeWinPrivDelete;
return(TRUE);
}