| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- // Copyright 2021 yuzu Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included
- #include <fmt/format.h>
- #include "core/hid/emulated_devices.h"
- #include "core/hid/input_converter.h"
- namespace Core::HID {
- EmulatedDevices::EmulatedDevices() = default;
- EmulatedDevices::~EmulatedDevices() = default;
- void EmulatedDevices::ReloadFromSettings() {
- const auto& mouse = Settings::values.mouse_buttons;
- for (std::size_t index = 0; index < mouse.size(); ++index) {
- mouse_button_params[index] = Common::ParamPackage(mouse[index]);
- }
- ReloadInput();
- }
- void EmulatedDevices::ReloadInput() {
- std::transform(mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_BEGIN,
- mouse_button_params.begin() + Settings::NativeMouseButton::MOUSE_HID_END,
- mouse_button_devices.begin(), Input::CreateDevice<Input::InputDevice>);
- std::transform(Settings::values.keyboard_keys.begin(), Settings::values.keyboard_keys.end(),
- keyboard_devices.begin(), Input::CreateDeviceFromString<Input::InputDevice>);
- std::transform(Settings::values.keyboard_mods.begin(), Settings::values.keyboard_mods.end(),
- keyboard_modifier_devices.begin(),
- Input::CreateDeviceFromString<Input::InputDevice>);
- for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
- if (!mouse_button_devices[index]) {
- continue;
- }
- Input::InputCallback button_callback{
- [this, index](Input::CallbackStatus callback) { SetMouseButton(callback, index); }};
- mouse_button_devices[index]->SetCallback(button_callback);
- }
- for (std::size_t index = 0; index < keyboard_devices.size(); ++index) {
- if (!keyboard_devices[index]) {
- continue;
- }
- Input::InputCallback button_callback{
- [this, index](Input::CallbackStatus callback) { SetKeyboardButton(callback, index); }};
- keyboard_devices[index]->SetCallback(button_callback);
- }
- for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) {
- if (!keyboard_modifier_devices[index]) {
- continue;
- }
- Input::InputCallback button_callback{[this, index](Input::CallbackStatus callback) {
- SetKeyboardModifier(callback, index);
- }};
- keyboard_modifier_devices[index]->SetCallback(button_callback);
- }
- }
- void EmulatedDevices::UnloadInput() {
- for (auto& button : mouse_button_devices) {
- button.reset();
- }
- for (auto& button : keyboard_devices) {
- button.reset();
- }
- for (auto& button : keyboard_modifier_devices) {
- button.reset();
- }
- }
- void EmulatedDevices::EnableConfiguration() {
- is_configuring = true;
- SaveCurrentConfig();
- }
- void EmulatedDevices::DisableConfiguration() {
- is_configuring = false;
- }
- bool EmulatedDevices::IsConfiguring() const {
- return is_configuring;
- }
- void EmulatedDevices::SaveCurrentConfig() {
- if (!is_configuring) {
- return;
- }
- auto& mouse = Settings::values.mouse_buttons;
- for (std::size_t index = 0; index < mouse.size(); ++index) {
- mouse[index] = mouse_button_params[index].Serialize();
- }
- }
- void EmulatedDevices::RestoreConfig() {
- if (!is_configuring) {
- return;
- }
- ReloadFromSettings();
- }
- Common::ParamPackage EmulatedDevices::GetMouseButtonParam(std::size_t index) const {
- if (index >= mouse_button_params.size()) {
- return {};
- }
- return mouse_button_params[index];
- }
- void EmulatedDevices::SetMouseButtonParam(std::size_t index, Common::ParamPackage param) {
- if (index >= mouse_button_params.size()) {
- return;
- }
- mouse_button_params[index] = param;
- ReloadInput();
- }
- void EmulatedDevices::SetKeyboardButton(Input::CallbackStatus callback, std::size_t index) {
- if (index >= device_status.keyboard_values.size()) {
- return;
- }
- std::lock_guard lock{mutex};
- bool value_changed = false;
- const auto new_status = TransformToButton(callback);
- auto& current_status = device_status.keyboard_values[index];
- current_status.toggle = new_status.toggle;
- // Update button status with current status
- if (!current_status.toggle) {
- current_status.locked = false;
- if (current_status.value != new_status.value) {
- current_status.value = new_status.value;
- value_changed = true;
- }
- } else {
- // Toggle button and lock status
- if (new_status.value && !current_status.locked) {
- current_status.locked = true;
- current_status.value = !current_status.value;
- value_changed = true;
- }
- // Unlock button, ready for next press
- if (!new_status.value && current_status.locked) {
- current_status.locked = false;
- }
- }
- if (!value_changed) {
- return;
- }
- if (is_configuring) {
- TriggerOnChange(DeviceTriggerType::Keyboard);
- return;
- }
- // TODO(german77): Do this properly
- // switch (index) {
- // case Settings::NativeKeyboard::A:
- // interface_status.keyboard_state.a.Assign(current_status.value);
- // break;
- // ....
- // }
- TriggerOnChange(DeviceTriggerType::Keyboard);
- }
- void EmulatedDevices::SetKeyboardModifier(Input::CallbackStatus callback, std::size_t index) {
- if (index >= device_status.keyboard_moddifier_values.size()) {
- return;
- }
- std::lock_guard lock{mutex};
- bool value_changed = false;
- const auto new_status = TransformToButton(callback);
- auto& current_status = device_status.keyboard_moddifier_values[index];
- current_status.toggle = new_status.toggle;
- // Update button status with current
- if (!current_status.toggle) {
- current_status.locked = false;
- if (current_status.value != new_status.value) {
- current_status.value = new_status.value;
- value_changed = true;
- }
- } else {
- // Toggle button and lock status
- if (new_status.value && !current_status.locked) {
- current_status.locked = true;
- current_status.value = !current_status.value;
- value_changed = true;
- }
- // Unlock button ready for next press
- if (!new_status.value && current_status.locked) {
- current_status.locked = false;
- }
- }
- if (!value_changed) {
- return;
- }
- if (is_configuring) {
- TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
- return;
- }
- switch (index) {
- case Settings::NativeKeyboard::LeftControl:
- case Settings::NativeKeyboard::RightControl:
- device_status.keyboard_moddifier_state.control.Assign(current_status.value);
- break;
- case Settings::NativeKeyboard::LeftShift:
- case Settings::NativeKeyboard::RightShift:
- device_status.keyboard_moddifier_state.shift.Assign(current_status.value);
- break;
- case Settings::NativeKeyboard::LeftAlt:
- device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value);
- break;
- case Settings::NativeKeyboard::RightAlt:
- device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value);
- break;
- case Settings::NativeKeyboard::CapsLock:
- device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value);
- break;
- case Settings::NativeKeyboard::ScrollLock:
- device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value);
- break;
- case Settings::NativeKeyboard::NumLock:
- device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value);
- break;
- }
- TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
- }
- void EmulatedDevices::SetMouseButton(Input::CallbackStatus callback, std::size_t index) {
- if (index >= device_status.mouse_button_values.size()) {
- return;
- }
- std::lock_guard lock{mutex};
- bool value_changed = false;
- const auto new_status = TransformToButton(callback);
- auto& current_status = device_status.mouse_button_values[index];
- current_status.toggle = new_status.toggle;
- // Update button status with current
- if (!current_status.toggle) {
- current_status.locked = false;
- if (current_status.value != new_status.value) {
- current_status.value = new_status.value;
- value_changed = true;
- }
- } else {
- // Toggle button and lock status
- if (new_status.value && !current_status.locked) {
- current_status.locked = true;
- current_status.value = !current_status.value;
- value_changed = true;
- }
- // Unlock button ready for next press
- if (!new_status.value && current_status.locked) {
- current_status.locked = false;
- }
- }
- if (!value_changed) {
- return;
- }
- if (is_configuring) {
- TriggerOnChange(DeviceTriggerType::Mouse);
- return;
- }
- switch (index) {
- case Settings::NativeMouseButton::Left:
- device_status.mouse_button_state.left.Assign(current_status.value);
- break;
- case Settings::NativeMouseButton::Right:
- device_status.mouse_button_state.right.Assign(current_status.value);
- break;
- case Settings::NativeMouseButton::Middle:
- device_status.mouse_button_state.middle.Assign(current_status.value);
- break;
- case Settings::NativeMouseButton::Forward:
- device_status.mouse_button_state.forward.Assign(current_status.value);
- break;
- case Settings::NativeMouseButton::Back:
- device_status.mouse_button_state.back.Assign(current_status.value);
- break;
- }
- TriggerOnChange(DeviceTriggerType::Mouse);
- }
- KeyboardValues EmulatedDevices::GetKeyboardValues() const {
- return device_status.keyboard_values;
- }
- KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const {
- return device_status.keyboard_moddifier_values;
- }
- MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const {
- return device_status.mouse_button_values;
- }
- KeyboardKey EmulatedDevices::GetKeyboard() const {
- return device_status.keyboard_state;
- }
- KeyboardModifier EmulatedDevices::GetKeyboardModifier() const {
- return device_status.keyboard_moddifier_state;
- }
- MouseButton EmulatedDevices::GetMouseButtons() const {
- return device_status.mouse_button_state;
- }
- MousePosition EmulatedDevices::GetMousePosition() const {
- return device_status.mouse_position_state;
- }
- void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
- for (const auto& poller_pair : callback_list) {
- const InterfaceUpdateCallback& poller = poller_pair.second;
- if (poller.on_change) {
- poller.on_change(type);
- }
- }
- }
- int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
- std::lock_guard lock{mutex};
- callback_list.insert_or_assign(last_callback_key, update_callback);
- return last_callback_key++;
- }
- void EmulatedDevices::DeleteCallback(int key) {
- std::lock_guard lock{mutex};
- if (!callback_list.contains(key)) {
- LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
- return;
- }
- callback_list.erase(key);
- }
- } // namespace Core::HID
|