Skip to content

Configurable hotkeys + fastforward hotkey as example #1519

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/config/CemuConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,15 @@ void CemuConfig::Load(XMLConfigParser& parser)
dsu_client.host = dsuc.get_attribute("host", dsu_client.host);
dsu_client.port = dsuc.get_attribute("port", dsu_client.port);

// hotkeys
auto xml_hotkeys = parser.get("Hotkeys");
hotkeys.modifiers = xml_hotkeys.get("modifiers", sHotkeyCfg{});
hotkeys.exitFullscreen = xml_hotkeys.get("ExitFullscreen", sHotkeyCfg{uKeyboardHotkey{WXK_ESCAPE}});
hotkeys.toggleFullscreen = xml_hotkeys.get("ToggleFullscreen", sHotkeyCfg{uKeyboardHotkey{WXK_F11}});
hotkeys.toggleFullscreenAlt = xml_hotkeys.get("ToggleFullscreenAlt", sHotkeyCfg{uKeyboardHotkey{WXK_CONTROL_M, true}}); // ALT+ENTER
hotkeys.takeScreenshot = xml_hotkeys.get("TakeScreenshot", sHotkeyCfg{uKeyboardHotkey{WXK_F12}});
hotkeys.toggleFastForward = xml_hotkeys.get("ToggleFastForward", sHotkeyCfg{});

// emulatedusbdevices
auto usbdevices = parser.get("EmulatedUsbDevices");
emulated_usb_devices.emulate_skylander_portal = usbdevices.get("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal);
Expand Down Expand Up @@ -544,6 +553,15 @@ void CemuConfig::Save(XMLConfigParser& parser)
dsuc.set_attribute("host", dsu_client.host);
dsuc.set_attribute("port", dsu_client.port);

// hotkeys
auto xml_hotkeys = config.set("Hotkeys");
xml_hotkeys.set("modifiers", hotkeys.modifiers);
xml_hotkeys.set("ExitFullscreen", hotkeys.exitFullscreen);
xml_hotkeys.set("ToggleFullscreen", hotkeys.toggleFullscreen);
xml_hotkeys.set("ToggleFullscreenAlt", hotkeys.toggleFullscreenAlt);
xml_hotkeys.set("TakeScreenshot", hotkeys.takeScreenshot);
xml_hotkeys.set("ToggleFastForward", hotkeys.toggleFastForward);

// emulated usb devices
auto usbdevices = config.set("EmulatedUsbDevices");
usbdevices.set("EmulateSkylanderPortal", emulated_usb_devices.emulate_skylander_portal.GetValue());
Expand Down
55 changes: 55 additions & 0 deletions src/config/CemuConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,50 @@ enum class CrashDump
ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled);
#endif

typedef union
{
struct
{
uint16 key : 13; // enough bits for all keycodes
uint16 alt : 1;
uint16 ctrl : 1;
uint16 shift : 1;
};
uint16 raw;
} uKeyboardHotkey;

typedef sint16 ControllerHotkey_t;

struct sHotkeyCfg
{
static constexpr uint8 keyboardNone{WXK_NONE};
static constexpr sint8 controllerNone{-1}; // no enums to work with, but buttons start from 0

uKeyboardHotkey keyboard{keyboardNone};
ControllerHotkey_t controller{controllerNone};

/* for defaults */
sHotkeyCfg(const uKeyboardHotkey& keyboard = {WXK_NONE}, const ControllerHotkey_t& controller = {-1}) :
keyboard(keyboard), controller(controller) {};

/* for reading from xml */
sHotkeyCfg(const char* xml_values)
{
std::istringstream iss(xml_values);
iss >> keyboard.raw >> controller;
}
};

template <>
struct fmt::formatter<sHotkeyCfg> : formatter<string_view>
{
template <typename FormatContext>
auto format(const sHotkeyCfg c, FormatContext &ctx) const {
std::string xml_values = fmt::format("{} {}", c.keyboard.raw, c.controller);
return formatter<string_view>::format(xml_values, ctx);
}
};

template <>
struct fmt::formatter<const PrecompiledShaderOption> : formatter<string_view> {
template <typename FormatContext>
Expand Down Expand Up @@ -499,6 +543,17 @@ struct CemuConfig
ConfigValue<uint16> port{ 26760 };
}dsu_client{};

// hotkeys
struct
{
sHotkeyCfg modifiers;
sHotkeyCfg toggleFullscreen;
sHotkeyCfg toggleFullscreenAlt;
sHotkeyCfg exitFullscreen;
sHotkeyCfg takeScreenshot;
sHotkeyCfg toggleFastForward;
} hotkeys{};

