diff --git a/Common/System/System.h b/Common/System/System.h index a1a10d9dd9..9ad7977590 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -243,6 +243,8 @@ enum SystemProperty { SYSPROP_USE_APP_STORE, SYSPROP_SUPPORTS_SHARE_TEXT, + SYSPROP_CAN_RESTRICT_ORIENTATION, + SYSPROP_INSTALLER_NAME, // Useful on Android to check if we were installed from the play store. }; diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index bbd1263832..7c1aee5720 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -294,7 +294,7 @@ void DisplayLayoutScreen::CreateViews() { rightColumn->Add(new CheckBox(&config.bIgnoreScreenInsets, gr->T("Ignore camera notch when centering"))); } - if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { + if (System_GetPropertyBool(SYSPROP_CAN_RESTRICT_ORIENTATION)) { rightColumn->Add(new Spacer(12.0f)); AddRotationPicker(screenManager(), rightColumn, true); } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2a5f35f001..4b1b6fa2e7 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1424,15 +1424,15 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { PopupSliderChoice *exitConfirmation = systemSettings->Add(new PopupSliderChoice(&g_Config.iAskForExitConfirmationAfterSeconds, 0, 1200, 300, sy->T("Ask for exit confirmation after seconds"), screenManager(), "s")); exitConfirmation->SetZeroLabel(sy->T("Off")); - if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { + if (System_GetPropertyBool(SYSPROP_CAN_RESTRICT_ORIENTATION)) { auto co = GetI18NCategory(I18NCat::CONTROLS); // Display rotation AddRotationPicker(screenManager(), systemSettings, true); + } - if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) { - systemSettings->Add(new CheckBox(&g_Config.bSustainedPerformanceMode, sy->T("Sustained performance mode")))->OnClick.Handle(this, &GameSettingsScreen::OnSustainedPerformanceModeChange); - } + if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) { + systemSettings->Add(new CheckBox(&g_Config.bSustainedPerformanceMode, sy->T("Sustained performance mode")))->OnClick.Handle(this, &GameSettingsScreen::OnSustainedPerformanceModeChange); } systemSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings); diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 669c6638eb..19543e30ce 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -760,7 +760,7 @@ void GamePauseScreen::CreateViews() { screenManager()->push(new GameScreen(gamePath_, true)); }); - if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { + if (System_GetPropertyBool(SYSPROP_CAN_RESTRICT_ORIENTATION)) { AddRotationPicker(screenManager(), middleColumn, false); } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 3315bb6be4..66248735d6 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -150,6 +150,7 @@ static int optimalSampleRate = 0; static int sampleRate = 0; static int framesPerBuffer = 0; static int androidVersion; +static int smallestScreenWidthDp; static int deviceType; // This is the ACTUAL display size, not the hardware scaled display size. @@ -529,6 +530,12 @@ bool System_GetPropertyBool(SystemProperty prop) { return false; // We can't create shortcuts directly from game code, but we can from the Android UI. case SYSPROP_DISPLAY_HAS_CAMERA_CUTOUT: return g_hasCameraCutout; + case SYSPROP_CAN_RESTRICT_ORIENTATION: + // On Android 17+, large displays (sw600dp+) ignore orientation restrictions. + if (androidVersion >= 37 && smallestScreenWidthDp >= 600) { + return false; + } + return true; #ifndef HTTPS_NOT_AVAILABLE case SYSPROP_SUPPORTS_HTTPS: return !g_Config.bDisableHTTPS; @@ -738,7 +745,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init (JNIEnv * env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath, jstring jdataDir, jstring jexternalStorageDir, jstring jexternalFilesDir, jstring jNativeLibDir, jstring jadditionalStorageDirs, jstring jcacheDir, jstring jshortcutParam, jstring jInstallerName, - jint jAndroidVersion, jstring jboard) { + jint jAndroidVersion, jstring jboard, jint jSmallestScreenWidthDp) { SetCurrentThreadName("androidInit"); // Makes sure we get early permission grants. @@ -750,6 +757,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init renderer_inited = false; exitRenderLoop = false; androidVersion = jAndroidVersion; + smallestScreenWidthDp = jSmallestScreenWidthDp; deviceType = jdeviceType; Path apkPath(GetJavaString(env, japkpath)); diff --git a/android/src/org/ppsspp/ppsspp/NativeApp.java b/android/src/org/ppsspp/ppsspp/NativeApp.java index 6dc3c42433..a2b575e193 100644 --- a/android/src/org/ppsspp/ppsspp/NativeApp.java +++ b/android/src/org/ppsspp/ppsspp/NativeApp.java @@ -29,7 +29,7 @@ public class NativeApp { public static final int RESULT_ERROR_ACTIVITY_NOT_FOUND = 1; public static final int RESULT_ERROR_OTHER_ACTIVITY_ERROR = 2; - public static native void init(String model, int deviceType, String languageRegion, String apkPath, String dataDir, String externalStorageDir, String extFilesDir, String nativeLibDir, String additionalStorageDirs, String cacheDir, String shortcutParam, String installerName, int androidVersion, String board); + public static native void init(String model, int deviceType, String languageRegion, String apkPath, String dataDir, String externalStorageDir, String extFilesDir, String nativeLibDir, String additionalStorageDirs, String cacheDir, String shortcutParam, String installerName, int androidVersion, String board, int smallestScreenWidthDp); public static native void audioInit(); public static native void audioShutdown(); public static native void audioConfig(int optimalFramesPerBuffer, int optimalSampleRate); diff --git a/android/src/org/ppsspp/ppsspp/PpssppActivity.java b/android/src/org/ppsspp/ppsspp/PpssppActivity.java index 40652eca41..9d16390bf2 100644 --- a/android/src/org/ppsspp/ppsspp/PpssppActivity.java +++ b/android/src/org/ppsspp/ppsspp/PpssppActivity.java @@ -533,8 +533,9 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList PackageManager packageManager = getPackageManager(); String installerName = getInstallerName(packageManager); + int smallestScreenWidthDp = getResources().getConfiguration().smallestScreenWidthDp; NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate); - NativeApp.init(model, deviceType, languageRegion, apkFilePath, dataDir, extStorageDir, externalFilesDir, nativeLibDir, additionalStorageDirs, cacheDir, shortcut, installerName, Build.VERSION.SDK_INT, Build.BOARD); + NativeApp.init(model, deviceType, languageRegion, apkFilePath, dataDir, extStorageDir, externalFilesDir, nativeLibDir, additionalStorageDirs, cacheDir, shortcut, installerName, Build.VERSION.SDK_INT, Build.BOARD, smallestScreenWidthDp); // Allow C++ to tell us to use JavaGL or not. javaGL = "true".equalsIgnoreCase(NativeApp.queryConfig("androidJavaGL")); @@ -605,6 +606,11 @@ public class PpssppActivity extends AppCompatActivity implements SensorEventList @SuppressLint("SourceLockedOrientationActivity") private void updateScreenRotation(String cause) { + if (Build.VERSION.SDK_INT >= 37 && getResources().getConfiguration().smallestScreenWidthDp >= 600) { + // Android 17+ on large screens (sw600dp+) ignores orientation requests to push for adaptive apps. + // If we try anyway, it's just a waste of time and might cause weirdness. + return; + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (isInMultiWindowMode()) { // Do not try to enforce rotation! This can result in re-init loops. diff --git a/ios/main.mm b/ios/main.mm index 3b9f574490..24231edb02 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -412,6 +412,9 @@ bool System_GetPropertyBool(SystemProperty prop) { case SYSPROP_CAN_READ_BATTERY_PERCENTAGE: return true; + case SYSPROP_CAN_RESTRICT_ORIENTATION: + return true; + default: return false; }