From 1c591be8f1edf4fd6df3ef469f266d1b82564694 Mon Sep 17 00:00:00 2001 From: jdgleaver Date: Wed, 13 Jan 2021 15:00:36 +0000 Subject: [PATCH] Add option to automatically enable 'game focus' mode when running/resuming content --- config.def.h | 4 + configuration.c | 1 + configuration.h | 1 + intl/msg_hash_lbl.h | 4 + intl/msg_hash_us.h | 20 +++++ menu/cbs/menu_cbs_sublabel.c | 4 + menu/menu_defines.h | 8 ++ menu/menu_displaylist.c | 4 + menu/menu_setting.c | 46 ++++++++++ msg_hash.h | 6 ++ retroarch.c | 158 +++++++++++++++++++++++++++-------- retroarch_data.h | 16 ++++ 12 files changed, 237 insertions(+), 35 deletions(-) diff --git a/config.def.h b/config.def.h index 7cc529414d..ce863a4729 100644 --- a/config.def.h +++ b/config.def.h @@ -1209,6 +1209,10 @@ static const bool input_autodetect_enable = true; #define DEFAULT_INPUT_SENSORS_ENABLE true #endif +/* Automatically enable game focus when running or + * resuming content */ +#define DEFAULT_INPUT_AUTO_GAME_FOCUS AUTO_GAME_FOCUS_OFF + /* Show the input descriptors set by the core instead * of the default ones. */ static const bool input_descriptor_label_show = true; diff --git a/configuration.c b/configuration.c index 89e801cce9..23652761e4 100644 --- a/configuration.c +++ b/configuration.c @@ -1876,6 +1876,7 @@ static struct config_uint_setting *populate_settings_uint( #if defined(DINGUX) && defined(HAVE_LIBSHAKE) SETTING_UINT("input_dingux_rumble_gain", &settings->uints.input_dingux_rumble_gain, true, DEFAULT_DINGUX_RUMBLE_GAIN, false); #endif + SETTING_UINT("input_auto_game_focus", &settings->uints.input_auto_game_focus, true, DEFAULT_INPUT_AUTO_GAME_FOCUS, false); SETTING_UINT("audio_latency", &settings->uints.audio_latency, false, 0 /* TODO */, false); SETTING_UINT("audio_resampler_quality", &settings->uints.audio_resampler_quality, true, audio_resampler_quality_level, false); SETTING_UINT("audio_block_frames", &settings->uints.audio_block_frames, true, 0, false); diff --git a/configuration.h b/configuration.h index 19d42525e1..f98527828d 100644 --- a/configuration.h +++ b/configuration.h @@ -156,6 +156,7 @@ typedef struct settings unsigned input_keyboard_gamepad_mapping_type; unsigned input_poll_type_behavior; unsigned input_dingux_rumble_gain; + unsigned input_auto_game_focus; unsigned netplay_port; unsigned netplay_input_latency_frames_min; diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 8e495c460c..f26e404239 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1340,6 +1340,10 @@ MSG_HASH( MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE, "input_sensors_enable" ) +MSG_HASH( + MENU_ENUM_LABEL_INPUT_AUTO_GAME_FOCUS, + "input_auto_game_focus" + ) MSG_HASH( MENU_ENUM_LABEL_INPUT_BUTTON_AXIS_THRESHOLD, "input_axis_threshold" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index dd849473e0..b1aeaf40c3 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2076,6 +2076,26 @@ MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_SENSORS_ENABLE, "Enables input from accelerometer, gyroscope and illuminance sensors, if supported by the current hardware. May have a performance impact and/or increase power drain on some platforms." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS, + "Auto Enable 'Game Focus' Mode" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_AUTO_GAME_FOCUS, + "Always enable 'Game Focus' mode when launching and resuming content. When set to 'Detect', option will be enabled if current core implements frontend keyboard callback functionality." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_OFF, + "OFF" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_ON, + "ON" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_DETECT, + "Detect" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_BUTTON_AXIS_THRESHOLD, "Input Button Axis Threshold" diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 92c9d426c8..b86bf4335a 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -514,6 +514,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_autodetect_enable, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_nowinkey_enable, MENU_ENUM_SUBLABEL_INPUT_NOWINKEY_ENABLE) #endif DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_sensors_enable, MENU_ENUM_SUBLABEL_INPUT_SENSORS_ENABLE) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_auto_game_focus, MENU_ENUM_SUBLABEL_INPUT_AUTO_GAME_FOCUS) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_swap_ok_cancel, MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_pause_libretro, MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_menu_savestate_resume, MENU_ENUM_SUBLABEL_MENU_SAVESTATE_RESUME) @@ -2895,6 +2896,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_sensors_enable); break; + case MENU_ENUM_LABEL_INPUT_AUTO_GAME_FOCUS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_auto_game_focus); + break; case MENU_ENUM_LABEL_INPUT_REMAP_BINDS_ENABLE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_remap_binds_enable); break; diff --git a/menu/menu_defines.h b/menu/menu_defines.h index 497ffdf84b..0f56e72355 100644 --- a/menu/menu_defines.h +++ b/menu/menu_defines.h @@ -403,6 +403,14 @@ enum quit_on_close_content_type QUIT_ON_CLOSE_CONTENT_LAST }; +enum input_auto_game_focus_type +{ + AUTO_GAME_FOCUS_OFF = 0, + AUTO_GAME_FOCUS_ON, + AUTO_GAME_FOCUS_DETECT, + AUTO_GAME_FOCUS_LAST +}; + RETRO_END_DECLS #endif diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 8f8152caff..5120e29f7d 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -6056,6 +6056,10 @@ unsigned menu_displaylist_build_list( MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE, PARSE_ONLY_BOOL, false) == 0) count++; + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, + MENU_ENUM_LABEL_INPUT_AUTO_GAME_FOCUS, + PARSE_ONLY_UINT, false) == 0) + count++; if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list, MENU_ENUM_LABEL_INPUT_HAPTIC_FEEDBACK_SETTINGS, PARSE_ACTION, false) == 0) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index c253a28dfe..cb51a917a2 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -5123,6 +5123,36 @@ static void setting_get_string_representation_uint_video_dingux_ipu_filter_type( } #endif +static void setting_get_string_representation_uint_input_auto_game_focus( + rarch_setting_t *setting, + char *s, size_t len) +{ + if (!setting) + return; + + switch (*setting->value.target.unsigned_integer) + { + case AUTO_GAME_FOCUS_OFF: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_OFF), + len); + break; + case AUTO_GAME_FOCUS_ON: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_ON), + len); + break; + case AUTO_GAME_FOCUS_DETECT: + strlcpy(s, + msg_hash_to_str( + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_DETECT), + len); + break; + } +} + /* A protected driver is such that the user cannot set to "null" using the UI. * Can prevent the user from locking him/herself out of the program. */ static bool setting_is_protected_driver(rarch_setting_t *setting) @@ -12098,6 +12128,22 @@ static bool setting_append_list( SD_FLAG_NONE ); + CONFIG_UINT( + list, list_info, + &settings->uints.input_auto_game_focus, + MENU_ENUM_LABEL_INPUT_AUTO_GAME_FOCUS, + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS, + DEFAULT_INPUT_AUTO_GAME_FOCUS, + &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; + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_uint_input_auto_game_focus; + menu_settings_list_current_add_range(list, list_info, 0, AUTO_GAME_FOCUS_LAST-1, 1, true, true); #if 0 CONFIG_BOOL( list, list_info, diff --git a/msg_hash.h b/msg_hash.h index 1a39756a4b..349b5ee61a 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -930,6 +930,12 @@ enum msg_hash_enums MENU_LABEL(INPUT_NOWINKEY_ENABLE), #endif MENU_LABEL(INPUT_SENSORS_ENABLE), + + MENU_LABEL(INPUT_AUTO_GAME_FOCUS), + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_OFF, + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_ON, + MENU_ENUM_LABEL_VALUE_INPUT_AUTO_GAME_FOCUS_DETECT, + MENU_LABEL(INPUT_DESCRIPTOR_LABEL_SHOW), MENU_LABEL(INPUT_DESCRIPTOR_HIDE_UNBOUND), MENU_LABEL(INPUT_BUTTON_AXIS_THRESHOLD), diff --git a/retroarch.c b/retroarch.c index f066cd56d1..f8982650c5 100644 --- a/retroarch.c +++ b/retroarch.c @@ -12831,6 +12831,7 @@ static void command_event_reinit(struct rarch_state *p_rarch, bool adaptive_vsync = settings->bools.video_adaptive_vsync; unsigned swap_interval = settings->uints.video_swap_interval; #endif + enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_REAPPLY; video_driver_reinit(flags); /* Poll input to avoid possibly stale data to corrupt things. */ @@ -12845,7 +12846,7 @@ static void command_event_reinit(struct rarch_state *p_rarch, if ( p_rarch->current_input && p_rarch->current_input->poll) p_rarch->current_input->poll(p_rarch->current_input_data); - command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, (void*)(intptr_t)-1); + command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, &game_focus_cmd); #ifdef HAVE_MENU p_rarch->dispgfx.framebuf_dirty = true; @@ -12920,6 +12921,19 @@ static void retroarch_audio_buffer_status_free(struct rarch_state *p_rarch) p_rarch->runloop_audio_latency = 0; } +static void retroarch_game_focus_free(struct rarch_state *p_rarch) +{ + /* Ensure that game focus mode is disabled */ + if (p_rarch->game_focus_state.enabled) + { + enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_OFF; + command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, &game_focus_cmd); + } + + p_rarch->game_focus_state.enabled = false; + p_rarch->game_focus_state.core_requested = false; +} + static void retroarch_system_info_free(struct rarch_state *p_rarch) { rarch_system_info_t *sys_info = &p_rarch->runloop_system; @@ -14403,49 +14417,88 @@ bool command_event(enum event_command cmd, void *data) break; case CMD_EVENT_GAME_FOCUS_TOGGLE: { - static bool game_focus_state = false; - bool video_fullscreen = settings->bools.video_fullscreen || p_rarch->rarch_force_fullscreen; - intptr_t mode = (intptr_t)data; + bool video_fullscreen = + settings->bools.video_fullscreen || p_rarch->rarch_force_fullscreen; + enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_TOGGLE; + bool current_enable_state = p_rarch->game_focus_state.enabled; + bool apply_update = false; + bool show_message = false; - /* mode = -1: restores current game focus state - * mode = 1: force set game focus, instead of toggling - * any other: toggle - */ - if (mode == 1) - game_focus_state = true; - else if (mode != -1) - game_focus_state = !game_focus_state; + if (data) + game_focus_cmd = *((enum input_game_focus_cmd_type*)data); - RARCH_LOG("%s => %s\n", - "Game focus", - game_focus_state ? "on" : "off"); - - if (game_focus_state) + switch (game_focus_cmd) { - input_driver_grab_mouse(p_rarch); - video_driver_hide_mouse(); - p_rarch->input_driver_block_hotkey = true; - p_rarch->keyboard_mapping_blocked = true; - if (mode != -1) - runloop_msg_queue_push(msg_hash_to_str(MSG_GAME_FOCUS_ON), - 1, 120, true, - NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + case GAME_FOCUS_CMD_OFF: + /* Force game focus off */ + p_rarch->game_focus_state.enabled = false; + if (p_rarch->game_focus_state.enabled != current_enable_state) + { + apply_update = true; + show_message = true; + } + break; + case GAME_FOCUS_CMD_ON: + /* Force game focus on */ + p_rarch->game_focus_state.enabled = true; + if (p_rarch->game_focus_state.enabled != current_enable_state) + { + apply_update = true; + show_message = true; + } + break; + case GAME_FOCUS_CMD_TOGGLE: + /* Invert current game focus state */ + p_rarch->game_focus_state.enabled = !p_rarch->game_focus_state.enabled; +#ifdef HAVE_MENU + /* If menu is currently active, disable + * 'toggle on' functionality */ + if (p_rarch->menu_driver_alive) + p_rarch->game_focus_state.enabled = false; +#endif + if (p_rarch->game_focus_state.enabled != current_enable_state) + { + apply_update = true; + show_message = true; + } + break; + case GAME_FOCUS_CMD_REAPPLY: + /* Reapply current game focus state */ + apply_update = true; + show_message = false; + break; + default: + break; } - else + + if (apply_update) { - if (!video_fullscreen) + if (p_rarch->game_focus_state.enabled) + { + input_driver_grab_mouse(p_rarch); + video_driver_hide_mouse(); + } + else if (!video_fullscreen) { input_driver_ungrab_mouse(p_rarch); video_driver_show_mouse(); } - p_rarch->input_driver_block_hotkey = false; - p_rarch->keyboard_mapping_blocked = false; - if (mode != -1) - runloop_msg_queue_push(msg_hash_to_str(MSG_GAME_FOCUS_OFF), - 1, 120, true, - NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); - } + p_rarch->input_driver_block_hotkey = p_rarch->game_focus_state.enabled; + p_rarch->keyboard_mapping_blocked = p_rarch->game_focus_state.enabled; + + if (show_message) + runloop_msg_queue_push( + p_rarch->game_focus_state.enabled ? + msg_hash_to_str(MSG_GAME_FOCUS_ON) : + msg_hash_to_str(MSG_GAME_FOCUS_OFF), + 1, 60, true, + NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + + RARCH_LOG("%s => %s\n", + "Game focus", + p_rarch->game_focus_state.enabled ? "ON" : "OFF"); + } } break; case CMD_EVENT_VOLUME_UP: @@ -16977,6 +17030,11 @@ static bool rarch_environment_cb(unsigned cmd, void *data) if (frontend_key_event && key_event) *frontend_key_event = *key_event; + + /* If a core calls RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK, + * then it is assumed that game focus mode is desired */ + p_rarch->game_focus_state.core_requested = true; + break; } @@ -18239,6 +18297,7 @@ static void uninit_libretro_symbols( retroarch_system_info_free(p_rarch); retroarch_frame_time_free(p_rarch); retroarch_audio_buffer_status_free(p_rarch); + retroarch_game_focus_free(p_rarch); p_rarch->camera_driver_active = false; p_rarch->location_driver_active = false; @@ -34930,6 +34989,16 @@ void retroarch_menu_running(void) if (audio_enable_menu && audio_enable_menu_bgm) audio_driver_mixer_play_menu_sound_looped(AUDIO_MIXER_SYSTEM_SLOT_BGM); #endif + + /* Ensure that game focus mode is disabled when + * running the menu (note: it is not currently + * possible for game focus to be enabled at this + * point, but must safeguard against future changes) */ + if (p_rarch->game_focus_state.enabled) + { + enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_OFF; + command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, &game_focus_cmd); + } #endif #ifdef HAVE_OVERLAY @@ -34963,6 +35032,21 @@ void retroarch_menu_running_finished(bool quit) audio_driver_mixer_stop_stream(AUDIO_MIXER_SYSTEM_SLOT_BGM); #endif + /* Enable game focus mode, if required */ + if (!quit && (p_rarch->current_core_type != CORE_TYPE_DUMMY)) + { + enum input_auto_game_focus_type auto_game_focus_type = settings ? + (enum input_auto_game_focus_type)settings->uints.input_auto_game_focus : + AUTO_GAME_FOCUS_OFF; + + if ((auto_game_focus_type == AUTO_GAME_FOCUS_ON) || + ((auto_game_focus_type == AUTO_GAME_FOCUS_DETECT) && + p_rarch->game_focus_state.core_requested)) + { + enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_ON; + command_event(CMD_EVENT_GAME_FOCUS_TOGGLE, &game_focus_cmd); + } + } #endif video_driver_set_texture_enable(false, false); #ifdef HAVE_OVERLAY @@ -35402,6 +35486,7 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data) p_rarch->runloop_autosave = false; retroarch_frame_time_free(p_rarch); retroarch_audio_buffer_status_free(p_rarch); + retroarch_game_focus_free(p_rarch); break; case RARCH_CTL_IS_IDLE: return p_rarch->runloop_idle; @@ -36889,7 +36974,10 @@ static enum runloop_state runloop_check_state( } /* Check game focus toggle */ - HOTKEY_CHECK(RARCH_GAME_FOCUS_TOGGLE, CMD_EVENT_GAME_FOCUS_TOGGLE, true, NULL); + { + enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_TOGGLE; + HOTKEY_CHECK(RARCH_GAME_FOCUS_TOGGLE, CMD_EVENT_GAME_FOCUS_TOGGLE, true, &game_focus_cmd); + } /* Check if we have pressed the UI companion toggle button */ HOTKEY_CHECK(RARCH_UI_COMPANION_TOGGLE, CMD_EVENT_UI_COMPANION_TOGGLE, true, NULL); /* Check close content key */ diff --git a/retroarch_data.h b/retroarch_data.h index a29aa0d98c..4ff972a27c 100644 --- a/retroarch_data.h +++ b/retroarch_data.h @@ -1315,6 +1315,14 @@ enum auto_shader_operation AUTO_SHADER_OP_EXISTS }; +enum input_game_focus_cmd_type +{ + GAME_FOCUS_CMD_OFF = 0, + GAME_FOCUS_CMD_ON, + GAME_FOCUS_CMD_TOGGLE, + GAME_FOCUS_CMD_REAPPLY +}; + typedef struct runloop_ctx_msg_info { const char *msg; @@ -1545,6 +1553,12 @@ struct input_keyboard_line bool enabled; }; +typedef struct input_game_focus_state +{ + bool enabled; + bool core_requested; +} input_game_focus_state_t; + #ifdef HAVE_RUNAHEAD typedef bool(*runahead_load_state_function)(const void*, size_t); #endif @@ -2304,6 +2318,8 @@ struct rarch_state bool input_driver_nonblock_state; bool input_driver_grab_mouse_state; + input_game_focus_state_t game_focus_state; /* bool alignment */ + #ifdef HAVE_MENU bool menu_input_dialog_keyboard_display; /* Is the menu driver still running? */