FullscreenUI: Use icon font for bindings

This commit is contained in:
Stenzek 2023-11-26 21:34:00 +10:00
parent 43c0ce0b3e
commit c1d0419361
No known key found for this signature in database
17 changed files with 798 additions and 511 deletions

View File

@ -1364,6 +1364,9 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
if (!visible) if (!visible)
return; return;
if (oneline)
InputManager::PrettifyInputBinding(value);
if (show_type) if (show_type)
{ {
if (icon_name) if (icon_name)
@ -1375,17 +1378,17 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
switch (type) switch (type)
{ {
case InputBindingInfo::Type::Button: case InputBindingInfo::Type::Button:
title.fmt(ICON_FA_DOT_CIRCLE "{}", display_name); title.fmt(ICON_FA_DOT_CIRCLE " {}", display_name);
break; break;
case InputBindingInfo::Type::Axis: case InputBindingInfo::Type::Axis:
case InputBindingInfo::Type::HalfAxis: case InputBindingInfo::Type::HalfAxis:
title.fmt(ICON_FA_BULLSEYE "{}", display_name); title.fmt(ICON_FA_BULLSEYE " {}", display_name);
break; break;
case InputBindingInfo::Type::Motor: case InputBindingInfo::Type::Motor:
title.fmt(ICON_FA_BELL "{}", display_name); title.fmt(ICON_FA_BELL " {}", display_name);
break; break;
case InputBindingInfo::Type::Macro: case InputBindingInfo::Type::Macro:
title.fmt(ICON_FA_PIZZA_SLICE "{}", display_name); title.fmt(ICON_FA_PIZZA_SLICE " {}", display_name);
break; break;
default: default:
title = display_name; title = display_name;
@ -1406,8 +1409,8 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, show_type ? title.c_str() : display_name, nullptr, nullptr, ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, show_type ? title.c_str() : display_name, nullptr, nullptr,
ImVec2(0.0f, 0.0f), &title_bb); ImVec2(0.0f, 0.0f), &title_bb);
ImGui::RenderTextClipped(bb.Min, bb.Max, value.empty() ? FSUI_CSTR("-") : value.c_str(), nullptr, ImGui::RenderTextClipped(bb.Min, bb.Max, value.empty() ? FSUI_CSTR("-") : value.c_str(), nullptr, &value_size,
&value_size, ImVec2(1.0f, 0.5f), &bb); ImVec2(1.0f, 0.5f), &bb);
ImGui::PopFont(); ImGui::PopFont();
} }
else else
@ -3407,9 +3410,27 @@ void FullscreenUI::DrawControllerSettingsPage()
std::string binds_string( std::string binds_string(
bsi->GetStringValue(section.c_str(), fmt::format("Macro{}Binds", macro_index + 1).c_str())); bsi->GetStringValue(section.c_str(), fmt::format("Macro{}Binds", macro_index + 1).c_str()));
if (MenuButton( TinyString pretty_binds_string;
if (!binds_string.empty())
{
for (const std::string_view& bind : StringUtil::SplitString(binds_string, '&', true))
{
const char* dispname = nullptr;
for (const Controller::ControllerBindingInfo& bi : ci->bindings)
{
if (bind == bi.name)
{
dispname = bi.icon_name ? bi.icon_name : Host::TranslateToCString(ci->name, bi.display_name);
break;
}
}
pretty_binds_string.append_fmt("{}{}", pretty_binds_string.empty() ? "" : " ", dispname);
}
}
if (MenuButtonWithValue(
TinyString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_KEYBOARD, "Macro {} Buttons")), macro_index + 1), TinyString::from_fmt(fmt::runtime(FSUI_ICONSTR(ICON_FA_KEYBOARD, "Macro {} Buttons")), macro_index + 1),
binds_string.empty() ? FSUI_CSTR("No Buttons Selected") : binds_string.c_str())) nullptr, pretty_binds_string.empty() ? FSUI_CSTR("-") : pretty_binds_string.c_str(), true,
LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
{ {
std::vector<std::string_view> buttons_split(StringUtil::SplitString(binds_string, '&', true)); std::vector<std::string_view> buttons_split(StringUtil::SplitString(binds_string, '&', true));
ImGuiFullscreen::ChoiceDialogOptions options; ImGuiFullscreen::ChoiceDialogOptions options;
@ -3476,10 +3497,10 @@ void FullscreenUI::DrawControllerSettingsPage()
s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0); s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0);
SmallString freq_summary; SmallString freq_summary;
if (frequency == 0) if (frequency == 0)
freq_summary = FSUI_VSTR("Macro will not auto-toggle."); freq_summary = FSUI_VSTR("Disabled");
else else
freq_summary.fmt(FSUI_FSTR("Macro will toggle every {} frames."), frequency); freq_summary.fmt(FSUI_FSTR("{} Frames"), frequency);
if (MenuButton(freq_title, freq_summary)) if (MenuButtonWithValue(freq_title, nullptr, freq_summary, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
ImGui::OpenPopup(freq_title); ImGui::OpenPopup(freq_title);
ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f)); ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f));
@ -6727,6 +6748,7 @@ void FullscreenUI::ProgressCallback::SetCancelled()
#if 0 #if 0
// TRANSLATION-STRING-AREA-BEGIN // TRANSLATION-STRING-AREA-BEGIN
TRANSLATE_NOOP("FullscreenUI", "${title}: Title of the game.\n${filetitle}: Name component of the game's filename.\n${serial}: Serial of the game."); TRANSLATE_NOOP("FullscreenUI", "${title}: Title of the game.\n${filetitle}: Name component of the game's filename.\n${serial}: Serial of the game.");
TRANSLATE_NOOP("FullscreenUI", "-");
TRANSLATE_NOOP("FullscreenUI", "1 Frame"); TRANSLATE_NOOP("FullscreenUI", "1 Frame");
TRANSLATE_NOOP("FullscreenUI", "10 Frames"); TRANSLATE_NOOP("FullscreenUI", "10 Frames");
TRANSLATE_NOOP("FullscreenUI", "100% [60 FPS (NTSC) / 50 FPS (PAL)]"); TRANSLATE_NOOP("FullscreenUI", "100% [60 FPS (NTSC) / 50 FPS (PAL)]");
@ -7061,7 +7083,6 @@ TRANSLATE_NOOP("FullscreenUI", "Logs messages to duckstation.log in the user dir
TRANSLATE_NOOP("FullscreenUI", "Logs messages to the console window."); TRANSLATE_NOOP("FullscreenUI", "Logs messages to the console window.");
TRANSLATE_NOOP("FullscreenUI", "Logs messages to the debug console where supported."); TRANSLATE_NOOP("FullscreenUI", "Logs messages to the debug console where supported.");
TRANSLATE_NOOP("FullscreenUI", "Logs out of RetroAchievements."); TRANSLATE_NOOP("FullscreenUI", "Logs out of RetroAchievements.");
TRANSLATE_NOOP("FullscreenUI", "Macro will toggle every {} frames.");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Buttons"); TRANSLATE_NOOP("FullscreenUI", "Macro {} Buttons");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Frequency"); TRANSLATE_NOOP("FullscreenUI", "Macro {} Frequency");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Trigger"); TRANSLATE_NOOP("FullscreenUI", "Macro {} Trigger");
@ -7081,7 +7102,6 @@ TRANSLATE_NOOP("FullscreenUI", "Mute All Sound");
TRANSLATE_NOOP("FullscreenUI", "Mute CD Audio"); TRANSLATE_NOOP("FullscreenUI", "Mute CD Audio");
TRANSLATE_NOOP("FullscreenUI", "No"); TRANSLATE_NOOP("FullscreenUI", "No");
TRANSLATE_NOOP("FullscreenUI", "No Binding"); TRANSLATE_NOOP("FullscreenUI", "No Binding");
TRANSLATE_NOOP("FullscreenUI", "No Buttons Selected");
TRANSLATE_NOOP("FullscreenUI", "No Game Selected"); TRANSLATE_NOOP("FullscreenUI", "No Game Selected");
TRANSLATE_NOOP("FullscreenUI", "No cheats found for {}."); TRANSLATE_NOOP("FullscreenUI", "No cheats found for {}.");
TRANSLATE_NOOP("FullscreenUI", "No input profiles available."); TRANSLATE_NOOP("FullscreenUI", "No input profiles available.");
@ -7321,6 +7341,7 @@ TRANSLATE_NOOP("FullscreenUI", "Writes textures which can be replaced to the dum
TRANSLATE_NOOP("FullscreenUI", "Yes"); TRANSLATE_NOOP("FullscreenUI", "Yes");
TRANSLATE_NOOP("FullscreenUI", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions."); TRANSLATE_NOOP("FullscreenUI", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions.");
TRANSLATE_NOOP("FullscreenUI", "\"PlayStation\" and \"PSX\" are registered trademarks of Sony Interactive Entertainment Europe Limited. This software is not affiliated in any way with Sony Interactive Entertainment."); TRANSLATE_NOOP("FullscreenUI", "\"PlayStation\" and \"PSX\" are registered trademarks of Sony Interactive Entertainment Europe Limited. This software is not affiliated in any way with Sony Interactive Entertainment.");
TRANSLATE_NOOP("FullscreenUI", "{} Frames");
TRANSLATE_NOOP("FullscreenUI", "{} deleted."); TRANSLATE_NOOP("FullscreenUI", "{} deleted.");
TRANSLATE_NOOP("FullscreenUI", "{} does not exist."); TRANSLATE_NOOP("FullscreenUI", "{} does not exist.");
TRANSLATE_NOOP("FullscreenUI", "{} is not a valid disc image."); TRANSLATE_NOOP("FullscreenUI", "{} is not a valid disc image.");

View File

@ -615,7 +615,7 @@ void ImGuiManager::DrawInputsOverlay()
continue; continue;
if (cinfo->icon_name) if (cinfo->icon_name)
text.append_fmt("{} {} |", cinfo->icon_name, port + 1u); text.append_fmt("{} {}", cinfo->icon_name, port + 1u);
else else
text.append_fmt("{} |", port + 1u); text.append_fmt("{} |", port + 1u);

View File

@ -934,6 +934,11 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
return g_nogui_window->ConvertHostKeyboardCodeToString(code); return g_nogui_window->ConvertHostKeyboardCodeToString(code);
} }
const char* InputManager::ConvertHostKeyboardCodeToIcon(u32 code)
{
return nullptr;
}
BEGIN_HOTKEY_LIST(g_host_hotkeys) BEGIN_HOTKEY_LIST(g_host_hotkeys)
END_HOTKEY_LIST() END_HOTKEY_LIST()

View File

