mirror of
https://github.com/libretro/RetroArch
synced 2025-02-24 09:40:07 +00:00
In Android builds, add input_android_physical_keyboard configuration option and its corresponding menu entry to force a device to act as a physical keyboard.
When running on Android, RetroArch considers most devices that emit dpad events as gamepads, even if they also emit other keyboard events; this is usually the right thing to do, but it has the side effect of not letting some actual keyboards (e.g.: Logitech K480) act as such inside RetroArch. This configuration option allows users to manually select a specific input device to act as a physical keyboard instead of a gamepad, which is handy when emulating computers as opposed to consoles.
This commit is contained in:
parent
860ffb2b6a
commit
9efc1f500d
@ -1430,6 +1430,9 @@ static struct config_array_setting *populate_settings_array(settings_t *settings
|
||||
SETTING_ARRAY("input_driver", settings->arrays.input_driver, false, NULL, true);
|
||||
SETTING_ARRAY("input_joypad_driver", settings->arrays.input_joypad_driver, false, NULL, true);
|
||||
SETTING_ARRAY("input_keyboard_layout", settings->arrays.input_keyboard_layout, false, NULL, true);
|
||||
#ifdef ANDROID
|
||||
SETTING_ARRAY("input_android_physical_keyboard", settings->arrays.input_android_physical_keyboard, false, NULL, true);
|
||||
#endif
|
||||
SETTING_ARRAY("led_driver", settings->arrays.led_driver, false, NULL, true);
|
||||
SETTING_ARRAY("netplay_mitm_server", settings->arrays.netplay_mitm_server, false, NULL, true);
|
||||
SETTING_ARRAY("midi_driver", settings->arrays.midi_driver, false, NULL, true);
|
||||
|
@ -434,6 +434,10 @@ typedef struct settings
|
||||
|
||||
char input_keyboard_layout[64];
|
||||
|
||||
#ifdef ANDROID
|
||||
char input_android_physical_keyboard[255];
|
||||
#endif
|
||||
|
||||
char audio_device[255];
|
||||
char camera_device[255];
|
||||
char netplay_mitm_server[255];
|
||||
|
@ -95,15 +95,6 @@ uint8_t *android_keyboard_state_get(unsigned port)
|
||||
return android_key_state[port];
|
||||
}
|
||||
|
||||
static void android_keyboard_free(void)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < DEFAULT_MAX_PADS; i++)
|
||||
for (j = 0; j < MAX_KEYS; j++)
|
||||
android_key_state[i][j] = 0;
|
||||
}
|
||||
|
||||
/* TODO/FIXME -
|
||||
* fix game focus toggle */
|
||||
|
||||
@ -192,6 +183,20 @@ static typeof(AMotionEvent_getButtonState) *p_AMotionEvent_getButtonState;
|
||||
static void *libandroid_handle;
|
||||
#endif
|
||||
|
||||
static void android_keyboard_free(void)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < DEFAULT_MAX_PADS; i++)
|
||||
for (j = 0; j < MAX_KEYS; j++)
|
||||
android_key_state[i][j] = 0;
|
||||
|
||||
for (i = 0; i < (unsigned) kbd_num; i++)
|
||||
kbd_id[i] = -1;
|
||||
|
||||
kbd_num = 0;
|
||||
}
|
||||
|
||||
static bool android_input_lookup_name_prekitkat(char *buf,
|
||||
int *vendorId, int *productId, size_t size, int id)
|
||||
{
|
||||
@ -297,6 +302,59 @@ static bool android_input_lookup_name(char *buf,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool android_input_can_be_keyboard_jni(int id)
|
||||
{
|
||||
jmethodID getKeyboardType = NULL;
|
||||
jobject device = NULL;
|
||||
jint keyboard_type = -1;
|
||||
jmethodID method = NULL;
|
||||
jclass class = NULL;
|
||||
const char *str = NULL;
|
||||
JNIEnv *env = (JNIEnv*)jni_thread_getenv();
|
||||
|
||||
if (!env)
|
||||
return false;
|
||||
|
||||
FIND_CLASS(env, class, "android/view/InputDevice");
|
||||
if (!class)
|
||||
return false;
|
||||
|
||||
GET_STATIC_METHOD_ID(env, method, class, "getDevice",
|
||||
"(I)Landroid/view/InputDevice;");
|
||||
if (!method)
|
||||
return false;
|
||||
|
||||
CALL_OBJ_STATIC_METHOD_PARAM(env, device, class, method, (jint)id);
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
GET_METHOD_ID(env, getKeyboardType, class, "getKeyboardType", "()I");
|
||||
if (!getKeyboardType)
|
||||
return false;
|
||||
|
||||
CALL_INT_METHOD(env, keyboard_type, device, getKeyboardType);
|
||||
if (keyboard_type < 0)
|
||||
return false;
|
||||
|
||||
return keyboard_type == AINPUT_KEYBOARD_TYPE_ALPHABETIC;
|
||||
}
|
||||
|
||||
bool android_input_can_be_keyboard(void *data, int port)
|
||||
{
|
||||
android_input_t *android = (android_input_t *) data;
|
||||
if (!android)
|
||||
return false;
|
||||
|
||||
if (port < 0 || port >= android->pads_connected)
|
||||
return false;
|
||||
|
||||
state_device_t *device = &android->pad_states[port];
|
||||
if (!device->id && string_is_empty(device->name))
|
||||
return false;
|
||||
|
||||
return android_input_can_be_keyboard_jni(device->id);
|
||||
}
|
||||
|
||||
static void android_input_poll_main_cmd(void)
|
||||
{
|
||||
int8_t cmd;
|
||||
@ -867,6 +925,55 @@ static int android_input_recover_port(android_input_t *android, int id)
|
||||
}
|
||||
|
||||
|
||||
static bool is_configured_as_physical_keyboard(int vendor_id, int product_id, const char *device_name)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
char keyboard_name[sizeof(settings->arrays.input_android_physical_keyboard)];
|
||||
int keyboard_vendor_id;
|
||||
int keyboard_product_id;
|
||||
|
||||
bool is_keyboard;
|
||||
bool compare_by_id;
|
||||
if (sscanf(settings->arrays.input_android_physical_keyboard, "%04x:%04x ", &keyboard_vendor_id, &keyboard_product_id) != 2)
|
||||
{
|
||||
strlcpy(keyboard_name, settings->arrays.input_android_physical_keyboard, sizeof(keyboard_name));
|
||||
is_keyboard = string_is_equal(device_name, keyboard_name);
|
||||
compare_by_id = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_keyboard = vendor_id == keyboard_vendor_id && product_id == keyboard_product_id;
|
||||
compare_by_id = true;
|
||||
}
|
||||
|
||||
if (is_keyboard)
|
||||
{
|
||||
/*
|
||||
* Check that there is not already a similar physical keyboard attached
|
||||
* attached to the system
|
||||
*/
|
||||
for (int i = 0; i < kbd_num; i++)
|
||||
{
|
||||
char kbd_device_name[256] = { 0 };
|
||||
int kbd_vendor_id = 0;
|
||||
int kbd_product_id = 0;
|
||||
|
||||
if (!engine_lookup_name(kbd_device_name, &kbd_vendor_id,
|
||||
&kbd_product_id, sizeof(kbd_device_name), kbd_id[i]))
|
||||
return false;
|
||||
|
||||
if (compare_by_id && vendor_id == kbd_vendor_id && product_id == kbd_product_id)
|
||||
return false;
|
||||
|
||||
if (!compare_by_id && string_is_equal(device_name, kbd_device_name))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void handle_hotplug(android_input_t *android,
|
||||
struct android_app *android_app, int *port, int id,
|
||||
int source)
|
||||
@ -1146,6 +1253,18 @@ static void handle_hotplug(android_input_t *android,
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the device is a keyboard, didn't match any of the devices above
|
||||
* and is designated as the physical keyboard, then assume it is a keyboard,
|
||||
* register the id, and return unless the
|
||||
* maximum number of keyboards are already registered. */
|
||||
else if ((source & AINPUT_SOURCE_KEYBOARD) && kbd_num < MAX_NUM_KEYBOARDS &&
|
||||
is_configured_as_physical_keyboard(vendorId, productId, device_name))
|
||||
{
|
||||
kbd_id[kbd_num] = id;
|
||||
kbd_num++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if device was not keyboard only, yet did not match any of the devices
|
||||
* then try to autoconfigure as gamepad based on device_name. */
|
||||
else if (!string_is_empty(device_name))
|
||||
|
@ -778,6 +778,12 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE,
|
||||
"deferred_dropdown_box_list_input_device_type"
|
||||
)
|
||||
#ifdef ANDROID
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
"deferred_dropdown_box_list_input_select_physical_keyboard"
|
||||
)
|
||||
#endif
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION,
|
||||
"deferred_dropdown_box_list_input_description"
|
||||
@ -1560,6 +1566,12 @@ MSG_HASH(
|
||||
"input_nowinkey_enable"
|
||||
)
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
"input_android_physical_keyboard"
|
||||
)
|
||||
#endif
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE,
|
||||
"input_sensors_enable"
|
||||
@ -1758,6 +1770,7 @@ MSG_HASH(
|
||||
MENU_ENUM_LABEL_INPUT_SMALL_KEYBOARD_ENABLE,
|
||||
"input_small_keyboard_enable"
|
||||
)
|
||||
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_INPUT_TOUCH_ENABLE,
|
||||
"input_touch_enable"
|
||||
|
@ -663,6 +663,18 @@ int msg_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_HELP_GAMEMODE_ENABLE), len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
case MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
snprintf(s, len,
|
||||
"If RetroArch identifies a hardware keyboard as some kind of\n"
|
||||
"gamepad, this setting can be used to force RetroArch to treat\n"
|
||||
"the misidentified device as a keyboard.\n"
|
||||
"This can be useful if you are trying to emulate a computer in some\n"
|
||||
"Android TV device and also own a physical keyboard that can be\n"
|
||||
"attached to the box.\n");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (string_is_empty(s))
|
||||
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_INFORMATION_AVAILABLE), len);
|
||||
|
@ -2676,6 +2676,16 @@ MSG_HASH(
|
||||
"Keep Win-key combinations inside the application."
|
||||
)
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
"Select physical keyboard"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
"Use this device as a physical keyboard and not as a gamepad."
|
||||
)
|
||||
#endif
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_SENSORS_ENABLE,
|
||||
"Auxiliary Sensor Input"
|
||||
|
@ -644,6 +644,10 @@ GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_disk_index, PUSH_D
|
||||
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_device_type, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_DEVICE_TYPE)
|
||||
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_description, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION)
|
||||
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_description_kbd, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION_KBD)
|
||||
#ifdef ANDROID
|
||||
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_input_select_physical_keyboard, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETWORKING
|
||||
GENERIC_DEFERRED_PUSH_GENERAL(deferred_push_dropdown_box_list_netplay_mitm_server, PUSH_DEFAULT, DISPLAYLIST_DROPDOWN_LIST_NETPLAY_MITM_SERVER)
|
||||
#endif
|
||||
@ -681,6 +685,9 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE, deferred_push_dropdown_box_list_input_device_type},
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION, deferred_push_dropdown_box_list_input_description},
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD, deferred_push_dropdown_box_list_input_description_kbd},
|
||||
#ifdef ANDROID
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, deferred_push_dropdown_box_list_input_select_physical_keyboard},
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKING
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_NETPLAY_MITM_SERVER, deferred_push_dropdown_box_list_netplay_mitm_server},
|
||||
#endif
|
||||
|
@ -301,6 +301,10 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION;
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD:
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD;
|
||||
#ifdef ANDROID
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD;
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKING
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_NETPLAY_MITM_SERVER:
|
||||
return MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_NETPLAY_MITM_SERVER;
|
||||
@ -796,6 +800,17 @@ int generic_action_ok_displaylist_push(const char *path,
|
||||
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE;
|
||||
dl_type = DISPLAYLIST_GENERIC;
|
||||
break;
|
||||
#ifdef ANDROID
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
info.type = type;
|
||||
info.directory_ptr = idx;
|
||||
info_path = path;
|
||||
info_label = msg_hash_to_str(
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD);
|
||||
info.enum_idx = MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD;
|
||||
dl_type = DISPLAYLIST_GENERIC;
|
||||
break;
|
||||
#endif
|
||||
case ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION:
|
||||
info.type = type;
|
||||
info.directory_ptr = idx;
|
||||
@ -6779,6 +6794,63 @@ static int action_ok_push_dropdown_item_input_device_type(const char *path,
|
||||
return action_cancel_pop_default(NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static int action_ok_push_dropdown_item_input_select_physical_keyboard(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
const char *menu_path = NULL;
|
||||
enum msg_hash_enums enum_idx;
|
||||
rarch_setting_t *setting;
|
||||
menu_entries_get_last_stack(&menu_path, NULL, NULL, NULL, NULL);
|
||||
enum_idx = (enum msg_hash_enums)atoi(menu_path);
|
||||
setting = menu_setting_find_enum(enum_idx);
|
||||
|
||||
if (!setting)
|
||||
return -1;
|
||||
|
||||
char* keyboard;
|
||||
const char* keyboard_name = path;
|
||||
const char* no_keyboard = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE);
|
||||
if (string_is_equal(keyboard_name, no_keyboard))
|
||||
settings->arrays.input_android_physical_keyboard[0] = '\0';
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < MAX_INPUT_DEVICES; i++)
|
||||
{
|
||||
const char* device_name = input_config_get_device_name(i);
|
||||
if (string_is_equal(device_name, keyboard_name))
|
||||
{
|
||||
uint16_t vendor_id = input_config_get_device_vid(i);
|
||||
uint16_t product_id = input_config_get_device_pid(i);
|
||||
snprintf(settings->arrays.input_android_physical_keyboard,
|
||||
sizeof(settings->arrays.input_android_physical_keyboard),
|
||||
"%04x:%04x %s",
|
||||
vendor_id, product_id, keyboard_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* if we did not find the selected device, do nothing, the user has chosen to keep
|
||||
* the previous configuration, which is to use a device that is either not plugged right
|
||||
* now or already working as the physical keyboard.
|
||||
*/
|
||||
}
|
||||
settings->modified = true;
|
||||
|
||||
command_event(CMD_EVENT_REINIT, NULL);
|
||||
|
||||
/* Refresh menu */
|
||||
bool refresh = false;
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
|
||||
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
|
||||
|
||||
return action_cancel_pop_default(NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int action_ok_push_dropdown_item_input_description(const char *path,
|
||||
const char *label, unsigned type, size_t idx, size_t entry_idx)
|
||||
{
|
||||
@ -8614,6 +8686,11 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
|
||||
case MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_TYPE:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_device_type);
|
||||
break;
|
||||
#ifdef ANDROID
|
||||
case MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_select_physical_keyboard);
|
||||
break;
|
||||
#endif
|
||||
case MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION:
|
||||
BIND_ACTION_OK(cbs, action_ok_push_dropdown_item_input_description);
|
||||
break;
|
||||
|
@ -711,6 +711,9 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_autodetect_enable, MENU_
|
||||
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_nowinkey_enable, MENU_ENUM_SUBLABEL_INPUT_NOWINKEY_ENABLE)
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_select_physical_keyboard, MENU_ENUM_SUBLABEL_INPUT_SELECT_PHYSICAL_KEYBOARD)
|
||||
#endif
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_sensors_enable, MENU_ENUM_SUBLABEL_INPUT_SENSORS_ENABLE)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_auto_mouse_grab, MENU_ENUM_SUBLABEL_INPUT_AUTO_MOUSE_GRAB)
|
||||
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_auto_game_focus, MENU_ENUM_SUBLABEL_INPUT_AUTO_GAME_FOCUS)
|
||||
@ -3611,6 +3614,11 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
|
||||
case MENU_ENUM_LABEL_INPUT_NOWINKEY_ENABLE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_nowinkey_enable);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
case MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_select_physical_keyboard);
|
||||
break;
|
||||
#endif
|
||||
case MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE:
|
||||
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_sensors_enable);
|
||||
|
@ -1813,6 +1813,9 @@ int menu_cbs_init_bind_title(menu_file_list_cbs_t *cbs,
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE, action_get_title_dropdown_item},
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION, action_get_title_dropdown_input_description},
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD, action_get_title_dropdown_input_description_kbd},
|
||||
#ifdef ANDROID
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD, action_get_title_dropdown_item},
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKING
|
||||
{MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_NETPLAY_MITM_SERVER, action_get_title_dropdown_item},
|
||||
#endif
|
||||
|
@ -53,6 +53,9 @@ enum
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD,
|
||||
#ifdef ANDROID
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKING
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_NETPLAY_MITM_SERVER,
|
||||
#endif
|
||||
|
@ -5160,6 +5160,131 @@ end:
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static int menu_displaylist_parse_input_select_physical_keyboard_list(
|
||||
menu_displaylist_info_t *info, settings_t *settings)
|
||||
{
|
||||
char device_label[128];
|
||||
const char *val_disabled = NULL;
|
||||
rarch_system_info_t *system = &runloop_state_get_ptr()->system;
|
||||
enum msg_hash_enums enum_idx = (enum msg_hash_enums)atoi(info->path);
|
||||
rarch_setting_t *setting = menu_setting_find_enum(enum_idx);
|
||||
size_t menu_index = 0;
|
||||
unsigned count = 0;
|
||||
|
||||
int i = 0;
|
||||
char keyboard[sizeof(settings->arrays.input_android_physical_keyboard)];
|
||||
bool keyboard_added = false;
|
||||
|
||||
input_driver_state_t *st = input_state_get_ptr();
|
||||
input_driver_t *current_input = st->current_driver;
|
||||
bool is_android_driver = string_is_equal(current_input->ident, "android");
|
||||
|
||||
device_label[0] = '\0';
|
||||
|
||||
if (!system || !settings || !setting || !is_android_driver)
|
||||
goto end;
|
||||
|
||||
val_disabled = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE);
|
||||
if (string_is_empty(settings->arrays.input_android_physical_keyboard))
|
||||
strlcpy(keyboard, val_disabled, sizeof(keyboard));
|
||||
else
|
||||
{
|
||||
unsigned int vendor_id;
|
||||
unsigned int product_id;
|
||||
if (sscanf(settings->arrays.input_android_physical_keyboard, "%04x:%04x ", &vendor_id, &product_id) != 2)
|
||||
strlcpy(keyboard, settings->arrays.input_android_physical_keyboard, sizeof(keyboard));
|
||||
else
|
||||
/* If the vendor_id:product_id is encoded in the name, ignore them. */
|
||||
strlcpy(keyboard, &settings->arrays.input_android_physical_keyboard[10], sizeof(keyboard));
|
||||
}
|
||||
|
||||
for (i = MAX_INPUT_DEVICES; i >= -1; --i)
|
||||
{
|
||||
device_label[0] = '\0';
|
||||
|
||||
if (i < 0)
|
||||
strlcpy(device_label, keyboard, sizeof(device_label));
|
||||
else if (i == MAX_INPUT_DEVICES)
|
||||
strlcpy(device_label, val_disabled, sizeof(device_label));
|
||||
else if (i < MAX_INPUT_DEVICES)
|
||||
{
|
||||
/*
|
||||
* Skip devices that do not look like keyboards
|
||||
*/
|
||||
if (!android_input_can_be_keyboard(st->current_data, i))
|
||||
continue;
|
||||
|
||||
const char *device_name = input_config_get_device_display_name(i) ?
|
||||
input_config_get_device_display_name(i) : input_config_get_device_name(i);
|
||||
|
||||
if (!string_is_empty(device_name))
|
||||
{
|
||||
unsigned idx = input_config_get_device_name_index(i);
|
||||
size_t _len = strlcpy(device_label, device_name,
|
||||
sizeof(device_label));
|
||||
|
||||
/*if idx is non-zero, it's part of a set*/
|
||||
if (idx > 0)
|
||||
snprintf(device_label + _len,
|
||||
sizeof(device_label) - _len, " (#%u)", idx);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string_is_empty(device_label))
|
||||
{
|
||||
size_t previous_position;
|
||||
if (file_list_search(info->list, device_label, &previous_position))
|
||||
continue;
|
||||
|
||||
/* Add menu entry */
|
||||
if (menu_entries_append(info->list,
|
||||
device_label,
|
||||
device_label,
|
||||
MSG_UNKNOWN,
|
||||
MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
0, menu_index, NULL))
|
||||
{
|
||||
/* Add checkmark if input is currently
|
||||
* mapped to this entry */
|
||||
if (string_is_equal(device_label, keyboard))
|
||||
{
|
||||
menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[menu_index].actiondata;
|
||||
if (cbs)
|
||||
cbs->checked = true;
|
||||
menu_navigation_set_selection(menu_index);
|
||||
keyboard_added = true;
|
||||
}
|
||||
count++;
|
||||
menu_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if nothing is configured, select None by default */
|
||||
if (!keyboard_added)
|
||||
{
|
||||
menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)info->list->list[0].actiondata;
|
||||
if (cbs)
|
||||
cbs->checked = true;
|
||||
menu_navigation_set_selection(0);
|
||||
}
|
||||
|
||||
end:
|
||||
/* Fallback */
|
||||
if (count == 0)
|
||||
if (menu_entries_append(info->list,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY),
|
||||
MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY,
|
||||
FILE_TYPE_NONE, 0, 0, NULL))
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int menu_displaylist_parse_input_description_list(
|
||||
menu_displaylist_info_t *info, settings_t *settings)
|
||||
{
|
||||
@ -7007,6 +7132,11 @@ unsigned menu_displaylist_build_list(
|
||||
MENU_ENUM_LABEL_ANDROID_INPUT_DISCONNECT_WORKAROUND,
|
||||
PARSE_ONLY_BOOL, false) == 0)
|
||||
count++;
|
||||
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
PARSE_ACTION, true) == 0)
|
||||
count++;
|
||||
#endif
|
||||
if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
|
||||
MENU_ENUM_LABEL_INPUT_SENSORS_ENABLE,
|
||||
@ -12966,6 +13096,14 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
|
||||
info->flags |= MD_FLAG_NEED_REFRESH
|
||||
| MD_FLAG_NEED_PUSH;
|
||||
break;
|
||||
#ifdef ANDROID
|
||||
case DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
|
||||
count = menu_displaylist_parse_input_select_physical_keyboard_list(info, settings);
|
||||
info->flags |= MD_FLAG_NEED_REFRESH
|
||||
| MD_FLAG_NEED_PUSH;
|
||||
break;
|
||||
#endif
|
||||
case DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION:
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
|
||||
count = menu_displaylist_parse_input_description_list(info, settings);
|
||||
|
@ -71,6 +71,9 @@ enum menu_displaylist_ctl_state
|
||||
DISPLAYLIST_DROPDOWN_LIST_INPUT_DEVICE_TYPE,
|
||||
DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION,
|
||||
DISPLAYLIST_DROPDOWN_LIST_INPUT_DESCRIPTION_KBD,
|
||||
#ifdef ANDROID
|
||||
DISPLAYLIST_DROPDOWN_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKING
|
||||
DISPLAYLIST_DROPDOWN_LIST_NETPLAY_MITM_SERVER,
|
||||
#endif
|
||||
|
@ -108,6 +108,9 @@ enum menu_settings_type
|
||||
MENU_SETTING_DROPDOWN_ITEM_DISK_INDEX,
|
||||
MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_TYPE,
|
||||
MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_INDEX,
|
||||
#ifdef ANDROID
|
||||
MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
#endif
|
||||
MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION,
|
||||
MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION_KBD,
|
||||
#ifdef HAVE_NETWORKING
|
||||
|
@ -2888,6 +2888,24 @@ static int setting_action_ok_libretro_device_type(
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static int setting_action_ok_select_physical_keyboard(
|
||||
rarch_setting_t *setting, size_t idx, bool wraparound)
|
||||
{
|
||||
char enum_idx[16];
|
||||
if (!setting)
|
||||
return -1;
|
||||
|
||||
snprintf(enum_idx, sizeof(enum_idx), "%d", setting->enum_idx);
|
||||
|
||||
generic_action_ok_displaylist_push(
|
||||
enum_idx, /* we will pass the enumeration index of the string as a path */
|
||||
NULL, NULL, 0, idx, 0,
|
||||
ACTION_OK_DL_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int setting_string_action_left_string_options(
|
||||
rarch_setting_t* setting, size_t idx, bool wraparound)
|
||||
{
|
||||
@ -6845,6 +6863,26 @@ static void setting_get_string_representation_input_touch_scale(rarch_setting_t
|
||||
snprintf(s, len, "x%d", *setting->value.target.unsigned_integer);
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
static void setting_get_string_representation_android_physical_keyboard(
|
||||
rarch_setting_t *setting,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (!setting)
|
||||
return;
|
||||
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
int keyboard_vendor_id;
|
||||
int keyboard_product_id;
|
||||
|
||||
if (sscanf(setting->value.target.string, "%04x:%04x ", &keyboard_vendor_id, &keyboard_product_id) != 2)
|
||||
strlcpy(s, setting->value.target.string, len);
|
||||
else
|
||||
strlcpy(s, &setting->value.target.string[10], len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LANGEXTRA
|
||||
static void setting_get_string_representation_uint_user_language(
|
||||
rarch_setting_t *setting,
|
||||
@ -7850,6 +7888,11 @@ static void general_read_handler(rarch_setting_t *setting)
|
||||
case MENU_ENUM_LABEL_INPUT_PLAYER5_JOYPAD_INDEX:
|
||||
*setting->value.target.integer = settings->uints.input_joypad_index[setting->enum_idx - MENU_ENUM_LABEL_INPUT_PLAYER1_JOYPAD_INDEX];
|
||||
break;
|
||||
#ifdef ANDROID
|
||||
case MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
setting->value.target.string = settings->arrays.input_android_physical_keyboard;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -8170,6 +8213,15 @@ static void general_write_handler(rarch_setting_t *setting)
|
||||
settings->uints.input_joypad_index[setting->enum_idx - MENU_ENUM_LABEL_INPUT_PLAYER1_JOYPAD_INDEX] = *setting->value.target.integer;
|
||||
}
|
||||
break;
|
||||
#ifdef ANDROID
|
||||
case MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD:
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
settings->modified = true;
|
||||
strlcpy(settings->arrays.input_android_physical_keyboard, setting->value.target.string, sizeof(settings->arrays.input_android_physical_keyboard));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case MENU_ENUM_LABEL_LOG_TO_FILE:
|
||||
if (verbosity_is_enabled())
|
||||
{
|
||||
@ -14064,6 +14116,24 @@ static bool setting_append_list(
|
||||
general_read_handler,
|
||||
SD_FLAG_NONE
|
||||
);
|
||||
|
||||
input_driver_state_t *st = input_state_get_ptr();
|
||||
input_driver_t *current_input = st->current_driver;
|
||||
if (string_is_equal(current_input->ident, "android"))
|
||||
{
|
||||
CONFIG_ACTION(
|
||||
list, list_info,
|
||||
MENU_ENUM_LABEL_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
MENU_ENUM_LABEL_VALUE_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_select_physical_keyboard;
|
||||
(*list)[list_info->index - 1].read_handler = &general_read_handler;
|
||||
(*list)[list_info->index - 1].change_handler = &general_write_handler;
|
||||
(*list)[list_info->index - 1].get_string_representation = &setting_get_string_representation_android_physical_keyboard;
|
||||
(*list)[list_info->index - 1].default_value.string = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NONE);
|
||||
}
|
||||
#endif
|
||||
|
||||
CONFIG_UINT(
|
||||
|
@ -1080,6 +1080,11 @@ enum msg_hash_enums
|
||||
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
|
||||
MENU_LABEL(INPUT_NOWINKEY_ENABLE),
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
MENU_LABEL(INPUT_SELECT_PHYSICAL_KEYBOARD),
|
||||
#endif
|
||||
|
||||
MENU_LABEL(INPUT_SENSORS_ENABLE),
|
||||
MENU_LABEL(INPUT_AUTO_MOUSE_GRAB),
|
||||
|
||||
@ -1710,6 +1715,9 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DEVICE_TYPE,
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION,
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_DESCRIPTION_KBD,
|
||||
#ifdef ANDROID
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
||||
#endif
|
||||
MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST_NETPLAY_MITM_SERVER,
|
||||
MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST,
|
||||
MENU_ENUM_LABEL_DEFERRED_CONFIGURATIONS_LIST,
|
||||
|
Loading…
x
Reference in New Issue
Block a user