2
1
Fork 0
mirror of https://github.com/yuzu-emu/yuzu.git synced 2024-07-04 23:31:19 +01:00

am: Deglobalize software keyboard applet

This commit is contained in:
Zach Hilman 2018-11-11 16:39:25 -05:00
parent a81645400f
commit e696ed1f4d
17 changed files with 182 additions and 102 deletions

View file

@ -214,13 +214,13 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t
return std::string(buffer, len); 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 max_len) {
std::size_t len = 0; std::size_t len = 0;
while (len < max_len && buffer[len] != '\0') while (len < max_len && buffer[len] != '\0')
++len; ++len;
return std::u16string(buffer, len); return std::u16string(buffer.begin(), buffer.begin() + len);
} }
const char* TrimSourcePath(const char* path, const char* root) { const char* TrimSourcePath(const char* path, const char* root) {

View file

@ -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 * 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. * max_len_bytes.
*/ */
std::u16string UTF16StringFromFixedZeroTerminatedBuffer(const char16_t* buffer, std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
std::size_t max_len); std::size_t max_len);
/** /**

View file

@ -23,12 +23,14 @@
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
#include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/scheduler.h"
#include "core/hle/kernel/thread.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/service.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#include "core/perf_stats.h" #include "core/perf_stats.h"
#include "core/settings.h" #include "core/settings.h"
#include "core/telemetry_session.h" #include "core/telemetry_session.h"
#include "frontend/applets/software_keyboard.h"
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
#include "video_core/renderer_base.h" #include "video_core/renderer_base.h"
@ -136,6 +138,10 @@ struct System::Impl {
if (virtual_filesystem == nullptr) if (virtual_filesystem == nullptr)
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>(); virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
/// Create default implementations of applets if one is not provided.
if (software_keyboard == nullptr)
software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
auto main_process = Kernel::Process::Create(kernel, "main"); auto main_process = Kernel::Process::Create(kernel, "main");
kernel.MakeCurrentProcess(main_process.get()); kernel.MakeCurrentProcess(main_process.get());
@ -289,6 +295,9 @@ struct System::Impl {
std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads; std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads;
std::size_t active_core{}; ///< Active core, only used in single thread mode std::size_t active_core{}; ///< Active core, only used in single thread mode
/// Frontend applets
std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
/// Service manager /// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager; std::shared_ptr<Service::SM::ServiceManager> service_manager;
@ -488,6 +497,14 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
return impl->virtual_filesystem; return impl->virtual_filesystem;
} }
void System::SetSoftwareKeyboard(std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> 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) { System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
return impl->Init(emu_window); return impl->Init(emu_window);
} }

View file

@ -13,6 +13,7 @@
namespace Core::Frontend { namespace Core::Frontend {
class EmuWindow; class EmuWindow;
class SoftwareKeyboardApplet;
} // namespace Core::Frontend } // namespace Core::Frontend
namespace FileSys { namespace FileSys {
@ -236,6 +237,10 @@ public:
std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const; std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
void SetSoftwareKeyboard(std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> applet);
const Core::Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const;
private: private:
System(); System();

View file

@ -3,16 +3,19 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include "common/logging/backend.h" #include "common/logging/backend.h"
#include "common/string_util.h"
#include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/software_keyboard.h"
namespace Frontend { namespace Core::Frontend {
bool DefaultSoftwareKeyboardApplet::GetText(Parameters parameters, std::u16string& text) { SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default;
bool DefaultSoftwareKeyboardApplet::GetText(SoftwareKeyboardParameters parameters,
std::u16string& text) const {
if (parameters.initial_text.empty()) if (parameters.initial_text.empty())
text = Common::UTF8ToUTF16("yuzu"); text = u"yuzu";
else else
text = parameters.initial_text; text = parameters.initial_text;
return true; return true;
} }
} // namespace Frontend
} // namespace Core::Frontend

View file

@ -8,10 +8,8 @@
#include "common/bit_field.h" #include "common/bit_field.h"
#include "common/common_types.h" #include "common/common_types.h"
namespace Frontend { namespace Core::Frontend {
class SoftwareKeyboardApplet { struct SoftwareKeyboardParameters {
public:
struct Parameters {
std::u16string submit_text; std::u16string submit_text;
std::u16string header_text; std::u16string header_text;
std::u16string sub_text; std::u16string sub_text;
@ -31,14 +29,18 @@ public:
BitField<6, 1, u8> disable_number; BitField<6, 1, u8> disable_number;
BitField<7, 1, u8> disable_download_code; BitField<7, 1, u8> disable_download_code;
}; };
}; };
virtual bool GetText(Parameters parameters, std::u16string& text) = 0; class SoftwareKeyboardApplet {
virtual ~SoftwareKeyboardApplet() = default; public:
virtual ~SoftwareKeyboardApplet();
virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0;
}; };
class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { 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

View file

@ -1207,14 +1207,15 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
return ERR_INVALID_ADDRESS; 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})", LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})",
addr, size); addr, size);
return ERR_INVALID_ADDRESS_STATE; return ERR_INVALID_ADDRESS_STATE;
} }
if (permissions > static_cast<u32>(MemoryPermission::ReadWrite) || const auto perms = static_cast<MemoryPermission>(permissions);
permissions == static_cast<u32>(MemoryPermission::Write)) { if (perms != MemoryPermission::None && perms != MemoryPermission::Read &&
perms != MemoryPermission::ReadWrite) {
LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
permissions); permissions);
return ERR_INVALID_MEMORY_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& kernel = Core::System::GetInstance().Kernel();
auto& handle_table = Core::CurrentProcess()->GetHandleTable(); auto& handle_table = Core::CurrentProcess()->GetHandleTable();
const auto perms = static_cast<MemoryPermission>(permissions);
const auto shared_mem_handle = SharedMemory::Create( const auto shared_mem_handle = SharedMemory::Create(
kernel, handle_table.Get<Process>(CurrentProcess), size, perms, perms, addr); kernel, handle_table.Get<Process>(CurrentProcess), size, perms, perms, addr);

View file

@ -501,6 +501,8 @@ IStorage::IStorage(std::vector<u8> buffer)
RegisterHandlers(functions); RegisterHandlers(functions);
} }
IStorage::~IStorage() = default;
const std::vector<u8>& IStorage::GetData() const { const std::vector<u8>& IStorage::GetData() const {
return buffer; return buffer;
} }
@ -670,6 +672,8 @@ IStorageAccessor::IStorageAccessor(IStorage& storage)
RegisterHandlers(functions); RegisterHandlers(functions);
} }
IStorageAccessor::~IStorageAccessor() = default;
void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) { void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
@ -685,7 +689,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
const u64 offset{rp.Pop<u64>()}; const u64 offset{rp.Pop<u64>()};
const std::vector<u8> data{ctx.ReadBuffer()}; const std::vector<u8> data{ctx.ReadBuffer()};
const auto size = std::min<std::size_t>(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); std::memcpy(&backing.buffer[offset], data.data(), size);
@ -701,7 +705,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
const u64 offset{rp.Pop<u64>()}; const u64 offset{rp.Pop<u64>()};
std::size_t size{ctx.GetWriteBufferSize()}; std::size_t size{ctx.GetWriteBufferSize()};
size = std::min<std::size_t>(size, backing.buffer.size() - offset); size = std::min(size, backing.buffer.size() - offset);
ctx.WriteBuffer(backing.buffer.data() + offset, size); ctx.WriteBuffer(backing.buffer.data() + offset, size);
@ -787,9 +791,9 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
return; return;
} }
std::vector<u8> memory(shared_mem->size); const auto mem_begin = shared_mem->backing_block->begin() + shared_mem->backing_block_offset;
std::memcpy(memory.data(), shared_mem->backing_block->data() + shared_mem->backing_block_offset, const auto mem_end = mem_begin + shared_mem->size;
memory.size()); std::vector<u8> memory{mem_begin, mem_end};
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);

View file

@ -158,27 +158,29 @@ private:
class IStorage final : public ServiceFramework<IStorage> { class IStorage final : public ServiceFramework<IStorage> {
public: public:
explicit IStorage(std::vector<u8> buffer); explicit IStorage(std::vector<u8> buffer);
~IStorage() override;
const std::vector<u8>& GetData() const; const std::vector<u8>& GetData() const;
private: private:
std::vector<u8> buffer;
void Open(Kernel::HLERequestContext& ctx); void Open(Kernel::HLERequestContext& ctx);
std::vector<u8> buffer;
friend class IStorageAccessor; friend class IStorageAccessor;
}; };
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
public: public:
explicit IStorageAccessor(IStorage& backing); explicit IStorageAccessor(IStorage& backing);
~IStorageAccessor() override;
private: private:
IStorage& backing;
void GetSize(Kernel::HLERequestContext& ctx); void GetSize(Kernel::HLERequestContext& ctx);
void Write(Kernel::HLERequestContext& ctx); void Write(Kernel::HLERequestContext& ctx);
void Read(Kernel::HLERequestContext& ctx); void Read(Kernel::HLERequestContext& ctx);
IStorage& backing;
}; };
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {

View file

@ -7,23 +7,13 @@
namespace Service::AM::Applets { namespace Service::AM::Applets {
std::shared_ptr<Frontend::SoftwareKeyboardApplet> software_keyboard = Applet::Applet() = default;
std::make_shared<Frontend::DefaultSoftwareKeyboardApplet>();
Applet::~Applet() = default;
void Applet::Initialize(std::vector<std::shared_ptr<IStorage>> storage) { void Applet::Initialize(std::vector<std::shared_ptr<IStorage>> storage) {
storage_stack = std::move(storage); storage_stack = std::move(storage);
initialized = true; initialized = true;
} }
void RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboardApplet> applet) {
if (applet == nullptr)
return;
software_keyboard = std::move(applet);
}
std::shared_ptr<Frontend::SoftwareKeyboardApplet> GetSoftwareKeyboard() {
return software_keyboard;
}
} // namespace Service::AM::Applets } // namespace Service::AM::Applets

View file

@ -20,10 +20,17 @@ namespace Applets {
class Applet { class Applet {
public: public:
Applet();
virtual ~Applet();
virtual void Initialize(std::vector<std::shared_ptr<IStorage>> storage); virtual void Initialize(std::vector<std::shared_ptr<IStorage>> storage);
virtual IStorage Execute() = 0; virtual IStorage Execute() = 0;
bool IsInitialized() const {
return initialized;
}
protected: protected:
struct CommonArguments { struct CommonArguments {
u32_le arguments_version; u32_le arguments_version;
@ -39,8 +46,5 @@ protected:
bool initialized = false; bool initialized = false;
}; };
void RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboardApplet> applet);
std::shared_ptr<Frontend::SoftwareKeyboardApplet> GetSoftwareKeyboard();
} // namespace Applets } // namespace Applets
} // namespace Service::AM } // namespace Service::AM

View file

@ -2,8 +2,10 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <cstring>
#include "common/assert.h" #include "common/assert.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h"
#include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/software_keyboard.h"
#include "core/hle/service/am/am.h" #include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/software_keyboard.h" #include "core/hle/service/am/applets/software_keyboard.h"
@ -11,11 +13,13 @@
namespace Service::AM::Applets { namespace Service::AM::Applets {
constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8; 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 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) { KeyboardConfig config, std::u16string initial_text) {
Frontend::SoftwareKeyboardApplet::Parameters params{}; Core::Frontend::SoftwareKeyboardParameters params{};
params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
config.submit_text.data(), config.submit_text.size()); config.submit_text.data(), config.submit_text.size());
@ -34,6 +38,10 @@ static Frontend::SoftwareKeyboardApplet::Parameters ConvertToFrontendParameters(
return params; return params;
} }
SoftwareKeyboard::SoftwareKeyboard() = default;
SoftwareKeyboard::~SoftwareKeyboard() = default;
void SoftwareKeyboard::Initialize(std::vector<std::shared_ptr<IStorage>> storage_) { void SoftwareKeyboard::Initialize(std::vector<std::shared_ptr<IStorage>> storage_) {
Applet::Initialize(std::move(storage_)); Applet::Initialize(std::move(storage_));

View file

@ -5,6 +5,7 @@
#pragma once #pragma once
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h" #include "core/hle/service/am/applets/applets.h"
namespace Service::AM::Applets { namespace Service::AM::Applets {
@ -45,13 +46,21 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz
class SoftwareKeyboard final : public Applet { class SoftwareKeyboard final : public Applet {
public: public:
SoftwareKeyboard();
~SoftwareKeyboard() override;
void Initialize(std::vector<std::shared_ptr<IStorage>> storage) override; void Initialize(std::vector<std::shared_ptr<IStorage>> storage) override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
void ReceiveInteractiveData(std::shared_ptr<IStorage> storage) override;
IStorage Execute() override; IStorage Execute() override;
private: private:
KeyboardConfig config; KeyboardConfig config;
std::u16string initial_text; std::u16string initial_text;
bool complete = false;
std::vector<u8> final_data;
}; };
} // namespace Service::AM::Applets } // namespace Service::AM::Applets

View file

@ -2,21 +2,20 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <locale> #include <algorithm>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QFont> #include <QFont>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "common/logging/backend.h"
#include "common/string_util.h"
#include "yuzu/applets/software_keyboard.h" #include "yuzu/applets/software_keyboard.h"
#include "yuzu/main.h"
QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
Frontend::SoftwareKeyboardApplet::Parameters parameters) Core::Frontend::SoftwareKeyboardParameters parameters)
: parameters(std::move(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) if (input.size() > parameters.max_length)
return Invalid; return Invalid;
if (parameters.disable_space && input.contains(' ')) 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('\\'))) if (parameters.disable_slash && (input.contains('/') || input.contains('\\')))
return Invalid; return Invalid;
if (parameters.disable_number && 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; return Invalid;
}
if (parameters.disable_download_code && 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 Invalid;
}
return Acceptable; return Acceptable;
} }
QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
QWidget* parent, Frontend::SoftwareKeyboardApplet::Parameters parameters_) QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_)
: QDialog(parent), parameters(std::move(parameters_)) { : QDialog(parent), parameters(std::move(parameters_)) {
layout = new QVBoxLayout; layout = new QVBoxLayout;
@ -79,9 +80,11 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
layout->addWidget(line_edit); layout->addWidget(line_edit);
layout->addWidget(buttons); layout->addWidget(buttons);
setLayout(layout); setLayout(layout);
setWindowTitle("Software Keyboard"); setWindowTitle(tr("Software Keyboard"));
} }
QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default;
void QtSoftwareKeyboardDialog::Submit() { void QtSoftwareKeyboardDialog::Submit() {
ok = true; ok = true;
text = line_edit->text().toStdU16String(); text = line_edit->text().toStdU16String();
@ -90,19 +93,33 @@ void QtSoftwareKeyboardDialog::Submit() {
void QtSoftwareKeyboardDialog::Reject() { void QtSoftwareKeyboardDialog::Reject() {
ok = false; ok = false;
text = Common::UTF8ToUTF16(""); text.clear();
accept(); accept();
} }
QtSoftwareKeyboard::QtSoftwareKeyboard(QWidget& parent) : parent(parent) {} std::u16string QtSoftwareKeyboardDialog::GetText() {
return text;
bool QtSoftwareKeyboard::GetText(Parameters parameters, std::u16string& text) { }
QtSoftwareKeyboardDialog dialog(&parent, parameters);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | bool QtSoftwareKeyboardDialog::GetStatus() {
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); return ok;
dialog.setWindowModality(Qt::WindowModal); }
dialog.exec();
QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& parent) : main_window(parent) {}
text = dialog.text;
return dialog.ok; 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;
}
void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message) const {
QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardInvokeCheckDialog",
Qt::BlockingQueuedConnection, Q_ARG(std::u16string, error_message));
} }

View file

@ -3,11 +3,13 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#pragma once #pragma once
#include <QDialog> #include <QDialog>
#include <QValidator> #include <QValidator>
#include "common/assert.h" #include "common/assert.h"
#include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/software_keyboard.h"
class GMainWindow;
class QDialogButtonBox; class QDialogButtonBox;
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
@ -16,11 +18,11 @@ class QtSoftwareKeyboard;
class QtSoftwareKeyboardValidator final : public QValidator { class QtSoftwareKeyboardValidator final : public QValidator {
public: public:
explicit QtSoftwareKeyboardValidator(Frontend::SoftwareKeyboardApplet::Parameters parameters); explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters);
State validate(QString&, int&) const override; State validate(QString& input, int& pos) const override;
private: private:
Frontend::SoftwareKeyboardApplet::Parameters parameters; Core::Frontend::SoftwareKeyboardParameters parameters;
}; };
class QtSoftwareKeyboardDialog final : public QDialog { class QtSoftwareKeyboardDialog final : public QDialog {
@ -28,10 +30,15 @@ class QtSoftwareKeyboardDialog final : public QDialog {
public: public:
QtSoftwareKeyboardDialog(QWidget* parent, QtSoftwareKeyboardDialog(QWidget* parent,
Frontend::SoftwareKeyboardApplet::Parameters parameters); Core::Frontend::SoftwareKeyboardParameters parameters);
~QtSoftwareKeyboardDialog() override;
void Submit(); void Submit();
void Reject(); void Reject();
std::u16string GetText();
bool GetStatus();
private: private:
bool ok = false; bool ok = false;
std::u16string text; std::u16string text;
@ -43,20 +50,18 @@ private:
QLineEdit* line_edit; QLineEdit* line_edit;
QVBoxLayout* layout; QVBoxLayout* layout;
Frontend::SoftwareKeyboardApplet::Parameters parameters; Core::Frontend::SoftwareKeyboardParameters parameters;
friend class QtSoftwareKeyboard;
}; };
class QtSoftwareKeyboard final : public QObject, public Frontend::SoftwareKeyboardApplet { class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet {
public: public:
explicit QtSoftwareKeyboard(QWidget& parent); explicit QtSoftwareKeyboard(GMainWindow& parent);
bool GetText(Parameters parameters, std::u16string& text) override; ~QtSoftwareKeyboard() override;
~QtSoftwareKeyboard() { bool GetText(Core::Frontend::SoftwareKeyboardParameters parameters,
UNREACHABLE(); std::u16string& text) const override;
} void SendTextCheckDialog(std::u16string error_message) const override;
private: private:
QWidget& parent; GMainWindow& main_window;
}; };

View file

@ -561,7 +561,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
system.SetGPUDebugContext(debug_context); system.SetGPUDebugContext(debug_context);
Service::AM::Applets::RegisterSoftwareKeyboard(std::make_shared<QtSoftwareKeyboard>(*this)); system.SetSoftwareKeyboard(std::make_unique<QtSoftwareKeyboard>(*this));
const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())};
@ -1232,8 +1232,13 @@ void GMainWindow::OnMenuRecentFile() {
void GMainWindow::OnStartGame() { void GMainWindow::OnStartGame() {
emu_thread->SetRunning(true); emu_thread->SetRunning(true);
qRegisterMetaType<Core::Frontend::SoftwareKeyboardParameters>(
"core::Frontend::SoftwareKeyboardParameters");
qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
qRegisterMetaType<std::string>("std::string"); qRegisterMetaType<std::string>("std::string");
qRegisterMetaType<std::u16string>("std::u16string");
connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
ui.action_Start->setEnabled(false); ui.action_Start->setEnabled(false);

View file

@ -29,6 +29,10 @@ class ProfilerWidget;
class WaitTreeWidget; class WaitTreeWidget;
enum class GameListOpenTarget; enum class GameListOpenTarget;
namespace Core::Frontend {
struct SoftwareKeyboardParameters;
} // namespace Core::Frontend
namespace FileSys { namespace FileSys {
class RegisteredCacheUnion; class RegisteredCacheUnion;
class VfsFilesystem; class VfsFilesystem;
@ -95,6 +99,11 @@ signals:
// Signal that tells widgets to update icons to use the current theme // Signal that tells widgets to update icons to use the current theme
void UpdateThemedIcons(); void UpdateThemedIcons();
public slots:
bool SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters,
std::u16string& text);
void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
private: private:
void InitializeWidgets(); void InitializeWidgets();
void InitializeDebugWidgets(); void InitializeDebugWidgets();