Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/classes/DisplayServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2544,7 +2544,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]
</constant>
<constant name="FEATURE_WINDOW_TRANSPARENCY" value="11" enum="Feature">
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]
</constant>
<constant name="FEATURE_HIDPI" value="12" enum="Feature">
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]
Expand Down Expand Up @@ -3079,7 +3079,7 @@
<constant name="WINDOW_FLAG_TRANSPARENT" value="3" enum="WindowFlags">
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.
</constant>
<constant name="WINDOW_FLAG_NO_FOCUS" value="4" enum="WindowFlags">
The window can't be focused. No-focus window will ignore all input, except mouse clicks.
Expand Down
14 changes: 12 additions & 2 deletions platform/android/display_server_android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -961,3 +967,7 @@ void DisplayServerAndroid::set_native_icon(const String &p_filename) {
void DisplayServerAndroid::set_icon(const Ref<Image> &p_icon) {
// NOT SUPPORTED
}

bool DisplayServerAndroid::is_window_transparency_available() const {
return GLOBAL_GET_CACHED(bool, "display/window/per_pixel_transparency/allowed");
}
2 changes: 2 additions & 0 deletions platform/android/display_server_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ class DisplayServerAndroid : public DisplayServer {
virtual void set_native_icon(const String &p_filename) override;
virtual void set_icon(const Ref<Image> &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();
};
20 changes: 19 additions & 1 deletion platform/android/export/export_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,10 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
store_string_at_path(manifest_path, manifest_text);
}

bool EditorExportPlatformAndroid::_should_be_transparent(const Ref<EditorExportPreset> &p_preset) const {
return (bool)get_project_setting(p_preset, "display/window/per_pixel_transparency/allowed");
}

void EditorExportPlatformAndroid::_fix_themes_xml(const Ref<EditorExportPreset> &p_preset) {
const String themes_xml_path = ExportTemplateManager::get_android_build_directory(p_preset).path_join("res/values/themes.xml");

Expand All @@ -1046,15 +1050,22 @@ void EditorExportPlatformAndroid::_fix_themes_xml(const Ref<EditorExportPreset>
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");

Expand Down Expand Up @@ -2952,7 +2963,8 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
valid = false;
}

if (p_preset->get("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<FileAccess> f = FileAccess::open(build_version_path, FileAccess::READ);
if (f.is_valid()) {
Expand All @@ -2963,6 +2975,12 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
err += "\n";
}
}
} else {
if (_should_be_transparent(p_preset)) {
// Warning only, so don't override `valid`.
err += vformat(TTR("\"Use Gradle Build\" is required for transparent background on Android"));
err += "\n";
}
}

String target_sdk_str = p_preset->get("gradle_build/target_sdk");
Expand Down
2 changes: 2 additions & 0 deletions platform/android/export/export_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {

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

bool _should_be_transparent(const Ref<EditorExportPreset> &p_preset) const;

void _fix_themes_xml(const Ref<EditorExportPreset> &p_preset);

void _fix_manifest(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &p_manifest, bool p_give_internet);
Expand Down
2 changes: 2 additions & 0 deletions platform/android/java/app/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<style name="GodotAppMainTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowSwipeToDismiss">false</item>
<item name="android:windowIsTranslucent">false</item>
</style>

<!-- GodotAppSplashTheme is auto-generated during export. Manual changes will be overwritten.
Expand All @@ -13,5 +14,6 @@
<item name="android:windowSplashScreenBackground">@mipmap/icon_background</item>
<item name="windowSplashScreenAnimatedIcon">@mipmap/icon_foreground</item>
<item name="postSplashScreenTheme">@style/GodotAppMainTheme</item>
<item name="android:windowIsTranslucent">false</item>
</style>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
android:launchMode="singleTask"
android:process=":GodotGame"
android:autoRemoveFromRecents="true"
android:theme="@style/GodotGameTheme"
android:supportsPictureInPicture="true"
android:screenOrientation="userLandscape">
<layout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
<resources>
<style name="GodotEditorTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name ="android:navigationBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>

<style name="GodotGameTheme" parent="GodotEditorTheme">
<item name="android:windowIsTranslucent">true</item>
</style>

<style name="GodotEditorSplashScreenTheme" parent="Theme.SplashScreen.IconBackground">
<!-- Set the theme of the Activity that directly follows your splash
screen. This is required. -->
Expand Down
11 changes: 8 additions & 3 deletions platform/android/java/lib/src/org/godotengine/godot/Godot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
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;
Expand Down Expand Up @@ -83,15 +82,15 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
private final GodotRenderer godotRenderer;
private final SparseArray<PointerIcon> 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;
this.godot = godot;
this.inputHandler = inputHandler;
this.godotRenderer = new GodotRenderer();
setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
init(xrMode, false, useDebugOpengl);
init(xrMode, shouldBeTranslucent, useDebugOpengl);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
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;
Expand All @@ -57,7 +57,7 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
private final VkRenderer mRenderer;
private final SparseArray<PointerIcon> 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;
Expand All @@ -67,6 +67,10 @@ public GodotVulkanRenderView(GodotHost host, Godot godot, GodotInputHandler inpu
setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
setFocusableInTouchMode(true);
setClickable(false);

if (shouldBeTranslucent) {
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be set at runtime, if window transparent flag changes in Godot.

}
}

@Override
Expand Down