From a005a044dac0d55d6e7b0eb783541e4fa88138d3 Mon Sep 17 00:00:00 2001 From: Tubbles Date: Sun, 10 May 2026 19:20:35 +0200 Subject: [PATCH] [rcore_android] Restore face-button input on Android gamepads (#5824) The KEYBOARD-source veto added in #5439 drops face-button key events that arrive with both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD set on the source bitmask. Confirmed reproducible on GameSir X2 Type-C and 8BitDo Ultimate Bluetooth, both reporting source 0x501 on every face-button key event. This source-bit pattern is general AOSP behaviour since Android 3.2 (commit 6f2fba4 in frameworks/base, Feb 2011): EventHub adds InputDeviceClass::KEYBOARD to any device whose evdev keyBitmask claims gamepad buttons (BTN_JOYSTICK..BTN_DIGI), and KeyboardInputMapper::getEventSource stamps the resulting KEYBOARD|GAMEPAD source on every outgoing key event. Use AndroidTranslateGamepadButton(keycode) as the discriminator instead. Recognised gamepad keycodes route to the gamepad path; unknown keycodes fall through to the keyboard handler. Assisted-by: Claude:claude-opus-4-7 --- src/platforms/rcore_android.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index ca0de7239..990b2fe6a 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -1273,27 +1273,28 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) int32_t keycode = AKeyEvent_getKeyCode(event); //int32_t AKeyEvent_getMetaState(event); - // Handle gamepad button presses and releases - // NOTE: Skip gamepad handling if this is a keyboard event, as some devices - // report both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD flags - if ((FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) || - FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) && - !FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD)) + // Handle gamepad button presses and releases. AOSP stamps the + // KEYBOARD source bit on every key event from a gamepad, so + // discriminate on the keycode rather than gating on source bits. + if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) || + FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) { - // Assuming a single gamepad, "detected" on its input event - CORE.Input.Gamepad.ready[0] = true; - GamepadButton button = AndroidTranslateGamepadButton(keycode); - if (button == GAMEPAD_BUTTON_UNKNOWN) return 1; - - if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) + if (button != GAMEPAD_BUTTON_UNKNOWN) { - CORE.Input.Gamepad.currentButtonState[0][button] = 1; - } - else CORE.Input.Gamepad.currentButtonState[0][button] = 0; // Key up + // Assuming a single gamepad, "detected" on its input event + CORE.Input.Gamepad.ready[0] = true; - return 1; // Handled gamepad button + if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) + { + CORE.Input.Gamepad.currentButtonState[0][button] = 1; + } + else CORE.Input.Gamepad.currentButtonState[0][button] = 0; // Key up + + return 1; // Handled gamepad button + } + // Unknown keycode: fall through to the keyboard handler below. } KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL;