Skip to content

Commit ae33da9

Browse files
committed
Merge pull request #106709 from m4gr3d/fix_transparency_flags
Fix transparency background issue on Android
2 parents 4adef85 + 547450b commit ae33da9

File tree

11 files changed

+61
-14
lines changed

11 files changed

+61
-14
lines changed

doc/classes/DisplayServer.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2543,7 +2543,7 @@
25432543
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]
25442544
</constant>
25452545
<constant name="FEATURE_WINDOW_TRANSPARENCY" value="11" enum="Feature">
2546-
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]
2546+
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]
25472547
</constant>
25482548
<constant name="FEATURE_HIDPI" value="12" enum="Feature">
25492549
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 @@
30733073
<constant name="WINDOW_FLAG_TRANSPARENT" value="3" enum="WindowFlags">
30743074
The window background can be transparent.
30753075
[b]Note:[/b] This flag has no effect if [method is_window_transparency_available] returns [code]false[/code].
3076-
[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.
3076+
[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.
30773077
</constant>
30783078
<constant name="WINDOW_FLAG_NO_FOCUS" value="4" enum="WindowFlags">
30793079
The window can't be focused. No-focus window will ignore all input, except mouse clicks.

platform/android/display_server_android.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ bool DisplayServerAndroid::has_feature(Feature p_feature) const {
7676
//case FEATURE_NATIVE_DIALOG_FILE_EXTRA:
7777
case FEATURE_NATIVE_DIALOG_FILE_MIME:
7878
//case FEATURE_NATIVE_ICON:
79-
//case FEATURE_WINDOW_TRANSPARENCY:
79+
case FEATURE_WINDOW_TRANSPARENCY:
8080
case FEATURE_CLIPBOARD:
8181
case FEATURE_KEEP_SCREEN_ON:
8282
case FEATURE_ORIENTATION:
@@ -592,7 +592,13 @@ void DisplayServerAndroid::window_set_flag(DisplayServer::WindowFlags p_flag, bo
592592
}
593593

594594
bool DisplayServerAndroid::window_get_flag(DisplayServer::WindowFlags p_flag, DisplayServer::WindowID p_window) const {
595-
return false;
595+
switch (p_flag) {
596+
case WindowFlags::WINDOW_FLAG_TRANSPARENT:
597+
return is_window_transparency_available();
598+
599+
default:
600+
return false;
601+
}
596602
}
597603

598604
void DisplayServerAndroid::window_request_attention(DisplayServer::WindowID p_window) {
@@ -961,3 +967,7 @@ void DisplayServerAndroid::set_native_icon(const String &p_filename) {
961967
void DisplayServerAndroid::set_icon(const Ref<Image> &p_icon) {
962968
// NOT SUPPORTED
963969
}
970+
971+
bool DisplayServerAndroid::is_window_transparency_available() const {
972+
return GLOBAL_GET_CACHED(bool, "display/window/per_pixel_transparency/allowed");
973+
}

platform/android/display_server_android.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ class DisplayServerAndroid : public DisplayServer {
256256
virtual void set_native_icon(const String &p_filename) override;
257257
virtual void set_icon(const Ref<Image> &p_icon) override;
258258

259+
virtual bool is_window_transparency_available() const override;
260+
259261
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);
260262
~DisplayServerAndroid();
261263
};

platform/android/export/export_plugin.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,10 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
10551055
store_string_at_path(manifest_path, manifest_text);
10561056
}
10571057

1058+
bool EditorExportPlatformAndroid::_should_be_transparent(const Ref<EditorExportPreset> &p_preset) const {
1059+
return (bool)get_project_setting(p_preset, "display/window/per_pixel_transparency/allowed");
1060+
}
1061+
10581062
void EditorExportPlatformAndroid::_fix_themes_xml(const Ref<EditorExportPreset> &p_preset) {
10591063
const String themes_xml_path = ExportTemplateManager::get_android_build_directory(p_preset).path_join("res/values/themes.xml");
10601064

@@ -1063,15 +1067,22 @@ void EditorExportPlatformAndroid::_fix_themes_xml(const Ref<EditorExportPreset>
10631067
return;
10641068
}
10651069

1070+
bool should_be_transparent = _should_be_transparent(p_preset);
1071+
10661072
// Default/Reserved theme attributes.
10671073
Dictionary main_theme_attributes;
10681074
main_theme_attributes["android:windowDrawsSystemBarBackgrounds"] = "false";
10691075
main_theme_attributes["android:windowSwipeToDismiss"] = bool_to_string(p_preset->get("gesture/swipe_to_dismiss"));
1076+
main_theme_attributes["android:windowIsTranslucent"] = bool_to_string(should_be_transparent);
1077+
if (should_be_transparent) {
1078+
main_theme_attributes["android:windowBackground"] = "@android:color/transparent";
1079+
}
10701080

10711081
Dictionary splash_theme_attributes;
10721082
splash_theme_attributes["android:windowSplashScreenBackground"] = "@mipmap/icon_background";
10731083
splash_theme_attributes["windowSplashScreenAnimatedIcon"] = "@mipmap/icon_foreground";
10741084
splash_theme_attributes["postSplashScreenTheme"] = "@style/GodotAppMainTheme";
1085+
splash_theme_attributes["android:windowIsTranslucent"] = bool_to_string(should_be_transparent);
10751086

10761087
Dictionary custom_theme_attributes = p_preset->get("gradle_build/custom_theme_attributes");
10771088

@@ -2976,7 +2987,8 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
29762987
valid = false;
29772988
}
29782989

2979-
if (p_preset->get("gradle_build/use_gradle_build")) {
2990+
bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
2991+
if (gradle_build_enabled) {
29802992
String build_version_path = ExportTemplateManager::get_android_build_directory(p_preset).get_base_dir().path_join(".build_version");
29812993
Ref<FileAccess> f = FileAccess::open(build_version_path, FileAccess::READ);
29822994
if (f.is_valid()) {
@@ -2987,6 +2999,12 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
29872999
err += "\n";
29883000
}
29893001
}
3002+
} else {
3003+
if (_should_be_transparent(p_preset)) {
3004+
// Warning only, so don't override `valid`.
3005+
err += vformat(TTR("\"Use Gradle Build\" is required for transparent background on Android"));
3006+
err += "\n";
3007+
}
29903008
}
29913009

29923010
String target_sdk_str = p_preset->get("gradle_build/target_sdk");

platform/android/export/export_plugin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
163163

164164
void _write_tmp_manifest(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, bool p_debug);
165165

166+
bool _should_be_transparent(const Ref<EditorExportPreset> &p_preset) const;
167+
166168
void _fix_themes_xml(const Ref<EditorExportPreset> &p_preset);
167169

168170
void _fix_manifest(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_manifest, bool p_give_internet);

platform/android/java/app/res/values/themes.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<style name="GodotAppMainTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar">
66
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
77
<item name="android:windowSwipeToDismiss">false</item>
8+
<item name="android:windowIsTranslucent">false</item>
89
</style>
910

1011
<!-- GodotAppSplashTheme is auto-generated during export. Manual changes will be overwritten.
@@ -13,5 +14,6 @@
1314
<item name="android:windowSplashScreenBackground">@mipmap/icon_background</item>
1415
<item name="windowSplashScreenAnimatedIcon">@mipmap/icon_foreground</item>
1516
<item name="postSplashScreenTheme">@style/GodotAppMainTheme</item>
17+
<item name="android:windowIsTranslucent">false</item>
1618
</style>
1719
</resources>

platform/android/java/editor/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
android:launchMode="singleTask"
7171
android:process=":GodotGame"
7272
android:autoRemoveFromRecents="true"
73+
android:theme="@style/GodotGameTheme"
7374
android:supportsPictureInPicture="true"
7475
android:screenOrientation="userLandscape">
7576
<layout

platform/android/java/editor/src/main/res/values/themes.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
<resources>
33
<style name="GodotEditorTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
44
<item name="android:statusBarColor">@android:color/transparent</item>
5-
<item name ="android:navigationBarColor">@android:color/transparent</item>
5+
<item name="android:navigationBarColor">@android:color/transparent</item>
66
<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
77
</style>
88

9+
<style name="GodotGameTheme" parent="GodotEditorTheme">
10+
<item name="android:windowIsTranslucent">true</item>
11+
</style>
12+
913
<style name="GodotEditorSplashScreenTheme" parent="Theme.SplashScreen.IconBackground">
1014
<!-- Set the theme of the Activity that directly follows your splash
1115
screen. This is required. -->

platform/android/java/lib/src/org/godotengine/godot/Godot.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,19 +478,24 @@ class Godot(private val context: Context) {
478478
editText.setBackgroundColor(Color.TRANSPARENT)
479479
// ...add to FrameLayout
480480
containerLayout?.addView(editText)
481+
482+
// Check whether the render view should be made transparent
483+
val shouldBeTransparent =
484+
!isProjectManagerHint() && !isEditorHint() && java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/per_pixel_transparency/allowed"))
485+
Log.d(TAG, "Render view should be transparent: $shouldBeTransparent")
481486
renderView = if (usesVulkan()) {
482487
if (meetsVulkanRequirements(activity.packageManager)) {
483-
GodotVulkanRenderView(host, this, godotInputHandler)
488+
GodotVulkanRenderView(host, this, godotInputHandler, shouldBeTransparent)
484489
} else if (canFallbackToOpenGL()) {
485490
// Fallback to OpenGl.
486-
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl)
491+
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
487492
} else {
488493
throw IllegalStateException(activity.getString(R.string.error_missing_vulkan_requirements_message))
489494
}
490495

491496
} else {
492497
// Fallback to OpenGl.
493-
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl)
498+
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
494499
}
495500

496501
if (host == primaryHost) {

platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import android.graphics.Bitmap;
4747
import android.graphics.BitmapFactory;
4848
import android.graphics.PixelFormat;
49-
import android.os.Build;
5049
import android.text.TextUtils;
5150
import android.util.SparseArray;
5251
import android.view.KeyEvent;
@@ -83,15 +82,15 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
8382
private final GodotRenderer godotRenderer;
8483
private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
8584

86-
public GodotGLRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler, XRMode xrMode, boolean useDebugOpengl) {
85+
public GodotGLRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler, XRMode xrMode, boolean useDebugOpengl, boolean shouldBeTranslucent) {
8786
super(host.getActivity());
8887

8988
this.host = host;
9089
this.godot = godot;
9190
this.inputHandler = inputHandler;
9291
this.godotRenderer = new GodotRenderer();
9392
setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
94-
init(xrMode, false, useDebugOpengl);
93+
init(xrMode, shouldBeTranslucent, useDebugOpengl);
9594
}
9695

9796
@Override

0 commit comments

Comments
 (0)