Skip to content

Commit

Permalink
Merge pull request #90743 from timothyqiu/empty-selection-clipboard
Browse files Browse the repository at this point in the history
Add TextEdit option to prevent copying without a selection
  • Loading branch information
akien-mga committed Sep 23, 2024
2 parents 155fcd0 + 504e065 commit 720c236
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 0 deletions.
3 changes: 3 additions & 0 deletions doc/classes/EditorSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,9 @@
<member name="text_editor/behavior/files/trim_trailing_whitespace_on_save" type="bool" setter="" getter="">
If [code]true[/code], trims trailing whitespace when saving a script. Trailing whitespace refers to tab and space characters placed at the end of lines. Since these serve no practical purpose, they can and should be removed to make version control diffs less noisy.
</member>
<member name="text_editor/behavior/general/empty_selection_clipboard" type="bool" setter="" getter="">
If [code]true[/code], copying or cutting without a selection is performed on all lines with a caret. Otherwise, copy and cut require a selection.
</member>
<member name="text_editor/behavior/indent/auto_indent" type="bool" setter="" getter="">
If [code]true[/code], automatically indents code when pressing the [kbd]Enter[/kbd] key based on blocks above the new line.
</member>
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/TextEdit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,9 @@
<member name="editable" type="bool" setter="set_editable" getter="is_editable" default="true" keywords="readonly, disabled, enabled">
If [code]false[/code], existing text cannot be modified and new text cannot be added.
</member>
<member name="empty_selection_clipboard_enabled" type="bool" setter="set_empty_selection_clipboard_enabled" getter="is_empty_selection_clipboard_enabled" default="true">
If [code]true[/code], copying or cutting without a selection is performed on all lines with a caret. Otherwise, copy and cut require a selection.
</member>
<member name="focus_mode" type="int" setter="set_focus_mode" getter="get_focus_mode" overrides="Control" enum="Control.FocusMode" default="2" />
<member name="highlight_all_occurrences" type="bool" setter="set_highlight_all_occurrences" getter="is_highlight_all_occurrences_enabled" default="false">
If [code]true[/code], all occurrences of the selected text will be highlighted.
Expand Down
3 changes: 3 additions & 0 deletions editor/code_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,9 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_draw_spaces(EDITOR_GET("text_editor/appearance/whitespace/draw_spaces"));
text_editor->add_theme_constant_override("line_spacing", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));

// Behavior: General
text_editor->set_empty_selection_clipboard_enabled(EDITOR_GET("text_editor/behavior/general/empty_selection_clipboard"));

// Behavior: Navigation
text_editor->set_scroll_past_end_of_file_enabled(EDITOR_GET("text_editor/behavior/navigation/scroll_past_end_of_file"));
text_editor->set_smooth_scroll_enabled(EDITOR_GET("text_editor/behavior/navigation/smooth_scrolling"));
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/appearance/whitespace/line_spacing", 4, "0,50,1")

// Behavior
// Behavior: General
_initial_set("text_editor/behavior/general/empty_selection_clipboard", true);

// Behavior: Navigation
_initial_set("text_editor/behavior/navigation/move_caret_on_right_click", true, true);
_initial_set("text_editor/behavior/navigation/scroll_past_end_of_file", false, true);
Expand Down
3 changes: 3 additions & 0 deletions scene/gui/code_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,9 @@ void CodeEdit::_cut_internal(int p_caret) {
delete_selection(p_caret);
return;
}
if (!is_empty_selection_clipboard_enabled()) {
return;
}
if (p_caret == -1) {
delete_lines();
} else {
Expand Down
20 changes: 20 additions & 0 deletions scene/gui/text_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3367,6 +3367,14 @@ bool TextEdit::is_middle_mouse_paste_enabled() const {
return middle_mouse_paste_enabled;
}

void TextEdit::set_empty_selection_clipboard_enabled(bool p_enabled) {
empty_selection_clipboard_enabled = p_enabled;
}

bool TextEdit::is_empty_selection_clipboard_enabled() const {
return empty_selection_clipboard_enabled;
}

// Text manipulation
void TextEdit::clear() {
setting_text = true;
Expand Down Expand Up @@ -6569,6 +6577,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_middle_mouse_paste_enabled", "enabled"), &TextEdit::set_middle_mouse_paste_enabled);
ClassDB::bind_method(D_METHOD("is_middle_mouse_paste_enabled"), &TextEdit::is_middle_mouse_paste_enabled);

ClassDB::bind_method(D_METHOD("set_empty_selection_clipboard_enabled", "enabled"), &TextEdit::set_empty_selection_clipboard_enabled);
ClassDB::bind_method(D_METHOD("is_empty_selection_clipboard_enabled"), &TextEdit::is_empty_selection_clipboard_enabled);

// Text manipulation
ClassDB::bind_method(D_METHOD("clear"), &TextEdit::clear);

Expand Down Expand Up @@ -6962,6 +6973,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_and_drop_selection_enabled"), "set_drag_and_drop_selection_enabled", "is_drag_and_drop_selection_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "empty_selection_clipboard_enabled"), "set_empty_selection_clipboard_enabled", "is_empty_selection_clipboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Arbitrary:1,Word:2,Word (Smart):3"), "set_autowrap_mode", "get_autowrap_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "indent_wrapped_lines"), "set_indent_wrapped_lines", "is_indent_wrapped_lines");
Expand Down Expand Up @@ -7216,6 +7228,10 @@ void TextEdit::_cut_internal(int p_caret) {
return;
}

