core/libraries: Misc. Ime fixes

This commit is contained in:
Daniel R 2024-11-30 12:51:00 +01:00
parent 36044043bc
commit 83d08bf96b
No known key found for this signature in database
GPG key ID: B8ADC8F57BA18DBA
5 changed files with 112 additions and 60 deletions

View file

@ -49,7 +49,11 @@ public:
openEvent.param.resourceIdArray.resourceId[0] = 1; 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) { if (ime_mode) {
g_ime_state = ImeState(&m_param.ime); g_ime_state = ImeState(&m_param.ime);
@ -58,6 +62,11 @@ public:
} }
s32 Update(OrbisImeEventHandler handler) { 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}; std::unique_lock lock{g_ime_state.queue_mutex};
while (!g_ime_state.event_queue.empty()) { 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() { bool IsIme() {
return m_ime_mode; return m_ime_mode;
} }
@ -100,6 +119,7 @@ private:
}; };
static std::unique_ptr<ImeHandler> g_ime_handler; static std::unique_ptr<ImeHandler> g_ime_handler;
static std::unique_ptr<ImeHandler> g_keyboard_handler;
int PS4_SYSV_ABI FinalizeImeModule() { int PS4_SYSV_ABI FinalizeImeModule() {
LOG_ERROR(Lib_Ime, "(STUBBED) called"); LOG_ERROR(Lib_Ime, "(STUBBED) called");
@ -132,9 +152,6 @@ s32 PS4_SYSV_ABI sceImeClose() {
if (!g_ime_handler) { if (!g_ime_handler) {
return ORBIS_IME_ERROR_NOT_OPENED; return ORBIS_IME_ERROR_NOT_OPENED;
} }
if (!g_ime_handler->IsIme()) {
return ORBIS_IME_ERROR_NOT_OPENED;
}
g_ime_handler.release(); g_ime_handler.release();
g_ime_ui = ImeUi(); 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) { s32 PS4_SYSV_ABI sceImeKeyboardClose(s32 userId) {
LOG_INFO(Lib_Ime, "(STUBBED) called"); LOG_INFO(Lib_Ime, "(STUBBED) called");
if (!g_ime_handler) { if (!g_keyboard_handler) {
return ORBIS_IME_ERROR_NOT_OPENED;
}
if (g_ime_handler->IsIme()) {
return ORBIS_IME_ERROR_NOT_OPENED; return ORBIS_IME_ERROR_NOT_OPENED;
} }
g_ime_handler.release(); g_keyboard_handler.release();
return ORBIS_OK; return ORBIS_OK;
} }
@ -257,18 +271,17 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() {
} }
s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) { s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) {
LOG_ERROR(Lib_Ime, "(STUBBED) called"); LOG_INFO(Lib_Ime, "called");
if (!param) { if (!param) {
return ORBIS_IME_ERROR_INVALID_ADDRESS; return ORBIS_IME_ERROR_INVALID_ADDRESS;
} }
if (g_ime_handler) { if (g_keyboard_handler) {
return ORBIS_IME_ERROR_BUSY; return ORBIS_IME_ERROR_BUSY;
} }
// g_ime_handler = std::make_unique<ImeHandler>(param); g_keyboard_handler = std::make_unique<ImeHandler>(param);
// return ORBIS_OK; return ORBIS_OK;
return ORBIS_IME_ERROR_CONNECTION_FAILED; // Fixup
} }
int PS4_SYSV_ABI sceImeKeyboardOpenInternal() { 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) { s32 PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const void* extended) {
LOG_INFO(Lib_Ime, "called"); LOG_INFO(Lib_Ime, "called");
if (!g_ime_handler) { if (!param) {
g_ime_handler = std::make_unique<ImeHandler>(param); return ORBIS_IME_ERROR_INVALID_ADDRESS;
} else { }
if (g_ime_handler->IsIme()) { if (g_ime_handler) {
return ORBIS_IME_ERROR_BUSY; return ORBIS_IME_ERROR_BUSY;
}
g_ime_handler->Init((void*)param, true);
} }
g_ime_handler = std::make_unique<ImeHandler>(param);
return ORBIS_OK; return ORBIS_OK;
} }
@ -324,13 +335,29 @@ int PS4_SYSV_ABI sceImeSetCandidateIndex() {
} }
int PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) { int PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) {
LOG_ERROR(Lib_Ime, "(STUBBED) called"); LOG_TRACE(Lib_Ime, "called");
return ORBIS_OK;
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() { s32 PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length) {
LOG_ERROR(Lib_Ime, "(STUBBED) called"); LOG_TRACE(Lib_Ime, "called");
return ORBIS_OK;
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() { int PS4_SYSV_ABI sceImeSetTextGeometry() {
@ -339,13 +366,19 @@ int PS4_SYSV_ABI sceImeSetTextGeometry() {
} }
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) { 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 ORBIS_IME_ERROR_NOT_OPENED;
} }
return g_ime_handler->Update(handler); return ORBIS_OK;
} }
int PS4_SYSV_ABI sceImeVshClearPreedit() { int PS4_SYSV_ABI sceImeVshClearPreedit() {

View file

@ -26,6 +26,24 @@ enum class OrbisImeKeyboardOption : u32 {
}; };
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption) 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 { struct OrbisImeKeyboardParam {
OrbisImeKeyboardOption option; OrbisImeKeyboardOption option;
s8 reserved1[4]; s8 reserved1[4];
@ -41,7 +59,7 @@ struct OrbisImeParam {
OrbisImeEnterLabel enterLabel; OrbisImeEnterLabel enterLabel;
OrbisImeInputMethod inputMethod; OrbisImeInputMethod inputMethod;
OrbisImeTextFilter filter; OrbisImeTextFilter filter;
u32 option; OrbisImeOption option;
u32 maxTextLength; u32 maxTextLength;
char16_t* inputTextBuffer; char16_t* inputTextBuffer;
float posx; float posx;
@ -93,7 +111,7 @@ int PS4_SYSV_ABI sceImeOpenInternal();
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param); void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param);
int PS4_SYSV_ABI sceImeSetCandidateIndex(); int PS4_SYSV_ABI sceImeSetCandidateIndex();
s32 PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret); 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(); int PS4_SYSV_ABI sceImeSetTextGeometry();
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler); s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler);
int PS4_SYSV_ABI sceImeVshClearPreedit(); int PS4_SYSV_ABI sceImeVshClearPreedit();

