diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index c4f69d18..0787a9f5 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -526,18 +526,55 @@ public class Game extends Activity implements SurfaceHolder.Callback, } private void setPreferredOrientationForCurrentDisplay() { - // If the display is somewhat square and OSC is disabled, allow any orientation. Otherwise, request landscape. - // The OSC code assumes a landscape display, so we force landscape if OSC is enabled. Display display = getWindowManager().getDefaultDisplay(); - if (!prefConfig.onscreenController && PreferenceConfiguration.isSquarishScreen(display.getWidth(), display.getHeight())) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER); + + // For semi-square displays, we use more complex logic to determine which orientation to use (if any) + if (PreferenceConfiguration.isSquarishScreen(display)) { + int desiredOrientation = Configuration.ORIENTATION_UNDEFINED; + + // OSC doesn't properly support portrait displays, so don't use it in portrait mode by default + if (prefConfig.onscreenController) { + desiredOrientation = Configuration.ORIENTATION_LANDSCAPE; + } + + // For native resolution, we will lock the orientation to the one that matches the specified resolution + if (PreferenceConfiguration.isNativeResolution(prefConfig.width, prefConfig.height)) { + if (prefConfig.width > prefConfig.height) { + desiredOrientation = Configuration.ORIENTATION_LANDSCAPE; + } + else { + desiredOrientation = Configuration.ORIENTATION_PORTRAIT; + } + } + + 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); + } + } + 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); + } } else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); + // 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); + } } } 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); } diff --git a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java index 42b76333..3e248564 100644 --- a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java +++ b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java @@ -5,6 +5,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.Build; import android.preference.PreferenceManager; +import android.view.Display; import com.limelight.nvstream.jni.MoonBridge; @@ -158,6 +159,21 @@ public class PreferenceConfiguration { return longDim / shortDim < 1.3f; } + public static boolean isSquarishScreen(Display display) { + int width, height; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + width = display.getMode().getPhysicalWidth(); + height = display.getMode().getPhysicalHeight(); + } + else { + width = display.getWidth(); + height = display.getHeight(); + } + + return isSquarishScreen(width, height); + } + private static String convertFromLegacyResolutionString(String resString) { if (resString.equalsIgnoreCase("360p")) { return RES_360P; diff --git a/app/src/main/java/com/limelight/preferences/StreamSettings.java b/app/src/main/java/com/limelight/preferences/StreamSettings.java index 800aee33..b25510b8 100644 --- a/app/src/main/java/com/limelight/preferences/StreamSettings.java +++ b/app/src/main/java/com/limelight/preferences/StreamSettings.java @@ -106,7 +106,7 @@ public class StreamSettings extends Activity { pref.setValue(value); } - private void addNativeResolutionEntry(int nativeWidth, int nativeHeight, boolean insetsRemoved) { + private void addNativeResolutionEntry(int nativeWidth, int nativeHeight, boolean insetsRemoved, boolean portrait) { ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING); String newName; @@ -118,6 +118,15 @@ public class StreamSettings extends Activity { newName = getResources().getString(R.string.resolution_prefix_native); } + if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) { + if (portrait) { + newName += " " + getResources().getString(R.string.resolution_prefix_native_portrait); + } + else { + newName += " " + getResources().getString(R.string.resolution_prefix_native_landscape); + } + } + newName += " ("+nativeWidth+"x"+nativeHeight+")"; String newValue = nativeWidth+"x"+nativeHeight; @@ -147,6 +156,13 @@ public class StreamSettings extends Activity { } } + private void addNativeResolutionEntries(int nativeWidth, int nativeHeight, boolean insetsRemoved) { + addNativeResolutionEntry(nativeWidth, nativeHeight, insetsRemoved, false); + if (PreferenceConfiguration.isSquarishScreen(nativeWidth, nativeHeight)) { + addNativeResolutionEntry(nativeHeight, nativeWidth, insetsRemoved, true); + } + } + private void removeValue(String preferenceKey, String value, Runnable onMatched) { int matchingCount = 0; @@ -300,7 +316,7 @@ public class StreamSettings extends Activity { int width = Math.max(metrics.widthPixels - widthInsets, metrics.heightPixels - heightInsets); int height = Math.min(metrics.widthPixels - widthInsets, metrics.heightPixels - heightInsets); - addNativeResolutionEntry(width, height, false); + addNativeResolutionEntries(width, height, false); hasInsets = true; } } @@ -325,7 +341,7 @@ public class StreamSettings extends Activity { // unless they report greater than 4K resolutions. if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION) || (width > 3840 || height > 2160)) { - addNativeResolutionEntry(width, height, hasInsets); + addNativeResolutionEntries(width, height, hasInsets); } if ((width >= 3840 || height >= 2160) && maxSupportedResW < 3840) { @@ -435,7 +451,7 @@ public class StreamSettings extends Activity { getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics); int width = Math.max(metrics.widthPixels, metrics.heightPixels); int height = Math.min(metrics.widthPixels, metrics.heightPixels); - addNativeResolutionEntry(width, height, false); + addNativeResolutionEntries(width, height, false); } else { // On Android 4.1, we have to resort to reflection to invoke hidden APIs @@ -446,7 +462,7 @@ public class StreamSettings extends Activity { Method getRawWidthFunc = Display.class.getMethod("getRawWidth"); int width = (Integer) getRawWidthFunc.invoke(display); int height = (Integer) getRawHeightFunc.invoke(display); - addNativeResolutionEntry(Math.max(width, height), Math.min(width, height), false); + addNativeResolutionEntries(Math.max(width, height), Math.min(width, height), false); } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ed1827bd..73d664ae 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -152,6 +152,8 @@ Stretch video to full-screen Native Native Full-Screen + (Landscape) + (Portrait) Audio Settings Surround sound configuration