From bba73bc096250a3c7fc036d84b1ea054d1b70b06 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sun, 23 Jun 2019 08:03:04 +0200 Subject: iOS: Initial working commit supporting iOS (ipad pro 11) using our OpenJFK 9 x86_64 and arm64 build. Test demo class is 'com.jogamp.opengl.demos.ios.Hello', residing in the new demo folder 'src/demos/com/jogamp/opengl/demos/ios/Hello.java'. This commit does not yet include a working NEWT specialization for iOS, but it shall followup soon. Instead this commit demonstrates JOGL operating on native UIWindow, UIView and CAEAGLLayer as provided by Nativewindow's IOSUtil. Test Video https://www.youtube.com/watch?v=Z4lUQNFTGMI +++ Notable bug: The FBO used and sharing the COLORBUFFER RENDERBUFFER memory resources with CAEAGLLayer to be displayed in the UIView seemingly cannot handle GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32 depth buffer - none at all (Device + Simulation). Therefor the default demo GLEventListener chosen here don't require a depth buffer ;-) This issue can hopefully be mitigated with other means than using a flat FBO sink similar to FBO multisampling. --- .../jogamp/nativewindow/NativeWindowFactory.java | 17 + .../jogamp/nativewindow/ios/IOSGraphicsDevice.java | 46 ++ .../jogamp/nativewindow/javafx/JFXAccessor.java | 2 + .../ios/IOSDummyUpstreamSurfaceHook.java | 83 +++ .../classes/jogamp/nativewindow/ios/IOSUtil.java | 333 +++++++++ src/nativewindow/native/JVM_JNI8.c | 47 ++ src/nativewindow/native/ios/CAEAGLLayered.h | 50 ++ src/nativewindow/native/ios/CAEAGLLayered.m | 66 ++ src/nativewindow/native/ios/IOSmisc.m | 813 +++++++++++++++++++++ .../native/ios/NativeWindowProtocols.h | 59 ++ src/nativewindow/native/macosx/OSXmisc.m | 16 +- 11 files changed, 1524 insertions(+), 8 deletions(-) create mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java create mode 100644 src/nativewindow/native/JVM_JNI8.c create mode 100644 src/nativewindow/native/ios/CAEAGLLayered.h create mode 100644 src/nativewindow/native/ios/CAEAGLLayered.m create mode 100644 src/nativewindow/native/ios/IOSmisc.m create mode 100644 src/nativewindow/native/ios/NativeWindowProtocols.h (limited to 'src/nativewindow') diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java index 323bc8c86..8e00d318c 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java @@ -52,6 +52,7 @@ import jogamp.nativewindow.NativeWindowFactoryImpl; import jogamp.nativewindow.ToolkitProperties; import jogamp.nativewindow.ResourceToolkitLock; import jogamp.nativewindow.WrappedWindow; +import jogamp.nativewindow.ios.IOSUtil; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.nativewindow.windows.GDIUtil; import jogamp.nativewindow.x11.X11Lib; @@ -65,6 +66,7 @@ import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.nativewindow.awt.AWTGraphicsScreen; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.nativewindow.ios.IOSGraphicsDevice; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; @@ -100,6 +102,9 @@ public abstract class NativeWindowFactory { /** Mac OS X type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ 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"; + /** Generic AWT type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */ public static final String TYPE_AWT = ".awt"; @@ -120,6 +125,8 @@ public abstract class NativeWindowFactory { private static final String X11UtilClassName = "jogamp.nativewindow.x11.X11Util"; /** {@link jogamp.nativewindow.macosx.OSXUtil} implements {@link ToolkitProperties}. */ private static final String OSXUtilClassName = "jogamp.nativewindow.macosx.OSXUtil"; + /** {@link jogamp.nativewindow.ios.IOSUtil} implements {@link ToolkitProperties}. */ + private static final String IOSUtilClassName = "jogamp.nativewindow.ios.IOSUtil"; /** {@link jogamp.nativewindow.windows.GDIUtil} implements {@link ToolkitProperties}. */ private static final String GDIClassName = "jogamp.nativewindow.windows.GDIUtil"; @@ -143,6 +150,8 @@ public abstract class NativeWindowFactory { return TYPE_ANDROID; case MACOS: return TYPE_MACOSX; + case IOS: + return TYPE_IOS; case WINDOWS: return TYPE_WINDOWS; case OPENKODE: @@ -204,6 +213,8 @@ public abstract class NativeWindowFactory { clazzName = GDIClassName; } else if( TYPE_MACOSX == nativeWindowingTypePure ) { clazzName = OSXUtilClassName; + } else if( TYPE_IOS == nativeWindowingTypePure ) { + clazzName = IOSUtilClassName; } else { clazzName = null; } @@ -294,6 +305,8 @@ public abstract class NativeWindowFactory { clazzName = GDIClassName; } else if( TYPE_MACOSX == nativeWindowingTypePure ) { clazzName = OSXUtilClassName; + } else if( TYPE_IOS == nativeWindowingTypePure ) { + clazzName = IOSUtilClassName; } else { clazzName = null; } @@ -677,6 +690,8 @@ public abstract class NativeWindowFactory { return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) { return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); + } else if( NativeWindowFactory.TYPE_IOS == nwt ) { + return new IOSGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT); } else if( NativeWindowFactory.TYPE_EGL == nwt ) { final EGLGraphicsDevice device; if( own ) { @@ -742,6 +757,8 @@ public abstract class NativeWindowFactory { return GDIUtil.GetRelativeLocation(nw.getWindowHandle(), 0, 0, 0); } else if( NativeWindowFactory.TYPE_MACOSX == nwt ) { return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), 0, 0); + } else if( NativeWindowFactory.TYPE_IOS == nwt ) { + return IOSUtil.GetLocationOnScreen(nw.getWindowHandle(), 0, 0); /** * FIXME: Needs service provider interface (SPI) for TK dependent implementation } else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java new file mode 100644 index 000000000..0a4354c9d --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java @@ -0,0 +1,46 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ + +package com.jogamp.nativewindow.ios; + +import com.jogamp.nativewindow.*; + +/** Encapsulates a graphics device on IOS platforms. + */ +public class IOSGraphicsDevice extends DefaultGraphicsDevice implements Cloneable { + /** Constructs a new IOSGraphicsDevice */ + public IOSGraphicsDevice(final int unitID) { + super(NativeWindowFactory.TYPE_IOS, AbstractGraphicsDevice.DEFAULT_CONNECTION, unitID); + } + + @Override + public Object clone() { + return super.clone(); + } +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java index bffabdd5a..9d38b1f4b 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java @@ -62,6 +62,7 @@ public class JFXAccessor { private static final String nwt; private static final boolean isOSX; + private static final boolean isIOS; private static final boolean isWindows; private static final boolean isX11; @@ -130,6 +131,7 @@ public class JFXAccessor { nwt = NativeWindowFactory.getNativeWindowType(false); isOSX = NativeWindowFactory.TYPE_MACOSX == nwt; + isIOS = NativeWindowFactory.TYPE_IOS == nwt; isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt; isX11 = NativeWindowFactory.TYPE_X11 == nwt; diff --git a/src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..a61287f8b --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java @@ -0,0 +1,83 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ +package jogamp.nativewindow.ios; + +import com.jogamp.nativewindow.NativeSurface; +import com.jogamp.nativewindow.NativeWindowException; +import com.jogamp.nativewindow.ProxySurface; +import com.jogamp.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; + +public class IOSDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + long uiWindow; + + /** + * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public IOSDummyUpstreamSurfaceHook(final int width, final int height) { + super(width, height); + uiWindow = 0; + } + + @Override + public final void create(final ProxySurface s) { + if(0 == uiWindow && 0 == s.getSurfaceHandle()) { + uiWindow = IOSUtil.CreateUIWindow(0, 0, 64, 64); + if(0 == uiWindow) { + throw new NativeWindowException("Error UI window 0"); + } + final long uiView = IOSUtil.GetUIView(uiWindow, true); + if(0 == uiView) { + throw new NativeWindowException("Error UI view 0"); + } + s.setSurfaceHandle(uiView); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(final ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( 0 == uiWindow || 0 == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no IOS view/window: "+s+", uiWindow 0x"+Long.toHexString(uiWindow)); + } + IOSUtil.DestroyUIWindow(uiWindow); + uiWindow = 0; + s.setSurfaceHandle(0); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java new file mode 100644 index 000000000..bd4b36239 --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java @@ -0,0 +1,333 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ +package jogamp.nativewindow.ios; + +import com.jogamp.nativewindow.NativeWindowException; +import com.jogamp.nativewindow.NativeWindowFactory; +import com.jogamp.nativewindow.util.Insets; +import com.jogamp.nativewindow.util.Point; +import com.jogamp.common.util.Function; +import com.jogamp.common.util.FunctionTask; +import com.jogamp.common.util.InterruptedRuntimeException; +import com.jogamp.common.util.RunnableTask; + +import jogamp.nativewindow.Debug; +import jogamp.nativewindow.NWJNILibLoader; +import jogamp.nativewindow.ToolkitProperties; + +public class IOSUtil implements ToolkitProperties { + private static boolean isInit = false; + private static final boolean DEBUG = Debug.debug("IOSUtil"); + + /** FIXME HiDPI: OSX unique and maximum value {@value} */ + public static final int MAX_PIXELSCALE = 2; + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static synchronized void initSingleton() { + if(!isInit) { + if(DEBUG) { + System.out.println("IOSUtil.initSingleton()"); + } + if(!NWJNILibLoader.loadNativeWindow("ios")) { + throw new NativeWindowException("NativeWindow IOS native library load error."); + } + + if( !initIDs0() ) { + throw new NativeWindowException("IOS: Could not initialized native stub"); + } + isInit = true; + } + } + + /** + * Called by {@link NativeWindowFactory#shutdown()} + * @see ToolkitProperties + */ + public static void shutdown() { } + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static boolean requiresToolkitLock() { return false; } + + /** + * Called by {@link NativeWindowFactory#initSingleton()} + * @see ToolkitProperties + */ + public static final boolean hasThreadingIssues() { return false; } + + public static boolean isCALayer(final long object) { + return 0 != object ? isCALayer0(object) : false; + } + + public static boolean isCAEAGLLayer(final long object) { + return 0 != object ? isCAEAGLLayer0(object) : false; + } + + public static boolean isUIView(final long object) { + return 0 != object ? isUIView0(object) : false; + } + + public static boolean isUIWindow(final long object) { + return 0 != object ? isUIWindow0(object) : false; + } + + /** + * @param windowOrView + * @param src_x + * @param src_y + * @return top-left client-area position in window units + */ + public static Point GetLocationOnScreen(final long windowOrView, final int src_x, final int src_y) { + return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + } + + public static Insets GetInsets(final long windowOrView) { + return (Insets) GetInsets0(windowOrView); + } + + public static double GetPixelScaleByDisplayID(final int displayID) { + if( 0 != displayID ) { + return GetPixelScale1(displayID); + } else { + return 1.0; // default + } + } + public static double GetPixelScale(final long windowOrView) { + if( 0 != windowOrView ) { + return GetPixelScale2(windowOrView); + } else { + return 1.0; // default + } + } + + public static long CreateUIWindow(final int x, final int y, final int width, final int height) { + final long res[] = { 0 }; + RunOnMainThread(true, false /* kickNSApp */, new Runnable() { + @Override + public void run() { + res[0] = CreateUIWindow0(x, y, width, height); + } } ); + return res[0]; + } + public static void DestroyUIWindow(final long uiWindow) { + DestroyUIWindow0(uiWindow); + } + public static long GetCALayer(final long uiView) { + return 0 != uiView ? GetCALayer0(uiView) : 0; + } + public static long GetCAEAGLLayer(final long uiView) { + return 0 != uiView ? GetCAEAGLLayer0(uiView) : 0; + } + public static long GetUIView(final long uiWindow, final boolean onlyEAGL) { + return 0 != uiWindow ? GetUIView0(uiWindow, onlyEAGL) : 0; + } + public static long GetUIWindow(final long uiView) { + return 0 != uiView ? GetUIWindow0(uiView) : 0; + } + + /** + * Set the UIView's pixelScale / contentScale for HiDPI + * + * @param uiView the mutable UIView instance + * @param contentScaleFactor scale for HiDPI support: pixel-dim = window-dim x scale + */ + public static void SetUIViewPixelScale(final long uiView, final float contentScaleFactor) { + SetUIViewPixelScale0(uiView, contentScaleFactor); + } + /** + * Get the UIView's pixelScale / contentScale for HiDPI + * + * @param uiView the UIView instance + * @return used scale for HiDPI support: pixel-dim = window-dim x scale + */ + public static float GetUIViewPixelScale(final long uiView) { + return GetUIViewPixelScale0(uiView); + } + + /** + * Set root and sub CALayer pixelScale / contentScale for HiDPI + * + * @param rootCALayer the root surface layer, maybe null. + * @param subCALayer the client surface layer, maybe null. + * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale + */ + public static void SetCALayerPixelScale(final long rootCALayer, final long subCALayer, final float contentsScale) { + if( 0==rootCALayer && 0==subCALayer ) { + return; + } + SetCALayerPixelScale0(rootCALayer, subCALayer, contentsScale); + } + /** + * Get the CALayer's pixelScale / contentScale for HiDPI + * + * @param caLayer the CALayer instance + * @return used scale for HiDPI support: pixel-dim = window-dim x scale + */ + public static float GetCALayerPixelScale(final long caLayer) { + return GetCALayerPixelScale0(caLayer); + } + + /** + * Run on OSX UI main thread. + *

+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link RunnableTask} to not freeze OSX main thread. + *

+ * + * @param waitUntilDone + * @param kickNSApp if true issues {@link #KickUIApp()} + * @param runnable + */ + public static void RunOnMainThread(final boolean waitUntilDone, final boolean kickNSApp, final Runnable runnable) { + if( IsMainThread0() ) { + runnable.run(); // don't leave the JVM + } else { + // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread, + // otherwise we may freeze the OSX main thread. + final Object sync = new Object(); + final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err ); + synchronized(sync) { + RunOnMainThread0(kickNSApp, rt); + if( waitUntilDone ) { + while( rt.isInQueue() ) { + try { + sync.wait(); + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } + final Throwable throwable = rt.getThrowable(); + if(null!=throwable) { + throw new RuntimeException(throwable); + } + } + } + } + } + } + + /** + * Run later on .. + * @param onMain if true, run on main-thread, otherwise on the current OSX thread. + * @param runnable + * @param delay delay to run the runnable in milliseconds + */ + public static void RunLater(final boolean onMain, final Runnable runnable, final int delay) { + RunLater0(onMain, false /* kickNSApp */, new RunnableTask( runnable, null, true, System.err ), delay); + } + + private static Runnable _nop = new Runnable() { @Override public void run() {}; }; + + /** Issues a {@link #RunOnMainThread(boolean, boolean, Runnable)} w/ an NOP runnable, while waiting until done and issuing {@link #KickUIApp()}. */ + public static void WaitUntilFinish() { + RunOnMainThread(true, true /* kickNSApp */, _nop); + } + + /** + * Run on OSX UI main thread. + *

+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link FunctionTask} to not freeze OSX main thread. + *

+ * + * @param waitUntilDone + * @param kickUIApp if true issues {@link #KickUIApp()} + * @param func + */ + public static R RunOnMainThread(final boolean waitUntilDone, final boolean kickUIApp, final Function func, final A... args) { + if( IsMainThread0() ) { + return func.eval(args); // don't leave the JVM + } else { + // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread, + // otherwise we may freeze the OSX main thread. + final Object sync = new Object(); + final FunctionTask rt = new FunctionTask( func, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err ); + synchronized(sync) { + rt.setArgs(args); + RunOnMainThread0(kickUIApp, rt); + if( waitUntilDone ) { + while( rt.isInQueue() ) { + try { + sync.wait(); + } catch (final InterruptedException ie) { + throw new InterruptedRuntimeException(ie); + } + final Throwable throwable = rt.getThrowable(); + if(null!=throwable) { + throw new RuntimeException(throwable); + } + } + } + } + return rt.getResult(); + } + } + + public static boolean IsMainThread() { + return IsMainThread0(); + } + + /** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */ + public static int GetScreenRefreshRate(final int scrn_idx) { + return GetScreenRefreshRate0(scrn_idx); + } + + public static void CreateGLViewDemoA() { + CreateGLViewDemoA0(); + } + + private static native boolean initIDs0(); + private static native boolean isCALayer0(long object); + private static native boolean isCAEAGLLayer0(long object); + private static native boolean isUIView0(long object); + private static native boolean isUIWindow0(long object); + private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); + private static native Object GetInsets0(long windowOrView); + private static native double GetPixelScale1(int displayID); + private static native double GetPixelScale2(long windowOrView); + private static native long CreateUIWindow0(int x, int y, int width, int height); + private static native void DestroyUIWindow0(long uiWindow); + private static native long GetCALayer0(long uiView); + private static native long GetCAEAGLLayer0(long uiView); + private static native long GetUIView0(long uiWindow, boolean onlyEAGL); + private static native long GetUIWindow0(long uiView); + private static native void SetUIViewPixelScale0(final long uiView, final float contentScaleFactor); + private static native float GetUIViewPixelScale0(final long uiView); + private static native void SetCALayerPixelScale0(long rootCALayer, long subCALayer, float contentsScale); + private static native float GetCALayerPixelScale0(final long caLayer); + + private static native void RunOnMainThread0(boolean kickNSApp, Runnable runnable); + private static native void RunLater0(boolean onMain, boolean kickNSApp, Runnable runnable, int delay); + private static native void KickUIApp0(); + private static native boolean IsMainThread0(); + private static native int GetScreenRefreshRate0(int scrn_idx); + private static native void CreateGLViewDemoA0(); + +} diff --git a/src/nativewindow/native/JVM_JNI8.c b/src/nativewindow/native/JVM_JNI8.c new file mode 100644 index 000000000..a7b4e5d90 --- /dev/null +++ b/src/nativewindow/native/JVM_JNI8.c @@ -0,0 +1,47 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ + +#include //required by android to identify NULL +#include + +#if defined (JNI_VERSION_1_8) + +JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_awt(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; } +JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_x11(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; } +JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_win32(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; } +JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_macosx(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; } +JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_ios(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; } + +JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_awt(JavaVM *vm, void *reserved) { } +JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_x11(JavaVM *vm, void *reserved) { } +JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_win32(JavaVM *vm, void *reserved) { } +JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_macosx(JavaVM *vm, void *reserved) { } +JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_ios(JavaVM *vm, void *reserved) { } + +#endif /* defined (JNI_VERSION_1_8) */ + diff --git a/src/nativewindow/native/ios/CAEAGLLayered.h b/src/nativewindow/native/ios/CAEAGLLayered.h new file mode 100644 index 000000000..fe94dc907 --- /dev/null +++ b/src/nativewindow/native/ios/CAEAGLLayered.h @@ -0,0 +1,50 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ + +#ifndef CAEAGL_LAYERED_H +#define CAEAGL_LAYERED_H 1 + +#import +#import + +#include "NativewindowCommon.h" + +@interface CAEAGLUIView : UIView +{ +} +// override ++ (Class)layerClass; + ++ (CAEAGLUIView*) findCAEAGLUIView: (UIWindow*) win + startIdx: (int) sidx; + ++ (UIView*) getUIView: (UIWindow*) win + startIdx: (int) sidx; +@end /* interface CAEAGLUIView */ + +#endif diff --git a/src/nativewindow/native/ios/CAEAGLLayered.m b/src/nativewindow/native/ios/CAEAGLLayered.m new file mode 100644 index 000000000..3d378e997 --- /dev/null +++ b/src/nativewindow/native/ios/CAEAGLLayered.m @@ -0,0 +1,66 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ + +#include "CAEAGLLayered.h" + +@implementation CAEAGLUIView +// override ++ (Class)layerClass { + return CAEAGLLayer.self; +} +/** +override class var layerClass : AnyClass { + return CAEAGLLayer.self +} +*/ ++ (CAEAGLUIView*) findCAEAGLUIView: (UIWindow*) win + startIdx: (int) sidx +{ + NSArray* subviews = [win subviews]; + if(NULL != subviews) { + for(int i=sidx; i<[subviews count]; i++) { + UIView* sub = [subviews objectAtIndex: i]; + if( [sub isKindOfClass:[CAEAGLUIView class]] ) { + return (CAEAGLUIView*)sub; + } + } + } + return (CAEAGLUIView*)NULL; +} ++ (UIView*) getUIView: (UIWindow*) win + startIdx: (int) sidx +{ + NSArray* subviews = [win subviews]; + if(NULL != subviews) { + if( sidx<[subviews count] ) { + return [subviews objectAtIndex: sidx]; + } + } + return (UIView*)NULL; +} +@end /* implementation CAEAGLUIView */ diff --git a/src/nativewindow/native/ios/IOSmisc.m b/src/nativewindow/native/ios/IOSmisc.m new file mode 100644 index 000000000..5826b9eef --- /dev/null +++ b/src/nativewindow/native/ios/IOSmisc.m @@ -0,0 +1,813 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ + +#include +#include +#include +#include +#include + +#include "CAEAGLLayered.h" + +#import "NativeWindowProtocols.h" + +#include "jogamp_nativewindow_ios_IOSUtil.h" + +// #define VERBOSE 1 +// +#ifdef VERBOSE + // #define DBG_PRINT(...) NSLog(@ ## __VA_ARGS__) + #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT(...) +#endif + +// #define VERBOSE2 1 +// +#ifdef VERBOSE2 + #define DBG_PRINT2(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT2(...) +#endif + +// #define DBG_LIFECYCLE 1 + +static const char * const ClazzNameRunnable = "java/lang/Runnable"; +static jmethodID runnableRunID = NULL; + +static const char * const ClazzAnyCstrName = ""; + +static const char * const ClazzNamePoint = "com/jogamp/nativewindow/util/Point"; +static const char * const ClazzNamePointCstrSignature = "(II)V"; +static jclass pointClz = NULL; +static jmethodID pointCstr = NULL; + +static const char * const ClazzNameInsets = "com/jogamp/nativewindow/util/Insets"; +static const char * const ClazzNameInsetsCstrSignature = "(IIII)V"; +static jclass insetsClz = NULL; +static jmethodID insetsCstr = NULL; + +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_ios_IOSUtil_initIDs0(JNIEnv *env, jclass _unused) { + if( NativewindowCommon_init(env) ) { + jclass c; + c = (*env)->FindClass(env, ClazzNamePoint); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't find %s", ClazzNamePoint); + } + pointClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==pointClz) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't use %s", ClazzNamePoint); + } + pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); + if(NULL==pointCstr) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't fetch %s.%s %s", + ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); + } + + c = (*env)->FindClass(env, ClazzNameInsets); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't find %s", ClazzNameInsets); + } + insetsClz = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + if(NULL==insetsClz) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't use %s", ClazzNameInsets); + } + insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature); + if(NULL==insetsCstr) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't fetch %s.%s %s", + ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature); + } + + c = (*env)->FindClass(env, ClazzNameRunnable); + if(NULL==c) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't find %s", ClazzNameRunnable); + } + runnableRunID = (*env)->GetMethodID(env, c, "run", "()V"); + if(NULL==runnableRunID) { + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't fetch %s.run()V", ClazzNameRunnable); + } + } + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_ios_IOSUtil_isCAEAGLLayer0(JNIEnv *env, jclass _unused, jlong object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + jboolean u = [nsObj isKindOfClass:[CAEAGLLayer class]]; + DBG_PRINT( "isEAGLCALayer(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u); + return u; +} + +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_ios_IOSUtil_isCALayer0(JNIEnv *env, jclass _unused, jlong object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + jboolean u = [nsObj isKindOfClass:[CALayer class]]; + DBG_PRINT( "isCALayer(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u); + return u; +} + +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_ios_IOSUtil_isUIView0(JNIEnv *env, jclass _unused, jlong object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + jboolean u = [nsObj isKindOfClass:[UIView class]]; + DBG_PRINT( "isUIView(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u); + return u; +} + +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_ios_IOSUtil_isUIWindow0(JNIEnv *env, jclass _unused, jlong object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + jboolean u = [nsObj isKindOfClass:[UIWindow class]]; + DBG_PRINT( "isUIWindow(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u); + return u; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: getLocationOnScreen0 + * Signature: (JII)Lcom/jogamp/nativewindow/util/Point; + */ +JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetLocationOnScreen0 + (JNIEnv *env, jclass unused, jlong winOrView, jint src_x, jint src_y) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + /** + * return location in 0/0 top-left space, + * OSX NSView is 0/0 bottom-left space naturally + * iOS UIView is 0/0 top-left space naturally + */ + NSObject *nsObj = (NSObject*) (intptr_t) winOrView; + UIWindow* win = NULL; + + if( [nsObj isKindOfClass:[UIWindow class]] ) { + win = (UIWindow*) nsObj; + } else if( nsObj != NULL && [nsObj isKindOfClass:[UIView class]] ) { + UIView* view = (UIView*) nsObj; + win = [view window]; + if( NULL == win ) { + NativewindowCommon_throwNewRuntimeException(env, "view has null window, view %p\n", nsObj); + } + } else { + NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj); + } + CGPoint p = CGPointMake(src_x, src_y); + UIScreen* screen = [win screen]; + CGPoint pS = [win convertPoint: p toCoordinateSpace: screen.fixedCoordinateSpace]; + +#ifdef VERBOSE_ON + CGRect winFrame = [self frame]; + DBG_PRINT( "GetLocationOnScreen0(window: %p):: point-in[%d/%d], winFrame[%d/%d %dx%d] -> %d/%d\n", + win, + (int)p.x, (int)p.y, + (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height, + (int)pS.x, (int)pS.y); +#endif + + jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)pS.x, (jint)pS.y); + + [pool release]; + + return res; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: getInsets0 + * Signature: (J)Lcom/jogamp/nativewindow/util/Insets; + */ +JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetInsets0 + (JNIEnv *env, jclass unused, jlong winOrView) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSObject *nsObj = (NSObject*) (intptr_t) winOrView; + UIWindow* win = NULL; + jint il,ir,it,ib; + + if( [nsObj isKindOfClass:[UIWindow class]] ) { + win = (UIWindow*) nsObj; + } else if( nsObj != NULL && [nsObj isKindOfClass:[UIView class]] ) { + UIView* view = (UIView*) nsObj; + win = [view window]; + if( NULL == win ) { + NativewindowCommon_throwNewRuntimeException(env, "view has null window, view %p\n", nsObj); + } + } else { + NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj); + } + + UIEdgeInsets uiInsets = [win safeAreaInsets]; + il = uiInsets.left; + ir = uiInsets.right; + it = uiInsets.top; + ib = uiInsets.bottom; + /** + CGRect frameRect = [win frame]; + CGRect contentRect = [win contentRectForFrameRect: frameRect]; + + // note: this is a simplistic implementation which doesn't take + // into account DPI and scaling factor + CGFloat l = contentRect.origin.x - frameRect.origin.x; + il = (jint)l; // l + ir = (jint)(frameRect.size.width - (contentRect.size.width + l)); // r + it = (jint)(frameRect.size.height - contentRect.size.height); // t + ib = (jint)(contentRect.origin.y - frameRect.origin.y); // b + */ + + jobject res = (*env)->NewObject(env, insetsClz, insetsCstr, il, ir, it, ib); + + [pool release]; + + return res; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetPixelScale1 + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetPixelScale1 + (JNIEnv *env, jclass unused, jint displayID) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + CGFloat pixelScale = 1.0; // default + // UIScreen *screen = IOSUtil_getUIScreenByCGDirectDisplayID((CGDirectDisplayID)displayID); + UIScreen *screen = [UIScreen mainScreen]; + if( NULL != screen ) { +NS_DURING + // Available >= 10.7 + pixelScale = [screen scale]; // HiDPI scaling +NS_HANDLER +NS_ENDHANDLER + } + [pool release]; + + return (jdouble)pixelScale; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetPixelScale1 + * Signature: (J)D + */ +JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetPixelScale2 + (JNIEnv *env, jclass unused, jlong winOrView) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSObject *nsObj = (NSObject*) (intptr_t) winOrView; + UIScreen *screen = NULL; + + if( [nsObj isKindOfClass:[UIWindow class]] ) { + UIWindow* win = (UIWindow*) nsObj; + screen = [win screen]; + } else if( nsObj != NULL && [nsObj isKindOfClass:[UIView class]] ) { + UIView* view = (UIView*) nsObj; + UIWindow* win = [view window]; + if( NULL == win ) { + NativewindowCommon_throwNewRuntimeException(env, "view has null window, view %p\n", nsObj); + } + screen = [win screen]; + } else { + NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj); + } + + CGFloat pixelScale = 1.0; // default +NS_DURING + // Available >= 10.7 + pixelScale = [screen scale]; // HiDPI scaling +NS_HANDLER +NS_ENDHANDLER + + [pool release]; + + return (jdouble)pixelScale; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: CreateUIWindow0 + * Signature: (IIIIZ)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_CreateUIWindow0 + (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [CATransaction begin]; + CGRect boundsWin = CGRectMake(x, y, width, height); + CGRect boundsView = CGRectMake(0, 0, width, height); + + // Allocate the window + UIWindow *myWindow = [[[[UIWindow alloc] initWithFrame:boundsWin] autorelease] retain]; + myWindow.rootViewController = [[[UIViewController alloc] initWithNibName:nil bundle:nil] autorelease]; + [myWindow setBackgroundColor: [UIColor redColor]]; + + // n/a iOS [myWindow setPreservesContentDuringLiveResize: YES]; + + // FIXME invisible .. (we keep it visible for testing) + // FIXME [myWindow setOpaque: NO]; + // FIXME [myWindow setBackgroundColor: [UIColor clearColor]]; + [myWindow makeKeyAndVisible]; + + CAEAGLUIView *uiView = [[CAEAGLUIView alloc] initWithFrame:boundsView]; + CAEAGLLayer* l = (CAEAGLLayer*)[uiView layer]; + [l setOpaque: YES]; + + [myWindow addSubview: uiView]; + + [CATransaction commit]; + [pool release]; + return (jlong) ((intptr_t) myWindow); +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: DestroyUIWindow0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_DestroyUIWindow0 + (JNIEnv *env, jclass unused, jlong nsWindow) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [CATransaction begin]; + +NS_DURING + UIWindow* mWin = (UIWindow*) ((intptr_t) nsWindow); + [mWin resignKeyWindow]; + [mWin setHidden: YES]; + NSArray* subviews = [mWin subviews]; + if(NULL != subviews) { + for(int i=0; i<[subviews count]; i++) { + UIView* sub = [subviews objectAtIndex: i]; + [sub setHidden: YES]; + [sub release]; + } + } + [mWin release]; +NS_HANDLER + // On killing or terminating the process [UIWindow _close], rarely + // throws an NSRangeException while ordering out menu items +NS_ENDHANDLER + + [CATransaction commit]; + [pool release]; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetCALayer0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetCALayer0 + (JNIEnv *env, jclass unused, jlong view) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + UIView* uiView = (UIWindow*) ((intptr_t) view); + + jlong res = (jlong) ((intptr_t) (CALayer *) [uiView layer]); + + DBG_PRINT( "GetCALayer(view: %p): %p\n", uiView, (void*) (intptr_t) res); + + [pool release]; + return res; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetCAEAGLLayer0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetCAEAGLLayer0 + (JNIEnv *env, jclass unused, jlong view) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + UIView* uiView = (UIWindow*) ((intptr_t) view); + + CALayer* l = [uiView layer]; + jboolean isRes = [l isKindOfClass:[CAEAGLLayer class]]; + jlong res = isRes ? (jlong) ((intptr_t) l) : 0; + + DBG_PRINT( "GetCAEAGLLayer(view: %p): CALayer %p, CAEAGLLayer %p (%d)\n", uiView, l, (void*) (intptr_t) res, isRes); + + [pool release]; + return res; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetUIView0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetUIView0 + (JNIEnv *env, jclass unused, jlong window, jboolean onlyCAEAGLUIView) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + UIWindow* win = (UIWindow*) ((intptr_t) window); + jlong res; + + if( onlyCAEAGLUIView ) { + CAEAGLUIView* v0 = [CAEAGLUIView findCAEAGLUIView: win + startIdx: 0]; + res = (jlong) ((intptr_t) v0); + } else { + UIView* v0 = [CAEAGLUIView getUIView: win startIdx: 0]; + res = (jlong) ((intptr_t) v0); + } + + DBG_PRINT( "GetUIView(window: %p): %p\n", win, (void*) (intptr_t) res); + + [pool release]; + return res; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetUIWindow0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetUIWindow0 + (JNIEnv *env, jclass unused, jlong view) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + UIView* v = (UIView*) ((intptr_t) view); + + jlong res = (jlong) ((intptr_t) [v window]); + + DBG_PRINT( "GetUIWindow(view: %p): %p\n", v, (void*) (intptr_t) res); + + [pool release]; + return res; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: SetUIViewPixelScale0 + * Signature: (JF)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_SetUIViewPixelScale0 + (JNIEnv *env, jclass unused, jlong view, jfloat contentScale) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + UIView* v = (UIView*) ((intptr_t) view); + +NS_DURING + if( NULL != v ) { + [v setContentScaleFactor: (CGFloat)contentScale]; + } +NS_HANDLER +NS_ENDHANDLER + + [pool release]; +} +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetUIViewPixelScale0 + * Signature: (J)F + */ +JNIEXPORT jfloat JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetUIViewPixelScale0 + (JNIEnv *env, jclass unused, jlong view) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + UIView* v = (UIView*) ((intptr_t) view); + jfloat r = 0.0f; + +NS_DURING + if( NULL != v ) { + r = [v contentScaleFactor]; + } +NS_HANDLER +NS_ENDHANDLER + + [pool release]; + return r; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: SetCALayerPixelScale0 + * Signature: (JJF)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_SetCALayerPixelScale0 + (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jfloat contentsScale) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer); + CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer); + + [CATransaction begin]; + [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; + +NS_DURING + if( NULL != rootLayer ) { + [rootLayer setContentsScale: (CGFloat)contentsScale]; + } + if( NULL != subLayer ) { + [subLayer setContentsScale: (CGFloat)contentsScale]; + } +NS_HANDLER +NS_ENDHANDLER + + [CATransaction commit]; + + [pool release]; +} +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: GetCALayerPixelScale0 + * Signature: (J)F + */ +JNIEXPORT jfloat JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetCALayerPixelScale0 + (JNIEnv *env, jclass unused, jlong caLayer) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + CALayer* v = (CALayer*) ((intptr_t) caLayer); + jfloat r = 0.0f; + +NS_DURING + if( NULL != v ) { + r = [v contentsScale]; + } +NS_HANDLER +NS_ENDHANDLER + + [pool release]; + return r; +} + +@interface MainRunnable : NSObject + +{ + jobject runnableObj; +} + +- (id) initWithRunnable: (jobject)runnable; +- (void) jRun; + +#ifdef DBG_LIFECYCLE +- (id)retain; +- (oneway void)release; +- (void)dealloc; +#endif + + +@end + +@implementation MainRunnable + +- (id) initWithRunnable: (jobject)runnable +{ + runnableObj = runnable; + return [super init]; +} + +- (void) jRun +{ + int shallBeDetached = 0; + JNIEnv* env = NativewindowCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached); + DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env)); + if(NULL!=env) { + DBG_PRINT2("MainRunnable.1.0\n"); + (*env)->CallVoidMethod(env, runnableObj, runnableRunID); + DBG_PRINT2("MainRunnable.1.1\n"); + (*env)->DeleteGlobalRef(env, runnableObj); + + DBG_PRINT2("MainRunnable.1.3\n"); + // detaching thread not required - daemon + // NativewindowCommon_ReleaseJNIEnv(shallBeDetached); + } + DBG_PRINT2("MainRunnable.X\n"); +} + +#ifdef DBG_LIFECYCLE + +- (id)retain +{ + DBG_PRINT2("MainRunnable::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]); + id o = [super retain]; + DBG_PRINT2("MainRunnable::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]); + return o; +} + +- (oneway void)release +{ + DBG_PRINT2("MainRunnable::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]); + [super release]; + // DBG_PRINT2("MainRunnable::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]); +} + +- (void)dealloc +{ + DBG_PRINT2("MainRunnable::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]); + [super dealloc]; + // DBG_PRINT2("MainRunnable.dealloc.X: %p\n", self); +} + +#endif + +@end + +// #define UIApp [UIApplication sharedApplication] +// #define NSApp [NSApplication sharedApplication] + +static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayInMS) +{ + BOOL isMainThread = [NSThread isMainThread]; + BOOL forkOnMain = onMain && ( NO == isMainThread || 0 < delayInMS ); + // UIApplication * UIApp = [UIApplication sharedApplication]; + + DBG_PRINT2( "RunOnThread0: forkOnMain %d [onMain %d, delay %dms, isMainThread %d], UIApp %d, UIApp-isRunning %d\n", + (int)forkOnMain, (int)onMain, (int)delayInMS, (int)isMainThread, (int)(NULL!=UIApp), (int)([UIApp applicationState])); + + if ( forkOnMain ) { + jobject runnableObj = (*env)->NewGlobalRef(env, runnable); + + DBG_PRINT2( "RunOnThread.1.0\n"); + MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj]; + + if( onMain ) { + [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO]; + } else { + NSTimeInterval delay = (double)delayInMS/1000.0; + [mr performSelector:@selector(jRun) withObject:nil afterDelay:delay]; + } + DBG_PRINT2( "RunOnThread.1.1\n"); + + [mr release]; + DBG_PRINT2( "RunOnThread.1.2\n"); + + } else { + DBG_PRINT2( "RunOnThread.2\n"); + (*env)->CallVoidMethod(env, runnable, runnableRunID); + } + DBG_PRINT2( "RunOnThread.X\n"); +} + +static void IOSUtil_KickUIApp() { + // UIApplication * UIApp = [UIApplication sharedApplication]; + /*** iOS-FIXME: UIEvent creation and post n/a !!! + UIEvent* event = [UIEvent otherEventWithType: UIApplicationDefined + location: NSMakePoint(0,0) + modifierFlags: 0 + timestamp: 0.0 + windowNumber: 0 + context: nil + subtype: 0 + data1: 0 + data2: 0]; + [UIApp postEvent: event atStart: true]; + */ +} + +/** + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: RunOnMainThread0 + * Signature: (ZLjava/lang/Runnable;)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_RunOnMainThread0 + (JNIEnv *env, jclass unused, jboolean kickUIApp, jobject runnable) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + RunOnThread (env, runnable, YES, 0); + if( kickUIApp ) { + IOSUtil_KickUIApp(); + } + [pool release]; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: RunLater0 + * Signature: (ZZLjava/lang/Runnable;I)V + */ +JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_RunLater0 + (JNIEnv *env, jclass unused, jboolean onMain, jboolean kickUIApp, jobject runnable, jint delay) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + RunOnThread (env, runnable, onMain ? YES : NO, delay); + if( kickUIApp ) { + IOSUtil_KickUIApp(); + } + [pool release]; +} + +/* + * Class: Java_jogamp_nativewindow_ios_IOSUtil + * Method: IsMainThread0 + * Signature: (V)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_ios_IOSUtil_IsMainThread0 + (JNIEnv *env, jclass unused) +{ + return ( [NSThread isMainThread] == YES ) ? JNI_TRUE : JNI_FALSE ; +} + +#define EAGL_TEST 1 + +#ifdef EAGL_TEST +#include +#include + +@interface GLView : UIView +{ + CAEAGLLayer *glLayer; + EAGLContext *glContext; + GLuint renderbuffer; +} +@end +@implementation GLView ++ (Class)layerClass +{ + return [CAEAGLLayer class]; +} + +- (id)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + [self initGL]; + [self render]; + } + + return self; +} + +- (void)render +{ + glClearColor(150.0/255.0, 200.0/255.0, 255.0/255.0, 1.0); + + glClear(GL_COLOR_BUFFER_BIT); + + [glContext presentRenderbuffer:GL_RENDERBUFFER]; +} + +- (void)initGL +{ + glLayer = (CAEAGLLayer *)self.layer; + glLayer.opaque = YES; + + glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + if (!glContext) { + NSLog(@"Unable to create EAGLContext"); + exit(1); + } + if (![EAGLContext setCurrentContext:glContext]) { + NSLog(@"Unable to set current EAGLContext"); + exit(1); + } + glGenRenderbuffers(1, &renderbuffer); + glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); + [glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:glLayer]; + + GLuint framebuffer; + glGenFramebuffers(1, &framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); +} +@end +#endif /* EAGL_TEST */ + +JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_CreateGLViewDemoA0 + (JNIEnv *env, jclass unused) +{ +#ifdef EAGL_TEST + CGRect boundsW2 = CGRectMake(500, 10, 320, 320); + CGRect boundsV2 = CGRectMake(0, 0, 320, 320); + UIWindow* window2 = [[[[UIWindow alloc] initWithFrame:boundsW2] autorelease] retain]; + window2.rootViewController = [[[UIViewController alloc] initWithNibName:nil bundle:nil] autorelease]; + [window2 setBackgroundColor: [UIColor redColor]]; + [window2 makeKeyAndVisible]; + + GLView *glView = [[GLView alloc] initWithFrame:boundsV2]; + [window2 addSubview:glView]; +#endif /* EAGL_TEST */ +} + diff --git a/src/nativewindow/native/ios/NativeWindowProtocols.h b/src/nativewindow/native/ios/NativeWindowProtocols.h new file mode 100644 index 000000000..b27afc70d --- /dev/null +++ b/src/nativewindow/native/ios/NativeWindowProtocols.h @@ -0,0 +1,59 @@ +/** + * Copyright 2019 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 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 JogAmp Community ``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 JogAmp Community 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 JogAmp Community. + */ + +#ifndef NATIVEWINDOWPROTOCOLS_H +#define NATIVEWINDOWPROTOCOLS_H 1 + +/** + * CALayer size needs to be set using the AWT component size. + * See detailed description in JAWTUtil.java and sync w/ changed. + */ +#define NW_DEDICATEDFRAME_QUIRK_SIZE ( 1 << 0 ) + +/** + * CALayer position needs to be set to zero. + * See detailed description in JAWTUtil.java and sync w/ changed. + */ +#define NW_DEDICATEDFRAME_QUIRK_POSITION ( 1 << 1 ) + +/** + * CALayer position needs to be derived from AWT position. + * in relation to super CALayer. + * See detailed description in JAWTUtil.java and sync w/ changed. + */ +#define NW_DEDICATEDFRAME_QUIRK_LAYOUT ( 1 << 2 ) + +// n/a iOS #import +#import + +@protocol NWDedicatedFrame +- (void)setDedicatedFrame:(CGRect)dFrame quirks:(int)quirks; +@end + +#endif /* NATIVEWINDOWPROTOCOLS_H_ */ + diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index c04ba786e..fb15c43b9 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -81,41 +81,41 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) { jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNamePoint); + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't find %s", ClazzNamePoint); } pointClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==pointClz) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNamePoint); + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't use %s", ClazzNamePoint); } pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature); if(NULL==pointCstr) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s", + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't fetch %s.%s %s", ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature); } c = (*env)->FindClass(env, ClazzNameInsets); if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameInsets); + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't find %s", ClazzNameInsets); } insetsClz = (jclass)(*env)->NewGlobalRef(env, c); (*env)->DeleteLocalRef(env, c); if(NULL==insetsClz) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNameInsets); + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't use %s", ClazzNameInsets); } insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature); if(NULL==insetsCstr) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s", + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't fetch %s.%s %s", ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature); } c = (*env)->FindClass(env, ClazzNameRunnable); if(NULL==c) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameRunnable); + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't find %s", ClazzNameRunnable); } runnableRunID = (*env)->GetMethodID(env, c, "run", "()V"); if(NULL==runnableRunID) { - NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.run()V", ClazzNameRunnable); + NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't fetch %s.run()V", ClazzNameRunnable); } } return JNI_TRUE; -- cgit v1.2.3