Initial revision

This commit is contained in:
Kaleb Keithley 2003-11-25 19:29:01 +00:00
commit 90f1536dd3
91 changed files with 27196 additions and 0 deletions

View file

@ -0,0 +1,42 @@
/*
* NSView subclass for Mac OS X rootless X server
*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/cr/XView.h,v 1.1 2003/06/07 05:49:07 torrey Exp $ */
#import <Cocoa/Cocoa.h>
@interface XView : NSQuickDrawView
- (BOOL)isFlipped;
- (BOOL)isOpaque;
- (BOOL)acceptsFirstResponder;
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;
- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent;
- (void)mouseDown:(NSEvent *)anEvent;
@end

View file

@ -0,0 +1,74 @@
/*
* NSView subclass for Mac OS X rootless X server
*
* Each rootless window contains an instance of this class.
* This class handles events while drawing is handled by Carbon
* code in the rootless Aqua implementation.
*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/cr/XView.m,v 1.2 2003/10/16 23:50:16 torrey Exp $ */
#import "XView.h"
@implementation XView
- (BOOL)isFlipped
{
return NO;
}
- (BOOL)isOpaque
{
return YES;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
return YES;
}
- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent
{
return YES;
}
- (void)mouseDown:(NSEvent *)anEvent
{
// Only X is allowed to restack windows.
[NSApp preventWindowOrdering];
if (! [NSApp isActive]) {
[NSApp activateIgnoringOtherApps:YES];
}
[[self nextResponder] mouseDown:anEvent];
}
@end

62
hw/darwin/quartz/cr/cr.h Normal file
View file

@ -0,0 +1,62 @@
/*
* Internal definitions of the Cocoa rootless implementation
*/
/*
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/cr/cr.h,v 1.3 2003/11/03 05:36:31 tsi Exp $ */
#ifndef _CR_H
#define _CR_H
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#import "XView.h"
#else
typedef struct OpaqueNSWindow NSWindow;
typedef struct OpaqueXView XView;
#endif
#undef BOOL
#define BOOL xBOOL
#include "screenint.h"
#include "window.h"
#undef BOOL
// Predefined style for the window which is about to be framed
extern WindowPtr nextWindowToFrame;
extern unsigned int nextWindowStyle;
typedef struct {
NSWindow *window;
XView *view;
GrafPtr port;
CGContextRef context;
} CRWindowRec, *CRWindowPtr;
Bool CRInit(ScreenPtr pScreen);
void CRAppleWMInit(void);
#endif /* _CR_H */

View file

@ -0,0 +1,157 @@
/*
* Cocoa rootless implementation functions for AppleWM extension
*/
/*
* Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/cr/crAppleWM.m,v 1.1 2003/09/16 00:36:14 torrey Exp $ */
#include "quartzCommon.h"
#include "cr.h"
#undef BOOL
#define BOOL xBOOL
#include "rootless.h"
#include "X.h"
#define _APPLEWM_SERVER_
#include "applewm.h"
#include "applewmExt.h"
#undef BOOL
#define StdDocumentStyleMask (NSTitledWindowMask | \
NSClosableWindowMask | \
NSMiniaturizableWindowMask | \
NSResizableWindowMask)
static int
CRDisableUpdate(void)
{
return Success;
}
static int
CREnableUpdate(void)
{
return Success;
}
static int CRSetWindowLevel(
WindowPtr pWin,
int level)
{
CRWindowPtr crWinPtr;
crWinPtr = (CRWindowPtr) RootlessFrameForWindow(pWin, TRUE);
if (crWinPtr == 0)
return BadWindow;
RootlessStopDrawing(pWin, FALSE);
[crWinPtr->window setLevel:level];
return Success;
}
static int CRFrameGetRect(
int type,
int class,
const BoxRec *outer,
const BoxRec *inner,
BoxRec *ret)
{
return Success;
}
static int CRFrameHitTest(
int class,
int x,
int y,
const BoxRec *outer,
const BoxRec *inner,
int *ret)
{
return 0;
}
static int CRFrameDraw(
WindowPtr pWin,
int class,
unsigned int attr,
const BoxRec *outer,
const BoxRec *inner,
unsigned int title_len,
const unsigned char *title_bytes)
{
CRWindowPtr crWinPtr;
NSWindow *window;
Bool hasResizeIndicator;
/* We assume the window has not yet been framed so
RootlessFrameForWindow() will cause it to be. Record the window
style so that the appropriate one will be used when it is framed.
If the window is already framed, we can't change the window
style and the following will have no effect. */
nextWindowToFrame = pWin;
if (class == AppleWMFrameClassDocument)
nextWindowStyle = StdDocumentStyleMask;
else
nextWindowStyle = NSBorderlessWindowMask;
crWinPtr = (CRWindowPtr) RootlessFrameForWindow(pWin, TRUE);
if (crWinPtr == 0)
return BadWindow;
window = crWinPtr->window;
[window setTitle:[NSString stringWithCString:title_bytes
length:title_len]];
hasResizeIndicator = (attr & AppleWMFrameGrowBox) ? YES : NO;
[window setShowsResizeIndicator:hasResizeIndicator];
return Success;
}
static AppleWMProcsRec crAppleWMProcs = {
CRDisableUpdate,
CREnableUpdate,
CRSetWindowLevel,
CRFrameGetRect,
CRFrameHitTest,
CRFrameDraw
};
void CRAppleWMInit(void)
{
AppleWMExtensionInit(&crAppleWMProcs);
}

