#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "quartzCommon.h"
#include "quartz.h"
#include "xpr.h"
#include "pseudoramiX.h"
#include "darwin.h"
#include "rootless.h"
#include "safeAlpha/safeAlpha.h"
#include "dri.h"
#include "globals.h"
#include "Xplugin.h"
#include "applewmExt.h"
WindowPtr xprGetXWindow(xp_window_id wid);
#ifdef DAMAGE
# include "damage.h"
#endif
#define XP_NO_DEFERRED_UPDATES 8
static const char *xprOpenGLBundle = "glxCGL.bundle";
static void
eventHandler(unsigned int type, const void *arg,
unsigned int arg_size, void *data)
{
switch (type) {
case XP_EVENT_DISPLAY_CHANGED:
DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n");
QuartzMessageServerThread(kXDarwinDisplayChanged, 0);
break;
case XP_EVENT_WINDOW_STATE_CHANGED:
DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED\n");
if (arg_size >= sizeof(xp_window_state_event)) {
const xp_window_state_event *ws_arg = arg;
QuartzMessageServerThread(kXDarwinWindowState, 2,
ws_arg->id, ws_arg->state);
}
break;
case XP_EVENT_WINDOW_MOVED:
DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n");
if (arg_size == sizeof(xp_window_id)) {
xp_window_id id = * (xp_window_id *) arg;
WindowPtr pWin = xprGetXWindow(id);
QuartzMessageServerThread(kXDarwinWindowMoved, 1, pWin);
}
break;
case XP_EVENT_SURFACE_DESTROYED:
DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n");
case XP_EVENT_SURFACE_CHANGED:
DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n");
if (arg_size == sizeof(xp_surface_id)) {
int kind;
if (type == XP_EVENT_SURFACE_DESTROYED)
kind = AppleDRISurfaceNotifyDestroyed;
else
kind = AppleDRISurfaceNotifyChanged;
DRISurfaceNotify(*(xp_surface_id *) arg, kind);
}
break;
default:
ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n",
type);
}
}
static CGDirectDisplayID
displayAtIndex(int index)
{
CGError err;
CGDisplayCount cnt;
CGDirectDisplayID dpy[index+1];
err = CGGetActiveDisplayList(index + 1, dpy, &cnt);
if (err == kCGErrorSuccess && cnt == index + 1)
return dpy[index];
else
return kCGNullDirectDisplay;
}
static CGRect
displayScreenBounds(CGDirectDisplayID id)
{
CGRect frame;
frame = CGDisplayBounds(id);
if (frame.origin.x == 0 && frame.origin.y == 0)
{
frame.origin.y += aquaMenuBarHeight;
frame.size.height -= aquaMenuBarHeight;
}
return frame;
}
static void
xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height)
{
CGDisplayCount i, displayCount;
CGDirectDisplayID *displayList = NULL;
CGRect unionRect = CGRectNull, frame;
CGGetActiveDisplayList(0, NULL, &displayCount);
displayList = xalloc(displayCount * sizeof(CGDirectDisplayID));
CGGetActiveDisplayList(displayCount, displayList, &displayCount);
for (i = 0; i < displayCount; i++)
{
CGDirectDisplayID dpy = displayList[i];
frame = displayScreenBounds(dpy);
unionRect = CGRectUnion(unionRect, frame);
}
*x = unionRect.origin.x;
*y = unionRect.origin.y;
*width = unionRect.size.width;
*height = unionRect.size.height;
for (i = 0; i < displayCount; i++)
{
CGDirectDisplayID dpy = displayList[i];
frame = displayScreenBounds(dpy);
frame.origin.x -= unionRect.origin.x;
frame.origin.y -= unionRect.origin.y;
PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
frame.size.width, frame.size.height);
}
xfree(displayList);
}
static void
xprDisplayInit(void)
{
CGDisplayCount displayCount;
CGGetActiveDisplayList(0, NULL, &displayCount);
if (noPseudoramiXExtension)
darwinScreensFound = displayCount;
else
darwinScreensFound = 1;
if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success)
FatalError("Could not initialize the Xplugin library.");
xp_select_events(XP_EVENT_DISPLAY_CHANGED
| XP_EVENT_WINDOW_STATE_CHANGED
| XP_EVENT_WINDOW_MOVED
| XP_EVENT_SURFACE_CHANGED
| XP_EVENT_SURFACE_DESTROYED,
eventHandler, NULL);
AppleDRIExtensionInit();
xprAppleWMInit();
}
static Bool
xprAddScreen(int index, ScreenPtr pScreen)
{
DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
dfb->colorType = TrueColor;
dfb->bitsPerComponent = 8;
dfb->bitsPerPixel = 32;
dfb->colorBitsPerPixel = 24;
if (darwinDesiredDepth == -1)
{
dfb->bitsPerComponent = CGDisplayBitsPerSample(kCGDirectMainDisplay);
dfb->bitsPerPixel = CGDisplayBitsPerPixel(kCGDirectMainDisplay);
dfb->colorBitsPerPixel =
CGDisplaySamplesPerPixel(kCGDirectMainDisplay) *
dfb->bitsPerComponent;
}
else if (darwinDesiredDepth == 15)
{
dfb->bitsPerComponent = 5;
dfb->bitsPerPixel = 16;
dfb->colorBitsPerPixel = 15;
}
else if (darwinDesiredDepth == 8)
{
dfb->colorType = PseudoColor;
dfb->bitsPerComponent = 8;
dfb->bitsPerPixel = 8;
dfb->colorBitsPerPixel = 8;
}
if (noPseudoramiXExtension)
{
CGDirectDisplayID dpy;
CGRect frame;
dpy = displayAtIndex(index);
frame = displayScreenBounds(dpy);
dfb->x = frame.origin.x;
dfb->y = frame.origin.y;
dfb->width = frame.size.width;
dfb->height = frame.size.height;
}
else
{
xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height);
}
dfb->pitch = 0;
dfb->framebuffer = NULL;
DRIScreenInit(pScreen);
return TRUE;
}
static Bool
xprSetupScreen(int index, ScreenPtr pScreen)
{
pScreen->PaintWindowBackground = SafeAlphaPaintWindow;
pScreen->PaintWindowBorder = SafeAlphaPaintWindow;
#ifdef RENDER
{
PictureScreenPtr ps = GetPictureScreen(pScreen);
ps->Composite = SafeAlphaComposite;
}
#endif
RootlessAccelInit(pScreen);
#ifdef DAMAGE
if (!DamageSetup(pScreen))
return FALSE;
#endif
if (!xprInit(pScreen))
return FALSE;
return DRIFinishScreenInit(pScreen);
}
static void
xprUpdateScreen(ScreenPtr pScreen)
{
rootlessGlobalOffsetX = darwinMainScreenX;
rootlessGlobalOffsetY = darwinMainScreenY;
AppleWMSetScreenOrigin(WindowTable[pScreen->myNum]);
RootlessRepositionWindows(pScreen);
RootlessUpdateScreenPixmap(pScreen);
}
static void
xprInitInput(int argc, char **argv)
{
int i;
rootlessGlobalOffsetX = darwinMainScreenX;
rootlessGlobalOffsetY = darwinMainScreenY;
for (i = 0; i < screenInfo.numScreens; i++)
AppleWMSetScreenOrigin(WindowTable[i]);
}
static QuartzModeProcsRec xprModeProcs = {
xprDisplayInit,
xprAddScreen,
xprSetupScreen,
xprInitInput,
QuartzInitCursor,
NULL, QuartzSuspendXCursor,
QuartzResumeXCursor,
NULL, NULL,
NULL, xprAddPseudoramiXScreens,
xprUpdateScreen,
xprIsX11Window,
xprHideWindows,
RootlessFrameForWindow,
TopLevelParent,
DRICreateSurface,
DRIDestroySurface
};
Bool
QuartzModeBundleInit(void)
{
quartzProcs = &xprModeProcs;
quartzOpenGLBundle = xprOpenGLBundle;
return TRUE;
}