From 53177035674c3c1b2a33abb021aecc2c0140b5e2 Mon Sep 17 00:00:00 2001
From: klirktag <[EMAIL REDACTED]>
Date: Sun, 21 Jun 2026 13:36:55 +0200
Subject: [PATCH] Android: hide system bars via WindowInsetsController on API
30+
The immersive-fullscreen code hid the status and navigation bars with the
deprecated View.setSystemUiVisibility() flags plus FLAG_FULLSCREEN. On
Android 15+ (API 35), edge-to-edge is enforced for apps targeting SDK 35+
and those flags are ignored, so the bars never hide (e.g. on a Samsung
S25). Android 14 and below still honour them, which is why older devices
were unaffected.
Hide/show the system bars with WindowInsetsController on API 30+ (using
BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE for sticky-immersive), keeping the
legacy setSystemUiVisibility() path for API < 30. The minimum supported
version is unchanged.
(cherry picked from commit a442367706d1bde3b29232a351e62f749559560d)
---
.../main/java/org/libsdl/app/SDLActivity.java | 60 +++++++++++++------
1 file changed, 43 insertions(+), 17 deletions(-)
diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
index 62abfa7aa4cf2..0ae1bcc99d4ef 100644
--- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
+++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
@@ -39,6 +39,8 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.view.WindowManager;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
@@ -952,15 +954,31 @@ public void handleMessage(Message msg) {
Window window = ((Activity) context).getWindow();
if (window != null) {
if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) {
- int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
- window.getDecorView().setSystemUiVisibility(flags);
- window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
- window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+ if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */) {
+ // The legacy setSystemUiVisibility() flags are ignored on
+ // Android 15+ (API 35+), where edge-to-edge is enforced for
+ // apps targeting that SDK, so the status/navigation bars
+ // would never hide. Use WindowInsetsController instead.
+ window.setDecorFitsSystemWindows(false);
+ final WindowInsetsController controller = window.getInsetsController();
+ if (controller != null) {
+ controller.hide(WindowInsets.Type.systemBars());
+ // Sticky-immersive (replaces SYSTEM_UI_FLAG_IMMERSIVE_STICKY):
+ // a swipe shows the bars transiently, then they auto-hide.
+ controller.setSystemBarsBehavior(
+ WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
+ }
+ } else {
+ int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
+ window.getDecorView().setSystemUiVisibility(flags);
+ window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+ }
SDLActivity.mFullscreenModeActive = true;
} else {
int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
@@ -1799,14 +1817,22 @@ public boolean onKey(DialogInterface d, int keyCode, KeyEvent event) {
private final Runnable rehideSystemUi = new Runnable() {
@Override
public void run() {
- int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
-
- SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags);
+ if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */) {
+ final WindowInsetsController controller =
+ SDLActivity.this.getWindow().getInsetsController();
+ if (controller != null) {
+ controller.hide(WindowInsets.Type.systemBars());
+ }
+ } else {
+ int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
+
+ SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags);
+ }
}
};