From a0e97059f58b3aa4d46ca73bfa01cd252cfcaddb Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Mon, 8 Mar 2021 01:39:46 +1000 Subject: [PATCH] Qt: Allow binding keyboard keys via fullscreen UI --- src/duckstation-nogui/sdl_host_interface.cpp | 24 +++++++++----------- src/duckstation-qt/inputbindingdialog.cpp | 3 ++- src/duckstation-qt/inputbindingwidgets.cpp | 5 ++-- src/duckstation-qt/qtdisplaywidget.cpp | 5 +++- src/duckstation-qt/qtdisplaywidget.h | 2 +- src/duckstation-qt/qthostinterface.cpp | 24 +++++++++++++++----- src/duckstation-qt/qthostinterface.h | 2 +- src/duckstation-qt/qtutils.cpp | 9 ++------ src/duckstation-qt/qtutils.h | 4 ++-- 9 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/duckstation-nogui/sdl_host_interface.cpp b/src/duckstation-nogui/sdl_host_interface.cpp index 96fd851ec..d49fe7cd5 100644 --- a/src/duckstation-nogui/sdl_host_interface.cpp +++ b/src/duckstation-nogui/sdl_host_interface.cpp @@ -306,27 +306,25 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event) case SDL_KEYDOWN: case SDL_KEYUP: { - // Binding mode - if (m_fullscreen_ui_enabled && m_controller_interface && m_controller_interface->HasHook() && - event->key.repeat == 0) - { - String keyName; - if (!SDLKeyNames::KeyEventToString(event, keyName)) - { - break; - } + const bool pressed = (event->type == SDL_KEYDOWN); - const bool pressed = (event->type == SDL_KEYDOWN); - if (FullscreenUI::HandleKeyboardBinding(keyName, pressed)) + // Binding mode + if (m_fullscreen_ui_enabled && FullscreenUI::IsBindingInput()) + { + if (event->key.repeat > 0) + return; + + TinyString key_string; + if (SDLKeyNames::KeyEventToString(event, key_string)) { - break; + if (FullscreenUI::HandleKeyboardBinding(key_string, pressed)) + return; } } if (!ImGui::GetIO().WantCaptureKeyboard && event->key.repeat == 0) { const u32 code = SDLKeyNames::KeyEventToInt(event); - const bool pressed = (event->type == SDL_KEYDOWN); HandleHostKeyEvent(code & SDLKeyNames::KEY_MASK, code & SDLKeyNames::MODIFIER_MASK, pressed); } } diff --git a/src/duckstation-qt/inputbindingdialog.cpp b/src/duckstation-qt/inputbindingdialog.cpp index e7a996ad6..49ff6f284 100644 --- a/src/duckstation-qt/inputbindingdialog.cpp +++ b/src/duckstation-qt/inputbindingdialog.cpp @@ -47,7 +47,8 @@ bool InputBindingDialog::eventFilter(QObject* watched, QEvent* event) } else if (event_type == QEvent::KeyPress) { - QString binding = QtUtils::KeyEventToString(static_cast(event)); + const QKeyEvent* key_event = static_cast(event); + const QString binding(QtUtils::KeyEventToString(key_event->key(), key_event->modifiers())); if (!binding.isEmpty()) m_new_binding_value = QStringLiteral("Keyboard/%1").arg(binding).toStdString(); diff --git a/src/duckstation-qt/inputbindingwidgets.cpp b/src/duckstation-qt/inputbindingwidgets.cpp index f251d7978..ea2b8dc20 100644 --- a/src/duckstation-qt/inputbindingwidgets.cpp +++ b/src/duckstation-qt/inputbindingwidgets.cpp @@ -36,7 +36,7 @@ void InputBindingWidget::updateText() if (m_bindings.empty()) setText(QString()); else if (m_bindings.size() > 1) - setText(tr("%n bindings", "", m_bindings.size())); + setText(tr("%n bindings", "", static_cast(m_bindings.size()))); else setText(QString::fromStdString(m_bindings[0])); } @@ -94,7 +94,8 @@ bool InputBindingWidget::eventFilter(QObject* watched, QEvent* event) } else if (event_type == QEvent::KeyPress) { - QString binding = QtUtils::KeyEventToString(static_cast(event)); + const QKeyEvent* key_event = static_cast(event); + const QString binding(QtUtils::KeyEventToString(key_event->key(), key_event->modifiers())); if (!binding.isEmpty()) m_new_binding_value = QStringLiteral("Keyboard/%1").arg(binding).toStdString(); diff --git a/src/duckstation-qt/qtdisplaywidget.cpp b/src/duckstation-qt/qtdisplaywidget.cpp index 1899f055b..0a2b29c06 100644 --- a/src/duckstation-qt/qtdisplaywidget.cpp +++ b/src/duckstation-qt/qtdisplaywidget.cpp @@ -129,7 +129,10 @@ bool QtDisplayWidget::event(QEvent* event) { const QKeyEvent* key_event = static_cast(event); if (!key_event->isAutoRepeat()) - emit windowKeyEvent(QtUtils::KeyEventToInt(key_event), event->type() == QEvent::KeyPress); + { + emit windowKeyEvent(key_event->key(), static_cast(key_event->modifiers()), + event->type() == QEvent::KeyPress); + } return true; } diff --git a/src/duckstation-qt/qtdisplaywidget.h b/src/duckstation-qt/qtdisplaywidget.h index 840058053..ce19c4515 100644 --- a/src/duckstation-qt/qtdisplaywidget.h +++ b/src/duckstation-qt/qtdisplaywidget.h @@ -27,7 +27,7 @@ Q_SIGNALS: void windowResizedEvent(int width, int height); void windowRestoredEvent(); void windowClosedEvent(); - void windowKeyEvent(int key_code, bool pressed); + void windowKeyEvent(int key_code, int mods, bool pressed); void windowMouseMoveEvent(int x, int y); void windowMouseButtonEvent(int button, bool pressed); void windowMouseWheelEvent(const QPoint& angle_delta); diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index b9176cf7d..ea0b798e1 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -9,6 +9,7 @@ #include "core/controller.h" #include "core/gpu.h" #include "core/system.h" +#include "frontend-common/fullscreen_ui.h" #include "frontend-common/game_list.h" #include "frontend-common/imgui_fullscreen.h" #include "frontend-common/imgui_styles.h" @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -373,20 +375,30 @@ void QtHostInterface::resumeSystemFromMostRecentState() loadState(QString::fromStdString(state_filename)); } -void QtHostInterface::onDisplayWindowKeyEvent(int key, bool pressed) +void QtHostInterface::onDisplayWindowKeyEvent(int key, int mods, bool pressed) { DebugAssert(isOnWorkerThread()); + ImGuiIO& io = ImGui::GetIO(); const u32 masked_key = static_cast(key) & IMGUI_KEY_MASK; if (masked_key < countof(ImGuiIO::KeysDown)) - { - ImGuiIO& io = ImGui::GetIO(); io.KeysDown[masked_key] = pressed; - if (io.WantCaptureKeyboard) - return; + + if (m_fullscreen_ui_enabled && FullscreenUI::IsBindingInput()) + { + QString key_string(QtUtils::KeyEventToString(key, static_cast(mods))); + if (!key_string.isEmpty()) + { + if (FullscreenUI::HandleKeyboardBinding(key_string.toUtf8().constData(), pressed)) + return; + } } - HandleHostKeyEvent(key & ~Qt::KeyboardModifierMask, key & Qt::KeyboardModifierMask, pressed); + if (io.WantCaptureKeyboard) + return; + + const int key_id = QtUtils::KeyEventToInt(key, static_cast(mods)); + HandleHostKeyEvent(key_id & ~Qt::KeyboardModifierMask, key_id & Qt::KeyboardModifierMask, pressed); } void QtHostInterface::onDisplayWindowMouseMoveEvent(int x, int y) diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h index ca99ad5bd..fe17fe922 100644 --- a/src/duckstation-qt/qthostinterface.h +++ b/src/duckstation-qt/qthostinterface.h @@ -183,7 +183,7 @@ private Q_SLOTS: void onDisplayWindowMouseWheelEvent(const QPoint& delta_angle); void onDisplayWindowResized(int width, int height); void onDisplayWindowFocused(); - void onDisplayWindowKeyEvent(int key, bool pressed); + void onDisplayWindowKeyEvent(int key, int mods, bool pressed); void doBackgroundControllerPoll(); void doSaveSettings(); diff --git a/src/duckstation-qt/qtutils.cpp b/src/duckstation-qt/qtutils.cpp index 230e56f41..84c540f70 100644 --- a/src/duckstation-qt/qtutils.cpp +++ b/src/duckstation-qt/qtutils.cpp @@ -578,15 +578,13 @@ std::optional GetKeyIdForIdentifier(const QString& key_identifier) return std::nullopt; } -QString KeyEventToString(const QKeyEvent* ke) +QString KeyEventToString(int key, Qt::KeyboardModifiers mods) { - const int key = ke->key(); QString key_name = GetKeyIdentifier(key); if (key_name.isEmpty()) return {}; QString ret; - const Qt::KeyboardModifiers mods = ke->modifiers(); for (const QtKeyModifierEntry& mod : s_qt_key_modifiers) { if (mods & mod.mod && key != mod.key) @@ -628,11 +626,8 @@ std::optional ParseKeyString(const QString& key_str) return ret; } -int KeyEventToInt(const QKeyEvent* ke) +int KeyEventToInt(int key, Qt::KeyboardModifiers mods) { - const Qt::KeyboardModifiers mods = ke->modifiers(); - const int key = ke->key(); - int val = key; if (mods != 0) { diff --git a/src/duckstation-qt/qtutils.h b/src/duckstation-qt/qtutils.h index 1e47e8aa5..fb18a836d 100644 --- a/src/duckstation-qt/qtutils.h +++ b/src/duckstation-qt/qtutils.h @@ -40,13 +40,13 @@ QString GetKeyIdentifier(int key); std::optional GetKeyIdForIdentifier(const QString& key_identifier); /// Stringizes a key event. -QString KeyEventToString(const QKeyEvent* ke); +QString KeyEventToString(int key, Qt::KeyboardModifiers mods); /// Returns an integer id for a stringized key event. Modifiers are in the upper bits. std::optional ParseKeyString(const QString& key_str); /// Returns a key id for a key event, including any modifiers. -int KeyEventToInt(const QKeyEvent* ke); +int KeyEventToInt(int key, Qt::KeyboardModifiers mods); /// Reads a whole stream to a Qt byte array. QByteArray ReadStreamToQByteArray(ByteStream* stream, bool rewind = false);