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
This commit is contained in:
Pengfei Zhu 2020-05-04 17:31:17 +08:00 committed by GitHub
parent 41bff0e3b7
commit 60669a7dd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 13 deletions

View File

@ -115,6 +115,7 @@ void QtKeyboard::Execute(const Frontend::KeyboardConfig& config) {
ok_id = static_cast<u8>(this->config.button_config); ok_id = static_cast<u8>(this->config.button_config);
} }
QMetaObject::invokeMethod(this, "OpenInputDialog", Qt::BlockingQueuedConnection); QMetaObject::invokeMethod(this, "OpenInputDialog", Qt::BlockingQueuedConnection);
Finalize(result_text, result_button);
} }
void QtKeyboard::ShowError(const std::string& error) { void QtKeyboard::ShowError(const std::string& error) {
@ -125,13 +126,15 @@ void QtKeyboard::ShowError(const std::string& error) {
void QtKeyboard::OpenInputDialog() { void QtKeyboard::OpenInputDialog() {
QtKeyboardDialog dialog(&parent, this); QtKeyboardDialog dialog(&parent, this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | dialog.setWindowFlags(dialog.windowFlags() &
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); ~(Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint));
dialog.setWindowModality(Qt::WindowModal); dialog.setWindowModality(Qt::WindowModal);
dialog.exec(); dialog.exec();
LOG_INFO(Frontend, "SWKBD input dialog finished, text={}, button={}", dialog.text.toStdString(),
dialog.button); result_text = dialog.text.toStdString();
Finalize(dialog.text.toStdString(), dialog.button); result_button = dialog.button;
LOG_INFO(Frontend, "SWKBD input dialog finished, text={}, button={}", result_text,
result_button);
} }
void QtKeyboard::ShowErrorDialog(QString message) { void QtKeyboard::ShowErrorDialog(QString message) {

View File

@ -62,6 +62,9 @@ private:
QWidget& parent; QWidget& parent;
std::string result_text;
int result_button;
friend class QtKeyboardDialog; friend class QtKeyboardDialog;
friend class QtKeyboardValidator; friend class QtKeyboardValidator;
}; };

View File

@ -120,12 +120,15 @@ ValidationError SoftwareKeyboard::ValidateButton(u8 button) const {
} }
ValidationError SoftwareKeyboard::Finalize(const std::string& text, u8 button) { ValidationError SoftwareKeyboard::Finalize(const std::string& text, u8 button) {
ValidationError error; // Skip check when OK is not pressed
if ((error = ValidateInput(text)) != ValidationError::None) { if (button == static_cast<u8>(config.button_config)) {
return error; ValidationError error;
} if ((error = ValidateInput(text)) != ValidationError::None) {
if ((error = ValidateButton(button)) != ValidationError::None) { return error;
return error; }
if ((error = ValidateButton(button)) != ValidationError::None) {
return error;
}
} }
data = {text, button}; data = {text, button};
data_ready = true; data_ready = true;

View File

@ -4,7 +4,6 @@
#pragma once #pragma once
#include <atomic>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -135,7 +134,7 @@ protected:
KeyboardConfig config; KeyboardConfig config;
KeyboardData data; KeyboardData data;
std::atomic_bool data_ready = false; bool data_ready = false;
}; };
class DefaultKeyboard final : public SoftwareKeyboard { class DefaultKeyboard final : public SoftwareKeyboard {