diff options
Diffstat (limited to 'src/newt/native/MacWindow.m')
-rw-r--r-- | src/newt/native/MacWindow.m | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m new file mode 100644 index 000000000..3b708acce --- /dev/null +++ b/src/newt/native/MacWindow.m @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +#import <inttypes.h> + +#import "jogamp_newt_macosx_MacWindow.h" +#import "NewtMacWindow.h" + +#import "MouseEvent.h" +#import "KeyEvent.h" + +#import <ApplicationServices/ApplicationServices.h> + +#import <stdio.h> + +NSString* jstringToNSString(JNIEnv* env, jstring jstr) +{ + const jchar* jstrChars = (*env)->GetStringChars(env, jstr, NULL); + NSString* str = [[NSString alloc] initWithCharacters: jstrChars length: (*env)->GetStringLength(env, jstr)]; + (*env)->ReleaseStringChars(env, jstr, jstrChars); + return str; +} + +void setFrameTopLeftPoint(NSWindow* pwin, NSWindow* win, jint x, jint y) +{ + NSScreen* screen = [NSScreen mainScreen]; + + // this allows for better compatibility with awt behavior + NSRect visibleRect; // either screen or parent-window + NSPoint pt; + int d_pty=0; // parent titlebar height + int d_ptx=0; + + if(NULL==pwin) { + visibleRect = [screen frame]; + } else { + visibleRect = [pwin frame]; + NSView* pview = [pwin contentView]; + NSRect viewRect = [pview frame]; + d_pty = visibleRect.size.height - viewRect.size.height; + (void) d_ptx; + //d_pty = visibleRect.origin.y - viewRect.size.height; + //d_ptx = visibleRect.size.height - viewRect.size.height; + fprintf(stderr, "pwin %lf/%lf %lfx%lf, pview %lf/%lf %lfx%lf -> %d/%d\n", + visibleRect.origin.x, + visibleRect.origin.y, + visibleRect.size.width, + visibleRect.size.height, + viewRect.origin.x, + viewRect.origin.y, + viewRect.size.width, + viewRect.size.height, + (int)x, (int)y); + + } + + pt = NSMakePoint(visibleRect.origin.x + x, visibleRect.origin.y + visibleRect.size.height - y - d_pty); + + [win setFrameTopLeftPoint: pt]; +} + +static NewtView * changeContentView(JNIEnv *env, jobject javaWindowObject, NSWindow *pwin, NSWindow *win, NewtView *newView) { + NSView* oldNSView = [win contentView]; + NewtView* oldView = NULL; + + if(NULL!=oldNSView) { +NS_DURING + // Available >= 10.5 - Makes the menubar disapear + if([oldNSView isInFullScreenMode]) { + [oldNSView exitFullScreenModeWithOptions: NULL]; + } +NS_HANDLER +NS_ENDHANDLER + if( [oldNSView isMemberOfClass:[NewtView class]] ) { + oldView = (NewtView *) oldNSView; + + jobject globJavaWindowObject = [oldView getJavaWindowObject]; + (*env)->DeleteGlobalRef(env, globJavaWindowObject); + [oldView setJavaWindowObject: NULL]; + } + /** FIXME: Tried child window: auto clip or message reception .. + if(NULL!=pwin) { + [oldView removeFromSuperview]; + } */ + } + if(NULL!=newView) { + jobject globJavaWindowObject = (*env)->NewGlobalRef(env, javaWindowObject); + [newView setJavaWindowObject: globJavaWindowObject]; + [newView setJNIEnv: env]; + + /** FIXME: Tried child window: auto clip or message reception .. + if(NULL!=pwin) { + NSView* pview = [pwin contentView]; + [pview addSubview: newView]; + } */ + } + [win setContentView: newView]; + + // make sure the insets are updated in the java object + NewtMacWindow* newtw = (NewtMacWindow*)win; + [newtw updateInsets: env]; + + return oldView; +} + +/* + * Class: jogamp_newt_macosx_MacDisplay + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_macosx_MacDisplay_initNSApplication0 + (JNIEnv *env, jclass clazz) +{ + static int initialized = 0; + + if(initialized) return JNI_TRUE; + initialized = 1; + + // This little bit of magic is needed in order to receive mouse + // motion events and allow key focus to be properly transferred. + // FIXME: are these Carbon APIs? They come from the + // ApplicationServices.framework. + ProcessSerialNumber psn; + if (GetCurrentProcess(&psn) == noErr) { + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + SetFrontProcess(&psn); + } + + // Initialize the shared NSApplication instance + [NSApplication sharedApplication]; + + // Need this when debugging, as it is necessary to attach gdb to + // the running java process -- "gdb java" doesn't work + // printf("Going to sleep for 10 seconds\n"); + // sleep(10); + + return (jboolean) JNI_TRUE; +} + +/* + * Class: jogamp_newt_macosx_MacDisplay + * Method: dispatchMessages0 + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacDisplay_dispatchMessages0 + (JNIEnv *env, jobject unused) +{ + NSEvent* event = NULL; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + +NS_DURING + + int num_events = 0; + + // Periodically take a break + do { + // FIXME: ignoring event mask for the time being + event = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate distantPast] + inMode: NSDefaultRunLoopMode + dequeue: YES]; + if (event != NULL) { + [NSApp sendEvent: event]; + + num_events++; + } + } while (num_events<100 && event != NULL); + +NS_HANDLER + + // just ignore it .. + +NS_ENDHANDLER + + [pool release]; +} + +/* + * Class: jogamp_newt_macosx_MacScreen + * Method: getWidthImpl + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_macosx_MacScreen_getWidthImpl0 + (JNIEnv *env, jclass clazz, jint screen_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rect = [screen frame]; + + [pool release]; + + return (jint) (rect.size.width); +} + +/* + * Class: jogamp_newt_macosx_MacScreen + * Method: getHeightImpl + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_newt_macosx_MacScreen_getHeightImpl0 + (JNIEnv *env, jclass clazz, jint screen_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + NSRect rect = [screen frame]; + + [pool release]; + + return (jint) (rect.size.height); +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: initIDs + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_newt_macosx_MacWindow_initIDs0 + (JNIEnv *env, jclass clazz) +{ + static int initialized = 0; + + if(initialized) return JNI_TRUE; + initialized = 1; + + // Need this when debugging, as it is necessary to attach gdb to + // the running java process -- "gdb java" doesn't work + // printf("Going to sleep for 10 seconds\n"); + // sleep(10); + + return (jboolean) [NewtMacWindow initNatives: env forClass: clazz]; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: createWindow0 + * Signature: (JIIIIZIIIJ)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_macosx_MacWindow_createWindow0 + (JNIEnv *env, jobject jthis, jlong parent, jint x, jint y, jint w, jint h, jboolean fullscreen, jint styleMask, + jint bufferingType, jint screen_idx, jlong jview) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSRect rect = NSMakeRect(x, y, w, h); + + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + NSScreen *screen = (NSScreen *) [screens objectAtIndex: screen_idx]; + + if (fullscreen) { + styleMask = NSBorderlessWindowMask; + NSRect rect = [screen frame]; + w = (jint) (rect.size.width); + h = (jint) (rect.size.height); + } + + // Allocate the window + NSWindow* window = [[[NewtMacWindow alloc] initWithContentRect: rect + styleMask: (NSUInteger) styleMask + backing: (NSBackingStoreType) bufferingType + screen: screen] retain]; + + NSObject *nsParentObj = (NSObject*) ((intptr_t) parent); + NSWindow* parentWindow = NULL; + if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) { + parentWindow = (NSWindow*) nsParentObj; + } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) { + NSView* view = (NSView*) nsParentObj; + parentWindow = [view window]; + fprintf(stderr, "createWindow0 - Parent is NSView : %p -> %p (win) \n", nsParentObj, parentWindow); + } else { + fprintf(stderr, "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj); + } + if(NULL!=parentWindow) { + [parentWindow addChildWindow: window ordered: NSWindowAbove]; + [window setParentWindow: parentWindow]; + } + + if (fullscreen) { + [window setOpaque: YES]; + } else { + // If the window is undecorated, assume we want the possibility of + // a shaped window, so make it non-opaque and the background color clear + if ((styleMask & NSTitledWindowMask) == 0) { + [window setOpaque: NO]; + [window setBackgroundColor: [NSColor clearColor]]; + } + } + + // Immediately re-position the window based on an upper-left coordinate system + setFrameTopLeftPoint(parentWindow, window, x, y); + + // specify we want mouse-moved events + [window setAcceptsMouseMovedEvents:YES]; + + // Use given NewtView or allocate an NewtView if NULL + NewtView* view = (0==jview)? [[NewtView alloc] initWithFrame: rect] : (NewtView*) ((intptr_t) jview) ; + + // Set the content view + (void) changeContentView(env, jthis, parentWindow, window, view); + +NS_DURING + // Available >= 10.5 - Makes the menubar disapear + if(fullscreen) { + [view enterFullScreenMode: screen withOptions:NULL]; + } +NS_HANDLER +NS_ENDHANDLER + + // Set the next responder to be the window so that we can forward + // right mouse button down events + [view setNextResponder: window]; + + [pool release]; + + return (jlong) ((intptr_t) window); +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: makeKeyAndOrderFront + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_makeKeyAndOrderFront0 + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win makeKeyAndOrderFront: win]; + [pool release]; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: makeKey + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_makeKey0 + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win makeKeyWindow]; + [pool release]; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: orderOut + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_orderOut0 + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + [win orderOut: win]; + [pool release]; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: close0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_close0 + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSView* view = [win contentView]; + [win orderOut: win]; +NS_DURING + if(NULL!=view) { + // Available >= 10.5 - Makes the menubar disapear + if([view isInFullScreenMode]) { + [view exitFullScreenModeWithOptions: NULL]; + } + } +NS_HANDLER +NS_ENDHANDLER + [win close]; + [pool release]; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: setTitle0 + * Signature: (JLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_setTitle0 + (JNIEnv *env, jobject unused, jlong window, jstring title) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSString* str = jstringToNSString(env, title); + [str autorelease]; + [win setTitle: str]; + [pool release]; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: contentView + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_macosx_MacWindow_contentView0 + (JNIEnv *env, jobject unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + jlong res = (jlong) ((intptr_t) [win contentView]); + [pool release]; + return res; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: changeContentView + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_macosx_MacWindow_changeContentView0 + (JNIEnv *env, jobject jthis, jlong parent, jlong window, jlong jview) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* pwin = (NewtMacWindow*) ((intptr_t) parent); + NSWindow* win = (NewtMacWindow*) ((intptr_t) window); + NewtView* newView = (NewtView *) ((intptr_t) jview); + + NewtView* oldView = changeContentView(env, jthis, pwin, win, newView); + + [pool release]; + + return (jlong) ((intptr_t) oldView); +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: setContentSize + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_setContentSize0 + (JNIEnv *env, jobject unused, jlong window, jint w, jint h) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + NSSize sz = NSMakeSize(w, h); + [win setContentSize: sz]; + [pool release]; +} + +/* + * Class: jogamp_newt_macosx_MacWindow + * Method: setFrameTopLeftPoint + * Signature: (JII)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_macosx_MacWindow_setFrameTopLeftPoint0 + (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* pwin = (NSWindow*) ((intptr_t) parent); + NSWindow* win = (NSWindow*) ((intptr_t) window); + setFrameTopLeftPoint(pwin, win, x, y); + [pool release]; +} + |