Merge pull request #55987 from bruvzg/wt🤎3
This commit is contained in:
commit
8a192cd0ab
19 changed files with 87 additions and 173 deletions
|
@ -36,6 +36,7 @@
|
||||||
#include "core/io/json.h"
|
#include "core/io/json.h"
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/math/geometry.h"
|
#include "core/math/geometry.h"
|
||||||
|
#include "core/method_bind_ext.gen.inc"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/project_settings.h"
|
#include "core/project_settings.h"
|
||||||
|
@ -471,7 +472,7 @@ Error _OS::shell_open(String p_uri) {
|
||||||
return OS::get_singleton()->shell_open(p_uri);
|
return OS::get_singleton()->shell_open(p_uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output, bool p_read_stderr) {
|
int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, Array p_output, bool p_read_stderr, bool p_open_console) {
|
||||||
OS::ProcessID pid = -2;
|
OS::ProcessID pid = -2;
|
||||||
int exitcode = 0;
|
int exitcode = 0;
|
||||||
List<String> args;
|
List<String> args;
|
||||||
|
@ -479,7 +480,7 @@ int _OS::execute(const String &p_path, const Vector<String> &p_arguments, bool p
|
||||||
args.push_back(p_arguments[i]);
|
args.push_back(p_arguments[i]);
|
||||||
}
|
}
|
||||||
String pipe;
|
String pipe;
|
||||||
Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, &exitcode, p_read_stderr);
|
Error err = OS::get_singleton()->execute(p_path, args, p_blocking, &pid, &pipe, &exitcode, p_read_stderr, nullptr, p_open_console);
|
||||||
p_output.clear();
|
p_output.clear();
|
||||||
p_output.push_back(pipe);
|
p_output.push_back(pipe);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
|
@ -1311,7 +1312,7 @@ void _OS::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_processor_count"), &_OS::get_processor_count);
|
ClassDB::bind_method(D_METHOD("get_processor_count"), &_OS::get_processor_count);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_executable_path"), &_OS::get_executable_path);
|
ClassDB::bind_method(D_METHOD("get_executable_path"), &_OS::get_executable_path);
|
||||||
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "blocking", "output", "read_stderr"), &_OS::execute, DEFVAL(true), DEFVAL(Array()), DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "blocking", "output", "read_stderr", "open_console"), &_OS::execute, DEFVAL(true), DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
|
||||||
ClassDB::bind_method(D_METHOD("kill", "pid"), &_OS::kill);
|
ClassDB::bind_method(D_METHOD("kill", "pid"), &_OS::kill);
|
||||||
ClassDB::bind_method(D_METHOD("shell_open", "uri"), &_OS::shell_open);
|
ClassDB::bind_method(D_METHOD("shell_open", "uri"), &_OS::shell_open);
|
||||||
ClassDB::bind_method(D_METHOD("get_process_id"), &_OS::get_process_id);
|
ClassDB::bind_method(D_METHOD("get_process_id"), &_OS::get_process_id);
|
||||||
|
|
|
@ -241,7 +241,7 @@ public:
|
||||||
int get_low_processor_usage_mode_sleep_usec() const;
|
int get_low_processor_usage_mode_sleep_usec() const;
|
||||||
|
|
||||||
String get_executable_path() const;
|
String get_executable_path() const;
|
||||||
int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking = true, Array p_output = Array(), bool p_read_stderr = false);
|
int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking = true, Array p_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
|
||||||
|
|
||||||
Error kill(int p_pid);
|
Error kill(int p_pid);
|
||||||
Error shell_open(String p_uri);
|
Error shell_open(String p_uri);
|
||||||
|
|
|
@ -234,8 +234,6 @@ public:
|
||||||
virtual void set_window_always_on_top(bool p_enabled) {}
|
virtual void set_window_always_on_top(bool p_enabled) {}
|
||||||
virtual bool is_window_always_on_top() const { return false; }
|
virtual bool is_window_always_on_top() const { return false; }
|
||||||
virtual bool is_window_focused() const { return true; }
|
virtual bool is_window_focused() const { return true; }
|
||||||
virtual void set_console_visible(bool p_enabled) {}
|
|
||||||
virtual bool is_console_visible() const { return false; }
|
|
||||||
virtual void request_attention() {}
|
virtual void request_attention() {}
|
||||||
virtual void center_window();
|
virtual void center_window();
|
||||||
|
|
||||||
|
@ -290,7 +288,7 @@ public:
|
||||||
virtual int get_low_processor_usage_mode_sleep_usec() const;
|
virtual int get_low_processor_usage_mode_sleep_usec() const;
|
||||||
|
|
||||||
virtual String get_executable_path() const;
|
virtual String get_executable_path() const;
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) = 0;
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) = 0;
|
||||||
virtual Error kill(const ProcessID &p_pid) = 0;
|
virtual Error kill(const ProcessID &p_pid) = 0;
|
||||||
virtual int get_process_id() const;
|
virtual int get_process_id() const;
|
||||||
virtual void vibrate_handheld(int p_duration_ms = 500);
|
virtual void vibrate_handheld(int p_duration_ms = 500);
|
||||||
|
|
|
@ -92,12 +92,14 @@
|
||||||
<argument index="2" name="blocking" type="bool" default="true" />
|
<argument index="2" name="blocking" type="bool" default="true" />
|
||||||
<argument index="3" name="output" type="Array" default="[ ]" />
|
<argument index="3" name="output" type="Array" default="[ ]" />
|
||||||
<argument index="4" name="read_stderr" type="bool" default="false" />
|
<argument index="4" name="read_stderr" type="bool" default="false" />
|
||||||
|
<argument index="5" name="open_console" type="bool" default="false" />
|
||||||
<description>
|
<description>
|
||||||
Execute the file at the given path with the arguments passed as an array of strings. Platform path resolution will take place. The resolved file must exist and be executable.
|
Execute the file at the given path with the arguments passed as an array of strings. Platform path resolution will take place. The resolved file must exist and be executable.
|
||||||
The arguments are used in the given order and separated by a space, so [code]OS.execute("ping", ["-w", "3", "godotengine.org"], false)[/code] will resolve to [code]ping -w 3 godotengine.org[/code] in the system's shell.
|
The arguments are used in the given order and separated by a space, so [code]OS.execute("ping", ["-w", "3", "godotengine.org"], false)[/code] will resolve to [code]ping -w 3 godotengine.org[/code] in the system's shell.
|
||||||
This method has slightly different behavior based on whether the [code]blocking[/code] mode is enabled.
|
This method has slightly different behavior based on whether the [code]blocking[/code] mode is enabled.
|
||||||
If [code]blocking[/code] is [code]true[/code], the Godot thread will pause its execution while waiting for the process to terminate. The shell output of the process will be written to the [code]output[/code] array as a single string. When the process terminates, the Godot thread will resume execution.
|
If [code]blocking[/code] is [code]true[/code], the Godot thread will pause its execution while waiting for the process to terminate. The shell output of the process will be written to the [code]output[/code] array as a single string. When the process terminates, the Godot thread will resume execution.
|
||||||
If [code]blocking[/code] is [code]false[/code], the Godot thread will continue while the new process runs. It is not possible to retrieve the shell output in non-blocking mode, so [code]output[/code] will be empty.
|
If [code]blocking[/code] is [code]false[/code], the Godot thread will continue while the new process runs. It is not possible to retrieve the shell output in non-blocking mode, so [code]output[/code] will be empty.
|
||||||
|
On Windows, if [code]open_console[/code] is [code]true[/code] and process is console app, new terminal window will be opened, it's ignored on other platforms.
|
||||||
The return value also depends on the blocking mode. When blocking, the method will return an exit code of the process. When non-blocking, the method returns a process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process forking (non-blocking) or opening (blocking) fails, the method will return [code]-1[/code] or another exit code.
|
The return value also depends on the blocking mode. When blocking, the method will return an exit code of the process. When non-blocking, the method returns a process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process forking (non-blocking) or opening (blocking) fails, the method will return [code]-1[/code] or another exit code.
|
||||||
Example of blocking mode and retrieving the shell output:
|
Example of blocking mode and retrieving the shell output:
|
||||||
[codeblock]
|
[codeblock]
|
||||||
|
|
|
@ -260,7 +260,7 @@ uint64_t OS_Unix::get_ticks_usec() const {
|
||||||
return longtime;
|
return longtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
|
Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
// Don't compile this code at all to avoid undefined references.
|
// Don't compile this code at all to avoid undefined references.
|
||||||
// Actual virtual call goes to OS_JavaScript.
|
// Actual virtual call goes to OS_JavaScript.
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
virtual void delay_usec(uint32_t p_usec) const;
|
virtual void delay_usec(uint32_t p_usec) const;
|
||||||
virtual uint64_t get_ticks_usec() const;
|
virtual uint64_t get_ticks_usec() const;
|
||||||
|
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr);
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false);
|
||||||
virtual Error kill(const ProcessID &p_pid);
|
virtual Error kill(const ProcessID &p_pid);
|
||||||
virtual int get_process_id() const;
|
virtual int get_process_id() const;
|
||||||
|
|
||||||
|
|
|
@ -2813,11 +2813,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
|
||||||
OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen());
|
OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen());
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case SETTINGS_TOGGLE_CONSOLE: {
|
|
||||||
bool was_visible = OS::get_singleton()->is_console_visible();
|
|
||||||
OS::get_singleton()->set_console_visible(!was_visible);
|
|
||||||
EditorSettings::get_singleton()->set_setting("interface/editor/hide_console_window", was_visible);
|
|
||||||
} break;
|
|
||||||
case EDITOR_SCREENSHOT: {
|
case EDITOR_SCREENSHOT: {
|
||||||
screenshot_timer->start();
|
screenshot_timer->start();
|
||||||
} break;
|
} break;
|
||||||
|
@ -6454,9 +6449,6 @@ EditorNode::EditorNode() {
|
||||||
p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F), SETTINGS_TOGGLE_FULLSCREEN);
|
p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F), SETTINGS_TOGGLE_FULLSCREEN);
|
||||||
#else
|
#else
|
||||||
p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN);
|
p->add_shortcut(ED_SHORTCUT("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KEY_MASK_SHIFT | KEY_F11), SETTINGS_TOGGLE_FULLSCREEN);
|
||||||
#endif
|
|
||||||
#ifdef WINDOWS_ENABLED
|
|
||||||
p->add_item(TTR("Toggle System Console"), SETTINGS_TOGGLE_CONSOLE);
|
|
||||||
#endif
|
#endif
|
||||||
p->add_separator();
|
p->add_separator();
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,6 @@ private:
|
||||||
SETTINGS_MANAGE_FEATURE_PROFILES,
|
SETTINGS_MANAGE_FEATURE_PROFILES,
|
||||||
SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE,
|
SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE,
|
||||||
SETTINGS_PICK_MAIN_SCENE,
|
SETTINGS_PICK_MAIN_SCENE,
|
||||||
SETTINGS_TOGGLE_CONSOLE,
|
|
||||||
SETTINGS_TOGGLE_FULLSCREEN,
|
SETTINGS_TOGGLE_FULLSCREEN,
|
||||||
SETTINGS_HELP,
|
SETTINGS_HELP,
|
||||||
SCENE_TAB_CLOSE,
|
SCENE_TAB_CLOSE,
|
||||||
|
|
|
@ -335,7 +335,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
||||||
hints["interface/editor/unfocused_low_processor_mode_sleep_usec"] = PropertyInfo(Variant::REAL, "interface/editor/unfocused_low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,1000000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
|
hints["interface/editor/unfocused_low_processor_mode_sleep_usec"] = PropertyInfo(Variant::REAL, "interface/editor/unfocused_low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,1000000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
|
||||||
_initial_set("interface/editor/separate_distraction_mode", false);
|
_initial_set("interface/editor/separate_distraction_mode", false);
|
||||||
_initial_set("interface/editor/automatically_open_screenshots", true);
|
_initial_set("interface/editor/automatically_open_screenshots", true);
|
||||||
_initial_set("interface/editor/hide_console_window", false);
|
|
||||||
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
|
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
|
||||||
_initial_set("interface/editor/quit_confirmation", true);
|
_initial_set("interface/editor/quit_confirmation", true);
|
||||||
|
|
||||||
|
|
|
@ -2123,10 +2123,6 @@ bool Main::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (project_manager || editor) {
|
if (project_manager || editor) {
|
||||||
// Hide console window if requested (Windows-only).
|
|
||||||
bool hide_console = EditorSettings::get_singleton()->get_setting("interface/editor/hide_console_window");
|
|
||||||
OS::get_singleton()->set_console_visible(!hide_console);
|
|
||||||
|
|
||||||
// Load SSL Certificates from Editor Settings (or builtin)
|
// Load SSL Certificates from Editor Settings (or builtin)
|
||||||
Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
|
Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
|
||||||
}
|
}
|
||||||
|
|
|
@ -890,7 +890,7 @@ void OS_JavaScript::finalize() {
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
|
||||||
Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
|
Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||||
Array args;
|
Array args;
|
||||||
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
|
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
|
||||||
args.push_back(E->get());
|
args.push_back(E->get());
|
||||||
|
|
|
@ -168,7 +168,7 @@ public:
|
||||||
virtual MainLoop *get_main_loop() const;
|
virtual MainLoop *get_main_loop() const;
|
||||||
bool main_loop_iterate();
|
bool main_loop_iterate();
|
||||||
|
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL);
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL, bool p_open_console = false);
|
||||||
virtual Error kill(const ProcessID &p_pid);
|
virtual Error kill(const ProcessID &p_pid);
|
||||||
virtual int get_process_id() const;
|
virtual int get_process_id() const;
|
||||||
int get_processor_count() const;
|
int get_processor_count() const;
|
||||||
|
|
|
@ -256,7 +256,7 @@ public:
|
||||||
virtual void set_offscreen_gl_current(bool p_current);
|
virtual void set_offscreen_gl_current(bool p_current);
|
||||||
|
|
||||||
virtual String get_executable_path() const;
|
virtual String get_executable_path() const;
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr);
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false);
|
||||||
|
|
||||||
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
|
||||||
virtual int keyboard_get_layout_count() const;
|
virtual int keyboard_get_layout_count() const;
|
||||||
|
|
|
@ -2970,7 +2970,7 @@ String OS_OSX::get_executable_path() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_OSX::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
|
Error OS_OSX::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||||
if (@available(macOS 10.15, *)) {
|
if (@available(macOS 10.15, *)) {
|
||||||
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
|
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
|
||||||
// If executable is bundled, always execute editor instances using NSWorkspace to ensure app window is registered and activated correctly.
|
// If executable is bundled, always execute editor instances using NSWorkspace to ensure app window is registered and activated correctly.
|
||||||
|
@ -3017,10 +3017,10 @@ Error OS_OSX::execute(const String &p_path, const List<String> &p_arguments, boo
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
return OS_Unix::execute(p_path, p_arguments, p_blocking, r_child_id, r_pipe, r_exitcode, read_stderr, p_pipe_mutex);
|
return OS_Unix::execute(p_path, p_arguments, p_blocking, r_child_id, r_pipe, r_exitcode, read_stderr, p_pipe_mutex, p_open_console);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return OS_Unix::execute(p_path, p_arguments, p_blocking, r_child_id, r_pipe, r_exitcode, read_stderr, p_pipe_mutex);
|
return OS_Unix::execute(p_path, p_arguments, p_blocking, r_child_id, r_pipe, r_exitcode, read_stderr, p_pipe_mutex, p_open_console);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -669,7 +669,7 @@ void OS_UWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_UWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
|
Error OS_UWP::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ public:
|
||||||
virtual void delay_usec(uint32_t p_usec) const;
|
virtual void delay_usec(uint32_t p_usec) const;
|
||||||
virtual uint64_t get_ticks_usec() const;
|
virtual uint64_t get_ticks_usec() const;
|
||||||
|
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL);
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL, bool p_open_console = false);
|
||||||
virtual Error kill(const ProcessID &p_pid);
|
virtual Error kill(const ProcessID &p_pid);
|
||||||
|
|
||||||
virtual bool has_environment(const String &p_var) const;
|
virtual bool has_environment(const String &p_var) const;
|
||||||
|
|
|
@ -183,9 +183,6 @@ def configure_msvc(env, manual_msvc_config):
|
||||||
env.Append(CCFLAGS=["/O1"])
|
env.Append(CCFLAGS=["/O1"])
|
||||||
env.Append(LINKFLAGS=["/OPT:REF"])
|
env.Append(LINKFLAGS=["/OPT:REF"])
|
||||||
|
|
||||||
env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"])
|
|
||||||
env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"])
|
|
||||||
|
|
||||||
elif env["target"] == "release_debug":
|
elif env["target"] == "release_debug":
|
||||||
if env["optimize"] == "speed": # optimize for speed (default)
|
if env["optimize"] == "speed": # optimize for speed (default)
|
||||||
env.Append(CCFLAGS=["/O2"])
|
env.Append(CCFLAGS=["/O2"])
|
||||||
|
@ -193,15 +190,16 @@ def configure_msvc(env, manual_msvc_config):
|
||||||
elif env["optimize"] == "size": # optimize for size
|
elif env["optimize"] == "size": # optimize for size
|
||||||
env.Append(CCFLAGS=["/O1"])
|
env.Append(CCFLAGS=["/O1"])
|
||||||
env.Append(LINKFLAGS=["/OPT:REF"])
|
env.Append(LINKFLAGS=["/OPT:REF"])
|
||||||
env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
|
|
||||||
|
|
||||||
elif env["target"] == "debug":
|
elif env["target"] == "debug":
|
||||||
env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"])
|
env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"])
|
||||||
env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
|
|
||||||
# Allow big objects. Only needed for debug, see MinGW branch for rationale.
|
# Allow big objects. Only needed for debug, see MinGW branch for rationale.
|
||||||
env.AppendUnique(CCFLAGS=["/bigobj"])
|
env.AppendUnique(CCFLAGS=["/bigobj"])
|
||||||
env.Append(LINKFLAGS=["/DEBUG"])
|
env.Append(LINKFLAGS=["/DEBUG"])
|
||||||
|
|
||||||
|
env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"])
|
||||||
|
env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"])
|
||||||
|
|
||||||
if env["debug_symbols"]:
|
if env["debug_symbols"]:
|
||||||
env.AppendUnique(CCFLAGS=["/Zi", "/FS"])
|
env.AppendUnique(CCFLAGS=["/Zi", "/FS"])
|
||||||
env.AppendUnique(LINKFLAGS=["/DEBUG"])
|
env.AppendUnique(LINKFLAGS=["/DEBUG"])
|
||||||
|
@ -316,8 +314,6 @@ def configure_mingw(env):
|
||||||
env.Append(CCFLAGS=["-O2"])
|
env.Append(CCFLAGS=["-O2"])
|
||||||
else: # optimize for size
|
else: # optimize for size
|
||||||
env.Prepend(CCFLAGS=["-Os"])
|
env.Prepend(CCFLAGS=["-Os"])
|
||||||
env.Append(LINKFLAGS=["-Wl,--subsystem,windows"])
|
|
||||||
|
|
||||||
if env["debug_symbols"]:
|
if env["debug_symbols"]:
|
||||||
env.Prepend(CCFLAGS=["-g2"])
|
env.Prepend(CCFLAGS=["-g2"])
|
||||||
|
|
||||||
|
@ -337,6 +333,8 @@ def configure_mingw(env):
|
||||||
# and are the only ones with too big objects).
|
# and are the only ones with too big objects).
|
||||||
env.Append(CCFLAGS=["-Wa,-mbig-obj"])
|
env.Append(CCFLAGS=["-Wa,-mbig-obj"])
|
||||||
|
|
||||||
|
env.Append(LINKFLAGS=["-Wl,--subsystem,windows"])
|
||||||
|
|
||||||
## Compiler configuration
|
## Compiler configuration
|
||||||
|
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
|
|
|
@ -108,69 +108,17 @@ static String format_error_message(DWORD id) {
|
||||||
extern HINSTANCE godot_hinstance;
|
extern HINSTANCE godot_hinstance;
|
||||||
|
|
||||||
void RedirectIOToConsole() {
|
void RedirectIOToConsole() {
|
||||||
int hConHandle;
|
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
|
FILE *fpstdin = stdin;
|
||||||
|
FILE *fpstdout = stdout;
|
||||||
|
FILE *fpstderr = stderr;
|
||||||
|
|
||||||
intptr_t lStdHandle;
|
freopen_s(&fpstdin, "CONIN$", "r", stdin);
|
||||||
|
freopen_s(&fpstdout, "CONOUT$", "w", stdout);
|
||||||
|
freopen_s(&fpstderr, "CONOUT$", "w", stderr);
|
||||||
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO coninfo;
|
printf("\n"); // Make sure our output is starting from the new line.
|
||||||
|
}
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
// allocate a console for this app
|
|
||||||
|
|
||||||
AllocConsole();
|
|
||||||
|
|
||||||
// set the screen buffer to be big enough to let us scroll text
|
|
||||||
|
|
||||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
|
|
||||||
|
|
||||||
&coninfo);
|
|
||||||
|
|
||||||
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
|
|
||||||
|
|
||||||
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
|
|
||||||
|
|
||||||
coninfo.dwSize);
|
|
||||||
|
|
||||||
// redirect unbuffered STDOUT to the console
|
|
||||||
|
|
||||||
lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
|
|
||||||
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
|
|
||||||
|
|
||||||
fp = _fdopen(hConHandle, "w");
|
|
||||||
|
|
||||||
*stdout = *fp;
|
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
|
||||||
|
|
||||||
// redirect unbuffered STDIN to the console
|
|
||||||
|
|
||||||
lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
|
|
||||||
|
|
||||||
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
|
|
||||||
|
|
||||||
fp = _fdopen(hConHandle, "r");
|
|
||||||
|
|
||||||
*stdin = *fp;
|
|
||||||
|
|
||||||
setvbuf(stdin, NULL, _IONBF, 0);
|
|
||||||
|
|
||||||
// redirect unbuffered STDERR to the console
|
|
||||||
|
|
||||||
lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
|
|
||||||
|
|
||||||
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
|
|
||||||
|
|
||||||
fp = _fdopen(hConHandle, "w");
|
|
||||||
|
|
||||||
*stderr = *fp;
|
|
||||||
|
|
||||||
setvbuf(stderr, NULL, _IONBF, 0);
|
|
||||||
|
|
||||||
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
|
|
||||||
|
|
||||||
// point to console as well
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) {
|
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) {
|
||||||
|
@ -210,7 +158,8 @@ void OS_Windows::initialize_core() {
|
||||||
last_button_state = 0;
|
last_button_state = 0;
|
||||||
restore_mouse_trails = 0;
|
restore_mouse_trails = 0;
|
||||||
|
|
||||||
//RedirectIOToConsole();
|
RedirectIOToConsole();
|
||||||
|
|
||||||
maximized = false;
|
maximized = false;
|
||||||
minimized = false;
|
minimized = false;
|
||||||
borderless = false;
|
borderless = false;
|
||||||
|
@ -2247,31 +2196,6 @@ bool OS_Windows::is_window_focused() const {
|
||||||
return window_focused;
|
return window_focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OS_Windows::_is_win11_terminal() const {
|
|
||||||
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
DWORD dwMode = 0;
|
|
||||||
if (GetConsoleMode(hStdOut, &dwMode)) {
|
|
||||||
return ((dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OS_Windows::set_console_visible(bool p_enabled) {
|
|
||||||
if (console_visible == p_enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!_is_win11_terminal()) {
|
|
||||||
// GetConsoleWindow is not supported by the Windows Terminal.
|
|
||||||
ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE);
|
|
||||||
console_visible = p_enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OS_Windows::is_console_visible() const {
|
|
||||||
return console_visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OS_Windows::get_window_per_pixel_transparency_enabled() const {
|
bool OS_Windows::get_window_per_pixel_transparency_enabled() const {
|
||||||
if (!is_layered_allowed())
|
if (!is_layered_allowed())
|
||||||
return false;
|
return false;
|
||||||
|
@ -2815,43 +2739,9 @@ String OS_Windows::_quote_command_line_argument(const String &p_text) const {
|
||||||
return p_text;
|
return p_text;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
|
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||||
String path = p_path.replace("/", "\\");
|
String path = p_path.replace("/", "\\");
|
||||||
|
|
||||||
if (p_blocking && r_pipe) {
|
|
||||||
String argss = _quote_command_line_argument(path);
|
|
||||||
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
|
|
||||||
argss += " " + _quote_command_line_argument(E->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_stderr) {
|
|
||||||
argss += " 2>&1"; // Read stderr too
|
|
||||||
}
|
|
||||||
// Note: _wpopen is calling command as "cmd.exe /c argss", instead of executing it directly, add extra quotes around full command, to prevent it from stripping quotes in the command.
|
|
||||||
argss = _quote_command_line_argument(argss);
|
|
||||||
|
|
||||||
FILE *f = _wpopen(argss.c_str(), L"r");
|
|
||||||
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
|
|
||||||
|
|
||||||
char buf[65535];
|
|
||||||
while (fgets(buf, 65535, f)) {
|
|
||||||
if (p_pipe_mutex) {
|
|
||||||
p_pipe_mutex->lock();
|
|
||||||
}
|
|
||||||
(*r_pipe) += String::utf8(buf);
|
|
||||||
if (p_pipe_mutex) {
|
|
||||||
p_pipe_mutex->unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int rv = _pclose(f);
|
|
||||||
if (r_exitcode) {
|
|
||||||
*r_exitcode = rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
String cmdline = _quote_command_line_argument(path);
|
String cmdline = _quote_command_line_argument(path);
|
||||||
const List<String>::Element *I = p_arguments.front();
|
const List<String>::Element *I = p_arguments.front();
|
||||||
while (I) {
|
while (I) {
|
||||||
|
@ -2871,17 +2761,62 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
|
||||||
modstr.write[i] = cmdline[i];
|
modstr.write[i] = cmdline[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD creation_flags = NORMAL_PRIORITY_CLASS & CREATE_NO_WINDOW;
|
bool inherit_handles = false;
|
||||||
if (p_path == get_executable_path() && GetConsoleWindow() != NULL && _is_win11_terminal()) {
|
HANDLE pipe[2] = { NULL, NULL };
|
||||||
// Open a new terminal as a workaround for Windows Terminal bug.
|
if (p_blocking && r_pipe) {
|
||||||
creation_flags |= CREATE_NEW_CONSOLE;
|
// Create pipe for StdOut and StdErr.
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
sa.bInheritHandle = true;
|
||||||
|
sa.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(!CreatePipe(&pipe[0], &pipe[1], &sa, 0), ERR_CANT_FORK);
|
||||||
|
ERR_FAIL_COND_V(!SetHandleInformation(pipe[0], HANDLE_FLAG_INHERIT, 0), ERR_CANT_FORK); // Read handle is for host process only and should not be inherited.
|
||||||
|
|
||||||
|
pi.si.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
pi.si.hStdOutput = pipe[1];
|
||||||
|
if (read_stderr) {
|
||||||
|
pi.si.hStdError = pipe[1];
|
||||||
|
}
|
||||||
|
inherit_handles = true;
|
||||||
|
}
|
||||||
|
DWORD creaton_flags = NORMAL_PRIORITY_CLASS;
|
||||||
|
if (p_open_console) {
|
||||||
|
creaton_flags |= CREATE_NEW_CONSOLE;
|
||||||
|
} else {
|
||||||
|
creaton_flags |= CREATE_NO_WINDOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = CreateProcessW(NULL, modstr.ptrw(), NULL, NULL, 0, creation_flags, NULL, NULL, si_w, &pi.pi);
|
int ret = CreateProcessW(NULL, modstr.ptrw(), NULL, NULL, inherit_handles, creaton_flags, NULL, NULL, si_w, &pi.pi);
|
||||||
|
if (!ret && r_pipe) {
|
||||||
|
CloseHandle(pipe[0]); // Cleanup pipe handles.
|
||||||
|
CloseHandle(pipe[1]);
|
||||||
|
}
|
||||||
ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
|
ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
|
||||||
|
|
||||||
if (p_blocking) {
|
if (p_blocking) {
|
||||||
WaitForSingleObject(pi.pi.hProcess, INFINITE);
|
if (r_pipe) {
|
||||||
|
CloseHandle(pipe[1]); // Close pipe write handle (only child process is writing).
|
||||||
|
char buf[4096];
|
||||||
|
DWORD read = 0;
|
||||||
|
for (;;) { // Read StdOut and StdErr from pipe.
|
||||||
|
bool success = ReadFile(pipe[0], buf, 4096, &read, NULL);
|
||||||
|
if (!success || read == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (p_pipe_mutex) {
|
||||||
|
p_pipe_mutex->lock();
|
||||||
|
}
|
||||||
|
(*r_pipe) += String::utf8(buf, read);
|
||||||
|
if (p_pipe_mutex) {
|
||||||
|
p_pipe_mutex->unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
CloseHandle(pipe[0]); // Close pipe read handle.
|
||||||
|
} else {
|
||||||
|
WaitForSingleObject(pi.pi.hProcess, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
if (r_exitcode) {
|
if (r_exitcode) {
|
||||||
DWORD ret2;
|
DWORD ret2;
|
||||||
GetExitCodeProcess(pi.pi.hProcess, &ret2);
|
GetExitCodeProcess(pi.pi.hProcess, &ret2);
|
||||||
|
@ -3689,7 +3624,6 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
|
||||||
minimized = false;
|
minimized = false;
|
||||||
was_maximized = false;
|
was_maximized = false;
|
||||||
window_focused = true;
|
window_focused = true;
|
||||||
console_visible = IsWindowVisible(GetConsoleWindow());
|
|
||||||
|
|
||||||
//Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
|
//Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
|
||||||
HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
|
HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
|
||||||
|
|
|
@ -371,8 +371,6 @@ class OS_Windows : public OS {
|
||||||
|
|
||||||
CrashHandler crash_handler;
|
CrashHandler crash_handler;
|
||||||
|
|
||||||
bool _is_win11_terminal() const;
|
|
||||||
|
|
||||||
void _drag_event(float p_x, float p_y, int idx);
|
void _drag_event(float p_x, float p_y, int idx);
|
||||||
void _touch_event(bool p_pressed, float p_x, float p_y, int idx);
|
void _touch_event(bool p_pressed, float p_x, float p_y, int idx);
|
||||||
|
|
||||||
|
@ -414,7 +412,6 @@ protected:
|
||||||
bool minimized;
|
bool minimized;
|
||||||
bool borderless;
|
bool borderless;
|
||||||
bool window_focused;
|
bool window_focused;
|
||||||
bool console_visible;
|
|
||||||
bool was_maximized;
|
bool was_maximized;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -469,8 +466,6 @@ public:
|
||||||
virtual void set_window_always_on_top(bool p_enabled);
|
virtual void set_window_always_on_top(bool p_enabled);
|
||||||
virtual bool is_window_always_on_top() const;
|
virtual bool is_window_always_on_top() const;
|
||||||
virtual bool is_window_focused() const;
|
virtual bool is_window_focused() const;
|
||||||
virtual void set_console_visible(bool p_enabled);
|
|
||||||
virtual bool is_console_visible() const;
|
|
||||||
virtual void request_attention();
|
virtual void request_attention();
|
||||||
virtual void *get_native_handle(int p_handle_type);
|
virtual void *get_native_handle(int p_handle_type);
|
||||||
|
|
||||||
|
@ -501,7 +496,7 @@ public:
|
||||||
virtual void delay_usec(uint32_t p_usec) const;
|
virtual void delay_usec(uint32_t p_usec) const;
|
||||||
virtual uint64_t get_ticks_usec() const;
|
virtual uint64_t get_ticks_usec() const;
|
||||||
|
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL);
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL, bool p_open_console = false);
|
||||||
virtual Error kill(const ProcessID &p_pid);
|
virtual Error kill(const ProcessID &p_pid);
|
||||||
virtual int get_process_id() const;
|
virtual int get_process_id() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue