mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-10 04:33:15 +00:00
core/libraries: IME implementation (#1436)
* core/libraries: IME implementation * Update ime_common.h --------- Co-authored-by: georgemoralis <giorgosmrls@gmail.com>
This commit is contained in:
parent
406041b7ad
commit
6e00121eb5
15 changed files with 818 additions and 130 deletions
|
@ -1,14 +1,108 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <queue>
|
||||
#include "ime.h"
|
||||
#include "ime_ui.h"
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/linker.h"
|
||||
|
||||
namespace Libraries::Ime {
|
||||
|
||||
static std::queue<OrbisImeEvent> g_ime_events;
|
||||
static ImeState g_ime_state{};
|
||||
static ImeUi g_ime_ui;
|
||||
|
||||
class ImeHandler {
|
||||
public:
|
||||
ImeHandler(const OrbisImeKeyboardParam* param) {
|
||||
Init(param, false);
|
||||
}
|
||||
ImeHandler(const OrbisImeParam* param) {
|
||||
Init(param, true);
|
||||
}
|
||||
~ImeHandler() = default;
|
||||
|
||||
void Init(const void* param, bool ime_mode) {
|
||||
if (ime_mode) {
|
||||
m_param.ime = *(OrbisImeParam*)param;
|
||||
} else {
|
||||
m_param.key = *(OrbisImeKeyboardParam*)param;
|
||||
}
|
||||
m_ime_mode = ime_mode;
|
||||
|
||||
// Open an event to let the game know the IME has started
|
||||
OrbisImeEvent openEvent{};
|
||||
openEvent.id = (ime_mode ? OrbisImeEventId::OPEN : OrbisImeEventId::KEYBOARD_OPEN);
|
||||
|
||||
if (ime_mode) {
|
||||
sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width,
|
||||
&openEvent.param.rect.height);
|
||||
openEvent.param.rect.x = m_param.ime.posx;
|
||||
openEvent.param.rect.y = m_param.ime.posy;
|
||||
} else {
|
||||
openEvent.param.resourceIdArray.userId = 1;
|
||||
openEvent.param.resourceIdArray.resourceId[0] = 1;
|
||||
}
|
||||
|
||||
Execute(nullptr, &openEvent, true);
|
||||
|
||||
if (ime_mode) {
|
||||
g_ime_state = ImeState(&m_param.ime);
|
||||
g_ime_ui = ImeUi(&g_ime_state, &m_param.ime);
|
||||
}
|
||||
}
|
||||
|
||||
s32 Update(OrbisImeEventHandler handler) {
|
||||
std::unique_lock lock{g_ime_state.queue_mutex};
|
||||
|
||||
while (!g_ime_state.event_queue.empty()) {
|
||||
OrbisImeEvent event = g_ime_state.event_queue.front();
|
||||
g_ime_state.event_queue.pop();
|
||||
Execute(handler, &event, false);
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void Execute(OrbisImeEventHandler handler, OrbisImeEvent* event, bool use_param_handler) {
|
||||
const auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||
|
||||
if (m_ime_mode) {
|
||||
OrbisImeParam param = m_param.ime;
|
||||
if (use_param_handler) {
|
||||
linker->ExecuteGuest(param.handler, param.arg, event);
|
||||
} else {
|
||||
linker->ExecuteGuest(handler, param.arg, event);
|
||||
}
|
||||
} else {
|
||||
OrbisImeKeyboardParam param = m_param.key;
|
||||
if (use_param_handler) {
|
||||
linker->ExecuteGuest(param.handler, param.arg, event);
|
||||
} else {
|
||||
linker->ExecuteGuest(handler, param.arg, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IsIme() {
|
||||
return m_ime_mode;
|
||||
}
|
||||
|
||||
private:
|
||||
union ImeParam {
|
||||
OrbisImeKeyboardParam key;
|
||||
OrbisImeParam ime;
|
||||
} m_param{};
|
||||
bool m_ime_mode = false;
|
||||
};
|
||||
|
||||
static std::unique_ptr<ImeHandler> g_ime_handler;
|
||||
|
||||
int PS4_SYSV_ABI FinalizeImeModule() {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
@ -34,8 +128,19 @@ int PS4_SYSV_ABI sceImeCheckUpdateTextInfo() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeClose() {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
s32 PS4_SYSV_ABI sceImeClose() {
|
||||
LOG_INFO(Lib_Ime, "(STUBBED) called");
|
||||
|
||||
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();
|
||||
g_ime_state = ImeState();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -104,13 +209,42 @@ int PS4_SYSV_ABI sceImeGetPanelPositionAndForm() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeGetPanelSize() {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
s32 PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!width || !height) {
|
||||
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
switch (param->type) {
|
||||
case OrbisImeType::DEFAULT:
|
||||
case OrbisImeType::BASIC_LATIN:
|
||||
case OrbisImeType::URL:
|
||||
case OrbisImeType::MAIL:
|
||||
// We set our custom sizes, commented sizes are the original ones
|
||||
*width = 500; // 793
|
||||
*height = 100; // 408
|
||||
break;
|
||||
case OrbisImeType::NUMBER:
|
||||
*width = 370;
|
||||
*height = 402;
|
||||
break;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeKeyboardClose() {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
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()) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
}
|
||||
|
||||
g_ime_handler.release();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -124,9 +258,19 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeKeyboardOpen() {
|
||||
s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
||||
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;
|
||||
return ORBIS_IME_ERROR_CONNECTION_FAILED; // Fixup
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeKeyboardOpenInternal() {
|
||||
|
@ -144,8 +288,19 @@ int PS4_SYSV_ABI sceImeKeyboardUpdate() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeOpen() {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
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);
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -154,9 +309,15 @@ int PS4_SYSV_ABI sceImeOpenInternal() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeParamInit() {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!param) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(param, 0, sizeof(OrbisImeParam));
|
||||
param->userId = -1;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeSetCandidateIndex() {
|
||||
|
@ -164,7 +325,7 @@ int PS4_SYSV_ABI sceImeSetCandidateIndex() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeSetCaret() {
|
||||
int PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
@ -179,9 +340,14 @@ int PS4_SYSV_ABI sceImeSetTextGeometry() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeUpdate() {
|
||||
LOG_ERROR(Lib_Ime, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
|
||||
LOG_TRACE(Lib_Ime, "called");
|
||||
|
||||
if (!g_ime_handler) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
}
|
||||
|
||||
return g_ime_handler->Update(handler);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeVshClearPreedit() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue