Gamepad button mapping not working in Chrome

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

I wrote code for an HTML5 game that will handle gamepad configuration, because different gamepads can give different HTML5 outputs for similar actions. It will ask the player to hold down a button or axis on their gamepad and will assign that button to a set of actions in InputMap.

That works fine when running from the Godot editor, and in HTML5 exports when they’re run in Firefox or Edge, but does not work in Chrome. In Chrome, if the user presses a gamepad button or axis, it can be read by Godot and it will show up in func _unhandled_input(event) as expected. And if I attempt to assign it to an action, then it looks like the gamepad button does get added to InputMap correctly. But in Chrome it doesn’t actually trigger Input.is_action_pressed("action_name"). In the Godot editor, Firefox, and Edge it works as expected.

It might be easier to see in this minimal project that demonstrates the issue.

The text at the top center will turn green if the ui_accept action is pressed, and the list of buttons mapped to ui_accept is shown on the right. The most recently pressed button (keyboard or gamepad) is shown on the left, and if you click the bottom UI button while holding down a key or gamepad button, then it will add it to the list of triggers for ui_accept. If you do that with a keyboard key (with a usual scancode in the 32-97 range), then it will be added to the list for ui_accept and will start turning the top text green as expected. If you do that with a gamepad button, it will be added to the list but won’t actually turn the text green in Chrome, but will in other browsers.

I’ve been burned a few times by strange things happening on my browsers that other people haven’t been able to reproduce, so I’d like to see if other people see the same behavior before I report it as an issue on GitHub, or see if anyone has insight about this browser-specific problem. Here’s the source code for the minimal issue reproduction project.

extends Control

func _ready():
	$Button.connect("pressed", self, "add_to_ui_accept")

func _physics_process(delta):
	# If no gamepad is plugged in, show the warning to plug in a gamepad
	$NoGamepad.visible = true
	if Input.get_connected_joypads().size() > 0:
		$NoGamepad.visible = false
	
	# Make the top line turn green if the ui_accept action is registering
	if Input.is_action_pressed("ui_accept"):
		$Green.modulate = Color.green
	else:
		$Green.modulate = Color.white
	
	# Show the current list of all actions that are mapped to ui_accept
	$ActionList.text = ""
	for event in InputMap.get_action_list("ui_accept"):
		$ActionList.text += event.as_text() + "\n"

func add_to_ui_accept():
	# Add any pressed keys to ui_accept
	# Loop through all scancodes to see which are pressed
	for new_scancode in range(32, 97):
		if Input.is_key_pressed(new_scancode):
			var new_key = InputEventKey.new()
			new_key.scancode = new_scancode
			InputMap.action_add_event("ui_accept", new_key)
	
	# Add any pressed gamepad buttons to ui_accept
	if Input.get_connected_joypads().size() > 0:
		for button_num in JOY_BUTTON_MAX:
			if Input.is_joy_button_pressed(Input.get_connected_joypads()[0], button_num):
				var new_button = InputEventJoypadButton.new()
				new_button.button_index = button_num
				new_button.pressed = true
				InputMap.action_add_event("ui_accept", new_button)

func _unhandled_input(event):
	# Show any events that are currently active
	if not event is InputEventMouseMotion:
		$EventAsText.text = event.as_text()