2003/10/16 05:39:20
[org.ibex.core.git] / src / org / xwt / plat / Darwin.cc
index 7cbfad0..fc05588 100644 (file)
@@ -28,6 +28,7 @@
 #include <org/xwt/util/Semaphore.h>
 
 #include <stdlib.h>
+#include <pthread.h>
 
 #include "DarwinCarbonHeaders.h"
 
@@ -56,8 +57,8 @@ static void* dlsym(char* symbol) {
                                                                  NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
   if (ret == NULL) ret = NSAddressOfSymbol(NSLookupSymbolInImage(SCHandle, symbol,
                                                                  NSLOOKUPSYMBOLINIMAGE_OPTION_BIND));
-  printf("linking symbol %s to address %x\n", symbol, ret);
-  fflush(stdout);
+  /*printf("linking symbol %s to address %x\n", symbol, ret);
+  fflush(stdout);*/
   return ret;
 }
 
@@ -154,6 +155,7 @@ declare_weak(aglUpdateContext);
 declare_weak(CPSEnableForegroundOperation);
 declare_weak(CPSSetFrontProcess);
 declare_weak(kCFAllocatorDefault);
+declare_weak(NewWindowPaintUPP);
 
 #define GetWindowEventTarget WC(GetWindowEventTarget)
 #define InstallEventHandler WC(InstallEventHandler)
