diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 15b3c997fbb..af17a38f8f3 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -2543,7 +2543,7 @@ Display server supports [url=https://en.wikipedia.org/wiki/Input_method]Input Method Editor[/url], which is commonly used for inputting Chinese/Japanese/Korean text. This is handled by the operating system, rather than by Godot. [b]Windows, macOS, Linux (X11)[/b] - Display server supports windows can use per-pixel transparency to make windows behind them partially or fully visible. [b]Windows, macOS, Linux (X11/Wayland)[/b] + Display server supports windows can use per-pixel transparency to make windows behind them partially or fully visible. [b]Windows, macOS, Linux (X11/Wayland), Android[/b] Display server supports querying the operating system's display scale factor. This allows automatically detecting the hiDPI display [i]reliably[/i], instead of guessing based on the screen resolution and the display's reported DPI (which might be unreliable due to broken monitor EDID). [b]Windows, Linux (Wayland), macOS[/b] @@ -3073,7 +3073,7 @@ The window background can be transparent. [b]Note:[/b] This flag has no effect if [method is_window_transparency_available] returns [code]false[/code]. - [b]Note:[/b] Transparency support is implemented on Linux (X11/Wayland), macOS, and Windows, but availability might vary depending on GPU driver, display manager, and compositor capabilities. + [b]Note:[/b] Transparency support is implemented on Android, Linux (X11/Wayland), macOS, and Windows, but availability might vary depending on GPU driver, display manager, and compositor capabilities. The window can't be focused. No-focus window will ignore all input, except mouse clicks. diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 32479316adf..64e1fea119d 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -76,7 +76,7 @@ bool DisplayServerAndroid::has_feature(Feature p_feature) const { //case FEATURE_NATIVE_DIALOG_FILE_EXTRA: case FEATURE_NATIVE_DIALOG_FILE_MIME: //case FEATURE_NATIVE_ICON: - //case FEATURE_WINDOW_TRANSPARENCY: + case FEATURE_WINDOW_TRANSPARENCY: case FEATURE_CLIPBOARD: case FEATURE_KEEP_SCREEN_ON: case FEATURE_ORIENTATION: @@ -592,7 +592,13 @@ void DisplayServerAndroid::window_set_flag(DisplayServer::WindowFlags p_flag, bo } bool DisplayServerAndroid::window_get_flag(DisplayServer::WindowFlags p_flag, DisplayServer::WindowID p_window) const { - return false; + switch (p_flag) { + case WindowFlags::WINDOW_FLAG_TRANSPARENT: + return is_window_transparency_available(); + + default: + return false; + } } void DisplayServerAndroid::window_request_attention(DisplayServer::WindowID p_window) { @@ -961,3 +967,7 @@ void DisplayServerAndroid::set_native_icon(const String &p_filename) { void DisplayServerAndroid::set_icon(const Ref &p_icon) { // NOT SUPPORTED } + +bool DisplayServerAndroid::is_window_transparency_available() const { + return GLOBAL_GET_CACHED(bool, "display/window/per_pixel_transparency/allowed"); +} diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 0b650f84fd8..5b09128ee3c 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -256,6 +256,8 @@ public: virtual void set_native_icon(const String &p_filename) override; virtual void set_icon(const Ref &p_icon) override; + virtual bool is_window_transparency_available() const override; + DisplayServerAndroid(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error); ~DisplayServerAndroid(); }; diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 090b31e1290..b3f2327a607 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1055,6 +1055,10 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref &p_preset) const { + return (bool)get_project_setting(p_preset, "display/window/per_pixel_transparency/allowed"); +} + void EditorExportPlatformAndroid::_fix_themes_xml(const Ref &p_preset) { const String themes_xml_path = ExportTemplateManager::get_android_build_directory(p_preset).path_join("res/values/themes.xml"); @@ -1063,15 +1067,22 @@ void EditorExportPlatformAndroid::_fix_themes_xml(const Ref return; } + bool should_be_transparent = _should_be_transparent(p_preset); + // Default/Reserved theme attributes. Dictionary main_theme_attributes; main_theme_attributes["android:windowDrawsSystemBarBackgrounds"] = "false"; main_theme_attributes["android:windowSwipeToDismiss"] = bool_to_string(p_preset->get("gesture/swipe_to_dismiss")); + main_theme_attributes["android:windowIsTranslucent"] = bool_to_string(should_be_transparent); + if (should_be_transparent) { + main_theme_attributes["android:windowBackground"] = "@android:color/transparent"; + } Dictionary splash_theme_attributes; splash_theme_attributes["android:windowSplashScreenBackground"] = "@mipmap/icon_background"; splash_theme_attributes["windowSplashScreenAnimatedIcon"] = "@mipmap/icon_foreground"; splash_theme_attributes["postSplashScreenTheme"] = "@style/GodotAppMainTheme"; + splash_theme_attributes["android:windowIsTranslucent"] = bool_to_string(should_be_transparent); Dictionary custom_theme_attributes = p_preset->get("gradle_build/custom_theme_attributes"); @@ -2976,7 +2987,8 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Refget("gradle_build/use_gradle_build")) { + bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); + if (gradle_build_enabled) { String build_version_path = ExportTemplateManager::get_android_build_directory(p_preset).get_base_dir().path_join(".build_version"); Ref f = FileAccess::open(build_version_path, FileAccess::READ); if (f.is_valid()) { @@ -2987,6 +2999,12 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Refget("gradle_build/target_sdk"); diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index aefb74abcd7..0620c9f966e 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -163,6 +163,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { void _write_tmp_manifest(const Ref &p_preset, bool p_give_internet, bool p_debug); + bool _should_be_transparent(const Ref &p_preset) const; + void _fix_themes_xml(const Ref &p_preset); void _fix_manifest(const Ref &p_preset, Vector &p_manifest, bool p_give_internet); diff --git a/platform/android/java/app/res/values/themes.xml b/platform/android/java/app/res/values/themes.xml index 53e3516154d..600775fb62e 100644 --- a/platform/android/java/app/res/values/themes.xml +++ b/platform/android/java/app/res/values/themes.xml @@ -5,6 +5,7 @@ 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 ebe4e8960ae..8b4973d5771 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt @@ -478,19 +478,24 @@ class Godot(private val context: Context) { editText.setBackgroundColor(Color.TRANSPARENT) // ...add to FrameLayout containerLayout?.addView(editText) + + // Check whether the render view should be made transparent + val shouldBeTransparent = + !isProjectManagerHint() && !isEditorHint() && java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/per_pixel_transparency/allowed")) + Log.d(TAG, "Render view should be transparent: $shouldBeTransparent") renderView = if (usesVulkan()) { if (meetsVulkanRequirements(activity.packageManager)) { - GodotVulkanRenderView(host, this, godotInputHandler) + GodotVulkanRenderView(host, this, godotInputHandler, shouldBeTransparent) } else if (canFallbackToOpenGL()) { // Fallback to OpenGl. - GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl) + GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent) } else { throw IllegalStateException(activity.getString(R.string.error_missing_vulkan_requirements_message)) } } else { // Fallback to OpenGl. - GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl) + GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent) } if (host == primaryHost) { diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 6b3f7c4a67c..bddea29b4d4 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -46,7 +46,6 @@ import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; -import android.os.Build; import android.text.TextUtils; import android.util.SparseArray; import android.view.KeyEvent; @@ -83,7 +82,7 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView { private final GodotRenderer godotRenderer; private final SparseArray customPointerIcons = new SparseArray<>(); - public GodotGLRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler, XRMode xrMode, boolean useDebugOpengl) { + public GodotGLRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler, XRMode xrMode, boolean useDebugOpengl, boolean shouldBeTranslucent) { super(host.getActivity()); this.host = host; @@ -91,7 +90,7 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView { this.inputHandler = inputHandler; this.godotRenderer = new GodotRenderer(); setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT)); - init(xrMode, false, useDebugOpengl); + init(xrMode, shouldBeTranslucent, useDebugOpengl); } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index 64e8119ee83..f9a552fd23d 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -38,7 +38,7 @@ import android.annotation.SuppressLint; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.os.Build; +import android.graphics.PixelFormat; import android.text.TextUtils; import android.util.SparseArray; import android.view.KeyEvent; @@ -57,7 +57,7 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView { private final VkRenderer mRenderer; private final SparseArray customPointerIcons = new SparseArray<>(); - public GodotVulkanRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler) { + public GodotVulkanRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler, boolean shouldBeTranslucent) { super(host.getActivity()); this.host = host; @@ -67,6 +67,10 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView { setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT)); setFocusableInTouchMode(true); setClickable(false); + + if (shouldBeTranslucent) { + this.getHolder().setFormat(PixelFormat.TRANSLUCENT); + } } @Override