@ -5,6 +5,8 @@
#include "common/string_util.h" #include "common/string_util.h"
#include "IconsPromptFont.h"
#include "fmt/format.h" #include "fmt/format.h"
#include "util/input_manager.h" #include "util/input_manager.h"
@ -14,446 +16,447 @@ struct KeyCodeName
{ {
int code; int code;
const char* name; const char* name;
const char* icon_name;
}; };
static constexpr KeyCodeName s_qt_key_names[] = {{Qt::Key_Escape, "Escape"}, static constexpr KeyCodeName s_qt_key_names[] = {{Qt::Key_Escape, "Escape", ICON_PF_ESC},
{Qt::Key_Tab, "Tab"}, {Qt::Key_Tab, "Tab", ICON_PF_TAB},
{Qt::Key_Backtab, "Backtab"}, {Qt::Key_Backtab, "Backtab", nullptr},
{Qt::Key_Backspace, "Backspace"}, {Qt::Key_Backspace, "Backspace", ICON_PF_BACKSPACE},
{Qt::Key_Return, "Return"}, {Qt::Key_Return, "Return", ICON_PF_ENTER},
{Qt::Key_Enter, "Enter"}, {Qt::Key_Enter, "Enter", ICON_PF_ENTER},
{Qt::Key_Insert, "Insert"}, {Qt::Key_Insert, "Insert", ICON_PF_INSERT},
{Qt::Key_Delete, "Delete"}, {Qt::Key_Delete, "Delete", ICON_PF_DELETE},
{Qt::Key_Pause, "Pause"}, {Qt::Key_Pause, "Pause", ICON_PF_PAUSE},
{Qt::Key_Print, "Print"}, {Qt::Key_Print, "Print", ICON_PF_PRTSC},
{Qt::Key_SysReq, "SysReq"}, {Qt::Key_SysReq, "SysReq", ICON_PF_PAUSE},
{Qt::Key_Clear, "Clear"}, {Qt::Key_Clear, "Clear", nullptr},
{Qt::Key_Home, "Home"}, {Qt::Key_Home, "Home", ICON_PF_HOME},
{Qt::Key_End, "End"}, {Qt::Key_End, "End", ICON_PF_END},
{Qt::Key_Left, "Left"}, {Qt::Key_Left, "Left", ICON_PF_ARROW_LEFT},
{Qt::Key_Up, "Up"}, {Qt::Key_Up, "Up", ICON_PF_ARROW_UP},
{Qt::Key_Right, "Right"}, {Qt::Key_Right, "Right", ICON_PF_ARROW_RIGHT},
{Qt::Key_Down, "Down"}, {Qt::Key_Down, "Down", ICON_PF_ARROW_DOWN},
{Qt::Key_PageUp, "PageUp"}, {Qt::Key_PageUp, "PageUp", ICON_PF_PAGE_UP},
{Qt::Key_PageDown, "PageDown"}, {Qt::Key_PageDown, "PageDown", ICON_PF_PAGE_DOWN},
{Qt::Key_Shift, "Shift"}, {Qt::Key_Shift, "Shift", ICON_PF_SHIFT},
{Qt::Key_Control, "Control"}, {Qt::Key_Control, "Control", ICON_PF_CTRL},
{Qt::Key_Meta, "Meta"}, {Qt::Key_Meta, "Meta", ICON_PF_SUPER},
{Qt::Key_Alt, "Alt"}, {Qt::Key_Alt, "Alt", ICON_PF_ALT},
{Qt::Key_CapsLock, "CapsLock"}, {Qt::Key_CapsLock, "CapsLock", ICON_PF_CAPS},
{Qt::Key_NumLock, "NumLock"}, {Qt::Key_NumLock, "NumLock", ICON_PF_NUMLOCK},
{Qt::Key_ScrollLock, "ScrollLock"}, {Qt::Key_ScrollLock, "ScrollLock", ICON_PF_SCRLK},
{Qt::Key_F1, "F1"}, {Qt::Key_F1, "F1", ICON_PF_F1},
{Qt::Key_F2, "F2"}, {Qt::Key_F2, "F2", ICON_PF_F2},
{Qt::Key_F3, "F3"}, {Qt::Key_F3, "F3", ICON_PF_F3},
{Qt::Key_F4, "F4"}, {Qt::Key_F4, "F4", ICON_PF_F4},
{Qt::Key_F5, "F5"}, {Qt::Key_F5, "F5", ICON_PF_F5},
{Qt::Key_F6, "F6"}, {Qt::Key_F6, "F6", ICON_PF_F6},
{Qt::Key_F7, "F7"}, {Qt::Key_F7, "F7", ICON_PF_F7},
{Qt::Key_F8, "F8"}, {Qt::Key_F8, "F8", ICON_PF_F8},
{Qt::Key_F9, "F9"}, {Qt::Key_F9, "F9", ICON_PF_F9},
{Qt::Key_F10, "F10"}, {Qt::Key_F10, "F10", ICON_PF_F10},
{Qt::Key_F11, "F11"}, {Qt::Key_F11, "F11", ICON_PF_F11},
{Qt::Key_F12, "F12"}, {Qt::Key_F12, "F12", ICON_PF_F12},
{Qt::Key_F13, "F13"}, {Qt::Key_F13, "F13", nullptr},
{Qt::Key_F14, "F14"}, {Qt::Key_F14, "F14", nullptr},
{Qt::Key_F15, "F15"}, {Qt::Key_F15, "F15", nullptr},
{Qt::Key_F16, "F16"}, {Qt::Key_F16, "F16", nullptr},
{Qt::Key_F17, "F17"}, {Qt::Key_F17, "F17", nullptr},
{Qt::Key_F18, "F18"}, {Qt::Key_F18, "F18", nullptr},
{Qt::Key_F19, "F19"}, {Qt::Key_F19, "F19", nullptr},
{Qt::Key_F20, "F20"}, {Qt::Key_F20, "F20", nullptr},
{Qt::Key_F21, "F21"}, {Qt::Key_F21, "F21", nullptr},
{Qt::Key_F22, "F22"}, {Qt::Key_F22, "F22", nullptr},
{Qt::Key_F23, "F23"}, {Qt::Key_F23, "F23", nullptr},
{Qt::Key_F24, "F24"}, {Qt::Key_F24, "F24", nullptr},
{Qt::Key_F25, "F25"}, {Qt::Key_F25, "F25", nullptr},
{Qt::Key_F26, "F26"}, {Qt::Key_F26, "F26", nullptr},
{Qt::Key_F27, "F27"}, {Qt::Key_F27, "F27", nullptr},
{Qt::Key_F28, "F28"}, {Qt::Key_F28, "F28", nullptr},
{Qt::Key_F29, "F29"}, {Qt::Key_F29, "F29", nullptr},
{Qt::Key_F30, "F30"}, {Qt::Key_F30, "F30", nullptr},
{Qt::Key_F31, "F31"}, {Qt::Key_F31, "F31", nullptr},
{Qt::Key_F32, "F32"}, {Qt::Key_F32, "F32", nullptr},
{Qt::Key_F33, "F33"}, {Qt::Key_F33, "F33", nullptr},
{Qt::Key_F34, "F34"}, {Qt::Key_F34, "F34", nullptr},
{Qt::Key_F35, "F35"}, {Qt::Key_F35, "F35", nullptr},
{Qt::Key_Super_L, "Super_L"}, {Qt::Key_Super_L, "Super_L", nullptr},
{Qt::Key_Super_R, "Super_R"}, {Qt::Key_Super_R, "Super_R", nullptr},
{Qt::Key_Menu, "Menu"}, {Qt::Key_Menu, "Menu", nullptr},
{Qt::Key_Hyper_L, "Hyper_L"}, {Qt::Key_Hyper_L, "Hyper_L", nullptr},
{Qt::Key_Hyper_R, "Hyper_R"}, {Qt::Key_Hyper_R, "Hyper_R", nullptr},
{Qt::Key_Help, "Help"}, {Qt::Key_Help, "Help", nullptr},
{Qt::Key_Direction_L, "Direction_L"}, {Qt::Key_Direction_L, "Direction_L", nullptr},
{Qt::Key_Direction_R, "Direction_R"}, {Qt::Key_Direction_R, "Direction_R", nullptr},
{Qt::Key_Space, "Space"}, {Qt::Key_Space, "Space", ICON_PF_SPACE},
{Qt::Key_Any, "Any"}, {Qt::Key_Any, "Any", nullptr},
{Qt::Key_Exclam, "Exclam"}, {Qt::Key_Exclam, "Exclam", nullptr},
{Qt::Key_QuoteDbl, "QuoteDbl"}, {Qt::Key_QuoteDbl, "QuoteDbl", nullptr},
{Qt::Key_NumberSign, "NumberSign"}, {Qt::Key_NumberSign, "NumberSign", nullptr},
{Qt::Key_Dollar, "Dollar"}, {Qt::Key_Dollar, "Dollar", nullptr},
{Qt::Key_Percent, "Percent"}, {Qt::Key_Percent, "Percent", nullptr},
{Qt::Key_Ampersand, "Ampersand"}, {Qt::Key_Ampersand, "Ampersand", nullptr},
{Qt::Key_Apostrophe, "Apostrophe"}, {Qt::Key_Apostrophe, "Apostrophe", nullptr},
{Qt::Key_ParenLeft, "ParenLeft"}, {Qt::Key_ParenLeft, "ParenLeft", nullptr},
{Qt::Key_ParenRight, "ParenRight"}, {Qt::Key_ParenRight, "ParenRight", nullptr},
{Qt::Key_Asterisk, "Asterisk"}, {Qt::Key_Asterisk, "Asterisk", nullptr},
{Qt::Key_Plus, "Plus"}, {Qt::Key_Plus, "Plus", nullptr},
{Qt::Key_Comma, "Comma"}, {Qt::Key_Comma, "Comma", nullptr},
{Qt::Key_Minus, "Minus"}, {Qt::Key_Minus, "Minus", nullptr},
{Qt::Key_Period, "Period"}, {Qt::Key_Period, "Period", nullptr},
{Qt::Key_Slash, "Slash"}, {Qt::Key_Slash, "Slash", nullptr},
{Qt::Key_0, "0"}, {Qt::Key_0, "0", ICON_PF_0},
{Qt::Key_1, "1"}, {Qt::Key_1, "1", ICON_PF_1},
{Qt::Key_2, "2"}, {Qt::Key_2, "2", ICON_PF_2},
{Qt::Key_3, "3"}, {Qt::Key_3, "3", ICON_PF_3},
{Qt::Key_4, "4"}, {Qt::Key_4, "4", ICON_PF_4},
{Qt::Key_5, "5"}, {Qt::Key_5, "5", ICON_PF_5},
{Qt::Key_6, "6"}, {Qt::Key_6, "6", ICON_PF_6},
{Qt::Key_7, "7"}, {Qt::Key_7, "7", ICON_PF_7},
{Qt::Key_8, "8"}, {Qt::Key_8, "8", ICON_PF_8},
{Qt::Key_9, "9"}, {Qt::Key_9, "9", ICON_PF_9},
{Qt::Key_Colon, "Colon"}, {Qt::Key_Colon, "Colon", nullptr},
{Qt::Key_Semicolon, "Semicolon"}, {Qt::Key_Semicolon, "Semicolon", nullptr},
{Qt::Key_Less, "Less"}, {Qt::Key_Less, "Less", nullptr},
{Qt::Key_Equal, "Equal"}, {Qt::Key_Equal, "Equal", nullptr},
{Qt::Key_Greater, "Greater"}, {Qt::Key_Greater, "Greater", nullptr},
{Qt::Key_Question, "Question"}, {Qt::Key_Question, "Question", nullptr},
{Qt::Key_At, "At"}, {Qt::Key_At, "At", nullptr},
{Qt::Key_A, "A"}, {Qt::Key_A, "A", ICON_PF_KEY_A},
{Qt::Key_B, "B"}, {Qt::Key_B, "B", ICON_PF_KEY_B},
{Qt::Key_C, "C"}, {Qt::Key_C, "C", ICON_PF_KEY_C},
{Qt::Key_D, "D"}, {Qt::Key_D, "D", ICON_PF_KEY_D},
{Qt::Key_E, "E"}, {Qt::Key_E, "E", ICON_PF_KEY_E},
{Qt::Key_F, "F"}, {Qt::Key_F, "F", ICON_PF_KEY_F},
{Qt::Key_G, "G"}, {Qt::Key_G, "G", ICON_PF_KEY_G},
{Qt::Key_H, "H"}, {Qt::Key_H, "H", ICON_PF_KEY_H},
{Qt::Key_I, "I"}, {Qt::Key_I, "I", ICON_PF_KEY_I},
{Qt::Key_J, "J"}, {Qt::Key_J, "J", ICON_PF_KEY_J},
{Qt::Key_K, "K"}, {Qt::Key_K, "K", ICON_PF_KEY_K},
{Qt::Key_L, "L"}, {Qt::Key_L, "L", ICON_PF_KEY_L},
{Qt::Key_M, "M"}, {Qt::Key_M, "M", ICON_PF_KEY_M},
{Qt::Key_N, "N"}, {Qt::Key_N, "N", ICON_PF_KEY_N},
{Qt::Key_O, "O"}, {Qt::Key_O, "O", ICON_PF_KEY_O},
{Qt::Key_P, "P"}, {Qt::Key_P, "P", ICON_PF_KEY_P},
{Qt::Key_Q, "Q"}, {Qt::Key_Q, "Q", ICON_PF_KEY_Q},
{Qt::Key_R, "R"}, {Qt::Key_R, "R", ICON_PF_KEY_R},
{Qt::Key_S, "S"}, {Qt::Key_S, "S", ICON_PF_KEY_S},
{Qt::Key_T, "T"}, {Qt::Key_T, "T", ICON_PF_KEY_T},
{Qt::Key_U, "U"}, {Qt::Key_U, "U", ICON_PF_KEY_U},
{Qt::Key_V, "V"}, {Qt::Key_V, "V", ICON_PF_KEY_V},
{Qt::Key_W, "W"}, {Qt::Key_W, "W", ICON_PF_KEY_W},
{Qt::Key_X, "X"}, {Qt::Key_X, "X", ICON_PF_KEY_X},
{Qt::Key_Y, "Y"}, {Qt::Key_Y, "Y", ICON_PF_KEY_Y},
{Qt::Key_Z, "Z"}, {Qt::Key_Z, "Z", ICON_PF_KEY_Z},
{Qt::Key_BracketLeft, "BracketLeft"}, {Qt::Key_BracketLeft, "BracketLeft", nullptr},
{Qt::Key_Backslash, "Backslash"}, {Qt::Key_Backslash, "Backslash", nullptr},
{Qt::Key_BracketRight, "BracketRight"}, {Qt::Key_BracketRight, "BracketRight", nullptr},
{Qt::Key_AsciiCircum, "AsciiCircum"}, {Qt::Key_AsciiCircum, "AsciiCircum", nullptr},
{Qt::Key_Underscore, "Underscore"}, {Qt::Key_Underscore, "Underscore", nullptr},
{Qt::Key_QuoteLeft, "QuoteLeft"}, {Qt::Key_QuoteLeft, "QuoteLeft", nullptr},
{Qt::Key_BraceLeft, "BraceLeft"}, {Qt::Key_BraceLeft, "BraceLeft", nullptr},
{Qt::Key_Bar, "Bar"}, {Qt::Key_Bar, "Bar", nullptr},
{Qt::Key_BraceRight, "BraceRight"}, {Qt::Key_BraceRight, "BraceRight", nullptr},
{Qt::Key_AsciiTilde, "AsciiTilde"}, {Qt::Key_AsciiTilde, "AsciiTilde", nullptr},
{Qt::Key_nobreakspace, "nobreakspace"}, {Qt::Key_nobreakspace, "nobreakspace", nullptr},
{Qt::Key_exclamdown, "exclamdown"}, {Qt::Key_exclamdown, "exclamdown", nullptr},
{Qt::Key_cent, "cent"}, {Qt::Key_cent, "cent", nullptr},
{Qt::Key_sterling, "sterling"}, {Qt::Key_sterling, "sterling", nullptr},
{Qt::Key_currency, "currency"}, {Qt::Key_currency, "currency", nullptr},
{Qt::Key_yen, "yen"}, {Qt::Key_yen, "yen", nullptr},
{Qt::Key_brokenbar, "brokenbar"}, {Qt::Key_brokenbar, "brokenbar", nullptr},
{Qt::Key_section, "section"}, {Qt::Key_section, "section", nullptr},
{Qt::Key_diaeresis, "diaeresis"}, {Qt::Key_diaeresis, "diaeresis", nullptr},
{Qt::Key_copyright, "copyright"}, {Qt::Key_copyright, "copyright", nullptr},
{Qt::Key_ordfeminine, "ordfeminine"}, {Qt::Key_ordfeminine, "ordfeminine", nullptr},
{Qt::Key_guillemotleft, "guillemotleft"}, {Qt::Key_guillemotleft, "guillemotleft", nullptr},
{Qt::Key_notsign, "notsign"}, {Qt::Key_notsign, "notsign", nullptr},
{Qt::Key_hyphen, "hyphen"}, {Qt::Key_hyphen, "hyphen", nullptr},
{Qt::Key_registered, "registered"}, {Qt::Key_registered, "registered", nullptr},
{Qt::Key_macron, "macron"}, {Qt::Key_macron, "macron", nullptr},
{Qt::Key_degree, "degree"}, {Qt::Key_degree, "degree", nullptr},
{Qt::Key_plusminus, "plusminus"}, {Qt::Key_plusminus, "plusminus", nullptr},
{Qt::Key_twosuperior, "twosuperior"}, {Qt::Key_twosuperior, "twosuperior", nullptr},
{Qt::Key_threesuperior, "threesuperior"}, {Qt::Key_threesuperior, "threesuperior", nullptr},
{Qt::Key_acute, "acute"}, {Qt::Key_acute, "acute", nullptr},
{Qt::Key_mu, "mu"}, {Qt::Key_mu, "mu", nullptr},
{Qt::Key_paragraph, "paragraph"}, {Qt::Key_paragraph, "paragraph", nullptr},
{Qt::Key_periodcentered, "periodcentered"}, {Qt::Key_periodcentered, "periodcentered", nullptr},
{Qt::Key_cedilla, "cedilla"}, {Qt::Key_cedilla, "cedilla", nullptr},
{Qt::Key_onesuperior, "onesuperior"}, {Qt::Key_onesuperior, "onesuperior", nullptr},
{Qt::Key_masculine, "masculine"}, {Qt::Key_masculine, "masculine", nullptr},
{Qt::Key_guillemotright, "guillemotright"}, {Qt::Key_guillemotright, "guillemotright", nullptr},
{Qt::Key_onequarter, "onequarter"}, {Qt::Key_onequarter, "onequarter", nullptr},
{Qt::Key_onehalf, "onehalf"}, {Qt::Key_onehalf, "onehalf", nullptr},
{Qt::Key_threequarters, "threequarters"}, {Qt::Key_threequarters, "threequarters", nullptr},
{Qt::Key_questiondown, "questiondown"}, {Qt::Key_questiondown, "questiondown", nullptr},
{Qt::Key_Agrave, "Agrave"}, {Qt::Key_Agrave, "Agrave", nullptr},
{Qt::Key_Aacute, "Aacute"}, {Qt::Key_Aacute, "Aacute", nullptr},
{Qt::Key_Acircumflex, "Acircumflex"}, {Qt::Key_Acircumflex, "Acircumflex", nullptr},
{Qt::Key_Atilde, "Atilde"}, {Qt::Key_Atilde, "Atilde", nullptr},
{Qt::Key_Adiaeresis, "Adiaeresis"}, {Qt::Key_Adiaeresis, "Adiaeresis", nullptr},
{Qt::Key_Aring, "Aring"}, {Qt::Key_Aring, "Aring", nullptr},
{Qt::Key_AE, "AE"}, {Qt::Key_AE, "AE", nullptr},
{Qt::Key_Ccedilla, "Ccedilla"}, {Qt::Key_Ccedilla, "Ccedilla", nullptr},
{Qt::Key_Egrave, "Egrave"}, {Qt::Key_Egrave, "Egrave", nullptr},
{Qt::Key_Eacute, "Eacute"}, {Qt::Key_Eacute, "Eacute", nullptr},
{Qt::Key_Ecircumflex, "Ecircumflex"}, {Qt::Key_Ecircumflex, "Ecircumflex", nullptr},
{Qt::Key_Ediaeresis, "Ediaeresis"}, {Qt::Key_Ediaeresis, "Ediaeresis", nullptr},
{Qt::Key_Igrave, "Igrave"}, {Qt::Key_Igrave, "Igrave", nullptr},
{Qt::Key_Iacute, "Iacute"}, {Qt::Key_Iacute, "Iacute", nullptr},
{Qt::Key_Icircumflex, "Icircumflex"}, {Qt::Key_Icircumflex, "Icircumflex", nullptr},
{Qt::Key_Idiaeresis, "Idiaeresis"}, {Qt::Key_Idiaeresis, "Idiaeresis", nullptr},
{Qt::Key_ETH, "ETH"}, {Qt::Key_ETH, "ETH", nullptr},
{Qt::Key_Ntilde, "Ntilde"}, {Qt::Key_Ntilde, "Ntilde", nullptr},
{Qt::Key_Ograve, "Ograve"}, {Qt::Key_Ograve, "Ograve", nullptr},
{Qt::Key_Oacute, "Oacute"}, {Qt::Key_Oacute, "Oacute", nullptr},
{Qt::Key_Ocircumflex, "Ocircumflex"}, {Qt::Key_Ocircumflex, "Ocircumflex", nullptr},
{Qt::Key_Otilde, "Otilde"}, {Qt::Key_Otilde, "Otilde", nullptr},
{Qt::Key_Odiaeresis, "Odiaeresis"}, {Qt::Key_Odiaeresis, "Odiaeresis", nullptr},
{Qt::Key_multiply, "multiply"}, {Qt::Key_multiply, "multiply", nullptr},
{Qt::Key_Ooblique, "Ooblique"}, {Qt::Key_Ooblique, "Ooblique", nullptr},
{Qt::Key_Ugrave, "Ugrave"}, {Qt::Key_Ugrave, "Ugrave", nullptr},
{Qt::Key_Uacute, "Uacute"}, {Qt::Key_Uacute, "Uacute", nullptr},
{Qt::Key_Ucircumflex, "Ucircumflex"}, {Qt::Key_Ucircumflex, "Ucircumflex", nullptr},
{Qt::Key_Udiaeresis, "Udiaeresis"}, {Qt::Key_Udiaeresis, "Udiaeresis", nullptr},
{Qt::Key_Yacute, "Yacute"}, {Qt::Key_Yacute, "Yacute", nullptr},
{Qt::Key_THORN, "THORN"}, {Qt::Key_THORN, "THORN", nullptr},
{Qt::Key_ssharp, "ssharp"}, {Qt::Key_ssharp, "ssharp", nullptr},
{Qt::Key_division, "division"}, {Qt::Key_division, "division", nullptr},
{Qt::Key_ydiaeresis, "ydiaeresis"}, {Qt::Key_ydiaeresis, "ydiaeresis", nullptr},
{Qt::Key_AltGr, "AltGr"}, {Qt::Key_AltGr, "AltGr", nullptr},
{Qt::Key_Multi_key, "Multi_key"}, {Qt::Key_Multi_key, "Multi_key", nullptr},
{Qt::Key_Codeinput, "Codeinput"}, {Qt::Key_Codeinput, "Codeinput", nullptr},
{Qt::Key_SingleCandidate, "SingleCandidate"}, {Qt::Key_SingleCandidate, "SingleCandidate", nullptr},
{Qt::Key_MultipleCandidate, "MultipleCandidate"}, {Qt::Key_MultipleCandidate, "MultipleCandidate", nullptr},
{Qt::Key_PreviousCandidate, "PreviousCandidate"}, {Qt::Key_PreviousCandidate, "PreviousCandidate", nullptr},
{Qt::Key_Mode_switch, "Mode_switch"}, {Qt::Key_Mode_switch, "Mode_switch", nullptr},
{Qt::Key_Kanji, "Kanji"}, {Qt::Key_Kanji, "Kanji", nullptr},
{Qt::Key_Muhenkan, "Muhenkan"}, {Qt::Key_Muhenkan, "Muhenkan", nullptr},
{Qt::Key_Henkan, "Henkan"}, {Qt::Key_Henkan, "Henkan", nullptr},
{Qt::Key_Romaji, "Romaji"}, {Qt::Key_Romaji, "Romaji", nullptr},
{Qt::Key_Hiragana, "Hiragana"}, {Qt::Key_Hiragana, "Hiragana", nullptr},
{Qt::Key_Katakana, "Katakana"}, {Qt::Key_Katakana, "Katakana", nullptr},
{Qt::Key_Hiragana_Katakana, "Hiragana_Katakana"}, {Qt::Key_Hiragana_Katakana, "Hiragana_Katakana", nullptr},
{Qt::Key_Zenkaku, "Zenkaku"}, {Qt::Key_Zenkaku, "Zenkaku", nullptr},
{Qt::Key_Hankaku, "Hankaku"}, {Qt::Key_Hankaku, "Hankaku", nullptr},
{Qt::Key_Zenkaku_Hankaku, "Zenkaku_Hankaku"}, {Qt::Key_Zenkaku_Hankaku, "Zenkaku_Hankaku", nullptr},
{Qt::Key_Touroku, "Touroku"}, {Qt::Key_Touroku, "Touroku", nullptr},
{Qt::Key_Massyo, "Massyo"}, {Qt::Key_Massyo, "Massyo", nullptr},
{Qt::Key_Kana_Lock, "Kana_Lock"}, {Qt::Key_Kana_Lock, "Kana_Lock", nullptr},
{Qt::Key_Kana_Shift, "Kana_Shift"}, {Qt::Key_Kana_Shift, "Kana_Shift", nullptr},
{Qt::Key_Eisu_Shift, "Eisu_Shift"}, {Qt::Key_Eisu_Shift, "Eisu_Shift", nullptr},
{Qt::Key_Eisu_toggle, "Eisu_toggle"}, {Qt::Key_Eisu_toggle, "Eisu_toggle", nullptr},
{Qt::Key_Hangul, "Hangul"}, {Qt::Key_Hangul, "Hangul", nullptr},
{Qt::Key_Hangul_Start, "Hangul_Start"}, {Qt::Key_Hangul_Start, "Hangul_Start", nullptr},
{Qt::Key_Hangul_End, "Hangul_End"}, {Qt::Key_Hangul_End, "Hangul_End", nullptr},
{Qt::Key_Hangul_Hanja, "Hangul_Hanja"}, {Qt::Key_Hangul_Hanja, "Hangul_Hanja", nullptr},
{Qt::Key_Hangul_Jamo, "Hangul_Jamo"}, {Qt::Key_Hangul_Jamo, "Hangul_Jamo", nullptr},
{Qt::Key_Hangul_Romaja, "Hangul_Romaja"}, {Qt::Key_Hangul_Romaja, "Hangul_Romaja", nullptr},
{Qt::Key_Hangul_Jeonja, "Hangul_Jeonja"}, {Qt::Key_Hangul_Jeonja, "Hangul_Jeonja", nullptr},
{Qt::Key_Hangul_Banja, "Hangul_Banja"}, {Qt::Key_Hangul_Banja, "Hangul_Banja", nullptr},
{Qt::Key_Hangul_PreHanja, "Hangul_PreHanja"}, {Qt::Key_Hangul_PreHanja, "Hangul_PreHanja", nullptr},
{Qt::Key_Hangul_PostHanja, "Hangul_PostHanja"}, {Qt::Key_Hangul_PostHanja, "Hangul_PostHanja", nullptr},
{Qt::Key_Hangul_Special, "Hangul_Special"}, {Qt::Key_Hangul_Special, "Hangul_Special", nullptr},
{Qt::Key_Dead_Grave, "Dead_Grave"}, {Qt::Key_Dead_Grave, "Dead_Grave", nullptr},
{Qt::Key_Dead_Acute, "Dead_Acute"}, {Qt::Key_Dead_Acute, "Dead_Acute", nullptr},
{Qt::Key_Dead_Circumflex, "Dead_Circumflex"}, {Qt::Key_Dead_Circumflex, "Dead_Circumflex", nullptr},
{Qt::Key_Dead_Tilde, "Dead_Tilde"}, {Qt::Key_Dead_Tilde, "Dead_Tilde", nullptr},
{Qt::Key_Dead_Macron, "Dead_Macron"}, {Qt::Key_Dead_Macron, "Dead_Macron", nullptr},
{Qt::Key_Dead_Breve, "Dead_Breve"}, {Qt::Key_Dead_Breve, "Dead_Breve", nullptr},
{Qt::Key_Dead_Abovedot, "Dead_Abovedot"}, {Qt::Key_Dead_Abovedot, "Dead_Abovedot", nullptr},
{Qt::Key_Dead_Diaeresis, "Dead_Diaeresis"}, {Qt::Key_Dead_Diaeresis, "Dead_Diaeresis", nullptr},
{Qt::Key_Dead_Abovering, "Dead_Abovering"}, {Qt::Key_Dead_Abovering, "Dead_Abovering", nullptr},
{Qt::Key_Dead_Doubleacute, "Dead_Doubleacute"}, {Qt::Key_Dead_Doubleacute, "Dead_Doubleacute", nullptr},
{Qt::Key_Dead_Caron, "Dead_Caron"}, {Qt::Key_Dead_Caron, "Dead_Caron", nullptr},
{Qt::Key_Dead_Cedilla, "Dead_Cedilla"}, {Qt::Key_Dead_Cedilla, "Dead_Cedilla", nullptr},
{Qt::Key_Dead_Ogonek, "Dead_Ogonek"}, {Qt::Key_Dead_Ogonek, "Dead_Ogonek", nullptr},
{Qt::Key_Dead_Iota, "Dead_Iota"}, {Qt::Key_Dead_Iota, "Dead_Iota", nullptr},
{Qt::Key_Dead_Voiced_Sound, "Dead_Voiced_Sound"}, {Qt::Key_Dead_Voiced_Sound, "Dead_Voiced_Sound", nullptr},
{Qt::Key_Dead_Semivoiced_Sound, "Dead_Semivoiced_Sound"}, {Qt::Key_Dead_Semivoiced_Sound, "Dead_Semivoiced_Sound", nullptr},
{Qt::Key_Dead_Belowdot, "Dead_Belowdot"}, {Qt::Key_Dead_Belowdot, "Dead_Belowdot", nullptr},
{Qt::Key_Dead_Hook, "Dead_Hook"}, {Qt::Key_Dead_Hook, "Dead_Hook", nullptr},
{Qt::Key_Dead_Horn, "Dead_Horn"}, {Qt::Key_Dead_Horn, "Dead_Horn", nullptr},
{Qt::Key_Back, "Back"}, {Qt::Key_Back, "Back", nullptr},
{Qt::Key_Forward, "Forward"}, {Qt::Key_Forward, "Forward", nullptr},
{Qt::Key_Stop, "Stop"}, {Qt::Key_Stop, "Stop", nullptr},
{Qt::Key_Refresh, "Refresh"}, {Qt::Key_Refresh, "Refresh", nullptr},
{Qt::Key_VolumeDown, "VolumeDown"}, {Qt::Key_VolumeDown, "VolumeDown", nullptr},
{Qt::Key_VolumeMute, "VolumeMute"}, {Qt::Key_VolumeMute, "VolumeMute", nullptr},
{Qt::Key_VolumeUp, "VolumeUp"}, {Qt::Key_VolumeUp, "VolumeUp", nullptr},
{Qt::Key_BassBoost, "BassBoost"}, {Qt::Key_BassBoost, "BassBoost", nullptr},
{Qt::Key_BassUp, "BassUp"}, {Qt::Key_BassUp, "BassUp", nullptr},
{Qt::Key_BassDown, "BassDown"}, {Qt::Key_BassDown, "BassDown", nullptr},
{Qt::Key_TrebleUp, "TrebleUp"}, {Qt::Key_TrebleUp, "TrebleUp", nullptr},
{Qt::Key_TrebleDown, "TrebleDown"}, {Qt::Key_TrebleDown, "TrebleDown", nullptr},
{Qt::Key_MediaPlay, "MediaPlay"}, {Qt::Key_MediaPlay, "MediaPlay", nullptr},
{Qt::Key_MediaStop, "MediaStop"}, {Qt::Key_MediaStop, "MediaStop", nullptr},
{Qt::Key_MediaPrevious, "MediaPrevious"}, {Qt::Key_MediaPrevious, "MediaPrevious", nullptr},
{Qt::Key_MediaNext, "MediaNext"}, {Qt::Key_MediaNext, "MediaNext", nullptr},
{Qt::Key_MediaRecord, "MediaRecord"}, {Qt::Key_MediaRecord, "MediaRecord", nullptr},
{Qt::Key_MediaPause, "MediaPause"}, {Qt::Key_MediaPause, "MediaPause", nullptr},
{Qt::Key_MediaTogglePlayPause, "MediaTogglePlayPause"}, {Qt::Key_MediaTogglePlayPause, "MediaTogglePlayPause", nullptr},
{Qt::Key_HomePage, "HomePage"}, {Qt::Key_HomePage, "HomePage", nullptr},
{Qt::Key_Favorites, "Favorites"}, {Qt::Key_Favorites, "Favorites", nullptr},
{Qt::Key_Search, "Search"}, {Qt::Key_Search, "Search", nullptr},
{Qt::Key_Standby, "Standby"}, {Qt::Key_Standby, "Standby", nullptr},
{Qt::Key_OpenUrl, "OpenUrl"}, {Qt::Key_OpenUrl, "OpenUrl", nullptr},
{Qt::Key_LaunchMail, "LaunchMail"}, {Qt::Key_LaunchMail, "LaunchMail", nullptr},
{Qt::Key_LaunchMedia, "LaunchMedia"}, {Qt::Key_LaunchMedia, "LaunchMedia", nullptr},
{Qt::Key_Launch0, "Launch0"}, {Qt::Key_Launch0, "Launch0", nullptr},
{Qt::Key_Launch1, "Launch1"}, {Qt::Key_Launch1, "Launch1", nullptr},
{Qt::Key_Launch2, "Launch2"}, {Qt::Key_Launch2, "Launch2", nullptr},
{Qt::Key_Launch3, "Launch3"}, {Qt::Key_Launch3, "Launch3", nullptr},
{Qt::Key_Launch4, "Launch4"}, {Qt::Key_Launch4, "Launch4", nullptr},
{Qt::Key_Launch5, "Launch5"}, {Qt::Key_Launch5, "Launch5", nullptr},
{Qt::Key_Launch6, "Launch6"}, {Qt::Key_Launch6, "Launch6", nullptr},
{Qt::Key_Launch7, "Launch7"}, {Qt::Key_Launch7, "Launch7", nullptr},
{Qt::Key_Launch8, "Launch8"}, {Qt::Key_Launch8, "Launch8", nullptr},
{Qt::Key_Launch9, "Launch9"}, {Qt::Key_Launch9, "Launch9", nullptr},
{Qt::Key_LaunchA, "LaunchA"}, {Qt::Key_LaunchA, "LaunchA", nullptr},
{Qt::Key_LaunchB, "LaunchB"}, {Qt::Key_LaunchB, "LaunchB", nullptr},
{Qt::Key_LaunchC, "LaunchC"}, {Qt::Key_LaunchC, "LaunchC", nullptr},
{Qt::Key_LaunchD, "LaunchD"}, {Qt::Key_LaunchD, "LaunchD", nullptr},
{Qt::Key_LaunchE, "LaunchE"}, {Qt::Key_LaunchE, "LaunchE", nullptr},
{Qt::Key_LaunchF, "LaunchF"}, {Qt::Key_LaunchF, "LaunchF", nullptr},
{Qt::Key_MonBrightnessUp, "MonBrightnessUp"}, {Qt::Key_MonBrightnessUp, "MonBrightnessUp", nullptr},
{Qt::Key_MonBrightnessDown, "MonBrightnessDown"}, {Qt::Key_MonBrightnessDown, "MonBrightnessDown", nullptr},
{Qt::Key_KeyboardLightOnOff, "KeyboardLightOnOff"}, {Qt::Key_KeyboardLightOnOff, "KeyboardLightOnOff", nullptr},
{Qt::Key_KeyboardBrightnessUp, "KeyboardBrightnessUp"}, {Qt::Key_KeyboardBrightnessUp, "KeyboardBrightnessUp", nullptr},
{Qt::Key_KeyboardBrightnessDown, "KeyboardBrightnessDown"}, {Qt::Key_KeyboardBrightnessDown, "KeyboardBrightnessDown", nullptr},
{Qt::Key_PowerOff, "PowerOff"}, {Qt::Key_PowerOff, "PowerOff", nullptr},
{Qt::Key_WakeUp, "WakeUp"}, {Qt::Key_WakeUp, "WakeUp", nullptr},
{Qt::Key_Eject, "Eject"}, {Qt::Key_Eject, "Eject", nullptr},
{Qt::Key_ScreenSaver, "ScreenSaver"}, {Qt::Key_ScreenSaver, "ScreenSaver", nullptr},
{Qt::Key_WWW, "WWW"}, {Qt::Key_WWW, "WWW", nullptr},
{Qt::Key_Memo, "Memo"}, {Qt::Key_Memo, "Memo", nullptr},
{Qt::Key_LightBulb, "LightBulb"}, {Qt::Key_LightBulb, "LightBulb", nullptr},
{Qt::Key_Shop, "Shop"}, {Qt::Key_Shop, "Shop", nullptr},
{Qt::Key_History, "History"}, {Qt::Key_History, "History", nullptr},
{Qt::Key_AddFavorite, "AddFavorite"}, {Qt::Key_AddFavorite, "AddFavorite", nullptr},
{Qt::Key_HotLinks, "HotLinks"}, {Qt::Key_HotLinks, "HotLinks", nullptr},
{Qt::Key_BrightnessAdjust, "BrightnessAdjust"}, {Qt::Key_BrightnessAdjust, "BrightnessAdjust", nullptr},
{Qt::Key_Finance, "Finance"}, {Qt::Key_Finance, "Finance", nullptr},
{Qt::Key_Community, "Community"}, {Qt::Key_Community, "Community", nullptr},
{Qt::Key_AudioRewind, "AudioRewind"}, {Qt::Key_AudioRewind, "AudioRewind", nullptr},
{Qt::Key_BackForward, "BackForward"}, {Qt::Key_BackForward, "BackForward", nullptr},
{Qt::Key_ApplicationLeft, "ApplicationLeft"}, {Qt::Key_ApplicationLeft, "ApplicationLeft", nullptr},
{Qt::Key_ApplicationRight, "ApplicationRight"}, {Qt::Key_ApplicationRight, "ApplicationRight", nullptr},
{Qt::Key_Book, "Book"}, {Qt::Key_Book, "Book", nullptr},
{Qt::Key_CD, "CD"}, {Qt::Key_CD, "CD", nullptr},
{Qt::Key_Calculator, "Calculator"}, {Qt::Key_Calculator, "Calculator", nullptr},
{Qt::Key_ToDoList, "ToDoList"}, {Qt::Key_ToDoList, "ToDoList", nullptr},
{Qt::Key_ClearGrab, "ClearGrab"}, {Qt::Key_ClearGrab, "ClearGrab", nullptr},
{Qt::Key_Close, "Close"}, {Qt::Key_Close, "Close", nullptr},
{Qt::Key_Copy, "Copy"}, {Qt::Key_Copy, "Copy", nullptr},
{Qt::Key_Cut, "Cut"}, {Qt::Key_Cut, "Cut", nullptr},
{Qt::Key_Display, "Display"}, {Qt::Key_Display, "Display", nullptr},
{Qt::Key_DOS, "DOS"}, {Qt::Key_DOS, "DOS", nullptr},
{Qt::Key_Documents, "Documents"}, {Qt::Key_Documents, "Documents", nullptr},
{Qt::Key_Excel, "Excel"}, {Qt::Key_Excel, "Excel", nullptr},
{Qt::Key_Explorer, "Explorer"}, {Qt::Key_Explorer, "Explorer", nullptr},
{Qt::Key_Game, "Game"}, {Qt::Key_Game, "Game", nullptr},
{Qt::Key_Go, "Go"}, {Qt::Key_Go, "Go", nullptr},
{Qt::Key_iTouch, "iTouch"}, {Qt::Key_iTouch, "iTouch", nullptr},
{Qt::Key_LogOff, "LogOff"}, {Qt::Key_LogOff, "LogOff", nullptr},
{Qt::Key_Market, "Market"}, {Qt::Key_Market, "Market", nullptr},
{Qt::Key_Meeting, "Meeting"}, {Qt::Key_Meeting, "Meeting", nullptr},
{Qt::Key_MenuKB, "MenuKB"}, {Qt::Key_MenuKB, "MenuKB", nullptr},
{Qt::Key_MenuPB, "MenuPB"}, {Qt::Key_MenuPB, "MenuPB", nullptr},
{Qt::Key_MySites, "MySites"}, {Qt::Key_MySites, "MySites", nullptr},
{Qt::Key_News, "News"}, {Qt::Key_News, "News", nullptr},
{Qt::Key_OfficeHome, "OfficeHome"}, {Qt::Key_OfficeHome, "OfficeHome", nullptr},
{Qt::Key_Option, "Option"}, {Qt::Key_Option, "Option", nullptr},
{Qt::Key_Paste, "Paste"}, {Qt::Key_Paste, "Paste", nullptr},
{Qt::Key_Phone, "Phone"}, {Qt::Key_Phone, "Phone", nullptr},
{Qt::Key_Calendar, "Calendar"}, {Qt::Key_Calendar, "Calendar", nullptr},
{Qt::Key_Reply, "Reply"}, {Qt::Key_Reply, "Reply", nullptr},
{Qt::Key_Reload, "Reload"}, {Qt::Key_Reload, "Reload", nullptr},
{Qt::Key_RotateWindows, "RotateWindows"}, {Qt::Key_RotateWindows, "RotateWindows", nullptr},
{Qt::Key_RotationPB, "RotationPB"}, {Qt::Key_RotationPB, "RotationPB", nullptr},
{Qt::Key_RotationKB, "RotationKB"}, {Qt::Key_RotationKB, "RotationKB", nullptr},
{Qt::Key_Save, "Save"}, {Qt::Key_Save, "Save", nullptr},
{Qt::Key_Send, "Send"}, {Qt::Key_Send, "Send", nullptr},
{Qt::Key_Spell, "Spell"}, {Qt::Key_Spell, "Spell", nullptr},
{Qt::Key_SplitScreen, "SplitScreen"}, {Qt::Key_SplitScreen, "SplitScreen", nullptr},
{Qt::Key_Support, "Support"}, {Qt::Key_Support, "Support", nullptr},
{Qt::Key_TaskPane, "TaskPane"}, {Qt::Key_TaskPane, "TaskPane", nullptr},
{Qt::Key_Terminal, "Terminal"}, {Qt::Key_Terminal, "Terminal", nullptr},
{Qt::Key_Tools, "Tools"}, {Qt::Key_Tools, "Tools", nullptr},
{Qt::Key_Travel, "Travel"}, {Qt::Key_Travel, "Travel", nullptr},
{Qt::Key_Video, "Video"}, {Qt::Key_Video, "Video", nullptr},
{Qt::Key_Word, "Word"}, {Qt::Key_Word, "Word", nullptr},
{Qt::Key_Xfer, "Xfer"}, {Qt::Key_Xfer, "Xfer", nullptr},
{Qt::Key_ZoomIn, "ZoomIn"}, {Qt::Key_ZoomIn, "ZoomIn", nullptr},
{Qt::Key_ZoomOut, "ZoomOut"}, {Qt::Key_ZoomOut, "ZoomOut", nullptr},
{Qt::Key_Away, "Away"}, {Qt::Key_Away, "Away", nullptr},
{Qt::Key_Messenger, "Messenger"}, {Qt::Key_Messenger, "Messenger", nullptr},
{Qt::Key_WebCam, "WebCam"}, {Qt::Key_WebCam, "WebCam", nullptr},
{Qt::Key_MailForward, "MailForward"}, {Qt::Key_MailForward, "MailForward", nullptr},
{Qt::Key_Pictures, "Pictures"}, {Qt::Key_Pictures, "Pictures", nullptr},
{Qt::Key_Music, "Music"}, {Qt::Key_Music, "Music", nullptr},
{Qt::Key_Battery, "Battery"}, {Qt::Key_Battery, "Battery", nullptr},
{Qt::Key_Bluetooth, "Bluetooth"}, {Qt::Key_Bluetooth, "Bluetooth", nullptr},
{Qt::Key_WLAN, "WLAN"}, {Qt::Key_WLAN, "WLAN", nullptr},
{Qt::Key_UWB, "UWB"}, {Qt::Key_UWB, "UWB", nullptr},
{Qt::Key_AudioForward, "AudioForward"}, {Qt::Key_AudioForward, "AudioForward", nullptr},
{Qt::Key_AudioRepeat, "AudioRepeat"}, {Qt::Key_AudioRepeat, "AudioRepeat", nullptr},
{Qt::Key_AudioRandomPlay, "AudioRandomPlay"}, {Qt::Key_AudioRandomPlay, "AudioRandomPlay", nullptr},
{Qt::Key_Subtitle, "Subtitle"}, {Qt::Key_Subtitle, "Subtitle", nullptr},
{Qt::Key_AudioCycleTrack, "AudioCycleTrack"}, {Qt::Key_AudioCycleTrack, "AudioCycleTrack", nullptr},
{Qt::Key_Time, "Time"}, {Qt::Key_Time, "Time", nullptr},
{Qt::Key_Hibernate, "Hibernate"}, {Qt::Key_Hibernate, "Hibernate", nullptr},
{Qt::Key_View, "View"}, {Qt::Key_View, "View", nullptr},
{Qt::Key_TopMenu, "TopMenu"}, {Qt::Key_TopMenu, "TopMenu", nullptr},
{Qt::Key_PowerDown, "PowerDown"}, {Qt::Key_PowerDown, "PowerDown", nullptr},
{Qt::Key_Suspend, "Suspend"}, {Qt::Key_Suspend, "Suspend", nullptr},
{Qt::Key_ContrastAdjust, "ContrastAdjust"}, {Qt::Key_ContrastAdjust, "ContrastAdjust", nullptr},
{Qt::Key_LaunchG, "LaunchG"}, {Qt::Key_LaunchG, "LaunchG", nullptr},
{Qt::Key_LaunchH, "LaunchH"}, {Qt::Key_LaunchH, "LaunchH", nullptr},
{Qt::Key_TouchpadToggle, "TouchpadToggle"}, {Qt::Key_TouchpadToggle, "TouchpadToggle", nullptr},
{Qt::Key_TouchpadOn, "TouchpadOn"}, {Qt::Key_TouchpadOn, "TouchpadOn", nullptr},
{Qt::Key_TouchpadOff, "TouchpadOff"}, {Qt::Key_TouchpadOff, "TouchpadOff", nullptr},
{Qt::Key_MicMute, "MicMute"}, {Qt::Key_MicMute, "MicMute", nullptr},
{Qt::Key_Red, "Red"}, {Qt::Key_Red, "Red", nullptr},
{Qt::Key_Green, "Green"}, {Qt::Key_Green, "Green", nullptr},
{Qt::Key_Yellow, "Yellow"}, {Qt::Key_Yellow, "Yellow", nullptr},
{Qt::Key_Blue, "Blue"}, {Qt::Key_Blue, "Blue", nullptr},
{Qt::Key_ChannelUp, "ChannelUp"}, {Qt::Key_ChannelUp, "ChannelUp", nullptr},
{Qt::Key_ChannelDown, "ChannelDown"}, {Qt::Key_ChannelDown, "ChannelDown", nullptr},
{Qt::Key_Guide, "Guide"}, {Qt::Key_Guide, "Guide", nullptr},
{Qt::Key_Info, "Info"}, {Qt::Key_Info, "Info", nullptr},
{Qt::Key_Settings, "Settings"}, {Qt::Key_Settings, "Settings", nullptr},
{Qt::Key_MicVolumeUp, "MicVolumeUp"}, {Qt::Key_MicVolumeUp, "MicVolumeUp", nullptr},
{Qt::Key_MicVolumeDown, "MicVolumeDown"}, {Qt::Key_MicVolumeDown, "MicVolumeDown", nullptr},
{Qt::Key_New, "New"}, {Qt::Key_New, "New", nullptr},
{Qt::Key_Open, "Open"}, {Qt::Key_Open, "Open", nullptr},
{Qt::Key_Find, "Find"}, {Qt::Key_Find, "Find", nullptr},
{Qt::Key_Undo, "Undo"}, {Qt::Key_Undo, "Undo", nullptr},
{Qt::Key_Redo, "Redo"}, {Qt::Key_Redo, "Redo", nullptr},
{Qt::Key_MediaLast, "MediaLast"}, {Qt::Key_MediaLast, "MediaLast", nullptr},
{Qt::Key_Select, "Select"}, {Qt::Key_Select, "Select", nullptr},
{Qt::Key_Yes, "Yes"}, {Qt::Key_Yes, "Yes", nullptr},
{Qt::Key_No, "No"}, {Qt::Key_No, "No", nullptr},
{Qt::Key_Cancel, "Cancel"}, {Qt::Key_Cancel, "Cancel", nullptr},
{Qt::Key_Printer, "Printer"}, {Qt::Key_Printer, "Printer", nullptr},
{Qt::Key_Execute, "Execute"}, {Qt::Key_Execute, "Execute", nullptr},
{Qt::Key_Sleep, "Sleep"}, {Qt::Key_Sleep, "Sleep", nullptr},
{Qt::Key_Play, "Play"}, {Qt::Key_Play, "Play", nullptr},
{Qt::Key_Zoom, "Zoom"}, {Qt::Key_Zoom, "Zoom", nullptr},
{Qt::Key_Exit, "Exit"}, {Qt::Key_Exit, "Exit", nullptr},
{Qt::Key_Context1, "Context1"}, {Qt::Key_Context1, "Context1", nullptr},
{Qt::Key_Context2, "Context2"}, {Qt::Key_Context2, "Context2", nullptr},
{Qt::Key_Context3, "Context3"}, {Qt::Key_Context3, "Context3", nullptr},
{Qt::Key_Context4, "Context4"}, {Qt::Key_Context4, "Context4", nullptr},
{Qt::Key_Call, "Call"}, {Qt::Key_Call, "Call", nullptr},
{Qt::Key_Hangup, "Hangup"}, {Qt::Key_Hangup, "Hangup", nullptr},
{Qt::Key_Flip, "Flip"}, {Qt::Key_Flip, "Flip", nullptr},
{Qt::Key_ToggleCallHangup, "ToggleCallHangup"}, {Qt::Key_ToggleCallHangup, "ToggleCallHangup", nullptr},
{Qt::Key_VoiceDial, "VoiceDial"}, {Qt::Key_VoiceDial, "VoiceDial", nullptr},
{Qt::Key_LastNumberRedial, "LastNumberRedial"}, {Qt::Key_LastNumberRedial, "LastNumberRedial", nullptr},
{Qt::Key_Camera, "Camera"}, {Qt::Key_Camera, "Camera", nullptr},
{Qt::Key_CameraFocus, "CameraFocus"}}; {Qt::Key_CameraFocus, "CameraFocus", nullptr}};
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str) std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
{ {
@ -497,6 +500,21 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
return ret; return ret;
} }
const char* InputManager::ConvertHostKeyboardCodeToIcon(u32 code)
{
if (code & Qt::KeyboardModifierMask)
return nullptr;
const u32 masked_code = (code & ~Qt::KeyboardModifierMask);
for (const KeyCodeName& name : s_qt_key_names)
{
if (static_cast<int>(masked_code) == name.code)
return name.icon_name;
}
return nullptr;
}
u32 QtUtils::KeyEventToCode(const QKeyEvent* ev) u32 QtUtils::KeyEventToCode(const QKeyEvent* ev)
{ {
return static_cast<u32>(ev->key()) | (static_cast<u32>(ev->modifiers()) & static_cast<u32>(Qt::KeypadModifier)); return static_cast<u32>(ev->key()) | (static_cast<u32>(ev->modifiers()) & static_cast<u32>(Qt::KeypadModifier));

View File

@ -363,6 +363,11 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
return std::nullopt; return std::nullopt;
} }
const char* InputManager::ConvertHostKeyboardCodeToIcon(u32 code)
{
return nullptr;
}
void Host::AddFixedInputBindings(SettingsInterface& si) void Host::AddFixedInputBindings(SettingsInterface& si)
{ {
// noop // noop

View File

@ -398,9 +398,9 @@ std::optional<InputBindingKey> DInputSource::ParseKeyString(const std::string_vi
return std::nullopt; return std::nullopt;
} }
std::string DInputSource::ConvertKeyToString(InputBindingKey key) TinyString DInputSource::ConvertKeyToString(InputBindingKey key)
{ {
std::string ret; TinyString ret;
if (key.source_type == InputSourceType::DInput) if (key.source_type == InputSourceType::DInput)
{ {
@ -408,23 +408,28 @@ std::string DInputSource::ConvertKeyToString(InputBindingKey key)
{ {
const char* modifier = const char* modifier =
(key.modifier == InputModifier::FullAxis ? "Full" : (key.modifier == InputModifier::Negate ? "-" : "+")); (key.modifier == InputModifier::FullAxis ? "Full" : (key.modifier == InputModifier::Negate ? "-" : "+"));
ret = fmt::format("DInput-{}/{}Axis{}{}", u32(key.source_index), modifier, u32(key.data), key.invert ? "~" : ""); ret.fmt("DInput-{}/{}Axis{}{}", u32(key.source_index), modifier, u32(key.data), key.invert ? "~" : "");
} }
else if (key.source_subtype == InputSubclass::ControllerButton && key.data >= MAX_NUM_BUTTONS) else if (key.source_subtype == InputSubclass::ControllerButton && key.data >= MAX_NUM_BUTTONS)
{ {
const u32 hat_num = (key.data - MAX_NUM_BUTTONS) / NUM_HAT_DIRECTIONS; const u32 hat_num = (key.data - MAX_NUM_BUTTONS) / NUM_HAT_DIRECTIONS;
const u32 hat_dir = (key.data - MAX_NUM_BUTTONS) % NUM_HAT_DIRECTIONS; const u32 hat_dir = (key.data - MAX_NUM_BUTTONS) % NUM_HAT_DIRECTIONS;
ret = fmt::format("DInput-{}/Hat{}{}", u32(key.source_index), hat_num, s_hat_directions[hat_dir]); ret.fmt("DInput-{}/Hat{}{}", u32(key.source_index), hat_num, s_hat_directions[hat_dir]);
} }
else if (key.source_subtype == InputSubclass::ControllerButton) else if (key.source_subtype == InputSubclass::ControllerButton)
{ {
ret = fmt::format("DInput-{}/Button{}", u32(key.source_index), u32(key.data)); ret.fmt("DInput-{}/Button{}", u32(key.source_index), u32(key.data));
} }
} }
return ret; return ret;
} }
TinyString DInputSource::ConvertKeyToIcon(InputBindingKey key)
{
return {};
}
void DInputSource::CheckForStateChanges(size_t index, const DIJOYSTATE& new_state) void DInputSource::CheckForStateChanges(size_t index, const DIJOYSTATE& new_state)
{ {
ControllerData& cd = m_controllers[index]; ControllerData& cd = m_controllers[index];

View File

@ -48,7 +48,8 @@ public:
std::optional<InputBindingKey> ParseKeyString(const std::string_view& device, std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) override; const std::string_view& binding) override;
std::string ConvertKeyToString(InputBindingKey key) override; TinyString ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToIcon(InputBindingKey key) override;
private: private:
template<typename T> template<typename T>

View File

@ -554,7 +554,11 @@ bool ImGuiManager::AddIconFonts(float size)
0xf545, 0xf545, 0xf547, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5aa, 0xf5aa, 0xf5e7, 0xf5e7, 0xf545, 0xf545, 0xf547, 0xf548, 0xf552, 0xf552, 0xf57a, 0xf57a, 0xf5a2, 0xf5a2, 0xf5aa, 0xf5aa, 0xf5e7, 0xf5e7,
0xf65d, 0xf65e, 0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf84c, 0xf84c, 0xf65d, 0xf65e, 0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf84c, 0xf84c,
0xf8cc, 0xf8cc, 0x0, 0x0}; 0xf8cc, 0xf8cc, 0x0, 0x0};
static constexpr ImWchar range_pf[] = { 0x2196,0x2199,0x219e,0x21a1,0x21b0,0x21b3,0x21ba,0x21c3,0x21c7,0x21ca,0x21d0,0x21d4,0x21e0,0x21e3,0x21ed,0x21ee,0x21f7,0x21f8,0x220b,0x220b,0x227a,0x227d,0x23ce,0x23ce,0x23f4,0x23f7,0x2427,0x243a,0x243c,0x243c,0x243e,0x243e,0x2460,0x246b,0x24f5,0x24fd,0x24ff,0x24ff,0x278a,0x278b,0x27fc,0x27fc,0xff21,0xff3a,0x0,0x0 }; static constexpr ImWchar range_pf[] = {0x2196, 0x2199, 0x219e, 0x21a1, 0x21b0, 0x21b3, 0x21ba, 0x21c3, 0x21c7, 0x21ca,
0x21d0, 0x21d4, 0x21dc, 0x21dd, 0x21e0, 0x21e3, 0x21ed, 0x21ee, 0x21f7, 0x21f8,
0x21fa, 0x21fb, 0x227a, 0x227d, 0x23f4, 0x23f7, 0x2427, 0x243a, 0x243c, 0x243c,
0x243e, 0x243e, 0x2460, 0x246b, 0x24f5, 0x24fd, 0x24ff, 0x24ff, 0x278a, 0x278e,
0x27fc, 0x27fc, 0xe001, 0xe001, 0xff21, 0xff3a, 0x0, 0x0};
{ {
ImFontConfig cfg; ImFontConfig cfg;

View File

@ -14,6 +14,8 @@
#include "imgui_manager.h" #include "imgui_manager.h"
#include "input_source.h" #include "input_source.h"
#include "IconsPromptFont.h"
#include "fmt/core.h" #include "fmt/core.h"
#include <array> #include <array>
@ -105,6 +107,7 @@ static std::optional<InputBindingKey> ParseSensorKey(const std::string_view& sou
static std::vector<std::string_view> SplitChord(const std::string_view& binding); static std::vector<std::string_view> SplitChord(const std::string_view& binding);
static bool SplitBinding(const std::string_view& binding, std::string_view* source, std::string_view* sub_binding); static bool SplitBinding(const std::string_view& binding, std::string_view* source, std::string_view* sub_binding);
static void PrettifyInputBindingPart(const std::string_view binding, SmallString& ret, bool& changed);
static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler); static void AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler);
static bool IsAxisHandler(const InputEventHandler& handler); static bool IsAxisHandler(const InputEventHandler& handler);
@ -333,7 +336,7 @@ std::string InputManager::ConvertInputBindingKeyToString(InputBindingInfo::Type
} }
else if (key.source_type < InputSourceType::Count && s_input_sources[static_cast<u32>(key.source_type)]) else if (key.source_type < InputSourceType::Count && s_input_sources[static_cast<u32>(key.source_type)])
{ {
return s_input_sources[static_cast<u32>(key.source_type)]->ConvertKeyToString(key); return std::string(s_input_sources[static_cast<u32>(key.source_type)]->ConvertKeyToString(key));
} }
} }
@ -367,6 +370,116 @@ std::string InputManager::ConvertInputBindingKeysToString(InputBindingInfo::Type
return ss.str(); return ss.str();
} }
bool InputManager::PrettifyInputBinding(std::string& binding)
{
if (binding.empty())
return false;
const std::string_view binding_view(binding);
SmallString ret;
bool changed = false;
std::string_view::size_type last = 0;
std::string_view::size_type next;
while ((next = binding_view.find('&', last)) != std::string_view::npos)
{
if (last != next)
{
const std::string_view part = StringUtil::StripWhitespace(binding_view.substr(last, next - last));
if (!part.empty())
{
if (!ret.empty())
ret.append(" + ");
PrettifyInputBindingPart(part, ret, changed);
}
}
last = next + 1;
}
if (last < (binding_view.size() - 1))
{
const std::string_view part = StringUtil::StripWhitespace(binding_view.substr(last));
if (!part.empty())
{
if (!ret.empty())
ret.append(" + ");
PrettifyInputBindingPart(part, ret, changed);
}
}
if (changed)
binding = ret.view();
return changed;
}
void InputManager::PrettifyInputBindingPart(const std::string_view binding, SmallString& ret, bool& changed)
{
std::string_view source, sub_binding;
if (!SplitBinding(binding, &source, &sub_binding))
return;
// lameee, string matching
if (StringUtil::StartsWith(source, "Keyboard"))
{
std::optional<InputBindingKey> key = ParseHostKeyboardKey(source, sub_binding);
const char* icon = key.has_value() ? ConvertHostKeyboardCodeToIcon(key->data) : nullptr;
if (icon)
{
ret.append(icon);
changed = true;
return;
}
}
else if (StringUtil::StartsWith(source, "Pointer"))
{
const std::optional<InputBindingKey> key = ParsePointerKey(source, sub_binding);
if (key.has_value())
{
if (key->source_subtype == InputSubclass::PointerButton)
{
static constexpr const char* button_icons[] = {
ICON_PF_MOUSE_BUTTON_1, ICON_PF_MOUSE_BUTTON_2, ICON_PF_MOUSE_BUTTON_3,
ICON_PF_MOUSE_BUTTON_4, ICON_PF_MOUSE_BUTTON_5,
};
if (key->data < std::size(button_icons))
{
ret.append(button_icons[key->data]);
changed = true;
return;
}
}
}
}
else if (StringUtil::StartsWith(source, "Sensor"))
{
}
else
{
for (u32 i = FIRST_EXTERNAL_INPUT_SOURCE; i < LAST_EXTERNAL_INPUT_SOURCE; i++)
{
if (s_input_sources[i])
{
std::optional<InputBindingKey> key = s_input_sources[i]->ParseKeyString(source, sub_binding);
if (key.has_value())
{
const TinyString icon = s_input_sources[i]->ConvertKeyToIcon(key.value());
if (!icon.empty())
{
ret.append(icon);
changed = true;
return;
}
break;
}
}
}
}
ret.append(binding);
}
void InputManager::AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler) void InputManager::AddBindings(const std::vector<std::string>& bindings, const InputEventHandler& handler)
{ {
for (const std::string& binding : bindings) for (const std::string& binding : bindings)

View File

@ -207,6 +207,9 @@ std::optional<u32> ConvertHostKeyboardStringToCode(const std::string_view& str);
/// Converts a key code from an identifier to a human-readable string. /// Converts a key code from an identifier to a human-readable string.
std::optional<std::string> ConvertHostKeyboardCodeToString(u32 code); std::optional<std::string> ConvertHostKeyboardCodeToString(u32 code);
/// Converts a key code from an identifier to an icon which can be drawn.
const char* ConvertHostKeyboardCodeToIcon(u32 code);
/// Creates a key for a host-specific key code. /// Creates a key for a host-specific key code.
InputBindingKey MakeHostKeyboardKey(u32 key_code); InputBindingKey MakeHostKeyboardKey(u32 key_code);
@ -230,6 +233,9 @@ std::string ConvertInputBindingKeyToString(InputBindingInfo::Type binding_type,
std::string ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type, const InputBindingKey* keys, std::string ConvertInputBindingKeysToString(InputBindingInfo::Type binding_type, const InputBindingKey* keys,
size_t num_keys); size_t num_keys);
/// Represents a binding with icon fonts, if available.
bool PrettifyInputBinding(std::string& binding);
/// Returns a list of all hotkeys. /// Returns a list of all hotkeys.
std::vector<const HotkeyInfo*> GetHotkeyList(); std::vector<const HotkeyInfo*> GetHotkeyList();

View File

@ -10,6 +10,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "common/small_string.h"
#include "common/types.h" #include "common/types.h"
#include "input_manager.h" #include "input_manager.h"
@ -30,7 +31,8 @@ public:
virtual std::optional<InputBindingKey> ParseKeyString(const std::string_view& device, virtual std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) = 0; const std::string_view& binding) = 0;
virtual std::string ConvertKeyToString(InputBindingKey key) = 0; virtual TinyString ConvertKeyToString(InputBindingKey key) = 0;
virtual TinyString ConvertKeyToIcon(InputBindingKey key) = 0;
/// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name. /// Enumerates available devices. Returns a pair of the prefix (e.g. SDL-0) and the device name.
virtual std::vector<std::pair<std::string, std::string>> EnumerateDevices() = 0; virtual std::vector<std::pair<std::string, std::string>> EnumerateDevices() = 0;

View File

@ -14,6 +14,8 @@
#include "common/path.h" #include "common/path.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "IconsPromptFont.h"
#include <cmath> #include <cmath>
#ifdef __APPLE__ #ifdef __APPLE__
@ -32,6 +34,14 @@ static constexpr const char* s_sdl_axis_names[] = {
"LeftTrigger", // SDL_CONTROLLER_AXIS_TRIGGERLEFT "LeftTrigger", // SDL_CONTROLLER_AXIS_TRIGGERLEFT
"RightTrigger", // SDL_CONTROLLER_AXIS_TRIGGERRIGHT "RightTrigger", // SDL_CONTROLLER_AXIS_TRIGGERRIGHT
}; };
static constexpr const char* s_sdl_axis_icons[][2] = {
{ICON_PF_LEFT_ANALOG_LEFT, ICON_PF_LEFT_ANALOG_RIGHT}, // SDL_CONTROLLER_AXIS_LEFTX
{ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // SDL_CONTROLLER_AXIS_LEFTY
{ICON_PF_RIGHT_ANALOG_LEFT, ICON_PF_RIGHT_ANALOG_RIGHT}, // SDL_CONTROLLER_AXIS_RIGHTX
{ICON_PF_RIGHT_ANALOG_UP, ICON_PF_RIGHT_ANALOG_DOWN}, // SDL_CONTROLLER_AXIS_RIGHTY
{nullptr, ICON_PF_LEFT_TRIGGER_PULL}, // SDL_CONTROLLER_AXIS_TRIGGERLEFT
{nullptr, ICON_PF_RIGHT_TRIGGER_PULL}, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT
};
static constexpr const GenericInputBinding s_sdl_generic_binding_axis_mapping[][2] = { static constexpr const GenericInputBinding s_sdl_generic_binding_axis_mapping[][2] = {
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // SDL_CONTROLLER_AXIS_LEFTX {GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // SDL_CONTROLLER_AXIS_LEFTX
{GenericInputBinding::LeftStickUp, GenericInputBinding::LeftStickDown}, // SDL_CONTROLLER_AXIS_LEFTY {GenericInputBinding::LeftStickUp, GenericInputBinding::LeftStickDown}, // SDL_CONTROLLER_AXIS_LEFTY
@ -64,6 +74,23 @@ static constexpr const char* s_sdl_button_names[] = {
"Paddle4", // SDL_CONTROLLER_BUTTON_PADDLE4 "Paddle4", // SDL_CONTROLLER_BUTTON_PADDLE4
"Touchpad", // SDL_CONTROLLER_BUTTON_TOUCHPAD "Touchpad", // SDL_CONTROLLER_BUTTON_TOUCHPAD
}; };
static constexpr const char* s_sdl_button_icons[] = {
ICON_PF_BUTTON_A, // SDL_CONTROLLER_BUTTON_A
ICON_PF_BUTTON_B, // SDL_CONTROLLER_BUTTON_B
ICON_PF_BUTTON_X, // SDL_CONTROLLER_BUTTON_X
ICON_PF_BUTTON_Y, // SDL_CONTROLLER_BUTTON_Y
ICON_PF_SHARE_CAPTURE, // SDL_CONTROLLER_BUTTON_BACK
ICON_PF_XBOX, // SDL_CONTROLLER_BUTTON_GUIDE
ICON_PF_BURGER_MENU, // SDL_CONTROLLER_BUTTON_START
ICON_PF_LEFT_ANALOG_CLICK, // SDL_CONTROLLER_BUTTON_LEFTSTICK
ICON_PF_RIGHT_ANALOG_CLICK, // SDL_CONTROLLER_BUTTON_RIGHTSTICK
ICON_PF_LEFT_SHOULDER_LB, // SDL_CONTROLLER_BUTTON_LEFTSHOULDER
ICON_PF_RIGHT_SHOULDER_RB, // SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
ICON_PF_XBOX_DPAD_UP, // SDL_CONTROLLER_BUTTON_DPAD_UP
ICON_PF_XBOX_DPAD_DOWN, // SDL_CONTROLLER_BUTTON_DPAD_DOWN
ICON_PF_XBOX_DPAD_LEFT, // SDL_CONTROLLER_BUTTON_DPAD_LEFT
ICON_PF_XBOX_DPAD_RIGHT, // SDL_CONTROLLER_BUTTON_DPAD_RIGHT
};
static constexpr const GenericInputBinding s_sdl_generic_binding_button_mapping[] = { static constexpr const GenericInputBinding s_sdl_generic_binding_button_mapping[] = {
GenericInputBinding::Cross, // SDL_CONTROLLER_BUTTON_A GenericInputBinding::Cross, // SDL_CONTROLLER_BUTTON_A
GenericInputBinding::Circle, // SDL_CONTROLLER_BUTTON_B GenericInputBinding::Circle, // SDL_CONTROLLER_BUTTON_B
@ -416,9 +443,9 @@ std::optional<InputBindingKey> SDLInputSource::ParseKeyString(const std::string_
return std::nullopt; return std::nullopt;
} }
std::string SDLInputSource::ConvertKeyToString(InputBindingKey key) TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key)
{ {
std::string ret; TinyString ret;
if (key.source_type == InputSourceType::SDL) if (key.source_type == InputSourceType::SDL)
{ {
@ -428,40 +455,64 @@ std::string SDLInputSource::ConvertKeyToString(InputBindingKey key)
(key.modifier == InputModifier::FullAxis ? "Full" : (key.modifier == InputModifier::Negate ? "-" : "+")); (key.modifier == InputModifier::FullAxis ? "Full" : (key.modifier == InputModifier::Negate ? "-" : "+"));
if (key.data < std::size(s_sdl_axis_names)) if (key.data < std::size(s_sdl_axis_names))
{ {
ret = fmt::format("SDL-{}/{}{}", static_cast<u32>(key.source_index), modifier, s_sdl_axis_names[key.data]); ret.fmt("SDL-{}/{}{}", static_cast<u32>(key.source_index), modifier, s_sdl_axis_names[key.data]);
} }
else else
{ {
ret = fmt::format("SDL-{}/{}Axis{}{}", static_cast<u32>(key.source_index), modifier, ret.fmt("SDL-{}/{}Axis{}{}", static_cast<u32>(key.source_index), modifier,
key.data - static_cast<u32>(std::size(s_sdl_axis_names)), key.invert ? "~" : ""); key.data - static_cast<u32>(std::size(s_sdl_axis_names)), key.invert ? "~" : "");
} }
} }
else if (key.source_subtype == InputSubclass::ControllerButton) else if (key.source_subtype == InputSubclass::ControllerButton)
{ {
if (key.data < std::size(s_sdl_button_names)) if (key.data < std::size(s_sdl_button_names))
{ {
ret = fmt::format("SDL-{}/{}", static_cast<u32>(key.source_index), s_sdl_button_names[key.data]); ret.fmt("SDL-{}/{}", static_cast<u32>(key.source_index), s_sdl_button_names[key.data]);
} }
else else
{ {
ret = fmt::format("SDL-{}/Button{}", static_cast<u32>(key.source_index), ret.fmt("SDL-{}/Button{}", static_cast<u32>(key.source_index),
key.data - static_cast<u32>(std::size(s_sdl_button_names))); key.data - static_cast<u32>(std::size(s_sdl_button_names)));
} }
} }
else if (key.source_subtype == InputSubclass::ControllerHat) else if (key.source_subtype == InputSubclass::ControllerHat)
{ {
const u32 hat_index = key.data / static_cast<u32>(std::size(s_sdl_hat_direction_names)); const u32 hat_index = key.data / static_cast<u32>(std::size(s_sdl_hat_direction_names));
const u32 hat_direction = key.data % static_cast<u32>(std::size(s_sdl_hat_direction_names)); const u32 hat_direction = key.data % static_cast<u32>(std::size(s_sdl_hat_direction_names));
ret = fmt::format("SDL-{}/Hat{}{}", static_cast<u32>(key.source_index), hat_index, ret.fmt("SDL-{}/Hat{}{}", static_cast<u32>(key.source_index), hat_index,
s_sdl_hat_direction_names[hat_direction]); s_sdl_hat_direction_names[hat_direction]);
} }
else if (key.source_subtype == InputSubclass::ControllerMotor) else if (key.source_subtype == InputSubclass::ControllerMotor)
{ {
ret = fmt::format("SDL-{}/{}Motor", static_cast<u32>(key.source_index), key.data ? "Large" : "Small"); ret.fmt("SDL-{}/{}Motor", static_cast<u32>(key.source_index), key.data ? "Large" : "Small");
} }
else if (key.source_subtype == InputSubclass::ControllerHaptic) else if (key.source_subtype == InputSubclass::ControllerHaptic)
{ {
ret = fmt::format("SDL-{}/Haptic", static_cast<u32>(key.source_index)); ret.fmt("SDL-{}/Haptic", static_cast<u32>(key.source_index));
}
}
return ret;
}
TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
{
TinyString ret;
if (key.source_type == InputSourceType::SDL)
{
if (key.source_subtype == InputSubclass::ControllerAxis)
{
if (key.data < std::size(s_sdl_axis_icons) && key.modifier != InputModifier::FullAxis)
{
ret.fmt("SDL-{} {}", static_cast<u32>(key.source_index),
s_sdl_axis_icons[key.data][key.modifier == InputModifier::None]);
}
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
if (key.data < std::size(s_sdl_button_icons))
ret.fmt("SDL-{} {}", static_cast<u32>(key.source_index), s_sdl_button_icons[key.data]);
} }
} }

View File

@ -34,7 +34,8 @@ public:
std::optional<InputBindingKey> ParseKeyString(const std::string_view& device, std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) override; const std::string_view& binding) override;
std::string ConvertKeyToString(InputBindingKey key) override; TinyString ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToIcon(InputBindingKey key) override;
bool ProcessSDLEvent(const SDL_Event* event); bool ProcessSDLEvent(const SDL_Event* event);

View File

@ -89,7 +89,12 @@ std::optional<InputBindingKey> Win32RawInputSource::ParseKeyString(const std::st
return std::nullopt; return std::nullopt;
} }
std::string Win32RawInputSource::ConvertKeyToString(InputBindingKey key) TinyString Win32RawInputSource::ConvertKeyToString(InputBindingKey key)
{
return {};
}
TinyString Win32RawInputSource::ConvertKeyToIcon(InputBindingKey key)
{ {
return {}; return {};
} }

