feat(term): implement copy_selection()

Implements the copy_selection() method, which returns the selected text.

Adds a copy_on_selection property. When this property is enabled, the
selected text will automatically be copied to the primary clipboard
(Linux X11/Wayland only).
This commit is contained in:
Leroy Hopson 2024-03-03 19:11:16 +13:00
parent 7f03761fb2
commit 13cf5ba023
No known key found for this signature in database
GPG key ID: D2747312A6DB51AA
3 changed files with 45 additions and 4 deletions

View file

@ -17,6 +17,10 @@
#include <libtsm.h> #include <libtsm.h>
#include <xkbcommon/xkbcommon-keysyms.h> #include <xkbcommon/xkbcommon-keysyms.h>
#if defined(__linux)
#include <godot_cpp/classes/display_server.hpp>
#endif
#define SHADERS_DIR "res://addons/godot_xterm/shaders/" #define SHADERS_DIR "res://addons/godot_xterm/shaders/"
#define FOREGROUND_SHADER_PATH SHADERS_DIR "foreground.gdshader" #define FOREGROUND_SHADER_PATH SHADERS_DIR "foreground.gdshader"
#define BACKGROUND_SHADER_PATH SHADERS_DIR "background.gdshader" #define BACKGROUND_SHADER_PATH SHADERS_DIR "background.gdshader"
@ -64,6 +68,12 @@ void Terminal::_bind_methods()
ClassDB::bind_method(D_METHOD("set_blink_off_time", "time"), &Terminal::set_blink_off_time); ClassDB::bind_method(D_METHOD("set_blink_off_time", "time"), &Terminal::set_blink_off_time);
ClassDB::add_property("Terminal", PropertyInfo(Variant::FLOAT, "blink_off_time"), "set_blink_off_time", "get_blink_off_time"); ClassDB::add_property("Terminal", PropertyInfo(Variant::FLOAT, "blink_off_time"), "set_blink_off_time", "get_blink_off_time");
// Selection copying.
ClassDB::bind_method(D_METHOD("copy_selection"), &Terminal::copy_selection);
ClassDB::bind_method(D_METHOD("set_copy_on_selection", "enabled"), &Terminal::set_copy_on_selection);
ClassDB::bind_method(D_METHOD("get_copy_on_selection"), &Terminal::get_copy_on_selection);
ClassDB::add_property("Terminal", PropertyInfo(Variant::BOOL, "copy_on_selection"), "set_copy_on_selection", "get_copy_on_selection");
// Methods. // Methods.
ClassDB::bind_method(D_METHOD("write", "data"), &Terminal::write); ClassDB::bind_method(D_METHOD("write", "data"), &Terminal::write);
@ -89,6 +99,8 @@ Terminal::Terminal()
bell_timer->set_one_shot(true); bell_timer->set_one_shot(true);
add_child(bell_timer, false, INTERNAL_MODE_FRONT); add_child(bell_timer, false, INTERNAL_MODE_FRONT);
copy_on_selection = false;
inverse_mode = InverseMode::INVERSE_MODE_INVERT; inverse_mode = InverseMode::INVERSE_MODE_INVERT;
if (tsm_screen_new(&screen, NULL, NULL)) if (tsm_screen_new(&screen, NULL, NULL))
@ -629,6 +641,25 @@ double Terminal::get_blink_off_time() const
return blink_off_time; return blink_off_time;
} }
String Terminal::copy_selection() {
char *out;
PackedByteArray data;
data.resize(tsm_screen_selection_copy(screen, &out));
memcpy(data.ptrw(), out, data.size());
std::free(out);
return data.get_string_from_utf8();
}
void Terminal::set_copy_on_selection(const bool p_enabled) {
copy_on_selection = p_enabled;
}
bool Terminal::get_copy_on_selection() const {
return copy_on_selection;
}
void Terminal::set_inverse_mode(const int mode) { void Terminal::set_inverse_mode(const int mode) {
inverse_mode = static_cast<InverseMode>(mode); inverse_mode = static_cast<InverseMode>(mode);
@ -754,6 +785,12 @@ void Terminal::_handle_selection(Ref<InputEventMouse> event) {
void Terminal::_on_selection_held() { void Terminal::_on_selection_held() {
if (!(Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) || selection_mode == SelectionMode::NONE) { if (!(Input::get_singleton()->is_mouse_button_pressed(MOUSE_BUTTON_LEFT)) || selection_mode == SelectionMode::NONE) {
#if defined(__linux__)
if (copy_on_selection) {
DisplayServer::get_singleton()->clipboard_set_primary(copy_selection());
}
#endif
selection_timer->stop(); selection_timer->stop();
return; return;
} }

View file

@ -71,6 +71,10 @@ namespace godot
void set_blink_off_time(const double p_blink_off_time); void set_blink_off_time(const double p_blink_off_time);
double get_blink_off_time() const; double get_blink_off_time() const;
String copy_selection();
void set_copy_on_selection(const bool p_enable);
bool get_copy_on_selection() const;
void set_inverse_mode(const int mode); void set_inverse_mode(const int mode);
int get_inverse_mode() const; int get_inverse_mode() const;
@ -89,6 +93,8 @@ namespace godot
double blink_on_time; double blink_on_time;
double blink_off_time; double blink_off_time;
bool copy_on_selection;
InverseMode inverse_mode; InverseMode inverse_mode;
RenderingServer *rs; RenderingServer *rs;

View file

@ -32,8 +32,7 @@ class TestInterface:
func test_has_property_blink_off_time(): func test_has_property_blink_off_time():
assert_has_property_with_default_value("blink_off_time", 0.3) assert_has_property_with_default_value("blink_off_time", 0.3)
# TODO: Implement copy_on_selection property. func test_has_property_copy_on_selection():
func xtest_has_property_copy_on_selection():
assert_has_property_with_default_value("copy_on_selection", false) assert_has_property_with_default_value("copy_on_selection", false)
# TODO: Implement update_mode property. # TODO: Implement update_mode property.
@ -53,8 +52,7 @@ class TestInterface:
func xtest_has_method_copy_all(): func xtest_has_method_copy_all():
assert_has_method_with_return_type("copy_all", TYPE_STRING) assert_has_method_with_return_type("copy_all", TYPE_STRING)
# TODO: Implement copy_selection() method. func test_has_method_copy_selection():
func xtest_has_method_copy_selection():
assert_has_method_with_return_type("copy_selection", TYPE_STRING) assert_has_method_with_return_type("copy_selection", TYPE_STRING)
func test_has_method_get_cols(): func test_has_method_get_cols():