From 71ce5857ecb76fdca3afc1a0882a575a3879d148 Mon Sep 17 00:00:00 2001 From: Marcel Admiraal Date: Sun, 24 Apr 2022 21:12:22 +0200 Subject: [PATCH] Add a method for obtaining display cutouts on Android --- doc/classes/DisplayServer.xml | 7 ++++++ platform/android/display_server_android.cpp | 6 +++++ platform/android/display_server_android.h | 2 ++ .../src/org/godotengine/godot/GodotIO.java | 21 ++++++++++++++++ platform/android/java_godot_io_wrapper.cpp | 24 +++++++++++++++++++ platform/android/java_godot_io_wrapper.h | 3 +++ servers/display_server.cpp | 2 ++ servers/display_server.h | 2 ++ 8 files changed, 67 insertions(+) diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 0d99c600d5a..8ceb4d9c9b4 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -104,6 +104,13 @@ + + + + Returns an [Array] of [Rect2], each of which is the bounding rectangle for a display cutout or notch. These are non-functional areas on edge-to-edge screens used by cameras and sensors. Returns an empty array if the device does not have cutouts. See also [method screen_get_usable_rect]. + [b]Note:[/b] Currently only implemented on Android. Other platforms will return an empty array even if they do have display cutouts or notches. + + diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index e7de287fc6f..f4487d28f9e 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -106,6 +106,12 @@ bool DisplayServerAndroid::clipboard_has() const { } } +Array DisplayServerAndroid::get_display_cutouts() const { + GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java(); + ERR_FAIL_NULL_V(godot_io_java, Array()); + return godot_io_java->get_display_cutouts(); +} + void DisplayServerAndroid::screen_set_keep_on(bool p_enable) { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); ERR_FAIL_COND(!godot_java); diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 1d268bbcfdd..a2ded8a0b35 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -95,6 +95,8 @@ public: virtual String clipboard_get() const override; virtual bool clipboard_has() const override; + virtual Array get_display_cutouts() const override; + virtual void screen_set_keep_on(bool p_enable) override; virtual bool screen_is_kept_on() const override; 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 e8e292df5dd..af1b54dbacb 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -38,6 +38,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.AssetManager; import android.graphics.Point; +import android.graphics.Rect; import android.net.Uri; import android.os.Build; import android.os.Environment; @@ -51,6 +52,7 @@ import android.view.DisplayCutout; import android.view.WindowInsets; import java.io.IOException; +import java.util.List; import java.util.Locale; // Wrapper for native library @@ -260,6 +262,25 @@ public class GodotIO { return result; } + public int[] getDisplayCutouts() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) + return new int[0]; + DisplayCutout cutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout(); + if (cutout == null) + return new int[0]; + List rects = cutout.getBoundingRects(); + int cutouts = rects.size(); + int[] result = new int[cutouts * 4]; + int index = 0; + for (Rect rect : rects) { + result[index++] = rect.left; + result[index++] = rect.top; + result[index++] = rect.width(); + result[index++] = rect.height(); + } + 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 5b21e696c30..b98e15a54ef 100644 --- a/platform/android/java_godot_io_wrapper.cpp +++ b/platform/android/java_godot_io_wrapper.cpp @@ -31,6 +31,8 @@ #include "java_godot_io_wrapper.h" #include "core/error/error_list.h" +#include "core/math/rect2.h" +#include "core/variant/variant.h" // JNIEnv is only valid within the thread it belongs to, in a multi threading environment // we can't cache it. @@ -51,6 +53,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc _open_URI = p_env->GetMethodID(cls, "openURI", "(Ljava/lang/String;)I"); _get_cache_dir = p_env->GetMethodID(cls, "getCacheDir", "()Ljava/lang/String;"); _get_data_dir = p_env->GetMethodID(cls, "getDataDir", "()Ljava/lang/String;"); + _get_display_cutouts = p_env->GetMethodID(cls, "getDisplayCutouts", "()[I"), _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"); @@ -176,6 +179,27 @@ void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) { } } +Array GodotIOJavaWrapper::get_display_cutouts() { + Array result; + ERR_FAIL_NULL_V(_get_display_cutouts, result); + JNIEnv *env = get_jni_env(); + ERR_FAIL_NULL_V(env, result); + jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _get_display_cutouts); + jint arrayLength = env->GetArrayLength(returnArray); + jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE); + int cutouts = arrayLength / 4; + for (int i = 0; i < cutouts; i++) { + int x = arrayBody[i * 4]; + int y = arrayBody[i * 4 + 1]; + int width = arrayBody[i * 4 + 2]; + int height = arrayBody[i * 4 + 3]; + Rect2 cutout(x, y, width, height); + result.append(cutout); + } + env->ReleaseIntArrayElements(returnArray, arrayBody, 0); + return result; +} + String GodotIOJavaWrapper::get_unique_id() { if (_get_unique_id) { JNIEnv *env = get_jni_env(); diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h index 08e3092afdc..7b87f3deee1 100644 --- a/platform/android/java_godot_io_wrapper.h +++ b/platform/android/java_godot_io_wrapper.h @@ -37,6 +37,7 @@ #include #include +#include "core/variant/array.h" #include "string_android.h" // Class that makes functions in java/src/org/godotengine/godot/GodotIO.java callable from C++ @@ -48,6 +49,7 @@ private: jmethodID _open_URI = 0; jmethodID _get_cache_dir = 0; jmethodID _get_data_dir = 0; + jmethodID _get_display_cutouts = 0; jmethodID _get_locale = 0; jmethodID _get_model = 0; jmethodID _get_screen_DPI = 0; @@ -76,6 +78,7 @@ public: float get_scaled_density(); float get_screen_refresh_rate(float fallback); void screen_get_usable_rect(int (&p_rect_xywh)[4]); + Array get_display_cutouts(); 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/servers/display_server.cpp b/servers/display_server.cpp index 67bfc75426b..111acbc0847 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -491,6 +491,8 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("clipboard_set_primary", "clipboard_primary"), &DisplayServer::clipboard_set_primary); ClassDB::bind_method(D_METHOD("clipboard_get_primary"), &DisplayServer::clipboard_get_primary); + ClassDB::bind_method(D_METHOD("get_display_cutouts"), &DisplayServer::get_display_cutouts); + ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count); ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW)); ClassDB::bind_method(D_METHOD("screen_get_size", "screen"), &DisplayServer::screen_get_size, DEFVAL(SCREEN_OF_MAIN_WINDOW)); diff --git a/servers/display_server.h b/servers/display_server.h index 4961b07ba34..3956e8260de 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -193,6 +193,8 @@ public: virtual void clipboard_set_primary(const String &p_text); virtual String clipboard_get_primary() const; + virtual Array get_display_cutouts() const { return Array(); } + enum { SCREEN_OF_MAIN_WINDOW = -1 };