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