From 60669a7dd8d1d7109c86874c4d24fc89ef39b244 Mon Sep 17 00:00:00 2001 From: Pengfei Zhu Date: Mon, 4 May 2020 17:31:17 +0800 Subject: [PATCH] swkbd: Fix a bug where clicking Cancel hangs the game (#5294) * swkbd: Fix a bug where clicking Cancel hangs the game The text is validated in `Finalize`. If the validation fails, an error is returned and the applet is not actually finalized. This can result in hangs. This is usually not a problem as the frontend is expected to validate the text passed to `Finalize`. However, when the user clicked on `Cancel`, the text is ignored and the frontend won't do any validation. Therefore, we should skip the validation here as well. Also fixed a potential data race. All these functions should now be called on the same thread * Address review comments Renamed the fields Remove close button --- src/citra_qt/applets/swkbd.cpp | 13 ++++++++----- src/citra_qt/applets/swkbd.h | 3 +++ src/core/frontend/applets/swkbd.cpp | 15 +++++++++------ src/core/frontend/applets/swkbd.h | 3 +-- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/citra_qt/applets/swkbd.cpp b/src/citra_qt/applets/swkbd.cpp index 8862a92a4..95d4fd4fa 100644 --- a/src/citra_qt/applets/swkbd.cpp +++ b/src/citra_qt/applets/swkbd.cpp @@ -115,6 +115,7 @@ void QtKeyboard::Execute(const Frontend::KeyboardConfig& config) { ok_id = static_cast(this->config.button_config); } QMetaObject::invokeMethod(this, "OpenInputDialog", Qt::BlockingQueuedConnection); + Finalize(result_text, result_button); } void QtKeyboard::ShowError(const std::string& error) { @@ -125,13 +126,15 @@ void QtKeyboard::ShowError(const std::string& error) { void QtKeyboard::OpenInputDialog() { QtKeyboardDialog dialog(&parent, this); - dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); + dialog.setWindowFlags(dialog.windowFlags() & + ~(Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)); dialog.setWindowModality(Qt::WindowModal); dialog.exec(); - LOG_INFO(Frontend, "SWKBD input dialog finished, text={}, button={}", dialog.text.toStdString(), - dialog.button); - Finalize(dialog.text.toStdString(), dialog.button); + + result_text = dialog.text.toStdString(); + result_button = dialog.button; + LOG_INFO(Frontend, "SWKBD input dialog finished, text={}, button={}", result_text, + result_button); } void QtKeyboard::ShowErrorDialog(QString message) { diff --git a/src/citra_qt/applets/swkbd.h b/src/citra_qt/applets/swkbd.h index 34b6a186d..95ed95844 100644 --- a/src/citra_qt/applets/swkbd.h +++ b/src/citra_qt/applets/swkbd.h @@ -62,6 +62,9 @@ private: QWidget& parent; + std::string result_text; + int result_button; + friend class QtKeyboardDialog; friend class QtKeyboardValidator; }; diff --git a/src/core/frontend/applets/swkbd.cpp b/src/core/frontend/applets/swkbd.cpp index c29166b65..bf53b4c45 100644 --- a/src/core/frontend/applets/swkbd.cpp +++ b/src/core/frontend/applets/swkbd.cpp @@ -120,12 +120,15 @@ ValidationError SoftwareKeyboard::ValidateButton(u8 button) const { } ValidationError SoftwareKeyboard::Finalize(const std::string& text, u8 button) { - ValidationError error; - if ((error = ValidateInput(text)) != ValidationError::None) { - return error; - } - if ((error = ValidateButton(button)) != ValidationError::None) { - return error; + // Skip check when OK is not pressed + if (button == static_cast(config.button_config)) { + ValidationError error; + if ((error = ValidateInput(text)) != ValidationError::None) { + return error; + } + if ((error = ValidateButton(button)) != ValidationError::None) { + return error; + } } data = {text, button}; data_ready = true; diff --git a/src/core/frontend/applets/swkbd.h b/src/core/frontend/applets/swkbd.h index 757130be4..7a716590d 100644 --- a/src/core/frontend/applets/swkbd.h +++ b/src/core/frontend/applets/swkbd.h @@ -4,7 +4,6 @@ #pragma once -#include #include #include #include @@ -135,7 +134,7 @@ protected: KeyboardConfig config; KeyboardData data; - std::atomic_bool data_ready = false; + bool data_ready = false; }; class DefaultKeyboard final : public SoftwareKeyboard {