diff --git a/README.md b/README.md index ee02ce819..027e464de 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ scripts\languagelist_updater.bat - PojavLauncher is licensed under [GNU GPLv3](https://github.com/khanhduytran0/PojavLauncher/blob/master/LICENSE). ## Third party components and it's licenses -- [Boardwalk](https://github.com/zhuowei/Boardwalk) (JVM Launcher): [Apache License 2.0](https://github.com/zhuowei/Boardwalk/blob/master/LICENSE). +- [Boardwalk](https://github.com/zhuowei/Boardwalk) (JVM Launcher): Unknown License/[Apache License 2.0](https://github.com/zhuowei/Boardwalk/blob/master/LICENSE) or GNU GPLv2. - Android Support Libraries: [Apache License 2.0](https://android.googlesource.com/platform/prebuilts/maven_repo/android/+/master/NOTICE.txt). - [GL4ES](https://github.com/ptitSeb/gl4es): [MIT License](https://github.com/ptitSeb/gl4es/blob/master/LICENSE).
- [OpenJDK](https://github.com/PojavLauncherTeam/openjdk-multiarch-jdk8u): [GNU GPLv2 License](https://openjdk.java.net/legal/gplv2+ce.html).
diff --git a/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java b/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java index 6e306ff25..53a7d598d 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java +++ b/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java @@ -196,7 +196,7 @@ public class AndroidLWJGLKeycode { try { if ((int) keyEvent.getDisplayLabel() != KeyEvent.KEYCODE_UNKNOWN && !CallbackBridge.isGrabbing()) { - mainActivity.sendKeyPress(androidToLwjglMap.get(keyEvent.getKeyCode()), (char) keyEvent.getUnicodeChar(), mods, isDown); + mainActivity.sendKeyPress(androidToLwjglMap.get(keyEvent.getKeyCode()), (char) keyEvent.getUnicodeChar(), keyEvent.getScanCode(), mods, isDown); } } catch (Throwable th) { th.printStackTrace(); diff --git a/app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java b/app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java index 2d91c808f..b60381317 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/BaseMainActivity.java @@ -1065,16 +1065,20 @@ public class BaseMainActivity extends LoggableActivity { } public static void sendKeyPress(int keyCode, int modifiers, boolean status) { - sendKeyPress(keyCode, '\u0000', modifiers, status); + sendKeyPress(keyCode, 0, modifiers, status); + } + + public static void sendKeyPress(int keyCode, int scancode, int modifiers, boolean status) { + sendKeyPress(keyCode, '\u0000', scancode, modifiers, status); } - public static void sendKeyPress(int keyCode, char keyChar, int modifiers, boolean status) { - CallbackBridge.sendKeycode(keyCode, keyChar, modifiers, status); + public static void sendKeyPress(int keyCode, char keyChar, int scancode, int modifiers, boolean status) { + CallbackBridge.sendKeycode(keyCode, keyChar, scancode, modifiers, status); } public void sendKeyPress(char keyChar) { - sendKeyPress(0, keyChar, 0, true); - sendKeyPress(0, keyChar, 0, false); + sendKeyPress(0, keyChar, 0, 0, true); + sendKeyPress(0, keyChar, 0, 0, false); } public void sendKeyPress(int keyCode) { diff --git a/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java index a3606e578..88a9d4640 100644 --- a/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java +++ b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -45,12 +45,16 @@ public class CallbackBridge { sendMouseKeycode(-1, 0, false); } - public static void sendKeycode(int keycode, char keychar, int modifiers, boolean isDown) { + 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 /* scancode */, isDown ? 1 : 0, modifiers); + 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); } @@ -124,12 +128,14 @@ public class CallbackBridge { */ public static native boolean nativeAttachThreadToOther(boolean isAndroid, boolean isUsePushPoll); - private static native boolean nativeSendChar(char codepoint /* int codepoint */); + /* + private static native boolean nativeSendChar(char codepoint); // GLFW: GLFWCharModsCallback deprecated, but is Minecraft still use? - private static native boolean nativeSendCharMods(int codepoint, int mods); + private static native boolean nativeSendCharMods(char codepoint, int mods); + */ // private static native void nativeSendCursorEnter(int entered); private static native void nativeSendCursorPos(int x, int y); - private static native void nativeSendKey(int key, int scancode, int action, int mods); + private static native void nativeSendKeycode(int keycode, char keychar, int scancode, int action, int mods); private static native void nativeSendMouseButton(int button, int action, int mods); private static native void nativeSendScroll(double xoffset, double yoffset); private static native void nativeSendScreenSize(int width, int height); diff --git a/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java.z b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java.z new file mode 100644 index 000000000..726e78421 --- /dev/null +++ b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java.z @@ -0,0 +1,133 @@ +package org.lwjgl.glfw; +import java.io.*; +import java.util.*; +import android.widget.*; +import net.kdt.pojavlaunch.*; +import android.content.*; + +public abstract class CallbackBridge { + public static final int ANDROID_TYPE_GRAB_STATE = 0; + + public static final int CLIPBOARD_COPY = 2000; + public static final int CLIPBOARD_PASTE = 2001; + + public static volatile int windowWidth, windowHeight; + public static int mouseX, mouseY; + public static boolean mouseLeft; + public static StringBuilder DEBUG_STRING = new StringBuilder(); + + public static final CallbackBridge INSTANCE = new CallbackBridgeV3(); + + // volatile private static boolean isGrabbing = false; + + public void putMouseEventWithCoords(int button, int x, int y /* , int dz, long nanos */) { + putMouseEventWithCoords(button, 1, x, y); + putMouseEventWithCoords(button, 0, x, y); + } + + public void putMouseEventWithCoords(int button, int state, int x, int y /* , int dz, long nanos */) { + sendCursorPos(x, y); + sendMouseKeycode(button, 0, state == 1); + } + + private static boolean threadAttached; + public void sendCursorPos(int x, int y) { + if (!threadAttached) { + threadAttached = CallbackBridge.nativeAttachThreadToOther(true, BaseMainActivity.isInputStackCall); + } + + DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n"); + mouseX = x; + mouseY = y; + nativeSendCursorPos(x, y); + } + + public void sendPrepareGrabInitialPos() { + DEBUG_STRING.append("Prepare set grab initial posititon"); + sendMouseKeycode(-1, 0, false); + } + + public void sendKeycode(int keycode, char keychar, int modifiers, boolean isDown) { + DEBUG_STRING.append("KeyCode=" + keycode + ", Char=" + keychar); + // TODO CHECK: This may cause input issue, not receive input! +/* + if (!nativeSendCharMods(keychar, modifiers) || !nativeSendChar(keychar)) { + nativeSendKey(keycode, 0, isDown ? 1 : 0, modifiers); + } +*/ + + nativeSendKeycode(keycode, keychar, modifiers, isDown); + + // sendData(JRE_TYPE_KEYCODE_CONTROL, keycode, Character.toString(keychar), Boolean.toString(isDown), modifiers); + } + + public 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 void sendMouseKeycode(int keycode) { + sendMouseKeycode(keycode, 0, true); + sendMouseKeycode(keycode, 0, false); + } + + public void sendScroll(double xoffset, double yoffset) { + DEBUG_STRING.append("ScrollX=" + xoffset + ",ScrollY=" + yoffset); + nativeSendScroll(xoffset, yoffset); + } + + public void sendUpdateWindowSize(int w, int h) { + nativeSendScreenSize(w, h); + } + + public static boolean isGrabbing() { + // return isGrabbing; + return nativeIsGrabbing(); + } + + // Called from JRE side + public static String accessAndroidClipboard(int type, String copy) { + switch (type) { + case CLIPBOARD_COPY: + BaseMainActivity.GLOBAL_CLIPBOARD.setPrimaryClip(ClipData.newPlainText("Copy", copy)); + return null; + + case CLIPBOARD_PASTE: + if (BaseMainActivity.GLOBAL_CLIPBOARD.hasPrimaryClip() && BaseMainActivity.GLOBAL_CLIPBOARD.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { + return BaseMainActivity.GLOBAL_CLIPBOARD.getPrimaryClip().getItemAt(0).getText().toString(); + } else { + return ""; + } + + default: return null; + } + } + public void receiveCallback(int type, String data) { + switch (type) { + case ANDROID_TYPE_GRAB_STATE: + // isGrabbing = Boolean.parseBoolean(data); + break; + } + } + + public static native boolean nativeAttachThreadToOther(boolean isAndroid, boolean isUsePushPoll); + public static native boolean nativeIsGrabbing(); + + protected abstract boolean nativeSendChar(char codepoint /* int codepoint */); + // GLFW: GLFWCharModsCallback deprecated, but is Minecraft still use? + protected abstract boolean nativeSendCharMods(char codepoint, int mods); + // protected abstract void nativeSendCursorEnter(int entered); + protected abstract void nativeSendCursorPos(int x, int y); + protected abstract void nativeSendKey(int key, int scancode, int action, int mods); + protected abstract void nativeSendMouseButton(int button, int action, int mods); + protected abstract void nativeSendScroll(double xoffset, double yoffset); + protected abstract void nativeSendScreenSize(int width, int height); + + + + static { + System.loadLibrary("pojavexec"); + } +} + diff --git a/app/src/main/java/org/lwjgl/glfw/CallbackBridgeV1.java.z b/app/src/main/java/org/lwjgl/glfw/CallbackBridgeV1.java.z new file mode 100644 index 000000000..fe2129dc3 --- /dev/null +++ b/app/src/main/java/org/lwjgl/glfw/CallbackBridgeV1.java.z @@ -0,0 +1,66 @@ +package org.lwjgl.glfw; + +public class CallbackBridgeV1 extends CallbackBridge +{ + public static final int JRE_TYPE_CURSOR_POS = 0; + public static final int JRE_TYPE_CURSOR_BUTTON = 1; + public static final int JRE_TYPE_KEYCODE_CONTROL = 2; + public static final int JRE_TYPE_KEYCODE_CHAR = 3; + public static final int JRE_TYPE_MOUSE_KEYCODE_CONTROL = 4; + public static final int JRE_TYPE_WINDOW_SIZE = 5; + public static final int JRE_TYPE_GRAB_INITIAL_POS_UNSET = 6; + + public static final int ANDROID_TYPE_GRAB_STATE = 0; + + public void nativeSendCursorPos(int x, int y) { + DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n"); + mouseX = x; + mouseY = y; + sendData(JRE_TYPE_CURSOR_POS, x, y); + } + + public void nativeSendGrabInitialPosUnset() { + DEBUG_STRING.append("Grab initial posititon uset"); + sendData(JRE_TYPE_GRAB_INITIAL_POS_UNSET); + } + + public void nativeSendKeycode(int keycode, char keychar, int modifiers, boolean isDown) { + DEBUG_STRING.append("KeyCode=" + keycode + ", Char=" + keychar); + sendData(JRE_TYPE_KEYCODE_CONTROL, keycode, Character.toString(keychar), Boolean.toString(isDown), modifiers); + } + + @Override + public void nativeSendMouseButton(int keycode, int action, int modifiers) { + DEBUG_STRING.append("MouseKey=" + keycode + ", down=" + action + "\n"); + // if (isGrabbing()) DEBUG_STRING.append("MouseGrabStrace: " + android.util.Log.getStackTraceString(new Throwable()) + "\n"); + sendData(JRE_TYPE_MOUSE_KEYCODE_CONTROL, keycode, action == 1, modifiers); + } + + public void nativeSendMouseKeycode(int keycode) { + sendMouseKeycode(keycode, 0, true); + sendMouseKeycode(keycode, 0, false); + } + + @Override + public void nativeSendScreenSize(int w, int h) { + sendData(JRE_TYPE_WINDOW_SIZE, w, h); + } + + private static String currData; + public void sendData(int type, Object... dataArr) { + currData = ""; + for (int i = 0; i < dataArr.length; i++) { + if (dataArr[i] instanceof Integer) { + currData += Integer.toString((int) dataArr[i]); + } else if (dataArr[i] instanceof String) { + currData += (String) dataArr[i]; + } else { + currData += dataArr[i].toString(); + } + currData += (i + 1 < dataArr.length ? ":" : ""); + } + nativeSendData(type, currData); + } + + protected native void nativeSendData(int type, String data); +} diff --git a/app/src/main/java/org/lwjgl/glfw/CallbackBridgeV3.java.z b/app/src/main/java/org/lwjgl/glfw/CallbackBridgeV3.java.z new file mode 100644 index 000000000..c7ad31719 --- /dev/null +++ b/app/src/main/java/org/lwjgl/glfw/CallbackBridgeV3.java.z @@ -0,0 +1,15 @@ +package org.lwjgl.glfw; + +public class CallbackBridgeV3 extends CallbackBridge +{ + @Override protected native boolean nativeSendChar(char codepoint /* int codepoint */); + // GLFW: GLFWCharModsCallback deprecated, but is Minecraft still use? + @Override protected native boolean nativeSendCharMods(char codepoint, int mods); + // @Override protected native void nativeSendCursorEnter(int entered); + @Override protected native void nativeSendCursorPos(int x, int y); + @Override protected native void nativeSendKey(int key, int scancode, int action, int mods); + @Override protected native void nativeSendMouseButton(int button, int action, int mods); + @Override protected native void nativeSendScroll(double xoffset, double yoffset); + @Override protected native void nativeSendScreenSize(int width, int height); +} + diff --git a/app/src/main/jni/input_bridge_v3.c b/app/src/main/jni/input_bridge_v3.c index cedee29aa..2457ea0e9 100644 --- a/app/src/main/jni/input_bridge_v3.c +++ b/app/src/main/jni/input_bridge_v3.c @@ -23,6 +23,7 @@ #define EVENT_TYPE_MOUSE_BUTTON 1006 #define EVENT_TYPE_SCROLL 1007 #define EVENT_TYPE_WINDOW_SIZE 1008 +#define EVENT_TYPE_KEYCODE 1009 typedef void GLFW_invoke_Char_func(void* window, unsigned int codepoint); typedef void GLFW_invoke_CharMods_func(void* window, unsigned int codepoint, int mods); @@ -40,9 +41,6 @@ int grabCursorX, grabCursorY, lastCursorX, lastCursorY; jclass inputBridgeClass_ANDROID, inputBridgeClass_JRE; jmethodID inputBridgeMethod_ANDROID, inputBridgeMethod_JRE; -jclass lwjgl2KeyboardClass; -jmethodID lwjgl2KeyboardCharMethod; - jboolean isGrabbing; jint JNI_OnLoad(JavaVM* vm, void* reserved) { @@ -121,12 +119,15 @@ void getJavaInputBridge(jclass* clazz, jmethodID* method) { if (*method == NULL && runtimeJNIEnvPtr_ANDROID != NULL) { *clazz = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID, "org/lwjgl/glfw/CallbackBridge"); assert(*clazz != NULL); - *method = (*runtimeJNIEnvPtr_ANDROID)->GetStaticMethodID(runtimeJNIEnvPtr_ANDROID, *clazz, "receiveCallback", "(IIIII)V"); + *method = (*runtimeJNIEnvPtr_ANDROID)->GetStaticMethodID(runtimeJNIEnvPtr_ANDROID, *clazz, "receiveCallback", "(IIIIII)V"); assert(*method != NULL); } } void sendData(int type, int i1, int i2, int i3, int i4) { + sendData(type, i1, i2, i3, i4, 0); +} +void sendData(int type, int i1, int i2, int i3, int i4, int i5) { #ifdef DEBUG LOGD("Debug: Send data, jnienv.isNull=%d\n", runtimeJNIEnvPtr_ANDROID == NULL); #endif @@ -139,30 +140,10 @@ void sendData(int type, int i1, int i2, int i3, int i4) { inputBridgeClass_ANDROID, inputBridgeMethod_ANDROID, type, - i1, i2, i3, i4 + i1, i2, i3, i4, i5 ); } -jboolean lwjgl2_triggerCharEvent(jchar keyChar) { - if (!runtimeJNIEnvPtr_ANDROID) { - return JNI_FALSE; - } else if (!lwjgl2KeyboardClass && !lwjgl2KeyboardCharMethod) { - lwjgl2KeyboardClass = (*runtimeJNIEnvPtr_ANDROID)->FindClass(runtimeJNIEnvPtr_ANDROID, "org/lwjgl/input/Keyboard"); - assert(lwjgl2KeyboardClass != NULL); - lwjgl2KeyboardCharMethod = (*runtimeJNIEnvPtr_ANDROID)->GetStaticMethodID(runtimeJNIEnvPtr_ANDROID, lwjgl2KeyboardClass, "addCharEvent", "(IC)V"); - assert(lwjgl2KeyboardCharMethod != NULL); - } - - (*runtimeJNIEnvPtr_ANDROID)->CallStaticVoidMethod( - runtimeJNIEnvPtr_ANDROID, - lwjgl2KeyboardClass, - lwjgl2KeyboardCharMethod, - (jint) savedKeycode, keyChar - ); - - return JNI_TRUE; -} - JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThreadToOther(JNIEnv* env, jclass clazz, jboolean isAndroid, jboolean isUseStackQueueBool) { #ifdef DEBUG LOGD("Debug: JNI attaching thread, isUseStackQueue=%d\n", isUseStackQueue); @@ -180,8 +161,8 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThread if (isUseStackQueueCall && isAndroid && result) { isPrepareGrabPos = true; - getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID); } + getJavaInputBridge(&inputBridgeClass_ANDROID, &inputBridgeMethod_ANDROID); return result; } @@ -220,21 +201,20 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendChar(JNI if (isUseStackQueueCall) { sendData(EVENT_TYPE_CHAR, codepoint, 0, 0, 0); } else { - // GLFW_invoke_Char(showingWindow, (unsigned int) codepoint); - return lwjgl2_triggerCharEvent(codepoint); + GLFW_invoke_Char(showingWindow, (unsigned int) codepoint); + // return lwjgl2_triggerCharEvent(codepoint); } return JNI_TRUE; } return JNI_FALSE; } -JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendCharMods(JNIEnv* env, jclass clazz, jint codepoint, jint mods) { +JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendCharMods(JNIEnv* env, jclass clazz, jchar codepoint, jint mods) { if (GLFW_invoke_CharMods && isInputReady) { if (isUseStackQueueCall) { sendData(EVENT_TYPE_CHAR_MODS, (unsigned int) codepoint, mods, 0, 0); } else { - // GLFW_invoke_CharMods(showingWindow, codepoint, mods); - return JNI_FALSE; + GLFW_invoke_CharMods(showingWindow, codepoint, mods); } return JNI_TRUE; } @@ -301,6 +281,18 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(JNIEnv* } } +JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendKeycode(JNIEnv* env, jclass clazz, jint keycode, jchar keychar, jint scancode, jint action, jint mods) { + if (isInputReady) { + if (isUseStackQueue) { + if (!Java_org_lwjgl_glfw_CallbackBridge_nativeSendCharMods(env, clazz, keychar, mods) && !Java_org_lwjgl_glfw_CallbackBridge_nativeSendChar(env, clazz, keychar)) { + Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(env, clazz, keycode, action, mods); + } + } else { + sendData(EVENT_TYPE_KEYCODE, keycode, keychar, scancode, action, mods); + } + } +} + JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(JNIEnv* env, jclass clazz, jint button, jint action, jint mods) { if (isInputReady) { if (button == -1) {