From 14afdf0e87943de6abb3a245ed8859b464149455 Mon Sep 17 00:00:00 2001 From: libretroadmin Date: Fri, 8 Jul 2022 21:03:19 +0200 Subject: [PATCH] (Android) Backport https://github.com/robinei/RetroArch/commit/2020e9ce6a15a9d87777fd26ecf10f6ab8cf7ecc - * Gingerbread support * Touchpads support * builtin Xperia Play autoconfig profile --- input/drivers/android_input.c | 169 ++++++++++++++++++++++++++++--- input/input_autodetect_builtin.c | 24 +++++ 2 files changed, 180 insertions(+), 13 deletions(-) diff --git a/input/drivers/android_input.c b/input/drivers/android_input.c index e071fc4c4a..5c162f6668 100644 --- a/input/drivers/android_input.c +++ b/input/drivers/android_input.c @@ -167,6 +167,10 @@ bool (*engine_lookup_name)(char *buf, int *vendorId, int *productId, size_t size, int id); void (*engine_handle_dpad)(struct android_app *, AInputEvent*, int, int); +static void android_input_poll_input_gingerbread(android_input_t *android, bool vibrate_on_keypress); +static void android_input_poll_input_default(android_input_t *android, bool vibrate_on_keypress); +static void (*android_input_poll_input)(android_input_t *android, bool vibrate_on_keypress); + static bool android_input_set_sensor_state(void *data, unsigned port, enum retro_sensor_action action, unsigned event_rate); @@ -541,11 +545,16 @@ static void *android_input_init(const char *joypad_driver) frontend_android_get_version_sdk(&sdk); if (sdk >= 19) - engine_lookup_name = android_input_lookup_name; + engine_lookup_name = android_input_lookup_name; else - engine_lookup_name = android_input_lookup_name_prekitkat; + engine_lookup_name = android_input_lookup_name_prekitkat; - engine_handle_dpad = engine_handle_dpad_default; + engine_handle_dpad = engine_handle_dpad_default; + + if (sdk > 10) + android_input_poll_input = android_input_poll_input_default; + else + android_input_poll_input = android_input_poll_input_gingerbread; if (!android_input_init_handle()) { @@ -1035,7 +1044,7 @@ static void handle_hotplug(android_input_t *android, strstr(device_model, "Xperia Play") || strstr(device_model, "Play") || strstr(device_model, "SO-01D") - ) && ( + ) || ( strstr(device_name, "keypad-game-zeus") || strstr(device_name, "keypad-zeus") || strstr(device_name, "Android Gamepad") @@ -1186,14 +1195,146 @@ static void handle_hotplug(android_input_t *android, static int android_input_get_id(AInputEvent *event) { int id = AInputEvent_getDeviceId(event); - if (id == pad_id2) - id = pad_id1; - + return pad_id1; return id; } -static void android_input_poll_input(android_input_t *android, +struct TOUCHSTATE +{ + int down; + int x; + int y; +}; + +static void engine_handle_touchpad( + struct android_app *android, AInputEvent *event, int port) +{ + unsigned n; + static struct TOUCHSTATE touchstate[64]; + int pointer_count = AMotionEvent_getPointerCount(event); + + for(n = 0; n < pointer_count; ++n) + { + int pointer_id = AMotionEvent_getPointerId(event, n); + int action = AMOTION_EVENT_ACTION_MASK + & AMotionEvent_getAction(event); + int raw_action = AMotionEvent_getAction(event); + if( action == AMOTION_EVENT_ACTION_POINTER_DOWN + || action == AMOTION_EVENT_ACTION_POINTER_UP ) + { + int pointer_index = (AMotionEvent_getAction( event ) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + pointer_id = AMotionEvent_getPointerId( event, pointer_index); + } + + if( action == AMOTION_EVENT_ACTION_DOWN + || action == AMOTION_EVENT_ACTION_POINTER_DOWN ) + touchstate[pointer_id].down = 1; + else if( action == AMOTION_EVENT_ACTION_UP + || action == AMOTION_EVENT_ACTION_POINTER_UP + || action == AMOTION_EVENT_ACTION_CANCEL ) + touchstate[pointer_id].down = 0; + + if (touchstate[pointer_id].down) + { + int x = touchstate[pointer_id].x = AMotionEvent_getX(event, n); + int y = touchstate[pointer_id].y = AMotionEvent_getY(event, n); + if (x < 360) + { + android->analog_state[port][0] = + (int16_t)((x / 180.0 - 1.0f) * 32767.0f); + android->analog_state[port][1] = + (int16_t)((y / 180.0 - 1.0f) * 32767.0f); + } + else if (x >= 606) + { + x -= 606; + android->analog_state[port][2] = + (int16_t)((x / 180.0 - 1.0f) * 32767.0f); + android->analog_state[port][3] = + (int16_t)((y / 180.0 - 1.0f) * 32767.0f); + } + } + else + { + if (touchstate[pointer_id].x < 360) + { + android->analog_state[port][0] = 0.0f; + android->analog_state[port][1] = 0.0f; + } + else if (touchstate[pointer_id].x >= 606) + { + android->analog_state[port][2] = 0.0f; + android->analog_state[port][3] = 0.0f; + } + } + } +} + +static void android_input_poll_input_gingerbread( + android_input_t *android, + bool vibrate_on_keypress) +{ + AInputEvent *event = NULL; + struct android_app *android_app = (struct android_app*)g_android; + + /* Read all pending events. */ + if (AInputQueue_getEvent(android_app->inputQueue, &event) >= 0) + { + int source, type_event, id, port; + int32_t handled = 0; + if (AInputQueue_preDispatchEvent(android_app->inputQueue, event)) + return; + source = AInputEvent_getSource(event); + type_event = AInputEvent_getType(event); + id = android_input_get_id(event); + port = android_input_get_id_port(android, id, source); + + if (port < 0 && !android_is_keyboard_id(id)) + port = android_input_recover_port(android, id); + + if (port < 0 && !android_is_keyboard_id(id)) + handle_hotplug(android, android_app, + &port, id, source); + + switch (type_event) + { + case AINPUT_EVENT_TYPE_MOTION: + if ((source & AINPUT_SOURCE_TOUCHPAD)) + engine_handle_touchpad(android_app, event, port); + /* Only handle events from a touchscreen or mouse */ + else if ((source & (AINPUT_SOURCE_TOUCHSCREEN + | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE))) + android_input_poll_event_type_motion(android, event, + port, source, vibrate_on_keypress); + else + engine_handle_dpad(android_app, event, port, source); + handled = 1; + break; + case AINPUT_EVENT_TYPE_KEY: + { + int keycode = AKeyEvent_getKeyCode(event); + + if (android_is_keyboard_id(id)) + { + android_input_poll_event_type_keyboard( + event, keycode, &handled); + android_input_poll_event_type_key( + android_app, event, ANDROID_KEYBOARD_PORT, + keycode, source, type_event, &handled); + } + else + android_input_poll_event_type_key(android_app, + event, port, keycode, source, type_event, &handled); + } + break; + } + + AInputQueue_finishEvent(android_app->inputQueue, event, handled); + } +} + +static void android_input_poll_input_default(android_input_t *android, bool vibrate_on_keypress) { AInputEvent *event = NULL; @@ -1212,18 +1353,20 @@ static void android_input_poll_input(android_input_t *android, int id = android_input_get_id(event); int port = android_input_get_id_port(android, id, source); - if (port < 0 && !android_is_keyboard_id(id)) - port = android_input_recover_port(android, id); + if (port < 0 && !android_is_keyboard_id(id)) + port = android_input_recover_port(android, id); if (port < 0 && !android_is_keyboard_id(id)) handle_hotplug(android, android_app, - &port, id, source); + &port, id, source); switch (type_event) { case AINPUT_EVENT_TYPE_MOTION: + if ((source & AINPUT_SOURCE_TOUCHPAD)) + engine_handle_touchpad(android_app, event, port); /* Only handle events from a touchscreen or mouse */ - if ((source & (AINPUT_SOURCE_TOUCHSCREEN + else if ((source & (AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE))) android_input_poll_event_type_motion(android, event, port, source, vibrate_on_keypress); @@ -1247,7 +1390,7 @@ static void android_input_poll_input(android_input_t *android, } else android_input_poll_event_type_key(android_app, - event, port, keycode, source, type_event, &handled); + event, port, keycode, source, type_event, &handled); } break; } diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index 2276886b9f..5efa9f2795 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -120,6 +120,29 @@ DECL_AXIS(r_x_plus, +2) \ DECL_AXIS(r_x_minus, -2) \ DECL_AXIS(r_y_plus, -3) \ DECL_AXIS(r_y_minus, +3) + +#define XPERIA_PLAY_DEFAULT_BINDS \ +DECL_BTN_EX(a, 4, "Circle") \ +DECL_BTN_EX(b, 23, "Cross") \ +DECL_BTN_EX(x, 100, "Triangle") \ +DECL_BTN_EX(y, 99, "Square") \ +DECL_BTN_EX(start, 108, "Start") \ +DECL_BTN_EX(select, 109, "Select") \ +DECL_BTN_EX(up, 19, "D-Pad Up") \ +DECL_BTN_EX(down, 20, "D-Pad Down") \ +DECL_BTN_EX(left, 21, "D-Pad Left") \ +DECL_BTN_EX(right, 22, "D-Pad Right") \ +DECL_BTN_EX(l, 102, "L") \ +DECL_BTN_EX(r, 103, "R") \ +DECL_BTN_EX(menu_toggle, 82, "Menu") \ +DECL_AXIS(l_x_plus, +0) \ +DECL_AXIS(l_x_minus, -0) \ +DECL_AXIS(l_y_plus, -1) \ +DECL_AXIS(l_y_minus, +1) \ +DECL_AXIS(r_x_plus, +2) \ +DECL_AXIS(r_x_minus, -2) \ +DECL_AXIS(r_y_plus, -3) \ +DECL_AXIS(r_y_minus, +3) #endif #ifdef __QNX__ @@ -726,6 +749,7 @@ const char* const input_builtin_autoconfs[] = #endif #if defined(ANDROID) DECL_AUTOCONF_DEVICE("Android Gamepad", "android", ANDROID_DEFAULT_BINDS), + DECL_AUTOCONF_DEVICE("XPERIA Play", "android", XPERIA_PLAY_DEFAULT_BINDS), #endif #ifdef __QNX__ DECL_AUTOCONF_DEVICE("QNX Controller", "qnx", QNX_DEFAULT_BINDS),