diff --git a/src/native/macosx/context.h b/src/native/macosx/context.h index ec0b7d73..2a3233a9 100644 --- a/src/native/macosx/context.h +++ b/src/native/macosx/context.h @@ -62,15 +62,16 @@ typedef struct { jobject jdisplay; jobject jmouse; jobject jkeyboard; + jboolean fullscreen; + jboolean undecorated; + jboolean resizable; + jboolean parented; + jboolean resized; + } MacOSXWindowInfo; -@interface MacOSXKeyableWindow : NSWindow - -- (BOOL)canBecomeKeyWindow; -@end - @interface MacOSXOpenGLView : NSView { @public @@ -128,5 +129,11 @@ typedef struct { GLLayer *glLayer; } MacOSXPeerInfo; +@interface MacOSXKeyableWindow : NSWindow ++ (void)createWindow; ++ (void)destroyWindow; +- (BOOL)canBecomeKeyWindow; +@end + NSOpenGLPixelFormat *choosePixelFormat(JNIEnv *env, jobject pixel_format, bool gl32, bool use_display_bpp, bool support_window, bool support_pbuffer, bool double_buffered); #endif diff --git a/src/native/macosx/org_lwjgl_opengl_Display.m b/src/native/macosx/org_lwjgl_opengl_Display.m index 408bd96a..508ceaad 100644 --- a/src/native/macosx/org_lwjgl_opengl_Display.m +++ b/src/native/macosx/org_lwjgl_opengl_Display.m @@ -53,7 +53,115 @@ static NSOpenGLPixelFormat *default_format = nil; static NSAutoreleasePool *pool; +static MacOSXPeerInfo *peer_info; + @implementation MacOSXKeyableWindow + ++ (void) createWindow { + MacOSXWindowInfo *window_info = peer_info->window_info; + + int width = window_info->display_rect.size.width; + int height = window_info->display_rect.size.height; + + NSRect view_rect = NSMakeRect(0.0, 0.0, width, height); + window_info->view = [[MacOSXOpenGLView alloc] initWithFrame:view_rect pixelFormat:peer_info->pixel_format]; + [window_info->view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + + // set nsapp delegate for catching app quit events + [NSApp setDelegate:window_info->view]; + + if (window_info->context != nil) { + [window_info->view setOpenGLContext:window_info->context]; + } + + if (!window_info->fullscreen) { + + if (window_info->parented) { + if (peer_info->isCALayer) { + window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; + [window_info->window setContentView:window_info->view]; + } + else { + window_info->window = [peer_info->parent window]; + [peer_info->parent addSubview:window_info->view]; + } + } + else { + + int default_window_mask = NSBorderlessWindowMask; // undecorated + + if (!window_info->undecorated) { + default_window_mask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; + } + + if (window_info->resizable) { + default_window_mask |= NSResizableWindowMask; + } + + window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:default_window_mask backing:NSBackingStoreBuffered defer:NO]; + + [window_info->window setContentView:window_info->view]; + [window_info->window setContentView:window_info->view]; // call twice to fix issue + + // set NSView as delegate of NSWindow to get windowShouldClose events + [window_info->window setDelegate:window_info->view]; + } + + // disable any fixed backbuffer size to allow resizing + CGLContextObj cgcontext = (CGLContextObj)[[window_info->view openGLContext] CGLContextObj]; + CGLDisable(cgcontext, kCGLCESurfaceBackingSize); + } + else { + // set a fixed backbuffer size for fullscreen + CGLContextObj cgcontext = (CGLContextObj)[window_info->context CGLContextObj]; + GLint dim[2] = {width, height}; + CGLSetParameter(cgcontext, kCGLCPSurfaceBackingSize, dim); + CGLEnable(cgcontext, kCGLCESurfaceBackingSize); + + // enter fullscreen mode + [window_info->view enterFullScreenMode: [NSScreen mainScreen] withOptions: nil ]; + window_info->window = [window_info->view window]; + + // adjust the NSView bounds to correct mouse coordinates in fullscreen + NSSize windowSize = [window_info->window frame].size; + NSSize newBounds = NSMakeSize(windowSize.width/width*windowSize.width, windowSize.height/height*windowSize.height); + [window_info->view setBoundsSize:newBounds]; + } + + // Inform the view of its parent window info; + [window_info->view setParent:window_info]; + + if (!window_info->fullscreen && peer_info->isCALayer) { + // hidden window when using CALayer + [window_info->window orderOut:nil]; + } + else { + [window_info->window makeFirstResponder:window_info->view]; + [window_info->window setInitialFirstResponder:window_info->view]; + [window_info->window makeKeyAndOrderFront:[NSApplication sharedApplication]]; + } +} + ++ (void) destroyWindow { + + MacOSXWindowInfo *window_info = peer_info->window_info; + + if (window_info->fullscreen) { + [window_info->view exitFullScreenModeWithOptions: nil]; + } + else { + if (window_info->window != nil) { + // if the nsview has no parent then close window + if ([window_info->window contentView] == window_info->view) { + [window_info->window close]; + } + + // release the nsview and remove it from any parent nsview + [window_info->view removeFromSuperviewWithoutNeedingDisplay]; + } + } +} + - (BOOL)canBecomeKeyWindow; { return YES; @@ -473,130 +581,36 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nCreateWindow(JNIE } } - pool = [[NSAutoreleasePool alloc] init]; - + peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); - MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle); - - NSRect view_rect = NSMakeRect(0.0, 0.0, width, height); - window_info->view = [[MacOSXOpenGLView alloc] initWithFrame:view_rect pixelFormat:peer_info->pixel_format]; - [window_info->view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - // set nsapp delegate for catching app quit events - [NSApp setDelegate:window_info->view]; - - if (window_info->context != nil) { - [window_info->view setOpenGLContext:window_info->context]; - } - - window_info->display_rect = NSMakeRect(x, y, width, height); - - if (!fullscreen) { - - if (parented) { - if (peer_info->isCALayer) { - window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; - [window_info->window setContentView:window_info->view]; - } - else { - window_info->window = [peer_info->parent window]; - [peer_info->parent addSubview:window_info->view]; - - if (window_info->jdisplay == NULL) { - window_info->jdisplay = (*env)->NewGlobalRef(env, this); - } - } - } - else { - - int default_window_mask = NSBorderlessWindowMask; // undecorated - - if (!undecorated) { - default_window_mask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; - } - - if (resizable) { - default_window_mask |= NSResizableWindowMask; - } - - window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:default_window_mask backing:NSBackingStoreBuffered defer:NO]; - - [window_info->window setContentView:window_info->view]; - - // Cache the necessary info for window-close callbacks into the JVM - if (window_info->jdisplay == NULL) { - window_info->jdisplay = (*env)->NewGlobalRef(env, this); - } - - // set NSView as delegate of NSWindow to get windowShouldClose events - [window_info->window setDelegate:window_info->view]; - } - - // disable any fixed backbuffer size to allow resizing - CGLContextObj cgcontext = (CGLContextObj)[[window_info->view openGLContext] CGLContextObj]; - CGLDisable(cgcontext, kCGLCESurfaceBackingSize); - } - else { - // Cache the necessary info for window-close callbacks into the JVM - if (window_info->jdisplay == NULL) { - window_info->jdisplay = (*env)->NewGlobalRef(env, this); - } - - // set a fixed backbuffer size for fullscreen - CGLContextObj cgcontext = (CGLContextObj)[window_info->context CGLContextObj]; - GLint dim[2] = {width, height}; - CGLSetParameter(cgcontext, kCGLCPSurfaceBackingSize, dim); - CGLEnable(cgcontext, kCGLCESurfaceBackingSize); - - // enter fullscreen mode - [window_info->view enterFullScreenMode: [NSScreen mainScreen] withOptions: nil ]; - window_info->window = [window_info->view window]; - - // adjust the NSView bounds to correct mouse coordinates in fullscreen - NSSize windowSize = [window_info->window frame].size; - NSSize newBounds = NSMakeSize(windowSize.width/width*windowSize.width, windowSize.height/height*windowSize.height); - [window_info->view setBoundsSize:newBounds]; - } - - // Inform the view of its parent window info; - [window_info->view setParent:window_info]; - - if (!fullscreen && peer_info->isCALayer) { - // hidden window when using CALayer - [window_info->window orderOut:nil]; - } - else { - [window_info->window performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:window_info->view waitUntilDone:NO]; - [window_info->window performSelectorOnMainThread:@selector(setInitialFirstResponder:) withObject:window_info->view waitUntilDone:NO]; - [window_info->window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:[NSApplication sharedApplication] waitUntilDone:NO]; - } window_info->fullscreen = fullscreen; + window_info->undecorated = undecorated; + window_info->resizable = resizable; + window_info->parented = parented; peer_info->window_info = window_info; - peer_info->isWindowed = true; + window_info->display_rect = NSMakeRect(x, y, width, height); + + // Cache the necessary info for window-close callbacks into the JVM + if (!peer_info->isCALayer && window_info->jdisplay == NULL) { + window_info->jdisplay = (*env)->NewGlobalRef(env, this); + } + + pool = [[NSAutoreleasePool alloc] init]; + + // create window on main thread + [MacOSXKeyableWindow performSelectorOnMainThread:@selector(createWindow) withObject:nil waitUntilDone:YES]; + return window_handle; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nDestroyWindow(JNIEnv *env, jobject this, jobject window_handle) { - MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle); - if (window_info->fullscreen) { - [window_info->view exitFullScreenModeWithOptions: nil]; - } - else { - if (window_info->window != nil) { - // if the nsview has no parent then close window - if ([window_info->window contentView] == window_info->view) { - [window_info->window performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:YES]; - } - - // release the nsview and remove it from any parent nsview using main thread - [window_info->view performSelectorOnMainThread:@selector(removeFromSuperviewWithoutNeedingDisplay) withObject:window_info->view waitUntilDone:YES]; - } - } + // destroy window on main thread + [MacOSXKeyableWindow performSelectorOnMainThread:@selector(destroyWindow) withObject:nil waitUntilDone:YES]; [pool drain]; } diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXNativeMouse.m b/src/native/macosx/org_lwjgl_opengl_MacOSXNativeMouse.m index 208496d0..3139ecf5 100644 --- a/src/native/macosx/org_lwjgl_opengl_MacOSXNativeMouse.m +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXNativeMouse.m @@ -157,10 +157,10 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeMouse_nDestroyCursor(JN JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXNativeMouse_nSetCursor(JNIEnv *env, jobject _this, jlong cursor_pointer) { if (cursor_pointer == 0) { // restore default cursor - [[NSCursor arrowCursor] set]; + [[NSCursor arrowCursor] performSelectorOnMainThread:@selector(set) withObject:nil waitUntilDone:NO]; } else { NSCursor *cursor = (NSCursor *)cursor_pointer; - [cursor set]; + [cursor performSelectorOnMainThread:@selector(set) withObject:nil waitUntilDone:NO]; } }