Skip to content

Commit 55c8fbe

Browse files
committed
Address remaining feedback on #106709
Address #106709 (comment)
1 parent 591e70f commit 55c8fbe

File tree

9 files changed

+102
-32
lines changed

9 files changed

+102
-32
lines changed

platform/android/display_server_android.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,13 +588,21 @@ bool DisplayServerAndroid::window_is_maximize_allowed(DisplayServer::WindowID p_
588588
}
589589

590590
void DisplayServerAndroid::window_set_flag(DisplayServer::WindowFlags p_flag, bool p_enabled, DisplayServer::WindowID p_window) {
591-
// Not supported on Android.
591+
ERR_FAIL_COND(p_window != MAIN_WINDOW_ID);
592+
switch (p_flag) {
593+
case WindowFlags::WINDOW_FLAG_TRANSPARENT:
594+
if (is_window_transparency_available()) {
595+
OS_Android::get_singleton()->get_godot_java()->set_window_flag(p_flag, p_enabled);
596+
}
597+
break;
598+
}
592599
}
593600

594601
bool DisplayServerAndroid::window_get_flag(DisplayServer::WindowFlags p_flag, DisplayServer::WindowID p_window) const {
602+
ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, false);
595603
switch (p_flag) {
596604
case WindowFlags::WINDOW_FLAG_TRANSPARENT:
597-
return is_window_transparency_available();
605+
return is_window_transparency_available() && OS_Android::get_singleton()->get_godot_java()->get_window_flag(p_flag);
598606

599607
default:
600608
return false;

platform/android/export/export_plugin.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,7 @@ 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 {
1058+
bool EditorExportPlatformAndroid::_is_transparency_allowed(const Ref<EditorExportPreset> &p_preset) const {
10591059
return (bool)get_project_setting(p_preset, "display/window/per_pixel_transparency/allowed");
10601060
}
10611061

@@ -1067,22 +1067,22 @@ void EditorExportPlatformAndroid::_fix_themes_xml(const Ref<EditorExportPreset>
10671067
return;
10681068
}
10691069

1070-
bool should_be_transparent = _should_be_transparent(p_preset);
1070+
bool transparency_allowed = _is_transparency_allowed(p_preset);
10711071

10721072
// Default/Reserved theme attributes.
10731073
Dictionary main_theme_attributes;
10741074
main_theme_attributes["android:windowDrawsSystemBarBackgrounds"] = "false";
10751075
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) {
1076+
main_theme_attributes["android:windowIsTranslucent"] = bool_to_string(transparency_allowed);
1077+
if (transparency_allowed) {
10781078
main_theme_attributes["android:windowBackground"] = "@android:color/transparent";
10791079
}
10801080

10811081
Dictionary splash_theme_attributes;
10821082
splash_theme_attributes["android:windowSplashScreenBackground"] = "@mipmap/icon_background";
10831083
splash_theme_attributes["windowSplashScreenAnimatedIcon"] = "@mipmap/icon_foreground";
10841084
splash_theme_attributes["postSplashScreenTheme"] = "@style/GodotAppMainTheme";
1085-
splash_theme_attributes["android:windowIsTranslucent"] = bool_to_string(should_be_transparent);
1085+
splash_theme_attributes["android:windowIsTranslucent"] = bool_to_string(transparency_allowed);
10861086

10871087
Dictionary custom_theme_attributes = p_preset->get("gradle_build/custom_theme_attributes");
10881088

@@ -3000,7 +3000,7 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
30003000
}
30013001
}
30023002
} else {
3003-
if (_should_be_transparent(p_preset)) {
3003+
if (_is_transparency_allowed(p_preset)) {
30043004
// Warning only, so don't override `valid`.
30053005
err += vformat(TTR("\"Use Gradle Build\" is required for transparent background on Android"));
30063006
err += "\n";

platform/android/export/export_plugin.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ 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;
166+
bool _is_transparency_allowed(const Ref<EditorExportPreset> &p_preset) const;
167167

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

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

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import android.content.pm.PackageManager
3838
import android.content.res.Configuration
3939
import android.content.res.Resources
4040
import android.graphics.Color
41+
import android.graphics.PixelFormat
4142
import android.hardware.Sensor
4243
import android.hardware.SensorManager
4344
import android.os.*
@@ -79,6 +80,7 @@ import java.io.FileInputStream
7980
import java.io.InputStream
8081
import java.security.MessageDigest
8182
import java.util.*
83+
import java.util.concurrent.ConcurrentHashMap
8284
import java.util.concurrent.atomic.AtomicBoolean
8385
import java.util.concurrent.atomic.AtomicReference
8486

@@ -189,6 +191,13 @@ class Godot(private val context: Context) {
189191
private var containerLayout: FrameLayout? = null
190192
var renderView: GodotRenderView? = null
191193

194+
/**
195+
* Stores the flags for the primary window.
196+
*
197+
* @see <a href="https://docs.godotengine.org/en/stable/classes/class_window.html#enum-window-flags">WindowFlags</a>
198+
*/
199+
private val primaryWindowFlags = ConcurrentHashMap<Int, Boolean>()
200+
192201
/**
193202
* Returns true if the native engine has been initialized through [onInitNativeLayer], false otherwise.
194203
*/
@@ -481,21 +490,32 @@ class Godot(private val context: Context) {
481490

482491
// Check whether the render view should be made transparent
483492
val shouldBeTransparent =
484-
!isProjectManagerHint() && !isEditorHint() && java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/per_pixel_transparency/allowed"))
493+
!isProjectManagerHint() &&
494+
!isEditorHint() &&
495+
java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/per_pixel_transparency/allowed")) &&
496+
java.lang.Boolean.parseBoolean(GodotLib.getGlobal("display/window/size/transparent"))
485497
Log.d(TAG, "Render view should be transparent: $shouldBeTransparent")
486498
renderView = if (usesVulkan()) {
487499
if (meetsVulkanRequirements(activity.packageManager)) {
488-
GodotVulkanRenderView(host, this, godotInputHandler, shouldBeTransparent)
500+
GodotVulkanRenderView(host, this, godotInputHandler)
489501
} else if (canFallbackToOpenGL()) {
490502
// Fallback to OpenGl.
491-
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
503+
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl)
492504
} else {
493505
throw IllegalStateException(activity.getString(R.string.error_missing_vulkan_requirements_message))
494506
}
495507

496508
} else {
497509
// Fallback to OpenGl.
498-
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl, shouldBeTransparent)
510+
GodotGLRenderView(host, this, godotInputHandler, xrMode, useDebugOpengl)
511+
}
512+
if (shouldBeTransparent) {
513+
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
514+
* If we want a translucent one, we should change the surface's
515+
* format here, using PixelFormat.TRANSLUCENT for GL Surfaces
516+
* is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
517+
*/
518+
renderView?.setPixelFormat(PixelFormat.TRANSLUCENT)
499519
}
500520

501521
if (host == primaryHost) {
@@ -1204,4 +1224,23 @@ class Godot(private val context: Context) {
12041224
private fun nativeOnEditorWorkspaceSelected(workspace: String) {
12051225
primaryHost?.onEditorWorkspaceSelected(workspace)
12061226
}
1227+
1228+
@Keep
1229+
private fun setWindowFlag(flag: Int, enabled: Boolean) {
1230+
primaryWindowFlags[flag] = enabled
1231+
if (flag == 3 /* WINDOW_FLAG_TRANSPARENT */) {
1232+
runOnUiThread {
1233+
val pixelFormat = if (enabled) {
1234+
PixelFormat.TRANSLUCENT
1235+
} else {
1236+
PixelFormat.OPAQUE
1237+
}
1238+
Log.d(TAG, "Updating pixel format to $pixelFormat")
1239+
renderView?.setPixelFormat(pixelFormat)
1240+
}
1241+
}
1242+
}
1243+
1244+
@Keep
1245+
private fun getWindowFlag(flag: Int): Boolean = primaryWindowFlags[flag] ?: false
12071246
}

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import android.content.res.AssetManager;
4646
import android.graphics.Bitmap;
4747
import android.graphics.BitmapFactory;
48-
import android.graphics.PixelFormat;
4948
import android.text.TextUtils;
5049
import android.util.SparseArray;
5150
import android.view.KeyEvent;
@@ -82,15 +81,15 @@ class GodotGLRenderView extends GLSurfaceView implements GodotRenderView {
8281
private final GodotRenderer godotRenderer;
8382
private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
8483

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

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

9695
@Override
@@ -236,7 +235,7 @@ public PointerIcon onResolvePointerIcon(MotionEvent me, int pointerIndex) {
236235
return getPointerIcon();
237236
}
238237

239-
private void init(XRMode xrMode, boolean translucent, boolean useDebugOpengl) {
238+
private void init(XRMode xrMode, boolean useDebugOpengl) {
240239
setPreserveEGLContextOnPause(true);
241240
setFocusableInTouchMode(true);
242241
switch (xrMode) {
@@ -253,15 +252,6 @@ private void init(XRMode xrMode, boolean translucent, boolean useDebugOpengl) {
253252

254253
case REGULAR:
255254
default:
256-
/* By default, GLSurfaceView() creates a RGB_565 opaque surface.
257-
* If we want a translucent one, we should change the surface's
258-
* format here, using PixelFormat.TRANSLUCENT for GL Surfaces
259-
* is interpreted as any 32-bit surface with alpha by SurfaceFlinger.
260-
*/
261-
if (translucent) {
262-
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
263-
}
264-
265255
/* Setup the context factory for 2.0 rendering.
266256
* See ContextFactory class definition below
267257
*/

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,17 @@ default boolean canCapturePointer() {
7171
// Pointer capture is not supported on native XR devices.
7272
return !DeviceUtils.isNativeXRDevice(getView().getContext()) && getInputHandler().canCapturePointer();
7373
}
74+
75+
/**
76+
* Update the render view pixel format.
77+
* @param format A constant from PixelFormat.
78+
*
79+
* @see android.view.SurfaceHolder#setFormat(int)
80+
*/
81+
default void setPixelFormat(int format) {
82+
SurfaceView surfaceView = getView();
83+
if (surfaceView != null && surfaceView.getHolder() != null) {
84+
surfaceView.getHolder().setFormat(format);
85+
}
86+
}
7487
}

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import android.content.res.AssetManager;
3939
import android.graphics.Bitmap;
4040
import android.graphics.BitmapFactory;
41-
import android.graphics.PixelFormat;
4241
import android.text.TextUtils;
4342
import android.util.SparseArray;
4443
import android.view.KeyEvent;
@@ -57,7 +56,7 @@ class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView {
5756
private final VkRenderer mRenderer;
5857
private final SparseArray<PointerIcon> customPointerIcons = new SparseArray<>();
5958

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

6362
this.host = host;
@@ -67,10 +66,6 @@ public GodotVulkanRenderView(GodotHost host, Godot godot, GodotInputHandler inpu
6766
setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_DEFAULT));
6867
setFocusableInTouchMode(true);
6968
setClickable(false);
70-
71-
if (shouldBeTranslucent) {
72-
this.getHolder().setFormat(PixelFormat.TRANSLUCENT);
73-
}
7469
}
7570

7671
@Override

platform/android/java_godot_wrapper.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
9494
_enable_immersive_mode = p_env->GetMethodID(godot_class, "nativeEnableImmersiveMode", "(Z)V");
9595
_is_in_immersive_mode = p_env->GetMethodID(godot_class, "isInImmersiveMode", "()Z");
9696
_on_editor_workspace_selected = p_env->GetMethodID(godot_class, "nativeOnEditorWorkspaceSelected", "(Ljava/lang/String;)V");
97+
_set_window_flag = p_env->GetMethodID(godot_class, "setWindowFlag", "(IZ)V");
98+
_get_window_flag = p_env->GetMethodID(godot_class, "getWindowFlag", "(I)Z");
9799
}
98100

99101
GodotJavaWrapper::~GodotJavaWrapper() {
@@ -599,3 +601,20 @@ void GodotJavaWrapper::on_editor_workspace_selected(const String &p_workspace) {
599601
env->CallVoidMethod(godot_instance, _on_editor_workspace_selected, j_workspace);
600602
}
601603
}
604+
605+
void GodotJavaWrapper::set_window_flag(DisplayServer::WindowFlags p_flag, bool p_enabled) {
606+
if (_set_window_flag) {
607+
JNIEnv *env = get_jni_env();
608+
ERR_FAIL_NULL(env);
609+
env->CallVoidMethod(godot_instance, _set_window_flag, p_flag, p_enabled);
610+
}
611+
}
612+
613+
bool GodotJavaWrapper::get_window_flag(DisplayServer::WindowFlags p_flag) {
614+
if (_get_window_flag) {
615+
JNIEnv *env = get_jni_env();
616+
ERR_FAIL_NULL_V(env, false);
617+
return env->CallBooleanMethod(godot_instance, _get_window_flag, p_flag);
618+
}
619+
return false;
620+
}

platform/android/java_godot_wrapper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
#include "core/math/color.h"
3636
#include "core/templates/list.h"
37+
#include "servers/display_server.h"
3738

3839
#include <android/log.h>
3940
#include <jni.h>
@@ -84,6 +85,8 @@ class GodotJavaWrapper {
8485
jmethodID _enable_immersive_mode = nullptr;
8586
jmethodID _is_in_immersive_mode = nullptr;
8687
jmethodID _on_editor_workspace_selected = nullptr;
88+
jmethodID _set_window_flag = nullptr;
89+
jmethodID _get_window_flag = nullptr;
8790

8891
public:
8992
GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance);
@@ -139,4 +142,7 @@ class GodotJavaWrapper {
139142
bool is_in_immersive_mode();
140143

141144
void on_editor_workspace_selected(const String &p_workspace);
145+
146+
void set_window_flag(DisplayServer::WindowFlags p_flag, bool p_enabled);
147+
bool get_window_flag(DisplayServer::WindowFlags p_flag);
142148
};

0 commit comments

Comments
 (0)