From 004c67c73a0309158c30929cd0d6513e23f34803 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 8 Jul 2019 05:11:56 +0200 Subject: NEWT iOS WindowDriver: native UIWindow/UIView creation change Astonishingly, the original code path doesn't show up the CAEAGL View/Layer (only the red test background) even though t is 1:1 equal to this alternative calls. Keeping the original path intact for future validation, another round of hours of analysis. The original code path will be removed in the next commit. --- .../jogamp/newt/driver/ios/WindowDriver.java | 69 +++++++++++--- src/newt/native/IOSWindow.m | 103 +++++++++++++++++++++ 2 files changed, 159 insertions(+), 13 deletions(-) diff --git a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java index 5469f74b1..39e3edc72 100644 --- a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java @@ -694,41 +694,52 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // Internals only // + /** + * Astonishingly, the original code path doesn't show up the CAEAGL View/Layer (only the red test background) + * even though the it is 1:1 equal to the alternative calls. + * Keeping the original path intact for future validation, another round of hours of analysis. + */ + private static final boolean altCreateWindow = true; + private void createWindow(final boolean offscreenInstance, final boolean recreate, final PointImmutable pS, final int width, final int height, final int flags) { final long parentWinHandle = getParentWindowHandle(); - final long preWinHandle = getWindowHandle(); + final long oldWinHandle = getWindowHandle(); if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+ ": offscreen "+offscreenInstance+", recreate "+recreate+ ", pS "+pS+", "+width+"x"+height+", state "+getReconfigStateMaskString(flags)+ - ", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+ + ", preWinHandle "+toHexString(oldWinHandle)+", parentWin "+toHexString(parentWinHandle)+ ", surfaceHandle "+toHexString(surfaceHandle)); // Thread.dumpStack(); } try { - if( 0 != preWinHandle ) { + if( 0 != oldWinHandle ) { setWindowHandle(0); if( 0 == surfaceHandle ) { throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView"); } - IOSUtil.RunOnMainThread(false, false /* kickNSApp */, new Runnable() { - @Override - public void run() { - changeContentView0(parentWinHandle, preWinHandle, 0); - close0( preWinHandle ); - } }); + if( !altCreateWindow ) { + IOSUtil.RunOnMainThread(false, false /* kickNSApp */, new Runnable() { + @Override + public void run() { + changeContentView0(parentWinHandle, oldWinHandle, 0); + close0( oldWinHandle ); + } }); + } } else { if( 0 != surfaceHandle ) { throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView"); } - surfaceHandle = createView0(pS.getX(), pS.getY(), width, height); - if( 0 == surfaceHandle ) { - throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this); + if( !altCreateWindow ) { + surfaceHandle = createView0(pS.getX(), pS.getY(), width, height, reqPixelScale[0]); + if( 0 == surfaceHandle ) { + throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this); + } } } @@ -750,6 +761,34 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl IOSUtil.RunOnMainThread(true, false /* kickNSApp */, new Runnable() { @Override public void run() { + if( altCreateWindow ) { + /** + * Does everything at once, same as original code path: + * 1) if oldWinHandle: changeContentView (detaching view) + close0(oldWindHandle) + * 2) create new window + * 3) create new view if previous didn't exist (oldWinHandle) + * 4) changeContentView (attaching view) etc .. + */ + final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance; + newWin[0] = createWindow1( oldWinHandle, parentWinHandle, pS.getX(), pS.getY(), width, height, reqPixelScale[0], + 0 != ( STATE_MASK_FULLSCREEN & flags), + windowStyle, NSBackingStoreBuffered, + isOpaque, + !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONTOP & flags), + !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags), + !offscreenInstance && 0 != ( STATE_MASK_VISIBLE & flags), + surfaceHandle); + final long uiView = IOSUtil.GetUIView(newWin[0], true); + surfaceHandle = uiView; + + if( offscreenInstance ) { + orderOut0(0!=parentWinHandle ? parentWinHandle : newWin[0]); + } else { + setTitle0(newWin[0], getTitle()); + } + + } else { + newWin[0] = createWindow0( pS.getX(), pS.getY(), width, height, 0 != ( STATE_MASK_FULLSCREEN & flags), windowStyle, @@ -768,9 +807,10 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl setTitle0(newWin[0], getTitle()); } } + } } }); - if ( newWin[0] == 0 ) { + if ( newWin[0] == 0 || 0 == surfaceHandle ) { throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this); } setWindowHandle( newWin[0] ); @@ -785,6 +825,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl /** Must be called on Main-Thread */ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale, boolean opaque, boolean atop, boolean abottom, boolean visible, long view); + private native long createWindow1(long oldWindow, long parentWindow, int x, int y, int w, int h, float reqPixelScale, + boolean fullscreen, int windowStyle, int backingStoreType, + boolean opaque, boolean atop, boolean abottom, boolean visible, long view); private native int getDisplayID0(long window); private native void setPixelScale0(long window, long view, float reqPixelScale); diff --git a/src/newt/native/IOSWindow.m b/src/newt/native/IOSWindow.m index 4778fed96..4c50b0e87 100644 --- a/src/newt/native/IOSWindow.m +++ b/src/newt/native/IOSWindow.m @@ -517,6 +517,109 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_createWindow0 return (jlong) ((intptr_t) myWindow); } +#ifdef VERBOSE_ON + #define DBG_PRINT_CREATEWIN1(n) NSLog(@"createWindow1.%d - parent(win %p scale %f, view %p scale %f), window %p (scale %f, superview %p, hidden %d), view: %p (scale %f, superview %p, hidden %d), CAEAGLLayer %p (opaque %d, scale %f, isCAEAGLLayer %d, hidden %d)\n", \ + (n), parentWindow, (NULL!=parentWindow?[parentWindow contentScaleFactor]:0.0f), parentView, (NULL!=parentView?[parentView contentScaleFactor]:0.0f), \ + myWindow, [myWindow contentScaleFactor], [myWindow superview], [myWindow isHidden], \ + myView, [myView contentScaleFactor], [myView superview], [myView isHidden], \ + l, [l isOpaque], [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]], [l isHidden]); fflush(stderr) +#else + #define DBG_PRINT_CREATEWIN1(n) +#endif + +/** + * Class: jogamp_newt_driver_ios_WindowDriver + * Method: createWindow1 + * Signature: (JJIIIIFZZZZJ)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_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]; + + NewtUIWindow* oldWindow = (NewtUIWindow*) (intptr_t) joldwin ; + NewtUIView* myView = (NewtUIView*) (intptr_t) jview ; + + NSObject* nsParentObj = (NSObject*) ((intptr_t) jparent); + UIWindow* parentWindow = NULL; + UIView* parentView = NULL; + if( nsParentObj != NULL && [nsParentObj isKindOfClass:[UIWindow class]] ) { + parentWindow = (UIWindow*) nsParentObj; + parentView = (UIView*)nsParentObj; + DBG_PRINT( "createWindow1 - Parent is UIWindow : %p (win) -> %p (view) \n", parentWindow, parentView); + } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[UIView class]] ) { + parentView = (UIView*) nsParentObj; + parentWindow = [parentView window]; + DBG_PRINT( "createWindow1 - Parent is UIView : %p -(view) > %p (win) \n", parentView, parentWindow); + } else { + DBG_PRINT( "createWindow1 - Parent is neither UIWindow nor UIView : %p\n", nsParentObj); + } + DBG_PRINT( "createWindow1.0 - %p (this), oldWin %p, parent(win %p, view %p), oldView %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_ios_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); + } + CGRect rectWin = CGRectMake(x, y, w, h); + NewtUIWindow* myWindow = [[[[NewtUIWindow alloc] initWithFrame: rectWin + styleMask: (NSUInteger) styleMask + backing: 0 // TODO (NSBackingStoreType) bufferingType + defer: YES + isFullscreenWindow: fullscreen] autorelease] retain]; + [myWindow setBackgroundColor: [UIColor redColor]]; + if( visible ) { + // Only if calling this before adding the view, the view receives touch events. + // Another 'funny' iOS API nightmare? + [myWindow makeKeyAndVisible]; + } + DBG_PRINT( "createWindow1.1 - window %p, isHidden %d, rootViewController %p\n", myWindow, [myWindow isHidden], myWindow.rootViewController); + + CGRect rectView = CGRectMake(0, 0, w, h); + if( NULL == myView ) { + myView = [[NewtUIView alloc] initWithFrame: rectView] ; + } + CAEAGLLayer* l = (CAEAGLLayer*)[myView layer]; + DBG_PRINT_CREATEWIN1(2); + + changeContentView(env, jthis, parentView, myWindow, myView, NO); + DBG_PRINT_CREATEWIN1(3); + + if(NULL!=parentWindow) { + [myWindow attachToParent: parentWindow]; + } + DBG_PRINT_CREATEWIN1(4); + + // Immediately re-position this window based on an upper-left coordinate system + setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO); + // SEE comment above at makeKeyAndVisible call + // if( visible ) { + // [myWindow makeKeyAndVisible]; + // } + DBG_PRINT_CREATEWIN1(5); + + [myView setDestroyNotifySent: false]; + setJavaWindowObject(env, jthis, myView); + DBG_PRINT_CREATEWIN1(6); + + [myWindow setPixelScale: (CGFloat)reqPixelScale defer:NO]; + DBG_PRINT_CREATEWIN1(88); + + [CATransaction commit]; + [pool release]; + + return (jlong) (intptr_t) myWindow; +} + JNIEXPORT jint JNICALL Java_jogamp_newt_driver_ios_WindowDriver_getDisplayID0(JNIEnv *env, jobject jthis, jlong window) { NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window); if( NULL == myWindow ) { -- cgit v1.2.3