Skip to content

Commit

Permalink
Merge pull request #60551 from madmiraal/implement-3466
Browse files Browse the repository at this point in the history
Add a method for obtaining display cutouts on Android
  • Loading branch information
akien-mga authored May 2, 2022
2 parents ce4326d + 71ce585 commit bc7ccc9
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 0 deletions.
7 changes: 7 additions & 0 deletions doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@
<description>
</description>
</method>
<method name="get_display_cutouts" qualifiers="const">
<return type="Array" />
<description>
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.
</description>
</method>
<method name="get_name" qualifiers="const">
<return type="String" />
<description>
Expand Down
6 changes: 6 additions & 0 deletions platform/android/display_server_android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,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);
Expand Down
2 changes: 2 additions & 0 deletions platform/android/display_server_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class DisplayServerAndroid : public DisplayServer {
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;

Expand Down
21 changes: 21 additions & 0 deletions platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
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;
Expand All @@ -51,6 +52,7 @@
import android.view.WindowInsets;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

// Wrapper for native library
Expand Down Expand Up @@ -260,6 +262,25 @@ public int[] screenGetUsableRect() {
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<Rect> 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);
Expand Down
24 changes: 24 additions & 0 deletions platform/android/java_godot_io_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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");
Expand Down Expand Up @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions platform/android/java_godot_io_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <android/log.h>
#include <jni.h>

#include "core/variant/array.h"
#include "string_android.h"

// Class that makes functions in java/src/org/godotengine/godot/GodotIO.java callable from C++
Expand All @@ -48,6 +49,7 @@ class GodotIOJavaWrapper {
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;
Expand Down Expand Up @@ -76,6 +78,7 @@ class GodotIOJavaWrapper {
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);
Expand Down
2 changes: 2 additions & 0 deletions servers/display_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,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));
Expand Down
2 changes: 2 additions & 0 deletions servers/display_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ class DisplayServer : public Object {
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
};
Expand Down

0 comments on commit bc7ccc9

Please sign in to comment.