#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <unistd.h>
#include "xpr.h"
#include "rootlessCommon.h"
#include "Xplugin.h"
#include "x-hash.h"
#include "x-list.h"
#include "applewmExt.h"
#include "propertyst.h"
#include "dix.h"
#include <X11/Xatom.h>
#include "windowstr.h"
#include <pthread.h>
#define DEFINE_ATOM_HELPER(func,atom_name) \
static Atom func (void) { \
static 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_window_id, "_NATIVE_WINDOW_ID")
static x_hash_table *window_hash;
static pthread_mutex_t window_hash_mutex;
static Bool no_configure_window;
static inline xp_error
xprConfigureWindow(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 void
xprSetNativeProperty(RootlessWindowPtr pFrame)
{
xp_error err;
unsigned int native_id;
long data;
err = xp_get_native_window((xp_window_id) pFrame->wid, &native_id);
if (err == Success)
{
data = native_id;
ChangeWindowProperty(pFrame->win, xa_native_window_id(),
XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
}
}
Bool
xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
int newX, int newY, RegionPtr pShape)
{
WindowPtr pWin = pFrame->win;
xp_window_changes wc;
unsigned int mask = 0;
xp_error err;
wc.x = newX;
wc.y = newY;
wc.width = pFrame->width;
wc.height = pFrame->height;
wc.bit_gravity = XP_GRAVITY_NONE;
mask |= XP_BOUNDS;
if (pWin->drawable.depth == 8)
{
wc.depth = XP_DEPTH_INDEX8;
#if 0
wc.colormap = xprColormapCallback;
wc.colormap_data = pScreen;
mask |= XP_COLORMAP;
#endif
}
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;
}
err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
if (err != Success)
{
return FALSE;
}
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, pFrame->wid, pFrame);
pthread_mutex_unlock(&window_hash_mutex);
xprSetNativeProperty(pFrame);
return TRUE;
}
void
xprDestroyFrame(RootlessFrameID wid)
{
pthread_mutex_lock(&window_hash_mutex);
x_hash_table_remove(window_hash, wid);
pthread_mutex_unlock(&window_hash_mutex);
xp_destroy_window((xp_window_id) wid);
}
void
xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
{
xp_window_changes wc;
wc.x = newX;
wc.y = newY;
xprConfigureWindow((xp_window_id) wid, XP_ORIGIN, &wc);
}
void
xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
int newX, int newY, unsigned int newW, unsigned int newH,
unsigned int gravity)
{
xp_window_changes wc;
wc.x = newX;
wc.y = newY;
wc.width = newW;
wc.height = newH;
wc.bit_gravity = gravity;
xprConfigureWindow((xp_window_id) wid, XP_BOUNDS, &wc);
}
void
xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
{
xp_window_changes wc;
if (nextWid == NULL)
{
wc.stack_mode = XP_MAPPED_ABOVE;
wc.sibling = 0;
}
else
{
wc.stack_mode = XP_MAPPED_BELOW;
wc.sibling = (xp_window_id) nextWid;
}
xprConfigureWindow((xp_window_id) wid, XP_STACKING, &wc);
}
void
xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
{
xp_window_changes wc;
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;
xprConfigureWindow((xp_window_id) wid, XP_SHAPE, &wc);
}
void
xprUnmapFrame(RootlessFrameID wid)
{
xp_window_changes wc;
wc.stack_mode = XP_UNMAPPED;
wc.sibling = 0;
xprConfigureWindow((xp_window_id) wid, XP_STACKING, &wc);
}
void
xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
{
void *data[2];
unsigned int rowbytes[2];
xp_error err;
err = xp_lock_window((xp_window_id) wid, NULL, NULL, data, rowbytes, NULL);
if (err != Success)
FatalError("Could not lock window %i for drawing.", (int) wid);
*pixelData = data[0];
*bytesPerRow = rowbytes[0];
}
void
xprStopDrawing(RootlessFrameID wid, Bool flush)
{
xp_unlock_window((xp_window_id) wid, flush);
}
void
xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
{
xp_flush_window((xp_window_id) wid);
}
void
xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
int shift_x, int shift_y)
{
xp_mark_window((xp_window_id) wid, nrects, rects, shift_x, shift_y);
}
void
xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
{
DeleteProperty(oldWin, xa_native_window_id());
xprSetNativeProperty(pFrame);
}
Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
{
WindowPtr pWin = pFrame->win;
return AppleWMDoReorderWindow(pWin);
}
void
xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
int dx, int dy)
{
xp_copy_window((xp_window_id) wid, (xp_window_id) wid,
dstNrects, dstRects, dx, dy);
}
static RootlessFrameProcsRec xprRootlessProcs = {
xprCreateFrame,
xprDestroyFrame,
xprMoveFrame,
xprResizeFrame,
xprRestackFrame,
xprReshapeFrame,
xprUnmapFrame,
xprStartDrawing,
xprStopDrawing,
xprUpdateRegion,
xprDamageRects,
xprSwitchWindow,
xprDoReorderWindow,
xp_copy_bytes,
xp_fill_bytes,
xp_composite_pixels,
xprCopyWindow
};
Bool
xprInit(ScreenPtr pScreen)
{
RootlessInit(pScreen, &xprRootlessProcs);
if(!access("/tmp/disable_fb.txt", F_OK)) {
fprintf(stderr,"setting rootless thresholds to zero to disable fb usage\n");
rootless_CopyBytes_threshold = 0;
rootless_FillBytes_threshold = 0;
rootless_CompositePixels_threshold = 0;
rootless_CopyWindow_threshold = 0;
} else {
rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
rootless_FillBytes_threshold = xp_fill_bytes_threshold;
rootless_CompositePixels_threshold = xp_composite_area_threshold;
rootless_CopyWindow_threshold = xp_scroll_area_threshold;
}
no_configure_window = FALSE;
return TRUE;
}
WindowPtr
xprGetXWindow(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;
}
WindowPtr
xprGetXWindowFromAppKit(int windowNumber)
{
RootlessWindowRec *winRec;
Bool ret;
xp_window_id wid;
if (window_hash == NULL)
return FALSE;
pthread_mutex_lock(&window_hash_mutex);
if (xp_lookup_native_window(windowNumber, &wid))
ret = xprGetXWindow(wid) != NULL;
else
ret = FALSE;
pthread_mutex_unlock(&window_hash_mutex);
if (!ret) return NULL;
winRec = x_hash_table_lookup(window_hash, (void *) wid, NULL);
return winRec != NULL ? winRec->win : NULL;
}
Bool
xprIsX11Window(void *nsWindow, int windowNumber)
{
Bool ret;
xp_window_id wid;
if (window_hash == NULL)
return FALSE;
pthread_mutex_lock(&window_hash_mutex);
if (xp_lookup_native_window(windowNumber, &wid))
ret = xprGetXWindow(wid) != NULL;
else
ret = FALSE;
pthread_mutex_unlock(&window_hash_mutex);
return ret;
}
void
xprHideWindows(Bool hide)
{
int screen;
WindowPtr pRoot, pWin;
for (screen = 0; screen < screenInfo.numScreens; screen++) {
pRoot = WindowTable[screenInfo.screens[screen]->myNum];
RootlessFrameID prevWid = NULL;
for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
RootlessWindowRec *winRec = WINREC(pWin);
if (winRec != NULL) {
if (hide) {
xprUnmapFrame(winRec->wid);
} else {
BoxRec box;
xprRestackFrame(winRec->wid, prevWid);
prevWid = winRec->wid;
box.x1 = 0;
box.y1 = 0;
box.x2 = winRec->width;
box.y2 = winRec->height;
xprDamageRects(winRec->wid, 1, &box, 0, 0);
RootlessQueueRedisplay(screenInfo.screens[screen]);
}
}
}
}
}