From 7b8e2ef59e08f288adc68f12a3e066476c86de52 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 12 Oct 2011 11:04:33 +0200 Subject: Newt/OSX: Fix top/child positioning, positionChanged(), rely on native pos/size notifications Newt/MacWindow - remove redundant manual window-move/set-size code - Use local getLocationOnScreen(..), fixes positionChanged(..) - setFrameTopLeftPoint(..) use totalHeight (w/ insets) - create: don't 'retain' the window reference (ref counter) - close: release view, - cache insets - to be used @ create --- .../jogamp/newt/driver/macosx/MacWindow.java | 27 +++---- src/newt/native/MacWindow.m | 82 ++++++++++++++++++---- src/newt/native/NewtMacWindow.h | 5 ++ src/newt/native/NewtMacWindow.m | 56 ++++++++++----- 4 files changed, 120 insertions(+), 50 deletions(-) (limited to 'src/newt') diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index a3470da6c..8114e5536 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -38,7 +38,6 @@ import javax.media.nativewindow.*; import com.jogamp.newt.event.*; -import jogamp.nativewindow.macosx.OSXUtil; import jogamp.newt.*; import javax.media.nativewindow.util.Insets; @@ -187,14 +186,13 @@ public class MacWindow extends WindowImpl { protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { int _x = x, _y = y; - if(0 == ( FLAG_IS_UNDECORATED & flags) && 0<=_x && 0<=_y) { - final InsetsImmutable i = getInsets(); - + final InsetsImmutable insets = getInsets(); // zero if undecorated + if(0<=_x && 0<=_y) { // client position -> top-level window position - _x -= i.getLeftWidth() ; - _y -= i.getTopHeight() ; + _x -= insets.getLeftWidth() ; + _y -= insets.getTopHeight() ; if(DEBUG_IMPLEMENTATION) { - System.err.println("MacWindow reconfig (insets: "+i+"): "+x+"/"+y+" -> "+_x+"/"+_y); + System.err.println("MacWindow reconfig (insets: "+insets+"): "+x+"/"+y+" -> "+_x+"/"+_y); } } // min val is 0 @@ -222,8 +220,6 @@ public class MacWindow extends WindowImpl { if( getWindowHandle() == 0 ) { if( 0 != ( FLAG_IS_VISIBLE & flags) ) { createWindow(false, _x, _y, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); - this.x = x; - this.y = y; makeKeyAndOrderFront0(getWindowHandle()); visibleChanged(false, true); // no native event .. } /* else { ?? } */ @@ -240,16 +236,10 @@ public class MacWindow extends WindowImpl { if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } } if(x>=0 && y>=0) { - setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), _x, _y, width, height); - this.x = x; - this.y = y; - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED); + setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), _x, _y, height+insets.getTotalHeight()); } if(width>0 && height>0) { setContentSize0(getWindowHandle(), width, height); - this.width = width; - this.height = height; - enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_RESIZED); } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 != ( FLAG_IS_VISIBLE & flags) ) { makeKeyAndOrderFront0(getWindowHandle()); @@ -262,7 +252,7 @@ public class MacWindow extends WindowImpl { } protected Point getLocationOnScreenImpl(int x, int y) { - return OSXUtil.GetLocationOnScreen(getWindowHandle(), x, y); + return (Point) getLocationOnScreen0(getWindowHandle(), x, y); } protected void updateInsetsImpl(Insets insets) { @@ -426,6 +416,7 @@ public class MacWindow extends WindowImpl { private native long contentView0(long window); private native long changeContentView0(long parentWindowOrViewHandle, long window, long view); private native void setContentSize0(long window, int w, int h); - private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y, int w, int h); + private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y, int totalHeight); private native void setAlwaysOnTop0(long window, boolean atop); + private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index d8839abe0..f480103f2 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -43,6 +43,12 @@ #import +static const char * const ClazzNamePoint = "javax/media/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); @@ -51,17 +57,21 @@ static NSString* jstringToNSString(JNIEnv* env, jstring jstr) return str; } -static void setFrameTopLeftPoint(NSWindow* pWin, NSWindow* mWin, jint x, jint y, jint w, jint h) { +static void setFrameTopLeftPoint(NSWindow* pWin, NSWindow* mWin, jint x, jint y, jint totalHeight) { NSScreen* screen = [NSScreen mainScreen]; - NSRect screenRect = [screen frame]; - NSPoint pS = NSMakePoint(screenRect.origin.x + x, screenRect.origin.y + screenRect.size.height - y - h); + NSRect screenTotal = [screen frame]; - DBG_PRINT( "setFrameTopLeftPoint screen %lf/%lf %lfx%lf, win top-left %d/%d -> scrn bottom-left %lf/%lf\n", - screenRect.origin.x, screenRect.origin.y, screenRect.size.width, screenRect.size.height, - (int)x, (int)y, pS.x, pS.y); + NSPoint pS = NSMakePoint(screenTotal.origin.x + x, screenTotal.origin.y + screenTotal.size.height - y - totalHeight); #ifdef VERBOSE_ON + NSMenu * menu = [NSApp mainMenu]; + int menuHeight = [NSMenu menuBarVisible] ? (int) [menu menuBarHeight] : 0; + + DBG_PRINT( "setFrameTopLeftPoint screen %lf/%lf %lfx%lf, menuHeight %d, win top-left %d/%d totalHeight %d -> scrn bottom-left %lf/%lf\n", + screenTotal.origin.x, screenTotal.origin.y, screenTotal.size.width, screenTotal.size.height, menuHeight, + (int)x, (int)y, (int)totalHeight, pS.x, pS.y); + if(NULL != pWin) { NSView* pView = [pWin contentView]; NSRect pViewFrame = [pView frame]; @@ -241,6 +251,22 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_initIDs0 if(initialized) return JNI_TRUE; initialized = 1; + jclass c; + c = (*env)->FindClass(env, ClazzNamePoint); + if(NULL==c) { + NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_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_MacWindow_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_MacWindow_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"); @@ -283,10 +309,12 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 } // Allocate the window - NSWindow* myWindow = [[[NewtMacWindow alloc] initWithContentRect: rect + NewtMacWindow* myWindow = [[NewtMacWindow alloc] initWithContentRect: rect styleMask: (NSUInteger) styleMask backing: (NSBackingStoreType) bufferingType - defer: NO screen: myScreen] retain]; + defer: NO + screen: myScreen]; + [myWindow setReleasedWhenClosed: YES]; // default NSObject *nsParentObj = (NSObject*) ((intptr_t) parent); NSWindow* parentWindow = NULL; @@ -327,7 +355,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 (void) changeContentView(env, jthis, parentWindow, parentView, myWindow, myView); // Immediately re-position the window based on an upper-left coordinate system - setFrameTopLeftPoint(parentWindow, myWindow, x, y, w, h); + setFrameTopLeftPoint(parentWindow, myWindow, x, y, h+myWindow->cachedInsets[2]+myWindow->cachedInsets[3]); // h+insets[top+bottom] NS_DURING // Available >= 10.5 - Makes the menubar disapear @@ -429,13 +457,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_close0 NSWindow* mWin = (NSWindow*) ((intptr_t) window); NSView* mView = [mWin contentView]; NSWindow* pWin = [mWin parentWindow]; - DBG_PRINT( "*************** windowClose.0: %p (parent %p)\n", mWin, pWin); + DBG_PRINT( "*************** windowClose.0: %p (view %p, parent %p)\n", mWin, mView, pWin); NS_DURING if(NULL!=mView) { // Available >= 10.5 - Makes the menubar disapear if([mView isInFullScreenMode]) { [mView exitFullScreenModeWithOptions: NULL]; } + [mWin setContentView: nil]; + [mView release]; } NS_HANDLER NS_ENDHANDLER @@ -445,10 +475,12 @@ NS_ENDHANDLER [pWin removeChildWindow: mWin]; } [mWin orderOut: mWin]; - [mWin performSelectorOnMainThread:@selector(close:) withObject:nil waitUntilDone:NO]; - // [mWin close] + + // [mWin performSelectorOnMainThread:@selector(close:) withObject:nil waitUntilDone:NO]; + [mWin close]; // performs release! DBG_PRINT( "*************** windowClose.X: %p (parent %p)\n", mWin, pWin); + [pool release]; } @@ -560,7 +592,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setContentSize0 * Signature: (JJII)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setFrameTopLeftPoint0 - (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y, jint w, jint h) + (JNIEnv *env, jobject unused, jlong parent, jlong window, jint x, jint y, jint totalHeight) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) window); @@ -576,7 +608,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setFrameTopLeftP DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (START)\n", mWin, pWin); - setFrameTopLeftPoint(pWin, mWin, x, y, w, h); + setFrameTopLeftPoint(pWin, mWin, x, y, totalHeight); DBG_PRINT( "setFrameTopLeftPoint0 - window: %p, parent %p (END)\n", mWin, pWin); @@ -607,3 +639,25 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setAlwaysOnTop0 [pool release]; } +/* + * Class: jogamp_newt_driver_macosx_MacWindow + * Method: getLocationOnScreen0 + * Signature: (JII)Ljavax/media/nativewindow/util/Point; + */ +JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_MacWindow_getLocationOnScreen0 + (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y) +{ + NSObject *nsObj = (NSObject*) ((intptr_t) win); + NewtMacWindow * mWin = NULL; + + if( [nsObj isKindOfClass:[NewtMacWindow class]] ) { + mWin = (NewtMacWindow*) nsObj; + } else { + NewtCommon_throwNewRuntimeException(env, "not NewtMacWindow %p\n", nsObj); + } + + NSPoint p0 = { src_x, src_y }; + p0 = [mWin getLocationOnScreen: p0]; + return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y); +} + diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h index a8931d6fc..911abb8aa 100644 --- a/src/newt/native/NewtMacWindow.h +++ b/src/newt/native/NewtMacWindow.h @@ -79,15 +79,20 @@ @interface NewtMacWindow : NSWindow #endif { +@public + int cachedInsets[4]; // l, r, t, b } + (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz; +- (NSPoint) getLocationOnScreen: (NSPoint) p; + - (void) updateInsets: (JNIEnv*) env; - (id) initWithContentRect: (NSRect) contentRect styleMask: (NSUInteger) windowStyle backing: (NSBackingStoreType) bufferingType + defer: (BOOL) deferCreation screen:(NSScreen *)screen; @end diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index eb1426dc2..a44914c97 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -197,6 +197,29 @@ static jmethodID windowDestroyNotifyID = NULL; return NO; } +- (NSPoint) getLocationOnScreen: (NSPoint) p +{ + /** + * return location in 0/0 top-left space, + * OSX is 0/0 bottom-left space naturally + */ + NSScreen* screen = [self screen]; + NSRect screenRect = [screen frame]; + + NSView* view = [self contentView]; + NSRect viewFrame = [view frame]; + + NSRect r; + r.origin.x = p.x; + r.origin.y = viewFrame.size.height - p.y; // y-flip for 0/0 top-left + r.size.width = 0; + r.size.height = 0; + // NSRect rS = [win convertRectToScreen: r]; // 10.7 + NSPoint oS = [self convertBaseToScreen: r.origin]; + oS.y = screenRect.origin.y + screenRect.size.height - oS.y; + return oS; +} + - (void) updateInsets: (JNIEnv*) env { NSView* nsview = [self contentView]; @@ -215,29 +238,34 @@ static jmethodID windowDestroyNotifyID = NULL; // note: this is a simplistic implementation which doesn't take // into account DPI and scaling factor CGFloat l = contentRect.origin.x - frameRect.origin.x; - jint top = (jint)(frameRect.size.height - contentRect.size.height); - jint left = (jint)l; - jint bottom = (jint)(contentRect.origin.y - frameRect.origin.y); - jint right = (jint)(frameRect.size.width - (contentRect.size.width + l)); + cachedInsets[0] = (int)l; // l + cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r + cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t + cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b - DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", (int)left, (int)right, (int)top, (int)bottom); + DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); - (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, JNI_TRUE, left, right, top, bottom); + (*env)->CallVoidMethod(env, javaWindowObject, insetsChangedID, JNI_TRUE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); } - (id) initWithContentRect: (NSRect) contentRect styleMask: (NSUInteger) windowStyle backing: (NSBackingStoreType) bufferingType + defer: (BOOL) deferCreation screen:(NSScreen *)screen { id res = [super initWithContentRect: contentRect styleMask: windowStyle backing: bufferingType - defer: YES + defer: deferCreation screen: screen]; // Why is this necessary? Without it we don't get any of the // delegate methods like resizing and window movement. [self setDelegate: self]; + cachedInsets[0] = 0; // l + cachedInsets[1] = 0; // r + cachedInsets[2] = 0; // t + cachedInsets[3] = 0; // b return res; } @@ -517,17 +545,9 @@ static jint mods2JavaMods(NSUInteger mods) return; } - NSRect rect = [self frame]; - NSScreen* screen = NULL; - NSRect screenRect; - NSPoint pt; - - screen = [self screen]; - // this allows for better compatibility with awt behavior - screenRect = [screen frame]; - pt = NSMakePoint(rect.origin.x, screenRect.origin.y + screenRect.size.height - rect.origin.y - rect.size.height); - - (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_TRUE, (jint) pt.x, (jint) pt.y); + NSPoint p0 = { 0, 0 }; + p0 = [self getLocationOnScreen: p0]; + (*env)->CallVoidMethod(env, javaWindowObject, positionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); if (shallBeDetached) { (*jvmHandle)->DetachCurrentThread(jvmHandle); -- cgit v1.2.3