* 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_controller.h"
#include "native_message_handler_callback.h"
#include "native_inputmethod_types.h"
#include "native_inputmethod_utils.h"
#include "string_ex.h"
#ifdef __cplusplus
extern "C" {
#endif
using namespace OHOS;
using namespace OHOS::MiscServices;
constexpr size_t INVALID_MSG_ID_SIZE = 256;
constexpr size_t INVALID_MSG_PARAM_SIZE = 128 * 1024;
static int32_t IsValidMessageHandlerProxy(InputMethod_MessageHandlerProxy *messageHandler)
{
if (messageHandler == nullptr) {
IMSA_HILOGE("messageHandler is nullptr");
return IME_ERR_OK;
}
if (messageHandler->onTerminatedFunc == nullptr) {
IMSA_HILOGE("onTerminatedFunc is nullptr");
return IME_ERR_NULL_POINTER;
}
if (messageHandler->onMessageFunc == nullptr) {
IMSA_HILOGE("onMessageFunc is nullptr");
return IME_ERR_NULL_POINTER;
}
return IME_ERR_OK;
}
InputMethod_ErrorCode OH_InputMethodProxy_ShowKeyboard(InputMethod_InputMethodProxy *inputMethodProxy)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->ShowCurrentInput());
}
InputMethod_ErrorCode OH_InputMethodProxy_ShowTextInput(
InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_AttachOptions *options)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
if (options == nullptr) {
IMSA_HILOGE("options is nullptr");
return IME_ERR_PARAMCHECK;
}
AttachOptions attachOptions;
attachOptions.isShowKeyboard = options->showKeyboard;
attachOptions.requestKeyboardReason =
static_cast<RequestKeyboardReason>(static_cast<int32_t>(options->requestKeyboardReason));
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->ShowTextInput(attachOptions));
}
InputMethod_ErrorCode OH_InputMethodProxy_HideKeyboard(InputMethod_InputMethodProxy *inputMethodProxy)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->HideCurrentInput());
}
InputMethod_ErrorCode OH_InputMethodProxy_NotifySelectionChange(
InputMethod_InputMethodProxy *inputMethodProxy, char16_t text[], size_t length, int start, int end)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
if (text == nullptr) {
IMSA_HILOGE("text is nullptr");
return IME_ERR_NULL_POINTER;
}
if (length > MAX_TEXT_LENGTH) {
IMSA_HILOGE("text length is too long length=%{public}zu", length);
return IME_ERR_PARAMCHECK;
}
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->OnSelectionChange(std::u16string(text, length), start, end));
}
InputMethod_ErrorCode OH_InputMethodProxy_NotifyConfigurationChange(InputMethod_InputMethodProxy *inputMethodProxy,
InputMethod_EnterKeyType enterKey, InputMethod_TextInputType textType)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
Configuration info;
info.SetEnterKeyType(static_cast<EnterKeyType>(enterKey));
info.SetTextInputType(static_cast<TextInputType>(textType));
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->OnConfigurationChange(info));
}
InputMethod_ErrorCode OH_InputMethodProxy_NotifyCursorUpdate(
InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_CursorInfo *cursorInfo)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
if (cursorInfo == nullptr) {
IMSA_HILOGE("cursorInfo is nullptr");
return IME_ERR_NULL_POINTER;
}
CursorInfo info;
info.left = cursorInfo->left;
info.top = cursorInfo->top;
info.width = cursorInfo->width;
info.height = cursorInfo->height;
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->OnCursorUpdate(info));
}
InputMethod_ErrorCode OH_InputMethodProxy_SendPrivateCommand(
InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_PrivateCommand *privateCommand[], size_t size)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
if (privateCommand == nullptr) {
IMSA_HILOGE("privateCommand is nullptr");
return IME_ERR_NULL_POINTER;
}
if (size > MAX_SYS_PRIVATE_COMMAND_COUNT) {
IMSA_HILOGE("privateCommand size is too large: %{public}zu", size);
return IME_ERR_PARAMCHECK;
}
std::unordered_map<std::string, PrivateDataValue> command;
for (size_t i = 0; i < size; i++) {
if (privateCommand[i] == nullptr) {
IMSA_HILOGE("privateCommand[%zu] is nullptr", i);
return IME_ERR_NULL_POINTER;
}
command.emplace(privateCommand[i]->key, privateCommand[i]->value);
}
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->SendPrivateCommand(command));
}
InputMethod_ErrorCode OH_InputMethodProxy_SendMessage(InputMethod_InputMethodProxy *inputMethodProxy,
const char16_t *msgId, size_t msgIdLength, const uint8_t *msgParam, size_t msgParamLength)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
if (msgId == nullptr || msgParam == nullptr) {
IMSA_HILOGE("msgId or msgParam is nullptr");
return IME_ERR_NULL_POINTER;
}
if (msgIdLength > INVALID_MSG_ID_SIZE || msgParamLength > INVALID_MSG_PARAM_SIZE) {
IMSA_HILOGE("ArrayBuffer size is invalid, msgIdLength: %{public}zu, msgParamLength: %{public}zu",
msgIdLength, msgParamLength);
return IME_ERR_PARAMCHECK;
}
ArrayBuffer arrayBuffer;
std::u16string msgIdStr(msgId, msgIdLength);
arrayBuffer.msgId = Str16ToStr8(msgIdStr);
arrayBuffer.msgParam.assign(msgParam, msgParam + msgParamLength);
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
return ErrorCodeConvert(instance->SendMessage(arrayBuffer));
}
InputMethod_ErrorCode OH_InputMethodProxy_RecvMessage(
InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_MessageHandlerProxy *messageHandler)
{
auto errCode = IsValidInputMethodProxy(inputMethodProxy);
if (errCode != IME_ERR_OK) {
IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
return errCode;
}
if (IsValidMessageHandlerProxy(messageHandler) != IME_ERR_OK) {
IMSA_HILOGE("invalid messageHandler");
return IME_ERR_NULL_POINTER;
}
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
IMSA_HILOGE("InputMethodController is nullptr");
return IME_ERR_NULL_POINTER;
}
if (messageHandler == nullptr) {
IMSA_HILOGI("UnRegister message handler.");
return ErrorCodeConvert(instance->RegisterMsgHandler(nullptr));
}
IMSA_HILOGI("Register message handler.");
std::shared_ptr<MsgHandlerCallbackInterface> msgHandler =
std::make_shared<NativeMessageHandlerCallback>(messageHandler);
return ErrorCodeConvert(instance->RegisterMsgHandler(msgHandler));
}
#ifdef __cplusplus
}
#endif