Skip to content

Commit f1b1dfe

Browse files
committed
Fix transparency background issue on Android
Fixes godotengine#106703
1 parent 4a44078 commit f1b1dfe

File tree

6 files changed

+62
-17
lines changed

6 files changed

+62
-17
lines changed

platform/android/export/export_plugin.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,9 +1037,14 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
10371037
store_string_at_path(manifest_path, manifest_text);
10381038
}
10391039

1040+
bool EditorExportPlatformAndroid::_should_be_transparent(const Ref<EditorExportPreset> &p_preset) const {
1041+
return (bool)get_project_setting(p_preset, "display/window/per_pixel_transparency/allowed") &&
1042+
(bool)get_project_setting(p_preset, "display/window/size/transparent") &&
1043+
(bool)get_project_setting(p_preset, "rendering/viewport/transparent_background");
1044+
}
1045+
10401046
void EditorExportPlatformAndroid::_fix_themes_xml(const Ref<EditorExportPreset> &p_preset) {
10411047
const String themes_xml_path = ExportTemplateManager::get_android_build_directory(p_preset).path_join("res/values/themes.xml");
1042-
bool enable_swipe_to_dismiss = p_preset->get("gesture/swipe_to_dismiss");
10431048

10441049
if (!FileAccess::exists(themes_xml_path)) {
10451050
print_error("res/values/themes.xml does not exist.");
@@ -1051,23 +1056,39 @@ void EditorExportPlatformAndroid::_fix_themes_xml(const Ref<EditorExportPreset>
10511056
PackedStringArray lines = file->get_as_text().split("\n");
10521057
file->close();
10531058

1059+
// Update the themes.xml is transparency is enabled.
1060+
bool should_be_transparent = _should_be_transparent(p_preset);
1061+
10541062
// Check if the themes.xml already contains <item name="android:windowSwipeToDismiss"> element.
10551063
// If found, update its value based on `enable_swipe_to_dismiss`.
1056-
bool found = false;
1064+
bool enable_swipe_to_dismiss = p_preset->get("gesture/swipe_to_dismiss");
1065+
bool found_enable_swipe_to_dismiss = false;
1066+
10571067
bool modified = false;
10581068
for (int i = 0; i < lines.size(); i++) {
10591069
String line = lines[i];
1060-
if (line.contains("<item name") && line.contains("\"android:windowSwipeToDismiss\">")) {
1061-
lines.set(i, vformat(" <item name=\"android:windowSwipeToDismiss\">%s</item>", bool_to_string(enable_swipe_to_dismiss)));
1062-
found = true;
1063-
modified = true;
1064-
break;
1070+
if (line.contains("<item name")) {
1071+
if (line.contains("\"android:windowSwipeToDismiss\">")) {
1072+
lines.set(i, vformat(" <item name=\"android:windowSwipeToDismiss\">%s</item>", bool_to_string(enable_swipe_to_dismiss)));
1073+
found_enable_swipe_to_dismiss = true;
1074+
modified = true;
1075+
} else if (line.contains("\"android:windowIsTranslucent\">")) {
1076+
lines.set(i, vformat(" <item name=\"android:windowIsTranslucent\">%s</item>", bool_to_string(should_be_transparent)));
1077+
modified = true;
1078+
} else if (line.contains("\"android:windowBackground\"")) {
1079+
if (should_be_transparent) {
1080+
lines.set(i, " <item name=\"android:windowBackground\">@android:color/transparent</item>");
1081+
} else {
1082+
lines.set(i, " <!--<item name=\"android:windowBackground\">@android:color/transparent</item>-->");
1083+
}
1084+
modified = true;
1085+
}
10651086
}
10661087
}
10671088

10681089
// If <item name="android:windowSwipeToDismiss"> is not found and `enable_swipe_to_dismiss` is false:
10691090
// Add a new <item> element before the closing </style> tag.
1070-
if (!found && !enable_swipe_to_dismiss) {
1091+
if (!found_enable_swipe_to_dismiss && !enable_swipe_to_dismiss) {
10711092
for (int i = 0; i < lines.size(); i++) {
10721093
if (lines[i].contains("</style>")) {
10731094
lines.insert(i, " <item name=\"android:windowSwipeToDismiss\">false</item>");
@@ -2882,7 +2903,8 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
28822903
valid = false;
28832904
}
28842905

2885-
if (p_preset->get("gradle_build/use_gradle_build")) {
2906+
bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
2907+
if (gradle_build_enabled) {
28862908
String build_version_path = ExportTemplateManager::get_android_build_directory(p_preset).get_base_dir().path_join(".build_version");
28872909
Ref<FileAccess> f = FileAccess::open(build_version_path, FileAccess::READ);
28882910
if (f.is_valid()) {
@@ -2893,6 +2915,12 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
28932915
err += "\n";
28942916
}
28952917
}
2918+
} else {
2919+
if (_should_be_transparent(p_preset)) {
2920+
// Warning only, so don't override `valid`.
2921+
err += vformat(TTR("\"Use Gradle Build\" is required for transparent background on Android"));
2922+
err += "\n";
2923+
}
28962924
}
28972925

28982926
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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<style name="GodotAppMainTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar">
55
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
66
<item name="android:windowSwipeToDismiss">false</item>
7+
<item name="android:windowIsTranslucent">false</item>
8+
<!--<item name="android:windowBackground">@android:color/transparent</item>-->
79
</style>
810

911
<style name="GodotAppSplashTheme" parent="Theme.SplashScreen">
@@ -18,5 +20,6 @@
1820
<!-- Set the theme of the Activity that directly follows your splash
1921
screen. This is required. -->
2022
<item name="postSplashScreenTheme">@style/GodotAppMainTheme</item>
23+
<item name="android:windowIsTranslucent">false</item>
2124
</style>
2225
</resources>

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

Lines changed: 10 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 = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/per_pixel_transparency/allowed")) &&
484+
java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/size/transparent")) &&
485+
java.lang.Boolean.parseBoolean(GodotLib.getGlobal("rendering/viewport/transparent_background"))
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) {
@@ -562,6 +567,8 @@ class Godot(private val context: Context) {
562567
if (pluginView != null) {
563568
if (plugin.shouldBeOnTop()) {
564569
containerLayout?.addView(pluginView)
570+
Log.w(TAG, "Disabling Z order on top because of plugin ${plugin.pluginName}")
571+
renderView?.view?.setZOrderOnTop(false)
565572
} else {
566573
containerLayout?.addView(pluginView, 0)
567574
}

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

Lines changed: 3 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
@@ -260,6 +259,7 @@ private void init(XRMode xrMode, boolean translucent, boolean useDebugOpengl) {
260259
* is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
261260
*/
262261
if (translucent) {
262+
setZOrderOnTop(true);
263263
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
264264
}
265265

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import android.content.res.AssetManager;
3939
import android.graphics.Bitmap;
4040
import android.graphics.BitmapFactory;
41-
import android.os.Build;
41+
import android.graphics.PixelFormat;
4242
import android.text.TextUtils;
4343
import android.util.SparseArray;
4444
import android.view.KeyEvent;
@@ -57,7 +57,7 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
5757
private final VkRenderer mRenderer;
5858
private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
5959

60-
public GodotVulkanRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler) {
60+
public GodotVulkanRenderView(GodotHost host, Godot godot, GodotInputHandler inputHandler, boolean shouldBeTranslucent) {
6161
super(host.getActivity());
6262

6363
this.host = host;
@@ -67,6 +67,11 @@ public GodotVulkanRenderView(GodotHost host, Godot godot, GodotInputHandler inpu
6767
setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
6868
setFocusableInTouchMode(true);
6969
setClickable(false);
70+
71+
if (shouldBeTranslucent) {
72+
setZOrderOnTop(true);
73+
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
74+
}
7075
}
7176

7277
@Override

0 commit comments

Comments
 (0)