View file

@ -0,0 +1,403 @@
/*
* Cocoa rootless implementation frame functions
*/
/*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
* Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/cr/crFrame.m,v 1.5 2003/11/13 20:26:31 torrey Exp $ */
#include "quartzCommon.h"
#include "cr.h"
#undef BOOL
#define BOOL xBOOL
#include "rootless.h"
#undef BOOL
WindowPtr nextWindowToFrame = NULL;
unsigned int nextWindowStyle = 0;
static void CRReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
/*
* CRCreateFrame
* Create a new physical window.
* Rootless windows must not autodisplay! Autodisplay can cause a deadlock.
* Event thread - autodisplay: locks view hierarchy, then window
* X Server thread - window resize: locks window, then view hierarchy
* Deadlock occurs if each thread gets one lock and waits for the other.
*/
static Bool
CRCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
int newX, int newY, RegionPtr pShape)
{
CRWindowPtr crWinPtr;
NSRect bounds;
NSWindow *theWindow;
XView *theView;
unsigned int theStyleMask = NSBorderlessWindowMask;
crWinPtr = (CRWindowPtr) xalloc(sizeof(CRWindowRec));
bounds = NSMakeRect(newX,
NSHeight([[NSScreen mainScreen] frame]) -
newY - pFrame->height,
pFrame->width, pFrame->height);
// Check if AppleWM has specified a style for this window
if (pFrame->win == nextWindowToFrame) {
theStyleMask = nextWindowStyle;
}
nextWindowToFrame = NULL;
// Create an NSWindow for the new X11 window
theWindow = [[NSWindow alloc] initWithContentRect:bounds
styleMask:theStyleMask
backing:NSBackingStoreBuffered
defer:NO];
if (!theWindow) return FALSE;
[theWindow setBackgroundColor:[NSColor clearColor]]; // erase transparent
[theWindow setAlphaValue:1.0]; // draw opaque
[theWindow setOpaque:YES]; // changed when window is shaped
[theWindow useOptimizedDrawing:YES]; // Has no overlapping sub-views
[theWindow setAutodisplay:NO]; // See comment above
[theWindow disableFlushWindow]; // We do all the flushing manually
[theWindow setHasShadow:YES]; // All windows have shadows
[theWindow setReleasedWhenClosed:YES]; // Default, but we want to be sure
theView = [[XView alloc] initWithFrame:bounds];
[theWindow setContentView:theView];
[theWindow setInitialFirstResponder:theView];
[theWindow setAcceptsMouseMovedEvents:YES];
crWinPtr->window = theWindow;
crWinPtr->view = theView;
[theView lockFocus];
// Fill the window with white to make sure alpha channel is set
NSEraseRect(bounds);
crWinPtr->port = [theView qdPort];
crWinPtr->context = [[NSGraphicsContext currentContext] graphicsPort];
// CreateCGContextForPort(crWinPtr->port, &crWinPtr->context);
[theView unlockFocus];
// Store the implementation private frame ID
pFrame->wid = (RootlessFrameID) crWinPtr;
// Reshape the frame if it was created shaped.
if (pShape != NULL)
CRReshapeFrame(pFrame->wid, pShape);
return TRUE;
}
/*
* CRDestroyFrame
* Destroy a frame.
*/
static void
CRDestroyFrame(RootlessFrameID wid)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
[crWinPtr->window orderOut:nil];
[crWinPtr->window close];
[crWinPtr->view release];
free(crWinPtr);
}
/*
* CRMoveFrame
* Move a frame on screen.
*/
static void
CRMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
NSPoint topLeft;
topLeft = NSMakePoint(newX,
NSHeight([[NSScreen mainScreen] frame]) - newY);
[crWinPtr->window setFrameTopLeftPoint:topLeft];
}
/*
* CRResizeFrame
* Move and resize a frame.
*/
static void
CRResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
int newX, int newY, unsigned int newW, unsigned int newH,
unsigned int gravity)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
NSRect bounds = NSMakeRect(newX, NSHeight([[NSScreen mainScreen] frame]) -
newY - newH, newW, newH);
[crWinPtr->window setFrame:bounds display:NO];
}
/*
* CRRestackFrame
* Change the frame order. Put the frame behind nextWid or on top if
* it is NULL. Unmapped frames are mapped by restacking them.
*/
static void
CRRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
CRWindowPtr crNextWinPtr = (CRWindowPtr) nextWid;
if (crNextWinPtr) {
int upperNum = [crNextWinPtr->window windowNumber];
[crWinPtr->window orderWindow:NSWindowBelow relativeTo:upperNum];
} else {
[crWinPtr->window makeKeyAndOrderFront:nil];
}
}
/*
* CRReshapeFrame
* Set the shape of a frame.
*/
static void
CRReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
NSRect bounds = [crWinPtr->view frame];
int winHeight = NSHeight(bounds);
BoxRec localBox = {0, 0, NSWidth(bounds), winHeight};
[crWinPtr->view lockFocus];
if (pShape != NULL) {
// Calculate the region outside the new shape.
REGION_INVERSE(NULL, pShape, pShape, &localBox);
}
// If window is currently shaped we need to undo the previous shape.
if (![crWinPtr->window isOpaque]) {
[[NSColor whiteColor] set];
NSRectFillUsingOperation(bounds, NSCompositeDestinationAtop);
}
if (pShape != NULL) {
int count = REGION_NUM_RECTS(pShape);
BoxRec *extRects = REGION_RECTS(pShape);
BoxRec *rects, *end;
// Make transparent if window is now shaped.
[crWinPtr->window setOpaque:NO];
// Clear the areas outside the window shape
[[NSColor clearColor] set];
for (rects = extRects, end = extRects+count; rects < end; rects++) {
int rectHeight = rects->y2 - rects->y1;
NSRectFill( NSMakeRect(rects->x1,
winHeight - rects->y1 - rectHeight,
rects->x2 - rects->x1, rectHeight) );
}
[[NSGraphicsContext currentContext] flushGraphics];
// force update of window shadow
[crWinPtr->window setHasShadow:NO];
[crWinPtr->window setHasShadow:YES];
} else {
[crWinPtr->window setOpaque:YES];
[[NSGraphicsContext currentContext] flushGraphics];
}
[crWinPtr->view unlockFocus];
}
/*
* CRUnmapFrame
* Unmap a frame.
*/
static void
CRUnmapFrame(RootlessFrameID wid)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
[crWinPtr->window orderOut:nil];
}
/*
* CRStartDrawing
* When a window's buffer is not being drawn to, the CoreGraphics
* window server may compress or move it. Call this routine
* to lock down the buffer during direct drawing. It returns
* a pointer to the backing buffer.
*/
static void
CRStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
PixMapHandle pix;
[crWinPtr->view lockFocus];
crWinPtr->port = [crWinPtr->view qdPort];
LockPortBits(crWinPtr->port);
[crWinPtr->view unlockFocus];
pix = GetPortPixMap(crWinPtr->port);
*pixelData = GetPixBaseAddr(pix);
*bytesPerRow = GetPixRowBytes(pix) & 0x3fff; // fixme is mask needed?
}
/*
* CRStopDrawing
* When direct access to a window's buffer is no longer needed, this
* routine should be called to allow CoreGraphics to compress or
* move it.
*/
static void
CRStopDrawing(RootlessFrameID wid, Bool flush)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
UnlockPortBits(crWinPtr->port);
if (flush) {
QDFlushPortBuffer(crWinPtr->port, NULL);
}
}
/*
* CRUpdateRegion
* Flush a region from a window's backing buffer to the screen.
*/
static void
CRUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
#ifdef ROOTLESS_TRACK_DAMAGE
int count = REGION_NUM_RECTS(pDamage);
BoxRec *rects = REGION_RECTS(pDamage);
BoxRec *end;
static RgnHandle rgn = NULL;
static RgnHandle box = NULL;
if (!rgn) rgn = NewRgn();
if (!box) box = NewRgn();
for (end = rects+count; rects < end; rects++) {
Rect qdRect;
qdRect.left = rects->x1;
qdRect.top = rects->y1;
qdRect.right = rects->x2;
qdRect.bottom = rects->y2;
RectRgn(box, &qdRect);
UnionRgn(rgn, box, rgn);
}
QDFlushPortBuffer(crWinPtr->port, rgn);
SetEmptyRgn(rgn);
SetEmptyRgn(box);
#else /* !ROOTLESS_TRACK_DAMAGE */
QDFlushPortBuffer(crWinPtr->port, NULL);
#endif
}
/*
* CRDamageRects
* Mark damaged rectangles as requiring redisplay to screen.
*/
static void
CRDamageRects(RootlessFrameID wid, int count, const BoxRec *rects,
int shift_x, int shift_y)
{
CRWindowPtr crWinPtr = (CRWindowPtr) wid;
const BoxRec *end;
for (end = rects + count; rects < end; rects++) {
Rect qdRect;
qdRect.left = rects->x1 + shift_x;
qdRect.top = rects->y1 + shift_y;
qdRect.right = rects->x2 + shift_x;
qdRect.bottom = rects->y2 + shift_y;
QDAddRectToDirtyRegion(crWinPtr->port, &qdRect);
}
}
static RootlessFrameProcsRec CRRootlessProcs = {
CRCreateFrame,
CRDestroyFrame,
CRMoveFrame,
CRResizeFrame,
CRRestackFrame,
CRReshapeFrame,
CRUnmapFrame,
CRStartDrawing,
CRStopDrawing,
CRUpdateRegion,
CRDamageRects,
NULL,
NULL,
NULL,
NULL
};
/*
* Initialize CR implementation
*/
Bool
CRInit(ScreenPtr pScreen)
{
RootlessInit(pScreen, &CRRootlessProcs);
rootless_CopyBytes_threshold = 0;
rootless_FillBytes_threshold = 0;
rootless_CompositePixels_threshold = 0;
rootless_CopyWindow_threshold = 0;
return TRUE;
}

