2003/09/26 02:56:56
[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   ((Darwin$CarbonSurface*)refCon)->render_();
673   //printf("hit %d %d %d %d\n", r.left, r.top, r.right, r.bottom);
674 }
675
676   long MyCustomWindowEventHandler (short code, WindowRef window, short message, long param) {
677       /*
678     switch (code)  {
679     case kEventWindowDrawFrame:
680       return noErr;
681         GetPort (&thePort);
682         GetPortBounds (thePort, &windBounds); 
683         PenNormal();
684         PenSize (10,10); 
685         FrameRect (windBounds);
686         return noErr;
687         break; 
688     }
689       */
690     return eventNotHandledErr;
691   }
692
693
694 void Darwin$CarbonSurface::natInit(jboolean framed) {
695     WindowRef window;
696     Rect rect;
697     WindowClass wc = framed ? kDocumentWindowClass : kPlainWindowClass;
698     // FIXME: unframed windows should appear in the window menu
699     // This probably needs a hack similar to whats in Cocoa.mm
700     WindowAttributes attr =  kWindowStandardHandlerAttribute|
701       (framed ? kWindowInWindowMenuAttribute|kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute : 0);
702     OSStatus r;
703     rect.top = 0; rect.left = 0; rect.bottom = 300; rect.right=300;
704     EventHandlerUPP upp = WC(NewEventHandlerUPP)(our_windowEventHandler);
705
706     ToolboxObjectClassRef customWindow; 
707     WC(RegisterToolboxObjectClass) ( CFSTR("org.xwt.plat.Darwin.CarbonWindow"),
708                                  NULL, sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),
709                                  eventTypeSpecs,
710                                  upp, NULL, &customWindow); 
711     WindowDefSpec myCustomWindowSpec;
712     myCustomWindowSpec.defType = kWindowDefObjectClass;
713     myCustomWindowSpec.u.classRef = customWindow;
714
715     r = WC(CreateCustomWindow) (&myCustomWindowSpec,
716                                 kDocumentWindowClass,
717                                 kWindowStandardHandlerAttribute | kWindowStandardDocumentAttributes, 
718                                 &rect,
719                                 &window);
720
721     //r = CreateNewWindow(kDocumentWindowClass, attr, &rect, &window);
722     Darwin$CarbonSurface* me = this;
723     WC(SetWindowProperty) (window, 'XWT!', 'XWT!', sizeof(me), &me);
724     checkStatus(r,"WC(CreateNewWindow)");
725
726     GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
727     r = InstallWindowEventHandler(window,upp,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
728     checkStatus(r,"InstallWindowEventHandler");
729
730     WC(InstallWindowContentPaintProc) (window, &paint, 0, this);
731     
732     rawWindowRef = (RawData*) window;
733     rawEventHandlerUPP = (RawData*) upp;  
734 }
735
736 void Darwin$CarbonSurface::natDispose() {
737     WindowRef window = (WindowRef) rawWindowRef;
738     WC(DisposeWindow)(window);
739 }
740
741 void Darwin$CarbonSurface::natSetIcon(org::xwt::Picture *_p) {
742 }
743
744 void Darwin$CarbonSurface::natSetLocation() {
745     WindowRef window = (WindowRef) rawWindowRef;
746     Rect rect;
747     jint x = root->x;
748     jint y = root->y;
749     OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect);
750     checkStatus(r,"WC(GetWindowBounds)");
751     rect.bottom = y + (rect.bottom - rect.top);
752     rect.right = x + (rect.right - rect.left);
753     rect.top = y;
754     rect.left = x;
755     r = WC(SetWindowBounds)(window,kWindowStructureRgn,&rect);
756     checkStatus(r,"WC(SetWindowBounds)");
757     r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
758     checkStatus(r,"WC(ConstrainWindowToScreen)");
759 }
760
761 void Darwin$CarbonSurface::natSetSize(jint w, jint h) {
762     WindowRef window = (WindowRef) rawWindowRef;
763     Rect rect;
764     OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect);
765     checkStatus(r,"WC(GetWindowBounds)");
766     rect.bottom = rect.top + h;
767     rect.right = rect.left + w;
768     r = WC(SetWindowBounds)(window,kWindowStructureRgn,&rect);
769     checkStatus(r,"WC(SetWindowBounds)");
770     r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
771     checkStatus(r,"WC(ConstrainWindowToScreen)");
772 }
773
774 void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint maxh) {
775     WindowRef window = (WindowRef) rawWindowRef;
776     const int maxMax = 32767;
777     const int minMinW = 80;
778     const int minMinH = 20;
779     HISize min,max;
780     min.width  = minw > maxMax ? maxMax : (minw < minMinW ? minMinW : minw);
781     min.height = minh > maxMax ? maxMax : (minh < minMinH ? minMinH : minh);
782     max.width  = maxw > maxMax ? maxMax : (maxw < minMinW ? minMinW : maxw);
783     max.height = maxh > maxMax ? maxMax : (maxh < minMinH ? minMinH : maxh);
784     OSStatus r = WC(SetWindowResizeLimits)(window,&min,&max);
785     checkStatus(r,"WC(SetWindowResizeLimits)");
786 }
787
788
789 #pragma mark ------ Carbon Methods ------
790 void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) {
791     Darwin$FileDialogHelper *helper = (Darwin$FileDialogHelper*) userData;
792     NavDialogRef dialog = callBackParms->context;
793     OSStatus r;
794     switch(callBackSelector) {
795         case kNavCBUserAction: {
796             NavUserAction action = WC(NavDialogGetUserAction)(dialog);
797             if(action == kNavUserActionNone || action == kNavUserActionCancel) {
798                 helper->fileName = 0;
799             } else {
800                 NavReplyRecord reply;
801                 r = WC(NavDialogGetReply)(dialog,&reply);
802                 checkStatus(r,"WC(NavDialogGetReply)");
803
804                 AEKeyword keyword;
805                 FSRef ref;
806                 char buf[4096];
807                 r = WC(AEGetNthPtr)(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
808                 checkStatus(r,"WC(AEGetNthPtr)");
809                 r = WC(FSRefMakePath)(&ref,(UInt8*)buf,sizeof(buf)-1);
810                 checkStatus(r,"WC(FSRefMakePath)");
811                 helper->fileName = JvNewStringLatin1(buf);
812                 if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
813                 r = WC(NavDisposeReply)(&reply);
814                 checkStatus(r,"WC(NavDialogGetReply)");
815             }
816             helper->sem->release();
817             break;
818         }
819         case kNavCBTerminate:
820             WC(DisposeNavEventUPP)((NavEventUPP)helper->rawUPP);
821             WC(NavDialogDispose)(dialog);
822             break;
823     }
824 }
825
826 void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_, jboolean write) {
827     NavDialogRef dlg;
828     SmartCFString suggestion = suggestion_;
829     CFStringRef message = CFSTR("By selecting a file in this dialog you are giving this XWT application permission to access that file.");
830     OSStatus r;
831     WindowRef window = WC(FrontWindow)();
832     NavDialogCreationOptions options;
833         
834     NavEventUPP handler = WC(NewNavEventUPP)(fileDialogEventHandler);
835     
836     WC(NavGetDefaultDialogCreationOptions)(&options);
837     options.optionFlags =
838         (options.optionFlags|kNavAllFilesInPopup|kNavSelectAllReadableItem|kNavDontUseCustomFrame|kNavDontConfirmReplacement)
839         &~(kNavAllowStationery|kNavAllowMultipleFiles);
840     options.clientName = CFSTR("XWT");
841     if(write)
842         options.saveFileName  = suggestion;
843     options.message = message;
844     options.modality = window ? kWindowModalityWindowModal : kWindowModalityAppModal;
845     options.parentWindow = window;
846     
847     if(write)
848         r = WC(NavCreatePutFileDialog)(&options,0,0,handler,helper,&dlg);
849     else
850         r = WC(NavCreateGetFileDialog)(&options,NULL,handler,NULL,NULL,helper,&dlg);
851     checkStatus(r,"NavCreate(Get/Put)FileDialog");
852     
853     helper->rawUPP = (RawData*)handler;
854     WC(NavDialogRun)(dlg);
855 }
856
857 jstring Darwin::natGetClipBoard() {
858     ScrapRef scrap;
859     OSStatus r;
860     Size size,size2;
861
862     r = WC(GetCurrentScrap)(&scrap);
863     checkStatus(r,"WC(GetCurrentScrap)");
864     
865     r = WC(GetScrapFlavorSize)( scrap, kScrapFlavorTypeUnicode, &size);
866     if(r == scrapFlavorNotFoundErr) return JvNewStringLatin1("");
867     checkStatus(r,"WC(GetScrapFlavorSize)");
868     
869     unsigned int length = size/sizeof(UniChar);
870     
871     jstring js = JvAllocString(length);
872     UniChar *buf = (UniChar*) JvGetStringChars(js);
873     size2 = size;
874     r = WC(GetScrapFlavorData)(scrap,kScrapFlavorTypeUnicode,&size2,buf);
875     if(r == scrapFlavorNotFoundErr);
876     checkStatus(r,"WC(GetScrapFlavorData)");
877     if(size2 != size) return JvNewStringLatin1("");
878     
879     return js;
880 }
881
882 void Darwin::natSetClipBoard(jstring js) {
883     unsigned int length = js->length();
884     ScrapRef scrap;
885     OSStatus r;
886
887     r = WC(GetCurrentScrap)(&scrap);
888     checkStatus(r,"WC(GetCurrentScrap)");
889     
890     r = WC(PutScrapFlavor)(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
891     checkStatus(r,"WC(PutScrapFlavor)");
892 }
893
894 HTTP$Proxy *Darwin::natDetectProxy() {
895     using org::xwt::HTTP$Proxy;
896     HTTP$Proxy *p=0;
897     CFStringRef string;
898     CFNumberRef number;
899     SmartCFString smartString;
900     CFArrayRef exceptionList;
901     int i;
902     
903     CFDictionaryRef proxyInfo = WC(SCDynamicStoreCopyProxies)(NULL);
904     if(proxyInfo == NULL) return 0;
905     
906 #define doproto(proto,var) \
907     number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxies ## proto ## Enable);    \
908     if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL;                 \
909     if(number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) {                               \
910         string = (CFStringRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\
911         if(string != NULL && WC(CFGetTypeID)(string) != WC(CFStringGetTypeID)()) string = NULL;             \
912         number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Port); \
913         if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL;    \
914         if(string && number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) {        \
915             if(!p) p = new HTTP$Proxy();                                                        \
916             p->var ## ProxyHost = cfStringToJString(string);                           \
917             p->var ## ProxyPort = i;                                                   \
918         }                                                                                  \
919     }                                                                                      
920 doproto(HTTP,http)
921 doproto(HTTPS,https)
922 doproto(SOCKS,socks)
923 #undef doproto
924
925     exceptionList = (CFArrayRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxiesExceptionsList);
926     if(exceptionList != NULL && WC(CFGetTypeID)(exceptionList) != WC(CFArrayGetTypeID)()) exceptionList = NULL;
927     if(p && exceptionList && WC(CFArrayGetCount)(exceptionList)) {
928         CFIndex count = WC(CFArrayGetCount)(exceptionList);
929         p->excluded = (JArray<java::lang::String*>*)
930             JvNewObjectArray(count,&java::lang::String::class$,0);
931         for(i=0;i<count;i++) {
932             string = (CFStringRef) WC(CFArrayGetValueAtIndex)(exceptionList,i);
933             if(string != NULL && WC(CFGetTypeID)(string) != WC(CFStringGetTypeID)()) string = NULL;
934             elements(p->excluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)");
935         }
936     }
937     WC(CFRelease)(proxyInfo);
938     
939     return p;
940 /*
941     exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
942     if(p && exceptionList && [exceptionList count]) {
943         NSLog(@"excl: %@",exceptionList);
944         p->excluded = (JArray<java::lang::String*>*)
945             JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
946         for(i=0;i<[exceptionList count];i++)
947             elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
948     }
949     return p;
950     */    
951             
952 /*
953     using org::xwt::Proxy;
954     AutoARP pool;
955     Proxy *p=0;
956     NSString *host;
957     NSNumber *port;
958     NSArray *exceptionList;
959     unsigned int i;
960     NSDictionary *proxyInfo = (NSDictionary*)WC(SCDynamicStoreCopyProxies)(NULL);
961     
962     if(proxyInfo == NULL) return 0;
963     if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPEnable] boolValue]) {
964         host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPProxy];
965         port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPPort];
966         if(host && [port intValue]) {
967             if(!p) p = new Proxy();
968             p->httpProxyHost = [host jstring];
969             p->httpProxyPort = [port intValue];
970         }
971     }
972     if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSEnable] boolValue]) {
973         host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSProxy];
974         port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSPort];
975         if(host && [port intValue]) {
976             if(!p) p = new Proxy();
977             p->httpsProxyHost = [host jstring];
978             p->httpsProxyPort = [port intValue];
979         }
980     }
981     if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSEnable] boolValue]) {
982         host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSProxy];
983         port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSPort];
984         if(host && [port intValue]) {
985             if(!p) p = new Proxy();
986             p->socksProxyHost = [host jstring];
987             p->socksProxyPort = [port intValue];
988         }
989     }
990    
991     exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
992     if(p && exceptionList && [exceptionList count]) {
993         NSLog(@"excl: %@",exceptionList);
994         p->excluded = (JArray<java::lang::String*>*)
995             JvNewObjectArray([exceptionList count],&java::lang::String::class$,0);
996         for(i=0;i<[exceptionList count];i++)
997             elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring];
998     }
999     return p;
1000 */
1001 }
1002
1003 jint Darwin::cgScreenWidth() {
1004     return WC(CGDisplayPixelsWide)(((CGDirectDisplayID)0));
1005 }
1006
1007 jint Darwin::cgScreenHeight() {
1008     return WC(CGDisplayPixelsHigh)(((CGDirectDisplayID)0));
1009 }
1010
1011 void Darwin::_newBrowserWindow(jstring js) {
1012     SmartCFString cfs = js;
1013     CFURLRef url = WC(CFURLCreateWithString)(WC(kCFAllocatorDefault),cfs,NULL);
1014     SmartCFString scheme = WC(CFURLCopyScheme)(url);
1015     if(scheme.equals(CFStringRef("http")))
1016         WC(LSOpenCFURLRef)(url,NULL);
1017     WC(CFRelease)(url);
1018 }
1019
1020 void Darwin::natInit() {     
1021     OSStatus r;
1022     #ifdef XWT_CARBON_NO_BUNDLE_HACK
1023     {        
1024         ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
1025         
1026         ::fprintf(stderr,"Doing XWT_CARBON_NO_BUNDLE_HACK\n");
1027         r = WC(GetCurrentProcess)(&currentProcess);
1028         checkStatus(r,"WC(GetCurrentProcess)");
1029         r = WC(CPSEnableForegroundOperation)( &currentProcess );
1030         checkStatus(r,"WC(CPSEnableForegroundOperation)");
1031         r = WC(CPSSetFrontProcess)(&currentProcess);
1032         checkStatus(r,"WC(CPSSetFrontProcess)");        
1033     }
1034     #else
1035     {
1036         IBNibRef nib;
1037         r = CreateNibReference(CFSTR("MainMenu"), &nib);
1038         checkStatus(r,"CreateNibReference");
1039         r = SetMenuBarFromNib(nib, CFSTR("MenuBar"));
1040         checkStatus(r,"SetMenuBarFromNib");
1041         DisposeNibReference(nib);
1042         
1043         // FIXME: Install menu event handler
1044     }
1045     #endif
1046 }
1047
1048 void Darwin::runApplicationEventLoop() {
1049     WC(RunApplicationEventLoop)();
1050     WC(ExitToShell)();
1051 }
1052
1053 #pragma mark ------ OpenGL Functions -----
1054
1055 void Darwin$CarbonOpenGL::activateSharedContext() {
1056     AGLContext ctx = (AGLContext) rawSharedContext;
1057     WC(aglSetCurrentContext)(ctx);
1058 }
1059
1060 jboolean Darwin$CarbonOpenGL::initPixelFormat() {
1061     GLint attr[] = {
1062         AGL_NO_RECOVERY,
1063         AGL_RGBA,
1064         AGL_DEPTH_SIZE, 32,
1065         AGL_RED_SIZE, 8,
1066         AGL_GREEN_SIZE, 8,
1067         AGL_RED_SIZE, 8,
1068         AGL_ALPHA_SIZE, 8,
1069         AGL_NONE
1070     };
1071     
1072     rawPixelFormat = (RawData*) WC(aglChoosePixelFormat)(NULL,0,attr);
1073     return rawPixelFormat != 0;
1074 }
1075
1076 void Darwin$CarbonOpenGL::initSharedContext() {
1077     AGLPixelFormat fmt =  (AGLPixelFormat) rawPixelFormat;
1078     rawSharedContext = (RawData*) WC(aglCreateContext)(fmt,NULL);
1079     checkStatus(rawSharedContext,"WC(aglCreateContext)");
1080 }
1081
1082 void Darwin$GLCarbonPixelBuffer::natInit() {
1083     WindowClass wc = kPlainWindowClass;
1084     WindowAttributes attr = 0;
1085     WindowRef window;
1086     Rect rect;
1087     OSStatus r;
1088     AGLContext ctx,shared;
1089     AGLPixelFormat fmt;
1090     GLboolean b;
1091     GLuint tex;
1092     GLuint target;
1093     
1094     rect.top = rect.left = 0;
1095     rect.right = width + rect.left;
1096     rect.bottom = height + rect.top; 
1097     
1098     r = WC(CreateNewWindow)(wc,attr,&rect,&window);
1099     checkStatus(r,"WC(CreateNewWindow)");
1100         
1101     shared = (AGLContext) gl->rawSharedContext;
1102     fmt = (AGLPixelFormat) gl->rawPixelFormat;
1103     ctx = WC(aglCreateContext)(fmt,shared);
1104     checkStatus(ctx, "WC(aglCreateContext)");
1105     
1106     b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
1107     checkStatus(b,"WC(aglSetDrawable)");
1108     
1109     WC(aglSetCurrentContext)(ctx);
1110     WC(aglUpdateContext)(ctx);
1111     drawableInit(width,height);
1112     glClear(GL_COLOR_BUFFER_BIT);
1113
1114     WC(aglSetCurrentContext)(shared);
1115     target = rectTexture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D;
1116     glEnable(target);
1117     glGenTextures(1,&tex);
1118     glBindTexture(target,tex);
1119     glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1120     glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1121     WC(aglSurfaceTexture) (shared, target, GL_RGBA, ctx);
1122     checkGLError();
1123     glDisable(target);
1124     
1125     //WC(ShowWindow)(window);
1126     textureName = (jint) tex;
1127     rawWindowRef = (RawData*) window;
1128     rawCTX = (RawData*) ctx;
1129 }
1130
1131 void Darwin$GLCarbonPixelBuffer::activateContext() {
1132     AGLContext ctx = (AGLContext) rawCTX;
1133     WC(aglSetCurrentContext)(ctx);
1134 }
1135
1136 void Darwin$GLCarbonPixelBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) {
1137     WindowRef window = (WindowRef) rawWindowRef;
1138     AGLContext ctx = (AGLContext) rawCTX;
1139     WC(aglDestroyContext)(ctx);
1140     WC(DisposeWindow)(window);
1141 }
1142
1143 void Darwin$GLCarbonSurface::natBlit(Darwin$GLCarbonPixelBuffer *db, jint sx1, jint sy1, jint dx1, jint dy1, jint dx2, jint dy2) {
1144     AGLContext ctx = (AGLContext) rawCTX;
1145     int sx2 = sx1 + (dx2-dx1);
1146     int sy2 = sy1 + (dy2-dy1);
1147     db->activateContext();
1148     glFlush();
1149     checkGLError();
1150     WC(aglSetCurrentContext)(ctx);
1151     checkGLError();
1152     if(db->rectTexture) {
1153         glEnable(GL_TEXTURE_RECTANGLE_EXT);
1154         checkGLError();
1155         glBindTexture(GL_TEXTURE_RECTANGLE_EXT, db->textureName);
1156         checkGLError();
1157         glBegin(GL_QUADS); 
1158             glTexCoord2i (sx1, sy1   );
1159             glVertex3i   (dx1, dy1, 0);   
1160             glTexCoord2i (sx2, sy1   ); 
1161             glVertex3i   (dx2, dy1, 0);
1162             glTexCoord2i (sx2, sy2   ); 
1163             glVertex3i   (dx2, dy2, 0);
1164             glTexCoord2i (sx1, sy2   );
1165             glVertex3i   (dx1, dy2, 0);
1166         glEnd();
1167         checkGLError();
1168         glDisable(GL_TEXTURE_RECTANGLE_EXT);
1169         checkGLError();
1170     } else {
1171         float tx1,ty1,tx2,ty2; // normalized texture coords
1172         tx1 = (float) sx1 / (float) db->width;
1173         ty1 = (float) sy1 / (float) db->height;
1174         tx2 = (float) sx2 / (float) db->width;
1175         ty2 = (float) sy2 / (float) db->height;
1176
1177         glColor4f(1.0f,1.0f,1.0f,1.0f);
1178         glEnable(GL_TEXTURE_2D);
1179         glBindTexture(GL_TEXTURE_2D, db->textureName);    
1180         checkGLError();
1181         glBegin(GL_QUADS); 
1182             glTexCoord2f (tx1, ty1   );
1183             glVertex3i   (dx1, dy1, 0);
1184             glTexCoord2f (tx2, ty1   ); 
1185             glVertex3i   (dx2, dy1, 0);
1186             glTexCoord2f (tx2, ty2   ); 
1187             glVertex3i   (dx2, dy2, 0);
1188             glTexCoord2f (tx1, ty2   );
1189             glVertex3i   (dx1, dy2, 0);
1190         glEnd();
1191         glDisable(GL_TEXTURE_2D);
1192         checkGLError();
1193     }
1194     glFlush();
1195 }
1196
1197 void Darwin$GLCarbonSurface::natReshape(jint w, jint h) {
1198     AGLContext ctx = (AGLContext) rawCTX;
1199     
1200     WC(aglSetCurrentContext) (ctx);
1201     WC(aglUpdateContext)(ctx);
1202     
1203     glViewport(0, 0, w, h);
1204     glMatrixMode(GL_PROJECTION);
1205     glLoadIdentity(); 
1206     glOrtho(0, w, h, 0, -1, 1);   
1207     glMatrixMode(GL_MODELVIEW);
1208     glLoadIdentity();
1209     glTranslatef (0.375, 0.375, 0.0);
1210     checkGLError();
1211 }
1212
1213 void Darwin$GLCarbonSurface::natInit() {
1214     WindowRef window = (WindowRef) rawWindowRef;
1215     AGLContext ctx,shared;
1216     AGLPixelFormat fmt;
1217     GLboolean b;
1218     
1219     shared = (AGLContext) gl->rawSharedContext;
1220     fmt = (AGLPixelFormat) gl->rawPixelFormat;
1221     ctx = WC(aglCreateContext)(fmt,shared);
1222     checkStatus(ctx, "WC(aglCreateContext)");
1223     
1224     b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
1225     checkStatus(b,"WC(aglSetDrawable)");
1226
1227     WC(aglSetCurrentContext)(ctx);
1228     checkGLError();
1229     
1230     rawCTX = (RawData*)ctx;
1231     
1232     reshape(10,10);
1233
1234     WC(aglSetCurrentContext)(ctx);
1235     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1236 }
1237
1238 void Darwin$GLCarbonSurface::natDispose() {
1239     AGLContext ctx = (AGLContext) rawCTX;
1240     WC(aglDestroyContext)(ctx);
1241     Darwin$CarbonSurface::natDispose();
1242 }
1243
1244 } } } // end namepsace org::xwt::plat
1245
1246
1247