questionable patch: merge of a lot of stuff from the svg branch
[org.ibex.core.git] / src / org / ibex / plat / Darwin.java
1 // Copyright 2004 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // Authors: Brian Alliet and Evan Jones
3
4 package org.ibex.plat;
5
6 import gnu.gcj.RawData;
7 import org.ibex.util.*;
8 import org.ibex.js.*;
9 import org.ibex.graphics.*;
10 import org.ibex.core.*;
11 import org.ibex.net.*;
12
13 public class Darwin extends POSIX {
14     public static void main(String[] s) throws Exception { org.ibex.core.Main.main(s); }
15     private static final Class openGLClass = OpenGL.class;
16     static Darwin singleton;
17     private CarbonOpenGL openGL;
18     boolean jaguar; // true if we are on OS X >= 10.2
19     
20     // General Methods
21     protected String _getAltKeyName() { return "Option"; }
22     protected boolean _needsAutoClick() { return false; }
23     protected boolean _needsAutoDoubleClick() { return false; }
24     protected String getDescriptiveName() { return "GCJ Darwin Binary"; }
25     protected boolean _isCaseSensitive() { return false; /* Well, not always, could be UFS */ }
26     
27     
28     // Native Methods
29     protected int    _getScreenWidth() { return cgScreenWidth(); }
30     protected int    _getScreenHeight() { return cgScreenHeight(); }
31     private native static int cgScreenWidth();
32     private native static int cgScreenHeight();
33     protected native void   _newBrowserWindow(String url);
34     protected native HTTP.Proxy   natDetectProxy();
35     private   native void    natInit();
36
37     private native String natGetClipBoard();
38     private native void natSetClipBoard(String text);
39     protected void _setClipBoard(final String text) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetClipBoard(text); } }); }
40     protected String _getClipBoard() {
41         final Semaphore sem = new Semaphore();
42         final String[] result = new String[1]; // Kind of like a pointer
43         CarbonMessage.add(new CarbonMessage() { public void perform() { result[0] = natGetClipBoard(); sem.release(); } });
44         sem.block();
45         return result[0];
46     }
47     
48     private static class FileDialogHelper {
49         public FileDialogHelper(boolean save) { this.save = save; }
50         public boolean save;
51         public Semaphore sem = new Semaphore();
52         public String fileName;
53         public String saveName;
54     }
55     private native void natFileDialog(FileDialogHelper helper, String suggestedFileName, boolean write);
56     protected String _fileDialog(final String fn, final boolean w) {
57         final FileDialogHelper helper = new FileDialogHelper(w);
58         CarbonMessage.add(new CarbonMessage() { public void perform() { natFileDialog(helper,fn,w); } });
59         helper.sem.block();
60         if(w)
61             return helper.fileName + "/" + helper.saveName;
62         else
63             return helper.fileName;
64     }
65
66     
67     static void abort(String err) {
68         throw new Error(err);
69     }
70     
71     public Darwin() {
72         synchronized(Darwin.class) {
73             if(singleton != null) abort("Tried to instansiate Darwin more than once");
74             singleton = this;
75         }
76     }
77     
78     protected synchronized HTTP.Proxy _detectProxy() {
79         return natDetectProxy();
80     }
81     
82     private static native final boolean isJaguar();
83     
84     public void postInit() {
85         jaguar = isJaguar();
86         try {
87             openGL = new CarbonOpenGL();
88             openGL.init();
89         } catch(OpenGL.NotSupportedException e) {
90             Log.info(this,"WARNING: OpenGL support not available: " + e);
91             // FEATURE: fall back to quartz 2d
92             throw new Error("No OpenGL support");
93         }
94         natInit();
95     }
96     
97     protected Platform.Scheduler _getScheduler() { return new DarwinScheduler(); }
98     protected native void runApplicationEventLoop();
99     private class DarwinScheduler extends Scheduler {
100         public void run() {
101             new Thread() { public void run() { defaultRun(); } }.start();
102             runApplicationEventLoop();
103         }
104     }
105     
106     private final class CarbonOpenGL extends OpenGL {
107         public RawData rawPixelFormat;
108         public RawData rawSharedContext;
109         public int maxAglSurfaceTexSize;
110         public int maxSurfaceWidth;
111         public int maxSurfaceHeight;
112         
113         private native boolean initPixelFormat();
114         private native void initSharedContext();
115         
116         public CarbonOpenGL() throws NotSupportedException {
117             if(!jaguar)
118                 throw new NotSupportedException("OpenGL requires Mac OS X 10.2 or greater");
119             if(!initPixelFormat())
120                 throw new NotSupportedException("Couldn't get an acceptable pixel format");
121             initSharedContext();
122         }
123         
124         public void init() throws NotSupportedException {
125             super.init();
126             maxAglSurfaceTexSize = rectangularTextures ? maxRectTexSize : maxTexSize;
127             if(renderer.startsWith("ATI Radeon 7500")) {
128                 maxAglSurfaceTexSize = Math.min(rectangularTextures ? 1600 : 1024,maxAglSurfaceTexSize);
129                 Log.info(this,"Working around Radeon 7500 bug: maxAglSurfaceTexSize: " + maxAglSurfaceTexSize);
130             }
131             maxSurfaceWidth = maxSurfaceHeight = maxAglSurfaceTexSize;
132         }
133         protected native void activateSharedContext();
134     }
135     
136     static abstract class CarbonSurface extends Surface {  
137         RawData rawWindowRef;
138         int modifiers;
139         int winWidth;
140         int winHeight;
141         
142         boolean pendingResize;
143          
144         private native void natSetInvisible(boolean i);
145         public void setInvisible(final boolean i) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetInvisible(i); } }); }
146         private native void nat_setMaximized(boolean b);
147         public void _setMaximized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMaximized(b); } }); }
148         private native void nat_setMinimized(boolean b);
149         public void _setMinimized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMinimized(b); } }); }
150         private native void natSetIcon(Picture p);
151         public void setIcon(final Picture p) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetIcon(p); } }); }
152         private native void natSetTitleBarText(String s);
153         public void setTitleBarText(final String s) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetTitleBarText(s); } }); }
154         private native void natSetSize(int w, int h);
155         public void _setSize(final int w, final int h) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetSize(w,h); } }); }
156         private native void natSetLocation();
157         public void setLocation() { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLocation(); } }); }
158         private native void natToFront();
159         public void toFront() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToFront(); } }); }
160         private native void natToBack();
161         public void toBack() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToBack(); } }); }
162         private native void natSetLimits(int minWidth, int minHeight, int maxWidth, int maxHeight);
163         public void setLimits(final int mnw, final int mnh, final int mxw, final int mxh) {
164             if(Darwin.singleton.jaguar)
165                 CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLimits(mnw,mnh,mxw,mxh); } });
166         }
167         private native void natSyncCursor(int n);
168         public void syncCursor() {
169             int n;
170             if(cursor.equals("default")) n = 0;
171             else if(cursor.equals("wait")) n = 1;
172             else if(cursor.equals("crosshair")) n = 2;
173             else if(cursor.equals("text")) n = 3;
174             else if(cursor.equals("hand")) n = 4;
175             else if(cursor.equals("move")) n = 5;
176             else if(cursor.equals("east") || cursor.equals("west")) n = 6;
177             else n = 0; 
178             final int n_ = n;
179             CarbonMessage.add(new CarbonMessage() { public void perform() { natSyncCursor(n_); } });
180         }
181        
182         /* Drawing stuff */
183         public abstract void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
184
185         public final void _dispose() { CarbonMessage.add(new CarbonMessage() { public void perform() { natDispose(); } }); }
186         public native void natDispose();
187         
188         public final native void natInit(boolean framed);
189         
190         public CarbonSurface(Box root, final boolean framed) {
191             super(root);
192             final Semaphore sem = new Semaphore();
193             CarbonMessage.add(new CarbonMessage() { public void perform() { CarbonSurface.this.natInit(framed); sem.release(); } });
194             sem.block();
195         }
196         
197         public void needsReshape() { }
198         protected static native void blitLock();
199         protected static native void blitUnlock();
200         protected static native void blitWait();
201     }
202     
203     static class GLCarbonPixelBuffer extends OpenGL.GLPixelBuffer {
204         RawData rawCTX;
205         RawData rawWindowRef;
206         int textureName;
207         boolean rectTexture;
208         CarbonOpenGL gl;
209         
210         private native void natInit();
211         private static native void natCleanup(RawData rawWindowRef, RawData rawCTX);
212         
213         private static final int fixupDimension(CarbonOpenGL gl, int n) {
214             if(!gl.rectangularTextures) n = OpenGL.roundToPowerOf2(n);
215             return Math.min(n,gl.maxAglSurfaceTexSize);
216         }
217         public GLCarbonPixelBuffer(int w, int h, final CarbonOpenGL gl) {
218             super(fixupDimension(gl,w),fixupDimension(gl,h));
219             this.gl = gl;
220             rectTexture = gl.hasRectangularTextures();
221             final Semaphore sem = new Semaphore();
222             CarbonMessage.add(new CarbonMessage() { public void perform() { GLCarbonPixelBuffer.this.natInit(); sem.release(); } });
223             sem.block();
224         }
225         public native void activateContext();
226         protected void finalize() {
227             CarbonMessage.add(new CarbonMessage() { public void perform() { natCleanup(rawWindowRef,rawCTX); } });
228             gl.deleteTexture(textureName);
229         }
230     }
231     
232     static class GLCarbonSurface extends CarbonSurface {
233         RawData rawCTX;
234         CarbonOpenGL gl;
235         boolean needsReshape;
236                 
237         private final native void natInit();
238         private final native void flush();
239         private final native void clear();
240
241         private PixelBuffer pb;
242         public PixelBuffer getPixelBuffer() { return pb; }
243
244         static class GLCarbonSurfacePixelBuffer extends GLCarbonPixelBuffer {
245             RawData rawCTX;
246             public native void activateContext();
247             public GLCarbonSurfacePixelBuffer(RawData rawCTX, CarbonOpenGL gl) {
248                 super(500, 500, gl);
249                 this.rawCTX = rawCTX;
250             }
251         }
252         
253         public GLCarbonSurface(Box root, boolean framed, CarbonOpenGL gl) {
254             super(root,framed);
255             this.gl = gl;
256             natInit();
257             pb = new GLCarbonSurfacePixelBuffer(rawCTX, gl);
258         }
259         
260         public void setLimits(int mnw,int mnh, int mxw, int mxh) {
261             mxw = Math.min(mxw,gl.maxSurfaceWidth);
262             mxh = Math.min(mxh,gl.maxSurfaceHeight);
263             super.setLimits(mnw,mnh,mxw,mxh);
264         }
265         
266         public void _setSize(int w, int h) {
267             w = Math.min(w,gl.maxSurfaceWidth);
268             h = Math.min(h,gl.maxSurfaceWidth);
269             super._setSize(w,h);
270         }
271         
272         private native void natBlit(GLCarbonPixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2);
273         public void blit(PixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2) {
274             natBlit((GLCarbonPixelBuffer)db,sx,sy,dx,dy,dx2,dy2);
275         }
276         
277         
278         // The blit_lock ensures the window size does not change through the entire blit operation.
279         public void render() {
280             /*
281             blitLock();
282             while(pendingResize) blitWait();
283             */
284             if(needsReshape) {
285                 needsReshape = false;
286                 
287                 reshape(winWidth,winHeight);
288                 clear();
289                 dirty(0,0,winWidth,winHeight);
290             }
291             super.render();
292             flush();
293             /*
294             blitUnlock();
295             */
296         }
297         
298         private native void reshape(int w, int h);
299         // blit_lock is assumed to be held
300         public void needsReshape() { needsReshape = true; }
301
302         public native void natDispose();
303     }
304
305     /*private class QZCarbonPixelBuffer extends PixelBuffer {
306         
307         public QZCarbonPixelBuffer(int width, int height) {
308         }
309     }
310        private class QZCarbonSurface extends CarbonSurface {
311         public QZCarbonSurface(Box root, boolean framed) {
312             super(b,root);
313         }
314         public native void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
315     }
316     
317     private class QZCarbonPicture extends Picture {
318         int width;
319         int height;
320         
321         public final int getWidth() { return width; }
322         public final int getHeight() { return height; }
323                 
324         public QZCarbonPicture(int w, int h) {
325             this.width = w;
326             this.height = h;
327         }
328     }*/
329     
330     protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) {
331         if(openGL != null)
332             return new GLCarbonPixelBuffer(w,h,openGL);
333         else
334             return /*new QZCarbonPixelBuffer(w,h)*/ null;
335     }
336     protected Surface _createSurface(Box b, boolean framed) {
337         if(openGL != null)
338             return new GLCarbonSurface(b,framed, openGL);
339         else
340             return /*new QZCarbonSufrace(b,framed)*/ null;
341     }
342     protected Picture _createPicture(JS r) {
343         if(openGL != null)
344             return openGL._createPicture(r, true);
345         else
346             return /*new QZCarbonPicture(data,w,h);*/ null;
347     }
348     protected org.ibex.graphics.Font.Glyph  _createGlyph(org.ibex.graphics.Font f, char c) {
349         if(openGL != null)
350             return openGL._createGlyph(f, c);
351         else
352             return super.createGlyph(f, c);
353     }
354     
355     /* A message that is sent through the carbon event queue */
356     private static abstract class CarbonMessage {
357         public abstract void perform();
358         
359         static { natInit(); }
360         public static native void natInit();
361         public static native void add(CarbonMessage m);
362     }
363 }