diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 8ec0e6593..367ae3e87 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -234,8 +234,7 @@ bool QtHost::SaveGameSettings(SettingsInterface* sif, bool delete_if_empty) // to read it at the same time. const auto lock = Host::GetSettingsLock(); - if (FileSystem::FileExists(ini->GetPath().c_str()) && - !FileSystem::DeleteFile(ini->GetPath().c_str(), &error)) + if (FileSystem::FileExists(ini->GetPath().c_str()) && !FileSystem::DeleteFile(ini->GetPath().c_str(), &error)) { Host::ReportErrorAsync( TRANSLATE_SV("QtHost", "Error"), @@ -1647,6 +1646,25 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo }); } +void Host::BeginTextInput() +{ + DEV_LOG("Host::BeginTextInput()"); + + // NOTE: Called on GPU thread. + QInputMethod* method = qApp->inputMethod(); + if (method) + QMetaObject::invokeMethod(method, "show", Qt::QueuedConnection); +} + +void Host::EndTextInput() +{ + DEV_LOG("Host::EndTextInput()"); + + QInputMethod* method = qApp->inputMethod(); + if (method) + QMetaObject::invokeMethod(method, "hide", Qt::QueuedConnection); +} + bool Host::CreateAuxiliaryRenderWindow(s32 x, s32 y, u32 width, u32 height, std::string_view title, std::string_view icon_name, AuxiliaryRenderWindowUserData userdata, AuxiliaryRenderWindowHandle* handle, WindowInfo* wi, Error* error) diff --git a/src/duckstation-regtest/regtest_host.cpp b/src/duckstation-regtest/regtest_host.cpp index 3d1e4364d..73f50cae1 100644 --- a/src/duckstation-regtest/regtest_host.cpp +++ b/src/duckstation-regtest/regtest_host.cpp @@ -370,6 +370,16 @@ void Host::ReleaseRenderWindow() // } +void Host::BeginTextInput() +{ + // +} + +void Host::EndTextInput() +{ + // +} + bool Host::CreateAuxiliaryRenderWindow(s32 x, s32 y, u32 width, u32 height, std::string_view title, std::string_view icon_name, AuxiliaryRenderWindowUserData userdata, AuxiliaryRenderWindowHandle* handle, WindowInfo* wi, Error* error) diff --git a/src/util/imgui_manager.cpp b/src/util/imgui_manager.cpp index 3a7e32272..2d8b196d8 100644 --- a/src/util/imgui_manager.cpp +++ b/src/util/imgui_manager.cpp @@ -119,6 +119,7 @@ static Timer s_last_render_time; // cached copies of WantCaptureKeyboard/Mouse, used to know when to dispatch events static std::atomic_bool s_imgui_wants_keyboard{false}; static std::atomic_bool s_imgui_wants_mouse{false}; +static std::atomic_bool s_imgui_wants_text{false}; // mapping of host key -> imgui key static std::unordered_map s_imgui_key_map; @@ -375,6 +376,16 @@ void ImGuiManager::NewFrame() ImGui::GetCurrentWindowRead()->Flags |= ImGuiWindowFlags_NoNavInputs; s_imgui_wants_keyboard.store(io.WantCaptureKeyboard, std::memory_order_relaxed); s_imgui_wants_mouse.store(io.WantCaptureMouse, std::memory_order_release); + + const bool wants_text_input = io.WantTextInput; + if (s_imgui_wants_text.load(std::memory_order_relaxed) != wants_text_input) + { + s_imgui_wants_text.store(wants_text_input, std::memory_order_release); + if (wants_text_input) + Host::BeginTextInput(); + else + Host::EndTextInput(); + } } void ImGuiManager::SetStyle(ImGuiStyle& style, float scale) diff --git a/src/util/imgui_manager.h b/src/util/imgui_manager.h index e3998a811..785a5617f 100644 --- a/src/util/imgui_manager.h +++ b/src/util/imgui_manager.h @@ -230,6 +230,13 @@ void RemoveKeyedOSDMessage(std::string key); void RemoveKeyedOSDWarning(std::string key); void ClearOSDMessages(bool clear_warnings); +/// Called by ImGuiManager when the cursor enters a text field. The host may choose to open an on-screen +/// keyboard for devices without a physical keyboard. +void BeginTextInput(); + +/// Called by ImGuiManager when the cursor leaves a text field. +void EndTextInput(); + #ifndef __ANDROID__ /// Auxiliary window management.