@@ -166,108 +168,123 @@ using java::lang::Object;
 
 namespace org { namespace xwt { namespace plat {
 
-namespace darwin { }
-using namespace darwin;
 
-#pragma mark ------ Darwin Namespace ------
+#pragma mark ----- Blit Locks ------
+static pthread_mutex_t blit_mutex;
+static pthread_cond_t blit_cond;
+
+static inline void blit_lock() { if(pthread_mutex_lock(&blit_mutex) != 0) abort(); }
+static inline void blit_unlock() { if(pthread_mutex_unlock(&blit_mutex) != 0) abort(); }
+static inline void blit_wait() { if(pthread_cond_wait(&blit_cond,&blit_mutex) != 0) abort(); }
+static inline void blit_signal() { if(pthread_cond_signal(&blit_cond) != 0) abort(); }
+
+void Darwin$CarbonSurface::blitLock() { blit_lock(); }
+void Darwin$CarbonSurface::blitUnlock() { blit_unlock(); }
+void Darwin$CarbonSurface::blitWait() { blit_wait(); }
 
-    // We put everything that isn't in org.xwt.plat.Darwin in 
-    // org.xwt.plat.darwin to prevent namespace conflicts
-    
-    template <bool CHECK> static inline int CompileTimeCheck() { const int something_is_wrong=1; something_is_wrong++; return 0; }
-    template <> static inline int CompileTimeCheck<true>() { return 0; }
-    const static int unichar_check = CompileTimeCheck<sizeof(jchar)==sizeof(UniChar)>();
-
-    void funcFailed(char *func,int r);
-    static inline void checkStatus(OSStatus r, char *func) { if(r != noErr) funcFailed(func,r); }
-    static inline void checkStatus(GLboolean b, char *func) { if(!b) funcFailed(func,-1); }
-    static inline void checkStatus(void *p, char *func) { if(!p) funcFailed(func,-1); }
-
-    jstring cfStringToJString(CFStringRef s) {
-        CFIndex length = WC(CFStringGetLength)(s);
-        CFRange range = CFRangeMake(0,length);
-        jstring js = JvAllocString(length);
-        UniChar *buf = (UniChar*)JvGetStringChars(js);
-        WC(CFStringGetCharacters)(s,range,buf);
-        return js;
-    }
-    
-    #pragma mark ------ SmartCFString ------
-    class SmartCFString {
-        private:
-            CFStringRef p;
-            void release() { if(p) WC(CFRelease)(p); }
-            void checkNull() { if(!p) throw new java::lang::Error(JvNewStringLatin1("CFString function failed")); }
-        public:
-            // Constructors
-            SmartCFString() : p(0) { }
-            SmartCFString(const char *s) : p(0) { *this = s; }
-            SmartCFString(jstring js) : p(0) { *this = js; }
-            SmartCFString(CFStringRef cf) : p(0) { *this = cf; }
-            // Destructor
-            ~SmartCFString() { release(); }
-            // Assignment
-            SmartCFString& operator= (const char *s) {
-                release();
-                if(!s) s = "(null)";
-                p = WC(CFStringCreateWithCString)(WC(kCFAllocatorDefault),s,kCFStringEncodingISOLatin1);
-                checkNull();
-                return *this;
-            }
-            SmartCFString& operator= (jstring js) {
-                if(!js) return *this = "(null)";
-                release();
-                UniChar *buf = (UniChar*) JvGetStringChars(js);
-                CFIndex length = js->length();
-                p = WC(CFStringCreateWithCharacters)(WC(kCFAllocatorDefault),buf,length);
-                checkNull();
-                return *this;
-            }
-            SmartCFString& operator= (CFStringRef cf) {
-                if(cf == NULL) return *this = "(null)";
-                release();
-                p = cf;
-                return *this;
-            }
-            operator CFStringRef() { return p; }
-            operator jstring() { return getJString(); }
-            
-            jstring getJString() { return cfStringToJString(p); }
-            
-            bool equals(const char *s) {
-                SmartCFString cfs(s);
-                return equals(cfs);
-            }
-            
-            bool equals(CFStringRef cfs) {
-                return WC(CFStringCompare)(p,cfs,0) == kCFCompareEqualTo;
-            }
-    };
-    
-    // CHECKME: Is just making up your own four char codes really correct?
-    const static UInt32 kEventClassCarbonMessage = 'xwta';
-    const static UInt32 kEventCarbonMessage = 'xwtb';
-    const static UInt32 kEventParamCarbonMessage = 'xwtc';
-    
-    OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
-    void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
 
+template <bool CHECK> static inline int CompileTimeCheck() { const int something_is_wrong=1; something_is_wrong++; return 0; }
+template <> static inline int CompileTimeCheck<true>() { return 0; }
+const static int unichar_check = CompileTimeCheck<sizeof(jchar)==sizeof(UniChar)>();
 
+static void funcFailed(const char *func,int r);
+static inline void funcFailed(const char *func) { funcFailed(func,-1); }
+
+static inline void checkStatus(OSStatus r, char *func) { if(r != noErr) funcFailed(func,r); }
+static inline void checkStatus(GLboolean b, char *func) { if(!b) funcFailed(func,-1); }
+static inline void checkStatus(void *p, char *func) { if(!p) funcFailed(func,-1); }
+
+jstring cfStringToJString(CFStringRef s) {
+    CFIndex length = WC(CFStringGetLength)(s);
+    CFRange range = CFRangeMake(0,length);
+    jstring js = JvAllocString(length);
+    UniChar *buf = (UniChar*)JvGetStringChars(js);
+    WC(CFStringGetCharacters)(s,range,buf);
+    return js;
+}
+
+#pragma mark ------ SmartCFString ------
+class SmartCFString {
+    private:
+        CFStringRef p;
+        void release() { if(p) WC(CFRelease)(p); }
+        void checkNull() { if(!p) funcFailed("CFString function"); }
+    public:
+        // Constructors
+        SmartCFString() : p(0) { }
+        SmartCFString(const char *s) : p(0) { *this = s; }
+        SmartCFString(jstring js) : p(0) { *this = js; }
+        SmartCFString(CFStringRef cf) : p(0) { *this = cf; }
+        // Destructor
+        ~SmartCFString() { release(); }
+        // Assignment
+        SmartCFString& operator= (const char *s) {
+            release();
+            if(!s) s = "(null)";
+            p = WC(CFStringCreateWithCString)(WC(kCFAllocatorDefault),s,kCFStringEncodingISOLatin1);
+            checkNull();
+            return *this;
+        }
+        SmartCFString& operator= (jstring js) {
+            if(!js) return *this = "(null)";
+            release();
+            UniChar *buf = (UniChar*) JvGetStringChars(js);
+            CFIndex length = js->length();
+            p = WC(CFStringCreateWithCharacters)(WC(kCFAllocatorDefault),buf,length);
+            checkNull();
+            return *this;
+        }
+        SmartCFString& operator= (CFStringRef cf) {
+            if(cf == NULL) return *this = "(null)";
+            release();
+            p = cf;
+            return *this;
+        }
+        operator CFStringRef() { return p; }
+        operator jstring() { return getJString(); }
+        
+        jstring getJString() { return cfStringToJString(p); }
+        
+        bool equals(const char *s) {
+            SmartCFString cfs(s);
+            return equals(cfs);
+        }
+        
+        bool equals(CFStringRef cfs) {
+            return WC(CFStringCompare)(p,cfs,0) == kCFCompareEqualTo;
+        }
+};
+
+// CHECKME: Is just making up your own four char codes really correct?
+const static UInt32 kEventClassCarbonMessage = 'xwta';
+const static UInt32 kEventCarbonMessage = 'xwtb';
+const static UInt32 kEventParamCarbonMessage = 'xwtc';
+
+static OSStatus carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
+static EventHandlerUPP carbonMessageEventHandlerUPP;
+
+static void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
+static NavEventUPP fileDialogEventHandlerUPP;
+
+static OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
+static EventHandlerUPP windowEventHandlerUPP;
+
+static OSStatus paintProc(GDHandle device,GrafPtr qdContext,WindowRef window,RgnHandle inClientPaintRgn,RgnHandle outSystemPaintRgn,void *userData);
+static WindowPaintUPP paintProcUPP;
 
 jboolean Darwin::isJaguar() {
     SInt32 version;
     OSStatus r = WC(Gestalt)(gestaltSystemVersion, &version);
-    checkStatus(r,"WC(Gestalt)");
+    checkStatus(r,"Gestalt");
     return version >= 0x1020;
 }
 
 void Darwin$CarbonMessage::natInit() {
     OSStatus r;
     
-    EventHandlerUPP upp = WC(NewEventHandlerUPP)(our_carbonMessageEventHandler);
     EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage };
-    r = InstallEventHandler(WC(GetApplicationEventTarget)(),upp,1,&eventTypes,NULL,NULL);
-    checkStatus(r,"WC(InstallEventHandler)");
+    r = InstallEventHandler(WC(GetApplicationEventTarget)(),carbonMessageEventHandlerUPP,1,&eventTypes,NULL,NULL);
+    checkStatus(r,"InstallEventHandler");
 }
 
 void Darwin$CarbonMessage::add(Darwin$CarbonMessage *msg) {
@@ -277,16 +294,16 @@ void Darwin$CarbonMessage::add(Darwin$CarbonMessage *msg) {
     GCJ$Retainer::retain(msg);
 
     r = WC(CreateEvent)(WC(kCFAllocatorDefault),kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event);
-    checkStatus(r,"WC(CreateEvent)");
+    checkStatus(r,"CreateEvent");
     r = WC(SetEventParameter)(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg);
-    checkStatus(r,"WC(SetEventParameter)");
+    checkStatus(r,"SetEventParameter");
     r = WC(PostEventToQueue)(WC(GetMainEventQueue)(),event,kEventPriorityHigh);
-    checkStatus(r,"WC(PostEventToQueue)");
+    checkStatus(r,"PostEventToQueue");
     WC(ReleaseEvent)(event);
 }
 
 
-OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+static OSStatus carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
     UInt32 eKind = WC(GetEventKind)(e);
     UInt32 eClass = WC(GetEventClass)(e);
     OSStatus r;
@@ -294,7 +311,7 @@ OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e,
     if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage)
         return eventNotHandledErr;
     r = WC(GetEventParameter)(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg);
-    checkStatus(r,"WC(GetEventParameter)");
+    checkStatus(r,"GetEventParameter");
     msg->perform();
     GCJ$Retainer::release(msg);
     return noErr;
@@ -303,7 +320,7 @@ OSStatus our_carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e,
 
 #pragma mark ------ Utility Functions ------
 
-void funcFailed(char *func,int r){
+static void funcFailed(const char *func,int r){
     fprintf(stderr,"%s() failed (%d)\n",func,r);
     exit(EXIT_FAILURE);
 } 
@@ -339,14 +356,14 @@ void Darwin$CarbonSurface::nat_setMaximized(jboolean b) {
     WindowRef window = (WindowRef) rawWindowRef;
     Point ideal = { 10000, 10000 };
     OSStatus r = WC(ZoomWindowIdeal)(window,(b?inZoomOut:inZoomIn),&ideal);
-    checkStatus(r,"WC(ZoomWindowIdeal)");
+    checkStatus(r,"ZoomWindowIdeal");
 }
 
 void Darwin$CarbonSurface::nat_setMinimized(jboolean b) {
     WindowRef window = (WindowRef) rawWindowRef;
     if((WC(IsWindowCollapsed)(window) ? 1 : 0) == (b ? 1 : 0)) return;
     OSStatus r = WC(CollapseWindow)(window,b);
-    checkStatus(r,"WC(CollapseWindow)");
+    checkStatus(r,"CollapseWindow");
 }
 
 void Darwin$CarbonSurface::natSetTitleBarText(jstring js) {
@@ -362,12 +379,11 @@ void Darwin$CarbonSurface::natToBack() {
 
 void Darwin$CarbonSurface::natToFront() {
     WindowRef window = (WindowRef) rawWindowRef;
-    fprintf(stderr,"WC(SelectWindow)()\n");
+    fprintf(stderr,"SelectWindow)()\n");
     WC(SelectWindow)(window);
 }
 
 #pragma mark ---- Window Event Handler ----
-namespace darwin {
 static const EventTypeSpec eventTypeSpecs[] = {
     // kEventClassCommand
     // { kEventClassCommand, ??? },
@@ -375,6 +391,7 @@ static const EventTypeSpec eventTypeSpecs[] = {
     // kEventClassWindow
     { kEventClassWindow, kEventWindowUpdate },
     { kEventClassWindow, kEventWindowBoundsChanged },
+    { kEventClassWindow, kEventWindowBoundsChanging },
     { kEventClassWindow, kEventWindowActivated },
     { kEventClassWindow, kEventWindowDeactivated },
     { kEventClassWindow, kEventWindowZoomed },
@@ -402,20 +419,8 @@ static const EventTypeSpec eventTypeSpecs[] = {
     { kEventClassMouse, kEventMouseWheelMoved },
 };
     
-OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+static OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
   Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*)userData;
-  if (surface == NULL) {
-    WindowRef window = 0;
-    WC(GetEventParameter) (e,
-                       kEventParamDirectObject,
-                       typeWindowRef,
-                       NULL,
-                       sizeof(window),
-                       NULL,
-                       &window);
-    UInt32 unused;
-    WC(GetWindowProperty) (window, 'XWT!', 'XWT!', sizeof(surface), &unused, &surface);
-  }
   UInt32 eKind = WC(GetEventKind)(e);
   UInt32 eClass = WC(GetEventClass)(e);
   OSStatus r;
@@ -438,7 +443,7 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                     jstring js;
                     
                     r = WC(GetEventParameter)(e,kEventParamKeyCode,typeUInt32,NULL,sizeof(keyCode),NULL,&keyCode);
-                    checkStatus(r,"WC(GetEventParameter)");
+                    checkStatus(r,"GetEventParameter");
                     
                     switch(keyCode) {
                         // These values were obtained by experimentation. I can't find any constants for them
@@ -476,13 +481,13 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                             UInt32 size;
                             UInt32 modifiers = surface->modifiers;
                             r = WC(GetEventParameter)(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,0,&size,NULL);
-                            checkStatus(r,"WC(GetEventParameter)");
+                            checkStatus(r,"GetEventParameter");
                             if(size == 0 || (modifiers & controlKey && size>sizeof(UniChar))) return eventNotHandledErr;
                             
                             js = JvAllocString(size/sizeof(UniChar));
                             UniChar *buf = (UniChar*)JvGetStringChars(js);
                             r = WC(GetEventParameter)(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,size,NULL,buf);
-                            checkStatus(r,"WC(GetEventParameter)");
+                            checkStatus(r,"GetEventParameter");
 
                             if(!buf[0]) return eventNotHandledErr; // shouldn't happen
                             // odd, when the ctrl key is pressed a-"`" become 1-31, this brings them back to the corect values
@@ -513,7 +518,7 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                     UInt32 oldModifiers = (UInt32) surface->modifiers;
                     UInt32 newModifiers;
                     r = WC(GetEventParameter)(e,kEventParamKeyModifiers,typeUInt32,NULL,sizeof(newModifiers),NULL,&newModifiers);
-                    checkStatus(r,"WC(GetEventParameter)");
+                    checkStatus(r,"GetEventParameter");
                     surface->modifiers = (jint) newModifiers;
                     UInt32 changedModifiers = oldModifiers ^ newModifiers;
                     
@@ -543,9 +548,9 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                     Rect rect;
                     
                     r = WC(GetEventParameter)(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p);
-                    checkStatus(r,"WC(GetEventParameter)");
+                    checkStatus(r,"GetEventParameter");
                     r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect);
-                    checkStatus(r,"WC(GetWindowBounds)");
+                    checkStatus(r,"GetWindowBounds");
                     surface->Move(p.h-rect.left,p.v-rect.top);
                     return noErr;
                 }
@@ -555,9 +560,9 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                     UInt32 clickCount;
                     jint xwtButton;
                     r = WC(GetEventParameter)(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button);
-                    checkStatus(r,"WC(GetEventParameter)");
+                    checkStatus(r,"GetEventParameter");
                     r = WC(GetEventParameter)(e,kEventParamClickCount,typeUInt32,NULL,sizeof(clickCount),NULL,&clickCount);
-                    checkStatus(r,"WC(GetEventParameter)");
+                    checkStatus(r,"GetEventParameter");
                     
                     switch(button) {
                         case kEventMouseButtonPrimary:   xwtButton = 1; break;
@@ -581,10 +586,10 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                     EventMouseWheelAxis axis;
                     SInt32 delta;
                     r = WC(GetEventParameter)(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis);
-                    checkStatus(r,"WC(GetEventParameter)");
+                    checkStatus(r,"GetEventParameter");
                     if(axis != kEventMouseWheelAxisY) break;
                     r = WC(GetEventParameter)(e,kEventParamMouseWheelDelta,typeSInt32,NULL,sizeof(delta),NULL,&delta);
-                    checkStatus(r,"WC(GetEventParameter)");
+                    checkStatus(r,"GetEventParameter");
                     fprintf(stderr,"kEventMouseWheelMoved: delta: %d",delta);
                     // surface->MouseWheelMoved(...) IMPROVMENT: mouse wheel support in xwt
                     return noErr;
@@ -595,33 +600,58 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
         case kEventClassWindow: {
             WindowRef window;
             r = WC(GetEventParameter)(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window);
-            checkStatus(r,"kEventClassWindow/WC(GetEventParameter)");
+            checkStatus(r,"kEventClassWindow/WC(GetEventParameter");
             
             if((RawData*)window != surface->rawWindowRef) Darwin::abort(JvNewStringLatin1("window != surface->window"));
             
             switch(eKind) {
-
-            case kEventWindowDrawFrame: {
-              return noErr;
-            }
-                case kEventWindowBoundsChanged: {
+                case kEventWindowBoundsChanging: {
                     UInt32 attr;
                     Rect rect;
+                    
                     r = WC(GetEventParameter)(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
-                    checkStatus(r,"kEventWindowBoundsChanged/WC(GetEventParameter)");
-                    r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect);
-                    checkStatus(r,"WC(GetWindowBounds)");
+                    checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
+                    
+                    r = WC(GetEventParameter)(e,kEventParamCurrentBounds,typeQDRectangle,NULL,sizeof(rect),NULL,&rect);
+                    checkStatus(r,"kEventWindowBoundsChanging/GetEventParameter"); 
+                    
                     if(attr & kWindowBoundsChangeSizeChanged) {
                         jint w = rect.right-rect.left;
                         jint h = rect.bottom-rect.top;
-                        if(attr & kWindowBoundsChangeUserResize && surface->maximized)
-                            surface->Maximized(false);
-                        surface->reshape(w,h);
+                            
+                        blit_lock();
+                        
+                        surface->winWidth = w;
+                        surface->winHeight = h;
+                        surface->pendingResize = true;
+                        surface->needsReshape();
+                            
+                        blit_unlock();
+    
                         surface->SizeChange(w,h);
+                        if(attr & kWindowBoundsChangeUserResize && surface->maximized)
+                                surface->Maximized(false);
                     }
+                    
                     if(attr & kWindowBoundsChangeOriginChanged) {
                         surface->PosChange(rect.left,rect.top);
                     }
+                    
+                    return noErr;
+                }
+                case kEventWindowBoundsChanged: {
+                    UInt32 attr;
+                    r = WC(GetEventParameter)(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
+                    checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
+                    
+                    if(attr & kWindowBoundsChangeSizeChanged) {
+                        blit_lock();
+
+                        surface->pendingResize = false;
+                        
+                        blit_signal();
+                        blit_unlock();
+                    }
                     return noErr;
                 }
                 case kEventWindowActivated:
@@ -630,7 +660,6 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                     return noErr;
                 }
                 case kEventWindowZoomed: {
-                    fprintf(stderr,"Zoomed....\n");
                     surface->Maximized(true);
                     return noErr;
                 }
@@ -647,49 +676,34 @@ OSStatus our_windowEventHandler(EventHandlerCallRef handler, EventRef e, void *u
                     return noErr;
                 }
                 case kEventWindowClosed: {
-                    WC(DisposeEventHandlerUPP)((EventHandlerUPP)surface->rawEventHandlerUPP);
                     GCJ$Retainer::release(surface);
                     return noErr;
                 }
+                case kEventWindowUpdate: {
+                    fprintf(stderr,"kEventWindowUpdate: Should not be here\n");
+                    abort();
+                }
             }
         }
         break;
     }
     return eventNotHandledErr;
 }
-} // end namespace
-
-OSStatus paint(GDHandle device,
-               GrafPtr qdContext,
-               WindowRef window,
-               RgnHandle inClientPaintRgn,
-               RgnHandle outSystemPaintRgn,
-               void * refCon) {
-  Rect r;
-  WC(GetRegionBounds)(inClientPaintRgn, &r);
-  ((Darwin$CarbonSurface*)refCon)->Dirty(r.left, r.top, r.right - r.left, r.bottom - r.top);
-  //((Darwin$CarbonSurface*)refCon)->blitDirtyScreenRegions();
-  ((Darwin$CarbonSurface*)refCon)->render_();
-  //printf("hit %d %d %d %d\n", r.left, r.top, r.right, r.bottom);
-}
-
-  long MyCustomWindowEventHandler (short code, WindowRef window, short message, long param) {
-      /*
-    switch (code)  {
-    case kEventWindowDrawFrame:
-      return noErr;
-        GetPort (&thePort);
-        GetPortBounds (thePort, &windBounds); 
-        PenNormal();
-        PenSize (10,10); 
-        FrameRect (windBounds);
-        return noErr;
-        break; 
-    }
-      */
-    return eventNotHandledErr;
-  }
 
+static OSStatus paintProc (
+   GDHandle device,
+   GrafPtr qdContext,
+   WindowRef window,
+   RgnHandle inClientPaintRgn,
+   RgnHandle outSystemPaintRgn,
+   void *userData
+) {
+    Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*) userData;
+    Rect rect;
+    WC(GetRegionBounds)(inClientPaintRgn, &rect);
+    surface->Dirty(rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top);
+    return noErr;
+}
 
 void Darwin$CarbonSurface::natInit(jboolean framed) {
     WindowRef window;
@@ -700,37 +714,24 @@ void Darwin$CarbonSurface::natInit(jboolean framed) {
     WindowAttributes attr =  kWindowStandardHandlerAttribute|
       (framed ? kWindowInWindowMenuAttribute|kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute : 0);
     OSStatus r;
-    rect.top = 0; rect.left = 0; rect.bottom = 300; rect.right=300;
-    EventHandlerUPP upp = WC(NewEventHandlerUPP)(our_windowEventHandler);
-
-    ToolboxObjectClassRef customWindow; 
-    WC(RegisterToolboxObjectClass) ( CFSTR("org.xwt.plat.Darwin.CarbonWindow"),
-                                 NULL, sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),
-                                 eventTypeSpecs,
-                                 upp, NULL, &customWindow); 
-    WindowDefSpec myCustomWindowSpec;
-    myCustomWindowSpec.defType = kWindowDefObjectClass;
-    myCustomWindowSpec.u.classRef = customWindow;
-
-    r = WC(CreateCustomWindow) (&myCustomWindowSpec,
-                                kDocumentWindowClass,
-                                kWindowStandardHandlerAttribute | kWindowStandardDocumentAttributes, 
-                                &rect,
-                                &window);
-
-    //r = CreateNewWindow(kDocumentWindowClass, attr, &rect, &window);
-    Darwin$CarbonSurface* me = this;
-    WC(SetWindowProperty) (window, 'XWT!', 'XWT!', sizeof(me), &me);
-    checkStatus(r,"WC(CreateNewWindow)");
+    rect.top = rect.left = 0;
+    rect.bottom = rect.right = 10;
+    winWidth = winHeight = 10;
+    
+    r = WC(CreateNewWindow)(wc, attr, &rect, &window);
+    checkStatus(r,"CreateNewWindow");
+
+    rawWindowRef = (RawData*) window;
 
     GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
-    r = InstallWindowEventHandler(window,upp,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
+    
+    r = InstallWindowEventHandler(window,windowEventHandlerUPP,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
     checkStatus(r,"InstallWindowEventHandler");
 
-    WC(InstallWindowContentPaintProc) (window, &paint, 0, this);
+    r = WC(InstallWindowContentPaintProc)(window,paintProcUPP,kWindowPaintProcOptionsNone,this);
+    checkStatus(r,"InstallWindowContentPaintProc");
     
-    rawWindowRef = (RawData*) window;
-    rawEventHandlerUPP = (RawData*) upp;  
+    WC(ShowWindow)(window);        
 }
 
 void Darwin$CarbonSurface::natDispose() {
@@ -747,28 +748,28 @@ void Darwin$CarbonSurface::natSetLocation() {
     jint x = root->x;
     jint y = root->y;
     OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect);
-    checkStatus(r,"WC(GetWindowBounds)");
+    checkStatus(r,"GetWindowBounds");
     rect.bottom = y + (rect.bottom - rect.top);
     rect.right = x + (rect.right - rect.left);
     rect.top = y;
     rect.left = x;
     r = WC(SetWindowBounds)(window,kWindowStructureRgn,&rect);
-    checkStatus(r,"WC(SetWindowBounds)");
+    checkStatus(r,"SetWindowBounds");
     r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
-    checkStatus(r,"WC(ConstrainWindowToScreen)");
+    checkStatus(r,"ConstrainWindowToScreen");
 }
 
 void Darwin$CarbonSurface::natSetSize(jint w, jint h) {
     WindowRef window = (WindowRef) rawWindowRef;
     Rect rect;
-    OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect);
-    checkStatus(r,"WC(GetWindowBounds)");
+    OSStatus r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect);
+    checkStatus(r,"GetWindowBounds");
     rect.bottom = rect.top + h;
     rect.right = rect.left + w;
-    r = WC(SetWindowBounds)(window,kWindowStructureRgn,&rect);
-    checkStatus(r,"WC(SetWindowBounds)");
+    r = WC(SetWindowBounds)(window,kWindowContentRgn,&rect);
+    checkStatus(r,"SetWindowBounds");
     r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
-    checkStatus(r,"WC(ConstrainWindowToScreen)");
+    checkStatus(r,"ConstrainWindowToScreen");
 }
 
 void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint maxh) {
@@ -782,7 +783,7 @@ void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint ma
     max.width  = maxw > maxMax ? maxMax : (maxw < minMinW ? minMinW : maxw);
     max.height = maxh > maxMax ? maxMax : (maxh < minMinH ? minMinH : maxh);
     OSStatus r = WC(SetWindowResizeLimits)(window,&min,&max);
-    checkStatus(r,"WC(SetWindowResizeLimits)");
+    checkStatus(r,"SetWindowResizeLimits");
 }
 
 
@@ -799,25 +800,24 @@ void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPt
             } else {
                 NavReplyRecord reply;
                 r = WC(NavDialogGetReply)(dialog,&reply);
-                checkStatus(r,"WC(NavDialogGetReply)");
+                checkStatus(r,"NavDialogGetReply");
 
                 AEKeyword keyword;
                 FSRef ref;
                 char buf[4096];
                 r = WC(AEGetNthPtr)(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
-                checkStatus(r,"WC(AEGetNthPtr)");
+                checkStatus(r,"AEGetNthPtr");
                 r = WC(FSRefMakePath)(&ref,(UInt8*)buf,sizeof(buf)-1);
-                checkStatus(r,"WC(FSRefMakePath)");
+                checkStatus(r,"FSRefMakePath");
                 helper->fileName = JvNewStringLatin1(buf);
                 if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
                 r = WC(NavDisposeReply)(&reply);
-                checkStatus(r,"WC(NavDialogGetReply)");
+                checkStatus(r,"NavDialogGetReply");
             }
             helper->sem->release();
             break;
         }
         case kNavCBTerminate:
-            WC(DisposeNavEventUPP)((NavEventUPP)helper->rawUPP);
             WC(NavDialogDispose)(dialog);
             break;
     }
@@ -830,8 +830,6 @@ void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_,
     OSStatus r;
     WindowRef window = WC(FrontWindow)();
     NavDialogCreationOptions options;
-        
-    NavEventUPP handler = WC(NewNavEventUPP)(fileDialogEventHandler);
     
     WC(NavGetDefaultDialogCreationOptions)(&options);
     options.optionFlags =
@@ -845,12 +843,11 @@ void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_,
     options.parentWindow = window;
     
     if(write)
-        r = WC(NavCreatePutFileDialog)(&options,0,0,handler,helper,&dlg);
+        r = WC(NavCreatePutFileDialog)(&options,0,0,fileDialogEventHandlerUPP,helper,&dlg);
     else
-        r = WC(NavCreateGetFileDialog)(&options,NULL,handler,NULL,NULL,helper,&dlg);
+        r = WC(NavCreateGetFileDialog)(&options,NULL,fileDialogEventHandlerUPP,NULL,NULL,helper,&dlg);
     checkStatus(r,"NavCreate(Get/Put)FileDialog");
     
-    helper->rawUPP = (RawData*)handler;
     WC(NavDialogRun)(dlg);
 }
 
