How to make Button Shortcuts SetInputAsHandled?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By JimArtificer

My goal is for the Esc key to work intuitively with my game’s menu system such that pressing it dismisses the top-level window.

I have created a button shortcut keyed off the ui_cancel action that is associated with Esc. As anticipated, pressing the key triggers the button’s pressed signal and performs the function of closing the window.

The problem that I am encountering is that SceneTree.SetInputAsHandled() is not called, so a single key press dismisses all open windows, not just the top-most one.

Is there a setting somewhere that I missed?

:bust_in_silhouette: Reply From: rakkarage

had a similar problem
‘solved’ it by only setting the shortcut when the dialog becomes active
and storing the ui stack so i can restore shortcuts and focus when ‘active window’ changes

func _clearFocus() -> void:
	var accept = _acceptStack[0]
	if accept != null: accept.shortcut = null
	var cancel = _cancelStack[0]
	if cancel != null: cancel.shortcut = null

func _applyFocus() -> void:
	_focusStack[0].grab_focus()
	var accept = _acceptStack[0]
	if accept != null: accept.shortcut = _accept
	var cancel = _cancelStack[0]
	if cancel != null: cancel.shortcut = _cancel

func _popFocus() -> void:
	_clearFocus()
	_focusStack.pop_front()
	_acceptStack.pop_front()
	_cancelStack.pop_front()
	_applyFocus()

func _pushFocus(focus: Control, accept: Control, cancel: Control):
	_clearFocus()
	_focusStack.push_front(focus)
	_acceptStack.push_front(accept)
	_cancelStack.push_front(cancel)
	_applyFocus()

func _focus(focus: Control, accept: Control, cancel: Control):
	_clearFocus()
	_focusStack[0] = focus
	_acceptStack[0] = accept
	_cancelStack[0] = cancel
	_applyFocus()

Thank you for the answer. I have also posted my solution.

JimArtificer | 2020-07-19 04:42

:bust_in_silhouette: Reply From: JimArtificer

Here is the solution that I settled on:

  • Convert the root node of the dialog window scenes I created to be of type Popup.
  • Open the windows with the popup_centered() function. (There are variants of the popup function that can set the size.)
    Popup — Godot Engine (stable) documentation in English
  • Rely on the default Popup handling of the ui_cancel action to close the top window.
  • Give the (invisible) root Popup node a full rect layout to prevent clicks outside the window from closing it.
    • Note: This is done because Popup.Exclusive will prevent clicks outside the window from closing it, but will also ignore ui_cancel.

Also note that there is a show_modal() function on the Control node, but this does not seem to function for Controls that are not children of Popup.