How does one accept shortcuts and focus events?

Godot Version

4.3

Question

I’ve more or less set up my input order (the “Using InputEvent” chart is most helpful). However, there’s still an area that isn’t explained there well enough - or that I just failed to understand. I can work around that, but I thought I’d rather ask & learn.

Consider the following two scenarios:

  1. A button has a Shortcut assigned to it. As usual, it has a “button pressed” signal which connects to the parent control’s “on_button_pressed”. However, if that button wasn’t actually pressed but rather activated with a shortcut – how can “on_button_pressed” stop that key press from propagating? There’s no “event” argument; “accept_event()” does nothing; mouse filter doesn’t apply.
    (if left alone, it does propagate to _unhandled_key_input() of other nodes, I’ve checked).

  2. A button has no shortcuts, but it is focused and was “pressed” using the “ui_accept” key. Usually spacebar. Once again, where would I intercept that press to set it as handled? Doing this in “on_button_pressed” does nothing, same as in the example above.

These seem like more or less the same case: a button is activated with a key but treats it as a mouse click. Sure, I can avoid shortcuts altogether and handle key presses in _unhandled_key_input(), but a) that’s just avoiding a tool that I couldn’t figure out; b) that’s less feasible with focus (which gets handled “under the hood”). So how do I intercept that press?

Hi, I encounter a weird issues with BaseButtons detecting “ui_accept” key, even if they are focused. If clicked “ui_accept” key, it will pressed the button but it wont work if I’m holding the shift key…
After some time debugging, i found that key pressed event for focus button will be detected by _gui_input Control — Godot Engine (stable) documentation in English

Just need to aware that your _gui_input need to be run in the focus node, example mine is in the script for BaseButton.

Below is a sample, you can replace it to detect “ui_accept” key. You can use Control — Godot Engine (stable) documentation in English to consume the event so it does not get read by other inputs handler

func _gui_input(event):
	if event is InputEventKey and event.pressed:
		if event.keycode == KEY_ENTER:
			button_pressed = false
			button_pressed = true
			accept_event()

For more info on how input events are handled:

if you consume the event at _input using Viewport.set_input_as_handled() , then the focus button will not detect the input.
Example, if “ui_accept” key is consumed at _input, the your button wont be pressed.