diff options
-rw-r--r-- | make/build-newt.xml | 2 | ||||
-rw-r--r-- | src/demos/com/jogamp/opengl/demos/ios/Hello.java | 137 | ||||
-rw-r--r-- | src/demos/com/jogamp/opengl/demos/ios/Hello1.java | 234 | ||||
-rw-r--r-- | src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java | 2 | ||||
-rw-r--r-- | src/nativewindow/native/ios/IOSmisc.m | 1 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java | 18 | ||||
-rw-r--r-- | src/newt/native/IOSNewtUIWindow.h | 88 | ||||
-rw-r--r-- | src/newt/native/IOSNewtUIWindow.m | 684 | ||||
-rw-r--r-- | src/newt/native/IOSWindow.m | 380 | ||||
-rw-r--r-- | src/newt/native/MacWindow.m | 5 | ||||
-rw-r--r-- | src/newt/native/MouseEvent.h | 6 | ||||
-rw-r--r-- | src/newt/native/NewtCommon.c | 5 | ||||
-rw-r--r-- | src/newt/native/NewtCommon.h | 2 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java | 2 |
14 files changed, 979 insertions, 587 deletions
diff --git a/make/build-newt.xml b/make/build-newt.xml index 1f10e6746..6c475be81 100644 --- a/make/build-newt.xml +++ b/make/build-newt.xml @@ -734,6 +734,8 @@ <includepath path="${src.generated.c}/X11" if="isX11"/> <includepath path="${src.generated.c}/MacOSX" if="isOSX"/> <includepath path="${src.generated.c}/iOS" if="isIOS"/> + <includepath path="${src}/nativewindow/native" if="isIOS"/> + <includepath path="${src}/nativewindow/native/ios" if="isIOS"/> <includepath path="${src.generated.c}/Windows" if="isWindows"/> <includepath path="${src.generated.c}/KD" if="setup.addNativeKD" /> <includepath path="${src.generated.c}/IntelGDL" if="setup.addNativeIntelGDL" /> diff --git a/src/demos/com/jogamp/opengl/demos/ios/Hello.java b/src/demos/com/jogamp/opengl/demos/ios/Hello.java index 9982d7d1f..378868bea 100644 --- a/src/demos/com/jogamp/opengl/demos/ios/Hello.java +++ b/src/demos/com/jogamp/opengl/demos/ios/Hello.java @@ -29,26 +29,20 @@ package com.jogamp.opengl.demos.ios; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.common.util.VersionUtil; -import com.jogamp.nativewindow.AbstractGraphicsScreen; -import com.jogamp.nativewindow.MutableGraphicsConfiguration; -import com.jogamp.nativewindow.NativeWindowFactory; -import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos; - +import com.jogamp.nativewindow.ScalableSurface; +import com.jogamp.newt.Display; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.opengl.GLWindow; import com.jogamp.common.GlueGenVersion; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.demos.es2.RedSquareES2; import com.jogamp.opengl.util.Animator; -import com.jogamp.opengl.util.AnimatorBase; -import jogamp.nativewindow.WrappedWindow; import jogamp.nativewindow.ios.IOSUtil; -import jogamp.opengl.GLDrawableFactoryImpl; -import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; -import com.jogamp.opengl.GLCapabilitiesImmutable; -import com.jogamp.opengl.GLDrawable; -import com.jogamp.opengl.GLDrawableFactory; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLProfile; @@ -60,8 +54,17 @@ public class Hello { } catch (final NumberFormatException nfe) {} return def; } + private static float parseFloat(final String s, final float def) { + try { + return Float.parseFloat(s); + } catch (final NumberFormatException nfe) {} + return def; + } public static void main(final String[] args) { + final float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE }; + + int secondsDuration = 10; // 10s int width = 832, height = 480; // ipad pro 11: 2388x1668 px (scale: 2) int fboDepthBits = -1; // CAEAGLLayer fails with depth 16 + 24 in Simulation; -1 means don't change boolean exitJVM = false; @@ -77,6 +80,11 @@ public class Hello { height = parseInt(args[++i], height); } else if(args[i].equals("-fboDepthBits") && i+1<args.length) { fboDepthBits = parseInt(args[++i], fboDepthBits); + } else if(args[i].equals("-pixelScale") && i+1<args.length) { + reqSurfacePixelScale[0] = parseFloat(args[++i], reqSurfacePixelScale[0]); + reqSurfacePixelScale[1] = reqSurfacePixelScale[0]; + } else if(args[i].equals("-seconds") && i+1<args.length) { + secondsDuration = parseInt(args[++i], secondsDuration); } else { System.err.println("ignoring arg["+i+"]: "+args[i]); } @@ -115,8 +123,7 @@ public class Hello { System.err.println("mark-04"); System.err.println(""); - GLAutoDrawableDelegate glad = null; - final long uiWindow = IOSUtil.CreateUIWindow(0, 0, width, height); + GLWindow glWindow = null; try { // 1) Config .. final GLProfile glp = GLProfile.getGL2ES2(); @@ -125,39 +132,44 @@ public class Hello { reqCaps.setDepthBits(fboDepthBits); } System.out.println("Requested GL Caps: "+reqCaps); - final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(glp); - - // 2) Create native window and wrap it around out NativeWindow structure - final long uiView = IOSUtil.GetUIView(uiWindow, true); - final long caeaglLayer = IOSUtil.GetCAEAGLLayer(uiView); - System.out.println("EAGL: UIWindow 0x"+Long.toHexString(uiWindow)); - System.out.println("EAGL: UIView 0x"+Long.toHexString(uiView)); - System.out.println("EAGL: EAGLLayer 0x"+Long.toHexString(caeaglLayer)); - System.out.println("isUIWindow "+IOSUtil.isUIWindow(uiWindow)+", isUIView "+IOSUtil.isUIView(uiView)+ - ", isCAEAGLLayer "+IOSUtil.isCAEAGLLayer(caeaglLayer)); - final AbstractGraphicsScreen aScreen = NativeWindowFactory.createScreen(NativeWindowFactory.createDevice(null, true /* own */), -1); - final UpstreamWindowHookMutableSizePos hook = new UpstreamWindowHookMutableSizePos(0, 0, width, height, width, height); - final MutableGraphicsConfiguration config = new MutableGraphicsConfiguration(aScreen, reqCaps, reqCaps); - final WrappedWindow nativeWindow = new WrappedWindow(config, uiView, hook, true, uiWindow); - - // 3) Create a GLDrawable .. - final GLDrawable drawable = factory.createGLDrawable(nativeWindow); - drawable.setRealized(true); - // final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(aScreen.getDevice(), reqCaps, null, width, height); - glad = new GLAutoDrawableDelegate(drawable, null, nativeWindow, false, null) { - @Override - protected void destroyImplInLock() { - super.destroyImplInLock(); // destroys drawable/context - nativeWindow.destroy(); // destroys the actual window, incl. the device - IOSUtil.DestroyUIWindow(uiWindow); + + // 2) Create newt native window + final Display dpy = NewtFactory.createDisplay(null); + final Screen screen = NewtFactory.createScreen(dpy, 0); + glWindow = GLWindow.create(screen, reqCaps); + glWindow.setSurfaceScale(reqSurfacePixelScale); + final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]); + glWindow.setSize(width, height); + glWindow.setPosition(0, 0); + final GLEventListener tracker = new GLEventListener() { + void printInfo(final String prefix, final GLAutoDrawable d, final String postfix) { + System.out.print(prefix+": drawable "+d.getSurfaceWidth()+"x"+d.getSurfaceHeight()); + if(null != postfix) { + System.out.println(" - "+postfix); + } else { + System.out.println(); } - }; - glad.display(); // force native context creation + } + @Override + public void init(final GLAutoDrawable drawable) { + printInfo("GLEvent::Init", drawable, null); + } - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); - System.out.println("Choosen GL Caps: "+chosenCaps); + @Override + public void dispose(final GLAutoDrawable drawable) { + printInfo("GLEvent::Dispose", drawable, null); + } + + @Override + public void display(final GLAutoDrawable drawable) { + } + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + printInfo("GLEvent::Reshape", drawable, "reshape["+x+"/"+y+" "+width+"x"+height+"]"); + } + }; + glWindow.addGLEventListener(tracker); GLEventListener demo = null; { try { @@ -170,15 +182,36 @@ public class Hello { } } System.out.println("Choosen demo "+demo.getClass().getName()); - glad.addGLEventListener(demo); + glWindow.addGLEventListener(demo); + glWindow.setVisible(true); // force native context creation + + // Check caps of GLDrawable after realization + System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); + System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+"[wu] "+glWindow.getWidth()+"x"+glWindow.getHeight()+"[wu] "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+"[px], "+glWindow.getInsets()); + + final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]); + System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ + valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+ + hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); + { + final long uiWindow = glWindow.getWindowHandle(); + final long uiView = IOSUtil.GetUIView(uiWindow, true); + final long caeaglLayer = IOSUtil.GetCAEAGLLayer(uiView); + System.out.println("EAGL: UIWindow 0x"+Long.toHexString(uiWindow)); + System.out.println("EAGL: UIView 0x"+Long.toHexString(uiView)); + System.out.println("EAGL: EAGLLayer 0x"+Long.toHexString(caeaglLayer)); + System.out.println("isUIWindow "+IOSUtil.isUIWindow(uiWindow)+", isUIView "+IOSUtil.isUIView(uiView)+ + ", isCAEAGLLayer "+IOSUtil.isCAEAGLLayer(caeaglLayer)); + } final Animator animator = new Animator(); // animator.setExclusiveContext(exclusiveContext); animator.setUpdateFPSFrames(60, System.err); - animator.add(glad); + animator.add(glWindow); animator.start(); - for(int i=0; i<10; i++) { // 10s + for(int i=0; i<secondsDuration; i++) { try { Thread.sleep(1000); } catch (final InterruptedException e) { @@ -188,13 +221,17 @@ public class Hello { animator.stop(); } finally { - if( null != glad ) { - glad.destroy(); + System.err.println(""); + System.err.println("mark-05"); + System.err.println(""); + + if( null != glWindow ) { + glWindow.destroy(); } } System.err.println(""); - System.err.println("mark-05"); + System.err.println("mark-06"); System.err.println(""); if( exitJVM ) { diff --git a/src/demos/com/jogamp/opengl/demos/ios/Hello1.java b/src/demos/com/jogamp/opengl/demos/ios/Hello1.java new file mode 100644 index 000000000..e0c3be871 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/ios/Hello1.java @@ -0,0 +1,234 @@ +/** + * Copyright 2019 Gothel Software e.K. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY Gothel Software e.K. ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Gothel Software e.K. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of Gothel Software e.K. + */ +package com.jogamp.opengl.demos.ios; + +import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.VersionUtil; +import com.jogamp.nativewindow.AbstractGraphicsScreen; +import com.jogamp.nativewindow.MutableGraphicsConfiguration; +import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos; + +import com.jogamp.common.GlueGenVersion; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.demos.es2.RedSquareES2; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; + +import jogamp.nativewindow.WrappedWindow; +import jogamp.nativewindow.ios.IOSUtil; +import jogamp.opengl.GLDrawableFactoryImpl; + +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLAutoDrawableDelegate; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLCapabilitiesImmutable; +import com.jogamp.opengl.GLDrawable; +import com.jogamp.opengl.GLDrawableFactory; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLProfile; + +public class Hello1 { + + private static int parseInt(final String s, final int def) { + try { + return Integer.parseInt(s); + } catch (final NumberFormatException nfe) {} + return def; + } + + public static void main(final String[] args) { + int width = 832, height = 480; // ipad pro 11: 2388x1668 px (scale: 2) + int fboDepthBits = -1; // CAEAGLLayer fails with depth 16 + 24 in Simulation; -1 means don't change + boolean exitJVM = false; + String demoName = "com.jogamp.opengl.demos.es2.GearsES2"; + for(int i=0; i<args.length; i++) { + if(args[i].equals("-exit")) { + exitJVM = true; + } else if(args[i].equals("-demo") && i+1<args.length) { + demoName = args[++i]; + } else if(args[i].equals("-width") && i+1<args.length) { + width = parseInt(args[++i], width); + } else if(args[i].equals("-height") && i+1<args.length) { + height = parseInt(args[++i], height); + } else if(args[i].equals("-fboDepthBits") && i+1<args.length) { + fboDepthBits = parseInt(args[++i], fboDepthBits); + } else { + System.err.println("ignoring arg["+i+"]: "+args[i]); + } + } + System.out.println("Hello JogAmp World: exitJVM "+exitJVM+", size "+width+"x"+height+", fboDepthBits "+fboDepthBits+", demo "+demoName); + System.out.println("os.name: <"+System.getProperty("os.name")+">"); + System.out.println("os.version: <"+System.getProperty("os.version")+">"); + System.out.println("os.arch: <"+System.getProperty("os.arch")+">"); + System.out.println("java.vendor: <"+System.getProperty("java.vendor")+">"); + System.out.println("java.vendor.url: <"+System.getProperty("java.vendor.url")+">"); + System.out.println("java.version: <"+System.getProperty("java.version")+">"); + System.out.println("java.vm.name: <"+System.getProperty("java.vm.name")+">"); + System.out.println("java.runtime.name: <"+System.getProperty("java.runtime.name")+">"); + System.out.println(""); + System.out.println(VersionUtil.getPlatformInfo()); + System.out.println(""); + System.out.println("Version Info:"); + System.out.println(GlueGenVersion.getInstance()); + System.out.println(""); + System.out.println("Full Manifest:"); + System.out.println(GlueGenVersion.getInstance().getFullManifestInfo(null)); + + System.out.println(""); + System.err.println("mark-01"); + System.err.println(""); + System.err.println(JoglVersion.getInstance()); + System.err.println(""); + System.err.println("mark-02"); + System.err.println(""); + GLProfile.initSingleton(); + System.err.println(""); + System.err.println("mark-03"); + System.out.println(""); + System.out.println(JoglVersion.getDefaultOpenGLInfo(GLProfile.getDefaultDevice(), null, true)); + System.out.println(""); + System.err.println("mark-04"); + System.err.println(""); + + GLAutoDrawableDelegate glad = null; + final long uiWindow = IOSUtil.CreateUIWindow(0, 0, width, height); + try { + // 1) Config .. + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities reqCaps = new GLCapabilities(glp); + if( 0 <= fboDepthBits) { + reqCaps.setDepthBits(fboDepthBits); + } + System.out.println("Requested GL Caps: "+reqCaps); + final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(glp); + + // 2) Create native window and wrap it around out NativeWindow structure + final long uiView = IOSUtil.GetUIView(uiWindow, true); + final long caeaglLayer = IOSUtil.GetCAEAGLLayer(uiView); + System.out.println("EAGL: UIWindow 0x"+Long.toHexString(uiWindow)); + System.out.println("EAGL: UIView 0x"+Long.toHexString(uiView)); + System.out.println("EAGL: EAGLLayer 0x"+Long.toHexString(caeaglLayer)); + System.out.println("isUIWindow "+IOSUtil.isUIWindow(uiWindow)+", isUIView "+IOSUtil.isUIView(uiView)+ + ", isCAEAGLLayer "+IOSUtil.isCAEAGLLayer(caeaglLayer)); + final AbstractGraphicsScreen aScreen = NativeWindowFactory.createScreen(NativeWindowFactory.createDevice(null, true /* own */), -1); + final UpstreamWindowHookMutableSizePos hook = new UpstreamWindowHookMutableSizePos(0, 0, width, height, width, height); + final MutableGraphicsConfiguration config = new MutableGraphicsConfiguration(aScreen, reqCaps, reqCaps); + final WrappedWindow nativeWindow = new WrappedWindow(config, uiView, hook, true, uiWindow); + + // 3) Create a GLDrawable .. + final GLDrawable drawable = factory.createGLDrawable(nativeWindow); + drawable.setRealized(true); + // final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(aScreen.getDevice(), reqCaps, null, width, height); + glad = new GLAutoDrawableDelegate(drawable, null, nativeWindow, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + nativeWindow.destroy(); // destroys the actual window, incl. the device + IOSUtil.DestroyUIWindow(uiWindow); + } + }; + final GLEventListener tracker = new GLEventListener() { + void printInfo(final String prefix, final GLAutoDrawable d, final String postfix) { + System.out.print(prefix+": drawable "+d.getSurfaceWidth()+"x"+d.getSurfaceHeight()); + if(null != postfix) { + System.out.println(" - "+postfix); + } else { + System.out.println(); + } + } + @Override + public void init(final GLAutoDrawable drawable) { + printInfo("GLEvent::Init", drawable, null); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + printInfo("GLEvent::Dispose", drawable, null); + } + + @Override + public void display(final GLAutoDrawable drawable) { + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + printInfo("GLEvent::Reshape", drawable, "reshape["+x+"/"+y+" "+width+"x"+height+"]"); + } + }; + glad.addGLEventListener(tracker); + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Choosen GL Caps: "+chosenCaps); + + GLEventListener demo = null; + { + try { + demo = (GLEventListener) ReflectionUtil.createInstance(demoName, Hello1.class.getClassLoader()); + } catch( final Exception e ) { + System.err.println(e.getMessage()+" using: <"+demoName+">"); + } + if( null == demo ) { + demo = new RedSquareES2(); + } + } + System.out.println("Choosen demo "+demo.getClass().getName()); + glad.addGLEventListener(demo); + + final Animator animator = new Animator(); + // animator.setExclusiveContext(exclusiveContext); + animator.setUpdateFPSFrames(60, System.err); + animator.add(glad); + animator.start(); + + for(int i=0; i<10; i++) { // 10s + try { + Thread.sleep(1000); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + animator.stop(); + + } finally { + if( null != glad ) { + glad.destroy(); + } + } + + System.err.println(""); + System.err.println("mark-05"); + System.err.println(""); + + if( exitJVM ) { + System.exit(0); + } + } +} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java index 8e00d318c..63063bef7 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java @@ -103,7 +103,7 @@ public abstract class NativeWindowFactory { public static final String TYPE_MACOSX = ".macosx"; /** iOS type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ - public static final String TYPE_IOS = ".iOS"; + public static final String TYPE_IOS = ".ios"; /** Generic AWT type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ public static final String TYPE_AWT = ".awt"; diff --git a/src/nativewindow/native/ios/IOSmisc.m b/src/nativewindow/native/ios/IOSmisc.m index 70cff4c06..1983143df 100644 --- a/src/nativewindow/native/ios/IOSmisc.m +++ b/src/nativewindow/native/ios/IOSmisc.m @@ -367,6 +367,7 @@ NS_DURING if(NULL != subviews) { for(int i=0; i<[subviews count]; i++) { UIView* sub = [subviews objectAtIndex: i]; + [sub removeFromSuperview]; [sub setHidden: YES]; [sub release]; } diff --git a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java index 79c35c310..5469f74b1 100644 --- a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java @@ -617,6 +617,21 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl SurfaceScaleUtils.scale(y, getPixelScaleY()), button, rotationXYZ, rotationScale); } + public final void sendTouchScreenEvent(final short eventType, final int modifiers, + final int[] pActionIdx, final short[] pNames, + final int[] pTypesI, final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) { + final int pCount = pNames.length; + final MouseEvent.PointerType[] pTypes = new MouseEvent.PointerType[pCount]; + for(int i=0; i<pCount; i++) { + pTypes[i] = MouseEvent.PointerType.valueOf(pTypesI[i]); + } + for(int i=0; i<pActionIdx.length; i++) { + doPointerEvent(false /*enqueue*/, false /*wait*/, + pTypes, eventType, modifiers, pActionIdx[i], true /*normalPNames*/, pNames, + pX, pY, pPressure, maxPressure, new float[] { 0f, 0f, 0f} /*rotationXYZ*/, 1f/*rotationScale*/); + } + } + @Override public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); @@ -765,7 +780,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } protected static native boolean initIDs0(); - private native long createView0(int x, int y, int w, int h); + private native long createView0(int x, int y, int w, int h, float reqPixelScale); private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view); /** Must be called on Main-Thread */ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale, @@ -787,7 +802,6 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl private native void close0(long window); /** Must be called on Main-Thread */ private native void setTitle0(long window, String title); - private native long contentView0(long window); /** Must be called on Main-Thread */ private native void changeContentView0(long parentWindowOrView, long window, long view); /** Must be called on Main-Thread */ diff --git a/src/newt/native/IOSNewtUIWindow.h b/src/newt/native/IOSNewtUIWindow.h index 27ca7f3c7..a335ac4ee 100644 --- a/src/newt/native/IOSNewtUIWindow.h +++ b/src/newt/native/IOSNewtUIWindow.h @@ -31,6 +31,7 @@ #import <pthread.h> #import "jni.h" +#include "CAEAGLLayered.h" #include "NewtCommon.h" // #define VERBOSE_ON 1 @@ -44,7 +45,30 @@ // #define DBG_LIFECYCLE 1 -@interface NewtUIView : UIView +NS_ASSUME_NONNULL_BEGIN + +@interface NamedUITouch : NSObject +{ + @public + short name; + UITouch *touch; + + @protected +} + +- (id)initWithName:(UITouch*)t name:(short)n; + +- (void) dealloc; + +/** Ensure NSPointerFunctionsObjectPointerPersonality for NSArray */ +- (BOOL)isEqual:(id)object; + +/** Ensure NSPointerFunctionsObjectPointerPersonality for NSArray */ +- (NSUInteger)hash; + +@end + +@interface NewtUIView : CAEAGLUIView { jobject javaWindowObject; @@ -52,6 +76,9 @@ volatile int softLockCount; pthread_mutex_t softLockSync; + NSMapTable<UITouch*, NamedUITouch*>* activeTouchMap; + NSMutableArray<NamedUITouch*>* activeTouches; + short nextTouchName; BOOL modsDown[4]; // shift, ctrl, alt/option, win/command } @@ -64,7 +91,7 @@ /* Register or deregister (NULL) the java Window object, ie, if NULL, no events are send */ -- (void) setJavaWindowObject: (jobject) javaWindowObj; +- (void) setJavaWindowObject: (nullable jobject) javaWindowObj; - (jobject) getJavaWindowObject; - (void) setDestroyNotifySent: (BOOL) v; @@ -74,33 +101,34 @@ - (BOOL) softUnlock; - (void) drawRect:(CGRect)dirtyRect; -- (BOOL) acceptsFirstResponder; - (BOOL) becomeFirstResponder; - (BOOL) resignFirstResponder; -- (void) sendMouseEvent: (UIEvent*) event eventType: (jshort) evType; -- (CGPoint) screenPos2NewtClientWinPos: (CGPoint) p; +- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; +- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches; +- (void)sendTouchEvent: (NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event + eventState:(int)eventState newtEventType:(short)newtEventType; -- (void) handleFlagsChanged:(NSUInteger) mods; -- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods; -- (void) sendKeyEvent: (UIEvent*) event eventType: (jshort) evType; -- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType; +- (CGPoint) screenPos2NewtClientWinPos: (CGPoint) p; @end @interface NewtUIWindow : UIWindow { +@protected BOOL realized; - jboolean withinLiveResize; + BOOL useAutoMaxPixelScale; + BOOL withinLiveResize; + NewtUIView* contentNewtUIView; @public - BOOL hasPresentationSwitch; - NSUInteger defaultPresentationOptions; - NSUInteger fullscreenPresentationOptions; BOOL isFullscreenWindow; int cachedInsets[4]; // l, r, t, b } -+ (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz; ++ (BOOL) initNatives: (_Nonnull JNIEnv* _Nonnull) env forClass: (jobject) clazz; - (id) initWithFrame: (CGRect) contentRect styleMask: (NSUInteger) windowStyle @@ -111,13 +139,18 @@ - (void) release; #endif - (void) dealloc; +- (void) setContentNewtUIView: (nullable NewtUIView*)v; +- (NewtUIView*) getContentNewtUIView; - (void) setRealized: (BOOL)v; - (BOOL) isRealized; - (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom; -- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin; -- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer; +- (void) setPixelScale: (CGFloat)reqPixelScale defer:(BOOL)defer; +- (void) updatePixelScale: (BOOL) defer; + +- (void) updateInsets: (_Nullable JNIEnv* _Nullable) env jwin: (nullable jobject) javaWin; +- (void) updateSizePosInsets: (_Nullable JNIEnv* _Nullable) env jwin: (nullable jobject) javaWin defer: (jboolean)defer; - (void) attachToParent: (UIWindow*) parent; - (void) detachFromParent: (UIWindow*) parent; @@ -126,27 +159,24 @@ - (CGPoint) getLocationOnScreen: (CGPoint) p; - (void) focusChanged: (BOOL) gained; +- (void) visibilityChanged: (BOOL) visible; -- (void) flagsChanged: (UIEvent *) theEvent; -- (BOOL) acceptsMouseMovedEvents; -- (BOOL) acceptsFirstResponder; +- (BOOL) canBecomeFirstResponder; - (BOOL) becomeFirstResponder; +- (BOOL) canResignFirstResponder; - (BOOL) resignFirstResponder; -- (BOOL) canBecomeKeyWindow; + - (void) becomeKeyWindow; - (void) resignKeyWindow; -- (void) windowDidBecomeKey: (NSNotification *) notification; -- (void) windowDidResignKey: (NSNotification *) notification; -- (void) windowWillStartLiveResize: (NSNotification *) notification; -- (void) windowDidEndLiveResize: (NSNotification *) notification; -- (CGSize) windowWillResize: (UIWindow *)sender toSize:(CGSize)frameSize; -- (void) windowDidResize: (NSNotification*) notification; -- (void) sendResizeEvent; +- (void) becameVisible: (NSNotification*)notice; +- (void) becameHidden: (NSNotification*)notice; +- (void) sendResizeEvent; - (void) windowDidMove: (NSNotification*) notification; - (BOOL) windowClosingImpl: (BOOL) force; -- (BOOL) windowShouldClose: (id) sender; -- (void) windowWillClose: (NSNotification*) notification; @end + +NS_ASSUME_NONNULL_END + diff --git a/src/newt/native/IOSNewtUIWindow.m b/src/newt/native/IOSNewtUIWindow.m index 6c5031efc..c20dad1a8 100644 --- a/src/newt/native/IOSNewtUIWindow.m +++ b/src/newt/native/IOSNewtUIWindow.m @@ -37,8 +37,9 @@ #define PRINTF(...) NSLog(@ __VA_ARGS__) -static jmethodID enqueueMouseEventID = NULL; -static jmethodID enqueueKeyEventID = NULL; +#define IOS_TOUCH_COUNT 10 + +static jmethodID sendTouchScreenEventID = NULL; static jmethodID requestFocusID = NULL; static jmethodID insetsChangedID = NULL; @@ -57,11 +58,58 @@ static jmethodID windowRepaintID = NULL; // AWT-AppKit // AWT-EventQueue-0 +@implementation NamedUITouch + +- (id)initWithName:(UITouch*)t name:(short)n +{ + self->name = n; + self->touch = [t retain]; + return self; +} +- (void) dealloc +{ + [touch release]; + [super dealloc]; +} + +- (BOOL)isEqual:(id)object +{ + // Ensure NSPointerFunctionsObjectPointerPersonality for NSArray + return self == object; +} +- (NSUInteger)hash +{ + // Ensure NSPointerFunctionsObjectPointerPersonality for NSArray + // + // When building 32-bit applications, NSUInteger is a 32-bit unsigned integer. + // A 64-bit application treats NSUInteger as a 64-bit unsigned integer + // https://developer.apple.com/documentation/objectivec/nsuinteger?language=objc + return (NSUInteger)self; +} + +@end + @implementation NewtUIView - (id)initWithFrame:(CGRect)frameRect { id res = [super initWithFrame:frameRect]; + CAEAGLLayer* l = (CAEAGLLayer*)[self layer]; + [l setOpaque: YES]; + l.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: /* defaults */ + [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; + [self setMultipleTouchEnabled: YES]; // NEWT supports multitouch .. + [self setExclusiveTouch: YES]; // NEWT touches shall keep with NEWT + [self setUserInteractionEnabled: YES]; // Default .. + + // NSMapTable<UITouch*, NamedUITouch*>* activeTouchMap; + // NSHashTable<NamedUITouch*>* activeTouches; + activeTouchMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableStrongMemory|NSMapTableObjectPointerPersonality + valueOptions:NSMapTableStrongMemory|NSMapTableObjectPointerPersonality + capacity:IOS_TOUCH_COUNT]; + activeTouches = [[NSMutableArray alloc] initWithCapacity:IOS_TOUCH_COUNT]; + nextTouchName = 0; + javaWindowObject = NULL; destroyNotifySent = NO; @@ -77,10 +125,10 @@ static jmethodID windowRepaintID = NULL; modsDown[2] = NO; // alt modsDown[3] = NO; // win - DBG_PRINT("NewtUIView::create: %p (refcnt %d)\n", res, (int)[res retainCount]); + DBG_PRINT("NewtUIView::create: %p/%p, CAEAGLLayer %p (pixelScale %f, isCAEAGLLayer %d) (res refcnt %d)\n", + res, self, l, [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]], (int)[res retainCount]); return res; } - #ifdef DBG_LIFECYCLE - (void) release { @@ -91,13 +139,17 @@ static jmethodID windowRepaintID = NULL; - (void) dealloc { - DBG_PRINT("NewtUIView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag); + DBG_PRINT("NewtUIView::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]); #ifdef DBG_LIFECYCLE NSLog(@"%@",[NSThread callStackSymbols]); #endif if( 0 < softLockCount ) { NSLog(@"NewtUIView::dealloc: softLock still hold @ dealloc!\n"); } + [activeTouchMap removeAllObjects]; + [activeTouchMap release]; + [activeTouches removeAllObjects]; + [activeTouches release]; pthread_mutex_destroy(&softLockSync); DBG_PRINT("NewtUIView::dealloc.X: %p\n", self); @@ -126,21 +178,20 @@ static jmethodID windowRepaintID = NULL; - (BOOL) softLock { - // DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self()); int err; if( 0 != ( err = pthread_mutex_lock(&softLockSync) ) ) { NSLog(@"NewtUIView::softLock failed: errCode %d - %@", err, [NSThread callStackSymbols]); return NO; } softLockCount++; - // DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self()); + // DBG_PRINT("*************** softLock: %p count %d\n", (void*)pthread_self(), softLockCount); return 0 < softLockCount; } - (BOOL) softUnlock { - // DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self()); softLockCount--; + // DBG_PRINT("*************** softUnlock: %p count %d\n", (void*)pthread_self(), softLockCount); int err; if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) { softLockCount++; @@ -152,7 +203,7 @@ static jmethodID windowRepaintID = NULL; - (void) drawRect:(CGRect)dirtyRect { - DBG_PRINT("*************** dirtyRect: %p %lf/%lf %lfx%lf\n", + DBG_PRINT("*************** drawRect: dirtyRect: %p %lf/%lf %lfx%lf\n", javaWindowObject, dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height); if(NULL==javaWindowObject) { @@ -176,11 +227,6 @@ static jmethodID windowRepaintID = NULL; // NewtCommon_ReleaseJNIEnv(shallBeDetached); } -- (BOOL) acceptsFirstResponder -{ - return YES; -} - - (BOOL) becomeFirstResponder { DBG_PRINT( "*************** View.becomeFirstResponder\n"); @@ -193,153 +239,210 @@ static jmethodID windowRepaintID = NULL; return [super resignFirstResponder]; } -- (void) sendMouseEvent: (UIEvent*) event eventType: (jshort) evType +- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event { - if (javaWindowObject == NULL) { - DBG_PRINT("sendMouseEvent: null javaWindowObject\n"); - return; - } - int shallBeDetached = 0; - JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); - if(NULL==env) { - DBG_PRINT("sendMouseEvent: null JNIEnv\n"); - return; - } - jint javaMods[] = { 0 } ; - javaMods[0] = 0; // TODO mods2JavaMods([event modifierFlags]); - - // convert to 1-based button number (or use zero if no button is involved) - // TODO: detect mouse button when mouse wheel scrolled - jshort javaButtonNum = 1; - jfloat scrollDeltaY = 0.0f; - /** - switch ([event type]) { - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSLeftMouseDragged: - javaButtonNum = 1; - break; - case NSRightMouseDown: - case NSRightMouseUp: - case NSRightMouseDragged: - javaButtonNum = 3; - break; - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: - javaButtonNum = 2; - break; - default: - javaButtonNum = 0; - break; - } */ - CGPoint location = CGPointMake(0,0); // TODO [self screenPos2NewtClientWinPos: [UIEvent mouseLocation]]; - - (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, - evType, javaMods[0], - (jint) location.x, (jint) location.y, - javaButtonNum, scrollDeltaY); - - // detaching thread not required - daemon - // NewtCommon_ReleaseJNIEnv(shallBeDetached); + [self sendTouchEvent: touches withEvent:event eventState:1 newtEventType:(short)EVENT_MOUSE_PRESSED]; } - -- (CGPoint) screenPos2NewtClientWinPos: (CGPoint) p +- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event { - CGRect viewFrame = [self frame]; - - CGRect r; - r.origin.x = p.x; - r.origin.y = p.y; - r.size.width = 0; - r.size.height = 0; - // CGRect rS = [[self window] convertRectFromScreen: r]; // 10.7 - CGPoint oS = r.origin; // TODO [[self window] convertScreenToBase: r.origin]; - oS.y = viewFrame.size.height - oS.y; // y-flip - return oS; + // Note use of MOUSE_MOVED event type because mouse dragged events are synthesized by Java + [self sendTouchEvent: touches withEvent:event eventState:0 newtEventType:(short)EVENT_MOUSE_MOVED]; } - -- (void) handleFlagsChanged:(NSUInteger) mods +- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event { - // TODO [self handleFlagsChanged: NSShiftKeyMask keyIndex: 0 keyCode: kVK_Shift modifiers: mods]; - // TODO [self handleFlagsChanged: NSControlKeyMask keyIndex: 1 keyCode: kVK_Control modifiers: mods]; - // TODO [self handleFlagsChanged: NSAlternateKeyMask keyIndex: 2 keyCode: kVK_Option modifiers: mods]; - // TODO [self handleFlagsChanged: NSCommandKeyMask keyIndex: 3 keyCode: kVK_Command modifiers: mods]; + [self sendTouchEvent: touches withEvent:event eventState:-1 newtEventType:(short)EVENT_MOUSE_RELEASED]; } - -- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods +- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event { - if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) { - modsDown[keyIdx] = YES; - [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED]; - } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) { - modsDown[keyIdx] = NO; - [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED]; - } + [self sendTouchEvent: touches withEvent:event eventState:-1 newtEventType:(short)EVENT_MOUSE_RELEASED]; } - -- (void) sendKeyEvent: (UIEvent*) event eventType: (jshort) evType +- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches { - jshort keyCode = 0; // TODO (jshort) [event keyCode]; - NSString* chars = NULL; // TODO [event charactersIgnoringModifiers]; - NSUInteger mods = 0; // TODO [event modifierFlags]; - [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType]; } -- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType +- (void)sendTouchEvent: (NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event + eventState:(int)eventState newtEventType:(short)newtEventType { if (javaWindowObject == NULL) { - DBG_PRINT("sendKeyEvent: null javaWindowObject\n"); + DBG_PRINT("sendTouchEvent: null javaWindowObject\n"); return; } int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); if(NULL==env) { - DBG_PRINT("sendKeyEvent: null JNIEnv\n"); + DBG_PRINT("sendTouchEvent: null JNIEnv\n"); return; } + jint newtEventModifiers = 0; // FIXME? + jint touchTypes[IOS_TOUCH_COUNT]; + jshort pointerNames[IOS_TOUCH_COUNT]; + jint x[IOS_TOUCH_COUNT]; + jint y[IOS_TOUCH_COUNT]; + jfloat pressure[IOS_TOUCH_COUNT]; + jint actionIdx[IOS_TOUCH_COUNT]; + int activeTouchesNewIdx = -1; + + DBG_PRINT( "sendTouchEvent.0: Window %p, state %d, newtType %d, touches %d, activeTouches %d, nextTouchName %d\n", + (void*)javaWindowObject, eventState, (int)newtEventType, (int)[touches count], (int)[activeTouches count], nextTouchName); + + // merge new touches into activeTouchMap (unify) and + // add to end of activeTouches array + { + NSEnumerator<UITouch*>* touchesEnum = [touches objectEnumerator]; + UITouch * t; + while( (t = [touchesEnum nextObject]) ) { + NamedUITouch *nt = (NamedUITouch*)[activeTouchMap objectForKey: t]; + if( nil == nt ) { + if( 1 != eventState ) { + // Ooops, not 'touchesBegan' but UITouch not mapped! + NewtCommon_throwNewRuntimeException(env, "Internal Error: touch event (window %p) state %d, newtType %d not mapped", + (void*)javaWindowObject, eventState, (int)newtEventType); + } + if( IOS_TOUCH_COUNT > [activeTouches count] ) { + nt = [[NamedUITouch alloc] initWithName:t name:nextTouchName++]; + [activeTouchMap setObject:nt forKey:t]; + [activeTouches addObject: nt]; + if( 0 > activeTouchesNewIdx ) { + activeTouchesNewIdx = [activeTouches count] - 1; + } + } + } + } + } +#ifdef VERBOSE_ON + { + int activeTouchesNewCount = activeTouchesNewIdx < 0 ? 0 : [activeTouches count] - activeTouchesNewIdx; + DBG_PRINT( "sendTouchEvent.1: Window %p, state %d, newtType %d, touches %d, activeTouches %d, nextTouchName %d, newActiveTouches %d\n", + (void*)javaWindowObject, eventState, (int)newtEventType, (int)[touches count], (int)[activeTouches count], nextTouchName, activeTouchesNewCount); + } +#endif /* VERBOSE_ON */ + + int cnt, actionCnt; + for(cnt=0, actionCnt=0; cnt<[activeTouches count]; cnt++) { + NamedUITouch *nt = [activeTouches objectAtIndex: cnt]; + switch( [nt->touch type] ) { + case UITouchTypeDirect: + case UITouchTypeIndirect: /* ??? */ + touchTypes[cnt] = POINTER_TYPE_TOUCHSCREEN; + break; + case UITouchTypePencil: + touchTypes[cnt] = POINTER_TYPE_PEN; + break; + default: + touchTypes[cnt] = POINTER_TYPE_UNDEF; + break; + } + CGPoint loc = [nt->touch preciseLocationInView: self]; // [touch locationInView: self]; + x[cnt] = (jint)(loc.x); + y[cnt] = (jint)(loc.y); + pressure[cnt] = (jfloat)(nt->touch.force); + pointerNames[cnt] = nt->name; + if( [touches member: nt->touch] ) { + actionIdx[actionCnt++] = cnt; + DBG_PRINT( "sendTouchEvent.2: Window %p, action-touchid[%d]: name %d, idx %d, ptr: %d/%d\n", + (void*)javaWindowObject, (actionCnt-1), nt->name, cnt, x[cnt], y[cnt]); + } else { + DBG_PRINT( "sendTouchEvent.2: Window %p, action-touchid[-1]: name %d, idx %d, ptr: %d/%d\n", + (void*)javaWindowObject, nt->name, cnt, x[cnt], y[cnt]); + } + } + if( 0 >= actionCnt || actionCnt != [touches count]) { + NewtCommon_throwNewRuntimeException(env, "Internal Error: touch event (window %p) %d actionIds not matching %d/%d touches", + (void*)javaWindowObject, actionCnt, (int)[touches count], cnt); + } + if( -1 == eventState ) { + NSEnumerator<UITouch*>* touchesEnum = [touches objectEnumerator]; + UITouch * t; + while( (t = [touchesEnum nextObject]) ) { + NamedUITouch *nt = (NamedUITouch*)[activeTouchMap objectForKey: t]; + if( nil == nt ) { + // Ooops, 'touchesEnded' but UITouch not mapped! + NewtCommon_throwNewRuntimeException(env, "Internal Error: touch event (window %p) state %d, newtType %d not mapped", + (void*)javaWindowObject, eventState, (int)newtEventType); + } + [activeTouchMap removeObjectForKey: t]; + [activeTouches removeObject: nt]; + } + if( 0 == [activeTouches count] ) { + // all finger released .. + nextTouchName = 0; + } + } + DBG_PRINT( "sendTouchEvent.3: Window %p, state %d, newtType %d, touches %d, activeTouches %d, nextTouchName %d\n", + (void*)javaWindowObject, eventState, (int)newtEventType, (int)[touches count], (int)[activeTouches count], nextTouchName); - int i; - int len = NULL != chars ? [chars length] : 0; - jint javaMods = 0; // TODO mods2JavaMods(mods); + jintArray jActionIdx = (*env)->NewIntArray(env, actionCnt); + if (jActionIdx == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", actionCnt); + } + (*env)->SetIntArrayRegion(env, jActionIdx, 0, actionCnt, actionIdx); - if(len > 0) { - // printable chars - for (i = 0; i < len; i++) { - // Note: the key code in the UIEvent does not map to anything we can use - UniChar keyChar = (UniChar) [chars characterAtIndex: i]; - UniChar keySymChar = 0; // TODO CKCH_CharForKeyCode(keyCode); + jshortArray jNames = (*env)->NewShortArray(env, cnt); + if (jNames == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate short array (names) of size %d", cnt); + } + (*env)->SetShortArrayRegion(env, jNames, 0, cnt, pointerNames); - DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar, - (int)mods, (int)javaMods, (int)keySymChar); + jintArray jTouchTypes = (*env)->NewIntArray(env, cnt); + if (jTouchTypes == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (TouchTypes) of size %d", cnt); + } + (*env)->SetIntArrayRegion(env, jTouchTypes, 0, cnt, touchTypes); - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); - } - } else { - // non-printable chars - jchar keyChar = (jchar) 0; + jintArray jX = (*env)->NewIntArray(env, cnt); + if (jX == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", cnt); + } + (*env)->SetIntArrayRegion(env, jX, 0, cnt, x); - DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode); + jintArray jY = (*env)->NewIntArray(env, cnt); + if (jY == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", cnt); + } + (*env)->SetIntArrayRegion(env, jY, 0, cnt, y); - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, keyChar, keyChar); + jfloatArray jPressure = (*env)->NewFloatArray(env, cnt); + if (jPressure == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", cnt); } + (*env)->SetFloatArrayRegion(env, jPressure, 0, cnt, pressure); + + /** + * Pressure (force) "1.0 represents the force of an average touch (predetermined by the system, not user-specific". + * So we pass 2.0f as the maxPressure value. + */ + (*env)->CallVoidMethod(env, javaWindowObject, sendTouchScreenEventID, + (jshort)newtEventType, (jint)newtEventModifiers, + jActionIdx, jNames, jTouchTypes, jX, jY, jPressure, (jfloat)2.0f); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); } +- (CGPoint) screenPos2NewtClientWinPos: (CGPoint) p +{ + CGRect viewFrame = [self frame]; + + CGRect r; + r.origin.x = p.x; + r.origin.y = p.y; + r.size.width = 0; + r.size.height = 0; + // CGRect rS = [[self window] convertRectFromScreen: r]; // 10.7 + CGPoint oS = r.origin; // TODO [[self window] convertScreenToBase: r.origin]; + oS.y = viewFrame.size.height - oS.y; // y-flip + return oS; +} + @end @implementation NewtUIWindow + (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz { - enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V"); - enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V"); + sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SI[I[S[I[I[I[FF)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V"); - updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)V"); + updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFFFZ)V"); visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V"); insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V"); @@ -348,7 +451,7 @@ static jmethodID windowRepaintID = NULL; windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); - if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && + if (sendTouchScreenEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID && sizeScreenPosInsetsChangedID && screenPositionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID) { @@ -364,43 +467,9 @@ static jmethodID windowRepaintID = NULL; defer: (BOOL) deferCreation isFullscreenWindow:(BOOL)isfs { - /** - id res = [super initWithContentRect: contentRect - styleMask: windowStyle - backing: bufferingType - defer: deferCreation]; - */ id res = [super initWithFrame: contentRect]; - // OSX 10.6 - /** TODO - if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] && - [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) { - hasPresentationSwitch = YES; - defaultPresentationOptions = [NSApp currentSystemPresentationOptions]; - fullscreenPresentationOptions = - // NSApplicationPresentationDefault| - // NSApplicationPresentationAutoHideDock| - NSApplicationPresentationHideDock| - // NSApplicationPresentationAutoHideMenuBar| - NSApplicationPresentationHideMenuBar| - NSApplicationPresentationDisableAppleMenu| - // NSApplicationPresentationDisableProcessSwitching| - // NSApplicationPresentationDisableSessionTermination| - NSApplicationPresentationDisableHideApplication| - // NSApplicationPresentationDisableMenuBarTransparency| - // NSApplicationPresentationFullScreen| // OSX 10.7 - 0 ; - } else { - */ - hasPresentationSwitch = NO; - defaultPresentationOptions = 0; - fullscreenPresentationOptions = 0; - // } - + self.rootViewController = [[[UIViewController alloc] initWithNibName:nil bundle:nil] autorelease]; isFullscreenWindow = NO; // TODO isfs; - // Why is this necessary? Without it we don't get any of the - // delegate methods like resizing and window movement. - // TODO [self setDelegate: self]; cachedInsets[0] = 0; // l cachedInsets[1] = 0; // r @@ -409,8 +478,19 @@ static jmethodID windowRepaintID = NULL; realized = YES; withinLiveResize = JNI_FALSE; - DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n", - res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]); + contentNewtUIView = NULL; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(becameVisible:) + name:UIWindowDidBecomeVisibleNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(becameHidden:) + name:UIWindowDidBecomeHiddenNotification + object:nil]; + + DBG_PRINT("NewtWindow::create: %p, realized %d, (refcnt %d)\n", + res, realized, (int)[res retainCount]); return res; } @@ -430,16 +510,36 @@ static jmethodID windowRepaintID = NULL; NSLog(@"%@",[NSThread callStackSymbols]); #endif - /** - NewtUIView* mView = (NewtUIView *)self; // TODO [self contentView]; - if( NULL != mView ) { - [mView release]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + if( NULL != contentNewtUIView ) { + [contentNewtUIView removeFromSuperview]; + [contentNewtUIView release]; + contentNewtUIView=NULL; } - */ [super dealloc]; DBG_PRINT("NewtWindow::dealloc.X: %p\n", self); } +- (void) setContentNewtUIView: (NewtUIView*)v +{ + DBG_PRINT( "NewtWindow::setContentNewtUIView.0: view %p -> %p\n", contentNewtUIView, v); + if( NULL != contentNewtUIView ) { + [contentNewtUIView removeFromSuperview]; + [contentNewtUIView release]; + contentNewtUIView=NULL; + } + contentNewtUIView = v; + if( NULL != contentNewtUIView ) { + [contentNewtUIView retain]; + [self addSubview: contentNewtUIView]; + } +} +- (NewtUIView*) getContentNewtUIView +{ + return contentNewtUIView; +} + - (void) setRealized: (BOOL)v { realized = v; @@ -465,6 +565,110 @@ static jmethodID windowRepaintID = NULL; } */ } +- (void) updatePixelScale: (BOOL) defer +{ + NewtUIView* newtView = contentNewtUIView; + DBG_PRINT( "updatePixelScale view %p, autoMaxPixelScale %d, defer %d\n", + newtView, useAutoMaxPixelScale, defer); + if( NULL == newtView ) { + return; + } + jobject javaWindowObject = [newtView getJavaWindowObject]; + if ( NULL == javaWindowObject ) { + DBG_PRINT("updatePixelScale: null javaWindowObject\n"); + return; + } + int shallBeDetached = 0; + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); + if(NULL==env) { + DBG_PRINT("updatePixelScale: null JNIEnv\n"); + return; + } + + CGFloat oldPixelScaleV = [newtView contentScaleFactor]; + CGFloat oldPixelScaleL = [[newtView layer] contentsScale]; + UIScreen* _screen = [self screen]; + CGFloat maxPixelScale = [_screen scale]; + CGFloat pixelScale; + BOOL changeScale; + if ( useAutoMaxPixelScale ) { + pixelScale = maxPixelScale; + changeScale = pixelScale != oldPixelScaleV || pixelScale != oldPixelScaleL; + } else { + pixelScale = oldPixelScaleV; + changeScale = NO; + } + DBG_PRINT("updatePixelScale: PixelScale: autoMaxPixelScale %d, max %f, view %f, layer %f -> %f (change %d)\n", + useAutoMaxPixelScale, (float)maxPixelScale, (float)oldPixelScaleV, (float)oldPixelScaleL, (float)pixelScale, changeScale); + if( changeScale ) { + [newtView setContentScaleFactor: pixelScale]; + [[newtView layer] setContentsScale: pixelScale]; + } + (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, defer?JNI_TRUE:JNI_FALSE, + (jfloat)oldPixelScaleV, (jfloat)pixelScale, (jfloat)maxPixelScale, (jboolean)changeScale); + + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); +} +- (void) setPixelScale: (CGFloat)reqPixelScale defer:(BOOL)defer +{ + NewtUIView* newtView = contentNewtUIView; + useAutoMaxPixelScale = NewtCommon_isFloatZero(reqPixelScale); + DBG_PRINT( "setPixelScale view %p, reqPixelScale %f, autoMaxPixelScale %d, defer %d\n", + newtView, reqPixelScale, useAutoMaxPixelScale, defer); + if( NULL == newtView ) { + return; + } + jobject javaWindowObject = [newtView getJavaWindowObject]; + if ( NULL == javaWindowObject ) { + DBG_PRINT("setPixelScale: null javaWindowObject\n"); + return; + } + int shallBeDetached = 0; + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); + if(NULL==env) { + DBG_PRINT("setPixelScale: null JNIEnv\n"); + return; + } + + CGFloat oldPixelScaleV = [newtView contentScaleFactor]; + CGFloat oldPixelScaleL = [[newtView layer] contentsScale]; + UIScreen* _screen = [self screen]; + { + CGRect _bounds = [_screen bounds]; + CGRect _nativeBounds = [_screen nativeBounds]; + CGFloat _scale = [_screen scale]; + CGFloat _nativeScale = [_screen nativeScale]; + DBG_PRINT("setPixelScale: screen %p[native %f/%f %fx%f scale %f; logical %f/%f %fx%f scale %f]\n", + _screen, + _nativeBounds.origin.x, _nativeBounds.origin.y, _nativeBounds.size.width, _nativeBounds.size.height, _nativeScale, + _bounds.origin.x, _bounds.origin.y, _bounds.size.width, _bounds.size.height, _scale); + } + CGFloat maxPixelScale = [_screen scale]; + CGFloat pixelScale; + BOOL changeScale; + if ( useAutoMaxPixelScale || maxPixelScale < reqPixelScale ) { + pixelScale = maxPixelScale; + } else if( 0 > reqPixelScale ) { + pixelScale = 1.0f; + } else { + pixelScale = reqPixelScale; + } + changeScale = pixelScale != oldPixelScaleV || pixelScale != oldPixelScaleL; + DBG_PRINT("setPixelScale: PixelScale: autoMaxPixelScale %d, max %f, view %f, layer %f, req %f -> %f (change %d)\n", + useAutoMaxPixelScale, (float)maxPixelScale, (float)oldPixelScaleV, (float)oldPixelScaleL, (float)reqPixelScale, (float)pixelScale, changeScale); + + if( changeScale ) { + [newtView setContentScaleFactor: pixelScale]; + [[newtView layer] setContentsScale: pixelScale]; + } + (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, defer?JNI_TRUE:JNI_FALSE, + (jfloat)oldPixelScaleV, (jfloat)pixelScale, (jfloat)maxPixelScale, (jboolean)changeScale); + + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); +} + - (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin { /** @@ -498,8 +702,8 @@ static jmethodID windowRepaintID = NULL; CGRect frameRect = [self frame]; - UIScreen* screen = [self screen]; - CGPoint pS = [self convertPoint: frameRect.origin toCoordinateSpace: screen.fixedCoordinateSpace]; + UIScreen* _screen = [self screen]; + CGPoint pS = [self convertPoint: frameRect.origin toCoordinateSpace: _screen.fixedCoordinateSpace]; DBG_PRINT( "updateSize: [ w %d, h %d ], liveResize %d\n", (jint) frameRect.size.width, (jint) frameRect.size.height, (jint)withinLiveResize); DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) pS.x, (jint) pS.y); @@ -518,26 +722,27 @@ static jmethodID windowRepaintID = NULL; - (void) attachToParent: (UIWindow*) parent { - /** TODO DBG_PRINT( "attachToParent.1\n"); - [parent addChildWindow: self ordered: UIWindowAbove]; - DBG_PRINT( "attachToParent.2\n"); - [self setParentWindow: parent]; + [parent addSubview: self]; + // [self setwindowLevel: [parent windowLevel]+1.0f]; + // NSWindow: [parent addChildWindow: self ordered: UIWindowAbove]; + // NSWindow: [self setParentWindow: parent]; DBG_PRINT( "attachToParent.X\n"); - */ } - (void) detachFromParent: (UIWindow*) parent { - /** TODO DBG_PRINT( "detachFromParent.1\n"); + [self removeFromSuperview]; + /** + // NSWindow: [self setParentWindow: nil]; if(NULL != parent) { DBG_PRINT( "detachFromParent.2\n"); [parent removeChildWindow: self]; } - DBG_PRINT( "detachFromParent.X\n"); */ + DBG_PRINT( "detachFromParent.X\n"); } /** @@ -561,8 +766,8 @@ static jmethodID windowRepaintID = NULL; */ - (CGPoint) getLocationOnScreen: (CGPoint) p { - UIScreen* screen = [self screen]; - CGPoint pS = [self convertPoint: p toCoordinateSpace: screen.fixedCoordinateSpace]; + UIScreen* _screen = [self screen]; + CGPoint pS = [self convertPoint: p toCoordinateSpace: _screen.fixedCoordinateSpace]; #ifdef VERBOSE_ON CGRect winFrame = [self frame]; @@ -577,10 +782,13 @@ static jmethodID windowRepaintID = NULL; - (void) focusChanged: (BOOL) gained { - DBG_PRINT( "focusChanged: gained %d\n", gained); - NewtUIView* newtView = (NewtUIView *) self; // TODO [self contentView]; + NewtUIView* newtView = contentNewtUIView; + DBG_PRINT( "focusChanged: gained %d, view %p\n", gained, newtView); + if( NULL == newtView ) { + return; + } jobject javaWindowObject = [newtView getJavaWindowObject]; - if (javaWindowObject == NULL) { + if ( NULL == javaWindowObject ) { DBG_PRINT("focusChanged: null javaWindowObject\n"); return; } @@ -597,48 +805,55 @@ static jmethodID windowRepaintID = NULL; // NewtCommon_ReleaseJNIEnv(shallBeDetached); } -- (void) flagsChanged:(UIEvent *) theEvent +- (void) visibilityChanged: (BOOL) visible { - NSUInteger mods = [theEvent modifierFlags]; - NewtUIView* newtView = (NewtUIView *) [self contentView]; - if( [newtView isKindOfClass:[NewtUIView class]] ) { - [newtView handleFlagsChanged: mods]; + DBG_PRINT( "visibilityChanged: visible %d\n", visible); + NewtUIView* newtView = contentNewtUIView; + if( NULL == newtView ) { + return; } -} + jobject javaWindowObject = [newtView getJavaWindowObject]; + if ( NULL == javaWindowObject ) { + DBG_PRINT("visibilityChanged: null javaWindowObject\n"); + return; + } + int shallBeDetached = 0; + JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); + if(NULL==env) { + DBG_PRINT("visibilityChanged: null JNIEnv\n"); + return; + } + (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE, (visible == YES) ? JNI_TRUE : JNI_FALSE); -- (BOOL) acceptsMouseMovedEvents -{ - return YES; + // detaching thread not required - daemon + // NewtCommon_ReleaseJNIEnv(shallBeDetached); } -- (BOOL) acceptsFirstResponder +- (BOOL) canBecomeFirstResponder { return YES; } - - (BOOL) becomeFirstResponder { DBG_PRINT( "*************** Win.becomeFirstResponder\n"); return [super becomeFirstResponder]; } +- (BOOL) canResignFirstResponder +{ + return YES; +} - (BOOL) resignFirstResponder { DBG_PRINT( "*************** Win.resignFirstResponder\n"); return [super resignFirstResponder]; } -- (BOOL) canBecomeKeyWindow -{ - // Even if the window is borderless, we still want it to be able - // to become the key window to receive keyboard events - return YES; -} - - (void) becomeKeyWindow { DBG_PRINT( "*************** becomeKeyWindow\n"); [super becomeKeyWindow]; + [self focusChanged: YES]; } - (void) resignKeyWindow @@ -647,66 +862,53 @@ static jmethodID windowRepaintID = NULL; if(!isFullscreenWindow) { [super resignKeyWindow]; } -} - -- (void) windowDidResignKey: (NSNotification *) notification -{ - DBG_PRINT( "*************** windowDidResignKey\n"); - // Implicit mouse exit by OS X [self focusChanged: NO]; } -- (void) windowWillStartLiveResize: (NSNotification *) notification +- (void) becameVisible: (NSNotification*)notice { - DBG_PRINT( "*************** windowWillStartLiveResize\n"); - withinLiveResize = JNI_TRUE; -} -- (void) windowDidEndLiveResize: (NSNotification *) notification -{ - DBG_PRINT( "*************** windowDidEndLiveResize\n"); - withinLiveResize = JNI_FALSE; - [self sendResizeEvent]; + DBG_PRINT( "*************** becameVisible\n"); + [self visibilityChanged: YES]; } -- (CGSize) windowWillResize: (UIWindow *)sender toSize:(CGSize)frameSize -{ - DBG_PRINT( "*************** windowWillResize %lfx%lf\n", frameSize.width, frameSize.height); - return frameSize; -} -- (void)windowDidResize: (NSNotification*) notification + +- (void) becameHidden: (NSNotification*)notice { - DBG_PRINT( "*************** windowDidResize\n"); - [self sendResizeEvent]; + DBG_PRINT( "*************** becameHidden\n"); + [self visibilityChanged: NO]; } - (void) sendResizeEvent { - jobject javaWindowObject = NULL; + // FIXME: Needs to be called + NewtUIView* newtView = contentNewtUIView; + if( NULL == newtView ) { + return; + } + jobject javaWindowObject = [newtView getJavaWindowObject]; + if ( NULL == javaWindowObject ) { + DBG_PRINT("sendResizeEvent: null javaWindowObject\n"); + return; + } int shallBeDetached = 0; JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); - if( NULL == env ) { DBG_PRINT("windowDidResize: null JNIEnv\n"); return; } - NewtUIView* newtView = (NewtUIView *) [self contentView]; - if( [newtView isKindOfClass:[NewtUIView class]] ) { - javaWindowObject = [newtView getJavaWindowObject]; - } - if( NULL != javaWindowObject ) { - [self updateSizePosInsets: env jwin: javaWindowObject defer:JNI_TRUE]; - } + [self updateSizePosInsets: env jwin: javaWindowObject defer:JNI_TRUE]; // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); } - (void)windowDidMove: (NSNotification*) notification { - NewtUIView* newtView = (NewtUIView *) [self contentView]; - if( ! [newtView isKindOfClass:[NewtUIView class]] ) { + // FIXME: Needs to be called + NewtUIView* newtView = contentNewtUIView; + if( NULL == newtView ) { return; } jobject javaWindowObject = [newtView getJavaWindowObject]; - if (javaWindowObject == NULL) { + if ( NULL == javaWindowObject ) { DBG_PRINT("windowDidMove: null javaWindowObject\n"); return; } @@ -726,31 +928,21 @@ static jmethodID windowRepaintID = NULL; // NewtCommon_ReleaseJNIEnv(shallBeDetached); } -- (BOOL)windowShouldClose: (id) sender -{ - return [self windowClosingImpl: NO]; -} - -- (void)windowWillClose: (NSNotification*) notification -{ - [self windowClosingImpl: YES]; -} - - (BOOL) windowClosingImpl: (BOOL) force { + // FIXME: Needs to be called jboolean closed = JNI_FALSE; - NewtUIView* newtView = (NewtUIView *) [self contentView]; - if( ! [newtView isKindOfClass:[NewtUIView class]] ) { + NewtUIView* newtView = contentNewtUIView; + if( NULL == newtView ) { return NO; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [newtView cursorHide: NO enter: -1]; if( false == [newtView getDestroyNotifySent] ) { jobject javaWindowObject = [newtView getJavaWindowObject]; DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); - if (javaWindowObject == NULL) { + if ( NULL == javaWindowObject ) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); [pool release]; return NO; diff --git a/src/newt/native/IOSWindow.m b/src/newt/native/IOSWindow.m index a8e816fbe..4778fed96 100644 --- a/src/newt/native/IOSWindow.m +++ b/src/newt/native/IOSWindow.m @@ -65,8 +65,7 @@ static void setWindowClientTopLeftPoint(NewtUIWindow* mWin, jint x, jint y, BOOL DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y); if( doDisplay ) { - // TODO UIView* mView = [mWin contentView]; - // TODO [mWin invalidateCursorRectsForView: mView]; + [mWin setNeedsDisplay]; } } @@ -75,14 +74,14 @@ static void setWindowClientTopLeftPointAndSize(NewtUIWindow* mWin, jint x, jint CGRect rect = CGRectMake(x, y, width, height); 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); - // TODO [mWin setFrame: rect display:doDisplay]; [mWin setFrame: rect]; + if( doDisplay ) { + [mWin setNeedsDisplay]; + } 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 ) { - // UIView* mView = [mWin contentView]; - // [mWin invalidateCursorRectsForView: mView]; + // [mWin setNeedsDisplay]; // } } @@ -112,39 +111,20 @@ static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtUI } static void changeContentView(JNIEnv *env, jobject javaWindowObject, UIView *pview, NewtUIWindow *win, NewtUIView *newView, BOOL setJavaWindow) { - UIView* oldUIView = NULL; // TODO [win contentView]; - NewtUIView* oldNewtUIView = NULL; + NewtUIView* oldNewtUIView = [win getContentNewtUIView]; #ifdef VERBOSE_ON int dbgIdx = 1; #endif + DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), parent view %p\n", + dbgIdx++, win, oldNewtUIView, getRetainCount(oldNewtUIView), newView, getRetainCount(newView), pview); - if( [oldUIView isKindOfClass:[NewtUIView class]] ) { - oldNewtUIView = (NewtUIView *) oldUIView; + if( NULL != oldNewtUIView ) { + [oldNewtUIView setDestroyNotifySent: false]; + setJavaWindowObject(env, NULL, oldNewtUIView); + [win setContentNewtUIView: NULL]; // includes [oldNewtUIView removeFromSuperview]; } - - DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n", - dbgIdx++, win, oldUIView, getRetainCount(oldUIView), NULL!=oldNewtUIView, newView, getRetainCount(newView), pview); - - if( NULL!=oldUIView ) { -NS_DURING - // Available >= 10.5 - Makes the menubar disapear - BOOL iifs = NO; // TODO [oldUIView isInFullScreenMode]; - if( iifs ) { - // TODO [oldUIView exitFullScreenModeWithOptions: NULL]; - } -NS_HANDLER -NS_ENDHANDLER - DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n", - dbgIdx++, win, oldUIView, getRetainCount(oldUIView), NULL!=oldNewtUIView, newView, getRetainCount(newView)); - - if( NULL != oldNewtUIView ) { - [oldNewtUIView setDestroyNotifySent: false]; - setJavaWindowObject(env, NULL, oldNewtUIView, NO); - } - // TODO [oldUIView removeFromSuperviewWithoutNeedingDisplay]; - } - DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", - dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); + DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d\n", + dbgIdx++, win, oldNewtUIView, getRetainCount(oldNewtUIView), newView, getRetainCount(newView), [newView isHidden]); if( NULL!=newView ) { [newView setDestroyNotifySent: false]; @@ -152,25 +132,22 @@ NS_ENDHANDLER setJavaWindowObject(env, javaWindowObject, newView); } DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n", - dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView)); - - if(NULL!=pview) { - // TODO [pview addSubview: newView positioned: UIWindowAbove relativeTo: nil]; - } - } - DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", - dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); + dbgIdx++, win, oldNewtUIView, getRetainCount(oldNewtUIView), newView, getRetainCount(newView)); - // TODO [win setContentView: newView]; + [win setContentNewtUIView: newView]; // includes [win addSubview: newView]; + // FIXME: Done in initWindow0: [pview addSubview: newView] - DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n", - dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]); + DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d\n", + dbgIdx++, win, oldNewtUIView, getRetainCount(oldNewtUIView), newView, getRetainCount(newView), [newView isHidden]); + } + DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d\n", + dbgIdx++, win, oldNewtUIView, getRetainCount(oldNewtUIView), newView, getRetainCount(newView), [newView isHidden]); // 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, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView)); + win, oldNewtUIView, getRetainCount(oldNewtUIView), newView, getRetainCount(newView)); } /* @@ -205,16 +182,16 @@ static void NewtScreen_dump() { int i; for(i=0; i<[screens count]; i++) { UIScreen * screen = (UIScreen *) [screens objectAtIndex: i]; - CGRect screenFrame = [screen frame]; - CGRect screenVisibleFrame = [screen visibleFrame]; - CGFloat pixelScale = 1.0; // default - pixelScale = [screen scale]; // HiDPI scaling - UIWindowDepth depth = [screen depth]; // an (int) value! - DBG_PRINT( "UIScreen #%d (%p): Frame %lf/%lf %lfx%lf (vis %lf/%lf %lfx%lf), scale %lf, depth %d\n", + CGRect screenPxFrame = [screen nativeBounds]; + CGRect screenPtFrame = [screen bounds]; + CGFloat pixelScale = [screen scale]; + CGFloat nativeScale = [screen nativeScale]; + int depth = 32; // [screen depth]; // an (int) value! + DBG_PRINT( "UIScreen #%d (%p): Frame %lf/%lf %lfx%lf px (%lf/%lf %lfx%lf pt), scale %lf (%lf native), 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); + screenPxFrame.origin.x, screenPxFrame.origin.y, screenPxFrame.size.width, screenPxFrame.size.height, + screenPtFrame.origin.x, screenPtFrame.origin.y, screenPtFrame.size.width, screenPtFrame.size.height, + pixelScale, nativeScale, depth); } #endif } @@ -270,7 +247,7 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorP fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL); #endif NSArray *screens = [UIScreen screens]; - int count = [screens count]; + // int count = [screens count]; UIScreen * screen = (UIScreen *) [screens objectAtIndex: crt_id]; if( NULL == screen ) { [pool release]; @@ -282,18 +259,24 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorP fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL); #endif - UIScreenMode * screenMode = [screen currentMode]; + // UIScreenMode * screenMode = [screen currentMode]; CGSize sizeMM = CGSizeMake(161.0, 228.0); // TODO ??? #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 = [screen bounds]; + CGRect bounds = [screen bounds]; #ifdef VERBOSE_ON - DBG_PRINT( "getMonitorProps0: crt_id 0x%X (prim %d), top-left displayBounds[%d/%d %dx%d]\n", - (int)crt_id, isPrimary, - (int)dBounds.origin.x, (int)dBounds.origin.y, (int)dBounds.size.width, (int)dBounds.size.height); + { + CGRect nativeBounds = [screen nativeBounds]; + CGFloat nativeScale = [screen nativeScale]; + CGFloat scale = [screen scale]; + DBG_PRINT( "getMonitorProps0: crt_id 0x%X (prim %d) %p[\n native %f/%f %fx%f scale %f; logical %f/%f %fx%f scale %f]\n", + (int)crt_id, isPrimary, screen, + nativeBounds.origin.x, nativeBounds.origin.y, nativeBounds.size.width, nativeBounds.size.height, nativeScale, + bounds.origin.x, bounds.origin.y, bounds.size.width, bounds.size.height, scale); + } #endif jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES; @@ -305,14 +288,14 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorP 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) + prop[offset++] = (jint) bounds.origin.x; // rotated viewport x (pixel units, will be fixed in java code) + prop[offset++] = (jint) bounds.origin.y; // rotated viewport y (pixel units, will be fixed in java code) + prop[offset++] = (jint) bounds.size.width; // rotated viewport width (pixel units, will be fixed in java code) + prop[offset++] = (jint) bounds.size.height; // rotated viewport height (pixel units, will be fixed in java code) + prop[offset++] = (jint) bounds.origin.x; // rotated viewport x (window units, will be fixed in java code) + prop[offset++] = (jint) bounds.origin.y; // rotated viewport y (window units, will be fixed in java code) + prop[offset++] = (jint) bounds.size.width; // rotated viewport width (window units, will be fixed in java code) + prop[offset++] = (jint) bounds.size.height; // rotated viewport height (window units, will be fixed in java code) jintArray properties = (*env)->NewIntArray(env, propCount); if (properties == NULL) { @@ -336,19 +319,13 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorM NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSArray<UIScreen*> *screens = [UIScreen screens]; - int count = [screens count]; + // int count = [screens count]; UIScreen * screen = (UIScreen *) [screens objectAtIndex: crt_id]; if( NULL == screen ) { [pool release]; return NULL; } - CGFloat pixelScale = 1.0; // default -NS_DURING - // Available >= 10.7 - pixelScale = [screen scale]; // HiDPI scaling -NS_HANDLER -NS_ENDHANDLER - + CGFloat pixelScale = [screen scale]; NSArray<UIScreenMode*> *availableModes = [screen availableModes]; int numberOfAvailableModes = [availableModes count]; CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes; @@ -361,7 +338,7 @@ NS_ENDHANDLER 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); + crt_id, screen, pixelScale, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot); } #endif @@ -387,10 +364,6 @@ NS_ENDHANDLER CGSize mSize = [mode size]; int mWidth = (int)mSize.width; int mHeight = (int)mSize.height; - 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 ) { @@ -491,15 +464,15 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_WindowDriver_initIDs0 * Signature: (IIII)J */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_createView0 - (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h) + (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h, jfloat reqPixelScale) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d (START)\n", - (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h); + DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d, reqPixelScale %f (START)\n", + (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale); CGRect rectView = CGRectMake(0, 0, w, h); - NewtUIView *myView = [[NewtUIView alloc] initWithFrame: rectView] ; + NewtUIView *myView = [[NewtUIView alloc] initWithFrame: rectView]; DBG_PRINT( "createView0.X - new view: %p\n", myView); [pool release]; @@ -519,6 +492,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_createWindow0 jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [CATransaction begin]; NewtUIView* myView = (NewtUIView*) (intptr_t) jview ; DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, view %p (START)\n", @@ -526,21 +500,18 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_createWindow0 (int)styleMask, (int)bufferingType, myView); (void)myView; - if (fullscreen) { - // TODO styleMask = NSBorderlessWindowMask; - } + (void)fullscreen; CGRect rectWin = CGRectMake(x, y, w, h); // Allocate the window - NewtUIWindow* myWindow = [[NewtUIWindow alloc] initWithContentRect: rectWin + NewtUIWindow* myWindow = [[[[NewtUIWindow alloc] initWithFrame: rectWin styleMask: (NSUInteger) styleMask backing: 0 // TODO (NSBackingStoreType) bufferingType defer: YES - isFullscreenWindow: fullscreen]; - // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]); - - DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]); + isFullscreenWindow: fullscreen] autorelease] retain]; + DBG_PRINT( "createWindow0.X - %p, isHidden %d\n", myWindow, [myWindow isHidden]); + [CATransaction commit]; [pool release]; return (jlong) ((intptr_t) myWindow); @@ -553,7 +524,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_ios_WindowDriver_getDisplayID0(JN return 0; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - UIScreen *screen = [myWindow screen]; + // UIScreen *screen = [myWindow screen]; int32_t displayID = 0; // TODO (int32_t)NewtScreen_getCGDirectDisplayIDByUIScreen(screen); [pool release]; return (jint) displayID; @@ -571,17 +542,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_initWindow0 jboolean opaque, jboolean atop, jboolean abottom, jboolean visible, jlong jview) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [CATransaction begin]; + NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window); NewtUIView* myView = (NewtUIView*) (intptr_t) jview ; + CAEAGLLayer* l = (CAEAGLLayer*)[myView layer]; BOOL fullscreen = myWindow->isFullscreenWindow; - DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, atop %d, abottom %d, fs %d, visible %d, view %p (START)\n", - (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale, - (int) opaque, (int)atop, (int)abottom, (int)fullscreen, (int)visible, myView); - - // TODO [myWindow setReleasedWhenClosed: NO]; // We control UIWindow destruction! - // TODO [myWindow setPreservesContentDuringLiveResize: NO]; - NSObject* nsParentObj = (NSObject*) ((intptr_t) parent); UIWindow* parentWindow = NULL; UIView* parentView = NULL; @@ -596,121 +563,79 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_initWindow0 } else { DBG_PRINT( "initWindow0 - Parent is neither UIWindow nor UIView : %p\n", nsParentObj); } - DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]); + DBG_PRINT( "initWindow0.1 - window %p, isHidden %d, rootViewController %p\n", myWindow, [myWindow isHidden], myWindow.rootViewController); + DBG_PRINT( "initWindow0.2 - parent(win %p scale %f, view %p scale %f), window %p (scale %f, superview %p), view: %p (scale %f, superview %p), CAEAGLLayer %p (opaque %d, scale %f, isCAEAGLLayer %d)\n", + parentWindow, (NULL!=parentWindow?[parentWindow contentScaleFactor]:0.0f), parentView, (NULL!=parentView?[parentView contentScaleFactor]:0.0f), + myWindow, [myWindow contentScaleFactor], [myWindow superview], + myView, [myView contentScaleFactor], [myView superview], + l, [l isOpaque], [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]]); // Remove animations for child windows - if(NULL != parentWindow) { - [UIView setAnimationsEnabled: NO]; - } + // if(NULL != parentWindow) { + // [UIView setAnimationsEnabled: NO]; + // } -#ifdef VERBOSE_ON - int dbgIdx = 1; -#endif if(opaque) { - [myWindow setOpaque: YES]; - DBG_PRINT( "initWindow0.%d\n", dbgIdx++); - if (!fullscreen) { - // TODO [myWindow setShowsResizeIndicator: YES]; - } - DBG_PRINT( "initWindow0.%d\n", dbgIdx++); + // FIXME [myWindow setOpaque: YES]; + (void) fullscreen; // No extra handling + [myWindow setBackgroundColor: [UIColor redColor]]; // FIXME TEST } else { [myWindow setOpaque: NO]; [myWindow setBackgroundColor: [UIColor clearColor]]; } [myWindow setAlwaysOn: atop bottom:abottom]; - // specify we want mouse-moved events - // TODO [myWindow setAcceptsMouseMovedEvents:YES]; - - DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", - dbgIdx++, myWindow, myView, [myWindow isVisible]); + DBG_PRINT( "initWindow0.3 - parent(win %p scale %f, view %p scale %f), window %p (scale %f, superview %p), view: %p (scale %f, superview %p), CAEAGLLayer %p (opaque %d, scale %f, isCAEAGLLayer %d)\n", + parentWindow, (NULL!=parentWindow?[parentWindow contentScaleFactor]:0.0f), parentView, (NULL!=parentView?[parentView contentScaleFactor]:0.0f), + myWindow, [myWindow contentScaleFactor], [myWindow superview], + myView, [myView contentScaleFactor], [myView superview], + l, [l isOpaque], [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]]); // Set the content view changeContentView(env, jthis, parentView, myWindow, myView, NO); - // TODO [myWindow setInitialFirstResponder: myView]; - DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", - dbgIdx++, myWindow, myView, [myWindow isVisible]); + DBG_PRINT( "initWindow0.4 - parent(win %p scale %f, view %p scale %f), window %p (scale %f, superview %p), view: %p (scale %f, superview %p), CAEAGLLayer %p (opaque %d, scale %f, isCAEAGLLayer %d)\n", + parentWindow, (NULL!=parentWindow?[parentWindow contentScaleFactor]:0.0f), parentView, (NULL!=parentView?[parentView contentScaleFactor]:0.0f), + myWindow, [myWindow contentScaleFactor], [myWindow superview], + myView, [myView contentScaleFactor], [myView superview], + l, [l isOpaque], [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]]); if(NULL!=parentWindow) { [myWindow attachToParent: parentWindow]; } - DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d, visible %d\n", - dbgIdx++, myWindow, myView, [myWindow isVisible], visible); + DBG_PRINT( "initWindow0.5 - parent(win %p scale %f, view %p scale %f), window %p (scale %f, superview %p), view: %p (scale %f, superview %p), CAEAGLLayer %p (opaque %d, scale %f, isCAEAGLLayer %d)\n", + parentWindow, (NULL!=parentWindow?[parentWindow contentScaleFactor]:0.0f), parentView, (NULL!=parentView?[parentView contentScaleFactor]:0.0f), + myWindow, [myWindow contentScaleFactor], [myWindow superview], + myView, [myView contentScaleFactor], [myView superview], + l, [l isOpaque], [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]]); // Immediately re-position this window based on an upper-left coordinate system setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO); - - DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", - dbgIdx++, myWindow, myView, [myWindow isVisible]); - - // TODO [myWindow setAllowsConcurrentViewDrawing: YES]; - - DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", - dbgIdx++, myWindow, myView, [myWindow isVisible]); - - // TODO [myView setCanDrawConcurrently: YES]; - - DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n", - dbgIdx++, myWindow, myView, [myWindow isVisible]); - - // visible on front if( visible ) { - // TODO [myWindow orderFront: myWindow]; + [myWindow makeKeyAndVisible]; } - DBG_PRINT( "initWindow0.%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 - // TODO [myView setNextResponder: myWindow]; - - DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", - dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); - + DBG_PRINT( "initWindow0.6 - parent(win %p scale %f, view %p scale %f), window %p (scale %f, superview %p), view: %p (scale %f, superview %p), CAEAGLLayer %p (opaque %d, scale %f, isCAEAGLLayer %d)\n", + parentWindow, (NULL!=parentWindow?[parentWindow contentScaleFactor]:0.0f), parentView, (NULL!=parentView?[parentView contentScaleFactor]:0.0f), + myWindow, [myWindow contentScaleFactor], [myWindow superview], + myView, [myView contentScaleFactor], [myView superview], + l, [l isOpaque], [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]]); [myView setDestroyNotifySent: false]; setJavaWindowObject(env, jthis, myView); - DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", - dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); - -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 @ - * <https://developer.apple.com/library/mac/documentation/graphicsimaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html> - * - UIScreen *myScreen = NewtScreen_getUIScreenByCoord(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 ) { - DBG_PRINT( "initWindow0.%d - %p view %p, setPresentationOptions 0x%X\n", - dbgIdx++, myWindow, myView, (int)myWindow->fullscreenPresentationOptions); - // TODO [NSApp setPresentationOptions: myWindow->fullscreenPresentationOptions]; - } - } -NS_HANDLER -NS_ENDHANDLER + [myWindow setPixelScale: (CGFloat)reqPixelScale defer:NO]; + + (void) fullscreen; // No extra handling - DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n", - dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); + DBG_PRINT( "initWindow0.X - parent(win %p scale %f, view %p scale %f), window %p (scale %f, superview %p), view: %p (scale %f, superview %p), CAEAGLLayer %p (opaque %d, scale %f, isCAEAGLLayer %d)\n", + parentWindow, (NULL!=parentWindow?[parentWindow contentScaleFactor]:0.0f), parentView, (NULL!=parentView?[parentView contentScaleFactor]:0.0f), + myWindow, [myWindow contentScaleFactor], [myWindow superview], + myView, [myView contentScaleFactor], [myView superview], + l, [l isOpaque], [l contentsScale], [l isKindOfClass:[CAEAGLLayer class]]); + [CATransaction commit]; [pool release]; - DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p\n", - (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView); } /** @@ -729,20 +654,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setPixelScale0 return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NewtUIView* myView = (NewtUIView*) (intptr_t) view ; -#ifdef VERBOSE_ON - int dbgIdx = 1; -#endif - DBG_PRINT( "setPixelScale0 - %p (this), %p (window), view %p, reqPixScale %f (START)\n", - (void*)(intptr_t)jthis, myWindow, myView, (float)reqPixelScale); - (void)myWindow; - - DBG_PRINT( "setPixelScale0.%d - %p (this), window: %p, view %p\n", - dbgIdx++, (void*)(intptr_t)jthis, myWindow, myView); + [myWindow setPixelScale: (CGFloat)reqPixelScale defer:YES]; [pool release]; - DBG_PRINT( "setPixelScale0.X - %p (this), window: %p, view %p\n", - (void*)(intptr_t)jthis, myWindow, myView); } /** @@ -762,7 +676,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_close0 } BOOL isNSWin = [mWin isKindOfClass:[UIWindow class]]; BOOL isNewtWin = [mWin isKindOfClass:[NewtUIWindow class]]; - UIWindow *pWin = NULL; // TODO [mWin parentWindow]; + UIWindow *pWin; + { + UIView *superview = [mWin superview]; + if( [superview isKindOfClass:[UIWindow class]] ) { + pWin = (UIWindow*)superview; + } else { + pWin = NULL; + } + } DBG_PRINT( "windowClose.0 - %p [isUIWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin); (void)isNSWin; // silence if( !isNewtWin ) { @@ -770,7 +692,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_close0 return; } NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NewtUIView* mView = (NewtUIView *)mWin; // TODO [mWin contentView]; + NewtUIView* mView = [mWin getContentNewtUIView]; BOOL fullscreen = mWin->isFullscreenWindow; BOOL destroyNotifySent, isUIView, isNewtUIView; if( NULL != mView ) { @@ -794,32 +716,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_close0 setJavaWindowObject(env, NULL, mView); } -NS_DURING - /** - * See Bug 914: We don't use exclusive fullscreen anymore (capturing display) - * See initWindow0(..) 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); - // TODO [NSApp setPresentationOptions: mWin->defaultPresentationOptions]; - } -NS_HANDLER -NS_ENDHANDLER + DBG_PRINT( "windowClose.1a - %p view %p, fullscreen %d\n", + mWin, mView, (int)fullscreen); if(NULL!=pWin) { [mWin detachFromParent: pWin]; @@ -946,7 +845,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_orderFront0 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; UIWindow* pWin = NULL; // TODO [mWin parentWindow]; - DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); + DBG_PRINT( "orderFront0 - window: (parent %p) %p hidden %d (START)\n", pWin, mWin, [mWin isHidden]); if( NULL == pWin ) { // TODO [mWin orderFrontRegardless]; @@ -975,7 +874,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_orderOut0 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; UIWindow* pWin = NULL; // TODO [mWin parentWindow]; - DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]); + DBG_PRINT( "orderOut0 - window: (parent %p) %p hidden %d (START)\n", pWin, mWin, [mWin isHidden]); if( NULL == pWin ) { // TODO [mWin orderOut: mWin]; @@ -1014,31 +913,6 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setTitle0 [pool release]; } -/* - * Class: jogamp_newt_driver_ios_WindowDriver - * Method: contentView0 - * Signature: (J)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_contentView0 - (JNIEnv *env, jobject unused, jlong window) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - UIWindow* win = (UIWindow*) ((intptr_t) window); - UIView* nsView = (UIView*)win; // TODO [win contentView]; - NewtUIView* newtView = NULL; - - if( [nsView isKindOfClass:[NewtUIView class]] ) { - newtView = (NewtUIView *) 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. * @@ -1062,7 +936,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_changeContentVie if( NULL != nsParentObj ) { if( [nsParentObj isKindOfClass:[UIWindow class]] ) { UIWindow * pWin = (UIWindow*) nsParentObj; - pView = (UIView*)pWin; // TODO [pWin contentView]; + pView = (UIView*)pWin; } else if( [nsParentObj isKindOfClass:[UIView class]] ) { pView = (UIView*) nsParentObj; } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 5775633be..c1fcdf51e 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -126,11 +126,9 @@ static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pvi #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); @@ -1066,9 +1064,6 @@ NS_DURING NS_HANDLER NS_ENDHANDLER - DBG_PRINT( "setPixelScale0.%d - %p (this), window: %p, view %p\n", - dbgIdx++, (void*)(intptr_t)jthis, myWindow, myView); - [pool release]; DBG_PRINT( "setPixelScale0.X - %p (this), window: %p, view %p\n", (void*)(intptr_t)jthis, myWindow, myView); diff --git a/src/newt/native/MouseEvent.h b/src/newt/native/MouseEvent.h index 59d63cecf..3baeb2dae 100644 --- a/src/newt/native/MouseEvent.h +++ b/src/newt/native/MouseEvent.h @@ -39,4 +39,10 @@ #define EVENT_MOUSE_WHEEL_MOVED 207 // Generated by Java: EVENT_MOUSE_DRAGGED = 206; +#define POINTER_TYPE_MOUSE 0 +#define POINTER_TYPE_TOUCHPAD 1 +#define POINTER_TYPE_TOUCHSCREEN 2 +#define POINTER_TYPE_PEN 3 +#define POINTER_TYPE_UNDEF 4 + #endif diff --git a/src/newt/native/NewtCommon.c b/src/newt/native/NewtCommon.c index d580012ef..ec10b2da5 100644 --- a/src/newt/native/NewtCommon.c +++ b/src/newt/native/NewtCommon.c @@ -27,6 +27,7 @@ */ #include "NewtCommon.h" #include <string.h> +#include <math.h> static const char * const ClazzNameRuntimeException = "java/lang/RuntimeException"; static jclass runtimeExceptionClz=NULL; @@ -166,3 +167,7 @@ void NewtCommon_ReleaseJNIEnv (int shallBeDetached) { } } +int NewtCommon_isFloatZero(float f) { + // EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d + return fabsf(f) < 1.1920929E-7f; +} diff --git a/src/newt/native/NewtCommon.h b/src/newt/native/NewtCommon.h index 43db72b5b..d4ce2f3e8 100644 --- a/src/newt/native/NewtCommon.h +++ b/src/newt/native/NewtCommon.h @@ -74,4 +74,6 @@ JNIEnv* NewtCommon_GetJNIEnv (int asDaemon, int * shallBeDetached); void NewtCommon_ReleaseJNIEnv (int shallBeDetached); +int NewtCommon_isFloatZero(float f); + #endif diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java index 6aebeb91b..d87a18b2f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java @@ -201,7 +201,7 @@ public class TestGearsES2SimpleNEWT extends UITestCase { System.err.println("NW chosen: "+glWindow.getDelegatedWindow().getChosenCapabilities()); System.err.println("GL chosen: "+glWindow.getChosenCapabilities()); - System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets()); + System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+"[wu] "+glWindow.getWidth()+"x"+glWindow.getHeight()+"[wu] "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+"[px], "+glWindow.getInsets()); final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]); System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+ |