From 3fcaa79f6e99c5ce54edc7733ecb8ea432060196 Mon Sep 17 00:00:00 2001 From: Leroy Hopson Date: Thu, 15 Feb 2024 06:53:53 +1300 Subject: [PATCH] Add support for key input --- addons/godot_xterm/native/src/terminal.cpp | 54 +++++++++++++++++++++- addons/godot_xterm/native/src/terminal.h | 6 +++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/addons/godot_xterm/native/src/terminal.cpp b/addons/godot_xterm/native/src/terminal.cpp index e56bda7..7798614 100644 --- a/addons/godot_xterm/native/src/terminal.cpp +++ b/addons/godot_xterm/native/src/terminal.cpp @@ -6,11 +6,13 @@ #include #include #include +#include #include #include #include #include #include +#include #define SHADERS_DIR "res://addons/godot_xterm/shaders/" #define FOREGROUND_SHADER_PATH SHADERS_DIR "foreground.gdshader" @@ -64,10 +66,13 @@ void Terminal::_bind_methods() ClassDB::bind_method(D_METHOD("write", "data"), &Terminal::write); ClassDB::bind_method(D_METHOD("get_cursor_pos"), &Terminal::get_cursor_pos); + ClassDB::bind_method(D_METHOD("_on_gui_input", "event"), &Terminal::_gui_input); } Terminal::Terminal() { + set_focus_mode(FOCUS_ALL); + max_scrollback = 1000; blink_on_time = 0.6; @@ -93,6 +98,7 @@ Terminal::Terminal() } tsm_vte_set_bell_cb(vte, &Terminal::_bell_cb, this); + initialize_input(); initialize_rendering(); update_theme(); update_sizes(); @@ -163,6 +169,10 @@ String Terminal::write(const Variant data) return response.get_string_from_utf8(); } +void Terminal::_gui_input(const Ref &event) { + _handle_key_input(event); +} + void Terminal::_notification(int what) { switch (what) @@ -592,4 +602,46 @@ void Terminal::set_inverse_mode(const int mode) { int Terminal::get_inverse_mode() const { return static_cast(inverse_mode); -} \ No newline at end of file +} + +void Terminal::initialize_input() { + connect("gui_input", Callable(this, "_on_gui_input")); +} + +void Terminal::_handle_key_input(Ref event) { + if (!event.is_valid() || !event->is_pressed()) + return; + + const Key keycode = event->get_keycode(); + char32_t unicode = event->get_unicode(); + uint32_t ascii = unicode <= 127 ? unicode : 0; + + unsigned int mods = 0; + if (event->is_alt_pressed()) + mods |= TSM_SHIFT_MASK; + if (event->is_ctrl_pressed()) + mods |= TSM_CONTROL_MASK; + if (event->is_shift_pressed()) + mods |= TSM_SHIFT_MASK; + + std::pair key = {keycode, unicode}; + uint32_t keysym = (KEY_MAP.count(key) > 0) ? KEY_MAP.at(key) : XKB_KEY_NoSymbol; + + last_input_event_key = event; + tsm_vte_handle_keyboard(vte, keysym, ascii, mods, unicode ? unicode : TSM_VTE_INVALID); + + // Return to the bottom of the scrollback buffer if we scrolled up. Ignore + // modifier keys pressed in isolation or if Ctrl+Shift modifier keys are + // pressed. + std::set mod_keys = {KEY_ALT, KEY_SHIFT, KEY_CTRL, KEY_META}; + if (mod_keys.find(keycode) == mod_keys.end() && + !(event->is_ctrl_pressed() && event->is_shift_pressed())) { + tsm_screen_sb_reset(screen); + queue_redraw(); + } + + // Prevent focus changing to other inputs when pressing Tab or Arrow keys. + std::set tab_arrow_keys = {KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_TAB}; + if (tab_arrow_keys.find(keycode) != tab_arrow_keys.end()) + accept_event(); +} diff --git a/addons/godot_xterm/native/src/terminal.h b/addons/godot_xterm/native/src/terminal.h index f50acb6..9851bf3 100644 --- a/addons/godot_xterm/native/src/terminal.h +++ b/addons/godot_xterm/native/src/terminal.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -75,6 +76,7 @@ namespace godot String write(const Variant data); + void _gui_input(const Ref &event) override; protected: static void _bind_methods(); @@ -146,6 +148,10 @@ namespace godot void _get_property_list(List *p_list) const; bool _is_valid_color_name(const String &p_name); bool _is_valid_font_type(const String &p_name); + + Ref last_input_event_key; + void initialize_input(); + void _handle_key_input(Ref event); }; } // namespace godot