if (!empty_selection_clipboard_enabled) {
return;
}

// Remove full lines.
begin_complex_operation();
begin_multicaret_edit();
Expand Down Expand Up @@ -7246,6 +7262,10 @@ void TextEdit::_copy_internal(int p_caret) {
return;
}

if (!empty_selection_clipboard_enabled) {
return;
}

// Copy full lines.
StringBuilder clipboard;
Vector<Point2i> line_ranges;
Expand Down
4 changes: 4 additions & 0 deletions scene/gui/text_edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ class TextEdit : public Control {
bool shortcut_keys_enabled = true;
bool virtual_keyboard_enabled = true;
bool middle_mouse_paste_enabled = true;
bool empty_selection_clipboard_enabled = true;

// Overridable actions.
String cut_copy_line = "";
Expand Down Expand Up @@ -770,6 +771,9 @@ class TextEdit : public Control {
void set_middle_mouse_paste_enabled(bool p_enabled);
bool is_middle_mouse_paste_enabled() const;

void set_empty_selection_clipboard_enabled(bool p_enabled);
bool is_empty_selection_clipboard_enabled() const;

// Text manipulation
void clear();

Expand Down
25 changes: 25 additions & 0 deletions tests/scene/test_code_edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -4779,6 +4779,31 @@ TEST_CASE("[SceneTree][CodeEdit] text manipulation") {
CHECK(code_edit->get_caret_column(3) == 0);
}

SUBCASE("[SceneTree][CodeEdit] cut when empty selection clipboard disabled") {
DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton());
code_edit->set_empty_selection_clipboard_enabled(false);
DS->clipboard_set("");

code_edit->set_text("this is\nsome\n");
code_edit->set_caret_line(0);
code_edit->set_caret_column(6);
MessageQueue::get_singleton()->flush();
SIGNAL_DISCARD("text_set");
SIGNAL_DISCARD("text_changed");
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");

code_edit->cut();
MessageQueue::get_singleton()->flush();
CHECK(DS->clipboard_get() == "");
CHECK(code_edit->get_text() == "this is\nsome\n");
CHECK(code_edit->get_caret_line() == 0);
CHECK(code_edit->get_caret_column() == 6);
SIGNAL_CHECK_FALSE("caret_changed");
SIGNAL_CHECK_FALSE("text_changed");
SIGNAL_CHECK_FALSE("lines_edited_from");
}

SUBCASE("[SceneTree][CodeEdit] new line") {
// Add a new line.
code_edit->set_text("test new line");
Expand Down
48 changes: 48 additions & 0 deletions tests/scene/test_text_edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -3585,6 +3585,54 @@ TEST_CASE("[SceneTree][TextEdit] text entry") {
SIGNAL_CHECK_FALSE("lines_edited_from");
}

SUBCASE("[TextEdit] cut when empty selection clipboard disabled") {
text_edit->set_empty_selection_clipboard_enabled(false);
DS->clipboard_set("");

text_edit->set_text("this is\nsome\n");
text_edit->set_caret_line(0);
text_edit->set_caret_column(6);
MessageQueue::get_singleton()->flush();
SIGNAL_DISCARD("text_set");
SIGNAL_DISCARD("text_changed");
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");

text_edit->cut();
MessageQueue::get_singleton()->flush();
CHECK(DS->clipboard_get() == "");
CHECK(text_edit->get_text() == "this is\nsome\n");
CHECK(text_edit->get_caret_line() == 0);
CHECK(text_edit->get_caret_column() == 6);
SIGNAL_CHECK_FALSE("caret_changed");
SIGNAL_CHECK_FALSE("text_changed");
SIGNAL_CHECK_FALSE("lines_edited_from");
}

SUBCASE("[TextEdit] copy when empty selection clipboard disabled") {
text_edit->set_empty_selection_clipboard_enabled(false);
DS->clipboard_set("");

text_edit->set_text("this is\nsome\n");
text_edit->set_caret_line(0);
text_edit->set_caret_column(6);
MessageQueue::get_singleton()->flush();
SIGNAL_DISCARD("text_set");
SIGNAL_DISCARD("text_changed");
SIGNAL_DISCARD("lines_edited_from");
SIGNAL_DISCARD("caret_changed");

text_edit->copy();
MessageQueue::get_singleton()->flush();
CHECK(DS->clipboard_get() == "");
CHECK(text_edit->get_text() == "this is\nsome\n");
CHECK(text_edit->get_caret_line() == 0);
CHECK(text_edit->get_caret_column() == 6);
SIGNAL_CHECK_FALSE("caret_changed");
SIGNAL_CHECK_FALSE("text_changed");
SIGNAL_CHECK_FALSE("lines_edited_from");
}

SIGNAL_UNWATCH(text_edit, "text_set");
SIGNAL_UNWATCH(text_edit, "text_changed");
SIGNAL_UNWATCH(text_edit, "lines_edited_from");
Expand Down

0 comments on commit 720c236

Please sign in to comment.