[Windows] Improve console handling and execute/create_process.
Always build with the GUI subsystem. Redirect stdout and stderr output to the parent process console. Use CreateProcessW for blocking `execute` calls with piped stdout and stderr (prevent console windows for popping up when used with the GUI subsystem build, and have more consistent behavior with `create_process`). Add `open_console` argument to the `execute` and `create_process` to open a new console window. Remove `interface/editor/hide_console_window` editor setting. Remove `Toggle System Console` menu option. Remove `set_console_visible` and `is_console_visible` functions.
This commit is contained in:
parent
b0e93711b3
commit
ea5bb8b47d
@ -224,14 +224,14 @@ 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, Array r_output, bool p_read_stderr) {
|
int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r_output, bool p_read_stderr, bool p_open_console) {
|
||||||
List<String> args;
|
List<String> args;
|
||||||
for (int i = 0; i < p_arguments.size(); i++) {
|
for (int i = 0; i < p_arguments.size(); i++) {
|
||||||
args.push_back(p_arguments[i]);
|
args.push_back(p_arguments[i]);
|
||||||
}
|
}
|
||||||
String pipe;
|
String pipe;
|
||||||
int exitcode = 0;
|
int exitcode = 0;
|
||||||
Error err = ::OS::get_singleton()->execute(p_path, args, &pipe, &exitcode, p_read_stderr);
|
Error err = ::OS::get_singleton()->execute(p_path, args, &pipe, &exitcode, p_read_stderr, nullptr, p_open_console);
|
||||||
r_output.push_back(pipe);
|
r_output.push_back(pipe);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -252,13 +252,13 @@ int OS::create_instance(const Vector<String> &p_arguments) {
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int OS::create_process(const String &p_path, const Vector<String> &p_arguments) {
|
int OS::create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console) {
|
||||||
List<String> args;
|
List<String> args;
|
||||||
for (int i = 0; i < p_arguments.size(); i++) {
|
for (int i = 0; i < p_arguments.size(); i++) {
|
||||||
args.push_back(p_arguments[i]);
|
args.push_back(p_arguments[i]);
|
||||||
}
|
}
|
||||||
::OS::ProcessID pid = 0;
|
::OS::ProcessID pid = 0;
|
||||||
Error err = ::OS::get_singleton()->create_process(p_path, args, &pid);
|
Error err = ::OS::get_singleton()->create_process(p_path, args, &pid, p_open_console);
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -557,8 +557,8 @@ 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", "output", "read_stderr"), &OS::execute, DEFVAL(Array()), DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
|
||||||
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments"), &OS::create_process);
|
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false));
|
||||||
ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
|
ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
|
||||||
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);
|
||||||
|
@ -164,8 +164,8 @@ public:
|
|||||||
void crash(const String &p_message);
|
void crash(const String &p_message);
|
||||||
|
|
||||||
String get_executable_path() const;
|
String get_executable_path() const;
|
||||||
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false);
|
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
|
||||||
int create_process(const String &p_path, const Vector<String> &p_arguments);
|
int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false);
|
||||||
int create_instance(const Vector<String> &p_arguments);
|
int create_instance(const Vector<String> &p_arguments);
|
||||||
Error kill(int p_pid);
|
Error kill(int p_pid);
|
||||||
Error shell_open(String p_uri);
|
Error shell_open(String p_uri);
|
||||||
|
@ -149,8 +149,8 @@ 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, 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, 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 create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) = 0;
|
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) = 0;
|
||||||
virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) { return create_process(get_executable_path(), p_arguments, r_child_id); };
|
virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) { return create_process(get_executable_path(), p_arguments, r_child_id); };
|
||||||
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;
|
||||||
|
@ -35,12 +35,6 @@
|
|||||||
[b]Note:[/b] This method is only implemented on Linux.
|
[b]Note:[/b] This method is only implemented on Linux.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="console_set_visible">
|
|
||||||
<return type="void" />
|
|
||||||
<argument index="0" name="console_visible" type="bool" />
|
|
||||||
<description>
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="create_sub_window">
|
<method name="create_sub_window">
|
||||||
<return type="int" />
|
<return type="int" />
|
||||||
<argument index="0" name="mode" type="int" enum="DisplayServer.WindowMode" />
|
<argument index="0" name="mode" type="int" enum="DisplayServer.WindowMode" />
|
||||||
@ -281,11 +275,6 @@
|
|||||||
<description>
|
<description>
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="is_console_visible" qualifiers="const">
|
|
||||||
<return type="bool" />
|
|
||||||
<description>
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="keyboard_get_current_layout" qualifiers="const">
|
<method name="keyboard_get_current_layout" qualifiers="const">
|
||||||
<return type="int" />
|
<return type="int" />
|
||||||
<description>
|
<description>
|
||||||
@ -803,23 +792,21 @@
|
|||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_NATIVE_DIALOG" value="9" enum="Feature">
|
<constant name="FEATURE_NATIVE_DIALOG" value="9" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_CONSOLE_WINDOW" value="10" enum="Feature">
|
<constant name="FEATURE_IME" value="10" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_IME" value="11" enum="Feature">
|
<constant name="FEATURE_WINDOW_TRANSPARENCY" value="11" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_WINDOW_TRANSPARENCY" value="12" enum="Feature">
|
<constant name="FEATURE_HIDPI" value="12" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_HIDPI" value="13" enum="Feature">
|
<constant name="FEATURE_ICON" value="13" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_ICON" value="14" enum="Feature">
|
<constant name="FEATURE_NATIVE_ICON" value="14" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_NATIVE_ICON" value="15" enum="Feature">
|
<constant name="FEATURE_ORIENTATION" value="15" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_ORIENTATION" value="16" enum="Feature">
|
<constant name="FEATURE_SWAP_BUFFERS" value="16" enum="Feature">
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="FEATURE_SWAP_BUFFERS" value="17" enum="Feature">
|
<constant name="FEATURE_CLIPBOARD_PRIMARY" value="18" enum="Feature">
|
||||||
</constant>
|
|
||||||
<constant name="FEATURE_CLIPBOARD_PRIMARY" value="19" enum="Feature">
|
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode">
|
<constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode">
|
||||||
Makes the mouse cursor visible if it is hidden.
|
Makes the mouse cursor visible if it is hidden.
|
||||||
|
@ -51,8 +51,10 @@
|
|||||||
<return type="int" />
|
<return type="int" />
|
||||||
<argument index="0" name="path" type="String" />
|
<argument index="0" name="path" type="String" />
|
||||||
<argument index="1" name="arguments" type="PackedStringArray" />
|
<argument index="1" name="arguments" type="PackedStringArray" />
|
||||||
|
<argument index="2" name="open_console" type="bool" default="false" />
|
||||||
<description>
|
<description>
|
||||||
Creates a new process that runs independently of Godot. It will not terminate if Godot terminates. The path specified in [code]path[/code] must exist and be executable file or macOS .app bundle. Platform path resolution will be used. The [code]arguments[/code] are used in the given order and separated by a space.
|
Creates a new process that runs independently of Godot. It will not terminate if Godot terminates. The path specified in [code]path[/code] must exist and be executable file or macOS .app bundle. Platform path resolution will be used. The [code]arguments[/code] are used in the given order and separated by a space.
|
||||||
|
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.
|
||||||
If the process creation succeeds, the method will return the new process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process creation fails, the method will return [code]-1[/code].
|
If the process creation succeeds, the method will return the new process ID, which you can use to monitor the process (and potentially terminate it with [method kill]). If the process creation fails, the method will return [code]-1[/code].
|
||||||
For example, running another instance of the project:
|
For example, running another instance of the project:
|
||||||
[codeblocks]
|
[codeblocks]
|
||||||
@ -109,8 +111,10 @@
|
|||||||
<argument index="1" name="arguments" type="PackedStringArray" />
|
<argument index="1" name="arguments" type="PackedStringArray" />
|
||||||
<argument index="2" name="output" type="Array" default="[]" />
|
<argument index="2" name="output" type="Array" default="[]" />
|
||||||
<argument index="3" name="read_stderr" type="bool" default="false" />
|
<argument index="3" name="read_stderr" type="bool" default="false" />
|
||||||
|
<argument index="4" name="open_console" type="bool" default="false" />
|
||||||
<description>
|
<description>
|
||||||
Executes a command. The file specified in [code]path[/code] must exist and be executable. Platform path resolution will be used. The [code]arguments[/code] are used in the given order and separated by a space. If an [code]output[/code] [Array] is provided, the complete shell output of the process will be appended as a single [String] element in [code]output[/code]. If [code]read_stderr[/code] is [code]true[/code], the output to the standard error stream will be included too.
|
Executes a command. The file specified in [code]path[/code] must exist and be executable. Platform path resolution will be used. The [code]arguments[/code] are used in the given order and separated by a space. If an [code]output[/code] [Array] is provided, the complete shell output of the process will be appended as a single [String] element in [code]output[/code]. If [code]read_stderr[/code] is [code]true[/code], the output to the standard error stream will be included too.
|
||||||
|
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.
|
||||||
If the command is successfully executed, the method will return the exit code of the command, or [code]-1[/code] if it fails.
|
If the command is successfully executed, the method will return the exit code of the command, or [code]-1[/code] if it fails.
|
||||||
[b]Note:[/b] The Godot thread will pause its execution until the executed command terminates. Use [Thread] to create a separate thread that will not pause the Godot thread, or use [method create_process] to create a completely independent process.
|
[b]Note:[/b] The Godot thread will pause its execution until the executed command terminates. Use [Thread] to create a separate thread that will not pause the Godot thread, or use [method create_process] to create a completely independent process.
|
||||||
For example, to retrieve a list of the working directory's contents:
|
For example, to retrieve a list of the working directory's contents:
|
||||||
@ -124,7 +128,7 @@
|
|||||||
int exitCode = OS.Execute("ls", new string[] {"-l", "/tmp"}, output);
|
int exitCode = OS.Execute("ls", new string[] {"-l", "/tmp"}, output);
|
||||||
[/csharp]
|
[/csharp]
|
||||||
[/codeblocks]
|
[/codeblocks]
|
||||||
To execute a composite command, a platform-specific shell can be invoked. For example:
|
If you wish to access a shell built-in or perform a composite command, a platform-specific shell can be invoked. For example:
|
||||||
[codeblocks]
|
[codeblocks]
|
||||||
[gdscript]
|
[gdscript]
|
||||||
var output = []
|
var output = []
|
||||||
|
@ -249,7 +249,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, 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, 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.
|
||||||
@ -318,7 +318,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_Unix::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
|
Error OS_Unix::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, 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.
|
||||||
|
@ -81,8 +81,8 @@ public:
|
|||||||
virtual void delay_usec(uint32_t p_usec) const override;
|
virtual void delay_usec(uint32_t p_usec) const override;
|
||||||
virtual uint64_t get_ticks_usec() const override;
|
virtual uint64_t get_ticks_usec() const override;
|
||||||
|
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) override;
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
|
||||||
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
|
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
|
||||||
virtual Error kill(const ProcessID &p_pid) override;
|
virtual Error kill(const ProcessID &p_pid) override;
|
||||||
virtual int get_process_id() const override;
|
virtual int get_process_id() const override;
|
||||||
|
|
||||||
|
@ -2852,11 +2852,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
|
|||||||
DisplayServer::get_singleton()->window_set_mode(DisplayServer::get_singleton()->window_get_mode() == DisplayServer::WINDOW_MODE_FULLSCREEN ? DisplayServer::WINDOW_MODE_WINDOWED : DisplayServer::WINDOW_MODE_FULLSCREEN);
|
DisplayServer::get_singleton()->window_set_mode(DisplayServer::get_singleton()->window_get_mode() == DisplayServer::WINDOW_MODE_FULLSCREEN ? DisplayServer::WINDOW_MODE_WINDOWED : DisplayServer::WINDOW_MODE_FULLSCREEN);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case SETTINGS_TOGGLE_CONSOLE: {
|
|
||||||
bool was_visible = DisplayServer::get_singleton()->is_console_visible();
|
|
||||||
DisplayServer::get_singleton()->console_set_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;
|
||||||
@ -6500,11 +6495,6 @@ EditorNode::EditorNode() {
|
|||||||
ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::F);
|
ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::F);
|
||||||
p->add_shortcut(ED_GET_SHORTCUT("editor/fullscreen_mode"), SETTINGS_TOGGLE_FULLSCREEN);
|
p->add_shortcut(ED_GET_SHORTCUT("editor/fullscreen_mode"), SETTINGS_TOGGLE_FULLSCREEN);
|
||||||
|
|
||||||
#if defined(WINDOWS_ENABLED) && defined(WINDOWS_SUBSYSTEM_CONSOLE)
|
|
||||||
// The console can only be toggled if the application was built for the console subsystem,
|
|
||||||
// not the GUI subsystem.
|
|
||||||
p->add_item(TTR("Toggle System Console"), SETTINGS_TOGGLE_CONSOLE);
|
|
||||||
#endif
|
|
||||||
p->add_separator();
|
p->add_separator();
|
||||||
|
|
||||||
if (OS::get_singleton()->get_data_path() == OS::get_singleton()->get_config_path()) {
|
if (OS::get_singleton()->get_data_path() == OS::get_singleton()->get_config_path()) {
|
||||||
|
@ -188,7 +188,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,
|
||||||
|
@ -428,7 +428,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
|||||||
_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);
|
||||||
EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/single_window_mode", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
|
EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/single_window_mode", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
|
||||||
_initial_set("interface/editor/hide_console_window", false);
|
|
||||||
_initial_set("interface/editor/mouse_extra_buttons_navigate_history", true);
|
_initial_set("interface/editor/mouse_extra_buttons_navigate_history", true);
|
||||||
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
|
_initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
|
||||||
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/show_internal_errors_in_toast_notifications", 0, "Auto,Enabled,Disabled")
|
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/show_internal_errors_in_toast_notifications", 0, "Auto,Enabled,Disabled")
|
||||||
|
@ -2529,13 +2529,6 @@ bool Main::start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (project_manager || editor) {
|
if (project_manager || editor) {
|
||||||
if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CONSOLE_WINDOW)) {
|
|
||||||
// Hide console window if requested (Windows-only).
|
|
||||||
bool hide_console = EditorSettings::get_singleton()->get_setting(
|
|
||||||
"interface/editor/hide_console_window");
|
|
||||||
DisplayServer::get_singleton()->console_set_visible(!hide_console);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load SSL Certificates from Editor Settings (or builtin)
|
// Load SSL Certificates from Editor Settings (or builtin)
|
||||||
Crypto::load_default_certificates(
|
Crypto::load_default_certificates(
|
||||||
EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
|
EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
|
||||||
|
@ -47,7 +47,6 @@ DisplayServerAndroid *DisplayServerAndroid::get_singleton() {
|
|||||||
|
|
||||||
bool DisplayServerAndroid::has_feature(Feature p_feature) const {
|
bool DisplayServerAndroid::has_feature(Feature p_feature) const {
|
||||||
switch (p_feature) {
|
switch (p_feature) {
|
||||||
//case FEATURE_CONSOLE_WINDOW:
|
|
||||||
case FEATURE_CURSOR_SHAPE:
|
case FEATURE_CURSOR_SHAPE:
|
||||||
//case FEATURE_CUSTOM_CURSOR_SHAPE:
|
//case FEATURE_CUSTOM_CURSOR_SHAPE:
|
||||||
//case FEATURE_GLOBAL_MENU:
|
//case FEATURE_GLOBAL_MENU:
|
||||||
|
@ -293,7 +293,6 @@ void DisplayServerIPhone::update_gyroscope(float p_x, float p_y, float p_z) {
|
|||||||
|
|
||||||
bool DisplayServerIPhone::has_feature(Feature p_feature) const {
|
bool DisplayServerIPhone::has_feature(Feature p_feature) const {
|
||||||
switch (p_feature) {
|
switch (p_feature) {
|
||||||
// case FEATURE_CONSOLE_WINDOW:
|
|
||||||
// case FEATURE_CURSOR_SHAPE:
|
// case FEATURE_CURSOR_SHAPE:
|
||||||
// case FEATURE_CUSTOM_CURSOR_SHAPE:
|
// case FEATURE_CUSTOM_CURSOR_SHAPE:
|
||||||
// case FEATURE_GLOBAL_MENU:
|
// case FEATURE_GLOBAL_MENU:
|
||||||
|
@ -746,7 +746,6 @@ DisplayServerJavaScript::~DisplayServerJavaScript() {
|
|||||||
|
|
||||||
bool DisplayServerJavaScript::has_feature(Feature p_feature) const {
|
bool DisplayServerJavaScript::has_feature(Feature p_feature) const {
|
||||||
switch (p_feature) {
|
switch (p_feature) {
|
||||||
//case FEATURE_CONSOLE_WINDOW:
|
|
||||||
//case FEATURE_GLOBAL_MENU:
|
//case FEATURE_GLOBAL_MENU:
|
||||||
//case FEATURE_HIDPI:
|
//case FEATURE_HIDPI:
|
||||||
//case FEATURE_IME:
|
//case FEATURE_IME:
|
||||||
|
@ -107,11 +107,11 @@ void OS_JavaScript::finalize() {
|
|||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
|
||||||
Error OS_JavaScript::execute(const String &p_path, const List<String> &p_arguments, 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, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||||
return create_process(p_path, p_arguments);
|
return create_process(p_path, p_arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_JavaScript::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
|
Error OS_JavaScript::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
|
||||||
Array args;
|
Array args;
|
||||||
for (const String &E : p_arguments) {
|
for (const String &E : p_arguments) {
|
||||||
args.push_back(E);
|
args.push_back(E);
|
||||||
|
@ -70,8 +70,8 @@ public:
|
|||||||
MainLoop *get_main_loop() const override;
|
MainLoop *get_main_loop() const override;
|
||||||
bool main_loop_iterate();
|
bool main_loop_iterate();
|
||||||
|
|
||||||
Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) override;
|
Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
|
||||||
Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
|
Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
|
||||||
Error kill(const ProcessID &p_pid) override;
|
Error kill(const ProcessID &p_pid) override;
|
||||||
int get_process_id() const override;
|
int get_process_id() const override;
|
||||||
int get_processor_count() const override;
|
int get_processor_count() const override;
|
||||||
|
@ -314,9 +314,6 @@ public:
|
|||||||
virtual void set_native_icon(const String &p_filename) override;
|
virtual void set_native_icon(const String &p_filename) override;
|
||||||
virtual void set_icon(const Ref<Image> &p_icon) override;
|
virtual void set_icon(const Ref<Image> &p_icon) override;
|
||||||
|
|
||||||
virtual void console_set_visible(bool p_enabled) override;
|
|
||||||
virtual bool is_console_visible() const override;
|
|
||||||
|
|
||||||
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
|
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
|
||||||
static Vector<String> get_rendering_drivers_func();
|
static Vector<String> get_rendering_drivers_func();
|
||||||
|
|
||||||
|
@ -1480,7 +1480,6 @@ bool DisplayServerOSX::has_feature(Feature p_feature) const {
|
|||||||
case FEATURE_CURSOR_SHAPE:
|
case FEATURE_CURSOR_SHAPE:
|
||||||
case FEATURE_CUSTOM_CURSOR_SHAPE:
|
case FEATURE_CUSTOM_CURSOR_SHAPE:
|
||||||
case FEATURE_NATIVE_DIALOG:
|
case FEATURE_NATIVE_DIALOG:
|
||||||
//case FEATURE_CONSOLE_WINDOW:
|
|
||||||
case FEATURE_IME:
|
case FEATURE_IME:
|
||||||
case FEATURE_WINDOW_TRANSPARENCY:
|
case FEATURE_WINDOW_TRANSPARENCY:
|
||||||
case FEATURE_HIDPI:
|
case FEATURE_HIDPI:
|
||||||
@ -3682,14 +3681,6 @@ void DisplayServerOSX::swap_buffers() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayServerOSX::console_set_visible(bool p_enabled) {
|
|
||||||
//TODO - open terminal and redirect
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DisplayServerOSX::is_console_visible() const {
|
|
||||||
return isatty(STDIN_FILENO);
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
|
DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
|
||||||
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
|
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ public:
|
|||||||
String get_locale() const override;
|
String get_locale() const override;
|
||||||
|
|
||||||
virtual String get_executable_path() const override;
|
virtual String get_executable_path() const override;
|
||||||
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
|
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
|
||||||
virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
|
virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
|
||||||
|
|
||||||
virtual String get_unique_id() const override; //++
|
virtual String get_unique_id() const override; //++
|
||||||
|
@ -497,13 +497,13 @@ Error OS_OSX::create_instance(const List<String> &p_arguments, ProcessID *r_chil
|
|||||||
if (nsappname != nil) {
|
if (nsappname != nil) {
|
||||||
String path;
|
String path;
|
||||||
path.parse_utf8([[[NSBundle mainBundle] bundlePath] UTF8String]);
|
path.parse_utf8([[[NSBundle mainBundle] bundlePath] UTF8String]);
|
||||||
return create_process(path, p_arguments, r_child_id);
|
return create_process(path, p_arguments, r_child_id, false);
|
||||||
} else {
|
} else {
|
||||||
return create_process(get_executable_path(), p_arguments, r_child_id);
|
return create_process(get_executable_path(), p_arguments, r_child_id, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_OSX::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
|
Error OS_OSX::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
|
||||||
if (@available(macOS 10.15, *)) {
|
if (@available(macOS 10.15, *)) {
|
||||||
// Use NSWorkspace if path is an .app bundle.
|
// Use NSWorkspace if path is an .app bundle.
|
||||||
NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
|
NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
|
||||||
@ -542,10 +542,10 @@ Error OS_OSX::create_process(const String &p_path, const List<String> &p_argumen
|
|||||||
|
|
||||||
return err;
|
return err;
|
||||||
} else {
|
} else {
|
||||||
return OS_Unix::create_process(p_path, p_arguments, r_child_id);
|
return OS_Unix::create_process(p_path, p_arguments, r_child_id, p_open_console);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return OS_Unix::create_process(p_path, p_arguments, r_child_id);
|
return OS_Unix::create_process(p_path, p_arguments, r_child_id, p_open_console);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,11 +629,11 @@ 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, 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, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
};
|
};
|
||||||
|
|
||||||
Error OS_UWP::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
|
Error OS_UWP::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
|
||||||
return FAILED;
|
return FAILED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,8 +195,8 @@ 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, 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, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false);
|
||||||
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr);
|
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, 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;
|
||||||
|
@ -65,7 +65,7 @@ def get_opts():
|
|||||||
# Vista support dropped after EOL due to GH-10243
|
# Vista support dropped after EOL due to GH-10243
|
||||||
("target_win_version", "Targeted Windows version, >= 0x0601 (Windows 7)", "0x0601"),
|
("target_win_version", "Targeted Windows version, >= 0x0601 (Windows 7)", "0x0601"),
|
||||||
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
|
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
|
||||||
EnumVariable("windows_subsystem", "Windows subsystem", "default", ("default", "console", "gui")),
|
EnumVariable("windows_subsystem", "Windows subsystem", "gui", ("gui", "console")),
|
||||||
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
|
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
|
||||||
("msvc_version", "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.", None),
|
("msvc_version", "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.", None),
|
||||||
BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", False),
|
BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", False),
|
||||||
@ -178,15 +178,6 @@ def configure_msvc(env, manual_msvc_config):
|
|||||||
|
|
||||||
# Build type
|
# Build type
|
||||||
|
|
||||||
if env["tests"]:
|
|
||||||
env["windows_subsystem"] = "console"
|
|
||||||
elif env["windows_subsystem"] == "default":
|
|
||||||
# Default means we use console for debug, gui for release.
|
|
||||||
if "debug" in env["target"]:
|
|
||||||
env["windows_subsystem"] = "console"
|
|
||||||
else:
|
|
||||||
env["windows_subsystem"] = "gui"
|
|
||||||
|
|
||||||
if env["target"] == "release":
|
if env["target"] == "release":
|
||||||
if env["optimize"] == "speed": # optimize for speed (default)
|
if env["optimize"] == "speed": # optimize for speed (default)
|
||||||
env.Append(CCFLAGS=["/O2"])
|
env.Append(CCFLAGS=["/O2"])
|
||||||
@ -326,15 +317,6 @@ def configure_mingw(env):
|
|||||||
|
|
||||||
## Build type
|
## Build type
|
||||||
|
|
||||||
if env["tests"]:
|
|
||||||
env["windows_subsystem"] = "console"
|
|
||||||
elif env["windows_subsystem"] == "default":
|
|
||||||
# Default means we use console for debug, gui for release.
|
|
||||||
if "debug" in env["target"]:
|
|
||||||
env["windows_subsystem"] = "console"
|
|
||||||
else:
|
|
||||||
env["windows_subsystem"] = "gui"
|
|
||||||
|
|
||||||
if env["target"] == "release":
|
if env["target"] == "release":
|
||||||
env.Append(CCFLAGS=["-msse2"])
|
env.Append(CCFLAGS=["-msse2"])
|
||||||
|
|
||||||
|
@ -68,7 +68,6 @@ bool DisplayServerWindows::has_feature(Feature p_feature) const {
|
|||||||
case FEATURE_CLIPBOARD:
|
case FEATURE_CLIPBOARD:
|
||||||
case FEATURE_CURSOR_SHAPE:
|
case FEATURE_CURSOR_SHAPE:
|
||||||
case FEATURE_CUSTOM_CURSOR_SHAPE:
|
case FEATURE_CUSTOM_CURSOR_SHAPE:
|
||||||
case FEATURE_CONSOLE_WINDOW:
|
|
||||||
case FEATURE_IME:
|
case FEATURE_IME:
|
||||||
case FEATURE_WINDOW_TRANSPARENCY:
|
case FEATURE_WINDOW_TRANSPARENCY:
|
||||||
case FEATURE_HIDPI:
|
case FEATURE_HIDPI:
|
||||||
@ -1198,23 +1197,6 @@ void DisplayServerWindows::window_set_ime_position(const Point2i &p_pos, WindowI
|
|||||||
ImmReleaseContext(wd.hWnd, himc);
|
ImmReleaseContext(wd.hWnd, himc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayServerWindows::console_set_visible(bool p_enabled) {
|
|
||||||
_THREAD_SAFE_METHOD_
|
|
||||||
|
|
||||||
if (console_visible == p_enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!((OS_Windows *)OS::get_singleton())->_is_win11_terminal()) {
|
|
||||||
// GetConsoleWindow is not supported by the Windows Terminal.
|
|
||||||
ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE);
|
|
||||||
console_visible = p_enabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DisplayServerWindows::is_console_visible() const {
|
|
||||||
return console_visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayServerWindows::cursor_set_shape(CursorShape p_shape) {
|
void DisplayServerWindows::cursor_set_shape(CursorShape p_shape) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
@ -3246,7 +3228,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||||||
shift_mem = false;
|
shift_mem = false;
|
||||||
control_mem = false;
|
control_mem = false;
|
||||||
meta_mem = false;
|
meta_mem = false;
|
||||||
console_visible = IsWindowVisible(GetConsoleWindow());
|
|
||||||
hInstance = ((OS_Windows *)OS::get_singleton())->get_hinstance();
|
hInstance = ((OS_Windows *)OS::get_singleton())->get_hinstance();
|
||||||
|
|
||||||
pressrc = 0;
|
pressrc = 0;
|
||||||
|
@ -414,7 +414,6 @@ class DisplayServerWindows : public DisplayServer {
|
|||||||
bool use_raw_input = false;
|
bool use_raw_input = false;
|
||||||
bool drop_events = false;
|
bool drop_events = false;
|
||||||
bool in_dispatch_input_event = false;
|
bool in_dispatch_input_event = false;
|
||||||
bool console_visible = false;
|
|
||||||
|
|
||||||
WNDCLASSEXW wc;
|
WNDCLASSEXW wc;
|
||||||
|
|
||||||
@ -477,7 +476,7 @@ public:
|
|||||||
|
|
||||||
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) 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 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);
|
virtual void gl_window_make_current(DisplayServer::WindowID p_window_id) override;
|
||||||
|
|
||||||
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
|
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
|
|
||||||
@ -529,9 +528,6 @@ public:
|
|||||||
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
|
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
|
||||||
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
|
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
|
||||||
|
|
||||||
virtual void console_set_visible(bool p_enabled) override;
|
|
||||||
virtual bool is_console_visible() const override;
|
|
||||||
|
|
||||||
virtual void cursor_set_shape(CursorShape p_shape) override;
|
virtual void cursor_set_shape(CursorShape p_shape) override;
|
||||||
virtual CursorShape cursor_get_shape() const override;
|
virtual CursorShape cursor_get_shape() const override;
|
||||||
virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
|
virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
|
||||||
|
@ -52,8 +52,6 @@
|
|||||||
#include <regstr.h>
|
#include <regstr.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
|
||||||
static const WORD MAX_CONSOLE_LINES = 1500;
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
||||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
@ -86,65 +84,17 @@ static String format_error_message(DWORD id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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, nullptr, _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, nullptr, _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, nullptr, _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) {
|
||||||
@ -172,7 +122,9 @@ void OS_Windows::initialize_debugging() {
|
|||||||
void OS_Windows::initialize() {
|
void OS_Windows::initialize() {
|
||||||
crash_handler.initialize();
|
crash_handler.initialize();
|
||||||
|
|
||||||
//RedirectIOToConsole();
|
#ifndef WINDOWS_SUBSYSTEM_CONSOLE
|
||||||
|
RedirectIOToConsole();
|
||||||
|
#endif
|
||||||
|
|
||||||
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
|
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
|
||||||
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
|
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
|
||||||
@ -406,78 +358,87 @@ 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, 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, 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("/", "\\");
|
||||||
String command = _quote_command_line_argument(path);
|
String command = _quote_command_line_argument(path);
|
||||||
for (const String &E : p_arguments) {
|
for (const String &E : p_arguments) {
|
||||||
command += " " + _quote_command_line_argument(E);
|
command += " " + _quote_command_line_argument(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_pipe) {
|
|
||||||
if (read_stderr) {
|
|
||||||
command += " 2>&1"; // Include stderr
|
|
||||||
}
|
|
||||||
// Add extra quotes around the full command, to prevent it from stripping quotes in the command,
|
|
||||||
// because _wpopen calls command as "cmd.exe /c command", instead of executing it directly
|
|
||||||
command = _quote_command_line_argument(command);
|
|
||||||
|
|
||||||
FILE *f = _wpopen((LPCWSTR)(command.utf16().get_data()), L"r");
|
|
||||||
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot create pipe from command: " + command);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessInfo pi;
|
ProcessInfo pi;
|
||||||
ZeroMemory(&pi.si, sizeof(pi.si));
|
ZeroMemory(&pi.si, sizeof(pi.si));
|
||||||
pi.si.cb = sizeof(pi.si);
|
pi.si.cb = sizeof(pi.si);
|
||||||
ZeroMemory(&pi.pi, sizeof(pi.pi));
|
ZeroMemory(&pi.pi, sizeof(pi.pi));
|
||||||
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
|
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
|
||||||
|
|
||||||
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;
|
bool inherit_handles = false;
|
||||||
#ifndef DEBUG_ENABLED
|
HANDLE pipe[2] = { nullptr, nullptr };
|
||||||
dwCreationFlags |= CREATE_NO_WINDOW;
|
if (r_pipe) {
|
||||||
#endif
|
// Create pipe for StdOut and StdErr.
|
||||||
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
sa.bInheritHandle = true;
|
||||||
|
sa.lpSecurityDescriptor = nullptr;
|
||||||
|
|
||||||
int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, dwCreationFlags, nullptr, nullptr, si_w, &pi.pi);
|
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(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, inherit_handles, creaton_flags, nullptr, nullptr, si_w, &pi.pi);
|
||||||
|
if (!ret && r_pipe) {
|
||||||
|
CloseHandle(pipe[0]); // Cleanup pipe handles.
|
||||||
|
CloseHandle(pipe[1]);
|
||||||
|
}
|
||||||
ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
|
ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
|
||||||
|
|
||||||
|
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);
|
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);
|
||||||
*r_exitcode = ret2;
|
*r_exitcode = ret2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(pi.pi.hProcess);
|
CloseHandle(pi.pi.hProcess);
|
||||||
CloseHandle(pi.pi.hThread);
|
CloseHandle(pi.pi.hThread);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool OS_Windows::_is_win11_terminal() const {
|
Error OS_Windows::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Error OS_Windows::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
|
|
||||||
String path = p_path.replace("/", "\\");
|
String path = p_path.replace("/", "\\");
|
||||||
String command = _quote_command_line_argument(path);
|
String command = _quote_command_line_argument(path);
|
||||||
for (const String &E : p_arguments) {
|
for (const String &E : p_arguments) {
|
||||||
@ -490,16 +451,14 @@ Error OS_Windows::create_process(const String &p_path, const List<String> &p_arg
|
|||||||
ZeroMemory(&pi.pi, sizeof(pi.pi));
|
ZeroMemory(&pi.pi, sizeof(pi.pi));
|
||||||
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
|
LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
|
||||||
|
|
||||||
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;
|
DWORD creaton_flags = NORMAL_PRIORITY_CLASS;
|
||||||
#ifndef DEBUG_ENABLED
|
if (p_open_console) {
|
||||||
dwCreationFlags |= CREATE_NO_WINDOW;
|
creaton_flags |= CREATE_NEW_CONSOLE;
|
||||||
#endif
|
} else {
|
||||||
if (p_path == get_executable_path() && GetConsoleWindow() != nullptr && _is_win11_terminal()) {
|
creaton_flags |= CREATE_NO_WINDOW;
|
||||||
// Open a new terminal as a workaround for Windows Terminal bug.
|
|
||||||
dwCreationFlags |= CREATE_NEW_CONSOLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, dwCreationFlags, nullptr, nullptr, si_w, &pi.pi);
|
int ret = CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, false, creaton_flags, nullptr, nullptr, si_w, &pi.pi);
|
||||||
ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
|
ERR_FAIL_COND_V_MSG(ret == 0, ERR_CANT_FORK, "Could not create child process: " + command);
|
||||||
|
|
||||||
ProcessID pid = pi.pi.dwProcessId;
|
ProcessID pid = pi.pi.dwProcessId;
|
||||||
|
@ -128,8 +128,8 @@ public:
|
|||||||
virtual void delay_usec(uint32_t p_usec) const override;
|
virtual void delay_usec(uint32_t p_usec) const override;
|
||||||
virtual uint64_t get_ticks_usec() const override;
|
virtual uint64_t get_ticks_usec() const override;
|
||||||
|
|
||||||
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr) override;
|
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
|
||||||
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
|
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
|
||||||
virtual Error kill(const ProcessID &p_pid) override;
|
virtual Error kill(const ProcessID &p_pid) override;
|
||||||
virtual int get_process_id() const override;
|
virtual int get_process_id() const override;
|
||||||
|
|
||||||
@ -157,7 +157,6 @@ public:
|
|||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
bool _is_win11_terminal() const;
|
|
||||||
virtual bool _check_internal_feature_support(const String &p_feature) override;
|
virtual bool _check_internal_feature_support(const String &p_feature) override;
|
||||||
|
|
||||||
virtual void disable_crash_handler() override;
|
virtual void disable_crash_handler() override;
|
||||||
|
@ -228,14 +228,6 @@ String DisplayServer::ime_get_text() const {
|
|||||||
ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server.");
|
ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayServer::console_set_visible(bool p_enabled) {
|
|
||||||
WARN_PRINT("Console window not supported by this display server.");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DisplayServer::is_console_visible() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
|
void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
|
||||||
WARN_PRINT("Virtual keyboard not supported by this display server.");
|
WARN_PRINT("Virtual keyboard not supported by this display server.");
|
||||||
}
|
}
|
||||||
@ -446,9 +438,6 @@ void DisplayServer::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
|
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
|
||||||
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
|
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("console_set_visible", "console_visible"), &DisplayServer::console_set_visible);
|
|
||||||
ClassDB::bind_method(D_METHOD("is_console_visible"), &DisplayServer::is_console_visible);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "multiline", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()), DEFVAL(false), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
|
ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "multiline", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2i()), DEFVAL(false), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
|
||||||
ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
|
ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
|
||||||
|
|
||||||
@ -493,7 +482,6 @@ void DisplayServer::_bind_methods() {
|
|||||||
BIND_ENUM_CONSTANT(FEATURE_CURSOR_SHAPE);
|
BIND_ENUM_CONSTANT(FEATURE_CURSOR_SHAPE);
|
||||||
BIND_ENUM_CONSTANT(FEATURE_CUSTOM_CURSOR_SHAPE);
|
BIND_ENUM_CONSTANT(FEATURE_CUSTOM_CURSOR_SHAPE);
|
||||||
BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG);
|
BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG);
|
||||||
BIND_ENUM_CONSTANT(FEATURE_CONSOLE_WINDOW);
|
|
||||||
BIND_ENUM_CONSTANT(FEATURE_IME);
|
BIND_ENUM_CONSTANT(FEATURE_IME);
|
||||||
BIND_ENUM_CONSTANT(FEATURE_WINDOW_TRANSPARENCY);
|
BIND_ENUM_CONSTANT(FEATURE_WINDOW_TRANSPARENCY);
|
||||||
BIND_ENUM_CONSTANT(FEATURE_HIDPI);
|
BIND_ENUM_CONSTANT(FEATURE_HIDPI);
|
||||||
|
@ -105,7 +105,6 @@ public:
|
|||||||
FEATURE_CURSOR_SHAPE,
|
FEATURE_CURSOR_SHAPE,
|
||||||
FEATURE_CUSTOM_CURSOR_SHAPE,
|
FEATURE_CUSTOM_CURSOR_SHAPE,
|
||||||
FEATURE_NATIVE_DIALOG,
|
FEATURE_NATIVE_DIALOG,
|
||||||
FEATURE_CONSOLE_WINDOW,
|
|
||||||
FEATURE_IME,
|
FEATURE_IME,
|
||||||
FEATURE_WINDOW_TRANSPARENCY,
|
FEATURE_WINDOW_TRANSPARENCY,
|
||||||
FEATURE_HIDPI,
|
FEATURE_HIDPI,
|
||||||
@ -304,9 +303,6 @@ public:
|
|||||||
virtual Point2i ime_get_selection() const;
|
virtual Point2i ime_get_selection() const;
|
||||||
virtual String ime_get_text() const;
|
virtual String ime_get_text() const;
|
||||||
|
|
||||||
virtual void console_set_visible(bool p_enabled);
|
|
||||||
virtual bool is_console_visible() const;
|
|
||||||
|
|
||||||
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
|
virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
|
||||||
virtual void virtual_keyboard_hide();
|
virtual void virtual_keyboard_hide();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user