diff options
Diffstat (limited to 'platform')
26 files changed, 343 insertions, 104 deletions
diff --git a/platform/android/SCsub b/platform/android/SCsub index ecc72019e5..d031d14499 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -18,6 +18,7 @@ android_files = [ "jni_utils.cpp", "android_keys_utils.cpp", "display_server_android.cpp", + "plugin/godot_plugin_jni.cpp", "vulkan/vulkan_context_android.cpp", ] diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 15f61db27c..3d0dabc56e 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -253,6 +253,24 @@ DisplayServer::WindowID DisplayServerAndroid::get_window_at_screen_position(cons return MAIN_WINDOW_ID; } +int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)((OS_Android *)OS::get_singleton())->get_godot_java()->get_activity(); + } + case WINDOW_VIEW: { + return 0; // Not supported. + } + default: { + return 0; + } + } +} + void DisplayServerAndroid::window_attach_instance_id(ObjectID p_instance, DisplayServer::WindowID p_window) { window_attached_instance_id = p_instance; } diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 6aadc7e1a9..e52e07bf1a 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -124,6 +124,9 @@ public: virtual Vector<WindowID> get_window_list() const override; virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override; diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 78155fbef3..61d2f897ef 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -975,20 +975,6 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p } } - if (tname == "meta-data" && attrname == "name" && value == "xr_mode_metadata_name") { - // Update the meta-data 'android:name' attribute based on the selected XR mode. - if (xr_mode_index == XR_MODE_OPENXR) { - string_table.write[attr_value] = "com.samsung.android.vr.application.mode"; - } - } - - if (tname == "meta-data" && attrname == "value" && value == "xr_mode_metadata_value") { - // Update the meta-data 'android:value' attribute based on the selected XR mode. - if (xr_mode_index == XR_MODE_OPENXR) { - string_table.write[attr_value] = "vr_only"; - } - } - if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_metadata_name") { if (xr_mode_index == XR_MODE_OPENXR && hand_tracking_index > XR_HAND_TRACKING_NONE) { string_table.write[attr_value] = "com.oculus.handtracking.frequency"; diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp index 287b669fd1..babd8173d0 100644 --- a/platform/android/export/gradle_export_util.cpp +++ b/platform/android/export/gradle_export_util.cpp @@ -278,7 +278,6 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_ " android:requestLegacyExternalStorage=\"%s\"\n" " tools:replace=\"android:allowBackup,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n" " tools:ignore=\"GoogleAppIndexingWarning\">\n\n" - " <meta-data tools:node=\"remove\" android:name=\"xr_mode_metadata_name\" />\n" " <meta-data tools:node=\"remove\" android:name=\"xr_hand_tracking_metadata_name\" />\n", bool_to_string(p_preset->get("user_data_backup/allow")), bool_to_string(p_preset->get("package/classify_as_game")), @@ -286,8 +285,6 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_ bool_to_string(p_has_storage_permission)); if (uses_xr) { - manifest_application_text += " <meta-data tools:node=\"replace\" android:name=\"com.samsung.android.vr.application.mode\" android:value=\"vr_only\" />\n"; - bool hand_tracking_enabled = (int)(p_preset->get("xr_features/hand_tracking")) > XR_HAND_TRACKING_NONE; if (hand_tracking_enabled) { int hand_tracking_frequency_index = p_preset->get("xr_features/hand_tracking_frequency"); @@ -296,6 +293,8 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_ " <meta-data tools:node=\"replace\" android:name=\"com.oculus.handtracking.frequency\" android:value=\"%s\" />\n", hand_tracking_frequency); } + } 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 += " </application>\n"; diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index 3924aacccd..4c4501729d 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -33,11 +33,6 @@ <!-- 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 mode metadata. This is modified by the exporter based on the selected xr mode. DO NOT CHANGE the values here. --> - <meta-data - android:name="xr_mode_metadata_name" - android:value="xr_mode_metadata_value" /> - <!-- 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. --> @@ -45,6 +40,12 @@ android:name="xr_hand_tracking_metadata_name" android:value="xr_hand_tracking_metadata_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" diff --git a/platform/android/plugin/godot_plugin_jni.cpp b/platform/android/plugin/godot_plugin_jni.cpp index 2207eec18d..48aeb3d070 100644 --- a/platform/android/plugin/godot_plugin_jni.cpp +++ b/platform/android/plugin/godot_plugin_jni.cpp @@ -126,7 +126,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeEmitS env->DeleteLocalRef(j_param); }; - singleton->emit_signal(SNAME(signal_name), args, count); + singleton->emit_signal(StringName(signal_name), args, count); } JNIEXPORT void JNICALL Java_org_godotengine_godot_plugin_GodotPlugin_nativeRegisterGDNativeLibraries(JNIEnv *env, jclass clazz, jobjectArray gdnlib_paths) { diff --git a/platform/iphone/display_server_iphone.h b/platform/iphone/display_server_iphone.h index de04bc88e3..6434483641 100644 --- a/platform/iphone/display_server_iphone.h +++ b/platform/iphone/display_server_iphone.h @@ -135,6 +135,8 @@ public: virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm index 77e1a6078c..48bda89fc3 100644 --- a/platform/iphone/display_server_iphone.mm +++ b/platform/iphone/display_server_iphone.mm @@ -407,6 +407,24 @@ DisplayServer::WindowID DisplayServerIPhone::get_window_at_screen_position(const return MAIN_WINDOW_ID; } +int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)AppDelegate.viewController; + } + case WINDOW_VIEW: { + return (int64_t)AppDelegate.viewController.godotView; + } + default: { + return 0; + } + } +} + void DisplayServerIPhone::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { window_attached_instance_id = p_instance; } diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index ea17f1ac61..fe00b1a3cd 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -83,7 +83,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "iPhone Developer")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), "")); @@ -178,6 +178,10 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ "scaleAspectFill", "scaleToFill" }; + String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : p_preset->get("application/code_sign_identity_debug"); + String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : p_preset->get("application/code_sign_identity_release"); + bool dbg_manual = !p_preset->get("application/provisioning_profile_uuid_debug").operator String().is_empty() || (dbg_sign_id != "iPhone Developer"); + bool rel_manual = !p_preset->get("application/provisioning_profile_uuid_release").operator String().is_empty() || (rel_sign_id != "iPhone Distribution"); String str; String strnew; str.parse_utf8((const char *)pfile.ptr(), pfile.size()); @@ -218,13 +222,25 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n"; } else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) { strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n"; + } else if (lines[i].find("$code_sign_style_debug") != -1) { + if (dbg_manual) { + strnew += lines[i].replace("$code_sign_style_debug", "Manual") + "\n"; + } else { + strnew += lines[i].replace("$code_sign_style_debug", "Automatic") + "\n"; + } + } else if (lines[i].find("$code_sign_style_release") != -1) { + if (rel_manual) { + strnew += lines[i].replace("$code_sign_style_release", "Manual") + "\n"; + } else { + strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n"; + } } else if (lines[i].find("$provisioning_profile_uuid") != -1) { String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release"); strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n"; } else if (lines[i].find("$code_sign_identity_debug") != -1) { - strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n"; + strnew += lines[i].replace("$code_sign_identity_debug", dbg_sign_id) + "\n"; } else if (lines[i].find("$code_sign_identity_release") != -1) { - strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n"; + strnew += lines[i].replace("$code_sign_identity_release", rel_sign_id) + "\n"; } else if (lines[i].find("$additional_plist_content") != -1) { strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n"; } else if (lines[i].find("$godot_archs") != -1) { @@ -770,10 +786,18 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) { if (p_file.ends_with(".dylib")) { CodesignData *data = (CodesignData *)p_userdata; print_line(String("Signing ") + p_file); + + String sign_id; + if (data->debug) { + sign_id = data->preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : data->preset->get("application/code_sign_identity_debug"); + } else { + sign_id = data->preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : data->preset->get("application/code_sign_identity_release"); + } + List<String> codesign_args; codesign_args.push_back("-f"); codesign_args.push_back("-s"); - codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release")); + codesign_args.push_back(sign_id); codesign_args.push_back(p_file); return OS::get_singleton()->execute("codesign", codesign_args); } @@ -1680,6 +1704,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p archive_args.push_back("-destination"); archive_args.push_back("generic/platform=iOS"); archive_args.push_back("archive"); + archive_args.push_back("-allowProvisioningUpdates"); archive_args.push_back("-archivePath"); archive_args.push_back(archive_path); String archive_str; diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index 45aa68ce7c..c946302862 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -87,6 +87,11 @@ Error HTTPClientJavaScript::request(Method p_method, const String &p_url, const ERR_FAIL_COND_V(port < 0, ERR_UNCONFIGURED); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); + Error err = verify_headers(p_headers); + if (err) { + return err; + } + String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + p_url; Vector<CharString> keeper; Vector<const char *> c_strings; diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js index ba61b14eb7..5628ddbab5 100644 --- a/platform/javascript/js/engine/config.js +++ b/platform/javascript/js/engine/config.js @@ -225,33 +225,34 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- */ Config.prototype.update = function (opts) { const config = opts || {}; - function parse(key, def) { + const me = this; + function parse(key) { if (typeof (config[key]) === 'undefined') { - return def; + return me[key]; } return config[key]; } // Module config - this.unloadAfterInit = parse('unloadAfterInit', this.unloadAfterInit); - this.onPrintError = parse('onPrintError', this.onPrintError); - this.onPrint = parse('onPrint', this.onPrint); - this.onProgress = parse('onProgress', this.onProgress); + this.unloadAfterInit = parse('unloadAfterInit'); + this.onPrintError = parse('onPrintError'); + this.onPrint = parse('onPrint'); + this.onProgress = parse('onProgress'); // Godot config - this.canvas = parse('canvas', this.canvas); - this.executable = parse('executable', this.executable); - this.mainPack = parse('mainPack', this.mainPack); - this.locale = parse('locale', this.locale); - this.canvasResizePolicy = parse('canvasResizePolicy', this.canvasResizePolicy); - this.persistentPaths = parse('persistentPaths', this.persistentPaths); - this.persistentDrops = parse('persistentDrops', this.persistentDrops); - this.experimentalVK = parse('experimentalVK', this.experimentalVK); - this.focusCanvas = parse('focusCanvas', this.focusCanvas); - this.gdnativeLibs = parse('gdnativeLibs', this.gdnativeLibs); - this.fileSizes = parse('fileSizes', this.fileSizes); - this.args = parse('args', this.args); - this.onExecute = parse('onExecute', this.onExecute); - this.onExit = parse('onExit', this.onExit); + this.canvas = parse('canvas'); + this.executable = parse('executable'); + this.mainPack = parse('mainPack'); + this.locale = parse('locale'); + this.canvasResizePolicy = parse('canvasResizePolicy'); + this.persistentPaths = parse('persistentPaths'); + this.persistentDrops = parse('persistentDrops'); + this.experimentalVK = parse('experimentalVK'); + this.focusCanvas = parse('focusCanvas'); + this.gdnativeLibs = parse('gdnativeLibs'); + this.fileSizes = parse('fileSizes'); + this.args = parse('args'); + this.onExecute = parse('onExecute'); + this.onExit = parse('onExit'); }; /** diff --git a/platform/javascript/js/libs/library_godot_input.js b/platform/javascript/js/libs/library_godot_input.js index 7a4d0d8126..1e64c260f8 100644 --- a/platform/javascript/js/libs/library_godot_input.js +++ b/platform/javascript/js/libs/library_godot_input.js @@ -87,7 +87,7 @@ const GodotInputGamepads = { }, init: function (onchange) { - GodotEventListeners.samples = []; + GodotInputGamepads.samples = []; function add(pad) { const guid = GodotInputGamepads.get_guid(pad); const c_id = GodotRuntime.allocString(pad.id); diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 0ce627ca4f..198eacd1f3 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -323,20 +323,21 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { //flush pending motion events _flush_mouse_motion(); - WindowData &main_window = windows[MAIN_WINDOW_ID]; + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + WindowData &window = windows[window_id]; if (XGrabPointer( - x11_display, main_window.x11_window, True, + x11_display, window.x11_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, windows[MAIN_WINDOW_ID].x11_window, None, CurrentTime) != GrabSuccess) { + GrabModeAsync, GrabModeAsync, window.x11_window, None, CurrentTime) != GrabSuccess) { ERR_PRINT("NO GRAB"); } if (mouse_mode == MOUSE_MODE_CAPTURED) { - center.x = main_window.size.width / 2; - center.y = main_window.size.height / 2; + center.x = window.size.width / 2; + center.y = window.size.height / 2; - XWarpPointer(x11_display, None, main_window.x11_window, + XWarpPointer(x11_display, None, window.x11_window, 0, 0, 0, 0, (int)center.x, (int)center.y); Input::get_singleton()->set_mouse_position(center); @@ -358,7 +359,8 @@ void DisplayServerX11::mouse_warp_to_position(const Point2i &p_to) { if (mouse_mode == MOUSE_MODE_CAPTURED) { last_mouse_pos = p_to; } else { - XWarpPointer(x11_display, None, windows[MAIN_WINDOW_ID].x11_window, + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + XWarpPointer(x11_display, None, windows[window_id].x11_window, 0, 0, 0, 0, (int)p_to.x, (int)p_to.y); } } @@ -1154,6 +1156,24 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { windows.erase(p_id); } +int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return (int64_t)x11_display; + } + case WINDOW_HANDLE: { + return (int64_t)windows[p_window].x11_window; + } + case WINDOW_VIEW: { + return 0; // Not supported. + } + default: { + return 0; + } + } +} + void DisplayServerX11::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; @@ -1314,8 +1334,9 @@ int DisplayServerX11::window_get_current_screen(WindowID p_window) const { void DisplayServerX11::gl_window_make_current(DisplayServer::WindowID p_window_id) { #if defined(GLES3_ENABLED) - if (gl_manager) + if (gl_manager) { gl_manager->window_make_current(p_window_id); + } #endif } @@ -3334,7 +3355,7 @@ void DisplayServerX11::process_events() { DEBUG_LOG_X11("[%u] FocusIn window=%lu (%u), mode='%u' \n", frame, event.xfocus.window, window_id, event.xfocus.mode); WindowData &wd = windows[window_id]; - + last_focused_window = window_id; wd.focused = true; if (wd.xic) { @@ -3534,9 +3555,9 @@ void DisplayServerX11::process_events() { // The X11 API requires filtering one-by-one through the motion // notify events, in order to figure out which event is the one // generated by warping the mouse pointer. - + WindowID focused_window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; while (true) { - if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[MAIN_WINDOW_ID].size.width / 2 && event.xmotion.y == windows[MAIN_WINDOW_ID].size.height / 2) { + if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[focused_window_id].size.width / 2 && event.xmotion.y == windows[focused_window_id].size.height / 2) { //this is likely the warp event since it was warped here center = Vector2(event.xmotion.x, event.xmotion.y); break; @@ -3611,9 +3632,8 @@ void DisplayServerX11::process_events() { // Reset to prevent lingering motion xi.relative_motion.x = 0; xi.relative_motion.y = 0; - if (mouse_mode == MOUSE_MODE_CAPTURED) { - pos = Point2i(windows[MAIN_WINDOW_ID].size.width / 2, windows[MAIN_WINDOW_ID].size.height / 2); + pos = Point2i(windows[focused_window_id].size.width / 2, windows[focused_window_id].size.height / 2); } Ref<InputEventMouseMotion> mm; diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 8929f528d6..c17e120db5 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -143,7 +143,7 @@ class DisplayServerX11 : public DisplayServer { bool borderless = false; bool resize_disabled = false; Vector2i last_position_before_fs; - bool focused = false; + bool focused = true; bool minimized = false; unsigned int focus_order = 0; @@ -151,6 +151,8 @@ class DisplayServerX11 : public DisplayServer { Map<WindowID, WindowData> windows; + WindowID last_focused_window = INVALID_WINDOW_ID; + WindowID window_id_counter = MAIN_WINDOW_ID; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); @@ -316,6 +318,8 @@ public: virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; diff --git a/platform/linuxbsd/gl_manager_x11.cpp b/platform/linuxbsd/gl_manager_x11.cpp index 1721d0e0b3..d3fb1d6705 100644 --- a/platform/linuxbsd/gl_manager_x11.cpp +++ b/platform/linuxbsd/gl_manager_x11.cpp @@ -68,8 +68,9 @@ static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) { int GLManager_X11::_find_or_create_display(Display *p_x11_display) { for (unsigned int n = 0; n < _displays.size(); n++) { const GLDisplay &d = _displays[n]; - if (d.x11_display == p_x11_display) + if (d.x11_display == p_x11_display) { return n; + } } // create @@ -82,8 +83,7 @@ int GLManager_X11::_find_or_create_display(Display *p_x11_display) { GLDisplay &d = _displays[new_display_id]; d.context = memnew(GLManager_X11_Private); - ; - d.context->glx_context = 0; + d.context->glx_context = nullptr; //Error err = _create_context(d); _create_context(d); @@ -124,7 +124,7 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) { }; int fbcount; - GLXFBConfig fbconfig = 0; + GLXFBConfig fbconfig = nullptr; XVisualInfo *vi = nullptr; gl_display.x_swa.event_mask = StructureNotifyMask; @@ -137,8 +137,9 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) { for (int i = 0; i < fbcount; i++) { vi = (XVisualInfo *)glXGetVisualFromFBConfig(x11_display, fbc[i]); - if (!vi) + if (!vi) { continue; + } XRenderPictFormat *pict_format = XRenderFindVisualFormat(x11_display, vi->visual); if (!pict_format) { @@ -262,22 +263,26 @@ void GLManager_X11::window_destroy(DisplayServer::WindowID p_window_id) { } void GLManager_X11::release_current() { - if (!_current_window) + if (!_current_window) { return; + } glXMakeCurrent(_x_windisp.x11_display, None, nullptr); } void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { - if (p_window_id == -1) + if (p_window_id == -1) { return; + } GLWindow &win = _windows[p_window_id]; - if (!win.in_use) + if (!win.in_use) { return; + } // noop - if (&win == _current_window) + if (&win == _current_window) { return; + } const GLDisplay &disp = get_display(win.gldisplay_id); @@ -287,8 +292,9 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { } void GLManager_X11::make_current() { - if (!_current_window) + if (!_current_window) { return; + } if (!_current_window->in_use) { WARN_PRINT("current window not in use!"); return; @@ -301,8 +307,9 @@ void GLManager_X11::swap_buffers() { // NO NEED TO CALL SWAP BUFFERS for each window... // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml - if (!_current_window) + if (!_current_window) { return; + } if (!_current_window->in_use) { WARN_PRINT("current window not in use!"); return; @@ -335,19 +342,23 @@ void GLManager_X11::set_use_vsync(bool p_use) { } // we need an active window to get a display to set the vsync - if (!_current_window) + if (!_current_window) { return; + } const GLDisplay &disp = get_current_display(); if (!setup) { setup = true; String extensions = glXQueryExtensionsString(disp.x11_display, DefaultScreen(disp.x11_display)); - if (extensions.find("GLX_EXT_swap_control") != -1) + if (extensions.find("GLX_EXT_swap_control") != -1) { glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT"); - if (extensions.find("GLX_MESA_swap_control") != -1) + } + if (extensions.find("GLX_MESA_swap_control") != -1) { glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA"); - if (extensions.find("GLX_SGI_swap_control") != -1) + } + if (extensions.find("GLX_SGI_swap_control") != -1) { glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI"); + } } int val = p_use ? 1 : 0; if (glXSwapIntervalMESA) { @@ -357,8 +368,9 @@ void GLManager_X11::set_use_vsync(bool p_use) { } else if (glXSwapIntervalEXT) { GLXDrawable drawable = glXGetCurrentDrawable(); glXSwapIntervalEXT(disp.x11_display, drawable, val); - } else + } else { return; + } use_vsync = p_use; } diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index b5f127bb16..e95a865636 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -448,7 +448,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) { // Create needed directories for decided trash can location. { - DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Error err = dir_access->make_dir_recursive(trash_path); // Issue an error if trash can is not created properly. @@ -457,7 +457,6 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) { ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files"); err = dir_access->make_dir_recursive(trash_path + "/info"); ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info"); - memdelete(dir_access); } // The trash can is successfully created, now we check that we don't exceed our file name length limit. @@ -497,16 +496,15 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) { String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n"; { Error err; - FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err); + FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err); ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo"); file->store_string(trash_info); file->close(); // Rename our resource before moving it to the trash can. - DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name); ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\""); - memdelete(dir_access); } // Move the given resource to the trash can. diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index d609a84e50..719a45c2a8 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -145,6 +145,8 @@ public: Map<WindowID, WindowData> windows; + WindowID last_focused_window = INVALID_WINDOW_ID; + WindowID window_id_counter = MAIN_WINDOW_ID; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect); @@ -282,6 +284,8 @@ public: virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; virtual void gl_window_make_current(DisplayServer::WindowID p_window_id) override; diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 1340aad9b2..f7add5b688 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -321,6 +321,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { } DS_OSX->window_focused = true; + DS_OSX->last_focused_window = window_id; DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); } @@ -355,6 +356,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; DS_OSX->window_focused = true; + DS_OSX->last_focused_window = window_id; DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); } @@ -1913,7 +1915,8 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { return; } - WindowData &wd = windows[MAIN_WINDOW_ID]; + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + WindowData &wd = windows[window_id]; if (p_mode == MOUSE_MODE_CAPTURED) { // Apple Docs state that the display parameter is not used. // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." @@ -1972,7 +1975,8 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) { if (mouse_mode == MOUSE_MODE_CAPTURED) { last_mouse_pos = p_to; } else { - WindowData &wd = windows[MAIN_WINDOW_ID]; + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + WindowData &wd = windows[window_id]; //local point in window coords const NSRect contentRect = [wd.window_view frame]; @@ -3526,6 +3530,24 @@ DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Po return INVALID_WINDOW_ID; } +int64_t DisplayServerOSX::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)windows[p_window].window_object; + } + case WINDOW_VIEW: { + return (int64_t)windows[p_window].window_view; + } + default: { + return 0; + } + } +} + void DisplayServerOSX::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { _THREAD_SAFE_METHOD_ diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 4d1f72f5c9..f0b58efb63 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -777,6 +777,24 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources"); } + Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); + if (translations.size() > 0) { + { + String fname = tmp_app_path_name + "/Contents/Resources/en.lproj"; + tmp_app_dir->make_dir_recursive(fname); + FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + } + + for (const String &E : translations) { + Ref<Translation> tr = ResourceLoader::load(E); + if (tr.is_valid()) { + String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj"; + tmp_app_dir->make_dir_recursive(fname); + FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + } + } + } + // Now process our template. bool found_binary = false; Vector<String> dylibs_found; diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index c9e2251b35..d288c27016 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -97,7 +97,10 @@ String DisplayServerWindows::get_name() const { void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { if (windows.has(MAIN_WINDOW_ID) && (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN)) { // Mouse is grabbed (captured or confined). - WindowData &wd = windows[MAIN_WINDOW_ID]; + + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + + WindowData &wd = windows[window_id]; RECT clipRect; GetClientRect(wd.hWnd, &clipRect); @@ -570,6 +573,24 @@ void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_wind #endif } +int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)windows[p_window].hWnd; + } + case WINDOW_VIEW: { + return 0; // Not supported. + } + default: { + return 0; + } + } +} + void DisplayServerWindows::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -688,6 +709,15 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); window_set_position(ofs + screen_get_position(p_screen), 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 { @@ -1050,6 +1080,15 @@ 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 { @@ -2879,6 +2918,9 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id, WPARAM alt_mem = false; control_mem = false; shift_mem = false; + + // Restore mouse mode. + _set_mouse_mode_impl(mouse_mode); } else { // WM_INACTIVE. Input::get_singleton()->release_pressed_events(); _send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_OUT); diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 3593dc1a05..803c2d4836 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -472,6 +472,8 @@ public: virtual void show_window(WindowID p_window) override; virtual void delete_sub_window(WindowID p_window) override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 68762db3a9..d30d0afc5c 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -76,8 +76,8 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), "")); @@ -89,6 +89,7 @@ void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); if (rcedit_path.is_empty()) { + WARN_PRINT("The rcedit tool is not configured in the Editor Settings (Export > Windows > Rcedit). No custom icon or app information data will be embedded in the exported executable."); return; } @@ -327,3 +328,46 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p return OK; } + +bool EditorExportPlatformWindows::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { + String err = ""; + bool valid = EditorExportPlatformPC::can_export(p_preset, err, r_missing_templates); + + String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); + if (rcedit_path.is_empty()) { + err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > Rcedit) to change the icon or app information data.") + "\n"; + } + + String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon")); + if (!icon_path.is_empty() && !FileAccess::exists(icon_path)) { + err += TTR("Invalid icon path:") + " " + icon_path + "\n"; + } + + // Only non-negative integers can exist in the version string. + + String file_version = p_preset->get("application/file_version"); + if (!file_version.is_empty()) { + PackedStringArray version_array = file_version.split(".", false); + if (version_array.size() != 4 || !version_array[0].is_valid_int() || + !version_array[1].is_valid_int() || !version_array[2].is_valid_int() || + !version_array[3].is_valid_int() || file_version.find("-") > -1) { + err += TTR("Invalid file version:") + " " + file_version + "\n"; + } + } + + String product_version = p_preset->get("application/product_version"); + if (!product_version.is_empty()) { + PackedStringArray version_array = product_version.split(".", false); + if (version_array.size() != 4 || !version_array[0].is_valid_int() || + !version_array[1].is_valid_int() || !version_array[2].is_valid_int() || + !version_array[3].is_valid_int() || product_version.find("-") > -1) { + err += TTR("Invalid product version:") + " " + product_version + "\n"; + } + } + + if (!err.is_empty()) { + r_error = err; + } + + return valid; +} diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 351333aa42..89e5b1b635 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -47,6 +47,7 @@ public: virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; virtual void get_export_options(List<ExportOption> *r_options) override; virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; }; #endif diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp index 7819ab9a32..618d5670d2 100644 --- a/platform/windows/godot_windows.cpp +++ b/platform/windows/godot_windows.cpp @@ -39,7 +39,7 @@ #ifndef TOOLS_ENABLED #if defined _MSC_VER #pragma section("pck", read) -__declspec(allocate("pck")) static char dummy[8] = { 0 }; +__declspec(allocate("pck")) static const char dummy[8] = { 0 }; #elif defined __GNUC__ static const char dummy[8] __attribute__((section("pck"), used)) = { 0 }; #endif @@ -140,6 +140,11 @@ int widechar_main(int argc, wchar_t **argv) { setlocale(LC_CTYPE, ""); +#ifndef TOOLS_ENABLED + // Workaround to prevent LTCG (MSVC LTO) from removing "pck" section + const char *dummy_guard = dummy; +#endif + char **argv_utf8 = new char *[argc]; for (int i = 0; i < argc; ++i) { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 06b8fea681..d844531071 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -83,15 +83,23 @@ static String format_error_message(DWORD id) { return msg; } +void RedirectStream(const char *p_file_name, const char *p_mode, FILE *p_cpp_stream, const DWORD p_std_handle) { + const HANDLE h_existing = GetStdHandle(p_std_handle); + if (h_existing != INVALID_HANDLE_VALUE) { // Redirect only if attached console have a valid handle. + const HANDLE h_cpp = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(p_cpp_stream))); + if (h_cpp == INVALID_HANDLE_VALUE) { // Redirect only if it's not already redirected to the pipe or file. + FILE *fp = p_cpp_stream; + freopen_s(&fp, p_file_name, p_mode, p_cpp_stream); // Redirect stream. + setvbuf(p_cpp_stream, nullptr, _IONBF, 0); // Disable stream buffering. + } + } +} + void RedirectIOToConsole() { if (AttachConsole(ATTACH_PARENT_PROCESS)) { - FILE *fpstdin = stdin; - FILE *fpstdout = stdout; - FILE *fpstderr = stderr; - - freopen_s(&fpstdin, "CONIN$", "r", stdin); - freopen_s(&fpstdout, "CONOUT$", "w", stdout); - freopen_s(&fpstderr, "CONOUT$", "w", stderr); + RedirectStream("CONIN$", "r", stdin, STD_INPUT_HANDLE); + RedirectStream("CONOUT$", "w", stdout, STD_OUTPUT_HANDLE); + RedirectStream("CONOUT$", "w", stderr, STD_ERROR_HANDLE); printf("\n"); // Make sure our output is starting from the new line. } @@ -385,14 +393,14 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, } inherit_handles = true; } - DWORD creaton_flags = NORMAL_PRIORITY_CLASS; + DWORD creation_flags = NORMAL_PRIORITY_CLASS; if (p_open_console) { - creaton_flags |= CREATE_NEW_CONSOLE; + creation_flags |= CREATE_NEW_CONSOLE; } else { - creaton_flags |= CREATE_NO_WINDOW; + creation_flags |= CREATE_NO_WINDOW; } - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, inherit_handles, creaton_flags, nullptr, nullptr, si_w, &pi.pi); + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, inherit_handles, creation_flags, nullptr, nullptr, si_w, &pi.pi); if (!ret && r_pipe) { CloseHandle(pipe[0]); // Cleanup pipe handles. CloseHandle(pipe[1]); @@ -446,14 +454,14 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg ZeroMemory(&pi.pi, sizeof(pi.pi)); LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si; - DWORD creaton_flags = NORMAL_PRIORITY_CLASS; + DWORD creation_flags = NORMAL_PRIORITY_CLASS; if (p_open_console) { - creaton_flags |= CREATE_NEW_CONSOLE; + creation_flags |= CREATE_NEW_CONSOLE; } else { - creaton_flags |= CREATE_NO_WINDOW; + creation_flags |= CREATE_NO_WINDOW; } - int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, creaton_flags, nullptr, nullptr, si_w, &pi.pi); + int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, creation_flags, nullptr, nullptr, si_w, &pi.pi); ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command); ProcessID pid = pi.pi.dwProcessId; |