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