/*
* Rootless implementation for Mac OS X Aqua environment
*/
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz_1.3/rootlessAquaImp.m,v 1.1 2002/03/28 02:21:20 torrey Exp $ */
#include "rootlessAquaImp.h"
#include "XWindow.h"
#include "fakeBoxRec.h"
#include "quartzCommon.h"
#include "pseudoramiX.h"
extern void ErrorF(const char *, ...);
typedef struct {
XWindow *window;
} AquaWindowRec;
#define WINREC(rw) ((AquaWindowRec *)rw)
// Multihead note: When rootless mode uses PseudoramiX, the
// X server only sees one screen; only PseudoramiX itself knows
// about all of the screens.
int AquaDisplayCount()
{
aquaNumScreens = [[NSScreen screens] count];
if (noPseudoramiXExtension) {
return aquaNumScreens;
} else {
return 1; // only PseudoramiX knows about the rest
}
}
void AquaScreenInit(int index, int *x, int *y, int *width, int *height,
int *rowBytes, unsigned long *bps, unsigned long *spp,
int *bpp)
{
*bps = 8;
*spp = 3;
*bpp = 32;
if (noPseudoramiXExtension) {
NSScreen *screen = [[NSScreen screens] objectAtIndex:index];
NSRect frame = [screen frame];
// set x, y so (0,0) is top left of main screen
*x = NSMinX(frame);
*y = NSHeight([[NSScreen mainScreen] frame]) - NSHeight(frame) -
NSMinY(frame);
*width = NSWidth(frame);
*height = NSHeight(frame);
*rowBytes = (*width) * (*bpp) / 8;
// Shift the usable part of main screen down to avoid the menu bar.
if (NSEqualRects(frame, [[NSScreen mainScreen] frame])) {
*y += aquaMenuBarHeight;
*height -= aquaMenuBarHeight;
}
} else {
int i;
NSRect unionRect = NSMakeRect(0, 0, 0, 0);
NSArray *screens = [NSScreen screens];
// Get the union of all screens (minus the menu bar on main screen)
for (i = 0; i < [screens count]; i++) {
NSScreen *screen = [screens objectAtIndex:i];
NSRect frame = [screen frame];
frame.origin.y = [[NSScreen mainScreen] frame].size.height -
frame.size.height - frame.origin.y;
if (NSEqualRects([screen frame], [[NSScreen mainScreen] frame])) {
frame.origin.y += aquaMenuBarHeight;
frame.size.height -= aquaMenuBarHeight;
}
unionRect = NSUnionRect(unionRect, frame);
}
// Use unionRect as the screen size for the X server.
*x = unionRect.origin.x;
*y = unionRect.origin.y;
*width = unionRect.size.width;
*height = unionRect.size.height;
*rowBytes = (*width) * (*bpp) / 8;
// Tell PseudoramiX about the real screens.
// InitOutput() will move the big screen to (0,0),
// so compensate for that here.
for (i = 0; i < [screens count]; i++) {
NSScreen *screen = [screens objectAtIndex:i];
NSRect frame = [screen frame];
int j;
// Skip this screen if it's a mirrored copy of an earlier screen.
for (j = 0; j < i; j++) {
if (NSEqualRects(frame, [[screens objectAtIndex:j] frame])) {
ErrorF("PseudoramiX screen i, j);
break;
}
}
if (j < i) continue; // this screen is a mirrored copy
frame.origin.y = [[NSScreen mainScreen] frame].size.height -
frame.size.height - frame.origin.y;
if (NSEqualRects([screen frame], [[NSScreen mainScreen] frame])) {
frame.origin.y += aquaMenuBarHeight;
frame.size.height -= aquaMenuBarHeight;
}
ErrorF("PseudoramiX screen (int)frame.size.width, (int)frame.size.height,
(int)frame.origin.x, (int)frame.origin.y);
frame.origin.x -= unionRect.origin.x;
frame.origin.y -= unionRect.origin.y;
ErrorF("PseudoramiX screen i, (int)frame.origin.x, (int)frame.origin.y);
PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
frame.size.width, frame.size.height);
}
}
}
void *AquaNewWindow(void *upperw, int x, int y, int w, int h, int isRoot)
{
AquaWindowRec *winRec = (AquaWindowRec *)malloc(sizeof(AquaWindowRec));
NSRect frame = NSMakeRect(x, NSHeight([[NSScreen mainScreen] frame]) -
y - h, w, h);
winRec->window = [[XWindow alloc] initWithContentRect:frame isRoot:isRoot];
if (upperw) {
AquaWindowRec *upperRec = WINREC(upperw);
int uppernum = [upperRec->window windowNumber];
[winRec->window orderWindow:NSWindowBelow relativeTo:uppernum];
} else {
[winRec->window orderFront:nil];
}
// fixme hide root for now
if (isRoot) [winRec->window orderOut:nil];
return winRec;
}
void AquaDestroyWindow(void *rw)
{
AquaWindowRec *winRec = WINREC(rw);
[winRec->window release];
}
void AquaMoveWindow(void *rw, int x, int y)
{
AquaWindowRec *winRec = WINREC(rw);
NSPoint topLeft = NSMakePoint(x, NSHeight([[NSScreen mainScreen] frame]) -
y);
[winRec->window setFrameTopLeftPoint:topLeft];
}
void AquaStartResizeWindow(void *rw, int x, int y, int w, int h)
{
AquaWindowRec *winRec = WINREC(rw);
NSRect frame = NSMakeRect(x, NSHeight([[NSScreen mainScreen] frame]) -
y - h, w, h);
[winRec->window setFrame:frame display:NO];
}
void AquaFinishResizeWindow(void *rw, int x, int y, int w, int h)
{
// refresh everything? fixme yes for testing
fakeBoxRec box = {0, 0, w, h};
AquaWindowRec *winRec = WINREC(rw);
[winRec->window refreshRects:&box count:1];
}
void AquaUpdateRects(void *rw, fakeBoxRec *rects, int count)
{
AquaWindowRec *winRec = WINREC(rw);
[winRec->window refreshRects:rects count:count];
}
// fixme is this upperw or lowerw?
void AquaRestackWindow(void *rw, void *upperw)
{
AquaWindowRec *winRec = WINREC(rw);
if (upperw) {
AquaWindowRec *upperRec = WINREC(upperw);
int uppernum = [upperRec->window windowNumber];
[winRec->window orderWindow:NSWindowBelow relativeTo:uppernum];
} else {
[winRec->window orderFront:nil];
}
// [winRec->window setAcceptsMouseMovedEvents:YES];
// fixme prefer to orderFront whenever possible - pass upperw, not lowerw
}
// rects are the areas not part of the new shape
void AquaReshapeWindow(void *rw, fakeBoxRec *rects, int count)
{
AquaWindowRec *winRec = WINREC(rw);
// make transparent if window is now shaped
// transparent windows never go back to opaque
if (count > 0) {
[winRec->window setOpaque:NO];
}
[[winRec->window contentView] reshapeRects:rects count:count];
if (! [winRec->window isOpaque]) {
// force update of window shadow
[winRec->window setHasShadow:NO];
[winRec->window setHasShadow:YES];
}
}
void AquaGetPixmap(void *rw, char **bits,
int *rowBytes, int *depth, int *bpp)
{
AquaWindowRec *winRec = WINREC(rw);
[winRec->window getBits:bits rowBytes:rowBytes depth:depth
bitsPerPixel:bpp];
}