diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 579d38666d7..6cb049e0e49 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -776,14 +776,14 @@ Returns [code]true[/code] if OS is using dark mode. - [b]Note:[/b] This method is implemented on macOS, Windows and Linux (X11). + [b]Note:[/b] This method is implemented on Android, iOS, macOS, Windows, and Linux (X11). Returns [code]true[/code] if OS supports dark mode. - [b]Note:[/b] This method is implemented on macOS, Windows and Linux (X11). + [b]Note:[/b] This method is implemented on Android, iOS, macOS, Windows, and Linux (X11). diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 3904d3afc48..11c0945ce02 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -111,6 +111,20 @@ void DisplayServerAndroid::tts_stop() { TTS_Android::stop(); } +bool DisplayServerAndroid::is_dark_mode_supported() const { + GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); + ERR_FAIL_NULL_V(godot_java, false); + + return godot_java->is_dark_mode_supported(); +} + +bool DisplayServerAndroid::is_dark_mode() const { + GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); + ERR_FAIL_NULL_V(godot_java, false); + + return godot_java->is_dark_mode(); +} + void DisplayServerAndroid::clipboard_set(const String &p_text) { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); ERR_FAIL_NULL(godot_java); diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index e0ad2cb9161..54912212dc9 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -103,6 +103,9 @@ public: virtual void tts_resume() override; virtual void tts_stop() override; + virtual bool is_dark_mode_supported() const override; + virtual bool is_dark_mode() const override; + virtual void clipboard_set(const String &p_text) override; virtual String clipboard_get() const override; virtual bool clipboard_has() const override; diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt index e115494cfdb..0e111d52470 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt @@ -35,6 +35,7 @@ import android.app.Activity import android.app.AlertDialog import android.content.* import android.content.pm.PackageManager +import android.content.res.Configuration import android.content.res.Resources import android.graphics.Rect import android.hardware.Sensor @@ -694,6 +695,25 @@ class Godot(private val context: Context) : SensorEventListener { } } + /** + * Returns true if dark mode is supported, false otherwise. + */ + @Keep + private fun isDarkModeSupported(): Boolean { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q + } + + /** + * Returns true if dark mode is supported and enabled, false otherwise. + */ + @Keep + private fun isDarkMode(): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return context.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES + } + return false + } + fun hasClipboard(): Boolean { return mClipboard.hasPrimaryClip() } diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index a01a74f1fd3..1703179b8e0 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -62,6 +62,8 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_ _finish = p_env->GetMethodID(godot_class, "forceQuit", "(I)Z"); _set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V"); _alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); + _is_dark_mode_supported = p_env->GetMethodID(godot_class, "isDarkModeSupported", "()Z"); + _is_dark_mode = p_env->GetMethodID(godot_class, "isDarkMode", "()Z"); _get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;"); _set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V"); _has_clipboard = p_env->GetMethodID(godot_class, "hasClipboard", "()Z"); @@ -172,6 +174,26 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) { } } +bool GodotJavaWrapper::is_dark_mode_supported() { + if (_is_dark_mode_supported) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_NULL_V(env, false); + return env->CallBooleanMethod(godot_instance, _is_dark_mode_supported); + } else { + return false; + } +} + +bool GodotJavaWrapper::is_dark_mode() { + if (_is_dark_mode) { + JNIEnv *env = get_jni_env(); + ERR_FAIL_NULL_V(env, false); + return env->CallBooleanMethod(godot_instance, _is_dark_mode); + } else { + return false; + } +} + bool GodotJavaWrapper::has_get_clipboard() { return _get_clipboard != nullptr; } diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index 2ce756807f9..f427a2937c3 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -53,6 +53,8 @@ private: jmethodID _finish = nullptr; jmethodID _set_keep_screen_on = nullptr; jmethodID _alert = nullptr; + jmethodID _is_dark_mode_supported = nullptr; + jmethodID _is_dark_mode = nullptr; jmethodID _get_clipboard = nullptr; jmethodID _set_clipboard = nullptr; jmethodID _has_clipboard = nullptr; @@ -86,6 +88,8 @@ public: bool force_quit(JNIEnv *p_env = nullptr, int p_instance_id = 0); void set_keep_screen_on(bool p_enabled); void alert(const String &p_message, const String &p_title); + bool is_dark_mode_supported(); + bool is_dark_mode(); bool has_get_clipboard(); String get_clipboard(); bool has_set_clipboard(); diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h index da16449c613..be4ea1e6abe 100644 --- a/platform/ios/display_server_ios.h +++ b/platform/ios/display_server_ios.h @@ -141,6 +141,9 @@ public: virtual void tts_resume() override; virtual void tts_stop() override; + virtual bool is_dark_mode_supported() const override; + virtual bool is_dark_mode() const override; + virtual Rect2i get_display_safe_area() const override; virtual int get_screen_count() const override; diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index 33eb16279f6..7d0228ff68c 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -354,6 +354,22 @@ void DisplayServerIOS::tts_stop() { [tts stopSpeaking]; } +bool DisplayServerIOS::is_dark_mode_supported() const { + if (@available(iOS 13.0, *)) { + return true; + } else { + return false; + } +} + +bool DisplayServerIOS::is_dark_mode() const { + if (@available(iOS 13.0, *)) { + return [UITraitCollection currentTraitCollection].userInterfaceStyle == UIUserInterfaceStyleDark; + } else { + return false; + } +} + Rect2i DisplayServerIOS::get_display_safe_area() const { if (@available(iOS 11, *)) { UIEdgeInsets insets = UIEdgeInsetsZero;