diff --git a/config.def.h b/config.def.h
index 47edc81f5e..35ba2611ed 100644
--- a/config.def.h
+++ b/config.def.h
@@ -816,6 +816,8 @@ static const unsigned midi_volume = 100;
/* Only applies to Android 7.0 (API 24) and up */
static const bool sustained_performance_mode = false;
+static const bool vibrate_on_keypress = false;
+
#if defined(HAKCHI)
static char buildbot_server_url[] = "http://hakchicloud.com/Libretro_Cores/";
#elif defined(ANDROID)
diff --git a/configuration.c b/configuration.c
index 8507cfb08c..25c4818a21 100644
--- a/configuration.c
+++ b/configuration.c
@@ -1584,6 +1584,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("playlist_sort_alphabetical", &settings->bools.playlist_sort_alphabetical, true, playlist_sort_alphabetical, false);
SETTING_BOOL("quit_press_twice", &settings->bools.quit_press_twice, true, quit_press_twice, false);
+ SETTING_BOOL("vibrate_on_keypress", &settings->bools.vibrate_on_keypress, true, vibrate_on_keypress, false);
*size = count;
diff --git a/configuration.h b/configuration.h
index ece38ba873..d26334807d 100644
--- a/configuration.h
+++ b/configuration.h
@@ -315,6 +315,7 @@ typedef struct settings
bool playlist_show_sublabels;
bool quit_press_twice;
+ bool vibrate_on_keypress;
} bools;
struct
diff --git a/frontend/drivers/platform_unix.c b/frontend/drivers/platform_unix.c
index cd08bc9c83..6b7c5c17c7 100644
--- a/frontend/drivers/platform_unix.c
+++ b/frontend/drivers/platform_unix.c
@@ -2036,6 +2036,8 @@ static void frontend_unix_init(void *data)
"setSustainedPerformanceMode", "(Z)V");
GET_METHOD_ID(env, android_app->setScreenOrientation, class,
"setScreenOrientation", "(I)V");
+ GET_METHOD_ID(env, android_app->doVibrate, class,
+ "doVibrate", "()V");
CALL_OBJ_METHOD(env, obj, android_app->activity->clazz,
android_app->getIntent);
diff --git a/frontend/drivers/platform_unix.h b/frontend/drivers/platform_unix.h
index 351104a0b4..c244abfedb 100644
--- a/frontend/drivers/platform_unix.h
+++ b/frontend/drivers/platform_unix.h
@@ -163,6 +163,7 @@ struct android_app
jmethodID getBatteryLevel;
jmethodID setSustainedPerformanceMode;
jmethodID setScreenOrientation;
+ jmethodID doVibrate;
};
enum
@@ -266,7 +267,9 @@ enum
*/
APP_CMD_DESTROY,
- APP_CMD_REINIT_DONE
+ APP_CMD_REINIT_DONE,
+
+ APP_CMD_VIBRATE_KEYPRESS
};
#define JNI_EXCEPTION(env) \
diff --git a/input/drivers/android_input.c b/input/drivers/android_input.c
index e95c8b13bf..a0079e4d5f 100644
--- a/input/drivers/android_input.c
+++ b/input/drivers/android_input.c
@@ -421,6 +421,15 @@ static void android_input_poll_main_cmd(void)
RARCH_LOG("APP_CMD_DESTROY\n");
android_app->destroyRequested = 1;
break;
+ case APP_CMD_VIBRATE_KEYPRESS:
+ {
+ JNIEnv *env = (JNIEnv*)jni_thread_getenv();
+
+ if (env && g_android)
+ CALL_VOID_METHOD(env, g_android->activity->clazz,
+ g_android->doVibrate);
+ break;
+ }
}
}
@@ -741,6 +750,10 @@ static INLINE int android_input_poll_event_type_motion(
else
{
int pointer_max = MIN(AMotionEvent_getPointerCount(event), MAX_TOUCH);
+ settings_t *settings = config_get_ptr();
+
+ if (settings && settings->bools.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)
{
diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h
index cc5a39e2b2..be4a3d666c 100644
--- a/intl/msg_hash_lbl.h
+++ b/intl/msg_hash_lbl.h
@@ -1801,3 +1801,5 @@ MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_SUBLABEL_RUNTIME_TYPE,
"playlist_sublabel_runtime_type")
MSG_HASH(MENU_ENUM_LABEL_HELP_SEND_DEBUG_INFO,
"help_send_debug_info")
+MSG_HASH(MENU_ENUM_LABEL_VIBRATE_ON_KEYPRESS,
+ "vibrate_on_keypress")
diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h
index a40fede827..d5619cf3a0 100644
--- a/intl/msg_hash_us.h
+++ b/intl/msg_hash_us.h
@@ -8414,3 +8414,7 @@ MSG_HASH(
MSG_PRESS_ONE_MORE_TIME_TO_SEND_DEBUG_INFO,
"Press one more time to submit diagnostic info to the RetroArch team."
)
+MSG_HASH(
+ MENU_ENUM_LABEL_VALUE_VIBRATE_ON_KEYPRESS,
+ "Vibrate on key press"
+ )
diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c
index 8c0a167e54..a2baa6d05f 100644
--- a/menu/menu_displaylist.c
+++ b/menu/menu_displaylist.c
@@ -7083,6 +7083,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
ret = menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_QUIT_PRESS_TWICE,
PARSE_ONLY_BOOL, false);
+ ret = menu_displaylist_parse_settings_enum(menu, info,
+ MENU_ENUM_LABEL_VIBRATE_ON_KEYPRESS,
+ PARSE_ONLY_BOOL, false);
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_INPUT_POLL_TYPE_BEHAVIOR,
PARSE_ONLY_UINT, false) == 0)
diff --git a/menu/menu_setting.c b/menu/menu_setting.c
index 381f158f61..befaf5c327 100644
--- a/menu/menu_setting.c
+++ b/menu/menu_setting.c
@@ -6943,6 +6943,22 @@ static bool setting_append_list(
SD_FLAG_NONE
);
+ CONFIG_BOOL(
+ list, list_info,
+ &settings->bools.vibrate_on_keypress,
+ MENU_ENUM_LABEL_VIBRATE_ON_KEYPRESS,
+ MENU_ENUM_LABEL_VALUE_VIBRATE_ON_KEYPRESS,
+ vibrate_on_keypress,
+ MENU_ENUM_LABEL_VALUE_OFF,
+ MENU_ENUM_LABEL_VALUE_ON,
+ &group_info,
+ &subgroup_info,
+ parent_group,
+ general_write_handler,
+ general_read_handler,
+ SD_FLAG_NONE
+ );
+
CONFIG_UINT(
list, list_info,
&settings->uints.input_poll_type_behavior,
diff --git a/msg_hash.h b/msg_hash.h
index 24fd06dbc9..9fb10c2671 100644
--- a/msg_hash.h
+++ b/msg_hash.h
@@ -2306,6 +2306,8 @@ enum msg_hash_enums
MSG_PRESS_TWO_MORE_TIMES_TO_SEND_DEBUG_INFO,
MSG_PRESS_ONE_MORE_TIME_TO_SEND_DEBUG_INFO,
+ MENU_LABEL(VIBRATE_ON_KEYPRESS),
+
MSG_LAST
};
diff --git a/pkg/android/phoenix/AndroidManifest.xml b/pkg/android/phoenix/AndroidManifest.xml
index 57a0331ddf..8517222c1e 100644
--- a/pkg/android/phoenix/AndroidManifest.xml
+++ b/pkg/android/phoenix/AndroidManifest.xml
@@ -14,6 +14,7 @@
+
= 26) {
+ vibrator.vibrate(VibrationEffect.createOneShot(33, VibrationEffect.DEFAULT_AMPLITUDE), new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build());
+ }else{
+ vibrator.vibrate(33);
+ }
+ }
+
// Exiting cleanly from NDK seems to be nearly impossible.
// Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches.
// Use a separate JNI function to explicitly trigger the readback.
diff --git a/pkg/android/phoenix64/AndroidManifest.xml b/pkg/android/phoenix64/AndroidManifest.xml
index 6bf3142939..f5adbd91b9 100644
--- a/pkg/android/phoenix64/AndroidManifest.xml
+++ b/pkg/android/phoenix64/AndroidManifest.xml
@@ -14,6 +14,7 @@
+