// debug
ConfigValueBounds<CrashDump> crash_dump{ CrashDump::Disabled };
ConfigValue<uint16> gdb_port{ 1337 };
Expand Down
5 changes: 4 additions & 1 deletion src/config/XMLConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <string>
#include <mutex>

template <typename T>
concept HasConstCharConstructor = requires { T(std::declval<const char*>()); };

class XMLConfigParser
{
public:
Expand Down Expand Up @@ -43,7 +46,7 @@ class XMLConfigParser
return element->Int64Text(default_value);
else if constexpr (std::is_same_v<T, uint64>) // doesnt support real uint64...
return (uint64)element->Int64Text((sint64)default_value);
else if constexpr (std::is_same_v<T, const char*> || std::is_same_v<T, std::string>)
else if constexpr (std::is_same_v<T, const char*> || std::is_same_v<T, std::string> || HasConstCharConstructor<T>)
{
const char* text = element->GetText();
return text ? text : default_value;
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ add_library(CemuGui
helpers/wxLogEvent.h
helpers/wxWayland.cpp
helpers/wxWayland.h
input/HotkeySettings.cpp
input/HotkeySettings.h
input/InputAPIAddWindow.cpp
input/InputAPIAddWindow.h
input/InputSettings2.cpp
Expand Down
3 changes: 3 additions & 0 deletions src/gui/CemuApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "input/InputManager.h"
#include "gui/helpers/wxHelpers.h"
#include "Cemu/ncrypto/ncrypto.h"
#include "gui/input/HotkeySettings.h"

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

HotkeySettings::Init(m_mainFrame);

SetTopWindow(m_mainFrame);
m_mainFrame->Show();

Expand Down
18 changes: 11 additions & 7 deletions src/gui/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "gui/helpers/wxHelpers.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VsyncDriver.h"
#include "gui/input/InputSettings2.h"
#include "gui/input/HotkeySettings.h"
#include "input/InputManager.h"

#if BOOST_OS_WINDOWS
Expand Down Expand Up @@ -91,6 +92,7 @@ enum
MAINFRAME_MENU_ID_OPTIONS_GENERAL2,
MAINFRAME_MENU_ID_OPTIONS_AUDIO,
MAINFRAME_MENU_ID_OPTIONS_INPUT,
MAINFRAME_MENU_ID_OPTIONS_HOTKEY,
// options -> account
MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_1 = 20350,
MAINFRAME_MENU_ID_OPTIONS_ACCOUNT_12 = 20350 + 11,
Expand Down Expand Up @@ -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_AUDIO, MainWindow::OnOptionsInput)
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_INPUT, MainWindow::OnOptionsInput)
EVT_MENU(MAINFRAME_MENU_ID_OPTIONS_HOTKEY, MainWindow::OnOptionsInput)
// tools menu
EVT_MENU(MAINFRAME_MENU_ID_TOOLS_MEMORY_SEARCHER, MainWindow::OnToolsInput)
EVT_MENU(MAINFRAME_MENU_ID_TOOLS_TITLE_MANAGER, MainWindow::OnToolsInput)
Expand Down Expand Up @@ -922,6 +925,12 @@ void MainWindow::OnOptionsInput(wxCommandEvent& event)
break;
}

case MAINFRAME_MENU_ID_OPTIONS_HOTKEY:
{
auto* frame = new HotkeySettings(this);
frame->Show();
break;
}
}
}

Expand Down Expand Up @@ -1437,13 +1446,7 @@ void MainWindow::OnKeyUp(wxKeyEvent& event)
if (swkbd_hasKeyboardInputHook())
return;

const auto code = event.GetKeyCode();
if (code == WXK_ESCAPE)
SetFullScreen(false);
else if (code == WXK_RETURN && event.AltDown() || code == WXK_F11)
SetFullScreen(!IsFullScreen());
else if (code == WXK_F12)
g_window_info.has_screenshot_request = true; // async screenshot request
HotkeySettings::CaptureInput(event);
}

void MainWindow::OnKeyDown(wxKeyEvent& event)
Expand Down Expand Up @@ -2159,6 +2162,7 @@ void MainWindow::RecreateMenu()
optionsMenu->AppendSeparator();
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_GENERAL2, _("&General settings"));
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_INPUT, _("&Input settings"));
optionsMenu->Append(MAINFRAME_MENU_ID_OPTIONS_HOTKEY, _("&Hotkey settings"));

optionsMenu->AppendSeparator();
optionsMenu->AppendSubMenu(m_optionsAccountMenu, _("&Active account"));
Expand Down
Loading
Loading