Merge pull request #366 from pmarcus93/android-respect-rotation-lock

Respect the device rotation lock on Android
This commit is contained in:
bryanthaboi
2026-07-31 08:08:19 -04:00
committed by GitHub
3 changed files with 54 additions and 2 deletions
+4 -1
View File
@@ -62,7 +62,10 @@ function love.conf(t)
-- the game follow the device. The renderer letterboxes the 160x144 -- the game follow the device. The renderer letterboxes the 160x144
-- viewport into whatever size results, and the on-screen touch controls -- viewport into whatever size results, and the on-screen touch controls
-- re-lay themselves out from the new window size, so both orientations -- re-lay themselves out from the new window size, so both orientations
-- just work. iOS follows the Info.plist orientations -- just work. FULL_SENSOR ignores the device's rotation lock, so
-- GameActivity.setOrientationBis remaps it to FULL_USER after SDL has
-- run: same orientations allowed, but auto-rotate being off now wins.
-- iOS follows the Info.plist orientations
-- (see mobile/ios/overlays/love-ios.plist, now portrait + landscape). -- (see mobile/ios/overlays/love-ios.plist, now portrait + landscape).
t.window.resizable = true t.window.resizable = true
-- Starting size is a tall portrait hint; the OS resizes to the real -- Starting size is a tall portrait hint; the OS resizes to the real
+1 -1
View File
@@ -82,7 +82,7 @@ scripts, tests, and mobile build sources are excluded.
| --- | --- | | --- | --- |
| `app.application_id` | `com.theboisclub.pokemonred` | | `app.application_id` | `com.theboisclub.pokemonred` |
| `app.name` | Pokemon Red | | `app.name` | Pokemon Red |
| `app.orientation` | `portrait` | | `app.orientation` | `fullUser`. This is only the manifest default: SDL requests FULL_SENSOR at window creation (resizable window, no `SDL_HINT_ORIENTATIONS`), and `GameActivity.setOrientationBis` remaps that to FULL_USER so the device's rotation lock is honoured. |
| `app.version_name` / `app.version_code` | set from `--version X.Y.Z` (code = major*10000 + minor*100 + patch); left as-is if `--version` is omitted | | `app.version_name` / `app.version_code` | set from `--version X.Y.Z` (code = major*10000 + minor*100 + patch); left as-is if `--version` is omitted |
| Permissions | INTERNET / RECORD_AUDIO / WRITE_EXTERNAL_STORAGE stripped; VIBRATE + BLUETOOTH kept | | Permissions | INTERNET / RECORD_AUDIO / WRITE_EXTERNAL_STORAGE stripped; VIBRATE + BLUETOOTH kept |
@@ -41,6 +41,7 @@ import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.media.AudioManager; import android.media.AudioManager;
@@ -303,6 +304,54 @@ public class GameActivity extends SDLActivity {
super.onResume(); super.onResume();
} }
/**
* SDL decides the activity's requested orientation at window creation
* (SDLActivity.setOrientationBis). With a resizable window and no
* SDL_HINT_ORIENTATIONS -- exactly what conf.lua produces on Android --
* it asks for SCREEN_ORIENTATION_FULL_SENSOR, and that request overrides
* the android:screenOrientation="fullUser" set in the manifest. The
* *_SENSOR constants follow the accelerometer even when the player has
* turned auto-rotate off, so the game kept rotating on a device whose
* rotation was locked.
*
* Remap SDL's choice onto the matching *_USER constant, which allows the
* same orientations but defers to the system rotation setting. Applied
* after super so SDL keeps deciding *which* orientations the window may
* take; this only changes who breaks the tie, the sensor or the player.
*/
@Override
public void setOrientationBis(int w, int h, boolean resizable, String hint) {
super.setOrientationBis(w, h, resizable, hint);
// The *_USER constants only exist from API 18; below that the sensor
// ones are all there is, so leave SDL's request alone.
if (android.os.Build.VERSION.SDK_INT < 18) {
return;
}
int requested = getRequestedOrientation();
int userRequested;
switch (requested) {
case ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR:
userRequested = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
break;
case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
userRequested = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE;
break;
case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
userRequested = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT;
break;
default:
// SENSOR / plain LANDSCAPE / PORTRAIT etc: either already
// explicit or never produced by setOrientationBis.
return;
}
Log.d("GameActivity", "requestedOrientation " + requested + " -> " + userRequested
+ " (honour the device rotation lock)");
setRequestedOrientation(userRequested);
}
@Keep @Keep
public void setImmersiveMode(boolean immersive_mode) { public void setImmersiveMode(boolean immersive_mode) {
if (android.os.Build.VERSION.SDK_INT >= 28) { if (android.os.Build.VERSION.SDK_INT >= 28) {