-// Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
-// see below for copyright information on the second portion of this file
+// 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
#include "POSIX.cc"
-#include <org/xwt/plat/Carbon.h>
-#include <org/xwt/plat/Carbon$CarbonSurface.h>
-#include <org/xwt/plat/Carbon$CarbonPicture.h>
-#include <org/xwt/plat/Carbon$CarbonDoubleBuffer.h>
-#include <org/xwt/plat/Carbon$WrappedRawData.h>
-#include <java/lang/System.h>
+#include "OpenGL.cc"
+
+#include <java/lang/Object.h>
#include <java/lang/Error.h>
-#include <java/io/PrintStream.h>
-
-// Apple's version of GCC automatically defines this symbol.
-// Since XWT is built with a "stock" version of GCC, we need to define
-// this manually to get the system header files to allow us to include them
-#define __APPLE_CPP__ 1
-
-// Standard GCC doesn't support precompiled headers,
-// meaning that it is WAY faster to just include the individual headers
-#include <CoreFoundation/CFString.h>
-#include <HIToolbox/MacWindows.h>
-#include <HIToolbox/MacApplication.h>
-#include <HIToolbox/Scrap.h>
-#include <HIToolbox/Appearance.h>
-#include <HIToolbox/CarbonEvents.h>
-#include <HIToolbox/HIView.h>
-#include <QD/ATSUnicode.h>
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) < (b) ? (b) : (a))
-
-#define FORMAT_RECT( x ) x.left, x.top, x.right, x.bottom
-#define PRINT_RECT( x ) fprintf( stderr, #x " = (%d, %d) (%d, %d)\n", x.left, x.top, x.right, x.bottom )
-#define PRINT_CGRECT( rect ) fprintf( stderr, #rect " = %f x %f @ (%f, %f)\n", rect.size.width, rect.size.height, rect.origin.x, rect.origin.y );
-
-
-static const EventTypeSpec CarbonSurfaceEventInfo[] = {
- { kEventClassWindow, kEventWindowUpdate },
- { kEventClassWindow, kEventWindowBoundsChanged },
- { kEventClassWindow, kEventWindowActivated },
- { kEventClassWindow, kEventWindowDeactivated },
- { kEventClassWindow, kEventWindowClose },
- { kEventClassWindow, kEventWindowZoomed },
- { kEventClassWindow, kEventWindowExpanded },
- { kEventClassWindow, kEventWindowCollapsed },
-
-
- { kEventClassKeyboard, kEventRawKeyDown },
- { kEventClassKeyboard, kEventRawKeyRepeat },
- { kEventClassKeyboard, kEventRawKeyUp },
- { kEventClassKeyboard, kEventRawKeyModifiersChanged },
-
-
- { kEventClassMouse, kEventMouseDown },
- { kEventClassMouse, kEventMouseUp },
- { kEventClassMouse, kEventMouseMoved },
- { kEventClassMouse, kEventMouseDragged },
- { kEventClassMouse, kEventMouseExited },
-
-
-};
-static inline UniChar GetCharacterWithoutModifiers( EventRef rawKeyboardEvent )
-{
- UInt32 keyCode;
- // Get the key code from the raw key event
- GetEventParameter( rawKeyboardEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof( keyCode ), NULL, &keyCode );
-
- // Get the current keyboard layout
- // TODO: If this is a performance sink, we need to cache these values
- SInt16 lastKeyLayoutID = GetScriptVariable( /*currentKeyScript*/ GetScriptManagerVariable(smKeyScript), smScriptKeys);
- Handle uchrHandle = GetResource('uchr', lastKeyLayoutID);
-
- // Translate the key press ignoring ctrl and option
- UInt32 ignoredDeadKeys = 0;
- UInt32 ignoredActualLength = 0;
- UniChar unicodeKey = 0;
-
- // We actually want the current shift key value
- UInt32 modifiers = (GetCurrentEventKeyModifiers() & shiftKey) >> 8;
- OSStatus err = UCKeyTranslate( reinterpret_cast<UCKeyboardLayout*>( *uchrHandle ), keyCode, kUCKeyActionDown,
- /* modifierKeyState */ modifiers, LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask, &ignoredDeadKeys,
- /* buffer length */ 1,
- /* actual length */ &ignoredActualLength,
- /* string */ &unicodeKey );
- assert( err == noErr );
-
- return unicodeKey;
+#include <org/xwt/plat/Carbon.h>
+#include <org/xwt/plat/Carbon$CarbonSurface.h>
+#include <org/xwt/plat/Carbon$GLCarbonSurface.h>
+#include <org/xwt/plat/Carbon$GLCarbonDoubleBuffer.h>
+#include <org/xwt/plat/Carbon$CarbonMessage.h>
+#include <org/xwt/plat/Carbon$CarbonOpenGL.h>
+#include <org/xwt/plat/Carbon$FileDialogHelper.h>
+#include <org/xwt/plat/GCJ$Retainer.h>
+#include <org/xwt/Proxy.h>
+#include <org/xwt/util/Semaphore.h>
+
+#include <Carbon/Carbon.h>
+#include <CoreFoundation/CoreFoundation.h>
+// For proxy stuff
+#include <SystemConfiguration/SystemConfiguration.h>
+// For LSOpenURLRef
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <AGL/agl.h>
+
+#include <stdlib.h>
+
+using namespace org::xwt::plat;
+using gnu::gcj::RawData;
+using org::xwt::util::Semaphore;
+using java::lang::Object;
+
+namespace org { namespace xwt { namespace plat {
+
+namespace carbon { }
+using namespace carbon;
+
+#pragma mark ------ Carbon Namespace ------
+namespace carbon {
+ // We put everything that isn't in org.xwt.plat.Carbon in
+ // org.xwt.plat.carbon 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 = CFStringGetLength(s);
+ CFRange range = CFRangeMake(0,length);
+ jstring js = JvAllocString(length);
+ UniChar *buf = (UniChar*)JvGetStringChars(js);
+ CFStringGetCharacters(s,range,buf);
+ return js;
+ }
+
+ #pragma mark ------ SmartCFString ------
+ class SmartCFString {
+ private:
+ CFStringRef p;
+ void release() { if(p) 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 = CFStringCreateWithCString(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 = CFStringCreateWithCharacters(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 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';
+
+ pascal OSStatus carbon::carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData);
+ void fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData);
+
+} // end namespace
+
+jboolean Carbon::isJaguar() {
+ SInt32 version;
+ OSStatus r = Gestalt(gestaltSystemVersion, &version);
+ checkStatus(r,"Gestalt");
+ return version >= 0x1020;
}
-static CFStringRef JavaToCFString(java::lang::String* s) {
- int len = min(1024, JvGetStringUTFLength(s));
-
- char* buffer = (char*) malloc( len );
- JvGetStringUTFRegion(s, 0, s->length(), buffer);
-
- // Create a CFString from the UTF8 string
- CFStringRef string = CFStringCreateWithBytes( NULL, (UInt8*) buffer, len, kCFStringEncodingUTF8, false );
- assert( string != NULL );
-
- free( buffer );
- buffer = NULL;
+void Carbon$CarbonMessage::natInit() {
+ OSStatus r;
+
+ EventHandlerUPP upp = NewEventHandlerUPP(carbonMessageEventHandler);
+ EventTypeSpec eventTypes = { kEventClassCarbonMessage, kEventCarbonMessage };
+ r = InstallEventHandler(GetApplicationEventTarget(),upp,1,&eventTypes,NULL,NULL);
+ checkStatus(r,"InstallEventHandler");
+}
- return string;
+void Carbon$CarbonMessage::add(Carbon$CarbonMessage *msg) {
+ EventRef event;
+ OSStatus r;
+
+ GCJ$Retainer::retain(msg);
+
+ r = CreateEvent(kCFAllocatorDefault,kEventClassCarbonMessage,kEventCarbonMessage,0,kEventAttributeNone,&event);
+ checkStatus(r,"CreateEvent");
+ r = SetEventParameter(event,kEventParamCarbonMessage,typeVoidPtr,sizeof(msg),(void*)&msg);
+ checkStatus(r,"SetEventParameter");
+ r = PostEventToQueue(GetMainEventQueue(),event,kEventPriorityHigh);
+ checkStatus(r,"PostEventToQueue");
+ ReleaseEvent(event);
}
-static jstring CFToJavaString( CFStringRef s ) {
- // TODO: I can probably use CFStringCreateExternalRepresentation
- // First determine the size of the buffer required
- const CFRange entireString = CFRangeMake( 0, CFStringGetLength( s ) );
- CFIndex requiredSize = 0;
- CFIndex charsConverted = CFStringGetBytes( s, entireString, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredSize );
- assert( charsConverted == CFStringGetLength( s ) );
- // Allocate the buffer, plus an additional byte for the null byte
- UInt8* buffer = (UInt8*) malloc( requiredSize + 1 );
- assert( buffer != NULL );
+pascal OSStatus carbon::carbonMessageEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+ UInt32 eKind = GetEventKind(e);
+ UInt32 eClass = GetEventClass(e);
+ OSStatus r;
+ Carbon$CarbonMessage *msg;
+ if(eClass != kEventClassCarbonMessage || eKind != kEventCarbonMessage)
+ return eventNotHandledErr;
+ r = GetEventParameter(e,kEventParamCarbonMessage,typeVoidPtr,NULL,sizeof(msg),NULL,&msg);
+ checkStatus(r,"GetEventParameter");
+ msg->perform();
+ GCJ$Retainer::release(msg);
+ return noErr;
+}
- // Convert the string
- charsConverted = CFStringGetBytes( s, entireString, kCFStringEncodingUTF8, 0, false, buffer, requiredSize, NULL );
- assert( charsConverted == CFStringGetLength( s ) );
- buffer[requiredSize] = '\0';
+#pragma mark ------ Utility Functions ------
- jstring string = JvNewStringUTF( (char*) buffer );
- assert( string != NULL );
+void carbon::funcFailed(char *func,int r){
+ fprintf(stderr,"%s() failed (%d)\n",func,r);
+ exit(EXIT_FAILURE);
+}
- free( buffer );
- buffer = NULL;
+#pragma mark ------ CarbonPicture Methods ------
- return string;
-}
+#pragma mark ----- Carbon Surface Methods ----
-static jstring UniCharToXWTString( UniChar character )
-{
- switch ( character ) {
- case '\t': return JvNewStringLatin1("tab");
- case kEscapeCharCode: return JvNewStringLatin1("escape");
- case '\n':
- case kEnterCharCode:
- case kReturnCharCode:
- return JvNewStringLatin1("enter");
- case kBackspaceCharCode: return JvNewStringLatin1("back_space");
- // escape == clear
- //case kClearCharCode: return JvNewStringLatin1("clear");
- //case VK_PAUSE: return JvNewStringLatin1("pause");
- case kPageUpCharCode: return JvNewStringLatin1("page_up");
- case kPageDownCharCode: return JvNewStringLatin1("page_down");
- case kEndCharCode: return JvNewStringLatin1("end");
- case kHomeCharCode: return JvNewStringLatin1("home");
- case kLeftArrowCharCode: return JvNewStringLatin1("left");
- case kUpArrowCharCode: return JvNewStringLatin1("up");
- case kRightArrowCharCode: return JvNewStringLatin1("right");
- case kDownArrowCharCode: return JvNewStringLatin1("down");
- // TODO: Is help always the insert key in the mac world? on my keyboard it is
- case kHelpCharCode: return JvNewStringLatin1("insert");
- case kDeleteCharCode: return JvNewStringLatin1("delete");
- // TODO: How can I determine if a numpad key was pressed?
- //case VK_NUMPAD0: return JvNewStringLatin1("numpad0");
- //case VK_NUMPAD1: return JvNewStringLatin1("numpad1");
- //case VK_NUMPAD2: return JvNewStringLatin1("numpad2");
- //case VK_NUMPAD3: return JvNewStringLatin1("numpad3");
- //case VK_NUMPAD4: return JvNewStringLatin1("numpad4");
- //case VK_NUMPAD5: return JvNewStringLatin1("numpad5");
- //case VK_NUMPAD6: return JvNewStringLatin1("numpad6");
- //case VK_NUMPAD7: return JvNewStringLatin1("numpad7");
- //case VK_NUMPAD8: return JvNewStringLatin1("numpad8");
- //case VK_NUMPAD9: return JvNewStringLatin1("numpad9");
- // TODO: How do I get the function key?
- case kFunctionKeyCharCode: return JvNewStringLatin1("f1");
- //case VK_F2: return JvNewStringLatin1("f2");
- //case VK_F3: return JvNewStringLatin1("f3");
- //case VK_F4: return JvNewStringLatin1("f4");
- //case VK_F5: return JvNewStringLatin1("f5");
- //case VK_F6: return JvNewStringLatin1("f6");
- //case VK_F7: return JvNewStringLatin1("f7");
- //case VK_F8: return JvNewStringLatin1("f8");
- //case VK_F9: return JvNewStringLatin1("f9");
- //case VK_F10: return JvNewStringLatin1("f10");
- //case VK_F11: return JvNewStringLatin1("f11");
- //case VK_F12: return JvNewStringLatin1("f12");
-
- default:
- // Convert the character into a CFString, then into a java string
- CFStringRef string = CFStringCreateWithCharactersNoCopy( NULL, &character, 1, kCFAllocatorNull );
- assert( string != NULL );
-
- jstring str = CFToJavaString( string );
-
- CFRelease( string );
- string = NULL;
-
- return str;
- }
-
- // We should never get here
- assert( false );
- return NULL;
-}
-static void ModifierKeyTest( org::xwt::plat::Carbon$CarbonSurface* surface, UInt32 changedModifiers, UInt32 currentModifiers, UInt32 keyMask, const char* string )
-{
- // If the modifier key changed
- if ( changedModifiers & keyMask ) {
- jstring str = JvNewStringLatin1( string );
-
- // And it is currently down, dispatch a keypressed event
- if ( currentModifiers & keyMask ) surface->KeyPressed( str );
- // otherwise dispatch a key released event
- else surface->KeyReleased( str );
- }
+void Carbon$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;
+ }
+ SetThemeCursor(c);
}
-
-// TODO: Do I have to make the event handlers "pascal", or use "NewEventHandlerUPP"?
-pascal static OSStatus CarbonSurfaceEventHandler( EventHandlerCallRef handler, EventRef event, void* data ) {
- UInt32 eventClass = GetEventClass( event );
- UInt32 eventKind = GetEventKind( event );
- OSStatus result = eventNotHandledErr;
- org::xwt::plat::Carbon$CarbonSurface* surface = (org::xwt::plat::Carbon$CarbonSurface*)data;
-
- //JvSynchronize dummy( surface );
-
- switch(eventClass) {
- case kEventClassWindow:
- switch(eventKind)
- {
- case kEventWindowUpdate:
- {
- //fprintf( stderr, "window update " );
-
- // Create the graphics context
- result = CreateCGContextForPort(GetWindowPort( (WindowRef) surface->window), (CGContextRef*) &surface->gc);
- assert( result == noErr && surface->gc != NULL );
-
- // Quartz uses the bottom left as its origin. Translate to use the top left.
- Rect bounds;
- GetWindowBounds( (WindowRef) surface->window, kWindowContentRgn, &bounds );
- assert( result == noErr );
- CGContextTranslateCTM( (CGContextRef) surface->gc, 0, bounds.bottom - bounds.top );
- CGContextScaleCTM( (CGContextRef) surface->gc, 1, -1 );
-
- // Convert the context to a CGRect with local coordinates
- CGRect contentBounds = CGRectMake( 0, 0, bounds.right - bounds.left, bounds.bottom - bounds.top );
-
- //PRINT_CGRECT( contentBounds );
-
- // Get the invalid region
- Rect globalInvalidRect;
- result = GetWindowBounds( (WindowRef) surface->window, kWindowUpdateRgn, &globalInvalidRect );
- assert( result == noErr );
-
- CGRect invalidRect = CGRectMake( globalInvalidRect.left - bounds.left, globalInvalidRect.top - bounds.top, globalInvalidRect.right - globalInvalidRect.left, globalInvalidRect.bottom - globalInvalidRect.top );
-
- //invalidRect = CGRectIntersection( invalidRect, contentBounds );
-
- //PRINT_CGRECT( invalidRect );
-
- BeginUpdate( (WindowRef) surface->window );
-
- // Erase the region with white
- // TODO: Draw the window background instead
- //result = SetThemeWindowBackground( (WindowRef) surface->window, ThemeBrush inBrush, true );
- CGContextSetRGBFillColor( (CGContextRef) surface->gc, 1.0, 1.0, 1.0, 1.0 );
- CGContextFillRect( (CGContextRef) surface->gc, invalidRect );
-
- //CGContextSetRGBFillColor( (CGContextRef) surface->gc, red, green, blue, 0.5 );
- //CGContextFillRect( (CGContextRef) surface->gc, CGRectMake( 0, 0, (bounds.right - bounds.left), (bounds.bottom - bounds.top) ) );
- // Add the invalid region to XWT's dirty regions
- surface->Dirty( (jint) invalidRect.origin.x, (jint) invalidRect.origin.y, (jint) invalidRect.size.width, (jint) invalidRect.size.height );
- // Then tell it to actually do the drawing
- surface->blitDirtyScreenRegions();
-
- EndUpdate( (WindowRef) surface->window );
-
- // Free the context
- CGContextFlush( (CGContextRef) surface->gc );
- CGContextRelease( (CGContextRef) surface->gc );
- surface->gc = NULL;
- result = noErr;
- break;
- }
-
- case kEventWindowBoundsChanged:
- {
- // We can't use the event parameter: it is the window bounds, not the content area bounds
- HIRect currentBounds;
- result = GetEventParameter( event, kEventParamCurrentBounds, typeHIRect, NULL, sizeof( currentBounds ), NULL, ¤tBounds );
- assert( result == noErr );
-
- // Get the event attributes to determine if size and/or origin have changed
- UInt32 attributes;
- result = GetEventParameter( event, kEventParamAttributes, typeUInt32, NULL, sizeof( attributes ), NULL, &attributes );
- assert( result == noErr );
-
- if ( attributes & kWindowBoundsChangeSizeChanged ) {
- // If maximize is set, unset it
- if ( attributes & kWindowBoundsChangeUserResize && surface->maximized ) {
- //fprintf( stderr, "maximized = 0\n" );
- surface->Maximized( false );
- }
-
- //fprintf( stderr, "size changed\n" );
- surface->SizeChange( (jint) currentBounds.size.width, (jint) currentBounds.size.height );
-
-
- }
-
- if ( attributes & kWindowBoundsChangeOriginChanged ) {
- //fprintf( stderr, "origin changed\n" );
- surface->PosChange( (jint) currentBounds.origin.x, (jint) currentBounds.origin.y );
- }
-
- result = noErr;
- break;
- }
-
- case kEventWindowActivated:
- case kEventWindowDeactivated:
- {
- //fprintf( stderr, "focus = %d\n", (eventKind == kEventWindowActivated) );
- surface->Focused( (eventKind == kEventWindowActivated) );
- result = noErr;
- break;
- }
-
- case kEventWindowZoomed:
- {
- // Toggle maximized whenever we recieve this event
- //fprintf( stderr, "maximized: %d\n", ! surface->maximized );
- surface->Maximized( ! surface->maximized );
- result = noErr;
- break;
- }
-
- case kEventWindowCollapsed:
- {
- //fprintf( stderr, "minimized true\n" );
- surface->Minimized( true );
- result = noErr;
- break;
- }
-
- case kEventWindowExpanded:
- {
- //fprintf( stderr, "minimized false\n" );
- surface->Minimized( false );
- result = noErr;
- break;
- }
-
- case kEventWindowClose:
- {
- //fprintf( stderr, "close\n" );
- surface->Close();
- result = noErr;
- break;
- }
- default:
- throw new java::lang::Error(JvNewStringLatin1("Unhandled Window Event"));
- }
- break;
-
- case kEventClassMouse:
- {
- HIPoint where;
- result = GetEventParameter( event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(where), NULL, &where );
- assert( result == noErr );
-
- // Create a hit test event to ask the standard window event handler where this press is
- EventRef hitTest;
- result = CreateEvent( NULL, kEventClassWindow, kEventWindowHitTest, 0, kEventAttributeNone, &hitTest );
- assert( result == noErr );
-
- result = SetEventParameter( hitTest, kEventParamMouseLocation, typeHIPoint, sizeof(where), &where );
- assert( result == noErr );
-
- result = SetEventParameter( hitTest, kEventParamDirectObject, typeWindowRef, sizeof(surface->window), &surface->window );
- assert( result == noErr );
-
- result = SendEventToEventTarget( hitTest, GetWindowEventTarget( (WindowRef) surface->window ) );
- assert( result == noErr );
-
- WindowDefPartCode part;
- result = GetEventParameter( hitTest, kEventParamWindowDefPart, typeWindowDefPartCode, NULL, sizeof(part), NULL, &part );
- assert( result == noErr );
-
- ReleaseEvent( hitTest );
- hitTest = NULL;
-
- // ignore the event if it is not in the content region.
- if ( part != wInContent )
- {
- return eventNotHandledErr;
- }
-
- // TODO: Can I get the content region's bounds as an HIRect?
- Rect bounds;
- GetWindowBounds( (WindowRef) surface->window, kWindowContentRgn, &bounds );
- assert( result == noErr );
- // Convert the context to a CGRect with local coordinates
- CGRect contentBounds = CGRectMake( bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top );
-
- // Now convert the point to content area relative coordinates:
- where.x -= contentBounds.origin.x;
- where.y -= contentBounds.origin.y;
-
- switch ( eventKind )
- {
- case kEventMouseDown:
- {
- //fprintf( stderr, "mouse down (%f, %f)\n", where.x, where.y );
- EventMouseButton mouseButton;
- result = GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton );
- assert( result == noErr );
-
- surface->Press( mouseButton );
- result = eventNotHandledErr;
- break;
- }
-
- case kEventMouseUp:
- {
- //fprintf( stderr, "mouse up (%f, %f)\n", where.x, where.y );
- EventMouseButton mouseButton;
- result = GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton );
- assert( result == noErr );
-
- UInt32 clickCount;
- result = GetEventParameter( event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount );
- assert( result == noErr );
-
- surface->Release( mouseButton );
-
- // deliver click/double click events
- if ( clickCount == 1 ) {
- //fprintf( stderr, "click (%f, %f)\n", where.x, where.y );
- surface->Click( mouseButton );
-
- //result = ActivateWindow( (WindowRef) surface->window, true );
- //assert( result == noErr );
-
- //ProcessSerialNumber psn = { 0, kCurrentProcess };
- //result = SetFrontProcess( &psn );
- //assert( result == noErr );
- } else if ( clickCount == 2 ) {
- //fprintf( stderr, "double click (%f, %f)\n", where.x, where.y );
- surface->DoubleClick( mouseButton );
- }
-
- result = noErr;
- break;
- }
-
- case kEventMouseMoved:
- case kEventMouseDragged:
- {
- surface->Move( (jint) where.x, (jint) where.y );
- result = noErr;
- //fprintf( stderr, "mousemoved (%f, %f)\n", where.x, where.y );
- break;
- }
-
- /*case kEventMouseExited:
- {
- // Move the mouse to (-1, -1) when it exits the window
- surface->Move( -1, -1 );
- result = noErr;
- fprintf( stderr, "mouse exited\n" );
- break;
- }*/
-
-
- /*case kEventMouseWheelMoved:
- {
- EventMouseWheelAxis inAxis;
- result = inEvent.GetParameter<EventMouseWheelAxis>( kEventParamMouseWheelAxis, typeMouseWheelAxis, &inAxis );
- assert( noErr == result );
-
- SInt32 inDelta;
- result = inEvent.GetParameter<SInt32>( kEventParamMouseWheelDelta, typeSInt32, &inDelta );
- assert( noErr == result );
-
- result = MouseWheelMoved( inAxis, inDelta, inKeyModifiers );
- break;
- }
- */
-
-
- // some other kind of Mouse event: This is (in my opinion) an error
- default:
- assert( false );
- break;
- }
- break;
- }
-
-
- case kEventClassKeyboard:
- switch (eventKind)
- {
- case kEventRawKeyDown:
- case kEventRawKeyRepeat:
- {
- // TODO: This breaks international input
- UniChar character = GetCharacterWithoutModifiers( event );
- surface->KeyPressed( UniCharToXWTString( character ) );
-
- result = noErr;
- break;
- }
-
- case kEventRawKeyUp:
- {
- UniChar character = GetCharacterWithoutModifiers( event );
- surface->KeyReleased( UniCharToXWTString( character ) );
-
- result = noErr;
- break;
- }
-
- case kEventRawKeyModifiersChanged:
- {
- static UInt32 previousModifiers = 0;
- UInt32 currentModifiers = GetCurrentEventKeyModifiers();
- UInt32 changedModifiers = previousModifiers ^ currentModifiers;
-
- ModifierKeyTest( surface, changedModifiers, currentModifiers, shiftKey, "shift" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, alphaLock, "caps_lock" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, controlKey, "control" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, optionKey, "alt" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, kEventKeyModifierNumLockMask, "num_lock" );
-
- previousModifiers = currentModifiers;
- result = noErr;
- break;
- }
-
- default:
- assert( false );
- break;
- }
- break;
-
- default:
- throw new java::lang::Error(JvNewStringLatin1("Unhandled Window Event"));
- }
-
- return result;
+
+void Carbon$CarbonSurface::natSetInvisible(jboolean b) {
+ WindowRef window = (WindowRef) rawWindowRef;
+ fprintf(stderr,"Making window %s\n",b?"invisible":"visible");
+ if(b) HideWindow(window);
+ else ShowWindow(window);
}
-/** Creates a next layout from string and style. If unicodeBuffer is not null, the caller is responsable for releasing it. */
-static ATSUTextLayout CreateTextLayout( CFStringRef string, ATSUStyle style, CFStringRef* unicodeBuffer ) {
- assert( string != NULL && unicodeBuffer != NULL && *unicodeBuffer == NULL && style != NULL );
-
- // Create layout
- ATSUTextLayout layout;
- OSStatus result = ATSUCreateTextLayout( &layout );
- assert( result == noErr && layout != NULL );
-
- // Try to get the unicode buffer directly
- CFIndex unicodeLength = CFStringGetLength( string );
- assert( unicodeLength != 0 );
- const UniChar* unicodeString = CFStringGetCharactersPtr( string );
- if ( unicodeString == NULL )
- {
- // That failed. Allocate a buffer using CFAllocator so the CFString can own it
- UniChar* buffer = (UniChar*) CFAllocatorAllocate( NULL, unicodeLength * sizeof( UniChar ), 0 );
- assert( buffer != NULL );
-
- // Get a copy of the text
- CFStringGetCharacters( string, CFRangeMake( 0, unicodeLength ), buffer );
-
- // Create a CFString which wraps and takes ownership of the buffer
- *unicodeBuffer = CFStringCreateWithCharactersNoCopy( NULL, buffer, unicodeLength, NULL );
- assert( *unicodeBuffer != NULL );
-
- unicodeString = buffer;
- }
-
- assert( unicodeString != NULL );
- //UniChar* unicode_string = malloc( sizeof( UniChar ) * unicode_length );
- //CFStringGetCharacters( string, CFRangeMake( 0, unicode_length ), unicode_string );
- ATSUSetTextPointerLocation( layout, unicodeString, kATSUFromTextBeginning, kATSUToTextEnd, unicodeLength );
-
- // Set the style
- result = ATSUSetRunStyle( layout, style, kATSUFromTextBeginning, kATSUToTextEnd );
- assert( result == noErr );
-
- // Using this setting makes rendering match TextEdit's (except for the antialiasing rules)
- ATSLineLayoutOptions rendering = kATSLineFractDisable; //kATSLineUseDeviceMetrics;
- ATSUAttributeTag tag = kATSULineLayoutOptionsTag;
- ByteCount size = sizeof( rendering );
- ATSUAttributeValuePtr value = &rendering;
- result = ATSUSetLayoutControls( layout, 1, &tag, &size, &value );
- assert( noErr == result );
-
- // Allow ATSUI to use its default font fallbacks for Unicode. This means that the font may not
- // match exactly, but it will display the characters if it can.
- result = ATSUSetTransientFontMatching( layout, true );
- assert( noErr == result );
-
- return layout;
+void Carbon$CarbonSurface::nat_setMaximized(jboolean b) {
+ WindowRef window = (WindowRef) rawWindowRef;
+ Point ideal = { 10000, 10000 };
+ OSStatus r = ZoomWindowIdeal(window,(b?inZoomOut:inZoomIn),&ideal);
+ checkStatus(r,"ZoomWindowIdeal");
}
-static void SetARGBFillColor( CGContextRef gc, jint argb )
-{
- uint8_t* colour = (uint8_t*) &argb;
- float alpha = colour[0] / 255.0;
- float red = colour[1] / 255.0;
- float green = colour[2] / 255.0;
- float blue = colour[3] / 255.0;
-
- CGContextSetRGBFillColor( gc, red, green, blue, alpha );
+void Carbon$CarbonSurface::nat_setMinimized(jboolean b) {
+ WindowRef window = (WindowRef) rawWindowRef;
+ if((IsWindowCollapsed(window) ? 1 : 0) == (b ? 1 : 0)) return;
+ OSStatus r = CollapseWindow(window,b);
+ checkStatus(r,"CollapseWindow");
}
-// CarbonDoubleBuffer //////////////////////////////////////////////////////////////////////
-
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::setClip(jint x1, jint y1, jint x2, jint y2) {
- // Restore the previous graphics state, which should be the initial state as saved in
- // natInit(). This sets the clipping region to the entire buffer.
- CGContextRestoreGState( (CGContextRef) gc );
- // We then immediately save the state again, so the we can reset the clipping area again
- CGContextSaveGState( (CGContextRef) gc );
-
- // Set the clipping area to the rectangle
- CGContextClipToRect( (CGContextRef) gc, CGRectMake( x1, y1, x2 - x1, y2 - y1 ) );
+void Carbon$CarbonSurface::natSetTitleBarText(jstring js) {
+ SmartCFString s = js;
+ WindowRef window = (WindowRef) rawWindowRef;
+ SetWindowTitleWithCFString(window,s);
}
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::drawPicture(org::xwt::Picture* s, jint x, jint y) {
- org::xwt::plat::Carbon$CarbonPicture* source = (org::xwt::plat::Carbon$CarbonPicture*)s;
-
- CGRect destination = CGRectMake( x, y, source->width, source->height );
- HIViewDrawCGImage( (CGContextRef) gc, &destination, (CGImageRef) source->image );
+void Carbon$CarbonSurface::natToBack() {
+ WindowRef window = (WindowRef) rawWindowRef;
+ SendBehind(window,NULL);
}
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::drawPicture(org::xwt::Picture* s,
- jint dx1, jint dy1, jint dx2, jint dy2, jint sx1, jint sy1, jint sx2, jint sy2) {
- org::xwt::plat::Carbon$CarbonPicture* source = (org::xwt::plat::Carbon$CarbonPicture*)s;
-
- //fprintf( stderr, "drawing stretched picture\n" );
- //CGContextSetRGBFillColor( (CGContextRef) gc, 1.0, 0.0, 0.0, 1.0 );
- //CGContextFillRect( (CGContextRef) gc, CGRectMake( dx1, dy1, dx2 - dx1, dy2 - dy1 ) );
- //return;
-
- // Some fancy clipping work is required here: draw only inside of the destination points
- CGContextSaveGState( (CGContextRef) gc );
- CGContextClipToRect( (CGContextRef) gc, CGRectMake( dx1, dy1, dx2 - dx1, dy2 - dy1 ) );
-
- // Some fancy scaling work is required here as well:
- // We want to copy a rectangle from the source image to a destination rectangle.
- // We are clipped to the destination rectangle, so now we must scale the source image
- // and line it up correctly.
- float destinationRectWidth = dx2 - dx1;
- float destinationRectHeight = dy2 - dy1;
- float sourceRectWidth = sx2 - sx1;
- float sourceRectHeight = sy2 - sy1;
- float horizontalScalingFactor = destinationRectWidth / sourceRectWidth;
- float verticalScalingFactor = destinationRectHeight / sourceRectHeight;
-
- // TODO: Work out the math for doing this. For now, no scaling is possible.
- CGRect destinationRect = CGRectMake( dx1 - sx1 * horizontalScalingFactor, dy1 - sy1 * verticalScalingFactor,
- source->width * horizontalScalingFactor, source->height * verticalScalingFactor );
- HIViewDrawCGImage( (CGContextRef) gc, &destinationRect, (CGImageRef) source->image );
-
- // Undo the clipping fun
- CGContextRestoreGState( (CGContextRef) gc );
+void Carbon$CarbonSurface::natToFront() {
+ WindowRef window = (WindowRef) rawWindowRef;
+ fprintf(stderr,"SelectWindow()\n");
+ SelectWindow(window);
}
-/*void CarbonPictureRelease( void* info, const void* data, size_t size )
-{
- // TODO: This should release a java reference, which should be
- // obtained when this is created.
- // It'll work without it, but that's only by "chance".
-}*/
-
-static CGImageRef CreateCGImageFromData( void* data, int width, int height, CGImageAlphaInfo alphaFormat )
-{
- // I'm assuming that data is in RGBA format
- const size_t NUM_COMPONENTS = 4;
- const size_t BITS_PER_COMPONENT = 8;
- const size_t BITS_PER_PIXEL = BITS_PER_COMPONENT * NUM_COMPONENTS;
- const size_t BYTES_PER_PIXEL = BITS_PER_PIXEL / 8;
- const size_t BYTES_PER_ROW = BYTES_PER_PIXEL * width;
-
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- assert( colorSpace != NULL );
-
- CGDataProviderRef dataProvider = CGDataProviderCreateWithData( NULL, data, width * height * BYTES_PER_PIXEL, NULL /*CarbonPictureRelease*/ );
- assert( dataProvider != NULL );
-
- CGImageRef image = CGImageCreate ( width, height, BITS_PER_COMPONENT, BITS_PER_PIXEL, BYTES_PER_ROW,
- colorSpace, alphaFormat, dataProvider, NULL, 1, kCGRenderingIntentDefault );
- assert( image != NULL );
-
- CGDataProviderRelease( dataProvider );
- dataProvider = NULL;
-
- CGColorSpaceRelease( colorSpace );
- colorSpace = NULL;
-
- return image;
+#pragma mark ---- Window Event Handler ----
+namespace carbon {
+static const EventTypeSpec eventTypeSpecs[] = {
+ // kEventClassCommand
+ // { kEventClassCommand, ??? },
+
+ // kEventClassWindow
+ { kEventClassWindow, kEventWindowUpdate },
+ { kEventClassWindow, kEventWindowBoundsChanged },
+ { kEventClassWindow, kEventWindowActivated },
+ { kEventClassWindow, kEventWindowDeactivated },
+ { kEventClassWindow, kEventWindowZoomed },
+ { kEventClassWindow, kEventWindowCollapsed },
+ { kEventClassWindow, kEventWindowExpanded },
+ { kEventClassWindow, kEventWindowClose },
+ { kEventClassWindow, kEventWindowClosed },
+
+ // kEventClassKeyboard
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyRepeat },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged },
+
+ // kEventClassMouse
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, kEventMouseDragged },
+ { kEventClassMouse, kEventMouseWheelMoved },
+};
+
+pascal OSStatus windowEventHandler(EventHandlerCallRef handler, EventRef e, void *userData) {
+ Carbon$CarbonSurface *surface = (Carbon$CarbonSurface*) userData;
+ UInt32 eKind = GetEventKind(e);
+ UInt32 eClass = GetEventClass(e);
+ OSStatus r;
+
+ 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 = 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 = 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 = 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 = 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 = 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 = GetEventParameter(e,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(p),NULL,&p);
+ checkStatus(r,"GetEventParameter");
+ r = 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 = GetEventParameter(e,kEventParamMouseButton,typeMouseButton,NULL,sizeof(button),NULL,&button);
+ checkStatus(r,"GetEventParameter");
+ r = 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 = GetEventParameter(e,kEventParamMouseWheelAxis,typeMouseWheelAxis,NULL,sizeof(axis),NULL,&axis);
+ checkStatus(r,"GetEventParameter");
+ if(axis != kEventMouseWheelAxisY) break;
+ r = 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 = GetEventParameter(e,kEventParamDirectObject,typeWindowRef,NULL,sizeof(window),NULL,&window);
+ checkStatus(r,"kEventClassWindow/GetEventParameter");
+
+ if((RawData*)window != surface->rawWindowRef) Carbon::abort(JvNewStringLatin1("window != surface->window"));
+
+ switch(eKind) {
+ case kEventWindowUpdate: {
+ surface->Dirty(0,0,surface->width,surface->height);
+ return noErr;
+ }
+ case kEventWindowBoundsChanged: {
+ UInt32 attr;
+ Rect rect;
+ r = GetEventParameter(e,kEventParamAttributes,typeUInt32,NULL,sizeof(attr),NULL,&attr);
+ checkStatus(r,"kEventWindowBoundsChanged/GetEventParameter");
+ r = GetWindowBounds(window,kWindowContentRgn,&rect);
+ checkStatus(r,"GetWindowBounds");
+ 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);
+ surface->SizeChange(w,h);
+ surface->Dirty(0,0,w,h);
+ surface->blitDirtyScreenRegions();
+ }
+ if(attr & kWindowBoundsChangeOriginChanged) {
+ surface->PosChange(rect.left,rect.top);
+ }
+ return noErr;
+ }
+ case kEventWindowActivated:
+ case kEventWindowDeactivated: {
+ surface->Focused(eKind == kEventWindowActivated);
+ return noErr;
+ }
+ case kEventWindowZoomed: {
+ fprintf(stderr,"Zoomed....\n");
+ 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: {
+ DisposeEventHandlerUPP((EventHandlerUPP)surface->rawEventHandlerUPP);
+ GCJ$Retainer::release(surface);
+ return noErr;
+ }
+ }
+ }
+ break;
+ }
+ return eventNotHandledErr;
}
-
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::natInit() {
- // FIRST: We create a CGBitmapContextRef so we can draw on this buffer
- const int BYTES_PER_PIXEL = 4; // RGBA
- const int BITS_PER_COMPONENT = 8;
-
- // Create a new bitmap context, along with the RAM for the bitmap itself
- const int bitmapBytesPerRow = (width * BYTES_PER_PIXEL);
- const int bitmapByteCount = (bitmapBytesPerRow * height);
-
- //fprintf( stderr, "alloced %ld bytes for %d x %d double buffer\n", bitmapByteCount, width, height );
-
- // create an RGB color space
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- assert( colorSpace != NULL );
-
- // create the bitmap
- bitmapData = (gnu::gcj::RawData*) malloc( bitmapByteCount );
- assert( bitmapData != NULL );
-
- // create the context
- // TODO: Use kCGImageAlphaPremultipliedLast for better performance
- gc = (gnu::gcj::RawData*) CGBitmapContextCreate( bitmapData, width, height, BITS_PER_COMPONENT, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst );
- assert( gc != NULL );
-
- // the context retains the color space, so we can release it
- // OPTIMIZATION: We could pass this colorSpace into CreateCGImageFromData
- CGColorSpaceRelease( colorSpace );
- colorSpace = NULL;
-
- // Clear the double buffer to transparent
- CGContextClearRect( (CGContextRef) gc, CGRectMake( 0, 0, width, height ) );
- //CGContextSetRGBFillColor( (CGContextRef) gc, 1.0, 1.0, 1.0, 1.0 );
- //CGContextFillRect( (CGContextRef) gc, CGRectMake( 0, 0, width, height ) );
-
- // Shift the coordinate origin to the top left corner (default = bottom right)
- CGContextTranslateCTM( (CGContextRef) gc, 0, height );
- CGContextScaleCTM( (CGContextRef) gc, 1, -1 );
-
-
- // SECOND: We create a CGImageRef that wraps this buffer, so we can copy it to a Surface
- image = (gnu::gcj::RawData*) CreateCGImageFromData( bitmapData, width, height, kCGImageAlphaPremultipliedFirst );
- assert( image != NULL );
-
- // THIRD: Save the current graphics state so we can set and reset the clipping state
- // We need to do this because the only way to make the clipping region larger is to
- // restore a previous graphics state. See setClip.
- CGContextSaveGState( (CGContextRef) gc );
+} // end namespace
+
+void Carbon$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 = 0; rect.left = 0; rect.bottom = 10; rect.right=10;
+ r = CreateNewWindow(wc,attr,&rect,&window);
+ checkStatus(r,"CreateNewWindow");
+
+ GCJ$Retainer::retain(this); // Need to account for the EventHandlers pointer to us
+ EventHandlerUPP upp = NewEventHandlerUPP(windowEventHandler);
+
+ r = InstallWindowEventHandler(window,upp,sizeof(eventTypeSpecs)/sizeof(EventTypeSpec),eventTypeSpecs,this,NULL);
+ checkStatus(r,"InstallWindowEventHandler");
+
+ rawWindowRef = (RawData*) window;
+ rawEventHandlerUPP = (RawData*) upp;
}
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::finalize() {
- CGContextRelease( (CGContextRef) gc );
- CGImageRelease( (CGImageRef) image );
- free( bitmapData );
- bitmapData = NULL;
+void Carbon$CarbonSurface::natDispose() {
+ WindowRef window = (WindowRef) rawWindowRef;
+ DisposeWindow(window);
}
-void org::xwt::plat::Carbon$CarbonSurface::blit(org::xwt::DoubleBuffer* db, jint sx, jint sy, jint dx1, jint dy1, jint dx2, jint dy2) {
- org::xwt::plat::Carbon$CarbonDoubleBuffer *xdb = (org::xwt::plat::Carbon$CarbonDoubleBuffer*)db;
- assert( xdb != NULL && xdb->gc != NULL && xdb->image != NULL );
-
- // This method is synchronized to prevent crappy threading fun
- //JvSynchronize dummy(this);
-
- /*fprintf( stderr, "reading image data...\n" );
- uint32_t* data = (uint32_t*) xdb->bitmapData;
- for ( int i = 0; i < xdb->width * xdb->height; ++ i )
- {
- uint32_t temp = data[i];
- ++ temp;
- }
- fprintf( stderr, "DONE\n" );*/
-
-
- // If we do not have a graphics context we simply mark this area as dirty and return.
- // We'll get a WindowPaint event later on.
- if ( gc == NULL )
- {
- Rect area;
- area.left = dx1;
- area.top = dy1;
- area.right = dx2;
- area.bottom = dy2;
- // Make the rectangle where we would blit this buffer as invalid
- OSStatus err = InvalWindowRect( (WindowRef) window, &area );
- //OSStatus err = QDAddRectToDirtyRegion( GetWindowPort( (WindowRef) window ), &area );
- assert( err == noErr );
-
- //fprintf( stderr, "blit: but marking invalid " );
- //PRINT_RECT( area );
- return;
- }
- assert( gc != NULL );
-
- //fprintf( stderr, "blit\n" );
-
- // Make sure that the CGImage is up to date
- CGContextFlush( (CGContextRef) xdb->gc );
-
- // Some fancy clipping work is required here: draw only inside of the destination rectangle
- CGContextSaveGState( (CGContextRef) gc );
- CGContextClipToRect( (CGContextRef) gc, CGRectMake( dx1, dy1, dx2 - dx1, dy2 - dy1 ) );
-
- // Draw the image on the surface
- CGRect destination = CGRectMake( dx1 - sx, dy1 - sy, xdb->width, xdb->height );
- HIViewDrawCGImage( (CGContextRef) gc, &destination, (CGImageRef) xdb->image );
-
- // Undo the clipping fun
- CGContextRestoreGState( (CGContextRef)gc );
+void Carbon$CarbonSurface::natSetIcon(org::xwt::Picture *_p) {
}
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::fillRect (jint x, jint y, jint x2, jint y2, jint argb) {
- // Set the Fill color to match
- SetARGBFillColor( (CGContextRef) gc, argb );
- CGContextFillRect( (CGContextRef) gc, CGRectMake( x, y, x2 - x, y2 - y ) );
+void Carbon$CarbonSurface::natSetLocation(jint x, jint y) {
+ WindowRef window = (WindowRef) rawWindowRef;
+ Rect rect;
+ OSStatus r = 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 = SetWindowBounds(window,kWindowStructureRgn,&rect);
+ checkStatus(r,"SetWindowBounds");
+ r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
+ checkStatus(r,"ConstrainWindowToScreen");
}
-void org::xwt::plat::Carbon$CarbonDoubleBuffer::drawString(::java::lang::String* font, ::java::lang::String* text, jint x, jint y, jint argb) {
- ATSUStyle style = (ATSUStyle) ((org::xwt::plat::Carbon*)org::xwt::plat::Carbon::platform)->_getATSUStyle( font );
- CFStringRef string = JavaToCFString( text );
-
- CFStringRef unicodeBuffer = NULL;
- ATSUTextLayout layout = CreateTextLayout( string, style, &unicodeBuffer );
-
- // Associate the graphics context with the text layout object
- ATSUAttributeTag tag = kATSUCGContextTag;
- ByteCount size = sizeof( gc );
- ATSUAttributeValuePtr value = &gc;
- OSStatus result = ATSUSetLayoutControls( layout, 1, &tag, &size, &value );
- assert( result == noErr );
-
- // The Quartz RGB fill color influences the ATSUI color
- SetARGBFillColor( (CGContextRef) gc, argb );
-
- // I've flipped the context to "standard" coordinates, but draw text needs it to be flipped back
- CGContextSaveGState( (CGContextRef) gc );
- CGContextScaleCTM( (CGContextRef) gc, 1.0, -1.0 );
- y = -y;
-
- // Draw text
- result = ATSUDrawText( layout, kATSUFromTextBeginning, kATSUToTextEnd, X2Fix( x ), X2Fix( y ) );
- assert( result == noErr );
-
- CGContextRestoreGState( (CGContextRef) gc );
-
- result = ATSUDisposeTextLayout( layout );
- assert( result == noErr );
- layout = NULL;
-
- if ( unicodeBuffer != NULL ) {
- CFRelease( unicodeBuffer );
- unicodeBuffer = NULL;
- }
-
- CFRelease( string );
- string = NULL;
+void Carbon$CarbonSurface::natSetSize(jint w, jint h) {
+ WindowRef window = (WindowRef) rawWindowRef;
+ Rect rect;
+ OSStatus r = GetWindowBounds(window,kWindowStructureRgn,&rect);
+ checkStatus(r,"GetWindowBounds");
+ rect.bottom = rect.top + h;
+ rect.right = rect.left + w;
+ r = SetWindowBounds(window,kWindowStructureRgn,&rect);
+ checkStatus(r,"SetWindowBounds");
+ r = ConstrainWindowToScreen(window,kWindowStructureRgn,kWindowConstrainMoveRegardlessOfFit,NULL,NULL);
+ checkStatus(r,"ConstrainWindowToScreen");
}
-// CarbonSurface //////////////////////////////////////////////////////////////////////
-
-void org::xwt::plat::Carbon$CarbonSurface::setIcon(org::xwt::Picture* pic) {
- org::xwt::plat::Carbon$CarbonPicture *picture = (org::xwt::plat::Carbon$CarbonPicture*)pic;
-
- // TODO: This sets the dock icon. Maybe I should set the document icon (the icon beside the window title)?
- // or set the "window preview" that is shown when a window is collapsed?
- // TODO: This doesn't seem to work. Maybe it is a size problem?
- OSStatus result = SetApplicationDockTileImage( (CGImageRef) picture->image );
- assert( result == noErr );
+void Carbon$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 = SetWindowResizeLimits(window,&min,&max);
+ checkStatus(r,"SetWindowResizeLimits");
}
-void org::xwt::plat::Carbon$CarbonSurface::setTitleBarText(java::lang::String* s) {
- CFStringRef string = JavaToCFString( s );
- OSStatus result = SetWindowTitleWithCFString( (WindowRef) window, string );
- assert( result == noErr );
- CFRelease( string );
- string = NULL;
+#pragma mark ------ Carbon Methods ------
+void carbon::fileDialogEventHandler(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *userData) {
+ Carbon$FileDialogHelper *helper = (Carbon$FileDialogHelper*) userData;
+ NavDialogRef dialog = callBackParms->context;
+ OSStatus r;
+ switch(callBackSelector) {
+ case kNavCBUserAction: {
+ NavUserAction action = NavDialogGetUserAction(dialog);
+ if(action == kNavUserActionNone || action == kNavUserActionCancel) {
+ helper->fileName = 0;
+ } else {
+ NavReplyRecord reply;
+ r = NavDialogGetReply(dialog,&reply);
+ checkStatus(r,"NavDialogGetReply");
+
+ AEKeyword keyword;
+ FSRef ref;
+ char buf[4096];
+ r = AEGetNthPtr(&reply.selection,1,typeFSRef,&keyword,NULL,&ref,sizeof(ref),NULL);
+ checkStatus(r,"AEGetNthPtr");
+ r = FSRefMakePath(&ref,(UInt8*)buf,sizeof(buf)-1);
+ checkStatus(r,"FSRefMakePath");
+ helper->fileName = JvNewStringLatin1(buf);
+ if(helper->save) helper->saveName = cfStringToJString(reply.saveFileName);
+ r = NavDisposeReply(&reply);
+ checkStatus(r,"NavDialogGetReply");
+ }
+ helper->sem->release();
+ break;
+ }
+ case kNavCBTerminate:
+ DisposeNavEventUPP((NavEventUPP)helper->rawUPP);
+ NavDialogDispose(dialog);
+ break;
+ }
}
-void org::xwt::plat::Carbon$CarbonSurface::setSize (jint width, jint height) {
- Rect bounds;
- OSStatus result = GetWindowBounds( (WindowRef) window, kWindowContentRgn, &bounds );
- assert( result == noErr );
-
- bounds.right = bounds.left + width;
- bounds.bottom = bounds.top + height;
-
- result = SetWindowBounds( (WindowRef) window, kWindowContentRgn, &bounds );
- assert( result == noErr );
- result = ConstrainWindowToScreen( (WindowRef) window, kWindowContentRgn, kWindowConstrainStandardOptions, NULL, NULL );
- assert( result == noErr );
-
- fprintf( stderr, "set size (%d, %d) (%d, %d)\n", FORMAT_RECT( bounds ) );
- // TODO: Shouldn't this deliver a "size changed" event automatically?
- //SizeChange( width, height );
+void Carbon::natFileDialog(Carbon$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 = FrontWindow();
+ NavDialogCreationOptions options;
+
+ NavEventUPP handler = NewNavEventUPP(carbon::fileDialogEventHandler);
+
+ 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 = NavCreatePutFileDialog(&options,0,0,handler,helper,&dlg);
+ else
+ r = NavCreateGetFileDialog(&options,NULL,handler,NULL,NULL,helper,&dlg);
+ checkStatus(r,"NavCreate(Get/Put)FileDialog");
+
+ helper->rawUPP = (RawData*)handler;
+ NavDialogRun(dlg);
}
-void org::xwt::plat::Carbon$CarbonSurface::setLocation (jint x, jint y) {
- Rect bounds;
- OSStatus result = GetWindowBounds( (WindowRef) window, kWindowStructureRgn, &bounds );
- assert( result == noErr );
-
- int temp = bounds.right - bounds.left;
- bounds.left = x;
- bounds.right = x + temp;
- temp = bounds.bottom - bounds.top;
- bounds.top = y;
- bounds.bottom = y + temp;
-
- result = SetWindowBounds( (WindowRef) window, kWindowStructureRgn, &bounds );
- assert( result == noErr );
- result = ConstrainWindowToScreen( (WindowRef) window, kWindowStructureRgn, kWindowConstrainStandardOptions, NULL, NULL );
- assert( result == noErr );
-
- fprintf( stderr, "set location (%d, %d) (%d, %d)\n", FORMAT_RECT( bounds ) );
+jstring Carbon::natGetClipBoard() {
+ ScrapRef scrap;
+ OSStatus r;
+ Size size,size2;
+
+ r = GetCurrentScrap(&scrap);
+ checkStatus(r,"GetCurrentScrap");
+
+ r = 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 = GetScrapFlavorData(scrap,kScrapFlavorTypeUnicode,&size2,buf);
+ if(r == scrapFlavorNotFoundErr);
+ checkStatus(r,"GetScrapFlavorData");
+ if(size2 != size) return JvNewStringLatin1("");
+
+ return js;
}
-void org::xwt::plat::Carbon$CarbonSurface::natInit (jboolean framed) {
- // Create a standard window. Maybe I should be using the Appearance Manager ones?
- OSStatus result = noErr;
- Rect bounds;
- bounds.left = 0;
- bounds.top = 0;
- bounds.right = 100;
- bounds.bottom = 100;
- if ( framed ) {
- OSStatus result = CreateNewWindow( kDocumentWindowClass,
- kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute,
- &bounds,
- (WindowRef*) &window
- );
- }
- else {
- OSStatus result = CreateNewWindow( kPlainWindowClass,
- kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute,
- &bounds,
- (WindowRef*) &window
- );
- }
- assert( result == noErr && window != NULL );
-
- // Install the event handler
- result = InstallEventHandler( GetWindowEventTarget( (WindowRef) window ),
- CarbonSurfaceEventHandler,
- GetEventTypeCount( CarbonSurfaceEventInfo ), CarbonSurfaceEventInfo,
- this,
- NULL );
- assert( result == noErr );
-
- // Make sure that this window is NOT visible
- //HideWindow( (WindowRef) window );
-}
+void Carbon::natSetClipBoard(jstring js) {
+ unsigned int length = js->length();
+ ScrapRef scrap;
+ OSStatus r;
-void org::xwt::plat::Carbon$CarbonSurface::toFront() {
- BringToFront( (WindowRef) window );
- //OSStatus result = ActivateWindow( (WindowRef) window, true );
- //assert( result == noErr );
-
- // Using the default "current process" or actually fetching the current process doesn't work
- ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
- OSStatus result = GetCurrentProcess( ¤tProcess );
- assert( result == noErr );
- result = SetFrontProcessWithOptions( ¤tProcess, kSetFrontProcessFrontWindowOnly );
- assert( result == noErr );
+ r = GetCurrentScrap(&scrap);
+ checkStatus(r,"GetCurrentScrap");
+
+ r = PutScrapFlavor(scrap,kScrapFlavorTypeUnicode,0,sizeof(UniChar)*length,JvGetStringChars(js));
+ checkStatus(r,"PutScrapFlavor");
}
-void org::xwt::plat::Carbon$CarbonSurface::toBack() {
- SendBehind( (WindowRef) window, NULL );
+Proxy *Carbon::natDetectProxy() {
+ using org::xwt::Proxy;
+ Proxy *p=0;
+ CFStringRef string;
+ CFNumberRef number;
+ SmartCFString smartString;
+ CFArrayRef exceptionList;
+ int i;
+
+ CFDictionaryRef proxyInfo = SCDynamicStoreCopyProxies(NULL);
+ if(proxyInfo == NULL) return 0;
+
+#define doproto(proto,var) \
+ number = (CFNumberRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxies ## proto ## Enable); \
+ if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL; \
+ if(number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) { \
+ string = (CFStringRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Proxy);\
+ if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL; \
+ number = (CFNumberRef) CFDictionaryGetValue(proxyInfo, kSCPropNetProxies ## proto ## Port); \
+ if(number != NULL && CFGetTypeID(number) != CFNumberGetTypeID()) number = NULL; \
+ if(string && number && CFNumberGetValue(number,kCFNumberIntType,&i) && i) { \
+ if(!p) p = new Proxy(); \
+ p->var ## ProxyHost = cfStringToJString(string); \
+ p->var ## ProxyPort = i; \
+ } \
+ }
+doproto(HTTP,http)
+doproto(HTTPS,https)
+doproto(SOCKS,socks)
+#undef doproto
+
+ exceptionList = (CFArrayRef) CFDictionaryGetValue(proxyInfo,kSCPropNetProxiesExceptionsList);
+ if(exceptionList != NULL && CFGetTypeID(exceptionList) != CFArrayGetTypeID()) exceptionList = NULL;
+ if(p && exceptionList && CFArrayGetCount(exceptionList)) {
+ CFIndex count = CFArrayGetCount(exceptionList);
+ p->excluded = (JArray<java::lang::String*>*)
+ JvNewObjectArray(count,&java::lang::String::class$,0);
+ for(i=0;i<count;i++) {
+ string = (CFStringRef) CFArrayGetValueAtIndex(exceptionList,i);
+ if(string != NULL && CFGetTypeID(string) != CFStringGetTypeID()) string = NULL;
+ elements(p->excluded)[i] = string ? cfStringToJString(string) : JvNewStringLatin1("(null)");
+ }
+ }
+ CFRelease(proxyInfo);
+
+ return p;
+/*
+ exceptionList = [proxyInfo objectForKey: (NSString*) kSCPropNetProxiesExceptionsList];
+ if(p && exceptionList && [exceptionList count]) {
+ NSLog(@"excl: %@",exceptionList);
+ p->excluded = (JArray<java::lang::String*>*)
+ 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*)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<java::lang::String*>*)
+ 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;
+*/
}
-void org::xwt::plat::Carbon$CarbonSurface::syncCursor() {
- ThemeCursor curs;
- if (cursor->equals(JvNewStringLatin1("crosshair"))) curs = kThemeCrossCursor;
- //else if (cursor->equals(east)) curs = kThemeArrowCursor;
- else if (cursor->equals(JvNewStringLatin1("hand"))) curs = kThemePointingHandCursor;
- //else if (cursor->equals(move)) curs = kThemeArrowCursor;
- //else if (cursor->equals(north)) curs = kThemeArrowCursor;
- //else if (cursor->equals(northeast)) curs = kThemeArrowCursor;
- //else if (cursor->equals(northwest)) curs = kThemeArrowCursor;
- //else if (cursor->equals(south)) curs = kThemeArrowCursor;
- //else if (cursor->equals(southeast)) curs = kThemeArrowCursor;
- //else if (cursor->equals(southwest)) curs = kThemeArrowCursor;
- else if (cursor->equals(JvNewStringLatin1("text"))) curs = kThemeIBeamCursor;
- //else if (cursor->equals(west)) curs = kThemeArrowCursor;
- else if (cursor->equals(JvNewStringLatin1("wait_string"))) curs = kThemeSpinningCursor;
- else curs = kThemeArrowCursor;
-
- // TODO: This should PROBABLY be activated/deactivated when over the window using mouse tracking regions
- SetThemeCursor( curs );
+jint Carbon::cgScreenWidth() {
+ return CGDisplayPixelsWide(kCGDirectMainDisplay);
}
-void org::xwt::plat::Carbon$CarbonSurface::_dispose() {
- ReleaseWindow( (WindowRef) window );
- window = NULL;
+jint Carbon::cgScreenHeight() {
+ return CGDisplayPixelsHigh(kCGDirectMainDisplay);
}
-void org::xwt::plat::Carbon$CarbonSurface::setInvisible(jboolean i) {
- //fprintf( stderr, "invisible = %d\n", i );
- if ( i ) {
- HideWindow( (WindowRef) window );
- } else {
- ShowWindow( (WindowRef) window );
- }
+void Carbon::_newBrowserWindow(jstring js) {
+ SmartCFString cfs = js;
+ CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault,cfs,NULL);
+ SmartCFString scheme = CFURLCopyScheme(url);
+ if(scheme.equals(CFStringRef("http")))
+ LSOpenCFURLRef(url,NULL);
+ CFRelease(url);
}
-void org::xwt::plat::Carbon$CarbonSurface::_setMaximized(jboolean b) {
- Point ideal;
- // TODO: Probably should use the actual screen size here
- ideal.h = CGDisplayPixelsWide( kCGDirectMainDisplay );
- ideal.v = CGDisplayPixelsHigh( kCGDirectMainDisplay );
- //fprintf( stderr, "maximized = %d\n", b );
- OSStatus result = ZoomWindowIdeal( (WindowRef) window, ( b ? inZoomOut : inZoomIn ), &ideal );
- // TODO: It seems to work, so why does it return an error? Theory: XWT is not in a bundle.
- assert( result == noErr );
+void Carbon::_exit() {
+ QuitApplicationEventLoop();
}
-void org::xwt::plat::Carbon$CarbonSurface::_setMinimized(jboolean b) {
- OSStatus result = CollapseWindow( (WindowRef) window, b );
- // TODO: It seems to work, so why does it return an error? Theory: XWT is not in a bundle.
- //assert( result == noErr );
+#define XWT_CARBON_NO_BUNDLE_HACK
+#ifdef XWT_CARBON_NO_BUNDLE_HACK
+extern "C" {
+ OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn);
+ OSErr CPSSetFrontProcess(ProcessSerialNumber *psn);
}
-
-void org::xwt::plat::Carbon$CarbonPicture::natInit() {
- assert( data->length == width * height );
- image = (gnu::gcj::RawData*) CreateCGImageFromData( elements(data), width, height, kCGImageAlphaFirst );
- assert( image != NULL );
+#endif
+void Carbon::natInit() {
+ OSStatus r;
+ #ifdef XWT_CARBON_NO_BUNDLE_HACK
+ {
+ ProcessSerialNumber currentProcess = { 0, kCurrentProcess };
+
+ ::fprintf(stderr,"Doing XWT_CARBON_NO_BUNDLE_HACK\n");
+ r = GetCurrentProcess(¤tProcess);
+ checkStatus(r,"GetCurrentProcess");
+ r = CPSEnableForegroundOperation( ¤tProcess );
+ checkStatus(r,"CPSEnableForegroundOperation");
+ r = 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);
+
+ // FIXME: Install menu event handler
+ }
+ #endif
}
-void org::xwt::plat::Carbon$CarbonPicture::finalize() {
- CGImageRelease( (CGImage*) image );
- image = NULL;
+void Carbon::_running() {
+ RunApplicationEventLoop();
+ ExitToShell();
}
-// Carbon ///////////////////////////////////////////////////////////////////
+#pragma mark ------ OpenGL Functions -----
-jint org::xwt::plat::Carbon::_getScreenWidth() {
- //fprintf( stderr, "screen width = %d\n", CGDisplayPixelsWide( kCGDirectMainDisplay ) );
- return CGDisplayPixelsWide( kCGDirectMainDisplay );
+void Carbon$CarbonOpenGL::activateSharedContext() {
+ AGLContext ctx = (AGLContext) rawSharedContext;
+ aglSetCurrentContext(ctx);
}
-jint org::xwt::plat::Carbon::_getScreenHeight() {
- //fprintf( stderr, "screen height = %d\n", CGDisplayPixelsHigh( kCGDirectMainDisplay ) );
- return CGDisplayPixelsHigh( kCGDirectMainDisplay );
+jboolean Carbon$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*) aglChoosePixelFormat(NULL,0,attr);
+ return rawPixelFormat != 0;
}
-jstring org::xwt::plat::Carbon::_getClipBoard() {
- // Get the clipboard reference
- ScrapRef scrap = NULL;
- OSStatus result = GetCurrentScrap( &scrap );
- assert( result == noErr );
-
- ScrapFlavorFlags flavorFlags;
- result = GetScrapFlavorFlags ( scrap, kScrapFlavorTypeUnicode, &flavorFlags );
-
- if ( result == noErr ) {
- // No error, we have unicode data in a Scrap. Find out how many bytes of data it is.
- Size bytes = 0;
- result = GetScrapFlavorSize( scrap, kScrapFlavorTypeUnicode, &bytes );
- assert( result == noErr );
- const Size numUniChars = bytes / sizeof( UniChar );
-
- // Allocate a buffer for the text using Core Foundation
- UniChar* buffer = reinterpret_cast<UniChar*>( CFAllocatorAllocate( NULL, bytes, 0 ) );
- assert( buffer != NULL );
-
- // Get a copy of the text
- Size nextBytes = bytes;
- result = GetScrapFlavorData( scrap, kScrapFlavorTypeUnicode, &nextBytes, buffer );
- assert( result == noErr );
-
- // Create a CFString which wraps and takes ownership of the buffer
- CFStringRef string = CFStringCreateWithCharactersNoCopy( NULL, buffer, numUniChars, NULL );
- assert( string != NULL );
- buffer = NULL; // string now owns this buffer
-
- jstring ret = CFToJavaString( string );
-
- // Default allocator releases both the CFString and the UniChar buffer (text)
- CFRelease( string );
- string = NULL;
-
- return ret;
- } else {
- return JvNewStringLatin1("");
- }
+void Carbon$CarbonOpenGL::initSharedContext() {
+ AGLPixelFormat fmt = (AGLPixelFormat) rawPixelFormat;
+ rawSharedContext = (RawData*) aglCreateContext(fmt,NULL);
+ checkStatus(rawSharedContext,"aglCreateContext");
}
-void org::xwt::plat::Carbon::_setClipBoard(jstring s) {
- CFStringRef string = JavaToCFString( s );
-
- OSStatus result = ClearCurrentScrap();
- assert( result == noErr );
-
- ScrapRef scrap = NULL;
- result = GetCurrentScrap( &scrap );
- assert( result == noErr );
-
- CFIndex numUniChars = CFStringGetLength( string );
-
- // Try to get a pointer to the unicode data first, then do the copy if needed
- const UniChar* buffer = CFStringGetCharactersPtr( string );
- if ( buffer != NULL )
- {
- result = PutScrapFlavor ( scrap, kScrapFlavorTypeUnicode, 0, sizeof( UniChar ) * numUniChars, buffer );
- assert( result == noErr );
- }
- else
- {
- UniChar* buffer = (UniChar*) malloc( sizeof( UniChar ) * numUniChars );
- assert( buffer != NULL );
- CFStringGetCharacters( string, CFRangeMake( 0, numUniChars ), buffer );
-
- result = PutScrapFlavor ( scrap, kScrapFlavorTypeUnicode, 0, sizeof( UniChar ) * numUniChars, buffer );
- assert( result == noErr );
-
- // Done with the UniChar* buffer
- free( buffer );
- buffer = NULL;
- }
-
- // Done with the CFString
- CFRelease( string );
- string = NULL;
+void Carbon$GLCarbonDoubleBuffer::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 = CreateNewWindow(wc,attr,&rect,&window);
+ checkStatus(r,"CreateNewWindow");
+
+ shared = (AGLContext) gl->rawSharedContext;
+ fmt = (AGLPixelFormat) gl->rawPixelFormat;
+ ctx = aglCreateContext(fmt,shared);
+ checkStatus(ctx, "aglCreateContext");
+
+ b = aglSetDrawable(ctx,GetWindowPort(window));
+ checkStatus(b,"aglSetDrawable");
+
+ aglSetCurrentContext(ctx);
+ aglUpdateContext(ctx);
+ drawableInit(width,height);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ 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);
+ aglSurfaceTexture (shared, target, GL_RGBA, ctx);
+ checkGLError();
+ glDisable(target);
+
+ //ShowWindow(window);
+ textureName = (jint) tex;
+ rawWindowRef = (RawData*) window;
+ rawCTX = (RawData*) ctx;
}
-/*
-JArray<java::lang::String*>* org::xwt::plat::Carbon::listNativeFonts() {
- ATSFontFamilyIterator iterator;
- OSStatus result = ATSFontFamilyIteratorCreate( kATSFontContextUnspecified, NULL, NULL, kATSOptionFlagsDefault, &iterator );
- if ( result != noErr ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
- // Iterate over fonts twice: The first time just to count the fonts so we can create the array
- // The second time gets the font names
- ATSFontFamilyRef font = NULL;
- int i = -1;
- while ( result == noErr )
- {
- i ++;
- result = ATSFontFamilyIteratorNext( iterator, &font );
- }
- if ( result != kATSIterationCompleted ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
- result = ATSFontFamilyIteratorReset( kATSFontContextUnspecified, NULL, NULL, kATSOptionFlagsDefault, &iterator );
- if ( result != noErr ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
- JArray<jstring>* fonts = (JArray<jstring>*)JvNewObjectArray( i, &(::java::lang::String::class$), NULL);
-
- ATSFontFamilyRef font = NULL;
- result = ATSFontFamilyIteratorNext( iterator, &font );
- while( result == noErr )
- {
- CFStringRef name = NULL;
- result = ATSFontFamilyGetName( font, kATSOptionFlagsDefault, &name );
- if ( result != noErr || name == NULL ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
- //const char* cstring = CFStringGetCStringPtr( name, kCFStringEncodingMacRoman );
- //if ( cstring != NULL ) fprintf( stderr, "%s\n", cstring );
-
- jstring xwtName = CFToJavaString( name );
-
- //
- xwtName = xwtName->replace(' ', '_')->toLowerCase()->concat( "0" );
- CFRelease( name );
- name = NULL;
-
- result = ATSFontFamilyIteratorNext( iterator, &font );
- i ++;
- }
- if ( result != kATSIterationCompleted ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
- result = ATSFontFamilyIteratorRelease ( &iterator );
- if ( result != noErr ) throw new java::lang::Error(JvNewStringLatin1("ASSERT"));
-
- return fonts;
+void Carbon$GLCarbonDoubleBuffer::activateContext() {
+ AGLContext ctx = (AGLContext) rawCTX;
+ aglSetCurrentContext(ctx);
}
-*/
-
-/*gnu::gcj::RawData* org::xwt::plat::Carbon::fontStringToStruct(jstring s) {
- throw new java::lang::Error(JvNewStringLatin1("FIXME"));
-}*/
-
-// HACK: WARNING: Undocumented Hack! This may break in the future
-// For now, however, it allows a non-bundled app to create Windows! Yay!
-extern "C" { OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn); }
-
-void org::xwt::plat::Carbon::natInit() {
- // HACK: WARNING: Undocumented Hack! This may break in the future
- // For now, however, it allows a non-bundled app to create Windows! Yay!
- ProcessSerialNumber currentProcess = { 0, kCurrentProcess }; // Using the default "current process" doesn't work
- OSStatus result = GetCurrentProcess( ¤tProcess );
- assert( result == noErr );
- result = CPSEnableForegroundOperation( ¤tProcess );
- assert( result == noErr );
-
- // Initiaize the native font hashtable
- // Get a copy of all available fonts
- ItemCount numFonts;
- result = ATSUFontCount( &numFonts );
- assert( result == noErr );
-
- ATSFontRef* fonts = (ATSFontRef*) malloc( sizeof(ATSFontRef) * numFonts );
- assert( fonts != NULL );
-
- ItemCount currentNumFonts;
- result = ATSUGetFontIDs( fonts, numFonts, ¤tNumFonts );
- assert( result == noErr );
- numFonts = min( currentNumFonts, numFonts ); // Just to be safe, maybe the number of fonts changed (unlikely!)
-
- const ByteCount MAX_NAME_LENGTH = 100;
- char familyName[MAX_NAME_LENGTH+1];
- for ( ItemCount i = 0; i < numFonts; i ++ ) {
- ByteCount actualBytes = 0;
- result = ATSUFindFontName( fonts[i], kFontFamilyName, (FontPlatformCode) kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
- MAX_NAME_LENGTH, familyName, &actualBytes, NULL );
-
- // If we were able to get a macintosh string for the font family name, use it to make a jstring
- if ( result == noErr && actualBytes > 0 )
- {
- familyName[actualBytes] = '\0';
-
- jstring xwtName = JvNewStringLatin1( familyName, actualBytes );
-
- // Convert the font family name to an XWT font name
- xwtName = xwtName->replace(' ', '_')->toLowerCase();
- // Map the first font we find to this family name. The first font is the "Regular" font.
- if ( nativeFontCache->get( xwtName ) == NULL )
- nativeFontCache->put( (java::lang::Object*) xwtName, new org::xwt::plat::Carbon$WrappedRawData( (::gnu::gcj::RawData*) fonts[i] ) );
- }
- else
- {
- //fprintf( stderr, "FONT HAS NO MAC NAME\n" );
- }
- }
-
- free( fonts );
- fonts = NULL;
+void Carbon$GLCarbonDoubleBuffer::natCleanup(RawData* rawWindowRef, RawData* rawCTX) {
+ WindowRef window = (WindowRef) rawWindowRef;
+ AGLContext ctx = (AGLContext) rawCTX;
+ aglDestroyContext(ctx);
+ DisposeWindow(window);
}
-jint org::xwt::plat::Carbon::_stringWidth(::java::lang::String* font, ::java::lang::String* text) {
- // If the string doesn't have any characters, return zero immediately
- if ( text->length() == 0 ) return 0;
-
- ATSUStyle style = (ATSUStyle) _getATSUStyle( font );
- CFStringRef string = JavaToCFString( text );
-
- CFStringRef unicodeBuffer = NULL;
- ATSUTextLayout layout = CreateTextLayout( string, style, &unicodeBuffer );
-
- unsigned long actualNumberOfBounds = 0;
- ATSTrapezoid glyphBounds;
-
- // We get a single bound, since the text should only require one. If it requires more, there is an issue
- OSStatus result = ATSUGetGlyphBounds( layout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &glyphBounds, &actualNumberOfBounds );
- assert( result == noErr && actualNumberOfBounds == 1 );
-
- ATSUDisposeTextLayout( layout );
- layout = NULL;
-
- if ( unicodeBuffer != NULL ) {
- CFRelease( unicodeBuffer );
- unicodeBuffer = NULL;
- }
-
- CFRelease( string );
- string = NULL;
-
- return Fix2Long( glyphBounds.upperRight.x - glyphBounds.upperLeft.x );
+void Carbon$GLCarbonSurface::natBlit(Carbon$GLCarbonDoubleBuffer *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);
+ db->activateContext();
+ glFlush();
+ checkGLError();
+ 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();
+ }
+ glFlush();
}
-jint org::xwt::plat::Carbon::_getMaxAscent(::java::lang::String* font) {
- ATSUStyle style = (ATSUStyle) _getATSUStyle( font );
-
- ByteCount actualSize = 0;
- ATSUTextMeasurement ascent;
- OSStatus result = ATSUGetAttribute( style, kATSUAscentTag, sizeof( ascent ), &ascent, &actualSize );
- assert( result == kATSUNotSetErr );
-
- //fprintf( stderr, "ascent = %ld\n", Fix2Long( ascent ) );
-
- return Fix2Long( ascent );
+void Carbon$GLCarbonSurface::natReshape(jint w, jint h) {
+ AGLContext ctx = (AGLContext) rawCTX;
+
+ aglSetCurrentContext (ctx);
+ 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();
}
-jint org::xwt::plat::Carbon::_getMaxDescent(::java::lang::String* font) {
- ATSUStyle style = (ATSUStyle) _getATSUStyle( font );
-
- ByteCount actualSize = 0;
- ATSUTextMeasurement descent;
- OSStatus result = ATSUGetAttribute( style, kATSUDescentTag, sizeof( descent ), &descent, &actualSize );
- assert( result == kATSUNotSetErr );
-
- //fprintf( stderr, "descent = %ld\n", Fix2Long( descent ) );
- return Fix2Long( descent );
+void Carbon$GLCarbonSurface::natInit() {
+ WindowRef window = (WindowRef) rawWindowRef;
+ AGLContext ctx,shared;
+ AGLPixelFormat fmt;
+ GLboolean b;
+
+ shared = (AGLContext) gl->rawSharedContext;
+ fmt = (AGLPixelFormat) gl->rawPixelFormat;
+ ctx = aglCreateContext(fmt,shared);
+ checkStatus(ctx, "aglCreateContext");
+
+ b = aglSetDrawable(ctx,GetWindowPort(window));
+ checkStatus(b,"aglSetDrawable");
+
+ aglSetCurrentContext(ctx);
+ checkGLError();
+
+ rawCTX = (RawData*)ctx;
+
+ reshape(10,10);
+
+ aglSetCurrentContext(ctx);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
-gnu::gcj::RawData* org::xwt::plat::Carbon::_createATSUStyle( gnu::gcj::RawData* fontRef, jint fontSize, jboolean isBold, jboolean isItalic, jboolean isUnderline ) {
- ATSUStyle style;
- OSStatus result = ATSUCreateStyle( &style );
- assert( result == noErr && style != NULL );
-
- // Font
- ATSFontRef font = (ATSFontRef) fontRef;
- Fixed size = X2Fix( fontSize );
- Boolean bold = isBold;
- Boolean italic = isItalic;
- Boolean underline = isUnderline;
-
- const ATSUAttributeTag tags[] = { kATSUFontTag, kATSUSizeTag, kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag };
- ByteCount sizes[] = { sizeof( font ), sizeof( size ), sizeof( bold ), sizeof( italic ), sizeof( underline ) };
- ATSUAttributeValuePtr values[] = { &font, &size, &bold, &italic, &underline };
-
- result = ATSUSetAttributes( style, sizeof( tags ) / sizeof( *tags ), tags, sizes, values );
- assert( result == noErr );
-
- // TODO: Why do I have to turn this off manually? This shouldn't this be the default?
- ATSUFontFeatureType featureType = kLigaturesType;
- ATSUFontFeatureSelector selector = kCommonLigaturesOffSelector;
- result = ATSUSetFontFeatures( style, 1, &featureType, &selector );
- assert( result == noErr );
-
- return (gnu::gcj::RawData*) style;
+void Carbon$GLCarbonSurface::natDispose() {
+ AGLContext ctx = (AGLContext) rawCTX;
+ aglDestroyContext(ctx);
+ Carbon$CarbonSurface::natDispose();
}
-
-/** Called once XWT is initialized and the application is running. */
-void org::xwt::plat::Carbon::_running() {
- // TODO: This is going to be a bit magical:
- // Let's see what happens when we mix multithreading and OS X applications.
- // Theory: Bad stuff may happen if events are delivered and other stuff is going on at
- // the same time. However, I'm going to pray that XWT's Java stuff locks things for me,
- // So by the time I call into the Java code, i'm the only code path active?
- RunApplicationEventLoop();
-
- org::xwt::plat::Carbon::exit();
-}
+} } } // end namepsace org::xwt::plat