2003/09/24 07:33:33
[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         public RawData rawUPP;
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     // Called by main thread after initialization, this is the event handler
82     protected native void runApplicationEventLoop();
83     
84     public void init() {
85         super.init();
86         jaguar = isJaguar();
87         try {
88             openGL = new CarbonOpenGL();
89             openGL.init();
90         } catch(OpenGL.NotSupportedException e) {
91             Log.log(this,"WARNING: OpenGL support not available: " + e);
92             // FEATURE: fall back to quartz 2d
93             throw new Error("No OpenGL support");
94         }
95         natInit();
96         new Thread() {
97             public void run() {
98                 runApplicationEventLoop();
99             }
100         }.start();
101     }
102     
103     private final class CarbonOpenGL extends OpenGL {
104         public RawData rawPixelFormat;
105         public RawData rawSharedContext;
106         public int maxAglSurfaceTexSize;
107         public int maxSurfaceWidth;
108         public int maxSurfaceHeight;
109         
110         private native boolean initPixelFormat();
111         private native void initSharedContext();
112         
113         public CarbonOpenGL() throws NotSupportedException {
114             if(!jaguar)
115                 throw new NotSupportedException("OpenGL requires Mac OS X 10.2 or greater");
116             if(!initPixelFormat())
117                 throw new NotSupportedException("Couldn't get an acceptable pixel format");
118             initSharedContext();
119         }
120         
121         public void init() throws NotSupportedException {
122             super.init();
123             maxAglSurfaceTexSize = rectangularTextures ? maxRectTexSize : maxTexSize;
124             if(renderer.startsWith("ATI Radeon 7500")) {
125                 maxAglSurfaceTexSize = Math.min(rectangularTextures ? 1600 : 1024,maxAglSurfaceTexSize);
126                 Log.log(this,"Working around Radeon 7500 bug: maxAglSurfaceTexSize: " + maxAglSurfaceTexSize);
127             }
128             maxSurfaceWidth = maxSurfaceHeight = maxAglSurfaceTexSize;
129         }
130         protected native void activateSharedContext();
131     }
132     
133     static abstract class CarbonSurface extends Surface.DoubleBufferedSurface {  
134         RawData rawWindowRef;
135         RawData rawEventHandlerUPP;
136         int modifiers;
137          
138         private native void natSetInvisible(boolean i);
139         public void setInvisible(final boolean i) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetInvisible(i); } }); }
140         private native void nat_setMaximized(boolean b);
141         public void _setMaximized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMaximized(b); } }); }
142         private native void nat_setMinimized(boolean b);
143         public void _setMinimized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMinimized(b); } }); }
144         private native void natSetIcon(Picture p);
145         public void setIcon(final Picture p) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetIcon(p); } }); }
146         private native void natSetTitleBarText(String s);
147         public void setTitleBarText(final String s) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetTitleBarText(s); } }); }
148         private native void natSetSize(int w, int h);
149         public void setSize(final int w, final int h) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetSize(w,h); } }); }
150         private native void natSetLocation();
151         public void setLocation() { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLocation(); } }); }
152         private native void natToFront();
153         public void toFront() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToFront(); } }); }
154         private native void natToBack();
155         public void toBack() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToBack(); } }); }
156         private native void natSetLimits(int minWidth, int minHeight, int maxWidth, int maxHeight);
157         public void setLimits(final int mnw, final int mnh, final int mxw, final int mxh) {
158             if(Darwin.singleton.jaguar)
159                 CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLimits(mnw,mnh,mxw,mxh); } });
160         }
161         private native void natSyncCursor(int n);
162         public void syncCursor() {
163             int n;
164             if(cursor.equals("default")) n = 0;
165             else if(cursor.equals("wait")) n = 1;
166             else if(cursor.equals("crosshair")) n = 2;
167             else if(cursor.equals("text")) n = 3;
168             else if(cursor.equals("hand")) n = 4;
169             else if(cursor.equals("move")) n = 5;
170             else if(cursor.equals("east") || cursor.equals("west")) n = 6;
171             else n = 0; 
172             final int n_ = n;
173             CarbonMessage.add(new CarbonMessage() { public void perform() { natSyncCursor(n_); } });
174         }
175
176         public void _sizeChange(int w, int h) { SizeChange(w,h); }
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 reshape(int w, int h) { }
194     }
195     
196     static class GLCarbonPixelBuffer extends OpenGL.GLPixelBuffer {
197         RawData rawCTX;
198         RawData rawWindowRef;
199         int textureName;
200         boolean rectTexture;
201         CarbonOpenGL gl;
202         
203         private native void natInit();
204         private static native void natCleanup(RawData rawWindowRef, RawData rawCTX);
205         
206         
207         private static final int fixupDimension(CarbonOpenGL gl, int n) {
208             if(!gl.rectangularTextures) n = OpenGL.roundToPowerOf2(n);
209             return Math.min(n,gl.maxAglSurfaceTexSize);
210         }
211         public GLCarbonPixelBuffer(int w, int h, final CarbonOpenGL gl) {
212             super(fixupDimension(gl,w),fixupDimension(gl,h));
213             this.gl = gl;
214             rectTexture = gl.hasRectangularTextures();
215             final Semaphore sem = new Semaphore();
216             CarbonMessage.add(new CarbonMessage() { public void perform() { GLCarbonPixelBuffer.this.natInit(); sem.release(); } });
217             sem.block();
218         }
219         public native void activateContext();
220         protected void finalize() {
221             CarbonMessage.add(new CarbonMessage() { public void perform() { natCleanup(rawWindowRef,rawCTX); } });
222             gl.deleteTexture(textureName);
223         }
224     }
225     
226     static class GLCarbonSurface extends CarbonSurface {
227         RawData rawCTX;
228         CarbonOpenGL gl;
229         boolean sizeChange;
230         
231         private final native void natInit();
232         
233         public GLCarbonSurface(Box root, boolean framed, CarbonOpenGL gl) {
234             super(root,framed);
235             this.gl = gl;
236             natInit();
237         }
238         
239         public void setLimits(int mnw,int mnh, int mxw, int mxh) {
240             mxw = Math.min(mxw,gl.maxSurfaceWidth);
241             mxh = Math.min(mxh,gl.maxSurfaceHeight);
242             super.setLimits(mnw,mnh,mxw,mxh);
243         }
244         public void _sizeChange(int w, int h) {
245             sizeChange = true;
246             super._sizeChange(w,h);
247         }
248         
249         public void setSize(int w, int h) {
250             sizeChange = true;
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 synchronized 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         private native void natReshape(int w, int h);
262         public synchronized void reshape(int w, int h) { natReshape(w,h); }
263         
264         public native void natDispose();
265     }
266
267     /*private class QZCarbonPixelBuffer extends PixelBuffer {
268         
269         public QZCarbonPixelBuffer(int width, int height) {
270         }
271     }
272        private class QZCarbonSurface extends CarbonSurface {
273         public QZCarbonSurface(Box root, boolean framed) {
274             super(b,root);
275         }
276         public native void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
277     }
278     
279     private class QZCarbonPicture extends Picture {
280         int width;
281         int height;
282         
283         public final int getWidth() { return width; }
284         public final int getHeight() { return height; }
285                 
286         public QZCarbonPicture(int w, int h) {
287             this.width = w;
288             this.height = h;
289         }
290     }*/
291     
292     protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) {
293         if(openGL != null)
294             return new GLCarbonPixelBuffer(w,h,openGL);
295         else
296             return /*new QZCarbonPixelBuffer(w,h)*/ null;
297     }
298     protected Surface _createSurface(Box b, boolean framed) {
299         if(openGL != null)
300             return new GLCarbonSurface(b,framed, openGL);
301         else
302             return /*new QZCarbonSufrace(b,framed)*/ null;
303     }
304     protected Picture _createPicture(int[] data, int w, int h) {
305         if(openGL != null)
306             return openGL.createPicture(data,w,h);
307         else
308             return /*new QZCarbonPicture(data,w,h);*/ null;
309     }
310     
311     /* A message that is sent through the carbon event queue */
312     private static abstract class CarbonMessage {
313         public abstract void perform();
314         
315         static { natInit(); }
316         public static native void natInit();
317         public static native void add(CarbonMessage m);
318     }
319 }