aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2019-06-23 08:03:04 +0200
committerSven Gothel <[email protected]>2019-06-23 08:03:04 +0200
commitbba73bc096250a3c7fc036d84b1ea054d1b70b06 (patch)
treeed02575eac2a46bd49627444dcce972946ae8d2e /src/newt
parent154e91978498d8b6db9ce34a1f06b298bcf4c361 (diff)
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.
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java91
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java426
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java225
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java812
-rw-r--r--src/newt/native/IOSNewtUIWindow.h152
-rw-r--r--src/newt/native/IOSNewtUIWindow.m783
-rw-r--r--src/newt/native/IOSUIWindow.m1161
-rw-r--r--src/newt/native/JVM_JNI8.c42
8 files changed, 3692 insertions, 0 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java
new file mode 100644
index 000000000..d2bb6de02
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java
@@ -0,0 +1,91 @@
+/**
+ * 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.newt.driver.ios;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.ios.IOSGraphicsDevice;
+import com.jogamp.nativewindow.util.PixelFormat;
+
+import jogamp.newt.DisplayImpl;
+import jogamp.newt.NEWTJNILibLoader;
+
+public class DisplayDriver extends DisplayImpl {
+
+ static {
+ NEWTJNILibLoader.loadNEWT();
+
+ if(!initUIApplication0()) {
+ throw new NativeWindowException("Failed to initialize native Application hook");
+ }
+ if(!WindowDriver.initIDs0()) {
+ throw new NativeWindowException("Failed to initialize jmethodIDs");
+ }
+ if(DEBUG) {
+ System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName());
+ }
+ }
+
+ public static void initSingleton() {
+ // just exist to ensure static init has been run
+ }
+
+ public DisplayDriver() {
+ }
+
+ @Override
+ public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.RGBA8888; }
+
+ @Override
+ protected void dispatchMessagesNative() {
+ // nop
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aDevice = new IOSGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ }
+
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
+ aDevice.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ * </p>
+ */
+ @Override
+ public final boolean getNativePointerIconForceDirectNIO() { return true; }
+
+ private static native boolean initUIApplication0();
+}
+
diff --git a/src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java b/src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java
new file mode 100644
index 000000000..e65602959
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java
@@ -0,0 +1,426 @@
+/**
+ * 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.newt.driver.ios;
+
+import com.jogamp.newt.event.KeyEvent;
+
+public class MacKeyUtil {
+
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ private static final short kVK_ANSI_A = 0x00;
+ private static final short kVK_ANSI_S = 0x01;
+ private static final short kVK_ANSI_D = 0x02;
+ private static final short kVK_ANSI_F = 0x03;
+ private static final short kVK_ANSI_H = 0x04;
+ private static final short kVK_ANSI_G = 0x05;
+ private static final short kVK_ANSI_Z = 0x06;
+ private static final short kVK_ANSI_X = 0x07;
+ private static final short kVK_ANSI_C = 0x08;
+ private static final short kVK_ANSI_V = 0x09;
+ private static final short kVK_ANSI_B = 0x0B;
+ private static final short kVK_ANSI_Q = 0x0C;
+ private static final short kVK_ANSI_W = 0x0D;
+ private static final short kVK_ANSI_E = 0x0E;
+ private static final short kVK_ANSI_R = 0x0F;
+ private static final short kVK_ANSI_Y = 0x10;
+ private static final short kVK_ANSI_T = 0x11;
+ private static final short kVK_ANSI_1 = 0x12;
+ private static final short kVK_ANSI_2 = 0x13;
+ private static final short kVK_ANSI_3 = 0x14;
+ private static final short kVK_ANSI_4 = 0x15;
+ private static final short kVK_ANSI_6 = 0x16;
+ private static final short kVK_ANSI_5 = 0x17;
+ private static final short kVK_ANSI_Equal = 0x18;
+ private static final short kVK_ANSI_9 = 0x19;
+ private static final short kVK_ANSI_7 = 0x1A;
+ private static final short kVK_ANSI_Minus = 0x1B;
+ private static final short kVK_ANSI_8 = 0x1C;
+ private static final short kVK_ANSI_0 = 0x1D;
+ private static final short kVK_ANSI_RightBracket = 0x1E;
+ private static final short kVK_ANSI_O = 0x1F;
+ private static final short kVK_ANSI_U = 0x20;
+ private static final short kVK_ANSI_LeftBracket = 0x21;
+ private static final short kVK_ANSI_I = 0x22;
+ private static final short kVK_ANSI_P = 0x23;
+ private static final short kVK_ANSI_L = 0x25;
+ private static final short kVK_ANSI_J = 0x26;
+ private static final short kVK_ANSI_Quote = 0x27;
+ private static final short kVK_ANSI_K = 0x28;
+ private static final short kVK_ANSI_Semicolon = 0x29;
+ private static final short kVK_ANSI_Backslash = 0x2A;
+ private static final short kVK_ANSI_Comma = 0x2B;
+ private static final short kVK_ANSI_Slash = 0x2C;
+ private static final short kVK_ANSI_N = 0x2D;
+ private static final short kVK_ANSI_M = 0x2E;
+ private static final short kVK_ANSI_Period = 0x2F;
+ private static final short kVK_ANSI_Grave = 0x32;
+ private static final short kVK_ANSI_KeypadDecimal = 0x41;
+ private static final short kVK_ANSI_KeypadMultiply = 0x43;
+ private static final short kVK_ANSI_KeypadPlus = 0x45;
+ private static final short kVK_ANSI_KeypadClear = 0x47;
+ private static final short kVK_ANSI_KeypadDivide = 0x4B;
+ private static final short kVK_ANSI_KeypadEnter = 0x4C;
+ private static final short kVK_ANSI_KeypadMinus = 0x4E;
+ private static final short kVK_ANSI_KeypadEquals = 0x51;
+ private static final short kVK_ANSI_Keypad0 = 0x52;
+ private static final short kVK_ANSI_Keypad1 = 0x53;
+ private static final short kVK_ANSI_Keypad2 = 0x54;
+ private static final short kVK_ANSI_Keypad3 = 0x55;
+ private static final short kVK_ANSI_Keypad4 = 0x56;
+ private static final short kVK_ANSI_Keypad5 = 0x57;
+ private static final short kVK_ANSI_Keypad6 = 0x58;
+ private static final short kVK_ANSI_Keypad7 = 0x59;
+ private static final short kVK_ANSI_Keypad8 = 0x5B;
+ private static final short kVK_ANSI_Keypad9 = 0x5C;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
+ private static final short kVK_Return = 0x24;
+ private static final short kVK_Tab = 0x30;
+ private static final short kVK_Space = 0x31;
+ private static final short kVK_Delete = 0x33;
+ private static final short kVK_Escape = 0x35;
+ private static final short kVK_Command = 0x37;
+ private static final short kVK_Shift = 0x38;
+ private static final short kVK_CapsLock = 0x39;
+ private static final short kVK_Option = 0x3A;
+ private static final short kVK_Control = 0x3B;
+ private static final short kVK_RightShift = 0x3C;
+ private static final short kVK_RightOption = 0x3D;
+ private static final short kVK_RightControl = 0x3E;
+ // private static final short kVK_Function = 0x3F;
+ private static final short kVK_F17 = 0x40;
+ // private static final short kVK_VolumeUp = 0x48;
+ // private static final short kVK_VolumeDown = 0x49;
+ // private static final short kVK_Mute = 0x4A;
+ private static final short kVK_F18 = 0x4F;
+ private static final short kVK_F19 = 0x50;
+ private static final short kVK_F20 = 0x5A;
+ private static final short kVK_F5 = 0x60;
+ private static final short kVK_F6 = 0x61;
+ private static final short kVK_F7 = 0x62;
+ private static final short kVK_F3 = 0x63;
+ private static final short kVK_F8 = 0x64;
+ private static final short kVK_F9 = 0x65;
+ private static final short kVK_F11 = 0x67;
+ private static final short kVK_F13 = 0x69;
+ private static final short kVK_F16 = 0x6A;
+ private static final short kVK_F14 = 0x6B;
+ private static final short kVK_F10 = 0x6D;
+ private static final short kVK_F12 = 0x6F;
+ private static final short kVK_F15 = 0x71;
+ private static final short kVK_Help = 0x72;
+ private static final short kVK_Home = 0x73;
+ private static final short kVK_PageUp = 0x74;
+ private static final short kVK_ForwardDelete = 0x75;
+ private static final short kVK_F4 = 0x76;
+ private static final short kVK_End = 0x77;
+ private static final short kVK_F2 = 0x78;
+ private static final short kVK_PageDown = 0x79;
+ private static final short kVK_F1 = 0x7A;
+ private static final short kVK_LeftArrow = 0x7B;
+ private static final short kVK_RightArrow = 0x7C;
+ private static final short kVK_DownArrow = 0x7D;
+ private static final short kVK_UpArrow = 0x7E;
+
+ //
+ // Key constants handled differently on Mac OS X than other platforms
+ //
+ private static final char NSUpArrowFunctionKey = 0xF700;
+ private static final char NSDownArrowFunctionKey = 0xF701;
+ private static final char NSLeftArrowFunctionKey = 0xF702;
+ private static final char NSRightArrowFunctionKey = 0xF703;
+ private static final char NSF1FunctionKey = 0xF704;
+ private static final char NSF2FunctionKey = 0xF705;
+ private static final char NSF3FunctionKey = 0xF706;
+ private static final char NSF4FunctionKey = 0xF707;
+ private static final char NSF5FunctionKey = 0xF708;
+ private static final char NSF6FunctionKey = 0xF709;
+ private static final char NSF7FunctionKey = 0xF70A;
+ private static final char NSF8FunctionKey = 0xF70B;
+ private static final char NSF9FunctionKey = 0xF70C;
+ private static final char NSF10FunctionKey = 0xF70D;
+ private static final char NSF11FunctionKey = 0xF70E;
+ private static final char NSF12FunctionKey = 0xF70F;
+ private static final char NSF13FunctionKey = 0xF710;
+ private static final char NSF14FunctionKey = 0xF711;
+ private static final char NSF15FunctionKey = 0xF712;
+ private static final char NSF16FunctionKey = 0xF713;
+ private static final char NSF17FunctionKey = 0xF714;
+ private static final char NSF18FunctionKey = 0xF715;
+ private static final char NSF19FunctionKey = 0xF716;
+ private static final char NSF20FunctionKey = 0xF717;
+ private static final char NSF21FunctionKey = 0xF718;
+ private static final char NSF22FunctionKey = 0xF719;
+ private static final char NSF23FunctionKey = 0xF71A;
+ private static final char NSF24FunctionKey = 0xF71B;
+ /**
+ private static final char NSF25FunctionKey = 0xF71C;
+ private static final char NSF26FunctionKey = 0xF71D;
+ private static final char NSF27FunctionKey = 0xF71E;
+ private static final char NSF28FunctionKey = 0xF71F;
+ private static final char NSF29FunctionKey = 0xF720;
+ private static final char NSF30FunctionKey = 0xF721;
+ private static final char NSF31FunctionKey = 0xF722;
+ private static final char NSF32FunctionKey = 0xF723;
+ private static final char NSF33FunctionKey = 0xF724;
+ private static final char NSF34FunctionKey = 0xF725;
+ private static final char NSF35FunctionKey = 0xF726;
+ */
+ private static final char NSInsertFunctionKey = 0xF727;
+ private static final char NSDeleteFunctionKey = 0xF728;
+ private static final char NSHomeFunctionKey = 0xF729;
+ private static final char NSBeginFunctionKey = 0xF72A;
+ private static final char NSEndFunctionKey = 0xF72B;
+ private static final char NSPageUpFunctionKey = 0xF72C;
+ private static final char NSPageDownFunctionKey = 0xF72D;
+ private static final char NSPrintScreenFunctionKey = 0xF72E;
+ private static final char NSScrollLockFunctionKey = 0xF72F;
+ private static final char NSPauseFunctionKey = 0xF730;
+ // private static final char NSSysReqFunctionKey = 0xF731;
+ // private static final char NSBreakFunctionKey = 0xF732;
+ // private static final char NSResetFunctionKey = 0xF733;
+ private static final char NSStopFunctionKey = 0xF734;
+ /**
+ private static final char NSMenuFunctionKey = 0xF735;
+ private static final char NSUserFunctionKey = 0xF736;
+ private static final char NSSystemFunctionKey = 0xF737;
+ private static final char NSPrintFunctionKey = 0xF738;
+ private static final char NSClearLineFunctionKey = 0xF739;
+ private static final char NSClearDisplayFunctionKey = 0xF73A;
+ private static final char NSInsertLineFunctionKey = 0xF73B;
+ private static final char NSDeleteLineFunctionKey = 0xF73C;
+ private static final char NSInsertCharFunctionKey = 0xF73D;
+ private static final char NSDeleteCharFunctionKey = 0xF73E;
+ private static final char NSPrevFunctionKey = 0xF73F;
+ private static final char NSNextFunctionKey = 0xF740;
+ private static final char NSSelectFunctionKey = 0xF741;
+ private static final char NSExecuteFunctionKey = 0xF742;
+ private static final char NSUndoFunctionKey = 0xF743;
+ private static final char NSRedoFunctionKey = 0xF744;
+ private static final char NSFindFunctionKey = 0xF745;
+ private static final char NSHelpFunctionKey = 0xF746;
+ private static final char NSModeSwitchFunctionKey = 0xF747;
+ */
+
+ static short validateKeyCode(final short keyCode, final char keyChar) {
+ // OS X Virtual Keycodes
+ switch(keyCode) {
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ case kVK_ANSI_A: return KeyEvent.VK_A;
+ case kVK_ANSI_S: return KeyEvent.VK_S;
+ case kVK_ANSI_D: return KeyEvent.VK_D;
+ case kVK_ANSI_F: return KeyEvent.VK_F;
+ case kVK_ANSI_H: return KeyEvent.VK_H;
+ case kVK_ANSI_G: return KeyEvent.VK_G;
+ case kVK_ANSI_Z: return KeyEvent.VK_Z;
+ case kVK_ANSI_X: return KeyEvent.VK_X;
+ case kVK_ANSI_C: return KeyEvent.VK_C;
+ case kVK_ANSI_V: return KeyEvent.VK_V;
+ case kVK_ANSI_B: return KeyEvent.VK_B;
+ case kVK_ANSI_Q: return KeyEvent.VK_Q;
+ case kVK_ANSI_W: return KeyEvent.VK_W;
+ case kVK_ANSI_E: return KeyEvent.VK_E;
+ case kVK_ANSI_R: return KeyEvent.VK_R;
+ case kVK_ANSI_Y: return KeyEvent.VK_Y;
+ case kVK_ANSI_T: return KeyEvent.VK_T;
+ case kVK_ANSI_1: return KeyEvent.VK_1;
+ case kVK_ANSI_2: return KeyEvent.VK_2;
+ case kVK_ANSI_3: return KeyEvent.VK_3;
+ case kVK_ANSI_4: return KeyEvent.VK_4;
+ case kVK_ANSI_6: return KeyEvent.VK_6;
+ case kVK_ANSI_5: return KeyEvent.VK_5;
+ case kVK_ANSI_Equal: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_9: return KeyEvent.VK_9;
+ case kVK_ANSI_7: return KeyEvent.VK_7;
+ case kVK_ANSI_Minus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_8: return KeyEvent.VK_8;
+ case kVK_ANSI_0: return KeyEvent.VK_0;
+ case kVK_ANSI_RightBracket: return KeyEvent.VK_CLOSE_BRACKET;
+ case kVK_ANSI_O: return KeyEvent.VK_O;
+ case kVK_ANSI_U: return KeyEvent.VK_U;
+ case kVK_ANSI_LeftBracket: return KeyEvent.VK_OPEN_BRACKET;
+ case kVK_ANSI_I: return KeyEvent.VK_I;
+ case kVK_ANSI_P: return KeyEvent.VK_P;
+ case kVK_ANSI_L: return KeyEvent.VK_L;
+ case kVK_ANSI_J: return KeyEvent.VK_J;
+ case kVK_ANSI_Quote: return KeyEvent.VK_QUOTE;
+ case kVK_ANSI_K: return KeyEvent.VK_K;
+ case kVK_ANSI_Semicolon: return KeyEvent.VK_SEMICOLON;
+ case kVK_ANSI_Backslash: return KeyEvent.VK_BACK_SLASH;
+ case kVK_ANSI_Comma: return KeyEvent.VK_COMMA;
+ case kVK_ANSI_Slash: return KeyEvent.VK_SLASH;
+ case kVK_ANSI_N: return KeyEvent.VK_N;
+ case kVK_ANSI_M: return KeyEvent.VK_M;
+ case kVK_ANSI_Period: return KeyEvent.VK_PERIOD;
+ case kVK_ANSI_Grave: return KeyEvent.VK_BACK_QUOTE; // KeyEvent.VK_DEAD_GRAVE
+ case kVK_ANSI_KeypadDecimal: return KeyEvent.VK_DECIMAL;
+ case kVK_ANSI_KeypadMultiply: return KeyEvent.VK_MULTIPLY;
+ case kVK_ANSI_KeypadPlus: return KeyEvent.VK_PLUS;
+ case kVK_ANSI_KeypadClear: return KeyEvent.VK_CLEAR;
+ case kVK_ANSI_KeypadDivide: return KeyEvent.VK_DIVIDE;
+ case kVK_ANSI_KeypadEnter: return KeyEvent.VK_ENTER;
+ case kVK_ANSI_KeypadMinus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_KeypadEquals: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_Keypad0: return KeyEvent.VK_0;
+ case kVK_ANSI_Keypad1: return KeyEvent.VK_1;
+ case kVK_ANSI_Keypad2: return KeyEvent.VK_2;
+ case kVK_ANSI_Keypad3: return KeyEvent.VK_3;
+ case kVK_ANSI_Keypad4: return KeyEvent.VK_4;
+ case kVK_ANSI_Keypad5: return KeyEvent.VK_5;
+ case kVK_ANSI_Keypad6: return KeyEvent.VK_6;
+ case kVK_ANSI_Keypad7: return KeyEvent.VK_7;
+ case kVK_ANSI_Keypad8: return KeyEvent.VK_8;
+ case kVK_ANSI_Keypad9: return KeyEvent.VK_9;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
+ case kVK_Return: return KeyEvent.VK_ENTER;
+ case kVK_Tab: return KeyEvent.VK_TAB;
+ case kVK_Space: return KeyEvent.VK_SPACE;
+ case kVK_Delete: return KeyEvent.VK_BACK_SPACE;
+ case kVK_Escape: return KeyEvent.VK_ESCAPE;
+ case kVK_Command: return KeyEvent.VK_WINDOWS;
+ case kVK_Shift: return KeyEvent.VK_SHIFT;
+ case kVK_CapsLock: return KeyEvent.VK_CAPS_LOCK;
+ case kVK_Option: return KeyEvent.VK_ALT;
+ case kVK_Control: return KeyEvent.VK_CONTROL;
+ case kVK_RightShift: return KeyEvent.VK_SHIFT;
+ case kVK_RightOption: return KeyEvent.VK_ALT_GRAPH;
+ case kVK_RightControl: return KeyEvent.VK_CONTROL;
+ // case kVK_Function: return KeyEvent.VK_F;
+ case kVK_F17: return KeyEvent.VK_F17;
+ // case kVK_VolumeUp:
+ // case kVK_VolumeDown:
+ // case kVK_Mute:
+ case kVK_F18: return KeyEvent.VK_F18;
+ case kVK_F19: return KeyEvent.VK_F19;
+ case kVK_F20: return KeyEvent.VK_F20;
+ case kVK_F5: return KeyEvent.VK_F5;
+ case kVK_F6: return KeyEvent.VK_F6;
+ case kVK_F7: return KeyEvent.VK_F7;
+ case kVK_F3: return KeyEvent.VK_F3;
+ case kVK_F8: return KeyEvent.VK_F8;
+ case kVK_F9: return KeyEvent.VK_F9;
+ case kVK_F11: return KeyEvent.VK_F11;
+ case kVK_F13: return KeyEvent.VK_F13;
+ case kVK_F16: return KeyEvent.VK_F16;
+ case kVK_F14: return KeyEvent.VK_F14;
+ case kVK_F10: return KeyEvent.VK_F10;
+ case kVK_F12: return KeyEvent.VK_F12;
+ case kVK_F15: return KeyEvent.VK_F15;
+ case kVK_Help: return KeyEvent.VK_HELP;
+ case kVK_Home: return KeyEvent.VK_HOME;
+ case kVK_PageUp: return KeyEvent.VK_PAGE_UP;
+ case kVK_ForwardDelete: return KeyEvent.VK_DELETE;
+ case kVK_F4: return KeyEvent.VK_F4;
+ case kVK_End: return KeyEvent.VK_END;
+ case kVK_F2: return KeyEvent.VK_F2;
+ case kVK_PageDown: return KeyEvent.VK_PAGE_DOWN;
+ case kVK_F1: return KeyEvent.VK_F1;
+ case kVK_LeftArrow: return KeyEvent.VK_LEFT;
+ case kVK_RightArrow: return KeyEvent.VK_RIGHT;
+ case kVK_DownArrow: return KeyEvent.VK_DOWN;
+ case kVK_UpArrow: return KeyEvent.VK_UP;
+ }
+
+ switch (keyChar) {
+ case NSUpArrowFunctionKey: return KeyEvent.VK_UP;
+ case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN;
+ case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT;
+ case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT;
+ case NSF1FunctionKey: return KeyEvent.VK_F1;
+ case NSF2FunctionKey: return KeyEvent.VK_F2;
+ case NSF3FunctionKey: return KeyEvent.VK_F3;
+ case NSF4FunctionKey: return KeyEvent.VK_F4;
+ case NSF5FunctionKey: return KeyEvent.VK_F5;
+ case NSF6FunctionKey: return KeyEvent.VK_F6;
+ case NSF7FunctionKey: return KeyEvent.VK_F7;
+ case NSF8FunctionKey: return KeyEvent.VK_F8;
+ case NSF9FunctionKey: return KeyEvent.VK_F9;
+ case NSF10FunctionKey: return KeyEvent.VK_F10;
+ case NSF11FunctionKey: return KeyEvent.VK_F11;
+ case NSF12FunctionKey: return KeyEvent.VK_F12;
+ case NSF13FunctionKey: return KeyEvent.VK_F13;
+ case NSF14FunctionKey: return KeyEvent.VK_F14;
+ case NSF15FunctionKey: return KeyEvent.VK_F15;
+ case NSF16FunctionKey: return KeyEvent.VK_F16;
+ case NSF17FunctionKey: return KeyEvent.VK_F17;
+ case NSF18FunctionKey: return KeyEvent.VK_F18;
+ case NSF19FunctionKey: return KeyEvent.VK_F19;
+ case NSF20FunctionKey: return KeyEvent.VK_F20;
+ case NSF21FunctionKey: return KeyEvent.VK_F21;
+ case NSF22FunctionKey: return KeyEvent.VK_F22;
+ case NSF23FunctionKey: return KeyEvent.VK_F23;
+ case NSF24FunctionKey: return KeyEvent.VK_F24;
+ case NSInsertFunctionKey: return KeyEvent.VK_INSERT;
+ case NSDeleteFunctionKey: return KeyEvent.VK_DELETE;
+ case NSHomeFunctionKey: return KeyEvent.VK_HOME;
+ case NSBeginFunctionKey: return KeyEvent.VK_BEGIN;
+ case NSEndFunctionKey: return KeyEvent.VK_END;
+ case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP;
+ case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN;
+ case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN;
+ case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK;
+ case NSPauseFunctionKey: return KeyEvent.VK_PAUSE;
+ // Not handled:
+ // NSSysReqFunctionKey
+ // NSBreakFunctionKey
+ // NSResetFunctionKey
+ case NSStopFunctionKey: return KeyEvent.VK_STOP;
+ // Not handled:
+ // NSMenuFunctionKey
+ // NSUserFunctionKey
+ // NSSystemFunctionKey
+ // NSPrintFunctionKey
+ // NSClearLineFunctionKey
+ // NSClearDisplayFunctionKey
+ // NSInsertLineFunctionKey
+ // NSDeleteLineFunctionKey
+ // NSInsertCharFunctionKey
+ // NSDeleteCharFunctionKey
+ // NSPrevFunctionKey
+ // NSNextFunctionKey
+ // NSSelectFunctionKey
+ // NSExecuteFunctionKey
+ // NSUndoFunctionKey
+ // NSRedoFunctionKey
+ // NSFindFunctionKey
+ // NSHelpFunctionKey
+ // NSModeSwitchFunctionKey
+ }
+
+ return (short) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java
new file mode 100644
index 000000000..47280865d
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java
@@ -0,0 +1,225 @@
+/**
+ * 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.newt.driver.ios;
+
+import com.jogamp.nativewindow.DefaultGraphicsScreen;
+import com.jogamp.nativewindow.util.Rectangle;
+
+import jogamp.nativewindow.ios.IOSUtil;
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.opengl.math.FloatUtil;
+
+public class ScreenDriver extends ScreenImpl {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ private MonitorMode getMonitorModeImpl(final MonitorModeProps.Cache cache, final int crt_id, final int mode_idx) {
+ final int[] modeProps = getMonitorMode0(crt_id, mode_idx);
+ final MonitorMode res;
+ if (null == modeProps || 0 >= modeProps.length) {
+ res = null;
+ } else {
+ res = MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
+ }
+ return res;
+ }
+
+ class CrtProps {
+ CrtProps() {
+ crtIDs = getMonitorDeviceIds0();
+ count = crtIDs.length;
+ pixelScaleArray = new float[count];
+ propsOrigArray = new int[count][];
+ propsFixedArray = new int[count][];
+
+ //
+ // Gather whole topology of monitors (NSScreens)
+ //
+ for(int crtIdx=0; crtIdx<count; crtIdx++) {
+ final int crt_id = crtIDs[crtIdx];
+ final float pixelScaleRaw = (float)IOSUtil.GetPixelScaleByDisplayID(crt_id);
+ pixelScaleArray[crtIdx] = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1.0f : pixelScaleRaw;
+ propsOrigArray[crtIdx] = getMonitorProps0(crt_id);
+ if ( null == propsOrigArray[crtIdx] ) {
+ throw new InternalError("Could not gather device props "+crtIdx+"/"+count+" -> "+Display.toHexString(crt_id));
+ }
+ // copy orig -> fixed
+ final int propsLen = propsOrigArray[crtIdx].length;
+ propsFixedArray[crtIdx] = new int[propsLen];
+ System.arraycopy(propsOrigArray[crtIdx], 0, propsFixedArray[crtIdx], 0, propsLen);
+ }
+
+ //
+ // Fix scaled viewport w/ pixelScale of each monitorProps,
+ // i.e. size by its own pixelScale and x/y offset by querying it's neighbors.
+ //
+ for(int crtIdx=0; crtIdx<count; crtIdx++) {
+ final int[] thisMonitorProps = propsFixedArray[crtIdx];
+ final int x = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0];
+ final int y = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1];
+ final float thisPixelScale = pixelScaleArray[crtIdx];
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] *= thisPixelScale; // fix width
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] *= thisPixelScale; // fix height
+ if( 0 != x ) {
+ // find matching viewport width for x-offset to apply it's pixelSize
+ for(int i=0; i<count; i++) {
+ if( i != crtIdx && x == propsOrigArray[i][MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] ) {
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0] *= pixelScaleArray[i];
+ break;
+ }
+ }
+ }
+ if( 0 != y ) {
+ // find matching viewport height for y-offset to apply it's pixelSize
+ for(int i=0; i<count; i++) {
+ if( i != crtIdx && y == propsOrigArray[i][MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] ) {
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1] *= pixelScaleArray[i];
+ break;
+ }
+ }
+ }
+ }
+ }
+ int getIndex(final int crt_id) {
+ for(int i=0; i<count; i++) {
+ if( crt_id == crtIDs[i] ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ final int count;
+ final int[] crtIDs;
+ final float[] pixelScaleArray;
+ final int[][] propsOrigArray;
+ final int[][] propsFixedArray;
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ final CrtProps crtProps = new CrtProps();
+
+ //
+ // Collect all monitorModes for all monitorDevices
+ //
+ for(int crtIdx=0; crtIdx<crtProps.count; crtIdx++) {
+ final int crt_id = crtProps.crtIDs[crtIdx];
+ final ArrayHashSet<MonitorMode> supportedModes =
+ new ArrayHashSet<MonitorMode>(false, ArrayHashSet.DEFAULT_INITIAL_CAPACITY, ArrayHashSet.DEFAULT_LOAD_FACTOR);
+ int modeIdx = 0;
+ {
+ // Get all supported modes for this monitorDevice
+ MonitorMode mode;
+ while( true ) {
+ mode = getMonitorModeImpl(cache, crt_id, modeIdx);
+ if( null != mode ) {
+ if( mode.getSurfaceSize().getBitsPerPixel() >= 24 ) { // drop otherwise
+ supportedModes.getOrAdd(mode);
+ }
+ modeIdx++; // next mode on same monitor
+ } else {
+ break; // done with modes on this monitor
+ }
+ }
+ }
+ if( 0 >= modeIdx ) {
+ throw new InternalError("Could not gather single mode of device "+crtIdx+"/"+crtProps.count+" -> "+Display.toHexString(crt_id));
+ }
+ final MonitorMode currentMode = getMonitorModeImpl(cache, crt_id, -1);
+ if ( null == currentMode ) {
+ throw new InternalError("Could not gather current mode of device "+crtIdx+"/"+crtProps.count+" -> "+Display.toHexString(crt_id)+", but gathered "+modeIdx+" modes");
+ }
+ // merge monitor-props + supported modes
+ final float pixelScale = crtProps.pixelScaleArray[crtIdx];
+ MonitorModeProps.streamInMonitorDevice(cache, this, currentMode,
+ new float[] { pixelScale, pixelScale },
+ supportedModes, crtProps.propsFixedArray[crtIdx], 0, null);
+ }
+ }
+
+ @Override
+ protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) {
+ final CrtProps crtProps = new CrtProps();
+ final int crt_id = monitor.getId();
+ if( 0 == crt_id ) {
+ throw new IllegalArgumentException("Invalid monitor id "+Display.toHexString(crt_id));
+ }
+ final int crt_idx = crtProps.getIndex(crt_id);
+ if( 0 > crt_idx || crt_idx >= crtProps.count ) {
+ throw new IndexOutOfBoundsException("monitor id "+crt_idx+" not within [0.."+(crtProps.count-1)+"]");
+ }
+ final int[] fixedMonitorProps = crtProps.propsFixedArray[crt_idx];
+ int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
+ viewportPU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
+ viewportWU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
+ final float _pixelScale = crtProps.pixelScaleArray[crt_idx];
+ pixelScale[0] = _pixelScale;
+ pixelScale[1] = _pixelScale;
+ return true;
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return getMonitorModeImpl(null, monitor.getId(), -1);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return setMonitorMode0(monitor.getId(), mode.getId(), mode.getRotation());
+ }
+
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // big-desktop w/ multiple monitor attached, only one screen available
+ }
+
+ private native int[] getMonitorDeviceIds0();
+ private native int[] getMonitorProps0(int crt_id);
+ private native int[] getMonitorMode0(int crt_id, int mode_idx);
+ private native boolean setMonitorMode0(int crt_id, int nativeId, int rot);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java
new file mode 100644
index 000000000..2a257436a
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java
@@ -0,0 +1,812 @@
+/**
+ * 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.newt.driver.ios;
+
+import com.jogamp.common.util.InterruptSource;
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.GraphicsConfigurationFactory;
+import com.jogamp.nativewindow.NativeWindow;
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.MutableSurface;
+import com.jogamp.nativewindow.ScalableSurface;
+import com.jogamp.nativewindow.VisualIDHolder;
+import com.jogamp.nativewindow.util.Point;
+import com.jogamp.nativewindow.util.PointImmutable;
+
+import jogamp.nativewindow.SurfaceScaleUtils;
+import jogamp.nativewindow.ios.IOSUtil;
+import jogamp.newt.ScreenImpl;
+import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.DriverClearFocus;
+import jogamp.newt.driver.DriverUpdatePosition;
+
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.opengl.math.FloatUtil;
+
+public class WindowDriver extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public WindowDriver() {
+ }
+
+ private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final boolean deferOffThread,
+ final float newPixelScaleRaw, final float maxPixelScaleRaw) {
+ final float[] newPixelScale = new float[2];
+ {
+ final float _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : newPixelScaleRaw;
+ newPixelScale[0]= _newPixelScale;
+ newPixelScale[1]= _newPixelScale;
+ final float _maxPixelScale = FloatUtil.isZero(maxPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : maxPixelScaleRaw;
+ maxPixelScale[0]= _maxPixelScale;
+ maxPixelScale[1]= _maxPixelScale;
+ }
+ // We keep minPixelScale at [1f, 1f]!
+
+ if( SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, newPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
+ if( sendEvent ) {
+ if( deferOffThread ) {
+ superSizeChangedOffThread(defer, getWidth(), getHeight(), true);
+ } else {
+ super.sizeChanged(defer, getWidth(), getHeight(), true);
+ }
+ } else {
+ defineSize(getWidth(), getHeight());
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean updatePixelScaleByDisplayID(final boolean sendEvent) {
+ final float maxPixelScaleRaw = (float) IOSUtil.GetPixelScaleByDisplayID(getDisplayID());
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)");
+ }
+ return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw);
+ }
+
+ private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) {
+ final long handle = getWindowHandle();
+ if( 0 != handle ) {
+ final float maxPixelScaleRaw = (float)IOSUtil.GetPixelScale(handle);
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)");
+ }
+ return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw);
+ } else {
+ return false;
+ }
+ }
+
+ /** Called from native code */
+ protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float maxPixelScaleRaw) {
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (new), "+maxPixelScaleRaw+" (max), drop "+!isNativeValid());
+ }
+ if( isNativeValid() ) {
+ updatePixelScale(true /* sendEvent*/, defer, true /*offthread */, newPixelScaleRaw, maxPixelScaleRaw);
+ }
+ }
+
+ @Override
+ protected final void instantiationFinishedImpl() {
+ updatePixelScaleByDisplayID(false /* sendEvent*/);
+ }
+
+ @Override
+ protected void setScreen(final ScreenImpl newScreen) { // never null !
+ super.setScreen(newScreen);
+ updatePixelScaleByDisplayID(false /* sendEvent*/); // caller (reparent, ..) will send reshape event
+ }
+
+ @Override
+ protected void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ updatePixelScaleByWindowHandle(false /* sendEvent*/); // send reshape event itself
+ }
+
+ @Override
+ public final boolean setSurfaceScale(final float[] pixelScale) {
+ super.setSurfaceScale(pixelScale);
+
+ boolean changed = false;
+ if( isNativeValid() ) {
+ if( isOffscreenInstance ) {
+ final NativeWindow pWin = getParent();
+ if( pWin instanceof ScalableSurface ) {
+ final ScalableSurface sSurf = (ScalableSurface)pWin;
+ sSurf.setSurfaceScale(reqPixelScale);
+ sSurf.getMaximumSurfaceScale(maxPixelScale);
+ sSurf.getMinimumSurfaceScale(minPixelScale);
+ final float[] pPixelScale = sSurf.getCurrentSurfaceScale(new float[2]);
+ changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, pPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale
+ } else {
+ // just notify updated pixelScale if offscreen
+ changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, reqPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale
+ }
+ } else {
+ // set pixelScale in native code, will issue an update updatePixelScale(..)
+ // hence we pre-query whether pixel-scale will change, without affecting current state 'hasPixelScale'!
+ final float[] _hasPixelScale = new float[2];
+ System.arraycopy(hasPixelScale, 0, _hasPixelScale, 0, 2);
+ if( SurfaceScaleUtils.setNewPixelScale(_hasPixelScale, _hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
+ IOSUtil.RunOnMainThread(true, false, new Runnable() {
+ @Override
+ public void run() {
+ setPixelScale0(getWindowHandle(), surfaceHandle, _hasPixelScale[0]); // HiDPI: uniformPixelScale
+ }
+ } );
+ changed = true;
+ }
+ }
+ }
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.setPixelScale: min["+minPixelScale[0]+", "+minPixelScale[1]+"], max["+
+ maxPixelScale[0]+", "+maxPixelScale[1]+"], req["+
+ reqPixelScale[0]+", "+reqPixelScale[1]+"] -> result["+
+ hasPixelScale[0]+", "+hasPixelScale[1]+"] - changed "+changed+", realized "+isNativeValid());
+ }
+ return changed;
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
+ if (null == cfg) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ setGraphicsConfiguration(cfg);
+ reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY, true));
+ if ( !isNativeValid() ) {
+ throw new NativeWindowException("Error creating window");
+ }
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ try {
+ if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
+ final long handle = getWindowHandle();
+ visibleChanged(true, false);
+ setWindowHandle(0);
+ surfaceHandle = 0;
+ sscSurfaceHandle = 0;
+ isOffscreenInstance = false;
+ resizeAnimatorPaused = false;
+ if (0 != handle) {
+ IOSUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ close0( handle );
+ } });
+ }
+ } catch (final Throwable t) {
+ if(DEBUG_IMPLEMENTATION) {
+ final Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ protected int lockSurfaceImpl() {
+ /**
+ * if( isOffscreenInstance ) {
+ * return LOCK_SUCCESS;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if( 0 != v && 0 != w ) {
+ return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
+ }
+ return LOCK_SURFACE_NOT_READY;
+ }
+
+ @Override
+ protected void unlockSurfaceImpl() {
+ /**
+ * if( isOffscreenInstance ) {
+ * return;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if(0 != w && 0 != v) {
+ if( !unlockSurface0(w, v) ) {
+ throw new NativeWindowException("Failed to unlock surface, probably not locked!");
+ }
+ }
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
+ }
+
+ @Override
+ public void setSurfaceHandle(final long surfaceHandle) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
+ }
+ sscSurfaceHandle = surfaceHandle;
+ if ( isNativeValid() ) {
+ if (0 != sscSurfaceHandle) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
+ } /** this is done by recreation!
+ else if (isVisible()){
+ IOSUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
+ } */
+ }
+ }
+
+ @Override
+ protected void setTitleImpl(final String title) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setTitle0(getWindowHandle(), title);
+ } } );
+ }
+
+ @Override
+ protected void requestFocusImpl(final boolean force) {
+ final boolean _isFullscreen = isFullscreen();
+ final boolean _isOffscreenInstance = isOffscreenInstance;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen);
+ }
+ if(!_isOffscreenInstance) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ requestFocus0(getWindowHandle(), force);
+ if(_isFullscreen) {
+ // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode!
+ focusChanged(false, true);
+ }
+ } } );
+ } else {
+ focusChanged(false, true);
+ }
+ }
+
+ @Override
+ public final void clearFocus() {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
+ }
+ if(!isOffscreenInstance) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ resignFocus0(getWindowHandle());
+ } } );
+ } else {
+ focusChanged(false, false);
+ }
+ }
+
+ private boolean useParent(final NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
+
+ @Override
+ public void updatePosition(final int x, final int y) {
+ final long handle = getWindowHandle();
+ if( 0 != handle && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ final Point p0S;
+ if( useParent ) {
+ p0S = getLocationOnScreenByParent(x, y, parent);
+ } else {
+ p0S = (Point) getLocationOnScreen0(handle, x, y);
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ final int pX=parent.getX(), pY=parent.getY();
+ System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" -> "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
+ }
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ // no native event (fullscreen, some reparenting)
+ positionChanged(true, x, y);
+ }
+ }
+
+ @Override
+ protected final int getSupportedReconfigMaskImpl() {
+ return minimumReconfigStateMask |
+ STATE_MASK_CHILDWIN |
+ STATE_MASK_UNDECORATED |
+ STATE_MASK_ALWAYSONTOP |
+ STATE_MASK_ALWAYSONBOTTOM |
+ STATE_MASK_STICKY |
+ STATE_MASK_RESIZABLE |
+ STATE_MASK_MAXIMIZED_VERT |
+ STATE_MASK_MAXIMIZED_HORZ |
+ STATE_MASK_POINTERVISIBLE |
+ STATE_MASK_POINTERCONFINED;
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(int _x, int _y, int _width, int _height, final int flags) {
+ final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
+ isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
+ final PointImmutable pClientLevelOnSreen;
+ if( isOffscreenInstance ) {
+ _x = 0; _y = 0;
+ pClientLevelOnSreen = new Point(0, 0);
+ } else {
+ final NativeWindow parent = getParent();
+ if( useParent(parent) ) {
+ pClientLevelOnSreen = getLocationOnScreenByParent(_x, _y, parent);
+ } else {
+ if( 0 != ( ( CHANGE_MASK_MAXIMIZED_HORZ | CHANGE_MASK_MAXIMIZED_VERT ) & flags ) ) {
+ final int[] posSize = { _x, _y, _width, _height };
+ reconfigMaximizedManual(flags, posSize, getInsets());
+ _x = posSize[0];
+ _y = posSize[1];
+ _width = posSize[2];
+ _height = posSize[3];
+ }
+ pClientLevelOnSreen = new Point(_x, _y);
+ }
+ }
+ final int x=_x, y=_y;
+ final int width=_width, height=_height;
+
+ final boolean hasFocus = hasFocus();
+
+ if(DEBUG_IMPLEMENTATION) {
+ final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration();
+ final NativeWindow pWin = getParent();
+ final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null;
+ System.err.println("MacWindow reconfig.0: "+x+"/"+y+" -> clientPosOnScreen "+pClientLevelOnSreen+" - "+width+"x"+height+
+ ", "+getReconfigStateMaskString(flags)+
+ ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+
+ ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+
+ ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+
+ ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+
+ ", ioi: "+_isOffscreenInstance+
+ ") -> "+isOffscreenInstance);
+ // Thread.dumpStack();
+ }
+
+ if( 0 != ( CHANGE_MASK_VISIBILITY & flags) &&
+ 0 == ( STATE_MASK_VISIBLE & flags) )
+ {
+ if ( !isOffscreenInstance ) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0(getWindowHandle());
+ visibleChanged(true, false);
+ } } );
+ } else {
+ visibleChanged(true, false);
+ }
+ }
+ final long oldWindowHandle = getWindowHandle();
+ if( ( 0 == oldWindowHandle && 0 != ( STATE_MASK_VISIBLE & flags) ) ||
+ 0 != ( CHANGE_MASK_PARENTING & flags) ||
+ 0 != ( CHANGE_MASK_DECORATION & flags) ||
+ 0 != ( CHANGE_MASK_ALWAYSONTOP & flags) ||
+ 0 != ( CHANGE_MASK_ALWAYSONBOTTOM & flags) ||
+ 0 != ( CHANGE_MASK_RESIZABLE & flags) ||
+ 0 != ( CHANGE_MASK_FULLSCREEN & flags) ) {
+ if(isOffscreenInstance) {
+ createWindow(true, 0 != oldWindowHandle, pClientLevelOnSreen, 64, 64, flags);
+ } else {
+ createWindow(false, 0 != oldWindowHandle, pClientLevelOnSreen, width, height, flags);
+ }
+ // no native event (fullscreen, some reparenting)
+ updatePixelScaleByWindowHandle(false /* sendEvent */);
+ if( isOffscreenInstance) {
+ super.sizeChanged(false, width, height, true);
+ positionChanged(false, x, y);
+ } else {
+ updateSizePosInsets0(getWindowHandle(), false);
+ }
+ visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
+ if( hasFocus ) {
+ requestFocusImpl(true);
+ }
+ } else if( 0 != oldWindowHandle ) {
+ if( width>0 && height>0 ) {
+ if( !isOffscreenInstance ) {
+ IOSUtil.RunOnMainThread(true, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPointAndSize0(oldWindowHandle,
+ pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(),
+ width, height, 0 != ( STATE_MASK_VISIBLE & flags));
+ } } );
+ updateSizePosInsets0(oldWindowHandle, false);
+ } else { // else offscreen size is realized via recreation
+ // no native event (fullscreen, some reparenting)
+ super.sizeChanged(false, width, height, false);
+ positionChanged(false, x, y);
+ }
+ }
+ if( 0 != ( CHANGE_MASK_VISIBILITY & flags) &&
+ 0 != ( STATE_MASK_VISIBLE & flags) )
+ {
+ if( !isOffscreenInstance ) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderFront0(getWindowHandle());
+ visibleChanged(true, true);
+ } } );
+ } else {
+ visibleChanged(true, true);
+ }
+ }
+ } else {
+ throw new InternalError("Null windowHandle but no re-creation triggered, check visibility: "+getStateMaskString());
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow reconfig.X: "+getLocationOnScreenImpl(0, 0)+" "+getWidth()+"x"+getHeight()+", insets "+getInsets()+", "+getStateMaskString());
+ }
+ return true;
+ }
+
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
+ final NativeWindow parent = getParent();
+ if( useParent(parent) ) {
+ return getLocationOnScreenByParent(x, y, parent);
+ } else {
+ final long windowHandle = getWindowHandle();
+ if( !isOffscreenInstance && 0 != windowHandle ) {
+ return (Point) getLocationOnScreen0(windowHandle, x, y);
+ } else {
+ return new Point(x, y);
+ }
+ }
+ }
+
+ private Point getLocationOnScreenByParent(final int x, final int y, final NativeWindow parent) {
+ return new Point(x, y).translate( parent.getLocationOnScreen(null) );
+ }
+
+ /** Callback for native screen position change event of the client area. */
+ protected void screenPositionChanged(final boolean defer, final int newX, final int newY) {
+ // passed coordinates are in screen position of the client area
+ if( isNativeValid() ) {
+ final NativeWindow parent = getParent();
+ if( !useParent(parent) || isOffscreenInstance ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+ }
+ positionChanged(defer, newX, newY);
+ } else {
+ final Runnable action = new Runnable() {
+ public void run() {
+ // screen position -> rel child window position
+ final Point absPos = new Point(newX, newY);
+ final Point parentOnScreen = parent.getLocationOnScreen(null);
+ absPos.translate( parentOnScreen.scale(-1, -1) );
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos);
+ }
+ positionChanged(false, absPos.getX(), absPos.getY());
+ } };
+ if( defer ) {
+ new InterruptSource.Thread(null, action).start();
+ } else {
+ action.run();
+ }
+
+ }
+ } else if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+ }
+ }
+
+ @Override
+ protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
+ if(force || getWidth() != newWidth || getHeight() != newHeight) {
+ if( isNativeValid() && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ if( useParent ) {
+ final int x=getX(), y=getY();
+ final Point p0S = getLocationOnScreenByParent(x, y, parent);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos");
+ }
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ }
+ }
+ superSizeChangedOffThread(defer, newWidth, newHeight, force);
+ }
+ }
+ private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
+ if( defer ) {
+ new InterruptSource.Thread() {
+ public void run() {
+ WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force);
+ } }.start();
+ } else {
+ WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force);
+ }
+ }
+
+ //
+ // Accumulated actions
+ //
+
+ /** Triggered by implementation's WM events to update the client-area position, size and insets. */
+ protected void sizeScreenPosInsetsChanged(final boolean defer,
+ final int newX, final int newY,
+ final int newWidth, final int newHeight,
+ final int left, final int right, final int top, final int bottom,
+ final boolean force,
+ final boolean withinLiveResize) {
+ final LifecycleHook lh = getLifecycleHook();
+ if( withinLiveResize && !resizeAnimatorPaused && null!=lh ) {
+ resizeAnimatorPaused = lh.pauseRenderingAction();
+ }
+ sizeChanged(defer, newWidth, newHeight, force);
+ screenPositionChanged(defer, newX, newY);
+ insetsChanged(defer, left, right, top, bottom);
+ if( !withinLiveResize && resizeAnimatorPaused ) {
+ resizeAnimatorPaused = false;
+ if( null!=lh ) {
+ lh.resumeRenderingAction();
+ }
+ }
+ }
+
+ @Override
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ super.doMouseEvent(enqueue, wait, eventType, modifiers,
+ SurfaceScaleUtils.scale(x, getPixelScaleX()),
+ SurfaceScaleUtils.scale(y, getPixelScaleY()), button, rotationXYZ, 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");
+ }
+
+ @Override
+ public final void enqueueKeyEvent(final boolean wait, 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");
+ }
+
+ protected final void enqueueKeyEvent(final boolean wait, final short eventType, int modifiers, final short _keyCode, final char keyChar, final char keySymChar) {
+ // Note that we send the key char for the key code on this
+ // platform -- we do not get any useful key codes out of the system
+ final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
+ final short keySym;
+ {
+ final short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
+ keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
+ }
+ /**
+ {
+ final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
+ System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+
+ ", keyCode 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+
+ ", keySymChar '"+keySymChar+"', 0x"+Integer.toHexString(keySymChar)+" -> 0x"+Integer.toHexString(keySym)+
+ ", mods "+toHexString(modifiers)+
+ ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode+
+ ", nativeValid "+isNativeValid()+", isOffscreen "+isOffscreenInstance);
+ } */
+
+ // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+ // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
+ switch(eventType) {
+ case KeyEvent.EVENT_KEY_RELEASED:
+ if( isKeyCodeTracked(keyCode) ) {
+ setKeyPressed(keyCode, false);
+ }
+ break;
+ case KeyEvent.EVENT_KEY_PRESSED:
+ if( isKeyCodeTracked(keyCode) ) {
+ if( setKeyPressed(keyCode, true) ) {
+ // key was already pressed
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+ super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
+ }
+ }
+ break;
+ }
+ super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
+ }
+
+ protected int getDisplayID() {
+ if( !isOffscreenInstance ) {
+ return getDisplayID0(getWindowHandle());
+ }
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+
+ private void createWindow(final boolean offscreenInstance, final boolean recreate,
+ final PointImmutable pS, final int width, final int height,
+ final int flags)
+ {
+ final long parentWinHandle = getParentWindowHandle();
+ final long preWinHandle = getWindowHandle();
+
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
+ ": offscreen "+offscreenInstance+", recreate "+recreate+
+ ", pS "+pS+", "+width+"x"+height+", state "+getReconfigStateMaskString(flags)+
+ ", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
+ ", surfaceHandle "+toHexString(surfaceHandle));
+ // Thread.dumpStack();
+ }
+
+ try {
+ if( 0 != preWinHandle ) {
+ setWindowHandle(0);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
+ }
+ IOSUtil.RunOnMainThread(false, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ changeContentView0(parentWinHandle, preWinHandle, 0);
+ close0( preWinHandle );
+ } });
+ } else {
+ if( 0 != surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
+ }
+ surfaceHandle = createView0(pS.getX(), pS.getY(), width, height);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
+ }
+ }
+
+ final int windowStyle;
+ {
+ int ws = 0;
+ if( 0 != ( STATE_MASK_UNDECORATED & flags) || offscreenInstance ) {
+ ws = NSBorderlessWindowMask;
+ } else {
+ ws = NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask;
+ if( 0 != ( STATE_MASK_RESIZABLE & flags) ) {
+ ws |= NSResizableWindowMask;
+ }
+ }
+ windowStyle = ws;
+ }
+ // Blocking initialization on main-thread!
+ final long[] newWin = { 0 };
+ IOSUtil.RunOnMainThread(true, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ newWin[0] = createWindow0( pS.getX(), pS.getY(), width, height,
+ 0 != ( STATE_MASK_FULLSCREEN & flags),
+ windowStyle,
+ NSBackingStoreBuffered, surfaceHandle);
+ if ( newWin[0] != 0 ) {
+ final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
+ initWindow0( parentWinHandle, newWin[0], pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */,
+ isOpaque,
+ !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONTOP & flags),
+ !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags),
+ !offscreenInstance && 0 != ( STATE_MASK_VISIBLE & flags),
+ surfaceHandle);
+ if( offscreenInstance ) {
+ orderOut0(0!=parentWinHandle ? parentWinHandle : newWin[0]);
+ } else {
+ setTitle0(newWin[0], getTitle());
+ }
+ }
+ } });
+
+ if ( newWin[0] == 0 ) {
+ throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
+ }
+ setWindowHandle( newWin[0] );
+ } catch (final Exception ie) {
+ ie.printStackTrace();
+ }
+ }
+
+ protected static native boolean initIDs0();
+ private native long createView0(int x, int y, int w, int h);
+ 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,
+ boolean opaque, boolean atop, boolean abottom, boolean visible, long view);
+
+ private native int getDisplayID0(long window);
+ private native void setPixelScale0(long window, long view, float reqPixelScale);
+ private native boolean lockSurface0(long window, long view);
+ private native boolean unlockSurface0(long window, long view);
+ /** Must be called on Main-Thread */
+ private native void requestFocus0(long window, boolean force);
+ /** Must be called on Main-Thread */
+ private native void resignFocus0(long window);
+ /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */
+ private native void orderOut0(long window);
+ /** Must be called on Main-Thread */
+ private native void orderFront0(long window);
+ /** Must be called on Main-Thread */
+ 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 */
+ private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
+ /** Must be called on Main-Thread */
+ private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
+ /** Triggers {@link #sizeScreenPosInsetsChanged(boolean, int, int, int, int, int, int, int, int, boolean)} */
+ private native void updateSizePosInsets0(long window, boolean defer);
+ private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
+
+ // Window styles
+ private static final int NSBorderlessWindowMask = 0;
+ private static final int NSTitledWindowMask = 1 << 0;
+ private static final int NSClosableWindowMask = 1 << 1;
+ private static final int NSMiniaturizableWindowMask = 1 << 2;
+ private static final int NSResizableWindowMask = 1 << 3;
+
+ // Window backing store types
+ private static final int NSBackingStoreRetained = 0;
+ private static final int NSBackingStoreNonretained = 1;
+ private static final int NSBackingStoreBuffered = 2;
+
+ private volatile long surfaceHandle = 0;
+ private long sscSurfaceHandle = 0;
+ private boolean isOffscreenInstance = false;
+ private boolean resizeAnimatorPaused = false;
+}
diff --git a/src/newt/native/IOSNewtUIWindow.h b/src/newt/native/IOSNewtUIWindow.h
new file mode 100644
index 000000000..27ca7f3c7
--- /dev/null
+++ b/src/newt/native/IOSNewtUIWindow.h
@@ -0,0 +1,152 @@
+/**
+ * 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import <pthread.h>
+#import "jni.h"
+
+#include "NewtCommon.h"
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) ; fflush(stderr)
+ // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+// #define DBG_LIFECYCLE 1
+
+@interface NewtUIView : UIView
+{
+ jobject javaWindowObject;
+
+ volatile BOOL destroyNotifySent;
+ volatile int softLockCount;
+ pthread_mutex_t softLockSync;
+
+ BOOL modsDown[4]; // shift, ctrl, alt/option, win/command
+}
+
+- (id)initWithFrame:(CGRect)frameRect;
+
+#ifdef DBG_LIFECYCLE
+- (void) release;
+#endif
+- (void) dealloc;
+
+/* Register or deregister (NULL) the java Window object,
+ ie, if NULL, no events are send */
+- (void) setJavaWindowObject: (jobject) javaWindowObj;
+- (jobject) getJavaWindowObject;
+
+- (void) setDestroyNotifySent: (BOOL) v;
+- (BOOL) getDestroyNotifySent;
+
+- (BOOL) softLock;
+- (BOOL) softUnlock;
+
+- (void) drawRect:(CGRect)dirtyRect;
+- (BOOL) acceptsFirstResponder;
+- (BOOL) becomeFirstResponder;
+- (BOOL) resignFirstResponder;
+
+- (void) sendMouseEvent: (UIEvent*) event eventType: (jshort) evType;
+- (CGPoint) screenPos2NewtClientWinPos: (CGPoint) p;
+
+- (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;
+
+@end
+
+@interface NewtUIWindow : UIWindow
+{
+ BOOL realized;
+ jboolean withinLiveResize;
+@public
+ BOOL hasPresentationSwitch;
+ NSUInteger defaultPresentationOptions;
+ NSUInteger fullscreenPresentationOptions;
+ BOOL isFullscreenWindow;
+ int cachedInsets[4]; // l, r, t, b
+}
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz;
+
+- (id) initWithFrame: (CGRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSUInteger) bufferingType
+ defer: (BOOL) deferCreation
+ isFullscreenWindow:(BOOL)isfs;
+#ifdef DBG_LIFECYCLE
+- (void) release;
+#endif
+- (void) dealloc;
+- (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) attachToParent: (UIWindow*) parent;
+- (void) detachFromParent: (UIWindow*) parent;
+
+- (CGPoint) newtRelClientTLWinPos2AbsTLScreenPos: (CGPoint) p;
+- (CGSize) newtClientSize2TLSize: (CGSize) nsz;
+- (CGPoint) getLocationOnScreen: (CGPoint) p;
+
+- (void) focusChanged: (BOOL) gained;
+
+- (void) flagsChanged: (UIEvent *) theEvent;
+- (BOOL) acceptsMouseMovedEvents;
+- (BOOL) acceptsFirstResponder;
+- (BOOL) becomeFirstResponder;
+- (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) windowDidMove: (NSNotification*) notification;
+- (BOOL) windowClosingImpl: (BOOL) force;
+- (BOOL) windowShouldClose: (id) sender;
+- (void) windowWillClose: (NSNotification*) notification;
+
+@end
diff --git a/src/newt/native/IOSNewtUIWindow.m b/src/newt/native/IOSNewtUIWindow.m
new file mode 100644
index 000000000..6c5031efc
--- /dev/null
+++ b/src/newt/native/IOSNewtUIWindow.m
@@ -0,0 +1,783 @@
+/**
+ * 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.
+ */
+
+#import "IOSNewtUIWindow.h"
+#import "InputEvent.h"
+#import "KeyEvent.h"
+#import "MouseEvent.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <math.h>
+
+#define PRINTF(...) NSLog(@ __VA_ARGS__)
+
+static jmethodID enqueueMouseEventID = NULL;
+static jmethodID enqueueKeyEventID = NULL;
+static jmethodID requestFocusID = NULL;
+
+static jmethodID insetsChangedID = NULL;
+static jmethodID sizeChangedID = NULL;
+static jmethodID sizeScreenPosInsetsChangedID = NULL;
+static jmethodID updatePixelScaleID = NULL;
+static jmethodID visibleChangedID = NULL;
+static jmethodID screenPositionChangedID = NULL;
+static jmethodID focusChangedID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+static jmethodID windowRepaintID = NULL;
+
+// Need to enqueue all events to EDT,
+// since we may operate on AWT-AppKit (Main Thread)
+// and direct issuing 'requestFocus()' would deadlock:
+// AWT-AppKit
+// AWT-EventQueue-0
+
+@implementation NewtUIView
+
+- (id)initWithFrame:(CGRect)frameRect
+{
+ id res = [super initWithFrame:frameRect];
+ javaWindowObject = NULL;
+
+ destroyNotifySent = NO;
+ softLockCount = 0;
+
+ pthread_mutexattr_t softLockSyncAttr;
+ pthread_mutexattr_init(&softLockSyncAttr);
+ pthread_mutexattr_settype(&softLockSyncAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive
+
+ modsDown[0] = NO; // shift
+ modsDown[1] = NO; // ctrl
+ modsDown[2] = NO; // alt
+ modsDown[3] = NO; // win
+
+ DBG_PRINT("NewtUIView::create: %p (refcnt %d)\n", res, (int)[res retainCount]);
+ return res;
+}
+
+#ifdef DBG_LIFECYCLE
+- (void) release
+{
+ DBG_PRINT("NewtUIView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super release];
+}
+#endif
+
+- (void) dealloc
+{
+ DBG_PRINT("NewtUIView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+ if( 0 < softLockCount ) {
+ NSLog(@"NewtUIView::dealloc: softLock still hold @ dealloc!\n");
+ }
+
+ pthread_mutex_destroy(&softLockSync);
+ DBG_PRINT("NewtUIView::dealloc.X: %p\n", self);
+ [super dealloc];
+}
+
+- (void) setJavaWindowObject: (jobject) javaWindowObj
+{
+ javaWindowObject = javaWindowObj;
+}
+
+- (jobject) getJavaWindowObject
+{
+ return javaWindowObject;
+}
+
+- (void) setDestroyNotifySent: (BOOL) v
+{
+ destroyNotifySent = v;
+}
+
+- (BOOL) getDestroyNotifySent
+{
+ return destroyNotifySent;
+}
+
+- (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());
+ return 0 < softLockCount;
+}
+
+- (BOOL) softUnlock
+{
+ // DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self());
+ softLockCount--;
+ int err;
+ if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) {
+ softLockCount++;
+ NSLog(@"NewtUIView::softUnlock failed: Not locked by current thread - errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ return YES;
+}
+
+- (void) drawRect:(CGRect)dirtyRect
+{
+ DBG_PRINT("*************** dirtyRect: %p %lf/%lf %lfx%lf\n",
+ javaWindowObject, dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height);
+
+ if(NULL==javaWindowObject) {
+ DBG_PRINT("drawRect: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("drawRect: null JNIEnv\n");
+ return;
+ }
+
+ CGRect viewFrame = [self frame];
+
+ (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE, // defer ..
+ (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y,
+ (int)dirtyRect.size.width, (int)dirtyRect.size.height);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL) becomeFirstResponder
+{
+ DBG_PRINT( "*************** View.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
+}
+
+- (BOOL) resignFirstResponder
+{
+ DBG_PRINT( "*************** View.resignFirstResponder\n");
+ return [super resignFirstResponder];
+}
+
+- (void) sendMouseEvent: (UIEvent*) event eventType: (jshort) evType
+{
+ 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);
+}
+
+- (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;
+}
+
+- (void) handleFlagsChanged:(NSUInteger) mods
+{
+ // 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];
+}
+
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods
+{
+ 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];
+ }
+}
+
+- (void) sendKeyEvent: (UIEvent*) event eventType: (jshort) evType
+{
+ 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
+{
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("sendKeyEvent: null JNIEnv\n");
+ return;
+ }
+
+ int i;
+ int len = NULL != chars ? [chars length] : 0;
+ jint javaMods = 0; // TODO mods2JavaMods(mods);
+
+ 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);
+
+ 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);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar);
+ }
+ } else {
+ // non-printable chars
+ jchar keyChar = (jchar) 0;
+
+ DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, keyChar, keyChar);
+ }
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+@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");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)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");
+ screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
+ 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 &&
+ insetsChangedID && sizeScreenPosInsetsChangedID &&
+ screenPositionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
+ {
+ // TODO CKCH_CreateDictionaries();
+ return YES;
+ }
+ return NO;
+}
+
+- (id) initWithFrame: (CGRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSUInteger) bufferingType
+ 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;
+ // }
+
+ 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
+ cachedInsets[2] = 0; // t
+ cachedInsets[3] = 0; // b
+
+ 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]);
+ return res;
+}
+
+#ifdef DBG_LIFECYCLE
+- (void) release
+{
+ DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"%@",[NSThread callStackSymbols]);
+ [super release];
+}
+#endif
+
+- (void) dealloc
+{
+ DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+
+ /**
+ NewtUIView* mView = (NewtUIView *)self; // TODO [self contentView];
+ if( NULL != mView ) {
+ [mView release];
+ }
+ */
+ [super dealloc];
+ DBG_PRINT("NewtWindow::dealloc.X: %p\n", self);
+}
+
+- (void) setRealized: (BOOL)v
+{
+ realized = v;
+}
+
+- (BOOL) isRealized
+{
+ return realized;
+}
+
+- (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom
+{
+ /**
+ if( top ) {
+ DBG_PRINT( "*************** setAlwaysOn -> top\n");
+ [self setLevel: kCGMaximumWindowLevel];
+ } else if ( bottom ) {
+ DBG_PRINT( "*************** setAlwaysOn -> bottom\n");
+ [self setLevel: kCGDesktopIconWindowLevel]; // w/ input
+ } else {
+ DBG_PRINT( "*************** setAlwaysOn -> normal\n");
+ [self setLevel:NSNormalWindowLevel];
+ } */
+}
+
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin
+{
+ /**
+ CGRect frameRect = [self frame];
+ CGRect contentRect = [self 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;
+ cachedInsets[0] = (int)l; // l
+ cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
+ cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
+ cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+ */
+ UIEdgeInsets uiInsets = [self safeAreaInsets];
+ cachedInsets[0] = uiInsets.left;
+ cachedInsets[1] = uiInsets.right;
+ cachedInsets[2] = uiInsets.top;
+ cachedInsets[3] = uiInsets.bottom;
+ DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+ }
+}
+
+- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer
+{
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: NULL jwin:NULL];
+
+ CGRect frameRect = [self frame];
+
+ 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);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer,
+ (jint) pS.x, (jint) pS.y,
+ (jint) frameRect.size.width, (jint) frameRect.size.height,
+ cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3],
+ JNI_FALSE, // force
+ withinLiveResize
+ );
+ }
+}
+
+
+- (void) attachToParent: (UIWindow*) parent
+{
+ /** TODO
+ DBG_PRINT( "attachToParent.1\n");
+ [parent addChildWindow: self ordered: UIWindowAbove];
+ DBG_PRINT( "attachToParent.2\n");
+ [self setParentWindow: parent];
+ DBG_PRINT( "attachToParent.X\n");
+ */
+}
+
+- (void) detachFromParent: (UIWindow*) parent
+{
+ /** TODO
+ DBG_PRINT( "detachFromParent.1\n");
+ [self setParentWindow: nil];
+ if(NULL != parent) {
+ DBG_PRINT( "detachFromParent.2\n");
+ [parent removeChildWindow: self];
+ }
+ DBG_PRINT( "detachFromParent.X\n");
+ */
+}
+
+/**
+ * p rel client window position w/ top-left origin
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (CGPoint) newtRelClientTLWinPos2AbsTLScreenPos: (CGPoint) p
+{
+ return [self getLocationOnScreen: p];
+}
+
+- (CGSize) newtClientSize2TLSize: (CGSize) nsz
+{
+ CGSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom
+ return topSZ;
+}
+
+/**
+ * p rel client window position w/ top-left origin
+ * returns: location in 0/0 top-left space.
+ */
+- (CGPoint) getLocationOnScreen: (CGPoint) p
+{
+ UIScreen* screen = [self screen];
+ CGPoint pS = [self convertPoint: p toCoordinateSpace: screen.fixedCoordinateSpace];
+
+#ifdef VERBOSE_ON
+ CGRect winFrame = [self frame];
+ DBG_PRINT( "getLocationOnScreen: point-in[%d/%d], winFrame[%d/%d %dx%d] -> %d/%d\n",
+ (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
+
+ return pS;
+}
+
+- (void) focusChanged: (BOOL) gained
+{
+ DBG_PRINT( "focusChanged: gained %d\n", gained);
+ NewtUIView* newtView = (NewtUIView *) self; // TODO [self contentView];
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("focusChanged: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("focusChanged: null JNIEnv\n");
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (void) flagsChanged:(UIEvent *) theEvent
+{
+ NSUInteger mods = [theEvent modifierFlags];
+ NewtUIView* newtView = (NewtUIView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtUIView class]] ) {
+ [newtView handleFlagsChanged: mods];
+ }
+}
+
+- (BOOL) acceptsMouseMovedEvents
+{
+ return YES;
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL) becomeFirstResponder
+{
+ DBG_PRINT( "*************** Win.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
+}
+
+- (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];
+}
+
+- (void) resignKeyWindow
+{
+ DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
+ 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
+{
+ DBG_PRINT( "*************** windowWillStartLiveResize\n");
+ withinLiveResize = JNI_TRUE;
+}
+- (void) windowDidEndLiveResize: (NSNotification *) notification
+{
+ DBG_PRINT( "*************** windowDidEndLiveResize\n");
+ withinLiveResize = JNI_FALSE;
+ [self sendResizeEvent];
+}
+- (CGSize) windowWillResize: (UIWindow *)sender toSize:(CGSize)frameSize
+{
+ DBG_PRINT( "*************** windowWillResize %lfx%lf\n", frameSize.width, frameSize.height);
+ return frameSize;
+}
+- (void)windowDidResize: (NSNotification*) notification
+{
+ DBG_PRINT( "*************** windowDidResize\n");
+ [self sendResizeEvent];
+}
+
+- (void) sendResizeEvent
+{
+ jobject javaWindowObject = NULL;
+ 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];
+ }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (void)windowDidMove: (NSNotification*) notification
+{
+ NewtUIView* newtView = (NewtUIView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtUIView class]] ) {
+ return;
+ }
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("windowDidMove: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("windowDidMove: null JNIEnv\n");
+ return;
+ }
+
+ CGPoint p0 = { 0, 0 };
+ p0 = [self getLocationOnScreen: p0];
+ DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y);
+ (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (BOOL)windowShouldClose: (id) sender
+{
+ return [self windowClosingImpl: NO];
+}
+
+- (void)windowWillClose: (NSNotification*) notification
+{
+ [self windowClosingImpl: YES];
+}
+
+- (BOOL) windowClosingImpl: (BOOL) force
+{
+ jboolean closed = JNI_FALSE;
+
+ NewtUIView* newtView = (NewtUIView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtUIView class]] ) {
+ 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) {
+ DBG_PRINT("windowWillClose: null javaWindowObject\n");
+ [pool release];
+ return NO;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("windowWillClose: null JNIEnv\n");
+ [pool release];
+ return NO;
+ }
+ [newtView setDestroyNotifySent: true]; // earmark assumption of being closed
+ closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE);
+ if(!force && !closed) {
+ // not closed on java side, not force -> clear flag
+ [newtView setDestroyNotifySent: false];
+ }
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+ DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed);
+ } else {
+ DBG_PRINT( "*************** windowWillClose (skip)\n");
+ }
+ [pool release];
+ return JNI_TRUE == closed ? YES : NO ;
+}
+
+@end
+
diff --git a/src/newt/native/IOSUIWindow.m b/src/newt/native/IOSUIWindow.m
new file mode 100644
index 000000000..780c2344f
--- /dev/null
+++ b/src/newt/native/IOSUIWindow.m
@@ -0,0 +1,1161 @@
+/**
+ * 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.
+ */
+
+#import <inttypes.h>
+
+#import "jogamp_newt_driver_ios_WindowDriver.h"
+#import "IOSNewtUIWindow.h"
+
+#import "MouseEvent.h"
+#import "KeyEvent.h"
+#import "ScreenMode.h"
+
+#import <stdio.h>
+
+#ifdef DBG_PERF
+ #include "timespec.h"
+#endif
+
+static const char * const ClazzNamePoint = "com/jogamp/nativewindow/util/Point";
+static const char * const ClazzAnyCstrName = "<init>";
+static const char * const ClazzNamePointCstrSignature = "(II)V";
+static jclass pointClz = NULL;
+static jmethodID pointCstr = NULL;
+
+static NSString* jstringToNSString(JNIEnv* env, jstring jstr)
+{
+ const jchar* jstrChars = (*env)->GetStringChars(env, jstr, NULL);
+ NSString* str = [[NSString alloc] initWithCharacters: jstrChars length: (*env)->GetStringLength(env, jstr)];
+ (*env)->ReleaseStringChars(env, jstr, jstrChars);
+ return str;
+}
+
+static void setWindowClientTopLeftPoint(NewtUIWindow* mWin, jint x, jint y, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay);
+ CGPoint pS = CGPointMake(x, y);
+ CGRect rect = [mWin frame];
+ rect.origin = pS;
+
+ [mWin setFrame: rect];
+ DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y);
+
+ if( doDisplay ) {
+ // TODO UIView* mView = [mWin contentView];
+ // TODO [mWin invalidateCursorRectsForView: mView];
+ }
+}
+
+static void setWindowClientTopLeftPointAndSize(NewtUIWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay);
+ 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];
+ 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];
+ // }
+}
+
+#ifdef VERBOSE_ON
+static int getRetainCount(NSObject * obj) {
+ return ( NULL == obj ) ? -1 : (int)([obj retainCount]) ;
+}
+#endif
+
+static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtUIView *view, BOOL enable) {
+ DBG_PRINT( "setJavaWindowObject.0: View %p\n", view);
+ if( !enable) {
+ jobject globJavaWindowObject = [view getJavaWindowObject];
+ if( NULL != globJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject);
+ (*env)->DeleteGlobalRef(env, globJavaWindowObject);
+ [view setJavaWindowObject: NULL];
+ }
+ } else if( NULL != newJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject);
+ jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject);
+ [view setJavaWindowObject: globJavaWindowObject];
+ }
+ DBG_PRINT( "setJavaWindowObject.X: View %p\n", view);
+}
+
+static void changeContentView(JNIEnv *env, jobject javaWindowObject, UIView *pview, NewtUIWindow *win, NewtUIView *newView, BOOL setJavaWindow) {
+ UIView* oldUIView = NULL; // TODO [win contentView];
+ NewtUIView* oldNewtUIView = NULL;
+#ifdef VERBOSE_ON
+ int dbgIdx = 1;
+#endif
+
+ if( [oldUIView isKindOfClass:[NewtUIView class]] ) {
+ oldNewtUIView = (NewtUIView *) oldUIView;
+ }
+
+ 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]);
+
+ if( NULL!=newView ) {
+ [newView setDestroyNotifySent: false];
+ if( setJavaWindow ) {
+ setJavaWindowObject(env, javaWindowObject, newView, YES);
+ }
+
+ 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]);
+
+ // TODO [win setContentView: 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]);
+
+ // 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));
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_DisplayDriver
+ * Method: initIDs
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_DisplayDriver_initUIApplication0
+ (JNIEnv *env, jclass clazz)
+{
+ static int initialized = 0;
+
+ if(initialized) return JNI_TRUE;
+ initialized = 1;
+
+ NewtCommon_init(env);
+
+ // Initialize the shared NSApplication instance
+ [UIApplication sharedApplication];
+
+ // Need this when debugging, as it is necessary to attach gdb to
+ // the running java process -- "gdb java" doesn't work
+ // printf("Going to sleep for 10 seconds\n");
+ // sleep(10);
+
+ return (jboolean) JNI_TRUE;
+}
+
+static void NewtScreen_dump() {
+#ifdef VERBOSE_ON
+ NSArray *screens = [UIScreen screens];
+ 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",
+ 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);
+ }
+#endif
+}
+
+// Duplicate each Mode by all possible rotations (4):
+// For each real-mode: [mode, 0], [mode, 90], [mode, 180], [mode, 270]
+#define ROTMODES_PER_REALMODE 1
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: getMonitorDeviceIds0
+ * Signature: ()I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorDeviceIds0
+ (JNIEnv *env, jobject obj)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSArray *screens = [UIScreen screens];
+ int count = [screens count];
+ int32_t displayIDs[count];
+ int i;
+ for(i=0; i<count; i++) {
+ // UIScreen * screen = (UIScreen *) [screens objectAtIndex: i];
+ displayIDs[i] = i; // TODO no unique screen name?
+ }
+ jintArray properties = (*env)->NewIntArray(env, count);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, count, displayIDs);
+ [pool release];
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: getMonitorProps0
+ * Signature: (I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorProps0
+ (JNIEnv *env, jobject obj, jint crt_id)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+ NSArray *screens = [UIScreen screens];
+ int count = [screens count];
+ UIScreen * screen = (UIScreen *) [screens objectAtIndex: crt_id];
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
+ BOOL isPrimary = 0 == crt_id;
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ 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];
+#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);
+#endif
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int offset = 0;
+ prop[offset++] = propCount;
+ prop[offset++] = crt_id;
+ prop[offset++] = 0; // isClone
+ 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)
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ [pool release];
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: getMonitorMode0
+ * Signature: (II)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jint crt_id, jint mode_idx)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray<UIScreen*> *screens = [UIScreen screens];
+ 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
+
+ NSArray<UIScreenMode*> *availableModes = [screen availableModes];
+ int numberOfAvailableModes = [availableModes count];
+ CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes;
+ int currentCCWRot = 0;
+ jint ccwRot = 0;
+ int nativeId = 0;
+ UIScreenMode * mode = NULL;
+
+#ifdef VERBOSE_ON
+ 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);
+ }
+#endif
+
+ if(numberOfAvailableModesRots<=mode_idx) {
+ // n/a - end of modes
+ DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n",
+ (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+ [pool release];
+ return NULL;
+ } else if(-1 < mode_idx) {
+ // only at initialization time, where index >= 0
+ nativeId = mode_idx / ROTMODES_PER_REALMODE;
+ ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
+ mode = (UIScreenMode*) [availableModes objectAtIndex: nativeId];
+ } else {
+ // current mode
+ mode = [screen currentMode];
+ ccwRot = 0;
+ nativeId = 0;
+ }
+ // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
+
+ 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 ) {
+ int tempWidth = mWidth;
+ mWidth = mHeight;
+ mHeight = tempWidth;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ int refreshRate = 60; // TODO
+ int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8)
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mWidth;
+ prop[propIndex++] = mHeight;
+ prop[propIndex++] = 32; // TODO CGDDGetModeBitsPerPixel(mode);
+ prop[propIndex++] = fRefreshRate * 100; // Hz*100
+ prop[propIndex++] = 0; // flags
+ prop[propIndex++] = nativeId;
+ prop[propIndex++] = ccwRot;
+
+ DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n",
+ (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes,
+ (int)prop[1], (int)prop[2], (int)prop[3],
+ (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]);
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef
+ [pool release];
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: setMonitorMode0
+ * Signature: (III)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint crt_id, jint nativeId, jint ccwRot)
+{
+ return false;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: initIDs
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_WindowDriver_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ static int initialized = 0;
+
+ if(initialized) return JNI_TRUE;
+ initialized = 1;
+
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NewtScreen_dump();
+
+ jclass c;
+ c = (*env)->FindClass(env, ClazzNamePoint);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_ios_WindowDriver_initIDs0: can't find %s", ClazzNamePoint);
+ }
+ pointClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==pointClz) {
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_ios_WindowDriver_initIDs0: can't use %s", ClazzNamePoint);
+ }
+ pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ if(NULL==pointCstr) {
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_ios_WindowDriver_initIDs0: can't fetch %s.%s %s",
+ ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ }
+
+ // Need this when debugging, as it is necessary to attach gdb to
+ // the running java process -- "gdb java" doesn't work
+ // printf("Going to sleep for 10 seconds\n");
+ // sleep(10);
+
+ BOOL res = [NewtUIWindow initNatives: env forClass: clazz];
+ [pool release];
+
+ return (jboolean) res;
+}
+
+/**
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: createView0
+ * 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)
+{
+ 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);
+
+ CGRect rectView = CGRectMake(0, 0, w, h);
+ NewtUIView *myView = [[NewtUIView alloc] initWithFrame: rectView] ;
+ DBG_PRINT( "createView0.X - new view: %p\n", myView);
+
+ [pool release];
+
+ return (jlong) (intptr_t) myView;
+}
+
+/**
+ * Method creates a deferred un-initialized Window, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: createWindow0
+ * Signature: (IIIIZIIJ)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_createWindow0
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h,
+ jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ 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",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen,
+ (int)styleMask, (int)bufferingType, myView);
+ (void)myView;
+
+ if (fullscreen) {
+ // TODO styleMask = NSBorderlessWindowMask;
+ }
+ CGRect rectWin = CGRectMake(x, y, w, h);
+
+ // Allocate the window
+ NewtUIWindow* myWindow = [[NewtUIWindow alloc] initWithContentRect: 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]);
+
+ [pool release];
+
+ return (jlong) ((intptr_t) myWindow);
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_ios_WindowDriver_getDisplayID0(JNIEnv *env, jobject jthis, jlong window) {
+ NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == myWindow ) {
+ DBG_PRINT( "getDisplayID0 - NULL NEWT win - abort\n");
+ return 0;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIScreen *screen = [myWindow screen];
+ int32_t displayID = 0; // TODO (int32_t)NewtScreen_getCGDirectDisplayIDByUIScreen(screen);
+ [pool release];
+ return (jint) displayID;
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: initWindow0
+ * Signature: (JJIIIIFZZZJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_initWindow0
+ (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, jfloat reqPixelScale,
+ jboolean opaque, jboolean atop, jboolean abottom, jboolean visible, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window);
+ NewtUIView* myView = (NewtUIView*) (intptr_t) jview ;
+ 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;
+ if( nsParentObj != NULL && [nsParentObj isKindOfClass:[UIWindow class]] ) {
+ parentWindow = (UIWindow*) nsParentObj;
+ parentView = (UIView*)nsParentObj;
+ DBG_PRINT( "initWindow0 - Parent is UIWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
+ } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[UIView class]] ) {
+ parentView = (UIView*) nsParentObj;
+ parentWindow = [parentView window];
+ DBG_PRINT( "initWindow0 - Parent is UIView : %p -(view) > %p (win) \n", parentView, parentWindow);
+ } else {
+ DBG_PRINT( "initWindow0 - Parent is neither UIWindow nor UIView : %p\n", nsParentObj);
+ }
+ DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+
+ // Remove animations for child windows
+ 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++);
+ } 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]);
+
+ // 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]);
+
+ if(NULL!=parentWindow) {
+ [myWindow attachToParent: parentWindow];
+ }
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d, visible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible], visible);
+
+ // 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];
+ }
+
+ 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);
+
+ [myView setDestroyNotifySent: false];
+ setJavaWindowObject(env, jthis, myView, YES);
+
+ 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
+
+ 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);
+
+ [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);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setPixelScale0
+ * Signature: (JJF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setPixelScale0
+ (JNIEnv *env, jobject jthis, jlong window, jlong view, jfloat reqPixelScale)
+{
+ NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == myWindow ) {
+ DBG_PRINT( "setPixelScale0 - NULL NEWT win - abort\n");
+ 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);
+
+ [pool release];
+ DBG_PRINT( "setPixelScale0.X - %p (this), window: %p, view %p\n",
+ (void*)(intptr_t)jthis, myWindow, myView);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: close0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_close0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n");
+ return;
+ }
+ BOOL isNSWin = [mWin isKindOfClass:[UIWindow class]];
+ BOOL isNewtWin = [mWin isKindOfClass:[NewtUIWindow class]];
+ UIWindow *pWin = NULL; // TODO [mWin parentWindow];
+ DBG_PRINT( "windowClose.0 - %p [isUIWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin);
+ (void)isNSWin; // silence
+ if( !isNewtWin ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtUIWindow %p", mWin);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIView* mView = (NewtUIView *)mWin; // TODO [mWin contentView];
+ BOOL fullscreen = mWin->isFullscreenWindow;
+ BOOL destroyNotifySent, isUIView, isNewtUIView;
+ if( NULL != mView ) {
+ isUIView = [mView isKindOfClass:[UIView class]];
+ isNewtUIView = [mView isKindOfClass:[NewtUIView class]];
+ destroyNotifySent = isNewtUIView ? [mView getDestroyNotifySent] : false;
+ } else {
+ isUIView = false;
+ isNewtUIView = false;
+ destroyNotifySent = false;
+ }
+
+ DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isUIView %d, isNewtUIView %d], fullscreen %d, parent %p\n",
+ mWin, destroyNotifySent, mView, isUIView, isNewtUIView, (int)fullscreen, pWin);
+
+ [mWin setRealized: NO];
+
+ if( isNewtUIView ) {
+ // cleanup view
+ [mView setDestroyNotifySent: true];
+ setJavaWindowObject(env, NULL, mView, NO);
+ }
+
+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
+
+ if(NULL!=pWin) {
+ [mWin detachFromParent: pWin];
+ }
+ // TODO [mWin orderOut: mWin];
+ [mWin setHidden: YES]; // no release, close n/a, .. well: ref count counts :-(
+
+ DBG_PRINT( "windowClose.2 - %p view %p, parent %p\n", mWin, mView, pWin);
+
+ [mWin release];
+
+ DBG_PRINT( "windowClose.Xp\n");
+
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_ios_WindowDriver
+ * Method: lockSurface0
+ * Signature: (JJ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_WindowDriver_lockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
+{
+ NewtUIWindow *mWin = (NewtUIWindow*) ((intptr_t) window);
+ if(NO == [mWin isRealized]) {
+ return JNI_FALSE;
+ }
+ NewtUIView * mView = (NewtUIView *) ((intptr_t) view);
+ return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE;
+ /** deadlocks, since we render independent of focus
+ return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_ios_WindowDriver
+ * Method: unlockSurface0
+ * Signature: (JJ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_WindowDriver_unlockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
+{
+ // NewtUIWindow *mWin = (NewtUIWindow*) ((intptr_t) window);
+ (void) window;
+ NewtUIView * mView = (NewtUIView *) ((intptr_t) view);
+ return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE;
+ /** deadlocks, since we render independent of focus
+ [mView unlockFocus]; */
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: requestFocus0
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_requestFocus0
+ (JNIEnv *env, jobject window, jlong w, jboolean force)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) w);
+ if( NULL == mWin ) {
+ DBG_PRINT( "requestFocus - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+#ifdef VERBOSE_ON
+ BOOL hasFocus = [mWin isKeyWindow];
+#endif
+ DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
+
+ // TODO [mWin setAcceptsMouseMovedEvents: YES];
+ // TODO [mWin makeFirstResponder: nil];
+ // TODO [mWin orderFrontRegardless];
+ [mWin makeKeyWindow];
+
+ DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: resignFocus0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_resignFocus0
+ (JNIEnv *env, jobject window, jlong w)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) w);
+ if( NULL == mWin ) {
+ DBG_PRINT( "resignFocus0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIWindow* pWin = NULL; // TODO [mWin parentWindow];
+ BOOL hasFocus = [mWin isKeyWindow];
+
+ DBG_PRINT( "resignFocus0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
+ if( hasFocus ) {
+ if(NULL != pWin) {
+ // [mWin makeFirstResponder: pWin];
+ [pWin makeKeyWindow];
+ } else {
+ [pWin resignKeyWindow];
+ }
+ }
+ DBG_PRINT( "resignFocus0 - window: %p (END)\n", mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: orderFront0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_orderFront0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "orderFront0 - NULL NEWT win - abort\n");
+ return;
+ }
+ 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]);
+
+ if( NULL == pWin ) {
+ // TODO [mWin orderFrontRegardless];
+ } else {
+ // TODO [mWin orderWindow: UIWindowAbove relativeTo: [pWin windowNumber]];
+ }
+
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: orderOut
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_orderOut0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "orderOut0 - NULL NEWT win - abort\n");
+ return;
+ }
+ 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]);
+
+ if( NULL == pWin ) {
+ // TODO [mWin orderOut: mWin];
+ } else {
+ // TODO [mWin orderWindow: UIWindowOut relativeTo: [pWin windowNumber]];
+ }
+
+ DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setTitle0
+ * Signature: (JLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setTitle0
+ (JNIEnv *env, jobject unused, jlong window, jstring title)
+{
+ UIWindow* win = (UIWindow*) ((intptr_t) window);
+ if( NULL == win ) {
+ DBG_PRINT( "setTitle0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "setTitle0 - window: %p (START)\n", win);
+
+ NSString* str = jstringToNSString(env, title);
+ [str autorelease];
+ // TODO [win setTitle: str];
+
+ DBG_PRINT( "setTitle0 - window: %p (END)\n", win);
+
+ [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.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: changeContentView
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_changeContentView0
+ (JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NewtUIView* newView = (NewtUIView *) ((intptr_t) jview);
+ NewtUIWindow* win = (NewtUIWindow*) ((intptr_t) window);
+
+ DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d)\n",
+ win, newView, getRetainCount(newView));
+
+ NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView);
+ UIView* pView = NULL;
+ if( NULL != nsParentObj ) {
+ if( [nsParentObj isKindOfClass:[UIWindow class]] ) {
+ UIWindow * pWin = (UIWindow*) nsParentObj;
+ pView = (UIView*)pWin; // TODO [pWin contentView];
+ } else if( [nsParentObj isKindOfClass:[UIView class]] ) {
+ pView = (UIView*) nsParentObj;
+ }
+ }
+
+ changeContentView(env, jthis, pView, win, newView, YES);
+
+ DBG_PRINT( "changeContentView0.X\n");
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: updateSizePosInsets0
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_updateSizePosInsets0
+ (JNIEnv *env, jobject jthis, jlong window, jboolean defer)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+
+ DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (START)\n", mWin, (int)defer);
+
+ [mWin updateSizePosInsets: env jwin:jthis defer:defer];
+
+ DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (END)\n", mWin, (int)defer);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setWindowClientTopLeftPointAndSize0
+ * Signature: (JIIIIZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setWindowClientTopLeftPointAndSize0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
+
+ setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
+
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setWindowClientTopLeftPoint0
+ * Signature: (JIIZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setWindowClientTopLeftPoint0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
+{
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "setWindowClientTopLeftPoint - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
+
+ setWindowClientTopLeftPoint(mWin, x, y, display);
+
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: getLocationOnScreen0
+ * Signature: (JII)Lcom/jogamp/nativewindow/util/Point;
+ */
+JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_ios_WindowDriver_getLocationOnScreen0
+ (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y)
+{
+ NewtUIWindow *mWin = (NewtUIWindow*) (intptr_t) win;
+ if( NULL == mWin ) {
+ DBG_PRINT( "getLocationOnScreen0 - NULL NEWT win - abort\n");
+ return NULL;
+ }
+ if( ![mWin isKindOfClass:[NewtUIWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtUIWindow %p", mWin);
+ return NULL;
+ }
+ CGPoint p0 = [mWin getLocationOnScreen: CGPointMake(src_x, src_y)];
+ return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y);
+}
+
diff --git a/src/newt/native/JVM_JNI8.c b/src/newt/native/JVM_JNI8.c
new file mode 100644
index 000000000..c023cb0f0
--- /dev/null
+++ b/src/newt/native/JVM_JNI8.c
@@ -0,0 +1,42 @@
+/**
+ * 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 <stdio.h> //required by android to identify NULL
+#include <jni.h>
+
+#if defined (JNI_VERSION_1_8)
+
+JNIEXPORT jint JNICALL JNI_OnLoad_newt(JavaVM *vm, void *reserved) {
+ return JNI_VERSION_1_8;
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload_newt(JavaVM *vm, void *reserved) {
+}
+
+#endif /* defined (JNI_VERSION_1_8) */
+