summaryrefslogtreecommitdiffstats
path: root/platform/android
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/display_server_android.cpp8
-rw-r--r--platform/android/export/export_plugin.cpp26
-rw-r--r--platform/android/export/export_plugin.h8
-rw-r--r--platform/android/file_access_android.cpp96
-rw-r--r--platform/android/file_access_android.h9
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp62
-rw-r--r--platform/android/file_access_filesystem_jandroid.h8
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt4
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt28
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.kt114
-rw-r--r--platform/android/java_godot_lib_jni.cpp11
-rw-r--r--platform/android/java_godot_wrapper.cpp20
-rw-r--r--platform/android/java_godot_wrapper.h5
14 files changed, 155 insertions, 246 deletions
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 8dc0e869d0..5bb520bd73 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -455,11 +455,15 @@ Size2i DisplayServerAndroid::window_get_size_with_decorations(DisplayServer::Win
}
void DisplayServerAndroid::window_set_mode(DisplayServer::WindowMode p_mode, DisplayServer::WindowID p_window) {
- // Not supported on Android.
+ OS_Android::get_singleton()->get_godot_java()->enable_immersive_mode(p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN);
}
DisplayServer::WindowMode DisplayServerAndroid::window_get_mode(DisplayServer::WindowID p_window) const {
- return WINDOW_MODE_FULLSCREEN;
+ if (OS_Android::get_singleton()->get_godot_java()->is_in_immersive_mode()) {
+ return WINDOW_MODE_FULLSCREEN;
+ } else {
+ return WINDOW_MODE_MAXIMIZED;
+ }
}
bool DisplayServerAndroid::window_is_maximize_allowed(DisplayServer::WindowID p_window) const {
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 0fdaca4839..f8ac591a78 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -2002,7 +2002,7 @@ String EditorExportPlatformAndroid::get_device_architecture(int p_index) const {
return devices[p_index].architecture;
}
-Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) {
ERR_FAIL_INDEX_V(p_device, devices.size(), ERR_INVALID_PARAMETER);
String can_export_error;
@@ -2024,11 +2024,11 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
}
const bool use_wifi_for_remote_debug = EDITOR_GET("export/android/use_wifi_for_remote_debug");
- const bool use_remote = (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) || (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT);
+ const bool use_remote = p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG) || p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT);
const bool use_reverse = devices[p_device].api_level >= 21 && !use_wifi_for_remote_debug;
if (use_reverse) {
- p_debug_flags |= DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST;
+ p_debug_flags.set_flag(DEBUG_FLAG_REMOTE_DEBUG_LOCALHOST);
}
String tmp_export_path = EditorPaths::get_singleton()->get_cache_dir().path_join("tmpexport." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
@@ -2107,7 +2107,7 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
OS::get_singleton()->execute(adb, args, &output, &rv, true);
print_verbose(output);
- if (p_debug_flags & DEBUG_FLAG_REMOTE_DEBUG) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG)) {
int dbg_port = EDITOR_GET("network/debug/remote_port");
args.clear();
args.push_back("-s");
@@ -2122,7 +2122,7 @@ Error EditorExportPlatformAndroid::run(const Ref<EditorExportPreset> &p_preset,
print_line("Reverse result: " + itos(rv));
}
- if (p_debug_flags & DEBUG_FLAG_DUMB_CLIENT) {
+ if (p_debug_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) {
int fs_port = EDITOR_GET("filesystem/file_server/port");
args.clear();
@@ -2667,7 +2667,7 @@ Error EditorExportPlatformAndroid::save_apk_expansion_file(const Ref<EditorExpor
return err;
}
-void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, int p_flags, Vector<uint8_t> &r_command_line_flags) {
+void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, Vector<uint8_t> &r_command_line_flags) {
String cmdline = p_preset->get("command_line/extra_args");
Vector<String> command_line_strings = cmdline.strip_edges().split(" ");
for (int i = 0; i < command_line_strings.size(); i++) {
@@ -2677,7 +2677,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
}
}
- gen_export_flags(command_line_strings, p_flags);
+ command_line_strings.append_array(gen_export_flags(p_flags));
bool apk_expansion = p_preset->get("apk_expansion/enable");
if (apk_expansion) {
@@ -2700,7 +2700,7 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
bool immersive = p_preset->get("screen/immersive_mode");
if (immersive) {
- command_line_strings.push_back("--use_immersive");
+ command_line_strings.push_back("--fullscreen");
}
bool debug_opengl = p_preset->get("graphics/opengl_debug");
@@ -3000,13 +3000,13 @@ bool EditorExportPlatformAndroid::_is_clean_build_required(const Ref<EditorExpor
return have_plugins_changed || has_build_dir_changed || first_build;
}
-Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags) {
int export_format = int(p_preset->get("gradle_build/export_format"));
bool should_sign = p_preset->get("package/signed");
return export_project_helper(p_preset, p_debug, p_path, export_format, should_sign, p_flags);
}
-Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags) {
+Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, BitField<EditorExportPlatform::DebugFlags> p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
const String base_dir = p_path.get_base_dir();
@@ -3022,7 +3022,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
bool use_gradle_build = bool(p_preset->get("gradle_build/use_gradle_build"));
String gradle_build_directory = use_gradle_build ? ExportTemplateManager::get_android_build_directory(p_preset) : "";
- bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG);
+ bool p_give_internet = p_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT) || p_flags.has_flag(DEBUG_FLAG_REMOTE_DEBUG);
bool apk_expansion = p_preset->get("apk_expansion/enable");
Vector<ABI> enabled_abis = get_enabled_abis(p_preset);
@@ -3127,7 +3127,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
user_data.assets_directory = assets_directory;
user_data.libs_directory = gradle_build_directory.path_join("libs");
user_data.debug = p_debug;
- if (p_flags & DEBUG_FLAG_DUMB_CLIENT) {
+ if (p_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) {
err = export_project_files(p_preset, p_debug, ignore_apk_file, &user_data, copy_gradle_so);
} else {
err = export_project_files(p_preset, p_debug, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so);
@@ -3500,7 +3500,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
}
err = OK;
- if (p_flags & DEBUG_FLAG_DUMB_CLIENT) {
+ if (p_flags.has_flag(DEBUG_FLAG_DUMB_CLIENT)) {
APKExportData ed;
ed.ep = &ep;
ed.apk = unaligned_apk;
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index 97bbd0c7bc..708288fbf4 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -214,7 +214,7 @@ public:
virtual String get_device_architecture(int p_index) const override;
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) override;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, BitField<EditorExportPlatform::DebugFlags> p_debug_flags) override;
virtual Ref<Texture2D> get_run_icon() const override;
@@ -242,7 +242,7 @@ public:
Error save_apk_expansion_file(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path);
- void get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, int p_flags, Vector<uint8_t> &r_command_line_flags);
+ void get_command_line_flags(const Ref<EditorExportPreset> &p_preset, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags, Vector<uint8_t> &r_command_line_flags);
Error sign_apk(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &export_path, EditorProgress &ep);
@@ -253,9 +253,9 @@ public:
static String join_list(const List<String> &p_parts, const String &p_separator);
static String join_abis(const Vector<ABI> &p_parts, const String &p_separator, bool p_use_arch);
- virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, BitField<EditorExportPlatform::DebugFlags> p_flags = 0) override;
- Error export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, int p_flags);
+ Error export_project_helper(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int export_format, bool should_sign, BitField<EditorExportPlatform::DebugFlags> p_flags);
virtual void get_platform_features(List<String> *r_features) const override;
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index ae336d6f9d..59b669eabb 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -113,87 +113,6 @@ bool FileAccessAndroid::eof_reached() const {
return eof;
}
-uint8_t FileAccessAndroid::get_8() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint8_t byte;
- AAsset_read(asset, &byte, 1);
- pos++;
- return byte;
-}
-
-uint16_t FileAccessAndroid::get_16() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint16_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 2);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP16(bytes);
- }
-
- return bytes;
-}
-
-uint32_t FileAccessAndroid::get_32() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint32_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 4);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP32(bytes);
- }
-
- return bytes;
-}
-
-uint64_t FileAccessAndroid::get_64() const {
- if (pos >= len) {
- eof = true;
- return 0;
- }
-
- uint64_t bytes = 0;
- int r = AAsset_read(asset, &bytes, 8);
-
- if (r >= 0) {
- pos += r;
- if (pos >= len) {
- eof = true;
- }
- }
-
- if (big_endian) {
- bytes = BSWAP64(bytes);
- }
-
- return bytes;
-}
-
uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@@ -209,6 +128,7 @@ uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const
pos = len;
}
}
+
return r;
}
@@ -220,19 +140,7 @@ void FileAccessAndroid::flush() {
ERR_FAIL();
}
-void FileAccessAndroid::store_8(uint8_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_16(uint16_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_32(uint32_t p_dest) {
- ERR_FAIL();
-}
-
-void FileAccessAndroid::store_64(uint64_t p_dest) {
+void FileAccessAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL();
}
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index b465a92c78..3224ab50b9 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -68,19 +68,12 @@ public:
virtual bool eof_reached() const override; // reading passed EOF
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
- virtual uint8_t get_8() const override; // get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; // get last error
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; // store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; // return true if a file exists
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index 9ae48dfb10..8b52a00ed8 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -169,43 +169,6 @@ void FileAccessFilesystemJAndroid::_set_eof(bool eof) {
}
}
-uint8_t FileAccessFilesystemJAndroid::get_8() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint8_t byte;
- get_buffer(&byte, 1);
- return byte;
-}
-
-uint16_t FileAccessFilesystemJAndroid::get_16() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint16_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 2);
- if (big_endian) {
- bytes = BSWAP16(bytes);
- }
- return bytes;
-}
-
-uint32_t FileAccessFilesystemJAndroid::get_32() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint32_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 4);
- if (big_endian) {
- bytes = BSWAP32(bytes);
- }
- return bytes;
-}
-
-uint64_t FileAccessFilesystemJAndroid::get_64() const {
- ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
- uint64_t bytes = 0;
- get_buffer(reinterpret_cast<uint8_t *>(&bytes), 8);
- if (big_endian) {
- bytes = BSWAP64(bytes);
- }
- return bytes;
-}
-
String FileAccessFilesystemJAndroid::get_line() const {
ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use.");
@@ -271,31 +234,6 @@ uint64_t FileAccessFilesystemJAndroid::get_buffer(uint8_t *p_dst, uint64_t p_len
}
}
-void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) {
- store_buffer(&p_dest, 1);
-}
-
-void FileAccessFilesystemJAndroid::store_16(uint16_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP16(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 2);
-}
-
-void FileAccessFilesystemJAndroid::store_32(uint32_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP32(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 4);
-}
-
-void FileAccessFilesystemJAndroid::store_64(uint64_t p_dest) {
- if (big_endian) {
- p_dest = BSWAP64(p_dest);
- }
- store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 8);
-}
-
void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
if (_file_write) {
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 2795ac02ac..1345b72fa6 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -78,20 +78,12 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual Error resize(int64_t p_length) override;
- virtual uint8_t get_8() const override; ///< get a byte
- virtual uint16_t get_16() const override;
- virtual uint32_t get_32() const override;
- virtual uint64_t get_64() const override;
virtual String get_line() const override; ///< get a line
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; ///< get last error
virtual void flush() override;
- virtual void store_8(uint8_t p_dest) override; ///< store a byte
- virtual void store_16(uint16_t p_dest) override;
- virtual void store_32(uint32_t p_dest) override;
- virtual void store_64(uint64_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt
index ba1185d647..b16e62149a 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/EditorMessageDispatcher.kt
@@ -176,7 +176,7 @@ internal class EditorMessageDispatcher(private val editor: GodotEditor) {
registerMessenger(senderId, senderMessenger)
// Register ourselves to the sender so that it can communicate with us.
- registerSelfTo(pm, senderMessenger, editor.getEditorId())
+ registerSelfTo(pm, senderMessenger, editor.getEditorWindowInfo().windowId)
}
/**
@@ -185,7 +185,7 @@ internal class EditorMessageDispatcher(private val editor: GodotEditor) {
*/
fun getMessageDispatcherPayload(): Bundle {
return Bundle().apply {
- putInt(KEY_EDITOR_ID, editor.getEditorId())
+ putInt(KEY_EDITOR_ID, editor.getEditorWindowInfo().windowId)
putParcelable(KEY_EDITOR_MESSENGER, Messenger(dispatcherHandler))
}
}
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
index 5d6da06f97..1995a38c2a 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt
@@ -40,6 +40,7 @@ import android.content.pm.PackageManager
import android.os.*
import android.util.Log
import android.view.View
+import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.CallSuper
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
@@ -78,6 +79,8 @@ open class GodotEditor : GodotActivity() {
protected val EXTRA_LAUNCH_IN_PIP = "launch_in_pip_requested"
// Command line arguments
+ private const val FULLSCREEN_ARG = "--fullscreen"
+ private const val FULLSCREEN_ARG_SHORT = "-f"
private const val EDITOR_ARG = "--editor"
private const val EDITOR_ARG_SHORT = "-e"
private const val EDITOR_PROJECT_MANAGER_ARG = "--project-manager"
@@ -116,11 +119,16 @@ open class GodotEditor : GodotActivity() {
override fun getGodotAppLayout() = R.layout.godot_editor_layout
- internal open fun getEditorId() = EDITOR_MAIN_INFO.windowId
+ internal open fun getEditorWindowInfo() = EDITOR_MAIN_INFO
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
+ // Prevent the editor window from showing in the display cutout
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && getEditorWindowInfo() == EDITOR_MAIN_INFO) {
+ window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
+ }
+
// We exclude certain permissions from the set we request at startup, as they'll be
// requested on demand based on use-cases.
PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
@@ -213,10 +221,24 @@ open class GodotEditor : GodotActivity() {
}
protected fun getNewGodotInstanceIntent(editorWindowInfo: EditorWindowInfo, args: Array<String>): Intent {
+ val updatedArgs = if (editorWindowInfo == EDITOR_MAIN_INFO &&
+ godot?.isInImmersiveMode() == true &&
+ !args.contains(FULLSCREEN_ARG) &&
+ !args.contains(FULLSCREEN_ARG_SHORT)
+ ) {
+ // If we're launching an editor window (project manager or editor) and we're in
+ // fullscreen mode, we want to remain in fullscreen mode.
+ // This doesn't apply to the play / game window since for that window fullscreen is
+ // controlled by the game logic.
+ args + FULLSCREEN_ARG
+ } else {
+ args
+ }
+
val newInstance = Intent()
.setComponent(ComponentName(this, editorWindowInfo.windowClassName))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- .putExtra(EXTRA_COMMAND_LINE_PARAMS, args)
+ .putExtra(EXTRA_COMMAND_LINE_PARAMS, updatedArgs)
val launchPolicy = resolveLaunchPolicyIfNeeded(editorWindowInfo.launchPolicy)
val isPiPAvailable = if (editorWindowInfo.supportsPiPMode && hasPiPSystemFeature()) {
@@ -235,7 +257,7 @@ open class GodotEditor : GodotActivity() {
}
} else if (launchPolicy == LaunchPolicy.SAME) {
if (isPiPAvailable &&
- (args.contains(BREAKPOINTS_ARG) || args.contains(BREAKPOINTS_ARG_SHORT))) {
+ (updatedArgs.contains(BREAKPOINTS_ARG) || updatedArgs.contains(BREAKPOINTS_ARG_SHORT))) {
Log.v(TAG, "Launching in PiP mode because of breakpoints")
newInstance.putExtra(EXTRA_LAUNCH_IN_PIP, true)
}
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt
index 33fcbf9030..6b4bf255f2 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt
@@ -128,7 +128,7 @@ class GodotGame : GodotEditor() {
override fun getGodotAppLayout() = R.layout.godot_game_layout
- override fun getEditorId() = RUN_GAME_INFO.windowId
+ override fun getEditorWindowInfo() = RUN_GAME_INFO
override fun overrideOrientationRequest() = false
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 49e8ffb008..38bd336e2d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -42,13 +42,16 @@ import android.hardware.Sensor
import android.hardware.SensorManager
import android.os.*
import android.util.Log
+import android.util.TypedValue
import android.view.*
import android.widget.FrameLayout
import androidx.annotation.Keep
import androidx.annotation.StringRes
import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsControllerCompat
import com.google.android.vending.expansion.downloader.*
import org.godotengine.godot.error.Error
import org.godotengine.godot.input.GodotEditText
@@ -105,36 +108,26 @@ class Godot(private val context: Context) {
GodotPluginRegistry.getPluginRegistry()
}
- private val accelerometer_enabled = AtomicBoolean(false)
+ private val accelerometerEnabled = AtomicBoolean(false)
private val mAccelerometer: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
}
- private val gravity_enabled = AtomicBoolean(false)
+ private val gravityEnabled = AtomicBoolean(false)
private val mGravity: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY)
}
- private val magnetometer_enabled = AtomicBoolean(false)
+ private val magnetometerEnabled = AtomicBoolean(false)
private val mMagnetometer: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)
}
- private val gyroscope_enabled = AtomicBoolean(false)
+ private val gyroscopeEnabled = AtomicBoolean(false)
private val mGyroscope: Sensor? by lazy {
mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
}
- private val uiChangeListener = View.OnSystemUiVisibilityChangeListener { visibility: Int ->
- if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
- val decorView = requireActivity().window.decorView
- decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- }}
-
val tts = GodotTTS(context)
val directoryAccessHandler = DirectoryAccessHandler(context)
val fileAccessHandler = FileAccessHandler(context)
@@ -185,7 +178,7 @@ class Godot(private val context: Context) {
private var xrMode = XRMode.REGULAR
private var expansionPackPath: String = ""
private var useApkExpansion = false
- private var useImmersive = false
+ private val useImmersive = AtomicBoolean(false)
private var useDebugOpengl = false
private var darkMode = false
@@ -254,15 +247,9 @@ class Godot(private val context: Context) {
xrMode = XRMode.OPENXR
} else if (commandLine[i] == "--debug_opengl") {
useDebugOpengl = true
- } else if (commandLine[i] == "--use_immersive") {
- useImmersive = true
- window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or // hide nav bar
- View.SYSTEM_UI_FLAG_FULLSCREEN or // hide status bar
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- registerUiChangeListener()
+ } else if (commandLine[i] == "--fullscreen") {
+ useImmersive.set(true)
+ newArgs.add(commandLine[i])
} else if (commandLine[i] == "--use_apk_expansion") {
useApkExpansion = true
} else if (hasExtra && commandLine[i] == "--apk_expansion_md5") {
@@ -336,6 +323,54 @@ class Godot(private val context: Context) {
}
/**
+ * Toggle immersive mode.
+ * Must be called from the UI thread.
+ */
+ private fun enableImmersiveMode(enabled: Boolean, override: Boolean = false) {
+ val activity = getActivity() ?: return
+ val window = activity.window ?: return
+
+ if (!useImmersive.compareAndSet(!enabled, enabled) && !override) {
+ return
+ }
+
+ WindowCompat.setDecorFitsSystemWindows(window, !enabled)
+ val controller = WindowInsetsControllerCompat(window, window.decorView)
+ if (enabled) {
+ controller.hide(WindowInsetsCompat.Type.systemBars())
+ controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+ } else {
+ val fullScreenThemeValue = TypedValue()
+ val hasStatusBar = if (activity.theme.resolveAttribute(android.R.attr.windowFullscreen, fullScreenThemeValue, true) && fullScreenThemeValue.type == TypedValue.TYPE_INT_BOOLEAN) {
+ fullScreenThemeValue.data == 0
+ } else {
+ // Fallback to checking the editor build
+ !isEditorBuild()
+ }
+
+ val types = if (hasStatusBar) {
+ WindowInsetsCompat.Type.navigationBars() or WindowInsetsCompat.Type.statusBars()
+ } else {
+ WindowInsetsCompat.Type.navigationBars()
+ }
+ controller.show(types)
+ }
+ }
+
+ /**
+ * Invoked from the render thread to toggle the immersive mode.
+ */
+ @Keep
+ private fun nativeEnableImmersiveMode(enabled: Boolean) {
+ runOnUiThread {
+ enableImmersiveMode(enabled)
+ }
+ }
+
+ @Keep
+ fun isInImmersiveMode() = useImmersive.get()
+
+ /**
* Initializes the native layer of the Godot engine.
*
* This must be preceded by [onCreate] and followed by [onInitRenderView] to complete
@@ -552,15 +587,7 @@ class Godot(private val context: Context) {
renderView?.onActivityResumed()
registerSensorsIfNeeded()
- if (useImmersive) {
- val window = requireActivity().window
- window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or // hide nav bar
- View.SYSTEM_UI_FLAG_FULLSCREEN or // hide status bar
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- }
+ enableImmersiveMode(useImmersive.get(), true)
for (plugin in pluginRegistry.allPlugins) {
plugin.onMainResume()
}
@@ -571,16 +598,16 @@ class Godot(private val context: Context) {
return
}
- if (accelerometer_enabled.get() && mAccelerometer != null) {
+ if (accelerometerEnabled.get() && mAccelerometer != null) {
mSensorManager.registerListener(godotInputHandler, mAccelerometer, SensorManager.SENSOR_DELAY_GAME)
}
- if (gravity_enabled.get() && mGravity != null) {
+ if (gravityEnabled.get() && mGravity != null) {
mSensorManager.registerListener(godotInputHandler, mGravity, SensorManager.SENSOR_DELAY_GAME)
}
- if (magnetometer_enabled.get() && mMagnetometer != null) {
+ if (magnetometerEnabled.get() && mMagnetometer != null) {
mSensorManager.registerListener(godotInputHandler, mMagnetometer, SensorManager.SENSOR_DELAY_GAME)
}
- if (gyroscope_enabled.get() && mGyroscope != null) {
+ if (gyroscopeEnabled.get() && mGyroscope != null) {
mSensorManager.registerListener(godotInputHandler, mGyroscope, SensorManager.SENSOR_DELAY_GAME)
}
}
@@ -696,10 +723,10 @@ class Godot(private val context: Context) {
Log.v(TAG, "OnGodotMainLoopStarted")
godotMainLoopStarted.set(true)
- accelerometer_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_accelerometer")))
- gravity_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gravity")))
- gyroscope_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gyroscope")))
- magnetometer_enabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_magnetometer")))
+ accelerometerEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_accelerometer")))
+ gravityEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gravity")))
+ gyroscopeEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_gyroscope")))
+ magnetometerEnabled.set(java.lang.Boolean.parseBoolean(GodotLib.getGlobal("input_devices/sensors/enable_magnetometer")))
runOnUiThread {
registerSensorsIfNeeded()
@@ -724,11 +751,6 @@ class Godot(private val context: Context) {
primaryHost?.onGodotRestartRequested(this)
}
- private fun registerUiChangeListener() {
- val decorView = requireActivity().window.decorView
- decorView.setOnSystemUiVisibilityChangeListener(uiChangeListener)
- }
-
fun alert(
@StringRes messageResId: Int,
@StringRes titleResId: Int,
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 1114969de8..390677df22 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -51,7 +51,10 @@
#include "core/config/project_settings.h"
#include "core/input/input.h"
#include "main/main.h"
+
+#ifndef _3D_DISABLED
#include "servers/xr_server.h"
+#endif // _3D_DISABLED
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
@@ -271,14 +274,16 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env,
}
if (step.get() == STEP_SHOW_LOGO) {
- bool xr_enabled;
+ bool xr_enabled = false;
+#ifndef _3D_DISABLED
+ // Unlike PCVR, there's no additional 2D screen onto which to render the boot logo,
+ // so we skip this step if xr is enabled.
if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
xr_enabled = GLOBAL_GET("xr/shaders/enabled");
} else {
xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
}
- // Unlike PCVR, there's no additional 2D screen onto which to render the boot logo,
- // so we skip this step if xr is enabled.
+#endif // _3D_DISABLED
if (!xr_enabled) {
Main::setup_boot_logo();
}
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index f1759af54a..d3b30e4589 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -86,6 +86,8 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_
_has_feature = p_env->GetMethodID(godot_class, "hasFeature", "(Ljava/lang/String;)Z");
_sign_apk = p_env->GetMethodID(godot_class, "nativeSignApk", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I");
_verify_apk = p_env->GetMethodID(godot_class, "nativeVerifyApk", "(Ljava/lang/String;)I");
+ _enable_immersive_mode = p_env->GetMethodID(godot_class, "nativeEnableImmersiveMode", "(Z)V");
+ _is_in_immersive_mode = p_env->GetMethodID(godot_class, "isInImmersiveMode", "()Z");
}
GodotJavaWrapper::~GodotJavaWrapper() {
@@ -465,3 +467,21 @@ Error GodotJavaWrapper::verify_apk(const String &p_apk_path) {
return ERR_UNCONFIGURED;
}
}
+
+void GodotJavaWrapper::enable_immersive_mode(bool p_enabled) {
+ if (_enable_immersive_mode) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL(env);
+ env->CallVoidMethod(godot_instance, _enable_immersive_mode, p_enabled);
+ }
+}
+
+bool GodotJavaWrapper::is_in_immersive_mode() {
+ if (_is_in_immersive_mode) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_NULL_V(env, false);
+ return env->CallBooleanMethod(godot_instance, _is_in_immersive_mode);
+ } else {
+ return false;
+ }
+}
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 6b66565981..51d7f98541 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -77,6 +77,8 @@ private:
jmethodID _has_feature = nullptr;
jmethodID _sign_apk = nullptr;
jmethodID _verify_apk = nullptr;
+ jmethodID _enable_immersive_mode = nullptr;
+ jmethodID _is_in_immersive_mode = nullptr;
public:
GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance);
@@ -122,6 +124,9 @@ public:
// Sign and verify apks
Error sign_apk(const String &p_input_path, const String &p_output_path, const String &p_keystore_path, const String &p_keystore_user, const String &p_keystore_password);
Error verify_apk(const String &p_apk_path);
+
+ void enable_immersive_mode(bool p_enabled);
+ bool is_in_immersive_mode();
};
#endif // JAVA_GODOT_WRAPPER_H