65a10bfe创建于 2025年8月1日历史提交
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "input_method_ffi.h"

#include "inputmethod_trace.h"
#include "cj_input_method_controller.h"
#include "input_method_property.h"
#include "setting_listeners.h"
#include "global.h"
#include "utils.h"
#include "input_method_utils.h"

namespace OHOS::MiscServices {
extern "C" {
int32_t FfiInputMethodGetDefaultInputMethod(CInputMethodProperty *props)
{
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    std::shared_ptr<Property> property;
    int32_t ret = Utils::ConvertErrorCode(ctrl->GetDefaultInputMethod(property));
    if (property == nullptr) {
        IMSA_HILOGE("default input method is nullptr!");
        return ret;
    }
    Utils::InputMethodProperty2C(props, *property);
    return ret;
}

int32_t FfiInputMethodGetCurrentInputMethod(CInputMethodProperty *props)
{
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    std::shared_ptr<Property> property = ctrl->GetCurrentInputMethod();
    if (property == nullptr) {
        IMSA_HILOGE("current input method is nullptr!");
        return ERR_NO_MEMORY;
    }
    Utils::InputMethodProperty2C(props, *property);
    return ErrorCode::NO_ERROR;
}

int32_t FfiInputMethodSwitchInputMethod(bool *result, CInputMethodProperty props)
{
    InputMethodSyncTrace tracer("CJInputMethod_SwitchInputMethod");
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    int32_t errCode =
        ctrl->SwitchInputMethod(SwitchTrigger::CURRENT_IME, std::string(props.name), std::string(props.id));
    if (errCode == ErrorCode::NO_ERROR) {
        *result = true;
    }
    return Utils::ConvertErrorCode(errCode);
}

int32_t FfiInputMethodSwitchCurrentInputMethodSubtype(bool *result, CInputMethodSubtype target)
{
    InputMethodSyncTrace tracer("CJInputMethod_SwitchCurrentInputMethodSubtype");
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    int32_t errCode =
        ctrl->SwitchInputMethod(SwitchTrigger::CURRENT_IME, std::string(target.name), std::string(target.id));
    if (errCode == ErrorCode::NO_ERROR) {
        *result = true;
    }
    return Utils::ConvertErrorCode(errCode);
}

int32_t FfiInputMethodGetCurrentInputMethodSubtype(CInputMethodSubtype *props)
{
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    std::shared_ptr<SubProperty> subProperty = ctrl->GetCurrentInputMethodSubtype();
    if (subProperty == nullptr) {
        IMSA_HILOGE("current input method subtype is nullptr!");
        return ERR_NO_MEMORY;
    }
    Utils::InputMethodSubProperty2C(props, *subProperty);
    return ErrorCode::NO_ERROR;
}

int32_t FfiInputMethodSwitchCurrentInputMethodAndSubtype(bool *result,
    CInputMethodProperty target, CInputMethodSubtype subtype)
{
    InputMethodSyncTrace tracer("CJInputMethod_SwitchCurrentInputMethodAndSubtype");
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    int32_t errCode = ctrl->SwitchInputMethod(SwitchTrigger::CURRENT_IME,
        std::string(subtype.name), std::string(subtype.id));
    if (errCode == ErrorCode::NO_ERROR) {
        *result = true;
    }
    return Utils::ConvertErrorCode(errCode);
}

int32_t FfiInputMethodGetSystemInputMethodConfigAbility(CElementName *elem)
{
    OHOS::AppExecFwk::ElementName inputMethodConfig;
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    int32_t ret = ctrl->GetInputMethodConfig(inputMethodConfig);
    if (ret == ErrorCode::NO_ERROR && elem != nullptr) {
        elem->deviceId = Utils::MallocCString(inputMethodConfig.GetDeviceID());
        elem->bundleName = Utils::MallocCString(inputMethodConfig.GetBundleName());
        elem->abilityName = Utils::MallocCString(inputMethodConfig.GetAbilityName());
        elem->moduleName = Utils::MallocCString(inputMethodConfig.GetModuleName());
    }
    return Utils::ConvertErrorCode(ret);
}

RetInputMethodSubtype FfiInputMethodSettingListInputMethodSubtype(CInputMethodProperty props)
{
    IMSA_HILOGD("run in ListInputMethodSubtype");
    RetInputMethodSubtype ret{};
    Property property = Utils::C2InputMethodProperty(props);
    std::vector<SubProperty> subProps;
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        ret.code = ERR_NO_MEMORY;
        return ret;
    }
    int32_t errCode = ctrl->ListInputMethodSubtype(property, subProps);
    ret.code = Utils::ConvertErrorCode(errCode);
    if (errCode != ErrorCode::NO_ERROR) {
        return ret;
    }
    IMSA_HILOGI("exec ListInputMethodSubtype success");
    ret.size = static_cast<int64_t>(subProps.size());
    if (ret.size > 0) {
        ret.head = static_cast<CInputMethodSubtype *>(malloc(sizeof(CInputMethodSubtype) * ret.size));
    }
    if (ret.head == nullptr) {
        ret.size = 0;
        return ret;
    }
    for (unsigned int i = 0; i < ret.size; i++) {
        CInputMethodSubtype subtype;
        Utils::InputMethodSubProperty2C(&subtype, subProps[i]);
        ret.head[i] = subtype;
    }
    return ret;
}

RetInputMethodSubtype FfiInputMethodSettingListCurrentInputMethodSubtype()
{
    IMSA_HILOGD("run in ListCurrentInputMethodSubtype");
    RetInputMethodSubtype ret{};
    std::vector<SubProperty> subProps;
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        ret.code = ERR_NO_MEMORY;
        return ret;
    }
    int32_t errCode = ctrl->ListCurrentInputMethodSubtype(subProps);
    ret.code = Utils::ConvertErrorCode(errCode);
    if (errCode != ErrorCode::NO_ERROR) {
        return ret;
    }
    IMSA_HILOGI("exec ListCurrentInputMethodSubtype success.");
    ret.size = static_cast<int64_t>(subProps.size());
    if (ret.size > 0) {
        ret.head = static_cast<CInputMethodSubtype *>(malloc(sizeof(CInputMethodSubtype) * ret.size));
    }
    if (ret.head == nullptr) {
        ret.size = 0;
        return ret;
    }
    for (unsigned int i = 0; i < ret.size; i++) {
        CInputMethodSubtype props;
        Utils::InputMethodSubProperty2C(&props, subProps[i]);
        ret.head[i] = props;
    }
    return ret;
}

RetInputMethodProperty FfiInputMethodSettingGetInputMethods(bool enable)
{
    IMSA_HILOGD("run in");
    RetInputMethodProperty ret{};
    std::vector<Property> properties;
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        ret.code = ERR_NO_MEMORY;
        return ret;
    }
    int32_t errCode = ctrl->ListInputMethod(enable, properties);
    ret.code = Utils::ConvertErrorCode(errCode);
    if (errCode != ErrorCode::NO_ERROR) {
        return ret;
    }
    ret.size = static_cast<int64_t>(properties.size());
    if (ret.size > 0) {
        ret.head = static_cast<CInputMethodProperty *>(malloc(sizeof(CInputMethodProperty) * ret.size));
    }
    if (ret.head == nullptr) {
        ret.size = 0;
        return ret;
    }
    for (unsigned int i = 0; i < ret.size; i++) {
        CInputMethodProperty props;
        Utils::InputMethodProperty2C(&props, properties[i]);
        ret.head[i] = props;
    }
    return ret;
}

RetInputMethodProperty FfiInputMethodSettingGetAllInputMethods()
{
    IMSA_HILOGD("run in");
    RetInputMethodProperty ret{};
    std::vector<Property> properties;
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        ret.code = ERR_NO_MEMORY;
        return ret;
    }
    int32_t errCode = ctrl->ListInputMethod(properties);
    ret.code = Utils::ConvertErrorCode(errCode);
    if (errCode != ErrorCode::NO_ERROR) {
        return ret;
    }
    ret.size = static_cast<int64_t>(properties.size());
    if (ret.size > 0) {
        ret.head = static_cast<CInputMethodProperty *>(malloc(sizeof(CInputMethodProperty) * ret.size));
    }
    if (ret.head == nullptr) {
        ret.size = 0;
        return ret;
    }
    for (unsigned int i = 0; i < ret.size; i++) {
        CInputMethodProperty props;
        Utils::InputMethodProperty2C(&props, properties[i]);
        ret.head[i] = props;
    }
    return ret;
}

int32_t FfiInputMethodSettingOn(uint32_t type, void (*func)(CInputMethodProperty, CInputMethodSubtype))
{
    auto setting = CJGetInputMethodSetting::GetIMSInstance();
    if (setting == nullptr) {
        return ERR_NO_MEMORY;
    }
    return Utils::ConvertErrorCode(setting->Subscribe(type, func));
}

