#include "rootless-common.h"
#include "rootless-window.h"
#include "darwin.h"
#include "Xplugin.h"
#include "x-hash.h"
#include "x-list.h"
#define _APPLEWM_SERVER_
#include "applewmstr.h"
#include "fb.h"
#include "propertyst.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#include <X11/Xatom.h>
#include <pthread.h>
#define DEFINE_ATOM_HELPER(func,atom_name) \
static Atom func (void) { \
static unsigned int generation; \
static Atom atom; \
if (generation != serverGeneration) { \
generation = serverGeneration; \
atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
} \
return atom; \
}
DEFINE_ATOM_HELPER (xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
DEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
static x_hash_table *window_hash;
static pthread_mutex_t window_hash_mutex;
static Bool no_configure_window;
static Bool windows_hidden;
static const int normal_window_levels[AppleWMNumWindowLevels+1] = {
0, 3, 4, 5, LONG_MIN + 30, LONG_MIN + 29,
};
static const int rooted_window_levels[AppleWMNumWindowLevels+1] = {
202, 203, 204, 205, 201, 200
};
static inline xp_error
configure_window (xp_window_id id, unsigned int mask,
const xp_window_changes *values)
{
if (!no_configure_window)
return xp_configure_window (id, mask, values);
else
return XP_Success;
}
static inline unsigned long
current_time_in_seconds (void)
{
unsigned long t = 0;
t += currentTime.milliseconds / 1000;
t += currentTime.months * 4294967;
return t;
}
static inline Bool
rootlessHasRoot (ScreenPtr pScreen)
{
return WINREC (WindowTable[pScreen->myNum]) != NULL;
}
void
RootlessNativeWindowStateChanged (xp_window_id id, unsigned int state)
{
WindowPtr pWin;
RootlessWindowRec *winRec;
pWin = RootlessGetXWindow (id);
if (pWin == NULL)
return;
winRec = WINREC (pWin);
if (winRec == NULL)
return;
winRec->is_offscreen = (state & XP_WINDOW_STATE_OFFSCREEN) != 0;
winRec->is_obscured = (state & XP_WINDOW_STATE_OBSCURED) != 0;
#ifdef ROOTLESS
pWin->rootlessUnhittable = winRec->is_offscreen;
#endif
}
void
RootlessNativeWindowMoved (xp_window_id id)
{
WindowPtr pWin;
xp_box bounds;
int sx, sy;
XID vlist[2];
Mask mask;
ClientPtr client;
pWin = RootlessGetXWindow (id);
if (pWin == NULL)
return;
if (xp_get_window_bounds (id, &bounds) != Success)
return;
sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX;
sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY;
vlist[0] = (INT16) bounds.x1 - sx;
vlist[1] = (INT16) bounds.y1 - sy;
mask = CWX | CWY;
client = LookupClient (pWin->drawable.id, NullClient);
no_configure_window = TRUE;
ConfigureWindow (pWin, mask, vlist, client);
no_configure_window = FALSE;
}
static void
set_screen_origin (WindowPtr pWin)
{
long data[2];
if (!IsRoot (pWin))
return;
data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x
+ darwinMainScreenX);
data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
+ darwinMainScreenY);
ChangeWindowProperty (pWin, xa_native_screen_origin (), XA_INTEGER,
32, PropModeReplace, 2, data, TRUE);
}
Bool
RootlessCreateWindow (WindowPtr pWin)
{
Bool result;
RegionRec saveRoot;
SCREEN_UNWRAP (pWin->drawable.pScreen, CreateWindow);
if (!IsRoot (pWin))
{
HUGE_ROOT (pWin);
SetWinSize (pWin);
SetBorderSize (pWin);
}
else
{
set_screen_origin (pWin);
}
result = pWin->drawable.pScreen->CreateWindow (pWin);
if (pWin->parent)
NORMAL_ROOT (pWin);
SCREEN_WRAP (pWin->drawable.pScreen, CreateWindow);
return result;
}
static void
rootlessDestroyFrame (WindowPtr pWin, RootlessWindowRec *winRec)
{
RootlessStopDrawing (pWin, FALSE);
pthread_mutex_lock (&window_hash_mutex);
x_hash_table_remove (window_hash, (void *) winRec->wid);
pthread_mutex_unlock (&window_hash_mutex);
xp_destroy_window (winRec->wid);
xfree (winRec);
WINREC (pWin) = NULL;
}
Bool
RootlessDestroyWindow (WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC(pWin);
Bool result;
if (winRec != NULL)
rootlessDestroyFrame (pWin, winRec);
SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
result = pWin->drawable.pScreen->DestroyWindow (pWin);
SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
return result;
}
#ifdef SHAPE
static Bool
RootlessGetShape (WindowPtr pWin, RegionPtr pShape)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
if (wBoundingShape (pWin) == NULL)
return FALSE;
REGION_NULL (pScreen, pShape);
REGION_COPY (pScreen, pShape, wBoundingShape (pWin));
REGION_TRANSLATE (pScreen, pShape, pWin->borderWidth, pWin->borderWidth);
return TRUE;
}
static void
rootlessSetShape (WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC (pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
RegionRec newShape;
RegionPtr pShape;
xp_window_changes wc;
if (winRec == NULL)
return;
RootlessStopDrawing (pWin, FALSE);
pShape = RootlessGetShape (pWin, &newShape) ? &newShape : NULL;
RL_DEBUG_MSG("reshaping...");
RL_DEBUG_MSG("numrects %d, extents %d %d %d %d\n",
REGION_NUM_RECTS(&newShape),
newShape.extents.x1, newShape.extents.y1,
newShape.extents.x2, newShape.extents.y2);
RootlessDisableUpdate (pWin);
if (pShape != NULL)
{
wc.shape_nrects = REGION_NUM_RECTS (pShape);
wc.shape_rects = REGION_RECTS (pShape);
}
else
{
wc.shape_nrects = -1;
wc.shape_rects = NULL;
}
wc.shape_tx = wc.shape_ty = 0;
configure_window (winRec->wid, XP_SHAPE, &wc);
if (pShape != NULL)
REGION_UNINIT(pScreen, &newShape);
}
void
RootlessSetShape (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
SCREEN_UNWRAP (pScreen, SetShape);
pScreen->SetShape (pWin);
SCREEN_WRAP (pScreen, SetShape);
rootlessSetShape (pWin);
}
#endif
Bool
RootlessChangeWindowAttributes (WindowPtr pWin, unsigned long vmask)
{
Bool result;
ScreenPtr pScreen = pWin->drawable.pScreen;
RL_DEBUG_MSG("change window attributes start\n");
SCREEN_UNWRAP (pScreen, ChangeWindowAttributes);
result = pScreen->ChangeWindowAttributes (pWin, vmask);
SCREEN_WRAP (pScreen, ChangeWindowAttributes);
if (WINREC (pWin) != NULL)
{
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)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec = WINREC (pWin);
Bool result;
RL_DEBUG_MSG("positionwindow start (win 0x%x)\n", pWin);
if (winRec != NULL)
{
if (winRec->is_drawing)
{
int bw = wBorderWidth (pWin);
winRec->pixmap->devPrivate.ptr = winRec->data;
TranslatePixmapBase (winRec->pixmap, - (x - bw), - (y - bw));
}
}
SCREEN_UNWRAP (pScreen, PositionWindow);
result = pScreen->PositionWindow (pWin, x, y);
SCREEN_WRAP(pScreen, PositionWindow);
RL_DEBUG_MSG("positionwindow end\n");
return result;
}
static void
rootlessInitializeFrame (WindowPtr pWin, RootlessWindowRec *winRec)
{
DrawablePtr d = &pWin->drawable;
int bw = wBorderWidth (pWin);
winRec->win = pWin;
winRec->x = d->x - bw;
winRec->y = d->y - bw;
winRec->width = d->width + 2*bw;
winRec->height = d->height + 2*bw;
winRec->borderWidth = bw;
}
static void
rootlessSetNativeProperty (RootlessWindowRec *winRec)
{
xp_error err;
unsigned int native_id;
long data;
err = xp_get_native_window (winRec->wid, &native_id);
if (err == Success)
{
data = native_id;
ChangeWindowProperty (winRec->win, xa_native_window_id (),
XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
}
}
static xp_error
rootlessColormapCallback (void *data, int first_color,
int n_colors, uint32_t *colors)
{
return (RootlessResolveColormap (data, first_color, n_colors, colors)
? XP_Success : XP_BadMatch);
}
static RootlessWindowRec *
rootlessEnsureFrame (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec;
RegionRec shape;
RegionPtr pShape = NULL;
xp_window_changes wc;
unsigned int mask;
xp_error err;
int sx, sy;
if (WINREC (pWin) != NULL)
return WINREC (pWin);
if (pWin->drawable.class != InputOutput)
return NULL;
winRec = xalloc (sizeof(RootlessWindowRec));
if (!winRec)
return NULL;
rootlessInitializeFrame (pWin, winRec);
winRec->is_drawing = FALSE;
winRec->pixmap = NULL;
winRec->wid = 0;
winRec->is_update_disabled = FALSE;
winRec->is_reorder_pending = FALSE;
winRec->level = !IsRoot (pWin) ? 0 : AppleWMNumWindowLevels;
WINREC(pWin) = winRec;
#ifdef SHAPE
if (RootlessGetShape (pWin, &shape))
pShape = &shape;
#endif
sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
mask = 0;
wc.x = sx + winRec->x;
wc.y = sy + winRec->y;
wc.width = winRec->width;
wc.height = winRec->height;
wc.bit_gravity = XP_GRAVITY_NONE;
mask |= XP_BOUNDS;
if (pWin->drawable.depth == 8)
{
wc.depth = XP_DEPTH_INDEX8;
wc.colormap = rootlessColormapCallback;
wc.colormap_data = pScreen;
mask |= XP_COLORMAP;
}
else if (pWin->drawable.depth == 15)
wc.depth = XP_DEPTH_RGB555;
else if (pWin->drawable.depth == 24)
wc.depth = XP_DEPTH_ARGB8888;
else
wc.depth = XP_DEPTH_NIL;
mask |= XP_DEPTH;
if (pShape != NULL)
{
wc.shape_nrects = REGION_NUM_RECTS (pShape);
wc.shape_rects = REGION_RECTS (pShape);
wc.shape_tx = wc.shape_ty = 0;
mask |= XP_SHAPE;
}
if (!rootlessHasRoot (pScreen))
wc.window_level = normal_window_levels[winRec->level];
else
wc.window_level = rooted_window_levels[winRec->level];
mask |= XP_WINDOW_LEVEL;
err = xp_create_window (mask, &wc, &winRec->wid);
if (err != Success)
{
xfree (winRec);
return NULL;
}
if (window_hash == NULL)
{
window_hash = x_hash_table_new (NULL, NULL, NULL, NULL);
pthread_mutex_init (&window_hash_mutex, NULL);
}
pthread_mutex_lock (&window_hash_mutex);
x_hash_table_insert (window_hash, (void *) winRec->wid, winRec);
pthread_mutex_unlock (&window_hash_mutex);
rootlessSetNativeProperty (winRec);
if (pShape != NULL)
REGION_UNINIT (pScreen, &shape);
return winRec;
}
Bool
RootlessRealizeWindow(WindowPtr pWin)
{
Bool result = FALSE;
RegionRec saveRoot;
ScreenPtr pScreen = pWin->drawable.pScreen;
XID pixel;
RL_DEBUG_MSG("realizewindow start (win 0x%x)\n", pWin);
if (IsTopLevel (pWin) && pWin->drawable.class == InputOutput)
{
RootlessWindowRec *winRec;
winRec = rootlessEnsureFrame (pWin);
if (winRec == NULL)
return FALSE;
winRec->is_reorder_pending = TRUE;
if (pWin->backgroundState == ParentRelative)
{
pixel = 0;
ChangeWindowAttributes (pWin, CWBackPixel, &pixel, serverClient);
}
}
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;
}
void
RootlessEnableRoot (ScreenPtr pScreen)
{
WindowPtr pRoot;
pRoot = WindowTable[pScreen->myNum];
rootlessEnsureFrame (pRoot);
(*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
RootlessReorderWindow (pRoot);
}
void
RootlessDisableRoot (ScreenPtr pScreen)
{
WindowPtr pRoot;
RootlessWindowRec *winRec;
pRoot = WindowTable[pScreen->myNum];
winRec = WINREC (pRoot);
if (winRec != NULL)
{
rootlessDestroyFrame (pRoot, winRec);
DeleteProperty (pRoot, xa_native_window_id ());
}
}
void
RootlessHideAllWindows (void)
{
int i;
ScreenPtr pScreen;
WindowPtr pWin;
RootlessWindowRec *winRec;
xp_window_changes wc;
if (windows_hidden)
return;
windows_hidden = TRUE;
for (i = 0; i < screenInfo.numScreens; i++)
{
pScreen = screenInfo.screens[i];
pWin = WindowTable[i];
if (pScreen == NULL || pWin == NULL)
continue;
for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
{
if (!pWin->realized)
continue;
RootlessStopDrawing (pWin, FALSE);
winRec = WINREC (pWin);
if (winRec != NULL)
{
wc.stack_mode = XP_UNMAPPED;
wc.sibling = 0;
configure_window (winRec->wid, XP_STACKING, &wc);
}
}
}
}
void
RootlessShowAllWindows (void)
{
int i;
ScreenPtr pScreen;
WindowPtr pWin;
RootlessWindowRec *winRec;
if (!windows_hidden)
return;
windows_hidden = FALSE;
for (i = 0; i < screenInfo.numScreens; i++)
{
pScreen = screenInfo.screens[i];
pWin = WindowTable[i];
if (pScreen == NULL || pWin == NULL)
continue;
for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
{
if (!pWin->realized)
continue;
winRec = rootlessEnsureFrame (pWin);
if (winRec == NULL)
continue;
RootlessReorderWindow (pWin);
}
RootlessScreenExpose (pScreen);
}
}
void
RootlessSetWindowLevel (WindowPtr pWin, int level)
{
RootlessWindowRec *winRec;
xp_window_changes wc;
winRec = WINREC (pWin);
if (!IsTopLevel (pWin) || winRec == NULL || winRec->level == level)
return;
RootlessStopDrawing (pWin, FALSE);
winRec->level = level;
if (!rootlessHasRoot (pWin->drawable.pScreen))
wc.window_level = normal_window_levels[level];
else
wc.window_level = rooted_window_levels[level];
configure_window (winRec->wid, XP_WINDOW_LEVEL, &wc);
}
xp_window_id
RootlessGetPhysicalWindow (WindowPtr pWin, Bool create)
{
RootlessWindowRec *winRec;
if (TopLevelParent (pWin) == NULL)
return 0;
winRec = WINREC (pWin);
if (winRec == NULL && create && !IsRoot (pWin)
&& pWin->drawable.class == InputOutput)
{
rootlessEnsureFrame (pWin);
winRec = WINREC (pWin);
}
if (winRec == NULL)
return 0;
return winRec->wid;
}
WindowPtr
RootlessGetXWindow (xp_window_id wid)
{
RootlessWindowRec *winRec;
if (window_hash == NULL)
return NULL;
winRec = x_hash_table_lookup (window_hash, (void *) wid, NULL);
return winRec != NULL ? winRec->win : NULL;
}
int
RootlessKnowsWindowNumber (int number)
{
Bool ret;
xp_window_id wid;
if (number == 0 || window_hash == NULL)
return FALSE;
pthread_mutex_lock (&window_hash_mutex);
if (xp_lookup_native_window (number, &wid))
ret = RootlessGetXWindow (wid) != NULL;
else
ret = FALSE;
pthread_mutex_unlock (&window_hash_mutex);
return ret;
}
Bool
RootlessUnrealizeWindow (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec = WINREC(pWin);
xp_window_changes wc;
Bool result;
RL_DEBUG_MSG("unrealizewindow start\n");
if (winRec != NULL)
{
RootlessStopDrawing (pWin, FALSE);
wc.stack_mode = XP_UNMAPPED;
wc.sibling = 0;
configure_window (winRec->wid, XP_STACKING, &wc);
winRec->unrealize_time = current_time_in_seconds ();
winRec->is_reorder_pending = FALSE;
RootlessReenableUpdate (pWin);
}
SCREEN_UNWRAP (pScreen, UnrealizeWindow);
result = pScreen->UnrealizeWindow (pWin);
SCREEN_WRAP (pScreen, UnrealizeWindow);
RL_DEBUG_MSG ("unrealizewindow end\n");
return result;
}
void
RootlessReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec = WINREC (pWin);
WindowPtr pTopWin;
if (IsRoot (pWin) || IsRoot (pWin->parent)
|| IsTopLevel (pWin) || winRec == NULL)
{
return;
}
pTopWin = TopLevelParent (pWin);
assert (pTopWin != pWin);
pWin->rootlessUnhittable = FALSE;
DeleteProperty (pWin, xa_native_window_id ());
if (WINREC (pTopWin) != NULL)
{
rootlessDestroyFrame (pWin, winRec);
}
else
{
xp_window_changes wc;
int sx, sy;
if (!pTopWin->realized && pWin->realized)
{
wc.stack_mode = XP_UNMAPPED;
wc.sibling = 0;
RootlessStopDrawing (pWin, FALSE);
configure_window (winRec->wid, XP_STACKING, &wc);
}
WINREC (pWin) = NULL;
WINREC (pTopWin) = winRec;
rootlessInitializeFrame (pTopWin, winRec);
rootlessSetShape (pTopWin);
sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
wc.x = sx + winRec->x;
wc.y = sy + winRec->y;
wc.width = winRec->width;
wc.height = winRec->height;
wc.bit_gravity = XP_GRAVITY_NONE;
RootlessStopDrawing (pWin, FALSE);
configure_window (winRec->wid, XP_BOUNDS, &wc);
rootlessSetNativeProperty (winRec);
if (pTopWin->realized && !pWin->realized)
winRec->is_reorder_pending = TRUE;
}
}
void
RootlessReorderWindow (WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC (pWin);
if (pWin->realized && winRec != NULL
&& !winRec->is_reorder_pending && !windows_hidden)
{
WindowPtr newPrevW;
RootlessWindowRec *newPrev;
xp_window_changes wc;
Atom atom;
PropertyPtr prop;
atom = xa_apple_no_order_in ();
for (prop = wUserProps (pWin); prop != NULL; prop = prop->next)
{
if (prop->propertyName == atom && prop->type == atom)
return;
}
RootlessStopDrawing (pWin, FALSE);
if (IsRoot (pWin))
{
wc.stack_mode = XP_MAPPED_BELOW;
wc.sibling = 0;
}
else
{
newPrevW = pWin->prevSib;
while (newPrevW
&& (WINREC (newPrevW) == NULL || !newPrevW->realized))
{
newPrevW = newPrevW->prevSib;
}
newPrev = newPrevW != NULL ? WINREC (newPrevW) : NULL;
if (newPrev == NULL)
{
wc.stack_mode = XP_MAPPED_ABOVE;
wc.sibling = 0;
}
else
{
if (newPrev->is_reorder_pending)
{
newPrev->is_reorder_pending = FALSE;
RootlessReorderWindow (newPrevW);
}
wc.stack_mode = XP_MAPPED_BELOW;
wc.sibling = newPrev->wid;
}
}
configure_window (winRec->wid, XP_STACKING, &wc);
}
}
void
RootlessRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib)
{
RegionRec saveRoot;
RootlessWindowRec *winRec = WINREC (pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
RL_DEBUG_MSG("restackwindow start\n");
if (winRec != NULL)
RL_DEBUG_MSG("restack top level \n");
HUGE_ROOT(pWin);
SCREEN_UNWRAP(pScreen, RestackWindow);
if (pScreen->RestackWindow != NULL)
pScreen->RestackWindow (pWin, pOldNextSib);
SCREEN_WRAP(pScreen, RestackWindow);
NORMAL_ROOT(pWin);
if (winRec != NULL && pWin->viewable)
RootlessReorderWindow (pWin);
RL_DEBUG_MSG("restackwindow end\n");
}
static pointer gResizeDeathBits = NULL;
static int gResizeDeathCount;
static PixmapPtr gResizeDeathPix[2];
static BoxRec gResizeDeathBounds[2];
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;
REGION_TRANSLATE (pWin->drawable.pScreen, prgnSrc, -dx, -dy);
}
static void
RootlessResizeCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg,
RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RegionRec rgnDst;
int dx, dy;
RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x)\n", pWin);
if (gResizeDeathCount == 0)
return;
RootlessStartDrawing (pWin);
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);
if (gResizeDeathCount == 1)
{
fbCopyRegion (&gResizeDeathPix[0]->drawable,
&pScreen->GetWindowPixmap(pWin)->drawable, 0,
&rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
}
else
{
int i;
RegionRec clip, clipped;
for (i = 0; i < gResizeDeathCount; i++)
{
REGION_INIT (pScreen, &clip, gResizeDeathBounds + 0, 1);
REGION_NULL (pScreen, &clipped);
REGION_INTERSECT (pScreen, &rgnDst, &clip, &clipped);
fbCopyRegion (&gResizeDeathPix[i]->drawable,
&pScreen->GetWindowPixmap(pWin)->drawable, 0,
&clipped, dx, dy, fbCopyWindowProc, 0, 0);
REGION_UNINIT (pScreen, &clipped);
REGION_UNINIT (pScreen, &clip);
}
}
REGION_UNINIT (pScreen, &rgnDst);
fbValidateDrawable (&pWin->drawable);
RL_DEBUG_MSG("resizecopywindowFB end\n");
}
void
RootlessCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec;
WindowPtr top;
RegionRec rgnDst;
int dx, dy;
BoxPtr extents;
unsigned int area;
RL_DEBUG_MSG("copywindowFB start (win 0x%x)\n", pWin);
top = TopLevelParent (pWin);
if (top == NULL)
{
RL_DEBUG_MSG("no parent\n");
return;
}
winRec = WINREC(top);
if (winRec == NULL)
{
RL_DEBUG_MSG("not framed\n");
return;
}
SCREEN_UNWRAP (pScreen, CopyWindow);
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);
extents = REGION_EXTENTS (pScreen, &rgnDst);
area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
if (area > xp_scroll_area_threshold)
{
REGION_TRANSLATE (pScreen, &rgnDst, -winRec->x, -winRec->y);
RootlessStopDrawing (pWin, FALSE);
xp_copy_window (winRec->wid, winRec->wid,
REGION_NUM_RECTS (&rgnDst),
REGION_RECTS (&rgnDst), dx, dy);
}
else
{
RootlessStartDrawing (pWin);
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");
}
enum {
WIDTH_SMALLER = 1,
HEIGHT_SMALLER = 2,
};
static inline unsigned int
resize_code (int oldX, int oldY, int oldW, int oldH,
int newX, int newY, int newW, int newH)
{
unsigned int code = 0;
if (newW < oldW)
code |= WIDTH_SMALLER;
if (newH < oldH)
code |= HEIGHT_SMALLER;
return code;
}
static inline unsigned int
resize_weighting (int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
int newX1, int newY1, int newX2, int newY2, int newBW)
{
if (newBW != oldBW)
return XP_GRAVITY_NONE;
if (newX1 == oldX1 && newY1 == oldY1)
return XP_GRAVITY_NORTH_WEST;
else if (newX1 == oldX1 && newY2 == oldY2)
return XP_GRAVITY_SOUTH_WEST;
else if (newX2 == oldX2 && newY2 == oldY2)
return XP_GRAVITY_SOUTH_EAST;
else if (newX2 == oldX2 && newY1 == oldY1)
return XP_GRAVITY_NORTH_EAST;
else
return XP_GRAVITY_NONE;
}
static void
resize_frame (ScreenPtr pScreen, WindowPtr pWin,
RootlessWindowRec *winRec, int gravity)
{
int sx, sy;
xp_window_changes wc;
sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
wc.x = sx + winRec->x;
wc.y = sy + winRec->y;
wc.width = winRec->width;
wc.height = winRec->height;
wc.bit_gravity = gravity;
configure_window (winRec->wid, XP_BOUNDS, &wc);
}
static Bool
StartFrameResize (WindowPtr pWin, Bool gravity,
int oldX, int oldY, int oldW, int oldH, int oldBW,
int newX, int newY, int newW, int newH, int newBW)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec = WINREC(pWin);
Bool need_window_source = FALSE, resize_after = FALSE;
BoxRec rect, copy_rect;
int oldX2, newX2;
int oldY2, newY2;
unsigned int weight;
oldX2 = oldX + oldW, newX2 = newX + newW;
oldY2 = oldY + oldH, newY2 = newY + newH;
weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
rect.x1 = max(oldX, newX);
rect.y1 = max(oldY, newY);
rect.x2 = min(oldX2, newX2);
rect.y2 = min(oldY2, newY2);
RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n",
oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
RootlessDisableUpdate (pWin);
RootlessRedisplay (pWin);
gResizeDeathCount = 0;
if (gravity && weight == XP_GRAVITY_NORTH_WEST)
{
unsigned int code;
need_window_source = TRUE;
code = resize_code (oldX, oldY, oldW, oldH,
newX, newY, newW, newH);
if (((code ^ (code >> 1)) & 1) == 0)
{
if (code == (WIDTH_SMALLER | HEIGHT_SMALLER))
{
resize_after = TRUE;
}
gResizeDeathCount = 1;
}
else
{
unsigned int copy_rowbytes, Bpp;
RootlessStartDrawing (pWin);
if (code == WIDTH_SMALLER)
{
copy_rect.x1 = rect.x2;
copy_rect.y1 = rect.y1;
copy_rect.x2 = oldX2;
copy_rect.y2 = oldY2;
}
else if (code == HEIGHT_SMALLER)
{
copy_rect.x1 = rect.x1;
copy_rect.y1 = rect.y2;
copy_rect.x2 = oldX2;
copy_rect.y2 = oldY2;
}
else
abort ();
Bpp = winRec->win->drawable.bitsPerPixel / 8;
copy_rowbytes = (((copy_rect.x2 - copy_rect.x1) * Bpp) + 31) & ~31;
gResizeDeathBits = xalloc (copy_rowbytes
* (copy_rect.y2 - copy_rect.y1));
xp_copy_bytes ((copy_rect.x2 - copy_rect.x1) * Bpp,
copy_rect.y2 - copy_rect.y1, ((char *) winRec->data)
+ ((copy_rect.y1 - oldY) * winRec->rowbytes)
+ (copy_rect.x1 - oldX) * Bpp, winRec->rowbytes,
gResizeDeathBits, copy_rowbytes);
gResizeDeathBounds[1] = copy_rect;
gResizeDeathPix[1]
= GetScratchPixmapHeader(pScreen, copy_rect.x2 - copy_rect.x1,
copy_rect.y2 - copy_rect.y1,
winRec->win->drawable.depth,
winRec->win->drawable.bitsPerPixel,
winRec->rowbytes,
(void *) gResizeDeathBits);
TranslatePixmapBase (gResizeDeathPix[1],
-copy_rect.x1, -copy_rect.y1);
gResizeDeathCount = 2;
}
}
else if (gravity)
{
RootlessStartDrawing (pWin);
gResizeDeathBits = xalloc(winRec->rowbytes * winRec->height);
memcpy(gResizeDeathBits, winRec->data,
winRec->rowbytes * winRec->height);
gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
gResizeDeathPix[0]
= GetScratchPixmapHeader(pScreen, winRec->width,
winRec->height,
winRec->win->drawable.depth,
winRec->win->drawable.bitsPerPixel,
winRec->rowbytes,
(void *) gResizeDeathBits);
TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
gResizeDeathCount = 1;
}
RootlessStopDrawing (pWin, FALSE);
winRec->x = newX;
winRec->y = newY;
winRec->width = newW;
winRec->height = newH;
winRec->borderWidth = newBW;
if (!resize_after)
resize_frame (pScreen, pWin, winRec, weight);
RootlessStartDrawing(pWin);
if (need_window_source)
{
gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
gResizeDeathPix[0]
= GetScratchPixmapHeader (pScreen, oldW, oldH,
winRec->win->drawable.depth,
winRec->win->drawable.bitsPerPixel,
winRec->rowbytes, winRec->data);
TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
}
if (gravity)
{
gResizeOldCopyWindowProc = pScreen->CopyWindow;
pScreen->CopyWindow = RootlessResizeCopyWindow;
}
if (gravity && weight == XP_GRAVITY_NONE)
{
PixmapPtr src, dst;
assert (gResizeDeathCount == 1);
src = gResizeDeathPix[0];
dst = pScreen->GetWindowPixmap(pWin);
RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
rect.x1, rect.y1, rect.x2, rect.y2);
if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL)
{
int dx, dy;
dx = newX - oldX;
dy = newY - oldY;
TranslatePixmapBase (dst, -dx, -dy);
fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
&rect, 1, 0, 0, FALSE, FALSE, 0, 0);
TranslatePixmapBase (dst, dx, dy);
}
}
return resize_after;
}
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, Bool resize_now)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
RootlessWindowRec *winRec = WINREC(pWin);
BoxRec box;
int i;
RootlessStopDrawing (pWin, FALSE);
if (resize_now)
{
unsigned int weight;
weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
resize_frame (pScreen, pWin, winRec, weight);
}
box.x1 = 0;
box.y1 = 0;
box.x2 = winRec->width;
box.y2 = winRec->height;
xp_mark_window (winRec->wid, 1, &box, 0, 0);
for (i = 0; i < 2; i++)
{
if (gResizeDeathPix[i] != NULL)
{
FreeScratchPixmapHeader (gResizeDeathPix[i]);
gResizeDeathPix[i] = NULL;
}
}
if (gResizeDeathBits != NULL)
{
xfree (gResizeDeathBits);
gResizeDeathBits = NULL;
}
if (gravity)
pScreen->CopyWindow = gResizeOldCopyWindowProc;
}
void
RootlessMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
{
RootlessWindowRec *winRec = WINREC(pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
CopyWindowProcPtr oldCopyWindowProc = NULL;
int oldX = 0, oldY = 0;
unsigned int oldW = 0, oldH = 0, oldBW = 0;
int newX = 0, newY = 0;
unsigned int newW = 0, newH = 0, newBW = 0;
Bool resize_after = FALSE;
RegionRec saveRoot;
RL_DEBUG_MSG("movewindow start \n");
if (winRec != NULL)
{
if (kind == VTMove)
{
oldX = winRec->x;
oldY = winRec->y;
RootlessRedisplay (pWin);
RootlessStartDrawing (pWin);
}
else
{
RL_DEBUG_MSG("movewindow border resizing ");
oldBW = winRec->borderWidth;
oldX = winRec->x;
oldY = winRec->y;
oldW = winRec->width;
oldH = winRec->height;
newBW = wBorderWidth (pWin);
newX = x;
newY = y;
newW = pWin->drawable.width + 2*newBW;
newH = pWin->drawable.height + 2*newBW;
resize_after = StartFrameResize (pWin, FALSE,
oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
}
HUGE_ROOT (pWin);
SCREEN_UNWRAP (pScreen, MoveWindow);
oldCopyWindowProc = pScreen->CopyWindow;
if (winRec != NULL)
pScreen->CopyWindow = RootlessNoCopyWindow;
pScreen->MoveWindow (pWin, x, y, pSib, kind);
if (winRec != NULL)
pScreen->CopyWindow = oldCopyWindowProc;
NORMAL_ROOT (pWin);
SCREEN_WRAP (pScreen, MoveWindow);
if (winRec != NULL)
{
if (kind == VTMove)
{
xp_window_changes wc;
int sx, sy;
RootlessStopDrawing (pWin, FALSE);
winRec->x = x;
winRec->y = y;
sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
wc.x = sx + winRec->x;
wc.y = sy + winRec->y;
configure_window (winRec->wid, XP_ORIGIN, &wc);
}
else
{
FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW, resize_after);
}
}
RL_DEBUG_MSG("movewindow end\n");
}
void
RootlessResizeWindow (WindowPtr pWin, int x, int y,
unsigned int w, unsigned int h, WindowPtr pSib)
{
RootlessWindowRec *winRec = WINREC(pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
RegionRec saveRoot;
int oldX = 0, oldY = 0;
unsigned int oldW = 0, oldH = 0, oldBW = 0;
int newX = 0, newY = 0;
unsigned int newW = 0, newH = 0, newBW = 0;
Bool resize_after = FALSE;
RL_DEBUG_MSG("resizewindow start (win 0x%x)\n", pWin);
if (winRec != NULL)
{
oldBW = winRec->borderWidth;
oldX = winRec->x;
oldY = winRec->y;
oldW = winRec->width;
oldH = winRec->height;
newBW = oldBW;
newX = x;
newY = y;
newW = w + 2*newBW;
newH = h + 2*newBW;
resize_after = StartFrameResize (pWin, TRUE,
oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW);
}
HUGE_ROOT (pWin);
SCREEN_UNWRAP (pScreen, ResizeWindow);
if (!IsRoot (pWin))
{
pScreen->ResizeWindow (pWin, x, y, w, h, pSib);
}
else
{
BoxRec box;
pWin->drawable.x = x;
pWin->drawable.y = y;
pWin->drawable.width = w;
pWin->drawable.height = h;
box.x1 = x; box.y1 = y;
box.x2 = x + w; box.y2 = y + h;
REGION_UNINIT (pScreen, &pWin->winSize);
REGION_INIT (pScreen, &pWin->winSize, &box, 1);
REGION_COPY (pScreen, &pWin->borderSize, &pWin->winSize);
REGION_COPY (pScreen, &pWin->clipList, &pWin->winSize);
REGION_COPY (pScreen, &pWin->borderClip, &pWin->winSize);
miSendExposures (pWin, &pWin->borderClip,
pWin->drawable.x, pWin->drawable.y);
}
SCREEN_WRAP (pScreen, ResizeWindow);
NORMAL_ROOT (pWin);
if (winRec != NULL)
{
FinishFrameResize (pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW, resize_after);
}
RL_DEBUG_MSG("resizewindow end\n");
}
void
RootlessRepositionWindow (WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC (pWin);
ScreenPtr pScreen = pWin->drawable.pScreen;
xp_window_changes wc;
int sx, sy;
if (IsRoot (pWin))
set_screen_origin (pWin);
if (winRec == NULL)
return;
RootlessStopDrawing (pWin, FALSE);
sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
wc.x = sx + winRec->x;
wc.y = sy + winRec->y;
if (!rootlessHasRoot (pScreen))
wc.window_level = normal_window_levels[winRec->level];
else
wc.window_level = rooted_window_levels[winRec->level];
configure_window (winRec->wid, XP_ORIGIN | XP_WINDOW_LEVEL, &wc);
RootlessReorderWindow (pWin);
}
void
RootlessFlushWindowColormap (WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC (pWin);
xp_window_changes wc;
if (winRec == NULL)
return;
RootlessStopDrawing (pWin, FALSE);
wc.colormap = rootlessColormapCallback;
wc.colormap_data = pWin->drawable.pScreen;
configure_window (winRec->wid, XP_COLORMAP, &wc);
}
static void
SetPixmapOfAncestors (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
WindowPtr topWin = TopLevelParent (pWin);
RootlessWindowRec *topWinRec = WINREC (topWin);
XID pixel;
while (pWin->backgroundState == ParentRelative)
{
if (pWin == topWin)
{
pixel = 0;
ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
break;
}
pWin = pWin->parent;
pScreen->SetWindowPixmap (pWin, topWinRec->pixmap);
}
}
void
RootlessPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
SCREEN_UNWRAP (pScreen, PaintWindowBackground);
RL_DEBUG_MSG("paintwindowbackground start (win 0x%x, framed %i)\n",
pWin, IsFramedWindow(pWin));
if (IsFramedWindow (pWin))
{
rootlessNoDRIDrawing++;
RootlessStartDrawing (pWin);
RootlessDamageRegion (pWin, pRegion);
if (pWin->backgroundState == ParentRelative)
SetPixmapOfAncestors (pWin);
pScreen->PaintWindowBackground (pWin, pRegion, what);
rootlessNoDRIDrawing--;
}
SCREEN_WRAP (pScreen, PaintWindowBackground);
RL_DEBUG_MSG("paintwindowbackground end\n");
}
void
RootlessPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what)
{
SCREEN_UNWRAP (pWin->drawable.pScreen, PaintWindowBorder);
RL_DEBUG_MSG("paintwindowborder start (win 0x%x)\n", pWin);
if (IsFramedWindow (pWin))
{
RootlessStartDrawing (pWin);
RootlessDamageRegion (pWin, pRegion);
if (!pWin->borderIsPixel && pWin->backgroundState == ParentRelative)
SetPixmapOfAncestors (pWin);
}
pWin->drawable.pScreen->PaintWindowBorder (pWin, pRegion, what);
SCREEN_WRAP (pWin->drawable.pScreen, PaintWindowBorder);
RL_DEBUG_MSG("paintwindowborder end\n");
}
void
RootlessChangeBorderWidth (WindowPtr pWin, unsigned int width)
{
RegionRec saveRoot;
Bool resize_after = FALSE;
RL_DEBUG_MSG("change border width\n");
if ((int) width != wBorderWidth (pWin))
{
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 != NULL)
{
oldBW = winRec->borderWidth;
oldX = winRec->x;
oldY = winRec->y;
oldW = winRec->width;
oldH = winRec->height;
newBW = width;
newX = pWin->drawable.x - newBW;
newY = pWin->drawable.y - newBW;
newW = pWin->drawable.width + 2*newBW;
newH = pWin->drawable.height + 2*newBW;
resize_after = 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 != NULL)
{
FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
newX, newY, newW, newH, newBW, resize_after);
}
}
RL_DEBUG_MSG("change border width end\n");
}
static void
RootlessFillRegionTiled(
DrawablePtr pDrawable,
RegionPtr pRegion,
PixmapPtr pTile)
{
FbBits *dst;
FbStride dstStride;
int dstBpp;
int dstXoff, dstYoff;
FbBits *tile;
FbStride tileStride;
int tileBpp;
int tileXoff, tileYoff;
int tileWidth, tileHeight;
int n = REGION_NUM_RECTS(pRegion);
BoxPtr pbox = REGION_RECTS(pRegion);
int xRot = pDrawable->x;
int yRot = pDrawable->y;
FbBits planeMask;
#ifdef PANORAMIX
if(!noPanoramiXExtension)
{
int index = pDrawable->pScreen->myNum;
if(&WindowTable[index]->drawable == pDrawable)
{
xRot -= panoramiXdataPtr[index].x;
yRot -= panoramiXdataPtr[index].y;
}
}
#endif
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp,
tileXoff, tileYoff);
tileWidth = pTile->drawable.width;
tileHeight = pTile->drawable.height;
xRot += dstXoff;
yRot += dstYoff;
planeMask = FB_ALLONES & ~RootlessAlphaMask(dstBpp);
while (n--)
{
fbTile (dst + (pbox->y1 + dstYoff) * dstStride,
dstStride,
(pbox->x1 + dstXoff) * dstBpp,
(pbox->x2 - pbox->x1) * dstBpp,
pbox->y2 - pbox->y1,
tile,
tileStride,
tileWidth * dstBpp,
tileHeight,
GXcopy,
planeMask,
dstBpp,
xRot * dstBpp,
yRot - pbox->y1);
pbox++;
}
}
void
RootlessPaintWindow(
WindowPtr pWin,
RegionPtr pRegion,
int what)
{
switch (what) {
case PW_BACKGROUND:
switch (pWin->backgroundState) {
case None:
break;
case ParentRelative:
do {
pWin = pWin->parent;
} while (pWin->backgroundState == ParentRelative);
(*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
what);
break;
case BackgroundPixmap:
RootlessFillRegionTiled (&pWin->drawable,
pRegion,
pWin->background.pixmap);
break;
case BackgroundPixel:
{
Pixel pixel = pWin->background.pixel |
RootlessAlphaMask(pWin->drawable.bitsPerPixel);
fbFillRegionSolid (&pWin->drawable, pRegion, 0,
fbReplicatePixel (pixel,
pWin->drawable.bitsPerPixel));
break;
}
}
break;
case PW_BORDER:
if (pWin->borderIsPixel)
{
Pixel pixel = pWin->border.pixel |
RootlessAlphaMask(pWin->drawable.bitsPerPixel);
fbFillRegionSolid (&pWin->drawable, pRegion, 0,
fbReplicatePixel (pixel,
pWin->drawable.bitsPerPixel));
}
else
{
WindowPtr pBgWin;
for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative;
pBgWin = pBgWin->parent);
RootlessFillRegionTiled (&pBgWin->drawable,
pRegion,
pWin->border.pixmap);
}
break;
}
fbValidateDrawable (&pWin->drawable);
}