/* * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. * Copyright (c) 2011 JogAmp Community. 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 #import "jogamp_newt_driver_macosx_WindowDriver.h" #import "MacNewtNSWindow.h" #import "MouseEvent.h" #import "KeyEvent.h" #import "ScreenMode.h" #import #import #import #ifdef DBG_PERF #include "timespec.h" #endif static const char * const ClazzNamePoint = "com/jogamp/nativewindow/util/Point"; static const char * const ClazzAnyCstrName = ""; static const char * const ClazzNamePointCstrSignature = "(II)V"; static jclass pointClz = NULL; static jmethodID pointCstr = NULL; static 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; } static void setWindowClientTopLeftPoint(NewtNSWindow* mWin, jint x, jint y, BOOL doDisplay) { DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay); NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]; DBG_PRINT( "setWindowClientTopLeftPoint.1: %d/%d\n", (int)pS.x, (int)pS.y); [mWin setFrameOrigin: pS]; DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y); if( doDisplay ) { NSView* mView = [mWin contentView]; [mWin invalidateCursorRectsForView: mView]; } } static void setWindowClientTopLeftPointAndSize(NewtNSWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) { DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay); NSSize clientSZ = NSMakeSize(width, height); NSPoint pS = [mWin newtAbsClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y) size: clientSZ]; NSSize topSZ = [mWin newtClientSize2TLSize: clientSZ]; NSRect rect = { pS, topSZ }; DBG_PRINT( "setWindowClientTopLeftPointAndSize.1: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height); [mWin setFrame: rect display:doDisplay]; DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height); // -> display:YES // if( doDisplay ) { // NSView* mView = [mWin contentView]; // [mWin invalidateCursorRectsForView: mView]; // } } #ifdef VERBOSE_ON static int getRetainCount(NSObject * obj) { return ( NULL == obj ) ? -1 : (int)([obj retainCount]) ; } #endif static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtNSView *view) { DBG_PRINT( "setJavaWindowObject.0: View %p\n", view); if( NULL == newJavaWindowObject ) { // disable jobject globJavaWindowObject = [view getJavaWindowObject]; if( NULL != globJavaWindowObject ) { DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject); (*env)->DeleteGlobalRef(env, globJavaWindowObject); [view setJavaWindowObject: NULL]; } } else { // enable DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject); jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject); [view setJavaWindowObject: globJavaWindowObject]; } DBG_PRINT( "setJavaWindowObject.X: View %p\n", view); } static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pview, NewtNSWindow *win, NewtNSView *newView, BOOL setJavaWindow) { NSView* oldNSView = [win contentView]; NewtNSView* oldNewtNSView = NULL; #ifdef VERBOSE_ON int dbgIdx = 1; #endif if( [oldNSView isKindOfClass:[NewtNSView class]] ) { oldNewtNSView = (NewtNSView *) oldNSView; } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n", dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtNSView, newView, getRetainCount(newView), pview); if( NULL!=oldNSView ) { NS_DURING // Available >= 10.5 - Makes the menubar disapear BOOL iifs; if ( [oldNSView respondsToSelector:@selector(isInFullScreenMode)] ) { iifs = [oldNSView isInFullScreenMode]; } else { iifs = NO; } if(iifs && [oldNSView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [oldNSView exitFullScreenModeWithOptions: NULL]; } NS_HANDLER NS_ENDHANDLER DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n", dbgIdx++, win, oldNSView, getRetainCount(oldNSView), NULL!=oldNewtNSView, newView, getRetainCount(newView)); if( NULL != oldNewtNSView ) { [oldNewtNSView setDestroyNotifySent: false]; setJavaWindowObject(env, NULL, oldNewtNSView); } [oldNSView removeFromSuperviewWithoutNeedingDisplay]; } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); if( NULL!=newView ) { [newView setDestroyNotifySent: false]; if( setJavaWindow ) { setJavaWindowObject(env, javaWindowObject, newView); } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n", dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView)); if(NULL!=pview) { [pview addSubview: newView positioned: NSWindowAbove relativeTo: nil]; } } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); [win setContentView: newView]; DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", dbgIdx++, win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); // make sure the insets are updated in the java object [win updateInsets: env jwin:javaWindowObject]; DBG_PRINT( "changeContentView.X win %p, view (%p,%d -> %p,%d)\n", win, oldNSView, getRetainCount(oldNSView), newView, getRetainCount(newView)); } /* * Class: jogamp_newt_driver_macosx_DisplayDriver * Method: initIDs * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_initNSApplication0 (JNIEnv *env, jclass clazz) { static int initialized = 0; if(initialized) return JNI_TRUE; initialized = 1; NewtCommon_init(env); // 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_driver_macosx_DisplayDriver * Method: runNSApplication0 * Signature: ()V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_runNSApplication0 (JNIEnv *env, jclass clazz) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; DBG_PRINT( "\nrunNSApplication0.0\n"); [NSApp run]; DBG_PRINT( "\nrunNSApplication0.X\n"); [pool release]; } /* * Class: jogamp_newt_driver_macosx_DisplayDriver * Method: stopNSApplication0 * Signature: ()V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplication0 (JNIEnv *env, jclass clazz) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; DBG_PRINT( "\nstopNSApplication0.0 nsApp.running %d\n", (NSApp && [NSApp isRunning])); if(NSApp && [NSApp isRunning]) { [NSApp performSelectorOnMainThread:@selector(stop:) withObject:nil waitUntilDone:YES]; // [NSApp stop: nil]; NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint(0,0) modifierFlags: 0 timestamp: 0.0 windowNumber: 0 context: nil subtype: 0 data1: 0 data2: 0]; DBG_PRINT( "\nstopNSApplication0.1\n"); [NSApp postEvent: event atStart: true]; } /** DBG_PRINT( "\nstopNSApplication0.2\n"); if(NSApp && [NSApp isRunning]) { DBG_PRINT( "\nstopNSApplication0.3\n"); [NSApp terminate:nil]; } */ DBG_PRINT( "\nstopNSApplication0.X\n"); [pool release]; } static NSImage * createNSImageFromData(JNIEnv *env, unsigned char * iconData, jint jiconWidth, jint jiconHeight) { if( NULL != iconData ) { NSInteger iconWidth = (NSInteger) jiconWidth; NSInteger iconHeight = (NSInteger) jiconHeight; const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp; const NSBitmapFormat bfmt = NSAlphaNonpremultipliedBitmapFormat; const BOOL hasAlpha = YES; NSBitmapImageRep* bir = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: &iconData pixelsWide: iconWidth pixelsHigh: iconHeight bitsPerSample: bpc samplesPerPixel: spp hasAlpha: hasAlpha isPlanar: NO colorSpaceName: NSCalibratedRGBColorSpace bitmapFormat: bfmt bytesPerRow: iconWidth*4 bitsPerPixel: bpp]; [bir autorelease]; NSImage* nsImage = [[NSImage alloc] initWithCGImage: [bir CGImage] size:NSZeroSize]; return nsImage; } return NULL; } /* * Class: jogamp_newt_driver_macosx_DisplayDriver * Method: setAppIcon0 */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0 (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height) { if( 0 == pixels ) { return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly! unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ? (*env)->GetDirectBufferAddress(env, pixels) : (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height); if( NULL != nsImage ) { [nsImage autorelease]; [NSApp setApplicationIconImage: nsImage]; } if ( JNI_FALSE == pixels_is_direct ) { (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); } [pool release]; } JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0 (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY) { if( 0 == pixels ) { return 0; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ? (*env)->GetDirectBufferAddress(env, pixels) : (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) ); NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height); NSCursor * res = NULL; if( NULL != nsImage ) { [nsImage autorelease]; NSPoint hotP = { hotX, hotY }; res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP]; } if ( JNI_FALSE == pixels_is_direct ) { (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT); } [pool release]; DBG_PRINT( "createPointerIcon0 %p\n", res); return (jlong) (intptr_t) res; } JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_destroyPointerIcon0 (JNIEnv *env, jobject unused, jlong handle) { NSCursor * c = (NSCursor*) (intptr_t) handle ; if( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c); return; } DBG_PRINT( "destroyPointerIcon0 %p\n", c); NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [c release]; [pool release]; } #if 0 static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { NSArray *screens = [NSScreen screens]; if( screen_idx<0 || screen_idx>=[screens count] ) { return NULL; } return (NSScreen *) [screens objectAtIndex: screen_idx]; } static NSScreen * NewtScreen_getNSScreenByCoord(int x, int y) { NSArray *screens = [NSScreen screens]; int i; for(i=[screens count]-1; i>=0; i--) { NSScreen * screen = (NSScreen *) [screens objectAtIndex: i]; NSRect frame = [screen frame]; if( x >= frame.origin.x && y >= frame.origin.y && x < frame.origin.x + frame.size.width && y < frame.origin.y + frame.size.height ) { return screen; } } return NULL; } #endif static void NewtScreen_dump() { #ifdef VERBOSE_ON NSArray *screens = [NSScreen screens]; int i; for(i=0; i<[screens count]; i++) { NSScreen * screen = (NSScreen *) [screens objectAtIndex: i]; NSRect screenFrame = [screen frame]; NSRect screenVisibleFrame = [screen visibleFrame]; CGFloat pixelScale = 1.0; // default NS_DURING // Available >= 10.7 pixelScale = [screen backingScaleFactor]; // HiDPI scaling NS_HANDLER NS_ENDHANDLER NSWindowDepth depth = [screen depth]; // an (int) value! DBG_PRINT( "NSScreen #%d (%p): Frame %lf/%lf %lfx%lf (vis %lf/%lf %lfx%lf), scale %lf, depth %d\n", i, screen, screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height, screenVisibleFrame.origin.x, screenVisibleFrame.origin.y, screenVisibleFrame.size.width, screenVisibleFrame.size.height, pixelScale, depth); } #endif } CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { if( NULL == screen ) { return (CGDirectDisplayID)0; } // Mind: typedef uint32_t CGDirectDisplayID; NSDictionary * dict = [screen deviceDescription]; NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size return (CGDirectDisplayID) [val integerValue]; } static NSScreen * NewtScreen_getNSScreenByCGDirectDisplayID(CGDirectDisplayID displayID) { NSArray *screens = [NSScreen screens]; int i; for(i=[screens count]-1; i>=0; i--) { NSScreen * screen = (NSScreen *) [screens objectAtIndex: i]; CGDirectDisplayID dID = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); if( dID == displayID ) { return screen; } } return NULL; } /** * Only in >= 10.6: * CGDisplayModeGetWidth(mode) * CGDisplayModeGetRefreshRate(mode) * CGDisplayModeGetHeight(mode) */ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) { long value = 0; CFNumberRef numRef; numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); if (numRef != NULL) CFNumberGetValue(numRef, kCFNumberLongType, &value); return value; } #define CGDDGetModeWidth(mode) GetDictionaryLong((mode), kCGDisplayWidth) #define CGDDGetModeHeight(mode) GetDictionaryLong((mode), kCGDisplayHeight) #define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) #define CGDDGetModeBitsPerPixel(mode) GetDictionaryLong((mode), kCGDisplayBitsPerPixel) // Duplicate each Mode by all possible rotations (4): // For each real-mode: [mode, 0], [mode, 90], [mode, 180], [mode, 270] #define ROTMODES_PER_REALMODE 4 /* * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: getMonitorDeviceIds0 * Signature: ()I */ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorDeviceIds0 (JNIEnv *env, jobject obj) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSArray *screens = [NSScreen screens]; int count = [screens count]; int32_t displayIDs[count]; int i; for(i=0; iNewIntArray(env, count); if (properties == NULL) { NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", count); } (*env)->SetIntArrayRegion(env, properties, 0, count, displayIDs); [pool release]; return properties; } /* * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: getMonitorProps0 * Signature: (I)[I */ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorProps0 (JNIEnv *env, jobject obj, jint crt_id) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; #ifdef DBG_PERF struct timespec t0, t1, td; long td_ms; timespec_now(&t0); #endif #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL); #endif CGDirectDisplayID displayID = (CGDirectDisplayID)crt_id; NSScreen *screen = NewtScreen_getNSScreenByCGDirectDisplayID(displayID); if( NULL == screen ) { [pool release]; return NULL; } CGDirectDisplayID mainDisplayID = CGMainDisplayID(); BOOL isPrimary = mainDisplayID == displayID; #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL); #endif CGSize sizeMM = CGDisplayScreenSize(displayID); #ifdef DBG_PERF timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); fprintf(stderr, "MacScreen_getMonitorProps0.3: %ld ms\n", td_ms); fflush(NULL); #endif CGRect dBounds = CGDisplayBounds (displayID); // origin top-left #ifdef VERBOSE_ON BOOL usesGL = CGDisplayUsesOpenGLAcceleration(displayID); NSRect sFrame = [screen frame]; // origin bottom-left DBG_PRINT( "getMonitorProps0: crt_id 0x%X (prim %d), top-left displayBounds[%d/%d %dx%d], bottom-left screenFrame[%d/%d %dx%d], usesGL %d\n", (int)crt_id, isPrimary, (int)dBounds.origin.x, (int)dBounds.origin.y, (int)dBounds.size.width, (int)dBounds.size.height, (int)sFrame.origin.x, (int)sFrame.origin.y, (int)sFrame.size.width, (int)sFrame.size.height, (int)usesGL); #endif jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES; jint prop[ propCount ]; int offset = 0; prop[offset++] = propCount; prop[offset++] = crt_id; prop[offset++] = 0; // isClone prop[offset++] = isPrimary ? 1 : 0; // isPrimary prop[offset++] = (jint) sizeMM.width; prop[offset++] = (jint) sizeMM.height; prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (pixel units, will be fixed in java code) prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (pixel units, will be fixed in java code) prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (pixel units, will be fixed in java code) prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (pixel units, will be fixed in java code) prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (window units, will be fixed in java code) prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (window units, will be fixed in java code) prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (window units, will be fixed in java code) prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (window units, will be fixed in java code) jintArray properties = (*env)->NewIntArray(env, propCount); if (properties == NULL) { NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount); } (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop); [pool release]; return properties; } /* * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: getMonitorMode0 * Signature: (II)[I */ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getMonitorMode0 (JNIEnv *env, jobject obj, jint crt_id, jint mode_idx) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; CGDirectDisplayID displayID = (CGDirectDisplayID)crt_id; NSScreen *screen = NewtScreen_getNSScreenByCGDirectDisplayID(displayID); if( NULL == screen ) { [pool release]; return NULL; } CGFloat pixelScale = 1.0; // default NS_DURING // Available >= 10.7 pixelScale = [screen backingScaleFactor]; // HiDPI scaling NS_HANDLER NS_ENDHANDLER CFArrayRef availableModes = CGDisplayAvailableModes(displayID); CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; CFDictionaryRef mode = NULL; int currentCCWRot = (int)CGDisplayRotation(displayID); jint ccwRot = 0; int nativeId = 0; #ifdef VERBOSE_ON if(0 >= mode_idx) { // only for current mode (-1) and first mode (scanning) DBG_PRINT( "getScreenMode0: crtID 0x%X (s %p, pscale %lf), mode %d, avail: %d/%d, current rot %d ccw\n", (uint32_t)displayID, screen, pixelScale, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot); } #endif if(numberOfAvailableModesRots<=mode_idx) { // n/a - end of modes DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n", (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); [pool release]; return NULL; } else if(-1 < mode_idx) { // only at initialization time, where index >= 0 nativeId = mode_idx / ROTMODES_PER_REALMODE; ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90; mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId); } else { // current mode mode = CGDisplayCurrentMode(displayID); ccwRot = currentCCWRot; CFRange range = CFRangeMake (0, numberOfAvailableModes); nativeId = CFArrayGetFirstIndexOfValue(availableModes, range, (CFDictionaryRef)mode); } // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef int mWidth = CGDDGetModeWidth(mode); int mHeight = CGDDGetModeHeight(mode); if( -1 == mode_idx ) { mWidth *= (int)pixelScale; // accomodate HiDPI mHeight *= (int)pixelScale; // accomodate HiDPI } // swap width and height, since OSX reflects rotated dimension, we don't if ( 90 == currentCCWRot || 270 == currentCCWRot ) { int tempWidth = mWidth; mWidth = mHeight; mHeight = tempWidth; } jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ]; int propIndex = 0; int refreshRate = CGDDGetModeRefreshRate(mode); int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8) prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL; prop[propIndex++] = mWidth; prop[propIndex++] = mHeight; prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); prop[propIndex++] = fRefreshRate * 100; // Hz*100 prop[propIndex++] = 0; // flags prop[propIndex++] = nativeId; prop[propIndex++] = ccwRot; DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n", (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, (int)prop[1], (int)prop[2], (int)prop[3], (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]); jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL); if (properties == NULL) { NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL); } (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop); // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef [pool release]; return properties; } /* * Class: jogamp_newt_driver_macosx_ScreenDriver * Method: setMonitorMode0 * Signature: (III)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_setMonitorMode0 (JNIEnv *env, jobject object, jint crt_id, jint nativeId, jint ccwRot) { jboolean res = JNI_TRUE; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; CGDirectDisplayID displayID = (CGDirectDisplayID)crt_id; NSScreen *screen = NewtScreen_getNSScreenByCGDirectDisplayID(displayID); if( NULL == screen ) { [pool release]; return JNI_FALSE; } CFArrayRef availableModes = CGDisplayAvailableModes(displayID); CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes); #ifdef VERBOSE_ON CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; #endif DBG_PRINT( "setScreenMode0: crtID 0x%X (%p), nativeID %d, rot %d ccw, avail: %d/%d\n", (uint32_t)displayID, screen, (int)nativeId, ccwRot, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots); CFDictionaryRef mode = NULL; if( 0 != ccwRot ) { // FIXME: How to rotate the display/screen on OSX programmatically ? DBG_PRINT( "setScreenMode0: Don't know how to rotate screen on OS X: rot %d ccw\n", ccwRot); res = JNI_FALSE; } else { if( numberOfAvailableModes <= nativeId ) { res = JNI_FALSE; } else { mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, nativeId); // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef } } if( NULL != mode ) { CGError err = CGDisplaySwitchToMode(displayID, mode); if(kCGErrorSuccess != err) { DBG_PRINT( "setScreenMode0: SetMode failed: %d\n", (int)err); res = JNI_FALSE; } } // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef [pool release]; return res; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: initIDs * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 (JNIEnv *env, jclass clazz) { static int initialized = 0; if(initialized) return JNI_TRUE; initialized = 1; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtScreen_dump(); jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't find %s", ClazzNamePoint); } pointClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==pointClz) { NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't use %s", ClazzNamePoint); } pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); if(NULL==pointCstr) { NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0: can't fetch %s.%s %s", ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } // 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); BOOL res = [NewtNSWindow initNatives: env forClass: clazz]; [pool release]; return (jboolean) res; } /** * Class: jogamp_newt_driver_ios_WindowDriver * Method: createWindow1 * Signature: (JJIIIIFZZZZJ)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow1 (JNIEnv *env, jobject jthis, jlong joldwin, jlong jparent, jint x, jint y, jint w, jint h, jfloat reqPixelScale, jboolean fullscreen, jint styleMask, jint bufferingType, jboolean opaque, jboolean atop, jboolean abottom, jboolean visible, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // [CATransaction begin]; NewtNSWindow* oldWindow = (NewtNSWindow*) (intptr_t) joldwin ; NewtNSView* myView = (NewtNSView*) (intptr_t) jview ; NSObject* nsParentObj = (NSObject*) ((intptr_t) jparent); NSWindow* parentWindow = NULL; NSView* parentView = NULL; if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) { parentWindow = (NSWindow*) nsParentObj; parentView = [parentWindow contentView]; DBG_PRINT( "createWindow1 - Parent is NSWindow : %p (win) -> %p (view) \n", parentWindow, parentView); } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) { parentView = (NSView*) nsParentObj; parentWindow = [parentView window]; DBG_PRINT( "createWindow1 - Parent is NSView : %p -(view) > %p (win) \n", parentView, parentWindow); } else { DBG_PRINT( "createWindow1 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj); } DBG_PRINT( "createWindow1.0 - %p (this), oldWin %p, parent(win %p, view %p), myView %p, %d/%d %dx%d, reqPixelScale %f, fullscreen %d, opaque %d, atop %d, abottom %d, visible %d (START)\n", (void*)(intptr_t)jthis, oldWindow, parentWindow, parentView, myView, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale, fullscreen, opaque, atop, abottom, visible); if( NULL != oldWindow ) { if( NULL == myView ) { NewtCommon_throwNewRuntimeException(env, "oldWindow %p given but no view %p (this %p)", oldWindow, myView, (void*)(intptr_t)jthis); } changeContentView(env, jthis, parentView, oldWindow, NULL, NO); Java_jogamp_newt_driver_macosx_WindowDriver_close0(env, NULL, joldwin); } else if( NULL != myView ) { NewtCommon_throwNewRuntimeException(env, "view %p given but no oldWindow %p (this %p)", oldWindow, myView, (void*)(intptr_t)jthis); } if (fullscreen) { styleMask = NSBorderlessWindowMask; } NSRect rectWin = NSMakeRect(x, y, w, h); NewtNSWindow* myWindow = [[NewtNSWindow alloc] initWithContentRect: rectWin styleMask: (NSUInteger) styleMask backing: (NSBackingStoreType) bufferingType defer: YES isFullscreenWindow: fullscreen]; #ifdef VERBOSE_ON int dbgIdx = 1; #endif DBG_PRINT( "createWindow1.%d - %p, isVisible %d\n", dbgIdx++, myWindow, [myWindow isVisible]); if( NULL == myView ) { NSRect rectView = NSMakeRect(0, 0, w, h); myView = [[NewtNSView alloc] initWithFrame: rectView] ; } NS_DURING // HiDPI scaling: Setup - Available >= 10.7 if( 1.0 == reqPixelScale ) { [myView setWantsBestResolutionOpenGLSurface: NO]; } else { [myView setWantsBestResolutionOpenGLSurface: YES]; } NS_HANDLER NS_ENDHANDLER [myWindow setReleasedWhenClosed: NO]; // We control NSWindow destruction! [myWindow setPreservesContentDuringLiveResize: NO]; NS_DURING if ( [myWindow respondsToSelector:@selector(setRestorable:)] ) { // Available >= 10.7 - Removes restauration 'feature', really close [myWindow setRestorable: NO]; } NS_HANDLER NS_ENDHANDLER // Remove animations for child windows if(NULL != parentWindow) { NS_DURING if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) { // Available >= 10.7 - Removes default animations [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; } NS_HANDLER NS_ENDHANDLER } DBG_PRINT( "createWindow1.%d\n", dbgIdx++); if(opaque) { [myWindow setOpaque: YES]; if (!fullscreen) { [myWindow setShowsResizeIndicator: YES]; } } else { [myWindow setOpaque: NO]; [myWindow setBackgroundColor: [NSColor clearColor]]; } DBG_PRINT( "createWindow1.%d\n", dbgIdx++); [myWindow setAlwaysOn: atop bottom:abottom]; // specify we want mouse-moved events [myWindow setAcceptsMouseMovedEvents:YES]; DBG_PRINT( "createWindow1.%d - %p view %p, isVisible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible]); // Set the content view changeContentView(env, jthis, parentView, myWindow, myView, NO); [myWindow setInitialFirstResponder: myView]; DBG_PRINT( "createWindow1.%d - %p view %p, isVisible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible]); if(NULL!=parentWindow) { [myWindow attachToParent: parentWindow]; } DBG_PRINT( "createWindow1.%d - %p view %p, isVisible %d, visible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible], visible); // Immediately re-position this window based on an upper-left coordinate system setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO); DBG_PRINT( "createWindow1.%d - %p view %p, isVisible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible]); NS_DURING // concurrent view rendering // Available >= 10.6 - Makes the menubar disapear if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) { [myWindow setAllowsConcurrentViewDrawing: YES]; } DBG_PRINT( "createWindow1.%d - %p view %p, isVisible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible]); if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) { [myView setCanDrawConcurrently: YES]; } NS_HANDLER NS_ENDHANDLER DBG_PRINT( "createWindow1.%d - %p view %p, isVisible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible]); #if 0 // Visible on front may lead to a deadlock on Java11 // WindowDriver's createWindow1 caller shall issue this w/o wait // after creation if( visible ) { #if 0 [myWindow makeKeyAndOrderFront: myWindow]; if( NULL != parentWindow ) { [myWindow orderWindow: NSWindowAbove relativeTo: [parentWindow windowNumber]]; } #endif #if 1 [myView setNextResponder: myWindow]; if( NULL == parentWindow ) { [myWindow orderFrontRegardless]; } else { [myWindow orderWindow: NSWindowAbove relativeTo: [parentWindow windowNumber]]; } #endif } #endif DBG_PRINT( "createWindow1.%d - %p view %p, isVisible %d\n", dbgIdx++, myWindow, myView, [myWindow isVisible]); // force surface creation // [myView lockFocus]; // [myView unlockFocus]; // Set the next responder to be the window so that we can forward // right mouse button down events [myView setNextResponder: myWindow]; DBG_PRINT( "createWindow1.%d - %p (this), %p (parent): new window: %p, view %p\n", dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)jparent, myWindow, myView); [myView setDestroyNotifySent: false]; setJavaWindowObject(env, jthis, myView); DBG_PRINT( "createWindow1.%d - %p view %p, fullscreen %d, setPresentationOptions has %d, options 0x%X\n", dbgIdx++, myWindow, myView, (int)fullscreen, (int)myWindow->hasPresentationSwitch, (int)myWindow->fullscreenPresentationOptions); NS_DURING if( fullscreen ) { /** * See Bug 914: We don't use exclusive fullscreen anymore (capturing display) * allowing ALT-TAB to allow process/app switching! * Shall have no penalty on modern GPU and is also recommended, see bottom box @ * * NSScreen *myScreen = NewtScreen_getNSScreenByCoord(x, y); if( NULL != myScreen ) { if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) { // Available >= 10.5 - Makes the menubar disapear [myView enterFullScreenMode: myScreen withOptions:NULL]; } } */ if( myWindow->hasPresentationSwitch ) { [NSApp setPresentationOptions: myWindow->fullscreenPresentationOptions]; } } NS_HANDLER NS_ENDHANDLER DBG_PRINT( "createWindow1.%d - %p (this), %p (parent): new window: %p, view %p\n", dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)jparent, myWindow, myView); // [CATransaction commit]; [pool release]; DBG_PRINT( "createWindow1.X - %p (this), %p (parent): new window: %p, view %p\n", (void*)(intptr_t)jthis, (void*)(intptr_t)jparent, myWindow, myView); return (jlong) (intptr_t) myWindow; } JNIEXPORT jint JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getDisplayID0(JNIEnv *env, jobject jthis, jlong window) { NewtNSWindow* myWindow = (NewtNSWindow*) ((intptr_t) window); if( NULL == myWindow ) { DBG_PRINT( "getDisplayID0 - NULL NEWT win - abort\n"); return 0; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSScreen *screen = [myWindow screen]; int32_t displayID = (int32_t)NewtScreen_getCGDirectDisplayIDByNSScreen(screen); [pool release]; return (jint) displayID; } /** * Method is called on Main-Thread, hence no special invocation required inside method. * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setPixelScale0 * Signature: (JJF)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPixelScale0 (JNIEnv *env, jobject jthis, jlong window, jlong view, jfloat reqPixelScale) { NewtNSWindow* myWindow = (NewtNSWindow*) ((intptr_t) window); if( NULL == myWindow ) { DBG_PRINT( "setPixelScale0 - NULL NEWT win - abort\n"); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtNSView* myView = (NewtNSView*) (intptr_t) view ; DBG_PRINT( "setPixelScale0 - %p (this), %p (window), view %p, reqPixScale %f (START)\n", (void*)(intptr_t)jthis, myWindow, myView, (float)reqPixelScale); (void)myWindow; NS_DURING // HiDPI scaling: Setup - Available >= 10.7 if( 1.0 == reqPixelScale ) { [myView setWantsBestResolutionOpenGLSurface: NO]; } else { [myView setWantsBestResolutionOpenGLSurface: YES]; } NS_HANDLER NS_ENDHANDLER [pool release]; DBG_PRINT( "setPixelScale0.X - %p (this), window: %p, view %p\n", (void*)(intptr_t)jthis, myWindow, myView); } /** * Method is called on Main-Thread, hence no special invocation required inside method. * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: close0 * Signature: (J)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 (JNIEnv *env, jobject unused, jlong window) { NewtNSWindow* mWin = (NewtNSWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n"); return; } BOOL isNSWin = [mWin isKindOfClass:[NSWindow class]]; BOOL isNewtWin = [mWin isKindOfClass:[NewtNSWindow class]]; NSWindow *pWin = [mWin parentWindow]; DBG_PRINT( "windowClose.0 - %p [isNSWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin); (void)isNSWin; // silence if( !isNewtWin ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSWindow %p", mWin); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtNSView* mView = (NewtNSView *)[mWin contentView]; BOOL fullscreen = mWin->isFullscreenWindow; BOOL destroyNotifySent, isNSView, isNewtNSView; if( NULL != mView ) { isNSView = [mView isKindOfClass:[NSView class]]; isNewtNSView = [mView isKindOfClass:[NewtNSView class]]; destroyNotifySent = isNewtNSView ? [mView getDestroyNotifySent] : false; } else { isNSView = false; isNewtNSView = false; destroyNotifySent = false; } DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isNSView %d, isNewtNSView %d], fullscreen %d, parent %p\n", mWin, destroyNotifySent, mView, isNSView, isNewtNSView, (int)fullscreen, pWin); [mWin setRealized: NO]; if( isNewtNSView ) { // cleanup view [mView setDestroyNotifySent: true]; setJavaWindowObject(env, NULL, mView); } NS_DURING /** * See Bug 914: We don't use exclusive fullscreen anymore (capturing display) * See createWindow1(..) above .. if(NULL!=mView) { BOOL iifs; if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) { iifs = [mView isInFullScreenMode]; } else { iifs = NO; } if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [mView exitFullScreenModeWithOptions: NULL]; } } */ // Note: mWin's release will also release it's mView! DBG_PRINT( "windowClose.1a - %p view %p, fullscreen %d, hasPresSwitch %d, defaultPresentationOptions 0x%X\n", mWin, mView, (int)fullscreen, (int)mWin->hasPresentationSwitch, (int)mWin->defaultPresentationOptions); if( fullscreen && mWin->hasPresentationSwitch ) { DBG_PRINT( "windowClose.1b - %p view %p, setPresentationOptions 0x%X\n", mWin, mView, (int)mWin->defaultPresentationOptions); [NSApp setPresentationOptions: mWin->defaultPresentationOptions]; } NS_HANDLER NS_ENDHANDLER if(NULL!=pWin) { [mWin detachFromParent: pWin]; } [mWin orderOut: mWin]; DBG_PRINT( "windowClose.2 - %p view %p, parent %p\n", mWin, mView, pWin); [mWin release]; DBG_PRINT( "windowClose.Xp\n"); [pool release]; } /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: lockSurface0 * Signature: (JJ)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_lockSurface0 (JNIEnv *env, jclass clazz, jlong window, jlong view) { NewtNSWindow *mWin = (NewtNSWindow*) ((intptr_t) window); if(NO == [mWin isRealized]) { return JNI_FALSE; } NewtNSView * mView = (NewtNSView *) ((intptr_t) view); return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE; /** deadlocks, since we render independent of focus return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */ } /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: unlockSurface0 * Signature: (JJ)Z */ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_unlockSurface0 (JNIEnv *env, jclass clazz, jlong window, jlong view) { // NewtNSWindow *mWin = (NewtNSWindow*) ((intptr_t) window); (void) window; NewtNSView * mView = (NewtNSView *) ((intptr_t) view); return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE; /** deadlocks, since we render independent of focus [mView unlockFocus]; */ } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: requestFocus0 * Signature: (JZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_requestFocus0 (JNIEnv *env, jobject window, jlong w, jboolean force) { NSWindow* mWin = (NSWindow*) ((intptr_t) w); if( NULL == mWin ) { DBG_PRINT( "requestFocus - NULL NEWT win - abort\n"); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; #ifdef VERBOSE_ON BOOL hasFocus = [mWin isKeyWindow]; #endif DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); [mWin setAcceptsMouseMovedEvents: YES]; [mWin makeFirstResponder: nil]; [mWin orderFrontRegardless]; [mWin makeKeyWindow]; DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: resignFocus0 * Signature: (J)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_resignFocus0 (JNIEnv *env, jobject window, jlong w) { NSWindow* mWin = (NSWindow*) ((intptr_t) w); if( NULL == mWin ) { DBG_PRINT( "resignFocus0 - NULL NEWT win - abort\n"); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* pWin = [mWin parentWindow]; BOOL hasFocus = [mWin isKeyWindow]; DBG_PRINT( "resignFocus0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); if( hasFocus ) { if(NULL != pWin) { // [mWin makeFirstResponder: pWin]; [pWin makeKeyWindow]; } else { [pWin resignKeyWindow]; } } DBG_PRINT( "resignFocus0 - window: %p (END)\n", mWin); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: orderFront0 * Signature: (J)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderFront0 (JNIEnv *env, jobject unused, jlong window) { NSWindow* mWin = (NSWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "orderFront0 - NULL NEWT win - abort\n"); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* pWin = [mWin parentWindow]; DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); if( NULL == pWin ) { [mWin orderFrontRegardless]; } else { [mWin orderWindow: NSWindowAbove relativeTo: [pWin windowNumber]]; } DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: orderOut * Signature: (J)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_orderOut0 (JNIEnv *env, jobject unused, jlong window) { NSWindow* mWin = (NSWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "orderOut0 - NULL NEWT win - abort\n"); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* pWin = [mWin parentWindow]; DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); if( NULL == pWin ) { [mWin orderOut: mWin]; } else { [mWin orderWindow: NSWindowOut relativeTo: [pWin windowNumber]]; } DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setTitle0 * Signature: (JLjava/lang/String;)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setTitle0 (JNIEnv *env, jobject unused, jlong window, jstring title) { NSWindow* win = (NSWindow*) ((intptr_t) window); if( NULL == win ) { DBG_PRINT( "setTitle0 - NULL NEWT win - abort\n"); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; DBG_PRINT( "setTitle0 - window: %p (START)\n", win); NSString* str = jstringToNSString(env, title); [str autorelease]; [win setTitle: str]; DBG_PRINT( "setTitle0 - window: %p (END)\n", win); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: contentView0 * Signature: (J)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_contentView0 (JNIEnv *env, jobject unused, jlong window) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* win = (NSWindow*) ((intptr_t) window); NSView* nsView = [win contentView]; NewtNSView* newtView = NULL; if( [nsView isKindOfClass:[NewtNSView class]] ) { newtView = (NewtNSView *) nsView; } DBG_PRINT( "contentView0 - window: %p, view: %p, newtView %p\n", win, nsView, newtView); jlong res = (jlong) ((intptr_t) nsView); [pool release]; return res; } /** * Method is called on Main-Thread, hence no special invocation required inside method. * * Class: jogamp_newt_driver_macosx_WindowDriver * Method: changeContentView * Signature: (J)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_changeContentView0 (JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtNSView* newView = (NewtNSView *) ((intptr_t) jview); NewtNSWindow* win = (NewtNSWindow*) ((intptr_t) window); DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d)\n", win, newView, getRetainCount(newView)); NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView); NSView* pView = NULL; if( NULL != nsParentObj ) { if( [nsParentObj isKindOfClass:[NSWindow class]] ) { NSWindow * pWin = (NSWindow*) nsParentObj; pView = [pWin contentView]; } else if( [nsParentObj isKindOfClass:[NSView class]] ) { pView = (NSView*) nsParentObj; } } changeContentView(env, jthis, pView, win, newView, YES); DBG_PRINT( "changeContentView0.X\n"); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: updateSizePosInsets0 * Signature: (JZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_updateSizePosInsets0 (JNIEnv *env, jobject jthis, jlong window, jboolean defer) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtNSWindow* mWin = (NewtNSWindow*) ((intptr_t) window); DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (START)\n", mWin, (int)defer); [mWin updateSizePosInsets: env jwin:jthis defer:defer]; DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (END)\n", mWin, (int)defer); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setWindowClientTopLeftPointAndSize0 * Signature: (JIIIIZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPointAndSize0 (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NewtNSWindow* mWin = (NewtNSWindow*) ((intptr_t) window); DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin); setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display); DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: setWindowClientTopLeftPoint0 * Signature: (JIIZ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setWindowClientTopLeftPoint0 (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display) { NewtNSWindow* mWin = (NewtNSWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "setWindowClientTopLeftPoint - NULL NEWT win - abort\n"); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin); setWindowClientTopLeftPoint(mWin, x, y, display); DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin); [pool release]; } /* * Class: jogamp_newt_driver_macosx_WindowDriver * Method: getLocationOnScreen0 * Signature: (JII)Lcom/jogamp/nativewindow/util/Point; */ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_getLocationOnScreen0 (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y) { NewtNSWindow *mWin = (NewtNSWindow*) (intptr_t) win; if( NULL == mWin ) { DBG_PRINT( "getLocationOnScreen0 - NULL NEWT win - abort\n"); return NULL; } if( ![mWin isKindOfClass:[NewtNSWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSWindow %p", mWin); return NULL; } NSPoint p0 = [mWin getLocationOnScreen: NSMakePoint(src_x, src_y)]; return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y); } JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerIcon0 (JNIEnv *env, jobject unused, jlong window, jlong handle) { NewtNSWindow *mWin = (NewtNSWindow*) (intptr_t) window; if( NULL == mWin ) { DBG_PRINT( "setPointerIcon0 - NULL NEWT win - abort\n"); return; } NSCursor *c = (NSCursor*) (intptr_t) handle ; if ( NULL != c && NO == [c isKindOfClass:[NSCursor class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NSCursor %p", c); return; } if( ! [mWin isKindOfClass:[NewtNSWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSWindow %p", mWin); return; } NewtNSView* nView = (NewtNSView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtNSView class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSView %p", nView); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setPointerIcon: c]; [pool release]; } /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: setPointerVisible0 * Signature: (JZ)Z */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setPointerVisible0 (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible) { NewtNSWindow *mWin = (NewtNSWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "setPointerVisible0 - NULL NEWT win - abort\n"); return; } if( ! [mWin isKindOfClass:[NewtNSWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSWindow %p", mWin); return; } NewtNSView* nView = (NewtNSView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtNSView class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSView %p", nView); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO]; [pool release]; } /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: confinePointer0 * Signature: (JZ)Z */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_confinePointer0 (JNIEnv *env, jclass clazz, jlong window, jboolean confine) { NewtNSWindow *mWin = (NewtNSWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "confinePointer0 - NULL NEWT win - abort\n"); return; } if( ! [mWin isKindOfClass:[NewtNSWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSWindow %p", mWin); return; } NewtNSView* nView = (NewtNSView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtNSView class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSView %p", nView); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setMouseConfined: ( JNI_TRUE == confine ) ? YES : NO]; [pool release]; } /* * Class: Java_jogamp_newt_driver_macosx_WindowDriver * Method: warpPointer0 * Signature: (JJII)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_warpPointer0 (JNIEnv *env, jclass clazz, jlong window, jint x, jint y) { NewtNSWindow *mWin = (NewtNSWindow*) ((intptr_t) window); if( NULL == mWin ) { DBG_PRINT( "warpPointer0 - NULL NEWT win - abort\n"); return; } if( ! [mWin isKindOfClass:[NewtNSWindow class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSWindow %p", mWin); return; } NewtNSView* nView = (NewtNSView *) [mWin contentView]; if( ! [nView isKindOfClass:[NewtNSView class]] ) { NewtCommon_throwNewRuntimeException(env, "Not a NewtNSView %p", nView); return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [nView setMousePosition: [mWin newtRelClientTLWinPos2AbsBLScreenPos: NSMakePoint(x, y)]]; [pool release]; }