Qt/ImGui: Add clipboard support and fix modfier keys

Signed-off-by: SternXD <stern@sidestore.io>
This commit is contained in:
SternXD
2026-06-04 20:59:54 -04:00
committed by Ty
parent 673917ae66
commit b5ed65ddd6
5 changed files with 92 additions and 6 deletions
+5
View File
@@ -222,6 +222,11 @@ bool Host::CopyTextToClipboard(const std::string_view text)
return false;
}
std::string Host::GetTextFromClipboard()
{
return std::string();
}
void Host::BeginTextInput()
{
// noop
+31
View File
@@ -77,6 +77,7 @@ namespace QtHost
static void SaveSettings();
static void HookSignals();
static void RegisterTypes();
static void InitializeClipboard();
static bool RunSetupWizard();
std::optional<bool> DownloadFile(QWidget* parent, const QString& title, std::string url, std::vector<u8>* data);
} // namespace QtHost
@@ -96,6 +97,8 @@ static bool s_run_setup_wizard = false;
static bool s_cleanup_after_update = false;
static bool s_boot_and_debug = false;
static std::atomic_int s_vm_locked_with_dialog = 0;
static std::string s_clipboard_cache;
static std::mutex s_clipboard_cache_mutex;
//////////////////////////////////////////////////////////////////////////
// CPU Thread
@@ -1666,6 +1669,12 @@ bool Host::CopyTextToClipboard(const std::string_view text)
return true;
}
std::string Host::GetTextFromClipboard()
{
std::lock_guard<std::mutex> lock(s_clipboard_cache_mutex);
return s_clipboard_cache;
}
void Host::BeginTextInput()
{
QInputMethod* method = qApp->inputMethod();
@@ -2351,6 +2360,26 @@ void QtHost::RegisterTypes()
qRegisterMetaType<Achievements::LoginRequestReason>();
}
void QtHost::InitializeClipboard()
{
QClipboard* clipboard = QGuiApplication::clipboard();
if (clipboard)
{
{
std::lock_guard<std::mutex> lock(s_clipboard_cache_mutex);
s_clipboard_cache = clipboard->text().toStdString();
}
QObject::connect(clipboard, &QClipboard::dataChanged, []() {
QClipboard* cb = QGuiApplication::clipboard();
if (cb)
{
std::lock_guard<std::mutex> lock(s_clipboard_cache_mutex);
s_clipboard_cache = cb->text().toStdString();
}
});
}
}
bool QtHost::RunSetupWizard()
{
SetupWizardDialog dialog;
@@ -2399,6 +2428,8 @@ int main(int argc, char* argv[])
PCSX2MainApplication app(argc, argv);
QtHost::InitializeClipboard();
#ifndef _WIN32
if (!PerformEarlyHardwareChecks())
return EXIT_FAILURE;
+3
View File
@@ -75,6 +75,9 @@ namespace Host
/// Copies the provided text to the host's clipboard, if present.
bool CopyTextToClipboard(const std::string_view text);
/// Returns the current text from the host's clipboard, if present.
std::string GetTextFromClipboard();
/// Requests settings reset. Can be called from any thread, will call back and apply on the CPU thread.
bool RequestResetSettings(bool folders, bool core, bool controllers, bool hotkeys, bool ui);
+48 -6
View File
@@ -148,6 +148,17 @@ bool ImGuiManager::Initialize()
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad;
io.KeyRepeatDelay = 0.5f;
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
platform_io.Platform_GetClipboardTextFn = [](ImGuiContext* ctx) -> const char* {
static thread_local std::string s_clipboard_text;
s_clipboard_text = Host::GetTextFromClipboard();
return s_clipboard_text.c_str();
};
platform_io.Platform_SetClipboardTextFn = [](ImGuiContext* ctx, const char* text) {
if (text)
Host::CopyTextToClipboard(text);
};
g.ConfigNavWindowingKeyNext = ImGuiKey_None;
g.ConfigNavWindowingKeyPrev = ImGuiKey_None;
g.ConfigNavWindowingWithGamepad = false;
@@ -398,10 +409,10 @@ void ImGuiManager::SetKeyMap()
static constexpr KeyMapping mapping[] = {{ImGuiKey_LeftArrow, "Left"}, {ImGuiKey_RightArrow, "Right"}, {ImGuiKey_UpArrow, "Up"},
{ImGuiKey_DownArrow, "Down"}, {ImGuiKey_PageUp, "PageUp"}, {ImGuiKey_PageDown, "PageDown"}, {ImGuiKey_Home, "Home"},
{ImGuiKey_End, "End"}, {ImGuiKey_Insert, "Insert"}, {ImGuiKey_Delete, "Delete"}, {ImGuiKey_Backspace, "Backspace"},
{ImGuiKey_Space, "Space"}, {ImGuiKey_Enter, "Return"}, {ImGuiKey_Escape, "Escape"}, {ImGuiKey_LeftCtrl, "LeftCtrl", "Ctrl"},
{ImGuiKey_LeftShift, "LeftShift", "Shift"}, {ImGuiKey_LeftAlt, "LeftAlt", "Alt"}, {ImGuiKey_LeftSuper, "LeftSuper", "Super"},
{ImGuiKey_Space, "Space"}, {ImGuiKey_Enter, "Return"}, {ImGuiKey_Escape, "Escape"}, {ImGuiKey_LeftCtrl, "LeftCtrl", "Control"},
{ImGuiKey_LeftShift, "LeftShift", "Shift"}, {ImGuiKey_LeftAlt, "LeftAlt", "Alt"}, {ImGuiKey_LeftSuper, "Meta", "Super_L"},
{ImGuiKey_RightCtrl, "RightCtrl"}, {ImGuiKey_RightShift, "RightShift"}, {ImGuiKey_RightAlt, "RightAlt"},
{ImGuiKey_RightSuper, "RightSuper"}, {ImGuiKey_Menu, "Menu"}, {ImGuiKey_0, "0"}, {ImGuiKey_1, "1"}, {ImGuiKey_2, "2"},
{ImGuiKey_RightSuper, "Super_R"}, {ImGuiKey_Menu, "Menu"}, {ImGuiKey_0, "0"}, {ImGuiKey_1, "1"}, {ImGuiKey_2, "2"},
{ImGuiKey_3, "3"}, {ImGuiKey_4, "4"}, {ImGuiKey_5, "5"}, {ImGuiKey_6, "6"}, {ImGuiKey_7, "7"}, {ImGuiKey_8, "8"}, {ImGuiKey_9, "9"},
{ImGuiKey_A, "A"}, {ImGuiKey_B, "B"}, {ImGuiKey_C, "C"}, {ImGuiKey_D, "D"}, {ImGuiKey_E, "E"}, {ImGuiKey_F, "F"}, {ImGuiKey_G, "G"},
{ImGuiKey_H, "H"}, {ImGuiKey_I, "I"}, {ImGuiKey_J, "J"}, {ImGuiKey_K, "K"}, {ImGuiKey_L, "L"}, {ImGuiKey_M, "M"}, {ImGuiKey_N, "N"},
@@ -1122,14 +1133,45 @@ bool ImGuiManager::ProcessPointerAxisEvent(InputBindingKey key, float value)
return s_imgui_wants_mouse.load(std::memory_order_acquire);
}
static ImGuiKey GetModifierForKey(ImGuiKey key)
{
static constexpr std::pair<ImGuiKey, ImGuiKey> modifier_map[] = {
{ImGuiKey_LeftCtrl, ImGuiMod_Ctrl},
{ImGuiKey_RightCtrl, ImGuiMod_Ctrl},
{ImGuiKey_LeftShift, ImGuiMod_Shift},
{ImGuiKey_RightShift, ImGuiMod_Shift},
{ImGuiKey_LeftAlt, ImGuiMod_Alt},
{ImGuiKey_RightAlt, ImGuiMod_Alt},
{ImGuiKey_LeftSuper, ImGuiMod_Super},
{ImGuiKey_RightSuper, ImGuiMod_Super},
};
for (const auto& [k, mod] : modifier_map)
{
if (key == k)
return mod;
}
return ImGuiKey_None;
}
bool ImGuiManager::ProcessHostKeyEvent(InputBindingKey key, float value)
{
decltype(s_imgui_key_map)::iterator iter;
if (!ImGui::GetCurrentContext() || (iter = s_imgui_key_map.find(key.data)) == s_imgui_key_map.end())
if (!ImGui::GetCurrentContext())
return false;
const auto iter = s_imgui_key_map.find(key.data);
if (iter == s_imgui_key_map.end())
return false;
// still update state anyway
MTGS::RunOnGSThread([imkey = iter->second, down = (value != 0.0f)]() { ImGui::GetIO().AddKeyEvent(imkey, down); });
MTGS::RunOnGSThread([imkey = iter->second, down = (value != 0.0f)]() {
ImGuiIO& io = ImGui::GetIO();
io.AddKeyEvent(imkey, down);
if (const ImGuiKey mod = GetModifierForKey(imkey); mod != ImGuiKey_None)
io.AddKeyEvent(mod, down);
});
return s_imgui_wants_keyboard.load(std::memory_order_acquire);
}
+5
View File
@@ -65,6 +65,11 @@ bool Host::CopyTextToClipboard(const std::string_view text)
return false;
}
std::string Host::GetTextFromClipboard()
{
return std::string();
}
void Host::BeginTextInput()
{
}