Skip to content

Commit 5e14ac5

Browse files
authored
#5387 - Fix keyboard input detected as gamepad on some Android devices (#5439)
* [rcore][android] Fix keyboard input detected as gamepad on some devices (#5387) * [core] Add keyboard vs gamepad input test example (#5387)
1 parent 1015021 commit 5e14ac5

File tree

2 files changed

+178
-2
lines changed

2 files changed

+178
-2
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*******************************************************************************************
2+
*
3+
* raylib [core] example - Keyboard vs Gamepad Input Test
4+
*
5+
* Example complexity rating: [★☆☆☆] 1/4
6+
*
7+
* This example is a diagnostic tool to verify that keyboard input is not
8+
* incorrectly detected as gamepad input on Android devices.
9+
*
10+
* Issue reference: https://github.com/raysan5/raylib/issues/5387
11+
*
12+
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
13+
* BSD-like license that allows static linking with closed source software
14+
*
15+
* Copyright (c) 2025 raylib contributors
16+
*
17+
********************************************************************************************/
18+
19+
#include "raylib.h"
20+
21+
//------------------------------------------------------------------------------------
22+
// Program main entry point
23+
//------------------------------------------------------------------------------------
24+
int main(void)
25+
{
26+
// Initialization
27+
//--------------------------------------------------------------------------------------
28+
const int screenWidth = 800;
29+
const int screenHeight = 450;
30+
31+
InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard vs gamepad test");
32+
33+
Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 };
34+
int lastKeyPressed = 0;
35+
36+
SetTargetFPS(60);
37+
//--------------------------------------------------------------------------------------
38+
39+
// Main game loop
40+
while (!WindowShouldClose())
41+
{
42+
// Update
43+
//----------------------------------------------------------------------------------
44+
45+
// Track keyboard input
46+
if (IsKeyDown(KEY_RIGHT)) ballPosition.x += 4.0f;
47+
if (IsKeyDown(KEY_LEFT)) ballPosition.x -= 4.0f;
48+
if (IsKeyDown(KEY_UP)) ballPosition.y -= 4.0f;
49+
if (IsKeyDown(KEY_DOWN)) ballPosition.y += 4.0f;
50+
51+
// Keep ball on screen
52+
if (ballPosition.x < 25) ballPosition.x = 25;
53+
if (ballPosition.x > screenWidth - 25) ballPosition.x = screenWidth - 25;
54+
if (ballPosition.y < 25) ballPosition.y = 25;
55+
if (ballPosition.y > screenHeight - 25) ballPosition.y = screenHeight - 25;
56+
57+
// Track last key pressed
58+
int key = GetKeyPressed();
59+
if (key != 0) lastKeyPressed = key;
60+
//----------------------------------------------------------------------------------
61+
62+
// Draw
63+
//----------------------------------------------------------------------------------
64+
BeginDrawing();
65+
66+
ClearBackground(RAYWHITE);
67+
68+
// Title
69+
DrawText("KEYBOARD vs GAMEPAD INPUT TEST", 180, 10, 20, DARKGRAY);
70+
DrawText("Issue #5387: Keyboard detected as gamepad on some Android devices", 120, 35, 14, GRAY);
71+
72+
// Divider
73+
DrawLine(0, 60, screenWidth, 60, LIGHTGRAY);
74+
75+
// Keyboard section
76+
DrawText("KEYBOARD INPUT", 20, 75, 18, DARKBLUE);
77+
DrawRectangle(20, 100, 360, 80, Fade(BLUE, 0.1f));
78+
79+
DrawText(TextFormat("Arrow Keys: [%s] [%s] [%s] [%s]",
80+
IsKeyDown(KEY_UP) ? "UP" : "--",
81+
IsKeyDown(KEY_DOWN) ? "DN" : "--",
82+
IsKeyDown(KEY_LEFT) ? "LT" : "--",
83+
IsKeyDown(KEY_RIGHT) ? "RT" : "--"), 30, 110, 16, BLACK);
84+
85+
DrawText(TextFormat("Last Key Pressed: %d", lastKeyPressed), 30, 135, 16, DARKGRAY);
86+
DrawText(TextFormat("Any Key Down: %s", (IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) ||
87+
IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT)) ? "YES" : "NO"), 30, 155, 16, DARKGRAY);
88+
89+
// Gamepad section
90+
DrawText("GAMEPAD STATUS", 420, 75, 18, DARKGREEN);
91+
DrawRectangle(420, 100, 360, 80, Fade(GREEN, 0.1f));
92+
93+
bool gamepadReady = IsGamepadAvailable(0);
94+
DrawText(TextFormat("Gamepad 0 Available: %s", gamepadReady ? "YES" : "NO"),
95+
430, 110, 16, gamepadReady ? RED : DARKGREEN);
96+
97+
if (gamepadReady)
98+
{
99+
DrawText(TextFormat("D-Pad: [%s] [%s] [%s] [%s]",
100+
IsGamepadButtonDown(0, GAMEPAD_BUTTON_LEFT_FACE_UP) ? "UP" : "--",
101+
IsGamepadButtonDown(0, GAMEPAD_BUTTON_LEFT_FACE_DOWN) ? "DN" : "--",
102+
IsGamepadButtonDown(0, GAMEPAD_BUTTON_LEFT_FACE_LEFT) ? "LT" : "--",
103+
IsGamepadButtonDown(0, GAMEPAD_BUTTON_LEFT_FACE_RIGHT) ? "RT" : "--"),
104+
430, 135, 16, RED);
105+
106+
DrawText(TextFormat("Gamepad Name: %.20s", GetGamepadName(0)), 430, 155, 14, DARKGRAY);
107+
}
108+
else
109+
{
110+
DrawText("No gamepad detected", 430, 135, 16, DARKGREEN);
111+
}
112+
113+
// Divider
114+
DrawLine(0, 190, screenWidth, 190, LIGHTGRAY);
115+
116+
// Test result section
117+
DrawText("TEST RESULT", 20, 200, 18, MAROON);
118+
119+
bool keyboardActive = IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) ||
120+
IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT);
121+
122+
if (keyboardActive && gamepadReady)
123+
{
124+
// BUG DETECTED: Keyboard is triggering gamepad detection
125+
DrawRectangle(20, 225, 760, 50, Fade(RED, 0.3f));
126+
DrawText("BUG DETECTED: Keyboard input is being detected as gamepad!", 30, 235, 18, RED);
127+
DrawText("The fix for issue #5387 may not be working correctly.", 30, 258, 14, DARKGRAY);
128+
}
129+
else if (keyboardActive && !gamepadReady)
130+
{
131+
// CORRECT: Keyboard works without triggering gamepad
132+
DrawRectangle(20, 225, 760, 50, Fade(GREEN, 0.3f));
133+
DrawText("PASS: Keyboard input detected correctly (no phantom gamepad)", 30, 235, 18, DARKGREEN);
134+
DrawText("Issue #5387 fix is working as expected.", 30, 258, 14, DARKGRAY);
135+
}
136+
else if (!keyboardActive && gamepadReady)
137+
{
138+
// Gamepad is connected (might be real or might be bug on idle)
139+
DrawRectangle(20, 225, 760, 50, Fade(ORANGE, 0.3f));
140+
DrawText("INFO: Gamepad detected - press keyboard keys to test", 30, 235, 18, ORANGE);
141+
DrawText("If gamepad stays active while pressing keyboard = BUG", 30, 258, 14, DARKGRAY);
142+
}
143+
else
144+
{
145+
// Idle state
146+
DrawRectangle(20, 225, 760, 50, Fade(GRAY, 0.1f));
147+
DrawText("WAITING: Press arrow keys to test keyboard input", 30, 235, 18, GRAY);
148+
DrawText("Gamepad should NOT become available when pressing keyboard keys", 30, 258, 14, DARKGRAY);
149+
}
150+
151+
// Ball controlled by keyboard
152+
DrawText("Ball Control (Arrow Keys):", 20, 295, 16, DARKGRAY);
153+
DrawCircleV(ballPosition, 25, MAROON);
154+
DrawCircleLines((int)ballPosition.x, (int)ballPosition.y, 25, DARKGRAY);
155+
156+
// Instructions
157+
DrawRectangle(0, screenHeight - 45, screenWidth, 45, Fade(BLACK, 0.05f));
158+
DrawText("Instructions: Press keyboard arrow keys - the ball should move and gamepad should stay 'NO'",
159+
20, screenHeight - 35, 14, DARKGRAY);
160+
DrawText("If gamepad becomes 'YES' while pressing keyboard = issue #5387 is NOT fixed",
161+
20, screenHeight - 18, 14, DARKGRAY);
162+
163+
EndDrawing();
164+
//----------------------------------------------------------------------------------
165+
}
166+
167+
// De-Initialization
168+
//--------------------------------------------------------------------------------------
169+
CloseWindow();
170+
//--------------------------------------------------------------------------------------
171+
172+
return 0;
173+
}

src/platforms/rcore_android.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,8 +1238,11 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
12381238
//int32_t AKeyEvent_getMetaState(event);
12391239

12401240
// Handle gamepad button presses and releases
1241-
if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
1242-
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD))
1241+
// NOTE: Skip gamepad handling if this is a keyboard event, as some devices
1242+
// report both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD flags
1243+
if ((FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
1244+
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) &&
1245+
!FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD))
12431246
{
12441247
// For now we'll assume a single gamepad which we "detect" on its input event
12451248
CORE.Input.Gamepad.ready[0] = true;

0 commit comments

Comments
 (0)