diff --git a/addons/godot_xterm/native/src/pty.cpp b/addons/godot_xterm/native/src/pty.cpp index 4974594..79710e5 100644 --- a/addons/godot_xterm/native/src/pty.cpp +++ b/addons/godot_xterm/native/src/pty.cpp @@ -67,6 +67,10 @@ void PTY::_bind_methods() { ClassDB::bind_method(D_METHOD("is_using_threads"), &PTY::is_using_threads); ClassDB::add_property("PTY", PropertyInfo(Variant::BOOL, "use_threads"), "set_use_threads", "is_using_threads"); + ClassDB::bind_method(D_METHOD("set_terminal_path", "path"), &PTY::set_terminal_path); + ClassDB::bind_method(D_METHOD("get_terminal_path"), &PTY::get_terminal_path); + ClassDB::add_property("PTY", PropertyInfo(Variant::NODE_PATH, "terminal_path", PropertyHint::PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Terminal"), "set_terminal_path", "get_terminal_path"); + ClassDB::bind_method(D_METHOD("get_pts_name"), &PTY::get_pts_name); ClassDB::bind_method(D_METHOD("fork", "file", "args", "cwd", "cols", "rows"), &PTY::fork, DEFVAL(""), DEFVAL(PackedStringArray()), DEFVAL("."), DEFVAL(80), DEFVAL(24)); @@ -145,6 +149,36 @@ bool PTY::is_using_threads() const { return use_threads; } +void PTY::set_terminal_path(NodePath p_terminal_path) { + terminal_path = p_terminal_path; + + Callable write = Callable(this, "write"); + Callable resizev = Callable(this, "resizev"); + + // Disconnect the current terminal, if any. + if (terminal != nullptr) { + disconnect("data_received", Callable(terminal, "write")); + terminal->disconnect("data_sent", write); + terminal->disconnect("size_changed", resizev); + } + + terminal = Object::cast_to(get_node_or_null(terminal_path)); + if (terminal == nullptr) return; + + // Connect the new terminal. + resize(terminal->get_cols(), terminal->get_rows()); + if (!terminal->is_connected("size_changed", resizev)) + terminal->connect("size_changed", resizev, CONNECT_PERSIST); + if (!terminal->is_connected("data_sent", write)) + terminal->connect("data_sent", write, CONNECT_PERSIST); + if (!is_connected("data_received", Callable(terminal, "write"))) + connect("data_received", Callable(terminal, "write"), CONNECT_PERSIST); +} + +NodePath PTY::get_terminal_path() const { + return terminal_path; +} + String PTY::get_pts_name() const { return pts_name; } @@ -213,8 +247,6 @@ void PTY::resize(const int p_cols, const int p_rows) { #if defined(__linux__) || defined(__APPLE__) if (fd > -1) { PTYUnix::resize(fd, cols, rows); - } else { - ERR_PRINT("fd <= -1"); } #endif } @@ -303,9 +335,11 @@ void PTY::_close() { if (!uv_is_closing((uv_handle_t *)&async_handle)) { uv_close((uv_handle_t *)&async_handle, _close_cb); } - - uv_run(&loop, UV_RUN_NOWAIT); - uv_loop_close(&loop); + + if (status == STATUS_OPEN) { + uv_run(&loop, UV_RUN_NOWAIT); + uv_loop_close(&loop); + } if (fd > 0) close(fd); if (pid > 0) kill(SIGNAL_SIGHUP); diff --git a/addons/godot_xterm/native/src/pty.h b/addons/godot_xterm/native/src/pty.h index 8802dbf..41e2c72 100644 --- a/addons/godot_xterm/native/src/pty.h +++ b/addons/godot_xterm/native/src/pty.h @@ -3,6 +3,8 @@ #pragma once +#include "terminal.h" + #include #include #include @@ -57,6 +59,9 @@ namespace godot void set_use_threads(bool p_use); bool is_using_threads() const; + void set_terminal_path(NodePath p_terminal_path); + NodePath get_terminal_path() const; + String get_pts_name() const; Error fork(const String &file = "", const PackedStringArray &args = PackedStringArray(), const String &cwd = ".", const int cols = 80, const int rows = 24); @@ -83,6 +88,9 @@ namespace godot String pts_name = ""; + NodePath terminal_path; + Terminal *terminal = nullptr; + String _get_fork_file(const String &file) const; Dictionary _get_fork_env() const; PackedStringArray _parse_env(const Dictionary &env) const; diff --git a/test/test_pty.gd b/test/test_pty.gd index f0f3f40..ee35ead 100644 --- a/test/test_pty.gd +++ b/test/test_pty.gd @@ -24,9 +24,8 @@ class TestInterface: func test_has_property_rows() -> void: assert_has_property_with_default_value("rows", 24) - # TODO: Implement terminal_path property. - func xtest_has_property_terminal_path() -> void: - assert_has_property("terminal_path") + func test_has_property_terminal_path() -> void: + assert_has_property_with_default_value("terminal_path", NodePath()) func test_has_proprty_use_os_env() -> void: assert_has_property_with_default_value("use_os_env", true) @@ -82,3 +81,27 @@ class TestInterface: func test_has_no_visible_children(): assert_eq(subject.get_child_count(), 0) + + +class TestSetTerminalPath: + extends PTYTest + + var terminal: Terminal + + func before_each(): + super.before_each() + terminal = Terminal.new() + add_child_autofree(terminal) + subject.terminal_path = terminal.get_path() + + func test_terminal_path_is_set(): + assert_eq(subject.terminal_path, terminal.get_path()) + + func test_data_sent_is_connected(): + assert_connected(terminal, subject, "data_sent", "write") + + func test_size_changed_is_connected(): + assert_connected(terminal, subject, "size_changed", "resizev") + + func test_data_received_is_connected(): + assert_connected(subject, terminal, "data_received", "write")