From ae53b84efd5523e2aba3255f9f713d4a1df563b3 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:10:58 -0500 Subject: frontend/applets: Add frontend software keyboard provider and default Default implementation will return "yuzu" for any string. GUI clients (or CLI) can implement the Frontend::SoftwareKeyboardApplet class and register an instance to provide functionality. --- src/core/frontend/applets/software_keyboard.cpp | 17 ++++++++++ src/core/frontend/applets/software_keyboard.h | 44 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/core/frontend/applets/software_keyboard.cpp create mode 100644 src/core/frontend/applets/software_keyboard.h (limited to 'src/core/frontend') diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp new file mode 100644 index 000000000..8cb888a62 --- /dev/null +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -0,0 +1,17 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/backend.h" +#include "core/frontend/applets/software_keyboard.h" + +namespace Frontend { +bool DefaultSoftwareKeyboardApplet::GetText(Parameters parameters, std::u16string& text) { + if (parameters.initial_text.empty()) + text = Common::UTF8ToUTF16("yuzu"); + else + text = parameters.initial_text; + + return true; +} +} // namespace Frontend diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h new file mode 100644 index 000000000..d368385d2 --- /dev/null +++ b/src/core/frontend/applets/software_keyboard.h @@ -0,0 +1,44 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/bit_field.h" +#include "common/common_types.h" + +namespace Frontend { +class SoftwareKeyboardApplet { +public: + struct Parameters { + std::u16string submit_text; + std::u16string header_text; + std::u16string sub_text; + std::u16string guide_text; + std::u16string initial_text; + std::size_t max_length; + bool password; + bool cursor_at_beginning; + + union { + u8 value; + + BitField<1, 1, u8> disable_space; + BitField<2, 1, u8> disable_address; + BitField<3, 1, u8> disable_percent; + BitField<4, 1, u8> disable_slash; + BitField<6, 1, u8> disable_number; + BitField<7, 1, u8> disable_download_code; + }; + }; + + virtual bool GetText(Parameters parameters, std::u16string& text) = 0; + virtual ~SoftwareKeyboardApplet() = default; +}; + +class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { + bool GetText(Parameters parameters, std::u16string& text) override; +}; + +} // namespace Frontend -- cgit v1.2.3 From a81645400f9ba40b272163ef6f751ba3428b85a1 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:38:11 -0500 Subject: qt/main: Register Qt Software Keyboard frontend with AM Allows using Qt provider over default. --- src/core/frontend/applets/software_keyboard.cpp | 1 + src/yuzu/applets/software_keyboard.cpp | 1 + src/yuzu/main.cpp | 4 ++++ 3 files changed, 6 insertions(+) (limited to 'src/core/frontend') diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 8cb888a62..c1bacefef 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/logging/backend.h" +#include "common/string_util.h" #include "core/frontend/applets/software_keyboard.h" namespace Frontend { diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 9e1c59626..bd8bd0dd0 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -9,6 +9,7 @@ #include #include #include "common/logging/backend.h" +#include "common/string_util.h" #include "yuzu/applets/software_keyboard.h" QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 999086e7f..7b2a01169 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -8,9 +8,11 @@ #include // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. +#include "applets/software_keyboard.h" #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_real.h" #include "core/hle/service/acc/profile_manager.h" +#include "core/hle/service/am/applets/applets.h" // These are wrappers to avoid the calls to CreateDirectory and CreateFile because of the Windows // defines. @@ -559,6 +561,8 @@ bool GMainWindow::LoadROM(const QString& filename) { system.SetGPUDebugContext(debug_context); + Service::AM::Applets::RegisterSoftwareKeyboard(std::make_shared(*this)); + const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; const auto drd_callout = -- cgit v1.2.3 From e696ed1f4d20f28f8b26c637498962938df7d96f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 16:39:25 -0500 Subject: am: Deglobalize software keyboard applet --- src/common/string_util.cpp | 4 +- src/common/string_util.h | 4 +- src/core/core.cpp | 17 +++++++ src/core/core.h | 5 ++ src/core/frontend/applets/software_keyboard.cpp | 13 +++-- src/core/frontend/applets/software_keyboard.h | 54 +++++++++++---------- src/core/hle/kernel/svc.cpp | 8 ++-- src/core/hle/service/am/am.cpp | 14 ++++-- src/core/hle/service/am/am.h | 10 ++-- src/core/hle/service/am/applets/applets.cpp | 16 ++----- src/core/hle/service/am/applets/applets.h | 10 ++-- .../hle/service/am/applets/software_keyboard.cpp | 12 ++++- .../hle/service/am/applets/software_keyboard.h | 9 ++++ src/yuzu/applets/software_keyboard.cpp | 55 ++++++++++++++-------- src/yuzu/applets/software_keyboard.h | 33 +++++++------ src/yuzu/main.cpp | 7 ++- src/yuzu/main.h | 9 ++++ 17 files changed, 180 insertions(+), 100 deletions(-) (limited to 'src/core/frontend') diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index a1360dd26..959f278aa 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -214,13 +214,13 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t return std::string(buffer, len); } -std::u16string UTF16StringFromFixedZeroTerminatedBuffer(const char16_t* buffer, +std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, std::size_t max_len) { std::size_t len = 0; while (len < max_len && buffer[len] != '\0') ++len; - return std::u16string(buffer, len); + return std::u16string(buffer.begin(), buffer.begin() + len); } const char* TrimSourcePath(const char* path, const char* root) { diff --git a/src/common/string_util.h b/src/common/string_util.h index 95b7badaf..583fd05e6 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -68,10 +68,10 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t /** * Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't - * NUL-terminated, then the string ends at the greatest multiple of two less then or equal to + * null-terminated, then the string ends at the greatest multiple of two less then or equal to * max_len_bytes. */ -std::u16string UTF16StringFromFixedZeroTerminatedBuffer(const char16_t* buffer, +std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, std::size_t max_len); /** diff --git a/src/core/core.cpp b/src/core/core.cpp index 6d5b5a2d0..6c72fdf4a 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -23,12 +23,14 @@ #include "core/hle/kernel/process.h" #include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" +#include "core/hle/service/am/applets/software_keyboard.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" #include "core/loader/loader.h" #include "core/perf_stats.h" #include "core/settings.h" #include "core/telemetry_session.h" +#include "frontend/applets/software_keyboard.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/gpu.h" #include "video_core/renderer_base.h" @@ -136,6 +138,10 @@ struct System::Impl { if (virtual_filesystem == nullptr) virtual_filesystem = std::make_shared(); + /// Create default implementations of applets if one is not provided. + if (software_keyboard == nullptr) + software_keyboard = std::make_unique(); + auto main_process = Kernel::Process::Create(kernel, "main"); kernel.MakeCurrentProcess(main_process.get()); @@ -289,6 +295,9 @@ struct System::Impl { std::array, NUM_CPU_CORES - 1> cpu_core_threads; std::size_t active_core{}; ///< Active core, only used in single thread mode + /// Frontend applets + std::unique_ptr software_keyboard; + /// Service manager std::shared_ptr service_manager; @@ -488,6 +497,14 @@ std::shared_ptr System::GetFilesystem() const { return impl->virtual_filesystem; } +void System::SetSoftwareKeyboard(std::unique_ptr applet) { + impl->software_keyboard = std::move(applet); +} + +const Core::Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const { + return *impl->software_keyboard; +} + System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { return impl->Init(emu_window); } diff --git a/src/core/core.h b/src/core/core.h index cfacceb81..be71bd437 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -13,6 +13,7 @@ namespace Core::Frontend { class EmuWindow; +class SoftwareKeyboardApplet; } // namespace Core::Frontend namespace FileSys { @@ -236,6 +237,10 @@ public: std::shared_ptr GetFilesystem() const; + void SetSoftwareKeyboard(std::unique_ptr applet); + + const Core::Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const; + private: System(); diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index c1bacefef..41d81c293 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -3,16 +3,19 @@ // Refer to the license.txt file included. #include "common/logging/backend.h" -#include "common/string_util.h" #include "core/frontend/applets/software_keyboard.h" -namespace Frontend { -bool DefaultSoftwareKeyboardApplet::GetText(Parameters parameters, std::u16string& text) { +namespace Core::Frontend { +SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; + +bool DefaultSoftwareKeyboardApplet::GetText(SoftwareKeyboardParameters parameters, + std::u16string& text) const { if (parameters.initial_text.empty()) - text = Common::UTF8ToUTF16("yuzu"); + text = u"yuzu"; else text = parameters.initial_text; return true; } -} // namespace Frontend + +} // namespace Core::Frontend diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index d368385d2..2ea9db889 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h @@ -8,37 +8,39 @@ #include "common/bit_field.h" #include "common/common_types.h" -namespace Frontend { +namespace Core::Frontend { +struct SoftwareKeyboardParameters { + std::u16string submit_text; + std::u16string header_text; + std::u16string sub_text; + std::u16string guide_text; + std::u16string initial_text; + std::size_t max_length; + bool password; + bool cursor_at_beginning; + + union { + u8 value; + + BitField<1, 1, u8> disable_space; + BitField<2, 1, u8> disable_address; + BitField<3, 1, u8> disable_percent; + BitField<4, 1, u8> disable_slash; + BitField<6, 1, u8> disable_number; + BitField<7, 1, u8> disable_download_code; + }; +}; + class SoftwareKeyboardApplet { public: - struct Parameters { - std::u16string submit_text; - std::u16string header_text; - std::u16string sub_text; - std::u16string guide_text; - std::u16string initial_text; - std::size_t max_length; - bool password; - bool cursor_at_beginning; - - union { - u8 value; - - BitField<1, 1, u8> disable_space; - BitField<2, 1, u8> disable_address; - BitField<3, 1, u8> disable_percent; - BitField<4, 1, u8> disable_slash; - BitField<6, 1, u8> disable_number; - BitField<7, 1, u8> disable_download_code; - }; - }; + virtual ~SoftwareKeyboardApplet(); - virtual bool GetText(Parameters parameters, std::u16string& text) = 0; - virtual ~SoftwareKeyboardApplet() = default; + virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0; }; class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { - bool GetText(Parameters parameters, std::u16string& text) override; +public: + bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const override; }; -} // namespace Frontend +} // namespace Core::Frontend diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 20af65ee7..f84b00a00 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1207,14 +1207,15 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 return ERR_INVALID_ADDRESS; } - if (addr + size <= addr) { + if (!IsValidAddressRange(addr, size)) { LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})", addr, size); return ERR_INVALID_ADDRESS_STATE; } - if (permissions > static_cast(MemoryPermission::ReadWrite) || - permissions == static_cast(MemoryPermission::Write)) { + const auto perms = static_cast(permissions); + if (perms != MemoryPermission::None && perms != MemoryPermission::Read && + perms != MemoryPermission::ReadWrite) { LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", permissions); return ERR_INVALID_MEMORY_PERMISSIONS; @@ -1222,7 +1223,6 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 auto& kernel = Core::System::GetInstance().Kernel(); auto& handle_table = Core::CurrentProcess()->GetHandleTable(); - const auto perms = static_cast(permissions); const auto shared_mem_handle = SharedMemory::Create( kernel, handle_table.Get(CurrentProcess), size, perms, perms, addr); diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 53580d673..fc464270e 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -501,6 +501,8 @@ IStorage::IStorage(std::vector buffer) RegisterHandlers(functions); } +IStorage::~IStorage() = default; + const std::vector& IStorage::GetData() const { return buffer; } @@ -670,6 +672,8 @@ IStorageAccessor::IStorageAccessor(IStorage& storage) RegisterHandlers(functions); } +IStorageAccessor::~IStorageAccessor() = default; + void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; @@ -685,7 +689,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; const std::vector data{ctx.ReadBuffer()}; - const auto size = std::min(data.size(), backing.buffer.size() - offset); + const auto size = std::min(data.size(), backing.buffer.size() - offset); std::memcpy(&backing.buffer[offset], data.data(), size); @@ -701,7 +705,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; std::size_t size{ctx.GetWriteBufferSize()}; - size = std::min(size, backing.buffer.size() - offset); + size = std::min(size, backing.buffer.size() - offset); ctx.WriteBuffer(backing.buffer.data() + offset, size); @@ -787,9 +791,9 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex return; } - std::vector memory(shared_mem->size); - std::memcpy(memory.data(), shared_mem->backing_block->data() + shared_mem->backing_block_offset, - memory.size()); + const auto mem_begin = shared_mem->backing_block->begin() + shared_mem->backing_block_offset; + const auto mem_end = mem_begin + shared_mem->size; + std::vector memory{mem_begin, mem_end}; IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 640901e4a..44c1bcde5 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -158,27 +158,29 @@ private: class IStorage final : public ServiceFramework { public: explicit IStorage(std::vector buffer); + ~IStorage() override; const std::vector& GetData() const; private: - std::vector buffer; - void Open(Kernel::HLERequestContext& ctx); + std::vector buffer; + friend class IStorageAccessor; }; class IStorageAccessor final : public ServiceFramework { public: explicit IStorageAccessor(IStorage& backing); + ~IStorageAccessor() override; private: - IStorage& backing; - void GetSize(Kernel::HLERequestContext& ctx); void Write(Kernel::HLERequestContext& ctx); void Read(Kernel::HLERequestContext& ctx); + + IStorage& backing; }; class ILibraryAppletCreator final : public ServiceFramework { diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 8cc4b0f1a..03b9d83e7 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -7,23 +7,13 @@ namespace Service::AM::Applets { -std::shared_ptr software_keyboard = - std::make_shared(); +Applet::Applet() = default; + +Applet::~Applet() = default; void Applet::Initialize(std::vector> storage) { storage_stack = std::move(storage); initialized = true; } -void RegisterSoftwareKeyboard(std::shared_ptr applet) { - if (applet == nullptr) - return; - - software_keyboard = std::move(applet); -} - -std::shared_ptr GetSoftwareKeyboard() { - return software_keyboard; -} - } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 1f91392b4..47db22fb4 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -20,10 +20,17 @@ namespace Applets { class Applet { public: + Applet(); + virtual ~Applet(); + virtual void Initialize(std::vector> storage); virtual IStorage Execute() = 0; + bool IsInitialized() const { + return initialized; + } + protected: struct CommonArguments { u32_le arguments_version; @@ -39,8 +46,5 @@ protected: bool initialized = false; }; -void RegisterSoftwareKeyboard(std::shared_ptr applet); -std::shared_ptr GetSoftwareKeyboard(); - } // namespace Applets } // namespace Service::AM diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index ad1797ef1..556dea3e4 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -2,8 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/assert.h" #include "common/string_util.h" +#include "core/core.h" #include "core/frontend/applets/software_keyboard.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/software_keyboard.h" @@ -11,11 +13,13 @@ namespace Service::AM::Applets { constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8; +constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4; constexpr std::size_t DEFAULT_MAX_LENGTH = 500; +constexpr bool INTERACTIVE_STATUS_OK = false; -static Frontend::SoftwareKeyboardApplet::Parameters ConvertToFrontendParameters( +static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( KeyboardConfig config, std::u16string initial_text) { - Frontend::SoftwareKeyboardApplet::Parameters params{}; + Core::Frontend::SoftwareKeyboardParameters params{}; params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( config.submit_text.data(), config.submit_text.size()); @@ -34,6 +38,10 @@ static Frontend::SoftwareKeyboardApplet::Parameters ConvertToFrontendParameters( return params; } +SoftwareKeyboard::SoftwareKeyboard() = default; + +SoftwareKeyboard::~SoftwareKeyboard() = default; + void SoftwareKeyboard::Initialize(std::vector> storage_) { Applet::Initialize(std::move(storage_)); diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 9a37ba45f..9d77f5802 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -5,6 +5,7 @@ #pragma once #include "common/common_funcs.h" +#include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applets.h" namespace Service::AM::Applets { @@ -45,13 +46,21 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz class SoftwareKeyboard final : public Applet { public: + SoftwareKeyboard(); + ~SoftwareKeyboard() override; + void Initialize(std::vector> storage) override; + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ReceiveInteractiveData(std::shared_ptr storage) override; IStorage Execute() override; private: KeyboardConfig config; std::u16string initial_text; + bool complete = false; + std::vector final_data; }; } // namespace Service::AM::Applets diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index bd8bd0dd0..fad150ec1 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -2,21 +2,20 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include #include #include #include #include #include -#include "common/logging/backend.h" -#include "common/string_util.h" #include "yuzu/applets/software_keyboard.h" +#include "yuzu/main.h" QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( - Frontend::SoftwareKeyboardApplet::Parameters parameters) + Core::Frontend::SoftwareKeyboardParameters parameters) : parameters(std::move(parameters)) {} -QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int&) const { +QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { if (input.size() > parameters.max_length) return Invalid; if (parameters.disable_space && input.contains(' ')) @@ -28,18 +27,20 @@ QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int&) co if (parameters.disable_slash && (input.contains('/') || input.contains('\\'))) return Invalid; if (parameters.disable_number && - std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) + std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { return Invalid; + } if (parameters.disable_download_code && - std::any_of(input.begin(), input.end(), [](QChar c) { return c == 'O' || c == 'I'; })) + std::any_of(input.begin(), input.end(), [](QChar c) { return c == 'O' || c == 'I'; })) { return Invalid; + } return Acceptable; } QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( - QWidget* parent, Frontend::SoftwareKeyboardApplet::Parameters parameters_) + QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_) : QDialog(parent), parameters(std::move(parameters_)) { layout = new QVBoxLayout; @@ -79,9 +80,11 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( layout->addWidget(line_edit); layout->addWidget(buttons); setLayout(layout); - setWindowTitle("Software Keyboard"); + setWindowTitle(tr("Software Keyboard")); } +QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; + void QtSoftwareKeyboardDialog::Submit() { ok = true; text = line_edit->text().toStdU16String(); @@ -90,19 +93,33 @@ void QtSoftwareKeyboardDialog::Submit() { void QtSoftwareKeyboardDialog::Reject() { ok = false; - text = Common::UTF8ToUTF16(""); + text.clear(); accept(); } -QtSoftwareKeyboard::QtSoftwareKeyboard(QWidget& parent) : parent(parent) {} +std::u16string QtSoftwareKeyboardDialog::GetText() { + return text; +} + +bool QtSoftwareKeyboardDialog::GetStatus() { + return ok; +} -bool QtSoftwareKeyboard::GetText(Parameters parameters, std::u16string& text) { - QtSoftwareKeyboardDialog dialog(&parent, parameters); - dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); - dialog.setWindowModality(Qt::WindowModal); - dialog.exec(); +QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& parent) : main_window(parent) {} + +QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; + +bool QtSoftwareKeyboard::GetText(Core::Frontend::SoftwareKeyboardParameters parameters, + std::u16string& text) const { + bool success; + QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardGetText", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, success), + Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters), + Q_ARG(std::u16string&, text)); + return success; +} - text = dialog.text; - return dialog.ok; +void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message) const { + QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardInvokeCheckDialog", + Qt::BlockingQueuedConnection, Q_ARG(std::u16string, error_message)); } diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 2a18419db..1069c10ec 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -3,11 +3,13 @@ // Refer to the license.txt file included. #pragma once + #include #include #include "common/assert.h" #include "core/frontend/applets/software_keyboard.h" +class GMainWindow; class QDialogButtonBox; class QLabel; class QLineEdit; @@ -16,11 +18,11 @@ class QtSoftwareKeyboard; class QtSoftwareKeyboardValidator final : public QValidator { public: - explicit QtSoftwareKeyboardValidator(Frontend::SoftwareKeyboardApplet::Parameters parameters); - State validate(QString&, int&) const override; + explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters); + State validate(QString& input, int& pos) const override; private: - Frontend::SoftwareKeyboardApplet::Parameters parameters; + Core::Frontend::SoftwareKeyboardParameters parameters; }; class QtSoftwareKeyboardDialog final : public QDialog { @@ -28,10 +30,15 @@ class QtSoftwareKeyboardDialog final : public QDialog { public: QtSoftwareKeyboardDialog(QWidget* parent, - Frontend::SoftwareKeyboardApplet::Parameters parameters); + Core::Frontend::SoftwareKeyboardParameters parameters); + ~QtSoftwareKeyboardDialog() override; + void Submit(); void Reject(); + std::u16string GetText(); + bool GetStatus(); + private: bool ok = false; std::u16string text; @@ -43,20 +50,18 @@ private: QLineEdit* line_edit; QVBoxLayout* layout; - Frontend::SoftwareKeyboardApplet::Parameters parameters; - - friend class QtSoftwareKeyboard; + Core::Frontend::SoftwareKeyboardParameters parameters; }; -class QtSoftwareKeyboard final : public QObject, public Frontend::SoftwareKeyboardApplet { +class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { public: - explicit QtSoftwareKeyboard(QWidget& parent); - bool GetText(Parameters parameters, std::u16string& text) override; + explicit QtSoftwareKeyboard(GMainWindow& parent); + ~QtSoftwareKeyboard() override; - ~QtSoftwareKeyboard() { - UNREACHABLE(); - } + bool GetText(Core::Frontend::SoftwareKeyboardParameters parameters, + std::u16string& text) const override; + void SendTextCheckDialog(std::u16string error_message) const override; private: - QWidget& parent; + GMainWindow& main_window; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 7b2a01169..9b2c09f32 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -561,7 +561,7 @@ bool GMainWindow::LoadROM(const QString& filename) { system.SetGPUDebugContext(debug_context); - Service::AM::Applets::RegisterSoftwareKeyboard(std::make_shared(*this)); + system.SetSoftwareKeyboard(std::make_unique(*this)); const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; @@ -1232,8 +1232,13 @@ void GMainWindow::OnMenuRecentFile() { void GMainWindow::OnStartGame() { emu_thread->SetRunning(true); + + qRegisterMetaType( + "core::Frontend::SoftwareKeyboardParameters"); qRegisterMetaType("Core::System::ResultStatus"); qRegisterMetaType("std::string"); + qRegisterMetaType("std::u16string"); + connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); ui.action_Start->setEnabled(false); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 929250e8c..38074e3f0 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -29,6 +29,10 @@ class ProfilerWidget; class WaitTreeWidget; enum class GameListOpenTarget; +namespace Core::Frontend { +struct SoftwareKeyboardParameters; +} // namespace Core::Frontend + namespace FileSys { class RegisteredCacheUnion; class VfsFilesystem; @@ -95,6 +99,11 @@ signals: // Signal that tells widgets to update icons to use the current theme void UpdateThemedIcons(); +public slots: + bool SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters, + std::u16string& text); + void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); + private: void InitializeWidgets(); void InitializeDebugWidgets(); -- cgit v1.2.3 From fed6ab14c37f196f2a2fd378b46d7e5bd0118224 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 16:41:31 -0500 Subject: am: Implement text check software keyboard mode Allows the game to verify and send a message to the frontend. --- src/core/frontend/applets/software_keyboard.cpp | 6 ++ src/core/frontend/applets/software_keyboard.h | 2 + src/core/hle/service/am/am.cpp | 37 ++++++++++-- src/core/hle/service/am/applets/applets.h | 5 ++ .../hle/service/am/applets/software_keyboard.cpp | 67 +++++++++++++++++++--- src/yuzu/main.cpp | 17 ++++++ 6 files changed, 120 insertions(+), 14 deletions(-) (limited to 'src/core/frontend') diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 41d81c293..05e2dc6b7 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -18,4 +18,10 @@ bool DefaultSoftwareKeyboardApplet::GetText(SoftwareKeyboardParameters parameter return true; } +void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(std::u16string error_message) const { + LOG_WARNING(Service_AM, + "(STUBBED) called - Default fallback software keyboard does not support text " + "check! (error_message={})", + Common::UTF16ToUTF8(error_message)); +} } // namespace Core::Frontend diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index 2ea9db889..0a82aac0d 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h @@ -36,11 +36,13 @@ public: virtual ~SoftwareKeyboardApplet(); virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0; + virtual void SendTextCheckDialog(std::u16string error_message) const = 0; }; class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { public: bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const override; + void SendTextCheckDialog(std::u16string error_message) const override; }; } // namespace Core::Frontend diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index fc464270e..ea00c5c72 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -544,7 +544,7 @@ public: {102, nullptr, "PushExtraStorage"}, {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, - {105, nullptr, "GetPopOutDataEvent"}, + {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"}, {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, {110, nullptr, "NeedsToExitProcess"}, {120, nullptr, "GetLibraryAppletInfo"}, @@ -558,6 +558,8 @@ public: auto& kernel = Core::System::GetInstance().Kernel(); state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:StateChangedEvent"); + pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, + "ILibraryAppletAccessor:PopDataOutEvent"); pop_interactive_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); @@ -585,9 +587,16 @@ private: ASSERT(applet != nullptr); applet->Initialize(storage_stack); - interactive_storage_stack.push_back(std::make_shared(applet->Execute())); + const auto data = std::make_shared(applet->Execute()); state_changed_event->Signal(); - pop_interactive_out_data_event->Signal(); + + if (applet->TransactionComplete()) { + storage_stack.push_back(data); + pop_out_data_event->Signal(); + } else { + interactive_storage_stack.push_back(data); + pop_interactive_out_data_event->Signal(); + } IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -617,6 +626,19 @@ private: IPC::RequestParser rp{ctx}; interactive_storage_stack.push_back(rp.PopIpcInterface()); + ASSERT(applet->IsInitialized()); + applet->ReceiveInteractiveData(interactive_storage_stack.back()); + const auto data = std::make_shared(applet->Execute()); + state_changed_event->Signal(); + + if (applet->TransactionComplete()) { + storage_stack.push_back(data); + pop_out_data_event->Signal(); + } else { + interactive_storage_stack.push_back(data); + pop_interactive_out_data_event->Signal(); + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -633,9 +655,13 @@ private: LOG_DEBUG(Service_AM, "called"); } - void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { - pop_interactive_out_data_event->Signal(); + void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(pop_out_data_event); + } + void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(pop_interactive_out_data_event); @@ -647,6 +673,7 @@ private: std::vector> storage_stack; std::vector> interactive_storage_stack; Kernel::SharedPtr state_changed_event; + Kernel::SharedPtr pop_out_data_event; Kernel::SharedPtr pop_interactive_out_data_event; }; diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 47db22fb4..6d90eb608 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -8,6 +8,8 @@ #include #include "common/swap.h" +union ResultCode; + namespace Frontend { class SoftwareKeyboardApplet; } @@ -25,6 +27,9 @@ public: virtual void Initialize(std::vector> storage); + virtual bool TransactionComplete() const = 0; + virtual ResultCode GetStatus() const = 0; + virtual void ReceiveInteractiveData(std::shared_ptr storage) = 0; virtual IStorage Execute() = 0; bool IsInitialized() const { diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 556dea3e4..044a16264 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -50,28 +50,77 @@ void SoftwareKeyboard::Initialize(std::vector> storage ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); - ASSERT_MSG(config.text_check == 0, "Text check software keyboard mode is not implemented!"); - const auto& work_buffer = storage_stack[2]->GetData(); - std::memcpy(initial_text.data(), work_buffer.data() + config.initial_string_offset, - config.initial_string_size); + + if (config.initial_string_size == 0) + return; + + std::vector string(config.initial_string_size); + std::memcpy(string.data(), work_buffer.data() + 4, string.size() * 2); + initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()); +} + +bool SoftwareKeyboard::TransactionComplete() const { + return complete; +} + +ResultCode SoftwareKeyboard::GetStatus() const { + return RESULT_SUCCESS; +} + +void SoftwareKeyboard::ReceiveInteractiveData(std::shared_ptr storage) { + if (complete) + return; + + const auto data = storage->GetData(); + const auto status = static_cast(data[0]); + + if (status == INTERACTIVE_STATUS_OK) { + complete = true; + } else { + const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; + + std::array string; + std::memcpy(string.data(), data.data() + 4, string.size() * 2); + frontend.SendTextCheckDialog( + Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size())); + } } IStorage SoftwareKeyboard::Execute() { - const auto frontend{GetSoftwareKeyboard()}; - ASSERT(frontend != nullptr); + if (complete) + return IStorage{final_data}; + + const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; const auto parameters = ConvertToFrontendParameters(config, initial_text); std::u16string text; - const auto success = frontend->GetText(parameters, text); + const auto success = frontend.GetText(parameters, text); std::vector output(SWKBD_OUTPUT_BUFFER_SIZE); if (success) { - output[0] = 1; + if (config.text_check) { + const auto size = static_cast(text.size() * 2 + 4); + std::memcpy(output.data(), &size, sizeof(u32)); + } else { + output[0] = 1; + } + std::memcpy(output.data() + 4, text.data(), - std::min(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); + std::min(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); + } else { + complete = true; + final_data = std::move(output); + return IStorage{final_data}; + } + + complete = !config.text_check; + + if (complete) { + final_data = std::move(output); + return IStorage{final_data}; } return IStorage{output}; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9b2c09f32..447d9dece 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -61,6 +61,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual #include "core/file_sys/romfs.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/submission_package.h" +#include "core/frontend/applets/software_keyboard.h" #include "core/hle/kernel/process.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_ldr.h" @@ -206,6 +207,22 @@ GMainWindow::~GMainWindow() { delete render_window; } +bool GMainWindow::SoftwareKeyboardGetText( + const Core::Frontend::SoftwareKeyboardParameters& parameters, std::u16string& text) { + QtSoftwareKeyboardDialog dialog(this, parameters); + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | + Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::WindowModal); + dialog.exec(); + + text = dialog.GetText(); + return dialog.GetStatus(); +} + +void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { + QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message)); +} + void GMainWindow::InitializeWidgets() { #ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING ui.action_Report_Compatibility->setVisible(true); -- cgit v1.2.3 From 3cf7246e376445320e2b55165265228736f65214 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 16:57:59 -0500 Subject: am: Implement ILibraryAppletAccessor IsCompleted and GetResult --- src/core/frontend/applets/software_keyboard.cpp | 1 + src/core/hle/service/am/am.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/core/frontend') diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 05e2dc6b7..cf5e2ea31 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/logging/backend.h" +#include "common/string_util.h" #include "core/frontend/applets/software_keyboard.h" namespace Core::Frontend { diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index ea00c5c72..3201e2d4b 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -533,7 +533,7 @@ public: // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, - {1, nullptr, "IsCompleted"}, + {1, &ILibraryAppletAccessor::IsCompleted, "IsCompleted"}, {10, &ILibraryAppletAccessor::Start, "Start"}, {20, nullptr, "RequestExit"}, {25, nullptr, "Terminate"}, @@ -576,11 +576,15 @@ private: LOG_WARNING(Service_AM, "(STUBBED) called"); } - void GetResult(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; + void IsCompleted(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); + rb.Push(applet->TransactionComplete()); + } - LOG_WARNING(Service_AM, "(STUBBED) called"); + void GetResult(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(applet->GetStatus()); } void Start(Kernel::HLERequestContext& ctx) { -- cgit v1.2.3 From 7cfb29de23836aa1873bbb108e3d25a0e9dcfa6d Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 20:16:38 -0500 Subject: am: Allow applets to push multiple and different channels of data --- src/core/frontend/applets/software_keyboard.cpp | 10 +++---- src/core/frontend/applets/software_keyboard.h | 5 ++-- src/core/hle/service/am/am.cpp | 34 ++++++++++------------ src/core/hle/service/am/applets/applets.h | 6 +++- .../hle/service/am/applets/software_keyboard.cpp | 27 +++++++---------- .../hle/service/am/applets/software_keyboard.h | 3 +- src/yuzu/applets/software_keyboard.cpp | 15 +++++----- src/yuzu/applets/software_keyboard.h | 8 ++--- src/yuzu/main.cpp | 14 +++++---- src/yuzu/main.h | 4 +-- 10 files changed, 62 insertions(+), 64 deletions(-) (limited to 'src/core/frontend') diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index cf5e2ea31..2445a980d 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -9,14 +9,12 @@ namespace Core::Frontend { SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; -bool DefaultSoftwareKeyboardApplet::GetText(SoftwareKeyboardParameters parameters, - std::u16string& text) const { +std::optional DefaultSoftwareKeyboardApplet::GetText( + SoftwareKeyboardParameters parameters) const { if (parameters.initial_text.empty()) - text = u"yuzu"; - else - text = parameters.initial_text; + return u"yuzu"; - return true; + return parameters.initial_text; } void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(std::u16string error_message) const { diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index 0a82aac0d..7387ee8d7 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include "common/bit_field.h" #include "common/common_types.h" @@ -35,13 +36,13 @@ class SoftwareKeyboardApplet { public: virtual ~SoftwareKeyboardApplet(); - virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0; + virtual std::optional GetText(SoftwareKeyboardParameters parameters) const = 0; virtual void SendTextCheckDialog(std::u16string error_message) const = 0; }; class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { public: - bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const override; + std::optional GetText(SoftwareKeyboardParameters parameters) const override; void SendTextCheckDialog(std::u16string error_message) const override; }; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 3201e2d4b..3f8d97d31 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -566,6 +566,16 @@ public: } private: + void AppletStorageProxyOutData(IStorage storage) { + storage_stack.push_back(std::make_shared(storage)); + pop_out_data_event->Signal(); + } + + void AppletStorageProxyOutInteractiveData(IStorage storage) { + interactive_storage_stack.push_back(std::make_shared(storage)); + pop_interactive_out_data_event->Signal(); + } + void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { state_changed_event->Signal(); @@ -591,17 +601,11 @@ private: ASSERT(applet != nullptr); applet->Initialize(storage_stack); - const auto data = std::make_shared(applet->Execute()); + applet->Execute( + [this](IStorage storage) { AppletStorageProxyOutData(storage); }, + [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }); state_changed_event->Signal(); - if (applet->TransactionComplete()) { - storage_stack.push_back(data); - pop_out_data_event->Signal(); - } else { - interactive_storage_stack.push_back(data); - pop_interactive_out_data_event->Signal(); - } - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -632,17 +636,11 @@ private: ASSERT(applet->IsInitialized()); applet->ReceiveInteractiveData(interactive_storage_stack.back()); - const auto data = std::make_shared(applet->Execute()); + applet->Execute( + [this](IStorage storage) { AppletStorageProxyOutData(storage); }, + [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }); state_changed_event->Signal(); - if (applet->TransactionComplete()) { - storage_stack.push_back(data); - pop_out_data_event->Signal(); - } else { - interactive_storage_stack.push_back(data); - pop_interactive_out_data_event->Signal(); - } - IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 6d90eb608..7fbaaf2f3 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include "common/swap.h" @@ -20,6 +21,8 @@ class IStorage; namespace Applets { +using AppletStorageProxyFunction = std::function; + class Applet { public: Applet(); @@ -30,7 +33,8 @@ public: virtual bool TransactionComplete() const = 0; virtual ResultCode GetStatus() const = 0; virtual void ReceiveInteractiveData(std::shared_ptr storage) = 0; - virtual IStorage Execute() = 0; + virtual void Execute(AppletStorageProxyFunction out_data, + AppletStorageProxyFunction out_interactive_data) = 0; bool IsInitialized() const { return initialized; diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 044a16264..7352f3bdf 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -87,42 +87,37 @@ void SoftwareKeyboard::ReceiveInteractiveData(std::shared_ptr storage) } } -IStorage SoftwareKeyboard::Execute() { +void SoftwareKeyboard::Execute(AppletStorageProxyFunction out_data, + AppletStorageProxyFunction out_interactive_data) { if (complete) - return IStorage{final_data}; + return; const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; const auto parameters = ConvertToFrontendParameters(config, initial_text); - std::u16string text; - const auto success = frontend.GetText(parameters, text); + const auto res = frontend.GetText(parameters); std::vector output(SWKBD_OUTPUT_BUFFER_SIZE); - if (success) { + if (res.has_value()) { if (config.text_check) { - const auto size = static_cast(text.size() * 2 + 4); + const auto size = static_cast(res->size() * 2 + 4); std::memcpy(output.data(), &size, sizeof(u32)); } else { output[0] = 1; } - std::memcpy(output.data() + 4, text.data(), - std::min(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); + std::memcpy(output.data() + 4, res->data(), + std::min(res->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); } else { complete = true; - final_data = std::move(output); - return IStorage{final_data}; + out_data(IStorage{output}); + return; } complete = !config.text_check; - if (complete) { - final_data = std::move(output); - return IStorage{final_data}; - } - - return IStorage{output}; + (complete ? out_data : out_interactive_data)(IStorage{output}); } } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 9d77f5802..66de4bc59 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -54,7 +54,8 @@ public: bool TransactionComplete() const override; ResultCode GetStatus() const override; void ReceiveInteractiveData(std::shared_ptr storage) override; - IStorage Execute() override; + void Execute(AppletStorageProxyFunction out_data, + AppletStorageProxyFunction out_interactive_data) override; private: KeyboardConfig config; diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index fad150ec1..92992ef87 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -97,11 +97,11 @@ void QtSoftwareKeyboardDialog::Reject() { accept(); } -std::u16string QtSoftwareKeyboardDialog::GetText() { +std::u16string QtSoftwareKeyboardDialog::GetText() const { return text; } -bool QtSoftwareKeyboardDialog::GetStatus() { +bool QtSoftwareKeyboardDialog::GetStatus() const { return ok; } @@ -109,13 +109,12 @@ QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& parent) : main_window(parent QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; -bool QtSoftwareKeyboard::GetText(Core::Frontend::SoftwareKeyboardParameters parameters, - std::u16string& text) const { - bool success; +std::optional QtSoftwareKeyboard::GetText( + Core::Frontend::SoftwareKeyboardParameters parameters) const { + std::optional success; QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardGetText", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, success), - Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters), - Q_ARG(std::u16string&, text)); + Q_RETURN_ARG(std::optional, success), + Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters)); return success; } diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 1069c10ec..8d95ca511 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -36,8 +36,8 @@ public: void Submit(); void Reject(); - std::u16string GetText(); - bool GetStatus(); + std::u16string GetText() const; + bool GetStatus() const; private: bool ok = false; @@ -58,8 +58,8 @@ public: explicit QtSoftwareKeyboard(GMainWindow& parent); ~QtSoftwareKeyboard() override; - bool GetText(Core::Frontend::SoftwareKeyboardParameters parameters, - std::u16string& text) const override; + std::optional GetText( + Core::Frontend::SoftwareKeyboardParameters parameters) const override; void SendTextCheckDialog(std::u16string error_message) const override; private: diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 447d9dece..a11eb7f86 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -207,16 +207,18 @@ GMainWindow::~GMainWindow() { delete render_window; } -bool GMainWindow::SoftwareKeyboardGetText( - const Core::Frontend::SoftwareKeyboardParameters& parameters, std::u16string& text) { +std::optional GMainWindow::SoftwareKeyboardGetText( + const Core::Frontend::SoftwareKeyboardParameters& parameters) { QtSoftwareKeyboardDialog dialog(this, parameters); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); dialog.exec(); - text = dialog.GetText(); - return dialog.GetStatus(); + if (!dialog.GetStatus()) + return std::nullopt; + + return dialog.GetText(); } void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { @@ -1251,10 +1253,10 @@ void GMainWindow::OnStartGame() { emu_thread->SetRunning(true); qRegisterMetaType( - "core::Frontend::SoftwareKeyboardParameters"); + "Core::Frontend::SoftwareKeyboardParameters"); qRegisterMetaType("Core::System::ResultStatus"); qRegisterMetaType("std::string"); - qRegisterMetaType("std::u16string"); + qRegisterMetaType>("std::optional"); connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 38074e3f0..8fbe998ea 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -100,8 +100,8 @@ signals: void UpdateThemedIcons(); public slots: - bool SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters, - std::u16string& text); + std::optional SoftwareKeyboardGetText( + const Core::Frontend::SoftwareKeyboardParameters& parameters); void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); private: -- cgit v1.2.3 From 8b433beff34c382e50334bb59c4f71394845558c Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 12 Nov 2018 11:08:09 -0500 Subject: software_keyboard: Make GetText asynchronous a --- src/core/frontend/applets/software_keyboard.cpp | 7 +++--- src/core/frontend/applets/software_keyboard.h | 7 ++++-- src/core/hle/service/am/am.cpp | 2 +- .../hle/service/am/applets/software_keyboard.cpp | 19 +++++++++++---- .../hle/service/am/applets/software_keyboard.h | 5 ++++ src/yuzu/applets/software_keyboard.cpp | 27 ++++++++++++++-------- src/yuzu/applets/software_keyboard.h | 15 +++++++++--- src/yuzu/main.cpp | 6 ++--- src/yuzu/main.h | 5 ++-- 9 files changed, 64 insertions(+), 29 deletions(-) (limited to 'src/core/frontend') diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 2445a980d..4105101b3 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -9,12 +9,13 @@ namespace Core::Frontend { SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; -std::optional DefaultSoftwareKeyboardApplet::GetText( +void DefaultSoftwareKeyboardApplet::RequestText( + std::function)> out, SoftwareKeyboardParameters parameters) const { if (parameters.initial_text.empty()) - return u"yuzu"; + out(u"yuzu"); - return parameters.initial_text; + out(parameters.initial_text); } void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(std::u16string error_message) const { diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index 7387ee8d7..5420ea883 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include "common/bit_field.h" @@ -36,13 +37,15 @@ class SoftwareKeyboardApplet { public: virtual ~SoftwareKeyboardApplet(); - virtual std::optional GetText(SoftwareKeyboardParameters parameters) const = 0; + virtual void RequestText(std::function)> out, + SoftwareKeyboardParameters parameters) const = 0; virtual void SendTextCheckDialog(std::u16string error_message) const = 0; }; class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { public: - std::optional GetText(SoftwareKeyboardParameters parameters) const override; + void RequestText(std::function)> out, + SoftwareKeyboardParameters parameters) const override; void SendTextCheckDialog(std::u16string error_message) const override; }; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 3f8d97d31..d040d4776 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -718,7 +718,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { const u64 offset{rp.Pop()}; const std::vector data{ctx.ReadBuffer()}; - const auto size = std::min(data.size(), backing.buffer.size() - offset); + const auto size = std::min(data.size(), backing.buffer.size() - offset); std::memcpy(&backing.buffer[offset], data.data(), size); diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 7352f3bdf..66b34d5ac 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -43,6 +43,10 @@ SoftwareKeyboard::SoftwareKeyboard() = default; SoftwareKeyboard::~SoftwareKeyboard() = default; void SoftwareKeyboard::Initialize(std::vector> storage_) { + complete = false; + initial_text.clear(); + final_data.clear(); + Applet::Initialize(std::move(storage_)); ASSERT(storage_stack.size() >= 2); @@ -96,20 +100,25 @@ void SoftwareKeyboard::Execute(AppletStorageProxyFunction out_data, const auto parameters = ConvertToFrontendParameters(config, initial_text); - const auto res = frontend.GetText(parameters); + this->out_data = out_data; + this->out_interactive_data = out_interactive_data; + frontend.RequestText([this](std::optional text) { WriteText(text); }, + parameters); +} +void SoftwareKeyboard::WriteText(std::optional text) { std::vector output(SWKBD_OUTPUT_BUFFER_SIZE); - if (res.has_value()) { + if (text.has_value()) { if (config.text_check) { - const auto size = static_cast(res->size() * 2 + 4); + const auto size = static_cast(text->size() * 2 + 4); std::memcpy(output.data(), &size, sizeof(u32)); } else { output[0] = 1; } - std::memcpy(output.data() + 4, res->data(), - std::min(res->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); + std::memcpy(output.data() + 4, text->data(), + std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); } else { complete = true; out_data(IStorage{output}); diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 66de4bc59..b08bff3d7 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -57,11 +57,16 @@ public: void Execute(AppletStorageProxyFunction out_data, AppletStorageProxyFunction out_interactive_data) override; + void WriteText(std::optional text); + private: KeyboardConfig config; std::u16string initial_text; bool complete = false; std::vector final_data; + + AppletStorageProxyFunction out_data; + AppletStorageProxyFunction out_interactive_data; }; } // namespace Service::AM::Applets diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 92992ef87..9fb179f5c 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -105,20 +105,27 @@ bool QtSoftwareKeyboardDialog::GetStatus() const { return ok; } -QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& parent) : main_window(parent) {} +QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { + connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window, + &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection); + connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window, + &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection); + connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this, + &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection); +} QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; -std::optional QtSoftwareKeyboard::GetText( - Core::Frontend::SoftwareKeyboardParameters parameters) const { - std::optional success; - QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardGetText", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(std::optional, success), - Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters)); - return success; +void QtSoftwareKeyboard::RequestText(std::function)> out, + Core::Frontend::SoftwareKeyboardParameters parameters) const { + text_output = out; + emit MainWindowGetText(parameters); } void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message) const { - QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardInvokeCheckDialog", - Qt::BlockingQueuedConnection, Q_ARG(std::u16string, error_message)); + emit MainWindowTextCheckDialog(error_message); +} + +void QtSoftwareKeyboard::MainWindowFinishedText(std::optional text) { + text_output(text); } diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 8d95ca511..670b05dc9 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -54,14 +54,23 @@ private: }; class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { + Q_OBJECT + public: explicit QtSoftwareKeyboard(GMainWindow& parent); ~QtSoftwareKeyboard() override; - std::optional GetText( - Core::Frontend::SoftwareKeyboardParameters parameters) const override; + void RequestText(std::function)> out, + Core::Frontend::SoftwareKeyboardParameters parameters) const override; void SendTextCheckDialog(std::u16string error_message) const override; +signals: + void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; + void MainWindowTextCheckDialog(std::u16string error_message) const; + +public slots: + void MainWindowFinishedText(std::optional text); + private: - GMainWindow& main_window; + mutable std::function)> text_output; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index a11eb7f86..28c53cc87 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -207,7 +207,7 @@ GMainWindow::~GMainWindow() { delete render_window; } -std::optional GMainWindow::SoftwareKeyboardGetText( +void GMainWindow::SoftwareKeyboardGetText( const Core::Frontend::SoftwareKeyboardParameters& parameters) { QtSoftwareKeyboardDialog dialog(this, parameters); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | @@ -216,9 +216,9 @@ std::optional GMainWindow::SoftwareKeyboardGetText( dialog.exec(); if (!dialog.GetStatus()) - return std::nullopt; + emit SoftwareKeyboardFinishedText(std::nullopt); - return dialog.GetText(); + emit SoftwareKeyboardFinishedText(dialog.GetText()); } void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 8fbe998ea..d83169805 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -99,9 +99,10 @@ signals: // Signal that tells widgets to update icons to use the current theme void UpdateThemedIcons(); + void SoftwareKeyboardFinishedText(std::optional text); + public slots: - std::optional SoftwareKeyboardGetText( - const Core::Frontend::SoftwareKeyboardParameters& parameters); + void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); private: -- cgit v1.2.3 From 19b2571aecfff680c7a414c505eafc26264b6f2f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 17 Nov 2018 12:18:03 -0500 Subject: applet: Add operation completed callback --- src/core/frontend/applets/software_keyboard.cpp | 4 +++- src/core/frontend/applets/software_keyboard.h | 6 ++++-- src/core/hle/service/am/am.cpp | 6 ++++-- src/core/hle/service/am/applets/software_keyboard.cpp | 2 +- src/yuzu/applets/software_keyboard.cpp | 14 +++++++++++++- src/yuzu/applets/software_keyboard.h | 5 ++++- src/yuzu/main.cpp | 5 ++++- src/yuzu/main.h | 1 + 8 files changed, 34 insertions(+), 9 deletions(-) (limited to 'src/core/frontend') diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 4105101b3..856ed33da 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp @@ -18,10 +18,12 @@ void DefaultSoftwareKeyboardApplet::RequestText( out(parameters.initial_text); } -void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(std::u16string error_message) const { +void DefaultSoftwareKeyboardApplet::SendTextCheckDialog( + std::u16string error_message, std::function finished_check) const { LOG_WARNING(Service_AM, "(STUBBED) called - Default fallback software keyboard does not support text " "check! (error_message={})", Common::UTF16ToUTF8(error_message)); + finished_check(); } } // namespace Core::Frontend diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index 5420ea883..f9b202664 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h @@ -39,14 +39,16 @@ public: virtual void RequestText(std::function)> out, SoftwareKeyboardParameters parameters) const = 0; - virtual void SendTextCheckDialog(std::u16string error_message) const = 0; + virtual void SendTextCheckDialog(std::u16string error_message, + std::function finished_check) const = 0; }; class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { public: void RequestText(std::function)> out, SoftwareKeyboardParameters parameters) const override; - void SendTextCheckDialog(std::u16string error_message) const override; + void SendTextCheckDialog(std::u16string error_message, + std::function finished_check) const override; }; } // namespace Core::Frontend diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 470253ef1..5cbcb8d91 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -605,8 +605,10 @@ private: ASSERT(applet != nullptr); applet->Initialize(storage_stack); - storage_stack.clear(); - interactive_storage_stack.clear(); + while (!storage_stack.empty()) + storage_stack.pop(); + while (!interactive_storage_stack.empty()) + interactive_storage_stack.pop(); applet->Execute([this](IStorage storage) { AppletStorageProxyOutData(storage); }, [this](IStorage storage) { AppletStorageProxyOutInteractiveData(storage); }, [this] { state_changed_event->Signal(); }); diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index bb28a2e8d..039bfcc0f 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -87,7 +87,7 @@ void SoftwareKeyboard::ReceiveInteractiveData(std::shared_ptr storage) std::array string; std::memcpy(string.data(), data.data() + 4, string.size() * 2); frontend.SendTextCheckDialog( - Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size())); + Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()), state); } } diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 9fb179f5c..83b9c320b 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -3,11 +3,13 @@ // Refer to the license.txt file included. #include +#include #include #include #include #include #include +#include "core/hle/lock.h" #include "yuzu/applets/software_keyboard.h" #include "yuzu/main.h" @@ -122,10 +124,20 @@ void QtSoftwareKeyboard::RequestText(std::function finished_check) const { + this->finished_check = finished_check; emit MainWindowTextCheckDialog(error_message); } void QtSoftwareKeyboard::MainWindowFinishedText(std::optional text) { + // Acquire the HLE mutex + std::lock_guard lock(HLE::g_hle_lock); text_output(text); } + +void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { + // Acquire the HLE mutex + std::lock_guard lock(HLE::g_hle_lock); + finished_check(); +} diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 670b05dc9..8d56f5db2 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -62,7 +62,8 @@ public: void RequestText(std::function)> out, Core::Frontend::SoftwareKeyboardParameters parameters) const override; - void SendTextCheckDialog(std::u16string error_message) const override; + void SendTextCheckDialog(std::u16string error_message, + std::function finished_check) const override; signals: void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; @@ -70,7 +71,9 @@ signals: public slots: void MainWindowFinishedText(std::optional text); + void MainWindowFinishedCheckDialog(); private: mutable std::function)> text_output; + mutable std::function finished_check; }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 28c53cc87..4262bd0eb 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -215,14 +215,17 @@ void GMainWindow::SoftwareKeyboardGetText( dialog.setWindowModality(Qt::WindowModal); dialog.exec(); - if (!dialog.GetStatus()) + if (!dialog.GetStatus()) { emit SoftwareKeyboardFinishedText(std::nullopt); + return; + } emit SoftwareKeyboardFinishedText(dialog.GetText()); } void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message)); + emit SoftwareKeyboardFinishedCheckDialog(); } void GMainWindow::InitializeWidgets() { diff --git a/src/yuzu/main.h b/src/yuzu/main.h index d83169805..674e73412 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -100,6 +100,7 @@ signals: void UpdateThemedIcons(); void SoftwareKeyboardFinishedText(std::optional text); + void SoftwareKeyboardFinishedCheckDialog(); public slots: void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); -- cgit v1.2.3