2004-11-15 09:38:00 -05:00
|
|
|
/*
|
2008-04-07 14:42:36 -04:00
|
|
|
* Copyright (c) 2002-2008 LWJGL Project
|
2004-11-15 09:38:00 -05:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* * Redistributions 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 'LWJGL' nor the names of
|
|
|
|
* its contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* $Id$
|
|
|
|
*
|
2005-02-23 06:11:08 -05:00
|
|
|
* Mac OS X specific display functions.
|
2004-11-15 09:38:00 -05:00
|
|
|
*
|
|
|
|
* @author elias_naur <elias_naur@users.sourceforge.net>
|
2013-04-21 10:37:02 -04:00
|
|
|
* @author mojang
|
|
|
|
* @author kappaOne <one.kappa@gmail.com>
|
2004-11-15 09:38:00 -05:00
|
|
|
* @version $Revision$
|
|
|
|
*/
|
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
#import <AppKit/NSApplication.h>
|
2004-11-15 09:38:00 -05:00
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
#import <Carbon/Carbon.h>
|
|
|
|
#import <jni.h>
|
|
|
|
#import <unistd.h>
|
|
|
|
#import "common_tools.h"
|
2008-02-19 09:06:48 -05:00
|
|
|
#import "org_lwjgl_opengl_MacOSXDisplay.h"
|
2008-04-30 10:58:47 -04:00
|
|
|
#import "org_lwjgl_MacOSXSysImplementation.h"
|
2012-11-01 16:54:17 -04:00
|
|
|
#import "context.h"
|
2004-11-15 09:38:00 -05:00
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
static NSOpenGLPixelFormat *default_format = nil;
|
|
|
|
|
2012-11-01 18:39:22 -04:00
|
|
|
static NSAutoreleasePool *pool;
|
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
static MacOSXPeerInfo *peer_info;
|
|
|
|
|
2013-10-28 19:51:44 -04:00
|
|
|
static bool leftMouseDown = false;
|
|
|
|
static bool rightMouseDown = false;
|
|
|
|
|
2013-11-02 20:17:37 -04:00
|
|
|
static NSUInteger lastModifierFlags = 0;
|
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
@implementation MacOSXKeyableWindow
|
2013-02-15 16:35:12 -05:00
|
|
|
|
|
|
|
+ (void) createWindow {
|
|
|
|
MacOSXWindowInfo *window_info = peer_info->window_info;
|
2013-02-15 16:49:19 -05:00
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
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) {
|
2013-03-12 20:51:32 -04:00
|
|
|
window_info->window = [peer_info->parent window];
|
|
|
|
[peer_info->parent addSubview:window_info->view];
|
2013-02-15 16:35:12 -05:00
|
|
|
}
|
|
|
|
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];
|
2013-11-06 18:41:16 -05:00
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
// 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];
|
|
|
|
|
2013-11-09 21:14:55 -05:00
|
|
|
if (window_info->enableFullscreenModeAPI && window_info->resizable) {
|
2013-11-06 18:41:16 -05:00
|
|
|
// manually create OS X 10.7+ mask to allow compilation on previous OS X versions
|
|
|
|
NSUInteger NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7;
|
|
|
|
[window_info->window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
|
|
|
}
|
|
|
|
|
2013-03-12 20:51:32 -04:00
|
|
|
[window_info->window makeFirstResponder:window_info->view];
|
|
|
|
[window_info->window setInitialFirstResponder:window_info->view];
|
|
|
|
[window_info->window makeKeyAndOrderFront:[NSApplication sharedApplication]];
|
2013-02-15 16:35:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
+ (void) destroyWindow {
|
|
|
|
MacOSXWindowInfo *window_info = peer_info->window_info;
|
|
|
|
|
|
|
|
if (window_info->fullscreen) {
|
|
|
|
[window_info->view exitFullScreenModeWithOptions: nil];
|
2013-03-12 20:51:32 -04:00
|
|
|
window_info->window = nil;
|
2013-02-15 16:35:12 -05:00
|
|
|
}
|
|
|
|
else {
|
2013-03-12 20:51:32 -04:00
|
|
|
if (peer_info->isCALayer) {
|
2013-04-13 21:14:32 -04:00
|
|
|
peer_info->isCALayer = false;
|
|
|
|
[peer_info->glLayer removeLayer];
|
|
|
|
[peer_info->glLayer release];
|
|
|
|
peer_info->glLayer = nil;
|
|
|
|
return;
|
2013-03-12 20:51:32 -04:00
|
|
|
}
|
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
if (window_info->window != nil) {
|
|
|
|
// if the nsview has no parent then close window
|
|
|
|
if ([window_info->window contentView] == window_info->view) {
|
2013-02-20 17:20:23 -05:00
|
|
|
// release the nsview and remove it from any parent nsview
|
|
|
|
[window_info->view removeFromSuperviewWithoutNeedingDisplay];
|
2013-02-15 16:35:12 -05:00
|
|
|
[window_info->window close];
|
2013-03-12 20:51:32 -04:00
|
|
|
window_info->window = nil;
|
2013-02-15 16:35:12 -05:00
|
|
|
}
|
2013-02-20 17:20:23 -05:00
|
|
|
else {
|
|
|
|
// release the nsview and remove it from any parent nsview
|
|
|
|
[window_info->view removeFromSuperviewWithoutNeedingDisplay];
|
|
|
|
}
|
2013-02-15 16:35:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
- (BOOL)canBecomeKeyWindow;
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation MacOSXOpenGLView
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
+ (NSOpenGLPixelFormat*)defaultPixelFormat {
|
|
|
|
NSOpenGLPixelFormatAttribute defaultAttribs[] = {
|
2012-12-18 17:10:44 -05:00
|
|
|
NSOpenGLPFADoubleBuffer,
|
|
|
|
NSOpenGLPFADepthSize, 16,
|
|
|
|
NSOpenGLPFAColorSize, 32,
|
|
|
|
0
|
|
|
|
};
|
2012-12-16 12:50:48 -05:00
|
|
|
if (default_format == nil) {
|
|
|
|
default_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:defaultAttribs];
|
2012-12-18 17:10:44 -05:00
|
|
|
}
|
|
|
|
return default_format;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-11-09 19:42:34 -05:00
|
|
|
- (BOOL)windowShouldClose:(id)sender {
|
|
|
|
if (_parent != nil) {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
|
|
|
jclass display_class = (*env)->GetObjectClass(env, _parent->jdisplay);
|
|
|
|
jmethodID close_callback = (*env)->GetMethodID(env, display_class, "doHandleQuit", "()V");
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jdisplay, close_callback);
|
|
|
|
}
|
2012-11-09 19:42:34 -05:00
|
|
|
return NO;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2013-02-07 16:55:53 -05:00
|
|
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
|
|
|
|
[self windowShouldClose:nil];
|
|
|
|
return NSTerminateCancel;
|
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format {
|
|
|
|
self = [super initWithFrame:frameRect];
|
|
|
|
if (self != nil) {
|
|
|
|
_pixelFormat = [format retain];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
2012-12-18 17:10:44 -05:00
|
|
|
selector:@selector(_surfaceNeedsUpdate:)
|
|
|
|
name:NSViewGlobalFrameDidChangeNotification
|
|
|
|
object:self];
|
|
|
|
}
|
|
|
|
return self;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (void) _surfaceNeedsUpdate:(NSNotification*)notification {
|
2012-12-18 17:10:44 -05:00
|
|
|
[self update];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (void)setOpenGLContext:(NSOpenGLContext*)context {
|
2012-12-18 17:10:44 -05:00
|
|
|
_openGLContext = context;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (NSOpenGLContext*)openGLContext {
|
2012-12-18 17:10:44 -05:00
|
|
|
return _openGLContext;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (void)clearGLContext {
|
|
|
|
[_openGLContext release];
|
|
|
|
_openGLContext = nil;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (void)prepareOpenGL {
|
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (void)update {
|
|
|
|
[_openGLContext update];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (void)lockFocus {
|
|
|
|
[super lockFocus];
|
|
|
|
|
|
|
|
NSOpenGLContext* context = [self openGLContext];
|
|
|
|
|
|
|
|
if (context == nil) return;
|
|
|
|
|
2012-12-03 16:39:54 -05:00
|
|
|
if ([context view] != self) {
|
2012-12-16 12:50:48 -05:00
|
|
|
[context setView:self];
|
|
|
|
}
|
|
|
|
|
|
|
|
[context makeCurrentContext];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (void)setPixelFormat:(NSOpenGLPixelFormat*)pixelFormat {
|
|
|
|
_pixelFormat = [pixelFormat retain];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 12:50:48 -05:00
|
|
|
- (NSOpenGLPixelFormat*)pixelFormat {
|
|
|
|
return _pixelFormat;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)acceptsFirstResponder {
|
2012-12-16 12:50:48 -05:00
|
|
|
return YES;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setParent:(MacOSXWindowInfo*)parent {
|
2012-12-16 12:50:48 -05:00
|
|
|
_parent = parent;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)keyDown:(NSEvent *)event {
|
2012-12-16 12:50:48 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass keyboard_class = (*env)->GetObjectClass(env, _parent->jkeyboard);
|
2013-10-13 10:45:08 -04:00
|
|
|
jmethodID keydown = (*env)->GetMethodID(env, keyboard_class, "keyPressed", "(ILjava/lang/String;J)V");
|
|
|
|
|
|
|
|
// convert key characters from NSString to jstring
|
|
|
|
const char *unichars = [[event characters] UTF8String];
|
|
|
|
jstring characters = (*env)->NewStringUTF(env, unichars);
|
|
|
|
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jkeyboard, keydown, [event keyCode], characters, time);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)keyUp:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass keyboard_class = (*env)->GetObjectClass(env, _parent->jkeyboard);
|
2013-10-13 10:45:08 -04:00
|
|
|
jmethodID keyup = (*env)->GetMethodID(env, keyboard_class, "keyReleased", "(ILjava/lang/String;J)V");
|
|
|
|
|
|
|
|
// convert key characters from NSString to jstring
|
|
|
|
const char *unichars = [[event characters] UTF8String];
|
|
|
|
jstring characters = (*env)->NewStringUTF(env, unichars);
|
|
|
|
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jkeyboard, keyup, [event keyCode], characters, time);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)flagsChanged:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
|
2013-11-02 20:17:37 -04:00
|
|
|
NSUInteger modifierFlags = [event modifierFlags];
|
|
|
|
unsigned short keyCode = [event keyCode];
|
|
|
|
|
2012-12-18 17:10:44 -05:00
|
|
|
NSUInteger mask = ~0;
|
2013-11-02 20:17:37 -04:00
|
|
|
|
|
|
|
switch(keyCode) {
|
|
|
|
case kVK_Control : mask = NSControlLeftKeyMask; break;
|
|
|
|
case kVK_Shift : mask = NSShiftLeftKeyMask; break;
|
|
|
|
case kVK_RightShift : mask = NSShiftRightKeyMask; break;
|
|
|
|
case kVK_Command : mask = NSCommandLeftKeyMask; break;
|
|
|
|
case 0x36 : mask = NSCommandRightKeyMask; break; // Should be: kVK_RightCommand -- missing O.o
|
|
|
|
case kVK_Option : mask = NSAlternateLeftKeyMask; break;
|
|
|
|
case kVK_RightOption : mask = NSAlternateRightKeyMask; break;
|
|
|
|
case kVK_RightControl: mask = NSControlRightKeyMask; break;
|
2012-12-18 17:10:44 -05:00
|
|
|
case kVK_CapsLock : mask = NSAlphaShiftKeyMask; break;
|
|
|
|
case kVK_Function : mask = NSFunctionKeyMask; break;
|
|
|
|
// case 0x?? : mask = NSNumericPadKeyMask; break; // Didn't have the keycode for this one :(
|
|
|
|
default:
|
2013-11-02 20:17:37 -04:00
|
|
|
// key code not specified when left Command key + Tab moves focus to another Window, therefore manually detect and specify correct key code
|
|
|
|
if (((lastModifierFlags & NSCommandLeftKeyMask) == NSCommandLeftKeyMask) && ((modifierFlags & NSCommandLeftKeyMask) != NSCommandLeftKeyMask)) {
|
|
|
|
keyCode = kVK_Command; // left command key code
|
|
|
|
}
|
|
|
|
// key code not specified when right Command key + Tab moves focus to another Window, therefore manually detect and specify correct key code
|
|
|
|
else if (((lastModifierFlags & NSCommandLeftKeyMask) == NSCommandLeftKeyMask) && ((modifierFlags & NSCommandLeftKeyMask) != NSCommandLeftKeyMask)) {
|
|
|
|
keyCode = 0x36; // right command key code
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NSLog(@"Unknown modifier with keycode: %d\n", [event keyCode]);
|
|
|
|
return;
|
|
|
|
}
|
2012-12-18 17:10:44 -05:00
|
|
|
}
|
|
|
|
|
2013-11-02 20:17:37 -04:00
|
|
|
// save current modifierFlags for next use
|
|
|
|
lastModifierFlags = [event modifierFlags];
|
|
|
|
|
2012-12-18 17:10:44 -05:00
|
|
|
jclass keyboard_class = (*env)->GetObjectClass(env, _parent->jkeyboard);
|
|
|
|
|
|
|
|
jmethodID keyMethod;
|
2013-11-02 20:17:37 -04:00
|
|
|
if ((modifierFlags & mask) == mask) {
|
2013-10-13 10:45:08 -04:00
|
|
|
keyMethod = (*env)->GetMethodID(env, keyboard_class, "keyPressed", "(ILjava/lang/String;J)V");
|
2012-12-18 17:10:44 -05:00
|
|
|
} else {
|
2013-10-13 10:45:08 -04:00
|
|
|
keyMethod = (*env)->GetMethodID(env, keyboard_class, "keyReleased", "(ILjava/lang/String;J)V");
|
2012-12-18 17:10:44 -05:00
|
|
|
}
|
|
|
|
|
2013-11-02 20:17:37 -04:00
|
|
|
(*env)->CallVoidMethod(env, _parent->jkeyboard, keyMethod, keyCode, NULL, time);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseButtonState:(NSEvent *)event :(int)button :(int)state {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jkeyboard == nil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse);
|
|
|
|
jmethodID mousebutton = (*env)->GetMethodID(env, mouse_class, "setButton", "(IIJ)V");
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jmouse, mousebutton, button, state, time);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseDown:(NSEvent *)event {
|
2013-10-28 19:51:44 -04:00
|
|
|
if ([event modifierFlags] & NSControlKeyMask) {
|
|
|
|
rightMouseDown = true;
|
|
|
|
[self rightMouseDown:event];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
leftMouseDown = true;
|
2012-12-18 17:10:44 -05:00
|
|
|
[self mouseButtonState:event :0 :1];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)rightMouseDown:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
[self mouseButtonState:event :1 :1];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)otherMouseDown:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
[self mouseButtonState:event :2 :1];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseUp:(NSEvent *)event {
|
2013-10-28 19:51:44 -04:00
|
|
|
if (rightMouseDown) {
|
|
|
|
rightMouseDown = false;
|
|
|
|
[self rightMouseUp:event];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (leftMouseDown) {
|
|
|
|
leftMouseDown = false;
|
|
|
|
[self mouseButtonState:event :0 :0];
|
|
|
|
}
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)rightMouseUp:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
[self mouseButtonState:event :1 :0];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)otherMouseUp:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
[self mouseButtonState:event :2 :0];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseDragged:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
2013-02-03 11:39:02 -05:00
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jmouse == nil) {
|
2012-12-18 17:10:44 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse);
|
|
|
|
jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V");
|
|
|
|
NSPoint loc = [self convertPoint:[event locationInWindow] toView:nil];
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], 0.0f, time);
|
2012-11-14 16:06:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)rightMouseDragged:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
2013-02-03 11:39:02 -05:00
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jmouse == nil) {
|
2012-12-18 17:10:44 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse);
|
|
|
|
jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V");
|
|
|
|
NSPoint loc = [self convertPoint:[event locationInWindow] toView:nil];
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], 0.0f, time);
|
2012-11-14 16:06:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)otherMouseDragged:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
2013-02-03 11:39:02 -05:00
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jmouse == nil) {
|
2012-12-18 17:10:44 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse);
|
|
|
|
jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V");
|
|
|
|
NSPoint loc = [self convertPoint:[event locationInWindow] toView:nil];
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], 0.0f, time);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseMoved:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
|
|
|
if (env == nil || event == nil || _parent == nil || _parent->jmouse == nil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse);
|
|
|
|
jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V");
|
|
|
|
NSPoint loc = [self convertPoint:[event locationInWindow] toView:nil];
|
2012-11-25 15:14:48 -05:00
|
|
|
(*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], 0.0f, time);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)scrollWheel:(NSEvent *)event {
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
|
|
|
if (env == nil || event == nil || _parent == nil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
long time = [event timestamp] * 1000000000;
|
|
|
|
jclass mouse_class = (*env)->GetObjectClass(env, _parent->jmouse);
|
|
|
|
jmethodID mousemove = (*env)->GetMethodID(env, mouse_class, "mouseMoved", "(FFFFFJ)V");
|
|
|
|
NSPoint loc = [self convertPoint:[event locationInWindow] toView:nil];
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jmouse, mousemove, loc.x, loc.y, [event deltaX], [event deltaY], 1.0f, time);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-18 17:10:44 -05:00
|
|
|
- (void)viewDidMoveToWindow {
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(windowResized:)
|
|
|
|
name:NSWindowDidResizeNotification
|
|
|
|
object:[self window]];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
[super dealloc];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-18 17:10:44 -05:00
|
|
|
- (void)windowResized:(NSNotification *)notification;
|
2012-11-01 16:54:17 -04:00
|
|
|
{
|
2012-12-18 17:10:44 -05:00
|
|
|
if (_parent != nil) {
|
2013-02-02 15:30:12 -05:00
|
|
|
_parent->display_rect = [self frame];
|
2012-12-18 17:10:44 -05:00
|
|
|
_parent->resized = JNI_TRUE;
|
|
|
|
}
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
2012-11-25 15:34:45 -05:00
|
|
|
|
2013-01-24 19:28:26 -05:00
|
|
|
-(void)updateTrackingAreas {
|
|
|
|
if(_trackingArea != nil) {
|
|
|
|
[self removeTrackingArea:_trackingArea];
|
|
|
|
[_trackingArea release];
|
|
|
|
}
|
|
|
|
|
2013-01-27 18:01:21 -05:00
|
|
|
int options = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
|
2013-01-24 19:28:26 -05:00
|
|
|
_trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
|
|
|
|
options:options
|
|
|
|
owner:self
|
|
|
|
userInfo:nil];
|
|
|
|
[self addTrackingArea:_trackingArea];
|
2013-02-03 13:58:00 -05:00
|
|
|
|
|
|
|
// since nstrackingarea's don't know if mouse is inside or outside on creation
|
|
|
|
// manually detect this and send a fake mouse entered/exited message
|
|
|
|
NSPoint mouseLocation = [[self window] mouseLocationOutsideOfEventStream];
|
|
|
|
mouseLocation = [self convertPoint:mouseLocation fromView:nil];
|
|
|
|
|
|
|
|
if (NSPointInRect(mouseLocation, [self bounds])) {
|
2013-02-03 15:54:27 -05:00
|
|
|
[self mouseEntered:nil];
|
2013-02-03 13:58:00 -05:00
|
|
|
}
|
|
|
|
else {
|
2013-02-03 15:54:27 -05:00
|
|
|
[self mouseExited:nil];
|
2013-02-03 13:58:00 -05:00
|
|
|
}
|
2013-01-24 19:28:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
-(void)mouseEntered:(NSEvent *)event {
|
2013-01-27 18:01:21 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
2013-02-03 13:58:00 -05:00
|
|
|
if (env == nil || _parent == nil || _parent->jdisplay == nil) {
|
2013-01-27 18:01:21 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
jclass display_class = (*env)->GetObjectClass(env, _parent->jdisplay);
|
2013-02-15 16:49:19 -05:00
|
|
|
jmethodID mouseInsideWindow_callback = (*env)->GetMethodID(env, display_class, "mouseInsideWindow", "(Z)V");
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jdisplay, mouseInsideWindow_callback, JNI_TRUE);
|
2013-01-24 19:28:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
-(void)mouseExited:(NSEvent *)event {
|
2013-01-27 18:01:21 -05:00
|
|
|
JNIEnv *env = attachCurrentThread();
|
2013-02-03 13:58:00 -05:00
|
|
|
if (env == nil || _parent == nil || _parent->jdisplay == nil) {
|
2013-01-27 18:01:21 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
jclass display_class = (*env)->GetObjectClass(env, _parent->jdisplay);
|
2013-02-15 16:49:19 -05:00
|
|
|
jmethodID mouseInsideWindow_callback = (*env)->GetMethodID(env, display_class, "mouseInsideWindow", "(Z)V");
|
|
|
|
(*env)->CallVoidMethod(env, _parent->jdisplay, mouseInsideWindow_callback, JNI_FALSE);
|
2013-01-24 19:28:26 -05:00
|
|
|
}
|
|
|
|
|
2012-11-29 20:02:04 -05:00
|
|
|
- (void) drawRect:(NSRect)rect {
|
2012-11-25 15:34:45 -05:00
|
|
|
// set black as the default background color
|
|
|
|
// for the nsview to avoid white flash on fullscreen
|
2012-12-18 17:10:44 -05:00
|
|
|
[[NSColor blackColor] setFill];
|
|
|
|
NSRectFill(rect);
|
2012-11-25 15:34:45 -05:00
|
|
|
}
|
2012-11-01 16:54:17 -04:00
|
|
|
@end
|
|
|
|
|
|
|
|
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nIsMiniaturized(JNIEnv *env, jobject this, jobject window_handle) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-18 17:10:44 -05:00
|
|
|
return (jboolean)[window_info->window isMiniaturized];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nIsFocused(JNIEnv *env, jobject this, jobject window_handle) {
|
2012-12-18 17:10:44 -05:00
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-16 11:19:44 -05:00
|
|
|
// Display is focused if nswindow is key window and nsview is first responder in that nswindow
|
2012-12-18 17:10:44 -05:00
|
|
|
return (jboolean)([[window_info->view window] isKeyWindow] && [[window_info->view window] firstResponder] == window_info->view);
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nResizeWindow(JNIEnv *env, jobject this, jobject window_handle, jint x, jint y, jint width, jint height) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-18 17:10:44 -05:00
|
|
|
window_info->display_rect = NSMakeRect(x, y, width, height);
|
|
|
|
[window_info->window setFrame:window_info->display_rect display:false];
|
|
|
|
[window_info->view update];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nWasResized(JNIEnv *env, jobject this, jobject window_handle) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-04 17:45:47 -05:00
|
|
|
jboolean was_resized = window_info->resized;
|
|
|
|
window_info->resized = JNI_FALSE;
|
|
|
|
return was_resized;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-11-11 13:43:14 -05:00
|
|
|
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nGetWidth(JNIEnv *env, jobject this, jobject window_handle) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-04 17:45:47 -05:00
|
|
|
jint width = window_info->display_rect.size.width;
|
|
|
|
return width;
|
2012-11-11 13:43:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nGetHeight(JNIEnv *env, jobject this, jobject window_handle) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-04 17:45:47 -05:00
|
|
|
jint height = window_info->display_rect.size.height;
|
|
|
|
return height;
|
2012-11-11 13:43:14 -05:00
|
|
|
}
|
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nSetResizable(JNIEnv *env, jobject this, jobject window_handle, jboolean resizable) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-18 17:10:44 -05:00
|
|
|
NSUInteger style_mask = [window_info->window styleMask];
|
|
|
|
if (resizable == true) {
|
|
|
|
style_mask |= NSResizableWindowMask;
|
|
|
|
} else {
|
|
|
|
style_mask &= ~NSResizableWindowMask;
|
|
|
|
}
|
|
|
|
[window_info->window setStyleMask:style_mask];
|
2013-11-09 21:14:55 -05:00
|
|
|
|
|
|
|
if (window_info->enableFullscreenModeAPI) {
|
|
|
|
if (resizable) {
|
|
|
|
// manually create OS X 10.7+ mask to allow compilation on previous OS X versions
|
|
|
|
NSUInteger NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7;
|
|
|
|
[window_info->window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// manually create OS X 10.7+ mask to allow compilation on previous OS X versions
|
|
|
|
NSUInteger NSFullScreenWindowMask = 1 << 14;
|
|
|
|
// on disabling resizing exit fullscreen mode exit otherwise will be stuck in it
|
|
|
|
if ((style_mask & NSFullScreenWindowMask) == NSFullScreenWindowMask) {
|
|
|
|
// call method using runtime selector as its a 10.7+ api and allows compiling on older SDK's
|
|
|
|
[window_info->window performSelector:NSSelectorFromString(@"toggleFullScreen:") withObject:nil];
|
|
|
|
}
|
|
|
|
[window_info->window setCollectionBehavior:NSWindowCollectionBehaviorDefault];
|
|
|
|
}
|
|
|
|
}
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-12-16 11:02:40 -05:00
|
|
|
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nGetX(JNIEnv *env, jobject this, jobject window_handle) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
|
|
|
jint x = [[window_info->view window] frame].origin.x;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nGetY(JNIEnv *env, jobject this, jobject window_handle) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
|
|
|
|
2012-12-25 09:00:09 -05:00
|
|
|
NSRect screenRect = [[window_info->window screen] frame];
|
2012-12-16 11:02:40 -05:00
|
|
|
NSRect winRect = [[window_info->view window] frame];
|
|
|
|
|
|
|
|
// get top corner of window frame, also flip coords so origin is in top left
|
|
|
|
jint y = screenRect.size.height - (winRect.origin.y + winRect.size.height) - 1;
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nSetTitle(JNIEnv *env, jobject this, jobject window_handle, jobject title_buffer) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
|
|
|
const char *title_cstr = (const char *)(*env)->GetDirectBufferAddress(env, title_buffer);
|
2012-12-18 17:10:44 -05:00
|
|
|
NSString *title = [[NSString alloc] initWithUTF8String:title_cstr];
|
2013-04-09 18:29:02 -04:00
|
|
|
[window_info->window performSelectorOnMainThread:@selector(setTitle:) withObject:title waitUntilDone:NO];
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2013-11-06 18:41:16 -05:00
|
|
|
JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nCreateWindow(JNIEnv *env, jobject this, jint x, jint y, jint width, jint height, jboolean fullscreen, jboolean undecorated, jboolean resizable, jboolean parented, jboolean enableFullscreenModeAPI, jobject peer_info_handle, jobject window_handle) {
|
2013-03-12 20:51:32 -04:00
|
|
|
|
|
|
|
pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
|
|
|
|
peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle);
|
|
|
|
|
|
|
|
if (peer_info->isCALayer && !fullscreen) {
|
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
|
|
|
window_info->fullscreen = fullscreen;
|
|
|
|
window_info->undecorated = undecorated;
|
|
|
|
window_info->parented = parented;
|
2013-11-06 18:41:16 -05:00
|
|
|
window_info->enableFullscreenModeAPI = enableFullscreenModeAPI;
|
2013-03-12 20:51:32 -04:00
|
|
|
|
|
|
|
return window_handle;
|
|
|
|
}
|
|
|
|
|
2012-12-18 17:10:44 -05:00
|
|
|
if (window_handle == NULL) {
|
|
|
|
window_handle = newJavaManagedByteBuffer(env, sizeof(MacOSXWindowInfo));
|
|
|
|
if (window_handle == NULL) {
|
|
|
|
throwException(env, "Could not create handle buffer");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2012-11-01 18:39:22 -04:00
|
|
|
|
2012-11-01 16:54:17 -04:00
|
|
|
MacOSXWindowInfo *window_info = (MacOSXWindowInfo *)(*env)->GetDirectBufferAddress(env, window_handle);
|
2012-12-18 17:10:44 -05:00
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
window_info->fullscreen = fullscreen;
|
|
|
|
window_info->undecorated = undecorated;
|
|
|
|
window_info->resizable = resizable;
|
|
|
|
window_info->parented = parented;
|
2013-11-06 18:41:16 -05:00
|
|
|
window_info->enableFullscreenModeAPI = enableFullscreenModeAPI;
|
2013-02-02 15:30:12 -05:00
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
peer_info->window_info = window_info;
|
|
|
|
peer_info->isWindowed = true;
|
2013-02-07 16:55:53 -05:00
|
|
|
|
2013-05-08 19:30:38 -04:00
|
|
|
window_info->display_rect = NSMakeRect(x, [[NSScreen mainScreen] frame].size.height - y - height, width, height);
|
2012-11-25 10:07:20 -05:00
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
// Cache the necessary info for window-close callbacks into the JVM
|
2013-03-12 20:51:32 -04:00
|
|
|
if (window_info->jdisplay == NULL) {
|
2013-02-15 16:35:12 -05:00
|
|
|
window_info->jdisplay = (*env)->NewGlobalRef(env, this);
|
2013-01-13 10:34:24 -05:00
|
|
|
}
|
2012-11-25 10:07:20 -05:00
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
// create window on main thread
|
|
|
|
[MacOSXKeyableWindow performSelectorOnMainThread:@selector(createWindow) withObject:nil waitUntilDone:YES];
|
2013-02-12 16:41:47 -05:00
|
|
|
|
2012-12-18 17:10:44 -05:00
|
|
|
return window_handle;
|
2012-11-01 16:54:17 -04:00
|
|
|
}
|
|
|
|
|
2012-11-01 18:39:22 -04:00
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nDestroyWindow(JNIEnv *env, jobject this, jobject window_handle) {
|
2013-01-14 18:35:46 -05:00
|
|
|
|
2013-02-15 16:35:12 -05:00
|
|
|
// destroy window on main thread
|
|
|
|
[MacOSXKeyableWindow performSelectorOnMainThread:@selector(destroyWindow) withObject:nil waitUntilDone:YES];
|
2012-11-25 10:07:20 -05:00
|
|
|
|
2012-12-03 16:39:54 -05:00
|
|
|
[pool drain];
|
2012-11-01 18:39:22 -04:00
|
|
|
}
|
|
|
|
|
2013-01-14 18:35:46 -05:00
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nDestroyCALayer(JNIEnv *env, jobject this, jobject peer_info_handle) {
|
|
|
|
MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle);
|
|
|
|
if (peer_info->isCALayer) {
|
|
|
|
peer_info->isCALayer = false;
|
|
|
|
[peer_info->glLayer performSelectorOnMainThread:@selector(removeLayer) withObject:nil waitUntilDone:YES];
|
|
|
|
[peer_info->glLayer release];
|
2013-04-13 21:14:32 -04:00
|
|
|
peer_info->glLayer = nil;
|
2013-01-14 18:35:46 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-15 18:09:03 -05:00
|
|
|
JNIEXPORT jboolean JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nIsNativeMode(JNIEnv *env, jobject this, jobject peer_info_handle) {
|
|
|
|
MacOSXPeerInfo *peer_info = (MacOSXPeerInfo *)(*env)->GetDirectBufferAddress(env, peer_info_handle);
|
|
|
|
if (peer_info->isCALayer) {
|
|
|
|
return JNI_FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return JNI_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-08 18:29:15 -05:00
|
|
|
JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nGetCurrentDisplayMode(JNIEnv *env, jobject this) {
|
|
|
|
|
|
|
|
jclass displayClass = (*env)->GetObjectClass(env, this);
|
|
|
|
jmethodID createDisplayModeMethod = (*env)->GetMethodID(env, displayClass, "createDisplayMode", "(IIII)Ljava/lang/Object;");
|
2013-07-06 16:52:59 -04:00
|
|
|
|
2013-07-08 20:01:18 -04:00
|
|
|
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { // if OS X 10.6+ use newer api
|
2013-07-06 16:52:59 -04:00
|
|
|
|
2013-07-08 20:01:18 -04:00
|
|
|
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
|
2013-02-08 18:29:15 -05:00
|
|
|
|
2013-07-08 20:01:18 -04:00
|
|
|
int width = (int) CGDisplayModeGetWidth(mode);
|
|
|
|
int height = (int) CGDisplayModeGetHeight(mode);
|
|
|
|
int refreshRate = (int)CGDisplayModeGetRefreshRate(mode);
|
|
|
|
int bitsPerPixel;
|
|
|
|
|
|
|
|
// get bitsPerPixel
|
|
|
|
CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode);
|
|
|
|
|
|
|
|
if(CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
|
|
|
bitsPerPixel = 16;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bitsPerPixel = 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject displayMode = (*env)->CallObjectMethod(env, this, createDisplayModeMethod, width, height, bitsPerPixel, refreshRate);
|
|
|
|
|
|
|
|
return displayMode;
|
2013-07-06 16:52:59 -04:00
|
|
|
|
2013-07-08 20:01:18 -04:00
|
|
|
} else {
|
|
|
|
|
|
|
|
CFDictionaryRef mode = CGDisplayCurrentMode(CGMainDisplayID());
|
2013-07-06 16:52:59 -04:00
|
|
|
|
|
|
|
long bitsPerPixel = 0;
|
|
|
|
long width = 0;
|
|
|
|
long height = 0;
|
|
|
|
long refreshRate = 0;
|
|
|
|
|
|
|
|
CFNumberRef value;
|
|
|
|
|
2013-07-07 17:04:50 -04:00
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel);
|
2013-07-06 16:52:59 -04:00
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &bitsPerPixel);
|
|
|
|
|
2013-07-07 17:04:50 -04:00
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayWidth);
|
2013-07-06 16:52:59 -04:00
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &width);
|
|
|
|
|
2013-07-07 17:04:50 -04:00
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayHeight);
|
2013-07-06 16:52:59 -04:00
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &height);
|
|
|
|
|
2013-07-07 17:04:50 -04:00
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayRefreshRate);
|
2013-07-06 16:52:59 -04:00
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &refreshRate);
|
2013-07-08 20:01:18 -04:00
|
|
|
|
|
|
|
jobject displayMode = (*env)->CallObjectMethod(env, this, createDisplayModeMethod, width, height, bitsPerPixel, refreshRate);
|
|
|
|
|
|
|
|
return displayMode;
|
2013-07-06 16:52:59 -04:00
|
|
|
}
|
2013-07-08 20:01:18 -04:00
|
|
|
}
|
2013-07-06 16:52:59 -04:00
|
|
|
|
2013-07-08 20:01:18 -04:00
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nGetDisplayModes(JNIEnv *env, jobject this, jobject modesList) {
|
|
|
|
|
|
|
|
jclass displayClass = (*env)->GetObjectClass(env, this);
|
|
|
|
jmethodID addDisplayModeMethod = (*env)->GetMethodID(env, displayClass, "addDisplayMode", "(Ljava/lang/Object;IIII)V");
|
|
|
|
|
|
|
|
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) { // if OS X 10.6+ use newer api
|
|
|
|
|
|
|
|
CFArrayRef modes = CGDisplayCopyAllDisplayModes(kCGDirectMainDisplay, NULL);
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < CFArrayGetCount(modes); i++) {
|
|
|
|
CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(modes, i);
|
|
|
|
|
|
|
|
int width = (int) CGDisplayModeGetWidth(mode);
|
|
|
|
int height = (int) CGDisplayModeGetHeight(mode);
|
|
|
|
int refreshRate = (int)CGDisplayModeGetRefreshRate(mode);
|
|
|
|
int bitsPerPixel;
|
|
|
|
|
|
|
|
// get bitsPerPixel
|
|
|
|
CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode);
|
|
|
|
if(CFStringCompare(pixelEncoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
|
|
|
bitsPerPixel = 32;
|
|
|
|
}
|
|
|
|
else if(CFStringCompare(pixelEncoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
|
|
|
bitsPerPixel = 16;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
continue; // ignore DisplayMode of other bitsPerPixel rates
|
|
|
|
}
|
|
|
|
|
|
|
|
(*env)->CallVoidMethod(env, this, addDisplayModeMethod, modesList, width, height, bitsPerPixel, refreshRate);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
CFArrayRef modes = CGDisplayAvailableModes(CGMainDisplayID());
|
|
|
|
CFIndex index, count;
|
|
|
|
CFDictionaryRef mode;
|
|
|
|
|
|
|
|
count = CFArrayGetCount(modes);
|
|
|
|
|
|
|
|
for (index = 0; index < count; index++) {
|
|
|
|
mode = CFArrayGetValueAtIndex(modes, index);
|
|
|
|
|
|
|
|
long bitsPerPixel = 0;
|
|
|
|
long width = 0;
|
|
|
|
long height = 0;
|
|
|
|
long refreshRate = 0;
|
|
|
|
|
|
|
|
CFNumberRef value;
|
|
|
|
|
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayBitsPerPixel);
|
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &bitsPerPixel);
|
|
|
|
|
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayWidth);
|
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &width);
|
|
|
|
|
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayHeight);
|
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &height);
|
|
|
|
|
|
|
|
value = CFDictionaryGetValue(mode, kCGDisplayRefreshRate);
|
|
|
|
CFNumberGetValue(value, kCFNumberLongType, &refreshRate);
|
|
|
|
|
|
|
|
(*env)->CallVoidMethod(env, this, addDisplayModeMethod, modesList, width, height, bitsPerPixel, refreshRate);
|
|
|
|
}
|
|
|
|
}
|
2013-07-06 16:52:59 -04:00
|
|
|
|
2013-02-08 18:29:15 -05:00
|
|
|
}
|
|
|
|
|
2012-12-18 17:10:44 -05:00
|
|
|
JNIEXPORT jint JNICALL Java_org_lwjgl_DefaultSysImplementation_getJNIVersion(JNIEnv *env, jobject ignored) {
|
2008-04-30 10:58:47 -04:00
|
|
|
return org_lwjgl_MacOSXSysImplementation_JNI_VERSION;
|
|
|
|
}
|
|
|
|
|
2004-11-16 09:08:31 -05:00
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_restoreGamma(JNIEnv *env, jobject this) {
|
|
|
|
CGDisplayRestoreColorSyncSettings();
|
|
|
|
}
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_setGammaRamp(JNIEnv *env, jobject this, jobject gamma_buffer) {
|
|
|
|
const CGGammaValue *values = (*env)->GetDirectBufferAddress(env, gamma_buffer);
|
2012-12-04 17:45:47 -05:00
|
|
|
uint32_t table_size = (*env)->GetDirectBufferCapacity(env, gamma_buffer);
|
2004-11-16 09:23:28 -05:00
|
|
|
CGDisplayErr err = CGSetDisplayTransferByTable(kCGDirectMainDisplay, table_size, values, values, values);
|
|
|
|
if (err != CGDisplayNoErr) {
|
|
|
|
throwException(env, "Could not set display gamma");
|
|
|
|
}
|
2012-12-18 17:10:44 -05:00
|
|
|
}
|