mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-15 07:39:00 -04:00
Merge pull request #4006 from PojavLauncherTeam/native-input
Native input
This commit is contained in:
commit
4aeb89922c
Binary file not shown.
@ -1 +1 @@
|
|||||||
1677612008557
|
1677849361119
|
@ -154,6 +154,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
|
|||||||
|
|
||||||
mVersionId = version;
|
mVersionId = version;
|
||||||
isInputStackCall = Tools.getVersionInfo(mVersionId).arguments != null;
|
isInputStackCall = Tools.getVersionInfo(mVersionId).arguments != null;
|
||||||
|
CallbackBridge.nativeSetUseInputStackQueue(isInputStackCall);
|
||||||
|
|
||||||
Tools.getDisplayMetrics(this);
|
Tools.getDisplayMetrics(this);
|
||||||
windowWidth = Tools.getDisplayFriendlyRes(currentDisplayMetrics.widthPixels, scaleFactor);
|
windowWidth = Tools.getDisplayFriendlyRes(currentDisplayMetrics.widthPixels, scaleFactor);
|
||||||
|
@ -782,7 +782,10 @@ public final class Tools {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void write(String path, String content) throws IOException {
|
public static void write(String path, String content) throws IOException {
|
||||||
try(FileOutputStream outStream = new FileOutputStream(path)) {
|
File file = new File(path);
|
||||||
|
File parent = file.getParentFile();
|
||||||
|
if(!parent.exists()) parent.mkdirs();
|
||||||
|
try(FileOutputStream outStream = new FileOutputStream(file)) {
|
||||||
IOUtils.write(content, outStream);
|
IOUtils.write(content, outStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ public class CallbackBridge {
|
|||||||
|
|
||||||
public static void sendCursorPos(float x, float y) {
|
public static void sendCursorPos(float x, float y) {
|
||||||
if (!threadAttached) {
|
if (!threadAttached) {
|
||||||
nativeSetUseInputStackQueue(MainActivity.isInputStackCall);
|
|
||||||
threadAttached = CallbackBridge.nativeAttachThreadToOther(true, MainActivity.isInputStackCall);
|
threadAttached = CallbackBridge.nativeAttachThreadToOther(true, MainActivity.isInputStackCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@ -43,15 +44,16 @@ typedef void GLFW_invoke_Scroll_func(void* window, double xoffset, double yoffse
|
|||||||
typedef void GLFW_invoke_WindowSize_func(void* window, int width, int height);
|
typedef void GLFW_invoke_WindowSize_func(void* window, int width, int height);
|
||||||
|
|
||||||
static float grabCursorX, grabCursorY, lastCursorX, lastCursorY;
|
static float grabCursorX, grabCursorY, lastCursorX, lastCursorY;
|
||||||
|
static double cursorX, cursorY, cLastX, cLastY;
|
||||||
|
|
||||||
jclass inputBridgeClass_ANDROID, inputBridgeClass_JRE;
|
|
||||||
jmethodID inputBridgeMethod_ANDROID, inputBridgeMethod_JRE;
|
|
||||||
jmethodID method_accessAndroidClipboard;
|
jmethodID method_accessAndroidClipboard;
|
||||||
jmethodID method_onGrabStateChanged;
|
jmethodID method_onGrabStateChanged;
|
||||||
jmethodID method_glftSetWindowAttrib;
|
jmethodID method_glftSetWindowAttrib;
|
||||||
|
jmethodID method_internalWindowSizeChanged;
|
||||||
jclass bridgeClazz;
|
jclass bridgeClazz;
|
||||||
jclass vmGlfwClass;
|
jclass vmGlfwClass;
|
||||||
jboolean isGrabbing;
|
jboolean isGrabbing;
|
||||||
|
jbyte* keyDownBuffer;
|
||||||
|
|
||||||
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||||
if (dalvikJavaVMPtr == NULL) {
|
if (dalvikJavaVMPtr == NULL) {
|
||||||
@ -67,6 +69,10 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|||||||
(*vm)->GetEnv(vm, (void**) &runtimeJNIEnvPtr_JRE, JNI_VERSION_1_4);
|
(*vm)->GetEnv(vm, (void**) &runtimeJNIEnvPtr_JRE, JNI_VERSION_1_4);
|
||||||
vmGlfwClass = (*runtimeJNIEnvPtr_JRE)->NewGlobalRef(runtimeJNIEnvPtr_JRE, (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "org/lwjgl/glfw/GLFW"));
|
vmGlfwClass = (*runtimeJNIEnvPtr_JRE)->NewGlobalRef(runtimeJNIEnvPtr_JRE, (*runtimeJNIEnvPtr_JRE)->FindClass(runtimeJNIEnvPtr_JRE, "org/lwjgl/glfw/GLFW"));
|
||||||
method_glftSetWindowAttrib = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, vmGlfwClass, "glfwSetWindowAttrib", "(JII)V");
|
method_glftSetWindowAttrib = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, vmGlfwClass, "glfwSetWindowAttrib", "(JII)V");
|
||||||
|
method_internalWindowSizeChanged = (*runtimeJNIEnvPtr_JRE)->GetStaticMethodID(runtimeJNIEnvPtr_JRE, vmGlfwClass, "internalWindowSizeChanged", "(JII)V");
|
||||||
|
jfieldID field_keyDownBuffer = (*runtimeJNIEnvPtr_JRE)->GetStaticFieldID(runtimeJNIEnvPtr_JRE, vmGlfwClass, "keyDownBuffer", "Ljava/nio/ByteBuffer;");
|
||||||
|
jobject keyDownBufferJ = (*runtimeJNIEnvPtr_JRE)->GetStaticObjectField(runtimeJNIEnvPtr_JRE, vmGlfwClass, field_keyDownBuffer);
|
||||||
|
keyDownBuffer = (*runtimeJNIEnvPtr_JRE)->GetDirectBufferAddress(runtimeJNIEnvPtr_JRE, keyDownBufferJ);
|
||||||
hookExec();
|
hookExec();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +92,7 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//dalvikJNIEnvPtr_JRE = NULL;
|
//dalvikJNIEnvPtr_JRE = NULL;
|
||||||
runtimeJNIEnvPtr_ANDROID = NULL;
|
//runtimeJNIEnvPtr_ANDROID = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADD_CALLBACK_WWIN(NAME) \
|
#define ADD_CALLBACK_WWIN(NAME) \
|
||||||
@ -127,22 +133,106 @@ jboolean attachThread(bool isAndroid, JNIEnv** secondJNIEnvPtr) {
|
|||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendData(int type, int i1, int i2, int i3, int i4) {
|
typedef struct {
|
||||||
#ifdef DEBUG
|
int type;
|
||||||
LOGD("Debug: Send data, jnienv.isNull=%d\n", runtimeJNIEnvPtr_ANDROID == NULL);
|
int i1;
|
||||||
#endif
|
int i2;
|
||||||
if (runtimeJNIEnvPtr_ANDROID == NULL) {
|
int i3;
|
||||||
LOGE("BUG: Input is ready but thread is not attached yet.");
|
int i4;
|
||||||
return;
|
} GLFWInputEvent;
|
||||||
|
static atomic_size_t eventCounter = 0;
|
||||||
|
static GLFWInputEvent events[500];
|
||||||
|
|
||||||
|
void handleFramebufferSizeJava(long window, int w, int h) {
|
||||||
|
(*runtimeJNIEnvPtr_JRE)->CallStaticVoidMethod(runtimeJNIEnvPtr_JRE, 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);
|
||||||
|
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(showingWindow, event.i1, event.i2);
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "NativeInput", "Pumped size event: %i %i",event.i1, event.i2);
|
||||||
|
if(GLFW_invoke_FramebufferSize) GLFW_invoke_FramebufferSize(window, event.i1, event.i2);
|
||||||
|
break;
|
||||||
|
case EVENT_TYPE_WINDOW_SIZE:
|
||||||
|
handleFramebufferSizeJava(showingWindow, event.i1, event.i2);
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "NativeInput", "Pumped size event: %i %i",event.i1, event.i2);
|
||||||
|
if(GLFW_invoke_WindowSize) GLFW_invoke_WindowSize(window, event.i1, event.i2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if((cLastX != cursorX || cLastY != cursorY) && GLFW_invoke_CursorPos) {
|
||||||
|
cLastX = cursorX;
|
||||||
|
cLastY = cursorY;
|
||||||
|
GLFW_invoke_CursorPos(window, cursorX, cursorY);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
// TODO: implement glfwGetCursorPos()
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
// TODO: implement nglfwGetCursorPosA()
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
// TODO: implement glfwSetCursorPos()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void sendData(int type, int i1, int i2, int i3, int i4) {
|
||||||
|
if(type == EVENT_TYPE_CURSOR_POS) {
|
||||||
|
cursorX = i1;
|
||||||
|
cursorY = i2;
|
||||||
|
}else {
|
||||||
|
size_t counter = atomic_load_explicit(&eventCounter, memory_order_acquire);
|
||||||
|
if (counter < 499) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
if(inputBridgeClass_ANDROID == NULL) return;
|
|
||||||
(*runtimeJNIEnvPtr_ANDROID)->CallStaticVoidMethod(
|
|
||||||
runtimeJNIEnvPtr_ANDROID,
|
|
||||||
inputBridgeClass_ANDROID,
|
|
||||||
inputBridgeMethod_ANDROID,
|
|
||||||
type,
|
|
||||||
i1, i2, i3, i4
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void closeGLFWWindow() {
|
void closeGLFWWindow() {
|
||||||
@ -206,21 +296,10 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeAttachThread
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
LOGD("Debug: JNI attaching thread, isUseStackQueue=%d\n", isUseStackQueueBool);
|
LOGD("Debug: JNI attaching thread, isUseStackQueue=%d\n", isUseStackQueueBool);
|
||||||
#endif
|
#endif
|
||||||
|
if (isUseStackQueueCall && isAndroid) {
|
||||||
jboolean result;
|
|
||||||
|
|
||||||
//isUseStackQueueCall = (int) isUseStackQueueBool;
|
|
||||||
if (isAndroid) {
|
|
||||||
result = attachThread(true, &runtimeJNIEnvPtr_ANDROID);
|
|
||||||
} /* else {
|
|
||||||
result = attachThread(false, &dalvikJNIEnvPtr_JRE);
|
|
||||||
// getJavaInputBridge(&inputBridgeClass_JRE, &inputBridgeMethod_JRE);
|
|
||||||
} */
|
|
||||||
|
|
||||||
if (isUseStackQueueCall && isAndroid && result) {
|
|
||||||
isPrepareGrabPos = true;
|
isPrepareGrabPos = true;
|
||||||
}
|
}
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jbyteArray copySrc) {
|
JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jbyteArray copySrc) {
|
||||||
@ -256,16 +335,12 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetInputRead
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
LOGD("Debug: Changing input state, isReady=%d, isUseStackQueueCall=%d\n", inputReady, isUseStackQueueCall);
|
LOGD("Debug: Changing input state, isReady=%d, isUseStackQueueCall=%d\n", inputReady, isUseStackQueueCall);
|
||||||
#endif
|
#endif
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, "NativeInput", "Input ready: %i", inputReady);
|
||||||
isInputReady = inputReady;
|
isInputReady = inputReady;
|
||||||
return isUseStackQueueCall;
|
return isUseStackQueueCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetGrabbing(JNIEnv* env, jclass clazz, jboolean grabbing, jint xset, jint yset) {
|
static void updateGrabCursor(jint xset, jint yset) {
|
||||||
JNIEnv *dalvikEnv;
|
|
||||||
(*dalvikJavaVMPtr)->AttachCurrentThread(dalvikJavaVMPtr, &dalvikEnv, NULL);
|
|
||||||
(*dalvikEnv)->CallStaticVoidMethod(dalvikEnv, bridgeClazz, method_onGrabStateChanged, grabbing);
|
|
||||||
(*dalvikJavaVMPtr)->DetachCurrentThread(dalvikJavaVMPtr);
|
|
||||||
isGrabbing = grabbing;
|
|
||||||
if (isGrabbing == JNI_TRUE) {
|
if (isGrabbing == JNI_TRUE) {
|
||||||
grabCursorX = xset; // savedWidth / 2;
|
grabCursorX = xset; // savedWidth / 2;
|
||||||
grabCursorY = yset; // savedHeight / 2;
|
grabCursorY = yset; // savedHeight / 2;
|
||||||
@ -273,6 +348,15 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetGrabbing(JNIE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetGrabbing(JNIEnv* env, jclass clazz, jboolean grabbing) {
|
||||||
|
JNIEnv *dalvikEnv;
|
||||||
|
(*dalvikJavaVMPtr)->AttachCurrentThread(dalvikJavaVMPtr, &dalvikEnv, NULL);
|
||||||
|
(*dalvikEnv)->CallStaticVoidMethod(dalvikEnv, bridgeClazz, method_onGrabStateChanged, grabbing);
|
||||||
|
(*dalvikJavaVMPtr)->DetachCurrentThread(dalvikJavaVMPtr);
|
||||||
|
isGrabbing = grabbing;
|
||||||
|
updateGrabCursor((jint)cursorX, (jint)cursorY);
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeIsGrabbing(JNIEnv* env, jclass clazz) {
|
JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeIsGrabbing(JNIEnv* env, jclass clazz) {
|
||||||
return isGrabbing;
|
return isGrabbing;
|
||||||
}
|
}
|
||||||
@ -356,9 +440,13 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendCursorPos(JN
|
|||||||
lastCursorY = y;
|
lastCursorY = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#define max(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; })
|
||||||
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(JNIEnv* env, jclass clazz, jint key, jint scancode, jint action, jint mods) {
|
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendKey(JNIEnv* env, jclass clazz, jint key, jint scancode, jint action, jint mods) {
|
||||||
if (GLFW_invoke_Key && isInputReady) {
|
if (GLFW_invoke_Key && isInputReady) {
|
||||||
|
keyDownBuffer[max(0, key-31)]=(jbyte)action;
|
||||||
if (isUseStackQueueCall) {
|
if (isUseStackQueueCall) {
|
||||||
sendData(EVENT_TYPE_KEY, key, scancode, action, mods);
|
sendData(EVENT_TYPE_KEY, key, scancode, action, mods);
|
||||||
} else {
|
} else {
|
||||||
@ -387,7 +475,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendMouseButton(
|
|||||||
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendScreenSize(JNIEnv* env, jclass clazz, jint width, jint height) {
|
JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSendScreenSize(JNIEnv* env, jclass clazz, jint width, jint height) {
|
||||||
savedWidth = width;
|
savedWidth = width;
|
||||||
savedHeight = height;
|
savedHeight = height;
|
||||||
|
|
||||||
if (isInputReady) {
|
if (isInputReady) {
|
||||||
if (GLFW_invoke_FramebufferSize) {
|
if (GLFW_invoke_FramebufferSize) {
|
||||||
if (isUseStackQueueCall) {
|
if (isUseStackQueueCall) {
|
||||||
@ -435,10 +522,4 @@ JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetWindowAttrib(
|
|||||||
vmGlfwClass, method_glftSetWindowAttrib,
|
vmGlfwClass, method_glftSetWindowAttrib,
|
||||||
(jlong) showingWindow, attrib, value
|
(jlong) showingWindow, attrib, value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
|
||||||
Java_org_lwjgl_glfw_CallbackBridge_setClass(JNIEnv *env, jclass clazz) {
|
|
||||||
inputBridgeMethod_ANDROID = (*env)->GetStaticMethodID(env, clazz, "receiveCallback", "(IIIII)V");
|
|
||||||
inputBridgeClass_ANDROID = (*env)->NewGlobalRef(env, clazz);
|
|
||||||
}
|
|
@ -3,7 +3,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
static JavaVM* runtimeJavaVMPtr;
|
static JavaVM* runtimeJavaVMPtr;
|
||||||
static JNIEnv* runtimeJNIEnvPtr_ANDROID;
|
|
||||||
static JNIEnv* runtimeJNIEnvPtr_JRE;
|
static JNIEnv* runtimeJNIEnvPtr_JRE;
|
||||||
|
|
||||||
static JavaVM* dalvikJavaVMPtr;
|
static JavaVM* dalvikJavaVMPtr;
|
||||||
|
@ -16,10 +16,6 @@ public class CallbackBridge {
|
|||||||
public static final int EVENT_TYPE_WINDOW_SIZE = 1008;
|
public static final int EVENT_TYPE_WINDOW_SIZE = 1008;
|
||||||
|
|
||||||
public static final int ANDROID_TYPE_GRAB_STATE = 0;
|
public static final int ANDROID_TYPE_GRAB_STATE = 0;
|
||||||
|
|
||||||
// Should pending events be limited?
|
|
||||||
volatile public static List<Integer[]> PENDING_EVENT_LIST = new ArrayList<>();
|
|
||||||
volatile public static boolean PENDING_EVENT_READY = false;
|
|
||||||
|
|
||||||
public static final boolean INPUT_DEBUG_ENABLED;
|
public static final boolean INPUT_DEBUG_ENABLED;
|
||||||
|
|
||||||
@ -42,38 +38,14 @@ public class CallbackBridge {
|
|||||||
//Quick and dirty: debul all key inputs to System.out
|
//Quick and dirty: debul all key inputs to System.out
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendGrabbing(boolean grab, int xset, int yset) {
|
|
||||||
// sendData(ANDROID_TYPE_GRAB_STATE, Boolean.toString(grab));
|
|
||||||
|
|
||||||
GLFW.mGLFWIsGrabbing = grab;
|
|
||||||
nativeSetGrabbing(grab, xset, yset);
|
|
||||||
}
|
|
||||||
// Called from Android side
|
|
||||||
public static void receiveCallback(int type, int i1, int 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 {
|
|
||||||
PENDING_EVENT_LIST.add(new Integer[]{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) {
|
public static void sendData(int type, String data) {
|
||||||
nativeSendData(false, type, data);
|
nativeSendData(false, type, data);
|
||||||
}
|
}
|
||||||
public static native void nativeSendData(boolean isAndroid, int type, String data);
|
public static native void nativeSendData(boolean isAndroid, int type, String data);
|
||||||
public static native boolean nativeSetInputReady(boolean ready);
|
public static native boolean nativeSetInputReady(boolean ready);
|
||||||
public static native String nativeClipboard(int action, byte[] copy);
|
public static native String nativeClipboard(int action, byte[] copy);
|
||||||
public static native void nativeAttachThreadToOther(boolean isAndroid, boolean isUseStackQueueBool);
|
public static native void nativeSetGrabbing(boolean grab);
|
||||||
private static native void nativeSetGrabbing(boolean grab, int xset, int yset);
|
|
||||||
public static native void setClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ import static org.lwjgl.system.MemoryStack.*;
|
|||||||
import static org.lwjgl.system.MemoryUtil.*;
|
import static org.lwjgl.system.MemoryUtil.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import sun.misc.Unsafe;
|
||||||
|
|
||||||
public class GLFW
|
public class GLFW
|
||||||
{
|
{
|
||||||
static FloatBuffer joystickData = (FloatBuffer)FloatBuffer.allocate(8).flip();
|
static FloatBuffer joystickData = (FloatBuffer)FloatBuffer.allocate(8).flip();
|
||||||
@ -485,7 +487,6 @@ public class GLFW
|
|||||||
/* volatile */ public static GLFWWindowSizeCallback mGLFWWindowSizeCallback;
|
/* volatile */ public static GLFWWindowSizeCallback mGLFWWindowSizeCallback;
|
||||||
|
|
||||||
volatile public static int mGLFWWindowWidth, mGLFWWindowHeight;
|
volatile public static int mGLFWWindowWidth, mGLFWWindowHeight;
|
||||||
volatile public static double mGLFWCursorX, mGLFWCursorY, mGLFWCursorLastX, mGLFWCursorLastY;
|
|
||||||
|
|
||||||
private static GLFWGammaRamp mGLFWGammaRamp;
|
private static GLFWGammaRamp mGLFWGammaRamp;
|
||||||
private static Map<Integer, String> mGLFWKeyCodes;
|
private static Map<Integer, String> mGLFWKeyCodes;
|
||||||
@ -495,9 +496,8 @@ public class GLFW
|
|||||||
private static double mGLFWInitialTime;
|
private static double mGLFWInitialTime;
|
||||||
|
|
||||||
private static ArrayMap<Long, GLFWWindowProperties> mGLFWWindowMap;
|
private static ArrayMap<Long, GLFWWindowProperties> mGLFWWindowMap;
|
||||||
|
public static boolean mGLFWIsInputReady;
|
||||||
public static boolean mGLFWIsGrabbing, mGLFWIsInputReady, mGLFWIsUseStackQueue = false;
|
public static final ByteBuffer keyDownBuffer = ByteBuffer.allocateDirect(317);
|
||||||
public static final byte[] keyDownBuffer = new byte[317];
|
|
||||||
private static final String PROP_WINDOW_WIDTH = "glfwstub.windowWidth";
|
private static final String PROP_WINDOW_WIDTH = "glfwstub.windowWidth";
|
||||||
private static final String PROP_WINDOW_HEIGHT= "glfwstub.windowHeight";
|
private static final String PROP_WINDOW_HEIGHT= "glfwstub.windowHeight";
|
||||||
public static long mainContext = 0;
|
public static long mainContext = 0;
|
||||||
@ -524,7 +524,6 @@ public class GLFW
|
|||||||
} catch (UnsatisfiedLinkError e) {
|
} catch (UnsatisfiedLinkError e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
CallbackBridge.setClass();
|
|
||||||
mGLFWErrorCallback = GLFWErrorCallback.createPrint();
|
mGLFWErrorCallback = GLFWErrorCallback.createPrint();
|
||||||
mGLFWKeyCodes = new ArrayMap<>();
|
mGLFWKeyCodes = new ArrayMap<>();
|
||||||
|
|
||||||
@ -613,7 +612,9 @@ public class GLFW
|
|||||||
MakeContextCurrent = apiGetFunctionAddress(GLFW, "pojavMakeCurrent"),
|
MakeContextCurrent = apiGetFunctionAddress(GLFW, "pojavMakeCurrent"),
|
||||||
Terminate = apiGetFunctionAddress(GLFW, "pojavTerminate"),
|
Terminate = apiGetFunctionAddress(GLFW, "pojavTerminate"),
|
||||||
SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"),
|
SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"),
|
||||||
SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval");
|
SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"),
|
||||||
|
PumpEvents = apiGetFunctionAddress(GLFW, "pojavPumpEvents"),
|
||||||
|
RewindEvents = apiGetFunctionAddress(GLFW, "pojavRewindEvents");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SharedLibrary getLibrary() {
|
public static SharedLibrary getLibrary() {
|
||||||
@ -1052,90 +1053,19 @@ public class GLFW
|
|||||||
public static void glfwPollEvents() {
|
public static void glfwPollEvents() {
|
||||||
if (!mGLFWIsInputReady) {
|
if (!mGLFWIsInputReady) {
|
||||||
mGLFWIsInputReady = true;
|
mGLFWIsInputReady = true;
|
||||||
mGLFWIsUseStackQueue = CallbackBridge.nativeSetInputReady(true);
|
CallbackBridge.nativeSetInputReady(true);
|
||||||
}
|
|
||||||
if(!CallbackBridge.PENDING_EVENT_READY) {
|
|
||||||
CallbackBridge.PENDING_EVENT_READY = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indirect event
|
for (Long ptr : mGLFWWindowMap.keySet()) callJV(ptr, Functions.PumpEvents);
|
||||||
while (CallbackBridge.PENDING_EVENT_LIST.size() > 0) {
|
callV(Functions.RewindEvents);
|
||||||
Integer[] dataArr = CallbackBridge.PENDING_EVENT_LIST.remove(0);
|
}
|
||||||
for (Long ptr : mGLFWWindowMap.keySet()) {
|
|
||||||
try {
|
|
||||||
switch (dataArr[0]) {
|
|
||||||
case CallbackBridge.EVENT_TYPE_CHAR:
|
|
||||||
if (mGLFWCharCallback != null) {
|
|
||||||
mGLFWCharCallback.invoke(ptr, dataArr[1]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CallbackBridge.EVENT_TYPE_CHAR_MODS:
|
|
||||||
if (mGLFWCharModsCallback != null) {
|
|
||||||
mGLFWCharModsCallback.invoke(ptr, dataArr[1], dataArr[2]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CallbackBridge.EVENT_TYPE_CURSOR_ENTER:
|
|
||||||
if (mGLFWCursorEnterCallback != null) {
|
|
||||||
mGLFWCursorEnterCallback.invoke(ptr, dataArr[1] == 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CallbackBridge.EVENT_TYPE_KEY:
|
|
||||||
if (mGLFWKeyCallback != null) {
|
|
||||||
keyDownBuffer[Math.max(0, dataArr[1]-31)]=(byte)(int)dataArr[3];
|
|
||||||
mGLFWKeyCallback.invoke(ptr, dataArr[1], dataArr[2], dataArr[3], dataArr[4]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CallbackBridge.EVENT_TYPE_MOUSE_BUTTON:
|
|
||||||
if (mGLFWMouseButtonCallback != null) {
|
|
||||||
mGLFWMouseButtonCallback.invoke(ptr, dataArr[1], dataArr[2], dataArr[3]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CallbackBridge.EVENT_TYPE_SCROLL:
|
|
||||||
if (mGLFWScrollCallback != null) {
|
|
||||||
mGLFWScrollCallback.invoke(ptr, dataArr[1], dataArr[2]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE:
|
|
||||||
case CallbackBridge.EVENT_TYPE_WINDOW_SIZE:
|
|
||||||
try {
|
|
||||||
internalChangeMonitorSize(dataArr[1], dataArr[2]);
|
|
||||||
glfwSetWindowSize(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
|
|
||||||
if (dataArr[0] == CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE && mGLFWFramebufferSizeCallback != null) {
|
|
||||||
mGLFWFramebufferSizeCallback.invoke(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
|
|
||||||
} else if (dataArr[0] == CallbackBridge.EVENT_TYPE_WINDOW_SIZE && mGLFWWindowSizeCallback != null) {
|
|
||||||
mGLFWWindowSizeCallback.invoke(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
|
|
||||||
}
|
|
||||||
} catch (Throwable th) {
|
|
||||||
// Some Minecraft versions cause a NPE when setting size, so we will have to ignore them to make game alive
|
|
||||||
th.printStackTrace();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
System.err.println("GLFWEvent: unknown callback type " + dataArr[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}catch (Throwable throwable){
|
|
||||||
throwable.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
public static void internalWindowSizeChanged(long window, int w, int h) {
|
||||||
}
|
try {
|
||||||
|
internalChangeMonitorSize(w, h);
|
||||||
if ((mGLFWCursorX != mGLFWCursorLastX || mGLFWCursorY != mGLFWCursorLastY) && mGLFWCursorPosCallback != null) {
|
glfwSetWindowSize(window, mGLFWWindowWidth, mGLFWWindowHeight);
|
||||||
mGLFWCursorLastX = mGLFWCursorX;
|
}catch (Exception e) {
|
||||||
mGLFWCursorLastY = mGLFWCursorY;
|
e.printStackTrace();
|
||||||
for (Long ptr : mGLFWWindowMap.keySet()) {
|
|
||||||
if (!mGLFWIsGrabbing && mGLFWWindowSizeCallback != null) {
|
|
||||||
try {
|
|
||||||
mGLFWWindowSizeCallback.invoke(ptr, mGLFWWindowWidth, mGLFWWindowHeight);
|
|
||||||
}catch (Throwable throwable){
|
|
||||||
throwable.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
mGLFWCursorPosCallback.invoke(ptr, mGLFWCursorX, mGLFWCursorY);
|
|
||||||
}
|
|
||||||
// System.out.println("CursorPos updated to x=" + mGLFWCursorX + ",y=" + mGLFWCursorY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,9 +1094,9 @@ public class GLFW
|
|||||||
if (mode == GLFW_CURSOR) {
|
if (mode == GLFW_CURSOR) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case GLFW_CURSOR_DISABLED:
|
case GLFW_CURSOR_DISABLED:
|
||||||
CallbackBridge.sendGrabbing(true, (int) mGLFWCursorX, (int) mGLFWCursorY);
|
CallbackBridge.nativeSetGrabbing(true);
|
||||||
break;
|
break;
|
||||||
default: CallbackBridge.sendGrabbing(false, (int) mGLFWCursorX, (int) mGLFWCursorY);
|
default: CallbackBridge.nativeSetGrabbing(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,29 +1112,30 @@ public class GLFW
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int glfwGetKey(@NativeType("GLFWwindow *") long window, int key) {
|
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) {
|
public static int glfwGetMouseButton(@NativeType("GLFWwindow *") long window, int button) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void glfwGetCursorPos(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("double *") DoubleBuffer xpos, @Nullable @NativeType("double *") DoubleBuffer ypos) {
|
public static void glfwGetCursorPos(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("double *") DoubleBuffer xpos, @Nullable @NativeType("double *") DoubleBuffer ypos) {
|
||||||
if (CHECKS) {
|
if (CHECKS) {
|
||||||
checkSafe(xpos, 1);
|
checkSafe(xpos, 1);
|
||||||
checkSafe(ypos, 1);
|
checkSafe(ypos, 1);
|
||||||
}
|
}
|
||||||
|
nglfwGetCursorPos(window, xpos, ypos);
|
||||||
xpos.put(mGLFWCursorX);
|
|
||||||
ypos.put(mGLFWCursorY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
mGLFWCursorX = mGLFWCursorLastX = xpos;
|
||||||
mGLFWCursorY = mGLFWCursorLastY = ypos;
|
mGLFWCursorY = mGLFWCursorLastY = ypos;
|
||||||
|
|
||||||
CallbackBridge.sendGrabbing(mGLFWIsGrabbing, (int) xpos, (int) ypos);
|
CallbackBridge.sendGrabbing(mGLFWIsGrabbing, (int) xpos, (int) ypos);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public static long glfwCreateCursor(@NativeType("const GLFWimage *") GLFWImage image, int xhot, int yhot) {
|
public static long glfwCreateCursor(@NativeType("const GLFWimage *") GLFWImage image, int xhot, int yhot) {
|
||||||
return 4L;
|
return 4L;
|
||||||
@ -1416,8 +1347,7 @@ public class GLFW
|
|||||||
checkSafe(xpos, 1);
|
checkSafe(xpos, 1);
|
||||||
checkSafe(ypos, 1);
|
checkSafe(ypos, 1);
|
||||||
}
|
}
|
||||||
xpos[0] = mGLFWCursorX;
|
nglfwGetCursorPosA(window, xpos, ypos);
|
||||||
ypos[0] = mGLFWCursorY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean glfwExtensionSupported(String ext) {
|
public static boolean glfwExtensionSupported(String ext) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user