@@ -860,11 +857,11 @@ jstring Darwin::natGetClipBoard() {
     Size size,size2;
 
     r = WC(GetCurrentScrap)(&scrap);
-    checkStatus(r,"WC(GetCurrentScrap)");
+    checkStatus(r,"GetCurrentScrap");
     
     r = WC(GetScrapFlavorSize)( scrap, kScrapFlavorTypeUnicode, &size);
     if(r == scrapFlavorNotFoundErr) return JvNewStringLatin1("");
-    checkStatus(r,"WC(GetScrapFlavorSize)");
+    checkStatus(r,"GetScrapFlavorSize");
     
     unsigned int length = size/sizeof(UniChar);
     
@@ -873,7 +870,7 @@ jstring Darwin::natGetClipBoard() {
     size2 = size;
     r = WC(GetScrapFlavorData)(scrap,kScrapFlavorTypeUnicode,&size2,buf);
     if(r == scrapFlavorNotFoundErr);
-    checkStatus(r,"WC(GetScrapFlavorData)");
+    checkStatus(r,"GetScrapFlavorData");
     if(size2 != size) return JvNewStringLatin1("");
     
     return js;
@@ -885,10 +882,10 @@ void Darwin::natSetClipBoard(jstring js) {
     OSStatus r;
 
     r = WC(GetCurrentScrap)(&scrap);
-    checkStatus(r,"WC(GetCurrentScrap)");
+    checkStatus(r,"GetCurrentScrap");
     
     r = WC(PutScrapFlavor)(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
-    checkStatus(r,"WC(PutScrapFlavor)");
+    checkStatus(r,"PutScrapFlavor");
 }
 
 HTTP$Proxy *Darwin::natDetectProxy() {
@@ -1019,17 +1016,26 @@ void Darwin::_newBrowserWindow(jstring js) {
 
 void Darwin::natInit() {     
     OSStatus r;
+    
+    if(pthread_mutex_init(&blit_mutex,NULL) != 0) funcFailed("pthread_mutex_init");
+    if(pthread_cond_init(&blit_cond,NULL) != 0) funcFailed("pthread_cond_init");
+    
+    carbonMessageEventHandlerUPP = WC(NewEventHandlerUPP)(carbonMessageEventHandler);
+    windowEventHandlerUPP = WC(NewEventHandlerUPP)(windowEventHandler);
+    fileDialogEventHandlerUPP = WC(NewNavEventUPP)(fileDialogEventHandler);
+    paintProcUPP = WC(NewWindowPaintUPP)(paintProc);
+
     #ifdef XWT_CARBON_NO_BUNDLE_HACK
     {        
         ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
         
         ::fprintf(stderr,"Doing XWT_CARBON_NO_BUNDLE_HACK\n");
         r = WC(GetCurrentProcess)(&currentProcess);
-        checkStatus(r,"WC(GetCurrentProcess)");
+        checkStatus(r,"GetCurrentProcess");
         r = WC(CPSEnableForegroundOperation)( &currentProcess );
-        checkStatus(r,"WC(CPSEnableForegroundOperation)");
+        checkStatus(r,"CPSEnableForegroundOperation");
         r = WC(CPSSetFrontProcess)(&currentProcess);
-        checkStatus(r,"WC(CPSSetFrontProcess)");        
+        checkStatus(r,"CPSSetFrontProcess");        
     }
     #else
     {
@@ -1040,7 +1046,7 @@ void Darwin::natInit() {
         checkStatus(r,"SetMenuBarFromNib");
         DisposeNibReference(nib);
         
-        // FIXME: Install menu event handler
+        // FEATURE: Install menu event handler
     }
     #endif
 }
@@ -1076,7 +1082,7 @@ jboolean Darwin$CarbonOpenGL::initPixelFormat() {
 void Darwin$CarbonOpenGL::initSharedContext() {
     AGLPixelFormat fmt =  (AGLPixelFormat) rawPixelFormat;
     rawSharedContext = (RawData*) WC(aglCreateContext)(fmt,NULL);
-    checkStatus(rawSharedContext,"WC(aglCreateContext)");
+    checkStatus(rawSharedContext,"aglCreateContext");
 }
 
 void Darwin$GLCarbonPixelBuffer::natInit() {
@@ -1096,15 +1102,15 @@ void Darwin$GLCarbonPixelBuffer::natInit() {
     rect.bottom = height + rect.top; 
     
     r = WC(CreateNewWindow)(wc,attr,&rect,&window);
-    checkStatus(r,"WC(CreateNewWindow)");
+    checkStatus(r,"CreateNewWindow");
         
     shared = (AGLContext) gl->rawSharedContext;
     fmt = (AGLPixelFormat) gl->rawPixelFormat;
     ctx = WC(aglCreateContext)(fmt,shared);
-    checkStatus(ctx, "WC(aglCreateContext)");
+    checkStatus(ctx, "aglCreateContext");
     
     b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
-    checkStatus(b,"WC(aglSetDrawable)");
+    checkStatus(b,"aglSetDrawable");
     
     WC(aglSetCurrentContext)(ctx);
     WC(aglUpdateContext)(ctx);
@@ -1140,15 +1146,63 @@ void Darwin$GLCarbonPixelBuffer::natCleanup(RawData* rawWindowRef, RawData* rawC
     WC(DisposeWindow)(window);
 }
 
+void Darwin$GLCarbonSurface::clear() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglSetCurrentContext)(ctx);
+    glColor4f(1.0f,1.0f,1.0f,1.0f);
+
+    glMatrixMode (GL_MODELVIEW);
+    glPushMatrix ();
+    glLoadIdentity ();
+    glMatrixMode (GL_PROJECTION);
+    glPushMatrix ();
+    glLoadIdentity ();
+    glBegin (GL_QUADS);
+    glVertex3i (-1, -1, -1);
+    glVertex3i (1, -1, -1);
+    glVertex3i (1, 1, -1);
+    glVertex3i (-1, 1, -1);
+    glEnd ();
+    glPopMatrix ();
+    glMatrixMode (GL_MODELVIEW);
+    glPopMatrix ();
+}
+
+void Darwin$GLCarbonSurface::flush() {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglSetCurrentContext)(ctx);
+    glFlush();
+}
+
+// blit_lock is assumed to be held
+void Darwin$GLCarbonSurface::reshape(jint w, jint h) {
+    AGLContext ctx = (AGLContext) rawCTX;
+    WC(aglSetCurrentContext)(ctx);
+    WC(aglUpdateContext)(ctx);
+    
+    glViewport(0,0,w,h);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity(); 
+    glOrtho(0,w,h,0,-1,1);   
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glTranslatef (0.375f, 0.375f, 0.0f);
+    checkGLError();
+}
+
+// blit_lock is assumed to be held
 void Darwin$GLCarbonSurface::natBlit(Darwin$GLCarbonPixelBuffer *db, jint sx1, jint sy1, jint dx1, jint dy1, jint dx2, jint dy2) {
     AGLContext ctx = (AGLContext) rawCTX;
     int sx2 = sx1 + (dx2-dx1);
     int sy2 = sy1 + (dy2-dy1);
+    jint w, h;
     db->activateContext();
     glFlush();
     checkGLError();
+
     WC(aglSetCurrentContext)(ctx);
     checkGLError();
+        
     if(db->rectTexture) {
         glEnable(GL_TEXTURE_RECTANGLE_EXT);
         checkGLError();
@@ -1191,23 +1245,6 @@ void Darwin$GLCarbonSurface::natBlit(Darwin$GLCarbonPixelBuffer *db, jint sx1, j
         glDisable(GL_TEXTURE_2D);
         checkGLError();
     }
-    glFlush();
-}
-
-void Darwin$GLCarbonSurface::natReshape(jint w, jint h) {
-    AGLContext ctx = (AGLContext) rawCTX;
-    
-    WC(aglSetCurrentContext) (ctx);
-    WC(aglUpdateContext)(ctx);
-    
-    glViewport(0, 0, w, h);
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity(); 
-    glOrtho(0, w, h, 0, -1, 1);   
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
-    glTranslatef (0.375, 0.375, 0.0);
-    checkGLError();
 }
 
 void Darwin$GLCarbonSurface::natInit() {
@@ -1219,20 +1256,20 @@ void Darwin$GLCarbonSurface::natInit() {
     shared = (AGLContext) gl->rawSharedContext;
     fmt = (AGLPixelFormat) gl->rawPixelFormat;
     ctx = WC(aglCreateContext)(fmt,shared);
-    checkStatus(ctx, "WC(aglCreateContext)");
+    checkStatus(ctx, "aglCreateContext");
     
     b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window));
-    checkStatus(b,"WC(aglSetDrawable)");
+    checkStatus(b,"aglSetDrawable");    
 
     WC(aglSetCurrentContext)(ctx);
-    checkGLError();
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
     
-    rawCTX = (RawData*)ctx;
+    glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
+    glClearDepth( 0.0f );
     
-    reshape(10,10);
-
-    WC(aglSetCurrentContext)(ctx);
-    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+    needsReshape();
+    
+    rawCTX = (RawData*)ctx;
 }
 
 void Darwin$GLCarbonSurface::natDispose() {