diff --git a/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar b/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar
index 4141a08bb..beb1da2cb 100644
Binary files a/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar and b/app_pojavlauncher/src/main/assets/components/lwjgl3/lwjgl-glfw-classes.jar differ
diff --git a/app_pojavlauncher/src/main/assets/components/lwjgl3/version b/app_pojavlauncher/src/main/assets/components/lwjgl3/version
index a4b0232d5..f476a7b5a 100644
--- a/app_pojavlauncher/src/main/assets/components/lwjgl3/version
+++ b/app_pojavlauncher/src/main/assets/components/lwjgl3/version
@@ -1 +1 @@
-1732218529630
\ No newline at end of file
+1735293224932
\ No newline at end of file
diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java
index dd9f5f10f..415d13f26 100644
--- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java
@@ -29,6 +29,7 @@ import androidx.annotation.RequiresApi;
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
import net.kdt.pojavlaunch.customcontrols.gamepad.DefaultDataProvider;
import net.kdt.pojavlaunch.customcontrols.gamepad.Gamepad;
+import net.kdt.pojavlaunch.customcontrols.gamepad.direct.DirectGamepad;
import net.kdt.pojavlaunch.customcontrols.mouse.AbstractTouchpad;
import net.kdt.pojavlaunch.customcontrols.mouse.AndroidPointerCapture;
import net.kdt.pojavlaunch.customcontrols.mouse.InGUIEventProcessor;
@@ -40,6 +41,7 @@ import net.kdt.pojavlaunch.utils.MCOptionUtils;
import org.lwjgl.glfw.CallbackBridge;
+import fr.spse.gamepad_remapper.GamepadHandler;
import fr.spse.gamepad_remapper.RemapperManager;
import fr.spse.gamepad_remapper.RemapperView;
@@ -48,7 +50,7 @@ import fr.spse.gamepad_remapper.RemapperView;
*/
public class MinecraftGLSurface extends View implements GrabListener {
/* Gamepad object for gamepad inputs, instantiated on need */
- private Gamepad mGamepad = null;
+ private GamepadHandler mGamepadHandler;
/* The RemapperView.Builder object allows you to set which buttons to remap */
private final RemapperManager mInputManager = new RemapperManager(getContext(), new RemapperView.Builder(null)
.remapA(true)
@@ -203,7 +205,11 @@ public class MinecraftGLSurface extends View implements GrabListener {
}
private void createGamepad(View contextView, InputDevice inputDevice) {
- mGamepad = new Gamepad(contextView, inputDevice, DefaultDataProvider.INSTANCE, true);
+ if(LauncherPreferences.PREF_DIRECT_CONTROLLER) {
+ mGamepadHandler = new DirectGamepad();
+ }else {
+ mGamepadHandler = new Gamepad(contextView, inputDevice, DefaultDataProvider.INSTANCE, true);
+ }
}
/**
@@ -215,9 +221,9 @@ public class MinecraftGLSurface extends View implements GrabListener {
int mouseCursorIndex = -1;
if(Gamepad.isGamepadEvent(event)){
- if(mGamepad == null) createGamepad(this, event.getDevice());
+ if(mGamepadHandler == null) createGamepad(this, event.getDevice());
- mInputManager.handleMotionEventInput(getContext(), event, mGamepad);
+ mInputManager.handleMotionEventInput(getContext(), event, mGamepadHandler);
return true;
}
@@ -287,9 +293,9 @@ public class MinecraftGLSurface extends View implements GrabListener {
}
if(Gamepad.isGamepadEvent(event)){
- if(mGamepad == null) createGamepad(this, event.getDevice());
+ if(mGamepadHandler == null) createGamepad(this, event.getDevice());
- mInputManager.handleKeyEventInput(getContext(), event, mGamepad);
+ mInputManager.handleKeyEventInput(getContext(), event, mGamepadHandler);
return true;
}
diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java
index 49fccca08..03466a3e7 100644
--- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/Gamepad.java
@@ -26,7 +26,6 @@ import androidx.core.math.MathUtils;
import net.kdt.pojavlaunch.GrabListener;
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
import net.kdt.pojavlaunch.R;
-import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.utils.MCOptionUtils;
import org.lwjgl.glfw.CallbackBridge;
diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/DirectGamepad.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/DirectGamepad.java
new file mode 100644
index 000000000..2d600eec2
--- /dev/null
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/DirectGamepad.java
@@ -0,0 +1,74 @@
+package net.kdt.pojavlaunch.customcontrols.gamepad.direct;
+
+import static android.view.MotionEvent.AXIS_HAT_X;
+import static android.view.MotionEvent.AXIS_HAT_Y;
+import static org.lwjgl.glfw.CallbackBridge.sGamepadAxisBuffer;
+import static org.lwjgl.glfw.CallbackBridge.sGamepadButtonBuffer;
+
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import fr.spse.gamepad_remapper.GamepadHandler;
+
+public class DirectGamepad implements GamepadHandler {
+ @Override
+ public void handleGamepadInput(int keycode, float value) {
+ int gKeycode = -1, gAxis = -1;
+ switch (keycode) {
+ case KeyEvent.KEYCODE_BUTTON_A: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_A; break;
+ case KeyEvent.KEYCODE_BUTTON_B: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_B; break;
+ case KeyEvent.KEYCODE_BUTTON_X: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_X; break;
+ case KeyEvent.KEYCODE_BUTTON_Y: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_Y; break;
+ case KeyEvent.KEYCODE_BUTTON_L1: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER; break;
+ case KeyEvent.KEYCODE_BUTTON_R1: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER; break;
+ case KeyEvent.KEYCODE_BUTTON_L2:
+ case MotionEvent.AXIS_LTRIGGER:
+ gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER;
+ break;
+ case KeyEvent.KEYCODE_BUTTON_R2:
+ case MotionEvent.AXIS_RTRIGGER:
+ gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER;
+ break;
+ case KeyEvent.KEYCODE_BUTTON_THUMBL: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_LEFT_THUMB; break;
+ case KeyEvent.KEYCODE_BUTTON_THUMBR: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB; break;
+ case KeyEvent.KEYCODE_BUTTON_START: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_START; break;
+ case KeyEvent.KEYCODE_BUTTON_SELECT: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_BACK; break;
+ case KeyEvent.KEYCODE_DPAD_UP: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_UP; break;
+ case KeyEvent.KEYCODE_DPAD_DOWN: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_DOWN; break;
+ case KeyEvent.KEYCODE_DPAD_LEFT: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_LEFT; break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT: gKeycode = GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT; break;
+ case KeyEvent.KEYCODE_DPAD_CENTER: break; // TODO
+ case MotionEvent.AXIS_X: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_LEFT_X; break;
+ case MotionEvent.AXIS_Y: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_LEFT_Y; break;
+ case MotionEvent.AXIS_Z: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_RIGHT_X; break;
+ case MotionEvent.AXIS_RZ: gAxis = GamepadKeycodes.GLFW_GAMEPAD_AXIS_RIGHT_Y; break;
+ case AXIS_HAT_X:
+ sGamepadButtonBuffer.put(
+ GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_LEFT,
+ value < -0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE
+ );
+ sGamepadButtonBuffer.put(
+ GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT,
+ value > 0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE
+ );
+ return;
+ case AXIS_HAT_Y:
+ sGamepadButtonBuffer.put(
+ GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_UP,
+ value < -0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE
+ );
+ sGamepadButtonBuffer.put(
+ GamepadKeycodes.GLFW_GAMEPAD_BUTTON_DPAD_DOWN,
+ value > 0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE
+ );
+ return;
+ }
+ if(gKeycode != -1) {
+ sGamepadButtonBuffer.put(gKeycode, value > 0.85 ? GamepadKeycodes.GLFW_PRESS : GamepadKeycodes.GLFW_RELEASE);
+ }
+ if(gAxis != -1) {
+ sGamepadAxisBuffer.put(gAxis, value);
+ }
+ }
+}
diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/GamepadKeycodes.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/GamepadKeycodes.java
new file mode 100644
index 000000000..b175e3d66
--- /dev/null
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/gamepad/direct/GamepadKeycodes.java
@@ -0,0 +1,36 @@
+package net.kdt.pojavlaunch.customcontrols.gamepad.direct;
+
+public class GamepadKeycodes {
+ public static final byte GLFW_RELEASE = 0;
+ public static final byte GLFW_PRESS = 1;
+ public static int NUM_KEYCODES = 0;
+
+ public static final short GLFW_GAMEPAD_BUTTON_A = 0;
+ public static final short GLFW_GAMEPAD_BUTTON_B = 1;
+ public static final short GLFW_GAMEPAD_BUTTON_X = 2;
+ public static final short GLFW_GAMEPAD_BUTTON_Y = 3;
+ public static final short GLFW_GAMEPAD_BUTTON_LEFT_BUMPER = 4;
+ public static final short GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER = 5;
+ public static final short GLFW_GAMEPAD_BUTTON_BACK = 6;
+ public static final short GLFW_GAMEPAD_BUTTON_START = 7;
+ public static final short GLFW_GAMEPAD_BUTTON_GUIDE = 8;
+ public static final short GLFW_GAMEPAD_BUTTON_LEFT_THUMB = 9;
+ public static final short GLFW_GAMEPAD_BUTTON_RIGHT_THUMB = 10;
+ public static final short GLFW_GAMEPAD_BUTTON_DPAD_UP = 11;
+ public static final short GLFW_GAMEPAD_BUTTON_DPAD_RIGHT = 12;
+ public static final short GLFW_GAMEPAD_BUTTON_DPAD_DOWN = 13;
+ public static final short GLFW_GAMEPAD_BUTTON_DPAD_LEFT = 14;
+ public static final short GLFW_GAMEPAD_BUTTON_LAST = GLFW_GAMEPAD_BUTTON_DPAD_LEFT;
+ public static final short GLFW_GAMEPAD_BUTTON_CROSS = GLFW_GAMEPAD_BUTTON_A;
+ public static final short GLFW_GAMEPAD_BUTTON_CIRCLE = GLFW_GAMEPAD_BUTTON_B;
+ public static final short GLFW_GAMEPAD_BUTTON_SQUARE = GLFW_GAMEPAD_BUTTON_X;
+ public static final short GLFW_GAMEPAD_BUTTON_TRIANGLE = GLFW_GAMEPAD_BUTTON_Y;
+
+ public static final short GLFW_GAMEPAD_AXIS_LEFT_X = 0;
+ public static final short GLFW_GAMEPAD_AXIS_LEFT_Y = 1;
+ public static final short GLFW_GAMEPAD_AXIS_RIGHT_X = 2;
+ public static final short GLFW_GAMEPAD_AXIS_RIGHT_Y = 3;
+ public static final short GLFW_GAMEPAD_AXIS_LEFT_TRIGGER = 4;
+ public static final short GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER = 5;
+ public static final short GLFW_GAMEPAD_AXIS_LAST = GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER;
+}
diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java
index b5480596f..fa2b25461 100644
--- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java
@@ -67,6 +67,7 @@ public class LauncherPreferences {
public static String PREF_DOWNLOAD_SOURCE = "default";
public static boolean PREF_SKIP_NOTIFICATION_PERMISSION_CHECK = false;
public static boolean PREF_VSYNC_IN_ZINK = true;
+ public static boolean PREF_DIRECT_CONTROLLER = false;
public static void loadPreferences(Context ctx) {
@@ -109,6 +110,7 @@ public class LauncherPreferences {
PREF_VERIFY_MANIFEST = DEFAULT_PREF.getBoolean("verifyManifest", true);
PREF_SKIP_NOTIFICATION_PERMISSION_CHECK = DEFAULT_PREF.getBoolean(PREF_KEY_SKIP_NOTIFICATION_CHECK, false);
PREF_VSYNC_IN_ZINK = DEFAULT_PREF.getBoolean("vsync_in_zink", true);
+ PREF_DIRECT_CONTROLLER = DEFAULT_PREF.getBoolean("directController", false);
String argLwjglLibname = "-Dorg.lwjgl.opengl.libname=";
for (String arg : JREUtils.parseJavaArguments(PREF_CUSTOM_JAVA_ARGS)) {
diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java
index 11f34e5dc..b9ae1e60e 100644
--- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java
@@ -89,6 +89,7 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen
requirePreference("gyroInvertX").setVisible(LauncherPreferences.PREF_ENABLE_GYRO);
requirePreference("gyroInvertY").setVisible(LauncherPreferences.PREF_ENABLE_GYRO);
requirePreference("gyroSmoothing").setVisible(LauncherPreferences.PREF_ENABLE_GYRO);
+ requirePreference("_frag_changeKeyBindings").setVisible(!LauncherPreferences.PREF_DIRECT_CONTROLLER);
}
}
diff --git a/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java
index 6a2697c74..a41b5e228 100644
--- a/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java
+++ b/app_pojavlauncher/src/main/java/org/lwjgl/glfw/CallbackBridge.java
@@ -8,6 +8,9 @@ import android.view.Choreographer;
import androidx.annotation.Keep;
import androidx.annotation.Nullable;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
import java.util.ArrayList;
import dalvik.annotation.optimization.CriticalNative;
@@ -27,6 +30,9 @@ public class CallbackBridge {
public volatile static boolean holdingAlt, holdingCapslock, holdingCtrl,
holdingNumlock, holdingShift;
+ public static final ByteBuffer sGamepadButtonBuffer;
+ public static final FloatBuffer sGamepadAxisBuffer;
+
public static void putMouseEventWithCoords(int button, float x, float y) {
putMouseEventWithCoords(button, true, x, y);
sChoreographer.postFrameCallbackDelayed(l -> putMouseEventWithCoords(button, false, x, y), 33);
@@ -193,6 +199,11 @@ public class CallbackBridge {
grabListeners.remove(listener);
}
}
+ public static FloatBuffer createGamepadAxisBuffer() {
+ ByteBuffer axisByteBuffer = nativeCreateGamepadAxisBuffer();
+ // NOTE: hardcoded order (also in jre_lwjgl3glfw CallbackBridge)
+ return axisByteBuffer.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer();
+ }
@Keep @CriticalNative public static native void nativeSetUseInputStackQueue(boolean useInputStackQueue);
@@ -206,8 +217,12 @@ public class CallbackBridge {
@Keep @CriticalNative private static native void nativeSendScroll(double xoffset, double yoffset);
@Keep @CriticalNative private static native void nativeSendScreenSize(int width, int height);
public static native void nativeSetWindowAttrib(int attrib, int value);
+ private static native ByteBuffer nativeCreateGamepadButtonBuffer();
+ private static native ByteBuffer nativeCreateGamepadAxisBuffer();
static {
System.loadLibrary("pojavexec");
+ sGamepadButtonBuffer = nativeCreateGamepadButtonBuffer();
+ sGamepadAxisBuffer = createGamepadAxisBuffer();
}
}
diff --git a/app_pojavlauncher/src/main/jni/environ/environ.h b/app_pojavlauncher/src/main/jni/environ/environ.h
index fbfdb1b09..62ec4a45d 100644
--- a/app_pojavlauncher/src/main/jni/environ/environ.h
+++ b/app_pojavlauncher/src/main/jni/environ/environ.h
@@ -28,6 +28,11 @@ typedef void GLFW_invoke_Key_func(void* window, int key, int scancode, int actio
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 struct {
+ unsigned char buttons [15];
+ float axes[6];
+} GLFWgamepadstate;
+
struct pojav_environ_s {
struct ANativeWindow* pojavWindow;
basic_render_window_t* mainWindowBundle;
@@ -58,6 +63,7 @@ struct pojav_environ_s {
bool isInputReady, isCursorEntered, isUseStackQueueCall, shouldUpdateMouse;
bool shouldUpdateMonitorSize, monitorSizeConsumed;
int savedWidth, savedHeight;
+ GLFWgamepadstate gamepadState;
#define ADD_CALLBACK_WWIN(NAME) \
GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME;
ADD_CALLBACK_WWIN(Char);
diff --git a/app_pojavlauncher/src/main/jni/input_bridge_v3.c b/app_pojavlauncher/src/main/jni/input_bridge_v3.c
index 03bb79f62..3bfac1f07 100644
--- a/app_pojavlauncher/src/main/jni/input_bridge_v3.c
+++ b/app_pojavlauncher/src/main/jni/input_bridge_v3.c
@@ -40,9 +40,10 @@ jint JNI_OnLoad(JavaVM* vm, __attribute__((unused)) void* reserved) {
//Save dalvik global JavaVM pointer
pojav_environ->dalvikJavaVMPtr = vm;
(*vm)->GetEnv(vm, (void**) &pojav_environ->dalvikJNIEnvPtr_ANDROID, JNI_VERSION_1_4);
- pojav_environ->bridgeClazz = (*pojav_environ->dalvikJNIEnvPtr_ANDROID)->NewGlobalRef(pojav_environ->dalvikJNIEnvPtr_ANDROID,(*pojav_environ->dalvikJNIEnvPtr_ANDROID) ->FindClass(pojav_environ->dalvikJNIEnvPtr_ANDROID,"org/lwjgl/glfw/CallbackBridge"));
- pojav_environ->method_accessAndroidClipboard = (*pojav_environ->dalvikJNIEnvPtr_ANDROID)->GetStaticMethodID(pojav_environ->dalvikJNIEnvPtr_ANDROID, pojav_environ->bridgeClazz, "accessAndroidClipboard", "(ILjava/lang/String;)Ljava/lang/String;");
- pojav_environ->method_onGrabStateChanged = (*pojav_environ->dalvikJNIEnvPtr_ANDROID)->GetStaticMethodID(pojav_environ->dalvikJNIEnvPtr_ANDROID, pojav_environ->bridgeClazz, "onGrabStateChanged", "(Z)V");
+ JNIEnv *env = pojav_environ->dalvikJNIEnvPtr_ANDROID;
+ pojav_environ->bridgeClazz = (*env)->NewGlobalRef(env,(*env) ->FindClass(env,"org/lwjgl/glfw/CallbackBridge"));
+ pojav_environ->method_accessAndroidClipboard = (*env)->GetStaticMethodID(env, pojav_environ->bridgeClazz, "accessAndroidClipboard", "(ILjava/lang/String;)Ljava/lang/String;");
+ pojav_environ->method_onGrabStateChanged = (*env)->GetStaticMethodID(env, pojav_environ->bridgeClazz, "onGrabStateChanged", "(Z)V");
pojav_environ->isUseStackQueueCall = JNI_FALSE;
} else if (pojav_environ->dalvikJavaVMPtr != vm) {
__android_log_print(ANDROID_LOG_INFO, "Native", "Saving JVM environ...");
@@ -644,3 +645,18 @@ static void registerFunctions(JNIEnv *env) {
use_critical_cc ? critical_fcns : noncritical_fcns,
sizeof(critical_fcns)/sizeof(critical_fcns[0]));
}
+
+JNIEXPORT jlong JNICALL
+Java_org_lwjgl_glfw_GLFW_internalGetGamepadDataPointer(JNIEnv *env, jclass clazz) {
+ return (jlong) &pojav_environ->gamepadState;
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_lwjgl_glfw_CallbackBridge_nativeCreateGamepadButtonBuffer(JNIEnv *env, jclass clazz) {
+ return (*env)->NewDirectByteBuffer(env, &pojav_environ->gamepadState.buttons, sizeof(pojav_environ->gamepadState.buttons));
+}
+
+JNIEXPORT jobject JNICALL
+Java_org_lwjgl_glfw_CallbackBridge_nativeCreateGamepadAxisBuffer(JNIEnv *env, jclass clazz) {
+ return (*env)->NewDirectByteBuffer(env, &pojav_environ->gamepadState.axes, sizeof(pojav_environ->gamepadState.axes));
+}
\ No newline at end of file
diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml
index 91104432d..2aff163bf 100644
--- a/app_pojavlauncher/src/main/res/values/strings.xml
+++ b/app_pojavlauncher/src/main/res/values/strings.xml
@@ -422,4 +422,6 @@
Unsuitable username
The username must be between 3–16 characters long, and must only contain latin letters, arabic numerals and underscores.
Quick settings
+ Use direct controller input
+ Disables keyboard/mouse emulation and lets the game use gamepad inputs directly.
diff --git a/app_pojavlauncher/src/main/res/xml/pref_control.xml b/app_pojavlauncher/src/main/res/xml/pref_control.xml
index 0d2778e17..cd0093bce 100644
--- a/app_pojavlauncher/src/main/res/xml/pref_control.xml
+++ b/app_pojavlauncher/src/main/res/xml/pref_control.xml
@@ -144,7 +144,13 @@
+
diff --git a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java
index 74b923867..17d25e203 100644
--- a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java
+++ b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java
@@ -1,4 +1,5 @@
package org.lwjgl.glfw;
+import java.nio.ByteBuffer;
import java.util.*;
public class CallbackBridge {
@@ -47,5 +48,7 @@ public class CallbackBridge {
public static native boolean nativeSetInputReady(boolean ready);
public static native String nativeClipboard(int action, byte[] copy);
public static native void nativeSetGrabbing(boolean grab);
+ public static native ByteBuffer nativeCreateGamepadButtonBuffer();
+ public static native ByteBuffer nativeCreateGamepadAxisBuffer();
}
diff --git a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java
index 53ea33596..b878cb149 100644
--- a/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java
+++ b/jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFW.java
@@ -13,6 +13,7 @@ import javax.annotation.*;
import org.lwjgl.*;
import org.lwjgl.system.*;
+import org.lwjgl.system.MemoryUtil;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.system.APIUtil.*;
@@ -24,8 +25,9 @@ import java.util.*;
public class GLFW
{
- static FloatBuffer joystickData = (FloatBuffer)FloatBuffer.allocate(8).flip();
- static ByteBuffer buttonData = (ByteBuffer)ByteBuffer.allocate(8).flip();
+ static FloatBuffer joystickAxisData;
+ static ByteBuffer joystickButtonData;
+ static ByteBuffer empty = (ByteBuffer)ByteBuffer.allocate(0);
/** The major version number of the GLFW library. This is incremented when the API is changed in non-compatible ways. */
public static final int GLFW_VERSION_MAJOR = 3;
@@ -515,6 +517,7 @@ public class GLFW
private static final String PROP_WINDOW_WIDTH = "glfwstub.windowWidth";
private static final String PROP_WINDOW_HEIGHT= "glfwstub.windowHeight";
public static long mainContext = 0;
+ private static long gamepadDataPointer;
static {
try {
@@ -636,6 +639,8 @@ public class GLFW
return win;
}
+ private static native long internalGetGamepadDataPointer();
+
// Generated stub callback methods
public static GLFWCharCallback glfwSetCharCallback(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("GLFWcharfun") GLFWCharCallbackI cbfun) {
GLFWCharCallback lastCallback = mGLFWCharCallback;
@@ -805,6 +810,10 @@ public class GLFW
mGLFWInitialTime = (double) System.nanoTime();
long __functionAddress = Functions.Init;
isGLFWReady = invokeI(__functionAddress) != 0;
+ gamepadDataPointer = internalGetGamepadDataPointer();
+ // NOTE: hardcoded order (also in android CallbackBridge)
+ joystickAxisData = CallbackBridge.nativeCreateGamepadAxisBuffer().order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer();
+ joystickButtonData = CallbackBridge.nativeCreateGamepadButtonBuffer();
}
return isGLFWReady;
}
@@ -1201,50 +1210,59 @@ public class GLFW
}
public static boolean glfwJoystickPresent(int jid) {
- if(jid == 0) {
+ if(jid == GLFW_JOYSTICK_1) {
return true;
}else return false;
}
public static String glfwGetJoystickName(int jid) {
- if(jid == 0) {
- return "AIC event bus controller";
+ if(jid == GLFW_JOYSTICK_1) {
+ return "Pojav XBOX 360 compatible gamepad";
}else return null;
}
public static FloatBuffer glfwGetJoystickAxes(int jid) {
- if(jid == 0) {
- return joystickData;
+ if(jid == GLFW_JOYSTICK_1) {
+ return joystickAxisData;
}else return null;
}
public static ByteBuffer glfwGetJoystickButtons(int jid) {
- if(jid == 0) {
- return buttonData;
+ if(jid == GLFW_JOYSTICK_1) {
+ return joystickButtonData;
}else return null;
}
- public static ByteBuffer glfwGetjoystickHats(int jid) {
- return null;
+ public static ByteBuffer glfwGetJoystickHats(int jid) {
+ if(jid == GLFW_JOYSTICK_1) {
+ return empty; // Maybe implement this later?
+ }else return null;
}
public static boolean glfwJoystickIsGamepad(int jid) {
- if(jid == 0) return true;
+ if(jid == GLFW_JOYSTICK_1) return true;
else return false;
}
public static String glfwGetJoystickGUID(int jid) {
- if(jid == 0) return "aio0";
+ // 16 8-bit characters to be compatible with SDL_GUID
+ if(jid == GLFW_JOYSTICK_1) return "AAAAAAAAAAAAAAAA";
else return null;
}
+
+ private static long mUserPointer;
+
public static long glfwGetJoystickUserPointer(int jid) {
- return 0;
+ return mUserPointer;
}
public static void glfwSetJoystickUserPointer(int jid, long pointer) {
-
+ mUserPointer = pointer;
}
public static boolean glfwUpdateGamepadMappings(ByteBuffer string) {
return false;
}
public static String glfwGetGamepadName(int jid) {
- return null;
+ if(jid == GLFW_JOYSTICK_1) return "Pojav XBOX 360 compatible gamepad";
+ else return null;
}
public static boolean glfwGetGamepadState(int jid, GLFWGamepadState state) {
- return false;
+ if(jid != 0) return false;
+ MemoryUtil.memCopy(gamepadDataPointer, state.address(), state.sizeof());
+ return true;
}
/** Array version of: {@link #glfwGetVersion GetVersion} */