am: Deglobalize software keyboard applet
This commit is contained in:
		
							parent
							
								
									a81645400f
								
							
						
					
					
						commit
						e696ed1f4d
					
				@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
@ -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<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");
 | 
			
		||||
        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::size_t active_core{}; ///< Active core, only used in single thread mode
 | 
			
		||||
 | 
			
		||||
    /// Frontend applets
 | 
			
		||||
    std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
 | 
			
		||||
 | 
			
		||||
    /// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    return impl->Init(emu_window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@
 | 
			
		||||
 | 
			
		||||
namespace Core::Frontend {
 | 
			
		||||
class EmuWindow;
 | 
			
		||||
class SoftwareKeyboardApplet;
 | 
			
		||||
} // namespace Core::Frontend
 | 
			
		||||
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
@ -236,6 +237,10 @@ public:
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
 | 
			
		||||
 | 
			
		||||
    void SetSoftwareKeyboard(std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> applet);
 | 
			
		||||
 | 
			
		||||
    const Core::Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    System();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    virtual ~SoftwareKeyboardApplet();
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -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<u32>(MemoryPermission::ReadWrite) ||
 | 
			
		||||
        permissions == static_cast<u32>(MemoryPermission::Write)) {
 | 
			
		||||
    const auto perms = static_cast<MemoryPermission>(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<MemoryPermission>(permissions);
 | 
			
		||||
    const auto shared_mem_handle = SharedMemory::Create(
 | 
			
		||||
        kernel, handle_table.Get<Process>(CurrentProcess), size, perms, perms, addr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -501,6 +501,8 @@ IStorage::IStorage(std::vector<u8> buffer)
 | 
			
		||||
    RegisterHandlers(functions);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IStorage::~IStorage() = default;
 | 
			
		||||
 | 
			
		||||
const std::vector<u8>& 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<u64>()};
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
@ -701,7 +705,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    const u64 offset{rp.Pop<u64>()};
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
@ -787,9 +791,9 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> 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<u8> memory{mem_begin, mem_end};
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2, 0, 1};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
 | 
			
		||||
@ -158,27 +158,29 @@ private:
 | 
			
		||||
class IStorage final : public ServiceFramework<IStorage> {
 | 
			
		||||
public:
 | 
			
		||||
    explicit IStorage(std::vector<u8> buffer);
 | 
			
		||||
    ~IStorage() override;
 | 
			
		||||
 | 
			
		||||
    const std::vector<u8>& GetData() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<u8> buffer;
 | 
			
		||||
 | 
			
		||||
    void Open(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> buffer;
 | 
			
		||||
 | 
			
		||||
    friend class IStorageAccessor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
 | 
			
		||||
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<ILibraryAppletCreator> {
 | 
			
		||||
 | 
			
		||||
@ -7,23 +7,13 @@
 | 
			
		||||
 | 
			
		||||
namespace Service::AM::Applets {
 | 
			
		||||
 | 
			
		||||
std::shared_ptr<Frontend::SoftwareKeyboardApplet> software_keyboard =
 | 
			
		||||
    std::make_shared<Frontend::DefaultSoftwareKeyboardApplet>();
 | 
			
		||||
Applet::Applet() = default;
 | 
			
		||||
 | 
			
		||||
Applet::~Applet() = default;
 | 
			
		||||
 | 
			
		||||
void Applet::Initialize(std::vector<std::shared_ptr<IStorage>> storage) {
 | 
			
		||||
    storage_stack = std::move(storage);
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -20,10 +20,17 @@ namespace Applets {
 | 
			
		||||
 | 
			
		||||
class Applet {
 | 
			
		||||
public:
 | 
			
		||||
    Applet();
 | 
			
		||||
    virtual ~Applet();
 | 
			
		||||
 | 
			
		||||
    virtual void Initialize(std::vector<std::shared_ptr<IStorage>> 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<Frontend::SoftwareKeyboardApplet> applet);
 | 
			
		||||
std::shared_ptr<Frontend::SoftwareKeyboardApplet> GetSoftwareKeyboard();
 | 
			
		||||
 | 
			
		||||
} // namespace Applets
 | 
			
		||||
} // namespace Service::AM
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,10 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#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<std::shared_ptr<IStorage>> storage_) {
 | 
			
		||||
    Applet::Initialize(std::move(storage_));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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<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;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    KeyboardConfig config;
 | 
			
		||||
    std::u16string initial_text;
 | 
			
		||||
    bool complete = false;
 | 
			
		||||
    std::vector<u8> final_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::AM::Applets
 | 
			
		||||
 | 
			
		||||
@ -2,21 +2,20 @@
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <locale>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <QDialogButtonBox>
 | 
			
		||||
#include <QFont>
 | 
			
		||||
#include <QLabel>
 | 
			
		||||
#include <QLineEdit>
 | 
			
		||||
#include <QVBoxLayout>
 | 
			
		||||
#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) {}
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
 | 
			
		||||
    text = dialog.text;
 | 
			
		||||
    return dialog.ok;
 | 
			
		||||
std::u16string QtSoftwareKeyboardDialog::GetText() {
 | 
			
		||||
    return text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QtSoftwareKeyboardDialog::GetStatus() {
 | 
			
		||||
    return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include <QValidator>
 | 
			
		||||
#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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -561,7 +561,7 @@ bool GMainWindow::LoadROM(const QString& filename) {
 | 
			
		||||
 | 
			
		||||
    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())};
 | 
			
		||||
 | 
			
		||||
@ -1232,8 +1232,13 @@ void GMainWindow::OnMenuRecentFile() {
 | 
			
		||||
 | 
			
		||||
void GMainWindow::OnStartGame() {
 | 
			
		||||
    emu_thread->SetRunning(true);
 | 
			
		||||
 | 
			
		||||
    qRegisterMetaType<Core::Frontend::SoftwareKeyboardParameters>(
 | 
			
		||||
        "core::Frontend::SoftwareKeyboardParameters");
 | 
			
		||||
    qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus");
 | 
			
		||||
    qRegisterMetaType<std::string>("std::string");
 | 
			
		||||
    qRegisterMetaType<std::u16string>("std::u16string");
 | 
			
		||||
 | 
			
		||||
    connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
 | 
			
		||||
 | 
			
		||||
    ui.action_Start->setEnabled(false);
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user