Browse Source

Implement OS.get_window_safe_area() for Android

Mark Riedesel 4 years ago
parent
commit
2bec10fd1c

+ 1 - 0
platform/android/java/app/res/values/themes.xml

@@ -5,5 +5,6 @@
 
 	<style name="GodotAppSplashTheme" parent="@style/GodotAppMainTheme">
 		<item name="android:windowBackground">@drawable/splash_drawable</item>
+		<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
 	</style>
 </resources>

+ 26 - 0
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);

+ 14 - 0
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();

+ 2 - 0
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);

+ 6 - 0
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";

+ 1 - 0
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;