2003/10/16 05:39:20
[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     // Called by main thread after initialization, this is the event handler
81     protected native void runApplicationEventLoop();
82     
83     public void init() {
84         super.init();
85         jaguar = isJaguar();
86         try {
87             openGL = new CarbonOpenGL();
88             openGL.init();
89         } catch(OpenGL.NotSupportedException e) {
90             Log.log(this,"WARNING: OpenGL support not available: " + e);
91             // FEATURE: fall back to quartz 2d
92             throw new Error("No OpenGL support");
93         }
94         natInit();
95     }
96     
97     public void _running() { runApplicationEventLoop(); }
98     
99     private final class CarbonOpenGL extends OpenGL {
100         public RawData rawPixelFormat;
101         public RawData rawSharedContext;
102         public int maxAglSurfaceTexSize;
103         public int maxSurfaceWidth;
104         public int maxSurfaceHeight;
105         
106         private native boolean initPixelFormat();
107         private native void initSharedContext();
108         
109         public CarbonOpenGL() throws NotSupportedException {
110             if(!jaguar)
111                 throw new NotSupportedException("OpenGL requires Mac OS X 10.2 or greater");
112             if(!initPixelFormat())
113                 throw new NotSupportedException("Couldn't get an acceptable pixel format");
114             initSharedContext();
115         }
116         
117         public void init() throws NotSupportedException {
118             super.init();
119             maxAglSurfaceTexSize = rectangularTextures ? maxRectTexSize : maxTexSize;
120             if(renderer.startsWith("ATI Radeon 7500")) {
121                 maxAglSurfaceTexSize = Math.min(rectangularTextures ? 1600 : 1024,maxAglSurfaceTexSize);
122                 Log.log(this,"Working around Radeon 7500 bug: maxAglSurfaceTexSize: " + maxAglSurfaceTexSize);
123             }
124             maxSurfaceWidth = maxSurfaceHeight = maxAglSurfaceTexSize;
125         }
126         protected native void activateSharedContext();
127     }
128     
129     static abstract class CarbonSurface extends Surface.DoubleBufferedSurface {  
130         RawData rawWindowRef;
131         int modifiers;
132         int winWidth;
133         int winHeight;
134         
135         boolean pendingResize;
136          
137         private native void natSetInvisible(boolean i);
138         public void setInvisible(final boolean i) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetInvisible(i); } }); }
139         private native void nat_setMaximized(boolean b);
140         public void _setMaximized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMaximized(b); } }); }
141         private native void nat_setMinimized(boolean b);
142         public void _setMinimized(final boolean b) { CarbonMessage.add(new CarbonMessage() { public void perform() { nat_setMinimized(b); } }); }
143         private native void natSetIcon(Picture p);
144         public void setIcon(final Picture p) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetIcon(p); } }); }
145         private native void natSetTitleBarText(String s);
146         public void setTitleBarText(final String s) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetTitleBarText(s); } }); }
147         private native void natSetSize(int w, int h);
148         public void setSize(final int w, final int h) { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetSize(w,h); } }); }
149         private native void natSetLocation();
150         public void setLocation() { CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLocation(); } }); }
151         private native void natToFront();
152         public void toFront() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToFront(); } }); }
153         private native void natToBack();
154         public void toBack() { CarbonMessage.add(new CarbonMessage() { public void perform() { natToBack(); } }); }
155         private native void natSetLimits(int minWidth, int minHeight, int maxWidth, int maxHeight);
156         public void setLimits(final int mnw, final int mnh, final int mxw, final int mxh) {
157             if(Darwin.singleton.jaguar)
158                 CarbonMessage.add(new CarbonMessage() { public void perform() { natSetLimits(mnw,mnh,mxw,mxh); } });
159         }
160         private native void natSyncCursor(int n);
161         public void syncCursor() {
162             int n;
163             if(cursor.equals("default")) n = 0;
164             else if(cursor.equals("wait")) n = 1;
165             else if(cursor.equals("crosshair")) n = 2;
166             else if(cursor.equals("text")) n = 3;
167             else if(cursor.equals("hand")) n = 4;
168             else if(cursor.equals("move")) n = 5;
169             else if(cursor.equals("east") || cursor.equals("west")) n = 6;
170             else n = 0; 
171             final int n_ = n;
172             CarbonMessage.add(new CarbonMessage() { public void perform() { natSyncCursor(n_); } });
173         }
174        
175         /* Drawing stuff */
176         public abstract void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
177
178         public final void _dispose() { CarbonMessage.add(new CarbonMessage() { public void perform() { natDispose(); } }); }
179         public native void natDispose();
180         
181         public final native void natInit(boolean framed);
182         
183         public CarbonSurface(Box root, final boolean framed) {
184             super(root);
185             final Semaphore sem = new Semaphore();
186             CarbonMessage.add(new CarbonMessage() { public void perform() { CarbonSurface.this.natInit(framed); sem.release(); } });
187             sem.block();
188         }
189         
190         public void needsReshape() { }
191         protected static native void blitLock();
192         protected static native void blitUnlock();
193         protected static native void blitWait();
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 needsReshape;
230                 
231         private final native void natInit();
232         private final native void flush();
233         private final native void clear();
234         
235         public GLCarbonSurface(Box root, boolean framed, CarbonOpenGL gl) {
236             super(root,framed);
237             this.gl = gl;
238             natInit();
239         }
240         
241         public void setLimits(int mnw,int mnh, int mxw, int mxh) {
242             mxw = Math.min(mxw,gl.maxSurfaceWidth);
243             mxh = Math.min(mxh,gl.maxSurfaceHeight);
244             super.setLimits(mnw,mnh,mxw,mxh);
245         }
246         
247         public void setSize(int w, int h) {
248             w = Math.min(w,gl.maxSurfaceWidth);
249             h = Math.min(h,gl.maxSurfaceWidth);
250             super.setSize(w,h);
251         }
252         
253         private native void natBlit(GLCarbonPixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2);
254         public void blit(PixelBuffer db, int sx, int sy, int dx, int dy, int dx2, int dy2) {
255             natBlit((GLCarbonPixelBuffer)db,sx,sy,dx,dy,dx2,dy2);
256         }
257         
258         
259         // The blit_lock ensures the window size does not change through the entire blit operation.
260         public void render_() {
261             blitLock();
262             while(pendingResize) blitWait();
263             if(needsReshape) {
264                 needsReshape = false;
265                 
266                 reshape(winWidth,winHeight);
267                 clear();
268                 Dirty(0,0,getWidth(),getHeight());
269             }
270             super.render_();
271             flush();
272             blitUnlock();
273         }
274         
275         private native void reshape(int w, int h);
276         // blit_lock is assumed to be held
277         public void needsReshape() { needsReshape = true; }
278
279         public native void natDispose();
280     }
281
282     /*private class QZCarbonPixelBuffer extends PixelBuffer {
283         
284         public QZCarbonPixelBuffer(int width, int height) {
285         }
286     }
287        private class QZCarbonSurface extends CarbonSurface {
288         public QZCarbonSurface(Box root, boolean framed) {
289             super(b,root);
290         }
291         public native void blit(PixelBuffer s, int sx, int sy, int dx, int dy, int dx2, int dy2);
292     }
293     
294     private class QZCarbonPicture extends Picture {
295         int width;
296         int height;
297         
298         public final int getWidth() { return width; }
299         public final int getHeight() { return height; }
300                 
301         public QZCarbonPicture(int w, int h) {
302             this.width = w;
303             this.height = h;
304         }
305     }*/
306     
307     protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) {
308         if(openGL != null)
309             return new GLCarbonPixelBuffer(w,h,openGL);
310         else
311             return /*new QZCarbonPixelBuffer(w,h)*/ null;
312     }
313     protected Surface _createSurface(Box b, boolean framed) {
314         if(openGL != null)
315             return new GLCarbonSurface(b,framed, openGL);
316         else
317             return /*new QZCarbonSufrace(b,framed)*/ null;
318     }
319     protected Picture _createPicture(int[] data, int w, int h) {
320         if(openGL != null)
321             return openGL.createPicture(data,w,h);
322         else
323             return /*new QZCarbonPicture(data,w,h);*/ null;
324     }
325     protected Picture _createAlphaOnlyPicture(byte[] data, int w, int h) {
326         if(openGL != null)
327             return openGL.createAlphaOnlyPicture(data,w,h);
328         else
329             return super.createAlphaOnlyPicture(data,w,h);
330     }
331     
332     /* A message that is sent through the carbon event queue */
333     private static abstract class CarbonMessage {
334         public abstract void perform();
335         
336         static { natInit(); }
337         public static native void natInit();
338         public static native void add(CarbonMessage m);
339     }
340 }