mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 19:13:03 +00:00
Add an option for absolute touch mode
This commit is contained in:
parent
363145a284
commit
cc877480ff
@ -6,9 +6,11 @@ import com.limelight.binding.input.ControllerHandler;
|
||||
import com.limelight.binding.input.KeyboardTranslator;
|
||||
import com.limelight.binding.input.capture.InputCaptureManager;
|
||||
import com.limelight.binding.input.capture.InputCaptureProvider;
|
||||
import com.limelight.binding.input.TouchContext;
|
||||
import com.limelight.binding.input.touch.AbsoluteTouchContext;
|
||||
import com.limelight.binding.input.touch.RelativeTouchContext;
|
||||
import com.limelight.binding.input.driver.UsbDriverService;
|
||||
import com.limelight.binding.input.evdev.EvdevListener;
|
||||
import com.limelight.binding.input.touch.TouchContext;
|
||||
import com.limelight.binding.input.virtual_controller.VirtualController;
|
||||
import com.limelight.binding.video.CrashListener;
|
||||
import com.limelight.binding.video.MediaCodecDecoderRenderer;
|
||||
@ -474,9 +476,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
|
||||
// Initialize touch contexts
|
||||
for (int i = 0; i < touchContextMap.length; i++) {
|
||||
touchContextMap[i] = new TouchContext(conn, i,
|
||||
REFERENCE_HORIZ_RES, REFERENCE_VERT_RES,
|
||||
streamView);
|
||||
if (!prefConfig.touchscreenTrackpad) {
|
||||
touchContextMap[i] = new AbsoluteTouchContext(conn, i, streamView);
|
||||
}
|
||||
else {
|
||||
touchContextMap[i] = new RelativeTouchContext(conn, i,
|
||||
REFERENCE_HORIZ_RES, REFERENCE_VERT_RES,
|
||||
streamView);
|
||||
}
|
||||
}
|
||||
|
||||
// Use sustained performance mode on N+ to ensure consistent
|
||||
@ -1332,7 +1339,10 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
{
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
context.touchDownEvent(eventX, eventY);
|
||||
for (TouchContext touchContext : touchContextMap) {
|
||||
touchContext.setPointerCount(event.getPointerCount());
|
||||
}
|
||||
context.touchDownEvent(eventX, eventY, true);
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
case MotionEvent.ACTION_UP:
|
||||
@ -1345,9 +1355,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
}
|
||||
context.touchUpEvent(eventX, eventY);
|
||||
for (TouchContext touchContext : touchContextMap) {
|
||||
touchContext.setPointerCount(event.getPointerCount() - 1);
|
||||
}
|
||||
if (actionIndex == 0 && event.getPointerCount() > 1 && !context.isCancelled()) {
|
||||
// The original secondary touch now becomes primary
|
||||
context.touchDownEvent((int)event.getX(1), (int)event.getY(1));
|
||||
context.touchDownEvent((int)event.getX(1), (int)event.getY(1), false);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
@ -1379,6 +1392,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
for (TouchContext aTouchContext : touchContextMap) {
|
||||
aTouchContext.cancelTouch();
|
||||
aTouchContext.setPointerCount(0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -0,0 +1,272 @@
|
||||
package com.limelight.binding.input.touch;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.view.View;
|
||||
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class AbsoluteTouchContext implements TouchContext {
|
||||
private int lastTouchDownX = 0;
|
||||
private int lastTouchDownY = 0;
|
||||
private long lastTouchDownTime = 0;
|
||||
private int lastTouchUpX = 0;
|
||||
private int lastTouchUpY = 0;
|
||||
private long lastTouchUpTime = 0;
|
||||
private int lastTouchLocationX = 0;
|
||||
private int lastTouchLocationY = 0;
|
||||
private boolean cancelled;
|
||||
private boolean confirmedLongPress;
|
||||
private boolean confirmedTap;
|
||||
private Timer longPressTimer;
|
||||
private Timer tapDownTimer;
|
||||
private float accumulatedScrollDelta;
|
||||
|
||||
private final NvConnection conn;
|
||||
private final int actionIndex;
|
||||
private final View targetView;
|
||||
|
||||
private static final int SCROLL_SPEED_DIVISOR = 20;
|
||||
|
||||
private static final int LONG_PRESS_TIME_THRESHOLD = 650;
|
||||
private static final int LONG_PRESS_DISTANCE_THRESHOLD = 30;
|
||||
|
||||
private static final int DOUBLE_TAP_TIME_THRESHOLD = 250;
|
||||
private static final int DOUBLE_TAP_DISTANCE_THRESHOLD = 60;
|
||||
|
||||
private static final int TOUCH_DOWN_DEAD_ZONE_TIME_THRESHOLD = 100;
|
||||
private static final int TOUCH_DOWN_DEAD_ZONE_DISTANCE_THRESHOLD = 20;
|
||||
|
||||
public AbsoluteTouchContext(NvConnection conn, int actionIndex, View view)
|
||||
{
|
||||
this.conn = conn;
|
||||
this.actionIndex = actionIndex;
|
||||
this.targetView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActionIndex()
|
||||
{
|
||||
return actionIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger)
|
||||
{
|
||||
if (!isNewFinger) {
|
||||
// We don't handle finger transitions for absolute mode
|
||||
return true;
|
||||
}
|
||||
|
||||
lastTouchLocationX = lastTouchDownX = eventX;
|
||||
lastTouchLocationY = lastTouchDownY = eventY;
|
||||
lastTouchDownTime = SystemClock.uptimeMillis();
|
||||
cancelled = confirmedTap = confirmedLongPress = false;
|
||||
accumulatedScrollDelta = 0;
|
||||
|
||||
if (actionIndex == 0) {
|
||||
// Start the timers
|
||||
startTapDownTimer();
|
||||
startLongPressTimer();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean distanceExceeds(int deltaX, int deltaY, double limit) {
|
||||
return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)) > limit;
|
||||
}
|
||||
|
||||
private void updatePosition(int eventX, int eventY) {
|
||||
// We may get values slightly outside our view region on ACTION_HOVER_ENTER and ACTION_HOVER_EXIT.
|
||||
// Normalize these to the view size. We can't just drop them because we won't always get an event
|
||||
// right at the boundary of the view, so dropping them would result in our cursor never really
|
||||
// reaching the sides of the screen.
|
||||
eventX = Math.min(Math.max(eventX, 0), targetView.getWidth());
|
||||
eventY = Math.min(Math.max(eventY, 0), targetView.getHeight());
|
||||
|
||||
conn.sendMousePosition((short)eventX, (short)eventY, (short)targetView.getWidth(), (short)targetView.getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchUpEvent(int eventX, int eventY)
|
||||
{
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionIndex == 0) {
|
||||
// Cancel the timers
|
||||
cancelLongPressTimer();
|
||||
cancelTapDownTimer();
|
||||
|
||||
// Raise the mouse buttons that we currently have down
|
||||
if (confirmedLongPress) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
else if (confirmedTap) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
else {
|
||||
// If we get here, this means that the tap completed within the touch down
|
||||
// deadzone time. We'll need to send the touch down and up events now at the
|
||||
// original touch down position.
|
||||
tapConfirmed();
|
||||
try {
|
||||
// FIXME: Sleeping on the main thread sucks
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException ignored) {}
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
lastTouchLocationX = lastTouchUpX = eventX;
|
||||
lastTouchLocationY = lastTouchUpY = eventY;
|
||||
lastTouchUpTime = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
private synchronized void startLongPressTimer() {
|
||||
longPressTimer = new Timer(true);
|
||||
longPressTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (AbsoluteTouchContext.this) {
|
||||
// Check if someone cancelled us
|
||||
if (longPressTimer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Uncancellable now
|
||||
longPressTimer = null;
|
||||
|
||||
// This timer should have already expired, but cancel it just in case
|
||||
cancelTapDownTimer();
|
||||
|
||||
// Switch from a left click to a right click after a long press
|
||||
confirmedLongPress = true;
|
||||
if (confirmedTap) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
}
|
||||
}, LONG_PRESS_TIME_THRESHOLD);
|
||||
}
|
||||
|
||||
private synchronized void cancelLongPressTimer() {
|
||||
if (longPressTimer != null) {
|
||||
longPressTimer.cancel();
|
||||
longPressTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void startTapDownTimer() {
|
||||
tapDownTimer = new Timer(true);
|
||||
tapDownTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (AbsoluteTouchContext.this) {
|
||||
// Check if someone cancelled us
|
||||
if (tapDownTimer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Uncancellable now
|
||||
tapDownTimer = null;
|
||||
|
||||
// Start our tap
|
||||
tapConfirmed();
|
||||
}
|
||||
}
|
||||
}, TOUCH_DOWN_DEAD_ZONE_TIME_THRESHOLD);
|
||||
}
|
||||
|
||||
private synchronized void cancelTapDownTimer() {
|
||||
if (tapDownTimer != null) {
|
||||
tapDownTimer.cancel();
|
||||
tapDownTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void tapConfirmed() {
|
||||
if (confirmedTap || confirmedLongPress) {
|
||||
return;
|
||||
}
|
||||
|
||||
confirmedTap = true;
|
||||
cancelTapDownTimer();
|
||||
|
||||
// Left button down at original position
|
||||
if (lastTouchDownTime - lastTouchUpTime > DOUBLE_TAP_TIME_THRESHOLD ||
|
||||
distanceExceeds(lastTouchDownX - lastTouchUpX, lastTouchDownY - lastTouchUpY, DOUBLE_TAP_DISTANCE_THRESHOLD)) {
|
||||
// Don't reposition for finger down events within the deadzone. This makes double-clicking easier.
|
||||
updatePosition(lastTouchDownX, lastTouchDownY);
|
||||
}
|
||||
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchMoveEvent(int eventX, int eventY)
|
||||
{
|
||||
if (cancelled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (actionIndex == 0) {
|
||||
if (distanceExceeds(eventX - lastTouchDownX, eventY - lastTouchDownY, LONG_PRESS_DISTANCE_THRESHOLD)) {
|
||||
// Moved too far since touch down. Cancel the long press timer.
|
||||
cancelLongPressTimer();
|
||||
}
|
||||
|
||||
// Ignore motion within the deadzone period after touch down
|
||||
if (confirmedTap || distanceExceeds(eventX - lastTouchDownX, eventY - lastTouchDownY, TOUCH_DOWN_DEAD_ZONE_DISTANCE_THRESHOLD)) {
|
||||
tapConfirmed();
|
||||
updatePosition(eventX, eventY);
|
||||
}
|
||||
}
|
||||
else if (actionIndex == 1) {
|
||||
accumulatedScrollDelta += (eventY - lastTouchLocationY) / (float)SCROLL_SPEED_DIVISOR;
|
||||
if ((short)accumulatedScrollDelta != 0) {
|
||||
conn.sendMouseHighResScroll((short)accumulatedScrollDelta);
|
||||
accumulatedScrollDelta -= (short)accumulatedScrollDelta;
|
||||
}
|
||||
}
|
||||
|
||||
lastTouchLocationX = eventX;
|
||||
lastTouchLocationY = eventY;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTouch() {
|
||||
cancelled = true;
|
||||
|
||||
// Cancel the timers
|
||||
cancelLongPressTimer();
|
||||
cancelTapDownTimer();
|
||||
|
||||
// Raise the mouse buttons
|
||||
if (confirmedLongPress) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
|
||||
}
|
||||
else if (confirmedTap) {
|
||||
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPointerCount(int pointerCount) {
|
||||
if (actionIndex == 0 && pointerCount > 1) {
|
||||
cancelTouch();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.limelight.binding.input;
|
||||
package com.limelight.binding.input.touch;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.view.View;
|
||||
|
||||
import com.limelight.nvstream.NvConnection;
|
||||
@ -8,7 +9,7 @@ import com.limelight.nvstream.input.MouseButtonPacket;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class TouchContext {
|
||||
public class RelativeTouchContext implements TouchContext {
|
||||
private int lastTouchX = 0;
|
||||
private int lastTouchY = 0;
|
||||
private int originalTouchX = 0;
|
||||
@ -32,8 +33,8 @@ public class TouchContext {
|
||||
private static final int TAP_TIME_THRESHOLD = 250;
|
||||
private static final int DRAG_TIME_THRESHOLD = 650;
|
||||
|
||||
public TouchContext(NvConnection conn, int actionIndex,
|
||||
int referenceWidth, int referenceHeight, View view)
|
||||
public RelativeTouchContext(NvConnection conn, int actionIndex,
|
||||
int referenceWidth, int referenceHeight, View view)
|
||||
{
|
||||
this.conn = conn;
|
||||
this.actionIndex = actionIndex;
|
||||
@ -42,6 +43,7 @@ public class TouchContext {
|
||||
this.targetView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActionIndex()
|
||||
{
|
||||
return actionIndex;
|
||||
@ -57,7 +59,7 @@ public class TouchContext {
|
||||
|
||||
private boolean isTap()
|
||||
{
|
||||
long timeDelta = System.currentTimeMillis() - originalTouchTime;
|
||||
long timeDelta = SystemClock.uptimeMillis() - originalTouchTime;
|
||||
|
||||
return isWithinTapBounds(lastTouchX, lastTouchY) && timeDelta <= TAP_TIME_THRESHOLD;
|
||||
}
|
||||
@ -72,7 +74,8 @@ public class TouchContext {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean touchDownEvent(int eventX, int eventY)
|
||||
@Override
|
||||
public boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger)
|
||||
{
|
||||
// Get the view dimensions to scale inputs on this touch
|
||||
xFactor = referenceWidth / (double)targetView.getWidth();
|
||||
@ -80,7 +83,7 @@ public class TouchContext {
|
||||
|
||||
originalTouchX = lastTouchX = eventX;
|
||||
originalTouchY = lastTouchY = eventY;
|
||||
originalTouchTime = System.currentTimeMillis();
|
||||
originalTouchTime = SystemClock.uptimeMillis();
|
||||
cancelled = confirmedDrag = confirmedMove = false;
|
||||
distanceMoved = 0;
|
||||
|
||||
@ -92,6 +95,7 @@ public class TouchContext {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void touchUpEvent(int eventX, int eventY)
|
||||
{
|
||||
if (cancelled) {
|
||||
@ -128,7 +132,7 @@ public class TouchContext {
|
||||
dragTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (TouchContext.this) {
|
||||
synchronized (RelativeTouchContext.this) {
|
||||
// Check if someone already set move
|
||||
if (confirmedMove) {
|
||||
return;
|
||||
@ -179,6 +183,7 @@ public class TouchContext {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchMoveEvent(int eventX, int eventY)
|
||||
{
|
||||
if (eventX != lastTouchX || eventY != lastTouchY)
|
||||
@ -223,6 +228,7 @@ public class TouchContext {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelTouch() {
|
||||
cancelled = true;
|
||||
|
||||
@ -235,7 +241,11 @@ public class TouchContext {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPointerCount(int pointerCount) {}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.limelight.binding.input.touch;
|
||||
|
||||
public interface TouchContext {
|
||||
int getActionIndex();
|
||||
void setPointerCount(int pointerCount);
|
||||
boolean touchDownEvent(int eventX, int eventY, boolean isNewFinger);
|
||||
boolean touchMoveEvent(int eventX, int eventY);
|
||||
void touchUpEvent(int eventX, int eventY);
|
||||
void cancelTouch();
|
||||
boolean isCancelled();
|
||||
}
|
@ -348,6 +348,12 @@ public class NvConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMouseHighResScroll(final short scrollAmount) {
|
||||
if (!isMonkey) {
|
||||
MoonBridge.sendMouseHighResScroll(scrollAmount);
|
||||
}
|
||||
}
|
||||
|
||||
public static String findExternalAddressForMdns(String stunHostname, int stunPort) {
|
||||
return MoonBridge.findExternalAddressIP4(stunHostname, stunPort);
|
||||
}
|
||||
|
@ -261,6 +261,8 @@ public class MoonBridge {
|
||||
|
||||
public static native void sendMouseScroll(byte scrollClicks);
|
||||
|
||||
public static native void sendMouseHighResScroll(short scrollAmount);
|
||||
|
||||
public static native String getStageName(int stage);
|
||||
|
||||
public static native String findExternalAddressIP4(String stunHostName, int stunPort);
|
||||
|
@ -41,7 +41,8 @@ public class PreferenceConfiguration {
|
||||
static final String UNLOCK_FPS_STRING = "checkbox_unlock_fps";
|
||||
private static final String VIBRATE_OSC_PREF_STRING = "checkbox_vibrate_osc";
|
||||
private static final String VIBRATE_FALLBACK_PREF_STRING = "checkbox_vibrate_fallback";
|
||||
private static final String FLIP_FACE_BUTTONS_PERF_STRING = "checkbox_flip_face_buttons";
|
||||
private static final String FLIP_FACE_BUTTONS_PREF_STRING = "checkbox_flip_face_buttons";
|
||||
private static final String TOUCHSCREEN_TRACKPAD_PREF_STRING = "checkbox_touchscreen_trackpad";
|
||||
|
||||
static final String DEFAULT_RESOLUTION = "720p";
|
||||
static final String DEFAULT_FPS = "60";
|
||||
@ -69,6 +70,7 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_VIBRATE_OSC = true;
|
||||
private static final boolean DEFAULT_VIBRATE_FALLBACK = false;
|
||||
private static final boolean DEFAULT_FLIP_FACE_BUTTONS = false;
|
||||
private static final boolean DEFAULT_TOUCHSCREEN_TRACKPAD = true;
|
||||
private static final String DEFAULT_AUDIO_CONFIG = "2"; // Stereo
|
||||
|
||||
public static final int FORCE_H265_ON = -1;
|
||||
@ -95,6 +97,7 @@ public class PreferenceConfiguration {
|
||||
public boolean unlockFps;
|
||||
public boolean vibrateOsc;
|
||||
public boolean vibrateFallbackToDevice;
|
||||
public boolean touchscreenTrackpad;
|
||||
public MoonBridge.AudioConfiguration audioConfiguration;
|
||||
|
||||
private static int getHeightFromResolutionString(String resString) {
|
||||
@ -370,7 +373,8 @@ public class PreferenceConfiguration {
|
||||
config.unlockFps = prefs.getBoolean(UNLOCK_FPS_STRING, DEFAULT_UNLOCK_FPS);
|
||||
config.vibrateOsc = prefs.getBoolean(VIBRATE_OSC_PREF_STRING, DEFAULT_VIBRATE_OSC);
|
||||
config.vibrateFallbackToDevice = prefs.getBoolean(VIBRATE_FALLBACK_PREF_STRING, DEFAULT_VIBRATE_FALLBACK);
|
||||
config.flipFaceButtons = prefs.getBoolean(FLIP_FACE_BUTTONS_PERF_STRING, DEFAULT_FLIP_FACE_BUTTONS);
|
||||
config.flipFaceButtons = prefs.getBoolean(FLIP_FACE_BUTTONS_PREF_STRING, DEFAULT_FLIP_FACE_BUTTONS);
|
||||
config.touchscreenTrackpad = prefs.getBoolean(TOUCHSCREEN_TRACKPAD_PREF_STRING, DEFAULT_TOUCHSCREEN_TRACKPAD);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
@ -141,9 +141,17 @@ public class StreamSettings extends Activity {
|
||||
// hide on-screen controls category on non touch screen devices
|
||||
if (!getActivity().getPackageManager().
|
||||
hasSystemFeature("android.hardware.touchscreen")) {
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_onscreen_controls");
|
||||
screen.removePreference(category);
|
||||
{
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_onscreen_controls");
|
||||
screen.removePreference(category);
|
||||
}
|
||||
|
||||
{
|
||||
PreferenceCategory category =
|
||||
(PreferenceCategory) findPreference("category_input_settings");
|
||||
category.removePreference(findPreference("checkbox_touchscreen_trackpad"));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove PiP mode on devices pre-Oreo
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f596e805755cf0b83c14375bc5c9aa182b1766e0
|
||||
Subproject commit c8faf3539b0c33b9e5eb8f5cf99c04d307c0e608
|
@ -49,6 +49,11 @@ Java_com_limelight_nvstream_jni_MoonBridge_sendMouseScroll(JNIEnv *env, jclass c
|
||||
LiSendScrollEvent(scrollClicks);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_sendMouseHighResScroll(JNIEnv *env, jclass clazz, jshort scrollAmount) {
|
||||
LiSendHighResScrollEvent(scrollAmount);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_limelight_nvstream_jni_MoonBridge_stopConnection(JNIEnv *env, jclass clazz) {
|
||||
LiStopConnection();
|
||||
|
@ -140,6 +140,8 @@
|
||||
<string name="summary_audio_config_list">Enable 5.1 or 7.1 surround sound for home-theater systems</string>
|
||||
|
||||
<string name="category_input_settings">Input Settings</string>
|
||||
<string name="title_checkbox_touchscreen_trackpad">Use the touchscreen as a trackpad</string>
|
||||
<string name="summary_checkbox_touchscreen_trackpad">If enabled, the touchscreen acts like a trackpad. If disabled, the touchscreen directly controls the mouse cursor.</string>
|
||||
<string name="title_checkbox_multi_controller">Automatic gamepad presence detection</string>
|
||||
<string name="summary_checkbox_multi_controller">Unchecking this option forces a gamepad to always be present</string>
|
||||
<string name="title_checkbox_vibrate_fallback">Emulate rumble support with vibration</string>
|
||||
|
@ -51,13 +51,19 @@
|
||||
android:entryValues="@array/audio_config_values"
|
||||
android:defaultValue="2" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/category_input_settings">
|
||||
<PreferenceCategory android:title="@string/category_input_settings"
|
||||
android:key="category_input_settings">
|
||||
<!--com.limelight.preferences.SeekBarPreference
|
||||
android:key="seekbar_deadzone"
|
||||
android:defaultValue="15"
|
||||
android:max="50"
|
||||
android:text="@string/suffix_seekbar_deadzone"
|
||||
android:title="@string/title_seekbar_deadzone"/-->
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_touchscreen_trackpad"
|
||||
android:title="@string/title_checkbox_touchscreen_trackpad"
|
||||
android:summary="@string/summary_checkbox_touchscreen_trackpad"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_multi_controller"
|
||||
android:title="@string/title_checkbox_multi_controller"
|
||||
|
Loading…
x
Reference in New Issue
Block a user