From 13007f152a0dee409955922ba79049a6d570d4db Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Thu, 17 Sep 2020 10:20:10 +0700 Subject: [PATCH] Improve input bridge; Add a pipe to callback data from JRE to Android thread --- .../kdt/pojavlaunch/AndroidLWJGLKeycode.java | 5 +- .../net/kdt/pojavlaunch/LWJGLInputSender.java | 53 ------ .../kdt/pojavlaunch/MCLauncherActivity.java | 19 +-- .../net/kdt/pojavlaunch/MainActivity.java | 156 +++++++++--------- .../main/java/net/kdt/pojavlaunch/Tools.java | 10 +- .../value/customcontrols/ControlButton.java | 14 +- .../value/customcontrols/CustomControls.java | 19 ++- .../java/org/lwjgl/glfw/CallbackBridge.java | 65 ++++++++ app/src/main/jni/egl_bridge.c | 2 +- app/src/main/jni/input_bridge.c | 49 ++++-- app/src/main/jni/utils.h | 2 +- 11 files changed, 208 insertions(+), 186 deletions(-) delete mode 100644 app/src/main/java/net/kdt/pojavlaunch/LWJGLInputSender.java create mode 100644 app/src/main/java/org/lwjgl/glfw/CallbackBridge.java diff --git a/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java b/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java index 0d21841b5..d1dad3371 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java +++ b/app/src/main/java/net/kdt/pojavlaunch/AndroidLWJGLKeycode.java @@ -3,6 +3,7 @@ package net.kdt.pojavlaunch; import android.util.*; import android.view.*; import java.util.*; +import org.lwjgl.glfw.*; public class AndroidLWJGLKeycode { // Fix double letters on MC 1.9 and above @@ -189,14 +190,14 @@ public class AndroidLWJGLKeycode { } try { - if (/* (int) keyEvent.getDisplayLabel() != KeyEvent.KEYCODE_UNKNOWN && */ !LWJGLInputSender.isGrabbing()) { + if (/* (int) keyEvent.getDisplayLabel() != KeyEvent.KEYCODE_UNKNOWN && */ !CallbackBridge.isGrabbing()) { mainActivity.sendKeyPress(0, (char) keyEvent.getUnicodeChar(), isDown); } } catch (Throwable th) { th.printStackTrace(); } - if (isBackspaceAfterChar && !LWJGLInputSender.isGrabbing() && i != KeyEvent.KEYCODE_DEL) { + if (isBackspaceAfterChar && !CallbackBridge.isGrabbing() && i != KeyEvent.KEYCODE_DEL) { mainActivity.sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_BACKSPACE, isDown); } } diff --git a/app/src/main/java/net/kdt/pojavlaunch/LWJGLInputSender.java b/app/src/main/java/net/kdt/pojavlaunch/LWJGLInputSender.java deleted file mode 100644 index 290e7eb0d..000000000 --- a/app/src/main/java/net/kdt/pojavlaunch/LWJGLInputSender.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.kdt.pojavlaunch; - -public class LWJGLInputSender -{ - public static final int TYPE_CURSOR_POS = 0; - public static final int TYPE_CURSOR_BUTTON = 1; - public static final int TYPE_KEYCODE_CONTROL = 2; - public static final int TYPE_KEYCODE_CHAR = 3; - public static final int TYPE_MOUSE_KEYCODE_CONTROL = 4; - public static final int TYPE_WINDOW_SIZE = 5; - - public static int windowWidth, windowHeight; - public static int mouseX, mouseY; - public static boolean mouseLeft; - public static StringBuilder DEBUG_STRING = new StringBuilder(); - - public static void sendMouseEvent(int x, int y, int keycode, boolean isDown) { - sendCursorPos(x, y); - sendKeycode(keycode, isDown); - } - - public static void sendCursorPos(int x, int y) { - DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n"); - mouseX = x; - mouseY = y; - sendDataToJRE(TYPE_CURSOR_POS, x + ":" + y); - } - - public static void sendKeycode(int keycode, boolean isDown) { - sendDataToJRE(TYPE_KEYCODE_CONTROL, keycode + ":" + Boolean.toString(isDown)); - } - - public static void sendMouseKeycode(int keycode, boolean isDown) { - DEBUG_STRING.append("MouseKey=" + keycode + ", down=" + isDown + "\n"); - sendDataToJRE(TYPE_MOUSE_KEYCODE_CONTROL, keycode + ":" + Boolean.toString(isDown)); - } - - public static void sendMouseKeycode(int keycode) { - sendMouseKeycode(keycode, true); - sendMouseKeycode(keycode, false); - } - - public static void sendUpdateWindowSize(int w, int h) { - sendDataToJRE(TYPE_WINDOW_SIZE, w + ":" + h); - } - - public static boolean isGrabbing() { - // TODO implement this method!!! - return false; - } - - public static native void sendDataToJRE(int type, String data); -} diff --git a/app/src/main/java/net/kdt/pojavlaunch/MCLauncherActivity.java b/app/src/main/java/net/kdt/pojavlaunch/MCLauncherActivity.java index 6e13e94f3..8cce15e4d 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/MCLauncherActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/MCLauncherActivity.java @@ -2,6 +2,7 @@ package net.kdt.pojavlaunch; import android.app.*; import android.content.*; +import android.graphics.*; import android.os.*; import android.support.design.widget.*; import android.support.v4.app.*; @@ -13,7 +14,6 @@ import android.widget.*; import android.widget.AdapterView.*; import com.google.gson.*; import com.kdt.filerapi.*; -import com.kdt.filermod.*; import java.io.*; import java.nio.charset.*; import java.util.*; @@ -21,14 +21,11 @@ import net.kdt.pojavlaunch.mcfragments.*; import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.util.*; import net.kdt.pojavlaunch.value.*; +import org.lwjgl.glfw.*; import android.app.AlertDialog; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; -import dalvik.system.*; -import java.lang.reflect.*; -import android.graphics.*; -import android.content.pm.*; //import android.support.v7.view.menu.*; //import net.zhuoweizhang.boardwalk.downloader.*; @@ -66,8 +63,8 @@ public class MCLauncherActivity extends AppCompatActivity gson = new Gson(); DisplayMetrics dm = Tools.getDisplayMetrics(this); - LWJGLInputSender.windowWidth = dm.widthPixels; - LWJGLInputSender.windowHeight = dm.heightPixels; + CallbackBridge.windowWidth = dm.widthPixels; + CallbackBridge.windowHeight = dm.heightPixels; viewInit(); final View decorView = getWindow().getDecorView(); @@ -276,10 +273,10 @@ public class MCLauncherActivity extends AppCompatActivity } private float updateWidthHeight() { - float leftRightWidth = (float) LWJGLInputSender.windowWidth / 100f * 32f; - float playButtonWidth = LWJGLInputSender.windowWidth - leftRightWidth * 2f; - LinearLayout.LayoutParams leftRightParams = new LinearLayout.LayoutParams((int) leftRightWidth, (int) Tools.dpToPx(this, LWJGLInputSender.windowHeight / 9)); - LinearLayout.LayoutParams playButtonParams = new LinearLayout.LayoutParams((int) playButtonWidth, (int) Tools.dpToPx(this, LWJGLInputSender.windowHeight / 9)); + float leftRightWidth = (float) CallbackBridge.windowWidth / 100f * 32f; + float playButtonWidth = CallbackBridge.windowWidth - leftRightWidth * 2f; + LinearLayout.LayoutParams leftRightParams = new LinearLayout.LayoutParams((int) leftRightWidth, (int) Tools.dpToPx(this, CallbackBridge.windowHeight / 9)); + LinearLayout.LayoutParams playButtonParams = new LinearLayout.LayoutParams((int) playButtonWidth, (int) Tools.dpToPx(this, CallbackBridge.windowHeight / 9)); leftView.setLayoutParams(leftRightParams); rightView.setLayoutParams(leftRightParams); playButton.setLayoutParams(playButtonParams); diff --git a/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java b/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java index 4a01781d7..97987e16b 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java +++ b/app/src/main/java/net/kdt/pojavlaunch/MainActivity.java @@ -7,28 +7,22 @@ import android.os.*; import android.support.design.widget.*; import android.support.v4.widget.*; import android.support.v7.app.*; -import android.system.*; import android.util.*; import android.view.*; import android.view.View.*; import android.view.inputmethod.*; import android.widget.*; -import com.kdt.glsupport.*; import com.kdt.pointer.*; -import dalvik.system.*; import java.io.*; -import java.lang.Process; import java.lang.reflect.*; -import java.security.*; import java.util.*; -import javax.microedition.khronos.egl.*; -import javax.microedition.khronos.opengles.*; -import net.kdt.pojavlaunch.exit.*; +import net.kdt.pojavlaunch.*; import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.value.customcontrols.*; +import org.lwjgl.glfw.*; import android.app.AlertDialog; -import com.oracle.dalvik.*; +import java.lang.Process; public class MainActivity extends AppCompatActivity implements OnTouchListener, OnClickListener { @@ -52,9 +46,9 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, public void handleMessage(Message msg) { switch (msg.what) { case MSG_LEFT_MOUSE_BUTTON_CHECK: { - int x = LWJGLInputSender.mouseX; - int y = LWJGLInputSender.mouseY; - if (LWJGLInputSender.isGrabbing() && + int x = CallbackBridge.mouseX; + int y = CallbackBridge.mouseY; + if (CallbackBridge.isGrabbing() && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { triggeredLeftMouseButton = true; @@ -178,9 +172,9 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, this.displayMetrics = Tools.getDisplayMetrics(this); - LWJGLInputSender.windowWidth = displayMetrics.widthPixels / scaleFactor; - LWJGLInputSender.windowHeight = displayMetrics.heightPixels / scaleFactor; - System.out.println("WidthHeight: " + LWJGLInputSender.windowWidth + ":" + LWJGLInputSender.windowHeight); + CallbackBridge.windowWidth = displayMetrics.widthPixels / scaleFactor; + CallbackBridge.windowHeight = displayMetrics.heightPixels / scaleFactor; + System.out.println("WidthHeight: " + CallbackBridge.windowWidth + ":" + CallbackBridge.windowHeight); gestureDetector = new GestureDetector(this, new SingleTapConfirm()); @@ -290,7 +284,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, AndroidLWJGLKeycode.isBackspaceAfterChar = mVersionInfo.minimumLauncherVersion >= 18; - placeMouseAt(LWJGLInputSender.windowWidth / 2, LWJGLInputSender.windowHeight / 2); + placeMouseAt(CallbackBridge.windowWidth / 2, CallbackBridge.windowHeight / 2); new Thread(new Runnable(){ private boolean isCapturing = false; @@ -303,29 +297,29 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, @Override public void run() { - if (lastGrab && !LWJGLInputSender.isGrabbing() && lastEnabled) { + if (lastGrab && !CallbackBridge.isGrabbing() && lastEnabled) { touchPad.setVisibility(View.VISIBLE); - placeMouseAt(LWJGLInputSender.windowWidth / 2, LWJGLInputSender.windowHeight / 2); + placeMouseAt(CallbackBridge.windowWidth / 2, CallbackBridge.windowHeight / 2); } - if (!LWJGLInputSender.isGrabbing()) { + if (!CallbackBridge.isGrabbing()) { lastEnabled = touchPad.getVisibility() == View.VISIBLE; } else if (touchPad.getVisibility() != View.GONE) { touchPad.setVisibility(View.GONE); } if (isPointerCaptureSupported()) { - if (!LWJGLInputSender.isGrabbing() && isCapturing) { + if (!CallbackBridge.isGrabbing() && isCapturing) { pointerSurface.releaseCapture(); // minecraftGLView.releasePointerCapture(); isCapturing = false; - } else if (LWJGLInputSender.isGrabbing() && !isCapturing) { + } else if (CallbackBridge.isGrabbing() && !isCapturing) { minecraftGLView.requestFocus(); pointerSurface.requestCapture(); // minecraftGLView.requestPointerCapture(); isCapturing = true; } } - lastGrab = LWJGLInputSender.isGrabbing(); + lastGrab = CallbackBridge.isGrabbing(); } }); @@ -355,10 +349,10 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, if (gestureDetector.onTouchEvent(event)) { - LWJGLInputSender.sendCursorPos((int) mouseX, (int) mouseY); - LWJGLInputSender.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT); + CallbackBridge.sendCursorPos((int) mouseX, (int) mouseY); + CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT); if (!rightOverride) { - LWJGLInputSender.mouseLeft = true; + CallbackBridge.mouseLeft = true; } } else { @@ -367,7 +361,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, case MotionEvent.ACTION_CANCEL: // 3 case MotionEvent.ACTION_POINTER_UP: // 6 if (!rightOverride) { - LWJGLInputSender.mouseLeft = false; + CallbackBridge.mouseLeft = false; } break; case MotionEvent.ACTION_MOVE: // 2 @@ -376,17 +370,17 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, mouseY += y - prevY; if (mouseX <= 0) { mouseX = 0; - } else if (mouseX >= LWJGLInputSender.windowWidth) { - mouseX = LWJGLInputSender.windowWidth; + } else if (mouseX >= CallbackBridge.windowWidth) { + mouseX = CallbackBridge.windowWidth; } if (mouseY <= 0) { mouseY = 0; - } else if (mouseY >= LWJGLInputSender.windowHeight) { - mouseY = LWJGLInputSender.windowHeight; + } else if (mouseY >= CallbackBridge.windowHeight) { + mouseY = CallbackBridge.windowHeight; } } finally { placeMouseAt(mouseX, mouseY); - LWJGLInputSender.sendCursorPos((int) mouseX, (int) mouseY); + CallbackBridge.sendCursorPos((int) mouseX, (int) mouseY); break; } } @@ -394,8 +388,8 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, prevX = x; prevY = y; - debugText.setText(LWJGLInputSender.DEBUG_STRING.toString()); - LWJGLInputSender.DEBUG_STRING.setLength(0); + debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); return true; } @@ -418,14 +412,14 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, int x = ((int) e.getX()) / scaleFactor; int y = (minecraftGLView.getHeight() - ((int) e.getY())) / scaleFactor; int hudKeyHandled = handleGuiBar(x, y, e); - if (!LWJGLInputSender.isGrabbing() && gestureDetector.onTouchEvent(e)) { + if (!CallbackBridge.isGrabbing() && gestureDetector.onTouchEvent(e)) { if (hudKeyHandled != -1) { sendKeyPress(hudKeyHandled); } else { - LWJGLInputSender.sendCursorPos(x, y); - LWJGLInputSender.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT); + CallbackBridge.sendCursorPos(x, y); + CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT); if (!rightOverride) { - LWJGLInputSender.mouseLeft = true; + CallbackBridge.mouseLeft = true; } } } else { @@ -440,13 +434,13 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, theHandler.sendEmptyMessageDelayed(MainActivity.MSG_DROP_ITEM_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); } else { - LWJGLInputSender.sendCursorPos(x, y); + CallbackBridge.sendCursorPos(x, y); if (!rightOverride) { - // LWJGLInputSender.mouseLeft = true; + // CallbackBridge.mouseLeft = true; } - if (LWJGLInputSender.isGrabbing()) { - LWJGLInputSender.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); + if (CallbackBridge.isGrabbing()) { + CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); initialX = x; initialY = y; theHandler.sendEmptyMessageDelayed(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); @@ -457,16 +451,16 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, case MotionEvent.ACTION_CANCEL: // 3 case MotionEvent.ACTION_POINTER_UP: // 6 if (!isTouchInHotbar) { - LWJGLInputSender.sendCursorPos(x, y); + CallbackBridge.sendCursorPos(x, y); // TODO uncomment after fix wrong trigger - // LWJGLInputSender.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 0, x, y, 0, System.nanoTime()); + // CallbackBridge.putMouseEventWithCoords(rightOverride ? (byte) 1 : (byte) 0, (byte) 0, x, y, 0, System.nanoTime()); if (!rightOverride) { - // LWJGLInputSender.mouseLeft = false; + // CallbackBridge.mouseLeft = false; } } - if (LWJGLInputSender.isGrabbing()) { + if (CallbackBridge.isGrabbing()) { // System.out.println((String) ("[Math.abs(" + initialX + " - " + x + ") = " + Math.abs(initialX - x) + "] < " + fingerStillThreshold)); // System.out.println((String) ("[Math.abs(" + initialY + " - " + y + ") = " + Math.abs(initialY - y) + "] < " + fingerStillThreshold)); if (isTouchInHotbar && Math.abs(hotbarX - x) < fingerStillThreshold && Math.abs(hotbarY - y) < fingerStillThreshold) { @@ -490,17 +484,17 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, default: if (!isTouchInHotbar) { - LWJGLInputSender.sendCursorPos(x, y); + CallbackBridge.sendCursorPos(x, y); } break; } } - debugText.setText(LWJGLInputSender.DEBUG_STRING.toString()); - LWJGLInputSender.DEBUG_STRING.setLength(0); + debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); return true; - // return !LWJGLInputSender.isGrabbing(); + // return !CallbackBridge.isGrabbing(); } }; @@ -549,23 +543,23 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, } } - LWJGLInputSender.sendCursorPos(x, y); + CallbackBridge.sendCursorPos(x, y); switch (e.getButtonState()) { - case MotionEvent.BUTTON_PRIMARY: LWJGLInputSender.mouseLeft = true; + case MotionEvent.BUTTON_PRIMARY: CallbackBridge.mouseLeft = true; break; - case MotionEvent.BUTTON_SECONDARY: LWJGLInputSender.mouseLeft = false; + case MotionEvent.BUTTON_SECONDARY: CallbackBridge.mouseLeft = false; break; } switch (e.getActionMasked()) { case MotionEvent.ACTION_DOWN: // 0 case MotionEvent.ACTION_POINTER_DOWN: // 5 - LWJGLInputSender.sendMouseKeycode(!LWJGLInputSender.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); + CallbackBridge.sendMouseKeycode(!CallbackBridge.mouseLeft ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); initialX = x; initialY = y; - sendMouseButton(LWJGLInputSender.mouseLeft ? 0 : 1, false); + sendMouseButton(CallbackBridge.mouseLeft ? 0 : 1, false); // theHandler.sendEmptyMessageDelayed(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK, LauncherPreferences.PREF_LONGPRESS_TRIGGER); break; @@ -573,9 +567,9 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, case MotionEvent.ACTION_UP: // 1 case MotionEvent.ACTION_CANCEL: // 3 case MotionEvent.ACTION_POINTER_UP: // 6 - LWJGLInputSender.sendCursorPos(x, y); - LWJGLInputSender.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); - // LWJGLInputSender.putMouseEventWithCoords(!LWJGLInputSender.mouseLeft /* rightOverride */ ? (byte) 1 : (byte) 0, (byte) 0, x, y, 0, System.nanoTime()); + CallbackBridge.sendCursorPos(x, y); + CallbackBridge.sendMouseKeycode(rightOverride ? LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT : LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_LEFT, true); + // CallbackBridge.putMouseEventWithCoords(!CallbackBridge.mouseLeft /* rightOverride */ ? (byte) 1 : (byte) 0, (byte) 0, x, y, 0, System.nanoTime()); /* if (!triggeredLeftMouseButton && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { sendMouseButton(1, true); @@ -586,15 +580,15 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, } */ - sendMouseButton(LWJGLInputSender.mouseLeft ? 0 : 1, true); + sendMouseButton(CallbackBridge.mouseLeft ? 0 : 1, true); // triggeredLeftMouseButton = false; // theHandler.removeMessages(MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK); break; } - debugText.setText(LWJGLInputSender.DEBUG_STRING.toString()); - LWJGLInputSender.DEBUG_STRING.setLength(0); + debugText.setText(CallbackBridge.DEBUG_STRING.toString()); + CallbackBridge.DEBUG_STRING.setLength(0); return true; // If onClick fail with false, change back to true @@ -614,7 +608,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, minecraftGLView.setOnHoverListener(new View.OnHoverListener(){ @Override public boolean onHover(View p1, MotionEvent p2) { - if (!LWJGLInputSender.isGrabbing() && mIsResuming) { + if (!CallbackBridge.isGrabbing() && mIsResuming) { return glTouchListener.onTouch(p1, p2); } return true; @@ -626,8 +620,8 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, private boolean isCalled = false; @Override public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { - LWJGLInputSender.windowWidth = width; - LWJGLInputSender.windowHeight = height; + CallbackBridge.windowWidth = width; + CallbackBridge.windowHeight = height; calculateMcScale(); // Should we do that? @@ -658,9 +652,9 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, @Override public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { - LWJGLInputSender.windowWidth = width; - LWJGLInputSender.windowHeight = height; - LWJGLInputSender.sendUpdateWindowSize(width, height); + CallbackBridge.windowWidth = width; + CallbackBridge.windowHeight = height; + CallbackBridge.sendUpdateWindowSize(width, height); calculateMcScale(); // TODO: Implement this method for GLFW window size callback @@ -746,7 +740,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, @Override protected void onPause() { - if (LWJGLInputSender.isGrabbing()){ + if (CallbackBridge.isGrabbing()){ sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_ESCAPE); } mIsResuming = false; @@ -798,12 +792,12 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, case R.id.control_jump: sendKeyPress(LWJGLGLFWKeycode.GLFW_KEY_SPACE, isDown); break; case R.id.control_primary: sendMouseButton(0, isDown); break; case R.id.control_secondary: - if (LWJGLInputSender.isGrabbing()) { + if (CallbackBridge.isGrabbing()) { sendMouseButton(1, isDown); } else { if (!isDown) { - LWJGLInputSender.sendCursorPos(LWJGLInputSender.mouseX, LWJGLInputSender.mouseY); - LWJGLInputSender.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT); + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); + CallbackBridge.sendMouseKeycode(LWJGLGLFWKeycode.GLFW_MOUSE_BUTTON_RIGHT); } setRightOverride(isDown); } break; @@ -973,9 +967,9 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, public void handleMessage(Message msg) { switch (msg.what) { case MainActivity.MSG_LEFT_MOUSE_BUTTON_CHECK /*1028*/: - int x = LWJGLInputSender.mouseX; - int y = LWJGLInputSender.mouseY; - if (LWJGLInputSender.isGrabbing() && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { + int x = CallbackBridge.mouseX; + int y = CallbackBridge.mouseY; + if (CallbackBridge.isGrabbing() && Math.abs(initialX - x) < fingerStillThreshold && Math.abs(initialY - y) < fingerStillThreshold) { triggeredLeftMouseButton = true; sendMouseButton(0, true); return; @@ -1026,7 +1020,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, } public void toggleMouse(View view) { - if (LWJGLInputSender.isGrabbing()) return; + if (CallbackBridge.isGrabbing()) return; boolean isVis = touchPad.getVisibility() == View.VISIBLE; touchPad.setVisibility(isVis ? View.GONE : View.VISIBLE); @@ -1098,7 +1092,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, public void sendKeyPress(int keyCode, char keyChar, boolean status) { // FIXME keyChar - LWJGLInputSender.sendKeycode(keyCode, /* keyChar, */ status); + CallbackBridge.sendKeycode(keyCode, /* keyChar, */ status); } public void sendKeyPress(char keyChar) { @@ -1113,13 +1107,13 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, public void sendMouseButton(int button, boolean status) { // TODO implement this method!!! - // LWJGLInputSender.setMouseButtonInGrabMode((byte) button, status ? (byte) 1 : (byte) 0); + // CallbackBridge.setMouseButtonInGrabMode((byte) button, status ? (byte) 1 : (byte) 0); } public void calculateMcScale() { int scale = 1; - int screenWidth = LWJGLInputSender.windowWidth; - int screenHeight = LWJGLInputSender.windowHeight; + int screenWidth = CallbackBridge.windowWidth; + int screenHeight = CallbackBridge.windowHeight; while (screenWidth / (scale + 1) >= 320 && screenHeight / (scale + 1) >= 240) { scale++; } @@ -1127,12 +1121,12 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener, } public int handleGuiBar(int x, int y, MotionEvent e) { - if (!LWJGLInputSender.isGrabbing()) { + if (!CallbackBridge.isGrabbing()) { return -1; } - int screenWidth = LWJGLInputSender.windowWidth; - int screenHeight = LWJGLInputSender.windowHeight; + int screenWidth = CallbackBridge.windowWidth; + int screenHeight = CallbackBridge.windowHeight; int barheight = mcscale(20); int barwidth = mcscale(180); int barx = (screenWidth / 2) - (barwidth / 2); diff --git a/app/src/main/java/net/kdt/pojavlaunch/Tools.java b/app/src/main/java/net/kdt/pojavlaunch/Tools.java index 5abd5afa9..53b6b81bd 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/app/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -14,12 +14,10 @@ import java.lang.reflect.*; import java.nio.charset.*; import java.util.*; import java.util.zip.*; -import javax.microedition.khronos.egl.*; +import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.util.*; import net.kdt.pojavlaunch.value.*; -import net.kdt.pojavlaunch.prefs.*; -import java.nio.*; -import org.apache.commons.compress.utils.*; +import org.lwjgl.glfw.*; public final class Tools { @@ -100,8 +98,8 @@ public final class Tools overrideableArgList.add("-Dorg.lwjgl.util.DebugLoader=true"); // GLFW Stub width height - overrideableArgList.add("-Dglfwstub.windowWidth=" + LWJGLInputSender.windowWidth); - overrideableArgList.add("-Dglfwstub.windowHeight=" + LWJGLInputSender.windowHeight); + overrideableArgList.add("-Dglfwstub.windowWidth=" + CallbackBridge.windowWidth); + overrideableArgList.add("-Dglfwstub.windowHeight=" + CallbackBridge.windowHeight); overrideableArgList.add("-Dglfwstub.initEgl=false"); diff --git a/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/ControlButton.java b/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/ControlButton.java index 3fcc1486f..b5d8045c5 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/ControlButton.java +++ b/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/ControlButton.java @@ -1,10 +1,8 @@ package net.kdt.pojavlaunch.value.customcontrols; -import net.kdt.pojavlaunch.*; -import android.view.*; import java.util.*; -import android.content.*; -import android.view.View.*; +import net.kdt.pojavlaunch.*; +import org.lwjgl.glfw.*; public class ControlButton implements Cloneable { @@ -26,10 +24,10 @@ public class ControlButton implements Cloneable if (SPECIAL_BUTTONS == null) { SPECIAL_BUTTONS = new ControlButton[]{ new ControlButton("Keyboard", SPECIALBTN_KEYBOARD, pixelOf2dp * 3 + pixelOf80dp * 2, pixelOf2dp, false), - new ControlButton("GUI", SPECIALBTN_TOGGLECTRL, pixelOf2dp, LWJGLInputSender.windowHeight - pixelOf50dp * 2 + pixelOf2dp * 4), - new ControlButton("PRI", SPECIALBTN_MOUSEPRI, pixelOf2dp, LWJGLInputSender.windowHeight - pixelOf50dp * 4 + pixelOf2dp * 2), - new ControlButton("SEC", SPECIALBTN_MOUSESEC, pixelOf2dp * 3 + pixelOf50dp * 2, LWJGLInputSender.windowHeight - pixelOf50dp * 4 + pixelOf2dp * 2), - new ControlButton("Mouse", SPECIALBTN_VIRTUALMOUSE, LWJGLInputSender.windowWidth - pixelOf80dp, pixelOf2dp, false) + new ControlButton("GUI", SPECIALBTN_TOGGLECTRL, pixelOf2dp, CallbackBridge.windowHeight - pixelOf50dp * 2 + pixelOf2dp * 4), + new ControlButton("PRI", SPECIALBTN_MOUSEPRI, pixelOf2dp, CallbackBridge.windowHeight - pixelOf50dp * 4 + pixelOf2dp * 2), + new ControlButton("SEC", SPECIALBTN_MOUSESEC, pixelOf2dp * 3 + pixelOf50dp * 2, CallbackBridge.windowHeight - pixelOf50dp * 4 + pixelOf2dp * 2), + new ControlButton("Mouse", SPECIALBTN_VIRTUALMOUSE, CallbackBridge.windowWidth - pixelOf80dp, pixelOf2dp, false) }; } diff --git a/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/CustomControls.java b/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/CustomControls.java index 94a4e876f..ff0ec85d4 100644 --- a/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/CustomControls.java +++ b/app/src/main/java/net/kdt/pojavlaunch/value/customcontrols/CustomControls.java @@ -1,8 +1,9 @@ package net.kdt.pojavlaunch.value.customcontrols; +import android.content.*; +import com.google.gson.*; import java.util.*; import net.kdt.pojavlaunch.*; -import com.google.gson.*; -import android.content.*; +import org.lwjgl.glfw.*; public class CustomControls { @@ -29,14 +30,14 @@ public class CustomControls this.button.add(new ControlButton(ctx, R.string.control_listplayers, LWJGLGLFWKeycode.GLFW_KEY_TAB, ControlButton.pixelOf2dp * 4 + ControlButton.pixelOf80dp * 3, ControlButton.pixelOf2dp, false)); this.button.add(new ControlButton(ctx, R.string.control_thirdperson, LWJGLGLFWKeycode.GLFW_KEY_F5, ControlButton.pixelOf2dp, ControlButton.pixelOf30dp + ControlButton.pixelOf2dp, false)); - this.button.add(new ControlButton(ctx, R.string.control_up, LWJGLGLFWKeycode.GLFW_KEY_W, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, LWJGLInputSender.windowHeight - ControlButton.pixelOf2dp * 3 - ControlButton.pixelOf50dp * 3, true)); - this.button.add(new ControlButton(ctx, R.string.control_left, LWJGLGLFWKeycode.GLFW_KEY_A, ControlButton.pixelOf2dp, LWJGLInputSender.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); - this.button.add(new ControlButton(ctx, R.string.control_down, LWJGLGLFWKeycode.GLFW_KEY_S, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, LWJGLInputSender.windowHeight - ControlButton.pixelOf2dp - ControlButton.pixelOf50dp, true)); - this.button.add(new ControlButton(ctx, R.string.control_right, LWJGLGLFWKeycode.GLFW_KEY_D, ControlButton.pixelOf2dp * 3 + ControlButton.pixelOf50dp * 2, LWJGLInputSender.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); + this.button.add(new ControlButton(ctx, R.string.control_up, LWJGLGLFWKeycode.GLFW_KEY_W, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 3 - ControlButton.pixelOf50dp * 3, true)); + this.button.add(new ControlButton(ctx, R.string.control_left, LWJGLGLFWKeycode.GLFW_KEY_A, ControlButton.pixelOf2dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); + this.button.add(new ControlButton(ctx, R.string.control_down, LWJGLGLFWKeycode.GLFW_KEY_S, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp - ControlButton.pixelOf50dp, true)); + this.button.add(new ControlButton(ctx, R.string.control_right, LWJGLGLFWKeycode.GLFW_KEY_D, ControlButton.pixelOf2dp * 3 + ControlButton.pixelOf50dp * 2, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); - this.button.add(new ControlButton(ctx, R.string.control_inventory, LWJGLGLFWKeycode.GLFW_KEY_E, ControlButton.pixelOf2dp * 3 + ControlButton.pixelOf50dp * 2, LWJGLInputSender.windowHeight - ControlButton.pixelOf2dp - ControlButton.pixelOf50dp, true)); - this.button.add(new ControlButton(ctx, R.string.control_shift, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, LWJGLInputSender.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); - this.button.add(new ControlButton(ctx, R.string.control_jump, LWJGLGLFWKeycode.GLFW_KEY_SPACE, LWJGLInputSender.windowWidth - ControlButton.pixelOf2dp * 3 - ControlButton.pixelOf50dp * 2, LWJGLInputSender.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); + this.button.add(new ControlButton(ctx, R.string.control_inventory, LWJGLGLFWKeycode.GLFW_KEY_E, ControlButton.pixelOf2dp * 3 + ControlButton.pixelOf50dp * 2, CallbackBridge.windowHeight - ControlButton.pixelOf2dp - ControlButton.pixelOf50dp, true)); + this.button.add(new ControlButton(ctx, R.string.control_shift, LWJGLGLFWKeycode.GLFW_KEY_LEFT_SHIFT, ControlButton.pixelOf2dp * 2 + ControlButton.pixelOf50dp, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); + this.button.add(new ControlButton(ctx, R.string.control_jump, LWJGLGLFWKeycode.GLFW_KEY_SPACE, CallbackBridge.windowWidth - ControlButton.pixelOf2dp * 3 - ControlButton.pixelOf50dp * 2, CallbackBridge.windowHeight - ControlButton.pixelOf2dp * 2 - ControlButton.pixelOf50dp * 2, true)); } diff --git a/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java new file mode 100644 index 000000000..94089741f --- /dev/null +++ b/app/src/main/java/org/lwjgl/glfw/CallbackBridge.java @@ -0,0 +1,65 @@ +package org.lwjgl.glfw; +import java.io.*; +import java.util.*; + +public class 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 ANDROID_TYPE_GRAB_STATE = 0; + + public static int windowWidth, windowHeight; + public static int mouseX, mouseY; + public static boolean mouseLeft; + public static StringBuilder DEBUG_STRING = new StringBuilder(); + + volatile private static boolean isGrabbing = false; + + public static void sendMouseEvent(int x, int y, int keycode, boolean isDown) { + sendCursorPos(x, y); + sendKeycode(keycode, isDown); + } + + public static void sendCursorPos(int x, int y) { + DEBUG_STRING.append("CursorPos=" + x + ", " + y + "\n"); + mouseX = x; + mouseY = y; + sendData(JRE_TYPE_CURSOR_POS, x + ":" + y); + } + + public static void sendKeycode(int keycode, boolean isDown) { + sendData(JRE_TYPE_KEYCODE_CONTROL, keycode + ":" + Boolean.toString(isDown)); + } + + public static void sendMouseKeycode(int keycode, boolean isDown) { + DEBUG_STRING.append("MouseKey=" + keycode + ", down=" + isDown + "\n"); + sendData(JRE_TYPE_MOUSE_KEYCODE_CONTROL, keycode + ":" + Boolean.toString(isDown)); + } + + public static void sendMouseKeycode(int keycode) { + sendMouseKeycode(keycode, true); + sendMouseKeycode(keycode, false); + } + + public static void sendUpdateWindowSize(int w, int h) { + sendData(JRE_TYPE_WINDOW_SIZE, w + ":" + h); + } + + public static boolean isGrabbing() { + return isGrabbing; + } + + // Called from JRE side + public static void receiveCallback(int type, String data) { + switch (type) { + case ANDROID_TYPE_GRAB_STATE: isGrabbing = Boolean.parseBoolean(data); + } + } + + public static native void sendData(int type, String data); +} + diff --git a/app/src/main/jni/egl_bridge.c b/app/src/main/jni/egl_bridge.c index 76bbd4d06..e8213c3e2 100644 --- a/app/src/main/jni/egl_bridge.c +++ b/app/src/main/jni/egl_bridge.c @@ -36,7 +36,7 @@ JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_JREUtils_setupBridgeWindow(JNIEn potatoBridge.androidWindow = ANativeWindow_fromSurface(env, surface); } -// Called from JNI_OnLoad of liblwjgl_opengl32 +// Called from JNI_OnLoad of liblwjgl_opengl void pojav_openGLOnLoad() { } diff --git a/app/src/main/jni/input_bridge.c b/app/src/main/jni/input_bridge.c index 3fb594b87..a9ca21a20 100644 --- a/app/src/main/jni/input_bridge.c +++ b/app/src/main/jni/input_bridge.c @@ -5,25 +5,46 @@ jclass inputBridgeClass; jmethodID inputBridgeMethod; -JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_LWJGLInputSender_sendDataToJRE(JNIEnv* env, jclass clazz, jint type, jstring data) { - if (runtimeJavaVMPtr != NULL) { - if (!isAndroidThreadAttached) { - // Allow invoke JRE reflection from Android side - (*runtimeJavaVMPtr)->AttachCurrentThread(runtimeJavaVMPtr, &runtimeJNIEnvPtr, NULL); - isAndroidThreadAttached = true; - } +JavaVM *firstJavaVM, secondJavaVM; +JNIEnv *firstJNIEnv, secondJNIEnv; + +void attachThreadIfNeed(bool* isAttached) { + if (!*isAttached && secondJavaVM && secondJniENV) { + (*secondVMPtr)->AttachCurrentThread(secondVMPtr, &secondJNIEnvPtr, NULL); + *isAttached = true; + } +} + +JNIEXPORT void JNICALL Java_org_lwjgl_glfw_CallbackBridge_sendData(JNIEnv* env, jclass clazz, jint type, jstring data) { + if (env == dalvikJNIEnvPtr) { + firstJavaVM = dalvikJavaVMPtr; + firstJNIEnv = dalvikJNIEnvPtr; + secondJavaVM = runtimeJavaVMPtr; + secondJNIEnv = runtimeJNIEnvPtr; - // Convert Dalvik string to JRE string: should or use directly? + attachThreadIfNeed(&isAndroidThreadAttached); + } else if (env == runtimeJNIEnvPtr) { + firstJavaVM = runtimeJavaVMPtr; + firstJNIEnv = runtimeJNIEnvPtr; + secondJavaVM = dalvikJavaVMPtr; + secondJNIEnv = dalvikJNIEnvPtr; + + attachThreadIfNeed(&isRuntimeThreadAttached); + } else { + return; + } + + if (secondJavaVM != NULL) { char *data_c = (char*)(*env)->GetStringUTFChars(env, data, 0); - jstring data_jre = (*runtimeJNIEnvPtr)->NewStringUTF(runtimeJNIEnvPtr, data_c); + jstring data_jre = (*secondJNIEnv)->NewStringUTF(secondJNIEnv, data_c); (*env)->ReleaseStringUTFChars(env, data, data_c); - + if (inputBridgeMethod == NULL) { - inputBridgeClass = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "org/lwjgl/glfw/CallbackReceiver"); - inputBridgeMethod = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, inputBridgeClass, "receiveCallback", "(ILjava/lang/String;)V"); + inputBridgeClass = (*secondJNIEnv)->FindClass(secondJNIEnv, "org/lwjgl/glfw/CallbackBridge"); + inputBridgeMethod = (*secondJNIEnv)->GetStaticMethodID(secondJNIEnv, inputBridgeClass, "receiveCallback", "(ILjava/lang/String;)V"); } - (*runtimeJNIEnvPtr)->CallStaticVoidMethod(runtimeJNIEnvPtr, inputBridgeClass, inputBridgeMethod, type, data_jre); - } + (*secondJNIEnv)->CallStaticVoidMethod(secondJNIEnv, inputBridgeClass, inputBridgeMethod, type, data_jre); + } // else: too early! } diff --git a/app/src/main/jni/utils.h b/app/src/main/jni/utils.h index 36d04038f..58ac6f459 100644 --- a/app/src/main/jni/utils.h +++ b/app/src/main/jni/utils.h @@ -9,7 +9,7 @@ JNIEnv *runtimeJNIEnvPtr; JavaVM *dalvikJavaVMPtr; JNIEnv *dalvikJNIEnvPtr; -bool isAndroidThreadAttached; +bool isAndroidThreadAttached, isRuntimeThreadAttached; char** convert_to_char_array(JNIEnv *env, jobjectArray jstringArray); jobjectArray convert_from_char_array(JNIEnv *env, char **charArray, int num_rows);