From 2bec10fd1caf3fcb42082ca6c3ae71e5a73485f5 Mon Sep 17 00:00:00 2001 From: Mark Riedesel Date: Mon, 26 Oct 2020 15:07:54 -0400 Subject: [PATCH] Implement OS.get_window_safe_area() for Android --- .../android/java/app/res/values/themes.xml | 1 + .../src/org/godotengine/godot/GodotIO.java | 26 +++++++++++++++++++ platform/android/java_godot_io_wrapper.cpp | 14 ++++++++++ platform/android/java_godot_io_wrapper.h | 2 ++ platform/android/os_android.cpp | 6 +++++ platform/android/os_android.h | 1 + 6 files changed, 50 insertions(+) diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml index 26912538d3..99f723f5ba 100644 --- a/platform/android/java/app/res/values/themes.xml +++ b/platform/android/java/app/res/values/themes.xml @@ -5,5 +5,6 @@ diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index 06f425a372..576f09fb24 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -37,12 +37,16 @@ import android.content.*; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.AssetManager; +import android.graphics.Point; import android.media.*; import android.net.Uri; import android.os.*; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; +import android.view.Display; +import android.view.DisplayCutout; +import android.view.WindowInsets; import java.io.IOException; import java.io.InputStream; @@ -494,6 +498,28 @@ public class GodotIO { return (int)(metrics.density * 160f); } + public int[] getWindowSafeArea() { + DisplayMetrics metrics = activity.getResources().getDisplayMetrics(); + Display display = activity.getWindowManager().getDefaultDisplay(); + Point size = new Point(); + display.getRealSize(size); + + int result[] = { 0, 0, size.x, size.y }; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); + DisplayCutout cutout = insets.getDisplayCutout(); + if (cutout != null) { + int insetLeft = cutout.getSafeInsetLeft(); + int insetTop = cutout.getSafeInsetTop(); + result[0] = insetLeft; + result[1] = insetTop; + result[2] -= insetLeft + cutout.getSafeInsetRight(); + result[3] -= insetTop + cutout.getSafeInsetBottom(); + } + } + return result; + } + public void showKeyboard(String p_existing_text, boolean p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) { if (edit != null) edit.showKeyboard(p_existing_text, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end); diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp index 6b26101688..8d3f667317 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -52,6 +52,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc _get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;"); _get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;"); _get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I"); + _get_window_safe_area = p_env->GetMethodID(cls, "getWindowSafeArea", "()[I"), _get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;"); _show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;ZIII)V"); _hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V"); @@ -121,6 +122,19 @@ int GodotIOJavaWrapper::get_screen_dpi() { } } +void GodotIOJavaWrapper::get_window_safe_area(int (&p_rect_xywh)[4]) { + if (_get_window_safe_area) { + JNIEnv *env = ThreadAndroid::get_env(); + jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _get_window_safe_area); + ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4); + jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE); + for (int i = 0; i < 4; i++) { + p_rect_xywh[i] = arrayBody[i]; + } + env->ReleaseIntArrayElements(returnArray, arrayBody, 0); + } +} + String GodotIOJavaWrapper::get_unique_id() { if (_get_unique_id) { JNIEnv *env = ThreadAndroid::get_env(); diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index 118939915a..d03e3cbde5 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -50,6 +50,7 @@ private: jmethodID _get_locale = 0; jmethodID _get_model = 0; jmethodID _get_screen_DPI = 0; + jmethodID _get_window_safe_area = 0; jmethodID _get_unique_id = 0; jmethodID _show_keyboard = 0; jmethodID _hide_keyboard = 0; @@ -71,6 +72,7 @@ public: String get_locale(); String get_model(); int get_screen_dpi(); + void get_window_safe_area(int (&p_rect_xywh)[4]); String get_unique_id(); bool has_vk(); void show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index cd4bc01a44..df59c95d61 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -291,6 +291,12 @@ Size2 OS_Android::get_window_size() const { return Vector2(default_videomode.width, default_videomode.height); } +Rect2 OS_Android::get_window_safe_area() const { + int xywh[4]; + godot_io_java->get_window_safe_area(xywh); + return Rect2(xywh[0], xywh[1], xywh[2], xywh[3]); +} + String OS_Android::get_name() const { return "Android"; diff --git a/platform/android/os_android.h b/platform/android/os_android.h index cacafb70ed..d5cc50f7e5 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -142,6 +142,7 @@ public: virtual void set_keep_screen_on(bool p_enabled); virtual Size2 get_window_size() const; + virtual Rect2 get_window_safe_area() const; virtual String get_name() const; virtual MainLoop *get_main_loop() const;