From 1f228c51ca2c510622f4204937f90c7f2bbc7bf6 Mon Sep 17 00:00:00 2001 From: german Date: Fri, 5 Mar 2021 19:21:04 -0600 Subject: [PATCH 1/3] Enable button toggle for keyboard in the modifier button --- src/input_common/keyboard.cpp | 29 +++++++++++++++++-- src/yuzu/bootmanager.cpp | 8 +++-- .../configuration/configure_input_player.cpp | 13 ++++++++- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/input_common/keyboard.cpp b/src/input_common/keyboard.cpp index 24a6f7a33..fa0e60ac1 100644 --- a/src/input_common/keyboard.cpp +++ b/src/input_common/keyboard.cpp @@ -12,20 +12,37 @@ namespace InputCommon { class KeyButton final : public Input::ButtonDevice { public: - explicit KeyButton(std::shared_ptr key_button_list_) - : key_button_list(std::move(key_button_list_)) {} + explicit KeyButton(std::shared_ptr key_button_list_, bool toggle_) + : key_button_list(std::move(key_button_list_)), toggle(toggle_) {} ~KeyButton() override; bool GetStatus() const override { + if (toggle) { + return toggled_status.load(); + } return status.load(); } + void ToggleButton() { + if (!lock) { + lock = true; + toggled_status.store(!toggled_status.load()); + } + } + + void UnlockButton() { + lock = false; + } + friend class KeyButtonList; private: std::shared_ptr key_button_list; std::atomic status{false}; + std::atomic toggled_status{false}; + bool lock = {}; + const bool toggle; }; struct KeyButtonPair { @@ -51,6 +68,11 @@ public: for (const KeyButtonPair& pair : list) { if (pair.key_code == key_code) { pair.key_button->status.store(pressed); + if (pressed) { + pair.key_button->ToggleButton(); + } else { + pair.key_button->UnlockButton(); + } } } } @@ -75,7 +97,8 @@ KeyButton::~KeyButton() { std::unique_ptr Keyboard::Create(const Common::ParamPackage& params) { const int key_code = params.Get("code", 0); - std::unique_ptr button = std::make_unique(key_button_list); + const bool toggle = params.Get("toggle", false); + std::unique_ptr button = std::make_unique(key_button_list, toggle); key_button_list->AddKeyButton(key_code, button.get()); return button; } diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 1c61d419d..50938fb04 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -376,11 +376,15 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { } void GRenderWindow::keyPressEvent(QKeyEvent* event) { - input_subsystem->GetKeyboard()->PressKey(event->key()); + if (!event->isAutoRepeat()) { + input_subsystem->GetKeyboard()->PressKey(event->key()); + } } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { - input_subsystem->GetKeyboard()->ReleaseKey(event->key()); + if (!event->isAutoRepeat()) { + input_subsystem->GetKeyboard()->ReleaseKey(event->key()); + } } void GRenderWindow::mousePressEvent(QMouseEvent* event) { diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 21d0d3449..e297eeffd 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -104,7 +104,9 @@ QString ButtonToText(const Common::ParamPackage& param) { } if (param.Get("engine", "") == "keyboard") { - return GetKeyName(param.Get("code", 0)); + const QString button_str = GetKeyName(param.Get("code", 0)); + const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); + return QObject::tr("%1%2").arg(toggle, button_str); } if (param.Get("engine", "") == "gcpad") { @@ -412,6 +414,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i analogs_param[analog_id].Set("modifier", ""); analog_map_modifier_button[analog_id]->setText(tr("[not set]")); }); + context_menu.addAction(tr("Toggle button"), [&] { + Common::ParamPackage modifier_param = + Common::ParamPackage{analogs_param[analog_id].Get("modifier", "")}; + const bool toggle_value = !modifier_param.Get("toggle", false); + modifier_param.Set("toggle", toggle_value); + analogs_param[analog_id].Set("modifier", modifier_param.Serialize()); + analog_map_modifier_button[analog_id]->setText( + ButtonToText(modifier_param)); + }); context_menu.exec( analog_map_modifier_button[analog_id]->mapToGlobal(menu_location)); }); From 4bcc5bacffb21e1f6c2859ba26faf865aaea8855 Mon Sep 17 00:00:00 2001 From: german Date: Sat, 6 Mar 2021 07:36:41 -0600 Subject: [PATCH 2/3] Add toggle button option for normal buttons --- src/yuzu/configuration/configure_input_player.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index e297eeffd..bd53f2cde 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -302,6 +302,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i buttons_param[button_id].Clear(); button_map[button_id]->setText(tr("[not set]")); }); + context_menu.addAction(tr("Toggle button"), [&] { + const bool toggle_value = !buttons_param[button_id].Get("toggle", false); + buttons_param[button_id].Set("toggle", toggle_value); + button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); + }); context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); ui->controllerFrame->SetPlayerInput(player_index, buttons_param, analogs_param); }); From 41e94b7b99f83a45633d555160b31b50f021c350 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 6 Mar 2021 13:27:02 -0600 Subject: [PATCH 3/3] Enable mouse toggle buttons --- src/input_common/keyboard.cpp | 12 ++++--- src/input_common/mouse/mouse_input.cpp | 36 +++++++++++++++++++ src/input_common/mouse/mouse_input.h | 5 +++ src/input_common/mouse/mouse_poller.cpp | 20 ++++++++--- .../configuration/configure_input_player.cpp | 3 +- 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/input_common/keyboard.cpp b/src/input_common/keyboard.cpp index fa0e60ac1..c467ff4c5 100644 --- a/src/input_common/keyboard.cpp +++ b/src/input_common/keyboard.cpp @@ -19,16 +19,18 @@ public: bool GetStatus() const override { if (toggle) { - return toggled_status.load(); + return toggled_status.load(std::memory_order_relaxed); } return status.load(); } void ToggleButton() { - if (!lock) { - lock = true; - toggled_status.store(!toggled_status.load()); + if (lock) { + return; } + lock = true; + const bool old_toggle_status = toggled_status.load(); + toggled_status.store(!old_toggle_status); } void UnlockButton() { @@ -41,7 +43,7 @@ private: std::shared_ptr key_button_list; std::atomic status{false}; std::atomic toggled_status{false}; - bool lock = {}; + bool lock{false}; const bool toggle; }; diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp index b864d26f2..6818d5eee 100644 --- a/src/input_common/mouse/mouse_input.cpp +++ b/src/input_common/mouse/mouse_input.cpp @@ -157,6 +157,42 @@ void Mouse::EndConfiguration() { configuring = false; } +bool Mouse::ToggleButton(std::size_t button_) { + if (button_ >= mouse_info.size()) { + return false; + } + const auto button = 1U << button_; + const bool button_state = (toggle_buttons & button) != 0; + const bool button_lock = (lock_buttons & button) != 0; + + if (button_lock) { + return button_state; + } + + lock_buttons |= static_cast(button); + + if (button_state) { + toggle_buttons &= static_cast(0xFF - button); + } else { + toggle_buttons |= static_cast(button); + } + + return !button_state; +} + +bool Mouse::UnlockButton(std::size_t button_) { + if (button_ >= mouse_info.size()) { + return false; + } + + const auto button = 1U << button_; + const bool button_state = (toggle_buttons & button) != 0; + + lock_buttons &= static_cast(0xFF - button); + + return button_state; +} + Common::SPSCQueue& Mouse::GetMouseQueue() { return mouse_queue; } diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h index 46aa676c1..a75f0ecb5 100644 --- a/src/input_common/mouse/mouse_input.h +++ b/src/input_common/mouse/mouse_input.h @@ -67,6 +67,9 @@ public: */ void ReleaseButton(int button_); + [[nodiscard]] bool ToggleButton(std::size_t button_); + [[nodiscard]] bool UnlockButton(std::size_t button_); + [[nodiscard]] Common::SPSCQueue& GetMouseQueue(); [[nodiscard]] const Common::SPSCQueue& GetMouseQueue() const; @@ -92,6 +95,8 @@ private: }; u16 buttons{}; + u16 toggle_buttons{}; + u16 lock_buttons{}; std::thread update_thread; MouseButton last_button{MouseButton::Undefined}; std::array mouse_info; diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp index bb56787ee..0e1db54fb 100644 --- a/src/input_common/mouse/mouse_poller.cpp +++ b/src/input_common/mouse/mouse_poller.cpp @@ -14,16 +14,25 @@ namespace InputCommon { class MouseButton final : public Input::ButtonDevice { public: - explicit MouseButton(u32 button_, const MouseInput::Mouse* mouse_input_) - : button(button_), mouse_input(mouse_input_) {} + explicit MouseButton(u32 button_, bool toggle_, MouseInput::Mouse* mouse_input_) + : button(button_), toggle(toggle_), mouse_input(mouse_input_) {} bool GetStatus() const override { - return mouse_input->GetMouseState(button).pressed; + const bool button_state = mouse_input->GetMouseState(button).pressed; + if (!toggle) { + return button_state; + } + + if (button_state) { + return mouse_input->ToggleButton(button); + } + return mouse_input->UnlockButton(button); } private: const u32 button; - const MouseInput::Mouse* mouse_input; + const bool toggle; + MouseInput::Mouse* mouse_input; }; MouseButtonFactory::MouseButtonFactory(std::shared_ptr mouse_input_) @@ -32,8 +41,9 @@ MouseButtonFactory::MouseButtonFactory(std::shared_ptr mouse_ std::unique_ptr MouseButtonFactory::Create( const Common::ParamPackage& params) { const auto button_id = params.Get("button", 0); + const auto toggle = params.Get("toggle", false); - return std::make_unique(button_id, mouse_input.get()); + return std::make_unique(button_id, toggle, mouse_input.get()); } Common::ParamPackage MouseButtonFactory::GetNextInput() const { diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index bd53f2cde..55adbd53d 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -158,7 +158,8 @@ QString ButtonToText(const Common::ParamPackage& param) { if (param.Get("engine", "") == "mouse") { if (param.Has("button")) { const QString button_str = QString::number(int(param.Get("button", 0))); - return QObject::tr("Click %1").arg(button_str); + const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : ""); + return QObject::tr("%1Click %2").arg(toggle, button_str); } return GetKeyName(param.Get("code", 0)); }