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)
return;
if (oneline)
InputManager::PrettifyInputBinding(value);
if (show_type)
{
if (icon_name)
@ -1375,17 +1378,17 @@ void FullscreenUI::DrawInputBindingButton(SettingsInterface* bsi, InputBindingIn
switch (type)
{
case InputBindingInfo::Type::Button:
title.fmt(ICON_FA_DOT_CIRCLE "{}", display_name);
title.fmt(ICON_FA_DOT_CIRCLE " {}", display_name);
break;
case InputBindingInfo::Type::Axis:
case InputBindingInfo::Type::HalfAxis:
title.fmt(ICON_FA_BULLSEYE "{}", display_name);
title.fmt(ICON_FA_BULLSEYE " {}", display_name);
break;
case InputBindingInfo::Type::Motor:
title.fmt(ICON_FA_BELL "{}", display_name);
title.fmt(ICON_FA_BELL " {}", display_name);
break;
case InputBindingInfo::Type::Macro:
title.fmt(ICON_FA_PIZZA_SLICE "{}", display_name);
title.fmt(ICON_FA_PIZZA_SLICE " {}", display_name);
break;
default:
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,
ImVec2(0.0f, 0.0f), &title_bb);
ImGui::RenderTextClipped(bb.Min, bb.Max, value.empty() ? FSUI_CSTR("-") : value.c_str(), nullptr,
&value_size, ImVec2(1.0f, 0.5f), &bb);
ImGui::RenderTextClipped(bb.Min, bb.Max, value.empty() ? FSUI_CSTR("-") : value.c_str(), nullptr, &value_size,
ImVec2(1.0f, 0.5f), &bb);
ImGui::PopFont();
}
else
@ -3407,9 +3410,27 @@ void FullscreenUI::DrawControllerSettingsPage()
std::string binds_string(
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),
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));
ImGuiFullscreen::ChoiceDialogOptions options;
@ -3476,10 +3497,10 @@ void FullscreenUI::DrawControllerSettingsPage()
s32 frequency = bsi->GetIntValue(section.c_str(), freq_key.c_str(), 0);
SmallString freq_summary;
if (frequency == 0)
freq_summary = FSUI_VSTR("Macro will not auto-toggle.");
freq_summary = FSUI_VSTR("Disabled");
else
freq_summary.fmt(FSUI_FSTR("Macro will toggle every {} frames."), frequency);
if (MenuButton(freq_title, freq_summary))
freq_summary.fmt(FSUI_FSTR("{} Frames"), frequency);
if (MenuButtonWithValue(freq_title, nullptr, freq_summary, true, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY))
ImGui::OpenPopup(freq_title);
ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f));
@ -6727,6 +6748,7 @@ void FullscreenUI::ProgressCallback::SetCancelled()
#if 0
// 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", "-");
TRANSLATE_NOOP("FullscreenUI", "1 Frame");
TRANSLATE_NOOP("FullscreenUI", "10 Frames");
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 debug console where supported.");
TRANSLATE_NOOP("FullscreenUI", "Logs out of RetroAchievements.");
TRANSLATE_NOOP("FullscreenUI", "Macro will toggle every {} frames.");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Buttons");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Frequency");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Trigger");
@ -7081,7 +7102,6 @@ TRANSLATE_NOOP("FullscreenUI", "Mute All Sound");
TRANSLATE_NOOP("FullscreenUI", "Mute CD Audio");
TRANSLATE_NOOP("FullscreenUI", "No");
TRANSLATE_NOOP("FullscreenUI", "No Binding");
TRANSLATE_NOOP("FullscreenUI", "No Buttons Selected");
TRANSLATE_NOOP("FullscreenUI", "No Game Selected");
TRANSLATE_NOOP("FullscreenUI", "No cheats found for {}.");
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", "\"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", "{} Frames");
TRANSLATE_NOOP("FullscreenUI", "{} deleted.");
TRANSLATE_NOOP("FullscreenUI", "{} does not exist.");
TRANSLATE_NOOP("FullscreenUI", "{} is not a valid disc image.");

