f94672931a85d86d7188413f72b965e6014b8ddf
[org.ibex.core.git] / src / org / xwt / plat / Darwin.cc
1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL]
2 // Authors: Brian Alliet and Evan Jones
3 #ifndef __APPLE_CC__
4 #define FSF_GCC
5 #define __APPLE_CC__
6 #else
7 #define APPLE_GCC
8 #endif
9
10 #define __private_extern__
11 #include <mach-o/dyld.h>
12
13 #include "POSIX.cc"
14 #include "OpenGL.cc"
15
16 #include <java/lang/Object.h>
17 #include <java/lang/Error.h>
18
19 #include <org/xwt/plat/Darwin.h>
20 #include <org/xwt/plat/Darwin$CarbonSurface.h>
21 #include <org/xwt/plat/Darwin$GLCarbonSurface.h>
22 #include <org/xwt/plat/Darwin$GLCarbonPixelBuffer.h>
23 #include <org/xwt/plat/Darwin$CarbonMessage.h>
24 #include <org/xwt/plat/Darwin$CarbonOpenGL.h>
25 #include <org/xwt/plat/Darwin$FileDialogHelper.h>
26 #include <org/xwt/plat/GCJ$Retainer.h>
27 #include <org/xwt/HTTP$Proxy.h>
28 #include <org/xwt/util/Semaphore.h>
29
30 #include <stdlib.h>
31
32 #include "DarwinCarbonHeaders.h"
33
34 #define XWT_CARBON_NO_BUNDLE_HACK
35 #ifdef XWT_CARBON_NO_BUNDLE_HACK
36 extern "C" {
37     OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn);
38     OSErr CPSSetFrontProcess(ProcessSerialNumber *psn);
39 }
40 #endif
41
42 static const mach_header* CarbonHandle = NULL;
43 static const mach_header* AGLHandle = NULL;
44 static const mach_header* SCHandle = NULL;
45 #define CARBON_LIBRARY_PATH "/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon"
46 #define AGL_LIBRARY_PATH "/System/Library/Frameworks/AGL.framework/Versions/A/AGL"
47 #define SC_LIBRARY_PATH "/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration"
48
49 static void* dlsym(char* symbol) {
50   if (CarbonHandle == NULL) CarbonHandle = NSAddImage(CARBON_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE);
51   if (AGLHandle == NULL) AGLHandle = NSAddImage(AGL_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE);
52   if (SCHandle == NULL) SCHandle = NSAddImage(SC_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE);
53   void* ret = NSAddressOfSymbol(NSLookupSymbolInImage(CarbonHandle, symbol,
54                                                       NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
55   if (ret == NULL) ret = NSAddressOfSymbol(NSLookupSymbolInImage(AGLHandle, symbol,
56                                                                  NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
57   if (ret == NULL) ret = NSAddressOfSymbol(NSLookupSymbolInImage(SCHandle, symbol,
58                                                                  NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
59   printf("linking symbol %s to address %x\n", symbol, ret);
60   fflush(stdout);
61   return ret;
62 }
63
64 #define declare_weak(symbol) typeof(symbol) *symbol##_weak = NULL
65 #define WC(func) \
66     (*((func##_weak != NULL) ? func##_weak : func##_weak = (typeof(func##_weak))dlsym("_" #func)))
67
68 declare_weak(GetRegionBounds);
69 declare_weak(RegisterToolboxObjectClass);
70 declare_weak(GetWindowProperty);
71 declare_weak(SetWindowProperty);
72 declare_weak(CreateCustomWindow);
73 declare_weak(InstallWindowContentPaintProc);
74 declare_weak(AEGetNthPtr);
75 declare_weak(CFArrayGetCount);
76 declare_weak(CFArrayGetTypeID);
77 declare_weak(CFArrayGetValueAtIndex);
78 declare_weak(CFDictionaryGetValue);
79 declare_weak(CFGetTypeID);
80 declare_weak(CFNumberGetTypeID);
81 declare_weak(CFNumberGetValue);
82 declare_weak(CFRelease);
83 declare_weak(CFStringCompare);
84 declare_weak(CFStringCreateWithCString);
85 declare_weak(CFStringCreateWithCharacters);
86 declare_weak(CFStringGetCharacters);
87 declare_weak(CFStringGetLength);
88 declare_weak(CFStringGetTypeID);
89 declare_weak(CFURLCopyScheme);
90 declare_weak(CFURLCreateWithString);
91 declare_weak(CGDisplayPixelsHigh);
92 declare_weak(CGDisplayPixelsWide);
93 declare_weak(CallNextEventHandler);
94 declare_weak(CollapseWindow);
95 declare_weak(ConstrainWindowToScreen);
96 declare_weak(CreateEvent);
97 declare_weak(CreateNewWindow);
98 declare_weak(DisposeEventHandlerUPP);
99 declare_weak(DisposeNavEventUPP);
100 declare_weak(DisposeWindow);
101 declare_weak(ExitToShell);
102 declare_weak(FSRefMakePath);
103 declare_weak(FrontWindow);
104 declare_weak(Gestalt);
105 declare_weak(GetApplicationEventTarget);
106 declare_weak(GetCurrentProcess);
107 declare_weak(GetCurrentScrap);
108 declare_weak(GetEventClass);
109 declare_weak(GetEventKind);
110 declare_weak(GetEventParameter);
111 declare_weak(GetMainEventQueue);
112 declare_weak(GetScrapFlavorData);
113 declare_weak(GetScrapFlavorSize);
114 declare_weak(GetWindowBounds);
115 declare_weak(GetWindowEventTarget);
116 declare_weak(GetWindowPort);
117 declare_weak(HideWindow);
118 declare_weak(InstallEventHandler);
119 declare_weak(IsWindowCollapsed);
120 declare_weak(LSOpenCFURLRef);
121 declare_weak(NavCreateGetFileDialog);
122 declare_weak(NavCreatePutFileDialog);
123 declare_weak(NavDialogDispose);
124 declare_weak(NavDialogGetReply);
125 declare_weak(NavDialogGetUserAction);
126 declare_weak(NavDialogRun);
127 declare_weak(NavDisposeReply);
128 declare_weak(NavGetDefaultDialogCreationOptions);
129 declare_weak(NewEventHandlerUPP);
130 declare_weak(NewNavEventUPP);
131 declare_weak(PostEventToQueue);
132 declare_weak(PutScrapFlavor);
133 declare_weak(QuitApplicationEventLoop);
134 declare_weak(ReleaseEvent);
135 declare_weak(RunApplicationEventLoop);
136 declare_weak(SCDynamicStoreCopyProxies);
137 declare_weak(SelectWindow);
138 declare_weak(SendBehind);
139 declare_weak(SetEventParameter);
140 declare_weak(SetThemeCursor);
141 declare_weak(SetWindowBounds);
142 declare_weak(SetWindowResizeLimits);
143 declare_weak(SetWindowTitleWithCFString);
144 declare_weak(ShowWindow);
145 declare_weak(ZoomWindowIdeal);
146 declare_weak(__CFStringMakeConstantString);
147 declare_weak(aglChoosePixelFormat);
148 declare_weak(aglCreateContext);
149 declare_weak(aglDestroyContext);
150 declare_weak(aglSetCurrentContext);
151 declare_weak(aglSetDrawable);
152 declare_weak(aglSurfaceTexture);
153 declare_weak(aglUpdateContext);
154 declare_weak(CPSEnableForegroundOperation);
155 declare_weak(CPSSetFrontProcess);
156 declare_weak(kCFAllocatorDefault);
157
158 #define GetWindowEventTarget WC(GetWindowEventTarget)
159 #define InstallEventHandler WC(InstallEventHandler)
160 #define __CFStringMakeConstantString WC(__CFStringMakeConstantString)
161
162 using namespace org::xwt::plat;
163 using gnu::gcj::RawData;
164 using org::xwt::util::Semaphore;
165 using java::lang::Object;
166
167 namespace org { namespace xwt { namespace plat {
168
169 namespace darwin { }
170 using namespace darwin;
171
172 #pragma mark ------ Darwin Namespace ------
173
174     // We put everything that isn't in org.xwt.plat.Darwin in 
175     // org.xwt.plat.darwin to prevent namespace conflicts
176     
177     template <bool CHECK> static inline int CompileTimeCheck() { const int something_is_wrong=1; something_is_wrong++; return 0; }
178     template <> static inline int CompileTimeCheck<true>() { return 0; }
179     const static int unichar_check = CompileTimeCheck<sizeof(jchar)==sizeof(UniChar)>();
180
181     void funcFailed(char *func,int r);
182     static inline void checkStatus(OSStatus r, char *func) { if(r != noErr) funcFailed(func,r); }
183     static inline void checkStatus(GLboolean b, char *func) { if(!b) funcFailed(func,-1); }
184     static inline void checkStatus(void *p, char *func) { if(!p) funcFailed(func,-1); }
185
186     jstring cfStringToJString(CFStringRef s) {
187         CFIndex length = WC(CFStringGetLength)(s);
188         CFRange range = CFRangeMake(0,length);
189         jstring js = JvAllocString(length);
190         UniChar *buf = (UniChar*)JvGetStringChars(js);
191         WC(CFStringGetCharacters)(s,range,buf);
192         return js;
193     }
194     
195     #pragma mark ------ SmartCFString ------
196     class SmartCFString {
197         private:
198             CFStringRef p;
199             void release() { if(p) WC(CFRelease)(p); }
200             void checkNull() { if(!p) throw new java::lang::Error(JvNewStringLatin1("CFString function failed")); }
201         public:
202             // Constructors
203             SmartCFString() : p(0) { }
204             SmartCFString(const char *s) : p(0) { *this = s; }
205             SmartCFString(jstring js) : p(0) { *this = js; }
206             SmartCFString(CFStringRef cf) : p(0) { *this = cf; }
207             // Destructor
208             ~SmartCFString() { release(); }
209             // Assignment
210             SmartCFString& operator= (const char *s) {
211                 release();
212                 if(!s) s = "(null)";
213                 p = WC(CFStringCreateWithCString)(WC(kCFAllocatorDefault),s,kCFStringEncodingISOLatin1);
214                 checkNull();
215                 return *this;
216             }
217             SmartCFString& operator= (jstring js) {
218                 if(!js) return *this = "(null)";
219                 release();
220                 UniChar *buf = (UniChar*) JvGetStringChars(js);
221                 CFIndex length = js->length();
222                 p = WC(CFStringCreateWithCharacters)(WC(kCFAllocatorDefault),buf,length);
223                 checkNull();
224                 return *this;
225             }
226             SmartCFString& operator= (CFStringRef cf) {
227                 if(cf == NULL) return *this = "(null)";
228                 release();
229                 p = cf;
230                 return *this;
231             }
232             operator CFStringRef() { return p; }
233             operator jstring() { return getJString(); }
234             
235             jstring getJString() { return cfStringToJString(p); }
236             
237             bool equals(const char *s) {
238                 SmartCFString cfs(s);
239                 return equals(cfs);
240             }
241             
242             bool equals(CFStringRef cfs) {
243                 return WC(CFStringCompare)(p,cfs,0) == kCFCompareEqualTo;
244             }
245     };
246     
247     // CHECKME: Is just making up your own four char codes really correct?
248     const static UInt32 kEventClassCarbonMessage = 'xwta';
249     const static UInt32 kEventCarbonMessage = 'xwtb';
250     const static UInt32 kEventParamCarbonMessage = 'xwtc';
251     
252     OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
253     void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
254
255
256
257 jboolean Darwin::isJaguar() {
258     SInt32 version;
259     OSStatus r = WC(Gestalt)(gestaltSystemVersion, &version);
260     checkStatus(r,"WC(Gestalt)");
261     return version >= 0x1020;
262 }
263
264 void Darwin$CarbonMessage::natInit() {
265     OSStatus r;
266     
267     EventHandlerUPP upp = WC(NewEventHandlerUPP)(our_carbonMessageEventHandler);
268     EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage };
269     r = InstallEventHandler(WC(GetApplicationEventTarget)(),upp,1,&eventTypes,NULL,NULL);
270     checkStatus(r,"WC(InstallEventHandler)");
271 }
272
273 void Darwin$CarbonMessage::add(Darwin$CarbonMessage *msg) {
274     EventRef event;
275     OSStatus r;
276     
277     GCJ$Retainer::retain(msg);
278
279     r = WC(CreateEvent)(WC(kCFAllocatorDefault),kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event);
280     checkStatus(r,"WC(CreateEvent)");
281     r = WC(SetEventParameter)(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg);
282     checkStatus(r,"WC(SetEventParameter)");
283     r = WC(PostEventToQueue)(WC(GetMainEventQueue)(),event,kEventPriorityHigh);
284     checkStatus(r,"WC(PostEventToQueue)");
285     WC(ReleaseEvent)(event);
286 }
287
288
289 OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
290     UInt32 eKind = WC(GetEventKind)(e);
291     UInt32 eClass = WC(GetEventClass)(e);
292     OSStatus r;
293     Darwin$CarbonMessage *msg;
294     if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage)
295         return eventNotHandledErr;
296     r = WC(GetEventParameter)(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg);
297     checkStatus(r,"WC(GetEventParameter)");
298     msg->perform();
299     GCJ$Retainer::release(msg);
300     return noErr;
301 }
302
303
304 #pragma mark ------ Utility Functions ------
305
306 void funcFailed(char *func,int r){
307     fprintf(stderr,"%s() failed (%d)\n",func,r);
308     exit(EXIT_FAILURE);
309
310
311 #pragma mark ------ CarbonPicture Methods ------ 
312
313 #pragma mark ----- Carbon Surface Methods ----
314
315
316 void Darwin$CarbonSurface::natSyncCursor(jint n) {
317     ThemeCursor c;
318     // see Carbon.java for what these numbers mean
319     switch(n) {
320         case 1: c = kThemeWatchCursor;
321         case 2: c = kThemePlusCursor;
322         case 3: c = kThemeIBeamCursor;
323         case 4: c = kThemePointingHandCursor;
324         case 5: c = kThemeOpenHandCursor;
325         case 6: c = kThemeResizeLeftRightCursor;
326         default: c = kThemeArrowCursor;
327     }
328     WC(SetThemeCursor)(c);
329 }
330    
331 void Darwin$CarbonSurface::natSetInvisible(jboolean b) {
332     WindowRef window = (WindowRef) rawWindowRef;
333     fprintf(stderr,"Making window %s\n",b?"invisible":"visible");
334     if(b) WC(HideWindow)(window);
335     else WC(ShowWindow)(window);
336 }
337
338 void Darwin$CarbonSurface::nat_setMaximized(jboolean b) {
339     WindowRef window = (WindowRef) rawWindowRef;
340     Point ideal = { 10000, 10000 };
341     OSStatus r = WC(ZoomWindowIdeal)(window,(b?inZoomOut:inZoomIn),&ideal);
342     checkStatus(r,"WC(ZoomWindowIdeal)");
343 }
344
345 void Darwin$CarbonSurface::nat_setMinimized(jboolean b) {
346     WindowRef window = (WindowRef) rawWindowRef;
347     if((WC(IsWindowCollapsed)(window) ? 1 : 0) == (b ? 1 : 0)) return;
348     OSStatus r = WC(CollapseWindow)(window,b);
349     checkStatus(r,"WC(CollapseWindow)");
350 }
351
352 void Darwin$CarbonSurface::natSetTitleBarText(jstring js) {
353     SmartCFString s = js;
354     WindowRef window = (WindowRef) rawWindowRef;
355     WC(SetWindowTitleWithCFString)(window,s);
356 }
357
358 void Darwin$CarbonSurface::natToBack() {
359     WindowRef window = (WindowRef) rawWindowRef;
360     WC(SendBehind)(window,NULL);
361 }
362
363 void Darwin$CarbonSurface::natToFront() {
364     WindowRef window = (WindowRef) rawWindowRef;
365     fprintf(stderr,"WC(SelectWindow)()\n");
366     WC(SelectWindow)(window);
367 }
368
369 #pragma mark ---- Window Event Handler ----
370 namespace darwin {
371 static const EventTypeSpec eventTypeSpecs[] = {
372     // kEventClassCommand
373     // { kEventClassCommand, ??? },
374     
375     // kEventClassWindow
376     { kEventClassWindow, kEventWindowUpdate },
377     { kEventClassWindow, kEventWindowBoundsChanged },
378     { kEventClassWindow, kEventWindowActivated },
379     { kEventClassWindow, kEventWindowDeactivated },
380     { kEventClassWindow, kEventWindowZoomed },
381     { kEventClassWindow, kEventWindowCollapsed },
382     { kEventClassWindow, kEventWindowExpanded },
383     { kEventClassWindow, kEventWindowClose },
384     { kEventClassWindow, kEventWindowClosed },
385     { kEventClassWindow, kEventWindowDrawFrame },
386     { kEventClassWindow, kEventWindowDrawPart },
387
388     // kEventClassControl
389     { kEventClassControl, kEventControlApplyBackground },
390     
391     // kEventClassKeyboard
392     { kEventClassKeyboard, kEventRawKeyDown },
393     { kEventClassKeyboard, kEventRawKeyRepeat },
394     { kEventClassKeyboard, kEventRawKeyUp },
395     { kEventClassKeyboard, kEventRawKeyModifiersChanged },
396     
397     // kEventClassMouse
398     { kEventClassMouse, kEventMouseDown },
399     { kEventClassMouse, kEventMouseUp },
400     { kEventClassMouse, kEventMouseMoved },
401     { kEventClassMouse, kEventMouseDragged },
402     { kEventClassMouse, kEventMouseWheelMoved },
403 };
404     
405 OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
406   Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*)userData;
407   if (surface == NULL) {
408     WindowRef window = 0;
409     WC(GetEventParameter) (e,
410                        kEventParamDirectObject,
411                        typeWindowRef,
412                        NULL,
413                        sizeof(window),
414                        NULL,
415                        &window);
416     UInt32 unused;
417     WC(GetWindowProperty) (window, 'XWT!', 'XWT!', sizeof(surface), &unused, &surface);
418   }
419   UInt32 eKind = WC(GetEventKind)(e);
420   UInt32 eClass = WC(GetEventClass)(e);
421   OSStatus r;
422   char* ec = (char*)&eClass;
423   if (surface == NULL) return eventNotHandledErr;
424     
425
426     switch(eClass) {
427         case kEventClassCommand:
428             switch(eKind) {
429                 // TODO: handle menu items
430             }
431             break;
432         case kEventClassKeyboard:
433             switch(eKind) {
434                 case kEventRawKeyDown:
435                 case kEventRawKeyRepeat: 
436                 case kEventRawKeyUp: {
437                     UInt32 keyCode;
438                     jstring js;
439                     
440                     r = WC(GetEventParameter)(e,kEventParamKeyCode,typeUInt32,NULL,sizeof(keyCode),NULL,&keyCode);
441                     checkStatus(r,"WC(GetEventParameter)");
442                     
443                     switch(keyCode) {
444                         // These values were obtained by experimentation. I can't find any constants for them
445                         // in the header files
446                         case 126: js = JvNewStringLatin1("up"); break;
447                         case 125: js = JvNewStringLatin1("down"); break;
448                         case 124: js = JvNewStringLatin1("right"); break;
449                         case 123: js = JvNewStringLatin1("left"); break;
450                         case 122: js = JvNewStringLatin1("f1"); break;
451                         case 120: js = JvNewStringLatin1("f2"); break;
452                         case 99:  js = JvNewStringLatin1("f3"); break;
453                         case 118: js = JvNewStringLatin1("f4"); break;
454                         case 96:  js = JvNewStringLatin1("f5"); break;
455                         case 97:  js = JvNewStringLatin1("f6"); break;
456                         case 98:  js = JvNewStringLatin1("f7"); break;
457                         case 100: js = JvNewStringLatin1("f8"); break;
458                         case 101: js = JvNewStringLatin1("f9"); break;
459                         case 109: js = JvNewStringLatin1("f10"); break;
460                         case 103: js = JvNewStringLatin1("f11"); break;
461                         case 111: js = JvNewStringLatin1("f12"); break;
462                         case 105: js = JvNewStringLatin1("f13"); break;
463                         case 114: js = JvNewStringLatin1("insert"); break;
464                         case 117: js = JvNewStringLatin1("delete"); break;
465                         case 116: js = JvNewStringLatin1("page_up"); break;
466                         case 121: js = JvNewStringLatin1("page_down"); break;
467                         case 115: js = JvNewStringLatin1("home"); break;
468                         case 119: js = JvNewStringLatin1("end"); break;
469                         case 71:  js = JvNewStringLatin1("num_lock"); break;
470                         case 53:  js = JvNewStringLatin1("escape"); break;
471                         case 51:  js = JvNewStringLatin1("back_space"); break;
472                         case 36:  js = JvNewStringLatin1("enter"); break;
473                         case 48:  js = JvNewStringLatin1("tab"); break;
474                         case 76:  js = JvNewStringLatin1("enter"); break; // number pad enter
475                         default: {                            
476                             UInt32 size;
477                             UInt32 modifiers = surface->modifiers;
478                             r = WC(GetEventParameter)(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,0,&size,NULL);
479                             checkStatus(r,"WC(GetEventParameter)");
480                             if(size == 0 || (modifiers & controlKey && size>sizeof(UniChar))) return eventNotHandledErr;
481                             
482                             js = JvAllocString(size/sizeof(UniChar));
483                             UniChar *buf = (UniChar*)JvGetStringChars(js);
484                             r = WC(GetEventParameter)(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,size,NULL,buf);
485                             checkStatus(r,"WC(GetEventParameter)");
486
487                             if(!buf[0]) return eventNotHandledErr; // shouldn't happen
488                             // odd, when the ctrl key is pressed a-"`" become 1-31, this brings them back to the corect values
489                             if(modifiers & controlKey && buf[0] < 32) buf[0] += 0x60;
490                             break;
491                         }
492                     }
493                     
494                     if(eKind == kEventRawKeyUp)
495                         surface->KeyReleased(js);
496                     else
497                         surface->KeyPressed(js);
498                     return noErr;
499                 }
500                 case kEventRawKeyModifiersChanged: {
501                     const static struct {
502                         UInt32 mask;
503                         jstring xwtKey;
504                     } modifiersTable[] = {
505                         { shiftKey,  JvNewStringLatin1("shift")     },
506                         { alphaLock, JvNewStringLatin1("caps_lock") },
507                         { controlKey,  JvNewStringLatin1("control")   },
508                         { optionKey,  JvNewStringLatin1("alt")       },
509                         { kEventKeyModifierNumLockMask,  JvNewStringLatin1("num_lock")  },
510                         { 0, 0 }                    
511                     };
512                     
513                     UInt32 oldModifiers = (UInt32) surface->modifiers;
514                     UInt32 newModifiers;
515                     r = WC(GetEventParameter)(e,kEventParamKeyModifiers,typeUInt32,NULL,sizeof(newModifiers),NULL,&newModifiers);
516                     checkStatus(r,"WC(GetEventParameter)");
517                     surface->modifiers = (jint) newModifiers;
518                     UInt32 changedModifiers = oldModifiers ^ newModifiers;
519                     
520                     for(int i=0;modifiersTable[i].mask;i++) {
521                         UInt32 mask = modifiersTable[i].mask;
522                         if(!(changedModifiers & mask)) continue;
523                         if(newModifiers & mask)
524                             surface->KeyPressed(modifiersTable[i].xwtKey);
525                         else
526                             surface->KeyReleased(modifiersTable[i].xwtKey);
527                     }
528                     return noErr;
529                 }
530             }
531             break;
532         case kEventClassMouse:
533             // The default handler gets first dibs on mouse events
534             // (this catches the titlebar, resize box, etc)
535             r = WC(CallNextEventHandler)(handler, e);
536             if(r != eventNotHandledErr && eKind != kEventMouseMoved && eKind != kEventMouseDragged) return r;
537             
538             switch(eKind) {
539                 case kEventMouseMoved:
540                 case kEventMouseDragged: {
541                     WindowRef window = (WindowRef) surface->rawWindowRef;
542                     Point p;
543                     Rect rect;
544                     
545                     r = WC(GetEventParameter)(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p);
546                     checkStatus(r,"WC(GetEventParameter)");
547                     r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect);
548                     checkStatus(r,"WC(GetWindowBounds)");
549                     surface->Move(p.h-rect.left,p.v-rect.top);
550                     return noErr;
551                 }
552                 case kEventMouseDown: 
553                 case kEventMouseUp: {
554                     EventMouseButton button;
555                     UInt32 clickCount;
556                     jint xwtButton;
557                     r = WC(GetEventParameter)(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button);
558                     checkStatus(r,"WC(GetEventParameter)");
559                     r = WC(GetEventParameter)(e,kEventParamClickCount,typeUInt32,NULL,sizeof(clickCount),NULL,&clickCount);
560                     checkStatus(r,"WC(GetEventParameter)");
561                     
562                     switch(button) {
563                         case kEventMouseButtonPrimary:   xwtButton = 1; break;
564                         case kEventMouseButtonSecondary: xwtButton = 2; break;
565                         case kEventMouseButtonTertiary:  xwtButton = 3; break;
566                         default: return noErr;
567                     }
568                     if(eKind == kEventMouseDown) {
569                         surface->Press(xwtButton);
570                     } else {
571                         surface->Release(xwtButton);
572                         while(clickCount > 1) {
573                             surface->DoubleClick(xwtButton);
574                             clickCount-=2;
575                         }
576                         if(clickCount) surface->Click(xwtButton);
577                     }
578                     return noErr;
579                 }
580                 case kEventMouseWheelMoved: {
581                     EventMouseWheelAxis axis;
582                     SInt32 delta;
583                     r = WC(GetEventParameter)(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis);
584                     checkStatus(r,"WC(GetEventParameter)");
585                     if(axis != kEventMouseWheelAxisY) break;
586                     r = WC(GetEventParameter)(e,kEventParamMouseWheelDelta,typeSInt32,NULL,sizeof(delta),NULL,&delta);
587                     checkStatus(r,"WC(GetEventParameter)");
588                     fprintf(stderr,"kEventMouseWheelMoved: delta: %d",delta);
589                     // surface->MouseWheelMoved(...) IMPROVMENT: mouse wheel support in xwt
590                     return noErr;
591                 }
592             }
593             break;
594         
595         case kEventClassWindow: {
596             WindowRef window;
597             r = WC(GetEventParameter)(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window);
598             checkStatus(r,"kEventClassWindow/WC(GetEventParameter)");
599             
600             if((RawData*)window != surface->rawWindowRef) Darwin::abort(JvNewStringLatin1("window != surface->window"));
601             
602             switch(eKind) {
603
604             case kEventWindowDrawFrame: {
605               return noErr;
606             }
607                 case kEventWindowBoundsChanged: {
608                     UInt32 attr;
609                     Rect rect;
610                     r = WC(GetEventParameter)(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
611                     checkStatus(r,"kEventWindowBoundsChanged/WC(GetEventParameter)");
612                     r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect);
613                     checkStatus(r,"WC(GetWindowBounds)");
614                     if(attr & kWindowBoundsChangeSizeChanged) {
615                         jint w = rect.right-rect.left;
616                         jint h = rect.bottom-rect.top;
617                         if(attr & kWindowBoundsChangeUserResize && surface->maximized)
618                             surface->Maximized(false);
619                         surface->reshape(w,h);
620                         surface->SizeChange(w,h);
621                     }
622                     if(attr & kWindowBoundsChangeOriginChanged) {
623                         surface->PosChange(rect.left,rect.top);
624                     }
625                     return noErr;
626                 }
627                 case kEventWindowActivated:
628                 case kEventWindowDeactivated: {
629                     surface->Focused(eKind == kEventWindowActivated);
630                     return noErr;
631                 }
632                 case kEventWindowZoomed: {
633                     fprintf(stderr,"Zoomed....\n");
634                     surface->Maximized(true);
635                     return noErr;
636                 }
637                 case kEventWindowCollapsed: {
638                     surface->Minimized(true);
639                     return noErr;
640                 }
641                 case kEventWindowExpanded: {
642                     surface->Minimized(false);
643                     return noErr;
644                 }
645                 case kEventWindowClose: {
646                     surface->Close();
647                     return noErr;
648                 }
649                 case kEventWindowClosed: {
650                     WC(DisposeEventHandlerUPP)((EventHandlerUPP)surface->rawEventHandlerUPP);
651                     GCJ$Retainer::release(surface);
652                     return noErr;
653                 }
654             }
655         }
656         break;
657     }
658     return eventNotHandledErr;
659 }
660 } // end namespace
661
662 OSStatus paint(GDHandle device,
663                GrafPtr qdContext,
664                WindowRef window,
665                RgnHandle inClientPaintRgn,
666                RgnHandle outSystemPaintRgn,
667                void * refCon) {
668   Rect r;
669   WC(GetRegionBounds)(inClientPaintRgn, &r);
670   ((Darwin$CarbonSurface*)refCon)->Dirty(r.left, r.top, r.right - r.left, r.bottom - r.top);
671   ((Darwin$CarbonSurface*)refCon)->blitDirtyScreenRegions();
672   //printf("hit %d %d %d %d\n", r.left, r.top, r.right, r.bottom);
673 }
674
675   long MyCustomWindowEventHandler (short code, WindowRef window, short message, long param) {
676       /*
677     switch (code)  {
678     case kEventWindowDrawFrame:
679       return noErr;
680         GetPort (&thePort);
681         GetPortBounds (thePort, &windBounds); 
682         PenNormal();
683         PenSize (10,10); 
684         FrameRect (windBounds);
685         return noErr;
686         break; 
687     }
688       */
689     return eventNotHandledErr;
690   }
691
692
693 void Darwin$CarbonSurface::natInit(jboolean framed) {
694     WindowRef window;
695     Rect rect;
696     WindowClass wc = framed ? kDocumentWindowClass : kPlainWindowClass;
697     // FIXME: unframed windows should appear in the window menu
698     // This probably needs a hack similar to whats in Cocoa.mm
699     WindowAttributes attr =  kWindowStandardHandlerAttribute|
700       (framed ? kWindowInWindowMenuAttribute|kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute : 0);
701     OSStatus r;
702     rect.top = 0; rect.left = 0; rect.bottom = 300; rect.right=300;
703     EventHandlerUPP upp = WC(NewEventHandlerUPP)(our_windowEventHandler);
704
705     ToolboxObjectClassRef customWindow; 
706     WC(RegisterToolboxObjectClass) ( CFSTR("org.xwt.plat.Darwin.CarbonWindow"),
707                                  NULL, sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),
708                                  eventTypeSpecs,
709                                  upp, NULL, &customWindow); 
710     WindowDefSpec myCustomWindowSpec;
711     myCustomWindowSpec.defType = kWindowDefObjectClass;
712     myCustomWindowSpec.u.classRef = customWindow;
713
714     r = WC(CreateCustomWindow) (&myCustomWindowSpec,
715                                 kDocumentWindowClass,
716                                 kWindowStandardHandlerAttribute | kWindowStandardDocumentAttributes, 
717                                 &rect,
718                                 &window);
719
720     //r = CreateNewWindow(kDocumentWindowClass, attr, &rect, &window);
721     Darwin$CarbonSurface* me = this;
722     WC(SetWindowProperty) (window, 'XWT!', 'XWT!', sizeof(me), &me);
723     checkStatus(r,"WC(CreateNewWindow)");
724
725     GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
726     r = InstallWindowEventHandler(window,upp,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
727     checkStatus(r,"InstallWindowEventHandler");
728
729     WC(InstallWindowContentPaintProc) (window, &paint, 0, this);
730     
731     rawWindowRef = (RawData*) window;
732     rawEventHandlerUPP = (RawData*) upp;  
733 }
734
735 void Darwin$CarbonSurface::natDispose() {
736     WindowRef window = (WindowRef) rawWindowRef;
737     WC(DisposeWindow)(window);
738 }
739
740 void Darwin$CarbonSurface::natSetIcon(org::xwt::Picture *_p) {
741 }
742
743 void Darwin$CarbonSurface::natSetLocation() {
744     WindowRef window = (WindowRef) rawWindowRef;
745     Rect rect;
746     jint x = root->x;
747     jint y = root->y;
748     OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect);
749     checkStatus(r,"WC(GetWindowBounds)");
750     rect.bottom = y + (rect.bottom - rect.top);
751     rect.right = x + (rect.right - rect.left);
752     rect.top = y;
753     rect.left = x;
754     r = WC(SetWindowBounds)(window,kWindowStructureRgn,&rect);
755     checkStatus(r,"WC(SetWindowBounds)");
756     r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
757     checkStatus(r,"WC(ConstrainWindowToScreen)");
758 }
759
760 void Darwin$CarbonSurface::natSetSize(jint w, jint h) {
761     WindowRef window = (WindowRef) rawWindowRef;
762     Rect rect;
763     OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect);
764     checkStatus(r,"WC(GetWindowBounds)");
765     rect.bottom = rect.top + h;
766     rect.right = rect.left + w;
767     r = WC(SetWindowBounds)(window,kWindowStructureRgn,&rect);
768     checkStatus(r,"WC(SetWindowBounds)");
769     r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
770     checkStatus(r,"WC(ConstrainWindowToScreen)");
771 }
772
773 void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint maxh) {
774     WindowRef window = (WindowRef) rawWindowRef;
775     const int maxMax = 32767;
776     const int minMinW = 80;
777     const int minMinH = 20;
778     HISize min,max;
779     min.width  = minw > maxMax ? maxMax : (minw < minMinW ? minMinW : minw);
780     min.height = minh > maxMax ? maxMax : (minh < minMinH ? minMinH : minh);
781     max.width  = maxw > maxMax ? maxMax : (maxw < minMinW ? minMinW : maxw);
782     max.height = maxh > maxMax ? maxMax : (maxh < minMinH ? minMinH : maxh);
783     OSStatus r = WC(SetWindowResizeLimits)(window,&min,&max);
784     checkStatus(r,"WC(SetWindowResizeLimits)");
785 }
786
787
788 #pragma mark ------ Carbon Methods ------
789 void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) {
790     Darwin$FileDialogHelper *helper = (Darwin$FileDialogHelper*) userData;
791     NavDialogRef dialog = callBackParms->context;
792     OSStatus r;
793     switch(callBackSelector) {
794         case kNavCBUserAction: {
795             NavUserAction action = WC(NavDialogGetUserAction)(dialog);
796             if(action == kNavUserActionNone || action == kNavUserActionCancel) {
797                 helper->fileName = 0;
798             } else {
799                 NavReplyRecord reply;
800                 r = WC(NavDialogGetReply)(dialog,&reply);
801                 checkStatus(r,"WC(NavDialogGetReply)");
802
803                 AEKeyword keyword;
804                 FSRef ref;
805                 char buf[4096];
806                 r = WC(AEGetNthPtr)(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
807                 checkStatus(r,"WC(AEGetNthPtr)");
808                 r = WC(FSRefMakePath)(&ref,(UInt8*)buf,sizeof(buf)-1);
809                 checkStatus(r,"WC(FSRefMakePath)");
810                 helper->fileName = JvNewStringLatin1(buf);
811                 if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
812                 r = WC(NavDisposeReply)(&reply);
813                 checkStatus(r,"WC(NavDialogGetReply)");
814             }
815             helper->sem->release();
816             break;
817         }
818         case kNavCBTerminate:
819             WC(DisposeNavEventUPP)((NavEventUPP)helper->rawUPP);
820             WC(NavDialogDispose)(dialog);
821             break;
822     }
823 }
824
825 void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_, jboolean write) {
826     NavDialogRef dlg;
827     SmartCFString suggestion = suggestion_;
828     CFStringRef message = CFSTR("By selecting a file in this dialog you are giving this XWT application permission to access that file.");
829     OSStatus r;
830     WindowRef window = WC(FrontWindow)();
831     NavDialogCreationOptions options;
832         
833     NavEventUPP handler = WC(NewNavEventUPP)(fileDialogEventHandler);
834     
835     WC(NavGetDefaultDialogCreationOptions)(&options);
836     options.optionFlags =
837         (options.optionFlags|kNavAllFilesInPopup|kNavSelectAllReadableItem|kNavDontUseCustomFrame|kNavDontConfirmReplacement)
838         &~(kNavAllowStationery|kNavAllowMultipleFiles);
839     options.clientName = CFSTR("XWT");
840     if(write)
841         options.saveFileName  = suggestion;
842     options.message = message;
843     options.modality = window ? kWindowModalityWindowModal : kWindowModalityAppModal;
844     options.parentWindow = window;
845     
846     if(write)
847         r = WC(NavCreatePutFileDialog)(&options,0,0,handler,helper,&dlg);
848     else
849         r = WC(NavCreateGetFileDialog)(&options,NULL,handler,NULL,NULL,helper,&dlg);
850     checkStatus(r,"NavCreate(Get/Put)FileDialog");
851     
852     helper->rawUPP = (RawData*)handler;
853     WC(NavDialogRun)(dlg);
854 }
855
856 jstring Darwin::natGetClipBoard() {
857     ScrapRef scrap;
858     OSStatus r;
859     Size size,size2;
860
861     r = WC(GetCurrentScrap)(&scrap);
862     checkStatus(r,"WC(GetCurrentScrap)");
863     
864     r = WC(GetScrapFlavorSize)( scrap, kScrapFlavorTypeUnicode, &size);
865     if(r == scrapFlavorNotFoundErr) return JvNewStringLatin1("");
866     checkStatus(r,"WC(GetScrapFlavorSize)");
867     
868     unsigned int length = size/sizeof(UniChar);
869     
870     jstring js = JvAllocString(length);
871     UniChar *buf = (UniChar*) JvGetStringChars(js);
872     size2 = size;
873     r = WC(GetScrapFlavorData)(scrap,kScrapFlavorTypeUnicode,&size2,buf);
874     if(r == scrapFlavorNotFoundErr);
875     checkStatus(r,"WC(GetScrapFlavorData)");
876     if(size2 != size) return JvNewStringLatin1("");
877     
878     return js;
879 }
880
881 void Darwin::natSetClipBoard(jstring js) {
882     unsigned int length = js->length();
883     ScrapRef scrap;
884     OSStatus r;
885
886     r = WC(GetCurrentScrap)(&scrap);
887     checkStatus(r,"WC(GetCurrentScrap)");
888     
889     r = WC(PutScrapFlavor)(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
890     checkStatus(r,"WC(PutScrapFlavor)");
891 }
892
893 HTTP$Proxy *Darwin::natDetectProxy() {
894     using org::xwt::HTTP$Proxy;
895     HTTP$Proxy *p=0;
896     CFStringRef string;
897     CFNumberRef number;
898     SmartCFString smartString;
899     CFArrayRef exceptionList;
900     int i;
901     
902     CFDictionaryRef proxyInfo = WC(SCDynamicStoreCopyProxies)(NULL);
903     if(proxyInfo == NULL) return 0;
904     
905 #define doproto(proto,var) \
906     number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxies ## proto ## Enable);    \
907     if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL;                 \
908     if(number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) {                               \
909         string = (CFStringRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\
910         if(string != NULL && WC(CFGetTypeID)(string) != WC(CFStringGetTypeID)()) string = NULL;             \
911         number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Port); \
912         if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL;    \
913         if(string && number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) {        \
914             if(!p) p = new HTTP$Proxy();                                                        \
915             p->var ## ProxyHost = cfStringToJString(string);                           \
916             p->var ## ProxyPort = i;                                                   \
917         }                                                                                  \
918     }                                                                                      
919 doproto(HTTP,http)
920 doproto(HTTPS,https)
921 doproto(SOCKS,socks)
922 #undef doproto
923
924     exceptionList = (CFArrayRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxiesExceptionsList);
925     if(exceptionList != NULL && WC(CFGetTypeID)(exceptionList) != WC(CFArrayGetTypeID)()) exceptionList = NULL;
926     if(p && exceptionList && WC(CFArrayGetCount)(exceptionList)) {
927         CFIndex count = WC(CFArrayGetCount)(exceptionList);
928         p->excluded = (JArray<java::lang::String*>*)
929             JvNewObjectArray(count,&java::lang::String::class$,0);
930         for(i=0;i<count;i++) {
931             string = (CFStringRef) WC(CFArrayGetValueAtIndex)(exceptionList,i);
932             if(string != NULL && WC(CFGetTypeID)(string) != WC(CFStringGetTypeID)()) string = NULL;
933             elements(p->excluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)");
934         }
935     }
936     WC(CFRelease)(proxyInfo);
937     
938     return p;
939 /*
940     exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
941     if(p && exceptionList && [exceptionList count]) {
942         NSLog(@"excl: %@",exceptionList);
943         p->excluded = (JArray<java::lang::String*>*)
944             JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
945         for(i=0;i<[exceptionList count];i++)
946             elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
947     }
948     return p;
949     */    
950             
951 /*
952     using org::xwt::Proxy;
953     AutoARP pool;
954     Proxy *p=0;
955     NSString *host;
956     NSNumber *port;
957     NSArray *exceptionList;
958     unsigned int i;
959     NSDictionary *proxyInfo = (NSDictionary*)WC(SCDynamicStoreCopyProxies)(NULL);
960     
961     if(proxyInfo == NULL) return 0;
962     if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPEnable] boolValue]) {
963         host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPProxy];
964         port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPPort];
965         if(host && [port intValue]) {
966             if(!p) p = new Proxy();
967             p->httpProxyHost = [host jstring];
968             p->httpProxyPort = [port intValue];
969         }
970     }
971     if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSEnable] boolValue]) {
972         host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSProxy];
973         port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSPort];
974         if(host && [port intValue]) {
975             if(!p) p = new Proxy();
976             p->httpsProxyHost = [host jstring];
977             p->httpsProxyPort = [port intValue];
978         }
979     }
980     if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSEnable] boolValue]) {
981         host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSProxy];
982         port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSPort];
983         if(host && [port intValue]) {
984             if(!p) p = new Proxy();
985             p->socksProxyHost = [host jstring];
986             p->socksProxyPort = [port intValue];
987         }
988     }
989    
990     exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
991     if(p && exceptionList && [exceptionList count]) {
992         NSLog(@"excl: %@",exceptionList);
993         p->excluded = (JArray<java::lang::String*>*)
994             JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
995         for(i=0;i<[exceptionList count];i++)
996             elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
997     }
998     return p;
999 */
1000 }
1001
1002 jint Darwin::cgScreenWidth() {
1003     return WC(CGDisplayPixelsWide)(((CGDirectDisplayID)0));
1004 }
1005
1006 jint Darwin::cgScreenHeight() {
1007     return WC(CGDisplayPixelsHigh)(((CGDirectDisplayID)0));
1008 }
1009
1010 void Darwin::_newBrowserWindow(jstring js) {
1011     SmartCFString cfs = js;
1012     CFURLRef url = WC(CFURLCreateWithString)(WC(kCFAllocatorDefault),cfs,NULL);
1013     SmartCFString scheme = WC(CFURLCopyScheme)(url);
1014     if(scheme.equals(CFStringRef("http")))
1015         WC(LSOpenCFURLRef)(url,NULL);
1016     WC(CFRelease)(url);
1017 }
1018
1019 void Darwin::natInit() {     
1020     OSStatus r;
1021     #ifdef XWT_CARBON_NO_BUNDLE_HACK
1022     {        
1023         ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
1024         
1025         ::fprintf(stderr,"Doing XWT_CARBON_NO_BUNDLE_HACK\n");
1026         r = WC(GetCurrentProcess)(&currentProcess);
1027         checkStatus(r,"WC(GetCurrentProcess)");
1028         r = WC(CPSEnableForegroundOperation)( &currentProcess );
1029         checkStatus(r,"WC(CPSEnableForegroundOperation)");
1030         r = WC(CPSSetFrontProcess)(&currentProcess);
1031         checkStatus(r,"WC(CPSSetFrontProcess)");        
1032     }
1033     #else
1034     {
1035         IBNibRef nib;
1036         r = CreateNibReference(CFSTR("MainMenu"), &nib);
1037         checkStatus(r,"CreateNibReference");
1038         r = SetMenuBarFromNib(nib, CFSTR("MenuBar"));
1039         checkStatus(r,"SetMenuBarFromNib");
1040         DisposeNibReference(nib);
1041         
1042         // FIXME: Install menu event handler
1043     }
1044     #endif
1045 }
1046
1047 void Darwin::runApplicationEventLoop() {
1048     WC(RunApplicationEventLoop)();
1049     WC(ExitToShell)();
1050 }
1051
1052 #pragma mark ------ OpenGL Functions -----
1053
1054 void Darwin$CarbonOpenGL::activateSharedContext() {
1055     AGLContext ctx = (AGLContext) rawSharedContext;
1056     WC(aglSetCurrentContext)(ctx);
1057 }
1058
1059 jboolean Darwin$CarbonOpenGL::initPixelFormat() {
1060     GLint attr[] = {
1061         AGL_NO_RECOVERY,
1062         AGL_RGBA,
1063         AGL_DEPTH_SIZE, 32,
1064         AGL_RED_SIZE, 8,
1065         AGL_GREEN_SIZE, 8,
1066         AGL_RED_SIZE, 8,
1067         AGL_ALPHA_SIZE, 8,
1068         AGL_NONE
1069     };
1070     
1071     rawPixelFormat = (RawData*) WC(aglChoosePixelFormat)(NULL,0,attr);
1072     return rawPixelFormat != 0;
1073 }
1074
1075 void Darwin$CarbonOpenGL::initSharedContext() {
1076     AGLPixelFormat fmt =  (AGLPixelFormat) rawPixelFormat;
1077     rawSharedContext = (RawData*) WC(aglCreateContext)(fmt,NULL);
1078     checkStatus(rawSharedContext,"WC(aglCreateContext)");
1079 }
1080
1081 void Darwin$GLCarbonPixelBuffer::natInit() {
1082     WindowClass wc = kPlainWindowClass;
1083     WindowAttributes attr = 0;
1084     WindowRef window;
1085     Rect rect;
1086     OSStatus r;
1087     AGLContext ctx,shared;
1088     AGLPixelFormat fmt;
1089     GLboolean b;
1090     GLuint tex;
1091     GLuint target;
1092     
1093     rect.top = rect.left = 0;
1094     rect.right = width + rect.left;
1095     rect.bottom = height + rect.top; 
1096     
1097     r = WC(CreateNewWindow)(wc,attr,&rect,&window);
1098     checkStatus(r,"WC(CreateNewWindow)");
1099         
1100     shared = (AGLContext) gl->rawSharedContext;
1101     fmt = (AGLPixelFormat) gl->rawPixelFormat;
1102     ctx = WC(aglCreateContext)(fmt,shared);
1103     checkStatus(ctx, "WC(aglCreateContext)");
1104     
1105     b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
1106     checkStatus(b,"WC(aglSetDrawable)");
1107     
1108     WC(aglSetCurrentContext)(ctx);
1109     WC(aglUpdateContext)(ctx);
1110     drawableInit(width,height);
1111     glClear(GL_COLOR_BUFFER_BIT);
1112
1113     WC(aglSetCurrentContext)(shared);
1114     target = rectTexture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
1115     glEnable(target);
1116     glGenTextures(1,&tex);
1117     glBindTexture(target,tex);
1118     glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1119     glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1120     WC(aglSurfaceTexture) (shared, target, GL_RGBA, ctx);
1121     checkGLError();
1122     glDisable(target);
1123     
1124     //WC(ShowWindow)(window);
1125     textureName = (jint) tex;
1126     rawWindowRef = (RawData*) window;
1127     rawCTX = (RawData*) ctx;
1128 }
1129
1130 void Darwin$GLCarbonPixelBuffer::activateContext() {
1131     AGLContext ctx = (AGLContext) rawCTX;
1132     WC(aglSetCurrentContext)(ctx);
1133 }
1134
1135 void Darwin$GLCarbonPixelBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) {
1136     WindowRef window = (WindowRef) rawWindowRef;
1137     AGLContext ctx = (AGLContext) rawCTX;
1138     WC(aglDestroyContext)(ctx);
1139     WC(DisposeWindow)(window);
1140 }
1141
1142 void Darwin$GLCarbonSurface::natBlit(Darwin$GLCarbonPixelBuffer *db, jint sx1, jint sy1, jint dx1, jint dy1, jint dx2, jint dy2) {
1143     AGLContext ctx = (AGLContext) rawCTX;
1144     int sx2 = sx1 + (dx2-dx1);
1145     int sy2 = sy1 + (dy2-dy1);
1146     db->activateContext();
1147     glFlush();
1148     checkGLError();
1149     WC(aglSetCurrentContext)(ctx);
1150     checkGLError();
1151     if(db->rectTexture) {
1152         glEnable(GL_TEXTURE_RECTANGLE_EXT);
1153         checkGLError();
1154         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, db->textureName);
1155         checkGLError();
1156         glBegin(GL_QUADS); 
1157             glTexCoord2i (sx1, sy1   );
1158             glVertex3i   (dx1, dy1, 0);   
1159             glTexCoord2i (sx2, sy1   ); 
1160             glVertex3i   (dx2, dy1, 0);
1161             glTexCoord2i (sx2, sy2   ); 
1162             glVertex3i   (dx2, dy2, 0);
1163             glTexCoord2i (sx1, sy2   );
1164             glVertex3i   (dx1, dy2, 0);
1165         glEnd();
1166         checkGLError();
1167         glDisable(GL_TEXTURE_RECTANGLE_EXT);
1168         checkGLError();
1169     } else {
1170         float tx1,ty1,tx2,ty2; // normalized texture coords
1171         tx1 = (float) sx1 / (float) db->width;
1172         ty1 = (float) sy1 / (float) db->height;
1173         tx2 = (float) sx2 / (float) db->width;
1174         ty2 = (float) sy2 / (float) db->height;
1175
1176         glColor4f(1.0f,1.0f,1.0f,1.0f);
1177         glEnable(GL_TEXTURE_2D);
1178         glBindTexture(GL_TEXTURE_2D, db->textureName);    
1179         checkGLError();
1180         glBegin(GL_QUADS); 
1181             glTexCoord2f (tx1, ty1   );
1182             glVertex3i   (dx1, dy1, 0);
1183             glTexCoord2f (tx2, ty1   ); 
1184             glVertex3i   (dx2, dy1, 0);
1185             glTexCoord2f (tx2, ty2   ); 
1186             glVertex3i   (dx2, dy2, 0);
1187             glTexCoord2f (tx1, ty2   );
1188             glVertex3i   (dx1, dy2, 0);
1189         glEnd();
1190         glDisable(GL_TEXTURE_2D);
1191         checkGLError();
1192     }
1193     glFlush();
1194 }
1195
1196 void Darwin$GLCarbonSurface::natReshape(jint w, jint h) {
1197     AGLContext ctx = (AGLContext) rawCTX;
1198     
1199     WC(aglSetCurrentContext) (ctx);
1200     WC(aglUpdateContext)(ctx);
1201     
1202     glViewport(0, 0, w, h);
1203     glMatrixMode(GL_PROJECTION);
1204     glLoadIdentity(); 
1205     glOrtho(0, w, h, 0, -1, 1);   
1206     glMatrixMode(GL_MODELVIEW);
1207     glLoadIdentity();
1208     glTranslatef (0.375, 0.375, 0.0);
1209     checkGLError();
1210 }
1211
1212 void Darwin$GLCarbonSurface::natInit() {
1213     WindowRef window = (WindowRef) rawWindowRef;
1214     AGLContext ctx,shared;
1215     AGLPixelFormat fmt;
1216     GLboolean b;
1217     
1218     shared = (AGLContext) gl->rawSharedContext;
1219     fmt = (AGLPixelFormat) gl->rawPixelFormat;
1220     ctx = WC(aglCreateContext)(fmt,shared);
1221     checkStatus(ctx, "WC(aglCreateContext)");
1222     
1223     b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
1224     checkStatus(b,"WC(aglSetDrawable)");
1225
1226     WC(aglSetCurrentContext)(ctx);
1227     checkGLError();
1228     
1229     rawCTX = (RawData*)ctx;
1230     
1231     reshape(10,10);
1232
1233     WC(aglSetCurrentContext)(ctx);
1234     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1235 }
1236
1237 void Darwin$GLCarbonSurface::natDispose() {
1238     AGLContext ctx = (AGLContext) rawCTX;
1239     WC(aglDestroyContext)(ctx);
1240     Darwin$CarbonSurface::natDispose();
1241 }
1242
1243 } } } // end namepsace org::xwt::plat
1244
1245
1246