2003/09/19 05:26:47
[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     // TEMPORARY HACKS (remove these when we ditch platform fonts)
17     protected int _stringWidth(String font, String text) { return (int)Math.round(6.5 * text.length()); }
18     protected int _getMaxAscent(String font) { return 10; }
19     protected int _getMaxDescent(String font) { return 2; }
20     
21     // General Methods
22     protected String _getAltKeyName() { return "Option"; }
23     protected boolean _needsAutoClick() { return false; }
24     protected boolean _needsAutoDoubleClick() { return false; }
25     protected String getDescriptiveName() { return "GCJ Darwin Binary"; }
26     protected boolean _isCaseSensitive() { return false; /* Well, not always, could be UFS */ }
27     
28     
29     // Native Methods
30     protected int    _getScreenWidth() { return cgScreenWidth(); }
31     protected int    _getScreenHeight() { return cgScreenHeight(); }
32     private native static int cgScreenWidth();
33     private native static int cgScreenHeight();
34     protected native void   _newBrowserWindow(String url);
35     protected native Proxy   natDetectProxy();
36     private   native void    natInit();
37     protected native void   _exit();
38
39     private native String natGetClipBoard();
40     private native void natSetClipBoard(String text);
41     protected void _setClipBoard(final String text) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetClipBoard(text); } }); }
42     protected String _getClipBoard() {
43         final Semaphore sem = new Semaphore();
44         final String[] result = new String[1]; // Kind of like a pointer
45         CarbonMessage.add(new CarbonMessage() { public void perform() { result[0] = natGetClipBoard(); sem.release(); } });
46         sem.block();
47         return result[0];
48     }
49     
50     private static class FileDialogHelper {
51         public FileDialogHelper(boolean save) { this.save = save; }
52         public boolean save;
53         public Semaphore sem = new Semaphore();
54         public String fileName;
55         public String saveName;
56         public RawData rawUPP;
57     }
58     private native void natFileDialog(FileDialogHelper helper, String suggestedFileName, boolean write);
59     protected String _fileDialog(final String fn, final boolean w) {
60         final FileDialogHelper helper = new FileDialogHelper(w);
61         CarbonMessage.add(new CarbonMessage() { public void perform() { natFileDialog(helper,fn,w); } });
62         helper.sem.block();
63         if(w)
64             return helper.fileName + "/" + helper.saveName;
65         else
66             return helper.fileName;
67     }
68
69     
70     // Called by main thread after initialization, this is the event handler
71     protected native void _running();
72     
73     static void abort(String err) {
74         throw new Error(err);
75     }
76     
77     public Darwin() {
78         synchronized(Darwin.class) {
79             if(singleton != null) abort("Tried to instansiate Darwin more than once");
80             singleton = this;
81         }
82     }
83     
84     protected synchronized Proxy _detectProxy() {
85         return natDetectProxy();
86     }
87     
88     private static native final boolean isJaguar();
89     private static native final void linkMe();
90     
91     public void init() {
92         super.init();
93         linkMe();
94         jaguar = isJaguar();
95         try {
96             openGL = new CarbonOpenGL();
97             openGL.init();
98         } catch(OpenGL.NotSupportedException e) {
99             Log.log(this,"WARNING: OpenGL support not available: " + e);
100             // FIXME: We need to fallback to Quartz2D
101             throw new Error("No OpenGL support");
102         }
103         natInit();
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.log(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         RawData rawEventHandlerUPP;
139         int modifiers;
140          
141         private native void natSetInvisible(boolean i);
142         public void setInvisible(final boolean i) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetInvisible(i); } }); }
143         private native void nat_setMaximized(boolean b);
144         public void _setMaximized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMaximized(b); } }); }
145         private native void nat_setMinimized(boolean b);
146         public void _setMinimized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMinimized(b); } }); }
147         private native void natSetIcon(Picture p);
148         public void setIcon(final Picture p) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetIcon(p); } }); }
149         private native void natSetTitleBarText(String s);
150         public void setTitleBarText(final String s) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetTitleBarText(s); } }); }
151         private native void natSetSize(int w, int h);
152         public void setSize(final int w, final int h) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetSize(w,h); } }); }
153         private native void natSetLocation(int x, int y);
154         public void setLocation(final int x, final int y) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLocation(x,y); } }); }
155         private native void natToFront();
156         public void toFront() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToFront(); } }); }
157         private native void natToBack();
158         public void toBack() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToBack(); } }); }
159         private native void natSetLimits(int minWidth, int minHeight, int maxWidth, int maxHeight);
160         public void setLimits(final int mnw, final int mnh, final int mxw, final int mxh) {
161             if(Darwin.singleton.jaguar)
162                 CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLimits(mnw,mnh,mxw,mxh); } });
163         }
164         private native void natSyncCursor(int n);
165         public void syncCursor() {
166             int n;
167             if(cursor.equals("default")) n = 0;
168             else if(cursor.equals("wait")) n = 1;
169             else if(cursor.equals("crosshair")) n = 2;
170             else if(cursor.equals("text")) n = 3;
171             else if(cursor.equals("hand")) n = 4;
172             else if(cursor.equals("move")) n = 5;
173             else if(cursor.equals("east") || cursor.equals("west")) n = 6;
174             else n = 0; 
175             final int n_ = n;
176             CarbonMessage.add(new CarbonMessage() { public void perform() { natSyncCursor(n_); } });
177         }
178
179         public void _sizeChange(int w, int h) { SizeChange(w,h); }
180         
181         /* Drawing stuff */
182         public abstract void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
183
184         public final void _dispose() { CarbonMessage.add(new CarbonMessage() { public void perform() { natDispose(); } }); }
185         public native void natDispose();
186         
187         public final native void natInit(boolean framed);
188         
189         public CarbonSurface(Box root, final boolean framed) {
190             super(root);
191             final Semaphore sem = new Semaphore();
192             CarbonMessage.add(new CarbonMessage() { public void perform() { CarbonSurface.this.natInit(framed); sem.release(); } });
193             sem.block();
194         }
195         
196         public void reshape(int w, int h) { }
197     }
198     
199     static class GLCarbonPixelBuffer extends OpenGL.GLDoubleBuffer {
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 activateContext();
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 sizeChange;
233         
234         private final native void natInit();
235         
236         public GLCarbonSurface(Box root, boolean framed, CarbonOpenGL gl) {
237             super(root,framed);
238             this.gl = gl;
239             natInit();
240         }
241         
242         public void setLimits(int mnw,int mnh, int mxw, int mxh) {
243             mxw = Math.min(mxw,gl.maxSurfaceWidth);
244             mxh = Math.min(mxh,gl.maxSurfaceHeight);
245             super.setLimits(mnw,mnh,mxw,mxh);
246         }
247         public void _sizeChange(int w, int h) {
248             sizeChange = true;
249             super._sizeChange(w,h);
250         }
251         
252         public void setSize(int w, int h) {
253             sizeChange = true;
254             w = Math.min(w,gl.maxSurfaceWidth);
255             h = Math.min(h,gl.maxSurfaceWidth);
256             super.setSize(w,h);
257         }
258         
259         private native void natBlit(GLCarbonPixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2);
260         public synchronized void blit(PixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2) {
261             natBlit((GLCarbonPixelBuffer)db,sx,sy,dx,dy,dx2,dy2);
262         }
263         
264         private native void natReshape(int w, int h);
265         public synchronized void reshape(int w, int h) { natReshape(w,h); }
266         
267         public native void natDispose();
268     }
269
270     /*private class QZCarbonPixelBuffer extends DoubleBuffer {
271         
272         public QZCarbonPixelBuffer(int width, int height) {
273         }
274     }
275        private class QZCarbonSurface extends CarbonSurface {
276         public QZCarbonSurface(Box root, boolean framed) {
277             super(b,root);
278         }
279         public native void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
280     }
281     
282     private class QZCarbonPicture extends Picture {
283         int width;
284         int height;
285         
286         public final int getWidth() { return width; }
287         public final int getHeight() { return height; }
288                 
289         public QZCarbonPicture(int w, int h) {
290             this.width = w;
291             this.height = h;
292         }
293     }*/
294     
295     protected PixelBuffer _createDoubleBuffer(int w, int h, Surface owner) {
296         if(openGL != null)
297             return new GLCarbonPixelBuffer(w,h,openGL);
298         else
299             return /*new QZCarbonPixelBuffer(w,h)*/ null;
300     }
301     protected Surface _createSurface(Box b, boolean framed) {
302         if(openGL != null)
303             return new GLCarbonSurface(b,framed, openGL);
304         else
305             return /*new QZCarbonSufrace(b,framed)*/ null;
306     }
307     protected Picture _createPicture(int[] data, int w, int h) {
308         if(openGL != null)
309             return openGL.createPicture(data,w,h);
310         else
311             return /*new QZCarbonPicture(data,w,h);*/ null;
312     }
313     
314     /* A message that is sent through the carbon event queue */
315     private static abstract class CarbonMessage {
316         public abstract void perform();
317         
318         static { natInit(); }
319         public static native void natInit();
320         public static native void add(CarbonMessage m);
321     }
322 }