View file

@ -0,0 +1,321 @@
/*
* Cocoa rootless implementation initialization
*/
/*
* Copyright (c) 2001 Greg Parker. All Rights Reserved.
* Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above copyright
* holders shall not be used in advertising or otherwise to promote the sale,
* use or other dealings in this Software without prior written authorization.
*/
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/cr/crScreen.m,v 1.5 2003/11/12 20:21:52 torrey Exp $ */
#include "quartzCommon.h"
#include "cr.h"
#undef BOOL
#define BOOL xBOOL
#include "darwin.h"
#include "quartz.h"
#include "quartzCursor.h"
#include "rootless.h"
#include "safeAlpha.h"
#include "pseudoramiX.h"
#include "applewmExt.h"
#include "regionstr.h"
#include "scrnintstr.h"
#include "picturestr.h"
#include "globals.h"
#undef BOOL
// Name of GLX bundle using AGL framework
static const char *crOpenGLBundle = "glxAGL.bundle";
static Class classXView = nil;
/*
* CRDisplayInit
* Find all screens.
*
* Multihead note: When rootless mode uses PseudoramiX, the
* X server only sees one screen; only PseudoramiX itself knows
* about all of the screens.
*/
static void
CRDisplayInit(void)
{
ErrorF("Display mode: Rootless Quartz -- Cocoa implementation\n");
if (noPseudoramiXExtension) {
darwinScreensFound = [[NSScreen screens] count];
} else {
darwinScreensFound = 1; // only PseudoramiX knows about the rest
}
CRAppleWMInit();
}
/*
* CRScreenParams
* Set the basic screen parameters.
*/
static void
CRScreenParams(int index, DarwinFramebufferPtr dfb)
{
dfb->bitsPerComponent = CGDisplayBitsPerSample(kCGDirectMainDisplay);
dfb->bitsPerPixel = CGDisplayBitsPerPixel(kCGDirectMainDisplay);
dfb->colorBitsPerPixel = 3 * dfb->bitsPerComponent;
if (noPseudoramiXExtension) {
NSScreen *screen = [[NSScreen screens] objectAtIndex:index];
NSRect frame = [screen frame];
// set x, y so (0,0) is top left of main screen
dfb->x = NSMinX(frame);
dfb->y = NSHeight([[NSScreen mainScreen] frame]) -
NSHeight(frame) - NSMinY(frame);
dfb->width = NSWidth(frame);
dfb->height = NSHeight(frame);
dfb->pitch = (dfb->width) * (dfb->bitsPerPixel) / 8;
// Shift the usable part of main screen down to avoid the menu bar.
if (NSEqualRects(frame, [[NSScreen mainScreen] frame])) {
dfb->y += aquaMenuBarHeight;
dfb->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.
dfb->x = unionRect.origin.x;
dfb->y = unionRect.origin.y;
dfb->width = unionRect.size.width;
dfb->height = unionRect.size.height;
dfb->pitch = (dfb->width) * (dfb->bitsPerPixel) / 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 %d is a mirror of screen %d.\n",
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 %d added: %dx%d @ (%d,%d).\n", i,
(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 %d placed at X11 coordinate (%d,%d).\n",
i, (int)frame.origin.x, (int)frame.origin.y);
PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
frame.size.width, frame.size.height);
}
}
}
/*
* CRAddScreen
* Init the framebuffer and record pixmap parameters for the screen.
*/
static Bool
CRAddScreen(int index, ScreenPtr pScreen)
{
DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
QuartzScreenPtr displayInfo = QUARTZ_PRIV(pScreen);
CGRect cgRect;
CGDisplayCount numDisplays;
CGDisplayCount allocatedDisplays = 0;
CGDirectDisplayID *displays = NULL;
CGDisplayErr cgErr;
CRScreenParams(index, dfb);
dfb->colorType = TrueColor;
// No frame buffer - it's all in window pixmaps.
dfb->framebuffer = NULL; // malloc(dfb.pitch * dfb.height);
// Get all CoreGraphics displays covered by this X11 display.
cgRect = CGRectMake(dfb->x, dfb->y, dfb->width, dfb->height);
do {
cgErr = CGGetDisplaysWithRect(cgRect, 0, NULL, &numDisplays);
if (cgErr) break;
allocatedDisplays = numDisplays;
displays = xrealloc(displays,
numDisplays * sizeof(CGDirectDisplayID));
cgErr = CGGetDisplaysWithRect(cgRect, allocatedDisplays, displays,
&numDisplays);
if (cgErr != CGDisplayNoErr) break;
} while (numDisplays > allocatedDisplays);
if (cgErr != CGDisplayNoErr || numDisplays == 0) {
ErrorF("Could not find CGDirectDisplayID(s) for X11 screen %d: %dx%d @ %d,%d.\n",
index, dfb->width, dfb->height, dfb->x, dfb->y);
return FALSE;
}
// This X11 screen covers all CoreGraphics displays we just found.
// If there's more than one CG display, then video mirroring is on
// or PseudoramiX is on.
displayInfo->displayCount = allocatedDisplays;
displayInfo->displayIDs = displays;
return TRUE;
}
/*
* CRSetupScreen
* Setup the screen for rootless access.
*/
static Bool
CRSetupScreen(int index, ScreenPtr pScreen)
{
// Add alpha protecting replacements for fb screen functions
pScreen->PaintWindowBackground = SafeAlphaPaintWindow;
pScreen->PaintWindowBorder = SafeAlphaPaintWindow;
#ifdef RENDER
{
PictureScreenPtr ps = GetPictureScreen(pScreen);
ps->Composite = SafeAlphaComposite;
}
#endif /* RENDER */
// Initialize generic rootless code
return CRInit(pScreen);
}
/*
* CRInitInput
* Finalize CR specific setup.
*/
static void
CRInitInput(int argc, char **argv)
{
int i;
rootlessGlobalOffsetX = darwinMainScreenX;
rootlessGlobalOffsetY = darwinMainScreenY;
for (i = 0; i < screenInfo.numScreens; i++)
AppleWMSetScreenOrigin(WindowTable[i]);
}
/*
* CRIsX11Window
* Returns TRUE if cr is displaying this window.
*/
static Bool
CRIsX11Window(void *nsWindow, int windowNumber)
{
NSWindow *theWindow = nsWindow;
if (!theWindow)
return FALSE;
if ([[theWindow contentView] isKindOfClass:classXView])
return TRUE;
else
return FALSE;
}
/*
* Quartz display mode function list.
*/
static QuartzModeProcsRec crModeProcs = {
CRDisplayInit,
CRAddScreen,
CRSetupScreen,
CRInitInput,
QuartzInitCursor,
QuartzReallySetCursor,
QuartzSuspendXCursor,
QuartzResumeXCursor,
NULL, // No capture or release in rootless mode
NULL,
CRIsX11Window,
RootlessFrameForWindow,
TopLevelParent,
NULL, // No support for DRI surfaces
NULL
};
/*
* QuartzModeBundleInit
* Initialize the display mode bundle after loading.
*/
Bool
QuartzModeBundleInit(void)
{
quartzProcs = &crModeProcs;
quartzOpenGLBundle = crOpenGLBundle;
classXView = [XView class];
return TRUE;
}