mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 08:43:10 +00:00
Improve haptic feedback for input overlays (#14517)
Repurpose vibrate_on_keypress to enable device's standard keypress feedback on overlay key/button state changes - Add keypress_vibrate function ptr to input_driver_t (only implemented on Android for now) - (Android) Remove APP_CMD_VIBRATE_KEYPRESS - (Android) Add doHapticFeedback, called directly to avoid latency
This commit is contained in:
parent
5b08c3fc22
commit
b98c53ddb7
@ -2088,6 +2088,8 @@ static void frontend_unix_init(void *data)
|
|||||||
"setScreenOrientation", "(I)V");
|
"setScreenOrientation", "(I)V");
|
||||||
GET_METHOD_ID(env, android_app->doVibrate, class,
|
GET_METHOD_ID(env, android_app->doVibrate, class,
|
||||||
"doVibrate", "(IIII)V");
|
"doVibrate", "(IIII)V");
|
||||||
|
GET_METHOD_ID(env, android_app->doHapticFeedback, class,
|
||||||
|
"doHapticFeedback", "(I)V");
|
||||||
GET_METHOD_ID(env, android_app->getUserLanguageString, class,
|
GET_METHOD_ID(env, android_app->getUserLanguageString, class,
|
||||||
"getUserLanguageString", "()Ljava/lang/String;");
|
"getUserLanguageString", "()Ljava/lang/String;");
|
||||||
GET_METHOD_ID(env, android_app->isPlayStoreBuild, class,
|
GET_METHOD_ID(env, android_app->isPlayStoreBuild, class,
|
||||||
|
@ -168,6 +168,7 @@ struct android_app
|
|||||||
jmethodID setScreenOrientation;
|
jmethodID setScreenOrientation;
|
||||||
jmethodID getUserLanguageString;
|
jmethodID getUserLanguageString;
|
||||||
jmethodID doVibrate;
|
jmethodID doVibrate;
|
||||||
|
jmethodID doHapticFeedback;
|
||||||
|
|
||||||
jmethodID isPlayStoreBuild;
|
jmethodID isPlayStoreBuild;
|
||||||
jmethodID getAvailableCores;
|
jmethodID getAvailableCores;
|
||||||
@ -290,9 +291,7 @@ enum
|
|||||||
*/
|
*/
|
||||||
APP_CMD_DESTROY,
|
APP_CMD_DESTROY,
|
||||||
|
|
||||||
APP_CMD_REINIT_DONE,
|
APP_CMD_REINIT_DONE
|
||||||
|
|
||||||
APP_CMD_VIBRATE_KEYPRESS
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define JNI_EXCEPTION(env) \
|
#define JNI_EXCEPTION(env) \
|
||||||
|
@ -168,9 +168,9 @@ bool (*engine_lookup_name)(char *buf,
|
|||||||
int *vendorId, int *productId, size_t size, int id);
|
int *vendorId, int *productId, size_t size, int id);
|
||||||
void (*engine_handle_dpad)(struct android_app *, AInputEvent*, int, int);
|
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_gingerbread(android_input_t *android);
|
||||||
static void android_input_poll_input_default(android_input_t *android, bool vibrate_on_keypress);
|
static void android_input_poll_input_default(android_input_t *android);
|
||||||
static void (*android_input_poll_input)(android_input_t *android, bool vibrate_on_keypress);
|
static void (*android_input_poll_input)(android_input_t *android);
|
||||||
|
|
||||||
static bool android_input_set_sensor_state(void *data, unsigned port,
|
static bool android_input_set_sensor_state(void *data, unsigned port,
|
||||||
enum retro_sensor_action action, unsigned event_rate);
|
enum retro_sensor_action action, unsigned event_rate);
|
||||||
@ -436,17 +436,6 @@ static void android_input_poll_main_cmd(void)
|
|||||||
case APP_CMD_DESTROY:
|
case APP_CMD_DESTROY:
|
||||||
android_app->destroyRequested = 1;
|
android_app->destroyRequested = 1;
|
||||||
break;
|
break;
|
||||||
case APP_CMD_VIBRATE_KEYPRESS:
|
|
||||||
{
|
|
||||||
JNIEnv *env = (JNIEnv*)jni_thread_getenv();
|
|
||||||
|
|
||||||
if (env && g_android && g_android->doVibrate)
|
|
||||||
{
|
|
||||||
CALL_VOID_METHOD_PARAM(env, g_android->activity->clazz,
|
|
||||||
g_android->doVibrate, (jint)-1, (jint)RETRO_RUMBLE_STRONG, (jint)255, (jint)1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,7 +625,7 @@ static INLINE void android_mouse_calculate_deltas(android_input_t *android,
|
|||||||
|
|
||||||
static INLINE void android_input_poll_event_type_motion(
|
static INLINE void android_input_poll_event_type_motion(
|
||||||
android_input_t *android, AInputEvent *event,
|
android_input_t *android, AInputEvent *event,
|
||||||
int port, int source, bool vibrate_on_keypress)
|
int port, int source)
|
||||||
{
|
{
|
||||||
int btn;
|
int btn;
|
||||||
int getaction = AMotionEvent_getAction(event);
|
int getaction = AMotionEvent_getAction(event);
|
||||||
@ -707,9 +696,6 @@ static INLINE void android_input_poll_event_type_motion(
|
|||||||
int pointer_max = MIN(
|
int pointer_max = MIN(
|
||||||
AMotionEvent_getPointerCount(event), MAX_TOUCH);
|
AMotionEvent_getPointerCount(event), MAX_TOUCH);
|
||||||
|
|
||||||
if (vibrate_on_keypress && action != AMOTION_EVENT_ACTION_MOVE)
|
|
||||||
android_app_write_cmd(g_android, APP_CMD_VIBRATE_KEYPRESS);
|
|
||||||
|
|
||||||
if (action == AMOTION_EVENT_ACTION_DOWN && ENABLE_TOUCH_SCREEN_MOUSE)
|
if (action == AMOTION_EVENT_ACTION_DOWN && ENABLE_TOUCH_SCREEN_MOUSE)
|
||||||
{
|
{
|
||||||
/* When touch screen is pressed, set mouse
|
/* When touch screen is pressed, set mouse
|
||||||
@ -1273,8 +1259,7 @@ static void engine_handle_touchpad(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void android_input_poll_input_gingerbread(
|
static void android_input_poll_input_gingerbread(
|
||||||
android_input_t *android,
|
android_input_t *android)
|
||||||
bool vibrate_on_keypress)
|
|
||||||
{
|
{
|
||||||
AInputEvent *event = NULL;
|
AInputEvent *event = NULL;
|
||||||
struct android_app *android_app = (struct android_app*)g_android;
|
struct android_app *android_app = (struct android_app*)g_android;
|
||||||
@ -1307,7 +1292,7 @@ static void android_input_poll_input_gingerbread(
|
|||||||
else if ((source & (AINPUT_SOURCE_TOUCHSCREEN
|
else if ((source & (AINPUT_SOURCE_TOUCHSCREEN
|
||||||
| AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)))
|
| AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)))
|
||||||
android_input_poll_event_type_motion(android, event,
|
android_input_poll_event_type_motion(android, event,
|
||||||
port, source, vibrate_on_keypress);
|
port, source);
|
||||||
else
|
else
|
||||||
engine_handle_dpad(android_app, event, port, source);
|
engine_handle_dpad(android_app, event, port, source);
|
||||||
handled = 1;
|
handled = 1;
|
||||||
@ -1335,8 +1320,7 @@ static void android_input_poll_input_gingerbread(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void android_input_poll_input_default(android_input_t *android,
|
static void android_input_poll_input_default(android_input_t *android)
|
||||||
bool vibrate_on_keypress)
|
|
||||||
{
|
{
|
||||||
AInputEvent *event = NULL;
|
AInputEvent *event = NULL;
|
||||||
struct android_app *android_app = (struct android_app*)g_android;
|
struct android_app *android_app = (struct android_app*)g_android;
|
||||||
@ -1370,7 +1354,7 @@ static void android_input_poll_input_default(android_input_t *android,
|
|||||||
else if ((source & (AINPUT_SOURCE_TOUCHSCREEN
|
else if ((source & (AINPUT_SOURCE_TOUCHSCREEN
|
||||||
| AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)))
|
| AINPUT_SOURCE_STYLUS | AINPUT_SOURCE_MOUSE)))
|
||||||
android_input_poll_event_type_motion(android, event,
|
android_input_poll_event_type_motion(android, event,
|
||||||
port, source, vibrate_on_keypress);
|
port, source);
|
||||||
else
|
else
|
||||||
engine_handle_dpad(android_app, event, port, source);
|
engine_handle_dpad(android_app, event, port, source);
|
||||||
break;
|
break;
|
||||||
@ -1466,15 +1450,10 @@ static void android_input_poll(void *data)
|
|||||||
? -1 : settings->uints.input_block_timeout,
|
? -1 : settings->uints.input_block_timeout,
|
||||||
NULL, NULL, NULL)) >= 0)
|
NULL, NULL, NULL)) >= 0)
|
||||||
{
|
{
|
||||||
bool vibrate_on_keypress = settings
|
|
||||||
? settings->bools.vibrate_on_keypress
|
|
||||||
: false;
|
|
||||||
|
|
||||||
switch (ident)
|
switch (ident)
|
||||||
{
|
{
|
||||||
case LOOPER_ID_INPUT:
|
case LOOPER_ID_INPUT:
|
||||||
android_input_poll_input(android,
|
android_input_poll_input(android);
|
||||||
vibrate_on_keypress);
|
|
||||||
break;
|
break;
|
||||||
case LOOPER_ID_USER:
|
case LOOPER_ID_USER:
|
||||||
android_input_poll_user(android);
|
android_input_poll_user(android);
|
||||||
@ -1848,6 +1827,18 @@ static float android_input_get_sensor_input(void *data,
|
|||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void android_input_keypress_vibrate()
|
||||||
|
{
|
||||||
|
static const int keyboard_press = 3;
|
||||||
|
JNIEnv *env = (JNIEnv*)jni_thread_getenv();
|
||||||
|
|
||||||
|
if (!env)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CALL_VOID_METHOD_PARAM(env, g_android->activity->clazz,
|
||||||
|
g_android->doHapticFeedback, (jint)keyboard_press);
|
||||||
|
}
|
||||||
|
|
||||||
input_driver_t input_android = {
|
input_driver_t input_android = {
|
||||||
android_input_init,
|
android_input_init,
|
||||||
android_input_poll,
|
android_input_poll,
|
||||||
@ -1859,5 +1850,6 @@ input_driver_t input_android = {
|
|||||||
"android",
|
"android",
|
||||||
|
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
NULL
|
NULL,
|
||||||
|
android_input_keypress_vibrate
|
||||||
};
|
};
|
||||||
|
@ -561,5 +561,6 @@ input_driver_t input_cocoa = {
|
|||||||
cocoa_input_get_capabilities,
|
cocoa_input_get_capabilities,
|
||||||
"cocoa",
|
"cocoa",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -46,5 +46,6 @@ input_driver_t input_ctr = {
|
|||||||
ctr_input_get_capabilities,
|
ctr_input_get_capabilities,
|
||||||
"ctr",
|
"ctr",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -1045,5 +1045,6 @@ input_driver_t input_dinput = {
|
|||||||
dinput_get_capabilities,
|
dinput_get_capabilities,
|
||||||
"dinput",
|
"dinput",
|
||||||
dinput_grab_mouse,
|
dinput_grab_mouse,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -133,5 +133,6 @@ input_driver_t input_dos = {
|
|||||||
dos_input_get_capabilities,
|
dos_input_get_capabilities,
|
||||||
"dos",
|
"dos",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -298,5 +298,6 @@ input_driver_t input_gx = {
|
|||||||
"gx",
|
"gx",
|
||||||
|
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -209,5 +209,6 @@ input_driver_t input_linuxraw = {
|
|||||||
linuxraw_get_capabilities,
|
linuxraw_get_capabilities,
|
||||||
"linuxraw",
|
"linuxraw",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
linux_terminal_grab_stdin
|
linux_terminal_grab_stdin,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -44,5 +44,6 @@ input_driver_t input_ps2 = {
|
|||||||
ps2_input_get_capabilities,
|
ps2_input_get_capabilities,
|
||||||
"ps2",
|
"ps2",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
NULL
|
NULL,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -218,5 +218,6 @@ input_driver_t input_ps3 = {
|
|||||||
"ps3",
|
"ps3",
|
||||||
|
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -143,5 +143,6 @@ input_driver_t input_ps4 = {
|
|||||||
ps4_input_get_capabilities,
|
ps4_input_get_capabilities,
|
||||||
"ps4",
|
"ps4",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -951,5 +951,6 @@ input_driver_t input_ps3 = {
|
|||||||
"ps3",
|
"ps3",
|
||||||
|
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -441,5 +441,6 @@ input_driver_t input_psp = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -852,5 +852,6 @@ input_driver_t input_qnx = {
|
|||||||
qnx_input_get_capabilities,
|
qnx_input_get_capabilities,
|
||||||
"qnx_input",
|
"qnx_input",
|
||||||
NULL,
|
NULL,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -686,5 +686,6 @@ input_driver_t input_rwebinput = {
|
|||||||
rwebinput_get_capabilities,
|
rwebinput_get_capabilities,
|
||||||
"rwebinput",
|
"rwebinput",
|
||||||
rwebinput_grab_mouse,
|
rwebinput_grab_mouse,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -50,5 +50,6 @@ input_driver_t input_sdl_dingux = {
|
|||||||
sdl_dingux_input_get_capabilities,
|
sdl_dingux_input_get_capabilities,
|
||||||
"sdl_dingux",
|
"sdl_dingux",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
NULL /* grab_stdin */
|
NULL, /* grab_stdin */
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -475,6 +475,7 @@ input_driver_t input_sdl = {
|
|||||||
"sdl",
|
"sdl",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
#endif
|
#endif
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -948,5 +948,6 @@ input_driver_t input_switch = {
|
|||||||
switch_input_get_capabilities,
|
switch_input_get_capabilities,
|
||||||
"switch",
|
"switch",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -1540,8 +1540,9 @@ input_driver_t input_udev = {
|
|||||||
"udev",
|
"udev",
|
||||||
udev_input_grab_mouse,
|
udev_input_grab_mouse,
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
linux_terminal_grab_stdin
|
linux_terminal_grab_stdin,
|
||||||
#else
|
#else
|
||||||
NULL
|
NULL,
|
||||||
#endif
|
#endif
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -168,5 +168,6 @@ input_driver_t input_uwp = {
|
|||||||
uwp_input_get_capabilities,
|
uwp_input_get_capabilities,
|
||||||
"uwp",
|
"uwp",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -426,5 +426,6 @@ input_driver_t input_wayland = {
|
|||||||
input_wl_get_capabilities,
|
input_wl_get_capabilities,
|
||||||
"wayland",
|
"wayland",
|
||||||
input_wl_grab_mouse, /* grab_mouse */
|
input_wl_grab_mouse, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -168,5 +168,6 @@ input_driver_t input_wiiu = {
|
|||||||
wiiu_input_get_capabilities,
|
wiiu_input_get_capabilities,
|
||||||
"wiiu",
|
"wiiu",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -1087,5 +1087,6 @@ input_driver_t input_winraw = {
|
|||||||
winraw_get_capabilities,
|
winraw_get_capabilities,
|
||||||
"raw",
|
"raw",
|
||||||
winraw_grab_mouse,
|
winraw_grab_mouse,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -615,5 +615,6 @@ input_driver_t input_x = {
|
|||||||
x_input_get_capabilities,
|
x_input_get_capabilities,
|
||||||
"x",
|
"x",
|
||||||
x_grab_mouse,
|
x_grab_mouse,
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -50,5 +50,6 @@ input_driver_t input_xinput = {
|
|||||||
xdk_input_get_capabilities,
|
xdk_input_get_capabilities,
|
||||||
"xinput",
|
"xinput",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -80,5 +80,6 @@ input_driver_t input_xenon360 = {
|
|||||||
xenon360_input_get_capabilities,
|
xenon360_input_get_capabilities,
|
||||||
"xenon360",
|
"xenon360",
|
||||||
NULL, /* grab_mouse */
|
NULL, /* grab_mouse */
|
||||||
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -109,6 +109,7 @@ static float input_null_get_sensor_input(void *data, unsigned port, unsigned id)
|
|||||||
static uint64_t input_null_get_capabilities(void *data) { return 0; }
|
static uint64_t input_null_get_capabilities(void *data) { return 0; }
|
||||||
static void input_null_grab_mouse(void *data, bool state) { }
|
static void input_null_grab_mouse(void *data, bool state) { }
|
||||||
static bool input_null_grab_stdin(void *data) { return false; }
|
static bool input_null_grab_stdin(void *data) { return false; }
|
||||||
|
static void input_null_keypress_vibrate() { }
|
||||||
|
|
||||||
static input_driver_t input_null = {
|
static input_driver_t input_null = {
|
||||||
input_null_init,
|
input_null_init,
|
||||||
@ -120,7 +121,8 @@ static input_driver_t input_null = {
|
|||||||
input_null_get_capabilities,
|
input_null_get_capabilities,
|
||||||
"null",
|
"null",
|
||||||
input_null_grab_mouse,
|
input_null_grab_mouse,
|
||||||
input_null_grab_stdin
|
input_null_grab_stdin,
|
||||||
|
input_null_keypress_vibrate
|
||||||
};
|
};
|
||||||
|
|
||||||
static input_device_driver_t null_joypad = {
|
static input_device_driver_t null_joypad = {
|
||||||
@ -1860,7 +1862,7 @@ void input_poll_overlay(
|
|||||||
unsigned analog_dpad_mode,
|
unsigned analog_dpad_mode,
|
||||||
float axis_threshold)
|
float axis_threshold)
|
||||||
{
|
{
|
||||||
input_overlay_state_t old_key_state;
|
input_overlay_state_t old_ol_state;
|
||||||
int i, j;
|
int i, j;
|
||||||
input_overlay_t *ol = (input_overlay_t*)ol_data;
|
input_overlay_t *ol = (input_overlay_t*)ol_data;
|
||||||
uint16_t key_mod = 0;
|
uint16_t key_mod = 0;
|
||||||
@ -1875,12 +1877,15 @@ void input_poll_overlay(
|
|||||||
settings->uints.input_overlay_show_inputs;
|
settings->uints.input_overlay_show_inputs;
|
||||||
unsigned input_overlay_show_inputs_port = settings->uints.input_overlay_show_inputs_port;
|
unsigned input_overlay_show_inputs_port = settings->uints.input_overlay_show_inputs_port;
|
||||||
float touch_scale = (float)settings->uints.input_touch_scale;
|
float touch_scale = (float)settings->uints.input_touch_scale;
|
||||||
|
bool osk_state_changed = false;
|
||||||
|
unsigned pointer_count = 0;
|
||||||
|
static unsigned old_pointer_count;
|
||||||
|
|
||||||
if (!ol_state)
|
if (!ol_state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(old_key_state.keys, ol_state->keys,
|
memcpy(&old_ol_state, ol_state,
|
||||||
sizeof(ol_state->keys));
|
sizeof(old_ol_state));
|
||||||
memset(ol_state, 0, sizeof(*ol_state));
|
memset(ol_state, 0, sizeof(*ol_state));
|
||||||
|
|
||||||
if (current_input->input_state)
|
if (current_input->input_state)
|
||||||
@ -1963,6 +1968,8 @@ void input_poll_overlay(
|
|||||||
|
|
||||||
polled = true;
|
polled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pointer_count = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( OVERLAY_GET_KEY(ol_state, RETROK_LSHIFT) ||
|
if ( OVERLAY_GET_KEY(ol_state, RETROK_LSHIFT) ||
|
||||||
@ -1984,10 +1991,11 @@ void input_poll_overlay(
|
|||||||
/* CAPSLOCK SCROLLOCK NUMLOCK */
|
/* CAPSLOCK SCROLLOCK NUMLOCK */
|
||||||
for (i = 0; i < ARRAY_SIZE(ol_state->keys); i++)
|
for (i = 0; i < ARRAY_SIZE(ol_state->keys); i++)
|
||||||
{
|
{
|
||||||
if (ol_state->keys[i] != old_key_state.keys[i])
|
if (ol_state->keys[i] != old_ol_state.keys[i])
|
||||||
{
|
{
|
||||||
uint32_t orig_bits = old_key_state.keys[i];
|
uint32_t orig_bits = old_ol_state.keys[i];
|
||||||
uint32_t new_bits = ol_state->keys[i];
|
uint32_t new_bits = ol_state->keys[i];
|
||||||
|
osk_state_changed = true;
|
||||||
|
|
||||||
for (j = 0; j < 32; j++)
|
for (j = 0; j < 32; j++)
|
||||||
if ((orig_bits & (1 << j)) != (new_bits & (1 << j)))
|
if ((orig_bits & (1 << j)) != (new_bits & (1 << j)))
|
||||||
@ -2059,6 +2067,24 @@ void input_poll_overlay(
|
|||||||
button_pressed, opacity);
|
button_pressed, opacity);
|
||||||
else
|
else
|
||||||
input_overlay_poll_clear(overlay_visibility, ol, opacity);
|
input_overlay_poll_clear(overlay_visibility, ol, opacity);
|
||||||
|
|
||||||
|
/* Create haptic feedback for any change in button/key state,
|
||||||
|
* unless pointer_count decreased. */
|
||||||
|
if ( current_input->keypress_vibrate
|
||||||
|
&& settings->bools.vibrate_on_keypress
|
||||||
|
&& pointer_count && pointer_count >= old_pointer_count
|
||||||
|
&& !ol->blocked)
|
||||||
|
{
|
||||||
|
if ( osk_state_changed
|
||||||
|
|| bits_any_different(
|
||||||
|
ol_state->buttons.data,
|
||||||
|
old_ol_state.buttons.data,
|
||||||
|
ARRAY_SIZE(old_ol_state.buttons.data))
|
||||||
|
)
|
||||||
|
current_input->keypress_vibrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
old_pointer_count = pointer_count;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -340,6 +340,12 @@ struct input_driver
|
|||||||
* @return True if the input driver has claimed stdin.
|
* @return True if the input driver has claimed stdin.
|
||||||
*/
|
*/
|
||||||
bool (*grab_stdin)(void *data);
|
bool (*grab_stdin)(void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Haptic feedback for touchscreen key presses. This function pointer can be
|
||||||
|
* set to NULL if haptic feedback / vibration is not supported.
|
||||||
|
*/
|
||||||
|
void (*keypress_vibrate)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rarch_joypad_driver
|
struct rarch_joypad_driver
|
||||||
|
@ -74,6 +74,17 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (a[i] != b[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef PATH_MAX_LENGTH
|
#ifndef PATH_MAX_LENGTH
|
||||||
#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(__PSL1GHT__) || defined(__PS3__)
|
#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(__PSL1GHT__) || defined(__PS3__)
|
||||||
#define PATH_MAX_LENGTH 512
|
#define PATH_MAX_LENGTH 512
|
||||||
|
@ -6249,23 +6249,25 @@ unsigned menu_displaylist_build_list(
|
|||||||
break;
|
break;
|
||||||
case DISPLAYLIST_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST:
|
case DISPLAYLIST_INPUT_HAPTIC_FEEDBACK_SETTINGS_LIST:
|
||||||
{
|
{
|
||||||
const char *input_driver_id = settings->arrays.input_driver;
|
input_driver_t *current_input =
|
||||||
|
input_state_get_ptr()->current_driver;
|
||||||
|
|
||||||
if (string_is_equal(input_driver_id, "android"))
|
if (current_input->keypress_vibrate)
|
||||||
{
|
|
||||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
MENU_ENUM_LABEL_VIBRATE_ON_KEYPRESS,
|
MENU_ENUM_LABEL_VIBRATE_ON_KEYPRESS,
|
||||||
PARSE_ONLY_BOOL, false) == 0)
|
PARSE_ONLY_BOOL, false) == 0)
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
if (string_is_equal(current_input->ident, "android"))
|
||||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
MENU_ENUM_LABEL_ENABLE_DEVICE_VIBRATION,
|
MENU_ENUM_LABEL_ENABLE_DEVICE_VIBRATION,
|
||||||
PARSE_ONLY_BOOL, false) == 0)
|
PARSE_ONLY_BOOL, false) == 0)
|
||||||
count++;
|
count++;
|
||||||
}
|
|
||||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||||
MENU_ENUM_LABEL_INPUT_RUMBLE_GAIN,
|
MENU_ENUM_LABEL_INPUT_RUMBLE_GAIN,
|
||||||
PARSE_ONLY_UINT, false) == 0)
|
PARSE_ONLY_UINT, false) == 0)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST:
|
case DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST:
|
||||||
|
@ -17,6 +17,7 @@ import android.os.Bundle;
|
|||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.os.storage.StorageVolume;
|
import android.os.storage.StorageVolume;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
@ -116,6 +117,13 @@ public class RetroActivityCommon extends NativeActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void doHapticFeedback(int effect)
|
||||||
|
{
|
||||||
|
getWindow().getDecorView().performHapticFeedback(effect,
|
||||||
|
HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING | HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
|
||||||
|
Log.i("RetroActivity", "Haptic Feedback effect " + effect);
|
||||||
|
}
|
||||||
|
|
||||||
// Exiting cleanly from NDK seems to be nearly impossible.
|
// Exiting cleanly from NDK seems to be nearly impossible.
|
||||||
// Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches.
|
// Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches.
|
||||||
// Use a separate JNI function to explicitly trigger the readback.
|
// Use a separate JNI function to explicitly trigger the readback.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user