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