Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to change the right click action to a double tap #1207

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
547c74a
Added the option to double tap to right click (#1064).
May 2, 2023
3f1cb62
Revert "Added the option to double tap to right click (#1064)."
May 2, 2023
5471bae
Added the option to double tap to right click (#1064)
May 2, 2023
dbd86bb
Translated using Weblate (Swedish)
bittin Nov 23, 2023
6ff9147
Merge branch 'master' into master
RadoMiami Dec 10, 2023
56ad484
Bump AGP to 8.2.0
cgutman Dec 30, 2023
1fe19e9
Update moonlight-common-c for X-SS-Connect-Data support
cgutman Dec 30, 2023
e63dc9a
Suppress bogus UnspecifiedRegisterReceiverFlag warning
cgutman Dec 30, 2023
4142907
Don't consume special key combos that we don't handle
cgutman Dec 31, 2023
2a09443
Don't override HDR color format for AV1
cgutman Dec 31, 2023
a102ec4
Fix inverted logic
cgutman Dec 31, 2023
69387c3
Display error codes when the connection is terminated
cgutman Dec 31, 2023
4330a22
Handle start+select as home button on Thrustmaster Score A gamepad (#…
guillaumezin Dec 31, 2023
57e19d7
Translated using Weblate (French)
jorys-paulin Jan 8, 2024
7b13f12
Update moonlight-common-c with new encryption support
cgutman Jan 15, 2024
f7520ba
Move encryption enablement logic into JNI code
cgutman Jan 15, 2024
3f9f8f7
Opt in for video encryption on platforms with fast AES implementations
cgutman Jan 15, 2024
3aab9eb
Analog stick for scrolling in mouse emulation mode
joaomacp Jan 7, 2024
dbf1b88
Adjust emulated rumble strength (#1288)
AlekLefebvre Jan 20, 2024
f2c6e9e
Update moonlight-common-c with finalized encryption changes
cgutman Jan 20, 2024
6ff37a1
Tweak strings for rumble strength options
cgutman Jan 20, 2024
fcd27b4
Eat all exceptions from attempting to start ACTION_REQUEST_CHANNEL_BR…
cgutman Jan 20, 2024
3ea9ef1
Merge remote-tracking branch 'origin/weblate'
cgutman Jan 20, 2024
3722106
Translated using Weblate (Dutch)
weblate Jan 20, 2024
27fe37f
Translated using Weblate (Romanian)
weblate Jan 20, 2024
83c698b
Translated using Weblate (Chinese (Simplified))
weblate Jan 20, 2024
78b8d1e
Translated using Weblate (Spanish)
gallegonovato Jan 20, 2024
523ca86
Translated using Weblate (Ukrainian)
onix Jan 21, 2024
8ff9f70
Translated using Weblate (Chinese (Simplified))
137615 Jan 22, 2024
aaaebde
Translated using Weblate (Swedish)
bittin Jan 23, 2024
3c58e2f
Translated using Weblate (Polish)
doasmike Jan 29, 2024
6aca18b
Translated using Weblate (French)
jorys-paulin Feb 4, 2024
224bab6
Translated using Weblate (French)
jorys-paulin Feb 9, 2024
f638548
Translated using Weblate (Greek)
ShadowDevman Feb 11, 2024
613ecff
Add Game Mode configuration
cgutman Feb 18, 2024
9a7381b
Update moonlight-common-c with RTSP encryption
cgutman Feb 18, 2024
2ba7f0d
Update to AGP 8.2.2
cgutman Feb 18, 2024
082cc84
Remove sustained performance mode
cgutman Feb 18, 2024
e70014b
Merge remote-tracking branch 'origin/weblate'
cgutman Feb 22, 2024
1b1b100
Version 12.1
cgutman Feb 28, 2024
6551076
Add Vendor 8BitDo to Xbox360Controller (#1333)
komurlu Feb 28, 2024
17df152
Drop support for Jelly Bean and KitKat
cgutman Mar 17, 2024
070c82b
Update to NDK 26c
cgutman Mar 17, 2024
01507d9
Enable BTI on ARMv8
cgutman Mar 17, 2024
124bfdf
Bump all dependencies to latest versions
cgutman Mar 17, 2024
f54f8c8
Update to libopus v1.5.1
cgutman Mar 18, 2024
85ed728
feat: Add `Guide menu` to on-screen virtual controller (#1265)
mattvgm Jul 27, 2024
b7b6ada
feat(activity): allow PC Name and AppName for ShortcutTrampoline (#1387)
ReenigneArcher Jul 27, 2024
24d3fb0
Update AGP and Gradle
cgutman Jul 27, 2024
34a9132
Update to NDK r27
cgutman Jul 27, 2024
eb7f088
Enable support for 16KB pages
cgutman Jul 27, 2024
f10085f
Update to libopus v1.5.2
cgutman Jul 27, 2024
01ac925
Updated to be in line with current version of Moonlight Android
RadoMiami Dec 4, 2024
415f9f1
Re-merged changes onto this branch
RadoMiami Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
apply plugin: 'com.android.application'

android {
ndkVersion "23.2.8568313"
<<<<<<< HEAD
ndkVersion "27.0.12077973"
=======
ndkVersion '25.2.9519653'
>>>>>>> 6ff914739a5141861a388e5758692c22155db5b8

compileSdk 34

namespace 'com.limelight'

defaultConfig {
minSdk 16
minSdk 21
targetSdk 34

versionName "12.0.2"
versionCode = 313
versionName "12.1"
versionCode = 314

// Generate native debug symbols to allow Google Play to symbolicate our native crashes
ndk.debugSymbolLevel = 'FULL'
Expand Down Expand Up @@ -136,12 +140,10 @@ android {
}

dependencies {
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
implementation 'org.jcodec:jcodec:0.2.3'
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
implementation 'com.squareup.okio:okio:1.17.5'
// 3.5.8 requires minSdk 19, uses StandardCharsets.UTF_8 internally
implementation 'org.jmdns:jmdns:3.5.7'
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
implementation 'org.jcodec:jcodec:0.2.5'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'org.jmdns:jmdns:3.5.9'
implementation 'com.github.cgutman:ShieldControllerExtensions:1.0.1'
}
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
<meta-data
android:name="com.android.graphics.intervention.wm.allowDownscale"
android:value="false"/>

<!-- Game Mode configuration -->
<meta-data
android:name="android.game_mode_config"
android:resource="@xml/game_mode_config" />

<!-- Samsung DeX support requires explicit placement of android:resizeableActivity="true"
in each activity even though it is implied by targeting API 24+ -->
Expand Down
162 changes: 79 additions & 83 deletions app/src/main/java/com/limelight/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
// Only 2 touches are supported
private final TouchContext[] touchContextMap = new TouchContext[2];
private long threeFingerDownTime = 0;
private long twoFingerDownTime = 0;

private static final int REFERENCE_HORIZ_RES = 1280;
private static final int REFERENCE_VERT_RES = 720;
Expand All @@ -108,6 +109,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private static final int STYLUS_UP_DEAD_ZONE_RADIUS = 50;

private static final int THREE_FINGER_TAP_THRESHOLD = 300;
private static final int TWO_FINGER_TAP_THRESHOLD = 300;

private ControllerHandler controllerHandler;
private KeyboardTranslator keyboardTranslator;
Expand Down Expand Up @@ -195,14 +197,12 @@ protected void onCreate(Bundle savedInstanceState) {

// If we're going to use immersive mode, we want to have
// the entire screen
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);

// Listen for UI visibility events
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
Expand Down Expand Up @@ -478,7 +478,6 @@ public void notifyCrash(Exception e) {
.setAttachedGamepadMask(gamepadMask)
.setClientRefreshRateX100((int)(displayRefreshRate * 100))
.setAudioConfiguration(prefConfig.audioConfiguration)
.setAudioEncryption(true)
.setColorSpace(decoderRenderer.getPreferredColorSpace())
.setColorRange(decoderRenderer.getPreferredColorRange())
.setPersistGamepadsAfterDisconnect(!prefConfig.multiController)
Expand All @@ -498,7 +497,7 @@ public void notifyCrash(Exception e) {
// Initialize touch contexts
for (int i = 0; i < touchContextMap.length; i++) {
if (!prefConfig.touchscreenTrackpad) {
touchContextMap[i] = new AbsoluteTouchContext(conn, i, streamView);
touchContextMap[i] = new AbsoluteTouchContext(conn, i, streamView, prefConfig);
}
else {
touchContextMap[i] = new RelativeTouchContext(conn, i,
Expand All @@ -507,12 +506,6 @@ public void notifyCrash(Exception e) {
}
}

// Use sustained performance mode on N+ to ensure consistent
// CPU availability
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
getWindow().setSustainedPerformanceMode(true);
}

if (prefConfig.onscreenController) {
// create virtual onscreen controller
virtualController = new VirtualController(controllerHandler,
Expand Down Expand Up @@ -567,39 +560,19 @@ private void setPreferredOrientationForCurrentDisplay() {
}

if (desiredOrientation == Configuration.ORIENTATION_LANDSCAPE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
else if (desiredOrientation == Configuration.ORIENTATION_PORTRAIT) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT);
}
else {
// If we don't have a reason to lock to portrait or landscape, allow any orientation
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
}
}
else {
// For regular displays, we always request landscape
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE);
}
}

Expand Down Expand Up @@ -927,7 +900,7 @@ else if (!isRefreshRateGoodMatch(candidate.getRefreshRate())) {
displayRefreshRate = bestMode.getRefreshRate();
}
// On L, we can at least tell the OS that we want a refresh rate
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
else {
float bestRefreshRate = display.getRefreshRate();
for (float candidate : display.getSupportedRefreshRates()) {
LimeLog.info("Examining refresh rate: "+candidate);
Expand All @@ -951,19 +924,12 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Apply the refresh rate change
getWindow().setAttributes(windowLayoutParams);
}
else {
// Otherwise, the active display refresh rate is just
// whatever is currently in use.
displayRefreshRate = display.getRefreshRate();
}

// From 4.4 to 5.1 we can't ask for a 4K display mode, so we'll
// Until Marshmallow, we can't ask for a 4K display mode, so we'll
// need to hint the OS to provide one.
boolean aspectRatioMatch = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
// On KitKat and later (where we can use the whole screen via immersive mode), we'll
// calculate whether we need to scale by aspect ratio or not. If not, we'll use
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// We'll calculate whether we need to scale by aspect ratio. If not, we'll use
// setFixedSize so we can handle 4K properly. The only known devices that have
// >= 4K screens have exactly 4K screens, so we'll be able to hit this good path
// on these devices. On Marshmallow, we can start changing to 4K manually but no
Expand Down Expand Up @@ -1018,8 +984,8 @@ public void run() {
Game.this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
// Use immersive mode on 4.4+ or standard low profile on previous builds
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
else {
// Use immersive mode
Game.this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
Expand All @@ -1028,11 +994,6 @@ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
else {
Game.this.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LOW_PROFILE);
}
}
};

Expand All @@ -1055,16 +1016,10 @@ public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
// that case here too.
if (isInMultiWindowMode) {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

// Disable performance optimizations for foreground
getWindow().setSustainedPerformanceMode(false);
decoderRenderer.notifyVideoBackground();
}
else {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

// Enable performance optimizations for foreground
getWindow().setSustainedPerformanceMode(true);
decoderRenderer.notifyVideoForeground();
}

Expand Down Expand Up @@ -1300,10 +1255,20 @@ else if (modifierFlags != 0) {
else if ((modifierFlags & (KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT)) ==
(KeyboardPacket.MODIFIER_CTRL | KeyboardPacket.MODIFIER_ALT | KeyboardPacket.MODIFIER_SHIFT) &&
(down && nonModifierKeyCode != KeyEvent.KEYCODE_UNKNOWN)) {
// Remember that a special key combo was activated, so we can consume all key events until the modifiers come up
specialKeyCode = androidKeyCode;
waitingForAllModifiersUp = true;
return true;
switch (androidKeyCode) {
case KeyEvent.KEYCODE_Z:
case KeyEvent.KEYCODE_Q:
case KeyEvent.KEYCODE_C:
// Remember that a special key combo was activated, so we can consume all key
// events until the modifiers come up
specialKeyCode = androidKeyCode;
waitingForAllModifiersUp = true;
return true;

default:
// This isn't a special combo that we consume on the client side
return false;
}
}

// Not a special combo
Expand Down Expand Up @@ -2050,6 +2015,21 @@ else if (event.getActionMasked() == MotionEvent.ACTION_UP || event.getActionMask
return true;
}

// Special handling for 2 finger right click, same as above
if (event.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN &&
<<<<<<< HEAD
event.getPointerCount() == 2) {
=======
event.getPointerCount() == 2 && prefConfig.twoFingerRightClick) {
>>>>>>> 6ff914739a5141861a388e5758692c22155db5b8
twoFingerDownTime = event.getEventTime();
for (TouchContext aTouchContext : touchContextMap) {
aTouchContext.cancelTouch();
}

return true;
}

// TODO: Re-enable native touch when have a better solution for handling
// cancelled touches from Android gestures and 3 finger taps to activate
// the software keyboard.
Expand Down Expand Up @@ -2085,6 +2065,22 @@ else if (event.getActionMasked() == MotionEvent.ACTION_UP || event.getActionMask
}
}

if (event.getPointerCount() == 1 &&
(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || (event.getFlags() & MotionEvent.FLAG_CANCELED) == 0)) {
<<<<<<< HEAD
// All fingers up
if (event.getEventTime() - twoFingerDownTime < TWO_FINGER_TAP_THRESHOLD) {
// This is a 3 finger tap to bring up the keyboard
=======
if (event.getEventTime() - twoFingerDownTime < TWO_FINGER_TAP_THRESHOLD) {
// This is a 2 finger tap to right click
>>>>>>> 6ff914739a5141861a388e5758692c22155db5b8
conn.sendMouseButtonDown(MouseButtonPacket.BUTTON_RIGHT);
conn.sendMouseButtonUp(MouseButtonPacket.BUTTON_RIGHT);
return true;
}
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && (event.getFlags() & MotionEvent.FLAG_CANCELED) != 0) {
context.cancelTouch();
}
Expand Down Expand Up @@ -2217,13 +2213,11 @@ public boolean onGenericMotion(View view, MotionEvent event) {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent event) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Tell the OS not to buffer input events for us
//
// NB: This is still needed even when we call the newer requestUnbufferedDispatch()!
view.requestUnbufferedDispatch(event);
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Tell the OS not to buffer input events for us
//
// NB: This is still needed even when we call the newer requestUnbufferedDispatch()!
view.requestUnbufferedDispatch(event);
}

return handleMotionEvent(view, event);
Expand Down Expand Up @@ -2361,7 +2355,16 @@ public void run() {
break;

default:
message = getResources().getString(R.string.conn_terminated_msg);
String errorCodeString;
// We'll assume large errors are hex values
if (Math.abs(errorCode) > 1000) {
errorCodeString = Integer.toHexString(errorCode);
}
else {
errorCodeString = Integer.toString(errorCode);
}
message = getResources().getString(R.string.conn_terminated_msg) + "\n\n" +
getResources().getString(R.string.error_code_prefix) + " " + errorCodeString;
break;
}
}
Expand Down Expand Up @@ -2661,14 +2664,7 @@ public void onSystemUiVisibilityChange(int visibility) {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
hideSystemUi(2000);
}
// This flag is only set on 4.4+
else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT &&
(visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
hideSystemUi(2000);
}
// This flag is only set before 4.4+
else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT &&
(visibility & View.SYSTEM_UI_FLAG_LOW_PROFILE) == 0) {
else if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
hideSystemUi(2000);
}
}
Expand Down
Loading