godotgdscript

How do I get which Control node currently has focus?


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?


Solution

  • 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)