Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows, 3.x] Improve console handling and execute. #55987

Merged
merged 1 commit into from
Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions core/bind/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "core/io/json.h"
#include "core/io/marshalls.h"
#include "core/math/geometry.h"
#include "core/method_bind_ext.gen.inc"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/project_settings.h"
Expand Down Expand Up @@ -471,15 +472,15 @@ Error _OS::shell_open(String 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;
int exitcode = 0;
List<String> args;
for (int i = 0; i < p_arguments.size(); i++) {
args.push_back(p_arguments[i]);
}
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.push_back(pipe);
if (err != OK) {
Expand Down Expand Up @@ -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_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("shell_open", "uri"), &_OS::shell_open);
ClassDB::bind_method(D_METHOD("get_process_id"), &_OS::get_process_id);
Expand Down
2 changes: 1 addition & 1 deletion core/bind/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class _OS : public Object {
int get_low_processor_usage_mode_sleep_usec() 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 shell_open(String p_uri);
Expand Down
4 changes: 1 addition & 3 deletions core/os/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,6 @@ class OS {
virtual void set_window_always_on_top(bool p_enabled) {}
virtual bool is_window_always_on_top() const { return false; }
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 center_window();

Expand Down Expand Up @@ -290,7 +288,7 @@ class OS {
virtual int get_low_processor_usage_mode_sleep_usec() 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 int get_process_id() const;
virtual void vibrate_handheld(int p_duration_ms = 500);
Expand Down
2 changes: 2 additions & 0 deletions doc/classes/OS.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,14 @@
<argument index="2" name="blocking" type="bool" default="true" />
<argument index="3" name="output" type="Array" default="[ ]" />
<argument index="4" name="read_stderr" type="bool" default="false" />
<argument index="5" name="open_console" type="bool" default="false" />
<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.
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.
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.
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.
Example of blocking mode and retrieving the shell output:
[codeblock]
Expand Down
2 changes: 1 addition & 1 deletion drivers/unix/os_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ uint64_t OS_Unix::get_ticks_usec() const {
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__
// Don't compile this code at all to avoid undefined references.
// Actual virtual call goes to OS_JavaScript.
Expand Down
2 changes: 1 addition & 1 deletion drivers/unix/os_unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class OS_Unix : public OS {
virtual void delay_usec(uint32_t p_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 int get_process_id() const;

Expand Down
8 changes: 0 additions & 8 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2803,11 +2803,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
OS::get_singleton()->set_window_fullscreen(!OS::get_singleton()->is_window_fullscreen());

} 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: {
screenshot_timer->start();
} break;
Expand Down Expand Up @@ -6437,9 +6432,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);
#else
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
p->add_separator();

Expand Down
1 change: 0 additions & 1 deletion editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ class EditorNode : public Node {
SETTINGS_MANAGE_FEATURE_PROFILES,
SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE,
SETTINGS_PICK_MAIN_SCENE,
SETTINGS_TOGGLE_CONSOLE,
SETTINGS_TOGGLE_FULLSCREEN,
SETTINGS_HELP,
SCENE_TAB_CLOSE,
Expand Down
1 change: 0 additions & 1 deletion editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
_initial_set("interface/editor/separate_distraction_mode", false);
_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/quit_confirmation", true);

Expand Down
4 changes: 0 additions & 4 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2089,10 +2089,6 @@ bool Main::start() {
}

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)
Crypto::load_default_certificates(EditorSettings::get_singleton()->get_setting("network/ssl/editor_ssl_certificates").operator String());
}
Expand Down
2 changes: 1 addition & 1 deletion platform/javascript/os_javascript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ void OS_JavaScript::finalize() {

// 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;
for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
args.push_back(E->get());
Expand Down
2 changes: 1 addition & 1 deletion platform/javascript/os_javascript.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ class OS_JavaScript : public OS_Unix {
virtual MainLoop *get_main_loop() const;
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 int get_process_id() const;
int get_processor_count() const;
Expand Down
2 changes: 1 addition & 1 deletion platform/osx/os_osx.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ class OS_OSX : public OS_Unix {
virtual void set_offscreen_gl_current(bool p_current);

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 int keyboard_get_layout_count() const;
Expand Down
6 changes: 3 additions & 3 deletions platform/osx/os_osx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2967,7 +2967,7 @@ static int get_screen_index(NSScreen *screen) {
}
}

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, *)) {
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.
Expand Down Expand Up @@ -3014,10 +3014,10 @@ static int get_screen_index(NSScreen *screen) {

return err;
} 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 {
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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion platform/uwp/os_uwp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ void OS_UWP::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
// 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;
};

Expand Down
2 changes: 1 addition & 1 deletion platform/uwp/os_uwp.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class OS_UWP : public OS {
virtual void delay_usec(uint32_t p_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 bool has_environment(const String &p_var) const;
Expand Down
12 changes: 5 additions & 7 deletions platform/windows/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,25 +183,23 @@ def configure_msvc(env, manual_msvc_config):
env.Append(CCFLAGS=["/O1"])
env.Append(LINKFLAGS=["/OPT:REF"])

env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"])
env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"])

elif env["target"] == "release_debug":
if env["optimize"] == "speed": # optimize for speed (default)
env.Append(CCFLAGS=["/O2"])
env.Append(LINKFLAGS=["/OPT:REF"])
elif env["optimize"] == "size": # optimize for size
env.Append(CCFLAGS=["/O1"])
env.Append(LINKFLAGS=["/OPT:REF"])
env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])

elif env["target"] == "debug":
env.AppendUnique(CCFLAGS=["/Zi", "/FS", "/Od", "/EHsc"])
env.Append(LINKFLAGS=["/SUBSYSTEM:CONSOLE"])
# Allow big objects. Only needed for debug, see MinGW branch for rationale.
env.AppendUnique(CCFLAGS=["/bigobj"])
env.Append(LINKFLAGS=["/DEBUG"])

env.Append(LINKFLAGS=["/SUBSYSTEM:WINDOWS"])
env.Append(LINKFLAGS=["/ENTRY:mainCRTStartup"])

if env["debug_symbols"]:
env.AppendUnique(CCFLAGS=["/Zi", "/FS"])
env.AppendUnique(LINKFLAGS=["/DEBUG"])
Expand Down Expand Up @@ -316,8 +314,6 @@ def configure_mingw(env):
env.Append(CCFLAGS=["-O2"])
else: # optimize for size
env.Prepend(CCFLAGS=["-Os"])
env.Append(LINKFLAGS=["-Wl,--subsystem,windows"])

if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])

Expand All @@ -337,6 +333,8 @@ def configure_mingw(env):
# and are the only ones with too big objects).
env.Append(CCFLAGS=["-Wa,-mbig-obj"])

env.Append(LINKFLAGS=["-Wl,--subsystem,windows"])

## Compiler configuration

if os.name == "nt":
Expand Down
Loading