X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fplat%2FCarbon.java;h=c6ec3505dd464fec3a51f6121dbf101032f6a428;hb=b5fa5227a80e97611a8433a275c18a6f695bf32b;hp=77d4dd90fa037ed1bb55ec9476b96213f519fc94;hpb=1d78b2dbeba31c5814824035a8da36a01d928be6;p=org.ibex.core.git diff --git a/src/org/xwt/plat/Carbon.java b/src/org/xwt/plat/Carbon.java index 77d4dd9..c6ec350 100644 --- a/src/org/xwt/plat/Carbon.java +++ b/src/org/xwt/plat/Carbon.java @@ -1,207 +1,321 @@ -// Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL] +// Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL] +// Authors: Brian Alliet and Evan Jones + package org.xwt.plat; -import java.awt.*; -import java.awt.image.*; import gnu.gcj.RawData; -import java.net.*; -import java.lang.reflect.*; -import java.io.*; -import java.util.*; -import java.awt.peer.*; import org.xwt.util.*; import org.xwt.*; +import java.util.*; -/** Platform implementation for Carbon UI on a POSIX-compliant OS (ie Mac OS X) */ public class Carbon extends POSIX { - - /** hashtable of all OS X fonts; key is an XWT font name, value is WrappedRawData which stores an ATSFontRef. - * Initialized by natInit(). */ - static Hashtable nativeFontCache = new Hashtable(); - - /** Cache of ATSUStyle objects; key is an XWT font spec, value is WrappedRawData which stores an ATSUStyle. - * According to an Apple technote, caching the style bjects can really increase performance. */ - static Hashtable atsuStyleCache = new Hashtable(); - - /** List of all XWT font specs. Initialized by init(). */ - static String[] fontList = null; - - // General Methods /////////////////////////////////////////////////////// - - protected String _getAltKeyName() { return "option"; } - protected String[] _listFonts() { return fontList; } - protected Picture _createPicture(int[] data, int w, int h) { return new CarbonPicture(data, w, h); } - protected DoubleBuffer _createDoubleBuffer(int w, int h, Surface owner) { return new CarbonDoubleBuffer(w, h); } - protected Surface _createSurface(Box b, boolean framed) { return new CarbonSurface(b, framed); } + static Carbon singleton; + private CarbonOpenGL openGL; + boolean jaguar; // true if we are on OS X >= 10.2 + + // TEMPORARY HACKS (remove these when we ditch platform fonts) + protected int _stringWidth(String font, String text) { return (int)Math.round(6.5 * text.length()); } + protected int _getMaxAscent(String font) { return 10; } + protected int _getMaxDescent(String font) { return 2; } + + // General Methods + protected String _getAltKeyName() { return "Option"; } protected boolean _needsAutoClick() { return false; } - protected native int _getScreenWidth(); - protected native int _getScreenHeight(); - protected native String _getClipBoard(); - protected native void _setClipBoard(String s); - static String defaultFontName = "lucida_grande"; - protected String _getDefaultFont() { return defaultFontName + "13"; } - protected native int _stringWidth(String fontSpec, String text); - protected native int _getMaxAscent(String font); - protected native int _getMaxDescent(String font); protected boolean _needsAutoDoubleClick() { return false; } + protected String getDescriptiveName() { return "GCJ Carbon Binary"; } + protected boolean _isCaseSensitive() { return false; /* Well, not always, could be UFS */ } + + + // Native Methods + protected int _getScreenWidth() { return cgScreenWidth(); } + protected int _getScreenHeight() { return cgScreenHeight(); } + private native static int cgScreenWidth(); + private native static int cgScreenHeight(); + protected native void _newBrowserWindow(String url); + protected native Proxy natDetectProxy(); + private native void natInit(); + protected native void _exit(); + + private native String natGetClipBoard(); + private native void natSetClipBoard(String text); + protected void _setClipBoard(final String text) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetClipBoard(text); } }); } + protected String _getClipBoard() { + final Semaphore sem = new Semaphore(); + final String[] result = new String[1]; // Kind of like a pointer + CarbonMessage.add(new CarbonMessage() { public void perform() { result[0] = natGetClipBoard(); sem.release(); } }); + sem.block(); + return result[0]; + } + + private static class FileDialogHelper { + public FileDialogHelper(boolean save) { this.save = save; } + public boolean save; + public Semaphore sem = new Semaphore(); + public String fileName; + public String saveName; + public RawData rawUPP; + } + private native void natFileDialog(FileDialogHelper helper, String suggestedFileName, boolean write); + protected String _fileDialog(final String fn, final boolean w) { + final FileDialogHelper helper = new FileDialogHelper(w); + CarbonMessage.add(new CarbonMessage() { public void perform() { natFileDialog(helper,fn,w); } }); + helper.sem.block(); + if(w) + return helper.fileName + "/" + helper.saveName; + else + return helper.fileName; + } - /** Returns the ATSUStyle associated with the given XWT font spec. - * This method first checks its internal cache before creating the - * ATSUStyle object from scratch. */ - protected RawData _getATSUStyle( String fontSpec ) { - WrappedRawData ret = null; - ret = (WrappedRawData) atsuStyleCache.get( fontSpec ); - if (ret != null) return ret.wrapee; - - Platform.ParsedFont pf = new Platform.ParsedFont( fontSpec ); - - // Find the font - if (pf.name.equals("serif")) pf.name = "lucida_grande"; - else if (pf.name.equals("sansserif")) pf.name = "helvetica"; - else if (pf.name.equals("monospace")) pf.name = "courier"; - else if (pf.name.equals("dialog")) pf.name = "lucida_grande"; - else if (pf.name.equals("tty")) pf.name = "courier"; - - // Find the ATSFontRef - WrappedRawData fontRef = (WrappedRawData) nativeFontCache.get( pf.name ); - // If we couldn't find the font, use the default font - if ( fontRef == null ) fontRef = (WrappedRawData) nativeFontCache.get( defaultFontName ); - if ( fontRef == null ) throw new Error( "Default font cannot be found" ); - - // Create the ATSUStyle object - ret = new WrappedRawData( _createATSUStyle( fontRef.wrapee, pf.size, pf.bold, pf.italic, pf.underline ) ); - - // Map this font spec to the ATSFontRef to optimize future requests - atsuStyleCache.put( fontSpec, ret ); - - return ret.wrapee; + + // Called by main thread after initialization, this is the event handler + protected native void _running(); + + static void abort(String err) { + throw new Error(err); + } + + public Carbon() { + synchronized(Carbon.class) { + if(singleton != null) abort("Tried to instansiate Carbon more than once"); + singleton = this; } - - /** Creates an ATSUStyle object with the specified attributes. */ - protected native RawData _createATSUStyle( RawData fontRef, int fontSize, boolean isBold, boolean isItalic, boolean isUnderline ); - - /** Called once XWT is initialized and the application is running. On Mac OS X this calls - * RunApplicationEventLoop(). */ - protected native void _running(); - - /** dumps a list of Mac OS X font strings. TODO: Will this be sufficient? */ - //private native String[] listNativeFonts(); - /** translates a font string into an ATSUFontRef? TODO: Will this be sufficient? */ - //public static native gnu.gcj.RawData fontStringToStruct(String s); - - public Carbon() { } - + } + + protected synchronized Proxy _detectProxy() { + return natDetectProxy(); + } + + private static native final boolean isJaguar(); + public void init() { - natInit(); + super.init(); + jaguar = isJaguar(); + try { + openGL = new CarbonOpenGL(); + openGL.init(); + } catch(OpenGL.NotSupportedException e) { + Log.log(this,"WARNING: OpenGL support not available: " + e); + // FIXME: We need to fallback to Quartz2D + throw new Error("No OpenGL support"); + } + natInit(); + } + + private final class CarbonOpenGL extends OpenGL { + public RawData rawPixelFormat; + public RawData rawSharedContext; + public int maxAglSurfaceTexSize; + public int maxSurfaceWidth; + public int maxSurfaceHeight; + + private native boolean initPixelFormat(); + private native void initSharedContext(); + + public CarbonOpenGL() throws NotSupportedException { + if(!jaguar) + throw new NotSupportedException("OpenGL requires Mac OS X 10.2 or greater"); + if(!initPixelFormat()) + throw new NotSupportedException("Couldn't get an acceptable pixel format"); + initSharedContext(); + } + + public void init() throws NotSupportedException { + super.init(); + maxAglSurfaceTexSize = rectangularTextures ? maxRectTexSize : maxTexSize; + if(renderer.startsWith("ATI Radeon 7500")) { + maxAglSurfaceTexSize = Math.min(rectangularTextures ? 1600 : 1024,maxAglSurfaceTexSize); + Log.log(this,"Working around Radeon 7500 bug: maxAglSurfaceTexSize: " + maxAglSurfaceTexSize); + } + maxSurfaceWidth = maxSurfaceHeight = maxAglSurfaceTexSize; + } + protected native void activateSharedContext(); + } + + static abstract class CarbonSurface extends Surface { + RawData rawWindowRef; + RawData rawEventHandlerUPP; + int modifiers; + + private native void natSetInvisible(boolean i); + public void setInvisible(final boolean i) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetInvisible(i); } }); } + private native void nat_setMaximized(boolean b); + public void _setMaximized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMaximized(b); } }); } + private native void nat_setMinimized(boolean b); + public void _setMinimized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMinimized(b); } }); } + private native void natSetIcon(Picture p); + public void setIcon(final Picture p) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetIcon(p); } }); } + private native void natSetTitleBarText(String s); + public void setTitleBarText(final String s) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetTitleBarText(s); } }); } + private native void natSetSize(int w, int h); + public void setSize(final int w, final int h) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetSize(w,h); } }); } + private native void natSetLocation(int x, int y); + public void setLocation(final int x, final int y) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLocation(x,y); } }); } + private native void natToFront(); + public void toFront() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToFront(); } }); } + private native void natToBack(); + public void toBack() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToBack(); } }); } + private native void natSetLimits(int minWidth, int minHeight, int maxWidth, int maxHeight); + public void setLimits(final int mnw, final int mnh, final int mxw, final int mxh) { + if(Carbon.singleton.jaguar) + CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLimits(mnw,mnh,mxw,mxh); } }); + } + private native void natSyncCursor(int n); + public void syncCursor() { + int n; + if(cursor.equals("default")) n = 0; + else if(cursor.equals("wait")) n = 1; + else if(cursor.equals("crosshair")) n = 2; + else if(cursor.equals("text")) n = 3; + else if(cursor.equals("hand")) n = 4; + else if(cursor.equals("move")) n = 5; + else if(cursor.equals("east") || cursor.equals("west")) n = 6; + else n = 0; + final int n_ = n; + CarbonMessage.add(new CarbonMessage() { public void perform() { natSyncCursor(n_); } }); + } - // nativeFontCache contains font NAMES. Each font exists as an outline font - // which can be any size, plus can have real or simulated bold or italic - fontList = new String[nativeFontCache.size()*4]; - Enumeration e = nativeFontCache.keys(); - for(int i=0; e.hasMoreElements(); i+=4) { - String fontName = (String)e.nextElement() + "0"; - - fontList[i] = fontName; - fontList[i+1] = fontName + "i"; - fontList[i+2] = fontName + "b"; - fontList[i+3] = fontName + "bi"; - } + public void _sizeChange(int w, int h) { SizeChange(w,h); } + + /* Drawing stuff */ + public abstract void blit(DoubleBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2); - // Make sure that the default font exists - if ( _getATSUStyle( _getDefaultFont() ) == null ) throw new Error( "Default font does not exist" ); + public final void _dispose() { CarbonMessage.add(new CarbonMessage() { public void perform() { natDispose(); } }); } + public native void natDispose(); + + public final native void natInit(boolean framed); + + public CarbonSurface(Box root, final boolean framed) { + super(root); + final Semaphore sem = new Semaphore(); + CarbonMessage.add(new CarbonMessage() { public void perform() { CarbonSurface.this.natInit(framed); sem.release(); } }); + sem.block(); } + + public void reshape(int w, int h) { } + } + + static class GLCarbonDoubleBuffer extends OpenGL.GLDoubleBuffer { + RawData rawCTX; + RawData rawWindowRef; + int textureName; + boolean rectTexture; + CarbonOpenGL gl; + private native void natInit(); - - /** so we can put ATSUStyles and ATSFontRefs into Hashtables */ - private static class WrappedRawData { - public RawData wrapee = null; - public WrappedRawData(RawData r) { wrapee = r; } + private static native void natCleanup(RawData rawWindowRef, RawData rawCTX); + + + private static final int fixupDimension(CarbonOpenGL gl, int n) { + if(!gl.rectangularTextures) n = OpenGL.roundToPowerOf2(n); + return Math.min(n,gl.maxAglSurfaceTexSize); + } + public GLCarbonDoubleBuffer(int w, int h, final CarbonOpenGL gl) { + super(fixupDimension(gl,w),fixupDimension(gl,h)); + this.gl = gl; + rectTexture = gl.hasRectangularTextures(); + final Semaphore sem = new Semaphore(); + CarbonMessage.add(new CarbonMessage() { public void perform() { GLCarbonDoubleBuffer.this.natInit(); sem.release(); } }); + sem.block(); + } + public native void activateContext(); + protected void finalize() { + CarbonMessage.add(new CarbonMessage() { public void perform() { natCleanup(rawWindowRef,rawCTX); } }); + gl.deleteTexture(textureName); + } + } + + static class GLCarbonSurface extends CarbonSurface { + RawData rawCTX; + CarbonOpenGL gl; + boolean sizeChange; + + private final native void natInit(); + + public GLCarbonSurface(Box root, boolean framed, CarbonOpenGL gl) { + super(root,framed); + this.gl = gl; + natInit(); + } + + public void setLimits(int mnw,int mnh, int mxw, int mxh) { + mxw = Math.min(mxw,gl.maxSurfaceWidth); + mxh = Math.min(mxh,gl.maxSurfaceHeight); + super.setLimits(mnw,mnh,mxw,mxh); + } + public void _sizeChange(int w, int h) { + sizeChange = true; + super._sizeChange(w,h); + } + + public void setSize(int w, int h) { + sizeChange = true; + w = Math.min(w,gl.maxSurfaceWidth); + h = Math.min(h,gl.maxSurfaceWidth); + super.setSize(w,h); + } + + private native void natBlit(GLCarbonDoubleBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2); + public synchronized void blit(DoubleBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2) { + natBlit((GLCarbonDoubleBuffer)db,sx,sy,dx,dy,dx2,dy2); + } + + private native void natReshape(int w, int h); + public synchronized void reshape(int w, int h) { natReshape(w,h); } + + public native void natDispose(); } - // CarbonSurface ///////////////////////////////////////////////////// - - /** Implements a Surface as an Carbon Window */ - public static class CarbonSurface extends Surface { - - /** The WindowRef that implements this Surface. */ - gnu.gcj.RawData window = null; - /** The CGContextRef. TODO: How do we get this??? */ - gnu.gcj.RawData gc = null; - - public native void setInvisible(boolean i); - public native void _setMaximized(boolean m); - public native void setIcon(Picture p); - public native void _setMinimized(boolean b); - public native void setTitleBarText(String s); - public native void setSize(int w, int h); - public native void setLocation(int x, int y); - public native void natInit(boolean framed); - public native void toFront(); - public native void toBack(); - public native void syncCursor(); - public native void _dispose(); - //public native void setLimits(int minw, int minh, int maxw, int maxh); + /*private class QZCarbonDoubleBuffer extends DoubleBuffer { + + public QZCarbonDoubleBuffer(int width, int height) { + } + } + + private class QZCarbonSurface extends CarbonSurface { + public QZCarbonSurface(Box root, boolean framed) { + super(b,root); + } public native void blit(DoubleBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2); - - public CarbonSurface(Box root, boolean framed) { super(root); natInit( framed ); } - } - - - // Our Subclass of Picture /////////////////////////////////////////////// - - /** Implements a Picture */ - public static class CarbonPicture extends Picture { + + private class QZCarbonPicture extends Picture { int width; int height; - int[] data = null; - - /** A CGImageRef of the picture. */ - RawData image = null; - - public int getWidth() { return width; } - public int getHeight() { return height; } - - public native void natInit(); - public native void finalize(); + + public final int getWidth() { return width; } + public final int getHeight() { return height; } - public CarbonPicture(int[] data, int w, int h) { - this.data = data; + public QZCarbonPicture(int w, int h) { this.width = w; this.height = h; - natInit(); } - + }*/ + + protected DoubleBuffer _createDoubleBuffer(int w, int h, Surface owner) { + if(openGL != null) + return new GLCarbonDoubleBuffer(w,h,openGL); + else + return /*new QZCarbonDoubleBuffer(w,h)*/ null; } - - /** A Carbon DoubleBuffer */ - public static class CarbonDoubleBuffer extends DoubleBuffer { - int width; - int height; - - /** A pointer to the raw bitmap data. */ - RawData bitmapData; - /** A CGBitmapContextRef. */ - RawData gc; - /** A CGImageRef which represents the CGBitmapContext. */ - RawData image; - - public int getWidth() { return width; } - public int getHeight() { return height; } - - public CarbonDoubleBuffer(int w, int h) { - this.width = w; - this.height = h; - natInit(); - } - - public native void setClip(int x, int y, int x2, int y2); - public native void drawPicture(Picture source, int x, int y); - public native void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2); - public native void fillRect(int x, int y, int x2, int y2, int color); - public native void drawString(String font, String text, int x, int y, int color); - public native void natInit(); - public native void finalize(); + protected Surface _createSurface(Box b, boolean framed) { + if(openGL != null) + return new GLCarbonSurface(b,framed, openGL); + else + return /*new QZCarbonSufrace(b,framed)*/ null; + } + protected Picture _createPicture(int[] data, int w, int h) { + if(openGL != null) + return openGL.createPicture(data,w,h); + else + return /*new QZCarbonPicture(data,w,h);*/ null; + } + + /* A message that is sent through the carbon event queue */ + private static abstract class CarbonMessage { + public abstract void perform(); + + static { natInit(); } + public static native void natInit(); + public static native void add(CarbonMessage m); } - }