Skip to content

Commit cdca5ea

Browse files
authored
UI: Add configurable hotkeys + a new fast forward hotkey (#1519)
1 parent e68c31e commit cdca5ea

15 files changed

+619
-8
lines changed

src/config/CemuConfig.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,15 @@ void CemuConfig::Load(XMLConfigParser& parser)
354354
dsu_client.host = dsuc.get_attribute("host", dsu_client.host);
355355
dsu_client.port = dsuc.get_attribute("port", dsu_client.port);
356356

357+
// hotkeys
358+
auto xml_hotkeys = parser.get("Hotkeys");
359+
hotkeys.modifiers = xml_hotkeys.get("modifiers", sHotkeyCfg{});
360+
hotkeys.exitFullscreen = xml_hotkeys.get("ExitFullscreen", sHotkeyCfg{uKeyboardHotkey{WXK_ESCAPE}});
361+
hotkeys.toggleFullscreen = xml_hotkeys.get("ToggleFullscreen", sHotkeyCfg{uKeyboardHotkey{WXK_F11}});
362+
hotkeys.toggleFullscreenAlt = xml_hotkeys.get("ToggleFullscreenAlt", sHotkeyCfg{uKeyboardHotkey{WXK_CONTROL_M, true}}); // ALT+ENTER
363+
hotkeys.takeScreenshot = xml_hotkeys.get("TakeScreenshot", sHotkeyCfg{uKeyboardHotkey{WXK_F12}});
364+
hotkeys.toggleFastForward = xml_hotkeys.get("ToggleFastForward", sHotkeyCfg{});
365+
357366
// emulatedusbdevices
358367
auto usbdevices = parser.get("EmulatedUsbDevices");
359368
emulated_usb_devices.emulate_skylander_portal = usbdevices.get("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal);
@@ -557,6 +566,15 @@ void CemuConfig::Save(XMLConfigParser& parser)
557566
dsuc.set_attribute("host", dsu_client.host);
558567
dsuc.set_attribute("port", dsu_client.port);
559568

569+
// hotkeys
570+
auto xml_hotkeys = config.set("Hotkeys");
571+
xml_hotkeys.set("modifiers", hotkeys.modifiers);
572+
xml_hotkeys.set("ExitFullscreen", hotkeys.exitFullscreen);
573+
xml_hotkeys.set("ToggleFullscreen", hotkeys.toggleFullscreen);
574+
xml_hotkeys.set("ToggleFullscreenAlt", hotkeys.toggleFullscreenAlt);
575+
xml_hotkeys.set("TakeScreenshot", hotkeys.takeScreenshot);
576+
xml_hotkeys.set("ToggleFastForward", hotkeys.toggleFastForward);
577+
560578
// emulated usb devices
561579
auto usbdevices = config.set("EmulatedUsbDevices");
562580
usbdevices.set("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal.GetValue());

src/config/CemuConfig.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,50 @@ enum class CrashDump
191191
ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled);
192192
#endif
193193

194+
typedef union
195+
{
196+
struct
197+
{
198+
uint16 key : 13; // enough bits for all keycodes
199+
uint16 alt : 1;
200+
uint16 ctrl : 1;
201+
uint16 shift : 1;
202+
};
203+
uint16 raw;
204+
} uKeyboardHotkey;
205+
206+
typedef sint16 ControllerHotkey_t;
207+
208+
struct sHotkeyCfg
209+
{
210+
static constexpr uint8 keyboardNone{WXK_NONE};
211+
static constexpr sint8 controllerNone{-1}; // no enums to work with, but buttons start from 0
212+
213+
uKeyboardHotkey keyboard{keyboardNone};
214+
ControllerHotkey_t controller{controllerNone};
215+
216+
/* for defaults */
217+
sHotkeyCfg(const uKeyboardHotkey& keyboard = {WXK_NONE}, const ControllerHotkey_t& controller = {-1}) :
218+
keyboard(keyboard), controller(controller) {};
219+
220+
/* for reading from xml */
221+
sHotkeyCfg(const char* xml_values)
222+
{
223+
std::istringstream iss(xml_values);
224+
iss >> keyboard.raw >> controller;
225+
}
226+
};
227+
228+
template <>
229+
struct fmt::formatter<sHotkeyCfg> : formatter<string_view>
230+
{
231+
template <typename FormatContext>
232+
auto format(const sHotkeyCfg c, FormatContext &ctx) const {
233+
std::string xml_values = fmt::format("{} {}", c.keyboard.raw, c.controller);
234+
return formatter<string_view>::format(xml_values, ctx);
235+
}
236+
};
237+
194238
template <>
195239
struct fmt::formatter<PrecompiledShaderOption> : formatter<string_view> {
196240
template <typename FormatContext>
@@ -499,6 +543,17 @@ struct CemuConfig
499543
ConfigValue<uint16> port{ 26760 };
500544
}dsu_client{};
501545

546+
// hotkeys
547+
struct
548+
{
549+
sHotkeyCfg modifiers;
550+
sHotkeyCfg toggleFullscreen;
551+
sHotkeyCfg toggleFullscreenAlt;
552+
sHotkeyCfg exitFullscreen;
553+
sHotkeyCfg takeScreenshot;
554+
sHotkeyCfg toggleFastForward;
555+
} hotkeys{};
556+
502557
// debug
503558
ConfigValueBounds<CrashDump> crash_dump{ CrashDump::Disabled };
504559
ConfigValue<uint16> gdb_port{ 1337 };

src/config/XMLConfig.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
#include <string>
88
#include <mutex>
99

10+
template <typename T>
11+
concept HasConstCharConstructor = requires { T(std::declval<const char*>()); };
12+
1013
class XMLConfigParser
1114
{
1215
public:
@@ -43,7 +46,7 @@ class XMLConfigParser
4346
return element->Int64Text(default_value);
4447
else if constexpr (std::is_same_v<T, uint64>) // doesnt support real uint64...
4548
return (uint64)element->Int64Text((sint64)default_value);
46-
else if constexpr (std::is_same_v<T, const char*> || std::is_same_v<T, std::string>)
49+
else if constexpr (std::is_same_v<T, const char*> || std::is_same_v<T, std::string> || HasConstCharConstructor<T>)
4750
{
4851
const char* text = element->GetText();
4952
return text ? text : default_value;

src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ add_library(CemuGui
7171
helpers/wxLogEvent.h
7272
helpers/wxWayland.cpp
7373
helpers/wxWayland.h
74+
input/HotkeySettings.cpp
75+
input/HotkeySettings.h
7476
input/InputAPIAddWindow.cpp
7577
input/InputAPIAddWindow.h
7678
input/InputSettings2.cpp

src/gui/CemuApp.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "input/InputManager.h"
1212
#include "gui/helpers/wxHelpers.h"
1313
#include "Cemu/ncrypto/ncrypto.h"
14+
#include "gui/input/HotkeySettings.h"
1415

1516
#if BOOST_OS_LINUX && HAS_WAYLAND
1617
#include "gui/helpers/wxWayland.h"
@@ -331,6 +332,8 @@ bool CemuApp::OnInit()
331332
std::unique_lock lock(g_mutex);
332333
g_window_info.app_active = true;
333334

335+
HotkeySettings::Init(m_mainFrame);
336+
334337
SetTopWindow(m_mainFrame);
335338
m_mainFrame->Show();
336339

src/gui/MainWindow.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "gui/helpers/wxHelpers.h"
4141
#include "Cafe/HW/Latte/Renderer/Vulkan/VsyncDriver.h"
4242
#include "gui/input/InputSettings2.h"
43+
#include "gui/input/HotkeySettings.h"
4344
#include "input/InputManager.h"
4445

4546
#if BOOST_OS_WINDOWS
@@ -91,6 +92,7 @@ enum
9192
MAINFRAME_MENU_ID_OPTIONS_GENERAL2,
9293
MAINFRAME_MENU_ID_OPTIONS_AUDIO,
9394
MAINFRAME_MENU_ID_OPTIONS_INPUT,
95+
MAINFRAME_MENU_ID_OPTIONS_HOTKEY,
9496
MAINFRAME_MENU_ID_OPTIONS_MAC_SETTINGS,
9597
// options -> account
9698
MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_1 = 20350,
@@ -189,6 +191,7 @@ EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_GENERAL, MainWindow::OnOptionsInput)
189191
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_GENERAL2, MainWindow::OnOptionsInput)
190192
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_AUDIO, MainWindow::OnOptionsInput)
191193
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_INPUT, MainWindow::OnOptionsInput)
194+
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_HOTKEY, MainWindow::OnOptionsInput)
192195
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_MAC_SETTINGS, MainWindow::OnOptionsInput)
193196
// tools menu
194197
EVT_MENU(MAINFRAME_MENU_ID_TOOLS_MEMORY_SEARCHER, MainWindow::OnToolsInput)
@@ -933,6 +936,12 @@ void MainWindow::OnOptionsInput(wxCommandEvent& event)
933936
break;
934937
}
935938

939+
case MAINFRAME_MENU_ID_OPTIONS_HOTKEY:
940+
{
941+
auto* frame = new HotkeySettings(this);
942+
frame->Show();
943+
break;
944+
}
936945
}
937946
}
938947

@@ -1446,13 +1455,7 @@ void MainWindow::OnKeyUp(wxKeyEvent& event)
14461455
if (swkbd_hasKeyboardInputHook())
14471456
return;
14481457

1449-
const auto code = event.GetKeyCode();
1450-
if (code == WXK_ESCAPE)
1451-
SetFullScreen(false);
1452-
else if (code == WXK_RETURN && event.AltDown() || code == WXK_F11)
1453-
SetFullScreen(!IsFullScreen());
1454-
else if (code == WXK_F12)
1455-
g_window_info.has_screenshot_request = true; // async screenshot request
1458+
HotkeySettings::CaptureInput(event);
14561459
}
14571460

14581461
void MainWindow::OnKeyDown(wxKeyEvent& event)
@@ -2189,6 +2192,7 @@ void MainWindow::RecreateMenu()
21892192
#endif
21902193
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_GENERAL2, _("&General settings"));
21912194
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_INPUT, _("&Input settings"));
2195+
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_HOTKEY, _("&Hotkey settings"));
21922196

21932197
optionsMenu->AppendSeparator();
21942198
optionsMenu->AppendSubMenu(m_optionsAccountMenu, _("&Active account"));

0 commit comments

Comments
 (0)