mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-06 23:11:18 +12:00
input: configurable hotkeys
This commit is contained in:
parent
8b5cafa98e
commit
5a17e983aa
7 changed files with 278 additions and 7 deletions
|
@ -343,6 +343,13 @@ void CemuConfig::Load(XMLConfigParser& parser)
|
||||||
dsu_client.host = dsuc.get_attribute("host", dsu_client.host);
|
dsu_client.host = dsuc.get_attribute("host", dsu_client.host);
|
||||||
dsu_client.port = dsuc.get_attribute("port", dsu_client.port);
|
dsu_client.port = dsuc.get_attribute("port", dsu_client.port);
|
||||||
|
|
||||||
|
// hotkeys
|
||||||
|
auto xml_hotkeys = parser.get("Hotkeys");
|
||||||
|
hotkeys.exitFullscreen.raw = xml_hotkeys.get("ExitFullscreen", WXK_ESCAPE);
|
||||||
|
hotkeys.toggleFullscreen.raw = xml_hotkeys.get("ToggleFullscreen", WXK_F11);
|
||||||
|
hotkeys.toggleFullscreenAlt.raw = xml_hotkeys.get("ToggleFullscreenAlt", uHotkey{WXK_CONTROL_M, true}.raw); // ALT+ENTER
|
||||||
|
hotkeys.takeScreenshot.raw = xml_hotkeys.get("TakeScreenshot", WXK_F12);
|
||||||
|
|
||||||
// emulatedusbdevices
|
// emulatedusbdevices
|
||||||
auto usbdevices = parser.get("EmulatedUsbDevices");
|
auto usbdevices = parser.get("EmulatedUsbDevices");
|
||||||
emulated_usb_devices.emulate_skylander_portal = usbdevices.get("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal);
|
emulated_usb_devices.emulate_skylander_portal = usbdevices.get("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal);
|
||||||
|
@ -544,6 +551,13 @@ void CemuConfig::Save(XMLConfigParser& parser)
|
||||||
dsuc.set_attribute("host", dsu_client.host);
|
dsuc.set_attribute("host", dsu_client.host);
|
||||||
dsuc.set_attribute("port", dsu_client.port);
|
dsuc.set_attribute("port", dsu_client.port);
|
||||||
|
|
||||||
|
// hotkeys
|
||||||
|
auto xml_hotkeys = config.set("Hotkeys");
|
||||||
|
xml_hotkeys.set("ExitFullscreen", hotkeys.exitFullscreen.raw);
|
||||||
|
xml_hotkeys.set("ToggleFullscreen", hotkeys.toggleFullscreen.raw);
|
||||||
|
xml_hotkeys.set("ToggleFullscreenAlt", hotkeys.toggleFullscreenAlt.raw);
|
||||||
|
xml_hotkeys.set("TakeScreenshot", hotkeys.takeScreenshot.raw);
|
||||||
|
|
||||||
// emulated usb devices
|
// emulated usb devices
|
||||||
auto usbdevices = config.set("EmulatedUsbDevices");
|
auto usbdevices = config.set("EmulatedUsbDevices");
|
||||||
usbdevices.set("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal.GetValue());
|
usbdevices.set("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal.GetValue());
|
||||||
|
|
|
@ -191,6 +191,18 @@ enum class CrashDump
|
||||||
ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled);
|
ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t key : 13; // enough bits for all keycodes
|
||||||
|
uint16_t alt : 1;
|
||||||
|
uint16_t ctrl : 1;
|
||||||
|
uint16_t shift : 1;
|
||||||
|
};
|
||||||
|
uint16_t raw;
|
||||||
|
} uHotkey;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct fmt::formatter<const PrecompiledShaderOption> : formatter<string_view> {
|
struct fmt::formatter<const PrecompiledShaderOption> : formatter<string_view> {
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
|
@ -499,6 +511,15 @@ struct CemuConfig
|
||||||
ConfigValue<uint16> port{ 26760 };
|
ConfigValue<uint16> port{ 26760 };
|
||||||
}dsu_client{};
|
}dsu_client{};
|
||||||
|
|
||||||
|
// hotkeys
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uHotkey toggleFullscreen{};
|
||||||
|
uHotkey toggleFullscreenAlt{};
|
||||||
|
uHotkey exitFullscreen{};
|
||||||
|
uHotkey takeScreenshot{};
|
||||||
|
} hotkeys{};
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
ConfigValueBounds<CrashDump> crash_dump{ CrashDump::Disabled };
|
ConfigValueBounds<CrashDump> crash_dump{ CrashDump::Disabled };
|
||||||
ConfigValue<uint16> gdb_port{ 1337 };
|
ConfigValue<uint16> gdb_port{ 1337 };
|
||||||
|
|
|
@ -71,6 +71,8 @@ add_library(CemuGui
|
||||||
helpers/wxLogEvent.h
|
helpers/wxLogEvent.h
|
||||||
helpers/wxWayland.cpp
|
helpers/wxWayland.cpp
|
||||||
helpers/wxWayland.h
|
helpers/wxWayland.h
|
||||||
|
input/HotkeySettings.cpp
|
||||||
|
input/HotkeySettings.h
|
||||||
input/InputAPIAddWindow.cpp
|
input/InputAPIAddWindow.cpp
|
||||||
input/InputAPIAddWindow.h
|
input/InputAPIAddWindow.h
|
||||||
input/InputSettings2.cpp
|
input/InputSettings2.cpp
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "input/InputManager.h"
|
#include "input/InputManager.h"
|
||||||
#include "gui/helpers/wxHelpers.h"
|
#include "gui/helpers/wxHelpers.h"
|
||||||
#include "Cemu/ncrypto/ncrypto.h"
|
#include "Cemu/ncrypto/ncrypto.h"
|
||||||
|
#include "gui/input/HotkeySettings.h"
|
||||||
|
|
||||||
#if BOOST_OS_LINUX && HAS_WAYLAND
|
#if BOOST_OS_LINUX && HAS_WAYLAND
|
||||||
#include "gui/helpers/wxWayland.h"
|
#include "gui/helpers/wxWayland.h"
|
||||||
|
@ -331,6 +332,8 @@ bool CemuApp::OnInit()
|
||||||
std::unique_lock lock(g_mutex);
|
std::unique_lock lock(g_mutex);
|
||||||
g_window_info.app_active = true;
|
g_window_info.app_active = true;
|
||||||
|
|
||||||
|
HotkeySettings::Init(m_mainFrame);
|
||||||
|
|
||||||
SetTopWindow(m_mainFrame);
|
SetTopWindow(m_mainFrame);
|
||||||
m_mainFrame->Show();
|
m_mainFrame->Show();
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "gui/helpers/wxHelpers.h"
|
#include "gui/helpers/wxHelpers.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VsyncDriver.h"
|
#include "Cafe/HW/Latte/Renderer/Vulkan/VsyncDriver.h"
|
||||||
#include "gui/input/InputSettings2.h"
|
#include "gui/input/InputSettings2.h"
|
||||||
|
#include "gui/input/HotkeySettings.h"
|
||||||
#include "input/InputManager.h"
|
#include "input/InputManager.h"
|
||||||
|
|
||||||
#if BOOST_OS_WINDOWS
|
#if BOOST_OS_WINDOWS
|
||||||
|
@ -91,6 +92,7 @@ enum
|
||||||
MAINFRAME_MENU_ID_OPTIONS_GENERAL2,
|
MAINFRAME_MENU_ID_OPTIONS_GENERAL2,
|
||||||
MAINFRAME_MENU_ID_OPTIONS_AUDIO,
|
MAINFRAME_MENU_ID_OPTIONS_AUDIO,
|
||||||
MAINFRAME_MENU_ID_OPTIONS_INPUT,
|
MAINFRAME_MENU_ID_OPTIONS_INPUT,
|
||||||
|
MAINFRAME_MENU_ID_OPTIONS_HOTKEY,
|
||||||
// options -> account
|
// options -> account
|
||||||
MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_1 = 20350,
|
MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_1 = 20350,
|
||||||
MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_12 = 20350 + 11,
|
MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_12 = 20350 + 11,
|
||||||
|
@ -186,6 +188,7 @@ EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_GENERAL, MainWindow::OnOptionsInput)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_GENERAL2, MainWindow::OnOptionsInput)
|
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_GENERAL2, MainWindow::OnOptionsInput)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_AUDIO, MainWindow::OnOptionsInput)
|
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_AUDIO, MainWindow::OnOptionsInput)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_INPUT, MainWindow::OnOptionsInput)
|
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_INPUT, MainWindow::OnOptionsInput)
|
||||||
|
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_HOTKEY, MainWindow::OnOptionsInput)
|
||||||
// tools menu
|
// tools menu
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_TOOLS_MEMORY_SEARCHER, MainWindow::OnToolsInput)
|
EVT_MENU(MAINFRAME_MENU_ID_TOOLS_MEMORY_SEARCHER, MainWindow::OnToolsInput)
|
||||||
EVT_MENU(MAINFRAME_MENU_ID_TOOLS_TITLE_MANAGER, MainWindow::OnToolsInput)
|
EVT_MENU(MAINFRAME_MENU_ID_TOOLS_TITLE_MANAGER, MainWindow::OnToolsInput)
|
||||||
|
@ -922,6 +925,12 @@ void MainWindow::OnOptionsInput(wxCommandEvent& event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MAINFRAME_MENU_ID_OPTIONS_HOTKEY:
|
||||||
|
{
|
||||||
|
auto* frame = new HotkeySettings(this);
|
||||||
|
frame->Show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1437,13 +1446,15 @@ void MainWindow::OnKeyUp(wxKeyEvent& event)
|
||||||
if (swkbd_hasKeyboardInputHook())
|
if (swkbd_hasKeyboardInputHook())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto code = event.GetKeyCode();
|
uHotkey hotkey{};
|
||||||
if (code == WXK_ESCAPE)
|
hotkey.key = event.GetKeyCode();
|
||||||
SetFullScreen(false);
|
hotkey.alt = event.AltDown();
|
||||||
else if (code == WXK_RETURN && event.AltDown() || code == WXK_F11)
|
hotkey.ctrl = event.ControlDown();
|
||||||
SetFullScreen(!IsFullScreen());
|
hotkey.shift = event.ShiftDown();
|
||||||
else if (code == WXK_F12)
|
const auto& hotkeyMap = HotkeySettings::s_hotkeyToFuncMap;
|
||||||
g_window_info.has_screenshot_request = true; // async screenshot request
|
const auto it = hotkeyMap.find(hotkey.raw);
|
||||||
|
if (it != hotkeyMap.end())
|
||||||
|
it->second();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::OnKeyDown(wxKeyEvent& event)
|
void MainWindow::OnKeyDown(wxKeyEvent& event)
|
||||||
|
@ -2159,6 +2170,7 @@ void MainWindow::RecreateMenu()
|
||||||
optionsMenu->AppendSeparator();
|
optionsMenu->AppendSeparator();
|
||||||
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_GENERAL2, _("&General settings"));
|
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_GENERAL2, _("&General settings"));
|
||||||
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_INPUT, _("&Input settings"));
|
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_INPUT, _("&Input settings"));
|
||||||
|
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_HOTKEY, _("&Hotkey settings"));
|
||||||
|
|
||||||
optionsMenu->AppendSeparator();
|
optionsMenu->AppendSeparator();
|
||||||
optionsMenu->AppendSubMenu(m_optionsAccountMenu, _("&Active account"));
|
optionsMenu->AppendSubMenu(m_optionsAccountMenu, _("&Active account"));
|
||||||
|
|
181
src/gui/input/HotkeySettings.cpp
Normal file
181
src/gui/input/HotkeySettings.cpp
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
#include "gui/input/HotkeySettings.h"
|
||||||
|
#include <config/ActiveSettings.h>
|
||||||
|
#include <gui/guiWrapper.h>
|
||||||
|
|
||||||
|
extern WindowInfo g_window_info;
|
||||||
|
const std::unordered_map<uHotkey*, std::function<void(void)>> HotkeySettings::s_cfgHotkeyToFuncMap{
|
||||||
|
{&s_cfgHotkeys.toggleFullscreen, [](void) { s_mainWindow->ShowFullScreen(!s_mainWindow->IsFullScreen()); }},
|
||||||
|
{&s_cfgHotkeys.toggleFullscreenAlt, [](void) { s_mainWindow->ShowFullScreen(!s_mainWindow->IsFullScreen()); }},
|
||||||
|
{&s_cfgHotkeys.exitFullscreen, [](void) { s_mainWindow->ShowFullScreen(false); }},
|
||||||
|
{&s_cfgHotkeys.takeScreenshot, [](void) { g_window_info.has_screenshot_request = true; }},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotkeyEntry
|
||||||
|
{
|
||||||
|
std::unique_ptr<wxStaticText> name;
|
||||||
|
std::unique_ptr<wxButton> keyInput;
|
||||||
|
uHotkey& hotkey;
|
||||||
|
|
||||||
|
HotkeyEntry(wxStaticText* name, wxButton* keyInput, uHotkey& hotkey)
|
||||||
|
: name(name), keyInput(keyInput), hotkey(hotkey)
|
||||||
|
{
|
||||||
|
keyInput->SetClientData(&hotkey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HotkeySettings::HotkeySettings(wxWindow* parent)
|
||||||
|
: wxFrame(parent, wxID_ANY, "Hotkey Settings")
|
||||||
|
{
|
||||||
|
m_panel = new wxPanel(this);
|
||||||
|
m_sizer = new wxFlexGridSizer(0, 2, wxSize(0, 0));
|
||||||
|
|
||||||
|
m_panel->SetSizer(m_sizer);
|
||||||
|
Center();
|
||||||
|
|
||||||
|
CreateHotkey("Toggle fullscreen", s_cfgHotkeys.toggleFullscreen);
|
||||||
|
CreateHotkey("Take screenshot", s_cfgHotkeys.takeScreenshot);
|
||||||
|
|
||||||
|
m_sizer->SetSizeHints(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
HotkeySettings::~HotkeySettings()
|
||||||
|
{
|
||||||
|
if (m_needToSave)
|
||||||
|
{
|
||||||
|
g_config.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HotkeySettings::Init(wxFrame* mainWindowFrame)
|
||||||
|
{
|
||||||
|
s_hotkeyToFuncMap.reserve(s_cfgHotkeyToFuncMap.size());
|
||||||
|
for (const auto& [cfgHotkey, func] : s_cfgHotkeyToFuncMap)
|
||||||
|
{
|
||||||
|
auto hotkeyRaw = cfgHotkey->raw;
|
||||||
|
if (hotkeyRaw > 0)
|
||||||
|
{
|
||||||
|
s_hotkeyToFuncMap[hotkeyRaw] = func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_mainWindow = mainWindowFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HotkeySettings::CreateHotkey(const wxString& label, uHotkey& hotkey)
|
||||||
|
{
|
||||||
|
/* add new hotkey */
|
||||||
|
{
|
||||||
|
auto* name = new wxStaticText(m_panel, wxID_ANY, label, wxDefaultPosition, wxSize(240, 30), wxALIGN_CENTER);
|
||||||
|
auto* keyInput = new wxButton(m_panel, wxID_ANY, To_wxString(hotkey), wxDefaultPosition, wxSize(120, 30), wxWANTS_CHARS);
|
||||||
|
|
||||||
|
keyInput->Bind(wxEVT_BUTTON, &HotkeySettings::OnHotkeyInputLeftClick, this);
|
||||||
|
keyInput->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(HotkeySettings::OnHotkeyInputRightClick), NULL, this);
|
||||||
|
|
||||||
|
auto flags = wxSizerFlags().Expand();
|
||||||
|
m_sizer->Add(name, flags);
|
||||||
|
m_sizer->Add(keyInput, flags);
|
||||||
|
|
||||||
|
m_hotkeys.emplace_back(name, keyInput, hotkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HotkeySettings::OnHotkeyInputLeftClick(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
auto* inputButton = static_cast<wxButton*>(event.GetEventObject());
|
||||||
|
if (m_activeInputButton)
|
||||||
|
{
|
||||||
|
/* ignore multiple clicks of the same button */
|
||||||
|
if (inputButton == m_activeInputButton) return;
|
||||||
|
FinalizeInput(m_activeInputButton);
|
||||||
|
}
|
||||||
|
inputButton->Bind(wxEVT_KEY_UP, &HotkeySettings::OnKeyUp, this);
|
||||||
|
inputButton->SetLabelText('_');
|
||||||
|
m_activeInputButton = inputButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HotkeySettings::OnHotkeyInputRightClick(wxMouseEvent& event) {
|
||||||
|
if (m_activeInputButton)
|
||||||
|
{
|
||||||
|
FinalizeInput(m_activeInputButton);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto* inputButton = static_cast<wxButton*>(event.GetEventObject());
|
||||||
|
auto& cfgHotkey = *static_cast<uHotkey*>(inputButton->GetClientData());
|
||||||
|
uHotkey newHotkey{};
|
||||||
|
if (cfgHotkey.raw != newHotkey.raw)
|
||||||
|
{
|
||||||
|
m_needToSave |= true;
|
||||||
|
s_hotkeyToFuncMap.erase(cfgHotkey.raw);
|
||||||
|
cfgHotkey = newHotkey;
|
||||||
|
}
|
||||||
|
FinalizeInput(inputButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HotkeySettings::OnKeyUp(wxKeyEvent& event)
|
||||||
|
{
|
||||||
|
auto* inputButton = static_cast<wxButton*>(event.GetEventObject());
|
||||||
|
auto& cfgHotkey = *static_cast<uHotkey*>(inputButton->GetClientData());
|
||||||
|
if (auto keycode = event.GetKeyCode(); IsValidKeycodeUp(keycode))
|
||||||
|
{
|
||||||
|
auto oldHotkey = cfgHotkey;
|
||||||
|
uHotkey newHotkey{};
|
||||||
|
newHotkey.key = keycode;
|
||||||
|
newHotkey.alt = event.AltDown();
|
||||||
|
newHotkey.ctrl = event.ControlDown();
|
||||||
|
newHotkey.shift = event.ShiftDown();
|
||||||
|
if ((newHotkey.raw != oldHotkey.raw) &&
|
||||||
|
(s_hotkeyToFuncMap.find(newHotkey.raw) == s_hotkeyToFuncMap.end()))
|
||||||
|
{
|
||||||
|
m_needToSave |= true;
|
||||||
|
cfgHotkey = newHotkey;
|
||||||
|
s_hotkeyToFuncMap.erase(oldHotkey.raw);
|
||||||
|
s_hotkeyToFuncMap[cfgHotkey.raw] = s_cfgHotkeyToFuncMap.at(&cfgHotkey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FinalizeInput(inputButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HotkeySettings::FinalizeInput(wxButton* inputButton)
|
||||||
|
{
|
||||||
|
auto& cfgHotkey = *static_cast<uHotkey*>(inputButton->GetClientData());
|
||||||
|
inputButton->Unbind(wxEVT_KEY_UP, &HotkeySettings::OnKeyUp, this);
|
||||||
|
inputButton->SetLabelText(To_wxString(cfgHotkey));
|
||||||
|
m_activeInputButton = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HotkeySettings::IsValidKeycodeUp(int keycode)
|
||||||
|
{
|
||||||
|
switch (keycode)
|
||||||
|
{
|
||||||
|
case WXK_NONE:
|
||||||
|
case WXK_ESCAPE:
|
||||||
|
case WXK_ALT:
|
||||||
|
case WXK_CONTROL:
|
||||||
|
case WXK_SHIFT:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString HotkeySettings::To_wxString(uHotkey hotkey)
|
||||||
|
{
|
||||||
|
if (hotkey.raw <= 0)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
wxString ret_val;
|
||||||
|
if (hotkey.alt)
|
||||||
|
{
|
||||||
|
ret_val.append("ALT + ");
|
||||||
|
}
|
||||||
|
if (hotkey.ctrl)
|
||||||
|
{
|
||||||
|
ret_val.append("CTRL + ");
|
||||||
|
}
|
||||||
|
if (hotkey.shift)
|
||||||
|
{
|
||||||
|
ret_val.append("SHIFT + ");
|
||||||
|
}
|
||||||
|
ret_val.append(wxAcceleratorEntry(0, hotkey.key).ToString());
|
||||||
|
return ret_val;
|
||||||
|
}
|
38
src/gui/input/HotkeySettings.h
Normal file
38
src/gui/input/HotkeySettings.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include "config/CemuConfig.h"
|
||||||
|
|
||||||
|
class HotkeyEntry;
|
||||||
|
|
||||||
|
class HotkeySettings : public wxFrame
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(wxFrame* mainWindowFrame);
|
||||||
|
inline static std::unordered_map<int, std::function<void(void)>> s_hotkeyToFuncMap{};
|
||||||
|
|
||||||
|
HotkeySettings(wxWindow* parent);
|
||||||
|
~HotkeySettings();
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline static wxFrame* s_mainWindow = nullptr;
|
||||||
|
inline static auto& s_cfgHotkeys = GetConfig().hotkeys;
|
||||||
|
static const std::unordered_map<uHotkey*, std::function<void(void)>> s_cfgHotkeyToFuncMap;
|
||||||
|
|
||||||
|
wxPanel* m_panel;
|
||||||
|
wxFlexGridSizer* m_sizer;
|
||||||
|
std::vector<HotkeyEntry> m_hotkeys;
|
||||||
|
wxButton* m_activeInputButton = nullptr;
|
||||||
|
bool m_needToSave = false;
|
||||||
|
|
||||||
|
/* helpers */
|
||||||
|
void CreateHotkey(const wxString& label, uHotkey& hotkey);
|
||||||
|
wxString To_wxString(uHotkey hotkey);
|
||||||
|
bool IsValidKeycodeUp(int keycode);
|
||||||
|
void FinalizeInput(wxButton* inputButton);
|
||||||
|
|
||||||
|
/* events */
|
||||||
|
void OnHotkeyInputLeftClick(wxCommandEvent& event);
|
||||||
|
void OnHotkeyInputRightClick(wxMouseEvent& event);
|
||||||
|
void OnKeyUp(wxKeyEvent& event);
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue