I'm trying to determine which Control node has just changed focus. Another Control node has been set up for using focus by changing the focus mode on the node to All
. From within that node's script, I can tell if it has focus by checking has_focus
. However, I want to tell from another script if it has changed focus.
I know that there's focused_entered
and focus_exited
signals that I could listen to, but these components are pretty far away from each other on the component tree and I don't want to connect or bubble up the signals through a bunch of unrelated components.
The Control documentation says:
Only one
Control
node can be in keyboard focus.
Since there's only ever one node in focus, is there a global function that can determine what the single node currently has focus? How can I tell when the global focus has changed?
The Viewport
has a gui_focus_changed
signal you can use for this. It will give you the Control that has focus each time it changes.
You can connect to it from code like this:
func ready() -> void:
get_viewport().connect("gui_focus_changed", self, "_on_focus_changed")
func _on_focus_changed(control:Control) -> void:
if control != null:
print(control.name)
By the way, if you have a look at the source code for get_focus_owner
(here), the code has the Control
ask the Viewport
it is in for the focus owner. Which is you need a Control
in the scene tree to use get_focus_owner
.
By using gui_focus_changed
, you don't have to use _process
which runs every frame. And thus, you would have less CPU usage.
Addendum for Godot 4: Control
no longer exposes get_focus_owner
, instead use get_viewport().gui_get_focus_owner()
.
Listening to the signal is a bit different too:
func _ready() -> void:
get_viewport().gui_focus_changed.connect(_on_focus_changedchanged)
func _on_focus_changed(control: Control) -> void:
print(control)