working with chords and direct sdl button access

This commit is contained in:
David Griswold 2026-02-03 21:45:39 +03:00
parent ede2258b0e
commit 20612442fa
5 changed files with 44 additions and 19 deletions

View File

@ -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");

View File

@ -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<QWidget*>(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<QWidget*>(hotkey_shortcut->parent());
if (parent && parent->isActiveWindow()) {
hotkey_shortcut->activated();
break;
}
}
}
it.lastStatus = currentStatus;
}
}
}

View File

@ -36,9 +36,16 @@ void HotkeyRegistry::LoadHotkeys() {
hk.controller_keyseq = shortcut.shortcut.controller_keyseq;
}
if (!hk.controller_keyseq.isEmpty()) {
hk.button_device =
Input::CreateDevice<Input::ButtonDevice>(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<Input::ButtonDevice>(paramList.at(0).toStdString());
if (paramList.length() > 1) {
hk.button_device2 =
Input::CreateDevice<Input::ButtonDevice>(paramList.at(1).toStdString());
}
buttonMonitor.addButton(shortcut.name, &hk);
}
}
for (auto const& [_, hotkey_shortcut] : hk.shortcuts) {
if (hotkey_shortcut) {

View File

@ -20,7 +20,8 @@ struct Hotkey {
QString controller_keyseq;
std::map<QString, QShortcut*> shortcuts;
Qt::ShortcutContext context = Qt::WindowShortcut;
std::unique_ptr<Input::ButtonDevice> button_device;
std::unique_ptr<Input::ButtonDevice> button_device = nullptr;
std::unique_ptr<Input::ButtonDevice> button_device2 = nullptr;
};
class HotkeyRegistry final {

View File

@ -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: