diff options
| author | 2021-01-30 14:38:00 -0500 | |
|---|---|---|
| committer | 2021-04-15 01:53:16 -0400 | |
| commit | 0f40c8c6340aa858cd2e2ffe2e6c54885e0a3649 (patch) | |
| tree | 64577d64b355f354ab35e058b077f17be358f303 /src | |
| parent | Merge pull request #6199 from lioncash/log-ns (diff) | |
| download | yuzu-0f40c8c6340aa858cd2e2ffe2e6c54885e0a3649.tar.gz yuzu-0f40c8c6340aa858cd2e2ffe2e6c54885e0a3649.tar.xz yuzu-0f40c8c6340aa858cd2e2ffe2e6c54885e0a3649.zip | |
applets: Remove the previous software keyboard applet implementation
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/frontend/applets/software_keyboard.cpp | 20 | ||||
| -rw-r--r-- | src/core/frontend/applets/software_keyboard.h | 34 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/software_keyboard.cpp | 182 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/software_keyboard.h | 51 | ||||
| -rw-r--r-- | src/yuzu/applets/software_keyboard.cpp | 143 | ||||
| -rw-r--r-- | src/yuzu/applets/software_keyboard.h | 48 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 23 | ||||
| -rw-r--r-- | src/yuzu/main.h | 5 |
8 files changed, 14 insertions, 492 deletions
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 856ed33da..73e7a89b9 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp | |||
| @@ -2,28 +2,10 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/backend.h" | ||
| 6 | #include "common/string_util.h" | ||
| 7 | #include "core/frontend/applets/software_keyboard.h" | 5 | #include "core/frontend/applets/software_keyboard.h" |
| 8 | 6 | ||
| 9 | namespace Core::Frontend { | 7 | namespace Core::Frontend { |
| 10 | SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; | ||
| 11 | |||
| 12 | void DefaultSoftwareKeyboardApplet::RequestText( | ||
| 13 | std::function<void(std::optional<std::u16string>)> out, | ||
| 14 | SoftwareKeyboardParameters parameters) const { | ||
| 15 | if (parameters.initial_text.empty()) | ||
| 16 | out(u"yuzu"); | ||
| 17 | 8 | ||
| 18 | out(parameters.initial_text); | 9 | SoftwareKeyboardApplet::~SoftwareKeyboardApplet() = default; |
| 19 | } | ||
| 20 | 10 | ||
| 21 | void DefaultSoftwareKeyboardApplet::SendTextCheckDialog( | ||
| 22 | std::u16string error_message, std::function<void()> finished_check) const { | ||
| 23 | LOG_WARNING(Service_AM, | ||
| 24 | "(STUBBED) called - Default fallback software keyboard does not support text " | ||
| 25 | "check! (error_message={})", | ||
| 26 | Common::UTF16ToUTF8(error_message)); | ||
| 27 | finished_check(); | ||
| 28 | } | ||
| 29 | } // namespace Core::Frontend | 11 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index f9b202664..54528837e 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h | |||
| @@ -4,51 +4,17 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <functional> | ||
| 8 | #include <optional> | ||
| 9 | #include <string> | ||
| 10 | #include "common/bit_field.h" | ||
| 11 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 12 | 8 | ||
| 13 | namespace Core::Frontend { | 9 | namespace Core::Frontend { |
| 14 | struct SoftwareKeyboardParameters { | ||
| 15 | std::u16string submit_text; | ||
| 16 | std::u16string header_text; | ||
| 17 | std::u16string sub_text; | ||
| 18 | std::u16string guide_text; | ||
| 19 | std::u16string initial_text; | ||
| 20 | std::size_t max_length; | ||
| 21 | bool password; | ||
| 22 | bool cursor_at_beginning; | ||
| 23 | |||
| 24 | union { | ||
| 25 | u8 value; | ||
| 26 | |||
| 27 | BitField<1, 1, u8> disable_space; | ||
| 28 | BitField<2, 1, u8> disable_address; | ||
| 29 | BitField<3, 1, u8> disable_percent; | ||
| 30 | BitField<4, 1, u8> disable_slash; | ||
| 31 | BitField<6, 1, u8> disable_number; | ||
| 32 | BitField<7, 1, u8> disable_download_code; | ||
| 33 | }; | ||
| 34 | }; | ||
| 35 | 10 | ||
| 36 | class SoftwareKeyboardApplet { | 11 | class SoftwareKeyboardApplet { |
| 37 | public: | 12 | public: |
| 38 | virtual ~SoftwareKeyboardApplet(); | 13 | virtual ~SoftwareKeyboardApplet(); |
| 39 | |||
| 40 | virtual void RequestText(std::function<void(std::optional<std::u16string>)> out, | ||
| 41 | SoftwareKeyboardParameters parameters) const = 0; | ||
| 42 | virtual void SendTextCheckDialog(std::u16string error_message, | ||
| 43 | std::function<void()> finished_check) const = 0; | ||
| 44 | }; | 14 | }; |
| 45 | 15 | ||
| 46 | class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { | 16 | class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { |
| 47 | public: | 17 | public: |
| 48 | void RequestText(std::function<void(std::optional<std::u16string>)> out, | ||
| 49 | SoftwareKeyboardParameters parameters) const override; | ||
| 50 | void SendTextCheckDialog(std::u16string error_message, | ||
| 51 | std::function<void()> finished_check) const override; | ||
| 52 | }; | 18 | }; |
| 53 | 19 | ||
| 54 | } // namespace Core::Frontend | 20 | } // namespace Core::Frontend |
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 79b209c6b..f966cf67b 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp | |||
| @@ -2,199 +2,27 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/string_util.h" | ||
| 8 | #include "core/core.h" | 5 | #include "core/core.h" |
| 9 | #include "core/frontend/applets/software_keyboard.h" | 6 | #include "core/frontend/applets/software_keyboard.h" |
| 10 | #include "core/hle/result.h" | ||
| 11 | #include "core/hle/service/am/am.h" | 7 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applets/software_keyboard.h" | 8 | #include "core/hle/service/am/applets/software_keyboard.h" |
| 13 | 9 | ||
| 14 | namespace Service::AM::Applets { | 10 | namespace Service::AM::Applets { |
| 15 | 11 | ||
| 16 | namespace { | ||
| 17 | enum class Request : u32 { | ||
| 18 | Finalize = 0x4, | ||
| 19 | SetUserWordInfo = 0x6, | ||
| 20 | SetCustomizeDic = 0x7, | ||
| 21 | Calc = 0xa, | ||
| 22 | SetCustomizedDictionaries = 0xb, | ||
| 23 | UnsetCustomizedDictionaries = 0xc, | ||
| 24 | UnknownD = 0xd, | ||
| 25 | UnknownE = 0xe, | ||
| 26 | }; | ||
| 27 | constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8; | ||
| 28 | constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8; | ||
| 29 | constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4; | ||
| 30 | constexpr std::size_t DEFAULT_MAX_LENGTH = 500; | ||
| 31 | constexpr bool INTERACTIVE_STATUS_OK = false; | ||
| 32 | } // Anonymous namespace | ||
| 33 | static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( | ||
| 34 | KeyboardConfig config, std::u16string initial_text) { | ||
| 35 | Core::Frontend::SoftwareKeyboardParameters params{}; | ||
| 36 | |||
| 37 | params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 38 | config.submit_text.data(), config.submit_text.size()); | ||
| 39 | params.header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer( | ||
| 40 | config.header_text.data(), config.header_text.size()); | ||
| 41 | params.sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.sub_text.data(), | ||
| 42 | config.sub_text.size()); | ||
| 43 | params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(), | ||
| 44 | config.guide_text.size()); | ||
| 45 | params.initial_text = std::move(initial_text); | ||
| 46 | params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit; | ||
| 47 | params.password = static_cast<bool>(config.is_password); | ||
| 48 | params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position); | ||
| 49 | params.value = static_cast<u8>(config.keyset_disable_bitmask); | ||
| 50 | |||
| 51 | return params; | ||
| 52 | } | ||
| 53 | |||
| 54 | SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, | 12 | SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, |
| 55 | const Core::Frontend::SoftwareKeyboardApplet& frontend_) | 13 | const Core::Frontend::SoftwareKeyboardApplet& frontend_) |
| 56 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} | 14 | : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} |
| 57 | 15 | ||
| 58 | SoftwareKeyboard::~SoftwareKeyboard() = default; | 16 | SoftwareKeyboard::~SoftwareKeyboard() = default; |
| 59 | 17 | ||
| 60 | void SoftwareKeyboard::Initialize() { | 18 | void SoftwareKeyboard::Initialize() {} |
| 61 | complete = false; | ||
| 62 | is_inline = false; | ||
| 63 | initial_text.clear(); | ||
| 64 | final_data.clear(); | ||
| 65 | |||
| 66 | Applet::Initialize(); | ||
| 67 | |||
| 68 | const auto keyboard_config_storage = broker.PopNormalDataToApplet(); | ||
| 69 | ASSERT(keyboard_config_storage != nullptr); | ||
| 70 | const auto& keyboard_config = keyboard_config_storage->GetData(); | ||
| 71 | |||
| 72 | if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) { | ||
| 73 | is_inline = true; | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | |||
| 77 | ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); | ||
| 78 | std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); | ||
| 79 | |||
| 80 | const auto work_buffer_storage = broker.PopNormalDataToApplet(); | ||
| 81 | ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; }); | ||
| 82 | const auto& work_buffer = work_buffer_storage->GetData(); | ||
| 83 | |||
| 84 | if (config.initial_string_size == 0) | ||
| 85 | return; | ||
| 86 | |||
| 87 | std::vector<char16_t> string(config.initial_string_size); | ||
| 88 | std::memcpy(string.data(), work_buffer.data() + config.initial_string_offset, | ||
| 89 | string.size() * 2); | ||
| 90 | initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()); | ||
| 91 | } | ||
| 92 | |||
| 93 | bool SoftwareKeyboard::TransactionComplete() const { | ||
| 94 | return complete; | ||
| 95 | } | ||
| 96 | |||
| 97 | ResultCode SoftwareKeyboard::GetStatus() const { | ||
| 98 | return RESULT_SUCCESS; | ||
| 99 | } | ||
| 100 | |||
| 101 | void SoftwareKeyboard::ExecuteInteractive() { | ||
| 102 | if (complete) | ||
| 103 | return; | ||
| 104 | |||
| 105 | const auto storage = broker.PopInteractiveDataToApplet(); | ||
| 106 | ASSERT(storage != nullptr); | ||
| 107 | const auto data = storage->GetData(); | ||
| 108 | if (!is_inline) { | ||
| 109 | const auto status = static_cast<bool>(data[0]); | ||
| 110 | if (status == INTERACTIVE_STATUS_OK) { | ||
| 111 | complete = true; | ||
| 112 | } else { | ||
| 113 | std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string; | ||
| 114 | std::memcpy(string.data(), data.data() + 4, string.size() * 2); | ||
| 115 | frontend.SendTextCheckDialog( | ||
| 116 | Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()), | ||
| 117 | [this] { broker.SignalStateChanged(); }); | ||
| 118 | } | ||
| 119 | } else { | ||
| 120 | Request request{}; | ||
| 121 | std::memcpy(&request, data.data(), sizeof(Request)); | ||
| 122 | |||
| 123 | switch (request) { | ||
| 124 | case Request::Finalize: | ||
| 125 | complete = true; | ||
| 126 | broker.SignalStateChanged(); | ||
| 127 | break; | ||
| 128 | case Request::Calc: { | ||
| 129 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1})); | ||
| 130 | broker.SignalStateChanged(); | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | default: | ||
| 134 | UNIMPLEMENTED_MSG("Request {:X} is not implemented", request); | ||
| 135 | break; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | void SoftwareKeyboard::Execute() { | ||
| 141 | if (complete) { | ||
| 142 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); | ||
| 143 | broker.SignalStateChanged(); | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | |||
| 147 | const auto parameters = ConvertToFrontendParameters(config, initial_text); | ||
| 148 | if (!is_inline) { | ||
| 149 | frontend.RequestText( | ||
| 150 | [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { | ||
| 155 | std::vector<u8> output_main(SWKBD_OUTPUT_BUFFER_SIZE); | ||
| 156 | |||
| 157 | if (text.has_value()) { | ||
| 158 | std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE); | ||
| 159 | |||
| 160 | if (config.utf_8) { | ||
| 161 | const u64 size = text->size() + sizeof(u64); | ||
| 162 | const auto new_text = Common::UTF16ToUTF8(*text); | ||
| 163 | 19 | ||
| 164 | std::memcpy(output_sub.data(), &size, sizeof(u64)); | 20 | bool SoftwareKeyboard::TransactionComplete() const {} |
| 165 | std::memcpy(output_sub.data() + 8, new_text.data(), | ||
| 166 | std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 8)); | ||
| 167 | 21 | ||
| 168 | output_main[0] = INTERACTIVE_STATUS_OK; | 22 | ResultCode SoftwareKeyboard::GetStatus() const {} |
| 169 | std::memcpy(output_main.data() + 4, new_text.data(), | ||
| 170 | std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4)); | ||
| 171 | } else { | ||
| 172 | const u64 size = text->size() * 2 + sizeof(u64); | ||
| 173 | std::memcpy(output_sub.data(), &size, sizeof(u64)); | ||
| 174 | std::memcpy(output_sub.data() + 8, text->data(), | ||
| 175 | std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8)); | ||
| 176 | 23 | ||
| 177 | output_main[0] = INTERACTIVE_STATUS_OK; | 24 | void SoftwareKeyboard::ExecuteInteractive() {} |
| 178 | std::memcpy(output_main.data() + 4, text->data(), | ||
| 179 | std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); | ||
| 180 | } | ||
| 181 | 25 | ||
| 182 | complete = !config.text_check; | 26 | void SoftwareKeyboard::Execute() {} |
| 183 | final_data = output_main; | ||
| 184 | 27 | ||
| 185 | if (complete) { | ||
| 186 | broker.PushNormalDataFromApplet( | ||
| 187 | std::make_shared<IStorage>(system, std::move(output_main))); | ||
| 188 | broker.SignalStateChanged(); | ||
| 189 | } else { | ||
| 190 | broker.PushInteractiveDataFromApplet( | ||
| 191 | std::make_shared<IStorage>(system, std::move(output_sub))); | ||
| 192 | } | ||
| 193 | } else { | ||
| 194 | output_main[0] = 1; | ||
| 195 | complete = true; | ||
| 196 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main))); | ||
| 197 | broker.SignalStateChanged(); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | } // namespace Service::AM::Applets | 28 | } // namespace Service::AM::Applets |
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 1d260fef8..c161ec9ac 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h | |||
| @@ -4,59 +4,17 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | #include <string> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "common/common_funcs.h" | 7 | #include "common/common_funcs.h" |
| 12 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 13 | #include "common/swap.h" | 9 | #include "core/hle/result.h" |
| 14 | #include "core/hle/service/am/am.h" | ||
| 15 | #include "core/hle/service/am/applets/applets.h" | 10 | #include "core/hle/service/am/applets/applets.h" |
| 16 | 11 | ||
| 17 | union ResultCode; | ||
| 18 | |||
| 19 | namespace Core { | 12 | namespace Core { |
| 20 | class System; | 13 | class System; |
| 21 | } | 14 | } |
| 22 | 15 | ||
| 23 | namespace Service::AM::Applets { | 16 | namespace Service::AM::Applets { |
| 24 | 17 | ||
| 25 | enum class KeysetDisable : u32 { | ||
| 26 | Space = 0x02, | ||
| 27 | Address = 0x04, | ||
| 28 | Percent = 0x08, | ||
| 29 | Slashes = 0x10, | ||
| 30 | Numbers = 0x40, | ||
| 31 | DownloadCode = 0x80, | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct KeyboardConfig { | ||
| 35 | INSERT_PADDING_BYTES(4); | ||
| 36 | std::array<char16_t, 9> submit_text; | ||
| 37 | u16_le left_symbol_key; | ||
| 38 | u16_le right_symbol_key; | ||
| 39 | INSERT_PADDING_BYTES(1); | ||
| 40 | KeysetDisable keyset_disable_bitmask; | ||
| 41 | u32_le initial_cursor_position; | ||
| 42 | std::array<char16_t, 65> header_text; | ||
| 43 | std::array<char16_t, 129> sub_text; | ||
| 44 | std::array<char16_t, 257> guide_text; | ||
| 45 | u32_le length_limit; | ||
| 46 | INSERT_PADDING_BYTES(4); | ||
| 47 | u32_le is_password; | ||
| 48 | INSERT_PADDING_BYTES(5); | ||
| 49 | bool utf_8; | ||
| 50 | bool draw_background; | ||
| 51 | u32_le initial_string_offset; | ||
| 52 | u32_le initial_string_size; | ||
| 53 | u32_le user_dictionary_offset; | ||
| 54 | u32_le user_dictionary_size; | ||
| 55 | bool text_check; | ||
| 56 | u64_le text_check_callback; | ||
| 57 | }; | ||
| 58 | static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect size."); | ||
| 59 | |||
| 60 | class SoftwareKeyboard final : public Applet { | 18 | class SoftwareKeyboard final : public Applet { |
| 61 | public: | 19 | public: |
| 62 | explicit SoftwareKeyboard(Core::System& system_, | 20 | explicit SoftwareKeyboard(Core::System& system_, |
| @@ -70,16 +28,9 @@ public: | |||
| 70 | void ExecuteInteractive() override; | 28 | void ExecuteInteractive() override; |
| 71 | void Execute() override; | 29 | void Execute() override; |
| 72 | 30 | ||
| 73 | void WriteText(std::optional<std::u16string> text); | ||
| 74 | |||
| 75 | private: | 31 | private: |
| 76 | const Core::Frontend::SoftwareKeyboardApplet& frontend; | 32 | const Core::Frontend::SoftwareKeyboardApplet& frontend; |
| 77 | 33 | ||
| 78 | KeyboardConfig config; | ||
| 79 | std::u16string initial_text; | ||
| 80 | bool complete = false; | ||
| 81 | bool is_inline = false; | ||
| 82 | std::vector<u8> final_data; | ||
| 83 | Core::System& system; | 34 | Core::System& system; |
| 84 | }; | 35 | }; |
| 85 | 36 | ||
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index ab8cfd8ee..da0fed774 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp | |||
| @@ -2,152 +2,17 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 6 | #include <mutex> | ||
| 7 | #include <QDialogButtonBox> | ||
| 8 | #include <QFont> | ||
| 9 | #include <QLabel> | ||
| 10 | #include <QLineEdit> | ||
| 11 | #include <QVBoxLayout> | ||
| 12 | #include "core/hle/lock.h" | ||
| 13 | #include "yuzu/applets/software_keyboard.h" | 5 | #include "yuzu/applets/software_keyboard.h" |
| 14 | #include "yuzu/main.h" | 6 | #include "yuzu/main.h" |
| 15 | 7 | ||
| 16 | QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( | 8 | QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator() {} |
| 17 | Core::Frontend::SoftwareKeyboardParameters parameters) | ||
| 18 | : parameters(std::move(parameters)) {} | ||
| 19 | 9 | ||
| 20 | QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { | 10 | QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {} |
| 21 | if (input.size() > static_cast<s64>(parameters.max_length)) { | ||
| 22 | return Invalid; | ||
| 23 | } | ||
| 24 | if (parameters.disable_space && input.contains(QLatin1Char{' '})) { | ||
| 25 | return Invalid; | ||
| 26 | } | ||
| 27 | if (parameters.disable_address && input.contains(QLatin1Char{'@'})) { | ||
| 28 | return Invalid; | ||
| 29 | } | ||
| 30 | if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) { | ||
| 31 | return Invalid; | ||
| 32 | } | ||
| 33 | if (parameters.disable_slash && | ||
| 34 | (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) { | ||
| 35 | return Invalid; | ||
| 36 | } | ||
| 37 | if (parameters.disable_number && | ||
| 38 | std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { | ||
| 39 | return Invalid; | ||
| 40 | } | ||
| 41 | 11 | ||
| 42 | if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) { | 12 | QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(QWidget* parent) : QDialog(parent) {} |
| 43 | return c == QLatin1Char{'O'} || c == QLatin1Char{'I'}; | ||
| 44 | })) { | ||
| 45 | return Invalid; | ||
| 46 | } | ||
| 47 | |||
| 48 | return Acceptable; | ||
| 49 | } | ||
| 50 | |||
| 51 | QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( | ||
| 52 | QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_) | ||
| 53 | : QDialog(parent), parameters(std::move(parameters_)) { | ||
| 54 | layout = new QVBoxLayout; | ||
| 55 | |||
| 56 | header_label = new QLabel(QString::fromStdU16String(parameters.header_text)); | ||
| 57 | header_label->setFont({header_label->font().family(), 11, QFont::Bold}); | ||
| 58 | if (header_label->text().isEmpty()) | ||
| 59 | header_label->setText(tr("Enter text:")); | ||
| 60 | |||
| 61 | sub_label = new QLabel(QString::fromStdU16String(parameters.sub_text)); | ||
| 62 | sub_label->setFont({sub_label->font().family(), sub_label->font().pointSize(), | ||
| 63 | sub_label->font().weight(), true}); | ||
| 64 | sub_label->setHidden(parameters.sub_text.empty()); | ||
| 65 | |||
| 66 | guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text)); | ||
| 67 | guide_label->setHidden(parameters.guide_text.empty()); | ||
| 68 | |||
| 69 | length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length)); | ||
| 70 | length_label->setAlignment(Qt::AlignRight); | ||
| 71 | length_label->setFont({length_label->font().family(), 8}); | ||
| 72 | |||
| 73 | line_edit = new QLineEdit; | ||
| 74 | line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters)); | ||
| 75 | line_edit->setMaxLength(static_cast<int>(parameters.max_length)); | ||
| 76 | line_edit->setText(QString::fromStdU16String(parameters.initial_text)); | ||
| 77 | line_edit->setCursorPosition( | ||
| 78 | parameters.cursor_at_beginning ? 0 : static_cast<int>(parameters.initial_text.size())); | ||
| 79 | line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal); | ||
| 80 | |||
| 81 | connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) { | ||
| 82 | length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); | ||
| 83 | }); | ||
| 84 | |||
| 85 | buttons = new QDialogButtonBox(QDialogButtonBox::Cancel); | ||
| 86 | if (parameters.submit_text.empty()) { | ||
| 87 | buttons->addButton(QDialogButtonBox::Ok); | ||
| 88 | } else { | ||
| 89 | buttons->addButton(QString::fromStdU16String(parameters.submit_text), | ||
| 90 | QDialogButtonBox::AcceptRole); | ||
| 91 | } | ||
| 92 | connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept); | ||
| 93 | connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject); | ||
| 94 | layout->addWidget(header_label); | ||
| 95 | layout->addWidget(sub_label); | ||
| 96 | layout->addWidget(guide_label); | ||
| 97 | layout->addWidget(length_label); | ||
| 98 | layout->addWidget(line_edit); | ||
| 99 | layout->addWidget(buttons); | ||
| 100 | setLayout(layout); | ||
| 101 | setWindowTitle(tr("Software Keyboard")); | ||
| 102 | } | ||
| 103 | 13 | ||
| 104 | QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; | 14 | QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; |
| 105 | 15 | ||
| 106 | void QtSoftwareKeyboardDialog::accept() { | 16 | QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) {} |
| 107 | text = line_edit->text().toStdU16String(); | ||
| 108 | QDialog::accept(); | ||
| 109 | } | ||
| 110 | |||
| 111 | void QtSoftwareKeyboardDialog::reject() { | ||
| 112 | text.clear(); | ||
| 113 | QDialog::reject(); | ||
| 114 | } | ||
| 115 | |||
| 116 | std::u16string QtSoftwareKeyboardDialog::GetText() const { | ||
| 117 | return text; | ||
| 118 | } | ||
| 119 | |||
| 120 | QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { | ||
| 121 | connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window, | ||
| 122 | &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection); | ||
| 123 | connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window, | ||
| 124 | &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection); | ||
| 125 | connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this, | ||
| 126 | &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection); | ||
| 127 | } | ||
| 128 | 17 | ||
| 129 | QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; | 18 | QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; |
| 130 | |||
| 131 | void QtSoftwareKeyboard::RequestText(std::function<void(std::optional<std::u16string>)> out, | ||
| 132 | Core::Frontend::SoftwareKeyboardParameters parameters) const { | ||
| 133 | text_output = std::move(out); | ||
| 134 | emit MainWindowGetText(parameters); | ||
| 135 | } | ||
| 136 | |||
| 137 | void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message, | ||
| 138 | std::function<void()> finished_check_) const { | ||
| 139 | finished_check = std::move(finished_check_); | ||
| 140 | emit MainWindowTextCheckDialog(error_message); | ||
| 141 | } | ||
| 142 | |||
| 143 | void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) { | ||
| 144 | // Acquire the HLE mutex | ||
| 145 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 146 | text_output(std::move(text)); | ||
| 147 | } | ||
| 148 | |||
| 149 | void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { | ||
| 150 | // Acquire the HLE mutex | ||
| 151 | std::lock_guard lock{HLE::g_hle_lock}; | ||
| 152 | finished_check(); | ||
| 153 | } | ||
diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 9e1094cce..8427c0a6c 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h | |||
| @@ -6,49 +6,23 @@ | |||
| 6 | 6 | ||
| 7 | #include <QDialog> | 7 | #include <QDialog> |
| 8 | #include <QValidator> | 8 | #include <QValidator> |
| 9 | |||
| 9 | #include "core/frontend/applets/software_keyboard.h" | 10 | #include "core/frontend/applets/software_keyboard.h" |
| 10 | 11 | ||
| 11 | class GMainWindow; | 12 | class GMainWindow; |
| 12 | class QDialogButtonBox; | ||
| 13 | class QLabel; | ||
| 14 | class QLineEdit; | ||
| 15 | class QVBoxLayout; | ||
| 16 | class QtSoftwareKeyboard; | ||
| 17 | 13 | ||
| 18 | class QtSoftwareKeyboardValidator final : public QValidator { | 14 | class QtSoftwareKeyboardValidator final : public QValidator { |
| 19 | public: | 15 | public: |
| 20 | explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters); | 16 | explicit QtSoftwareKeyboardValidator(); |
| 21 | State validate(QString& input, int& pos) const override; | 17 | State validate(QString& input, int& pos) const override; |
| 22 | |||
| 23 | private: | ||
| 24 | Core::Frontend::SoftwareKeyboardParameters parameters; | ||
| 25 | }; | 18 | }; |
| 26 | 19 | ||
| 27 | class QtSoftwareKeyboardDialog final : public QDialog { | 20 | class QtSoftwareKeyboardDialog final : public QDialog { |
| 28 | Q_OBJECT | 21 | Q_OBJECT |
| 29 | 22 | ||
| 30 | public: | 23 | public: |
| 31 | QtSoftwareKeyboardDialog(QWidget* parent, | 24 | QtSoftwareKeyboardDialog(QWidget* parent); |
| 32 | Core::Frontend::SoftwareKeyboardParameters parameters); | ||
| 33 | ~QtSoftwareKeyboardDialog() override; | 25 | ~QtSoftwareKeyboardDialog() override; |
| 34 | |||
| 35 | void accept() override; | ||
| 36 | void reject() override; | ||
| 37 | |||
| 38 | std::u16string GetText() const; | ||
| 39 | |||
| 40 | private: | ||
| 41 | std::u16string text; | ||
| 42 | |||
| 43 | QDialogButtonBox* buttons; | ||
| 44 | QLabel* header_label; | ||
| 45 | QLabel* sub_label; | ||
| 46 | QLabel* guide_label; | ||
| 47 | QLabel* length_label; | ||
| 48 | QLineEdit* line_edit; | ||
| 49 | QVBoxLayout* layout; | ||
| 50 | |||
| 51 | Core::Frontend::SoftwareKeyboardParameters parameters; | ||
| 52 | }; | 26 | }; |
| 53 | 27 | ||
| 54 | class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { | 28 | class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { |
| @@ -57,20 +31,4 @@ class QtSoftwareKeyboard final : public QObject, public Core::Frontend::Software | |||
| 57 | public: | 31 | public: |
| 58 | explicit QtSoftwareKeyboard(GMainWindow& parent); | 32 | explicit QtSoftwareKeyboard(GMainWindow& parent); |
| 59 | ~QtSoftwareKeyboard() override; | 33 | ~QtSoftwareKeyboard() override; |
| 60 | |||
| 61 | void RequestText(std::function<void(std::optional<std::u16string>)> out, | ||
| 62 | Core::Frontend::SoftwareKeyboardParameters parameters) const override; | ||
| 63 | void SendTextCheckDialog(std::u16string error_message, | ||
| 64 | std::function<void()> finished_check_) const override; | ||
| 65 | |||
| 66 | signals: | ||
| 67 | void MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; | ||
| 68 | void MainWindowTextCheckDialog(std::u16string error_message) const; | ||
| 69 | |||
| 70 | private: | ||
| 71 | void MainWindowFinishedText(std::optional<std::u16string> text); | ||
| 72 | void MainWindowFinishedCheckDialog(); | ||
| 73 | |||
| 74 | mutable std::function<void(std::optional<std::u16string>)> text_output; | ||
| 75 | mutable std::function<void()> finished_check; | ||
| 76 | }; | 34 | }; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index fbf96be03..e9d6e7421 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -414,27 +414,6 @@ void GMainWindow::ProfileSelectorSelectProfile() { | |||
| 414 | emit ProfileSelectorFinishedSelection(uuid); | 414 | emit ProfileSelectorFinishedSelection(uuid); |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | void GMainWindow::SoftwareKeyboardGetText( | ||
| 418 | const Core::Frontend::SoftwareKeyboardParameters& parameters) { | ||
| 419 | QtSoftwareKeyboardDialog dialog(this, parameters); | ||
| 420 | dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | | ||
| 421 | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | | ||
| 422 | Qt::WindowCloseButtonHint); | ||
| 423 | dialog.setWindowModality(Qt::WindowModal); | ||
| 424 | |||
| 425 | if (dialog.exec() == QDialog::Rejected) { | ||
| 426 | emit SoftwareKeyboardFinishedText(std::nullopt); | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | |||
| 430 | emit SoftwareKeyboardFinishedText(dialog.GetText()); | ||
| 431 | } | ||
| 432 | |||
| 433 | void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) { | ||
| 434 | QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message)); | ||
| 435 | emit SoftwareKeyboardFinishedCheckDialog(); | ||
| 436 | } | ||
| 437 | |||
| 438 | void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, | 417 | void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, |
| 439 | bool is_local) { | 418 | bool is_local) { |
| 440 | #ifdef YUZU_USE_QT_WEB_ENGINE | 419 | #ifdef YUZU_USE_QT_WEB_ENGINE |
| @@ -2188,8 +2167,6 @@ void GMainWindow::OnStartGame() { | |||
| 2188 | emu_thread->SetRunning(true); | 2167 | emu_thread->SetRunning(true); |
| 2189 | 2168 | ||
| 2190 | qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); | 2169 | qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); |
| 2191 | qRegisterMetaType<Core::Frontend::SoftwareKeyboardParameters>( | ||
| 2192 | "Core::Frontend::SoftwareKeyboardParameters"); | ||
| 2193 | qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); | 2170 | qRegisterMetaType<Core::System::ResultStatus>("Core::System::ResultStatus"); |
| 2194 | qRegisterMetaType<std::string>("std::string"); | 2171 | qRegisterMetaType<std::string>("std::string"); |
| 2195 | qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>"); | 2172 | qRegisterMetaType<std::optional<std::u16string>>("std::optional<std::u16string>"); |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 04d37d4ae..6429549ae 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -128,9 +128,6 @@ signals: | |||
| 128 | 128 | ||
| 129 | void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); | 129 | void ProfileSelectorFinishedSelection(std::optional<Common::UUID> uuid); |
| 130 | 130 | ||
| 131 | void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); | ||
| 132 | void SoftwareKeyboardFinishedCheckDialog(); | ||
| 133 | |||
| 134 | void WebBrowserExtractOfflineRomFS(); | 131 | void WebBrowserExtractOfflineRomFS(); |
| 135 | void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); | 132 | void WebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, std::string last_url); |
| 136 | 133 | ||
| @@ -141,8 +138,6 @@ public slots: | |||
| 141 | const Core::Frontend::ControllerParameters& parameters); | 138 | const Core::Frontend::ControllerParameters& parameters); |
| 142 | void ErrorDisplayDisplayError(QString body); | 139 | void ErrorDisplayDisplayError(QString body); |
| 143 | void ProfileSelectorSelectProfile(); | 140 | void ProfileSelectorSelectProfile(); |
| 144 | void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); | ||
| 145 | void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); | ||
| 146 | void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, | 141 | void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args, |
| 147 | bool is_local); | 142 | bool is_local); |
| 148 | void OnAppFocusStateChanged(Qt::ApplicationState state); | 143 | void OnAppFocusStateChanged(Qt::ApplicationState state); |