From 20612442fa0f5e4f2f8be6558832402be2dceada Mon Sep 17 00:00:00 2001 From: David Griswold Date: Tue, 3 Feb 2026 21:45:39 +0300 Subject: [PATCH] working with chords and direct sdl button access --- src/citra_qt/citra_qt.cpp | 2 +- src/citra_qt/hotkey_monitor.cpp | 34 +++++++++++++++++++------------ src/citra_qt/hotkeys.cpp | 13 +++++++++--- src/citra_qt/hotkeys.h | 3 ++- src/input_common/sdl/sdl_impl.cpp | 11 +++++++++- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/citra_qt/citra_qt.cpp b/src/citra_qt/citra_qt.cpp index dd95a10ad..5b300ac02 100644 --- a/src/citra_qt/citra_qt.cpp +++ b/src/citra_qt/citra_qt.cpp @@ -768,7 +768,7 @@ void GMainWindow::InitializeSaveStateMenuActions() { void GMainWindow::InitializeHotkeys() { hotkey_registry.LoadHotkeys(); - hotkey_registry.buttonMonitor.start(32); // poll 60Hz + hotkey_registry.buttonMonitor.start(16); LOG_DEBUG(Frontend, "Initializing hotkeys"); const QString main_window = QStringLiteral("Main Window"); const QString fullscreen = QStringLiteral("Fullscreen"); diff --git a/src/citra_qt/hotkey_monitor.cpp b/src/citra_qt/hotkey_monitor.cpp index d7366bccc..a1103999b 100644 --- a/src/citra_qt/hotkey_monitor.cpp +++ b/src/citra_qt/hotkey_monitor.cpp @@ -12,7 +12,8 @@ struct ControllerHotkeyMonitor::ButtonState { Hotkey* hk; - bool lastStatus; + bool lastStatus = false; + bool lastStatus2 = false; }; ControllerHotkeyMonitor::ControllerHotkeyMonitor() { @@ -39,22 +40,29 @@ void ControllerHotkeyMonitor::removeButton(const QString& name) { void ControllerHotkeyMonitor::checkAllButtons() { for (auto& [name, it] : *m_buttons) { - + bool trigger = false; bool currentStatus = it.hk->button_device->GetStatus(); - if (currentStatus != it.lastStatus) { - if (it.lastStatus && !currentStatus) { - std::cerr << "Detected button release" << std::endl; - for (auto const& [name, hotkey_shortcut] : it.hk->shortcuts) { - if (hotkey_shortcut && hotkey_shortcut->isEnabled()) { - QWidget* parent = qobject_cast(hotkey_shortcut->parent()); - if (parent && parent->isActiveWindow()) { - hotkey_shortcut->activated(); - break; - } + if (it.hk->button_device2) { + // two buttons, need both pressed and one *just now* pressed + bool currentStatus2 = it.hk->button_device2->GetStatus(); + trigger = currentStatus && currentStatus2 && (!it.lastStatus || !it.lastStatus2); + it.lastStatus = currentStatus; + it.lastStatus2 = currentStatus2; + } else { + // if only one button, trigger as soon as pressed + trigger = currentStatus && !it.lastStatus; + it.lastStatus = currentStatus; + } + if (trigger) { + for (auto const& [name, hotkey_shortcut] : it.hk->shortcuts) { + if (hotkey_shortcut && hotkey_shortcut->isEnabled()) { + QWidget* parent = qobject_cast(hotkey_shortcut->parent()); + if (parent && parent->isActiveWindow()) { + hotkey_shortcut->activated(); + break; } } } - it.lastStatus = currentStatus; } } } \ No newline at end of file diff --git a/src/citra_qt/hotkeys.cpp b/src/citra_qt/hotkeys.cpp index bdb34dbf5..0bde5769a 100644 --- a/src/citra_qt/hotkeys.cpp +++ b/src/citra_qt/hotkeys.cpp @@ -36,9 +36,16 @@ void HotkeyRegistry::LoadHotkeys() { hk.controller_keyseq = shortcut.shortcut.controller_keyseq; } if (!hk.controller_keyseq.isEmpty()) { - hk.button_device = - Input::CreateDevice(hk.controller_keyseq.toStdString()); - buttonMonitor.addButton(shortcut.name, &hk); + QStringList paramList = hk.controller_keyseq.split(QStringLiteral("||")); + if (paramList.length() > 0) { + hk.button_device = + Input::CreateDevice(paramList.at(0).toStdString()); + if (paramList.length() > 1) { + hk.button_device2 = + Input::CreateDevice(paramList.at(1).toStdString()); + } + buttonMonitor.addButton(shortcut.name, &hk); + } } for (auto const& [_, hotkey_shortcut] : hk.shortcuts) { if (hotkey_shortcut) { diff --git a/src/citra_qt/hotkeys.h b/src/citra_qt/hotkeys.h index 123ce3715..a550131c4 100644 --- a/src/citra_qt/hotkeys.h +++ b/src/citra_qt/hotkeys.h @@ -20,7 +20,8 @@ struct Hotkey { QString controller_keyseq; std::map shortcuts; Qt::ShortcutContext context = Qt::WindowShortcut; - std::unique_ptr button_device; + std::unique_ptr button_device = nullptr; + std::unique_ptr button_device2 = nullptr; }; class HotkeyRegistry final { diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 1833e49cb..47862380c 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -187,11 +187,20 @@ public: state.buttons[button] = value; } + // no longer used, at least as a test bool GetButton(int button) const { std::lock_guard lock{mutex}; return state.buttons.at(button); } + // better than maintaining the state manually, and + // seems to have no effect on performance + bool GetButtonDirect(int button) const { + if (!sdl_joystick) + return false; + return SDL_JoystickGetButton(sdl_joystick.get(), button) != 0; + } + void SetAxis(int axis, Sint16 value) { std::lock_guard lock{mutex}; state.axes[axis] = value; @@ -613,7 +622,7 @@ public: : joystick(std::move(joystick_)), button(button_) {} bool GetStatus() const override { - return joystick->GetButton(button); + return joystick->GetButtonDirect(button); } private: