_gui_input vs _unhandled_input for key presses

Godot Version

4.2.1

Question

I’m messing around with keyboard inputs for the first time and I found a lot of examples use _unhandled_input() (or _unhandled_key_input()) for handling key events in GUIs. I have a simple GUI, and I added an input map for the esc key called “Exit Menu”. To test this, I added a few lines:

func _gui_input(event: InputEvent) -> void:
	if event.is_action_pressed("Exit Menu"):
		print("accepted")

This never seems to work. However, this does:

func _unhandled_key_input(event: InputEvent) -> void:
	if event.is_action_pressed("Exit Menu"):
		print("accepted")

I’m confused as to why, what I’ve read seems to suggest _gui_input() should work for this.

As I wrote this, I realized the test I did on my top-level UI element (which is a CanvasLayer) probably shouldn’t work with _gui_input(). But I’ve also tested it on the Control that’s right below it, as well as a menu that I bring up that’s a MarginContainer. In all these cases, _unhandled_key_input() seems to work, but _gui_input() does not.

As I have a path forward with _unhandled_key_input() this isn’t dire, but it’s more a matter of understanding what functions I’m supposed to be using.

Yes? I’ve seen this. I’m not embedding windows (#1, #2), and I’m not (to my knowledge) reading and consuming the input anywhere (#3). So I’m at #4, where it should go to _gui_input(), and that’s not working, hence my question. If you were hoping to direct me to something more specific, please elaborate.

Control._gui_input() is special and will only get called when the Control is focused or when a mouse event passes the conditions listed in the documentation:

The event won’t trigger if:

1 Like

Ah, so this I also saw, but on closer consideration I was just assuming that my UI element was focused because I hadn’t specified anything else, but that’s not the case.

Setting Focus > Mode to all was step 1. Step 2 was in my display menu code, calling grab_focus().

Thanks for helping me crack the case!