#include "rootlessCommon.h"
#include "rootlessWindow.h"
#include "fb.h"
Bool
RootlessCreateWindow(WindowPtr pWin)
{
Bool result;
RegionRec saveRoot;
WINREC(pWin) = NULL;
SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
if (!IsRoot(pWin)) {
HUGE_ROOT(pWin);
SetWinSize(pWin);
SetBorderSize(pWin);
}
result = pWin->drawable.pScreen->CreateWindow(pWin);
if (pWin->parent) {
NORMAL_ROOT(pWin);
}
SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
return result;
}
Bool
RootlessDestroyWindow(WindowPtr pWin)
{
Bool result;
SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
result = pWin->drawable.pScreen->DestroyWindow(pWin);
SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
return result;
}
#ifdef SHAPE
void
RootlessSetShape(WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessDamageShape(pWin);
SCREEN_UNWRAP(pScreen, SetShape);
pScreen->SetShape(pWin);
SCREEN_WRAP(pScreen, SetShape);
}
#endif // SHAPE
Bool
RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
{
Bool result;
ScreenPtr pScreen = pWin->drawable.pScreen;
RL_DEBUG_MSG("change window attributes start ");
SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
result = pScreen->ChangeWindowAttributes(pWin, vmask);
SCREEN_WRAP(pScreen, ChangeWindowAttributes);
if (WINREC(pWin)) {
if (pWin->backgroundState == ParentRelative) {
XID pixel = 0;
ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
}
}
RL_DEBUG_MSG("change window attributes end\n");
return result;
}
Bool
RootlessPositionWindow(WindowPtr pWin, int x, int y)
{
RootlessWindowRec *winRec = WINREC(pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
Bool result;
RL_DEBUG_MSG("positionwindow start\n");
if (winRec) {
winRec->frame.x = x - pWin->borderWidth;
winRec->frame.y = y - pWin->borderWidth;
}
UpdatePixmap(pWin);
SCREEN_UNWRAP(pScreen, PositionWindow);
result = pScreen->PositionWindow(pWin, x, y);
SCREEN_WRAP(pScreen, PositionWindow);
RL_DEBUG_MSG("positionwindow end\n");
return result;
}
Bool
RootlessRealizeWindow(WindowPtr pWin)
{
Bool result = FALSE;
RegionRec saveRoot;
ScreenPtr pScreen = pWin->drawable.pScreen;
RL_DEBUG_MSG("realizewindow start ");
if (IsTopLevel(pWin) || IsRoot(pWin)) {
DrawablePtr d = &pWin->drawable;
RootlessWindowRec *winRec = xalloc(sizeof(RootlessWindowRec));
if (! winRec) goto windowcreatebad;
winRec->frame.isRoot = (pWin == WindowTable[pScreen->myNum]);
winRec->frame.x = d->x - pWin->borderWidth;
winRec->frame.y = d->y - pWin->borderWidth;
winRec->frame.w = d->width + 2*pWin->borderWidth;
winRec->frame.h = d->height + 2*pWin->borderWidth;
winRec->frame.win = pWin;
winRec->frame.devPrivate = NULL;
REGION_NULL(pScreen, &winRec->damage);
winRec->borderWidth = pWin->borderWidth;
winRec->pixmap = NULL;
WINREC(pWin) = winRec;
RL_DEBUG_MSG("creating frame ");
CallFrameProc(pScreen, CreateFrame,
(pScreen, &WINREC(pWin)->frame,
pWin->prevSib ? &WINREC(pWin->prevSib)->frame : NULL));
if (pWin->backgroundState == ParentRelative) {
XID pixel = 0;
ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
}
#ifdef SHAPE
winRec->shapeDamage = TRUE;
#endif
}
UpdatePixmap(pWin);
if (!IsRoot(pWin)) HUGE_ROOT(pWin);
SCREEN_UNWRAP(pScreen, RealizeWindow);
result = pScreen->RealizeWindow(pWin);
SCREEN_WRAP(pScreen, RealizeWindow);
if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
RL_DEBUG_MSG("realizewindow end\n");
return result;
windowcreatebad:
RL_DEBUG_MSG("window create bad! ");
RL_DEBUG_MSG("realizewindow end\n");
return NULL;
}
Bool
RootlessUnrealizeWindow(WindowPtr pWin)
{
Bool result;
ScreenPtr pScreen = pWin->drawable.pScreen;
RL_DEBUG_MSG("unrealizewindow start ");
if (IsTopLevel(pWin) || IsRoot(pWin)) {
RootlessWindowRec *winRec = WINREC(pWin);
RootlessRedisplay(pWin);
CallFrameProc(pScreen, DestroyFrame, (pScreen, &winRec->frame));
REGION_UNINIT(pScreen, &winRec->damage);
xfree(winRec);
WINREC(pWin) = NULL;
}
SCREEN_UNWRAP(pScreen, UnrealizeWindow);
result = pScreen->UnrealizeWindow(pWin);
SCREEN_WRAP(pScreen, UnrealizeWindow);
RL_DEBUG_MSG("unrealizewindow end\n");
return result;
}
void
RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
{
RegionRec saveRoot;
RootlessWindowRec *winRec = WINREC(pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
RL_DEBUG_MSG("restackwindow start ");
if (winRec) RL_DEBUG_MSG("restack top level \n");
HUGE_ROOT(pWin);
SCREEN_UNWRAP(pScreen, RestackWindow);
if (pScreen->RestackWindow) pScreen->RestackWindow(pWin, pOldNextSib);
SCREEN_WRAP(pScreen, RestackWindow);
NORMAL_ROOT(pWin);
if (winRec) {
WindowPtr oldNextW, newNextW, oldPrevW, newPrevW;
RootlessFramePtr oldNext, newNext, oldPrev, newPrev;
oldNextW = pOldNextSib;
while (oldNextW && ! WINREC(oldNextW)) oldNextW = oldNextW->nextSib;
oldNext = oldNextW ? &WINREC(oldNextW)->frame : NULL;
newNextW = pWin->nextSib;
while (newNextW && ! WINREC(newNextW)) newNextW = newNextW->nextSib;
newNext = newNextW ? &WINREC(newNextW)->frame : NULL;
oldPrevW= pOldNextSib ? pOldNextSib->prevSib : pWin->parent->lastChild;
while (oldPrevW && ! WINREC(oldPrevW)) oldPrevW = oldPrevW->prevSib;
oldPrev = oldPrevW ? &WINREC(oldPrevW)->frame : NULL;
newPrevW = pWin->prevSib;
while (newPrevW && ! WINREC(newPrevW)) newPrevW = newPrevW->prevSib;
newPrev = newPrevW ? &WINREC(newPrevW)->frame : NULL;
if (pWin->prevSib) {
WindowPtr w = pWin->prevSib;
while (w) {
RL_DEBUG_MSG("w 0x%x\n", w);
w = w->parent;
}
}
CallFrameProc(pScreen, RestackFrame,
(pScreen, &winRec->frame, oldPrev, newPrev));
}
RL_DEBUG_MSG("restackwindow end\n");
}
static PixmapPtr gResizeDeathPix = NULL;
static pointer gResizeDeathBits = NULL;
static PixmapPtr gResizeCopyWindowSource = NULL;
static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
static void
RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
RegionPtr prgnSrc)
{
int dx = ptOldOrg.x - pWin->drawable.x;
int dy = ptOldOrg.y - pWin->drawable.y;
RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
}
static void
RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
SCREEN_UNWRAP(pScreen, CopyWindow);
RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
{
RegionRec rgnDst;
int dx, dy;
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
REGION_NULL(pScreen, &rgnDst);
REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
fbCopyRegion (&gResizeCopyWindowSource->drawable,
&pScreen->GetWindowPixmap(pWin)->drawable,
0,
&rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
REGION_UNINIT(pScreen, &rgnDst);
fbValidateDrawable (&pWin->drawable);
}
SCREEN_WRAP(pScreen, CopyWindow);
RL_DEBUG_MSG("resizecopywindowFB end\n");
}
void
RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
SCREEN_UNWRAP(pScreen, CopyWindow);
RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
{
RegionRec rgnDst;
int dx, dy;
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
REGION_NULL(pScreen, &rgnDst);
REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
fbCopyRegion ((DrawablePtr)pWin, (DrawablePtr)pWin,
0,
&rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
RootlessDamageRegion(pWin, prgnSrc);
REGION_UNINIT(pScreen, &rgnDst);
fbValidateDrawable (&pWin->drawable);
}
SCREEN_WRAP(pScreen, CopyWindow);
RL_DEBUG_MSG("copywindowFB end\n");
}
static void
StartFrameResize(WindowPtr pWin, Bool gravity,
int oldX, int oldY,
unsigned int oldW, unsigned int oldH, unsigned int oldBW,
int newX, int newY,
unsigned int newW, unsigned int newH, unsigned int newBW)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec = WINREC(pWin);
RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW ");
RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d ",
oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
RootlessRedisplay(pWin);
gResizeDeathBits = xalloc(winRec->frame.bytesPerRow * winRec->frame.h);
memcpy(gResizeDeathBits, winRec->frame.pixelData,
winRec->frame.bytesPerRow * winRec->frame.h);
gResizeDeathPix =
GetScratchPixmapHeader(pScreen, winRec->frame.w, winRec->frame.h,
winRec->frame.depth, winRec->frame.bitsPerPixel,
winRec->frame.bytesPerRow, gResizeDeathBits);
SetPixmapBaseToScreen(gResizeDeathPix, winRec->frame.x, winRec->frame.y);
winRec->frame.x = newX;
winRec->frame.y = newY;
winRec->frame.w = newW;
winRec->frame.h = newH;
winRec->borderWidth = newBW;
CallFrameProc(pScreen, StartResizeFrame,
(pScreen, &winRec->frame, oldX, oldY, oldW, oldH));
UpdatePixmap(pWin);
if (gravity) {
gResizeCopyWindowSource = gResizeDeathPix;
gResizeOldCopyWindowProc = pScreen->CopyWindow;
pScreen->CopyWindow = RootlessResizeCopyWindow;
}
{
RegionRec r;
DrawablePtr src = &gResizeDeathPix->drawable;
DrawablePtr dst = &pScreen->GetWindowPixmap(pWin)->drawable;
int oldX2 = (int)(oldX + oldW), newX2 = (int)(newX + newW);
int oldY2 = (int)(oldY + oldH), newY2 = (int)(newY + newH);
r.data = NULL;
r.extents.x1 = max(oldX, newX);
r.extents.y1 = max(oldY, newY);
r.extents.x2 = min(oldX2, newX2);
r.extents.y2 = min(oldY2, newY2);
if (r.extents.x2 > r.extents.x1 && r.extents.y2 > r.extents.y1) {
#if 0
DDXPointRec srcPt = {r.extents.x1, r.extents.y1};
int dx = newX - oldX;
int dy = newY - oldY;
REGION_TRANSLATE(pScreen, &r, dx, dy);
#endif
fbCopyRegion(src, dst, NULL, &r, 0, 0, fbCopyWindowProc, 0, 0);
}
REGION_UNINIT(pScreen, &r);
}
}
static void
FinishFrameResize(WindowPtr pWin, Bool gravity,
int oldX, int oldY,
unsigned int oldW, unsigned int oldH, unsigned int oldBW,
int newX, int newY,
unsigned int newW, unsigned int newH, unsigned int newBW)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec = WINREC(pWin);
CallFrameProc(pScreen, FinishResizeFrame,
(pScreen, &winRec->frame, oldX, oldY, oldW, oldH));
if (wBoundingShape(pWin)) {
RootlessDamageShape(pWin);
}
FreeScratchPixmapHeader(gResizeDeathPix);
xfree(gResizeDeathBits);
gResizeDeathPix = gResizeDeathBits = NULL;
if (gravity) {
pScreen->CopyWindow = gResizeOldCopyWindowProc;
gResizeCopyWindowSource = NULL;
}
}
void
RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
{
CopyWindowProcPtr oldCopyWindowProc = NULL;
RegionRec saveRoot;
RootlessWindowRec *winRec = WINREC(pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
int oldX = 0, oldY = 0, newX = 0, newY = 0;
unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
RL_DEBUG_MSG("movewindow start \n");
if (winRec) {
if (kind == VTMove) {
oldX = winRec->frame.x;
oldY = winRec->frame.y;
RootlessRedisplay(pWin);
} else {
RL_DEBUG_MSG("movewindow border resizing ");
oldBW = winRec->borderWidth;
oldX = winRec->frame.x;
oldY = winRec->frame.y;
oldW = winRec->frame.w;
oldH = winRec->frame.h;
newBW = pWin->borderWidth;
newX = x;
newY = y;
newW = pWin->drawable.width + 2*newBW;
newH = pWin->drawable.height + 2*newBW;
StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
}
HUGE_ROOT(pWin);
SCREEN_UNWRAP(pScreen, MoveWindow);
if (winRec) {
oldCopyWindowProc = pScreen->CopyWindow;
pScreen->CopyWindow = RootlessNoCopyWindow;
}
pScreen->MoveWindow(pWin, x, y, pSib, kind);
if (winRec) {
pScreen->CopyWindow = oldCopyWindowProc;
}
NORMAL_ROOT(pWin);
SCREEN_WRAP(pScreen, MoveWindow);
if (winRec) {
if (kind == VTMove) {
CallFrameProc(pScreen, MoveFrame,
(pScreen, &winRec->frame, oldX, oldY));
} else {
FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
}
RL_DEBUG_MSG("movewindow end\n");
}
void
RootlessResizeWindow(WindowPtr pWin, int x, int y,
unsigned int w, unsigned int h, WindowPtr pSib)
{
RegionRec saveRoot;
RootlessWindowRec *winRec = WINREC(pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
int oldX = 0, oldY = 0, newX = 0, newY = 0;
unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
if (winRec) {
oldBW = winRec->borderWidth;
oldX = winRec->frame.x;
oldY = winRec->frame.y;
oldW = winRec->frame.w;
oldH = winRec->frame.h;
newBW = oldBW;
newX = x;
newY = y;
newW = w + 2*newBW;
newH = h + 2*newBW;
StartFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
HUGE_ROOT(pWin);
SCREEN_UNWRAP(pScreen, ResizeWindow);
pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
SCREEN_WRAP(pScreen, ResizeWindow);
NORMAL_ROOT(pWin);
if (winRec) {
FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
RL_DEBUG_MSG("resizewindow end\n");
}
void
RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
{
RegionRec saveRoot;
RL_DEBUG_MSG("change border width ");
if (width != pWin->borderWidth) {
RootlessWindowRec *winRec = WINREC(pWin);
int oldX = 0, oldY = 0, newX = 0, newY = 0;
unsigned int oldW = 0, oldH = 0, oldBW = 0;
unsigned int newW = 0, newH = 0, newBW = 0;
if (winRec) {
oldBW = winRec->borderWidth;
oldX = winRec->frame.x;
oldY = winRec->frame.y;
oldW = winRec->frame.w;
oldH = winRec->frame.h;
newBW = width;
newX = pWin->drawable.x - newBW;
newY = pWin->drawable.y - newBW;
newW = pWin->drawable.width + 2*newBW;
newH = pWin->drawable.height + 2*newBW;
StartFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
HUGE_ROOT(pWin);
SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
NORMAL_ROOT(pWin);
if (winRec) {
FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
}
RL_DEBUG_MSG("change border width end\n");
}