View file

@ -143,7 +143,7 @@ struct OrbisImeKeycode {
struct OrbisImeKeyboardResourceIdArray { struct OrbisImeKeyboardResourceIdArray {
s32 userId; s32 userId;
u32 resourceId[6]; u32 resourceId[5];
}; };
enum class OrbisImeCaretMovementDirection : u32 { enum class OrbisImeCaretMovementDirection : u32 {

View file

@ -26,15 +26,13 @@ ImeState::ImeState(const OrbisImeParam* param) {
} }
ImeState::ImeState(ImeState&& other) noexcept ImeState::ImeState(ImeState&& other) noexcept
: input_changed(other.input_changed), work_buffer(other.work_buffer), : work_buffer(other.work_buffer), text_buffer(other.text_buffer),
text_buffer(other.text_buffer), current_text(std::move(other.current_text)), current_text(std::move(other.current_text)), event_queue(std::move(other.event_queue)) {
event_queue(std::move(other.event_queue)) {
other.text_buffer = nullptr; other.text_buffer = nullptr;
} }
ImeState& ImeState::operator=(ImeState&& other) noexcept { ImeState& ImeState::operator=(ImeState&& other) noexcept {
if (this != &other) { if (this != &other) {
input_changed = other.input_changed;
work_buffer = other.work_buffer; work_buffer = other.work_buffer;
text_buffer = other.text_buffer; text_buffer = other.text_buffer;
current_text = std::move(other.current_text); current_text = std::move(other.current_text);
@ -63,6 +61,10 @@ void ImeState::SendCloseEvent() {
SendEvent(&closeEvent); 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, bool ImeState::ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len,
char* utf8_text, std::size_t utf8_text_len) { char* utf8_text, std::size_t utf8_text_len) {
std::fill(utf8_text, utf8_text + utf8_text_len, '\0'); 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, if (InputTextEx("##ImeInput", nullptr, state->current_text.begin(), ime_param->maxTextLength,
input_size, ImGuiInputTextFlags_CallbackAlways, InputTextCallback, this)) { input_size, ImGuiInputTextFlags_CallbackAlways, InputTextCallback, this)) {
state->input_changed = true;
} }
} }
@ -190,25 +191,6 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
ImeUi* ui = static_cast<ImeUi*>(data->UserData); ImeUi* ui = static_cast<ImeUi*>(data->UserData);
ASSERT(ui); 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; static std::string lastText;
std::string currentText(data->Buf, data->BufTextLen); std::string currentText(data->Buf, data->BufTextLen);
if (currentText != lastText) { if (currentText != lastText) {
@ -242,6 +224,25 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
ui->state->SendEvent(&event); 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; return 0;
} }

View file

@ -22,10 +22,7 @@ class ImeState {
friend class ImeHandler; friend class ImeHandler;
friend class ImeUi; friend class ImeUi;
bool input_changed = false;
void* work_buffer{}; void* work_buffer{};
char16_t* text_buffer{}; char16_t* text_buffer{};
// A character can hold up to 4 bytes in UTF-8 // A character can hold up to 4 bytes in UTF-8
@ -43,6 +40,9 @@ public:
void SendEnterEvent(); void SendEnterEvent();
void SendCloseEvent(); void SendCloseEvent();
void SetText(const char16_t* text, u32 length);
void SetCaret(u32 position);
private: private:
bool ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text, bool ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text,
std::size_t native_text_len); std::size_t native_text_len);