From b673857d7dfc72f38d9242b315cd590b859795ff Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 13 Nov 2021 23:25:45 -0600 Subject: core/hid: Improve accuracy of the keyboard implementation --- src/common/settings_input.h | 35 +- src/core/hid/emulated_devices.cpp | 3 +- src/core/hid/hid_types.h | 398 +++++++++++++++------- src/core/hle/service/hid/controllers/keyboard.cpp | 1 + src/core/hle/service/hid/hid.cpp | 35 +- src/core/hle/service/hid/hid.h | 2 + src/input_common/drivers/keyboard.cpp | 53 ++- src/input_common/drivers/keyboard.h | 7 + src/input_common/main.cpp | 9 + src/input_common/main.h | 3 + src/yuzu/bootmanager.cpp | 276 ++++++++++++++- src/yuzu/bootmanager.h | 6 + src/yuzu/configuration/config.cpp | 167 +-------- 13 files changed, 682 insertions(+), 313 deletions(-) diff --git a/src/common/settings_input.h b/src/common/settings_input.h index 2c0eb31d3..a2982fca4 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h @@ -129,7 +129,6 @@ extern const std::array mapping; namespace NativeKeyboard { enum Keys { None, - Error, A = 4, B, @@ -167,22 +166,22 @@ enum Keys { N8, N9, N0, - Enter, + Return, Escape, Backspace, Tab, Space, Minus, - Equal, - LeftBrace, - RightBrace, - Backslash, + Plus, + OpenBracket, + CloseBracket, + Pipe, Tilde, Semicolon, - Apostrophe, - Grave, + Quote, + Backquote, Comma, - Dot, + Period, Slash, CapsLockKey, @@ -199,7 +198,7 @@ enum Keys { F11, F12, - SystemRequest, + PrintScreen, ScrollLockKey, Pause, Insert, @@ -268,8 +267,18 @@ enum Keys { ScrollLockActive, KPComma, - KPLeftParenthesis, - KPRightParenthesis, + Ro = 0x87, + KatakanaHiragana, + Yen, + Henkan, + Muhenkan, + NumPadCommaPc98, + + HangulEnglish = 0x90, + Hanja, + KatakanaKey, + HiraganaKey, + ZenkakuHankaku, LeftControlKey = 0xE0, LeftShiftKey, @@ -318,6 +327,8 @@ enum Modifiers { CapsLock, ScrollLock, NumLock, + Katakana, + Hiragana, NumKeyboardMods, }; diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index e97470240..0d840a003 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -170,13 +170,14 @@ void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, return; } + // Index should be converted from NativeKeyboard to KeyboardKeyIndex UpdateKey(index, current_status.value); TriggerOnChange(DeviceTriggerType::Keyboard); } void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) { - constexpr u8 KEYS_PER_BYTE = 8; + constexpr std::size_t KEYS_PER_BYTE = 8; auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE]; const u8 mask = static_cast(1 << (key_index % KEYS_PER_BYTE)); if (status) { diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 41bc65ce2..af95f3aff 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -12,6 +12,195 @@ namespace Core::HID { +enum class DeviceIndex : u8 { + Left = 0, + Right = 1, + None = 2, + MaxDeviceIndex = 3, +}; + +// This is nn::hid::NpadButton +enum class NpadButton : u64 { + None = 0, + A = 1U << 0, + B = 1U << 1, + X = 1U << 2, + Y = 1U << 3, + StickL = 1U << 4, + StickR = 1U << 5, + L = 1U << 6, + R = 1U << 7, + ZL = 1U << 8, + ZR = 1U << 9, + Plus = 1U << 10, + Minus = 1U << 11, + + Left = 1U << 12, + Up = 1U << 13, + Right = 1U << 14, + Down = 1U << 15, + + StickLLeft = 1U << 16, + StickLUp = 1U << 17, + StickLRight = 1U << 18, + StickLDown = 1U << 19, + + StickRLeft = 1U << 20, + StickRUp = 1U << 21, + StickRRight = 1U << 22, + StickRDown = 1U << 23, + + LeftSL = 1U << 24, + LeftSR = 1U << 25, + + RightSL = 1U << 26, + RightSR = 1U << 27, + + Palma = 1U << 28, + Verification = 1U << 29, + HandheldLeftB = 1U << 30, + LagonCLeft = 1U << 31, + LagonCUp = 1ULL << 32, + LagonCRight = 1ULL << 33, + LagonCDown = 1ULL << 34, +}; +DECLARE_ENUM_FLAG_OPERATORS(NpadButton); + +enum class KeyboardKeyIndex : u32 { + A = 4, + B = 5, + C = 6, + D = 7, + E = 8, + F = 9, + G = 10, + H = 11, + I = 12, + J = 13, + K = 14, + L = 15, + M = 16, + N = 17, + O = 18, + P = 19, + Q = 20, + R = 21, + S = 22, + T = 23, + U = 24, + V = 25, + W = 26, + X = 27, + Y = 28, + Z = 29, + D1 = 30, + D2 = 31, + D3 = 32, + D4 = 33, + D5 = 34, + D6 = 35, + D7 = 36, + D8 = 37, + D9 = 38, + D0 = 39, + Return = 40, + Escape = 41, + Backspace = 42, + Tab = 43, + Space = 44, + Minus = 45, + Plus = 46, + OpenBracket = 47, + CloseBracket = 48, + Pipe = 49, + Tilde = 50, + Semicolon = 51, + Quote = 52, + Backquote = 53, + Comma = 54, + Period = 55, + Slash = 56, + CapsLock = 57, + F1 = 58, + F2 = 59, + F3 = 60, + F4 = 61, + F5 = 62, + F6 = 63, + F7 = 64, + F8 = 65, + F9 = 66, + F10 = 67, + F11 = 68, + F12 = 69, + PrintScreen = 70, + ScrollLock = 71, + Pause = 72, + Insert = 73, + Home = 74, + PageUp = 75, + Delete = 76, + End = 77, + PageDown = 78, + RightArrow = 79, + LeftArrow = 80, + DownArrow = 81, + UpArrow = 82, + NumLock = 83, + NumPadDivide = 84, + NumPadMultiply = 85, + NumPadSubtract = 86, + NumPadAdd = 87, + NumPadEnter = 88, + NumPad1 = 89, + NumPad2 = 90, + NumPad3 = 91, + NumPad4 = 92, + NumPad5 = 93, + NumPad6 = 94, + NumPad7 = 95, + NumPad8 = 96, + NumPad9 = 97, + NumPad0 = 98, + NumPadDot = 99, + Backslash = 100, + Application = 101, + Power = 102, + NumPadEquals = 103, + F13 = 104, + F14 = 105, + F15 = 106, + F16 = 107, + F17 = 108, + F18 = 109, + F19 = 110, + F20 = 111, + F21 = 112, + F22 = 113, + F23 = 114, + F24 = 115, + NumPadComma = 133, + Ro = 135, + KatakanaHiragana = 136, + Yen = 137, + Henkan = 138, + Muhenkan = 139, + NumPadCommaPc98 = 140, + HangulEnglish = 144, + Hanja = 145, + Katakana = 146, + Hiragana = 147, + ZenkakuHankaku = 148, + LeftControl = 224, + LeftShift = 225, + LeftAlt = 226, + LeftGui = 227, + RightControl = 228, + RightShift = 229, + RightAlt = 230, + RightGui = 231, +}; + // This is nn::hid::NpadIdType enum class NpadIdType : u32 { Player1 = 0x0, @@ -28,62 +217,6 @@ enum class NpadIdType : u32 { Invalid = 0xFFFFFFFF, }; -/// Converts a NpadIdType to an array index. -constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { - switch (npad_id_type) { - case NpadIdType::Player1: - return 0; - case NpadIdType::Player2: - return 1; - case NpadIdType::Player3: - return 2; - case NpadIdType::Player4: - return 3; - case NpadIdType::Player5: - return 4; - case NpadIdType::Player6: - return 5; - case NpadIdType::Player7: - return 6; - case NpadIdType::Player8: - return 7; - case NpadIdType::Handheld: - return 8; - case NpadIdType::Other: - return 9; - default: - return 0; - } -} - -/// Converts an array index to a NpadIdType -constexpr NpadIdType IndexToNpadIdType(size_t index) { - switch (index) { - case 0: - return NpadIdType::Player1; - case 1: - return NpadIdType::Player2; - case 2: - return NpadIdType::Player3; - case 3: - return NpadIdType::Player4; - case 4: - return NpadIdType::Player5; - case 5: - return NpadIdType::Player6; - case 6: - return NpadIdType::Player7; - case 7: - return NpadIdType::Player8; - case 8: - return NpadIdType::Handheld; - case 9: - return NpadIdType::Other; - default: - return NpadIdType::Invalid; - } -} - // This is nn::hid::NpadStyleIndex enum class NpadStyleIndex : u8 { None = 0, @@ -124,6 +257,27 @@ enum class NpadStyleSet : u32 { }; static_assert(sizeof(NpadStyleSet) == 4, "NpadStyleSet is an invalid size"); +// This is nn::hid::VibrationDevicePosition +enum class VibrationDevicePosition : u32 { + None = 0, + Left = 1, + Right = 2, +}; + +// This is nn::hid::VibrationDeviceType +enum class VibrationDeviceType : u32 { + Unknown = 0, + LinearResonantActuator = 1, + GcErm = 2, +}; + +// This is nn::hid::VibrationGcErmCommand +enum class VibrationGcErmCommand : u64 { + Stop = 0, + Start = 1, + StopHard = 2, +}; + // This is nn::hid::NpadStyleTag struct NpadStyleTag { union { @@ -220,53 +374,6 @@ struct LedPattern { }; }; -// This is nn::hid::NpadButton -enum class NpadButton : u64 { - None = 0, - A = 1U << 0, - B = 1U << 1, - X = 1U << 2, - Y = 1U << 3, - StickL = 1U << 4, - StickR = 1U << 5, - L = 1U << 6, - R = 1U << 7, - ZL = 1U << 8, - ZR = 1U << 9, - Plus = 1U << 10, - Minus = 1U << 11, - - Left = 1U << 12, - Up = 1U << 13, - Right = 1U << 14, - Down = 1U << 15, - - StickLLeft = 1U << 16, - StickLUp = 1U << 17, - StickLRight = 1U << 18, - StickLDown = 1U << 19, - - StickRLeft = 1U << 20, - StickRUp = 1U << 21, - StickRRight = 1U << 22, - StickRDown = 1U << 23, - - LeftSL = 1U << 24, - LeftSR = 1U << 25, - - RightSL = 1U << 26, - RightSR = 1U << 27, - - Palma = 1U << 28, - Verification = 1U << 29, - HandheldLeftB = 1U << 30, - LagonCLeft = 1U << 31, - LagonCUp = 1ULL << 32, - LagonCRight = 1ULL << 33, - LagonCDown = 1ULL << 34, -}; -DECLARE_ENUM_FLAG_OPERATORS(NpadButton); - struct NpadButtonState { union { NpadButton raw{}; @@ -342,13 +449,6 @@ struct DebugPadButton { }; static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"); -enum class DeviceIndex : u8 { - Left = 0, - Right = 1, - None = 2, - MaxDeviceIndex = 3, -}; - // This is nn::hid::ConsoleSixAxisSensorHandle struct ConsoleSixAxisSensorHandle { u8 unknown_1; @@ -383,20 +483,6 @@ struct VibrationDeviceHandle { }; static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size"); -// This is nn::hid::VibrationDeviceType -enum class VibrationDeviceType : u32 { - Unknown = 0, - LinearResonantActuator = 1, - GcErm = 2, -}; - -// This is nn::hid::VibrationDevicePosition -enum class VibrationDevicePosition : u32 { - None = 0, - Left = 1, - Right = 2, -}; - // This is nn::hid::VibrationValue struct VibrationValue { f32 low_amplitude; @@ -406,13 +492,6 @@ struct VibrationValue { }; static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); -// This is nn::hid::VibrationGcErmCommand -enum class VibrationGcErmCommand : u64 { - Stop = 0, - Start = 1, - StopHard = 2, -}; - // This is nn::hid::VibrationDeviceInfo struct VibrationDeviceInfo { VibrationDeviceType type{}; @@ -482,4 +561,61 @@ struct MouseState { MouseAttribute attribute; }; static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); + +/// Converts a NpadIdType to an array index. +constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { + switch (npad_id_type) { + case NpadIdType::Player1: + return 0; + case NpadIdType::Player2: + return 1; + case NpadIdType::Player3: + return 2; + case NpadIdType::Player4: + return 3; + case NpadIdType::Player5: + return 4; + case NpadIdType::Player6: + return 5; + case NpadIdType::Player7: + return 6; + case NpadIdType::Player8: + return 7; + case NpadIdType::Handheld: + return 8; + case NpadIdType::Other: + return 9; + default: + return 0; + } +} + +/// Converts an array index to a NpadIdType +constexpr NpadIdType IndexToNpadIdType(size_t index) { + switch (index) { + case 0: + return NpadIdType::Player1; + case 1: + return NpadIdType::Player2; + case 2: + return NpadIdType::Player3; + case 3: + return NpadIdType::Player4; + case 4: + return NpadIdType::Player5; + case 5: + return NpadIdType::Player6; + case 6: + return NpadIdType::Player7; + case 7: + return NpadIdType::Player8; + case 8: + return NpadIdType::Handheld; + case 9: + return NpadIdType::Other; + default: + return NpadIdType::Invalid; + } +} + } // namespace Core::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index d6505dbc5..0ef8af0e6 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -42,6 +42,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, next_state.key = keyboard_state; next_state.modifier = keyboard_modifier_state; + // This is always enabled on HW. Check what it actually does next_state.modifier.unknown.Assign(1); } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 496b55d0e..e740b4331 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -35,8 +35,9 @@ namespace Service::HID { // Updating period for each HID device. // Period time is obtained by measuring the number of samples in a second on HW using a homebrew -constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) -constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) +constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000}; // (4ms, 250Hz) +constexpr auto keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz) +constexpr auto motion_update_ns = std::chrono::nanoseconds{5 * 1000 * 1000}; // (5ms, 200Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; IAppletResource::IAppletResource(Core::System& system_, @@ -78,14 +79,21 @@ IAppletResource::IAppletResource(Core::System& system_, const auto guard = LockService(); UpdateControllers(user_data, ns_late); }); + keyboard_update_event = Core::Timing::CreateEvent( + "HID::UpdatekeyboardCallback", + [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + const auto guard = LockService(); + UpdateKeyboard(user_data, ns_late); + }); motion_update_event = Core::Timing::CreateEvent( - "HID::MotionPadCallback", + "HID::UpdateMotionCallback", [this](std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { const auto guard = LockService(); UpdateMotion(user_data, ns_late); }); system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); + system.CoreTiming().ScheduleEvent(keyboard_update_ns, keyboard_update_event); system.CoreTiming().ScheduleEvent(motion_update_ns, motion_update_event); system.HIDCore().ReloadInputDevices(); @@ -101,6 +109,7 @@ void IAppletResource::DeactivateController(HidController controller) { IAppletResource::~IAppletResource() { system.CoreTiming().UnscheduleEvent(pad_update_event, 0); + system.CoreTiming().UnscheduleEvent(keyboard_update_event, 0); system.CoreTiming().UnscheduleEvent(motion_update_event, 0); } @@ -117,18 +126,36 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data, auto& core_timing = system.CoreTiming(); for (const auto& controller : controllers) { + // Keyboard has it's own update event + if (controller == controllers[static_cast(HidController::Keyboard)]) { + continue; + } controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); } // If ns_late is higher than the update rate ignore the delay - if (ns_late > motion_update_ns) { + if (ns_late > pad_update_ns) { ns_late = {}; } core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); } +void IAppletResource::UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { + auto& core_timing = system.CoreTiming(); + + controllers[static_cast(HidController::Keyboard)]->OnUpdate( + core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); + + // If ns_late is higher than the update rate ignore the delay + if (ns_late > keyboard_update_ns) { + ns_late = {}; + } + + core_timing.ScheduleEvent(keyboard_update_ns - ns_late, keyboard_update_event); +} + void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { auto& core_timing = system.CoreTiming(); diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 973e6a8ac..bbad165f8 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -70,11 +70,13 @@ private: void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); + void UpdateKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); KernelHelpers::ServiceContext& service_context; std::shared_ptr pad_update_event; + std::shared_ptr keyboard_update_event; std::shared_ptr motion_update_event; std::array, static_cast(HidController::MaxControllers)> diff --git a/src/input_common/drivers/keyboard.cpp b/src/input_common/drivers/keyboard.cpp index 549704e89..328fe1ac1 100644 --- a/src/input_common/drivers/keyboard.cpp +++ b/src/input_common/drivers/keyboard.cpp @@ -3,26 +3,71 @@ // Refer to the license.txt file included #include "common/param_package.h" +#include "common/settings_input.h" #include "input_common/drivers/keyboard.h" namespace InputCommon { -constexpr PadIdentifier identifier = { +constexpr PadIdentifier key_identifier = { .guid = Common::UUID{Common::INVALID_UUID}, .port = 0, .pad = 0, }; +constexpr PadIdentifier modifier_identifier = { + .guid = Common::UUID{Common::INVALID_UUID}, + .port = 0, + .pad = 1, +}; Keyboard::Keyboard(const std::string& input_engine_) : InputEngine(input_engine_) { - PreSetController(identifier); + PreSetController(key_identifier); + PreSetController(modifier_identifier); } void Keyboard::PressKey(int key_code) { - SetButton(identifier, key_code, true); + SetButton(key_identifier, key_code, true); } void Keyboard::ReleaseKey(int key_code) { - SetButton(identifier, key_code, false); + SetButton(key_identifier, key_code, false); +} + +void Keyboard::SetModifiers(int key_modifiers) { + for (int i = 0; i < 32; ++i) { + bool key_value = ((key_modifiers >> i) & 0x1) != 0; + SetButton(modifier_identifier, i, key_value); + // Use the modifier to press the key button equivalent + switch (i) { + case Settings::NativeKeyboard::LeftControl: + SetButton(key_identifier, Settings::NativeKeyboard::LeftControlKey, key_value); + break; + case Settings::NativeKeyboard::LeftShift: + SetButton(key_identifier, Settings::NativeKeyboard::LeftShiftKey, key_value); + break; + case Settings::NativeKeyboard::LeftAlt: + SetButton(key_identifier, Settings::NativeKeyboard::LeftAltKey, key_value); + break; + case Settings::NativeKeyboard::LeftMeta: + SetButton(key_identifier, Settings::NativeKeyboard::LeftMetaKey, key_value); + break; + case Settings::NativeKeyboard::RightControl: + SetButton(key_identifier, Settings::NativeKeyboard::RightControlKey, key_value); + break; + case Settings::NativeKeyboard::RightShift: + SetButton(key_identifier, Settings::NativeKeyboard::RightShiftKey, key_value); + break; + case Settings::NativeKeyboard::RightAlt: + SetButton(key_identifier, Settings::NativeKeyboard::RightAltKey, key_value); + break; + case Settings::NativeKeyboard::RightMeta: + SetButton(key_identifier, Settings::NativeKeyboard::RightMetaKey, key_value); + break; + default: + // Other modifier keys should be pressed with PressKey since they stay enabled until + // next press + break; + } + } } void Keyboard::ReleaseAllKeys() { diff --git a/src/input_common/drivers/keyboard.h b/src/input_common/drivers/keyboard.h index 46fe78576..2ab92fd6c 100644 --- a/src/input_common/drivers/keyboard.h +++ b/src/input_common/drivers/keyboard.h @@ -28,6 +28,13 @@ public: */ void ReleaseKey(int key_code); + /** + * Sets the status of all keyboard modifier keys + * @param key_modifiers the code of the key to release + */ + void SetModifiers(int key_modifiers); + + /// Sets all keys to the non pressed state void ReleaseAllKeys(); /// Used for automapping features diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index df36a337c..ae2518f53 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -402,6 +402,15 @@ std::string GenerateKeyboardParam(int key_code) { return param.Serialize(); } +std::string GenerateModdifierKeyboardParam(int key_code) { + Common::ParamPackage param; + param.Set("engine", "keyboard"); + param.Set("code", key_code); + param.Set("toggle", false); + param.Set("pad", 1); + return param.Serialize(); +} + std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, int key_modifier, float modifier_scale) { Common::ParamPackage circle_pad_param{ diff --git a/src/input_common/main.h b/src/input_common/main.h index a4a24d076..9ea395465 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h @@ -134,6 +134,9 @@ private: /// Generates a serialized param package for creating a keyboard button device. std::string GenerateKeyboardParam(int key_code); +/// Generates a serialized param package for creating a moddifier keyboard button device. +std::string GenerateModdifierKeyboardParam(int key_code); + /// Generates a serialized param package for creating an analog device taking input from keyboard. std::string GenerateAnalogParamFromKeys(int key_up, int key_down, int key_left, int key_right, int key_modifier, float modifier_scale); diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 3c5590a01..61513a5b4 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -392,15 +392,287 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { QWidget::closeEvent(event); } +int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { + switch (qt_key) { + case Qt::Key_A: + return Settings::NativeKeyboard::A; + case Qt::Key_B: + return Settings::NativeKeyboard::B; + case Qt::Key_C: + return Settings::NativeKeyboard::C; + case Qt::Key_D: + return Settings::NativeKeyboard::D; + case Qt::Key_E: + return Settings::NativeKeyboard::E; + case Qt::Key_F: + return Settings::NativeKeyboard::F; + case Qt::Key_G: + return Settings::NativeKeyboard::G; + case Qt::Key_H: + return Settings::NativeKeyboard::H; + case Qt::Key_I: + return Settings::NativeKeyboard::I; + case Qt::Key_J: + return Settings::NativeKeyboard::J; + case Qt::Key_K: + return Settings::NativeKeyboard::K; + case Qt::Key_L: + return Settings::NativeKeyboard::L; + case Qt::Key_M: + return Settings::NativeKeyboard::M; + case Qt::Key_N: + return Settings::NativeKeyboard::N; + case Qt::Key_O: + return Settings::NativeKeyboard::O; + case Qt::Key_P: + return Settings::NativeKeyboard::P; + case Qt::Key_Q: + return Settings::NativeKeyboard::Q; + case Qt::Key_R: + return Settings::NativeKeyboard::R; + case Qt::Key_S: + return Settings::NativeKeyboard::S; + case Qt::Key_T: + return Settings::NativeKeyboard::T; + case Qt::Key_U: + return Settings::NativeKeyboard::U; + case Qt::Key_V: + return Settings::NativeKeyboard::V; + case Qt::Key_W: + return Settings::NativeKeyboard::W; + case Qt::Key_X: + return Settings::NativeKeyboard::X; + case Qt::Key_Y: + return Settings::NativeKeyboard::Y; + case Qt::Key_Z: + return Settings::NativeKeyboard::Z; + case Qt::Key_1: + return Settings::NativeKeyboard::N1; + case Qt::Key_2: + return Settings::NativeKeyboard::N2; + case Qt::Key_3: + return Settings::NativeKeyboard::N3; + case Qt::Key_4: + return Settings::NativeKeyboard::N4; + case Qt::Key_5: + return Settings::NativeKeyboard::N5; + case Qt::Key_6: + return Settings::NativeKeyboard::N6; + case Qt::Key_7: + return Settings::NativeKeyboard::N7; + case Qt::Key_8: + return Settings::NativeKeyboard::N8; + case Qt::Key_9: + return Settings::NativeKeyboard::N9; + case Qt::Key_0: + return Settings::NativeKeyboard::N0; + case Qt::Key_Return: + return Settings::NativeKeyboard::Return; + case Qt::Key_Escape: + return Settings::NativeKeyboard::Escape; + case Qt::Key_Backspace: + return Settings::NativeKeyboard::Backspace; + case Qt::Key_Tab: + return Settings::NativeKeyboard::Tab; + case Qt::Key_Space: + return Settings::NativeKeyboard::Space; + case Qt::Key_Minus: + return Settings::NativeKeyboard::Minus; + case Qt::Key_Plus: + case Qt::Key_questiondown: + return Settings::NativeKeyboard::Plus; + case Qt::Key_BracketLeft: + case Qt::Key_BraceLeft: + return Settings::NativeKeyboard::OpenBracket; + case Qt::Key_BracketRight: + case Qt::Key_BraceRight: + return Settings::NativeKeyboard::CloseBracket; + case Qt::Key_Bar: + return Settings::NativeKeyboard::Pipe; + case Qt::Key_Dead_Tilde: + return Settings::NativeKeyboard::Tilde; + case Qt::Key_Ntilde: + case Qt::Key_Semicolon: + return Settings::NativeKeyboard::Semicolon; + case Qt::Key_Apostrophe: + return Settings::NativeKeyboard::Quote; + case Qt::Key_Dead_Grave: + return Settings::NativeKeyboard::Backquote; + case Qt::Key_Comma: + return Settings::NativeKeyboard::Comma; + case Qt::Key_Period: + return Settings::NativeKeyboard::Period; + case Qt::Key_Slash: + return Settings::NativeKeyboard::Slash; + case Qt::Key_CapsLock: + return Settings::NativeKeyboard::CapsLock; + case Qt::Key_F1: + return Settings::NativeKeyboard::F1; + case Qt::Key_F2: + return Settings::NativeKeyboard::F2; + case Qt::Key_F3: + return Settings::NativeKeyboard::F3; + case Qt::Key_F4: + return Settings::NativeKeyboard::F4; + case Qt::Key_F5: + return Settings::NativeKeyboard::F5; + case Qt::Key_F6: + return Settings::NativeKeyboard::F6; + case Qt::Key_F7: + return Settings::NativeKeyboard::F7; + case Qt::Key_F8: + return Settings::NativeKeyboard::F8; + case Qt::Key_F9: + return Settings::NativeKeyboard::F9; + case Qt::Key_F10: + return Settings::NativeKeyboard::F10; + case Qt::Key_F11: + return Settings::NativeKeyboard::F11; + case Qt::Key_F12: + return Settings::NativeKeyboard::F12; + case Qt::Key_Print: + return Settings::NativeKeyboard::PrintScreen; + case Qt::Key_ScrollLock: + return Settings::NativeKeyboard::ScrollLock; + case Qt::Key_Pause: + return Settings::NativeKeyboard::Pause; + case Qt::Key_Insert: + return Settings::NativeKeyboard::Insert; + case Qt::Key_Home: + return Settings::NativeKeyboard::Home; + case Qt::Key_PageUp: + return Settings::NativeKeyboard::PageUp; + case Qt::Key_Delete: + return Settings::NativeKeyboard::Delete; + case Qt::Key_End: + return Settings::NativeKeyboard::End; + case Qt::Key_PageDown: + return Settings::NativeKeyboard::PageDown; + case Qt::Key_Right: + return Settings::NativeKeyboard::Right; + case Qt::Key_Left: + return Settings::NativeKeyboard::Left; + case Qt::Key_Down: + return Settings::NativeKeyboard::Down; + case Qt::Key_Up: + return Settings::NativeKeyboard::Up; + case Qt::Key_NumLock: + return Settings::NativeKeyboard::NumLock; + // Numpad keys are missing here + case Qt::Key_F13: + return Settings::NativeKeyboard::F13; + case Qt::Key_F14: + return Settings::NativeKeyboard::F14; + case Qt::Key_F15: + return Settings::NativeKeyboard::F15; + case Qt::Key_F16: + return Settings::NativeKeyboard::F16; + case Qt::Key_F17: + return Settings::NativeKeyboard::F17; + case Qt::Key_F18: + return Settings::NativeKeyboard::F18; + case Qt::Key_F19: + return Settings::NativeKeyboard::F19; + case Qt::Key_F20: + return Settings::NativeKeyboard::F20; + case Qt::Key_F21: + return Settings::NativeKeyboard::F21; + case Qt::Key_F22: + return Settings::NativeKeyboard::F22; + case Qt::Key_F23: + return Settings::NativeKeyboard::F23; + case Qt::Key_F24: + return Settings::NativeKeyboard::F24; + // case Qt::: + // return Settings::NativeKeyboard::KPComma; + // case Qt::: + // return Settings::NativeKeyboard::Ro; + case Qt::Key_Hiragana_Katakana: + return Settings::NativeKeyboard::KatakanaHiragana; + case Qt::Key_yen: + return Settings::NativeKeyboard::Yen; + case Qt::Key_Henkan: + return Settings::NativeKeyboard::Henkan; + case Qt::Key_Muhenkan: + return Settings::NativeKeyboard::Muhenkan; + // case Qt::: + // return Settings::NativeKeyboard::NumPadCommaPc98; + case Qt::Key_Hangul: + return Settings::NativeKeyboard::HangulEnglish; + case Qt::Key_Hangul_Hanja: + return Settings::NativeKeyboard::Hanja; + case Qt::Key_Katakana: + return Settings::NativeKeyboard::KatakanaKey; + case Qt::Key_Hiragana: + return Settings::NativeKeyboard::HiraganaKey; + case Qt::Key_Zenkaku_Hankaku: + return Settings::NativeKeyboard::ZenkakuHankaku; + // Modifier keys are handled by the modifier property + default: + return 0; + } +} + +int GRenderWindow::QtModifierToSwitchModdifier(quint32 qt_moddifiers) { + int moddifier = 0; + // The values are obtained through testing, Qt doesn't seem to provide a proper enum + if ((qt_moddifiers & 0x1) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftShift; + } + if ((qt_moddifiers & 0x2) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftControl; + } + if ((qt_moddifiers & 0x4) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftAlt; + } + if ((qt_moddifiers & 0x08) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::LeftMeta; + } + if ((qt_moddifiers & 0x10) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightShift; + } + if ((qt_moddifiers & 0x20) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightControl; + } + if ((qt_moddifiers & 0x40) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightAlt; + } + if ((qt_moddifiers & 0x80) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::RightMeta; + } + if ((qt_moddifiers & 0x100) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::CapsLock; + } + if ((qt_moddifiers & 0x200) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::NumLock; + } + // Verify the last two keys + if ((qt_moddifiers & 0x400) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::Katakana; + } + if ((qt_moddifiers & 0x800) != 0) { + moddifier |= 1 << Settings::NativeKeyboard::Hiragana; + } + return moddifier; +} + void GRenderWindow::keyPressEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { - input_subsystem->GetKeyboard()->PressKey(event->key()); + const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); + // Replace event->key() with event->nativeVirtualKey() since the second one provides raw key + // buttons + const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); + input_subsystem->GetKeyboard()->SetModifiers(moddifier); + input_subsystem->GetKeyboard()->PressKey(key); } } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { if (!event->isAutoRepeat()) { - input_subsystem->GetKeyboard()->ReleaseKey(event->key()); + const auto moddifier = QtModifierToSwitchModdifier(event->nativeModifiers()); + const auto key = QtKeyToSwitchKey(Qt::Key(event->key())); + input_subsystem->GetKeyboard()->SetModifiers(moddifier); + input_subsystem->GetKeyboard()->ReleaseKey(key); } } diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 95594f81c..c42d139be 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -158,6 +158,12 @@ public: void resizeEvent(QResizeEvent* event) override; + /// Converts a Qt keybard key into NativeKeyboard key + static int QtKeyToSwitchKey(Qt::Key qt_keys); + + /// Converts a Qt modifier keys into NativeKeyboard modifier keys + static int QtModifierToSwitchModdifier(quint32 qt_moddifiers); + void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 7669fe474..ccf274895 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -65,157 +65,6 @@ const std::array Config::defa Qt::Key_BracketLeft, Qt::Key_BracketRight, Qt::Key_Apostrophe, Qt::Key_Minus, Qt::Key_Equal, }; -const std::array Config::default_keyboard_keys = { - 0, - 0, - 0, - 0, - Qt::Key_A, - Qt::Key_B, - Qt::Key_C, - Qt::Key_D, - Qt::Key_E, - Qt::Key_F, - Qt::Key_G, - Qt::Key_H, - Qt::Key_I, - Qt::Key_J, - Qt::Key_K, - Qt::Key_L, - Qt::Key_M, - Qt::Key_N, - Qt::Key_O, - Qt::Key_P, - Qt::Key_Q, - Qt::Key_R, - Qt::Key_S, - Qt::Key_T, - Qt::Key_U, - Qt::Key_V, - Qt::Key_W, - Qt::Key_X, - Qt::Key_Y, - Qt::Key_Z, - Qt::Key_1, - Qt::Key_2, - Qt::Key_3, - Qt::Key_4, - Qt::Key_5, - Qt::Key_6, - Qt::Key_7, - Qt::Key_8, - Qt::Key_9, - Qt::Key_0, - Qt::Key_Enter, - Qt::Key_Escape, - Qt::Key_Backspace, - Qt::Key_Tab, - Qt::Key_Space, - Qt::Key_Minus, - Qt::Key_Equal, - Qt::Key_BracketLeft, - Qt::Key_BracketRight, - Qt::Key_Backslash, - Qt::Key_Dead_Tilde, - Qt::Key_Semicolon, - Qt::Key_Apostrophe, - Qt::Key_Dead_Grave, - Qt::Key_Comma, - Qt::Key_Period, - Qt::Key_Slash, - Qt::Key_CapsLock, - - Qt::Key_F1, - Qt::Key_F2, - Qt::Key_F3, - Qt::Key_F4, - Qt::Key_F5, - Qt::Key_F6, - Qt::Key_F7, - Qt::Key_F8, - Qt::Key_F9, - Qt::Key_F10, - Qt::Key_F11, - Qt::Key_F12, - - Qt::Key_SysReq, - Qt::Key_ScrollLock, - Qt::Key_Pause, - Qt::Key_Insert, - Qt::Key_Home, - Qt::Key_PageUp, - Qt::Key_Delete, - Qt::Key_End, - Qt::Key_PageDown, - Qt::Key_Right, - Qt::Key_Left, - Qt::Key_Down, - Qt::Key_Up, - - Qt::Key_NumLock, - Qt::Key_Slash, - Qt::Key_Asterisk, - Qt::Key_Minus, - Qt::Key_Plus, - Qt::Key_Enter, - Qt::Key_1, - Qt::Key_2, - Qt::Key_3, - Qt::Key_4, - Qt::Key_5, - Qt::Key_6, - Qt::Key_7, - Qt::Key_8, - Qt::Key_9, - Qt::Key_0, - Qt::Key_Period, - - 0, - 0, - Qt::Key_PowerOff, - Qt::Key_Equal, - - Qt::Key_F13, - Qt::Key_F14, - Qt::Key_F15, - Qt::Key_F16, - Qt::Key_F17, - Qt::Key_F18, - Qt::Key_F19, - Qt::Key_F20, - Qt::Key_F21, - Qt::Key_F22, - Qt::Key_F23, - Qt::Key_F24, - - Qt::Key_Open, - Qt::Key_Help, - Qt::Key_Menu, - 0, - Qt::Key_Stop, - Qt::Key_AudioRepeat, - Qt::Key_Undo, - Qt::Key_Cut, - Qt::Key_Copy, - Qt::Key_Paste, - Qt::Key_Find, - Qt::Key_VolumeMute, - Qt::Key_VolumeUp, - Qt::Key_VolumeDown, - Qt::Key_CapsLock, - Qt::Key_NumLock, - Qt::Key_ScrollLock, - Qt::Key_Comma, - - Qt::Key_ParenLeft, - Qt::Key_ParenRight, -}; - -const std::array Config::default_keyboard_mods = { - Qt::Key_Control, Qt::Key_Shift, Qt::Key_Alt, Qt::Key_ApplicationLeft, - Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, -}; - // This shouldn't have anything except static initializers (no functions). So // QKeySequence(...).toString() is NOT ALLOWED HERE. // This must be in alphabetical order according to action name as it must have the same order as @@ -496,14 +345,14 @@ void Config::ReadDebugValues() { void Config::ReadKeyboardValues() { ReadBasicSetting(Settings::values.keyboard_enabled); - std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), - Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_keys.begin() + - Settings::NativeKeyboard::LeftControlKey, - InputCommon::GenerateKeyboardParam); - std::transform(default_keyboard_mods.begin(), default_keyboard_mods.end(), - Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); + for (std::size_t i = 0; i < Settings::values.keyboard_keys.size(); ++i) { + Settings::values.keyboard_keys[i] = InputCommon::GenerateKeyboardParam(static_cast(i)); + } + + for (std::size_t i = 0; i < Settings::values.keyboard_mods.size(); ++i) { + Settings::values.keyboard_mods[i] = + InputCommon::GenerateModdifierKeyboardParam(static_cast(i)); + } } void Config::ReadMouseValues() { -- cgit v1.2.3