int32_t FfiInputMethodSettingOff(uint32_t type)
{
    auto setting = CJGetInputMethodSetting::GetIMSInstance();
    if (setting == nullptr) {
        return ERR_NO_MEMORY;
    }
    return Utils::ConvertErrorCode(setting->UnSubscribe(type));
}

int32_t FfiInputMethodSettingShowOptionalInputMethods(bool *result)
{
    IMSA_HILOGD("start JsGetInputMethodSetting.");
    auto ctrl = InputMethodController::GetInstance();
    if (ctrl == nullptr) {
        return ERR_NO_MEMORY;
    }
    int32_t errCode = ctrl->DisplayOptionalInputMethod();
    if (errCode == ErrorCode::NO_ERROR) {
        IMSA_HILOGI("exec DisplayOptionalInputMethod success");
        *result = true;
    }
    return Utils::ConvertErrorCode(errCode);
}

int32_t FfiInputMethodControllerOn(int8_t type, int64_t id)
{
    return Utils::ConvertErrorCode(CjInputMethodController::Subscribe(type, id));
}

int32_t FfiInputMethodControllerOff(int8_t type)
{
    return Utils::ConvertErrorCode(CjInputMethodController::Unsubscribe(type));
}

int32_t FfiInputMethodControllerAttach(bool showKeyboard, CTextConfig txtCfg)
{
    AttachOptions attachOptions;
    attachOptions.isShowKeyboard = showKeyboard;
    attachOptions.requestKeyboardReason = RequestKeyboardReason::NONE;
    return Utils::ConvertErrorCode(CjInputMethodController::Attach(txtCfg, attachOptions));
}

int32_t FfiInputMethodControllerAttachWithReason(bool showKeyboard, CTextConfig txtCfg, int32_t reason)
{
    AttachOptions attachOptions;
    attachOptions.isShowKeyboard = showKeyboard;
    attachOptions.requestKeyboardReason = static_cast<RequestKeyboardReason>(reason);
    return Utils::ConvertErrorCode(CjInputMethodController::Attach(txtCfg, attachOptions));
}

int32_t FfiInputMethodControllerDetach()
{
    return Utils::ConvertErrorCode(CjInputMethodController::Detach());
}

int32_t FfiInputMethodControllerShowTextInput()
{
    AttachOptions attachOptions;
    attachOptions.isShowKeyboard = false;
    attachOptions.requestKeyboardReason = RequestKeyboardReason::NONE;
    return Utils::ConvertErrorCode(CjInputMethodController::ShowTextInput(attachOptions));
}

int32_t FfiInputMethodControllerShowTextInputWithReason(int32_t reason)
{
    AttachOptions attachOptions;
    attachOptions.isShowKeyboard = false;
    attachOptions.requestKeyboardReason = static_cast<RequestKeyboardReason>(reason);
    return Utils::ConvertErrorCode(CjInputMethodController::ShowTextInput(attachOptions));
}

int32_t FfiInputMethodControllerHideTextInput()
{
    return Utils::ConvertErrorCode(CjInputMethodController::HideTextInput());
}

int32_t FfiInputMethodControllerSetCallingWindow(uint32_t windowId)
{
    return Utils::ConvertErrorCode(CjInputMethodController::SetCallingWindow(windowId));
}

int32_t FfiInputMethodControllerUpdateCursor(CCursorInfo cursor)
{
    return Utils::ConvertErrorCode(CjInputMethodController::UpdateCursor(cursor));
}

int32_t FfiInputMethodControllerChangeSelection(char *text, int32_t start, int32_t end)
{
    return Utils::ConvertErrorCode(CjInputMethodController::ChangeSelection(std::string(text), start, end));
}

int32_t FfiInputMethodControllerUpdateAttribute(CInputAttribute inputAttribute)
{
    return Utils::ConvertErrorCode(CjInputMethodController::UpdateAttribute(inputAttribute));
}

int32_t FfiInputMethodControllerShowSoftKeyboard()
{
    return Utils::ConvertErrorCode(CjInputMethodController::ShowSoftKeyboard());
}

int32_t FfiInputMethodControllerHideSoftKeyboard()
{
    return Utils::ConvertErrorCode(CjInputMethodController::HideSoftKeyboard());
}

int32_t FfiInputMethodControllerStopInputSession()
{
    return Utils::ConvertErrorCode(CjInputMethodController::StopInputSession());
}
}
}