Skip to content

Commit 456f50a

Browse files
authored
Merge pull request #42 from TouchController/v3_openjdk
TouchController touch input integration
2 parents 433f217 + b7c61d4 commit 456f50a

12 files changed

Lines changed: 195 additions & 7 deletions

File tree

app_pojavlauncher/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ dependencies {
228228

229229
// implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.0'
230230

231+
implementation 'top.fifthlight.touchcontroller:proxy-client-android:0.0.4'
232+
231233
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
232234

233235
implementation project(":MobileGlues")

app_pojavlauncher/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
2121
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
2222
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
23+
<uses-permission android:name="android.permission.VIBRATE" />
2324

2425
<application
2526
android:name=".PojavApplication"

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MainActivity.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import net.kdt.pojavlaunch.services.GameService;
6464
import net.kdt.pojavlaunch.utils.JREUtils;
6565
import net.kdt.pojavlaunch.utils.MCOptionUtils;
66+
import net.kdt.pojavlaunch.utils.TouchControllerUtils;
6667
import net.kdt.pojavlaunch.value.MinecraftAccount;
6768
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
6869
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
@@ -102,8 +103,14 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
102103
@Override
103104
public void onCreate(Bundle savedInstanceState) {
104105
super.onCreate(savedInstanceState);
106+
105107
minecraftProfile = LauncherProfiles.getCurrentProfile();
106-
MCOptionUtils.load(Tools.getGameDirPath(minecraftProfile).getAbsolutePath());
108+
109+
String gameDirPath = Tools.getGameDirPath(minecraftProfile).getAbsolutePath();
110+
MCOptionUtils.load(gameDirPath);
111+
if (Tools.hasTouchController(new File(gameDirPath)) || LauncherPreferences.PREF_FORCE_ENABLE_TOUCHCONTROLLER) {
112+
TouchControllerUtils.initialize(this);
113+
}
107114

108115
Intent gameServiceIntent = new Intent(this, GameService.class);
109116
// Start the service a bit early

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MinecraftGLSurface.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
4040
import net.kdt.pojavlaunch.utils.JREUtils;
4141
import net.kdt.pojavlaunch.utils.MCOptionUtils;
42+
import net.kdt.pojavlaunch.utils.TouchControllerUtils;
4243

4344
import org.lwjgl.glfw.CallbackBridge;
4445

@@ -202,6 +203,7 @@ public boolean onTouchEvent(MotionEvent e) {
202203
CallbackBridge.sendCursorPos( e.getX(i) * LauncherPreferences.PREF_SCALE_FACTOR, e.getY(i) * LauncherPreferences.PREF_SCALE_FACTOR);
203204
return true; //mouse event handled successfully
204205
}
206+
TouchControllerUtils.processTouchEvent(e, this);
205207
if (mIngameProcessor == null || mInGUIProcessor == null) return true;
206208
return mCurrentTouchProcessor.processTouchEvent(e);
207209
}

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,27 @@ private static boolean hasSodium(File gameDir) {
227227
return false;
228228
}
229229

230+
/**
231+
* Search for TouchController mod to automatically enable TouchController mod support.
232+
*
233+
* @param gameDir current game directory
234+
* @return whether TouchController is found
235+
*/
236+
public static boolean hasTouchController(File gameDir) {
237+
File modsDir = new File(gameDir, "mods");
238+
File[] mods = modsDir.listFiles(file -> file.isFile() && file.getName().endsWith(".jar"));
239+
if (mods == null) {
240+
return false;
241+
}
242+
for (File file : mods) {
243+
String name = file.getName().toLowerCase(Locale.ROOT);
244+
if (name.contains("touchcontroller")) {
245+
return true;
246+
}
247+
}
248+
return false;
249+
}
250+
230251
/**
231252
* Initialize OpenGL and do checks to see if the GPU of the device is affected by the render
232253
* distance issue.

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public class LauncherPreferences {
7070
public static String PREF_DOWNLOAD_SOURCE = "default";
7171
public static boolean PREF_SKIP_NOTIFICATION_PERMISSION_CHECK = false;
7272
public static boolean PREF_VSYNC_IN_ZINK = true;
73+
public static boolean PREF_FORCE_ENABLE_TOUCHCONTROLLER = false;
74+
public static int PREF_TOUCHCONTROLLER_VIBRATE_LENGTH = 100;
7375

7476

7577
public static void loadPreferences(Context ctx) {
@@ -112,6 +114,8 @@ public static void loadPreferences(Context ctx) {
112114
PREF_VERIFY_MANIFEST = DEFAULT_PREF.getBoolean("verifyManifest", true);
113115
PREF_SKIP_NOTIFICATION_PERMISSION_CHECK = DEFAULT_PREF.getBoolean(PREF_KEY_SKIP_NOTIFICATION_CHECK, false);
114116
PREF_VSYNC_IN_ZINK = DEFAULT_PREF.getBoolean("vsync_in_zink", true);
117+
PREF_FORCE_ENABLE_TOUCHCONTROLLER = DEFAULT_PREF.getBoolean("forceEnableTouchController", false);
118+
PREF_TOUCHCONTROLLER_VIBRATE_LENGTH = DEFAULT_PREF.getInt("touchControllerVibrateLength", 100);
115119

116120
String argLwjglLibname = "-Dorg.lwjgl.opengl.libname=";
117121
for (String arg : JREUtils.parseJavaArguments(PREF_CUSTOM_JAVA_ARGS)) {

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/screens/LauncherPreferenceControlFragment.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313

1414
public class LauncherPreferenceControlFragment extends LauncherPreferenceFragment {
1515
private boolean mGyroAvailable = false;
16+
1617
@Override
1718
public void onCreatePreferences(Bundle b, String str) {
1819
// Get values
1920
int longPressTrigger = LauncherPreferences.PREF_LONGPRESS_TRIGGER;
2021
int prefButtonSize = (int) LauncherPreferences.PREF_BUTTONSIZE;
2122
int mouseScale = (int) (LauncherPreferences.PREF_MOUSESCALE * 100);
2223
int gyroSampleRate = LauncherPreferences.PREF_GYRO_SAMPLE_RATE;
24+
int touchControllerVibrateLength = LauncherPreferences.PREF_TOUCHCONTROLLER_VIBRATE_LENGTH;
2325
float mouseSpeed = LauncherPreferences.PREF_MOUSESPEED;
2426
float gyroSpeed = LauncherPreferences.PREF_GYRO_SENSITIVITY;
2527
float joystickDeadzone = LauncherPreferences.PREF_DEADZONE_SCALE;
@@ -45,7 +47,7 @@ public void onCreatePreferences(Bundle b, String str) {
4547

4648
CustomSeekBarPreference seek6 = requirePreference("mousespeed",
4749
CustomSeekBarPreference.class);
48-
seek6.setValue((int)(mouseSpeed *100f));
50+
seek6.setValue((int) (mouseSpeed * 100f));
4951
seek6.setSuffix(" %");
5052

5153
CustomSeekBarPreference deadzoneSeek = requirePreference("gamepad_deadzone_scale",
@@ -55,22 +57,29 @@ public void onCreatePreferences(Bundle b, String str) {
5557

5658

5759
Context context = getContext();
58-
if(context != null) {
60+
if (context != null) {
5961
mGyroAvailable = Tools.deviceSupportsGyro(context);
6062
}
61-
PreferenceCategory gyroCategory = requirePreference("gyroCategory",
63+
PreferenceCategory gyroCategory = requirePreference("gyroCategory",
6264
PreferenceCategory.class);
6365
gyroCategory.setVisible(mGyroAvailable);
6466

6567
CustomSeekBarPreference gyroSensitivitySeek = requirePreference("gyroSensitivity",
6668
CustomSeekBarPreference.class);
67-
gyroSensitivitySeek.setValue((int) (gyroSpeed*100f));
69+
gyroSensitivitySeek.setValue((int) (gyroSpeed * 100f));
6870
gyroSensitivitySeek.setSuffix(" %");
6971

7072
CustomSeekBarPreference gyroSampleRateSeek = requirePreference("gyroSampleRate",
7173
CustomSeekBarPreference.class);
7274
gyroSampleRateSeek.setValue(gyroSampleRate);
7375
gyroSampleRateSeek.setSuffix(" ms");
76+
77+
CustomSeekBarPreference touchControllerVibrateLengthSeek = requirePreference(
78+
"touchControllerVibrateLength",
79+
CustomSeekBarPreference.class);
80+
touchControllerVibrateLengthSeek.setValue(touchControllerVibrateLength);
81+
touchControllerVibrateLengthSeek.setSuffix(" ms");
82+
7483
computeVisibility();
7584
}
7685

@@ -80,7 +89,7 @@ public void onSharedPreferenceChanged(SharedPreferences p, String s) {
8089
computeVisibility();
8190
}
8291

83-
private void computeVisibility(){
92+
private void computeVisibility() {
8493
requirePreference("timeLongPressTrigger").setVisible(!LauncherPreferences.PREF_DISABLE_GESTURES);
8594
requirePreference("gyroSensitivity").setVisible(LauncherPreferences.PREF_ENABLE_GYRO);
8695
requirePreference("gyroSampleRate").setVisible(LauncherPreferences.PREF_ENABLE_GYRO);
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package net.kdt.pojavlaunch.utils;
2+
3+
import android.content.Context;
4+
import android.os.Vibrator;
5+
6+
import top.fifthlight.touchcontroller.proxy.client.LauncherProxyClient;
7+
import top.fifthlight.touchcontroller.proxy.client.MessageTransport;
8+
import top.fifthlight.touchcontroller.proxy.client.android.transport.UnixSocketTransportKt;
9+
import top.fifthlight.touchcontroller.proxy.message.VibrateMessage;
10+
11+
import android.system.ErrnoException;
12+
import android.system.Os;
13+
import android.util.Log;
14+
import android.util.SparseIntArray;
15+
import android.view.MotionEvent;
16+
import android.view.View;
17+
18+
import androidx.annotation.NonNull;
19+
import androidx.core.content.ContextCompat;
20+
21+
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
22+
23+
public class TouchControllerUtils {
24+
private TouchControllerUtils() {
25+
}
26+
27+
public static LauncherProxyClient proxyClient;
28+
private static final String socketName = "Amethyst";
29+
30+
private static class VibrationHandler implements LauncherProxyClient.VibrationHandler {
31+
private final Vibrator vibrator;
32+
33+
public VibrationHandler(Vibrator vibrator) {
34+
this.vibrator = vibrator;
35+
}
36+
37+
@Override
38+
@SuppressWarnings("DEPRECATION")
39+
public void vibrate(@NonNull VibrateMessage.Kind kind) {
40+
vibrator.vibrate(LauncherPreferences.PREF_TOUCHCONTROLLER_VIBRATE_LENGTH);
41+
}
42+
}
43+
44+
private static final SparseIntArray pointerIdMap = new SparseIntArray();
45+
private static int nextPointerId = 1;
46+
47+
public static void processTouchEvent(MotionEvent motionEvent, View view) {
48+
if (proxyClient == null) {
49+
return;
50+
}
51+
int pointerId;
52+
switch (motionEvent.getActionMasked()) {
53+
case MotionEvent.ACTION_DOWN:
54+
pointerId = nextPointerId++;
55+
pointerIdMap.put(motionEvent.getPointerId(0), pointerId);
56+
proxyClient.addPointer(pointerId, motionEvent.getX(0) / view.getWidth(), motionEvent.getY(0) / view.getHeight());
57+
break;
58+
case MotionEvent.ACTION_POINTER_DOWN:
59+
pointerId = nextPointerId++;
60+
int actionIndex = motionEvent.getActionIndex();
61+
pointerIdMap.put(motionEvent.getPointerId(actionIndex), pointerId);
62+
proxyClient.addPointer(pointerId, motionEvent.getX(actionIndex) / view.getWidth(), motionEvent.getY(actionIndex) / view.getHeight());
63+
break;
64+
case MotionEvent.ACTION_MOVE:
65+
for (int i = 0; i < motionEvent.getPointerCount(); i++) {
66+
pointerId = pointerIdMap.get(motionEvent.getPointerId(i));
67+
if (pointerId == 0) {
68+
Log.d("TouchController", "Move pointerId is 0");
69+
continue;
70+
}
71+
proxyClient.addPointer(pointerId, motionEvent.getX(i) / view.getWidth(), motionEvent.getY(i) / view.getHeight());
72+
}
73+
break;
74+
case MotionEvent.ACTION_UP:
75+
case MotionEvent.ACTION_CANCEL:
76+
if (proxyClient != null) {
77+
proxyClient.clearPointer();
78+
pointerIdMap.clear();
79+
}
80+
break;
81+
case MotionEvent.ACTION_POINTER_UP:
82+
if (proxyClient != null) {
83+
int i = motionEvent.getActionIndex();
84+
pointerId = pointerIdMap.get(motionEvent.getPointerId(i));
85+
if (pointerId == 0) {
86+
Log.d("TouchController", "Pointer up pointerId is 0");
87+
break;
88+
}
89+
pointerIdMap.delete(pointerId);
90+
proxyClient.removePointer(pointerId);
91+
}
92+
break;
93+
}
94+
}
95+
96+
public static void initialize(Context context) {
97+
if (proxyClient != null) {
98+
return;
99+
}
100+
try {
101+
Os.setenv("TOUCH_CONTROLLER_PROXY_SOCKET", socketName, true);
102+
} catch (ErrnoException e) {
103+
Log.w("TouchController", "Failed to set TouchController environment variable", e);
104+
}
105+
MessageTransport transport = UnixSocketTransportKt.UnixSocketTransport(socketName);
106+
proxyClient = new LauncherProxyClient(transport);
107+
proxyClient.run();
108+
Vibrator vibrator = ContextCompat.getSystemService(context, Vibrator.class);
109+
if (vibrator != null) {
110+
LauncherProxyClient.VibrationHandler vibrationHandler = new VibrationHandler(vibrator);
111+
proxyClient.setVibrationHandler(vibrationHandler);
112+
}
113+
}
114+
}

app_pojavlauncher/src/main/res/values-zh-rCN/strings.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,4 +399,10 @@
399399
<string name="mg_renderer_title_computeShaderext">启用实验性的 Compute Shader 扩展</string>
400400
<string name="mg_renderer_summary_computeShaderext">可能有助于解决光影渲染异常。非必要请禁用,可能会导致错误。</string>
401401
<string name="mg_renderer_title_errorSetting">OpenGL 报错设置</string>
402+
403+
<string name="preference_category_touchcontroller_settings">TouchController 设置</string>
404+
<string name="preference_force_enable_touchcontroller_title">强制启用 TouchController</string>
405+
<string name="preference_force_enable_touchcontroller_description">启用 TouchController 集成,即使没有找到模组文件。</string>
406+
<string name="preference_touchcontroller_vibrate_length_title">TouchController 震动长度</string>
407+
<string name="preference_touchcontroller_vibrate_length_description">设置使用 TouchController 时的震动长度。</string>
402408
</resources>

app_pojavlauncher/src/main/res/values/strings.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,4 +456,10 @@
456456
<string name="modloader_dl_install_neoforge">Create Neoforge profile</string>
457457
<string name="neoforge_dl_select_version">Select NeoForge version</string>
458458
<string name="neoforge_dl_no_installer">Sorry, but this version of NeoForge does not have an installer, which is not yet supported.</string>
459+
460+
<string name="preference_category_touchcontroller_settings">TouchController Settings</string>
461+
<string name="preference_force_enable_touchcontroller_title">Force enable TouchController</string>
462+
<string name="preference_force_enable_touchcontroller_description">Force enable TouchController integration, even if mod file is not found.</string>
463+
<string name="preference_touchcontroller_vibrate_length_title">TouchController vibrate length</string>
464+
<string name="preference_touchcontroller_vibrate_length_description">Set the length of the vibration when using TouchController.</string>
459465
</resources>

0 commit comments

Comments
 (0)