From 9c1fe59cc9e9c3616416d78e1ed4b37be1bb2f66 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Fri, 3 Feb 2023 19:11:31 +1300 Subject: [PATCH] Insert a more solid abstraction between Qt and Imgui --- Source/Core/DolphinLib.props | 1 + Source/Core/DolphinQt/RenderWidget.cpp | 44 +++++++--------------- Source/Core/DolphinQt/RenderWidget.h | 4 +- Source/Core/VideoCommon/CMakeLists.txt | 1 + Source/Core/VideoCommon/OnScreenUI.cpp | 22 +++++++++-- Source/Core/VideoCommon/OnScreenUI.h | 3 +- Source/Core/VideoCommon/OnScreenUIKeyMap.h | 37 ++++++++++++++++++ Source/Core/VideoCommon/Present.cpp | 2 +- Source/Core/VideoCommon/Present.h | 4 +- 9 files changed, 80 insertions(+), 38 deletions(-) create mode 100644 Source/Core/VideoCommon/OnScreenUIKeyMap.h diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index ff461840e3..f7f7606982 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -675,6 +675,7 @@ + diff --git a/Source/Core/DolphinQt/RenderWidget.cpp b/Source/Core/DolphinQt/RenderWidget.cpp index cebbd490c3..c39621ad73 100644 --- a/Source/Core/DolphinQt/RenderWidget.cpp +++ b/Source/Core/DolphinQt/RenderWidget.cpp @@ -19,8 +19,6 @@ #include #include -#include - #include "Core/Config/MainSettings.h" #include "Core/Core.h" #include "Core/State.h" @@ -32,6 +30,7 @@ #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "VideoCommon/OnScreenUI.h" #include "VideoCommon/Present.h" #include "VideoCommon/VideoConfig.h" @@ -62,7 +61,7 @@ RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent) connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) { if (state == Core::State::Running) - SetImGuiKeyMap(); + SetPresenterKeyMap(); }); // We have to use Qt::DirectConnection here because we don't want those signals to get queued @@ -338,7 +337,7 @@ void RenderWidget::SetWaitingForMessageBox(bool waiting_for_message_box) bool RenderWidget::event(QEvent* event) { - PassEventToImGui(event); + PassEventToPresenter(event); switch (event->type()) { @@ -470,7 +469,7 @@ bool RenderWidget::event(QEvent* event) return QWidget::event(event); } -void RenderWidget::PassEventToImGui(const QEvent* event) +void RenderWidget::PassEventToPresenter(const QEvent* event) { if (!Core::IsRunningAndStarted()) return; @@ -498,7 +497,7 @@ void RenderWidget::PassEventToImGui(const QEvent* event) chars = utf8.constData(); } - // Pass the key onto ImGui + // Pass the key onto Presenter (for the imgui UI) g_presenter->SetKey(key, is_down, chars); } break; @@ -529,31 +528,16 @@ void RenderWidget::PassEventToImGui(const QEvent* event) } } -void RenderWidget::SetImGuiKeyMap() +void RenderWidget::SetPresenterKeyMap() { - static std::array, 21> key_map{{ - {ImGuiKey_Tab, Qt::Key_Tab}, - {ImGuiKey_LeftArrow, Qt::Key_Left}, - {ImGuiKey_RightArrow, Qt::Key_Right}, - {ImGuiKey_UpArrow, Qt::Key_Up}, - {ImGuiKey_DownArrow, Qt::Key_Down}, - {ImGuiKey_PageUp, Qt::Key_PageUp}, - {ImGuiKey_PageDown, Qt::Key_PageDown}, - {ImGuiKey_Home, Qt::Key_Home}, - {ImGuiKey_End, Qt::Key_End}, - {ImGuiKey_Insert, Qt::Key_Insert}, - {ImGuiKey_Delete, Qt::Key_Delete}, - {ImGuiKey_Backspace, Qt::Key_Backspace}, - {ImGuiKey_Space, Qt::Key_Space}, - {ImGuiKey_Enter, Qt::Key_Return}, - {ImGuiKey_Escape, Qt::Key_Escape}, - {ImGuiKey_A, Qt::Key_A}, - {ImGuiKey_C, Qt::Key_C}, - {ImGuiKey_V, Qt::Key_V}, - {ImGuiKey_X, Qt::Key_X}, - {ImGuiKey_Y, Qt::Key_Y}, - {ImGuiKey_Z, Qt::Key_Z}, - }}; + static constexpr DolphinKeyMap key_map = { + Qt::Key_Tab, Qt::Key_Left, Qt::Key_Right, Qt::Key_Up, Qt::Key_Down, + Qt::Key_PageUp, Qt::Key_PageDown, Qt::Key_Home, Qt::Key_End, Qt::Key_Insert, + Qt::Key_Delete, Qt::Key_Backspace, Qt::Key_Space, Qt::Key_Return, Qt::Key_Escape, + Qt::Key_Enter, // Keypad enter + Qt::Key_A, Qt::Key_C, Qt::Key_V, Qt::Key_X, Qt::Key_Y, + Qt::Key_Z, + }; g_presenter->SetKeyMap(key_map); } diff --git a/Source/Core/DolphinQt/RenderWidget.h b/Source/Core/DolphinQt/RenderWidget.h index c8ea1e3a84..87235a3986 100644 --- a/Source/Core/DolphinQt/RenderWidget.h +++ b/Source/Core/DolphinQt/RenderWidget.h @@ -39,8 +39,8 @@ private: void OnLockCursorChanged(); void OnKeepOnTopChanged(bool top); void UpdateCursor(); - void PassEventToImGui(const QEvent* event); - void SetImGuiKeyMap(); + void PassEventToPresenter(const QEvent* event); + void SetPresenterKeyMap(); void dragEnterEvent(QDragEnterEvent* event) override; void dropEvent(QDropEvent* event) override; diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 632120ee09..392e53df91 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -89,6 +89,7 @@ add_library(videocommon OnScreenDisplay.h OnScreenUI.cpp OnScreenUI.h + OnScreenUIKeyMap.h OpcodeDecoding.cpp OpcodeDecoding.h PerfQueryBase.cpp diff --git a/Source/Core/VideoCommon/OnScreenUI.cpp b/Source/Core/VideoCommon/OnScreenUI.cpp index 291f0c23e2..e2fa2593a7 100644 --- a/Source/Core/VideoCommon/OnScreenUI.cpp +++ b/Source/Core/VideoCommon/OnScreenUI.cpp @@ -3,6 +3,7 @@ #include "VideoCommon/OnScreenUI.h" +#include "Common/EnumMap.h" #include "Common/Profiler.h" #include "Common/Timer.h" @@ -346,15 +347,30 @@ void OnScreenUI::SetScale(float backbuffer_scale) m_backbuffer_scale = backbuffer_scale; } -void OnScreenUI::SetKeyMap(std::span> key_map) +void OnScreenUI::SetKeyMap(const DolphinKeyMap& key_map) { + // Right now this is a 1:1 mapping. But might not be true later + static constexpr DolphinKeyMap dolphin_to_imgui_map = { + ImGuiKey_Tab, ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, + ImGuiKey_DownArrow, ImGuiKey_PageUp, ImGuiKey_PageDown, ImGuiKey_Home, + ImGuiKey_End, ImGuiKey_Insert, ImGuiKey_Delete, ImGuiKey_Backspace, + ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_KeyPadEnter, + ImGuiKey_A, ImGuiKey_C, ImGuiKey_V, ImGuiKey_X, + ImGuiKey_Y, ImGuiKey_Z, + }; + static_assert(dolphin_to_imgui_map.size() == ImGuiKey_COUNT); // Fail if ImGui adds keys + auto lock = GetImGuiLock(); if (!ImGui::GetCurrentContext()) return; - for (auto [imgui_key, qt_key] : key_map) - ImGui::GetIO().KeyMap[imgui_key] = (qt_key & 0x1FF); + for (int dolphin_key = 0; dolphin_key <= static_cast(DolphinKey::Z); dolphin_key++) + { + int imgui_key = dolphin_to_imgui_map[DolphinKey(dolphin_key)]; + if (imgui_key >= 0) + ImGui::GetIO().KeyMap[imgui_key] = (key_map[DolphinKey(dolphin_key)] & 0x1FF); + } } void OnScreenUI::SetKey(u32 key, bool is_down, const char* chars) diff --git a/Source/Core/VideoCommon/OnScreenUI.h b/Source/Core/VideoCommon/OnScreenUI.h index 43dc6144d1..a0becbc126 100644 --- a/Source/Core/VideoCommon/OnScreenUI.h +++ b/Source/Core/VideoCommon/OnScreenUI.h @@ -9,6 +9,7 @@ #include #include "Common/CommonTypes.h" +#include "VideoCommon/OnScreenUIKeyMap.h" class NativeVertexFormat; class AbstractTexture; @@ -52,7 +53,7 @@ public: void Finalize(); // Receive keyboard and mouse from QT - void SetKeyMap(std::span> key_map); + void SetKeyMap(const DolphinKeyMap& key_map); void SetKey(u32 key, bool is_down, const char* chars); void SetMousePos(float x, float y); void SetMousePress(u32 button_mask); diff --git a/Source/Core/VideoCommon/OnScreenUIKeyMap.h b/Source/Core/VideoCommon/OnScreenUIKeyMap.h new file mode 100644 index 0000000000..c637f3938b --- /dev/null +++ b/Source/Core/VideoCommon/OnScreenUIKeyMap.h @@ -0,0 +1,37 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "Common/EnumMap.h" + +// The main point of this is to allow other parts of dolphin to set ImGui's key map without +// having to import ImGui headers. +// But the idea is that it can be expanded in the future with more keys to support more things. +enum class DolphinKey +{ + Tab, + LeftArrow, + RightArrow, + UpArrow, + DownArrow, + PageUp, + PageDown, + Home, + End, + Insert, + Delete, + Backspace, + Space, + Enter, + Escape, + KeyPadEnter, + A, // for text edit CTRL+A: select all + C, // for text edit CTRL+C: copy + V, // for text edit CTRL+V: paste + X, // for text edit CTRL+X: cut + Y, // for text edit CTRL+Y: redo + Z, // for text edit CTRL+Z: undo +}; + +using DolphinKeyMap = Common::EnumMap; diff --git a/Source/Core/VideoCommon/Present.cpp b/Source/Core/VideoCommon/Present.cpp index fa3be6acc5..068c4693fa 100644 --- a/Source/Core/VideoCommon/Present.cpp +++ b/Source/Core/VideoCommon/Present.cpp @@ -571,7 +571,7 @@ void Presenter::Present() g_gfx->EndUtilityDrawing(); } -void Presenter::SetKeyMap(std::span> key_map) +void Presenter::SetKeyMap(const DolphinKeyMap& key_map) { if (m_onscreen_ui) m_onscreen_ui->SetKeyMap(key_map); diff --git a/Source/Core/VideoCommon/Present.h b/Source/Core/VideoCommon/Present.h index 235dba11d4..eee98d0c1a 100644 --- a/Source/Core/VideoCommon/Present.h +++ b/Source/Core/VideoCommon/Present.h @@ -6,6 +6,7 @@ #include "Common/Flag.h" #include "Common/MathUtil.h" +#include "VideoCommon/OnScreenUIKeyMap.h" #include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/TextureConfig.h" #include "VideoCommon/VideoCommon.h" @@ -18,6 +19,7 @@ class AbstractTexture; struct SurfaceInfo; +enum class DolphinKey; namespace VideoCommon { @@ -82,7 +84,7 @@ public: bool SurfaceChangedTestAndClear() { return m_surface_changed.TestAndClear(); } void* GetNewSurfaceHandle(); - void SetKeyMap(std::span> key_map); + void SetKeyMap(const DolphinKeyMap& key_map); void SetKey(u32 key, bool is_down, const char* chars); void SetMousePos(float x, float y);