From 83d08bf96bfb8ab9c0268fcc53c3369b6ab41a37 Mon Sep 17 00:00:00 2001 From: Daniel R <47796739+polybiusproxy@users.noreply.github.com> Date: Sat, 30 Nov 2024 12:51:00 +0100 Subject: [PATCH] core/libraries: Misc. Ime fixes --- src/core/libraries/ime/ime.cpp | 93 +++++++++++++++++++---------- src/core/libraries/ime/ime.h | 22 ++++++- src/core/libraries/ime/ime_common.h | 2 +- src/core/libraries/ime/ime_ui.cpp | 49 +++++++-------- src/core/libraries/ime/ime_ui.h | 6 +- 5 files changed, 112 insertions(+), 60 deletions(-) diff --git a/src/core/libraries/ime/ime.cpp b/src/core/libraries/ime/ime.cpp index efb988c72..92f5d1be3 100644 --- a/src/core/libraries/ime/ime.cpp +++ b/src/core/libraries/ime/ime.cpp @@ -49,7 +49,11 @@ public: openEvent.param.resourceIdArray.resourceId[0] = 1; } - Execute(nullptr, &openEvent, true); + // Are we supposed to call the event handler on init with + // ADD_OSK? + if (!ime_mode && False(m_param.key.option & OrbisImeKeyboardOption::ADD_OSK)) { + Execute(nullptr, &openEvent, true); + } if (ime_mode) { g_ime_state = ImeState(&m_param.ime); @@ -58,6 +62,11 @@ public: } s32 Update(OrbisImeEventHandler handler) { + if (!m_ime_mode) { + /* We don't handle any events for ImeKeyboard */ + return ORBIS_OK; + } + std::unique_lock lock{g_ime_state.queue_mutex}; while (!g_ime_state.event_queue.empty()) { @@ -87,6 +96,16 @@ public: } } + s32 SetText(const char16_t* text, u32 length) { + g_ime_state.SetText(text, length); + return ORBIS_OK; + } + + s32 SetCaret(const OrbisImeCaret* caret) { + g_ime_state.SetCaret(caret->index); + return ORBIS_OK; + } + bool IsIme() { return m_ime_mode; } @@ -100,6 +119,7 @@ private: }; static std::unique_ptr g_ime_handler; +static std::unique_ptr g_keyboard_handler; int PS4_SYSV_ABI FinalizeImeModule() { LOG_ERROR(Lib_Ime, "(STUBBED) called"); @@ -132,9 +152,6 @@ s32 PS4_SYSV_ABI sceImeClose() { if (!g_ime_handler) { return ORBIS_IME_ERROR_NOT_OPENED; } - if (!g_ime_handler->IsIme()) { - return ORBIS_IME_ERROR_NOT_OPENED; - } g_ime_handler.release(); g_ime_ui = ImeUi(); @@ -235,14 +252,11 @@ s32 PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* s32 PS4_SYSV_ABI sceImeKeyboardClose(s32 userId) { LOG_INFO(Lib_Ime, "(STUBBED) called"); - if (!g_ime_handler) { - return ORBIS_IME_ERROR_NOT_OPENED; - } - if (g_ime_handler->IsIme()) { + if (!g_keyboard_handler) { return ORBIS_IME_ERROR_NOT_OPENED; } - g_ime_handler.release(); + g_keyboard_handler.release(); return ORBIS_OK; } @@ -257,18 +271,17 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() { } s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) { - LOG_ERROR(Lib_Ime, "(STUBBED) called"); + LOG_INFO(Lib_Ime, "called"); if (!param) { return ORBIS_IME_ERROR_INVALID_ADDRESS; } - if (g_ime_handler) { + if (g_keyboard_handler) { return ORBIS_IME_ERROR_BUSY; } - // g_ime_handler = std::make_unique(param); - // return ORBIS_OK; - return ORBIS_IME_ERROR_CONNECTION_FAILED; // Fixup + g_keyboard_handler = std::make_unique(param); + return ORBIS_OK; } int PS4_SYSV_ABI sceImeKeyboardOpenInternal() { @@ -289,16 +302,14 @@ int PS4_SYSV_ABI sceImeKeyboardUpdate() { s32 PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const void* extended) { LOG_INFO(Lib_Ime, "called"); - if (!g_ime_handler) { - g_ime_handler = std::make_unique(param); - } else { - if (g_ime_handler->IsIme()) { - return ORBIS_IME_ERROR_BUSY; - } - - g_ime_handler->Init((void*)param, true); + if (!param) { + return ORBIS_IME_ERROR_INVALID_ADDRESS; + } + if (g_ime_handler) { + return ORBIS_IME_ERROR_BUSY; } + g_ime_handler = std::make_unique(param); return ORBIS_OK; } @@ -324,13 +335,29 @@ int PS4_SYSV_ABI sceImeSetCandidateIndex() { } int PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) { - LOG_ERROR(Lib_Ime, "(STUBBED) called"); - return ORBIS_OK; + LOG_TRACE(Lib_Ime, "called"); + + if (!g_ime_handler) { + return ORBIS_IME_ERROR_NOT_OPENED; + } + if (!caret) { + return ORBIS_IME_ERROR_INVALID_ADDRESS; + } + + return g_ime_handler->SetCaret(caret); } -int PS4_SYSV_ABI sceImeSetText() { - LOG_ERROR(Lib_Ime, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length) { + LOG_TRACE(Lib_Ime, "called"); + + if (!g_ime_handler) { + return ORBIS_IME_ERROR_NOT_OPENED; + } + if (!text) { + return ORBIS_IME_ERROR_INVALID_ADDRESS; + } + + return g_ime_handler->SetText(text, length); } int PS4_SYSV_ABI sceImeSetTextGeometry() { @@ -339,13 +366,19 @@ int PS4_SYSV_ABI sceImeSetTextGeometry() { } s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) { - LOG_TRACE(Lib_Ime, "called"); + if (g_ime_handler) { + g_ime_handler->Update(handler); + } - if (!g_ime_handler) { + if (g_keyboard_handler) { + g_keyboard_handler->Update(handler); + } + + if (!g_ime_handler || !g_keyboard_handler) { return ORBIS_IME_ERROR_NOT_OPENED; } - return g_ime_handler->Update(handler); + return ORBIS_OK; } int PS4_SYSV_ABI sceImeVshClearPreedit() { diff --git a/src/core/libraries/ime/ime.h b/src/core/libraries/ime/ime.h index fc98d426a..20117eb8f 100644 --- a/src/core/libraries/ime/ime.h +++ b/src/core/libraries/ime/ime.h @@ -26,6 +26,24 @@ enum class OrbisImeKeyboardOption : u32 { }; DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption) +enum class OrbisImeOption : u32 { + DEFAULT = 0, + MULTILINE = 1, + NO_AUTO_CAPITALIZATION = 2, + PASSWORD = 4, + LANGUAGES_FORCED = 8, + EXT_KEYBOARD = 16, + NO_LEARNING = 32, + FIXED_POSITION = 64, + DISABLE_RESUME = 256, + DISABLE_AUTO_SPACE = 512, + DISABLE_POSITION_ADJUSTMENT = 2048, + EXPANDED_PREEDIT_BUFFER = 4096, + USE_JAPANESE_EISUU_KEY_AS_CAPSLOCK = 8192, + USE_2K_COORDINATES = 16384, +}; +DECLARE_ENUM_FLAG_OPERATORS(OrbisImeOption) + struct OrbisImeKeyboardParam { OrbisImeKeyboardOption option; s8 reserved1[4]; @@ -41,7 +59,7 @@ struct OrbisImeParam { OrbisImeEnterLabel enterLabel; OrbisImeInputMethod inputMethod; OrbisImeTextFilter filter; - u32 option; + OrbisImeOption option; u32 maxTextLength; char16_t* inputTextBuffer; float posx; @@ -93,7 +111,7 @@ int PS4_SYSV_ABI sceImeOpenInternal(); void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param); int PS4_SYSV_ABI sceImeSetCandidateIndex(); s32 PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret); -int PS4_SYSV_ABI sceImeSetText(); +s32 PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length); int PS4_SYSV_ABI sceImeSetTextGeometry(); s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler); int PS4_SYSV_ABI sceImeVshClearPreedit(); diff --git a/src/core/libraries/ime/ime_common.h b/src/core/libraries/ime/ime_common.h index 078a6469e..b0f5325d4 100644 --- a/src/core/libraries/ime/ime_common.h +++ b/src/core/libraries/ime/ime_common.h @@ -143,7 +143,7 @@ struct OrbisImeKeycode { struct OrbisImeKeyboardResourceIdArray { s32 userId; - u32 resourceId[6]; + u32 resourceId[5]; }; enum class OrbisImeCaretMovementDirection : u32 { diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index 09d361263..4b8e4e0d6 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -26,15 +26,13 @@ ImeState::ImeState(const OrbisImeParam* param) { } ImeState::ImeState(ImeState&& other) noexcept - : input_changed(other.input_changed), work_buffer(other.work_buffer), - text_buffer(other.text_buffer), current_text(std::move(other.current_text)), - event_queue(std::move(other.event_queue)) { + : work_buffer(other.work_buffer), text_buffer(other.text_buffer), + current_text(std::move(other.current_text)), event_queue(std::move(other.event_queue)) { other.text_buffer = nullptr; } ImeState& ImeState::operator=(ImeState&& other) noexcept { if (this != &other) { - input_changed = other.input_changed; work_buffer = other.work_buffer; text_buffer = other.text_buffer; current_text = std::move(other.current_text); @@ -63,6 +61,10 @@ void ImeState::SendCloseEvent() { SendEvent(&closeEvent); } +void ImeState::SetText(const char16_t* text, u32 length) {} + +void ImeState::SetCaret(u32 position) {} + bool ImeState::ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text, std::size_t utf8_text_len) { std::fill(utf8_text, utf8_text + utf8_text_len, '\0'); @@ -182,7 +184,6 @@ void ImeUi::DrawInputText() { } if (InputTextEx("##ImeInput", nullptr, state->current_text.begin(), ime_param->maxTextLength, input_size, ImGuiInputTextFlags_CallbackAlways, InputTextCallback, this)) { - state->input_changed = true; } } @@ -190,25 +191,6 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeUi* ui = static_cast(data->UserData); ASSERT(ui); - static int lastCaretPos = -1; - if (lastCaretPos == -1) { - lastCaretPos = data->CursorPos; - } else if (data->CursorPos != lastCaretPos) { - OrbisImeCaretMovementDirection caretDirection = OrbisImeCaretMovementDirection::STILL; - if (data->CursorPos < lastCaretPos) { - caretDirection = OrbisImeCaretMovementDirection::LEFT; - } else if (data->CursorPos > lastCaretPos) { - caretDirection = OrbisImeCaretMovementDirection::RIGHT; - } - - OrbisImeEvent event{}; - event.id = OrbisImeEventId::UPDATE_CARET; - event.param.caretMove = caretDirection; - - lastCaretPos = data->CursorPos; - ui->state->SendEvent(&event); - } - static std::string lastText; std::string currentText(data->Buf, data->BufTextLen); if (currentText != lastText) { @@ -242,6 +224,25 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ui->state->SendEvent(&event); } + static int lastCaretPos = -1; + if (lastCaretPos == -1) { + lastCaretPos = data->CursorPos; + } else if (data->CursorPos != lastCaretPos) { + OrbisImeCaretMovementDirection caretDirection = OrbisImeCaretMovementDirection::STILL; + if (data->CursorPos < lastCaretPos) { + caretDirection = OrbisImeCaretMovementDirection::LEFT; + } else if (data->CursorPos > lastCaretPos) { + caretDirection = OrbisImeCaretMovementDirection::RIGHT; + } + + OrbisImeEvent event{}; + event.id = OrbisImeEventId::UPDATE_CARET; + event.param.caretMove = caretDirection; + + lastCaretPos = data->CursorPos; + ui->state->SendEvent(&event); + } + return 0; } diff --git a/src/core/libraries/ime/ime_ui.h b/src/core/libraries/ime/ime_ui.h index ebd70a7c8..a2a806bb9 100644 --- a/src/core/libraries/ime/ime_ui.h +++ b/src/core/libraries/ime/ime_ui.h @@ -22,10 +22,7 @@ class ImeState { friend class ImeHandler; friend class ImeUi; - bool input_changed = false; - void* work_buffer{}; - char16_t* text_buffer{}; // A character can hold up to 4 bytes in UTF-8 @@ -43,6 +40,9 @@ public: void SendEnterEvent(); void SendCloseEvent(); + void SetText(const char16_t* text, u32 length); + void SetCaret(u32 position); + private: bool ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text, std::size_t native_text_len);