diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java index 2b8c3f87..74a9cc1a 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java @@ -89,36 +89,6 @@ public class UIKit { method.invoke(null, new Object[]{new String[]{}}); } - public static void callback_SurfaceViewController_onTouch(int event, float x, float y) { - switch (event) { - case ACTION_DOWN: - case ACTION_UP: - if (!GLFW.mGLFWIsGrabbing) { - CallbackBridge.mouseX = x; - CallbackBridge.mouseY = y; - } - break; - - case ACTION_MOVE: - if (GLFW.mGLFWIsGrabbing) { - CallbackBridge.mouseX += x - CallbackBridge.mouseLastX; - CallbackBridge.mouseY += y - CallbackBridge.mouseLastY; - } else { - CallbackBridge.mouseX = x; - CallbackBridge.mouseY = y; - } - break; - - case ACTION_MOVE_MOTION: - CallbackBridge.mouseX += x; - CallbackBridge.mouseY += y; - } - CallbackBridge.mouseLastX = x; - CallbackBridge.mouseLastY = y; - - CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - } - public static void updateMCGuiScale() { MCOptionUtils.load(); String str = MCOptionUtils.get("guiScale"); diff --git a/JavaApp/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/JavaApp/src/main/java/org/lwjgl/glfw/CallbackBridge.java index eb6b9473..212e87c7 100644 --- a/JavaApp/src/main/java/org/lwjgl/glfw/CallbackBridge.java +++ b/JavaApp/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -1,12 +1,5 @@ package org.lwjgl.glfw; - -import java.io.*; import java.util.*; -import android.util.*; - -import net.kdt.pojavlaunch.*; -import net.kdt.pojavlaunch.uikit.UIKit; -import net.kdt.pojavlaunch.utils.MCOptionUtils; public class CallbackBridge { public static final int CLIPBOARD_COPY = 2000; @@ -20,210 +13,38 @@ public class CallbackBridge { public static final int EVENT_TYPE_KEY = 1005; public static final int EVENT_TYPE_MOUSE_BUTTON = 1006; public static final int EVENT_TYPE_SCROLL = 1007; - public static final int EVENT_TYPE_WINDOW_POS = 1008; - public static final int EVENT_TYPE_WINDOW_SIZE = 1009; + public static final int EVENT_TYPE_WINDOW_SIZE = 1008; public static final int ANDROID_TYPE_GRAB_STATE = 0; - // Should pending events be limited? - volatile public static List PENDING_EVENT_LIST = new ArrayList<>(); - volatile public static boolean PENDING_EVENT_READY = false; - public static final boolean INPUT_DEBUG_ENABLED; - private static boolean inputReady; - // TODO send grab state event to Android static { - System.load(System.getenv("BUNDLE_PATH") + "/PojavLauncher"); - - // Forge 1.17+ initialize their very own space (both Java and JNI) so we re-init stuff here - MCOptionUtils.load(); - Tools.mGLFWWindowWidth = Integer.parseInt(MCOptionUtils.get("overrideWidth")); - Tools.mGLFWWindowHeight = Integer.parseInt(MCOptionUtils.get("overrideHeight")); - MCOptionUtils.save(); // Free the loaded data - CallbackBridge.setClass(); - try { - Class.forName("net.kdt.pojavlaunch.uikit.UIKit"); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - INPUT_DEBUG_ENABLED = Boolean.parseBoolean(System.getProperty("glfwstub.debugInput", "false")); - } - -// BEGIN launcher side - public static float mouseX, mouseY, mouseLastX, mouseLastY; - public static boolean mouseLeft; - //public static StringBuilder DEBUG_STRING = new StringBuilder(); - public static boolean nativeIsGrabbing() { - return GLFW.mGLFWIsGrabbing; - } - - private static void nativeSendCursorPos(float x, float y) { - if (!inputReady) return; - GLFW.mGLFWCursorX = x + GLFW.internalGetWindow(GLFW.mainContext).x; - GLFW.mGLFWCursorY = y + GLFW.internalGetWindow(GLFW.mainContext).y; - } - private static void nativeSendKeycode(int keycode, char keychar, int scancode, int action, int mods) { - if (!inputReady) return; - // TODO keycode - // PENDING_EVENT_LIST.add(new Integer[]{EVENR_TYPE_CHAR_MODS}); - } - private static void nativeSendMouseButton(int button, int action, int mods) { - if (!inputReady) return; - PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_MOUSE_BUTTON, button, action, mods, 0}); - } - private static void nativeSendScroll(double xoffset, double yoffset) { - if (!inputReady) return; - PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_SCROLL, (int) xoffset, (int) yoffset, 0, 0}); - } - private static void nativeSendScreenSize(int width, int height) { - if (!inputReady) return; - PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_FRAMEBUFFER_SIZE, width, height, 0, 0}); - PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_WINDOW_SIZE, width, height, 0, 0}); - } - private static void nativeSendWindowPos(int x, int y) { - if (!inputReady) return; - PENDING_EVENT_LIST.add(new Object[]{EVENT_TYPE_WINDOW_POS, x, y, 0, 0}); - } - - // volatile private static boolean isGrabbing = false; - public static class PusherRunnable implements Runnable { - int button; float x; float y; - public PusherRunnable(int button, float x, float y) { - this.button = button; - this.x = x; - this.y = y; - } - @Override - public void run() { - putMouseEventWithCoords(button, 1, x, y); - try { Thread.sleep(40); } catch (InterruptedException e) {} - putMouseEventWithCoords(button, 0, x, y); - } - } - public static void putMouseEventWithCoords(int button, float x, float y /* , int dz, long nanos */) { - new Thread(new PusherRunnable(button,x,y)).run(); - } - - public static void putMouseEventWithCoords(int button, int state, float x, float y /* , int dz, long nanos */) { - sendCursorPos(x, y); - sendMouseKeycode(button, CallbackBridge.getCurrentMods(), state == 1); - } - - private static boolean threadAttached; - public static void sendCursorPos(float x, float y) { - if (!threadAttached) { - threadAttached = true; // CallbackBridge.nativeAttachThreadToOther(true, true /* TODO BaseMainActivity.isInputStackCall */); - } - - //DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n"); - mouseX = x; - mouseY = y; - nativeSendCursorPos(x, y); - } - - public static void sendKeycode(int keycode, char keychar, int scancode, int modifiers, boolean isDown) { - //DEBUG_STRING.append("KeyCode=" + keycode + ", Char=" + keychar); - // TODO CHECK: This may cause input issue, not receive input! - /* - if (!nativeSendCharMods((int) keychar, modifiers) || !nativeSendChar(keychar)) { - nativeSendKey(keycode, 0, isDown ? 1 : 0, modifiers); - } - */ - - nativeSendKeycode(keycode, keychar, scancode, isDown ? 1 : 0, modifiers); - - // sendData(JRE_TYPE_KEYCODE_CONTROL, keycode, Character.toString(keychar), Boolean.toString(isDown), modifiers); - } - - public static void sendMouseKeycode(int button, int modifiers, boolean isDown) { - //DEBUG_STRING.append("MouseKey=" + button + ", down=" + isDown + "\n"); - // if (isGrabbing()) DEBUG_STRING.append("MouseGrabStrace: " + android.util.Log.getStackTraceString(new Throwable()) + "\n"); - nativeSendMouseButton(button, isDown ? 1 : 0, modifiers); - } - - public static void sendMouseKeycode(int keycode) { - sendMouseKeycode(keycode, CallbackBridge.getCurrentMods(), true); - sendMouseKeycode(keycode, CallbackBridge.getCurrentMods(), false); - } - - public static void sendScroll(double xoffset, double yoffset) { - //DEBUG_STRING.append("ScrollX=" + xoffset + ",ScrollY=" + yoffset); - nativeSendScroll(xoffset, yoffset); - } - - public static void sendUpdateWindowSize(int w, int h) { - nativeSendScreenSize(w, h); - } - - public static boolean isGrabbing() { - return nativeIsGrabbing(); - } - - public static boolean holdingAlt, holdingCapslock, holdingCtrl, - holdingNumlock, holdingShift; - public static int getCurrentMods() { - int currMods = 0; - if (holdingAlt) { - currMods &= LWJGLGLFWKeycode.GLFW_MOD_ALT; - } if (holdingCapslock) { - currMods &= LWJGLGLFWKeycode.GLFW_MOD_CAPS_LOCK; - } if (holdingCtrl) { - currMods &= LWJGLGLFWKeycode.GLFW_MOD_CONTROL; - } if (holdingNumlock) { - currMods &= LWJGLGLFWKeycode.GLFW_MOD_NUM_LOCK; - } if (holdingShift) { - currMods &= LWJGLGLFWKeycode.GLFW_MOD_SHIFT; - } - return currMods; - } -// END launcher side - - public static void sendGrabbing(boolean grab, float xset, float yset) { - // sendData(ANDROID_TYPE_GRAB_STATE, Boolean.toString(grab)); - if (grab) { - UIKit.updateMCGuiScale(); +/* + if (isDebugEnabled) { + //try { + //debugEventStream = new PrintStream(new File(System.getProperty("user.dir"), "glfwstub_inputeventlog.txt")); + debugEventStream = System.out; + //} catch (FileNotFoundException e) { + // e.printStackTrace(); + //} } - - mouseX = xset; - mouseY = yset; - - GLFW.mGLFWIsGrabbing = grab; - nativeSetGrabbing(grab, xset, yset); + + //Quick and dirty: debul all key inputs to System.out +*/ } - - // Called from native code - public static void receiveCallback(int type, float i1, float i2, int i3, int i4) { - /* - if (INPUT_DEBUG_ENABLED) { - System.out.println("LWJGL GLFW Callback received type=" + Integer.toString(type) + ", data=" + i1 + ", " + i2 + ", " + i3 + ", " + i4); - } - */ - if (PENDING_EVENT_READY) { - if (type == EVENT_TYPE_CURSOR_POS) { - GLFW.mGLFWCursorX = (double) i1; - GLFW.mGLFWCursorY = (double) i2; - } else if (type == EVENT_TYPE_SCROLL) { - PENDING_EVENT_LIST.add(new Object[]{type, i1, i2, i3, i4}); - } else { - PENDING_EVENT_LIST.add(new Object[]{type, (int)i1, (int)i2, i3, i4}); - } - } // else System.out.println("Event input is not ready yet!"); + + + public static void sendData(int type, String data) { + nativeSendData(false, type, data); } - - // public static native void nativeSendData(boolean isAndroid, int type, String data); - public static boolean nativeSetInputReady(boolean ready) { - inputReady = ready; - return true; - } - - public static native String nativeClipboard(int action, String copy); - private static native void nativeSetGrabbing(boolean grab, float xset, float yset); - public static native void setClass(); + public static native void nativeSendData(boolean isAndroid, int type, String data); + public static native boolean nativeSetInputReady(boolean ready); + public static native String nativeClipboard(int action, byte[] copy); + public static native void nativeSetGrabbing(boolean grab); } - diff --git a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java index f24331a7..5e2ff69b 100644 --- a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java +++ b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java @@ -26,6 +26,8 @@ import static org.lwjgl.system.MemoryStack.*; import static org.lwjgl.system.MemoryUtil.*; import java.util.*; +import sun.misc.Unsafe; + public class GLFW { static FloatBuffer joystickData = (FloatBuffer)FloatBuffer.allocate(8).flip(); @@ -345,7 +347,7 @@ public class GLFW /** * The omni-directional resize cursor/move shape. - * + * *

This is usually either a combined horizontal and vertical double-headed arrow or a grabbing hand.

*/ public static final int GLFW_RESIZE_ALL_CURSOR = 0x36009; @@ -431,7 +433,7 @@ public class GLFW /** * Specifies whether to allow access to the window menu via the Alt+Space and Alt-and-then-Space keyboard shortcuts. - * + * *

This is ignored on other platforms.

*/ public static final int GLFW_WIN32_KEYBOARD_MENU = 0x25001; @@ -488,43 +490,46 @@ public class GLFW /* volatile */ public static GLFWWindowRefreshCallback mGLFWWindowRefreshCallback; /* volatile */ public static GLFWWindowSizeCallback mGLFWWindowSizeCallback; - volatile public static double mGLFWCursorX, mGLFWCursorY, mGLFWCursorLastX, mGLFWCursorLastY; - + volatile public static int mGLFWWindowWidth, mGLFWWindowHeight; + private static GLFWGammaRamp mGLFWGammaRamp; private static Map mGLFWKeyCodes; private static GLFWVidMode mGLFWVideoMode; private static long mGLFWWindowMonitor; - - private static double mGLFWInitialTime; - - private static ArrayMap mGLFWWindowMap; - public static boolean mGLFWIsGrabbing, mGLFWIsInputReady, mGLFWIsUseStackQueue = false; - public static final byte[] keyDownBuffer = new byte[317]; + private static double mGLFWInitialTime; + + private static ArrayMap mGLFWWindowMap; + public static boolean mGLFWIsInputReady; + public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317); + private static final String PROP_WINDOW_WIDTH = "glfwstub.windowWidth"; + private static final String PROP_WINDOW_HEIGHT= "glfwstub.windowHeight"; public static long mainContext = 0; + static { try { System.load(System.getenv("BUNDLE_PATH") + "/PojavLauncher"); } catch (UnsatisfiedLinkError e) { e.printStackTrace(); } + mGLFWWindowWidth = Tools.mGLFWWindowWidth; + mGLFWWindowHeight = Tools.mGLFWWindowHeight; // Minecraft triggers a glfwPollEvents() on splash screen, so update window size there. - // note: these calls are required, otherwise mouse input will break - CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight, 0, 0); - CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_WINDOW_SIZE, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight, 0, 0); + // CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE, mGLFWWindowWidth, mGLFWWindowHeight, 0, 0); + // CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_WINDOW_SIZE, mGLFWWindowWidth, mGLFWWindowHeight, 0, 0); mGLFWErrorCallback = GLFWErrorCallback.createPrint(); mGLFWKeyCodes = new ArrayMap<>(); - - mGLFWWindowMap = new ArrayMap<>(); - - mGLFWVideoMode = new GLFWVidMode(ByteBuffer.allocateDirect(GLFWVidMode.SIZEOF)); - internalChangeMonitorSize(Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight); - memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.REDBITS, 8); - memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.GREENBITS, 8); - memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.BLUEBITS, 8); + mGLFWWindowMap = new ArrayMap<>(); + + mGLFWVideoMode = new GLFWVidMode(ByteBuffer.allocateDirect(GLFWVidMode.SIZEOF)); + memPutInt(mGLFWVideoMode.address() + mGLFWVideoMode.WIDTH, mGLFWWindowWidth); + memPutInt(mGLFWVideoMode.address() + mGLFWVideoMode.HEIGHT, mGLFWWindowHeight); + memPutInt(mGLFWVideoMode.address() + mGLFWVideoMode.REDBITS, 8); + memPutInt(mGLFWVideoMode.address() + mGLFWVideoMode.GREENBITS, 8); + memPutInt(mGLFWVideoMode.address() + mGLFWVideoMode.BLUEBITS, 8); memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.REFRESHRATE, Integer.parseInt(System.getProperty("UIScreen.maximumFramesPerSecond"))); // A way to generate key code names @@ -533,9 +538,9 @@ public class GLFW for (Field thisField : thisFieldArr) { if (thisField.getName().startsWith("GLFW_KEY_")) { mGLFWKeyCodes.put( - (int) thisField.get(null), - thisField.getName().substring(9, 10).toUpperCase() + - thisField.getName().substring(10).replace("_", " ").toLowerCase() + (int) thisField.get(null), + thisField.getName().substring(9, 10).toUpperCase() + + thisField.getName().substring(10).replace("_", " ").toLowerCase() ); } } @@ -552,11 +557,10 @@ public class GLFW private static native long nglfwSetKeyCallback(long window, long ptr); private static native long nglfwSetMouseButtonCallback(long window, long ptr); private static native long nglfwSetScrollCallback(long window, long ptr); - private static native long nglfwSetWindowPosCallback(long window, long ptr); private static native long nglfwSetWindowSizeCallback(long window, long ptr); // private static native void nglfwSetInputReady(); private static native void nglfwSetShowingWindow(long window); - + /* private static void priGlfwSetError(int error) { mGLFW_currentError = error; @@ -583,43 +587,40 @@ public class GLFW /** Function address. */ public static final long - Init = apiGetFunctionAddress(GLFW, "pojavInit"), - CreateContext = apiGetFunctionAddress(GLFW, "pojavCreateContext"), - GetCurrentContext = apiGetFunctionAddress(GLFW, "pojavGetCurrentContext"), - //DetachOnCurrentThread = apiGetFunctionAddress(GLFW, "pojavDetachOnCurrentThread"), - MakeContextCurrent = apiGetFunctionAddress(GLFW, "pojavMakeCurrent"), - Terminate = apiGetFunctionAddress(GLFW, "pojavTerminate"), - SetWindowHint = apiGetFunctionAddress(GLFW, "pojavSetWindowHint"), - SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"), - SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"); + Init = apiGetFunctionAddress(GLFW, "pojavInit"), + CreateContext = apiGetFunctionAddress(GLFW, "pojavCreateContext"), + GetCurrentContext = apiGetFunctionAddress(GLFW, "pojavGetCurrentContext"), + //DetachOnCurrentThread = apiGetFunctionAddress(GLFW, "pojavDetachOnCurrentThread"), + MakeContextCurrent = apiGetFunctionAddress(GLFW, "pojavMakeCurrent"), + Terminate = apiGetFunctionAddress(GLFW, "pojavTerminate"), + SetWindowHint = apiGetFunctionAddress(GLFW, "pojavSetWindowHint"), + SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"), + SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"), + PumpEvents = apiGetFunctionAddress(GLFW, "pojavPumpEvents"), + RewindEvents = apiGetFunctionAddress(GLFW, "pojavRewindEvents"); } public static SharedLibrary getLibrary() { return GLFW; } - + public static void internalChangeMonitorSize(int width, int height) { - Tools.mGLFWWindowWidth = width; - Tools.mGLFWWindowHeight = height; - memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.WIDTH, Tools.mGLFWWindowWidth); - memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.HEIGHT, Tools.mGLFWWindowHeight); + mGLFWWindowWidth = width; + mGLFWWindowHeight = height; + if (mGLFWVideoMode == null) return; + memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.WIDTH, mGLFWWindowWidth); + memPutInt(mGLFWVideoMode.address() + (long) mGLFWVideoMode.HEIGHT, mGLFWWindowHeight); } - + public static GLFWWindowProperties internalGetWindow(long window) { GLFWWindowProperties win = mGLFWWindowMap.get(window); if (win == null) { - System.err.println("GLFW: No window pointer found: " + window); - win = mGLFWWindowMap.get(mainContext); - // throw new IllegalArgumentException("No window pointer found: " + window); - } - if (win == null) { - System.err.println("GLFW: Stills no window pointer found: " + window); - win = mGLFWWindowMap.valueAt(0); + throw new IllegalArgumentException("No window pointer found: " + window); } return win; } -// Generated stub callback methods + // Generated stub callback methods public static GLFWCharCallback glfwSetCharCallback(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("GLFWcharfun") GLFWCharCallbackI cbfun) { GLFWCharCallback lastCallback = mGLFWCharCallback; if (cbfun == null) mGLFWCharCallback = null; @@ -651,7 +652,7 @@ public class GLFW return lastCallback; } - + public static GLFWDropCallback glfwSetDropCallback(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("GLFWdropfun") GLFWDropCallbackI cbfun) { GLFWDropCallback lastCallback = mGLFWDropCallback; if (cbfun == null) mGLFWDropCallback = null; @@ -792,7 +793,7 @@ public class GLFW public static void glfwTerminate() { mGLFWIsInputReady = false; CallbackBridge.nativeSetInputReady(false); - + long __functionAddress = Functions.Terminate; invokeV(__functionAddress); } @@ -847,21 +848,18 @@ public class GLFW xpos.put(0); ypos.put(0); - width.put(Tools.mGLFWWindowWidth); - height.put(Tools.mGLFWWindowHeight); + width.put(mGLFWWindowWidth); + height.put(mGLFWWindowHeight); } @NativeType("GLFWmonitor *") public static long glfwGetWindowMonitor(@NativeType("GLFWwindow *") long window) { - return internalGetWindow(window).monitor; + return mGLFWWindowMonitor; } public static void glfwSetWindowMonitor(@NativeType("GLFWwindow *") long window, @NativeType("GLFWmonitor *") long monitor, int xpos, int ypos, int width, int height, int refreshRate) { - GLFWWindowProperties properties = internalGetWindow(window); - properties.monitor = monitor; - properties.x = xpos; - properties.y = ypos; - internalChangeMonitorSize(width, height); + // weird calculation to fake pointer + mGLFWWindowMonitor = window * monitor; } public static int glfwGetWindowAttrib(@NativeType("GLFWwindow *") long window, int attrib) { @@ -878,7 +876,7 @@ public class GLFW checkSafe(minor, 1); checkSafe(rev, 1); } - + major.put(GLFW_VERSION_MAJOR); minor.put(GLFW_VERSION_MINOR); rev.put(GLFW_VERSION_REVISION); @@ -895,12 +893,13 @@ public class GLFW @Nullable @NativeType("GLFWvidmode const *") public static GLFWVidMode.Buffer glfwGetVideoModes(@NativeType("GLFWmonitor *") long monitor) { - MemoryStack stack = stackGet(); - int stackPointer = stack.getPointer(); + MemoryStack stack = stackGet(); int stackPointer = stack.getPointer(); try { // long __result = nglfwGetVideoModes(monitor, memAddress(count)); long __result = glfwGetVideoMode(monitor).address(); - return GLFWVidMode.createSafe(__result, 1); + GLFWVidMode.Buffer buffer = GLFWVidMode.createSafe(__result, 1); + buffer.put(glfwGetVideoMode(monitor)); + return buffer; } finally { stack.setPointer(stackPointer); } @@ -939,34 +938,35 @@ public class GLFW // System.out.println("glfwGetTime"); return (System.nanoTime() - mGLFWInitialTime) / 1.e9; } - + public static void glfwSetTime(double time) { mGLFWInitialTime = System.nanoTime() - (long) time; } - + public static long glfwGetTimerValue() { return System.currentTimeMillis(); } - + public static long glfwGetTimerFrequency() { // FIXME set correct value!! return 60; } - + // GLFW Window functions public static long nglfwCreateContext(long share) { return invokePP(share, Functions.CreateContext); } public static long glfwCreateWindow(int width, int height, CharSequence title, long monitor, long share) { EventLoop.OffScreen.check(); - // Create an ACTUAL EGL context + // Create an ACTUAL EGL context long ptr = nglfwCreateContext(share); //nativeEglMakeCurrent(ptr); GLFWWindowProperties win = new GLFWWindowProperties(); + // win.width = width; + // win.height = height; - win.width = width; - win.height = height; - + win.width = mGLFWWindowWidth; + win.height = mGLFWWindowHeight; win.title = title; win.windowAttribs.put(GLFW_HOVERED, 1); @@ -980,8 +980,13 @@ public class GLFW public static void glfwDestroyWindow(long window) { // Check window exists - internalGetWindow(window); - mGLFWWindowMap.remove(window); + try { + internalGetWindow(window); + mGLFWWindowMap.remove(window); + } catch (IllegalArgumentException e) { + System.out.println("GLFW: Warning: failed to remove window " + window); + e.printStackTrace(); + } nglfwSetShowingWindow(mGLFWWindowMap.size() == 0 ? 0 : mGLFWWindowMap.keyAt(mGLFWWindowMap.size() - 1)); } @@ -998,21 +1003,15 @@ public class GLFW internalGetWindow(window).x = x; internalGetWindow(window).y = y; } - + public static void glfwSetWindowSize(long window, int width, int height) { - try { - internalChangeMonitorSize(width, height); - internalGetWindow(window).width = width; - internalGetWindow(window).height = height; - System.out.println("GLFW: Set size for window " + window + ", width=" + width + ", height=" + height); - } catch (Throwable th) { - System.err.println("Unable to set window size for window " + window); - th.printStackTrace(); - } + internalGetWindow(window).width = width; + internalGetWindow(window).height = height; + + System.out.println("GLFW: Set size for window " + window + ", width=" + width + ", height=" + height); } public static void glfwShowWindow(long window) { - System.out.println("GLFW: Showing window " + window + ", " + internalGetWindow(window).toString()); nglfwSetShowingWindow(window); } public static void glfwWindowHint(int hint, int value) { @@ -1030,91 +1029,33 @@ public class GLFW public static void glfwSetWindowShouldClose(long window, boolean close) { internalGetWindow(window).shouldClose = close; } - + public static void glfwSetWindowTitle(@NativeType("GLFWwindow *") long window, @NativeType("char const *") ByteBuffer title) { - + } public static void glfwSetWindowTitle(@NativeType("GLFWwindow *") long window, @NativeType("char const *") CharSequence title) { internalGetWindow(window).title = title; } - + public static void glfwSetWindowIcon(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("GLFWimage const *") GLFWImage.Buffer images) {} public static void glfwPollEvents() { if (!mGLFWIsInputReady) { mGLFWIsInputReady = true; - mGLFWIsUseStackQueue = CallbackBridge.nativeSetInputReady(true); + CallbackBridge.nativeSetInputReady(true); } - - if (!CallbackBridge.PENDING_EVENT_READY) { - CallbackBridge.PENDING_EVENT_READY = true; - // nglfwSetInputReady(); - } - - // Indirect event - while (CallbackBridge.PENDING_EVENT_LIST.size() > 0) { - Object[] dataArr = CallbackBridge.PENDING_EVENT_LIST.remove(0); - for (Long ptr : mGLFWWindowMap.keySet()) { - switch ((int)dataArr[0]) { - case CallbackBridge.EVENT_TYPE_CHAR: - if (mGLFWCharCallback != null) { - mGLFWCharCallback.invoke(ptr, (int)dataArr[1]); - } - break; - case CallbackBridge.EVENT_TYPE_CHAR_MODS: - if (mGLFWCharModsCallback != null) { - mGLFWCharModsCallback.invoke(ptr, (int)dataArr[1], (int)dataArr[2]); - } - break; - case CallbackBridge.EVENT_TYPE_CURSOR_ENTER: - if (mGLFWCursorEnterCallback != null) { - mGLFWCursorEnterCallback.invoke(ptr, (int)dataArr[1] == 1); - } - break; - case CallbackBridge.EVENT_TYPE_KEY: - if (mGLFWKeyCallback != null) { - keyDownBuffer[Math.max(0, (int)dataArr[1]-31)]=(byte)(int)dataArr[3]; - mGLFWKeyCallback.invoke(ptr, (int)dataArr[1], (int)dataArr[2], (int)dataArr[3], (int)dataArr[4]); - } - break; - case CallbackBridge.EVENT_TYPE_MOUSE_BUTTON: - if (mGLFWMouseButtonCallback != null) { - mGLFWMouseButtonCallback.invoke(ptr, (int)dataArr[1], (int)dataArr[2], (int)dataArr[3]); - } - break; - case CallbackBridge.EVENT_TYPE_SCROLL: - if (mGLFWScrollCallback != null) { - mGLFWScrollCallback.invoke(ptr, (float)dataArr[1], (float)dataArr[2]); - } - break; - case CallbackBridge.EVENT_TYPE_WINDOW_POS: - glfwSetWindowPos(ptr, (int)dataArr[1], (int)dataArr[2]); - break; - case CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE: - case CallbackBridge.EVENT_TYPE_WINDOW_SIZE: - glfwSetWindowSize(ptr, (int)dataArr[1], (int)dataArr[2]); - if ((int)dataArr[0] == CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE && mGLFWFramebufferSizeCallback != null) { - mGLFWFramebufferSizeCallback.invoke(ptr, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight); - } else if ((int)dataArr[0] == CallbackBridge.EVENT_TYPE_WINDOW_SIZE && mGLFWWindowSizeCallback != null) { - mGLFWWindowSizeCallback.invoke(ptr, Tools.mGLFWWindowWidth, Tools.mGLFWWindowHeight); - } - break; - default: - System.err.println("GLFWEvent: unknown callback type " + (int)dataArr[0]); - break; - } - } - } - - if ((mGLFWCursorX != mGLFWCursorLastX || mGLFWCursorY != mGLFWCursorLastY) && mGLFWCursorPosCallback != null) { - mGLFWCursorLastX = mGLFWCursorX; - mGLFWCursorLastY = mGLFWCursorY; - for (Long ptr : mGLFWWindowMap.keySet()) { - mGLFWCursorPosCallback.invoke(ptr, mGLFWCursorX, mGLFWCursorY); - } - //System.out.println("CursorPos updated to x=" + mGLFWCursorX + ",y=" + mGLFWCursorY); + for (Long ptr : mGLFWWindowMap.keySet()) callJV(ptr, Functions.PumpEvents); + callV(Functions.RewindEvents); + } + + public static void internalWindowSizeChanged(long window, int w, int h) { + try { + internalChangeMonitorSize(w, h); + glfwSetWindowSize(window, mGLFWWindowWidth, mGLFWWindowHeight); + }catch (Exception e) { + e.printStackTrace(); } } @@ -1123,12 +1064,12 @@ public class GLFW public static void glfwWaitEventsTimeout(double timeout) { // Boardwalk: this isn't how you do a frame limiter, but oh well // System.out.println("Frame limiter"); - + /* try { Thread.sleep((long)(timeout * 1000)); } catch (InterruptedException ie) { } - + */ // System.out.println("Out of the frame limiter"); } @@ -1143,12 +1084,13 @@ public class GLFW if (mode == GLFW_CURSOR) { switch (value) { case GLFW_CURSOR_DISABLED: - CallbackBridge.sendGrabbing(true, (int) mGLFWCursorX, (int) mGLFWCursorY); + net.kdt.pojavlaunch.uikit.UIKit.updateMCGuiScale(); + CallbackBridge.nativeSetGrabbing(true); break; - default: CallbackBridge.sendGrabbing(false, (int) mGLFWCursorX, (int) mGLFWCursorY); + default: CallbackBridge.nativeSetGrabbing(false); } } - + internalGetWindow(window).inputModes.put(mode, value); } public static String glfwGetKeyName(int key, int scancode) { @@ -1161,30 +1103,31 @@ public class GLFW } public static int glfwGetKey(@NativeType("GLFWwindow *") long window, int key) { - return keyDownBuffer[Math.max(0, key-31)]; + return keyDownBuffer.get(Math.max(0, key-31)); } public static int glfwGetMouseButton(@NativeType("GLFWwindow *") long window, int button) { return 0; } - public static void glfwGetCursorPos(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("double *") DoubleBuffer xpos, @Nullable @NativeType("double *") DoubleBuffer ypos) { if (CHECKS) { checkSafe(xpos, 1); checkSafe(ypos, 1); } - - xpos.put(mGLFWCursorX); - ypos.put(mGLFWCursorY); + nglfwGetCursorPos(window, xpos, ypos); } - - public static void glfwSetCursorPos(@NativeType("GLFWwindow *") long window, double xpos, double ypos) { + + + public static native void nglfwGetCursorPos(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("double *") DoubleBuffer xpos, @Nullable @NativeType("double *") DoubleBuffer ypos); + public static native void nglfwGetCursorPosA(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("double *") double[] xpos, @Nullable @NativeType("double *") double[] ypos); + + public static native void glfwSetCursorPos(@NativeType("GLFWwindow *") long window, double xpos, double ypos); /*{ mGLFWCursorX = mGLFWCursorLastX = xpos; mGLFWCursorY = mGLFWCursorLastY = ypos; - + CallbackBridge.sendGrabbing(mGLFWIsGrabbing, (int) xpos, (int) ypos); - } - + }*/ + public static long glfwCreateCursor(@NativeType("const GLFWimage *") GLFWImage image, int xhot, int yhot) { return 4L; } @@ -1193,20 +1136,22 @@ public class GLFW } public static void glfwDestroyCursor(@NativeType("GLFWcursor *") long cursor) {} public static void glfwSetCursor(@NativeType("GLFWwindow *") long window, @NativeType("GLFWcursor *") long cursor) {} - + public static boolean glfwRawMouseMotionSupported() { // Should be not supported? return false; } - + public static void glfwSetClipboardString(@NativeType("GLFWwindow *") long window, @NativeType("char const *") ByteBuffer string) { - glfwSetClipboardString(window, memUTF8Safe(string)); + byte[] arr = new byte[string.remaining()]; + string.get(arr); + CallbackBridge.nativeClipboard(CallbackBridge.CLIPBOARD_COPY, arr); } public static void glfwSetClipboardString(@NativeType("GLFWwindow *") long window, @NativeType("char const *") CharSequence string) { - CallbackBridge.nativeClipboard(CallbackBridge.CLIPBOARD_COPY, string.toString()); + glfwSetClipboardString(window, memUTF8Safe(string)); } - + public static String glfwGetClipboardString(@NativeType("GLFWwindow *") long window) { return CallbackBridge.nativeClipboard(CallbackBridge.CLIPBOARD_PASTE, null); } @@ -1252,7 +1197,7 @@ public class GLFW } public static boolean glfwUpdateGamepadMappings(ByteBuffer string) { -return false; + return false; } public static String glfwGetGamepadName(int jid) { return null; @@ -1296,8 +1241,8 @@ return false; xpos[0] = 0; ypos[0] = 0; - width[0] = Tools.mGLFWWindowWidth; - height[0] = Tools.mGLFWWindowHeight; + width[0] = mGLFWWindowWidth; + height[0] = mGLFWWindowHeight; } /** Array version of: {@link #glfwGetMonitorPhysicalSize GetMonitorPhysicalSize} */ @@ -1305,7 +1250,7 @@ return false; public static void glfwGetMonitorPhysicalSize(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("int *") int[] widthMM, @Nullable @NativeType("int *") int[] heightMM) { long __functionAddress = Functions.GetMonitorPhysicalSize; if (CHECKS) { - check(monitor); + // check(monitor); checkSafe(widthMM, 1); checkSafe(heightMM, 1); } @@ -1318,7 +1263,7 @@ return false; public static void glfwGetMonitorContentScale(@NativeType("GLFWmonitor *") long monitor, @Nullable @NativeType("float *") float[] xscale, @Nullable @NativeType("float *") float[] yscale) { long __functionAddress = Functions.GetMonitorContentScale; if (CHECKS) { - check(monitor); + // check(monitor); checkSafe(xscale, 1); checkSafe(yscale, 1); } @@ -1378,7 +1323,7 @@ return false; public static void glfwGetWindowContentScale(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("float *") float[] xscale, @Nullable @NativeType("float *") float[] yscale) { long __functionAddress = Functions.GetWindowContentScale; if (CHECKS) { - check(window); + // check(window); checkSafe(xscale, 1); checkSafe(yscale, 1); } @@ -1393,8 +1338,7 @@ return false; checkSafe(xpos, 1); checkSafe(ypos, 1); } - xpos[0] = mGLFWCursorX; - ypos[0] = mGLFWCursorY; + nglfwGetCursorPosA(window, xpos, ypos); } @NativeType("int") diff --git a/Natives/JavaGUIViewController.m b/Natives/JavaGUIViewController.m index 02705c09..76a884e5 100644 --- a/Natives/JavaGUIViewController.m +++ b/Natives/JavaGUIViewController.m @@ -191,6 +191,7 @@ const void * _CGDataProviderGetBytePointerCallbackAWT(void *info) { rgbArray = calloc(4, (size_t) (windowWidth * windowHeight)); + setenv("POJAV_SKIP_JNI_GLFW", "1", 1); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ launchJVM(nil, self.filepath, windowWidth, windowHeight, 8); }); diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index 8cdcdb4d..50675e61 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -489,12 +489,12 @@ BOOL slideableHotbar; virtualMouseFrame.origin.y = clamp(virtualMouseFrame.origin.y, 0, self.surfaceView.frame.size.height); lastVirtualMousePoint = location; self.mousePointerView.frame = virtualMouseFrame; - callback_SurfaceViewController_onTouch(event, virtualMouseFrame.origin.x * screenScale, virtualMouseFrame.origin.y * screenScale); + CallbackBridge_nativeSendCursorPos(event, virtualMouseFrame.origin.x * screenScale, virtualMouseFrame.origin.y * screenScale); return; } lastVirtualMousePoint = location; } - callback_SurfaceViewController_onTouch(event, location.x * screenScale, location.y * screenScale); + CallbackBridge_nativeSendCursorPos(event, location.x * screenScale, location.y * screenScale); } #pragma mark - Input: on-surface functions @@ -547,7 +547,7 @@ BOOL slideableHotbar; if (touchEvent == self.primaryTouch) { if ([self isTouchInactive:self.primaryTouch]) return; // FIXME: should be? ACTION_UP will never be sent - if (event == ACTION_MOVE) { + if (event == ACTION_MOVE && isGrabbing) { event = ACTION_MOVE_MOTION; CGPoint prevLocationInView = [touchEvent previousLocationInView:self.rootView]; locationInView.x -= prevLocationInView.x; diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index e13e4ca3..87d0dee2 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -75,8 +75,6 @@ void* egl_make_current(void* window); #define RENDERER_VIRGL 3 #define RENDERER_VULKAN 4 -int config_renderer; - typedef jint RegalMakeCurrent_func(EGLContext context); // Called from JNI_OnLoad of liblwjgl_opengl, TODO: check if unused diff --git a/Natives/environ.h b/Natives/environ.h new file mode 100644 index 00000000..bb3a9a8b --- /dev/null +++ b/Natives/environ.h @@ -0,0 +1,75 @@ +// +// Created by maks on 24.09.2022. +// + +#ifndef POJAVLAUNCHER_ENVIRON_H +#define POJAVLAUNCHER_ENVIRON_H + +#include +#include "jni.h" + +typedef struct { + short type; + short i1; + short i2; + short i3; + short i4; +} GLFWInputEvent; + +typedef void GLFW_invoke_Char_func(void* window, unsigned int codepoint); +typedef void GLFW_invoke_CharMods_func(void* window, unsigned int codepoint, int mods); +typedef void GLFW_invoke_CursorEnter_func(void* window, int entered); +typedef void GLFW_invoke_CursorPos_func(void* window, double xpos, double ypos); +typedef void GLFW_invoke_FramebufferSize_func(void* window, int width, int height); +typedef void GLFW_invoke_Key_func(void* window, int key, int scancode, int action, int mods); +typedef void GLFW_invoke_MouseButton_func(void* window, int button, int action, int mods); +typedef void GLFW_invoke_Scroll_func(void* window, double xoffset, double yoffset); +typedef void GLFW_invoke_WindowPos_func(void* window, int x, int y); +typedef void GLFW_invoke_WindowSize_func(void* window, int width, int height); + +//struct pojav_environ_s { + //struct ANativeWindow* pojavWindow; + //render_window_t* mainWindowBundle; + int config_renderer; + //BOOL force_vsync; + atomic_size_t eventCounter; + GLFWInputEvent events[8000]; + double cursorX, cursorY, cLastX, cLastY; + //jmethodID method_accessAndroidClipboard; + //jmethodID method_onGrabStateChanged; + jmethodID method_glfwSetWindowAttrib; + jmethodID method_internalWindowSizeChanged; + jclass bridgeClazz; + jclass vmGlfwClass; + jboolean isGrabbing; + jbyte* keyDownBuffer; + JavaVM* runtimeJavaVMPtr; + JNIEnv* runtimeJNIEnvPtr; + //JavaVM* dalvikJavaVMPtr; + //JNIEnv* dalvikJNIEnvPtr_ANDROID; + long showingWindow; + bool isInputReady, isCursorEntered, isUseStackQueueCall; + //int savedWidth, savedHeight; + int windowWidth, windowHeight; + int physicalWidth, physicalHeight; +#define ADD_CALLBACK_WWIN(NAME) \ + GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME; + ADD_CALLBACK_WWIN(Char); + ADD_CALLBACK_WWIN(CharMods); + ADD_CALLBACK_WWIN(CursorEnter); + ADD_CALLBACK_WWIN(CursorPos); + ADD_CALLBACK_WWIN(FramebufferSize); + ADD_CALLBACK_WWIN(Key); + ADD_CALLBACK_WWIN(MouseButton); + ADD_CALLBACK_WWIN(Scroll); + ADD_CALLBACK_WWIN(WindowPos); + ADD_CALLBACK_WWIN(WindowSize); + +#undef ADD_CALLBACK_WWIN +//}; + +float resolutionScale; +BOOL virtualMouseEnabled; +BOOL isControlModifiable; + +#endif //POJAVLAUNCHER_ENVIRON_H diff --git a/Natives/input_bridge_v3.m b/Natives/input_bridge_v3.m index e4dee6bf..08a94a90 100644 --- a/Natives/input_bridge_v3.m +++ b/Natives/input_bridge_v3.m @@ -5,9 +5,6 @@ * - Active development * - Works with some bugs: * + Modded versions gives broken stuff.. - * - * TODO: - * - Implements glfwSetCursorPos() to handle grab camera pos correctly. */ #import @@ -18,6 +15,7 @@ #include #include #include +#include #include "jni.h" #include "glfw_keycodes.h" @@ -28,25 +26,6 @@ jint (*orig_ProcessImpl_forkAndExec)(JNIEnv *env, jobject process, jint mode, jbyteArray helperpath, jbyteArray prog, jbyteArray argBlock, jint argc, jbyteArray envBlock, jint envc, jbyteArray dir, jintArray std_fds, jboolean redirectErrorStream); -typedef void GLFW_invoke_Char_func(void* window, unsigned int codepoint); -typedef void GLFW_invoke_CharMods_func(void* window, unsigned int codepoint, int mods); -typedef void GLFW_invoke_CursorEnter_func(void* window, int entered); -typedef void GLFW_invoke_CursorPos_func(void* window, double xpos, double ypos); -typedef void GLFW_invoke_FramebufferSize_func(void* window, int width, int height); -typedef void GLFW_invoke_Key_func(void* window, int key, int scancode, int action, int mods); -typedef void GLFW_invoke_MouseButton_func(void* window, int button, int action, int mods); -typedef void GLFW_invoke_Scroll_func(void* window, double xoffset, double yoffset); -typedef void GLFW_invoke_WindowSize_func(void* window, int width, int height); -typedef void GLFW_invoke_WindowPos_func(void* window, int x, int y); - -CGFloat grabCursorX, grabCursorY, lastCursorX, lastCursorY; - -jclass inputBridgeClass_ANDROID; -jmethodID inputBridgeMethod_ANDROID; - -jclass uikitBridgeClass; -jmethodID uikitBridgeTouchMethod; - NSString* processPath(NSString* path) { if ([path hasPrefix:@"file:"]) { path = [path substringFromIndex:5].stringByRemovingPercentEncoding.stringByResolvingSymlinksInPath; @@ -110,28 +89,57 @@ hooked_ProcessImpl_forkAndExec(JNIEnv *env, jobject process, jint mode, jbyteArr return 0; } -void hookExec(JNIEnv *env) { +void hookExec() { jclass cls; orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_UNIXProcess_forkAndExec"); if (!orig_ProcessImpl_forkAndExec) { orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_ProcessImpl_forkAndExec"); - cls = (*env)->FindClass(env, "java/lang/ProcessImpl"); + cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "java/lang/ProcessImpl"); } else { - cls = (*env)->FindClass(env, "java/lang/UNIXProcess"); + cls = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "java/lang/UNIXProcess"); } JNINativeMethod methods[] = { {"forkAndExec", "(I[B[B[BI[BI[B[IZ)I", (void *)&hooked_ProcessImpl_forkAndExec} }; - (*env)->RegisterNatives(env, cls, methods, 1); + (*runtimeJNIEnvPtr)->RegisterNatives(runtimeJNIEnvPtr, cls, methods, 1); } // JNI_OnLoad +void JNI_OnLoadGLFW() { + vmGlfwClass = (*runtimeJNIEnvPtr)->NewGlobalRef(runtimeJNIEnvPtr, (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "org/lwjgl/glfw/GLFW")); + method_glfwSetWindowAttrib = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, vmGlfwClass, "glfwSetWindowAttrib", "(JII)V"); + method_internalWindowSizeChanged = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, vmGlfwClass, "internalWindowSizeChanged", "(JII)V"); + jfieldID field_keyDownBuffer = (*runtimeJNIEnvPtr)->GetStaticFieldID(runtimeJNIEnvPtr, vmGlfwClass, "keyDownBuffer", "Ljava/nio/ByteBuffer;"); + jobject keyDownBufferJ = (*runtimeJNIEnvPtr)->GetStaticObjectField(runtimeJNIEnvPtr, vmGlfwClass, field_keyDownBuffer); + keyDownBuffer = (*runtimeJNIEnvPtr)->GetDirectBufferAddress(runtimeJNIEnvPtr, keyDownBufferJ); +} +/* jint JNI_OnLoad(JavaVM* vm, void* reserved) { - JNIEnv *env; - (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4); - hookExec(env); - runtimeJavaVMPtr = vm; + + dispatch_async(dispatch_get_main_queue(), ^{ + (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL); + if (!getenv("POJAV_SKIP_JNI_GLFW")) { + JNI_OnLoadGLFW(); + } + hookExec(); + }); + + return JNI_VERSION_1_4; +} +*/ + +jint JNI_OnLoad(JavaVM* vm, void* reserved) { + runtimeJavaVMPtr = vm; + + (*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, (void **)&runtimeJNIEnvPtr, JNI_VERSION_1_4); + hookExec(); + if (getenv("POJAV_SKIP_JNI_GLFW")) { + runtimeJNIEnvPtr = nil; + } else { + JNI_OnLoadGLFW(); + } + return JNI_VERSION_1_4; } @@ -141,39 +149,106 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) { } #define ADD_CALLBACK_WWIN(NAME) \ -GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME; \ JNIEXPORT jlong JNICALL Java_org_lwjgl_glfw_GLFW_nglfwSet##NAME##Callback(JNIEnv * env, jclass cls, jlong window, jlong callbackptr) { \ void** oldCallback = (void**) &GLFW_invoke_##NAME; \ GLFW_invoke_##NAME = (GLFW_invoke_##NAME##_func*) (uintptr_t) callbackptr; \ return (jlong) (uintptr_t) *oldCallback; \ } -ADD_CALLBACK_WWIN(Char); -ADD_CALLBACK_WWIN(CharMods); -ADD_CALLBACK_WWIN(CursorEnter); -ADD_CALLBACK_WWIN(CursorPos); -ADD_CALLBACK_WWIN(FramebufferSize); -ADD_CALLBACK_WWIN(Key); -ADD_CALLBACK_WWIN(MouseButton); -ADD_CALLBACK_WWIN(Scroll); -ADD_CALLBACK_WWIN(WindowSize); -ADD_CALLBACK_WWIN(WindowPos); +ADD_CALLBACK_WWIN(Char) +ADD_CALLBACK_WWIN(CharMods) +ADD_CALLBACK_WWIN(CursorEnter) +ADD_CALLBACK_WWIN(CursorPos) +ADD_CALLBACK_WWIN(FramebufferSize) +ADD_CALLBACK_WWIN(Key) +ADD_CALLBACK_WWIN(MouseButton) +ADD_CALLBACK_WWIN(Scroll) +ADD_CALLBACK_WWIN(WindowPos) +ADD_CALLBACK_WWIN(WindowSize) #undef ADD_CALLBACK_WWIN -void sendData(int type, CGFloat i1, CGFloat i2, int i3, int i4) { - //NSDebugLog(@"Debug: Send data, jnienv.isNull=%d, bridgeClass.isNull=%d\n", runtimeJNIEnvPtr == NULL, inputBridgeClass_ANDROID == NULL); - if (runtimeJNIEnvPtr == NULL) { - (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL); +void handleFramebufferSizeJava(void* window, int w, int h) { + if(GLFW_invoke_CursorEnter)GLFW_invoke_CursorEnter(window, 1); + if(GLFW_invoke_WindowPos)GLFW_invoke_WindowPos(window, 0, 0); + (*runtimeJNIEnvPtr)->CallStaticVoidMethod(runtimeJNIEnvPtr, vmGlfwClass, method_internalWindowSizeChanged, (long)window, w, h); +} + +void pojavPumpEvents(void* window) { + //__android_log_print(ANDROID_LOG_INFO, "input_bridge_v3", "pojavPumpevents %d", eventCounter); + size_t counter = atomic_load_explicit(&eventCounter, memory_order_acquire); + if((cLastX != cursorX || cLastY != cursorY) && GLFW_invoke_CursorPos) { + cLastX = cursorX; + cLastY = cursorY; + if (isUseStackQueueCall) + GLFW_invoke_CursorPos(window, cursorX, cursorY); } - if(inputBridgeClass_ANDROID == NULL) return; - (*runtimeJNIEnvPtr)->CallStaticVoidMethod( - runtimeJNIEnvPtr, - inputBridgeClass_ANDROID, - inputBridgeMethod_ANDROID, - type, - (jfloat)i1, (jfloat)i2, i3, i4 - ); + for(size_t i = 0; i < counter; i++) { + GLFWInputEvent event = events[i]; + switch(event.type) { + case EVENT_TYPE_CHAR: + if(GLFW_invoke_Char) GLFW_invoke_Char(window, event.i1); + break; + case EVENT_TYPE_CHAR_MODS: + if(GLFW_invoke_CharMods) GLFW_invoke_CharMods(window, event.i1, event.i2); + break; + case EVENT_TYPE_KEY: + if(GLFW_invoke_Key) GLFW_invoke_Key(window, event.i1, event.i2, event.i3, event.i4); + break; + case EVENT_TYPE_MOUSE_BUTTON: + if(GLFW_invoke_MouseButton) GLFW_invoke_MouseButton(window, event.i1, event.i2, event.i3); + break; + case EVENT_TYPE_SCROLL: + if(GLFW_invoke_Scroll) GLFW_invoke_Scroll(window, event.i1, event.i2); + break; + case EVENT_TYPE_FRAMEBUFFER_SIZE: + handleFramebufferSizeJava(window, event.i1, event.i2); + if(GLFW_invoke_FramebufferSize) GLFW_invoke_FramebufferSize(window, event.i1, event.i2); + break; + case EVENT_TYPE_WINDOW_SIZE: + handleFramebufferSizeJava(window, event.i1, event.i2); + if(GLFW_invoke_WindowSize) GLFW_invoke_WindowSize(window, event.i1, event.i2); + break; + } + } + atomic_store_explicit(&eventCounter, counter, memory_order_release); +} +void pojavRewindEvents() { + atomic_store_explicit(&eventCounter, 0, memory_order_release); +} + +JNIEXPORT void JNICALL +Java_org_lwjgl_glfw_GLFW_nglfwGetCursorPos(JNIEnv *env, jclass clazz, jlong window, jobject xpos, + jobject ypos) { + *(double*)(*env)->GetDirectBufferAddress(env, xpos) = cursorX; + *(double*)(*env)->GetDirectBufferAddress(env, ypos) = cursorY; +} + +JNIEXPORT void JNICALL +Java_org_lwjgl_glfw_GLFW_nglfwGetCursorPosA(JNIEnv *env, jclass clazz, jlong window, + jdoubleArray xpos, jdoubleArray ypos) { + (*env)->SetDoubleArrayRegion(env, xpos, 0,1, &cursorX); + (*env)->SetDoubleArrayRegion(env, ypos, 0,1, &cursorY); +} + +JNIEXPORT void JNICALL +Java_org_lwjgl_glfw_GLFW_glfwSetCursorPos(JNIEnv *env, jclass clazz, jlong window, jdouble xpos, + jdouble ypos) { + cLastX = cursorX = xpos; + cLastY = cursorY = ypos; +} + +void sendData(short type, short i1, short i2, short i3, short i4) { + size_t counter = atomic_load_explicit(&eventCounter, memory_order_acquire); + if (counter < 7999) { + GLFWInputEvent *event = &events[counter++]; + event->type = type; + event->i1 = i1; + event->i2 = i2; + event->i3 = i3; + event->i4 = i4; + } + atomic_store_explicit(&eventCounter, counter, memory_order_release); } void closeGLFWWindow() { @@ -194,47 +269,6 @@ void closeGLFWWindow() { exit(-1); } -/* -void callback_SurfaceViewController_launchMinecraft(int width, int height) { - NSDebugLog(@"Received SurfaceViewController callback, width=%d, height=%d\n", width, height); - - // Because UI init after JVM init, this should not be null - assert(runtimeJNIEnvPtr != NULL); - - if (!uikitBridgeClass) { - uikitBridgeClass = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/kdt/pojavlaunch/uikit/UIKit"); - assert(uikitBridgeClass != NULL); - } - - jstring rendererLibStr = (*runtimeJNIEnvPtr)->NewStringUTF(runtimeJNIEnvPtr, getenv("POJAV_RENDERER")); - - jmethodID method = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, uikitBridgeClass, "callback_SurfaceViewController_launchMinecraft", "(IILjava/lang/String;)V"); - assert(method != NULL); - - (*runtimeJNIEnvPtr)->CallStaticVoidMethod( - runtimeJNIEnvPtr, - uikitBridgeClass, method, - width, height, - rendererLibStr - ); -} -*/ - -void callback_SurfaceViewController_onTouch(int event, CGFloat x, CGFloat y) { - if (!isInputReady) return; - - if (!runtimeJNIEnvPtr) { - (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL); - } - - - (*runtimeJNIEnvPtr)->CallStaticVoidMethod( - runtimeJNIEnvPtr, - uikitBridgeClass, uikitBridgeTouchMethod, - event, (jfloat)x, (jfloat)y - ); -} - const int hotbarKeys[9] = { GLFW_KEY_1, GLFW_KEY_2, GLFW_KEY_3, GLFW_KEY_4, GLFW_KEY_5, GLFW_KEY_6, @@ -272,30 +306,26 @@ JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNI JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetInputReady(JNIEnv* env, jclass clazz, jboolean inputReady) { //NSDebugLog(@"Debug: Changing input state, isReady=%d, isUseStackQueueCall=%d\n", inputReady, isUseStackQueueCall); isInputReady = inputReady; + if (isUseStackQueueCall) { + sendData(EVENT_TYPE_FRAMEBUFFER_SIZE, windowWidth, windowHeight, 0, 0); + sendData(EVENT_TYPE_WINDOW_SIZE, windowWidth, windowHeight, 0, 0); + } return isUseStackQueueCall; } JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetGrabbing(JNIEnv* env, jclass clazz, jboolean grabbing, jfloat xset, jfloat yset) { isGrabbing = grabbing; - if (isGrabbing == JNI_TRUE) { - grabCursorX = xset; // savedWidth / 2; - grabCursorY = yset; // savedHeight / 2; - isPrepareGrabPos = true; - - CGRect screenBounds = [[UIScreen mainScreen] bounds]; - virtualMouseFrame.origin.x = screenBounds.size.width / 2; - virtualMouseFrame.origin.y = screenBounds.size.height / 2; - } dispatch_async(dispatch_get_main_queue(), ^{ - UIView *surfaceView = ((SurfaceViewController *)currentWindow().rootViewController).surfaceView; + SurfaceViewController *vc = ((SurfaceViewController *)currentWindow().rootViewController); + UIView *surfaceView = vc.surfaceView; if (isGrabbing == JNI_TRUE) { CGFloat screenScale = [[UIScreen mainScreen] scale] * resolutionScale; - callback_SurfaceViewController_onTouch(ACTION_DOWN, lastVirtualMousePoint.x * screenScale, lastVirtualMousePoint.y * screenScale); - ((SurfaceViewController *)currentWindow().rootViewController).mousePointerView.frame = virtualMouseFrame; + CallbackBridge_nativeSendCursorPos(ACTION_DOWN, lastVirtualMousePoint.x * screenScale, lastVirtualMousePoint.y * screenScale);//TODO + vc.mousePointerView.frame = virtualMouseFrame; } - ((SurfaceViewController *)currentWindow().rootViewController).scrollPanGesture.enabled = !isGrabbing; - ((SurfaceViewController *)currentWindow().rootViewController).mousePointerView.hidden = isGrabbing || !virtualMouseEnabled; + vc.scrollPanGesture.enabled = !isGrabbing; + vc.mousePointerView.hidden = isGrabbing || !virtualMouseEnabled; }); } @@ -334,46 +364,36 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendCursorEnter( } } */ -void CallbackBridge_nativeSendCursorPos(CGFloat x, CGFloat y) { - if (GLFW_invoke_CursorPos && isInputReady) { - if (!isCursorEntered) { - if (GLFW_invoke_CursorEnter) { - isCursorEntered = true; - if (isUseStackQueueCall) { - sendData(EVENT_TYPE_CURSOR_ENTER, 1, 0, 0, 0); - } else { - GLFW_invoke_CursorEnter((void*) showingWindow, 1); - } - } else if (isGrabbing) { - // Some Minecraft versions does not use GLFWCursorEnterCallback - // This is a smart check, as Minecraft will not in grab mode if already not. - isCursorEntered = true; +void CallbackBridge_nativeSendCursorPos(char event, CGFloat x, CGFloat y) { + if (!GLFW_invoke_CursorPos || !isInputReady) return; + + switch (event) { + case ACTION_DOWN: + case ACTION_UP: + if (!isGrabbing) { + cursorX = x; + cursorY = y; } - } - - if (isGrabbing) { - if (!isPrepareGrabPos) { - grabCursorX += x - lastCursorX; - grabCursorY += y - lastCursorY; + break; + + case ACTION_MOVE: + if (isGrabbing) { + cursorX += x - cLastX; + cursorY += y - cLastY; + } else { + cursorX = x; + cursorY = y; } - - lastCursorX = x; - lastCursorY = y; - - if (isPrepareGrabPos) { - isPrepareGrabPos = false; - return; - } - } - - if (!isUseStackQueueCall) { - GLFW_invoke_CursorPos((void*) showingWindow, (double) (x), (double) (y)); - } else { - sendData(EVENT_TYPE_CURSOR_POS, (isGrabbing ? grabCursorX : x), (isGrabbing ? grabCursorY : y), 0, 0); - } - - lastCursorX = x; - lastCursorY = y; + break; + + case ACTION_MOVE_MOTION: + cursorX += x; + cursorY += y; + break; + } + + if (!isUseStackQueueCall) { + GLFW_invoke_CursorPos((void*) showingWindow, (double) cursorX, (double) cursorY); } } @@ -409,6 +429,7 @@ char getKeyModifiers(int key, int action) { void CallbackBridge_nativeSendKey(int key, int scancode, int action, int mods) { if (GLFW_invoke_Key && isInputReady) { + keyDownBuffer[MAX(0, key-31)]=(jbyte)action; if (mods == 0) { mods = getKeyModifiers(key, action); } @@ -424,8 +445,6 @@ void CallbackBridge_nativeSendKey(int key, int scancode, int action, int mods) { void CallbackBridge_nativeSendMouseButton(int button, int action, int mods) { if (isInputReady) { if (button == -1) { - // Notify to prepare set new grab pos - isPrepareGrabPos = true; } else if (GLFW_invoke_MouseButton) { if (mods == 0) { mods = getKeyModifiers(0, action); @@ -474,16 +493,6 @@ void CallbackBridge_nativeSendScroll(CGFloat xoffset, CGFloat yoffset) { } } -void CallbackBridge_nativeSendWindowPos(int x, int y) { - if (GLFW_invoke_WindowPos && isInputReady) { - if (isUseStackQueueCall) { - sendData(EVENT_TYPE_WINDOW_POS, x, y, 0, 0); - } else { - GLFW_invoke_WindowPos((void*) showingWindow, x, y); - } - } -} - JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nglfwSetShowingWindow(JNIEnv* env, jclass clazz, jlong window) { showingWindow = (long) window; } @@ -495,27 +504,9 @@ void CallbackBridge_setWindowAttrib(int attrib, int value) { return; } - jclass glfwClazz = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "org/lwjgl/glfw/GLFW"); - assert(glfwClazz != NULL); - jmethodID glfwMethod = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, glfwClazz, "glfwSetWindowAttrib", "(JII)V"); - assert(glfwMethod != NULL); - (*runtimeJNIEnvPtr)->CallStaticVoidMethod( runtimeJNIEnvPtr, - glfwClazz, glfwMethod, + vmGlfwClass, method_glfwSetWindowAttrib, (jlong) showingWindow, attrib, value ); } - -JNIEXPORT void JNICALL -Java_org_lwjgl_glfw_CallbackBridge_setClass(JNIEnv *env, jclass clazz) { - inputBridgeMethod_ANDROID = (*env)->GetStaticMethodID(env, clazz, "receiveCallback", "(IFFII)V"); - assert(inputBridgeMethod_ANDROID != NULL); - inputBridgeClass_ANDROID = (*env)->NewGlobalRef(env, clazz); - assert(inputBridgeClass_ANDROID != NULL); - - uikitBridgeClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "net/kdt/pojavlaunch/uikit/UIKit")); - assert(uikitBridgeClass != NULL); - uikitBridgeTouchMethod = (*env)->GetStaticMethodID(env, uikitBridgeClass, "callback_SurfaceViewController_onTouch", "(IFF)V"); - assert(uikitBridgeTouchMethod != NULL); -} diff --git a/Natives/utils.h b/Natives/utils.h index 30a9ca76..38e12fe6 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -3,10 +3,11 @@ #import #include +#include "environ.h" #include "jni.h" // Remove date + time from NSLog, unneeded -#define NSLog(args...) customNSLog(__FILE__,__LINE__,__PRETTY_FUNCTION__,args); +#define NSLog(args...) customNSLog(__FILE__,__LINE__,__PRETTY_FUNCTION__,args); // Control button actions #define ACTION_DOWN 0 @@ -50,8 +51,6 @@ #define NSDebugLog(...) if (debugLogEnabled) { NSLog(__VA_ARGS__); } BOOL debugBoundsEnabled, debugLogEnabled; -JavaVM* runtimeJavaVMPtr; -JNIEnv* runtimeJNIEnvPtr; //__weak UIViewController *viewController; #define CS_DEBUGGED 0x10000000 @@ -59,15 +58,6 @@ int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize); BOOL isJITEnabled(BOOL checkCSOps); void* gbuffer; // OSMesa framebuffer -long showingWindow; -int windowWidth, windowHeight; -int physicalWidth, physicalHeight; -BOOL isInputReady, isCursorEntered, isPrepareGrabPos, isUseStackQueueCall; -jboolean isGrabbing; -BOOL virtualMouseEnabled; - -float resolutionScale; -BOOL isControlModifiable; // Init functions void init_hookFunctions(); @@ -97,21 +87,19 @@ void _CGDataProviderReleaseBytePointerCallback(void *info,const void *pointer); jboolean attachThread(bool isAndroid, JNIEnv** secondJNIEnvPtr); -void sendData(int type, CGFloat i1, CGFloat i2, int i3, int i4); +void sendData(short type, short i1, short i2, short i3, short i4); void closeGLFWWindow(); void callback_LauncherViewController_installMinecraft(); void callback_SurfaceViewController_launchMinecraft(int width, int height); -void callback_SurfaceViewController_onTouch(int event, CGFloat x, CGFloat y); int callback_SurfaceViewController_touchHotbar(CGFloat x, CGFloat y); BOOL CallbackBridge_nativeSendChar(jchar codepoint /* jint codepoint */); BOOL CallbackBridge_nativeSendCharMods(jchar codepoint, int mods); -void CallbackBridge_nativeSendCursorPos(CGFloat x, CGFloat y); +void CallbackBridge_nativeSendCursorPos(char event, CGFloat x, CGFloat y); void CallbackBridge_nativeSendKey(int key, int scancode, int action, int mods); void CallbackBridge_nativeSendMouseButton(int button, int action, int mods); void CallbackBridge_nativeSendScreenSize(int width, int height); void CallbackBridge_nativeSendScroll(CGFloat xoffset, CGFloat yoffset); -void CallbackBridge_nativeSendWindowPos(jint x, jint y); void CallbackBridge_sendKeycode(int keycode, jchar keychar, int scancode, int modifiers, BOOL isDown); void CallbackBridge_setWindowAttrib(int attrib, int value);