diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 8ac44a195..57a241b2b 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -139,6 +139,9 @@
If [code]true[/code], the context menu will appear when right-clicked.
+
+ If [code]true[/code], the selected text will be deselected when focus is lost.
+
If [code]false[/code], existing text cannot be modified and new text cannot be added.
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 34ef2e51f..68ed02849 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -249,6 +249,9 @@
The currently installed custom effects. This is an array of [RichTextEffect]s.
To add a custom effect, it's more convenient to use [method install_effect].
+
+ If [code]true[/code], the selected text will be deselected when focus is lost.
+
If [code]true[/code], the label's height will be automatically updated to fit its content.
[b]Note:[/b] This property is used as a workaround to fix issues with [RichTextLabel] in [Container]s, but it's unreliable in some cases and will be removed in future versions.
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index bf8cc77e8..8dfcf39aa 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -485,6 +485,9 @@
If [code]true[/code], a right-click displays the context menu.
+
+ If [code]true[/code], the selected text will be deselected when focus is lost.
+
If [code]true[/code], the "space" character will have a visible representation.
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 88547f485..45ae0de52 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -30,26 +30,24 @@
#include "code_editor.h"
-#include "core/os/input.h"
-#include "core/os/keyboard.h"
-#include "core/string_builder.h"
-#include "editor/editor_scale.h"
-#include "editor_node.h"
-#include "editor_settings.h"
-#include "scene/gui/texture_button.h"
-#include "scene/resources/dynamic_font.h"
#include "core/array.h"
#include "core/class_db.h"
#include "core/dictionary.h"
#include "core/math/math_funcs.h"
#include "core/math/vector2.h"
+#include "core/os/input.h"
#include "core/os/input_event.h"
+#include "core/os/keyboard.h"
#include "core/os/memory.h"
#include "core/resource.h"
#include "core/script_language.h"
+#include "core/string_builder.h"
#include "core/typedefs.h"
#include "core/vector.h"
+#include "editor/editor_scale.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor_node.h"
+#include "editor_settings.h"
#include "scene/2d/canvas_item.h"
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
@@ -59,9 +57,11 @@
#include "scene/gui/scroll_container.h"
#include "scene/gui/shortcut.h"
#include "scene/gui/text_edit.h"
+#include "scene/gui/texture_button.h"
#include "scene/gui/tool_button.h"
#include "scene/main/node.h"
#include "scene/main/timer.h"
+#include "scene/resources/dynamic_font.h"
#include "scene/resources/font.h"
#include "scene/resources/texture.h"
@@ -1735,6 +1735,7 @@ CodeTextEditor::CodeTextEditor() {
text_editor->set_show_line_numbers(true);
text_editor->set_brace_matching(true);
text_editor->set_auto_indent(true);
+ text_editor->set_deselect_on_focus_loss_enabled(false);
status_bar = memnew(HBoxContainer);
add_child(status_bar);
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 61fc55c02..d8b14247a 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -190,7 +190,7 @@ EditorLog::EditorLog() {
log->set_custom_minimum_size(Size2(0, 180) * EDSCALE);
log->set_v_size_flags(SIZE_EXPAND_FILL);
log->set_h_size_flags(SIZE_EXPAND_FILL);
- //log->set_deselect_on_focus_loss_enabled(false);
+ log->set_deselect_on_focus_loss_enabled(false);
vb->add_child(log);
add_message(VERSION_FULL_NAME " (c) 2007-2022 Juan Linietsky, Ariel Manzur & Godot Contributors.");
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 170ff8bee..d762836bb 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -980,6 +980,10 @@ void LineEdit::_notification(int p_what) {
OS::get_singleton()->hide_virtual_keyboard();
}
+ if (deselect_on_focus_loss_enabled) {
+ deselect();
+ }
+
} break;
case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
if (has_focus()) {
@@ -1748,6 +1752,17 @@ bool LineEdit::is_selecting_enabled() const {
return selecting_enabled;
}
+void LineEdit::set_deselect_on_focus_loss_enabled(const bool p_enabled) {
+ deselect_on_focus_loss_enabled = p_enabled;
+ if (p_enabled && selection.enabled && !has_focus()) {
+ deselect();
+ }
+}
+
+bool LineEdit::is_deselect_on_focus_loss_enabled() const {
+ return deselect_on_focus_loss_enabled;
+}
+
void LineEdit::set_right_icon(const Ref &p_icon) {
if (right_icon == p_icon) {
return;
@@ -1904,6 +1919,8 @@ void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_shortcut_keys_enabled"), &LineEdit::is_shortcut_keys_enabled);
ClassDB::bind_method(D_METHOD("set_selecting_enabled", "enable"), &LineEdit::set_selecting_enabled);
ClassDB::bind_method(D_METHOD("is_selecting_enabled"), &LineEdit::is_selecting_enabled);
+ ClassDB::bind_method(D_METHOD("set_deselect_on_focus_loss_enabled", "enable"), &LineEdit::set_deselect_on_focus_loss_enabled);
+ ClassDB::bind_method(D_METHOD("is_deselect_on_focus_loss_enabled"), &LineEdit::is_deselect_on_focus_loss_enabled);
ClassDB::bind_method(D_METHOD("set_right_icon", "icon"), &LineEdit::set_right_icon);
ClassDB::bind_method(D_METHOD("get_right_icon"), &LineEdit::get_right_icon);
@@ -1937,6 +1954,7 @@ void LineEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon");
ADD_GROUP("Placeholder", "placeholder_");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text"), "set_placeholder", "get_placeholder");
@@ -1964,6 +1982,7 @@ LineEdit::LineEdit() {
clear_button_status.pressing_inside = false;
shortcut_keys_enabled = true;
selecting_enabled = true;
+ deselect_on_focus_loss_enabled = true;
undo_stack_pos = nullptr;
_create_undo_state();
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 90c2a7dfd..b27e432df 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -75,6 +75,7 @@ private:
Point2 ime_selection;
bool selecting_enabled;
+ bool deselect_on_focus_loss_enabled;
bool context_menu_enabled;
PopupMenu *menu;
@@ -241,6 +242,9 @@ public:
void set_selecting_enabled(bool p_enabled);
bool is_selecting_enabled() const;
+ void set_deselect_on_focus_loss_enabled(const bool p_enabled);
+ bool is_deselect_on_focus_loss_enabled() const;
+
void set_right_icon(const Ref &p_icon);
Ref get_right_icon();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 1f1ce1007..1cdb1c75b 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1064,7 +1064,13 @@ void RichTextLabel::_notification(int p_what) {
_update_fx(main, dt);
update();
}
- }
+ } break;
+ case NOTIFICATION_FOCUS_EXIT: {
+ if (deselect_on_focus_loss_enabled) {
+ selection.active = false;
+ update();
+ }
+ } break;
}
}
@@ -2501,6 +2507,14 @@ void RichTextLabel::set_selection_enabled(bool p_enabled) {
}
}
+void RichTextLabel::set_deselect_on_focus_loss_enabled(const bool p_enabled) {
+ deselect_on_focus_loss_enabled = p_enabled;
+ if (p_enabled && selection.active && !has_focus()) {
+ selection.active = false;
+ update();
+ }
+}
+
bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p_search_previous) {
ERR_FAIL_COND_V(!selection.enabled, false);
Item *it = main;
@@ -2612,6 +2626,10 @@ bool RichTextLabel::is_selection_enabled() const {
return selection.enabled;
}
+bool RichTextLabel::is_deselect_on_focus_loss_enabled() const {
+ return deselect_on_focus_loss_enabled;
+}
+
void RichTextLabel::set_bbcode(const String &p_bbcode) {
bbcode = p_bbcode;
if (is_inside_tree() && use_bbcode) {
@@ -2772,6 +2790,9 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_selection_enabled", "enabled"), &RichTextLabel::set_selection_enabled);
ClassDB::bind_method(D_METHOD("is_selection_enabled"), &RichTextLabel::is_selection_enabled);
+ ClassDB::bind_method(D_METHOD("set_deselect_on_focus_loss_enabled", "enable"), &RichTextLabel::set_deselect_on_focus_loss_enabled);
+ ClassDB::bind_method(D_METHOD("is_deselect_on_focus_loss_enabled"), &RichTextLabel::is_deselect_on_focus_loss_enabled);
+
ClassDB::bind_method(D_METHOD("parse_bbcode", "bbcode"), &RichTextLabel::parse_bbcode);
ClassDB::bind_method(D_METHOD("append_bbcode", "bbcode"), &RichTextLabel::append_bbcode);
@@ -2819,6 +2840,8 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selection_enabled"), "set_selection_enabled", "is_selection_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_selected_font_color"), "set_override_selected_font_color", "is_overriding_selected_font_color");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled");
+
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "custom_effects", PROPERTY_HINT_RESOURCE_TYPE, "17/17:RichTextEffect", (PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE), "RichTextEffect"), "set_effects", "get_effects");
ADD_SIGNAL(MethodInfo("meta_clicked", PropertyInfo(Variant::NIL, "meta", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
@@ -3010,6 +3033,7 @@ RichTextLabel::RichTextLabel() {
selection.click = nullptr;
selection.active = false;
selection.enabled = false;
+ deselect_on_focus_loss_enabled = true;
visible_characters = -1;
percent_visible = 1;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 30c642470..42d62baec 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -363,6 +363,7 @@ private:
};
Selection selection;
+ bool deselect_on_focus_loss_enabled;
int visible_characters;
float percent_visible;
@@ -473,6 +474,9 @@ public:
String get_selected_text();
void selection_copy();
+ void set_deselect_on_focus_loss_enabled(const bool p_enabled);
+ bool is_deselect_on_focus_loss_enabled() const;
+
Error parse_bbcode(const String &p_bbcode);
Error append_bbcode(const String &p_bbcode);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 858a7a26a..90e0377e6 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1889,12 +1889,18 @@ void TextEdit::_notification(int p_what) {
if (OS::get_singleton()->has_virtual_keyboard() && virtual_keyboard_enabled) {
OS::get_singleton()->hide_virtual_keyboard();
}
+
+ if (deselect_on_focus_loss_enabled) {
+ deselect();
+ }
} break;
case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
if (has_focus()) {
ime_text = OS::get_singleton()->get_ime_text();
ime_selection = OS::get_singleton()->get_ime_selection();
update();
+ } else if (deselect_on_focus_loss_enabled) {
+ deselect();
}
} break;
}
@@ -7153,6 +7159,17 @@ bool TextEdit::is_selecting_enabled() const {
return selecting_enabled;
}
+void TextEdit::set_deselect_on_focus_loss_enabled(const bool p_enabled) {
+ deselect_on_focus_loss_enabled = p_enabled;
+ if (p_enabled && selection.active && !has_focus()) {
+ deselect();
+ }
+}
+
+bool TextEdit::is_deselect_on_focus_loss_enabled() const {
+ return deselect_on_focus_loss_enabled;
+}
+
bool TextEdit::is_shortcut_keys_enabled() const {
return shortcut_keys_enabled;
}
@@ -7261,6 +7278,8 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_virtual_keyboard_enabled"), &TextEdit::is_virtual_keyboard_enabled);
ClassDB::bind_method(D_METHOD("set_selecting_enabled", "enable"), &TextEdit::set_selecting_enabled);
ClassDB::bind_method(D_METHOD("is_selecting_enabled"), &TextEdit::is_selecting_enabled);
+ ClassDB::bind_method(D_METHOD("set_deselect_on_focus_loss_enabled", "enable"), &TextEdit::set_deselect_on_focus_loss_enabled);
+ ClassDB::bind_method(D_METHOD("is_deselect_on_focus_loss_enabled"), &TextEdit::is_deselect_on_focus_loss_enabled);
ClassDB::bind_method(D_METHOD("is_line_set_as_safe", "line"), &TextEdit::is_line_set_as_safe);
ClassDB::bind_method(D_METHOD("set_line_as_safe", "line", "safe"), &TextEdit::set_line_as_safe);
ClassDB::bind_method(D_METHOD("is_line_set_as_bookmark", "line"), &TextEdit::is_line_set_as_bookmark);
@@ -7372,6 +7391,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_on_focus_loss_enabled"), "set_deselect_on_focus_loss_enabled", "is_deselect_on_focus_loss_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smooth_scrolling"), "set_smooth_scroll_enable", "is_smooth_scroll_enabled");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_scroll_speed"), "set_v_scroll_speed", "get_v_scroll_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hiding_enabled"), "set_hiding_enabled", "is_hiding_enabled");
@@ -7537,6 +7557,7 @@ TextEdit::TextEdit() {
minimap_line_spacing = 1;
selecting_enabled = true;
+ deselect_on_focus_loss_enabled = true;
context_menu_enabled = true;
shortcut_keys_enabled = true;
menu = memnew(PopupMenu);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index d2ad1abb2..64984af2f 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -434,6 +434,7 @@ private:
int search_result_col;
bool selecting_enabled;
+ bool deselect_on_focus_loss_enabled;
bool context_menu_enabled;
bool shortcut_keys_enabled;
@@ -844,6 +845,9 @@ public:
void set_selecting_enabled(bool p_enabled);
bool is_selecting_enabled() const;
+ void set_deselect_on_focus_loss_enabled(const bool p_enabled);
+ bool is_deselect_on_focus_loss_enabled() const;
+
void set_shortcut_keys_enabled(bool p_enabled);
bool is_shortcut_keys_enabled() const;