-// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL]
+// Authors: Brian Alliet and Evan Jones
+
package org.xwt.plat;
+import gnu.gcj.RawData;
+import org.xwt.util.*;
import org.xwt.*;
+import java.util.*;
+
+public class Darwin extends POSIX {
+ static Darwin 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 boolean _needsAutoDoubleClick() { return false; }
+ protected String getDescriptiveName() { return "GCJ Darwin 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;
+ }
+
+
+ // 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 Darwin() {
+ synchronized(Darwin.class) {
+ if(singleton != null) abort("Tried to instansiate Darwin more than once");
+ singleton = this;
+ }
+ }
+
+ protected synchronized Proxy _detectProxy() {
+ return natDetectProxy();
+ }
+
+ private static native final boolean isJaguar();
+
+ public void init() {
+ 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_); } });
+ }
+
+ 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);
+
+ 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();
+ 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();
+ }
-/** All Darwin-derived operating systems (Mac OS X, OpenDarwin) */
-public abstract class Darwin extends X11 {
+ /*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);
+ }
+
+ private class QZCarbonPicture extends Picture {
+ int width;
+ int height;
+
+ public final int getWidth() { return width; }
+ public final int getHeight() { return height; }
+
+ public QZCarbonPicture(int w, int h) {
+ this.width = w;
+ this.height = h;
+ }
+ }*/
+
+ 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;
+ }
+ 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);
+ }
}