diff --git a/config.def.h b/config.def.h index 175d9bc7d5..8378602635 100644 --- a/config.def.h +++ b/config.def.h @@ -1075,7 +1075,7 @@ static const unsigned input_bind_timeout = 5; static const unsigned input_bind_hold = 2; -static const unsigned input_hotkey_block_delay = 5; +#define DEFAULT_INPUT_HOTKEY_BLOCK_DELAY 5 static const unsigned gfx_thumbnails_default = 3; diff --git a/configuration.c b/configuration.c index cabafcfb66..2b211beefa 100644 --- a/configuration.c +++ b/configuration.c @@ -1758,7 +1758,7 @@ static struct config_uint_setting *populate_settings_uint( SETTING_UINT("input_max_users", input_driver_get_uint(INPUT_ACTION_MAX_USERS), true, input_max_users, false); SETTING_UINT("fps_update_interval", &settings->uints.fps_update_interval, true, DEFAULT_FPS_UPDATE_INTERVAL, false); SETTING_UINT("input_menu_toggle_gamepad_combo", &settings->uints.input_menu_toggle_gamepad_combo, true, menu_toggle_gamepad_combo, false); - SETTING_UINT("input_hotkey_block_delay", &settings->uints.input_hotkey_block_delay, true, input_hotkey_block_delay, false); + SETTING_UINT("input_hotkey_block_delay", &settings->uints.input_hotkey_block_delay, true, DEFAULT_INPUT_HOTKEY_BLOCK_DELAY, false); #ifdef GEKKO SETTING_UINT("input_mouse_scale", &settings->uints.input_mouse_scale, true, DEFAULT_MOUSE_SCALE, false); #endif diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 04bc8b13fb..9457ac2868 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1298,6 +1298,10 @@ MSG_HASH( MENU_ENUM_LABEL_INPUT_HOTKEY_BINDS_BEGIN, "input_hotkey_binds_begin" ) +MSG_HASH( + MENU_ENUM_LABEL_INPUT_HOTKEY_BLOCK_DELAY, + "input_hotkey_block_delay" + ) MSG_HASH( MENU_ENUM_LABEL_INPUT_ICADE_ENABLE, "input_icade_enable" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 2910447751..727f869a43 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2221,7 +2221,19 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY, - "Hotkeys" + "Hotkey Enable" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_META_ENABLE_HOTKEY, + "When assigned, the 'Hotkey Enable' key must be pressed (and held) before any other hotkeys are recognised. Allows controller buttons to be mapped to hotkey functions without affecting normal input." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BLOCK_DELAY, + "Hotkey Enable Delay (Frames)" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_HOTKEY_BLOCK_DELAY, + "Adds a delay in frames before normal input is blocked after pressing (and holding) the assigned 'Hotkey Enable' key. Allows normal input from the 'Hotkey Enable' key to be captured when it is mapped to another action (e.g. RetroPad 'Select')." ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_META_VOLUME_UP, diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index be429f74b3..f2c3b4a3f5 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -213,6 +213,8 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_statistics_show, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_netplay_settings, MENU_ENUM_SUBLABEL_NETPLAY) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_user_bind_settings, MENU_ENUM_SUBLABEL_INPUT_USER_BINDS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_hotkey_settings, MENU_ENUM_SUBLABEL_INPUT_HOTKEY_BINDS) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_enable_hotkey, MENU_ENUM_SUBLABEL_INPUT_META_ENABLE_HOTKEY) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_hotkey_block_delay, MENU_ENUM_SUBLABEL_INPUT_HOTKEY_BLOCK_DELAY) #ifdef HAVE_MATERIALUI DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_materialui_icons_enable, MENU_ENUM_SUBLABEL_MATERIALUI_ICONS_ENABLE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_materialui_landscape_layout_optimization, MENU_ENUM_SUBLABEL_MATERIALUI_LANDSCAPE_LAYOUT_OPTIMIZATION) @@ -1385,6 +1387,16 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, } #endif + /* Hotkey binds require special handling + * > Only the 'enable_hotkey' entry has a sublabel */ + if ((cbs->enum_idx >= MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN) && + (cbs->enum_idx <= MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_END) && + string_is_equal(label, "enable_hotkey")) + { + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_meta_enable_hotkey); + return 0; + } + if (cbs->enum_idx != MSG_UNKNOWN) { switch (cbs->enum_idx) @@ -2917,6 +2929,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_INPUT_HOTKEY_BINDS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_hotkey_settings); break; + case MENU_ENUM_LABEL_INPUT_HOTKEY_BLOCK_DELAY: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_hotkey_block_delay); + break; case MENU_ENUM_LABEL_INPUT_USER_1_BINDS: case MENU_ENUM_LABEL_INPUT_USER_2_BINDS: case MENU_ENUM_LABEL_INPUT_USER_3_BINDS: diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 919c449c6d..4d25ccbc84 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -4456,21 +4456,56 @@ unsigned menu_displaylist_build_list( count++; break; case DISPLAYLIST_INPUT_HOTKEY_BINDS_LIST: - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_QUIT_PRESS_TWICE, - PARSE_ONLY_BOOL, false) == 0) - count++; - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, - PARSE_ONLY_UINT, false) == 0) - count++; - for (i = 0; i < RARCH_BIND_LIST_END; i++) { + bool hotkey_enable_found = false; + size_t hotkey_enable_index = 0; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, - (enum msg_hash_enums)( - MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN + i), - PARSE_ONLY_BIND, false) == 0) + MENU_ENUM_LABEL_QUIT_PRESS_TWICE, + PARSE_ONLY_BOOL, false) == 0) count++; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_INPUT_MENU_ENUM_TOGGLE_GAMEPAD_COMBO, + PARSE_ONLY_UINT, false) == 0) + count++; + + /* Hotkey enable bind comes first - due to the + * way binds are implemented, have to search the + * entire list for it... */ + for (i = 0; i < RARCH_BIND_LIST_END; i++) + { + if (string_is_equal(input_config_bind_map_get_base(i), "enable_hotkey")) + { + hotkey_enable_found = true; + hotkey_enable_index = i; + + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + (enum msg_hash_enums)( + MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN + i), + PARSE_ONLY_BIND, false) == 0) + count++; + + break; + } + } + + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_INPUT_HOTKEY_BLOCK_DELAY, + PARSE_ONLY_UINT, false) == 0) + count++; + + /* All other binds come last */ + for (i = 0; i < RARCH_BIND_LIST_END; i++) + { + if (hotkey_enable_found && (hotkey_enable_index == i)) + continue; + + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + (enum msg_hash_enums)( + MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN + i), + PARSE_ONLY_BIND, false) == 0) + count++; + } } break; case DISPLAYLIST_SHADER_PRESET_REMOVE: diff --git a/menu/menu_setting.c b/menu/menu_setting.c index e07b625df6..1af80f5a44 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -11439,6 +11439,21 @@ static bool setting_append_list( &setting_get_string_representation_toggle_gamepad_combo; menu_settings_list_current_add_range(list, list_info, 0, (INPUT_TOGGLE_LAST-1), 1, true, true); + CONFIG_UINT( + list, list_info, + &settings->uints.input_hotkey_block_delay, + MENU_ENUM_LABEL_INPUT_HOTKEY_BLOCK_DELAY, + MENU_ENUM_LABEL_VALUE_INPUT_HOTKEY_BLOCK_DELAY, + DEFAULT_INPUT_HOTKEY_BLOCK_DELAY, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_COMBOBOX; + (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; + menu_settings_list_current_add_range(list, list_info, 0, 600, 1, true, true); + CONFIG_BOOL( list, list_info, &settings->bools.input_menu_swap_ok_cancel_buttons, diff --git a/msg_hash.h b/msg_hash.h index e244ffee6a..9c537b7b7e 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -713,6 +713,7 @@ enum msg_hash_enums MENU_ENUM_LABEL_INPUT_SETTINGS_BEGIN, MENU_LABEL(INPUT_HOTKEY_BINDS), + MENU_LABEL(INPUT_HOTKEY_BLOCK_DELAY), MENU_LABEL(INPUT_SPLIT_JOYCON), MENU_ENUM_LABEL_INPUT_HOTKEY_BINDS_BEGIN, @@ -854,6 +855,8 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_INPUT_SAVE_AUTOCONFIG, MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_INDEX, + MENU_ENUM_SUBLABEL_INPUT_META_ENABLE_HOTKEY, + MENU_LABEL(INPUT_MAX_USERS), MENU_LABEL(INPUT_USER_BINDS), MENU_LABEL(INPUT_DUTY_CYCLE),