diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 4ee19df7f..16b687ea1 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -355,6 +355,10 @@ Rect2 _OS::get_window_safe_area() const { return OS::get_singleton()->get_window_safe_area(); } +Array _OS::get_display_cutouts() const { + return OS::get_singleton()->get_display_cutouts(); +} + void _OS::set_window_fullscreen(bool p_enabled) { OS::get_singleton()->set_window_fullscreen(p_enabled); } @@ -1281,6 +1285,7 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("set_min_window_size", "size"), &_OS::set_min_window_size); ClassDB::bind_method(D_METHOD("set_window_size", "size"), &_OS::set_window_size); ClassDB::bind_method(D_METHOD("get_window_safe_area"), &_OS::get_window_safe_area); + ClassDB::bind_method(D_METHOD("get_display_cutouts"), &_OS::get_display_cutouts); ClassDB::bind_method(D_METHOD("set_window_fullscreen", "enabled"), &_OS::set_window_fullscreen); ClassDB::bind_method(D_METHOD("is_window_fullscreen"), &_OS::is_window_fullscreen); ClassDB::bind_method(D_METHOD("set_window_resizable", "enabled"), &_OS::set_window_resizable); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index f015642b4..8fc23d653 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -197,6 +197,7 @@ public: virtual Size2 get_window_size() const; virtual Size2 get_real_window_size() const; virtual Rect2 get_window_safe_area() const; + virtual Array get_display_cutouts() const; virtual void set_max_window_size(const Size2 &p_size); virtual void set_min_window_size(const Size2 &p_size); virtual void set_window_size(const Size2 &p_size); diff --git a/core/os/os.h b/core/os/os.h index 8cc043107..7fa503cf8 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -270,6 +270,8 @@ public: return Rect2(0, 0, window_size.width, window_size.height); } + virtual Array get_display_cutouts() const { return Array(); } + virtual void set_borderless_window(bool p_borderless) {} virtual bool get_borderless_window() { return false; } diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 4490989ca..bd223a40c 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -217,6 +217,13 @@ The returned Dictionary's values will be the same as [method get_datetime], with the exception of Daylight Savings Time as it cannot be determined from the epoch. + + + + 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 get_window_safe_area]. + [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/java/lib/src/net/relintai/pandemonium/pandemonium/PandemoniumIO.java b/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/PandemoniumIO.java index 5808e3760..2e222cbcd 100644 --- a/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/PandemoniumIO.java +++ b/platform/android/java/lib/src/net/relintai/pandemonium/pandemonium/PandemoniumIO.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 PandemoniumIO { 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_pandemonium_io_wrapper.cpp b/platform/android/java_pandemonium_io_wrapper.cpp index ea589a1a7..b078d3609 100644 --- a/platform/android/java_pandemonium_io_wrapper.cpp +++ b/platform/android/java_pandemonium_io_wrapper.cpp @@ -29,7 +29,10 @@ /*************************************************************************/ #include "java_pandemonium_io_wrapper.h" +#include "core/array.h" #include "core/error_list.h" +#include "core/math/rect2.h" +#include "core/variant.h" // JNIEnv is only valid within the thread it belongs to, in a multi threading environment // we can't cache it. @@ -50,6 +53,7 @@ PandemoniumIOJavaWrapper::PandemoniumIOJavaWrapper(JNIEnv *p_env, jobject p_pand _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"); @@ -174,6 +178,27 @@ void PandemoniumIOJavaWrapper::get_window_safe_area(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 PandemoniumIOJavaWrapper::get_unique_id() { if (_get_unique_id) { JNIEnv *env = get_jni_env(); diff --git a/platform/android/java_pandemonium_io_wrapper.h b/platform/android/java_pandemonium_io_wrapper.h index 11c729f8c..785acadf1 100644 --- a/platform/android/java_pandemonium_io_wrapper.h +++ b/platform/android/java_pandemonium_io_wrapper.h @@ -47,6 +47,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; @@ -74,6 +75,7 @@ public: int get_screen_dpi(); float get_scaled_density(); void get_window_safe_area(int (&p_rect_xywh)[4]); + Array get_display_cutouts(); float get_screen_refresh_rate(float p_fallback); String get_unique_id(); bool has_vk(); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index ce830feac..287688c90 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -30,6 +30,7 @@ #include "os_android.h" +#include "core/array.h" #include "core/project_settings.h" #include "drivers/gles2/rasterizer_gles2.h" #include "drivers/unix/dir_access_unix.h" @@ -291,6 +292,10 @@ Rect2 OS_Android::get_window_safe_area() const { return Rect2(xywh[0], xywh[1], xywh[2], xywh[3]); } +Array OS_Android::get_display_cutouts() const { + return pandemonium_io_java->get_display_cutouts(); +} + String OS_Android::get_name() const { return "Android"; } diff --git a/platform/android/os_android.h b/platform/android/os_android.h index c40cc358b..3642a6d4b 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -116,6 +116,7 @@ public: virtual Size2 get_window_size() const; virtual Rect2 get_window_safe_area() const; + virtual Array get_display_cutouts() const; virtual String get_name() const; virtual MainLoop *get_main_loop() const;