View File

@ -32,7 +32,8 @@ public:
std::optional<InputBindingKey> ParseKeyString(const std::string_view& device, std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) override; const std::string_view& binding) override;
std::string ConvertKeyToString(InputBindingKey key) override; TinyString ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToIcon(InputBindingKey key) override;
private: private:
struct MouseState struct MouseState

View File

@ -1,16 +1,20 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com> // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "xinput_source.h" #include "xinput_source.h"
#include "input_manager.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/log.h" #include "common/log.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/host.h"
#include "input_manager.h" #include "IconsPromptFont.h"
#include <cmath> #include <cmath>
Log_SetChannel(XInputSource); Log_SetChannel(XInputSource);
const char* XInputSource::s_axis_names[XInputSource::NUM_AXES] = { static const char* s_axis_names[XInputSource::NUM_AXES] = {
"LeftX", // AXIS_LEFTX "LeftX", // AXIS_LEFTX
"LeftY", // AXIS_LEFTY "LeftY", // AXIS_LEFTY
"RightX", // AXIS_RIGHTX "RightX", // AXIS_RIGHTX
@ -18,6 +22,14 @@ const char* XInputSource::s_axis_names[XInputSource::NUM_AXES] = {
"LeftTrigger", // AXIS_TRIGGERLEFT "LeftTrigger", // AXIS_TRIGGERLEFT
"RightTrigger", // AXIS_TRIGGERRIGHT "RightTrigger", // AXIS_TRIGGERRIGHT
}; };
static constexpr const char* s_axis_icons[][2] = {
{ICON_PF_LEFT_ANALOG_LEFT, ICON_PF_LEFT_ANALOG_RIGHT}, // AXIS_LEFTX
{ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // AXIS_LEFTY
{ICON_PF_RIGHT_ANALOG_LEFT, ICON_PF_RIGHT_ANALOG_RIGHT}, // AXIS_RIGHTX
{ICON_PF_RIGHT_ANALOG_UP, ICON_PF_RIGHT_ANALOG_DOWN}, // AXIS_RIGHTY
{nullptr, ICON_PF_LEFT_TRIGGER_PULL}, // AXIS_TRIGGERLEFT
{nullptr, ICON_PF_RIGHT_TRIGGER_PULL}, // AXIS_TRIGGERRIGHT
};
static const GenericInputBinding s_xinput_generic_binding_axis_mapping[][2] = { static const GenericInputBinding s_xinput_generic_binding_axis_mapping[][2] = {
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // AXIS_LEFTX {GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // AXIS_LEFTX
{GenericInputBinding::LeftStickUp, GenericInputBinding::LeftStickDown}, // AXIS_LEFTY {GenericInputBinding::LeftStickUp, GenericInputBinding::LeftStickDown}, // AXIS_LEFTY
@ -27,7 +39,7 @@ static const GenericInputBinding s_xinput_generic_binding_axis_mapping[][2] = {
{GenericInputBinding::Unknown, GenericInputBinding::R2}, // AXIS_TRIGGERRIGHT {GenericInputBinding::Unknown, GenericInputBinding::R2}, // AXIS_TRIGGERRIGHT
}; };
const char* XInputSource::s_button_names[XInputSource::NUM_BUTTONS] = { static const char* s_button_names[XInputSource::NUM_BUTTONS] = {
"DPadUp", // XINPUT_GAMEPAD_DPAD_UP "DPadUp", // XINPUT_GAMEPAD_DPAD_UP
"DPadDown", // XINPUT_GAMEPAD_DPAD_DOWN "DPadDown", // XINPUT_GAMEPAD_DPAD_DOWN
"DPadLeft", // XINPUT_GAMEPAD_DPAD_LEFT "DPadLeft", // XINPUT_GAMEPAD_DPAD_LEFT
@ -44,7 +56,7 @@ const char* XInputSource::s_button_names[XInputSource::NUM_BUTTONS] = {
"Y", // XINPUT_GAMEPAD_Y "Y", // XINPUT_GAMEPAD_Y
"Guide", // XINPUT_GAMEPAD_GUIDE "Guide", // XINPUT_GAMEPAD_GUIDE
}; };
const u16 XInputSource::s_button_masks[XInputSource::NUM_BUTTONS] = { static const u16 s_button_masks[XInputSource::NUM_BUTTONS] = {
XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_UP,
XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_LEFT,
@ -61,6 +73,23 @@ const u16 XInputSource::s_button_masks[XInputSource::NUM_BUTTONS] = {
XINPUT_GAMEPAD_Y, XINPUT_GAMEPAD_Y,
0x400, // XINPUT_GAMEPAD_GUIDE 0x400, // XINPUT_GAMEPAD_GUIDE
}; };
static constexpr const char* s_button_icons[] = {
ICON_PF_XBOX_DPAD_UP, // XINPUT_GAMEPAD_DPAD_UP
ICON_PF_XBOX_DPAD_DOWN, // XINPUT_GAMEPAD_DPAD_DOWN
ICON_PF_XBOX_DPAD_LEFT, // XINPUT_GAMEPAD_DPAD_LEFT
ICON_PF_XBOX_DPAD_RIGHT, // XINPUT_GAMEPAD_DPAD_RIGHT
ICON_PF_BURGER_MENU, // XINPUT_GAMEPAD_START
ICON_PF_SHARE_CAPTURE, // XINPUT_GAMEPAD_BACK
ICON_PF_LEFT_ANALOG_CLICK, // XINPUT_GAMEPAD_LEFT_THUMB
ICON_PF_RIGHT_ANALOG_CLICK, // XINPUT_GAMEPAD_RIGHT_THUMB
ICON_PF_LEFT_SHOULDER_LB, // XINPUT_GAMEPAD_LEFT_SHOULDER
ICON_PF_RIGHT_SHOULDER_RB, // XINPUT_GAMEPAD_RIGHT_SHOULDER
ICON_PF_BUTTON_A, // XINPUT_GAMEPAD_A
ICON_PF_BUTTON_B, // XINPUT_GAMEPAD_B
ICON_PF_BUTTON_X, // XINPUT_GAMEPAD_X
ICON_PF_BUTTON_Y, // XINPUT_GAMEPAD_Y
ICON_PF_XBOX, // XINPUT_GAMEPAD_GUIDE
};
static const GenericInputBinding s_xinput_generic_binding_button_mapping[] = { static const GenericInputBinding s_xinput_generic_binding_button_mapping[] = {
GenericInputBinding::DPadUp, // XINPUT_GAMEPAD_DPAD_UP GenericInputBinding::DPadUp, // XINPUT_GAMEPAD_DPAD_UP
GenericInputBinding::DPadDown, // XINPUT_GAMEPAD_DPAD_DOWN GenericInputBinding::DPadDown, // XINPUT_GAMEPAD_DPAD_DOWN
@ -287,24 +316,48 @@ std::optional<InputBindingKey> XInputSource::ParseKeyString(const std::string_vi
return std::nullopt; return std::nullopt;
} }
std::string XInputSource::ConvertKeyToString(InputBindingKey key) TinyString XInputSource::ConvertKeyToString(InputBindingKey key)
{ {
std::string ret; TinyString ret;
if (key.source_type == InputSourceType::XInput) if (key.source_type == InputSourceType::XInput)
{ {
if (key.source_subtype == InputSubclass::ControllerAxis && key.data < std::size(s_axis_names)) if (key.source_subtype == InputSubclass::ControllerAxis && key.data < std::size(s_axis_names))
{ {
const char modifier = key.modifier == InputModifier::Negate ? '-' : '+'; const char modifier = key.modifier == InputModifier::Negate ? '-' : '+';
ret = fmt::format("XInput-{}/{}{}", static_cast<u32>(key.source_index), modifier, s_axis_names[key.data]); ret.fmt("XInput-{}/{}{}", static_cast<u32>(key.source_index), modifier, s_axis_names[key.data]);
} }
else if (key.source_subtype == InputSubclass::ControllerButton && key.data < std::size(s_button_names)) else if (key.source_subtype == InputSubclass::ControllerButton && key.data < std::size(s_button_names))
{ {
ret = fmt::format("XInput-{}/{}", static_cast<u32>(key.source_index), s_button_names[key.data]); ret.fmt("XInput-{}/{}", static_cast<u32>(key.source_index), s_button_names[key.data]);
} }
else if (key.source_subtype == InputSubclass::ControllerMotor) else if (key.source_subtype == InputSubclass::ControllerMotor)
{ {
ret = fmt::format("XInput-{}/{}Motor", static_cast<u32>(key.source_index), key.data ? "Large" : "Small"); ret.fmt("XInput-{}/{}Motor", static_cast<u32>(key.source_index), key.data ? "Large" : "Small");
}
}
return ret;
}
TinyString XInputSource::ConvertKeyToIcon(InputBindingKey key)
{
TinyString ret;
if (key.source_type == InputSourceType::SDL)
{
if (key.source_subtype == InputSubclass::ControllerAxis)
{
if (key.data < std::size(s_axis_icons) && key.modifier != InputModifier::FullAxis)
{
ret.fmt("XInput-{} {}", static_cast<u32>(key.source_index),
s_axis_icons[key.data][key.modifier == InputModifier::None]);
}
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
if (key.data < std::size(s_button_icons))
ret.fmt("XInput-{} {}", static_cast<u32>(key.source_index), s_button_icons[key.data]);
} }
} }
@ -384,8 +437,7 @@ void XInputSource::HandleControllerConnection(u32 index)
cd.has_small_motor = caps.Vibration.wRightMotorSpeed != 0; cd.has_small_motor = caps.Vibration.wRightMotorSpeed != 0;
cd.last_state = {}; cd.last_state = {};
InputManager::OnInputDeviceConnected(fmt::format("XInput-{}", index), InputManager::OnInputDeviceConnected(fmt::format("XInput-{}", index), fmt::format("XInput Controller {}", index));
fmt::format("XInput Controller {}", index));
} }
void XInputSource::HandleControllerDisconnection(u32 index) void XInputSource::HandleControllerDisconnection(u32 index)

View File

@ -15,6 +15,23 @@ class SettingsInterface;
class XInputSource final : public InputSource class XInputSource final : public InputSource
{ {
public: public:
enum : u32
{
NUM_CONTROLLERS = XUSER_MAX_COUNT, // 4
NUM_BUTTONS = 15,
};
enum : u32
{
AXIS_LEFTX,
AXIS_LEFTY,
AXIS_RIGHTX,
AXIS_RIGHTY,
AXIS_LEFTTRIGGER,
AXIS_RIGHTTRIGGER,
NUM_AXES,
};
XInputSource(); XInputSource();
~XInputSource(); ~XInputSource();
@ -33,26 +50,10 @@ public:
std::optional<InputBindingKey> ParseKeyString(const std::string_view& device, std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) override; const std::string_view& binding) override;
std::string ConvertKeyToString(InputBindingKey key) override; TinyString ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToIcon(InputBindingKey key) override;
private: private:
enum : u32
{
NUM_CONTROLLERS = XUSER_MAX_COUNT, // 4
NUM_BUTTONS = 15,
};
enum : u32
{
AXIS_LEFTX,
AXIS_LEFTY,
AXIS_RIGHTX,
AXIS_RIGHTY,
AXIS_LEFTTRIGGER,
AXIS_RIGHTTRIGGER,
NUM_AXES,
};
struct ControllerData struct ControllerData
{ {
XINPUT_STATE last_state; XINPUT_STATE last_state;
@ -74,8 +75,4 @@ private:
DWORD(WINAPI* m_xinput_get_state)(DWORD, XINPUT_STATE*) = nullptr; DWORD(WINAPI* m_xinput_get_state)(DWORD, XINPUT_STATE*) = nullptr;
DWORD(WINAPI* m_xinput_set_state)(DWORD, XINPUT_VIBRATION*) = nullptr; DWORD(WINAPI* m_xinput_set_state)(DWORD, XINPUT_VIBRATION*) = nullptr;
DWORD(WINAPI* m_xinput_get_capabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*) = nullptr; DWORD(WINAPI* m_xinput_get_capabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*) = nullptr;
static const char* s_axis_names[NUM_AXES];
static const char* s_button_names[NUM_BUTTONS];
static const u16 s_button_masks[NUM_BUTTONS];
}; };