Android: Improve external controller/add auto-hide touch option
This commit is contained in:
parent
3b6b7007b3
commit
2a824751e7
|
@ -8,10 +8,12 @@ import androidx.appcompat.app.ActionBar;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.AndroidException;
|
||||
|
@ -187,6 +189,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
|||
|
||||
// Hook up controller input.
|
||||
updateControllers();
|
||||
registerInputDeviceListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -209,6 +212,8 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
|||
mWasDestroyed = true;
|
||||
AndroidHostInterface.getInstance().stopEmulationThread();
|
||||
}
|
||||
|
||||
unregisterInputDeviceListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -397,14 +402,15 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
|||
public void updateControllers() {
|
||||
final String controllerType = getStringSetting("Controller1/Type", "DigitalController");
|
||||
final String viewType = getStringSetting("Controller1/TouchscreenControllerView", "digital");
|
||||
final boolean autoHideTouchscreenController = getBooleanSetting("Controller1/AutoHideTouchscreenController", false);
|
||||
final FrameLayout activityLayout = findViewById(R.id.frameLayout);
|
||||
|
||||
Log.i("EmulationActivity", "Controller type: " + controllerType);
|
||||
Log.i("EmulationActivity", "View type: " + viewType);
|
||||
|
||||
mContentView.initControllerKeyMapping(controllerType);
|
||||
final boolean hasAnyControllers = mContentView.initControllerMapping(controllerType);
|
||||
|
||||
if (controllerType == "none" || viewType == "none") {
|
||||
if (controllerType == "none" || viewType == "none" || (hasAnyControllers && autoHideTouchscreenController)) {
|
||||
if (mTouchscreenController != null) {
|
||||
activityLayout.removeView(mTouchscreenController);
|
||||
mTouchscreenController = null;
|
||||
|
@ -418,4 +424,44 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
|
|||
mTouchscreenController.init(0, controllerType, viewType);
|
||||
}
|
||||
}
|
||||
|
||||
private InputManager.InputDeviceListener mInputDeviceListener;
|
||||
private void registerInputDeviceListener() {
|
||||
if (mInputDeviceListener != null)
|
||||
return;
|
||||
|
||||
mInputDeviceListener = new InputManager.InputDeviceListener() {
|
||||
@Override
|
||||
public void onInputDeviceAdded(int i) {
|
||||
Log.i("EmulationActivity", String.format("InputDeviceAdded %d", i));
|
||||
updateControllers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceRemoved(int i) {
|
||||
Log.i("EmulationActivity", String.format("InputDeviceRemoved %d", i));
|
||||
updateControllers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputDeviceChanged(int i) {
|
||||
Log.i("EmulationActivity", String.format("InputDeviceChanged %d", i));
|
||||
updateControllers();
|
||||
}
|
||||
};
|
||||
|
||||
InputManager inputManager = ((InputManager)getSystemService(Context.INPUT_SERVICE));
|
||||
if (inputManager != null)
|
||||
inputManager.registerInputDeviceListener(mInputDeviceListener, null);
|
||||
}
|
||||
private void unregisterInputDeviceListener() {
|
||||
if (mInputDeviceListener == null)
|
||||
return;
|
||||
|
||||
InputManager inputManager = ((InputManager)getSystemService(Context.INPUT_SERVICE));
|
||||
if (inputManager != null)
|
||||
inputManager.unregisterInputDeviceListener(mInputDeviceListener);
|
||||
|
||||
mInputDeviceListener = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.github.stenzek.duckstation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
@ -10,6 +11,9 @@ import android.view.KeyEvent;
|
|||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EmulationSurfaceView extends SurfaceView {
|
||||
public EmulationSurfaceView(Context context) {
|
||||
super(context);
|
||||
|
@ -33,7 +37,7 @@ public class EmulationSurfaceView extends SurfaceView {
|
|||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (isDPadOrButtonEvent(event) && event.getRepeatCount() == 0 &&
|
||||
handleControllerKey(keyCode, true)) {
|
||||
handleControllerKey(event.getDeviceId(), keyCode, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -43,7 +47,7 @@ public class EmulationSurfaceView extends SurfaceView {
|
|||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (isDPadOrButtonEvent(event) && event.getRepeatCount() == 0 &&
|
||||
handleControllerKey(keyCode, false)) {
|
||||
handleControllerKey(event.getDeviceId(), keyCode, false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -56,58 +60,110 @@ public class EmulationSurfaceView extends SurfaceView {
|
|||
if ((source & InputDevice.SOURCE_JOYSTICK) == 0)
|
||||
return super.onGenericMotionEvent(event);
|
||||
|
||||
final InputDevice device = event.getDevice();
|
||||
for (int axis : AXISES) {
|
||||
Integer mapping = mControllerAxisMapping.containsKey(axis) ? mControllerAxisMapping.get(axis) : null;
|
||||
Pair<Integer, Integer> buttonMapping = mControllerAxisButtonMapping.containsKey(axis) ? mControllerAxisButtonMapping.get(axis) : null;
|
||||
if (mapping == null && buttonMapping == null)
|
||||
final int deviceId = event.getDeviceId();
|
||||
for (AxisMapping mapping : mControllerAxisMapping) {
|
||||
if (mapping.deviceId != deviceId)
|
||||
continue;
|
||||
|
||||
final float axisValue = event.getAxisValue(axis);
|
||||
final float axisValue = event.getAxisValue(mapping.deviceAxisOrButton);
|
||||
float emuValue;
|
||||
|
||||
final InputDevice.MotionRange range = device.getMotionRange(axis, source);
|
||||
if (range != null) {
|
||||
final float transformedValue = (axisValue - range.getMin()) / range.getRange();
|
||||
if (mapping.deviceMotionRange != null) {
|
||||
final float transformedValue = (axisValue - mapping.deviceMotionRange.getMin()) / mapping.deviceMotionRange.getRange();
|
||||
emuValue = (transformedValue * 2.0f) - 1.0f;
|
||||
} else {
|
||||
emuValue = axisValue;
|
||||
}
|
||||
Log.d("EmulationSurfaceView", String.format("axis %d value %f emuvalue %f", axis, axisValue, emuValue));
|
||||
if (mapping != null) {
|
||||
AndroidHostInterface.getInstance().setControllerAxisState(0, mapping, emuValue);
|
||||
} else {
|
||||
final float DEAD_ZONE = 0.25f;
|
||||
AndroidHostInterface.getInstance().setControllerButtonState(0, buttonMapping.first, (emuValue <= -DEAD_ZONE));
|
||||
AndroidHostInterface.getInstance().setControllerButtonState(0, buttonMapping.second, (emuValue >= DEAD_ZONE));
|
||||
Log.d("EmulationSurfaceView", String.format("using emuValue %f for buttons %d %d", emuValue, buttonMapping.first, buttonMapping.second));
|
||||
Log.d("EmulationSurfaceView", String.format("axis %d value %f emuvalue %f", mapping.deviceAxisOrButton, axisValue, emuValue));
|
||||
|
||||
if (mapping.axisMapping >= 0) {
|
||||
AndroidHostInterface.getInstance().setControllerAxisState(0, mapping.axisMapping, emuValue);
|
||||
}
|
||||
|
||||
final float DEAD_ZONE = 0.25f;
|
||||
if (mapping.negativeButton >= 0) {
|
||||
AndroidHostInterface.getInstance().setControllerButtonState(0, mapping.negativeButton, (emuValue <= -DEAD_ZONE));
|
||||
}
|
||||
if (mapping.positiveButton >= 0) {
|
||||
AndroidHostInterface.getInstance().setControllerButtonState(0, mapping.positiveButton, (emuValue >= DEAD_ZONE));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private ArrayMap<Integer, Integer> mControllerKeyMapping;
|
||||
private ArrayMap<Integer, Integer> mControllerAxisMapping;
|
||||
private ArrayMap<Integer, Pair<Integer, Integer>> mControllerAxisButtonMapping;
|
||||
static final int[] AXISES = new int[]{MotionEvent.AXIS_X, MotionEvent.AXIS_Y, MotionEvent.AXIS_Z,
|
||||
MotionEvent.AXIS_RZ, MotionEvent.AXIS_LTRIGGER, MotionEvent.AXIS_RTRIGGER,
|
||||
MotionEvent.AXIS_HAT_X, MotionEvent.AXIS_HAT_Y};
|
||||
private class ButtonMapping {
|
||||
public ButtonMapping(int deviceId, int deviceButton, int controllerIndex, int button) {
|
||||
this.deviceId = deviceId;
|
||||
this.deviceAxisOrButton = deviceButton;
|
||||
this.controllerIndex = controllerIndex;
|
||||
this.buttonMapping = button;
|
||||
}
|
||||
|
||||
private void addControllerKeyMapping(int keyCode, String controllerType, String buttonName) {
|
||||
public int deviceId;
|
||||
public int deviceAxisOrButton;
|
||||
public int controllerIndex;
|
||||
public int buttonMapping;
|
||||
}
|
||||
|
||||
private class AxisMapping {
|
||||
public AxisMapping(int deviceId, int deviceAxis, InputDevice.MotionRange motionRange, int controllerIndex, int axis) {
|
||||
this.deviceId = deviceId;
|
||||
this.deviceAxisOrButton = deviceAxis;
|
||||
this.deviceMotionRange = motionRange;
|
||||
this.controllerIndex = controllerIndex;
|
||||
this.axisMapping = axis;
|
||||
this.positiveButton = -1;
|
||||
this.negativeButton = -1;
|
||||
}
|
||||
|
||||
public AxisMapping(int deviceId, int deviceAxis, InputDevice.MotionRange motionRange, int controllerIndex, int positiveButton, int negativeButton) {
|
||||
this.deviceId = deviceId;
|
||||
this.deviceAxisOrButton = deviceAxis;
|
||||
this.deviceMotionRange = motionRange;
|
||||
this.controllerIndex = controllerIndex;
|
||||
this.axisMapping = -1;
|
||||
this.positiveButton = positiveButton;
|
||||
this.negativeButton = negativeButton;
|
||||
}
|
||||
|
||||
public int deviceId;
|
||||
public int deviceAxisOrButton;
|
||||
public InputDevice.MotionRange deviceMotionRange;
|
||||
public int controllerIndex;
|
||||
public int axisMapping;
|
||||
public int positiveButton;
|
||||
public int negativeButton;
|
||||
}
|
||||
|
||||
private ArrayList<ButtonMapping> mControllerKeyMapping;
|
||||
private ArrayList<AxisMapping> mControllerAxisMapping;
|
||||
|
||||
private void addControllerKeyMapping(int deviceId, int keyCode, int controllerIndex, String controllerType, String buttonName) {
|
||||
int mapping = AndroidHostInterface.getControllerButtonCode(controllerType, buttonName);
|
||||
Log.i("EmulationSurfaceView", String.format("Map %d to %d (%s)", keyCode, mapping,
|
||||
buttonName));
|
||||
if (mapping >= 0)
|
||||
mControllerKeyMapping.put(keyCode, mapping);
|
||||
if (mapping >= 0) {
|
||||
mControllerKeyMapping.add(new ButtonMapping(deviceId, keyCode, controllerIndex, mapping));
|
||||
}
|
||||
}
|
||||
|
||||
private void addControllerAxisMapping(int axis, String controllerType, String axisName, String negativeButtonName, String positiveButtonName) {
|
||||
private void addControllerAxisMapping(int deviceId, List<InputDevice.MotionRange> motionRanges, int axis, int controllerIndex, String controllerType, String axisName, String negativeButtonName, String positiveButtonName) {
|
||||
InputDevice.MotionRange range = null;
|
||||
for (InputDevice.MotionRange curRange : motionRanges) {
|
||||
if (curRange.getAxis() == axis) {
|
||||
range = curRange;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (range == null)
|
||||
return;
|
||||
|
||||
if (axisName != null) {
|
||||
int mapping = AndroidHostInterface.getControllerAxisCode(controllerType, axisName);
|
||||
Log.i("EmulationSurfaceView", String.format("Map axis %d to %d (%s)", axis, mapping, axisName));
|
||||
if (mapping >= 0) {
|
||||
mControllerAxisMapping.put(axis, mapping);
|
||||
mControllerAxisMapping.add(new AxisMapping(deviceId, axis, range, controllerIndex, mapping));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -118,48 +174,87 @@ public class EmulationSurfaceView extends SurfaceView {
|
|||
Log.i("EmulationSurfaceView", String.format("Map axis %d to %d %d (button %s %s)", axis, negativeMapping, positiveMapping,
|
||||
negativeButtonName, positiveButtonName));
|
||||
if (negativeMapping >= 0 && positiveMapping >= 0) {
|
||||
mControllerAxisButtonMapping.put(axis, new Pair<Integer, Integer>(negativeMapping, positiveMapping));
|
||||
mControllerAxisMapping.add(new AxisMapping(deviceId, axis, range, controllerIndex, positiveMapping, negativeMapping));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void initControllerKeyMapping(String controllerType) {
|
||||
mControllerKeyMapping = new ArrayMap<>();
|
||||
mControllerAxisMapping = new ArrayMap<>();
|
||||
mControllerAxisButtonMapping = new ArrayMap<>();
|
||||
|
||||
// TODO: Don't hardcode...
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_DPAD_UP, controllerType, "Up");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_DPAD_RIGHT, controllerType, "Right");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_DPAD_DOWN, controllerType, "Down");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_DPAD_LEFT, controllerType, "Left");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_L1, controllerType, "L1");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_L2, controllerType, "L2");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_SELECT, controllerType, "Select");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_START, controllerType, "Start");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_Y, controllerType, "Triangle");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_B, controllerType, "Circle");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_A, controllerType, "Cross");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_X, controllerType, "Square");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_R1, controllerType, "R1");
|
||||
addControllerKeyMapping(KeyEvent.KEYCODE_BUTTON_R2, controllerType, "R2");
|
||||
addControllerAxisMapping(MotionEvent.AXIS_X, controllerType, "LeftX", null, null);
|
||||
addControllerAxisMapping(MotionEvent.AXIS_Y, controllerType, "LeftY", null, null);
|
||||
addControllerAxisMapping(MotionEvent.AXIS_Z, controllerType, "RightX", null, null);
|
||||
addControllerAxisMapping(MotionEvent.AXIS_RZ, controllerType, "RightY", null, null);
|
||||
addControllerAxisMapping(MotionEvent.AXIS_LTRIGGER, controllerType, "L2", "L2", "L2");
|
||||
addControllerAxisMapping(MotionEvent.AXIS_RTRIGGER, controllerType, "R2", "R2", "R2");
|
||||
addControllerAxisMapping(MotionEvent.AXIS_HAT_X, controllerType, null, "Left", "Right");
|
||||
addControllerAxisMapping(MotionEvent.AXIS_HAT_Y, controllerType, null, "Up", "Down");
|
||||
}
|
||||
|
||||
private boolean handleControllerKey(int keyCode, boolean pressed) {
|
||||
if (!mControllerKeyMapping.containsKey(keyCode))
|
||||
private static boolean isJoystickDevice(int deviceId) {
|
||||
if (deviceId < 0)
|
||||
return false;
|
||||
|
||||
final int mapping = mControllerKeyMapping.get(keyCode);
|
||||
AndroidHostInterface.getInstance().setControllerButtonState(0, mapping, pressed);
|
||||
Log.d("EmulationSurfaceView", String.format("handleControllerKey %d -> %d %d", keyCode, mapping, pressed ? 1 : 0));
|
||||
return true;
|
||||
final InputDevice dev = InputDevice.getDevice(deviceId);
|
||||
if (dev == null)
|
||||
return false;
|
||||
|
||||
final int sources = dev.getSources();
|
||||
if ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0)
|
||||
return true;
|
||||
|
||||
if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|
||||
return true;
|
||||
|
||||
if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean initControllerMapping(String controllerType) {
|
||||
mControllerKeyMapping = new ArrayList<>();
|
||||
mControllerAxisMapping = new ArrayList<>();
|
||||
|
||||
final int[] deviceIds = InputDevice.getDeviceIds();
|
||||
for (int deviceId : deviceIds) {
|
||||
if (!isJoystickDevice(deviceId))
|
||||
continue;
|
||||
|
||||
InputDevice device = InputDevice.getDevice(deviceId);
|
||||
List<InputDevice.MotionRange> motionRanges = device.getMotionRanges();
|
||||
int controllerIndex = 0;
|
||||
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_DPAD_UP, controllerIndex, controllerType, "Up");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_DPAD_RIGHT, controllerIndex, controllerType, "Right");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_DPAD_DOWN, controllerIndex, controllerType, "Down");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_DPAD_LEFT, controllerIndex, controllerType, "Left");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_L1, controllerIndex, controllerType, "L1");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_L2, controllerIndex, controllerType, "L2");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_SELECT, controllerIndex, controllerType, "Select");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_START, controllerIndex, controllerType, "Start");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_Y, controllerIndex, controllerType, "Triangle");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_B, controllerIndex, controllerType, "Circle");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_A, controllerIndex, controllerType, "Cross");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_X, controllerIndex, controllerType, "Square");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_R1, controllerIndex, controllerType, "R1");
|
||||
addControllerKeyMapping(deviceId, KeyEvent.KEYCODE_BUTTON_R2, controllerIndex, controllerType, "R2");
|
||||
if (motionRanges != null) {
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_X, controllerIndex, controllerType, "LeftX", null, null);
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_Y, controllerIndex, controllerType, "LeftY", null, null);
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_RX, controllerIndex, controllerType, "RightX", null, null);
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_RY, controllerIndex, controllerType, "RightY", null, null);
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_Z, controllerIndex, controllerType, "RightX", null, null);
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_RZ, controllerIndex, controllerType, "RightY", null, null);
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_LTRIGGER, controllerIndex, controllerType, "L2", "L2", "L2");
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_RTRIGGER, controllerIndex, controllerType, "R2", "R2", "R2");
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_HAT_X, controllerIndex, controllerType, null, "Left", "Right");
|
||||
addControllerAxisMapping(deviceId, motionRanges, MotionEvent.AXIS_HAT_Y, controllerIndex, controllerType, null, "Up", "Down");
|
||||
}
|
||||
}
|
||||
|
||||
return !mControllerKeyMapping.isEmpty() || !mControllerKeyMapping.isEmpty();
|
||||
}
|
||||
|
||||
private boolean handleControllerKey(int deviceId, int keyCode, boolean pressed) {
|
||||
boolean result = false;
|
||||
for (ButtonMapping mapping : mControllerKeyMapping) {
|
||||
if (mapping.deviceId != deviceId || mapping.deviceAxisOrButton != keyCode)
|
||||
continue;
|
||||
|
||||
AndroidHostInterface.getInstance().setControllerButtonState(0, mapping.buttonMapping, pressed);
|
||||
Log.d("EmulationSurfaceView", String.format("handleControllerKey %d -> %d %d", keyCode, mapping.buttonMapping, pressed ? 1 : 0));
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,6 +266,12 @@
|
|||
app:defaultValue="digital"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
app:iconSpaceReserved="false" />
|
||||
<SwitchPreferenceCompat
|
||||
app:key="Controller1/AutoHideTouchscreenController"
|
||||
app:title="Auto-Hide Touchscreen Controller"
|
||||
app:defaultValue="false"
|
||||
app:summary="Hides the touchscreen controller when an external controller is detected."
|
||||
app:iconSpaceReserved="false"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory app:title="Memory Cards" app:iconSpaceReserved="false">
|
||||
|
|
Loading…
Reference in New Issue