Add option to automatically enable 'game focus' mode when running/resuming content

This commit is contained in:
jdgleaver 2021-01-13 15:00:36 +00:00
parent 036e6fb221
commit 1c591be8f1
12 changed files with 237 additions and 35 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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"

View file

@ -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"

View file

@ -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;

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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),

View file

@ -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 */

View file

@ -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? */