X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fplat%2FDarwin.cc;h=fc05588ccfa8b8325e77a1dc9f8efa2000fa0559;hb=745fb6aad79e10eb8c402b8fa6a591769c0fcdfb;hp=824aa5645825d589d497f73aa18be530164d6f7a;hpb=99ed0a0824a0bd20bea291d3950b921957388e0b;p=org.ibex.core.git diff --git a/src/org/xwt/plat/Darwin.cc b/src/org/xwt/plat/Darwin.cc index 824aa56..fc05588 100644 --- a/src/org/xwt/plat/Darwin.cc +++ b/src/org/xwt/plat/Darwin.cc @@ -1,2 +1,1284 @@ -#include -#include "X11.cc" +// Copyright 2003 Adam Megacz, see the COPYING file for licensing [LGPL] +// Authors: Brian Alliet and Evan Jones +#ifndef __APPLE_CC__ +#define FSF_GCC +#define __APPLE_CC__ +#else +#define APPLE_GCC +#endif + +#define __private_extern__ +#include + +#include "POSIX.cc" +#include "OpenGL.cc" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "DarwinCarbonHeaders.h" + +#define XWT_CARBON_NO_BUNDLE_HACK +#ifdef XWT_CARBON_NO_BUNDLE_HACK +extern "C" { + OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn); + OSErr CPSSetFrontProcess(ProcessSerialNumber *psn); +} +#endif + +static const mach_header* CarbonHandle = NULL; +static const mach_header* AGLHandle = NULL; +static const mach_header* SCHandle = NULL; +#define CARBON_LIBRARY_PATH "/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon" +#define AGL_LIBRARY_PATH "/System/Library/Frameworks/AGL.framework/Versions/A/AGL" +#define SC_LIBRARY_PATH "/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration" + +static void* dlsym(char* symbol) { + if (CarbonHandle == NULL) CarbonHandle = NSAddImage(CARBON_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE); + if (AGLHandle == NULL) AGLHandle = NSAddImage(AGL_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE); + if (SCHandle == NULL) SCHandle = NSAddImage(SC_LIBRARY_PATH, NSADDIMAGE_OPTION_NONE); + void* ret = NSAddressOfSymbol(NSLookupSymbolInImage(CarbonHandle, symbol, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND)); + if (ret == NULL) ret = NSAddressOfSymbol(NSLookupSymbolInImage(AGLHandle, 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);*/ + return ret; +} + +#define declare_weak(symbol) typeof(symbol) *symbol##_weak = NULL +#define WC(func) \ + (*((func##_weak != NULL) ? func##_weak : func##_weak = (typeof(func##_weak))dlsym("_" #func))) + +declare_weak(GetRegionBounds); +declare_weak(RegisterToolboxObjectClass); +declare_weak(GetWindowProperty); +declare_weak(SetWindowProperty); +declare_weak(CreateCustomWindow); +declare_weak(InstallWindowContentPaintProc); +declare_weak(AEGetNthPtr); +declare_weak(CFArrayGetCount); +declare_weak(CFArrayGetTypeID); +declare_weak(CFArrayGetValueAtIndex); +declare_weak(CFDictionaryGetValue); +declare_weak(CFGetTypeID); +declare_weak(CFNumberGetTypeID); +declare_weak(CFNumberGetValue); +declare_weak(CFRelease); +declare_weak(CFStringCompare); +declare_weak(CFStringCreateWithCString); +declare_weak(CFStringCreateWithCharacters); +declare_weak(CFStringGetCharacters); +declare_weak(CFStringGetLength); +declare_weak(CFStringGetTypeID); +declare_weak(CFURLCopyScheme); +declare_weak(CFURLCreateWithString); +declare_weak(CGDisplayPixelsHigh); +declare_weak(CGDisplayPixelsWide); +declare_weak(CallNextEventHandler); +declare_weak(CollapseWindow); +declare_weak(ConstrainWindowToScreen); +declare_weak(CreateEvent); +declare_weak(CreateNewWindow); +declare_weak(DisposeEventHandlerUPP); +declare_weak(DisposeNavEventUPP); +declare_weak(DisposeWindow); +declare_weak(ExitToShell); +declare_weak(FSRefMakePath); +declare_weak(FrontWindow); +declare_weak(Gestalt); +declare_weak(GetApplicationEventTarget); +declare_weak(GetCurrentProcess); +declare_weak(GetCurrentScrap); +declare_weak(GetEventClass); +declare_weak(GetEventKind); +declare_weak(GetEventParameter); +declare_weak(GetMainEventQueue); +declare_weak(GetScrapFlavorData); +declare_weak(GetScrapFlavorSize); +declare_weak(GetWindowBounds); +declare_weak(GetWindowEventTarget); +declare_weak(GetWindowPort); +declare_weak(HideWindow); +declare_weak(InstallEventHandler); +declare_weak(IsWindowCollapsed); +declare_weak(LSOpenCFURLRef); +declare_weak(NavCreateGetFileDialog); +declare_weak(NavCreatePutFileDialog); +declare_weak(NavDialogDispose); +declare_weak(NavDialogGetReply); +declare_weak(NavDialogGetUserAction); +declare_weak(NavDialogRun); +declare_weak(NavDisposeReply); +declare_weak(NavGetDefaultDialogCreationOptions); +declare_weak(NewEventHandlerUPP); +declare_weak(NewNavEventUPP); +declare_weak(PostEventToQueue); +declare_weak(PutScrapFlavor); +declare_weak(QuitApplicationEventLoop); +declare_weak(ReleaseEvent); +declare_weak(RunApplicationEventLoop); +declare_weak(SCDynamicStoreCopyProxies); +declare_weak(SelectWindow); +declare_weak(SendBehind); +declare_weak(SetEventParameter); +declare_weak(SetThemeCursor); +declare_weak(SetWindowBounds); +declare_weak(SetWindowResizeLimits); +declare_weak(SetWindowTitleWithCFString); +declare_weak(ShowWindow); +declare_weak(ZoomWindowIdeal); +declare_weak(__CFStringMakeConstantString); +declare_weak(aglChoosePixelFormat); +declare_weak(aglCreateContext); +declare_weak(aglDestroyContext); +declare_weak(aglSetCurrentContext); +declare_weak(aglSetDrawable); +declare_weak(aglSurfaceTexture); +declare_weak(aglUpdateContext); +declare_weak(CPSEnableForegroundOperation); +declare_weak(CPSSetFrontProcess); +declare_weak(kCFAllocatorDefault); +declare_weak(NewWindowPaintUPP); + +#define GetWindowEventTarget WC(GetWindowEventTarget) +#define InstallEventHandler WC(InstallEventHandler) +#define __CFStringMakeConstantString WC(__CFStringMakeConstantString) + +using namespace org::xwt::plat; +using gnu::gcj::RawData; +using org::xwt::util::Semaphore; +using java::lang::Object; + +namespace org { namespace xwt { namespace plat { + + +#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(); } + + +template static inline int CompileTimeCheck() { const int something_is_wrong=1; something_is_wrong++; return 0; } +template <> static inline int CompileTimeCheck() { return 0; } +const static int unichar_check = CompileTimeCheck(); + +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,"Gestalt"); + return version >= 0x1020; +} + +void Darwin$CarbonMessage::natInit() { + OSStatus r; + + EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage }; + r = InstallEventHandler(WC(GetApplicationEventTarget)(),carbonMessageEventHandlerUPP,1,&eventTypes,NULL,NULL); + checkStatus(r,"InstallEventHandler"); +} + +void Darwin$CarbonMessage::add(Darwin$CarbonMessage *msg) { + EventRef event; + OSStatus r; + + GCJ$Retainer::retain(msg); + + r = WC(CreateEvent)(WC(kCFAllocatorDefault),kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event); + checkStatus(r,"CreateEvent"); + r = WC(SetEventParameter)(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg); + checkStatus(r,"SetEventParameter"); + r = WC(PostEventToQueue)(WC(GetMainEventQueue)(),event,kEventPriorityHigh); + checkStatus(r,"PostEventToQueue"); + WC(ReleaseEvent)(event); +} + + +static OSStatus carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) { + UInt32 eKind = WC(GetEventKind)(e); + UInt32 eClass = WC(GetEventClass)(e); + OSStatus r; + Darwin$CarbonMessage *msg; + if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage) + return eventNotHandledErr; + r = WC(GetEventParameter)(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg); + checkStatus(r,"GetEventParameter"); + msg->perform(); + GCJ$Retainer::release(msg); + return noErr; +} + + +#pragma mark ------ Utility Functions ------ + +static void funcFailed(const char *func,int r){ + fprintf(stderr,"%s() failed (%d)\n",func,r); + exit(EXIT_FAILURE); +} + +#pragma mark ------ CarbonPicture Methods ------ + +#pragma mark ----- Carbon Surface Methods ---- + + +void Darwin$CarbonSurface::natSyncCursor(jint n) { + ThemeCursor c; + // see Carbon.java for what these numbers mean + switch(n) { + case 1: c = kThemeWatchCursor; + case 2: c = kThemePlusCursor; + case 3: c = kThemeIBeamCursor; + case 4: c = kThemePointingHandCursor; + case 5: c = kThemeOpenHandCursor; + case 6: c = kThemeResizeLeftRightCursor; + default: c = kThemeArrowCursor; + } + WC(SetThemeCursor)(c); +} + +void Darwin$CarbonSurface::natSetInvisible(jboolean b) { + WindowRef window = (WindowRef) rawWindowRef; + fprintf(stderr,"Making window %s\n",b?"invisible":"visible"); + if(b) WC(HideWindow)(window); + else WC(ShowWindow)(window); +} + +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,"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,"CollapseWindow"); +} + +void Darwin$CarbonSurface::natSetTitleBarText(jstring js) { + SmartCFString s = js; + WindowRef window = (WindowRef) rawWindowRef; + WC(SetWindowTitleWithCFString)(window,s); +} + +void Darwin$CarbonSurface::natToBack() { + WindowRef window = (WindowRef) rawWindowRef; + WC(SendBehind)(window,NULL); +} + +void Darwin$CarbonSurface::natToFront() { + WindowRef window = (WindowRef) rawWindowRef; + fprintf(stderr,"SelectWindow)()\n"); + WC(SelectWindow)(window); +} + +#pragma mark ---- Window Event Handler ---- +static const EventTypeSpec eventTypeSpecs[] = { + // kEventClassCommand + // { kEventClassCommand, ??? }, + + // kEventClassWindow + { kEventClassWindow, kEventWindowUpdate }, + { kEventClassWindow, kEventWindowBoundsChanged }, + { kEventClassWindow, kEventWindowBoundsChanging }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassWindow, kEventWindowZoomed }, + { kEventClassWindow, kEventWindowCollapsed }, + { kEventClassWindow, kEventWindowExpanded }, + { kEventClassWindow, kEventWindowClose }, + { kEventClassWindow, kEventWindowClosed }, + { kEventClassWindow, kEventWindowDrawFrame }, + { kEventClassWindow, kEventWindowDrawPart }, + + // kEventClassControl + { kEventClassControl, kEventControlApplyBackground }, + + // kEventClassKeyboard + { kEventClassKeyboard, kEventRawKeyDown }, + { kEventClassKeyboard, kEventRawKeyRepeat }, + { kEventClassKeyboard, kEventRawKeyUp }, + { kEventClassKeyboard, kEventRawKeyModifiersChanged }, + + // kEventClassMouse + { kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseDragged }, + { kEventClassMouse, kEventMouseWheelMoved }, +}; + +static OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) { + Darwin$CarbonSurface *surface = (Darwin$CarbonSurface*)userData; + UInt32 eKind = WC(GetEventKind)(e); + UInt32 eClass = WC(GetEventClass)(e); + OSStatus r; + char* ec = (char*)&eClass; + if (surface == NULL) return eventNotHandledErr; + + + switch(eClass) { + case kEventClassCommand: + switch(eKind) { + // TODO: handle menu items + } + break; + case kEventClassKeyboard: + switch(eKind) { + case kEventRawKeyDown: + case kEventRawKeyRepeat: + case kEventRawKeyUp: { + UInt32 keyCode; + jstring js; + + r = WC(GetEventParameter)(e,kEventParamKeyCode,typeUInt32,NULL,sizeof(keyCode),NULL,&keyCode); + checkStatus(r,"GetEventParameter"); + + switch(keyCode) { + // These values were obtained by experimentation. I can't find any constants for them + // in the header files + case 126: js = JvNewStringLatin1("up"); break; + case 125: js = JvNewStringLatin1("down"); break; + case 124: js = JvNewStringLatin1("right"); break; + case 123: js = JvNewStringLatin1("left"); break; + case 122: js = JvNewStringLatin1("f1"); break; + case 120: js = JvNewStringLatin1("f2"); break; + case 99: js = JvNewStringLatin1("f3"); break; + case 118: js = JvNewStringLatin1("f4"); break; + case 96: js = JvNewStringLatin1("f5"); break; + case 97: js = JvNewStringLatin1("f6"); break; + case 98: js = JvNewStringLatin1("f7"); break; + case 100: js = JvNewStringLatin1("f8"); break; + case 101: js = JvNewStringLatin1("f9"); break; + case 109: js = JvNewStringLatin1("f10"); break; + case 103: js = JvNewStringLatin1("f11"); break; + case 111: js = JvNewStringLatin1("f12"); break; + case 105: js = JvNewStringLatin1("f13"); break; + case 114: js = JvNewStringLatin1("insert"); break; + case 117: js = JvNewStringLatin1("delete"); break; + case 116: js = JvNewStringLatin1("page_up"); break; + case 121: js = JvNewStringLatin1("page_down"); break; + case 115: js = JvNewStringLatin1("home"); break; + case 119: js = JvNewStringLatin1("end"); break; + case 71: js = JvNewStringLatin1("num_lock"); break; + case 53: js = JvNewStringLatin1("escape"); break; + case 51: js = JvNewStringLatin1("back_space"); break; + case 36: js = JvNewStringLatin1("enter"); break; + case 48: js = JvNewStringLatin1("tab"); break; + case 76: js = JvNewStringLatin1("enter"); break; // number pad enter + default: { + UInt32 size; + UInt32 modifiers = surface->modifiers; + r = WC(GetEventParameter)(e,kEventParamKeyUnicodes,typeUnicodeText,NULL,0,&size,NULL); + 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,"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 + if(modifiers & controlKey && buf[0] < 32) buf[0] += 0x60; + break; + } + } + + if(eKind == kEventRawKeyUp) + surface->KeyReleased(js); + else + surface->KeyPressed(js); + return noErr; + } + case kEventRawKeyModifiersChanged: { + const static struct { + UInt32 mask; + jstring xwtKey; + } modifiersTable[] = { + { shiftKey, JvNewStringLatin1("shift") }, + { alphaLock, JvNewStringLatin1("caps_lock") }, + { controlKey, JvNewStringLatin1("control") }, + { optionKey, JvNewStringLatin1("alt") }, + { kEventKeyModifierNumLockMask, JvNewStringLatin1("num_lock") }, + { 0, 0 } + }; + + UInt32 oldModifiers = (UInt32) surface->modifiers; + UInt32 newModifiers; + r = WC(GetEventParameter)(e,kEventParamKeyModifiers,typeUInt32,NULL,sizeof(newModifiers),NULL,&newModifiers); + checkStatus(r,"GetEventParameter"); + surface->modifiers = (jint) newModifiers; + UInt32 changedModifiers = oldModifiers ^ newModifiers; + + for(int i=0;modifiersTable[i].mask;i++) { + UInt32 mask = modifiersTable[i].mask; + if(!(changedModifiers & mask)) continue; + if(newModifiers & mask) + surface->KeyPressed(modifiersTable[i].xwtKey); + else + surface->KeyReleased(modifiersTable[i].xwtKey); + } + return noErr; + } + } + break; + case kEventClassMouse: + // The default handler gets first dibs on mouse events + // (this catches the titlebar, resize box, etc) + r = WC(CallNextEventHandler)(handler, e); + if(r != eventNotHandledErr && eKind != kEventMouseMoved && eKind != kEventMouseDragged) return r; + + switch(eKind) { + case kEventMouseMoved: + case kEventMouseDragged: { + WindowRef window = (WindowRef) surface->rawWindowRef; + Point p; + Rect rect; + + r = WC(GetEventParameter)(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p); + checkStatus(r,"GetEventParameter"); + r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect); + checkStatus(r,"GetWindowBounds"); + surface->Move(p.h-rect.left,p.v-rect.top); + return noErr; + } + case kEventMouseDown: + case kEventMouseUp: { + EventMouseButton button; + UInt32 clickCount; + jint xwtButton; + r = WC(GetEventParameter)(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button); + checkStatus(r,"GetEventParameter"); + r = WC(GetEventParameter)(e,kEventParamClickCount,typeUInt32,NULL,sizeof(clickCount),NULL,&clickCount); + checkStatus(r,"GetEventParameter"); + + switch(button) { + case kEventMouseButtonPrimary: xwtButton = 1; break; + case kEventMouseButtonSecondary: xwtButton = 2; break; + case kEventMouseButtonTertiary: xwtButton = 3; break; + default: return noErr; + } + if(eKind == kEventMouseDown) { + surface->Press(xwtButton); + } else { + surface->Release(xwtButton); + while(clickCount > 1) { + surface->DoubleClick(xwtButton); + clickCount-=2; + } + if(clickCount) surface->Click(xwtButton); + } + return noErr; + } + case kEventMouseWheelMoved: { + EventMouseWheelAxis axis; + SInt32 delta; + r = WC(GetEventParameter)(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis); + checkStatus(r,"GetEventParameter"); + if(axis != kEventMouseWheelAxisY) break; + r = WC(GetEventParameter)(e,kEventParamMouseWheelDelta,typeSInt32,NULL,sizeof(delta),NULL,&delta); + checkStatus(r,"GetEventParameter"); + fprintf(stderr,"kEventMouseWheelMoved: delta: %d",delta); + // surface->MouseWheelMoved(...) IMPROVMENT: mouse wheel support in xwt + return noErr; + } + } + break; + + case kEventClassWindow: { + WindowRef window; + r = WC(GetEventParameter)(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window); + checkStatus(r,"kEventClassWindow/WC(GetEventParameter"); + + if((RawData*)window != surface->rawWindowRef) Darwin::abort(JvNewStringLatin1("window != surface->window")); + + switch(eKind) { + case kEventWindowBoundsChanging: { + UInt32 attr; + Rect rect; + + r = WC(GetEventParameter)(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr); + 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; + + 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: + case kEventWindowDeactivated: { + surface->Focused(eKind == kEventWindowActivated); + return noErr; + } + case kEventWindowZoomed: { + surface->Maximized(true); + return noErr; + } + case kEventWindowCollapsed: { + surface->Minimized(true); + return noErr; + } + case kEventWindowExpanded: { + surface->Minimized(false); + return noErr; + } + case kEventWindowClose: { + surface->Close(); + return noErr; + } + case kEventWindowClosed: { + GCJ$Retainer::release(surface); + return noErr; + } + case kEventWindowUpdate: { + fprintf(stderr,"kEventWindowUpdate: Should not be here\n"); + abort(); + } + } + } + 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; + Rect rect; + WindowClass wc = framed ? kDocumentWindowClass : kPlainWindowClass; + // FIXME: unframed windows should appear in the window menu + // This probably needs a hack similar to whats in Cocoa.mm + WindowAttributes attr = kWindowStandardHandlerAttribute| + (framed ? kWindowInWindowMenuAttribute|kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute : 0); + OSStatus r; + 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,windowEventHandlerUPP,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL); + checkStatus(r,"InstallWindowEventHandler"); + + r = WC(InstallWindowContentPaintProc)(window,paintProcUPP,kWindowPaintProcOptionsNone,this); + checkStatus(r,"InstallWindowContentPaintProc"); + + WC(ShowWindow)(window); +} + +void Darwin$CarbonSurface::natDispose() { + WindowRef window = (WindowRef) rawWindowRef; + WC(DisposeWindow)(window); +} + +void Darwin$CarbonSurface::natSetIcon(org::xwt::Picture *_p) { +} + +void Darwin$CarbonSurface::natSetLocation() { + WindowRef window = (WindowRef) rawWindowRef; + Rect rect; + jint x = root->x; + jint y = root->y; + OSStatus r = WC(GetWindowBounds)(window,kWindowStructureRgn,&rect); + 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,"SetWindowBounds"); + r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL); + checkStatus(r,"ConstrainWindowToScreen"); +} + +void Darwin$CarbonSurface::natSetSize(jint w, jint h) { + WindowRef window = (WindowRef) rawWindowRef; + Rect rect; + OSStatus r = WC(GetWindowBounds)(window,kWindowContentRgn,&rect); + checkStatus(r,"GetWindowBounds"); + rect.bottom = rect.top + h; + rect.right = rect.left + w; + r = WC(SetWindowBounds)(window,kWindowContentRgn,&rect); + checkStatus(r,"SetWindowBounds"); + r = WC(ConstrainWindowToScreen)(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL); + checkStatus(r,"ConstrainWindowToScreen"); +} + +void Darwin$CarbonSurface::natSetLimits(jint minw, jint minh, jint maxw, jint maxh) { + WindowRef window = (WindowRef) rawWindowRef; + const int maxMax = 32767; + const int minMinW = 80; + const int minMinH = 20; + HISize min,max; + min.width = minw > maxMax ? maxMax : (minw < minMinW ? minMinW : minw); + min.height = minh > maxMax ? maxMax : (minh < minMinH ? minMinH : minh); + 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,"SetWindowResizeLimits"); +} + + +#pragma mark ------ Carbon Methods ------ +void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) { + Darwin$FileDialogHelper *helper = (Darwin$FileDialogHelper*) userData; + NavDialogRef dialog = callBackParms->context; + OSStatus r; + switch(callBackSelector) { + case kNavCBUserAction: { + NavUserAction action = WC(NavDialogGetUserAction)(dialog); + if(action == kNavUserActionNone || action == kNavUserActionCancel) { + helper->fileName = 0; + } else { + NavReplyRecord reply; + r = WC(NavDialogGetReply)(dialog,&reply); + 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,"AEGetNthPtr"); + r = WC(FSRefMakePath)(&ref,(UInt8*)buf,sizeof(buf)-1); + checkStatus(r,"FSRefMakePath"); + helper->fileName = JvNewStringLatin1(buf); + if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName); + r = WC(NavDisposeReply)(&reply); + checkStatus(r,"NavDialogGetReply"); + } + helper->sem->release(); + break; + } + case kNavCBTerminate: + WC(NavDialogDispose)(dialog); + break; + } +} + +void Darwin::natFileDialog(Darwin$FileDialogHelper *helper,jstring suggestion_, jboolean write) { + NavDialogRef dlg; + SmartCFString suggestion = suggestion_; + CFStringRef message = CFSTR("By selecting a file in this dialog you are giving this XWT application permission to access that file."); + OSStatus r; + WindowRef window = WC(FrontWindow)(); + NavDialogCreationOptions options; + + WC(NavGetDefaultDialogCreationOptions)(&options); + options.optionFlags = + (options.optionFlags|kNavAllFilesInPopup|kNavSelectAllReadableItem|kNavDontUseCustomFrame|kNavDontConfirmReplacement) + &~(kNavAllowStationery|kNavAllowMultipleFiles); + options.clientName = CFSTR("XWT"); + if(write) + options.saveFileName = suggestion; + options.message = message; + options.modality = window ? kWindowModalityWindowModal : kWindowModalityAppModal; + options.parentWindow = window; + + if(write) + r = WC(NavCreatePutFileDialog)(&options,0,0,fileDialogEventHandlerUPP,helper,&dlg); + else + r = WC(NavCreateGetFileDialog)(&options,NULL,fileDialogEventHandlerUPP,NULL,NULL,helper,&dlg); + checkStatus(r,"NavCreate(Get/Put)FileDialog"); + + WC(NavDialogRun)(dlg); +} + +jstring Darwin::natGetClipBoard() { + ScrapRef scrap; + OSStatus r; + Size size,size2; + + r = WC(GetCurrentScrap)(&scrap); + checkStatus(r,"GetCurrentScrap"); + + r = WC(GetScrapFlavorSize)( scrap, kScrapFlavorTypeUnicode, &size); + if(r == scrapFlavorNotFoundErr) return JvNewStringLatin1(""); + checkStatus(r,"GetScrapFlavorSize"); + + unsigned int length = size/sizeof(UniChar); + + jstring js = JvAllocString(length); + UniChar *buf = (UniChar*) JvGetStringChars(js); + size2 = size; + r = WC(GetScrapFlavorData)(scrap,kScrapFlavorTypeUnicode,&size2,buf); + if(r == scrapFlavorNotFoundErr); + checkStatus(r,"GetScrapFlavorData"); + if(size2 != size) return JvNewStringLatin1(""); + + return js; +} + +void Darwin::natSetClipBoard(jstring js) { + unsigned int length = js->length(); + ScrapRef scrap; + OSStatus r; + + r = WC(GetCurrentScrap)(&scrap); + checkStatus(r,"GetCurrentScrap"); + + r = WC(PutScrapFlavor)(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js)); + checkStatus(r,"PutScrapFlavor"); +} + +HTTP$Proxy *Darwin::natDetectProxy() { + using org::xwt::HTTP$Proxy; + HTTP$Proxy *p=0; + CFStringRef string; + CFNumberRef number; + SmartCFString smartString; + CFArrayRef exceptionList; + int i; + + CFDictionaryRef proxyInfo = WC(SCDynamicStoreCopyProxies)(NULL); + if(proxyInfo == NULL) return 0; + +#define doproto(proto,var) \ + number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxies ## proto ## Enable); \ + if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL; \ + if(number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) { \ + string = (CFStringRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\ + if(string != NULL && WC(CFGetTypeID)(string) != WC(CFStringGetTypeID)()) string = NULL; \ + number = (CFNumberRef) WC(CFDictionaryGetValue)(proxyInfo, kSCPropNetProxies ## proto ## Port); \ + if(number != NULL && WC(CFGetTypeID)(number) != WC(CFNumberGetTypeID)()) number = NULL; \ + if(string && number && WC(CFNumberGetValue)(number,kCFNumberIntType,&i) && i) { \ + if(!p) p = new HTTP$Proxy(); \ + p->var ## ProxyHost = cfStringToJString(string); \ + p->var ## ProxyPort = i; \ + } \ + } +doproto(HTTP,http) +doproto(HTTPS,https) +doproto(SOCKS,socks) +#undef doproto + + exceptionList = (CFArrayRef) WC(CFDictionaryGetValue)(proxyInfo,kSCPropNetProxiesExceptionsList); + if(exceptionList != NULL && WC(CFGetTypeID)(exceptionList) != WC(CFArrayGetTypeID)()) exceptionList = NULL; + if(p && exceptionList && WC(CFArrayGetCount)(exceptionList)) { + CFIndex count = WC(CFArrayGetCount)(exceptionList); + p->excluded = (JArray*) + JvNewObjectArray(count,&java::lang::String::class$,0); + for(i=0;iexcluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)"); + } + } + WC(CFRelease)(proxyInfo); + + return p; +/* + exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList]; + if(p && exceptionList && [exceptionList count]) { + NSLog(@"excl: %@",exceptionList); + p->excluded = (JArray*) + JvNewObjectArray([exceptionList count],&java::lang::String::class$,0); + for(i=0;i<[exceptionList count];i++) + elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring]; + } + return p; + */ + +/* + using org::xwt::Proxy; + AutoARP pool; + Proxy *p=0; + NSString *host; + NSNumber *port; + NSArray *exceptionList; + unsigned int i; + NSDictionary *proxyInfo = (NSDictionary*)WC(SCDynamicStoreCopyProxies)(NULL); + + if(proxyInfo == NULL) return 0; + if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPEnable] boolValue]) { + host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPProxy]; + port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPPort]; + if(host && [port intValue]) { + if(!p) p = new Proxy(); + p->httpProxyHost = [host jstring]; + p->httpProxyPort = [port intValue]; + } + } + if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSEnable] boolValue]) { + host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSProxy]; + port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesHTTPSPort]; + if(host && [port intValue]) { + if(!p) p = new Proxy(); + p->httpsProxyHost = [host jstring]; + p->httpsProxyPort = [port intValue]; + } + } + if([[proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSEnable] boolValue]) { + host = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSProxy]; + port = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesSOCKSPort]; + if(host && [port intValue]) { + if(!p) p = new Proxy(); + p->socksProxyHost = [host jstring]; + p->socksProxyPort = [port intValue]; + } + } + + exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList]; + if(p && exceptionList && [exceptionList count]) { + NSLog(@"excl: %@",exceptionList); + p->excluded = (JArray*) + JvNewObjectArray([exceptionList count],&java::lang::String::class$,0); + for(i=0;i<[exceptionList count];i++) + elements(p->excluded)[i] = [[exceptionList objectAtIndex: i] jstring]; + } + return p; +*/ +} + +jint Darwin::cgScreenWidth() { + return WC(CGDisplayPixelsWide)(((CGDirectDisplayID)0)); +} + +jint Darwin::cgScreenHeight() { + return WC(CGDisplayPixelsHigh)(((CGDirectDisplayID)0)); +} + +void Darwin::_newBrowserWindow(jstring js) { + SmartCFString cfs = js; + CFURLRef url = WC(CFURLCreateWithString)(WC(kCFAllocatorDefault),cfs,NULL); + SmartCFString scheme = WC(CFURLCopyScheme)(url); + if(scheme.equals(CFStringRef("http"))) + WC(LSOpenCFURLRef)(url,NULL); + WC(CFRelease)(url); +} + +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)(¤tProcess); + checkStatus(r,"GetCurrentProcess"); + r = WC(CPSEnableForegroundOperation)( ¤tProcess ); + checkStatus(r,"CPSEnableForegroundOperation"); + r = WC(CPSSetFrontProcess)(¤tProcess); + checkStatus(r,"CPSSetFrontProcess"); + } + #else + { + IBNibRef nib; + r = CreateNibReference(CFSTR("MainMenu"), &nib); + checkStatus(r,"CreateNibReference"); + r = SetMenuBarFromNib(nib, CFSTR("MenuBar")); + checkStatus(r,"SetMenuBarFromNib"); + DisposeNibReference(nib); + + // FEATURE: Install menu event handler + } + #endif +} + +void Darwin::runApplicationEventLoop() { + WC(RunApplicationEventLoop)(); + WC(ExitToShell)(); +} + +#pragma mark ------ OpenGL Functions ----- + +void Darwin$CarbonOpenGL::activateSharedContext() { + AGLContext ctx = (AGLContext) rawSharedContext; + WC(aglSetCurrentContext)(ctx); +} + +jboolean Darwin$CarbonOpenGL::initPixelFormat() { + GLint attr[] = { + AGL_NO_RECOVERY, + AGL_RGBA, + AGL_DEPTH_SIZE, 32, + AGL_RED_SIZE, 8, + AGL_GREEN_SIZE, 8, + AGL_RED_SIZE, 8, + AGL_ALPHA_SIZE, 8, + AGL_NONE + }; + + rawPixelFormat = (RawData*) WC(aglChoosePixelFormat)(NULL,0,attr); + return rawPixelFormat != 0; +} + +void Darwin$CarbonOpenGL::initSharedContext() { + AGLPixelFormat fmt = (AGLPixelFormat) rawPixelFormat; + rawSharedContext = (RawData*) WC(aglCreateContext)(fmt,NULL); + checkStatus(rawSharedContext,"aglCreateContext"); +} + +void Darwin$GLCarbonPixelBuffer::natInit() { + WindowClass wc = kPlainWindowClass; + WindowAttributes attr = 0; + WindowRef window; + Rect rect; + OSStatus r; + AGLContext ctx,shared; + AGLPixelFormat fmt; + GLboolean b; + GLuint tex; + GLuint target; + + rect.top = rect.left = 0; + rect.right = width + rect.left; + rect.bottom = height + rect.top; + + r = WC(CreateNewWindow)(wc,attr,&rect,&window); + checkStatus(r,"CreateNewWindow"); + + shared = (AGLContext) gl->rawSharedContext; + fmt = (AGLPixelFormat) gl->rawPixelFormat; + ctx = WC(aglCreateContext)(fmt,shared); + checkStatus(ctx, "aglCreateContext"); + + b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window)); + checkStatus(b,"aglSetDrawable"); + + WC(aglSetCurrentContext)(ctx); + WC(aglUpdateContext)(ctx); + drawableInit(width,height); + glClear(GL_COLOR_BUFFER_BIT); + + WC(aglSetCurrentContext)(shared); + target = rectTexture ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D; + glEnable(target); + glGenTextures(1,&tex); + glBindTexture(target,tex); + glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + WC(aglSurfaceTexture) (shared, target, GL_RGBA, ctx); + checkGLError(); + glDisable(target); + + //WC(ShowWindow)(window); + textureName = (jint) tex; + rawWindowRef = (RawData*) window; + rawCTX = (RawData*) ctx; +} + +void Darwin$GLCarbonPixelBuffer::activateContext() { + AGLContext ctx = (AGLContext) rawCTX; + WC(aglSetCurrentContext)(ctx); +} + +void Darwin$GLCarbonPixelBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) { + WindowRef window = (WindowRef) rawWindowRef; + AGLContext ctx = (AGLContext) rawCTX; + WC(aglDestroyContext)(ctx); + 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(); + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, db->textureName); + checkGLError(); + glBegin(GL_QUADS); + glTexCoord2i (sx1, sy1 ); + glVertex3i (dx1, dy1, 0); + glTexCoord2i (sx2, sy1 ); + glVertex3i (dx2, dy1, 0); + glTexCoord2i (sx2, sy2 ); + glVertex3i (dx2, dy2, 0); + glTexCoord2i (sx1, sy2 ); + glVertex3i (dx1, dy2, 0); + glEnd(); + checkGLError(); + glDisable(GL_TEXTURE_RECTANGLE_EXT); + checkGLError(); + } else { + float tx1,ty1,tx2,ty2; // normalized texture coords + tx1 = (float) sx1 / (float) db->width; + ty1 = (float) sy1 / (float) db->height; + tx2 = (float) sx2 / (float) db->width; + ty2 = (float) sy2 / (float) db->height; + + glColor4f(1.0f,1.0f,1.0f,1.0f); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, db->textureName); + checkGLError(); + glBegin(GL_QUADS); + glTexCoord2f (tx1, ty1 ); + glVertex3i (dx1, dy1, 0); + glTexCoord2f (tx2, ty1 ); + glVertex3i (dx2, dy1, 0); + glTexCoord2f (tx2, ty2 ); + glVertex3i (dx2, dy2, 0); + glTexCoord2f (tx1, ty2 ); + glVertex3i (dx1, dy2, 0); + glEnd(); + glDisable(GL_TEXTURE_2D); + checkGLError(); + } +} + +void Darwin$GLCarbonSurface::natInit() { + WindowRef window = (WindowRef) rawWindowRef; + AGLContext ctx,shared; + AGLPixelFormat fmt; + GLboolean b; + + shared = (AGLContext) gl->rawSharedContext; + fmt = (AGLPixelFormat) gl->rawPixelFormat; + ctx = WC(aglCreateContext)(fmt,shared); + checkStatus(ctx, "aglCreateContext"); + + b = WC(aglSetDrawable)(ctx,WC(GetWindowPort)(window)); + checkStatus(b,"aglSetDrawable"); + + WC(aglSetCurrentContext)(ctx); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glClearColor (1.0f, 1.0f, 1.0f, 1.0f); + glClearDepth( 0.0f ); + + needsReshape(); + + rawCTX = (RawData*)ctx; +} + +void Darwin$GLCarbonSurface::natDispose() { + AGLContext ctx = (AGLContext) rawCTX; + WC(aglDestroyContext)(ctx); + Darwin$CarbonSurface::natDispose(); +} + +} } } // end namepsace org::xwt::plat + + +