diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java
index 9a8b75ad6..84292159c 100644
--- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java
@@ -35,6 +35,7 @@ import android.provider.OpenableColumns;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.InputDevice;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
@@ -1557,4 +1558,19 @@ public final class Tools {
}
return Integer.parseInt(iVersionArray[0] + iVersionArray[1] + iVersionArray[2]);
}
+
+ public static boolean isPointerDeviceConnected() {
+ int[] deviceIds = InputDevice.getDeviceIds();
+ for (int id : deviceIds) {
+ InputDevice device = InputDevice.getDevice(id);
+ if (device == null) continue;
+ int sources = device.getSources();
+ if ((sources & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE
+ || (sources & InputDevice.SOURCE_TOUCHPAD) == InputDevice.SOURCE_TOUCHPAD
+ || (sources & InputDevice.SOURCE_TRACKBALL) == InputDevice.SOURCE_TRACKBALL) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/mouse/AndroidPointerCapture.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/mouse/AndroidPointerCapture.java
index 38f6dd4ca..4e918cb3b 100644
--- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/mouse/AndroidPointerCapture.java
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/customcontrols/mouse/AndroidPointerCapture.java
@@ -1,13 +1,18 @@
package net.kdt.pojavlaunch.customcontrols.mouse;
+import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_MOUSE_GRAB_FORCE;
+
+import android.content.SharedPreferences;
import android.os.Build;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import net.kdt.pojavlaunch.GrabListener;
import net.kdt.pojavlaunch.MinecraftGLSurface;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
@@ -15,7 +20,7 @@ import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import org.lwjgl.glfw.CallbackBridge;
@RequiresApi(api = Build.VERSION_CODES.O)
-public class AndroidPointerCapture implements ViewTreeObserver.OnWindowFocusChangeListener, View.OnCapturedPointerListener {
+public class AndroidPointerCapture implements ViewTreeObserver.OnWindowFocusChangeListener, View.OnCapturedPointerListener, GrabListener, SharedPreferences.OnSharedPreferenceChangeListener {
private static final float TOUCHPAD_SCROLL_THRESHOLD = 1;
private final AbstractTouchpad mTouchpad;
private final View mHostView;
@@ -32,14 +37,44 @@ public class AndroidPointerCapture implements ViewTreeObserver.OnWindowFocusChan
this.mHostView = hostView;
hostView.setOnCapturedPointerListener(this);
hostView.getViewTreeObserver().addOnWindowFocusChangeListener(this);
+ if (!PREF_MOUSE_GRAB_FORCE)
+ CallbackBridge.addGrabListener(this);
}
private void enableTouchpadIfNecessary() {
- if(!mTouchpad.getDisplayState()) mTouchpad.enable(true);
+ if(!mTouchpad.getDisplayState() && !Tools.isPointerDeviceConnected()) mTouchpad.enable(true);
+ }
+
+ // Needed so it releases the cursor when inside game menu
+ @Override
+ public void onGrabState(boolean isGrabbing) {
+ updateCursorState(isGrabbing);
+ }
+ // It's only here so the side-dialog changes it live
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
+ updateCursorState(CallbackBridge.isGrabbing());
+ }
+ private void updateCursorState(boolean isGrabbing) {
+ if (!isGrabbing // Only capture if not in menu and user said so
+ && !PREF_MOUSE_GRAB_FORCE) {
+ mHostView.releasePointerCapture(); // Release the capture since user said so
+ }
+ // Capture the pointer when not inside a menu
+ // So user doesn't have to click to get rid of cursor
+ handleAutomaticCapture();
}
public void handleAutomaticCapture() {
- if(!mHostView.hasWindowFocus()) {
+ if (!CallbackBridge.isGrabbing() // Only capture if not in menu and user said so
+ && !PREF_MOUSE_GRAB_FORCE) {
+ return;
+ }
+ if (mHostView.hasPointerCapture()) {
+ enableTouchpadIfNecessary();
+ return;
+ }
+ if (!mHostView.hasWindowFocus()) {
mHostView.requestFocus();
} else {
mHostView.requestPointerCapture();
@@ -128,7 +163,11 @@ public class AndroidPointerCapture implements ViewTreeObserver.OnWindowFocusChan
@Override
public void onWindowFocusChanged(boolean hasFocus) {
- if(hasFocus && Tools.isAndroid8OrHigher()) mHostView.requestPointerCapture();
+ if (!CallbackBridge.isGrabbing() // Only capture if not in menu and user said so
+ && !PREF_MOUSE_GRAB_FORCE) {
+ return;
+ }
+ if (hasFocus && Tools.isAndroid8OrHigher()) mHostView.requestPointerCapture();
}
public void detach() {
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 dc4dd71ad..ab8c0cddd 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
@@ -72,6 +72,8 @@ public class LauncherPreferences {
public static boolean PREF_FORCE_ENABLE_TOUCHCONTROLLER = false;
public static int PREF_TOUCHCONTROLLER_VIBRATE_LENGTH = 100;
+ public static boolean PREF_MOUSE_GRAB_FORCE = false;
+
public static void loadPreferences(Context ctx) {
//Required for CTRLDEF_FILE and MultiRT
@@ -114,6 +116,7 @@ public class LauncherPreferences {
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);
+ PREF_MOUSE_GRAB_FORCE = DEFAULT_PREF.getBoolean("always_grab_mouse", 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/QuickSettingSideDialog.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/QuickSettingSideDialog.java
index 5458dbf57..6a2b82dd1 100644
--- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/QuickSettingSideDialog.java
+++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/QuickSettingSideDialog.java
@@ -7,6 +7,7 @@ import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_GYRO_INVERT_Y;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_GYRO_SENSITIVITY;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_LONGPRESS_TRIGGER;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_MOUSESPEED;
+import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_MOUSE_GRAB_FORCE;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_SCALE_FACTOR;
import android.annotation.SuppressLint;
@@ -31,11 +32,11 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
private SharedPreferences.Editor mEditor;
@SuppressLint("UseSwitchCompatOrMaterialCode")
- private Switch mGyroSwitch, mGyroXSwitch, mGyroYSwitch, mGestureSwitch;
+ private Switch mGyroSwitch, mGyroXSwitch, mGyroYSwitch, mGestureSwitch, mMouseGrabSwitch;
private CustomSeekbar mGyroSensitivityBar, mMouseSpeedBar, mGestureDelayBar, mResolutionBar;
private TextView mGyroSensitivityText, mGyroSensitivityDisplayText, mMouseSpeedText, mGestureDelayText, mGestureDelayDisplayText, mResolutionText;
- private boolean mOriginalGyroEnabled, mOriginalGyroXEnabled, mOriginalGyroYEnabled, mOriginalGestureDisabled;
+ private boolean mOriginalGyroEnabled, mOriginalGyroXEnabled, mOriginalGyroYEnabled, mOriginalGestureDisabled, mOriginalMouseGrab;
private float mOriginalGyroSensitivity, mOriginalMouseSpeed, mOriginalResolution;
private int mOriginalGestureDelay;
@@ -65,6 +66,7 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
mGyroXSwitch = mDialogContent.findViewById(R.id.checkboxGyroX);
mGyroYSwitch = mDialogContent.findViewById(R.id.checkboxGyroY);
mGestureSwitch = mDialogContent.findViewById(R.id.checkboxGesture);
+ mMouseGrabSwitch = mDialogContent.findViewById(R.id.always_grab_mouse_side_dialog);
mGyroSensitivityBar = mDialogContent.findViewById(R.id.editGyro_seekbar);
mMouseSpeedBar = mDialogContent.findViewById(R.id.editMouseSpeed_seekbar);
@@ -86,6 +88,7 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
mOriginalGyroXEnabled = PREF_GYRO_INVERT_X;
mOriginalGyroYEnabled = PREF_GYRO_INVERT_Y;
mOriginalGestureDisabled = PREF_DISABLE_GESTURES;
+ mOriginalMouseGrab = PREF_MOUSE_GRAB_FORCE;
mOriginalGyroSensitivity = PREF_GYRO_SENSITIVITY;
mOriginalMouseSpeed = PREF_MOUSESPEED;
@@ -122,6 +125,10 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
mEditor.putBoolean("disableGestures", isChecked);
});
+ mMouseGrabSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ mEditor.putBoolean("always_grab_mouse", isChecked);
+ });
+
mGyroSensitivityBar.setOnSeekBarChangeListener((SimpleSeekBarListener) (seekBar, progress, fromUser) -> {
PREF_GYRO_SENSITIVITY = progress / 100f;
mEditor.putInt("gyroSensitivity", progress);
@@ -156,6 +163,7 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
setSeekTextPercent(mResolutionText, mResolutionBar.getProgress());
+ updateMouseGrabVisibility();
updateGyroVisibility(mOriginalGyroEnabled);
updateGestureVisibility(mOriginalGestureDisabled);
}
@@ -172,6 +180,10 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
target.setText(target.getContext().getString(format, value));
}
+ private void updateMouseGrabVisibility(){
+ mMouseGrabSwitch.setVisibility(Tools.isPointerDeviceConnected()? View.VISIBLE : View.GONE);
+ }
+
private void updateGyroVisibility(boolean isEnabled) {
int visibility = isEnabled ? View.VISIBLE : View.GONE;
mGyroXSwitch.setVisibility(visibility);
@@ -202,6 +214,7 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
mGyroXSwitch.setOnCheckedChangeListener(null);
mGyroYSwitch.setOnCheckedChangeListener(null);
mGestureSwitch.setOnCheckedChangeListener(null);
+ mMouseGrabSwitch.setOnCheckedChangeListener(null);
mGyroSensitivityBar.setOnSeekBarChangeListener(null);
mMouseSpeedBar.setOnSeekBarChangeListener(null);
@@ -225,6 +238,7 @@ public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView {
PREF_GYRO_INVERT_X = mOriginalGyroXEnabled;
PREF_GYRO_INVERT_Y = mOriginalGyroYEnabled;
PREF_DISABLE_GESTURES = mOriginalGestureDisabled;
+ PREF_MOUSE_GRAB_FORCE = mOriginalMouseGrab;
PREF_GYRO_SENSITIVITY = mOriginalGyroSensitivity;
PREF_MOUSESPEED = mOriginalMouseSpeed;
diff --git a/app_pojavlauncher/src/main/res/layout/dialog_quick_setting.xml b/app_pojavlauncher/src/main/res/layout/dialog_quick_setting.xml
index b85a83f7c..1d0ec167e 100644
--- a/app_pojavlauncher/src/main/res/layout/dialog_quick_setting.xml
+++ b/app_pojavlauncher/src/main/res/layout/dialog_quick_setting.xml
@@ -202,4 +202,15 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/editGestureDelay_textView" />
+
+
\ 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 04a41f500..15ff64e01 100644
--- a/app_pojavlauncher/src/main/res/values/strings.xml
+++ b/app_pojavlauncher/src/main/res/values/strings.xml
@@ -171,6 +171,8 @@
Disables double tapping on the hotbar item to swap it in the second hand.
Mouse Speed
Changes the speed of the virtual mouse.
+ Use virtual cursor
+ Ensures the cursor stays inside the game. Prevents mouse from clicking touch control layout.
Mouse pass-thru
Swipeable
Forward lock
diff --git a/app_pojavlauncher/src/main/res/xml/pref_control.xml b/app_pojavlauncher/src/main/res/xml/pref_control.xml
index 77c02f91c..0f2a7ec02 100644
--- a/app_pojavlauncher/src/main/res/xml/pref_control.xml
+++ b/app_pojavlauncher/src/main/res/xml/pref_control.xml
@@ -97,6 +97,11 @@
android:title="@string/preference_mouse_start_title"
android:summary="@string/preference_mouse_start_description"
/>
+