View file

@ -615,7 +615,7 @@ void ImGuiManager::DrawInputsOverlay()
continue;
if (cinfo->icon_name)
text.append_fmt("{} {} |", cinfo->icon_name, port + 1u);
text.append_fmt("{} {}", cinfo->icon_name, port + 1u);
else
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);
}
const char* InputManager::ConvertHostKeyboardCodeToIcon(u32 code)
{
return nullptr;
}
BEGIN_HOTKEY_LIST(g_host_hotkeys)
END_HOTKEY_LIST()

View file

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

View file

@ -398,9 +398,9 @@ std::optional<InputBindingKey> DInputSource::ParseKeyString(const std::string_vi
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)
{
@ -408,23 +408,28 @@ std::string DInputSource::ConvertKeyToString(InputBindingKey key)
{
const char* modifier =
(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)
{
const u32 hat_num = (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)
{
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;
}
TinyString DInputSource::ConvertKeyToIcon(InputBindingKey key)
{
return {};
}
void DInputSource::CheckForStateChanges(size_t index, const DIJOYSTATE& new_state)
{
ControllerData& cd = m_controllers[index];

View file

@ -48,7 +48,8 @@ public:
std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) override;
std::string ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToIcon(InputBindingKey key) override;
private:
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,
0xf65d, 0xf65e, 0xf6a9, 0xf6a9, 0xf7c2, 0xf7c2, 0xf807, 0xf807, 0xf815, 0xf815, 0xf818, 0xf818, 0xf84c, 0xf84c,
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;

View file

@ -14,6 +14,8 @@
#include "imgui_manager.h"
#include "input_source.h"
#include "IconsPromptFont.h"
#include "fmt/core.h"
#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 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 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)])
{
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();
}
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)
{
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.
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.
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,
size_t num_keys);
/// Represents a binding with icon fonts, if available.
bool PrettifyInputBinding(std::string& binding);
/// Returns a list of all hotkeys.
std::vector<const HotkeyInfo*> GetHotkeyList();

View file

@ -10,6 +10,7 @@
#include <utility>
#include <vector>
#include "common/small_string.h"
#include "common/types.h"
#include "input_manager.h"
@ -30,7 +31,8 @@ public:
virtual std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
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.
virtual std::vector<std::pair<std::string, std::string>> EnumerateDevices() = 0;

View file

@ -14,6 +14,8 @@
#include "common/path.h"
#include "common/string_util.h"
#include "IconsPromptFont.h"
#include <cmath>
#ifdef __APPLE__
@ -32,6 +34,14 @@ static constexpr const char* s_sdl_axis_names[] = {
"LeftTrigger", // SDL_CONTROLLER_AXIS_TRIGGERLEFT
"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] = {
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // SDL_CONTROLLER_AXIS_LEFTX
{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
"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[] = {
GenericInputBinding::Cross, // SDL_CONTROLLER_BUTTON_A
GenericInputBinding::Circle, // SDL_CONTROLLER_BUTTON_B
@ -416,9 +443,9 @@ std::optional<InputBindingKey> SDLInputSource::ParseKeyString(const std::string_
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)
{
@ -428,40 +455,64 @@ std::string SDLInputSource::ConvertKeyToString(InputBindingKey key)
(key.modifier == InputModifier::FullAxis ? "Full" : (key.modifier == InputModifier::Negate ? "-" : "+"));
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
{
ret = fmt::format("SDL-{}/{}Axis{}{}", static_cast<u32>(key.source_index), modifier,
key.data - static_cast<u32>(std::size(s_sdl_axis_names)), key.invert ? "~" : "");
ret.fmt("SDL-{}/{}Axis{}{}", static_cast<u32>(key.source_index), modifier,
key.data - static_cast<u32>(std::size(s_sdl_axis_names)), key.invert ? "~" : "");
}
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
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
{
ret = fmt::format("SDL-{}/Button{}", static_cast<u32>(key.source_index),
key.data - static_cast<u32>(std::size(s_sdl_button_names)));
ret.fmt("SDL-{}/Button{}", static_cast<u32>(key.source_index),
key.data - static_cast<u32>(std::size(s_sdl_button_names)));
}
}
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_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,
s_sdl_hat_direction_names[hat_direction]);
ret.fmt("SDL-{}/Hat{}{}", static_cast<u32>(key.source_index), hat_index,
s_sdl_hat_direction_names[hat_direction]);
}
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)
{
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,
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);

View file

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

View file

@ -32,7 +32,8 @@ public:
std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) override;
std::string ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToIcon(InputBindingKey key) override;
private:
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)
#include "xinput_source.h"
#include "input_manager.h"
#include "common/assert.h"
#include "common/log.h"
#include "common/string_util.h"
#include "core/host.h"
#include "input_manager.h"
#include "IconsPromptFont.h"
#include <cmath>
Log_SetChannel(XInputSource);
const char* XInputSource::s_axis_names[XInputSource::NUM_AXES] = {
static const char* s_axis_names[XInputSource::NUM_AXES] = {
"LeftX", // AXIS_LEFTX
"LeftY", // AXIS_LEFTY
"RightX", // AXIS_RIGHTX
@ -18,6 +22,14 @@ const char* XInputSource::s_axis_names[XInputSource::NUM_AXES] = {
"LeftTrigger", // AXIS_TRIGGERLEFT
"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] = {
{GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // AXIS_LEFTX
{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
};
const char* XInputSource::s_button_names[XInputSource::NUM_BUTTONS] = {
static const char* s_button_names[XInputSource::NUM_BUTTONS] = {
"DPadUp", // XINPUT_GAMEPAD_DPAD_UP
"DPadDown", // XINPUT_GAMEPAD_DPAD_DOWN
"DPadLeft", // XINPUT_GAMEPAD_DPAD_LEFT
@ -44,7 +56,7 @@ const char* XInputSource::s_button_names[XInputSource::NUM_BUTTONS] = {
"Y", // XINPUT_GAMEPAD_Y
"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_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT,
@ -61,6 +73,23 @@ const u16 XInputSource::s_button_masks[XInputSource::NUM_BUTTONS] = {
XINPUT_GAMEPAD_Y,
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[] = {
GenericInputBinding::DPadUp, // XINPUT_GAMEPAD_DPAD_UP
GenericInputBinding::DPadDown, // XINPUT_GAMEPAD_DPAD_DOWN
@ -287,24 +316,48 @@ std::optional<InputBindingKey> XInputSource::ParseKeyString(const std::string_vi
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_subtype == InputSubclass::ControllerAxis && key.data < std::size(s_axis_names))
{
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))
{
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)
{
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.last_state = {};
InputManager::OnInputDeviceConnected(fmt::format("XInput-{}", index),
fmt::format("XInput Controller {}", index));
InputManager::OnInputDeviceConnected(fmt::format("XInput-{}", index), fmt::format("XInput Controller {}", index));
}
void XInputSource::HandleControllerDisconnection(u32 index)

View file

@ -15,6 +15,23 @@ class SettingsInterface;
class XInputSource final : public InputSource
{
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();
@ -33,26 +50,10 @@ public:
std::optional<InputBindingKey> ParseKeyString(const std::string_view& device,
const std::string_view& binding) override;
std::string ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToString(InputBindingKey key) override;
TinyString ConvertKeyToIcon(InputBindingKey key) override;
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
{
XINPUT_STATE last_state;
@ -74,8 +75,4 @@ private:
DWORD(WINAPI* m_xinput_get_state)(DWORD, XINPUT_STATE*) = nullptr;
DWORD(WINAPI* m_xinput_set_state)(DWORD, XINPUT_VIBRATION*) = 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];
};