diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index c5c7a0a6460..f4bf94fa268 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -1706,7 +1706,7 @@ ProjectSettings::ProjectSettings() {
#endif
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
- GLOBAL_DEF("gui/common/always_show_focus_state", false);
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/common/show_focus_state_on_pointer_event", PROPERTY_HINT_ENUM, "Never,Control Supports Keyboard Input,Always"), 1);
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 1a9746b7b2f..d28eff5fa5a 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -627,7 +627,7 @@
Steal the focus from another control and become the focused control (see [member focus_mode]).
- If [param hide_focus] is [code]true[/code], the control will not visually show its focused state. Has no effect if [member ProjectSettings.gui/common/always_show_focus_state] is set to [code]true[/code].
+ If [param hide_focus] is [code]true[/code], the control will not visually show its focused state. Has no effect for [LineEdit] and [TextEdit] when [member ProjectSettings.gui/common/show_focus_state_on_pointer_event] is set to [code]Control Supports Keyboard Input[/code], or for any control when it is set to [code]Always[/code].
[b]Note:[/b] Using this method together with [method Callable.call_deferred] makes it more reliable, especially when called inside [method Node._ready].
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 0f65f710f87..9bf78365e56 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1183,12 +1183,15 @@
Override for [member filesystem/import/fbx2gltf/enabled] on the Web where FBX2glTF can't easily be accessed from Godot.
-
- If [code]true[/code], [Control]s will always show if they're focused, even if said focus was gained via mouse/touch input.
-
Default value for [member ScrollContainer.scroll_deadzone], which will be used for all [ScrollContainer]s unless overridden.
+
+ Determines whether a [Control] should visually indicate focus when said focus is gained using a mouse or touch input.
+ - [b]Never[/b] ([code]0[/code]) show the focused state for mouse/touch input.
+ - [b]Control Supports Keyboard Input[/b] ([code]1[/code]) shows the focused state even when gained via mouse/touch input (similar to how browsers handle focus).
+ - [b]Always[/b] ([code]2[/code]) show the focused state, even if said focus was gained via mouse/touch input.
+
If [code]true[/code], snaps [Control] node vertices to the nearest pixel to ensure they remain crisp even when the camera moves or zooms.
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 99d98d5cc5b..ee99e2fe0e9 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -31,6 +31,7 @@
#include "line_edit.h"
#include "line_edit.compat.inc"
+#include "core/config/project_settings.h"
#include "core/input/input_map.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -1349,7 +1350,7 @@ void LineEdit::_notification(int p_what) {
style->draw(ci, Rect2(Point2(), size));
}
- if (has_focus(true)) {
+ if (has_focus(Engine::get_singleton()->is_editor_hint() || GLOBAL_GET_CACHED(int, "gui/common/show_focus_state_on_pointer_event") != 1)) {
theme_cache.focus->draw(ci, Rect2(Point2(), size));
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index f97c217e64f..37a60bc1181 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -950,7 +950,7 @@ void TextEdit::_notification(int p_what) {
if (!editable) {
draw_caret = is_drawing_caret_when_editable_disabled();
}
- if (has_focus(true)) {
+ if (has_focus(Engine::get_singleton()->is_editor_hint() || GLOBAL_GET_CACHED(int, "gui/common/show_focus_state_on_pointer_event") != 1)) {
theme_cache.style_focus->draw(ci, Rect2(Point2(), size));
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 943fdc462f3..6888283a98e 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -534,7 +534,7 @@ void Viewport::_update_viewport_path() {
}
bool Viewport::_can_hide_focus_state() {
- return Engine::get_singleton()->is_editor_hint() || !GLOBAL_GET_CACHED(bool, "gui/common/always_show_focus_state");
+ return Engine::get_singleton()->is_editor_hint() || GLOBAL_GET_CACHED(int, "gui/common/show_focus_state_on_pointer_event") < 2;
}
void Viewport::_on_settings_changed() {