Misc Ime fixes continue (#1655)

* core/libraries: Misc. Ime fixes

* fixed issues

---------

Co-authored-by: Daniel R <47796739+polybiusproxy@users.noreply.github.com>
This commit is contained in:
georgemoralis 2024-12-03 10:05:51 +02:00 committed by GitHub
parent e69f648979
commit e5879c622e
5 changed files with 131 additions and 79 deletions

View file

@ -44,10 +44,14 @@ public:
openEvent.param.rect.y = m_param.ime.posy;
} else {
openEvent.param.resource_id_array.userId = 1;
openEvent.param.resource_id_array.resource_id[0] = 1;
openEvent.param.resource_id_array.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::AddOsk)) {
Execute(nullptr, &openEvent, true);
}
if (ime_mode) {
g_ime_state = ImeState(&m_param.ime);
@ -56,6 +60,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()) {
@ -85,6 +94,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;
}
@ -98,6 +117,7 @@ private:
};
static std::unique_ptr<ImeHandler> g_ime_handler;
static std::unique_ptr<ImeHandler> g_keyboard_handler;
int PS4_SYSV_ABI FinalizeImeModule() {
LOG_ERROR(Lib_Ime, "(STUBBED) called");
@ -130,9 +150,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();
@ -233,14 +250,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;
}
@ -255,18 +269,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<ImeHandler>(param);
// return ORBIS_OK;
return ORBIS_IME_ERROR_CONNECTION_FAILED; // Fixup
g_keyboard_handler = std::make_unique<ImeHandler>(param);
return ORBIS_OK;
}
int PS4_SYSV_ABI sceImeKeyboardOpenInternal() {
@ -287,16 +300,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<ImeHandler>(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<ImeHandler>(param);
return ORBIS_OK;
}
@ -322,13 +333,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() {
@ -337,13 +364,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() {

View file

@ -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,9 +59,9 @@ struct OrbisImeParam {
OrbisImeEnterLabel enter_label;
OrbisImeInputMethod input_method;
OrbisImeTextFilter filter;
u32 option;
u32 max_text_length;
char16_t* input_text_buffer;
OrbisImeOption option;
u32 maxTextLength;
char16_t* inputTextBuffer;
float posx;
float posy;
OrbisImeHorizontalAlignment horizontal_alignment;
@ -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();

View file

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

View file

@ -16,7 +16,7 @@ ImeState::ImeState(const OrbisImeParam* param) {
}
work_buffer = param->work;
text_buffer = param->input_text_buffer;
text_buffer = param->inputTextBuffer;
std::size_t text_len = std::char_traits<char16_t>::length(text_buffer);
if (!ConvertOrbisToUTF8(text_buffer, text_len, current_text.begin(),
@ -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');
@ -180,9 +182,8 @@ void ImeUi::DrawInputText() {
if (first_render) {
SetKeyboardFocusHere();
}
if (InputTextEx("##ImeInput", nullptr, state->current_text.begin(), ime_param->max_text_length,
if (InputTextEx("##ImeInput", nullptr, state->current_text.begin(), ime_param->maxTextLength,
input_size, ImGuiInputTextFlags_CallbackAlways, InputTextCallback, this)) {
state->input_changed = true;
}
}
@ -190,6 +191,39 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
ImeUi* ui = static_cast<ImeUi*>(data->UserData);
ASSERT(ui);
static std::string lastText;
std::string currentText(data->Buf, data->BufTextLen);
if (currentText != lastText) {
OrbisImeEditText eventParam{};
eventParam.str = reinterpret_cast<char16_t*>(ui->ime_param->work);
eventParam.caret_index = data->CursorPos;
eventParam.area_num = 1;
eventParam.text_area[0].mode = 1; // Edit mode
eventParam.text_area[0].index = data->CursorPos;
eventParam.text_area[0].length = data->BufTextLen;
if (!ui->state->ConvertUTF8ToOrbis(data->Buf, data->BufTextLen, eventParam.str,
ui->ime_param->maxTextLength)) {
LOG_ERROR(Lib_ImeDialog, "Failed to convert Orbis char to UTF-8");
return 0;
}
if (!ui->state->ConvertUTF8ToOrbis(data->Buf, data->BufTextLen,
ui->ime_param->inputTextBuffer,
ui->ime_param->maxTextLength)) {
LOG_ERROR(Lib_ImeDialog, "Failed to convert Orbis char to UTF-8");
return 0;
}
OrbisImeEvent event{};
event.id = OrbisImeEventId::UpdateText;
event.param.text = eventParam;
lastText = currentText;
ui->state->SendEvent(&event);
}
static int lastCaretPos = -1;
if (lastCaretPos == -1) {
lastCaretPos = data->CursorPos;
@ -209,39 +243,6 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
ui->state->SendEvent(&event);
}
static std::string lastText;
std::string currentText(data->Buf, data->BufTextLen);
if (currentText != lastText) {
OrbisImeEditText eventParam{};
eventParam.str = reinterpret_cast<char16_t*>(ui->ime_param->work);
eventParam.caret_index = data->CursorPos;
eventParam.area_num = 1;
eventParam.text_area[0].mode = 1; // Edit mode
eventParam.text_area[0].index = data->CursorPos;
eventParam.text_area[0].length = data->BufTextLen;
if (!ui->state->ConvertUTF8ToOrbis(data->Buf, data->BufTextLen, eventParam.str,
ui->ime_param->max_text_length)) {
LOG_ERROR(Lib_ImeDialog, "Failed to convert Orbis char to UTF-8");
return 0;
}
if (!ui->state->ConvertUTF8ToOrbis(data->Buf, data->BufTextLen,
ui->ime_param->input_text_buffer,
ui->ime_param->max_text_length)) {
LOG_ERROR(Lib_ImeDialog, "Failed to convert Orbis char to UTF-8");
return 0;
}
OrbisImeEvent event{};
event.id = OrbisImeEventId::UpdateText;
event.param.text = eventParam;
lastText = currentText;
ui->state->SendEvent(&event);
}
return 0;
}

View file

@ -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);