Merge pull request #55987 from bruvzg/wt🤎3

This commit is contained in:
Rémi Verschelde 2022-01-10 16:43:56 +01:00 committed by GitHub
commit 8a192cd0ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 87 additions and 173 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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]

View file

@ -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.

View file

@ -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;

View file

@ -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();

View file

@ -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,

View file

@ -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);

View file

@ -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());
} }

View file

@ -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());

View file

@ -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;

View file

@ -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;

View file

@ -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);
} }
} }

View file

@ -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;
}; };

View file

@ -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;

View file

@ -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":

View file

@ -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");

View file

@ -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;