From 004c67c73a0309158c30929cd0d6513e23f34803 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
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(-)

(limited to 'src')

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