am: Deglobalize software keyboard applet
This commit is contained in:
parent
a81645400f
commit
e696ed1f4d
17 changed files with 182 additions and 102 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -8,37 +8,39 @@
|
||||||
#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 {
|
||||||
|
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 {
|
class SoftwareKeyboardApplet {
|
||||||
public:
|
public:
|
||||||
struct Parameters {
|
virtual ~SoftwareKeyboardApplet();
|
||||||
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 {
|
virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0;
|
||||||
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 {
|
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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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_));
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue