summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/android_input_handler.cpp62
-rw-r--r--platform/android/android_input_handler.h8
-rw-r--r--platform/android/audio_driver_opensl.cpp12
-rw-r--r--platform/android/audio_driver_opensl.h27
-rw-r--r--platform/android/display_server_android.cpp2
-rw-r--r--platform/android/export/export_plugin.cpp148
-rw-r--r--platform/android/export/export_plugin.h10
-rw-r--r--platform/android/export/gradle_export_util.cpp45
-rw-r--r--platform/android/export/gradle_export_util.h6
-rw-r--r--platform/android/file_access_android.cpp4
-rw-r--r--platform/android/file_access_android.h2
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp6
-rw-r--r--platform/android/file_access_filesystem_jandroid.h2
-rw-r--r--platform/android/java/app/AndroidManifest.xml30
-rw-r--r--platform/android/java/app/build.gradle8
-rw-r--r--platform/android/java/app/gradle.properties4
-rw-r--r--platform/android/java/app/settings.gradle2
-rw-r--r--platform/android/java/app/src/com/godot/game/GodotApp.java2
-rw-r--r--platform/android/java/build.gradle14
-rw-r--r--platform/android/java/editor/src/main/res/values/dimens.xml2
-rw-r--r--platform/android/java/gradle.properties2
-rw-r--r--platform/android/java/lib/AndroidManifest.xml10
-rw-r--r--platform/android/java/lib/res/values/strings.xml1
-rw-r--r--platform/android/java/lib/res/xml/godot_provider_paths.xml11
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java36
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java38
-rw-r--r--platform/android/java_godot_lib_jni.cpp2
-rw-r--r--platform/ios/SCsub1
-rw-r--r--platform/ios/export/export_plugin.cpp1
-rw-r--r--platform/ios/godot_view.h5
-rw-r--r--platform/ios/godot_view.mm82
-rw-r--r--platform/ios/godot_view_gesture_recognizer.h46
-rw-r--r--platform/ios/godot_view_gesture_recognizer.mm186
-rw-r--r--platform/ios/joypad_ios.mm19
-rw-r--r--platform/linuxbsd/SCsub17
-rw-r--r--platform/linuxbsd/dbus-so_wrap.c4
-rw-r--r--platform/linuxbsd/dbus-so_wrap.h4
-rw-r--r--platform/linuxbsd/detect.py145
-rw-r--r--platform/linuxbsd/fontconfig-so_wrap.c4
-rw-r--r--platform/linuxbsd/fontconfig-so_wrap.h4
-rw-r--r--platform/linuxbsd/freedesktop_portal_desktop.cpp8
-rw-r--r--platform/linuxbsd/freedesktop_screensaver.cpp8
-rw-r--r--platform/linuxbsd/joypad_linux.cpp6
-rw-r--r--platform/linuxbsd/libudev-so_wrap.c4
-rw-r--r--platform/linuxbsd/libudev-so_wrap.h4
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp10
-rw-r--r--platform/linuxbsd/os_linuxbsd.h4
-rw-r--r--platform/linuxbsd/speechd-so_wrap.c4
-rw-r--r--platform/linuxbsd/speechd-so_wrap.h4
-rw-r--r--platform/linuxbsd/tts_linux.cpp10
-rw-r--r--platform/linuxbsd/tts_linux.h4
-rw-r--r--platform/linuxbsd/x11/SCsub20
-rw-r--r--platform/linuxbsd/x11/detect_prime_x11.cpp6
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp188
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h31
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c4
-rw-r--r--platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h4
-rw-r--r--platform/linuxbsd/x11/gl_manager_x11.h15
-rw-r--r--platform/linuxbsd/xkbcommon-so_wrap.c160
-rw-r--r--platform/linuxbsd/xkbcommon-so_wrap.h62
-rw-r--r--platform/macos/display_server_macos.mm20
-rw-r--r--platform/macos/export/export_plugin.cpp38
-rw-r--r--platform/web/audio_driver_web.cpp8
-rw-r--r--platform/web/audio_driver_web.h14
-rw-r--r--platform/web/display_server_web.cpp25
-rw-r--r--platform/web/display_server_web.h2
-rw-r--r--platform/web/export/editor_http_server.h3
-rw-r--r--platform/web/godot_audio.h4
-rw-r--r--platform/web/http_client_web.cpp10
-rw-r--r--platform/web/http_client_web.h2
-rw-r--r--platform/web/js/libs/library_godot_audio.js12
-rw-r--r--platform/windows/display_server_windows.cpp122
-rw-r--r--platform/windows/gl_manager_windows.h1
-rw-r--r--platform/windows/os_windows.cpp6
87 files changed, 1172 insertions, 715 deletions
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp
index 17903b3965..63045237e9 100644
--- a/platform/android/android_input_handler.cpp
+++ b/platform/android/android_input_handler.cpp
@@ -49,11 +49,19 @@ void AndroidInputHandler::process_joy_event(AndroidInputHandler::JoypadEvent p_e
}
}
-void AndroidInputHandler::_set_key_modifier_state(Ref<InputEventWithModifiers> ev) {
- ev->set_shift_pressed(shift_mem);
- ev->set_alt_pressed(alt_mem);
- ev->set_meta_pressed(meta_mem);
- ev->set_ctrl_pressed(control_mem);
+void AndroidInputHandler::_set_key_modifier_state(Ref<InputEventWithModifiers> ev, Key p_keycode) {
+ if (p_keycode != Key::SHIFT) {
+ ev->set_shift_pressed(shift_mem);
+ }
+ if (p_keycode != Key::ALT) {
+ ev->set_alt_pressed(alt_mem);
+ }
+ if (p_keycode != Key::META) {
+ ev->set_meta_pressed(meta_mem);
+ }
+ if (p_keycode != Key::CTRL) {
+ ev->set_ctrl_pressed(control_mem);
+ }
}
void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicode, int p_key_label, bool p_pressed) {
@@ -118,7 +126,7 @@ void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicod
ev->set_unicode(fix_unicode(unicode));
ev->set_pressed(p_pressed);
- _set_key_modifier_state(ev);
+ _set_key_modifier_state(ev, keycode);
if (p_physical_keycode == AKEYCODE_BACK) {
if (DisplayServerAndroid *dsa = Object::cast_to<DisplayServerAndroid>(DisplayServer::get_singleton())) {
@@ -129,13 +137,22 @@ void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicod
Input::get_singleton()->parse_input_event(ev);
}
-void AndroidInputHandler::_parse_all_touch(bool p_pressed, bool p_double_tap) {
+void AndroidInputHandler::_cancel_all_touch() {
+ _parse_all_touch(false, false, true);
+ touch.clear();
+}
+
+void AndroidInputHandler::_parse_all_touch(bool p_pressed, bool p_double_tap, bool reset_index) {
if (touch.size()) {
//end all if exist
for (int i = 0; i < touch.size(); i++) {
Ref<InputEventScreenTouch> ev;
ev.instantiate();
- ev->set_index(touch[i].id);
+ if (reset_index) {
+ ev->set_index(-1);
+ } else {
+ ev->set_index(touch[i].id);
+ }
ev->set_pressed(p_pressed);
ev->set_position(touch[i].pos);
ev->set_double_tap(p_double_tap);
@@ -196,7 +213,9 @@ void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const
}
} break;
- case AMOTION_EVENT_ACTION_CANCEL:
+ case AMOTION_EVENT_ACTION_CANCEL: {
+ _cancel_all_touch();
+ } break;
case AMOTION_EVENT_ACTION_UP: { //release
_release_all_touch();
} break;
@@ -236,6 +255,12 @@ void AndroidInputHandler::process_touch_event(int p_event, int p_pointer, const
}
}
+void AndroidInputHandler::_cancel_mouse_event_info(bool p_source_mouse_relative) {
+ buttons_state = BitField<MouseButtonMask>();
+ _parse_mouse_event_info(BitField<MouseButtonMask>(), false, false, p_source_mouse_relative);
+ mouse_event_info.valid = false;
+}
+
void AndroidInputHandler::_parse_mouse_event_info(BitField<MouseButtonMask> event_buttons_mask, bool p_pressed, bool p_double_click, bool p_source_mouse_relative) {
if (!mouse_event_info.valid) {
return;
@@ -243,7 +268,7 @@ void AndroidInputHandler::_parse_mouse_event_info(BitField<MouseButtonMask> even
Ref<InputEventMouseButton> ev;
ev.instantiate();
- _set_key_modifier_state(ev);
+ _set_key_modifier_state(ev, Key::NONE);
if (p_source_mouse_relative) {
ev->set_position(hover_prev_pos);
ev->set_global_position(hover_prev_pos);
@@ -277,7 +302,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an
// https://developer.android.com/reference/android/view/MotionEvent.html#ACTION_HOVER_ENTER
Ref<InputEventMouseMotion> ev;
ev.instantiate();
- _set_key_modifier_state(ev);
+ _set_key_modifier_state(ev, Key::NONE);
ev->set_position(p_event_pos);
ev->set_global_position(p_event_pos);
ev->set_relative(p_event_pos - hover_prev_pos);
@@ -296,8 +321,11 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an
_parse_mouse_event_info(event_buttons_mask, true, p_double_click, p_source_mouse_relative);
} break;
+ case AMOTION_EVENT_ACTION_CANCEL: {
+ _cancel_mouse_event_info(p_source_mouse_relative);
+ } break;
+
case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
case AMOTION_EVENT_ACTION_BUTTON_RELEASE: {
_release_mouse_event_info(p_source_mouse_relative);
} break;
@@ -309,7 +337,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an
Ref<InputEventMouseMotion> ev;
ev.instantiate();
- _set_key_modifier_state(ev);
+ _set_key_modifier_state(ev, Key::NONE);
if (p_source_mouse_relative) {
ev->set_position(hover_prev_pos);
ev->set_global_position(hover_prev_pos);
@@ -328,7 +356,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an
case AMOTION_EVENT_ACTION_SCROLL: {
Ref<InputEventMouseButton> ev;
ev.instantiate();
- _set_key_modifier_state(ev);
+ _set_key_modifier_state(ev, Key::NONE);
if (p_source_mouse_relative) {
ev->set_position(hover_prev_pos);
ev->set_global_position(hover_prev_pos);
@@ -355,7 +383,7 @@ void AndroidInputHandler::process_mouse_event(int p_event_action, int p_event_an
void AndroidInputHandler::_wheel_button_click(BitField<MouseButtonMask> event_buttons_mask, const Ref<InputEventMouseButton> &ev, MouseButton wheel_button, float factor) {
Ref<InputEventMouseButton> evd = ev->duplicate();
- _set_key_modifier_state(evd);
+ _set_key_modifier_state(evd, Key::NONE);
evd->set_button_index(wheel_button);
evd->set_button_mask(BitField<MouseButtonMask>(event_buttons_mask.operator int64_t() ^ int64_t(mouse_button_to_mask(wheel_button))));
evd->set_factor(factor);
@@ -369,7 +397,7 @@ void AndroidInputHandler::_wheel_button_click(BitField<MouseButtonMask> event_bu
void AndroidInputHandler::process_magnify(Point2 p_pos, float p_factor) {
Ref<InputEventMagnifyGesture> magnify_event;
magnify_event.instantiate();
- _set_key_modifier_state(magnify_event);
+ _set_key_modifier_state(magnify_event, Key::NONE);
magnify_event->set_position(p_pos);
magnify_event->set_factor(p_factor);
Input::get_singleton()->parse_input_event(magnify_event);
@@ -378,7 +406,7 @@ void AndroidInputHandler::process_magnify(Point2 p_pos, float p_factor) {
void AndroidInputHandler::process_pan(Point2 p_pos, Vector2 p_delta) {
Ref<InputEventPanGesture> pan_event;
pan_event.instantiate();
- _set_key_modifier_state(pan_event);
+ _set_key_modifier_state(pan_event, Key::NONE);
pan_event->set_position(p_pos);
pan_event->set_delta(p_delta);
Input::get_singleton()->parse_input_event(pan_event);
diff --git a/platform/android/android_input_handler.h b/platform/android/android_input_handler.h
index 6e53dcfc89..2badd32636 100644
--- a/platform/android/android_input_handler.h
+++ b/platform/android/android_input_handler.h
@@ -76,7 +76,7 @@ private:
MouseEventInfo mouse_event_info;
Point2 hover_prev_pos; // needed to calculate the relative position on hover events
- void _set_key_modifier_state(Ref<InputEventWithModifiers> ev);
+ void _set_key_modifier_state(Ref<InputEventWithModifiers> ev, Key p_keycode);
static MouseButton _button_index_from_mask(BitField<MouseButtonMask> button_mask);
static BitField<MouseButtonMask> _android_button_mask_to_godot_button_mask(int android_button_mask);
@@ -87,10 +87,14 @@ private:
void _release_mouse_event_info(bool p_source_mouse_relative = false);
- void _parse_all_touch(bool p_pressed, bool p_double_tap);
+ void _cancel_mouse_event_info(bool p_source_mouse_relative = false);
+
+ void _parse_all_touch(bool p_pressed, bool p_double_tap, bool reset_index = false);
void _release_all_touch();
+ void _cancel_all_touch();
+
public:
void process_mouse_event(int p_event_action, int p_event_android_buttons_mask, Point2 p_event_pos, Vector2 p_delta, bool p_double_click, bool p_source_mouse_relative);
void process_touch_event(int p_event, int p_pointer, const Vector<TouchPos> &p_points, bool p_double_tap);
diff --git a/platform/android/audio_driver_opensl.cpp b/platform/android/audio_driver_opensl.cpp
index 9dad0c9357..5fc32132e3 100644
--- a/platform/android/audio_driver_opensl.cpp
+++ b/platform/android/audio_driver_opensl.cpp
@@ -80,10 +80,6 @@ void AudioDriverOpenSL::_buffer_callbacks(
ad->_buffer_callback(queueItf);
}
-const char *AudioDriverOpenSL::get_name() const {
- return "Android";
-}
-
Error AudioDriverOpenSL::init() {
SLresult res;
SLEngineOption EngineOption[] = {
@@ -204,7 +200,7 @@ void AudioDriverOpenSL::_record_buffer_callbacks(SLAndroidSimpleBufferQueueItf q
ad->_record_buffer_callback(queueItf);
}
-Error AudioDriverOpenSL::capture_init_device() {
+Error AudioDriverOpenSL::init_input_device() {
SLDataLocator_IODevice loc_dev = {
SL_DATALOCATOR_IODEVICE,
SL_IODEVICE_AUDIOINPUT,
@@ -271,15 +267,15 @@ Error AudioDriverOpenSL::capture_init_device() {
return OK;
}
-Error AudioDriverOpenSL::capture_start() {
+Error AudioDriverOpenSL::input_start() {
if (OS::get_singleton()->request_permission("RECORD_AUDIO")) {
- return capture_init_device();
+ return init_input_device();
}
return OK;
}
-Error AudioDriverOpenSL::capture_stop() {
+Error AudioDriverOpenSL::input_stop() {
SLuint32 state;
SLresult res = (*recordItf)->GetRecordState(recordItf, &state);
ERR_FAIL_COND_V(res != SL_RESULT_SUCCESS, ERR_CANT_OPEN);
diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h
index ae8c33fec0..6ea0f77def 100644
--- a/platform/android/audio_driver_opensl.h
+++ b/platform/android/audio_driver_opensl.h
@@ -84,23 +84,26 @@ class AudioDriverOpenSL : public AudioDriver {
SLAndroidSimpleBufferQueueItf queueItf,
void *pContext);
- virtual Error capture_init_device();
+ Error init_input_device();
public:
- virtual const char *get_name() const;
+ virtual const char *get_name() const override {
+ return "Android";
+ }
- virtual Error init();
- virtual void start();
- virtual int get_mix_rate() const;
- virtual SpeakerMode get_speaker_mode() const;
- virtual void lock();
- virtual void unlock();
- virtual void finish();
+ virtual Error init() override;
+ virtual void start() override;
+ virtual int get_mix_rate() const override;
+ virtual SpeakerMode get_speaker_mode() const override;
- virtual void set_pause(bool p_pause);
+ virtual void lock() override;
+ virtual void unlock() override;
+ virtual void finish() override;
- virtual Error capture_start();
- virtual Error capture_stop();
+ virtual Error input_start() override;
+ virtual Error input_stop() override;
+
+ void set_pause(bool p_pause);
AudioDriverOpenSL();
};
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 3fcb926f86..af4ba1255b 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -656,6 +656,7 @@ void DisplayServerAndroid::_cursor_set_shape_helper(CursorShape p_shape, bool fo
}
void DisplayServerAndroid::cursor_set_shape(DisplayServer::CursorShape p_shape) {
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
_cursor_set_shape_helper(p_shape);
}
@@ -664,6 +665,7 @@ DisplayServer::CursorShape DisplayServerAndroid::cursor_get_shape() const {
}
void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
String cursor_path = p_cursor.is_valid() ? p_cursor->get_path() : "";
if (!cursor_path.is_empty()) {
cursor_path = ProjectSettings::get_singleton()->globalize_path(cursor_path);
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 587caf81bf..641258a26c 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -251,7 +251,8 @@ static const int EXPORT_FORMAT_AAB = 1;
static const char *APK_ASSETS_DIRECTORY = "res://android/build/assets";
static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/installTime/src/main/assets";
-static const int DEFAULT_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
+static const int OPENGL_MIN_SDK_VERSION = 21; // Should match the value in 'platform/android/java/app/config.gradle#minSdk'
+static const int VULKAN_MIN_SDK_VERSION = 24;
static const int DEFAULT_TARGET_SDK_VERSION = 32; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk'
#ifndef ANDROID_ENABLED
@@ -799,6 +800,12 @@ bool EditorExportPlatformAndroid::_has_manage_external_storage_permission(const
return p_permissions.find("android.permission.MANAGE_EXTERNAL_STORAGE") != -1;
}
+bool EditorExportPlatformAndroid::_uses_vulkan() {
+ String current_renderer = GLOBAL_GET("rendering/renderer/rendering_method.mobile");
+ bool uses_vulkan = (current_renderer == "forward_plus" || current_renderer == "mobile") && GLOBAL_GET("rendering/rendering_device/driver.android") == "vulkan";
+ return uses_vulkan;
+}
+
void EditorExportPlatformAndroid::_get_permissions(const Ref<EditorExportPreset> &p_preset, bool p_give_internet, Vector<String> &r_permissions) {
const char **aperms = android_perms;
while (*aperms) {
@@ -853,7 +860,7 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref<EditorExportPres
}
}
- manifest_text += _get_xr_features_tag(p_preset);
+ manifest_text += _get_xr_features_tag(p_preset, _uses_vulkan());
manifest_text += _get_application_tag(p_preset, _has_read_write_storage_permission(perms));
manifest_text += "</manifest>\n";
String manifest_path = vformat("res://android/build/src/%s/AndroidManifest.xml", (p_debug ? "debug" : "release"));
@@ -899,10 +906,6 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
bool screen_support_large = p_preset->get("screen/support_large");
bool screen_support_xlarge = p_preset->get("screen/support_xlarge");
- int xr_mode_index = p_preset->get("xr_features/xr_mode");
- int hand_tracking_index = p_preset->get("xr_features/hand_tracking");
- int hand_tracking_frequency_index = p_preset->get("xr_features/hand_tracking_frequency");
-
bool backup_allowed = p_preset->get("user_data_backup/allow");
int app_category = p_preset->get("package/app_category");
bool retain_data_on_uninstall = p_preset->get("package/retain_data_on_uninstall");
@@ -1027,6 +1030,10 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
encode_uint32(is_resizeable, &p_manifest.write[iofs + 16]);
}
+ if (tname == "provider" && attrname == "authorities") {
+ string_table.write[attr_value] = get_package_name(package_name) + String(".fileprovider");
+ }
+
if (tname == "supports-screens") {
if (attrname == "smallScreens") {
encode_uint32(screen_support_small ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
@@ -1042,25 +1049,6 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
}
- // Hand tracking related configurations
- if (xr_mode_index == XR_MODE_OPENXR && hand_tracking_index > XR_HAND_TRACKING_NONE) {
- if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_metadata_name") {
- string_table.write[attr_value] = "com.oculus.handtracking.frequency";
- }
-
- if (tname == "meta-data" && attrname == "value" && value == "xr_hand_tracking_metadata_value") {
- string_table.write[attr_value] = (hand_tracking_frequency_index == XR_HAND_TRACKING_FREQUENCY_LOW ? "LOW" : "HIGH");
- }
-
- if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_version_name") {
- string_table.write[attr_value] = "com.oculus.handtracking.version";
- }
-
- if (tname == "meta-data" && attrname == "value" && value == "xr_hand_tracking_version_value") {
- string_table.write[attr_value] = "V2.0";
- }
- }
-
iofs += 20;
}
@@ -1075,26 +1063,11 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
Vector<bool> feature_required_list;
Vector<int> feature_versions;
- if (xr_mode_index == XR_MODE_OPENXR) {
- // Set degrees of freedom
- feature_names.push_back("android.hardware.vr.headtracking");
+ if (_uses_vulkan()) {
+ // Require vulkan hardware level 1 support
+ feature_names.push_back("android.hardware.vulkan.level");
feature_required_list.push_back(true);
feature_versions.push_back(1);
-
- // Check for hand tracking
- if (hand_tracking_index > XR_HAND_TRACKING_NONE) {
- feature_names.push_back("oculus.software.handtracking");
- feature_required_list.push_back(hand_tracking_index == XR_HAND_TRACKING_REQUIRED);
- feature_versions.push_back(-1); // no version attribute should be added.
- }
-
- // Check for passthrough
- int passthrough_mode = p_preset->get("xr_features/passthrough");
- if (passthrough_mode > XR_PASSTHROUGH_NONE) {
- feature_names.push_back("com.oculus.feature.PASSTHROUGH");
- feature_required_list.push_back(passthrough_mode == XR_PASSTHROUGH_REQUIRED);
- feature_versions.push_back(-1);
- }
}
if (feature_names.size() > 0) {
@@ -1716,6 +1689,7 @@ Vector<EditorExportPlatformAndroid::ABI> EditorExportPlatformAndroid::get_enable
void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
r_features->push_back("etc2");
+ r_features->push_back("astc");
Vector<ABI> abis = get_enabled_abis(p_preset);
for (int i = 0; i < abis.size(); ++i) {
@@ -1728,12 +1702,12 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_build/use_custom_build"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "custom_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "gradle_build/use_gradle_build"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "gradle_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
// Using String instead of int to default to an empty string (no override) with placeholder for instructions (see GH-62465).
// This implies doing validation that the string is a proper int.
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_MIN_SDK_VERSION)), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), ""));
Vector<PluginConfigAndroid> plugins_configs = get_plugins();
for (int i = 0; i < plugins_configs.size(); i++) {
@@ -2158,11 +2132,11 @@ String EditorExportPlatformAndroid::get_apksigner_path(int p_target_sdk, bool p_
bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
bool valid = false;
- const bool custom_build_enabled = p_preset->get("custom_build/use_custom_build");
+ const bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
// Look for export templates (first official, and if defined custom templates).
- if (!custom_build_enabled) {
+ if (!gradle_build_enabled) {
String template_err;
bool dvalid = false;
bool rvalid = false;
@@ -2269,7 +2243,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
valid = false;
}
- String target_sdk_version = p_preset->get("custom_build/target_sdk");
+ String target_sdk_version = p_preset->get("gradle_build/target_sdk");
if (!target_sdk_version.is_valid_int()) {
target_sdk_version = itos(DEFAULT_TARGET_SDK_VERSION);
}
@@ -2293,7 +2267,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const {
String err;
bool valid = true;
- const bool custom_build_enabled = p_preset->get("custom_build/use_custom_build");
+ const bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
// Validate the project configuration.
bool apk_expansion = p_preset->get("apk_expansion/enable");
@@ -2322,11 +2296,11 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
err += etc_error;
}
- // Ensure that `Use Custom Build` is enabled if a plugin is selected.
+ // Ensure that `Use Gradle Build` is enabled if a plugin is selected.
String enabled_plugins_names = PluginConfigAndroid::get_plugins_names(get_enabled_plugins(p_preset));
- if (!enabled_plugins_names.is_empty() && !custom_build_enabled) {
+ if (!enabled_plugins_names.is_empty() && !gradle_build_enabled) {
valid = false;
- err += TTR("\"Use Custom Build\" must be enabled to use the plugins.");
+ err += TTR("\"Use Gradle Build\" must be enabled to use the plugins.");
err += "\n";
}
@@ -2334,6 +2308,12 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
int xr_mode_index = p_preset->get("xr_features/xr_mode");
int hand_tracking = p_preset->get("xr_features/hand_tracking");
int passthrough_mode = p_preset->get("xr_features/passthrough");
+ if (xr_mode_index == XR_MODE_OPENXR && !gradle_build_enabled) {
+ valid = false;
+ err += TTR("OpenXR requires \"Use Gradle Build\" to be enabled");
+ err += "\n";
+ }
+
if (xr_mode_index != XR_MODE_OPENXR) {
if (hand_tracking > XR_HAND_TRACKING_NONE) {
valid = false;
@@ -2348,20 +2328,20 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
}
}
- if (int(p_preset->get("custom_build/export_format")) == EXPORT_FORMAT_AAB &&
- !custom_build_enabled) {
+ if (int(p_preset->get("gradle_build/export_format")) == EXPORT_FORMAT_AAB &&
+ !gradle_build_enabled) {
valid = false;
- err += TTR("\"Export AAB\" is only valid when \"Use Custom Build\" is enabled.");
+ err += TTR("\"Export AAB\" is only valid when \"Use Gradle Build\" is enabled.");
err += "\n";
}
// Check the min sdk version.
- String min_sdk_str = p_preset->get("custom_build/min_sdk");
- int min_sdk_int = DEFAULT_MIN_SDK_VERSION;
+ String min_sdk_str = p_preset->get("gradle_build/min_sdk");
+ int min_sdk_int = VULKAN_MIN_SDK_VERSION;
if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
- if (!custom_build_enabled) {
+ if (!gradle_build_enabled) {
valid = false;
- err += TTR("\"Min SDK\" can only be overridden when \"Use Custom Build\" is enabled.");
+ err += TTR("\"Min SDK\" can only be overridden when \"Use Gradle Build\" is enabled.");
err += "\n";
}
if (!min_sdk_str.is_valid_int()) {
@@ -2370,21 +2350,21 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
err += "\n";
} else {
min_sdk_int = min_sdk_str.to_int();
- if (min_sdk_int < DEFAULT_MIN_SDK_VERSION) {
+ if (min_sdk_int < OPENGL_MIN_SDK_VERSION) {
valid = false;
- err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), DEFAULT_MIN_SDK_VERSION);
+ err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), OPENGL_MIN_SDK_VERSION);
err += "\n";
}
}
}
// Check the target sdk version.
- String target_sdk_str = p_preset->get("custom_build/target_sdk");
+ String target_sdk_str = p_preset->get("gradle_build/target_sdk");
int target_sdk_int = DEFAULT_TARGET_SDK_VERSION;
if (!target_sdk_str.is_empty()) { // Empty means no override, nothing to do.
- if (!custom_build_enabled) {
+ if (!gradle_build_enabled) {
valid = false;
- err += TTR("\"Target SDK\" can only be overridden when \"Use Custom Build\" is enabled.");
+ err += TTR("\"Target SDK\" can only be overridden when \"Use Gradle Build\" is enabled.");
err += "\n";
}
if (!target_sdk_str.is_valid_int()) {
@@ -2407,6 +2387,18 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
err += "\n";
}
+ String current_renderer = GLOBAL_GET("rendering/renderer/rendering_method.mobile");
+ if (current_renderer == "forward_plus") {
+ // Warning only, so don't override `valid`.
+ err += vformat(TTR("The \"%s\" renderer is designed for Desktop devices, and is not suitable for Android devices."), current_renderer);
+ err += "\n";
+ }
+ if (_uses_vulkan() && min_sdk_int < VULKAN_MIN_SDK_VERSION) {
+ // Warning only, so don't override `valid`.
+ err += vformat(TTR("\"Min SDK\" should be greater or equal to %d for the \"%s\" renderer."), VULKAN_MIN_SDK_VERSION, current_renderer);
+ err += "\n";
+ }
+
r_error = err;
return valid;
}
@@ -2492,12 +2484,12 @@ void EditorExportPlatformAndroid::get_command_line_flags(const Ref<EditorExportP
}
Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &export_path, EditorProgress &ep) {
- int export_format = int(p_preset->get("custom_build/export_format"));
+ int export_format = int(p_preset->get("gradle_build/export_format"));
String export_label = export_format == EXPORT_FORMAT_AAB ? "AAB" : "APK";
String release_keystore = p_preset->get("keystore/release");
String release_username = p_preset->get("keystore/release_user");
String release_password = p_preset->get("keystore/release_password");
- String target_sdk_version = p_preset->get("custom_build/target_sdk");
+ String target_sdk_version = p_preset->get("gradle_build/target_sdk");
if (!target_sdk_version.is_valid_int()) {
target_sdk_version = itos(DEFAULT_TARGET_SDK_VERSION);
}
@@ -2674,7 +2666,7 @@ String EditorExportPlatformAndroid::join_abis(const Vector<EditorExportPlatformA
}
Error EditorExportPlatformAndroid::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
- int export_format = int(p_preset->get("custom_build/export_format"));
+ 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);
}
@@ -2687,7 +2679,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
EditorProgress ep("export", TTR("Exporting for Android"), 105, true);
- bool use_custom_build = bool(p_preset->get("custom_build/use_custom_build"));
+ bool use_gradle_build = bool(p_preset->get("gradle_build/use_gradle_build"));
bool p_give_internet = p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG);
bool apk_expansion = p_preset->get("apk_expansion/enable");
Vector<ABI> enabled_abis = get_enabled_abis(p_preset);
@@ -2697,7 +2689,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
print_verbose("- export path: " + p_path);
print_verbose("- export format: " + itos(export_format));
print_verbose("- sign build: " + bool_to_string(should_sign));
- print_verbose("- custom build enabled: " + bool_to_string(use_custom_build));
+ print_verbose("- gradle build enabled: " + bool_to_string(use_gradle_build));
print_verbose("- apk expansion enabled: " + bool_to_string(apk_expansion));
print_verbose("- enabled abis: " + join_abis(enabled_abis, ",", false));
print_verbose("- export filter: " + itos(p_preset->get_export_filter()));
@@ -2737,14 +2729,14 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return ERR_UNCONFIGURED;
}
- if (use_custom_build) {
- print_verbose("Starting custom build...");
+ if (use_gradle_build) {
+ print_verbose("Starting gradle build...");
//test that installed build version is alright
{
print_verbose("Checking build version...");
Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::READ);
if (f.is_null()) {
- add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Trying to build from a gradle built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
return ERR_UNCONFIGURED;
}
String version = f->get_line().strip_edges();
@@ -2814,11 +2806,11 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
String package_name = get_package_name(p_preset->get("package/unique_name"));
String version_code = itos(p_preset->get("version/code"));
String version_name = p_preset->get("version/name");
- String min_sdk_version = p_preset->get("custom_build/min_sdk");
+ String min_sdk_version = p_preset->get("gradle_build/min_sdk");
if (!min_sdk_version.is_valid_int()) {
- min_sdk_version = itos(DEFAULT_MIN_SDK_VERSION);
+ min_sdk_version = itos(VULKAN_MIN_SDK_VERSION);
}
- String target_sdk_version = p_preset->get("custom_build/target_sdk");
+ String target_sdk_version = p_preset->get("gradle_build/target_sdk");
if (!target_sdk_version.is_valid_int()) {
target_sdk_version = itos(DEFAULT_TARGET_SDK_VERSION);
}
@@ -2944,7 +2936,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return ERR_CANT_CREATE;
}
- print_verbose("Successfully completed Android custom build.");
+ print_verbose("Successfully completed Android gradle build.");
return OK;
}
// This is the start of the Legacy build system
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index bff769fcba..337a0228d0 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -74,7 +74,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
Vector<PluginConfigAndroid> plugins;
String last_plugin_names;
- uint64_t last_custom_build_time = 0;
+ uint64_t last_gradle_build_time = 0;
SafeFlag plugins_changed;
Mutex plugins_lock;
Vector<Device> devices;
@@ -172,6 +172,8 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
static Vector<ABI> get_enabled_abis(const Ref<EditorExportPreset> &p_preset);
+ static bool _uses_vulkan();
+
public:
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
@@ -213,14 +215,14 @@ public:
inline bool is_clean_build_required(Vector<PluginConfigAndroid> enabled_plugins) {
String plugin_names = PluginConfigAndroid::get_plugins_names(enabled_plugins);
- bool first_build = last_custom_build_time == 0;
+ bool first_build = last_gradle_build_time == 0;
bool have_plugins_changed = false;
if (!first_build) {
have_plugins_changed = plugin_names != last_plugin_names;
if (!have_plugins_changed) {
for (int i = 0; i < enabled_plugins.size(); i++) {
- if (enabled_plugins.get(i).last_updated > last_custom_build_time) {
+ if (enabled_plugins.get(i).last_updated > last_gradle_build_time) {
have_plugins_changed = true;
break;
}
@@ -228,7 +230,7 @@ public:
}
}
- last_custom_build_time = OS::get_singleton()->get_unix_time();
+ last_gradle_build_time = OS::get_singleton()->get_unix_time();
last_plugin_names = plugin_names;
return have_plugins_changed || first_build;
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index e450f3edb3..b889d58199 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -166,7 +166,7 @@ Error store_string_at_path(const String &p_path, const String &p_data) {
// This method will only be called as an input to export_project_files.
// It is used by the export_project_files method to save all the asset files into the gradle project.
// It's functionality mirrors that of the method save_apk_file.
-// This method will be called ONLY when custom build is enabled.
+// This method will be called ONLY when gradle build is enabled.
Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key) {
CustomExportData *export_data = static_cast<CustomExportData *>(p_userdata);
String dst_path = p_path.replace_first("res://", export_data->assets_directory + "/");
@@ -254,13 +254,11 @@ String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_screen_sizes;
}
-String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) {
+String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_vulkan) {
String manifest_xr_features;
int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
if (uses_xr) {
- manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vr.headtracking\" android:required=\"true\" android:version=\"1\" />\n";
-
int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required
if (hand_tracking_index == XR_HAND_TRACKING_OPTIONAL) {
manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"oculus.software.handtracking\" android:required=\"false\" />\n";
@@ -275,27 +273,46 @@ String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) {
manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"com.oculus.feature.PASSTHROUGH\" android:required=\"true\" />\n";
}
}
+
+ if (p_uses_vulkan) {
+ manifest_xr_features += " <uses-feature tools:node=\"replace\" android:name=\"android.hardware.vulkan.level\" android:required=\"true\" android:version=\"1\" />\n";
+ }
return manifest_xr_features;
}
-String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
- int xr_mode_index = (int)(p_preset->get("xr_features/xr_mode"));
- bool uses_xr = xr_mode_index == XR_MODE_OPENXR;
+String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr) {
String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))));
String manifest_activity_text = vformat(
" <activity android:name=\"com.godot.game.GodotApp\" "
"tools:replace=\"android:screenOrientation,android:excludeFromRecents,android:resizeableActivity\" "
+ "tools:node=\"mergeOnlyAttributes\" "
"android:excludeFromRecents=\"%s\" "
"android:screenOrientation=\"%s\" "
"android:resizeableActivity=\"%s\">\n",
bool_to_string(p_preset->get("package/exclude_from_recents")),
orientation,
bool_to_string(bool(GLOBAL_GET("display/window/size/resizable"))));
- if (uses_xr) {
- manifest_activity_text += " <meta-data tools:node=\"replace\" android:name=\"com.oculus.vr.focusaware\" android:value=\"true\" />\n";
+
+ if (p_uses_xr) {
+ manifest_activity_text += " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\" />\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\" />\n"
+ "\n"
+ " <!-- Enable access to OpenXR on Oculus mobile devices, no-op on other Android\n"
+ " platforms. -->\n"
+ " <category android:name=\"com.oculus.intent.category.VR\" />\n"
+ "\n"
+ " <!-- OpenXR category tag to indicate the activity starts in an immersive OpenXR mode. \n"
+ " See https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#android-runtime-category. -->\n"
+ " <category android:name=\"org.khronos.openxr.intent.category.IMMERSIVE_HMD\" />\n"
+ " </intent-filter>\n";
} else {
- manifest_activity_text += " <meta-data tools:node=\"remove\" android:name=\"com.oculus.vr.focusaware\" />\n";
+ manifest_activity_text += " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\" />\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\" />\n"
+ " </intent-filter>\n";
}
+
manifest_activity_text += " </activity>\n";
return manifest_activity_text;
}
@@ -316,9 +333,7 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
" android:hasFragileUserData=\"%s\"\n"
" android:requestLegacyExternalStorage=\"%s\"\n"
" tools:replace=\"android:allowBackup,android:appCategory,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n"
- " tools:ignore=\"GoogleAppIndexingWarning\">\n\n"
- " <meta-data tools:node=\"remove\" android:name=\"xr_hand_tracking_version_name\" />\n"
- " <meta-data tools:node=\"remove\" android:name=\"xr_hand_tracking_metadata_name\" />\n",
+ " tools:ignore=\"GoogleAppIndexingWarning\">\n\n",
bool_to_string(p_preset->get("user_data_backup/allow")),
_get_app_category_label(app_category_index),
bool_to_string(is_game),
@@ -335,10 +350,8 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
hand_tracking_frequency);
manifest_application_text += " <meta-data tools:node=\"replace\" android:name=\"com.oculus.handtracking.version\" android:value=\"V2.0\" />\n";
}
- } else {
- manifest_application_text += " <meta-data tools:node=\"remove\" android:name=\"com.oculus.supportedDevices\" />\n";
}
- manifest_application_text += _get_activity_tag(p_preset);
+ manifest_application_text += _get_activity_tag(p_preset, uses_xr);
manifest_application_text += " </application>\n";
return manifest_application_text;
}
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index 0fa857cb75..8a885a0d12 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -104,7 +104,7 @@ Error store_string_at_path(const String &p_path, const String &p_data);
// This method will only be called as an input to export_project_files.
// It is used by the export_project_files method to save all the asset files into the gradle project.
// It's functionality mirrors that of the method save_apk_file.
-// This method will be called ONLY when custom build is enabled.
+// This method will be called ONLY when gradle build is enabled.
Error rename_and_store_file_in_gradle_project(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
// Creates strings.xml files inside the gradle project for different locales.
@@ -116,9 +116,9 @@ String _get_gles_tag();
String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset);
-String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset);
+String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_vulkan);
-String _get_activity_tag(const Ref<EditorExportPreset> &p_preset);
+String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr);
String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission);
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index 5df05580a5..1249f2219f 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -169,6 +169,10 @@ bool FileAccessAndroid::file_exists(const String &p_path) {
return true;
}
+void FileAccessAndroid::close() {
+ _close();
+}
+
FileAccessAndroid::~FileAccessAndroid() {
_close();
}
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index 1d25a28d90..b8f45628e5 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -78,6 +78,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+ virtual void close() override;
+
~FileAccessAndroid();
};
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index 7174d57344..ea8459d1ed 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -333,6 +333,12 @@ void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) {
_file_last_modified = env->GetMethodID(cls, "fileLastModified", "(Ljava/lang/String;)J");
}
+void FileAccessFilesystemJAndroid::close() {
+ if (is_open()) {
+ _close();
+ }
+}
+
FileAccessFilesystemJAndroid::FileAccessFilesystemJAndroid() {
id = 0;
}
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 7829ab7cf9..5e74d9de24 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -93,6 +93,8 @@ public:
virtual uint32_t _get_unix_permissions(const String &p_file) override { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override { return FAILED; }
+ virtual void close() override;
+
FileAccessFilesystemJAndroid();
~FileAccessFilesystemJAndroid();
};
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 8c8608cbbb..ce4a2ecfe4 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -31,29 +31,6 @@
android:name="org.godotengine.editor.version"
android:value="${godotEditorVersion}" />
- <!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. -->
- <!-- Do these changes in the export preset. Adding new ones is fine. -->
-
- <!-- XR hand tracking metadata -->
- <!-- This is modified by the exporter based on the selected xr mode. DO NOT CHANGE the values here. -->
- <!-- Removed at export time if the xr mode is not VR or hand tracking is disabled. -->
- <meta-data
- android:name="xr_hand_tracking_metadata_name"
- android:value="xr_hand_tracking_metadata_value"/>
-
- <!-- XR hand tracking version -->
- <!-- This is modified by the exporter based on the selected xr mode. DO NOT CHANGE the values here. -->
- <!-- Removed at export time if the xr mode is not VR or hand tracking is disabled. -->
- <meta-data
- android:name="xr_hand_tracking_version_name"
- android:value="xr_hand_tracking_version_value"/>
-
- <!-- Supported Meta devices -->
- <!-- This is removed by the exporter if the xr mode is not VR. -->
- <meta-data
- android:name="com.oculus.supportedDevices"
- android:value="all" />
-
<activity
android:name=".GodotApp"
android:label="@string/godot_project_name_string"
@@ -66,16 +43,9 @@
android:resizeableActivity="false"
tools:ignore="UnusedAttribute" >
- <!-- Focus awareness metadata is removed at export time if the xr mode is not VR. -->
- <meta-data android:name="com.oculus.vr.focusaware" android:value="true" />
-
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
-
- <!-- Enable access to OpenXR on Oculus mobile devices, no-op on other Android
- platforms. -->
- <category android:name="com.oculus.intent.category.VR" />
</intent-filter>
</activity>
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
index 63b10e62b1..01b148aeef 100644
--- a/platform/android/java/app/build.gradle
+++ b/platform/android/java/app/build.gradle
@@ -50,7 +50,7 @@ dependencies {
} else if (rootProject.findProject(":godot:lib")) {
implementation project(":godot:lib")
} else {
- // Custom build mode. In this scenario this project is the only one around and the Godot
+ // Godot gradle build mode. In this scenario this project is the only one around and the Godot
// library is available through the pre-generated godot-lib.*.aar android archive files.
debugImplementation fileTree(dir: 'libs/debug', include: ['*.jar', '*.aar'])
devImplementation fileTree(dir: 'libs/dev', include: ['*.jar', '*.aar'])
@@ -153,7 +153,7 @@ android {
debug {
// Signing and zip-aligning are skipped for prebuilt builds, but
- // performed for custom builds.
+ // performed for Godot gradle builds.
zipAlignEnabled shouldZipAlign()
if (shouldSign()) {
signingConfig signingConfigs.debug
@@ -165,7 +165,7 @@ android {
dev {
initWith debug
// Signing and zip-aligning are skipped for prebuilt builds, but
- // performed for custom builds.
+ // performed for Godot gradle builds.
zipAlignEnabled shouldZipAlign()
if (shouldSign()) {
signingConfig signingConfigs.debug
@@ -176,7 +176,7 @@ android {
release {
// Signing and zip-aligning are skipped for prebuilt builds, but
- // performed for custom builds.
+ // performed for Godot gradle builds.
zipAlignEnabled shouldZipAlign()
if (shouldSign()) {
signingConfig signingConfigs.release
diff --git a/platform/android/java/app/gradle.properties b/platform/android/java/app/gradle.properties
index 0ad8e611ca..d9f79b6818 100644
--- a/platform/android/java/app/gradle.properties
+++ b/platform/android/java/app/gradle.properties
@@ -1,5 +1,5 @@
-# Godot custom build Gradle settings.
-# These properties apply when running custom build from the Godot editor.
+# Godot gradle build settings.
+# These properties apply when running a gradle build from the Godot editor.
# NOTE: This should be kept in sync with 'godot/platform/android/java/gradle.properties' except
# where otherwise specified.
diff --git a/platform/android/java/app/settings.gradle b/platform/android/java/app/settings.gradle
index ba53aefe7f..b4524a3f60 100644
--- a/platform/android/java/app/settings.gradle
+++ b/platform/android/java/app/settings.gradle
@@ -1,4 +1,4 @@
-// This is the root directory of the Godot custom build.
+// This is the root directory of the Godot Android gradle build.
pluginManagement {
apply from: 'config.gradle'
diff --git a/platform/android/java/app/src/com/godot/game/GodotApp.java b/platform/android/java/app/src/com/godot/game/GodotApp.java
index a43e289b6b..1d2cc05715 100644
--- a/platform/android/java/app/src/com/godot/game/GodotApp.java
+++ b/platform/android/java/app/src/com/godot/game/GodotApp.java
@@ -35,7 +35,7 @@ import org.godotengine.godot.FullScreenGodotApp;
import android.os.Bundle;
/**
- * Template activity for Godot Android custom builds.
+ * Template activity for Godot Android builds.
* Feel free to extend and modify this class for your custom logic.
*/
public class GodotApp extends FullScreenGodotApp {
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index 5a91e5ce32..cffe0a33d9 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -152,14 +152,14 @@ task copyReleaseAARToBin(type: Copy) {
}
/**
- * Generate Godot custom build template by zipping the source files from the app directory, as well
+ * Generate Godot gradle build template by zipping the source files from the app directory, as well
* as the AAR files generated by 'copyDebugAAR', 'copyDevAAR' and 'copyReleaseAAR'.
- * The zip file also includes some gradle tools to allow building of the custom build.
+ * The zip file also includes some gradle tools to enable gradle builds from the Godot Editor.
*/
-task zipCustomBuild(type: Zip) {
+task zipGradleBuild(type: Zip) {
onlyIf { generateGodotTemplates.state.executed || generateDevTemplate.state.executed }
doFirst {
- logger.lifecycle("Generating Godot custom build template")
+ logger.lifecycle("Generating Godot gradle build template")
}
from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradlew', 'gradlew.bat', 'gradle/**']))
include '**/*'
@@ -195,7 +195,7 @@ def templateBuildTasks() {
&& targetLibs.listFiles() != null
&& targetLibs.listFiles().length > 0) {
String capitalizedTarget = target.capitalize()
- // Copy the generated aar library files to the custom build directory.
+ // Copy the generated aar library files to the build directory.
tasks += "copy" + capitalizedTarget + "AARToAppModule"
// Copy the generated aar library files to the bin directory.
tasks += "copy" + capitalizedTarget + "AARToBin"
@@ -260,7 +260,7 @@ task generateGodotTemplates {
gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
dependsOn = templateBuildTasks()
- finalizedBy 'zipCustomBuild'
+ finalizedBy 'zipGradleBuild'
}
/**
@@ -273,7 +273,7 @@ task generateDevTemplate {
gradle.startParameter.excludedTaskNames += templateExcludedBuildTask()
dependsOn = templateBuildTasks()
- finalizedBy 'zipCustomBuild'
+ finalizedBy 'zipGradleBuild'
}
task clean(type: Delete) {
diff --git a/platform/android/java/editor/src/main/res/values/dimens.xml b/platform/android/java/editor/src/main/res/values/dimens.xml
index 03fb6184d2..98bfe40179 100644
--- a/platform/android/java/editor/src/main/res/values/dimens.xml
+++ b/platform/android/java/editor/src/main/res/values/dimens.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="editor_default_window_height">600dp</dimen>
- <dimen name="editor_default_window_width">800dp</dimen>
+ <dimen name="editor_default_window_width">1024dp</dimen>
</resources>
diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties
index 5cd94e85d9..39a0dcda16 100644
--- a/platform/android/java/gradle.properties
+++ b/platform/android/java/gradle.properties
@@ -24,5 +24,5 @@ org.gradle.jvmargs=-Xmx4536m
org.gradle.warning.mode=all
# Disable resource optimizations for template release build.
-# NOTE: This is turned on for custom build in order to improve the release build.
+# NOTE: This is turned on for Godot Editor's gradle builds in order to improve the release build.
android.enableResourceOptimizations=false
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
index 1f77e2fc34..f03a1dd47a 100644
--- a/platform/android/java/lib/AndroidManifest.xml
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -20,6 +20,16 @@
android:exported="false"
/>
+ <provider
+ android:name="androidx.core.content.FileProvider"
+ android:authorities="${applicationId}.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/godot_provider_paths" />
+ </provider>
+
</application>
</manifest>
diff --git a/platform/android/java/lib/res/values/strings.xml b/platform/android/java/lib/res/values/strings.xml
index 7efac4ce71..03752e092e 100644
--- a/platform/android/java/lib/res/values/strings.xml
+++ b/platform/android/java/lib/res/values/strings.xml
@@ -14,6 +14,7 @@
<string name="text_button_cancel_verify">Cancel Verification</string>
<string name="text_error_title">Error!</string>
<string name="error_engine_setup_message">Unable to setup the Godot Engine! Aborting…</string>
+ <string name="error_missing_vulkan_requirements_message">Warning - this device does not meet the requirements for Vulkan support</string>
<!-- APK Expansion Strings -->
diff --git a/platform/android/java/lib/res/xml/godot_provider_paths.xml b/platform/android/java/lib/res/xml/godot_provider_paths.xml
new file mode 100644
index 0000000000..1255f576bf
--- /dev/null
+++ b/platform/android/java/lib/res/xml/godot_provider_paths.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <external-path
+ name="public"
+ path="." />
+
+ <external-files-path
+ name="app"
+ path="." />
+</paths>
diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
index 65032d6a68..677c9d8f13 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
@@ -99,7 +99,7 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God
// from scratch. Therefore, we need to kill the whole app process and relaunch it.
//
// Restarting only the activity, wouldn't be enough unless it did proper cleanup (including
- // releasing and reloading native libs or resetting their state somehow and clearing statics).
+ // releasing and reloading native libs or resetting their state somehow and clearing static data).
Log.v(TAG, "Restarting Godot instance...");
ProcessPhoenix.triggerRebirth(FullScreenGodotApp.this);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index 50263bc392..a03da7292b 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -83,6 +83,7 @@ import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.annotation.CallSuper;
import androidx.annotation.Keep;
@@ -258,13 +259,13 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
*/
@Keep
private boolean onVideoInit() {
- final Activity activity = getActivity();
+ final Activity activity = requireActivity();
containerLayout = new FrameLayout(activity);
containerLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
// GodotEditText layout
GodotEditText editText = new GodotEditText(activity);
- editText.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
+ editText.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
(int)getResources().getDimension(R.dimen.text_edit_height)));
// ...add to FrameLayout
containerLayout.addView(editText);
@@ -275,11 +276,14 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
return false;
}
- final String renderer = GodotLib.getGlobal("rendering/renderer/rendering_method");
- if (renderer.equals("gl_compatibility")) {
- mRenderView = new GodotGLRenderView(activity, this, xrMode, use_debug_opengl);
- } else {
+ if (usesVulkan()) {
+ if (!meetsVulkanRequirements(activity.getPackageManager())) {
+ Log.w(TAG, "Missing requirements for vulkan support!");
+ }
mRenderView = new GodotVulkanRenderView(activity, this);
+ } else {
+ // Fallback to openGl
+ mRenderView = new GodotGLRenderView(activity, this, xrMode, use_debug_opengl);
}
View view = mRenderView.getView();
@@ -317,6 +321,26 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
return true;
}
+ /**
+ * Returns true if `Vulkan` is used for rendering.
+ */
+ private boolean usesVulkan() {
+ final String renderer = GodotLib.getGlobal("rendering/renderer/rendering_method");
+ final String renderingDevice = GodotLib.getGlobal("rendering/rendering_device/driver");
+ return ("forward_plus".equals(renderer) || "mobile".equals(renderer)) && "vulkan".equals(renderingDevice);
+ }
+
+ /**
+ * Returns true if the device meets the base requirements for Vulkan support, false otherwise.
+ */
+ private boolean meetsVulkanRequirements(@Nullable PackageManager packageManager) {
+ if (packageManager == null) {
+ return false;
+ }
+
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL, 1);
+ }
+
public void setKeepScreenOn(final boolean p_enabled) {
runOnUiThread(() -> {
if (p_enabled) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index 41d06a6458..edcd9c4d1f 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -49,6 +49,9 @@ import android.view.Display;
import android.view.DisplayCutout;
import android.view.WindowInsets;
+import androidx.core.content.FileProvider;
+
+import java.io.File;
import java.util.List;
import java.util.Locale;
@@ -84,29 +87,42 @@ public class GodotIO {
// MISCELLANEOUS OS IO
/////////////////////////
- public int openURI(String p_uri) {
+ public int openURI(String uriString) {
try {
- String path = p_uri;
- String type = "";
- if (path.startsWith("/")) {
- //absolute path to filesystem, prepend file://
- path = "file://" + path;
- if (p_uri.endsWith(".png") || p_uri.endsWith(".jpg") || p_uri.endsWith(".gif") || p_uri.endsWith(".webp")) {
- type = "image/*";
+ Uri dataUri;
+ String dataType = "";
+ boolean grantReadUriPermission = false;
+
+ if (uriString.startsWith("/") || uriString.startsWith("file://")) {
+ String filePath = uriString;
+ // File uris needs to be provided via the FileProvider
+ grantReadUriPermission = true;
+ if (filePath.startsWith("file://")) {
+ filePath = filePath.replace("file://", "");
}
+
+ File targetFile = new File(filePath);
+ dataUri = FileProvider.getUriForFile(activity, activity.getPackageName() + ".fileprovider", targetFile);
+ dataType = activity.getContentResolver().getType(dataUri);
+ } else {
+ dataUri = Uri.parse(uriString);
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
- if (!type.equals("")) {
- intent.setDataAndType(Uri.parse(path), type);
+ if (TextUtils.isEmpty(dataType)) {
+ intent.setData(dataUri);
} else {
- intent.setData(Uri.parse(path));
+ intent.setDataAndType(dataUri, dataType);
+ }
+ if (grantReadUriPermission) {
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
activity.startActivity(intent);
return 0;
} catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Unable to open uri " + uriString, e);
return 1;
}
}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 1ee1cccb82..e7abe580f1 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -488,7 +488,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_calldeferred(JNIEnv *
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result) {
String permission = jstring_to_string(p_permission, env);
if (permission == "android.permission.RECORD_AUDIO" && p_result) {
- AudioDriver::get_singleton()->capture_start();
+ AudioDriver::get_singleton()->input_start();
}
if (os_android->get_main_loop()) {
diff --git a/platform/ios/SCsub b/platform/ios/SCsub
index f3925c146f..18ba6617af 100644
--- a/platform/ios/SCsub
+++ b/platform/ios/SCsub
@@ -17,7 +17,6 @@ ios_lib = [
"display_layer.mm",
"godot_app_delegate.m",
"godot_view_renderer.mm",
- "godot_view_gesture_recognizer.mm",
"device_metrics.m",
"keyboard_input_view.mm",
"key_mapping_ios.mm",
diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp
index 87b599bc81..c6f7ec09b1 100644
--- a/platform/ios/export/export_plugin.cpp
+++ b/platform/ios/export/export_plugin.cpp
@@ -43,6 +43,7 @@
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
// Vulkan and OpenGL ES 3.0 both mandate ETC2 support.
r_features->push_back("etc2");
+ r_features->push_back("astc");
Vector<String> architectures = _get_preset_architectures(p_preset);
for (int i = 0; i < architectures.size(); ++i) {
diff --git a/platform/ios/godot_view.h b/platform/ios/godot_view.h
index 077584baa6..b00ca37ebe 100644
--- a/platform/ios/godot_view.h
+++ b/platform/ios/godot_view.h
@@ -59,9 +59,4 @@ class String;
- (void)stopRendering;
- (void)startRendering;
-- (void)godotTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
-- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
-
@end
diff --git a/platform/ios/godot_view.mm b/platform/ios/godot_view.mm
index 4b10f95ab8..fafec79bf6 100644
--- a/platform/ios/godot_view.mm
+++ b/platform/ios/godot_view.mm
@@ -35,7 +35,6 @@
#include "core/string/ustring.h"
#import "display_layer.h"
#include "display_server_ios.h"
-#import "godot_view_gesture_recognizer.h"
#import "godot_view_renderer.h"
#import <CoreMotion/CoreMotion.h>
@@ -60,8 +59,6 @@ static const float earth_gravity = 9.80665;
@property(strong, nonatomic) CMMotionManager *motionManager;
-@property(strong, nonatomic) GodotViewGestureRecognizer *delayGestureRecognizer;
-
@end
@implementation GodotView
@@ -148,10 +145,6 @@ static const float earth_gravity = 9.80665;
[self.animationTimer invalidate];
self.animationTimer = nil;
}
-
- if (self.delayGestureRecognizer) {
- self.delayGestureRecognizer = nil;
- }
}
- (void)godot_commonInit {
@@ -171,11 +164,6 @@ static const float earth_gravity = 9.80665;
self.motionManager = nil;
}
}
-
- // Initialize delay gesture recognizer
- GodotViewGestureRecognizer *gestureRecognizer = [[GodotViewGestureRecognizer alloc] init];
- self.delayGestureRecognizer = gestureRecognizer;
- [self addGestureRecognizer:self.delayGestureRecognizer];
}
- (void)stopRendering {
@@ -347,58 +335,42 @@ static const float earth_gravity = 9.80665;
}
}
-- (void)godotTouchesBegan:(NSSet *)touchesSet withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touchesSet containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
- }
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ CGPoint touchPoint = [touch locationInView:self];
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, true, touch.tapCount > 1);
}
}
-- (void)godotTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- CGPoint touchPoint = [touch locationInView:self];
- CGPoint prev_point = [touch previousLocationInView:self];
- CGFloat alt = [touch altitudeAngle];
- CGVector azim = [touch azimuthUnitVectorInView:self];
- DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt));
- }
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ CGPoint touchPoint = [touch locationInView:self];
+ CGPoint prev_point = [touch previousLocationInView:self];
+ CGFloat alt = [touch altitudeAngle];
+ CGVector azim = [touch azimuthUnitVectorInView:self];
+ DisplayServerIOS::get_singleton()->touch_drag(tid, prev_point.x * self.contentScaleFactor, prev_point.y * self.contentScaleFactor, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, [touch force] / [touch maximumPossibleForce], Vector2(azim.dx, azim.dy) * Math::cos(alt));
}
}
-- (void)godotTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- [self removeTouch:touch];
- CGPoint touchPoint = [touch locationInView:self];
- DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
- }
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ [self removeTouch:touch];
+ CGPoint touchPoint = [touch locationInView:self];
+ DisplayServerIOS::get_singleton()->touch_press(tid, touchPoint.x * self.contentScaleFactor, touchPoint.y * self.contentScaleFactor, false, false);
}
}
-- (void)godotTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
- NSArray *tlist = [event.allTouches allObjects];
- for (unsigned int i = 0; i < [tlist count]; i++) {
- if ([touches containsObject:[tlist objectAtIndex:i]]) {
- UITouch *touch = [tlist objectAtIndex:i];
- int tid = [self getTouchIDForTouch:touch];
- ERR_FAIL_COND(tid == -1);
- DisplayServerIOS::get_singleton()->touches_canceled(tid);
- }
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+ for (UITouch *touch in touches) {
+ int tid = [self getTouchIDForTouch:touch];
+ ERR_FAIL_COND(tid == -1);
+ DisplayServerIOS::get_singleton()->touches_canceled(tid);
}
[self clearTouches];
}
diff --git a/platform/ios/godot_view_gesture_recognizer.h b/platform/ios/godot_view_gesture_recognizer.h
deleted file mode 100644
index 57bfc75568..0000000000
--- a/platform/ios/godot_view_gesture_recognizer.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/**************************************************************************/
-/* godot_view_gesture_recognizer.h */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-// GLViewGestureRecognizer allows iOS gestures to work correctly by
-// emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer.
-// It catches all gestures incoming to UIView and delays them for 150ms
-// (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer)
-// If touch cancellation or end message is fired it fires delayed
-// begin touch immediately as well as last touch signal
-
-#import <UIKit/UIKit.h>
-
-@interface GodotViewGestureRecognizer : UIGestureRecognizer
-
-@property(nonatomic, readonly, assign) NSTimeInterval delayTimeInterval;
-
-- (instancetype)init;
-
-@end
diff --git a/platform/ios/godot_view_gesture_recognizer.mm b/platform/ios/godot_view_gesture_recognizer.mm
deleted file mode 100644
index 9b71228864..0000000000
--- a/platform/ios/godot_view_gesture_recognizer.mm
+++ /dev/null
@@ -1,186 +0,0 @@
-/**************************************************************************/
-/* godot_view_gesture_recognizer.mm */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#import "godot_view_gesture_recognizer.h"
-
-#import "godot_view.h"
-
-#include "core/config/project_settings.h"
-
-// Minimum distance for touches to move to fire
-// a delay timer before scheduled time.
-// Should be the low enough to not cause issues with dragging
-// but big enough to allow click to work.
-const CGFloat kGLGestureMovementDistance = 0.5;
-
-@interface GodotViewGestureRecognizer ()
-
-@property(nonatomic, readwrite, assign) NSTimeInterval delayTimeInterval;
-
-@end
-
-@interface GodotViewGestureRecognizer ()
-
-// Timer used to delay begin touch message.
-// Should work as simple emulation of UIDelayedAction
-@property(strong, nonatomic) NSTimer *delayTimer;
-
-// Delayed touch parameters
-@property(strong, nonatomic) NSSet *delayedTouches;
-@property(strong, nonatomic) UIEvent *delayedEvent;
-
-@end
-
-@implementation GodotViewGestureRecognizer
-
-- (GodotView *)godotView {
- return (GodotView *)self.view;
-}
-
-- (instancetype)init {
- self = [super init];
-
- self.cancelsTouchesInView = YES;
- self.delaysTouchesBegan = YES;
- self.delaysTouchesEnded = YES;
- self.requiresExclusiveTouchType = NO;
-
- self.delayTimeInterval = GLOBAL_GET("input_devices/pointing/ios/touch_delay");
-
- return self;
-}
-
-- (void)dealloc {
- if (self.delayTimer) {
- [self.delayTimer invalidate];
- self.delayTimer = nil;
- }
-
- if (self.delayedTouches) {
- self.delayedTouches = nil;
- }
-
- if (self.delayedEvent) {
- self.delayedEvent = nil;
- }
-}
-
-- (void)delayTouches:(NSSet *)touches andEvent:(UIEvent *)event {
- [self.delayTimer fire];
-
- self.delayedTouches = touches;
- self.delayedEvent = event;
-
- self.delayTimer = [NSTimer
- scheduledTimerWithTimeInterval:self.delayTimeInterval
- target:self
- selector:@selector(fireDelayedTouches:)
- userInfo:nil
- repeats:NO];
-}
-
-- (void)fireDelayedTouches:(id)timer {
- [self.delayTimer invalidate];
- self.delayTimer = nil;
-
- if (self.delayedTouches) {
- [self.godotView godotTouchesBegan:self.delayedTouches withEvent:self.delayedEvent];
- }
-
- self.delayedTouches = nil;
- self.delayedEvent = nil;
-}
-
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseBegan];
- [self delayTouches:cleared andEvent:event];
-
- [super touchesBegan:touches withEvent:event];
-}
-
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseMoved];
-
- if (self.delayTimer) {
- // We should check if movement was significant enough to fire an event
- // for dragging to work correctly.
- for (UITouch *touch in cleared) {
- CGPoint from = [touch locationInView:self.godotView];
- CGPoint to = [touch previousLocationInView:self.godotView];
- CGFloat xDistance = from.x - to.x;
- CGFloat yDistance = from.y - to.y;
-
- CGFloat distance = sqrt(xDistance * xDistance + yDistance * yDistance);
-
- // Early exit, since one of touches has moved enough to fire a drag event.
- if (distance > kGLGestureMovementDistance) {
- [self.delayTimer fire];
- [self.godotView godotTouchesMoved:cleared withEvent:event];
- return;
- }
- }
-
- return;
- }
-
- [self.godotView godotTouchesMoved:cleared withEvent:event];
-
- [super touchesMoved:touches withEvent:event];
-}
-
-- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
- [self.delayTimer fire];
-
- NSSet *cleared = [self copyClearedTouches:touches phase:UITouchPhaseEnded];
- [self.godotView godotTouchesEnded:cleared withEvent:event];
-
- [super touchesEnded:touches withEvent:event];
-}
-
-- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
- [self.delayTimer fire];
- [self.godotView godotTouchesCancelled:touches withEvent:event];
-
- [super touchesCancelled:touches withEvent:event];
-}
-
-- (NSSet *)copyClearedTouches:(NSSet *)touches phase:(UITouchPhase)phaseToSave {
- NSMutableSet *cleared = [touches mutableCopy];
-
- for (UITouch *touch in touches) {
- if (touch.view != self.view || touch.phase != phaseToSave) {
- [cleared removeObject:touch];
- }
- }
-
- return cleared;
-}
-
-@end
diff --git a/platform/ios/joypad_ios.mm b/platform/ios/joypad_ios.mm
index 057f439b81..9194b09ef6 100644
--- a/platform/ios/joypad_ios.mm
+++ b/platform/ios/joypad_ios.mm
@@ -305,6 +305,25 @@ void JoypadIOS::start_processing() {
float value = gamepad.rightTrigger.value;
Input::get_singleton()->joy_axis(joy_id, JoyAxis::TRIGGER_RIGHT, value);
}
+
+ if (@available(iOS 13, *)) {
+ // iOS uses 'buttonOptions' and 'buttonMenu' names for BACK and START joy buttons.
+ if (element == gamepad.buttonOptions) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::BACK,
+ gamepad.buttonOptions.isPressed);
+ } else if (element == gamepad.buttonMenu) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::START,
+ gamepad.buttonMenu.isPressed);
+ }
+ }
+
+ if (@available(iOS 14, *)) {
+ // iOS uses 'buttonHome' for the GUIDE joy button.
+ if (element == gamepad.buttonHome) {
+ Input::get_singleton()->joy_button(joy_id, JoyButton::GUIDE,
+ gamepad.buttonHome.isPressed);
+ }
+ }
};
} else if (controller.microGamepad != nil) {
// micro gamepads were added in OS 9 and feature just 2 buttons and a d-pad
diff --git a/platform/linuxbsd/SCsub b/platform/linuxbsd/SCsub
index 3c5dc78c60..4dd74ff9d0 100644
--- a/platform/linuxbsd/SCsub
+++ b/platform/linuxbsd/SCsub
@@ -11,23 +11,30 @@ common_linuxbsd = [
"joypad_linux.cpp",
"freedesktop_portal_desktop.cpp",
"freedesktop_screensaver.cpp",
- "xkbcommon-so_wrap.c",
]
+if env["use_sowrap"]:
+ common_linuxbsd.append("xkbcommon-so_wrap.c")
+
if env["x11"]:
common_linuxbsd += SConscript("x11/SCsub")
if env["speechd"]:
- common_linuxbsd.append(["speechd-so_wrap.c", "tts_linux.cpp"])
+ common_linuxbsd.append("tts_linux.cpp")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("speechd-so_wrap.c")
if env["fontconfig"]:
- common_linuxbsd.append("fontconfig-so_wrap.c")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("fontconfig-so_wrap.c")
if env["udev"]:
- common_linuxbsd.append("libudev-so_wrap.c")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("libudev-so_wrap.c")
if env["dbus"]:
- common_linuxbsd.append("dbus-so_wrap.c")
+ if env["use_sowrap"]:
+ common_linuxbsd.append("dbus-so_wrap.c")
prog = env.add_program("#bin/godot", ["godot_linuxbsd.cpp"] + common_linuxbsd)
diff --git a/platform/linuxbsd/dbus-so_wrap.c b/platform/linuxbsd/dbus-so_wrap.c
index d03a9166a3..4aec9dc48f 100644
--- a/platform/linuxbsd/dbus-so_wrap.c
+++ b/platform/linuxbsd/dbus-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:26:35
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/dbus/dbus.h --sys-include "thirdparty/linuxbsd_headers/dbus/dbus.h" --soname libdbus-1.so.3 --init-name dbus --output-header ./platform/linuxbsd/dbus-so_wrap.h --output-implementation ./platform/linuxbsd/dbus-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:26:35
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/dbus/dbus.h --sys-include "thirdparty/linuxbsd_headers/dbus/dbus.h" --soname libdbus-1.so.3 --init-name dbus --output-header ./platform/linuxbsd/dbus-so_wrap.h --output-implementation ./platform/linuxbsd/dbus-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/dbus-so_wrap.h b/platform/linuxbsd/dbus-so_wrap.h
index 6981912a12..2c63757932 100644
--- a/platform/linuxbsd/dbus-so_wrap.h
+++ b/platform/linuxbsd/dbus-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_DBUS
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:26:35
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/dbus/dbus.h --sys-include "thirdparty/linuxbsd_headers/dbus/dbus.h" --soname libdbus-1.so.3 --init-name dbus --output-header ./platform/linuxbsd/dbus-so_wrap.h --output-implementation ./platform/linuxbsd/dbus-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:26:35
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/dbus/dbus.h --sys-include "thirdparty/linuxbsd_headers/dbus/dbus.h" --soname libdbus-1.so.3 --init-name dbus --output-header ./platform/linuxbsd/dbus-so_wrap.h --output-implementation ./platform/linuxbsd/dbus-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 36e149f2b4..3f713d2db3 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -43,6 +43,7 @@ def get_opts():
BoolVariable("use_lsan", "Use LLVM/GCC compiler leak sanitizer (LSAN)", False),
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
BoolVariable("use_msan", "Use LLVM compiler memory sanitizer (MSAN)", False),
+ BoolVariable("use_sowrap", "Dynamically load system libraries", True),
BoolVariable("alsa", "Use ALSA", True),
BoolVariable("pulseaudio", "Use PulseAudio", True),
BoolVariable("dbus", "Use D-Bus to handle screensaver and portal desktop settings", True),
@@ -184,25 +185,30 @@ def configure(env: "Environment"):
## Dependencies
+ if env["use_sowrap"]:
+ env.Append(CPPDEFINES=["SOWRAP_ENABLED"])
+
if env["touch"]:
env.Append(CPPDEFINES=["TOUCH_ENABLED"])
# FIXME: Check for existence of the libs before parsing their flags with pkg-config
# freetype depends on libpng and zlib, so bundling one of them while keeping others
- # as shared libraries leads to weird issues
- if (
- env["builtin_freetype"]
- or env["builtin_libpng"]
- or env["builtin_zlib"]
- or env["builtin_graphite"]
- or env["builtin_harfbuzz"]
- ):
- env["builtin_freetype"] = True
- env["builtin_libpng"] = True
- env["builtin_zlib"] = True
- env["builtin_graphite"] = True
- env["builtin_harfbuzz"] = True
+ # as shared libraries leads to weird issues. And graphite and harfbuzz need freetype.
+ ft_linked_deps = [
+ env["builtin_freetype"],
+ env["builtin_libpng"],
+ env["builtin_zlib"],
+ env["builtin_graphite"],
+ env["builtin_harfbuzz"],
+ ]
+ if (not all(ft_linked_deps)) and any(ft_linked_deps): # All or nothing.
+ print(
+ "These libraries should be either all builtin, or all system provided:\n"
+ "freetype, libpng, zlib, graphite, harfbuzz.\n"
+ "Please specify `builtin_<name>=no` for all of them, or none."
+ )
+ sys.exit()
if not env["builtin_freetype"]:
env.ParseConfig("pkg-config freetype2 --cflags --libs")
@@ -210,8 +216,8 @@ def configure(env: "Environment"):
if not env["builtin_graphite"]:
env.ParseConfig("pkg-config graphite2 --cflags --libs")
- if not env["builtin_icu"]:
- env.ParseConfig("pkg-config icu-uc --cflags --libs")
+ if not env["builtin_icu4c"]:
+ env.ParseConfig("pkg-config icu-i18n icu-uc --cflags --libs")
if not env["builtin_harfbuzz"]:
env.ParseConfig("pkg-config harfbuzz harfbuzz-icu --cflags --libs")
@@ -266,31 +272,93 @@ def configure(env: "Environment"):
if not env["builtin_pcre2"]:
env.ParseConfig("pkg-config libpcre2-32 --cflags --libs")
+ if not env["builtin_recastnavigation"]:
+ # No pkgconfig file so far, hardcode default paths.
+ env.Prepend(CPPPATH=["/usr/include/recastnavigation"])
+ env.Append(LIBS=["Recast"])
+
if not env["builtin_embree"]:
# No pkgconfig file so far, hardcode expected lib name.
env.Append(LIBS=["embree3"])
## Flags
-
if env["fontconfig"]:
- env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists fontconfig") == 0: # 0 means found
+ env.ParseConfig("pkg-config fontconfig --cflags --libs")
+ env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
+ else:
+ print("Warning: fontconfig development libraries not found. Disabling the system fonts support.")
+ env["fontconfig"] = False
+ else:
+ env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
if env["alsa"]:
- env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists alsa") == 0: # 0 means found
+ env.ParseConfig("pkg-config alsa --cflags --libs")
+ env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
+ else:
+ print("Warning: ALSA development libraries not found. Disabling the ALSA audio driver.")
+ env["alsa"] = False
+ else:
+ env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
if env["pulseaudio"]:
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists libpulse") == 0: # 0 means found
+ env.ParseConfig("pkg-config libpulse --cflags --libs")
+ env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"])
+ else:
+ print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.")
+ env["pulseaudio"] = False
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"])
if env["dbus"]:
- env.Append(CPPDEFINES=["DBUS_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists dbus-1") == 0: # 0 means found
+ env.ParseConfig("pkg-config dbus-1 --cflags --libs")
+ env.Append(CPPDEFINES=["DBUS_ENABLED"])
+ else:
+ print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.")
+ env["dbus"] = False
+ else:
+ env.Append(CPPDEFINES=["DBUS_ENABLED"])
if env["speechd"]:
- env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists speech-dispatcher") == 0: # 0 means found
+ env.ParseConfig("pkg-config speech-dispatcher --cflags --libs")
+ env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
+ else:
+ print("Warning: speech-dispatcher development libraries not found. Disabling text to speech support.")
+ env["speechd"] = False
+ else:
+ env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
+
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists xkbcommon") == 0: # 0 means found
+ env.ParseConfig("pkg-config xkbcommon --cflags --libs")
+ env.Append(CPPDEFINES=["XKB_ENABLED"])
+ else:
+ print(
+ "Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support."
+ )
+ else:
+ env.Append(CPPDEFINES=["XKB_ENABLED"])
if platform.system() == "Linux":
env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
if env["udev"]:
- env.Append(CPPDEFINES=["UDEV_ENABLED"])
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists libudev") == 0: # 0 means found
+ env.ParseConfig("pkg-config libudev --cflags --libs")
+ env.Append(CPPDEFINES=["UDEV_ENABLED"])
+ else:
+ print("Warning: libudev development libraries not found. Disabling controller hotplugging support.")
+ env["udev"] = False
+ else:
+ env.Append(CPPDEFINES=["UDEV_ENABLED"])
else:
env["udev"] = False # Linux specific
@@ -298,7 +366,9 @@ def configure(env: "Environment"):
if not env["builtin_zlib"]:
env.ParseConfig("pkg-config zlib --cflags --libs")
- env.Prepend(CPPPATH=["#platform/linuxbsd", "#thirdparty/linuxbsd_headers"])
+ env.Prepend(CPPPATH=["#platform/linuxbsd"])
+ if env["use_sowrap"]:
+ env.Prepend(CPPPATH=["#thirdparty/linuxbsd_headers"])
env.Append(
CPPDEFINES=[
@@ -309,6 +379,35 @@ def configure(env: "Environment"):
)
if env["x11"]:
+ if not env["use_sowrap"]:
+ if os.system("pkg-config --exists x11"):
+ print("Error: X11 libraries not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config x11 --cflags --libs")
+ if os.system("pkg-config --exists xcursor"):
+ print("Error: Xcursor library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xcursor --cflags --libs")
+ if os.system("pkg-config --exists xinerama"):
+ print("Error: Xinerama library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xinerama --cflags --libs")
+ if os.system("pkg-config --exists xext"):
+ print("Error: Xext library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xext --cflags --libs")
+ if os.system("pkg-config --exists xrandr"):
+ print("Error: XrandR library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xrandr --cflags --libs")
+ if os.system("pkg-config --exists xrender"):
+ print("Error: XRender library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xrender --cflags --libs")
+ if os.system("pkg-config --exists xi"):
+ print("Error: Xi library not found. Aborting.")
+ sys.exit(255)
+ env.ParseConfig("pkg-config xi --cflags --libs")
env.Append(CPPDEFINES=["X11_ENABLED"])
if env["vulkan"]:
@@ -346,7 +445,7 @@ def configure(env: "Environment"):
gnu_ld_version = re.search("^GNU ld [^$]*(\d+\.\d+)$", linker_version_str, re.MULTILINE)
if not gnu_ld_version:
print(
- "Warning: Creating template binaries enabled for PCK embedding is currently only supported with GNU ld, not gold or LLD."
+ "Warning: Creating export template binaries enabled for PCK embedding is currently only supported with GNU ld, not gold, LLD or mold."
)
else:
if float(gnu_ld_version.group(1)) >= 2.30:
diff --git a/platform/linuxbsd/fontconfig-so_wrap.c b/platform/linuxbsd/fontconfig-so_wrap.c
index 6278522b69..86aacbc647 100644
--- a/platform/linuxbsd/fontconfig-so_wrap.c
+++ b/platform/linuxbsd/fontconfig-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:15:54
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/fontconfig/fontconfig.h --sys-include "thirdparty/linuxbsd_headers/fontconfig/fontconfig.h" --soname libfontconfig.so.1 --init-name fontconfig --omit-prefix FcCharSetFirst --omit-prefix FcCharSetNext --output-header ./platform/linuxbsd/fontconfig-so_wrap.h --output-implementation ./platform/linuxbsd/fontconfig-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:15:54
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/fontconfig/fontconfig.h --sys-include "thirdparty/linuxbsd_headers/fontconfig/fontconfig.h" --soname libfontconfig.so.1 --init-name fontconfig --omit-prefix FcCharSetFirst --omit-prefix FcCharSetNext --output-header ./platform/linuxbsd/fontconfig-so_wrap.h --output-implementation ./platform/linuxbsd/fontconfig-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/fontconfig-so_wrap.h b/platform/linuxbsd/fontconfig-so_wrap.h
index 021b2148ae..956c094711 100644
--- a/platform/linuxbsd/fontconfig-so_wrap.h
+++ b/platform/linuxbsd/fontconfig-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_FONTCONFIG
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:15:54
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/fontconfig/fontconfig.h --sys-include "thirdparty/linuxbsd_headers/fontconfig/fontconfig.h" --soname libfontconfig.so.1 --init-name fontconfig --omit-prefix FcCharSetFirst --omit-prefix FcCharSetNext --output-header ./platform/linuxbsd/fontconfig-so_wrap.h --output-implementation ./platform/linuxbsd/fontconfig-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:15:54
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/fontconfig/fontconfig.h --sys-include "thirdparty/linuxbsd_headers/fontconfig/fontconfig.h" --soname libfontconfig.so.1 --init-name fontconfig --omit-prefix FcCharSetFirst --omit-prefix FcCharSetNext --output-header ./platform/linuxbsd/fontconfig-so_wrap.h --output-implementation ./platform/linuxbsd/fontconfig-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/freedesktop_portal_desktop.cpp b/platform/linuxbsd/freedesktop_portal_desktop.cpp
index 72d4e3772f..ec1fcf6698 100644
--- a/platform/linuxbsd/freedesktop_portal_desktop.cpp
+++ b/platform/linuxbsd/freedesktop_portal_desktop.cpp
@@ -36,7 +36,11 @@
#include "core/os/os.h"
#include "core/string/ustring.h"
+#ifdef SOWRAP_ENABLED
#include "dbus-so_wrap.h"
+#else
+#include <dbus/dbus.h>
+#endif
#include "core/variant/variant.h"
@@ -124,12 +128,16 @@ uint32_t FreeDesktopPortalDesktop::get_appearance_color_scheme() {
}
FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
unsupported = (initialize_dbus(dylibloader_verbose) != 0);
+#else
+ unsupported = false;
+#endif
}
#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/freedesktop_screensaver.cpp b/platform/linuxbsd/freedesktop_screensaver.cpp
index 159fd0df61..d07e781a5f 100644
--- a/platform/linuxbsd/freedesktop_screensaver.cpp
+++ b/platform/linuxbsd/freedesktop_screensaver.cpp
@@ -34,7 +34,11 @@
#include "core/config/project_settings.h"
+#ifdef SOWRAP_ENABLED
#include "dbus-so_wrap.h"
+#else
+#include <dbus/dbus.h>
+#endif
#define BUS_OBJECT_NAME "org.freedesktop.ScreenSaver"
#define BUS_OBJECT_PATH "/org/freedesktop/ScreenSaver"
@@ -127,12 +131,16 @@ void FreeDesktopScreenSaver::uninhibit() {
}
FreeDesktopScreenSaver::FreeDesktopScreenSaver() {
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
unsupported = (initialize_dbus(dylibloader_verbose) != 0);
+#else
+ unsupported = false;
+#endif
}
#endif // DBUS_ENABLED
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index b77f989677..0256af0a59 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -39,7 +39,11 @@
#include <unistd.h>
#ifdef UDEV_ENABLED
+#ifdef SOWRAP_ENABLED
#include "libudev-so_wrap.h"
+#else
+#include <libudev.h>
+#endif
#endif
#define LONG_BITS (sizeof(long) * 8)
@@ -70,6 +74,7 @@ void JoypadLinux::Joypad::reset() {
JoypadLinux::JoypadLinux(Input *in) {
#ifdef UDEV_ENABLED
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@@ -81,6 +86,7 @@ JoypadLinux::JoypadLinux(Input *in) {
} else {
print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
}
+#endif
#else
print_verbose("JoypadLinux: udev disabled, parsing /dev/input to detect joypads.");
#endif
diff --git a/platform/linuxbsd/libudev-so_wrap.c b/platform/linuxbsd/libudev-so_wrap.c
index 9593b5fb0f..5455c1ab4e 100644
--- a/platform/linuxbsd/libudev-so_wrap.c
+++ b/platform/linuxbsd/libudev-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:23:01
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/udev/libudev.h --sys-include "thirdparty/linuxbsd_headers/udev/libudev.h" --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header ./platform/linuxbsd/libudev-so_wrap.h --output-implementation ./platform/linuxbsd/libudev-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:23:01
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/udev/libudev.h --sys-include "thirdparty/linuxbsd_headers/udev/libudev.h" --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header ./platform/linuxbsd/libudev-so_wrap.h --output-implementation ./platform/linuxbsd/libudev-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/libudev-so_wrap.h b/platform/linuxbsd/libudev-so_wrap.h
index 9b9627877a..174a3663d4 100644
--- a/platform/linuxbsd/libudev-so_wrap.h
+++ b/platform/linuxbsd/libudev-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_LIBUDEV
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:23:01
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/udev/libudev.h --sys-include "thirdparty/linuxbsd_headers/udev/libudev.h" --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header ./platform/linuxbsd/libudev-so_wrap.h --output-implementation ./platform/linuxbsd/libudev-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:23:01
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/udev/libudev.h --sys-include "thirdparty/linuxbsd_headers/udev/libudev.h" --soname libudev.so.1 --init-name libudev --omit-prefix gnu_ --output-header ./platform/linuxbsd/libudev-so_wrap.h --output-implementation ./platform/linuxbsd/libudev-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 75c23655f2..54bb34ef73 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -81,7 +81,7 @@ void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
List<String> args;
if (program.ends_with("zenity")) {
- args.push_back("--error");
+ args.push_back("--warning");
args.push_back("--width");
args.push_back("500");
args.push_back("--title");
@@ -91,7 +91,9 @@ void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
}
if (program.ends_with("kdialog")) {
- args.push_back("--error");
+ // `--sorry` uses the same icon as `--warning` in Zenity.
+ // As of KDialog 22.12.1, its `--warning` options are only available for yes/no questions.
+ args.push_back("--sorry");
args.push_back(p_alert);
args.push_back("--title");
args.push_back(p_title);
@@ -1081,12 +1083,16 @@ OS_LinuxBSD::OS_LinuxBSD() {
#endif
#ifdef FONTCONFIG_ENABLED
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
font_config_initialized = (initialize_fontconfig(dylibloader_verbose) == 0);
+#else
+ font_config_initialized = true;
+#endif
if (font_config_initialized) {
config = FcInitLoadConfigAndFonts();
if (!config) {
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index 045d3d95ba..9423514944 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -41,7 +41,11 @@
#include "servers/audio_server.h"
#ifdef FONTCONFIG_ENABLED
+#ifdef SOWRAP_ENABLED
#include "fontconfig-so_wrap.h"
+#else
+#include <fontconfig/fontconfig.h>
+#endif
#endif
class OS_LinuxBSD : public OS_Unix {
diff --git a/platform/linuxbsd/speechd-so_wrap.c b/platform/linuxbsd/speechd-so_wrap.c
index c860c686f0..1dc5f08c10 100644
--- a/platform/linuxbsd/speechd-so_wrap.c
+++ b/platform/linuxbsd/speechd-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:07:46
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/speechd/libspeechd.h --sys-include "thirdparty/linuxbsd_headers/speechd/libspeechd.h" --soname libspeechd.so.2 --init-name speechd --omit-prefix spd_get_client_list --output-header ./platform/linuxbsd/speechd-so_wrap.h --output-implementation ./platform/linuxbsd/speechd-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:07:46
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/speechd/libspeechd.h --sys-include "thirdparty/linuxbsd_headers/speechd/libspeechd.h" --soname libspeechd.so.2 --init-name speechd --omit-prefix spd_get_client_list --output-header ./platform/linuxbsd/speechd-so_wrap.h --output-implementation ./platform/linuxbsd/speechd-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/speechd-so_wrap.h b/platform/linuxbsd/speechd-so_wrap.h
index 8e0762041a..2967cfa929 100644
--- a/platform/linuxbsd/speechd-so_wrap.h
+++ b/platform/linuxbsd/speechd-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_SPEECHD
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-12 10:07:46
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/speechd/libspeechd.h --sys-include "thirdparty/linuxbsd_headers/speechd/libspeechd.h" --soname libspeechd.so.2 --init-name speechd --omit-prefix spd_get_client_list --output-header ./platform/linuxbsd/speechd-so_wrap.h --output-implementation ./platform/linuxbsd/speechd-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-12 10:07:46
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/speechd/libspeechd.h --sys-include "thirdparty/linuxbsd_headers/speechd/libspeechd.h" --soname libspeechd.so.2 --init-name speechd --omit-prefix spd_get_client_list --output-header ./platform/linuxbsd/speechd-so_wrap.h --output-implementation ./platform/linuxbsd/speechd-so_wrap.c
//
#include <stdint.h>
diff --git a/platform/linuxbsd/tts_linux.cpp b/platform/linuxbsd/tts_linux.cpp
index 4662aaf02d..04d7c5444f 100644
--- a/platform/linuxbsd/tts_linux.cpp
+++ b/platform/linuxbsd/tts_linux.cpp
@@ -39,12 +39,18 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) {
TTS_Linux *tts = (TTS_Linux *)p_userdata;
if (tts) {
MutexLock thread_safe_method(tts->_thread_safe_);
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
- if (initialize_speechd(dylibloader_verbose) == 0) {
+ if (initialize_speechd(dylibloader_verbose) != 0) {
+ print_verbose("Text-to-Speech: Cannot load Speech Dispatcher library!");
+ } else {
+#else
+ {
+#endif
CharString class_str;
String config_name = GLOBAL_GET("application/config/name");
if (config_name.length() == 0) {
@@ -64,8 +70,6 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) {
} else {
print_verbose("Text-to-Speech: Cannot initialize Speech Dispatcher synthesizer!");
}
- } else {
- print_verbose("Text-to-Speech: Cannot load Speech Dispatcher library!");
}
}
}
diff --git a/platform/linuxbsd/tts_linux.h b/platform/linuxbsd/tts_linux.h
index 425654d975..3fe7b659d0 100644
--- a/platform/linuxbsd/tts_linux.h
+++ b/platform/linuxbsd/tts_linux.h
@@ -39,7 +39,11 @@
#include "core/variant/array.h"
#include "servers/display_server.h"
+#ifdef SOWRAP_ENABLED
#include "speechd-so_wrap.h"
+#else
+#include <libspeechd.h>
+#endif
class TTS_Linux {
_THREAD_SAFE_CLASS_
diff --git a/platform/linuxbsd/x11/SCsub b/platform/linuxbsd/x11/SCsub
index 8b2e2aabe4..a4890391ce 100644
--- a/platform/linuxbsd/x11/SCsub
+++ b/platform/linuxbsd/x11/SCsub
@@ -5,15 +5,21 @@ Import("env")
source_files = [
"display_server_x11.cpp",
"key_mapping_x11.cpp",
- "dynwrappers/xlib-so_wrap.c",
- "dynwrappers/xcursor-so_wrap.c",
- "dynwrappers/xinerama-so_wrap.c",
- "dynwrappers/xinput2-so_wrap.c",
- "dynwrappers/xrandr-so_wrap.c",
- "dynwrappers/xrender-so_wrap.c",
- "dynwrappers/xext-so_wrap.c",
]
+if env["use_sowrap"]:
+ source_files.append(
+ [
+ "dynwrappers/xlib-so_wrap.c",
+ "dynwrappers/xcursor-so_wrap.c",
+ "dynwrappers/xinerama-so_wrap.c",
+ "dynwrappers/xinput2-so_wrap.c",
+ "dynwrappers/xrandr-so_wrap.c",
+ "dynwrappers/xrender-so_wrap.c",
+ "dynwrappers/xext-so_wrap.c",
+ ]
+ )
+
if env["vulkan"]:
source_files.append("vulkan_context_x11.cpp")
diff --git a/platform/linuxbsd/x11/detect_prime_x11.cpp b/platform/linuxbsd/x11/detect_prime_x11.cpp
index 8d586599e6..3d07be1c76 100644
--- a/platform/linuxbsd/x11/detect_prime_x11.cpp
+++ b/platform/linuxbsd/x11/detect_prime_x11.cpp
@@ -41,7 +41,13 @@
#include "thirdparty/glad/glad/gl.h"
#include "thirdparty/glad/glad/glx.h"
+#ifdef SOWRAP_ENABLED
#include "dynwrappers/xlib-so_wrap.h"
+#else
+#include <X11/XKBlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
#include <cstring>
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 428cf3a145..00547c4560 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -1324,14 +1324,22 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
}
#endif
- XDestroyWindow(x11_display, wd.x11_xim_window);
-
- XUnmapWindow(x11_display, wd.x11_window);
- XDestroyWindow(x11_display, wd.x11_window);
if (wd.xic) {
XDestroyIC(wd.xic);
wd.xic = nullptr;
}
+ XDestroyWindow(x11_display, wd.x11_xim_window);
+#ifdef XKB_ENABLED
+ if (xkb_loaded) {
+ if (wd.xkb_state) {
+ xkb_compose_state_unref(wd.xkb_state);
+ wd.xkb_state = nullptr;
+ }
+ }
+#endif
+
+ XUnmapWindow(x11_display, wd.x11_window);
+ XDestroyWindow(x11_display, wd.x11_window);
windows.erase(p_id);
}
@@ -1610,7 +1618,7 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
// a subwindow and its parent are both destroyed.
if (!wd_window.no_focus && !wd_window.is_popup && wd_window.focused) {
if ((xwa.map_state == IsViewable) && !wd_parent.no_focus && !wd_window.is_popup) {
- XSetInputFocus(x11_display, wd_parent.x11_window, RevertToParent, CurrentTime);
+ XSetInputFocus(x11_display, wd_parent.x11_window, RevertToPointerRoot, CurrentTime);
}
}
} else {
@@ -2515,7 +2523,7 @@ void DisplayServerX11::window_set_ime_active(const bool p_active, WindowID p_win
XSync(x11_display, False);
XGetWindowAttributes(x11_display, wd.x11_xim_window, &xwa);
if (xwa.map_state == IsViewable) {
- XSetInputFocus(x11_display, wd.x11_xim_window, RevertToPointerRoot, CurrentTime);
+ XSetInputFocus(x11_display, wd.x11_xim_window, RevertToParent, CurrentTime);
}
XSetICFocus(wd.xic);
} else {
@@ -2591,6 +2599,8 @@ DisplayServerX11::CursorShape DisplayServerX11::cursor_get_shape() const {
void DisplayServerX11::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
+
if (p_cursor.is_valid()) {
HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape);
@@ -2936,11 +2946,13 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_keycode, nullptr);
String keysym;
- if (xkb_keysym_to_utf32 && xkb_keysym_to_upper) {
+#ifdef XKB_ENABLED
+ if (xkb_loaded) {
KeySym keysym_unicode_nm = 0; // keysym used to find unicode
XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_unicode_nm, nullptr);
keysym = String::chr(xkb_keysym_to_utf32(xkb_keysym_to_upper(keysym_unicode_nm)));
}
+#endif
// Meanwhile, XLookupString returns keysyms useful for unicode.
@@ -3029,6 +3041,66 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
}
} while (status == XBufferOverflow);
#endif
+#ifdef XKB_ENABLED
+ } else if (xkeyevent->type == KeyPress && wd.xkb_state && xkb_loaded) {
+ xkb_compose_feed_result res = xkb_compose_state_feed(wd.xkb_state, keysym_unicode);
+ if (res == XKB_COMPOSE_FEED_ACCEPTED) {
+ if (xkb_compose_state_get_status(wd.xkb_state) == XKB_COMPOSE_COMPOSED) {
+ bool keypress = xkeyevent->type == KeyPress;
+ Key keycode = KeyMappingX11::get_keycode(keysym_keycode);
+ Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
+
+ if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) {
+ keycode -= 'a' - 'A';
+ }
+
+ char str_xkb[256] = {};
+ int str_xkb_size = xkb_compose_state_get_utf8(wd.xkb_state, str_xkb, 255);
+
+ String tmp;
+ tmp.parse_utf8(str_xkb, str_xkb_size);
+ for (int i = 0; i < tmp.length(); i++) {
+ Ref<InputEventKey> k;
+ k.instantiate();
+ if (physical_keycode == Key::NONE && keycode == Key::NONE && tmp[i] == 0) {
+ continue;
+ }
+
+ if (keycode == Key::NONE) {
+ keycode = (Key)physical_keycode;
+ }
+
+ _get_key_modifier_state(xkeyevent->state, k);
+
+ k->set_window_id(p_window);
+ k->set_pressed(keypress);
+
+ k->set_keycode(keycode);
+ k->set_physical_keycode(physical_keycode);
+ if (!keysym.is_empty()) {
+ k->set_key_label(fix_key_label(keysym[0], keycode));
+ } else {
+ k->set_key_label(keycode);
+ }
+ if (keypress) {
+ k->set_unicode(fix_unicode(tmp[i]));
+ }
+
+ k->set_echo(false);
+
+ if (k->get_keycode() == Key::BACKTAB) {
+ //make it consistent across platforms.
+ k->set_keycode(Key::TAB);
+ k->set_physical_keycode(Key::TAB);
+ k->set_shift_pressed(true);
+ }
+
+ Input::get_singleton()->parse_input_event(k);
+ }
+ return;
+ }
+ }
+#endif
}
/* Phase 2, obtain a Godot keycode from the keysym */
@@ -3608,8 +3680,23 @@ Rect2i DisplayServerX11::window_get_popup_safe_rect(WindowID p_window) const {
void DisplayServerX11::popup_open(WindowID p_window) {
_THREAD_SAFE_METHOD_
+ bool has_popup_ancestor = false;
+ WindowID transient_root = p_window;
+ while (true) {
+ WindowID parent = windows[transient_root].transient_parent;
+ if (parent == INVALID_WINDOW_ID) {
+ break;
+ } else {
+ transient_root = parent;
+ if (windows[parent].is_popup) {
+ has_popup_ancestor = true;
+ break;
+ }
+ }
+ }
+
WindowData &wd = windows[p_window];
- if (wd.is_popup) {
+ if (wd.is_popup || has_popup_ancestor) {
// Find current popup parent, or root popup if new window is not transient.
List<WindowID>::Element *C = nullptr;
List<WindowID>::Element *E = popup_list.back();
@@ -3755,10 +3842,6 @@ void DisplayServerX11::process_events() {
for (uint32_t event_index = 0; event_index < events.size(); ++event_index) {
XEvent &event = events[event_index];
- if (ignore_events) {
- XFreeEventData(x11_display, &event.xcookie);
- continue;
- }
bool ime_window_event = false;
WindowID window_id = MAIN_WINDOW_ID;
@@ -3788,7 +3871,7 @@ void DisplayServerX11::process_events() {
_refresh_device_info();
} break;
case XI_RawMotion: {
- if (ime_window_event) {
+ if (ime_window_event || ignore_events) {
break;
}
XIRawEvent *raw_event = (XIRawEvent *)event_data;
@@ -3893,7 +3976,7 @@ void DisplayServerX11::process_events() {
#ifdef TOUCH_ENABLED
case XI_TouchBegin:
case XI_TouchEnd: {
- if (ime_window_event) {
+ if (ime_window_event || ignore_events) {
break;
}
bool is_begin = event_data->evtype == XI_TouchBegin;
@@ -3926,7 +4009,7 @@ void DisplayServerX11::process_events() {
} break;
case XI_TouchUpdate: {
- if (ime_window_event) {
+ if (ime_window_event || ignore_events) {
break;
}
HashMap<int, Vector2>::Iterator curr_pos_elem = xi.state.find(index);
@@ -4030,7 +4113,7 @@ void DisplayServerX11::process_events() {
case FocusIn: {
DEBUG_LOG_X11("[%u] FocusIn window=%lu (%u), mode='%u' \n", frame, event.xfocus.window, window_id, event.xfocus.mode);
- if (ime_window_event) {
+ if (ime_window_event || (event.xfocus.detail == NotifyInferior)) {
break;
}
@@ -4078,7 +4161,7 @@ void DisplayServerX11::process_events() {
case FocusOut: {
DEBUG_LOG_X11("[%u] FocusOut window=%lu (%u), mode='%u' \n", frame, event.xfocus.window, window_id, event.xfocus.mode);
WindowData &wd = windows[window_id];
- if (wd.ime_active && event.xfocus.detail == NotifyInferior) {
+ if (ime_window_event || (event.xfocus.detail == NotifyInferior)) {
break;
}
if (wd.ime_active) {
@@ -4148,7 +4231,7 @@ void DisplayServerX11::process_events() {
case ButtonPress:
case ButtonRelease: {
- if (ime_window_event) {
+ if (ime_window_event || ignore_events) {
break;
}
/* exit in case of a mouse button press */
@@ -4249,7 +4332,7 @@ void DisplayServerX11::process_events() {
} break;
case MotionNotify: {
- if (ime_window_event) {
+ if (ime_window_event || ignore_events) {
break;
}
// The X11 API requires filtering one-by-one through the motion
@@ -4397,6 +4480,9 @@ void DisplayServerX11::process_events() {
} break;
case KeyPress:
case KeyRelease: {
+ if (ignore_events) {
+ break;
+ }
#ifdef DISPLAY_SERVER_X11_DEBUG_LOGS_ENABLED
if (event.type == KeyPress) {
DEBUG_LOG_X11("[%u] KeyPress window=%lu (%u), keycode=%u, time=%lu \n", frame, event.xkey.window, window_id, event.xkey.keycode, event.xkey.time);
@@ -4833,7 +4919,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
// handling decorations and placement.
// On the other hand, focus changes need to be handled manually when this is set.
// - save_under is a hint for the WM to keep the content of windows behind to avoid repaint.
- if (wd.is_popup || wd.no_focus) {
+ if (wd.no_focus) {
windowAttributes.override_redirect = True;
windowAttributes.save_under = True;
valuemask |= CWOverrideRedirect | CWSaveUnder;
@@ -4858,6 +4944,11 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
win_rect.position = wpos;
}
+ // Position and size hints are set from these values before they are updated to the actual
+ // window size, so we need to initialize them here.
+ wd.position = win_rect.position;
+ wd.size = win_rect.size;
+
{
wd.x11_window = XCreateWindow(x11_display, RootWindow(x11_display, visualInfo.screen), win_rect.position.x, win_rect.position.y, win_rect.size.width > 0 ? win_rect.size.width : 1, win_rect.size.height > 0 ? win_rect.size.height : 1, 0, visualInfo.depth, InputOutput, visualInfo.visual, valuemask, &windowAttributes);
@@ -4865,7 +4956,11 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
window_attributes_ime.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask | ExposureMask;
wd.x11_xim_window = XCreateWindow(x11_display, wd.x11_window, 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, CWEventMask, &window_attributes_ime);
-
+#ifdef XKB_ENABLED
+ if (dead_tbl && xkb_loaded) {
+ wd.xkb_state = xkb_compose_state_new(dead_tbl, XKB_COMPOSE_STATE_NO_FLAGS);
+ }
+#endif
// Enable receiving notification when the window is initialized (MapNotify)
// so the focus can be set at the right time.
if (!wd.no_focus && !wd.is_popup) {
@@ -5130,6 +5225,7 @@ static ::XIMStyle _get_best_xim_style(const ::XIMStyle &p_style_a, const ::XIMSt
DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) {
KeyMappingX11::initialize();
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
@@ -5144,9 +5240,9 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Can't load XCursor dynamically.");
}
-
- initialize_xkbcommon(dylibloader_verbose); // Optional, used for key_label.
-
+#ifdef XKB_ENABLED
+ xkb_loaded = (initialize_xkbcommon(dylibloader_verbose) == 0);
+#endif
if (initialize_xext(dylibloader_verbose) != 0) {
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Can't load Xext dynamically.");
@@ -5171,6 +5267,30 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
r_error = ERR_UNAVAILABLE;
ERR_FAIL_MSG("Can't load Xinput2 dynamically.");
}
+#else
+#ifdef XKB_ENABLED
+ xkb_loaded = true;
+#endif
+#endif
+
+#ifdef XKB_ENABLED
+ if (xkb_loaded) {
+ xkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ if (xkb_ctx) {
+ const char *locale = getenv("LC_ALL");
+ if (!locale || !*locale) {
+ locale = getenv("LC_CTYPE");
+ }
+ if (!locale || !*locale) {
+ locale = getenv("LANG");
+ }
+ if (!locale || !*locale) {
+ locale = "C";
+ }
+ dead_tbl = xkb_compose_table_new_from_locale(xkb_ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
+ }
+ }
+#endif
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
@@ -5612,10 +5732,30 @@ DisplayServerX11::~DisplayServerX11() {
XDestroyIC(wd.xic);
wd.xic = nullptr;
}
+ XDestroyWindow(x11_display, wd.x11_xim_window);
+#ifdef XKB_ENABLED
+ if (xkb_loaded) {
+ if (wd.xkb_state) {
+ xkb_compose_state_unref(wd.xkb_state);
+ wd.xkb_state = nullptr;
+ }
+ }
+#endif
XUnmapWindow(x11_display, wd.x11_window);
XDestroyWindow(x11_display, wd.x11_window);
}
+#ifdef XKB_ENABLED
+ if (xkb_loaded) {
+ if (dead_tbl) {
+ xkb_compose_table_unref(dead_tbl);
+ }
+ if (xkb_ctx) {
+ xkb_context_unref(xkb_ctx);
+ }
+ }
+#endif
+
//destroy drivers
#if defined(VULKAN_ENABLED)
if (rendering_device_vulkan) {
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index bfb97ae44c..dbe8a0ce2b 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -36,6 +36,8 @@
#include "servers/display_server.h"
#include "core/input/input.h"
+#include "core/os/mutex.h"
+#include "core/os/thread.h"
#include "core/templates/local_vector.h"
#include "drivers/alsa/audio_driver_alsa.h"
#include "drivers/alsamidi/midi_driver_alsamidi.h"
@@ -69,6 +71,7 @@
#include <X11/Xutil.h>
#include <X11/keysym.h>
+#ifdef SOWRAP_ENABLED
#include "dynwrappers/xlib-so_wrap.h"
#include "dynwrappers/xcursor-so_wrap.h"
@@ -79,6 +82,25 @@
#include "dynwrappers/xrender-so_wrap.h"
#include "../xkbcommon-so_wrap.h"
+#else
+#include <X11/XKBlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <X11/Xcursor/Xcursor.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/Xinerama.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/shape.h>
+
+#ifdef XKB_ENABLED
+#include <xkbcommon/xkbcommon-compose.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
+#include <xkbcommon/xkbcommon.h>
+#endif
+#endif
typedef struct _xrr_monitor_info {
Atom name;
@@ -142,6 +164,9 @@ class DisplayServerX11 : public DisplayServer {
bool ime_active = false;
bool ime_in_progress = false;
bool ime_suppress_next_keyup = false;
+#ifdef XKB_ENABLED
+ xkb_compose_state *xkb_state = nullptr;
+#endif
Size2i min_size;
Size2i max_size;
@@ -185,6 +210,12 @@ class DisplayServerX11 : public DisplayServer {
Point2i im_selection;
String im_text;
+#ifdef XKB_ENABLED
+ bool xkb_loaded = false;
+ xkb_context *xkb_ctx = nullptr;
+ xkb_compose_table *dead_tbl = nullptr;
+#endif
+
HashMap<WindowID, WindowData> windows;
unsigned int last_mouse_monitor_mask = 0;
diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
index ecd2c25662..bba21b9cb7 100644
--- a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:09:53
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include "thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h" --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:09:53
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include "thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h" --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
//
// NOTE: Generated from Xcursor 1.2.0.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
index dc3684ff09..9f8d8bbca2 100644
--- a/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XCURSOR
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:09:53
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include "thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h" --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:09:53
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h --sys-include "thirdparty/linuxbsd_headers/X11/Xcursor/Xcursor.h" --soname libXcursor.so.1 --init-name xcursor --output-header ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xcursor-so_wrap.c
//
// NOTE: Generated from Xcursor 1.2.0.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
index e9af9033a3..4e3349c574 100644
--- a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:11:29
-// flags: ../dynload-wrapper/generate-wrapper.py --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xext.h" --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/shape.h" --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:29
+// flags: generate-wrapper.py --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xext.h" --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/shape.h" --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
//
// NOTE: Generated from Xext 1.3.5.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
index bbf23fff34..e535756d82 100644
--- a/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XEXT
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:11:29
-// flags: ../dynload-wrapper/generate-wrapper.py --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xext.h" --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/shape.h" --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:29
+// flags: generate-wrapper.py --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xext.h" --include ./thirdparty/linuxbsd_headers/X11/extensions/shape.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/shape.h" --soname libXext.so.6 --init-name xext --output-header ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xext-so_wrap.c
//
// NOTE: Generated from Xext 1.3.5.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
index ab53b232d6..850ed1fc6b 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:11:35
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h" --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:35
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h" --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
//
// NOTE: Generated from Xinerama 1.1.4.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
index 48d5cc44b7..e3cedfc8ad 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XINERAMA
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:11:35
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h" --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:11:35
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xinerama.h" --soname libXinerama.so.1 --init-name xinerama --output-header ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinerama-so_wrap.c
//
// NOTE: Generated from Xinerama 1.1.4.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
index d37f2b4d94..fc08b97e3c 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:12:16
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/XInput2.h" --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:12:16
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/XInput2.h" --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
//
// NOTE: Generated from Xi 1.7.10.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
index e39661ffb9..571072c3cd 100644
--- a/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XINPUT2
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:12:16
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/XInput2.h" --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:12:16
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/XInput2.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/XInput2.h" --soname libXi.so.6 --init-name xinput2 --output-header ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xinput2-so_wrap.c
//
// NOTE: Generated from Xi 1.7.10.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c
index a746b6c526..d2838569b0 100644
--- a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:13:26
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include "thirdparty/linuxbsd_headers/X11/Xlib.h" --sys-include "thirdparty/linuxbsd_headers/X11/Xutil.h" --sys-include "thirdparty/linuxbsd_headers/X11/XKBlib.h" --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c~
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:26
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include "thirdparty/linuxbsd_headers/X11/Xlib.h" --sys-include "thirdparty/linuxbsd_headers/X11/Xutil.h" --sys-include "thirdparty/linuxbsd_headers/X11/XKBlib.h" --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c~
//
// NOTE: Generated from Xlib 1.6.9.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h
index b40a25f601..5bad21002d 100644
--- a/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XLIB
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:13:26
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include "thirdparty/linuxbsd_headers/X11/Xlib.h" --sys-include "thirdparty/linuxbsd_headers/X11/Xutil.h" --sys-include "thirdparty/linuxbsd_headers/X11/XKBlib.h" --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c~
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:26
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/Xlib.h --include ./thirdparty/linuxbsd_headers/X11/Xutil.h --include ./thirdparty/linuxbsd_headers/X11/XKBlib.h --sys-include "thirdparty/linuxbsd_headers/X11/Xlib.h" --sys-include "thirdparty/linuxbsd_headers/X11/Xutil.h" --sys-include "thirdparty/linuxbsd_headers/X11/XKBlib.h" --soname libX11.so.6 --init-name xlib --omit-prefix XkbGetDeviceIndicatorState --omit-prefix XkbAddSymInterpret --output-header ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xlib-so_wrap.c~
//
// NOTE: Generated from Xlib 1.6.9.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
index 21e30a03de..05f98d2506 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:13:54
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h" --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:54
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h" --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
//
// NOTE: Generated from Xrandr 1.5.2.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
index f301234b53..db5d44203d 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XRANDR
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:13:54
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h" --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:13:54
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrandr.h" --soname libXrandr.so.2 --init-name xrandr --output-header ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrandr-so_wrap.c
//
// NOTE: Generated from Xrandr 1.5.2.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
index 5c720bee21..7421f94601 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
+++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:14:14
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrender.h" --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c~
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:14:14
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrender.h" --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c~
//
// NOTE: Generated from Xrender 0.9.10.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
index 29a8430476..5d3f695959 100644
--- a/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
+++ b/platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XRENDER
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:14:14
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrender.h" --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c~
+// generated by generate-wrapper.py 0.3 on 2023-01-23 15:14:14
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/X11/extensions/Xrender.h --sys-include "thirdparty/linuxbsd_headers/X11/extensions/Xrender.h" --soname libXrender.so.1 --init-name xrender --output-header ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xrender-so_wrap.c~
//
// NOTE: Generated from Xrender 0.9.10.
// This has been handpatched to workaround some issues with the generator that
diff --git a/platform/linuxbsd/x11/gl_manager_x11.h b/platform/linuxbsd/x11/gl_manager_x11.h
index 713b13376c..0eb8ab64f4 100644
--- a/platform/linuxbsd/x11/gl_manager_x11.h
+++ b/platform/linuxbsd/x11/gl_manager_x11.h
@@ -37,9 +37,22 @@
#include "core/os/os.h"
#include "core/templates/local_vector.h"
-#include "dynwrappers/xext-so_wrap.h"
+
+#ifdef SOWRAP_ENABLED
#include "dynwrappers/xlib-so_wrap.h"
+
+#include "dynwrappers/xext-so_wrap.h"
#include "dynwrappers/xrender-so_wrap.h"
+#else
+#include <X11/XKBlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/Xrender.h>
+#include <X11/extensions/shape.h>
+#endif
+
#include "servers/display_server.h"
struct GLManager_X11_Private;
diff --git a/platform/linuxbsd/xkbcommon-so_wrap.c b/platform/linuxbsd/xkbcommon-so_wrap.c
index 601d4c5052..3382e2e553 100644
--- a/platform/linuxbsd/xkbcommon-so_wrap.c
+++ b/platform/linuxbsd/xkbcommon-so_wrap.c
@@ -1,7 +1,7 @@
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:14:21
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h" --soname libxkbcommon.so.0 --init-name xkbcommon --output-header ./platform/linuxbsd/x11/dynwrappers/xkbcommon-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xkbcommon-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-30 10:40:26
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-compose.h --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-keysyms.h --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h" --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-compose.h" --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-keysyms.h" --soname libxkbcommon.so.0 --init-name xkbcommon --output-header ./platform/linuxbsd/xkbcommon-so_wrap.h --output-implementation ./platform/linuxbsd/xkbcommon-so_wrap.c
//
#include <stdint.h>
@@ -81,7 +81,23 @@
#define xkb_state_layout_index_is_active xkb_state_layout_index_is_active_dylibloader_orig_xkbcommon
#define xkb_state_led_name_is_active xkb_state_led_name_is_active_dylibloader_orig_xkbcommon
#define xkb_state_led_index_is_active xkb_state_led_index_is_active_dylibloader_orig_xkbcommon
+#define xkb_compose_table_new_from_locale xkb_compose_table_new_from_locale_dylibloader_orig_xkbcommon
+#define xkb_compose_table_new_from_file xkb_compose_table_new_from_file_dylibloader_orig_xkbcommon
+#define xkb_compose_table_new_from_buffer xkb_compose_table_new_from_buffer_dylibloader_orig_xkbcommon
+#define xkb_compose_table_ref xkb_compose_table_ref_dylibloader_orig_xkbcommon
+#define xkb_compose_table_unref xkb_compose_table_unref_dylibloader_orig_xkbcommon
+#define xkb_compose_state_new xkb_compose_state_new_dylibloader_orig_xkbcommon
+#define xkb_compose_state_ref xkb_compose_state_ref_dylibloader_orig_xkbcommon
+#define xkb_compose_state_unref xkb_compose_state_unref_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_compose_table xkb_compose_state_get_compose_table_dylibloader_orig_xkbcommon
+#define xkb_compose_state_feed xkb_compose_state_feed_dylibloader_orig_xkbcommon
+#define xkb_compose_state_reset xkb_compose_state_reset_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_status xkb_compose_state_get_status_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_utf8 xkb_compose_state_get_utf8_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_one_sym xkb_compose_state_get_one_sym_dylibloader_orig_xkbcommon
#include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h"
+#include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-compose.h"
+#include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-keysyms.h"
#undef xkb_keysym_get_name
#undef xkb_keysym_from_name
#undef xkb_keysym_to_utf8
@@ -158,6 +174,20 @@
#undef xkb_state_layout_index_is_active
#undef xkb_state_led_name_is_active
#undef xkb_state_led_index_is_active
+#undef xkb_compose_table_new_from_locale
+#undef xkb_compose_table_new_from_file
+#undef xkb_compose_table_new_from_buffer
+#undef xkb_compose_table_ref
+#undef xkb_compose_table_unref
+#undef xkb_compose_state_new
+#undef xkb_compose_state_ref
+#undef xkb_compose_state_unref
+#undef xkb_compose_state_get_compose_table
+#undef xkb_compose_state_feed
+#undef xkb_compose_state_reset
+#undef xkb_compose_state_get_status
+#undef xkb_compose_state_get_utf8
+#undef xkb_compose_state_get_one_sym
#include <dlfcn.h>
#include <stdio.h>
int (*xkb_keysym_get_name_dylibloader_wrapper_xkbcommon)( xkb_keysym_t, char*, size_t);
@@ -236,6 +266,20 @@ int (*xkb_state_layout_name_is_active_dylibloader_wrapper_xkbcommon)(struct xkb_
int (*xkb_state_layout_index_is_active_dylibloader_wrapper_xkbcommon)(struct xkb_state*, xkb_layout_index_t,enum xkb_state_component);
int (*xkb_state_led_name_is_active_dylibloader_wrapper_xkbcommon)(struct xkb_state*,const char*);
int (*xkb_state_led_index_is_active_dylibloader_wrapper_xkbcommon)(struct xkb_state*, xkb_led_index_t);
+struct xkb_compose_table* (*xkb_compose_table_new_from_locale_dylibloader_wrapper_xkbcommon)(struct xkb_context*,const char*,enum xkb_compose_compile_flags);
+struct xkb_compose_table* (*xkb_compose_table_new_from_file_dylibloader_wrapper_xkbcommon)(struct xkb_context*, FILE*,const char*,enum xkb_compose_format,enum xkb_compose_compile_flags);
+struct xkb_compose_table* (*xkb_compose_table_new_from_buffer_dylibloader_wrapper_xkbcommon)(struct xkb_context*,const char*, size_t,const char*,enum xkb_compose_format,enum xkb_compose_compile_flags);
+struct xkb_compose_table* (*xkb_compose_table_ref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_table*);
+void (*xkb_compose_table_unref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_table*);
+struct xkb_compose_state* (*xkb_compose_state_new_dylibloader_wrapper_xkbcommon)(struct xkb_compose_table*,enum xkb_compose_state_flags);
+struct xkb_compose_state* (*xkb_compose_state_ref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+void (*xkb_compose_state_unref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+struct xkb_compose_table* (*xkb_compose_state_get_compose_table_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+enum xkb_compose_feed_result (*xkb_compose_state_feed_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*, xkb_keysym_t);
+void (*xkb_compose_state_reset_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+enum xkb_compose_status (*xkb_compose_state_get_status_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+int (*xkb_compose_state_get_utf8_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*, char*, size_t);
+xkb_keysym_t (*xkb_compose_state_get_one_sym_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
int initialize_xkbcommon(int verbose) {
void *handle;
char *error;
@@ -855,5 +899,117 @@ int initialize_xkbcommon(int verbose) {
fprintf(stderr, "%s\n", error);
}
}
+// xkb_compose_table_new_from_locale
+ *(void **) (&xkb_compose_table_new_from_locale_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_table_new_from_locale");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_table_new_from_file
+ *(void **) (&xkb_compose_table_new_from_file_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_table_new_from_file");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_table_new_from_buffer
+ *(void **) (&xkb_compose_table_new_from_buffer_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_table_new_from_buffer");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_table_ref
+ *(void **) (&xkb_compose_table_ref_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_table_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_table_unref
+ *(void **) (&xkb_compose_table_unref_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_table_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_new
+ *(void **) (&xkb_compose_state_new_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_new");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_ref
+ *(void **) (&xkb_compose_state_ref_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_ref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_unref
+ *(void **) (&xkb_compose_state_unref_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_unref");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_get_compose_table
+ *(void **) (&xkb_compose_state_get_compose_table_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_get_compose_table");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_feed
+ *(void **) (&xkb_compose_state_feed_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_feed");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_reset
+ *(void **) (&xkb_compose_state_reset_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_reset");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_get_status
+ *(void **) (&xkb_compose_state_get_status_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_get_status");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_get_utf8
+ *(void **) (&xkb_compose_state_get_utf8_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_get_utf8");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
+// xkb_compose_state_get_one_sym
+ *(void **) (&xkb_compose_state_get_one_sym_dylibloader_wrapper_xkbcommon) = dlsym(handle, "xkb_compose_state_get_one_sym");
+ if (verbose) {
+ error = dlerror();
+ if (error != NULL) {
+ fprintf(stderr, "%s\n", error);
+ }
+ }
return 0;
}
diff --git a/platform/linuxbsd/xkbcommon-so_wrap.h b/platform/linuxbsd/xkbcommon-so_wrap.h
index f7e6f4c4cf..4ae69fdf1f 100644
--- a/platform/linuxbsd/xkbcommon-so_wrap.h
+++ b/platform/linuxbsd/xkbcommon-so_wrap.h
@@ -2,8 +2,8 @@
#define DYLIBLOAD_WRAPPER_XKBCOMMON
// This file is generated. Do not edit!
// see https://github.com/hpvb/dynload-wrapper for details
-// generated by ../dynload-wrapper/generate-wrapper.py 0.3 on 2023-01-23 15:14:21
-// flags: ../dynload-wrapper/generate-wrapper.py --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h" --soname libxkbcommon.so.0 --init-name xkbcommon --output-header ./platform/linuxbsd/x11/dynwrappers/xkbcommon-so_wrap.h --output-implementation ./platform/linuxbsd/x11/dynwrappers/xkbcommon-so_wrap.c
+// generated by generate-wrapper.py 0.3 on 2023-01-30 10:40:26
+// flags: generate-wrapper.py --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-compose.h --include ./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-keysyms.h --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h" --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-compose.h" --sys-include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-keysyms.h" --soname libxkbcommon.so.0 --init-name xkbcommon --output-header ./platform/linuxbsd/xkbcommon-so_wrap.h --output-implementation ./platform/linuxbsd/xkbcommon-so_wrap.c
//
#include <stdint.h>
@@ -83,7 +83,23 @@
#define xkb_state_layout_index_is_active xkb_state_layout_index_is_active_dylibloader_orig_xkbcommon
#define xkb_state_led_name_is_active xkb_state_led_name_is_active_dylibloader_orig_xkbcommon
#define xkb_state_led_index_is_active xkb_state_led_index_is_active_dylibloader_orig_xkbcommon
+#define xkb_compose_table_new_from_locale xkb_compose_table_new_from_locale_dylibloader_orig_xkbcommon
+#define xkb_compose_table_new_from_file xkb_compose_table_new_from_file_dylibloader_orig_xkbcommon
+#define xkb_compose_table_new_from_buffer xkb_compose_table_new_from_buffer_dylibloader_orig_xkbcommon
+#define xkb_compose_table_ref xkb_compose_table_ref_dylibloader_orig_xkbcommon
+#define xkb_compose_table_unref xkb_compose_table_unref_dylibloader_orig_xkbcommon
+#define xkb_compose_state_new xkb_compose_state_new_dylibloader_orig_xkbcommon
+#define xkb_compose_state_ref xkb_compose_state_ref_dylibloader_orig_xkbcommon
+#define xkb_compose_state_unref xkb_compose_state_unref_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_compose_table xkb_compose_state_get_compose_table_dylibloader_orig_xkbcommon
+#define xkb_compose_state_feed xkb_compose_state_feed_dylibloader_orig_xkbcommon
+#define xkb_compose_state_reset xkb_compose_state_reset_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_status xkb_compose_state_get_status_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_utf8 xkb_compose_state_get_utf8_dylibloader_orig_xkbcommon
+#define xkb_compose_state_get_one_sym xkb_compose_state_get_one_sym_dylibloader_orig_xkbcommon
#include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon.h"
+#include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-compose.h"
+#include "./thirdparty/linuxbsd_headers/xkbcommon/xkbcommon-keysyms.h"
#undef xkb_keysym_get_name
#undef xkb_keysym_from_name
#undef xkb_keysym_to_utf8
@@ -160,6 +176,20 @@
#undef xkb_state_layout_index_is_active
#undef xkb_state_led_name_is_active
#undef xkb_state_led_index_is_active
+#undef xkb_compose_table_new_from_locale
+#undef xkb_compose_table_new_from_file
+#undef xkb_compose_table_new_from_buffer
+#undef xkb_compose_table_ref
+#undef xkb_compose_table_unref
+#undef xkb_compose_state_new
+#undef xkb_compose_state_ref
+#undef xkb_compose_state_unref
+#undef xkb_compose_state_get_compose_table
+#undef xkb_compose_state_feed
+#undef xkb_compose_state_reset
+#undef xkb_compose_state_get_status
+#undef xkb_compose_state_get_utf8
+#undef xkb_compose_state_get_one_sym
#ifdef __cplusplus
extern "C" {
#endif
@@ -239,6 +269,20 @@ extern "C" {
#define xkb_state_layout_index_is_active xkb_state_layout_index_is_active_dylibloader_wrapper_xkbcommon
#define xkb_state_led_name_is_active xkb_state_led_name_is_active_dylibloader_wrapper_xkbcommon
#define xkb_state_led_index_is_active xkb_state_led_index_is_active_dylibloader_wrapper_xkbcommon
+#define xkb_compose_table_new_from_locale xkb_compose_table_new_from_locale_dylibloader_wrapper_xkbcommon
+#define xkb_compose_table_new_from_file xkb_compose_table_new_from_file_dylibloader_wrapper_xkbcommon
+#define xkb_compose_table_new_from_buffer xkb_compose_table_new_from_buffer_dylibloader_wrapper_xkbcommon
+#define xkb_compose_table_ref xkb_compose_table_ref_dylibloader_wrapper_xkbcommon
+#define xkb_compose_table_unref xkb_compose_table_unref_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_new xkb_compose_state_new_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_ref xkb_compose_state_ref_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_unref xkb_compose_state_unref_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_get_compose_table xkb_compose_state_get_compose_table_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_feed xkb_compose_state_feed_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_reset xkb_compose_state_reset_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_get_status xkb_compose_state_get_status_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_get_utf8 xkb_compose_state_get_utf8_dylibloader_wrapper_xkbcommon
+#define xkb_compose_state_get_one_sym xkb_compose_state_get_one_sym_dylibloader_wrapper_xkbcommon
extern int (*xkb_keysym_get_name_dylibloader_wrapper_xkbcommon)( xkb_keysym_t, char*, size_t);
extern xkb_keysym_t (*xkb_keysym_from_name_dylibloader_wrapper_xkbcommon)(const char*,enum xkb_keysym_flags);
extern int (*xkb_keysym_to_utf8_dylibloader_wrapper_xkbcommon)( xkb_keysym_t, char*, size_t);
@@ -315,6 +359,20 @@ extern int (*xkb_state_layout_name_is_active_dylibloader_wrapper_xkbcommon)(stru
extern int (*xkb_state_layout_index_is_active_dylibloader_wrapper_xkbcommon)(struct xkb_state*, xkb_layout_index_t,enum xkb_state_component);
extern int (*xkb_state_led_name_is_active_dylibloader_wrapper_xkbcommon)(struct xkb_state*,const char*);
extern int (*xkb_state_led_index_is_active_dylibloader_wrapper_xkbcommon)(struct xkb_state*, xkb_led_index_t);
+extern struct xkb_compose_table* (*xkb_compose_table_new_from_locale_dylibloader_wrapper_xkbcommon)(struct xkb_context*,const char*,enum xkb_compose_compile_flags);
+extern struct xkb_compose_table* (*xkb_compose_table_new_from_file_dylibloader_wrapper_xkbcommon)(struct xkb_context*, FILE*,const char*,enum xkb_compose_format,enum xkb_compose_compile_flags);
+extern struct xkb_compose_table* (*xkb_compose_table_new_from_buffer_dylibloader_wrapper_xkbcommon)(struct xkb_context*,const char*, size_t,const char*,enum xkb_compose_format,enum xkb_compose_compile_flags);
+extern struct xkb_compose_table* (*xkb_compose_table_ref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_table*);
+extern void (*xkb_compose_table_unref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_table*);
+extern struct xkb_compose_state* (*xkb_compose_state_new_dylibloader_wrapper_xkbcommon)(struct xkb_compose_table*,enum xkb_compose_state_flags);
+extern struct xkb_compose_state* (*xkb_compose_state_ref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+extern void (*xkb_compose_state_unref_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+extern struct xkb_compose_table* (*xkb_compose_state_get_compose_table_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+extern enum xkb_compose_feed_result (*xkb_compose_state_feed_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*, xkb_keysym_t);
+extern void (*xkb_compose_state_reset_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+extern enum xkb_compose_status (*xkb_compose_state_get_status_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
+extern int (*xkb_compose_state_get_utf8_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*, char*, size_t);
+extern xkb_keysym_t (*xkb_compose_state_get_one_sym_dylibloader_wrapper_xkbcommon)(struct xkb_compose_state*);
int initialize_xkbcommon(int verbose);
#ifdef __cplusplus
}
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 2832495693..14778b5f03 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -3284,6 +3284,8 @@ DisplayServerMacOS::CursorShape DisplayServerMacOS::cursor_get_shape() const {
void DisplayServerMacOS::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
+
if (p_cursor.is_valid()) {
HashMap<CursorShape, Vector<Variant>>::Iterator cursor_c = cursors_cache.find(p_shape);
@@ -3681,8 +3683,23 @@ Rect2i DisplayServerMacOS::window_get_popup_safe_rect(WindowID p_window) const {
void DisplayServerMacOS::popup_open(WindowID p_window) {
_THREAD_SAFE_METHOD_
+ bool has_popup_ancestor = false;
+ WindowID transient_root = p_window;
+ while (true) {
+ WindowID parent = windows[transient_root].transient_parent;
+ if (parent == INVALID_WINDOW_ID) {
+ break;
+ } else {
+ transient_root = parent;
+ if (windows[parent].is_popup) {
+ has_popup_ancestor = true;
+ break;
+ }
+ }
+ }
+
WindowData &wd = windows[p_window];
- if (wd.is_popup) {
+ if (wd.is_popup || has_popup_ancestor) {
bool was_empty = popup_list.is_empty();
// Find current popup parent, or root popup if new window is not transient.
List<WindowID>::Element *C = nullptr;
@@ -3905,6 +3922,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
}
}
show_window(MAIN_WINDOW_ID);
+ force_process_and_drop_events();
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp
index 5c20016aa5..bb96308a75 100644
--- a/platform/macos/export/export_plugin.cpp
+++ b/platform/macos/export/export_plugin.cpp
@@ -48,16 +48,18 @@
#endif
void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const {
- if (p_preset->get("texture_format/s3tc")) {
+ r_features->push_back(p_preset->get("binary_format/architecture"));
+ String architecture = p_preset->get("binary_format/architecture");
+
+ if (architecture == "universal" || architecture == "x86_64") {
r_features->push_back("s3tc");
- }
- if (p_preset->get("texture_format/etc")) {
- r_features->push_back("etc");
- }
- if (p_preset->get("texture_format/etc2")) {
+ r_features->push_back("bptc");
+ } else if (architecture == "arm64") {
r_features->push_back("etc2");
+ r_features->push_back("astc");
+ } else {
+ ERR_PRINT("Invalid architecture");
}
- r_features->push_back(p_preset->get("binary_format/architecture"));
}
bool EditorExportPlatformMacOS::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const {
@@ -210,10 +212,6 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/removable_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
- r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
-
String run_script = "#!/usr/bin/env bash\n"
"unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"\n"
"open \"{temp_dir}/{exe_name}.app\" --args {cmd_args}";
@@ -1766,6 +1764,24 @@ bool EditorExportPlatformMacOS::has_valid_export_configuration(const Ref<EditorE
}
}
+ String architecture = p_preset->get("binary_format/architecture");
+
+ if (architecture == "universal" || architecture == "x86_64") {
+ const String bc_error = test_bc();
+ if (!bc_error.is_empty()) {
+ valid = false;
+ err += bc_error;
+ }
+ } else if (architecture == "arm64") {
+ const String etc_error = test_etc2();
+ if (!etc_error.is_empty()) {
+ valid = false;
+ err += etc_error;
+ }
+ } else {
+ ERR_PRINT("Invalid architecture");
+ }
+
// Look for export templates (official templates, check only is custom templates are not set).
if (!dvalid || !rvalid) {
dvalid = exists_export_template("macos.zip", &err);
diff --git a/platform/web/audio_driver_web.cpp b/platform/web/audio_driver_web.cpp
index a5234627d1..1d7b96d707 100644
--- a/platform/web/audio_driver_web.cpp
+++ b/platform/web/audio_driver_web.cpp
@@ -166,18 +166,18 @@ void AudioDriverWeb::finish() {
}
}
-Error AudioDriverWeb::capture_start() {
+Error AudioDriverWeb::input_start() {
lock();
input_buffer_init(buffer_length);
unlock();
- if (godot_audio_capture_start()) {
+ if (godot_audio_input_start()) {
return FAILED;
}
return OK;
}
-Error AudioDriverWeb::capture_stop() {
- godot_audio_capture_stop();
+Error AudioDriverWeb::input_stop() {
+ godot_audio_input_stop();
lock();
input_buffer.clear();
unlock();
diff --git a/platform/web/audio_driver_web.h b/platform/web/audio_driver_web.h
index f3afbdbb92..be13935bd9 100644
--- a/platform/web/audio_driver_web.h
+++ b/platform/web/audio_driver_web.h
@@ -77,12 +77,12 @@ public:
virtual void start() final;
virtual void finish() final;
- virtual float get_latency() override;
virtual int get_mix_rate() const override;
virtual SpeakerMode get_speaker_mode() const override;
+ virtual float get_latency() override;
- virtual Error capture_start() override;
- virtual Error capture_stop() override;
+ virtual Error input_start() override;
+ virtual Error input_stop() override;
static void resume();
@@ -111,10 +111,12 @@ protected:
virtual void finish_driver() override;
public:
- virtual const char *get_name() const override { return "AudioWorklet"; }
+ virtual const char *get_name() const override {
+ return "AudioWorklet";
+ }
- void lock() override;
- void unlock() override;
+ virtual void lock() override;
+ virtual void unlock() override;
};
#endif // AUDIO_DRIVER_WEB_H
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index d71fd60543..565d439a92 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -108,11 +108,19 @@ void DisplayServerWeb::request_quit_callback() {
// Keys
-void DisplayServerWeb::dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod) {
- ev->set_shift_pressed(p_mod & 1);
- ev->set_alt_pressed(p_mod & 2);
- ev->set_ctrl_pressed(p_mod & 4);
- ev->set_meta_pressed(p_mod & 8);
+void DisplayServerWeb::dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod, Key p_keycode) {
+ if (p_keycode != Key::SHIFT) {
+ ev->set_shift_pressed(p_mod & 1);
+ }
+ if (p_keycode != Key::ALT) {
+ ev->set_alt_pressed(p_mod & 2);
+ }
+ if (p_keycode != Key::CTRL) {
+ ev->set_ctrl_pressed(p_mod & 4);
+ }
+ if (p_keycode != Key::META) {
+ ev->set_meta_pressed(p_mod & 8);
+ }
}
void DisplayServerWeb::key_callback(int p_pressed, int p_repeat, int p_modifiers) {
@@ -138,7 +146,7 @@ void DisplayServerWeb::key_callback(int p_pressed, int p_repeat, int p_modifiers
ev->set_key_label(fix_key_label(c, keycode));
ev->set_unicode(fix_unicode(c));
ev->set_pressed(p_pressed);
- dom2godot_mod(ev, p_modifiers);
+ dom2godot_mod(ev, p_modifiers, fix_keycode(c, keycode));
Input::get_singleton()->parse_input_event(ev);
@@ -157,7 +165,7 @@ int DisplayServerWeb::mouse_button_callback(int p_pressed, int p_button, double
ev->set_position(pos);
ev->set_global_position(pos);
ev->set_pressed(p_pressed);
- dom2godot_mod(ev, p_modifiers);
+ dom2godot_mod(ev, p_modifiers, Key::NONE);
switch (p_button) {
case DOM_BUTTON_LEFT:
@@ -235,7 +243,7 @@ void DisplayServerWeb::mouse_move_callback(double p_x, double p_y, double p_rel_
Point2 pos(p_x, p_y);
Ref<InputEventMouseMotion> ev;
ev.instantiate();
- dom2godot_mod(ev, p_modifiers);
+ dom2godot_mod(ev, p_modifiers, Key::NONE);
ev->set_button_mask(input_mask);
ev->set_position(pos);
@@ -387,6 +395,7 @@ DisplayServer::CursorShape DisplayServerWeb::cursor_get_shape() const {
}
void DisplayServerWeb::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
if (p_cursor.is_valid()) {
Ref<Texture2D> texture = p_cursor;
Ref<AtlasTexture> atlas_texture = p_cursor;
diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h
index 6d76af4e56..2e50a6bbc8 100644
--- a/platform/web/display_server_web.h
+++ b/platform/web/display_server_web.h
@@ -81,7 +81,7 @@ private:
bool swap_cancel_ok = false;
// utilities
- static void dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod);
+ static void dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod, Key p_keycode);
static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape);
// events
diff --git a/platform/web/export/editor_http_server.h b/platform/web/export/editor_http_server.h
index ce6b0be713..3f87288537 100644
--- a/platform/web/export/editor_http_server.h
+++ b/platform/web/export/editor_http_server.h
@@ -205,8 +205,7 @@ public:
if (tls.is_null()) {
tls = Ref<StreamPeerTLS>(StreamPeerTLS::create());
peer = tls;
- tls->set_blocking_handshake_enabled(false);
- if (tls->accept_stream(tcp, key, cert) != OK) {
+ if (tls->accept_stream(tcp, TLSOptions::server(key, cert)) != OK) {
_clear_client();
return;
}
diff --git a/platform/web/godot_audio.h b/platform/web/godot_audio.h
index d7bff078f8..c6f92161fa 100644
--- a/platform/web/godot_audio.h
+++ b/platform/web/godot_audio.h
@@ -43,8 +43,8 @@ extern int godot_audio_has_script_processor();
extern int godot_audio_init(int *p_mix_rate, int p_latency, void (*_state_cb)(int), void (*_latency_cb)(float));
extern void godot_audio_resume();
-extern int godot_audio_capture_start();
-extern void godot_audio_capture_stop();
+extern int godot_audio_input_start();
+extern void godot_audio_input_stop();
// Worklet
typedef int32_t GodotAudioState[4];
diff --git a/platform/web/http_client_web.cpp b/platform/web/http_client_web.cpp
index 31f54dad9f..3e4ba5a2ae 100644
--- a/platform/web/http_client_web.cpp
+++ b/platform/web/http_client_web.cpp
@@ -37,20 +37,20 @@ void HTTPClientWeb::_parse_headers(int p_len, const char **p_headers, void *p_re
}
}
-Error HTTPClientWeb::connect_to_host(const String &p_host, int p_port, bool p_tls, bool p_verify_host) {
+Error HTTPClientWeb::connect_to_host(const String &p_host, int p_port, Ref<TLSOptions> p_tls_options) {
+ ERR_FAIL_COND_V(p_tls_options.is_valid() && p_tls_options->is_server(), ERR_INVALID_PARAMETER);
+
close();
- if (p_tls && !p_verify_host) {
- WARN_PRINT("Disabling HTTPClientWeb's host verification is not supported for the Web platform, host will be verified");
- }
port = p_port;
- use_tls = p_tls;
+ use_tls = p_tls_options.is_valid();
host = p_host;
String host_lower = host.to_lower();
if (host_lower.begins_with("http://")) {
host = host.substr(7, host.length() - 7);
+ use_tls = false;
} else if (host_lower.begins_with("https://")) {
use_tls = true;
host = host.substr(8, host.length() - 8);
diff --git a/platform/web/http_client_web.h b/platform/web/http_client_web.h
index 993ec6c0e2..def7837a27 100644
--- a/platform/web/http_client_web.h
+++ b/platform/web/http_client_web.h
@@ -86,7 +86,7 @@ public:
Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) override;
- Error connect_to_host(const String &p_host, int p_port = -1, bool p_tls = false, bool p_verify_host = true) override;
+ Error connect_to_host(const String &p_host, int p_port = -1, Ref<TLSOptions> p_tls_options = Ref<TLSOptions>()) override;
void set_connection(const Ref<StreamPeer> &p_connection) override;
Ref<StreamPeer> get_connection() const override;
void close() override;
diff --git a/platform/web/js/libs/library_godot_audio.js b/platform/web/js/libs/library_godot_audio.js
index 68348a3962..1993d66310 100644
--- a/platform/web/js/libs/library_godot_audio.js
+++ b/platform/web/js/libs/library_godot_audio.js
@@ -186,17 +186,17 @@ const GodotAudio = {
}
},
- godot_audio_capture_start__proxy: 'sync',
- godot_audio_capture_start__sig: 'i',
- godot_audio_capture_start: function () {
+ godot_audio_input_start__proxy: 'sync',
+ godot_audio_input_start__sig: 'i',
+ godot_audio_input_start: function () {
return GodotAudio.create_input(function (input) {
input.connect(GodotAudio.driver.get_node());
});
},
- godot_audio_capture_stop__proxy: 'sync',
- godot_audio_capture_stop__sig: 'v',
- godot_audio_capture_stop: function () {
+ godot_audio_input_stop__proxy: 'sync',
+ godot_audio_input_stop__sig: 'v',
+ godot_audio_input_stop: function () {
if (GodotAudio.input) {
const tracks = GodotAudio.input['mediaStream']['getTracks']();
for (let i = 0; i < tracks.length; i++) {
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 89a7114583..d2889a3442 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -829,6 +829,10 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
}
DestroyWindow(windows[p_window].hWnd);
windows.erase(p_window);
+
+ if (last_focused_window == p_window) {
+ last_focused_window = INVALID_WINDOW_ID;
+ }
}
void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_window_id) {
@@ -991,15 +995,6 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
window_set_position(wpos, p_window);
}
-
- // Don't let the mouse leave the window when resizing to a smaller resolution.
- if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
- RECT crect;
- GetClientRect(wd.hWnd, &crect);
- ClientToScreen(wd.hWnd, (POINT *)&crect.left);
- ClientToScreen(wd.hWnd, (POINT *)&crect.right);
- ClipCursor(&crect);
- }
}
Point2i DisplayServerWindows::window_get_position(WindowID p_window) const {
@@ -1077,15 +1072,6 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
AdjustWindowRectEx(&rc, style, false, exStyle);
MoveWindow(wd.hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
- // Don't let the mouse leave the window when moved.
- if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
- RECT rect;
- GetClientRect(wd.hWnd, &rect);
- ClientToScreen(wd.hWnd, (POINT *)&rect.left);
- ClientToScreen(wd.hWnd, (POINT *)&rect.right);
- ClipCursor(&rect);
- }
-
wd.last_pos = p_position;
_update_real_mouse_position(p_window);
}
@@ -1227,15 +1213,6 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
}
MoveWindow(wd.hWnd, rect.left, rect.top, w, h, TRUE);
-
- // Don't let the mouse leave the window when resizing to a smaller resolution.
- if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
- RECT crect;
- GetClientRect(wd.hWnd, &crect);
- ClientToScreen(wd.hWnd, (POINT *)&crect.left);
- ClientToScreen(wd.hWnd, (POINT *)&crect.right);
- ClipCursor(&crect);
- }
}
Size2i DisplayServerWindows::window_get_size(WindowID p_window) const {
@@ -1423,15 +1400,6 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window)
SystemParametersInfoA(SPI_SETMOUSETRAILS, 0, 0, 0);
}
}
-
- // Don't let the mouse leave the window when resizing to a smaller resolution.
- if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
- RECT crect;
- GetClientRect(wd.hWnd, &crect);
- ClientToScreen(wd.hWnd, (POINT *)&crect.left);
- ClientToScreen(wd.hWnd, (POINT *)&crect.right);
- ClipCursor(&crect);
- }
}
DisplayServer::WindowMode DisplayServerWindows::window_get_mode(WindowID p_window) const {
@@ -1626,7 +1594,7 @@ Vector2i DisplayServerWindows::ime_get_selection() const {
ImmGetCompositionStringW(wd.im_himc, GCS_COMPSTR, string, length);
int32_t utf32_cursor = 0;
- for (int32_t i = 0; i < length / sizeof(wchar_t); i++) {
+ for (int32_t i = 0; i < length / int32_t(sizeof(wchar_t)); i++) {
if ((string[i] & 0xfffffc00) == 0xd800) {
i++;
}
@@ -1751,6 +1719,8 @@ DisplayServer::CursorShape DisplayServerWindows::cursor_get_shape() const {
void DisplayServerWindows::cursor_set_custom_image(const Ref<Resource> &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
_THREAD_SAFE_METHOD_
+ ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
+
if (p_cursor.is_valid()) {
RBMap<CursorShape, Vector<Variant>>::Element *cursor_c = cursors_cache.find(p_shape);
@@ -2396,8 +2366,23 @@ Rect2i DisplayServerWindows::window_get_popup_safe_rect(WindowID p_window) const
void DisplayServerWindows::popup_open(WindowID p_window) {
_THREAD_SAFE_METHOD_
- const WindowData &wd = windows[p_window];
- if (wd.is_popup) {
+ bool has_popup_ancestor = false;
+ WindowID transient_root = p_window;
+ while (true) {
+ WindowID parent = windows[transient_root].transient_parent;
+ if (parent == INVALID_WINDOW_ID) {
+ break;
+ } else {
+ transient_root = parent;
+ if (windows[parent].is_popup) {
+ has_popup_ancestor = true;
+ break;
+ }
+ }
+ }
+
+ WindowData &wd = windows[p_window];
+ if (wd.is_popup || has_popup_ancestor) {
// Find current popup parent, or root popup if new window is not transient.
List<WindowID>::Element *C = nullptr;
List<WindowID>::Element *E = popup_list.back();
@@ -3381,6 +3366,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
Callable::CallError ce;
window.rect_changed_callback.callp(args, 1, ret, ce);
}
+
+ // Update cursor clip region after window rect has changed.
+ if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
+ RECT crect;
+ GetClientRect(window.hWnd, &crect);
+ ClientToScreen(window.hWnd, (POINT *)&crect.left);
+ ClientToScreen(window.hWnd, (POINT *)&crect.right);
+ ClipCursor(&crect);
+ }
}
// Return here to prevent WM_MOVE and WM_SIZE from being sent
@@ -3676,10 +3670,18 @@ void DisplayServerWindows::_process_key_events() {
}
k->set_window_id(ke.window_id);
- k->set_shift_pressed(ke.shift);
- k->set_alt_pressed(ke.alt);
- k->set_ctrl_pressed(ke.control);
- k->set_meta_pressed(ke.meta);
+ if (keycode != Key::SHIFT) {
+ k->set_shift_pressed(ke.shift);
+ }
+ if (keycode != Key::ALT) {
+ k->set_alt_pressed(ke.alt);
+ }
+ if (keycode != Key::CTRL) {
+ k->set_ctrl_pressed(ke.control);
+ }
+ if (keycode != Key::META) {
+ k->set_meta_pressed(ke.meta);
+ }
k->set_pressed(true);
k->set_keycode(keycode);
k->set_physical_keycode(physical_keycode);
@@ -3701,11 +3703,6 @@ void DisplayServerWindows::_process_key_events() {
k.instantiate();
k->set_window_id(ke.window_id);
- k->set_shift_pressed(ke.shift);
- k->set_alt_pressed(ke.alt);
- k->set_ctrl_pressed(ke.control);
- k->set_meta_pressed(ke.meta);
-
k->set_pressed(ke.uMsg == WM_KEYDOWN);
Key keycode = KeyMappingWindows::get_keysym(ke.wParam);
@@ -3727,6 +3724,18 @@ void DisplayServerWindows::_process_key_events() {
}
}
+ if (keycode != Key::SHIFT) {
+ k->set_shift_pressed(ke.shift);
+ }
+ if (keycode != Key::ALT) {
+ k->set_alt_pressed(ke.alt);
+ }
+ if (keycode != Key::CTRL) {
+ k->set_ctrl_pressed(ke.control);
+ }
+ if (keycode != Key::META) {
+ k->set_meta_pressed(ke.meta);
+ }
k->set_keycode(keycode);
k->set_physical_keycode(physical_keycode);
k->set_key_label(key_label);
@@ -3971,10 +3980,19 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
wd.im_position = Vector2();
- // FIXME this is wrong in cases where the window coordinates were changed due to full screen mode; use WindowRect
- wd.last_pos = p_rect.position;
- wd.width = p_rect.size.width;
- wd.height = p_rect.size.height;
+ if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN || p_mode == WINDOW_MODE_MAXIMIZED) {
+ RECT r;
+ GetClientRect(wd.hWnd, &r);
+ ClientToScreen(wd.hWnd, (POINT *)&r.left);
+ ClientToScreen(wd.hWnd, (POINT *)&r.right);
+ wd.last_pos = Point2i(r.left, r.top) - _get_screens_origin();
+ wd.width = r.right - r.left;
+ wd.height = r.bottom - r.top;
+ } else {
+ wd.last_pos = p_rect.position;
+ wd.width = p_rect.size.width;
+ wd.height = p_rect.size.height;
+ }
window_id_counter++;
}
diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h
index b97d0f667c..361c559a5a 100644
--- a/platform/windows/gl_manager_windows.h
+++ b/platform/windows/gl_manager_windows.h
@@ -74,7 +74,6 @@ private:
GLWindow *_current_window = nullptr;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr;
- PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr;
// funcs
void _internal_set_current_window(GLWindow *p_win);
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 08299d9b98..d384049fb5 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -830,7 +830,7 @@ class FallbackTextAnalysisSource : public IDWriteTextAnalysisSource {
IDWriteNumberSubstitution *n_sub = nullptr;
public:
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) {
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID **ppvInterface) override {
if (IID_IUnknown == riid) {
AddRef();
*ppvInterface = (IUnknown *)this;
@@ -844,11 +844,11 @@ public:
return S_OK;
}
- ULONG STDMETHODCALLTYPE AddRef() {
+ ULONG STDMETHODCALLTYPE AddRef() override {
return InterlockedIncrement(&_cRef);
}
- ULONG STDMETHODCALLTYPE Release() {
+ ULONG STDMETHODCALLTYPE Release() override {
ULONG ulRef = InterlockedDecrement(&_cRef);
if (0 == ulRef) {
delete this;