diff --git a/app_pojavlauncher/build.gradle b/app_pojavlauncher/build.gradle index a6421dc10..99caaa7bf 100644 --- a/app_pojavlauncher/build.gradle +++ b/app_pojavlauncher/build.gradle @@ -228,6 +228,8 @@ dependencies { // implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.0' + implementation 'top.fifthlight.touchcontroller:proxy-client-android:0.0.4' + implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation project(":MobileGlues") diff --git a/app_pojavlauncher/src/main/AndroidManifest.xml b/app_pojavlauncher/src/main/AndroidManifest.xml index 7cd3261d0..a25fb0d92 100644 --- a/app_pojavlauncher/src/main/AndroidManifest.xml +++ b/app_pojavlauncher/src/main/AndroidManifest.xml @@ -20,6 +20,7 @@ + file.isFile() && file.getName().endsWith(".jar")); + if (mods == null) { + return false; + } + for (File file : mods) { + String name = file.getName().toLowerCase(Locale.ROOT); + if (name.contains("touchcontroller")) { + return true; + } + } + return false; + } + /** * Initialize OpenGL and do checks to see if the GPU of the device is affected by the render * distance issue. 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 d6f168f24..d6dfc112b 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 @@ -70,6 +70,8 @@ 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_FORCE_ENABLE_TOUCHCONTROLLER = false; + public static int PREF_TOUCHCONTROLLER_VIBRATE_LENGTH = 100; public static void loadPreferences(Context ctx) { @@ -112,6 +114,8 @@ 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_FORCE_ENABLE_TOUCHCONTROLLER = DEFAULT_PREF.getBoolean("forceEnableTouchController", false); + PREF_TOUCHCONTROLLER_VIBRATE_LENGTH = DEFAULT_PREF.getInt("touchControllerVibrateLength", 100); 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 7002f8452..bc793cba0 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 @@ -13,6 +13,7 @@ import net.kdt.pojavlaunch.prefs.LauncherPreferences; public class LauncherPreferenceControlFragment extends LauncherPreferenceFragment { private boolean mGyroAvailable = false; + @Override public void onCreatePreferences(Bundle b, String str) { // Get values @@ -20,6 +21,7 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen int prefButtonSize = (int) LauncherPreferences.PREF_BUTTONSIZE; int mouseScale = (int) (LauncherPreferences.PREF_MOUSESCALE * 100); int gyroSampleRate = LauncherPreferences.PREF_GYRO_SAMPLE_RATE; + int touchControllerVibrateLength = LauncherPreferences.PREF_TOUCHCONTROLLER_VIBRATE_LENGTH; float mouseSpeed = LauncherPreferences.PREF_MOUSESPEED; float gyroSpeed = LauncherPreferences.PREF_GYRO_SENSITIVITY; float joystickDeadzone = LauncherPreferences.PREF_DEADZONE_SCALE; @@ -45,7 +47,7 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen CustomSeekBarPreference seek6 = requirePreference("mousespeed", CustomSeekBarPreference.class); - seek6.setValue((int)(mouseSpeed *100f)); + seek6.setValue((int) (mouseSpeed * 100f)); seek6.setSuffix(" %"); CustomSeekBarPreference deadzoneSeek = requirePreference("gamepad_deadzone_scale", @@ -55,22 +57,29 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen Context context = getContext(); - if(context != null) { + if (context != null) { mGyroAvailable = Tools.deviceSupportsGyro(context); } - PreferenceCategory gyroCategory = requirePreference("gyroCategory", + PreferenceCategory gyroCategory = requirePreference("gyroCategory", PreferenceCategory.class); gyroCategory.setVisible(mGyroAvailable); CustomSeekBarPreference gyroSensitivitySeek = requirePreference("gyroSensitivity", CustomSeekBarPreference.class); - gyroSensitivitySeek.setValue((int) (gyroSpeed*100f)); + gyroSensitivitySeek.setValue((int) (gyroSpeed * 100f)); gyroSensitivitySeek.setSuffix(" %"); CustomSeekBarPreference gyroSampleRateSeek = requirePreference("gyroSampleRate", CustomSeekBarPreference.class); gyroSampleRateSeek.setValue(gyroSampleRate); gyroSampleRateSeek.setSuffix(" ms"); + + CustomSeekBarPreference touchControllerVibrateLengthSeek = requirePreference( + "touchControllerVibrateLength", + CustomSeekBarPreference.class); + touchControllerVibrateLengthSeek.setValue(touchControllerVibrateLength); + touchControllerVibrateLengthSeek.setSuffix(" ms"); + computeVisibility(); } @@ -80,7 +89,7 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen computeVisibility(); } - private void computeVisibility(){ + private void computeVisibility() { requirePreference("timeLongPressTrigger").setVisible(!LauncherPreferences.PREF_DISABLE_GESTURES); requirePreference("gyroSensitivity").setVisible(LauncherPreferences.PREF_ENABLE_GYRO); requirePreference("gyroSampleRate").setVisible(LauncherPreferences.PREF_ENABLE_GYRO); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/TouchControllerUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/TouchControllerUtils.java new file mode 100644 index 000000000..c999a283e --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/utils/TouchControllerUtils.java @@ -0,0 +1,114 @@ +package net.kdt.pojavlaunch.utils; + +import android.content.Context; +import android.os.Vibrator; + +import top.fifthlight.touchcontroller.proxy.client.LauncherProxyClient; +import top.fifthlight.touchcontroller.proxy.client.MessageTransport; +import top.fifthlight.touchcontroller.proxy.client.android.transport.UnixSocketTransportKt; +import top.fifthlight.touchcontroller.proxy.message.VibrateMessage; + +import android.system.ErrnoException; +import android.system.Os; +import android.util.Log; +import android.util.SparseIntArray; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + +import net.kdt.pojavlaunch.prefs.LauncherPreferences; + +public class TouchControllerUtils { + private TouchControllerUtils() { + } + + public static LauncherProxyClient proxyClient; + private static final String socketName = "Amethyst"; + + private static class VibrationHandler implements LauncherProxyClient.VibrationHandler { + private final Vibrator vibrator; + + public VibrationHandler(Vibrator vibrator) { + this.vibrator = vibrator; + } + + @Override + @SuppressWarnings("DEPRECATION") + public void vibrate(@NonNull VibrateMessage.Kind kind) { + vibrator.vibrate(LauncherPreferences.PREF_TOUCHCONTROLLER_VIBRATE_LENGTH); + } + } + + private static final SparseIntArray pointerIdMap = new SparseIntArray(); + private static int nextPointerId = 1; + + public static void processTouchEvent(MotionEvent motionEvent, View view) { + if (proxyClient == null) { + return; + } + int pointerId; + switch (motionEvent.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + pointerId = nextPointerId++; + pointerIdMap.put(motionEvent.getPointerId(0), pointerId); + proxyClient.addPointer(pointerId, motionEvent.getX(0) / view.getWidth(), motionEvent.getY(0) / view.getHeight()); + break; + case MotionEvent.ACTION_POINTER_DOWN: + pointerId = nextPointerId++; + int actionIndex = motionEvent.getActionIndex(); + pointerIdMap.put(motionEvent.getPointerId(actionIndex), pointerId); + proxyClient.addPointer(pointerId, motionEvent.getX(actionIndex) / view.getWidth(), motionEvent.getY(actionIndex) / view.getHeight()); + break; + case MotionEvent.ACTION_MOVE: + for (int i = 0; i < motionEvent.getPointerCount(); i++) { + pointerId = pointerIdMap.get(motionEvent.getPointerId(i)); + if (pointerId == 0) { + Log.d("TouchController", "Move pointerId is 0"); + continue; + } + proxyClient.addPointer(pointerId, motionEvent.getX(i) / view.getWidth(), motionEvent.getY(i) / view.getHeight()); + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (proxyClient != null) { + proxyClient.clearPointer(); + pointerIdMap.clear(); + } + break; + case MotionEvent.ACTION_POINTER_UP: + if (proxyClient != null) { + int i = motionEvent.getActionIndex(); + pointerId = pointerIdMap.get(motionEvent.getPointerId(i)); + if (pointerId == 0) { + Log.d("TouchController", "Pointer up pointerId is 0"); + break; + } + pointerIdMap.delete(pointerId); + proxyClient.removePointer(pointerId); + } + break; + } + } + + public static void initialize(Context context) { + if (proxyClient != null) { + return; + } + try { + Os.setenv("TOUCH_CONTROLLER_PROXY_SOCKET", socketName, true); + } catch (ErrnoException e) { + Log.w("TouchController", "Failed to set TouchController environment variable", e); + } + MessageTransport transport = UnixSocketTransportKt.UnixSocketTransport(socketName); + proxyClient = new LauncherProxyClient(transport); + proxyClient.run(); + Vibrator vibrator = ContextCompat.getSystemService(context, Vibrator.class); + if (vibrator != null) { + LauncherProxyClient.VibrationHandler vibrationHandler = new VibrationHandler(vibrator); + proxyClient.setVibrationHandler(vibrationHandler); + } + } +} diff --git a/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml b/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml index 2bc458563..c422d6ccb 100644 --- a/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml +++ b/app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml @@ -399,4 +399,10 @@ 启用实验性的 Compute Shader 扩展 可能有助于解决光影渲染异常。非必要请禁用,可能会导致错误。 OpenGL 报错设置 + + TouchController 设置 + 强制启用 TouchController + 启用 TouchController 集成,即使没有找到模组文件。 + TouchController 震动长度 + 设置使用 TouchController 时的震动长度。 diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml index 2104b8d3a..874252e46 100644 --- a/app_pojavlauncher/src/main/res/values/strings.xml +++ b/app_pojavlauncher/src/main/res/values/strings.xml @@ -456,4 +456,10 @@ Create Neoforge profile Select NeoForge version Sorry, but this version of NeoForge does not have an installer, which is not yet supported. + + TouchController Settings + Force enable TouchController + Force enable TouchController integration, even if mod file is not found. + TouchController vibrate length + Set the length of the vibration when using TouchController. diff --git a/app_pojavlauncher/src/main/res/values/values.xml b/app_pojavlauncher/src/main/res/values/values.xml index 3220345b6..95eaf3533 100644 --- a/app_pojavlauncher/src/main/res/values/values.xml +++ b/app_pojavlauncher/src/main/res/values/values.xml @@ -34,4 +34,6 @@ 8 256 + 10 + 1000 \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/xml/pref_control.xml b/app_pojavlauncher/src/main/res/xml/pref_control.xml index 0d2778e17..77c02f91c 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_control.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_control.xml @@ -164,7 +164,21 @@ - + + + + \ No newline at end of file