!784 【需求】绑定编辑框信息002-原子化绑定

Merge pull request !784 from Hollokin/master
This commit is contained in:
openharmony_ci 2023-07-09 13:27:15 +00:00 committed by Gitee
commit 705e33be26
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
39 changed files with 1089 additions and 171 deletions

View File

@ -456,36 +456,68 @@ napi_value JsGetInputMethodController::HandleSoftKeyboard(
return asyncCall.Call(env, exec, "handleSoftKeyboard");
}
napi_status JsGetInputMethodController::ParseAttachInput(
bool JsGetInputMethodController::GetValue(napi_env env, napi_value in, SelectionRange &out)
{
auto ret = JsUtil::Object::ReadProperty(env, in, "start", out.start);
return ret && JsUtil::Object::ReadProperty(env, in, "end", out.end);
}
/**
* let textConfig: TextConfig = {
* inputAttribute: InputAttribute = {
* textInputType: TextInputType = TextInputType.TEXT,
* enterKeyType: EnterKeyType = EnterKeyType.NONE
* },
* cursorInfo?: CursorInfo = {
* left: number,
* top: number,
* width: number,
* height: number,
* },
* selection?: Range = {
* start: number,
* end: number
* },
* windowId?: number
* }
*/
bool JsGetInputMethodController::GetValue(napi_env env, napi_value in, TextConfig &out)
{
napi_value attributeResult = nullptr;
napi_status status = JsUtils::GetValue(env, in, "inputAttribute", attributeResult);
CHECK_RETURN(status == napi_ok, "get inputAttribute", false);
bool ret = JsGetInputMethodController::GetValue(env, attributeResult, out.inputAttribute);
CHECK_RETURN(ret, "get inputAttribute of TextConfig", ret);
napi_value cursorInfoResult = nullptr;
status = JsUtils::GetValue(env, in, "cursorInfo", cursorInfoResult);
bool result = false;
if (status == napi_ok) {
result = JsGetInputMethodController::GetValue(env, cursorInfoResult, out.cursorInfo);
IMSA_HILOGE("get cursorInfo end, ret = %{public}d", result);
}
napi_value rangeResult = nullptr;
status = JsUtils::GetValue(env, in, "selection", rangeResult);
if (status == napi_ok) {
result = JsGetInputMethodController::GetValue(env, rangeResult, out.range);
IMSA_HILOGE("get selectionRange end, ret = %{public}d", result);
}
result = JsUtil::Object::ReadProperty(env, in, "windowId", out.windowId);
IMSA_HILOGE("get windowId end, ret = %{public}d", result);
return ret;
}
bool JsGetInputMethodController::ParseAttachInput(
napi_env env, size_t argc, napi_value *argv, const std::shared_ptr<AttachContext> &ctxt)
{
// 0 means the first parameter: showkeyboard
napi_status status = JsUtils::GetValue(env, argv[0], ctxt->showKeyboard);
if (status != napi_ok) {
return status;
}
bool ret = JsUtil::GetValue(env, argv[0], ctxt->showKeyboard);
IMSA_HILOGE("get showKeyboard end, ret = %{public}d", ret);
// 1 means the second parameter: textConfig
napi_value attributeResult = nullptr;
status = JsUtils::GetValue(env, argv[1], "inputAttribute", attributeResult);
if (status != napi_ok) {
return status;
}
napi_value textResult = nullptr;
status = JsUtils::GetValue(env, attributeResult, "textInputType", textResult);
if (status != napi_ok) {
return status;
}
status = JsUtils::GetValue(env, textResult, ctxt->attribute.inputPattern);
if (status != napi_ok) {
return status;
}
napi_value enterResult = nullptr;
status = JsUtils::GetValue(env, attributeResult, "enterKeyType", enterResult);
if (status != napi_ok) {
return status;
}
return JsUtils::GetValue(env, enterResult, ctxt->attribute.enterKeyType);
return ret && JsGetInputMethodController::GetValue(env, argv[1], ctxt->textConfig);
}
napi_value JsGetInputMethodController::Attach(napi_env env, napi_callback_info info)
@ -493,14 +525,14 @@ napi_value JsGetInputMethodController::Attach(napi_env env, napi_callback_info i
auto ctxt = std::make_shared<AttachContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 1, "should 2 or 3 parameters!", TYPE_NONE, napi_generic_failure);
napi_status status = ParseAttachInput(env, argc, argv, ctxt);
PARAM_CHECK_RETURN(env, status == napi_ok, "paramters of attach is error. ", TYPE_NONE, status);
return status;
bool ret = ParseAttachInput(env, argc, argv, ctxt);
PARAM_CHECK_RETURN(env, ret, "paramters of attach is error. ", TYPE_NONE, napi_generic_failure);
return napi_ok;
};
auto exec = [ctxt, env](AsyncCall::Context *ctx) {
ctxt->textListener = JsGetInputMethodTextChangedListener::GetInstance();
auto status =
InputMethodController::GetInstance()->Attach(ctxt->textListener, ctxt->showKeyboard, ctxt->attribute);
InputMethodController::GetInstance()->Attach(ctxt->textListener, ctxt->showKeyboard, ctxt->textConfig);
ctxt->SetErrorCode(status);
CHECK_RETURN_VOID(status == ErrorCode::NO_ERROR, "attach return error!");
ctxt->SetState(napi_ok);

View File

@ -48,6 +48,7 @@ struct AttachContext : public AsyncCall::Context {
sptr<OnTextChangedListener> textListener;
InputAttribute attribute;
bool showKeyboard = false;
TextConfig textConfig;
AttachContext() : Context(nullptr, nullptr) {};
AttachContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {};
@ -193,10 +194,12 @@ private:
static napi_value CreateSendFunctionKey(napi_env env, int32_t functionKey);
void RegisterListener(napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj);
void UnRegisterListener(napi_value callback, std::string type);
static napi_status ParseAttachInput(
static bool ParseAttachInput(
napi_env env, size_t argc, napi_value *argv, const std::shared_ptr<AttachContext> &ctxt);
static bool GetValue(napi_env env, napi_value in, CursorInfo &out);
static bool GetValue(napi_env env, napi_value in, InputAttribute &out);
static bool GetValue(napi_env env, napi_value in, TextConfig &out);
static bool GetValue(napi_env env, napi_value in, SelectionRange &out);
static napi_value GetJsKeyboardStatusProperty(napi_env env);
static napi_value GetJsEnterKeyTypeProperty(napi_env env);
static napi_value GetJsTextInputTypeProperty(napi_env env);

View File

@ -272,12 +272,6 @@ napi_status JsUtils::GetValue(napi_env env, napi_value in, PanelInfo &out)
return status;
}
bool JsUtils::GetValue(napi_env env, napi_value in, SelectionRange &out)
{
auto ret = JsUtil::Object::ReadProperty(env, in, "start", out.start);
return ret && JsUtil::Object::ReadProperty(env, in, "end", out.end);
}
napi_value JsUtils::GetValue(napi_env env, const std::vector<InputWindowInfo> &in)
{
napi_value array = nullptr;

View File

@ -106,7 +106,6 @@ public:
static napi_status GetValue(napi_env env, napi_value in, std::string &out);
static napi_status GetValue(napi_env env, napi_value in, const std::string &type, napi_value &out);
static napi_status GetValue(napi_env env, napi_value in, PanelInfo &out);
static bool GetValue(napi_env env, napi_value in, SelectionRange &out);
static napi_value GetValue(napi_env env, const std::vector<InputWindowInfo> &in);
static napi_value GetValue(napi_env env, const InputWindowInfo &in);
static napi_value GetValue(napi_env env, const InputAttribute &attribute);

View File

@ -44,7 +44,8 @@ public:
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.miscservices.inputmethod.IInputMethodCore");
virtual int32_t ShowKeyboard(const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard) = 0;
virtual int32_t ShowKeyboard(
const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard, bool attachFlag) = 0;
virtual bool HideKeyboard(int32_t flags) = 0;
virtual int32_t InitInputControlChannel(
sptr<IInputControlChannel> &inputControlChannel, const std::string &imeId) = 0;

View File

@ -68,6 +68,7 @@ public:
int32_t GetEnterKeyType(int32_t &keyType);
int32_t GetInputPattern(int32_t &inputPattern);
int32_t GetTextIndexAtCursor(int32_t &index);
int32_t GetTextConfig(TextTotalConfig &textConfig);
void OnImeReady();
int32_t CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context, const PanelInfo &panelInfo,
std::shared_ptr<InputMethodPanel> &inputMethodPanel);
@ -122,6 +123,7 @@ private:
void OnConfigurationChange(Message *msg);
void ShowInputWindow(bool isShowKeyboard);
void DismissInputWindow();
void OnTextConfigChange(const TextTotalConfig &textConfig);
bool isImeReady_{ false };
InputStartNotifier notifier_;
ConcurrentMap<PanelType, std::shared_ptr<InputMethodPanel>> panels_{};

View File

@ -35,7 +35,8 @@ public:
DISALLOW_COPY_AND_MOVE(InputMethodCoreProxy);
int32_t ShowKeyboard(const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard) override;
int32_t ShowKeyboard(
const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard, bool attachFlag) override;
bool HideKeyboard(int32_t flags) override;
int32_t InitInputControlChannel(sptr<IInputControlChannel> &inputControlChannel, const std::string &imeId) override;
void StopInputService(std::string imeId) override;

View File

@ -39,7 +39,8 @@ public:
explicit InputMethodCoreStub(int userId);
virtual ~InputMethodCoreStub();
int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
int32_t ShowKeyboard(const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard) override;
int32_t ShowKeyboard(
const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard, bool attachFlag) override;
bool HideKeyboard(int32_t flags) override;
int32_t InitInputControlChannel(sptr<IInputControlChannel> &inputControlChannel, const std::string &imeId) override;
void StopInputService(std::string imeId) override;

View File

@ -37,6 +37,8 @@ class MessageHandler;
using namespace MessageID;
sptr<InputMethodAbility> InputMethodAbility::instance_;
std::mutex InputMethodAbility::instanceLock_;
constexpr double INVALID_CURSOR_VALUE = -1.0;
constexpr int32_t INVALID_SELECTION_VALUE = -1;
InputMethodAbility::InputMethodAbility() : stop_(false)
{
writeInputChannel = nullptr;
@ -149,6 +151,10 @@ void InputMethodAbility::OnImeReady()
return;
}
IMSA_HILOGI("InputMethodAbility::Ime Ready, notify InputStart");
TextTotalConfig textConfig{};
int32_t ret = GetTextConfig(textConfig);
IMSA_HILOGI("InputMethodAbility, get text config failed, ret is %{public}d", ret);
OnTextConfigChange(textConfig);
ShowInputWindow(notifier_.isShowKeyboard);
}
@ -238,15 +244,25 @@ void InputMethodAbility::OnShowKeyboard(Message *msg)
MessageParcel *data = msg->msgContent_;
sptr<IRemoteObject> channelObject = nullptr;
bool isShowKeyboard = false;
if (!ITypesUtil::Unmarshal(*data, channelObject, isShowKeyboard)) {
bool attachFlag = false;
if (!ITypesUtil::Unmarshal(*data, channelObject, isShowKeyboard, attachFlag)) {
IMSA_HILOGE("InputMethodAbility::OnShowKeyboard read message parcel failed");
return;
}
if (channelObject == nullptr) {
IMSA_HILOGI("InputMethodAbility::OnShowKeyboard channelObject is nullptr");
IMSA_HILOGE("InputMethodAbility::OnShowKeyboard channelObject is nullptr");
return;
}
SetInputDataChannel(channelObject);
if (attachFlag) {
TextTotalConfig textConfig = {};
int32_t ret = GetTextConfig(textConfig);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("InputMethodAbility, get text config failed, ret is %{public}d", ret);
return;
}
OnTextConfigChange(textConfig);
}
ShowInputWindow(isShowKeyboard);
}
@ -396,15 +412,48 @@ void InputMethodAbility::ShowInputWindow(bool isShowKeyboard)
}
channel->SendKeyboardStatus(KEYBOARD_SHOW);
auto result = panels_.Find(SOFT_KEYBOARD);
if (!result.first) {
IMSA_HILOGE("Not find SOFT_KEYBOARD panel.");
if (result.first) {
IMSA_HILOGI("find SOFT_KEYBOARD panel.");
auto ret = result.second->ShowPanel();
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("Show panel failed, ret = %{public}d.", ret);
}
return;
}
auto ret = result.second->ShowPanel();
if (ret != NO_ERROR) {
IMSA_HILOGE("Show panel failed, ret = %{public}d.", ret);
}
void InputMethodAbility::OnTextConfigChange(const TextTotalConfig &textConfig)
{
IMSA_HILOGI("InputMethodAbility run in.");
if (kdListener_ == nullptr) {
IMSA_HILOGE("kdListener_ is nullptr.");
} else {
IMSA_HILOGI("send on('editorAttributeChanged') callback.");
kdListener_->OnEditorAttributeChange(textConfig.inputAttribute);
if (textConfig.cursorInfo.left != INVALID_CURSOR_VALUE) {
IMSA_HILOGI("send on('cursorUpdate') callback.");
kdListener_->OnCursorUpdate(
textConfig.cursorInfo.left, textConfig.cursorInfo.top, textConfig.cursorInfo.height);
}
if (textConfig.textSelection.newBegin != INVALID_SELECTION_VALUE) {
IMSA_HILOGI("send on('selectionChange') callback.");
kdListener_->OnSelectionChange(textConfig.textSelection.oldBegin, textConfig.textSelection.oldEnd,
textConfig.textSelection.newBegin, textConfig.textSelection.newEnd);
}
}
if (textConfig.windowId == INVALID_WINDOW_ID) {
return;
}
panels_.ForEach([&textConfig](const PanelType &panelType, const std::shared_ptr<InputMethodPanel> &panel) {
panel->SetCallingWindow(textConfig.windowId);
return false;
});
if (imeListener_ == nullptr) {
IMSA_HILOGE("imeListener_ is nullptr, do not need to send callback of setCallingWindow.");
return;
}
imeListener_->OnSetCallingWindow(textConfig.windowId);
IMSA_HILOGD("setCallingWindow end.");
}
void InputMethodAbility::DismissInputWindow()
@ -585,6 +634,17 @@ int32_t InputMethodAbility::GetTextIndexAtCursor(int32_t &index)
return channel->GetTextIndexAtCursor(index);
}
int32_t InputMethodAbility::GetTextConfig(TextTotalConfig &textConfig)
{
IMSA_HILOGD("InputMethodAbility, run in.");
auto channel = GetInputDataChannelProxy();
if (channel == nullptr) {
IMSA_HILOGE("InputMethodAbility::channel is nullptr");
return ErrorCode::ERROR_CLIENT_NULL_POINTER;
}
return channel->GetTextConfig(textConfig);
}
void InputMethodAbility::SetInputDataChannel(sptr<IRemoteObject> &object)
{
IMSA_HILOGD("run in SetInputDataChannel");

View File

@ -39,11 +39,12 @@ int32_t InputMethodCoreProxy::InitInputControlChannel(
});
}
int32_t InputMethodCoreProxy::ShowKeyboard(const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard)
int32_t InputMethodCoreProxy::ShowKeyboard(
const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard, bool attachFlag)
{
IMSA_HILOGD("InputMethodCoreProxy::showKeyboard");
return SendRequest(SHOW_KEYBOARD, [&inputDataChannel, &isShowKeyboard](MessageParcel &data) {
return ITypesUtil::Marshal(data, inputDataChannel->AsObject(), isShowKeyboard);
return SendRequest(SHOW_KEYBOARD, [&inputDataChannel, isShowKeyboard, attachFlag](MessageParcel &data) {
return ITypesUtil::Marshal(data, inputDataChannel->AsObject(), isShowKeyboard, attachFlag);
});
}

View File

@ -157,10 +157,11 @@ void InputMethodCoreStub::ShowKeyboardOnRemote(MessageParcel &data, MessageParce
IMSA_HILOGD("InputMethodCoreStub::ShowKeyboardOnRemote");
sptr<IRemoteObject> channel;
bool isShowKeyboard = false;
int32_t ret =
SendMessage(MessageID::MSG_ID_SHOW_KEYBOARD, [&data, &channel, &isShowKeyboard](MessageParcel &parcel) {
return ITypesUtil::Unmarshal(data, channel, isShowKeyboard)
&& ITypesUtil::Marshal(parcel, channel, isShowKeyboard);
bool attachFlag = false;
int32_t ret = SendMessage(
MessageID::MSG_ID_SHOW_KEYBOARD, [&data, &channel, &isShowKeyboard, &attachFlag](MessageParcel &parcel) {
return ITypesUtil::Unmarshal(data, channel, isShowKeyboard, attachFlag) &&
ITypesUtil::Marshal(parcel, channel, isShowKeyboard, attachFlag);
});
reply.WriteInt32(ret);
}
@ -185,7 +186,7 @@ void InputMethodCoreStub::ClearDataChannelOnRemote(MessageParcel &data, MessageP
}
int32_t InputMethodCoreStub::ShowKeyboard(
const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard)
const sptr<IInputDataChannel> &inputDataChannel, bool isShowKeyboard, bool attachFlag)
{
return ErrorCode::NO_ERROR;
}

View File

@ -275,6 +275,9 @@ void InputMethodPanel::SetPanelStatusListener(
return;
}
panelStatusListener_ = std::move(statusListener);
if (window_ != nullptr && IsShowing()) {
panelStatusListener_->OnPanelStatus(windowId_, true);
}
}
void InputMethodPanel::ClearPanelListener(const std::string &type)

View File

@ -44,6 +44,7 @@ public:
SELECT_BY_MOVEMENT,
HANDLE_EXTEND_ACTION,
GET_TEXT_INDEX_AT_CURSOR,
GET_TEXT_CONFIG,
};
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.miscservices.inputmethod.IInputDataChannel");
@ -53,6 +54,7 @@ public:
virtual int32_t DeleteBackward(int32_t length) = 0;
virtual int32_t GetTextBeforeCursor(int32_t number, std::u16string &text) = 0;
virtual int32_t GetTextAfterCursor(int32_t number, std::u16string &text) = 0;
virtual int32_t GetTextConfig(TextTotalConfig &textConfig) = 0;
virtual void SendKeyboardStatus(int32_t status) = 0;
virtual int32_t SendFunctionKey(int32_t funcKey) = 0;
virtual int32_t MoveCursor(int32_t keyCode) = 0;

View File

@ -49,6 +49,7 @@ public:
int32_t SelectByMovement(int32_t direction, int32_t cursorMoveSkip) override;
int32_t HandleExtendAction(int32_t action) override;
int32_t GetTextIndexAtCursor(int32_t &index) override;
int32_t GetTextConfig(TextTotalConfig &textConfig) override;
private:
static inline BrokerDelegator<InputDataChannelProxy> delegator_;

View File

@ -52,6 +52,7 @@ public:
int32_t SelectByRange(int32_t start, int32_t end) override;
int32_t SelectByMovement(int32_t direction, int32_t cursorMoveSkip) override;
int32_t HandleExtendAction(int32_t action) override;
int32_t GetTextConfig(TextTotalConfig &textConfig) override;
private:
MessageHandler *msgHandler;

View File

@ -45,7 +45,7 @@ public:
DISALLOW_COPY_AND_MOVE(InputMethodSystemAbilityProxy);
int32_t PrepareInput(InputClientInfo &inputClientInfo) override;
int32_t StartInput(sptr<IInputClient> client, bool isShowKeyboard) override;
int32_t StartInput(sptr<IInputClient> client, bool isShowKeyboard, bool attachFlag) override;
int32_t ShowCurrentInput() override;
int32_t HideCurrentInput() override;
int32_t StopInputSession() override;

View File

@ -22,6 +22,9 @@
namespace OHOS {
namespace MiscServices {
constexpr uint32_t INIT_WINDOW_ID = 0;
constexpr uint32_t INVALID_WINDOW_ID = INIT_WINDOW_ID - 1;
constexpr int32_t INVALID_VALUE = -1;
enum class EnterKeyType { UNSPECIFIED = 0, NONE, GO, SEARCH, SEND, NEXT, DONE, PREVIOUS };
enum class TextInputType {
@ -79,10 +82,10 @@ private:
};
struct CursorInfo {
double left = 0.0;
double top = 0.0;
double width = 0.0;
double height = 0.0;
double left = -1.0;
double top = -1.0;
double width = -1.0;
double height = -1.0;
bool operator==(const CursorInfo &info) const
{
return (left == info.left && top == info.top && width == info.width && height == info.height);
@ -111,15 +114,30 @@ private:
};
struct SelectionRange {
int32_t start = -1;
int32_t end = -1;
int32_t start = INVALID_VALUE;
int32_t end = INVALID_VALUE;
};
struct TextSelection {
int32_t oldBegin = -1;
int32_t oldEnd = -1;
int32_t newBegin = -1;
int32_t newEnd = -1;
int32_t oldBegin = INVALID_VALUE;
int32_t oldEnd = INVALID_VALUE;
int32_t newBegin = INVALID_VALUE;
int32_t newEnd = INVALID_VALUE;
};
class TextTotalConfig {
public:
InputAttribute inputAttribute = {};
CursorInfo cursorInfo = {};
TextSelection textSelection = {};
uint32_t windowId = INVALID_WINDOW_ID;
};
struct TextConfig {
InputAttribute inputAttribute = {};
CursorInfo cursorInfo = {};
SelectionRange range = {};
uint32_t windowId = INVALID_WINDOW_ID;
};
} // namespace MiscServices
} // namespace OHOS

View File

@ -45,6 +45,9 @@ public:
static bool Marshalling(uint64_t input, MessageParcel &data);
static bool Unmarshalling(uint64_t &output, MessageParcel &data);
static bool Marshalling(double input, MessageParcel &data);
static bool Unmarshalling(double &output, MessageParcel &data);
static bool Marshalling(const std::u16string &input, MessageParcel &data);
static bool Unmarshalling(std::u16string &output, MessageParcel &data);
@ -72,6 +75,9 @@ public:
static bool Marshalling(const InputWindowInfo &input, MessageParcel &data);
static bool Unmarshalling(InputWindowInfo &output, MessageParcel &data);
static bool Marshalling(const TextTotalConfig &input, MessageParcel &data);
static bool Unmarshalling(TextTotalConfig &output, MessageParcel &data);
static bool Marshalling(EventType input, MessageParcel &data);
static bool Unmarshalling(EventType &output, MessageParcel &data);

View File

@ -111,6 +111,14 @@ int32_t InputDataChannelProxy::GetTextIndexAtCursor(int32_t &index)
[&index](MessageParcel &parcel) { return ITypesUtil::Unmarshal(parcel, index);});
}
int32_t InputDataChannelProxy::GetTextConfig(TextTotalConfig &textConfig)
{
IMSA_HILOGD("InputDataChannelProxy run in");
return SendRequest(GET_TEXT_CONFIG, nullptr, [&textConfig](MessageParcel &parcel) {
return ITypesUtil::Unmarshal(parcel, textConfig);
});
}
int32_t InputDataChannelProxy::SelectByRange(int32_t start, int32_t end)
{
IMSA_HILOGD("InputDataChannelProxy run in");

View File

@ -103,6 +103,12 @@ int32_t InputDataChannelStub::OnRemoteRequest(
SelectByMovementOnRemote(data, reply);
break;
}
case GET_TEXT_CONFIG: {
TextTotalConfig textConfig = {};
reply.WriteInt32(GetTextConfig(textConfig));
ITypesUtil::Marshal(reply, textConfig);
break;
}
default:
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
@ -266,6 +272,12 @@ int32_t InputDataChannelStub::GetInputPattern(int32_t &inputPattern)
return InputMethodController::GetInstance()->GetInputPattern(inputPattern);
}
int32_t InputDataChannelStub::GetTextConfig(TextTotalConfig &textConfig)
{
IMSA_HILOGI("InputDataChannelStub run in.");
return InputMethodController::GetInstance()->GetTextConfig(textConfig);
}
void InputDataChannelStub::SendKeyboardStatus(int32_t status)
{
IMSA_HILOGI("InputDataChannelStub::SendKeyboardStatus");

View File

@ -377,6 +377,13 @@ void InputMethodController::OnPanelStatusChange(
settingListener_->OnPanelStatusChange(status, windowInfo);
}
void InputMethodController::SaveTextConfig(const TextConfig &textConfig)
{
IMSA_HILOGI("InputMethodController in, save text config.");
std::lock_guard<std::mutex> lock(textConfigLock_);
textConfig_ = textConfig;
}
int32_t InputMethodController::Attach(sptr<OnTextChangedListener> &listener)
{
return Attach(listener, true);
@ -394,19 +401,29 @@ int32_t InputMethodController::Attach(
{
IMSA_HILOGI("InputMethodController::Attach isShowKeyboard %{public}s", isShowKeyboard ? "true" : "false");
InputmethodTrace tracer("InputMethodController Attach trace.");
TextConfig textConfig;
textConfig.inputAttribute = attribute;
return Attach(listener, isShowKeyboard, textConfig);
}
int32_t InputMethodController::Attach(
sptr<OnTextChangedListener> &listener, bool isShowKeyboard, const TextConfig &textConfig)
{
IMSA_HILOGI("isShowKeyboard %{public}d", isShowKeyboard);
InputmethodTrace tracer("InputMethodController Attach with textConfig trace.");
{
std::lock_guard<std::mutex> lock(textListenerLock_);
textListener_ = listener;
}
clientInfo_.isShowKeyboard = isShowKeyboard;
clientInfo_.attribute = attribute;
SaveTextConfig(textConfig);
int32_t ret = PrepareInput(clientInfo_);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("failed to prepare, ret: %{public}d", ret);
return ret;
}
ret = StartInput(clientInfo_.client, isShowKeyboard);
ret = StartInput(clientInfo_.client, isShowKeyboard, true);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("failed to start input, ret:%{public}d", ret);
return ret;
@ -430,7 +447,7 @@ int32_t InputMethodController::ShowTextInput()
}
clientInfo_.isShowKeyboard = true;
InputMethodSysEvent::OperateSoftkeyboardBehaviour(IME_SHOW_ENEDITABLE);
int32_t ret = StartInput(clientInfo_.client, true);
int32_t ret = StartInput(clientInfo_.client, true, false);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("failed to start input, ret: %{public}d", ret);
return ret;
@ -590,7 +607,7 @@ std::shared_ptr<SubProperty> InputMethodController::GetCurrentInputMethodSubtype
return property;
}
int32_t InputMethodController::StartInput(sptr<IInputClient> &client, bool isShowKeyboard)
int32_t InputMethodController::StartInput(sptr<IInputClient> &client, bool isShowKeyboard, bool attachFlag)
{
IMSA_HILOGI("InputMethodController::StartInput");
auto proxy = GetSystemAbilityProxy();
@ -598,7 +615,7 @@ int32_t InputMethodController::StartInput(sptr<IInputClient> &client, bool isSho
IMSA_HILOGE("proxy is nullptr");
return ErrorCode::ERROR_SERVICE_START_FAILED;
}
return proxy->StartInput(client, isShowKeyboard);
return proxy->StartInput(client, isShowKeyboard, attachFlag);
}
int32_t InputMethodController::ReleaseInput(sptr<IInputClient> &client)
@ -669,15 +686,17 @@ void InputMethodController::RestoreAttachInfoInSaDied()
return;
}
auto attach = [=]() -> bool {
auto errCode = Attach(textListener_, clientInfo_.isShowKeyboard, clientInfo_.attribute);
if (errCode == ErrorCode::NO_ERROR) {
isDiedAttached_.store(true);
OnCursorUpdate(cursorInfo_);
OnSelectionChange(textString_, selectNewBegin_, selectNewEnd_);
IMSA_HILOGI("attach success.");
return true;
TextConfig tempConfig{};
{
std::lock_guard<std::mutex> lock(textConfigLock_);
tempConfig = textConfig_;
tempConfig.cursorInfo = cursorInfo_;
tempConfig.range.start = selectNewBegin_;
tempConfig.range.end = selectNewEnd_;
}
return false;
auto errCode = Attach(textListener_, clientInfo_.isShowKeyboard, tempConfig);
IMSA_HILOGI("attach end, errCode = %{public}d", errCode);
return errCode == ErrorCode::NO_ERROR;
};
if (attach()) {
return;
@ -754,13 +773,19 @@ int32_t InputMethodController::OnSelectionChange(std::u16string text, int start,
int32_t InputMethodController::OnConfigurationChange(Configuration info)
{
IMSA_HILOGI("InputMethodController::OnConfigurationChange");
std::lock_guard<std::mutex> lock(configurationMutex_);
enterKeyType_ = static_cast<uint32_t>(info.GetEnterKeyType());
inputPattern_ = static_cast<uint32_t>(info.GetTextInputType());
if (!isBound_.load()) {
IMSA_HILOGE("not bound yet");
return ErrorCode::ERROR_CLIENT_NOT_BOUND;
}
{
std::lock_guard<std::mutex> lock(textConfigLock_);
textConfig_.inputAttribute.enterKeyType = static_cast<uint32_t>(info.GetEnterKeyType());
textConfig_.inputAttribute.inputPattern = static_cast<uint32_t>(info.GetTextInputType());
}
std::lock_guard<std::mutex> agentLock(agentLock_);
if (agent_ == nullptr) {
IMSA_HILOGE("agent is nullptr");
return ErrorCode::NO_ERROR;
return ErrorCode::ERROR_SERVICE_START_FAILED;
}
agent_->OnConfigurationChange(info);
return ErrorCode::NO_ERROR;
@ -825,16 +850,39 @@ bool InputMethodController::DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyE
int32_t InputMethodController::GetEnterKeyType(int32_t &keyType)
{
IMSA_HILOGI("InputMethodController::GetEnterKeyType");
std::lock_guard<std::mutex> lock(configurationMutex_);
keyType = enterKeyType_;
std::lock_guard<std::mutex> lock(textConfigLock_);
keyType = textConfig_.inputAttribute.enterKeyType;
return ErrorCode::NO_ERROR;
}
int32_t InputMethodController::GetInputPattern(int32_t &inputpattern)
{
IMSA_HILOGI("InputMethodController::GetInputPattern");
std::lock_guard<std::mutex> lock(configurationMutex_);
inputpattern = inputPattern_;
std::lock_guard<std::mutex> lock(textConfigLock_);
inputpattern = textConfig_.inputAttribute.inputPattern;
return ErrorCode::NO_ERROR;
}
int32_t InputMethodController::GetTextConfig(TextTotalConfig &config)
{
IMSA_HILOGI("InputMethodController run in.");
std::lock_guard<std::mutex> lock(textConfigLock_);
config.inputAttribute = textConfig_.inputAttribute;
config.cursorInfo = textConfig_.cursorInfo;
config.windowId = textConfig_.windowId;
if (textConfig_.range.start == INVALID_VALUE) {
IMSA_HILOGI("no valid SelectionRange param.");
return ErrorCode::NO_ERROR;
}
{
std::lock_guard<std::mutex> editorLock(editorContentLock_);
config.textSelection.oldBegin = selectOldBegin_;
config.textSelection.oldEnd = selectOldEnd_;
}
config.textSelection.newBegin = textConfig_.range.start;
config.textSelection.newEnd = textConfig_.range.end;
return ErrorCode::NO_ERROR;
}
@ -979,6 +1027,10 @@ void InputMethodController::ClearEditorCache()
selectNewBegin_ = 0;
selectNewEnd_ = 0;
}
{
std::lock_guard<std::mutex> lock(textConfigLock_);
textConfig_ = {};
}
std::lock_guard<std::mutex> lock(cursorInfoMutex_);
cursorInfo_ = {};
}

View File

@ -37,12 +37,13 @@ int32_t InputMethodSystemAbilityProxy::PrepareInput(InputClientInfo &inputClient
});
}
int32_t InputMethodSystemAbilityProxy::StartInput(sptr<IInputClient> client, bool isShowKeyboard)
int32_t InputMethodSystemAbilityProxy::StartInput(sptr<IInputClient> client, bool isShowKeyboard, bool attachFlag)
{
IMSA_HILOGD("%{public}s in", __func__);
return SendRequest(
static_cast<uint32_t>(InputMethodInterfaceCode::START_INPUT), [isShowKeyboard, client](MessageParcel &data) {
return data.WriteRemoteObject(client->AsObject()) && data.WriteBool(isShowKeyboard);
return SendRequest(static_cast<uint32_t>(InputMethodInterfaceCode::START_INPUT),
[isShowKeyboard, client, attachFlag](MessageParcel &data) {
return data.WriteRemoteObject(client->AsObject()) && data.WriteBool(isShowKeyboard) &&
data.WriteBool(attachFlag);
});
}

View File

@ -72,6 +72,16 @@ bool ITypesUtil::Unmarshalling(uint64_t &output, MessageParcel &data)
return data.ReadUint64(output);
}
bool ITypesUtil::Marshalling(double input, MessageParcel &data)
{
return data.WriteDouble(input);
}
bool ITypesUtil::Unmarshalling(double &output, MessageParcel &data)
{
return data.ReadDouble(output);
}
bool ITypesUtil::Marshalling(const std::string &input, MessageParcel &data)
{
return data.WriteString(input);
@ -143,7 +153,7 @@ bool ITypesUtil::Marshalling(const SubProperty &input, MessageParcel &data)
bool ITypesUtil::Unmarshalling(SubProperty &output, MessageParcel &data)
{
if (!Unmarshal(data, output.label, output.labelId, output.name, output.id, output.mode, output.locale,
output.language, output.icon, output.iconId)) {
output.language, output.icon, output.iconId)) {
IMSA_HILOGE("ITypesUtil::read SubProperty from message parcel failed");
return false;
}
@ -168,6 +178,52 @@ bool ITypesUtil::Unmarshalling(InputAttribute &output, MessageParcel &data)
return true;
}
bool ITypesUtil::Marshalling(const TextTotalConfig &input, MessageParcel &data)
{
if (!Marshal(data, input.inputAttribute.inputPattern, input.inputAttribute.enterKeyType,
input.inputAttribute.inputOption)) {
IMSA_HILOGE("write InputAttribute to message parcel failed");
return false;
}
if (!Marshal(data, input.cursorInfo.left, input.cursorInfo.top, input.cursorInfo.height, input.cursorInfo.width)) {
IMSA_HILOGE("write CursorInfo to message parcel failed");
return false;
}
if (!Marshal(data, input.textSelection.oldBegin, input.textSelection.oldEnd, input.textSelection.newBegin,
input.textSelection.newEnd)) {
IMSA_HILOGE("write TextSelection to message parcel failed");
return false;
}
if (!Marshal(data, input.windowId)) {
IMSA_HILOGE("write windowId to message parcel failed");
return false;
}
return true;
}
bool ITypesUtil::Unmarshalling(TextTotalConfig &output, MessageParcel &data)
{
if (!Unmarshalling(output.inputAttribute, data)) {
IMSA_HILOGE("read InputAttribute from message parcel failed");
return false;
}
if (!Unmarshal(data, output.cursorInfo.left, output.cursorInfo.top,
output.cursorInfo.height, output.cursorInfo.width)) {
IMSA_HILOGE("read CursorInfo from message parcel failed");
return false;
}
if (!Unmarshal(data, output.textSelection.oldBegin, output.textSelection.oldEnd,
output.textSelection.newBegin, output.textSelection.newEnd)) {
IMSA_HILOGE("read TextSelection from message parcel failed");
return false;
}
if (!Unmarshal(data, output.windowId)) {
IMSA_HILOGE("read windowId from message parcel failed");
return false;
}
return true;
}
bool ITypesUtil::Marshalling(const InputClientInfo &input, MessageParcel &data)
{
if (!Marshal(data, input.pid, input.uid, input.userID, input.displayID, input.attribute, input.isShowKeyboard,

View File

@ -109,6 +109,21 @@ public:
*/
IMF_API int32_t Attach(sptr<OnTextChangedListener> &listener, bool isShowKeyboard, const InputAttribute &attribute);
/**
* @brief Set listener and bind IMSA with given states and textConfig.
*
* This function is used to set listener and bind IMSA.
* Show soft keyboard when state is true, and customized attribute.
*
* @param listener Indicates the listener in order to manipulate text.
* @param isShowKeyboard Indicates the state, if you want to show soft keyboard, please pass in true.
* @param textConfig Indicates the textConfig, such as input attribute, cursorInfo, range of text selection,
* windowId.
* @return Returns 0 for success, others for failure.
* @since 10
*/
IMF_API int32_t Attach(sptr<OnTextChangedListener> &listener, bool isShowKeyboard, const TextConfig &textConfig);
/**
* @brief Show soft keyboard.
*
@ -266,6 +281,17 @@ public:
*/
IMF_API int32_t GetInputPattern(int32_t &inputPattern);
/**
* @brief Get text config.
*
* This function is used to get text config of current client.
*
* @param textConfig Indicates the text config of current client that will be obtained.
* @return Returns 0 for success, others for failure.
* @since 10
*/
IMF_API int32_t GetTextConfig(TextTotalConfig &config);
/**
* @brief Get current input method property.
*
@ -410,7 +436,7 @@ private:
bool Initialize();
sptr<IInputMethodSystemAbility> GetSystemAbilityProxy();
int32_t PrepareInput(InputClientInfo &inputClientInfo);
int32_t StartInput(sptr<IInputClient> &client, bool isShowKeyboard);
int32_t StartInput(sptr<IInputClient> &client, bool isShowKeyboard, bool attachFlag);
int32_t StopInput(sptr<IInputClient> &client);
int32_t ReleaseInput(sptr<IInputClient> &client);
void OnSwitchInput(const Property &property, const SubProperty &subProperty);
@ -427,6 +453,7 @@ private:
void RestoreAttachInfoInSaDied();
int32_t RestoreListenEventFlag();
void UpdateNativeEventFlag(EventType eventType, bool isOn);
void SaveTextConfig(const TextConfig &textConfig);
void GetText(const Message *msg);
void GetTextIndexAtCursor(const Message *msg);
@ -458,9 +485,6 @@ private:
std::thread workThreadHandler;
MessageHandler *msgHandler_;
bool stop_;
std::mutex configurationMutex_;
int32_t enterKeyType_ = 0;
int32_t inputPattern_ = 0;
std::atomic_bool isEditable_{ false };
std::atomic_bool isBound_{ false };
@ -470,6 +494,9 @@ private:
static constexpr int CURSOR_DIRECTION_BASE_VALUE = 2011;
std::atomic_bool isDiedRestoreListen_{ false };
std::mutex textConfigLock_;
TextConfig textConfig_;
};
} // namespace MiscServices
} // namespace OHOS

View File

@ -41,7 +41,7 @@ public:
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.miscservices.inputmethod.IInputMethodSystemAbility");
virtual int32_t PrepareInput(InputClientInfo &clientInfo) = 0;
virtual int32_t StartInput(sptr<IInputClient> client, bool isShowKeyboard) = 0;
virtual int32_t StartInput(sptr<IInputClient> client, bool isShowKeyboard, bool attachFlag) = 0;
virtual int32_t ShowCurrentInput() = 0;
virtual int32_t HideCurrentInput() = 0;
virtual int32_t StopInputSession() = 0;

View File

@ -43,6 +43,12 @@ struct InputAttribute {
{
return inputPattern == PATTERN_PASSWORD;
}
bool operator==(const InputAttribute &info) const
{
return inputPattern == info.inputPattern && enterKeyType == info.enterKeyType &&
inputOption == info.inputOption;
}
};
} // namespace MiscServices
} // namespace OHOS

View File

@ -59,7 +59,7 @@ public:
~InputMethodSystemAbility();
int32_t PrepareInput(InputClientInfo &clientInfo) override;
int32_t StartInput(sptr<IInputClient> client, bool isShowKeyboard) override;
int32_t StartInput(sptr<IInputClient> client, bool isShowKeyboard, bool attachFlag) override;
int32_t ShowCurrentInput() override;
int32_t HideCurrentInput() override;
int32_t StopInput(sptr<IInputClient> client) override;

View File

@ -75,7 +75,7 @@ public:
~PerUserSession();
int32_t OnPrepareInput(const InputClientInfo &clientInfo);
int32_t OnStartInput(const sptr<IInputClient> &client, bool isShowKeyboard);
int32_t OnStartInput(const sptr<IInputClient> &client, bool isShowKeyboard, bool attachFlag);
int32_t OnStopInput(sptr<IInputClient> client);
int32_t OnReleaseInput(const sptr<IInputClient> &client);
int32_t OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IInputMethodAgent> &agent);
@ -122,8 +122,8 @@ private:
int AddClient(sptr<IRemoteObject> inputClient, const InputClientInfo &clientInfo, ClientAddEvent event);
void UpdateClient(sptr<IRemoteObject> inputClient, bool isShowKeyboard);
int32_t RemoveClient(const sptr<IRemoteObject> &client, bool isClientDied);
int32_t ShowKeyboard(
const sptr<IInputDataChannel> &channel, const sptr<IInputClient> &inputClient, bool isShowKeyboard);
int32_t ShowKeyboard(const sptr<IInputDataChannel> &channel, const sptr<IInputClient> &inputClient,
bool isShowKeyboard, bool attachFlag);
int32_t HideKeyboard(const sptr<IInputClient> &inputClient);
int32_t ClearDataChannel(const sptr<IInputDataChannel> &channel);
int32_t SendAgentToSingleClient(const sptr<IInputClient> &client);

View File

@ -245,7 +245,7 @@ int32_t InputMethodSystemAbility::ReleaseInput(sptr<IInputClient> client)
return userSession_->OnReleaseInput(client);
};
int32_t InputMethodSystemAbility::StartInput(sptr<IInputClient> client, bool isShowKeyboard)
int32_t InputMethodSystemAbility::StartInput(sptr<IInputClient> client, bool isShowKeyboard, bool attachFlag)
{
if (!BundleChecker::IsFocused(IPCSkeleton::GetCallingUid())) {
return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
@ -254,7 +254,7 @@ int32_t InputMethodSystemAbility::StartInput(sptr<IInputClient> client, bool isS
IMSA_HILOGE("InputMethodSystemAbility::client is nullptr");
return ErrorCode::ERROR_CLIENT_NULL_POINTER;
}
return userSession_->OnStartInput(client, isShowKeyboard);
return userSession_->OnStartInput(client, isShowKeyboard, attachFlag);
};
int32_t InputMethodSystemAbility::StopInput(sptr<IInputClient> client)

View File

@ -63,7 +63,8 @@ int32_t InputMethodSystemAbilityStub::StartInputOnRemote(MessageParcel &data, Me
return ErrorCode::ERROR_EX_PARCELABLE;
}
bool isShowKeyboard = data.ReadBool();
int32_t ret = StartInput(iface_cast<IInputClient>(clientObject), isShowKeyboard);
bool attachFlag = data.ReadBool();
int32_t ret = StartInput(iface_cast<IInputClient>(clientObject), isShowKeyboard, attachFlag);
return reply.WriteInt32(ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE;
}

View File

@ -141,8 +141,8 @@ int32_t PerUserSession::RemoveClient(const sptr<IRemoteObject> &client, bool isC
* @return ErrorCode::ERROR_KBD_SHOW_FAILED failed to show keyboard
* @return other errors returned by binder driver
*/
int32_t PerUserSession::ShowKeyboard(
const sptr<IInputDataChannel>& channel, const sptr<IInputClient> &inputClient, bool isShowKeyboard)
int32_t PerUserSession::ShowKeyboard(const sptr<IInputDataChannel> &channel, const sptr<IInputClient> &inputClient,
bool isShowKeyboard, bool attachFlag)
{
IMSA_HILOGD("PerUserSession, run in");
if (inputClient == nullptr) {
@ -153,7 +153,7 @@ int32_t PerUserSession::ShowKeyboard(
IMSA_HILOGE("Aborted! imsCore[%{public}d] is nullptr", CURRENT_IME);
return ErrorCode::ERROR_IME_NOT_STARTED;
}
int32_t ret = core->ShowKeyboard(channel, isShowKeyboard);
int32_t ret = core->ShowKeyboard(channel, isShowKeyboard, attachFlag);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("failed to show keyboard, ret: %{public}d", ret);
return ErrorCode::ERROR_KBD_SHOW_FAILED;
@ -268,7 +268,7 @@ int PerUserSession::OnShowKeyboardSelf()
IMSA_HILOGE("client info not found");
return ErrorCode::ERROR_CLIENT_NOT_FOUND;
}
return ShowKeyboard(clientInfo->channel, client, true);
return ShowKeyboard(clientInfo->channel, client, true, false);
}
/** Get ClientInfo
@ -337,9 +337,9 @@ int32_t PerUserSession::OnReleaseInput(const sptr<IInputClient>& client)
* @param the parameters from remote client
* @return ErrorCode
*/
int32_t PerUserSession::OnStartInput(const sptr<IInputClient> &client, bool isShowKeyboard)
int32_t PerUserSession::OnStartInput(const sptr<IInputClient> &client, bool isShowKeyboard, bool attachFlag)
{
IMSA_HILOGD("start input with keyboard[%{public}d]", isShowKeyboard);
IMSA_HILOGD("start input with keyboard[%{public}d], attchFlag[%{public}d]", isShowKeyboard, attachFlag);
if (client == nullptr) {
IMSA_HILOGE("client is nullptr");
return ErrorCode::ERROR_CLIENT_NULL_POINTER;
@ -363,7 +363,7 @@ int32_t PerUserSession::OnStartInput(const sptr<IInputClient> &client, bool isSh
return ret;
}
// build channel from ima to imc
return ShowKeyboard(clientInfo->channel, client, isShowKeyboard);
return ShowKeyboard(clientInfo->channel, client, isShowKeyboard, attachFlag);
}
int32_t PerUserSession::OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IInputMethodAgent> &agent)
@ -391,7 +391,7 @@ int32_t PerUserSession::OnSetCoreAndAgent(const sptr<IInputMethodCore> &core, co
if (client != nullptr) {
auto clientInfo = GetClientInfo(client->AsObject());
if (clientInfo != nullptr) {
ret = OnStartInput(clientInfo->client, clientInfo->isShowKeyboard);
ret = OnStartInput(clientInfo->client, clientInfo->isShowKeyboard, true);
IMSA_HILOGI("start input ret: %{public}d", ret);
}
}

View File

@ -67,7 +67,7 @@ bool FuzzPerUserSession(const uint8_t *rawData, size_t size)
userSessions->OnSwitchIme(property, subProperty, true);
userSessions->StopInputService(str);
userSessions->OnHideKeyboardSelf();
userSessions->OnStartInput(client, isShowKeyboard);
userSessions->OnStartInput(client, isShowKeyboard, false);
userSessions->OnStopInput(client);
userSessions->OnReleaseInput(client);
userSessions->OnSetCoreAndAgent(core, agent);

View File

@ -20,6 +20,7 @@ group("unittest") {
deps += [
"cpp_test:InputMethodAbilityTest",
"cpp_test:InputMethodAttachTest",
"cpp_test:InputMethodControllerTest",
"cpp_test:InputMethodDfxTest",
"cpp_test:InputMethodEditorTest",

View File

@ -57,6 +57,31 @@ ohos_unittest("InputMethodControllerTest") {
]
}
ohos_unittest("InputMethodAttachTest") {
module_out_path = module_output_path
sources = [ "src/input_method_attach_test.cpp" ]
configs = [ ":module_private_config" ]
deps = [
"${inputmethod_path}/frameworks/native/inputmethod_ability:inputmethod_ability",
"${inputmethod_path}/interfaces/inner_api/inputmethod_controller:inputmethod_client_static",
"${inputmethod_path}/services:inputmethod_service",
"${inputmethod_path}/test/unittest/cpp_test/common:inputmethod_tdd_util",
"//third_party/googletest:gmock",
"//third_party/googletest:gtest_main",
]
external_deps = [
"ability_base:want",
"ability_runtime:ability_context_native",
"ability_runtime:ability_manager",
"c_utils:utils",
"hilog:libhilog",
"napi:ace_napi",
]
}
ohos_unittest("InputMethodAbilityTest") {
module_out_path = module_output_path

View File

@ -44,7 +44,6 @@ constexpr const uint16_t EACH_LINE_LENGTH = 500;
constexpr int32_t BUFF_LENGTH = 10;
constexpr const char *CMD_PIDOF_IMS = "pidof inputmethod_ser";
uint64_t TddUtil::selfTokenID_ = 0;
uint64_t TddUtil::testTokenID_ = 0;
int64_t TddUtil::selfUid_ = -1;
int32_t TddUtil::userID_ = INVALID_USER_ID;
int32_t TddUtil::GetCurrentUserId()
@ -71,27 +70,19 @@ uint64_t TddUtil::AllocTestTokenID(bool isSystemApp, bool needPermission, const
HapInfoParams infoParams = { .userID = GetCurrentUserId(),
.bundleName = bundleName,
.instIndex = 0,
.appIDDesc = "ohos.inputmethod_test.demo",
.isSystemApp = true };
.appIDDesc = bundleName,
.isSystemApp = isSystemApp };
PermissionStateFull permissionState = { .permissionName = "ohos.permission.CONNECT_IME_ABILITY",
.isGeneral = true,
.resDeviceID = { "local" },
.grantStatus = { PermissionState::PERMISSION_GRANTED },
.grantFlags = { 1 } };
HapPolicyParams policyParams = { .apl = APL_NORMAL,
.domain = "test.domain.inputmethod",
.domain = bundleName,
.permList = {},
.permStateList = { permissionState } };
if (!needPermission) {
policyParams = { .apl = APL_NORMAL, .domain = "test.domain.inputmethod", .permList = {}, .permStateList = {} };
}
if (!isSystemApp) {
infoParams = {
.userID = GetCurrentUserId(),
.bundleName = bundleName,
.instIndex = 0,
.appIDDesc = "ohos.inputmethod_test.demo"
};
policyParams = { .apl = APL_NORMAL, .domain = bundleName, .permList = {}, .permStateList = {} };
}
auto tokenInfo = AccessTokenKit::AllocHapToken(infoParams, policyParams);
return tokenInfo.tokenIDEx;
@ -185,7 +176,7 @@ void TddUtil::KillImsaProcess()
IMSA_HILOGE("Kill failed, ret: %{public}d", ret);
return;
}
IMSA_HILOGE("Kill success.");
IMSA_HILOGI("Kill success.");
}
sptr<OHOS::AppExecFwk::IBundleMgr> TddUtil::GetBundleMgr()

View File

@ -173,7 +173,7 @@ HWTEST_F(InputMethodAbilityTest, testShowKeyboardInputMethodCoreProxy, TestSize.
sptr<InputMethodCoreProxy> coreProxy = new InputMethodCoreProxy(coreObject);
sptr<InputDataChannelProxy> channelProxy = new InputDataChannelProxy(channelObject);
auto ret = coreProxy->ShowKeyboard(channelProxy, false);
auto ret = coreProxy->ShowKeyboard(channelProxy, false, false);
std::unique_lock<std::mutex> lock(InputMethodAbilityTest::imeListenerCallbackLock_);
auto cvStatus = InputMethodAbilityTest::imeListenerCv_.wait_for(lock, std::chrono::seconds(DEALY_TIME));
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
@ -350,6 +350,28 @@ HWTEST_F(InputMethodAbilityTest, testGetEnterKeyType, TestSize.Level0)
EXPECT_EQ(inputPattern, (int)textInputType);
}
/**
* @tc.name: testGetTextConfig
* @tc.desc: InputMethodAbility GetTextConfig
* @tc.type: FUNC
* @tc.require:
* @tc.author: Hollokin
*/
HWTEST_F(InputMethodAbilityTest, testGetTextConfig, TestSize.Level0)
{
IMSA_HILOGI("InputMethodAbility testGetTextConfig START");
sptr<OnTextChangedListener> textListener = new TextListener();
TextConfig textConfig;
textConfig.inputAttribute = { .inputPattern = 0, .enterKeyType = 1 };
auto ret = imc_->Attach(textListener, false, textConfig);
TextTotalConfig textTotalConfig;
ret = inputMethodAbility_->GetTextConfig(textTotalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(textTotalConfig.inputAttribute.inputPattern, textConfig.inputAttribute.inputPattern);
EXPECT_EQ(textTotalConfig.inputAttribute.enterKeyType, textConfig.inputAttribute.enterKeyType);
textListener = nullptr;
}
/**
* @tc.name: testSelectByRange_001
* @tc.desc: InputMethodAbility SelectByRange

View File

@ -0,0 +1,628 @@
/*
* Copyright (C) 2023 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 <gtest/gtest.h>
#include <string_ex.h>
#include "global.h"
#include "input_attribute.h"
#include "input_method_ability.h"
#include "input_method_controller.h"
#include "tdd_util.h"
#include "text_listener.h"
using namespace testing::ext;
namespace OHOS {
namespace MiscServices {
class InputMethodAttachTest : public testing::Test {
public:
static sptr<InputMethodController> inputMethodController_;
static sptr<InputMethodAbility> inputMethodAbility_;
class EngineListenerImpl : public InputMethodEngineListener {
public:
EngineListenerImpl() = default;
~EngineListenerImpl() = default;
void OnKeyboardStatus(bool isShow)
{
IMSA_HILOGI("EngineListenerImpl OnKeyboardStatus");
}
void OnInputStart()
{
IMSA_HILOGI("EngineListenerImpl OnInputStart");
}
void OnInputStop(const std::string &imeId)
{
IMSA_HILOGI("EngineListenerImpl OnInputStop");
}
void OnSetCallingWindow(uint32_t windowId)
{
IMSA_HILOGI("EngineListenerImpl OnSetCallingWindow");
}
void OnSetSubtype(const SubProperty &property)
{
IMSA_HILOGI("EngineListenerImpl OnSetSubtype");
}
};
static void SetUpTestCase(void)
{
IMSA_HILOGI("InputMethodAttachTest::SetUpTestCase");
// Set the tokenID to the tokenID of the current ime
TddUtil::StorageSelfTokenID();
std::shared_ptr<Property> property = InputMethodController::GetInstance()->GetCurrentInputMethod();
std::string bundleName = property != nullptr ? property->name : "default.inputmethod.unittest";
TddUtil::SetTestTokenID(TddUtil::GetTestTokenID(bundleName));
inputMethodAbility_ = InputMethodAbility::GetInstance();
inputMethodAbility_->OnImeReady();
inputMethodAbility_->SetCoreAndAgent();
TddUtil::RestoreSelfTokenID();
// Set the uid to the uid of the focus app
TddUtil::StorageSelfUid();
TddUtil::SetTestUid();
inputMethodController_ = InputMethodController::GetInstance();
}
static void TearDownTestCase(void)
{
IMSA_HILOGI("InputMethodAttachTest::TearDownTestCase");
TddUtil::RestoreSelfUid();
}
void SetUp()
{
IMSA_HILOGI("InputMethodAttachTest::SetUp");
}
void TearDown()
{
IMSA_HILOGI("InputMethodAttachTest::TearDown");
inputMethodController_->Close();
}
};
sptr<InputMethodController> InputMethodAttachTest::inputMethodController_;
sptr<InputMethodAbility> InputMethodAttachTest::inputMethodAbility_;
/**
* @tc.name: testAttach001
* @tc.desc: test Attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testAttach001, TestSize.Level0)
{
IMSA_HILOGI("test testAttach001 after attach.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int32_t keyType = -1;
ret = inputMethodAbility_->GetEnterKeyType(keyType);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(keyType, 0);
int32_t inputPattern = -1;
ret = inputMethodAbility_->GetInputPattern(inputPattern);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
auto pattern = InputAttribute::PATTERN_TEXT;
EXPECT_EQ(inputPattern, pattern);
}
/**
* @tc.name: testAttach002
* @tc.desc: test Attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testAttach002, TestSize.Level0)
{
IMSA_HILOGI("test testAttach002 after attach.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener, false);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int32_t keyType = -1;
ret = inputMethodAbility_->GetEnterKeyType(keyType);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(keyType, 0);
int32_t inputPattern = -1;
ret = inputMethodAbility_->GetInputPattern(inputPattern);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
auto pattern = InputAttribute::PATTERN_TEXT;
EXPECT_EQ(inputPattern, pattern);
}
/**
* @tc.name: testAttach003
* @tc.desc: test Attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testAttach003, TestSize.Level0)
{
IMSA_HILOGI("test testAttach003 after attach.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 2;
attribute.enterKeyType = 1;
auto ret = inputMethodController_->Attach(textListener, true, attribute);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int32_t keyType = -1;
ret = inputMethodAbility_->GetEnterKeyType(keyType);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(keyType, attribute.enterKeyType);
int32_t inputPattern = -1;
ret = inputMethodAbility_->GetInputPattern(inputPattern);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(inputPattern, attribute.inputPattern);
}
/**
* @tc.name: testAttach004
* @tc.desc: test Attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testAttach004, TestSize.Level0)
{
IMSA_HILOGI("test testAttach004 after attach.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
auto ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int32_t keyType = -1;
ret = inputMethodAbility_->GetEnterKeyType(keyType);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(keyType, config.inputAttribute.enterKeyType);
int32_t inputPattern = -1;
ret = inputMethodAbility_->GetInputPattern(inputPattern);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(inputPattern, config.inputAttribute.inputPattern);
}
/**
* @tc.name: testAttach005
* @tc.desc: test Attach, test optional param in TextConfig
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testAttach005, TestSize.Level0)
{
IMSA_HILOGI("test testAttach005 after attach.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
CursorInfo cursorInfo;
cursorInfo.left = 0;
cursorInfo.top = 1;
cursorInfo.width = 0.5;
cursorInfo.height = 1.2;
config.cursorInfo = cursorInfo;
SelectionRange selectionRange;
selectionRange.start = 0;
selectionRange.end = 2;
config.range = selectionRange;
config.windowId = 10;
auto ret = inputMethodController_->Attach(textListener, true, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int32_t keyType = -1;
ret = inputMethodAbility_->GetEnterKeyType(keyType);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(keyType, config.inputAttribute.enterKeyType);
int32_t inputPattern = -1;
ret = inputMethodAbility_->GetInputPattern(inputPattern);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(inputPattern, config.inputAttribute.inputPattern);
TextTotalConfig textConfig;
ret = inputMethodAbility_->GetTextConfig(textConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(textConfig.inputAttribute, config.inputAttribute);
EXPECT_EQ(textConfig.windowId, config.windowId);
EXPECT_EQ(textConfig.cursorInfo, config.cursorInfo);
EXPECT_EQ(textConfig.textSelection.newBegin, config.range.start);
EXPECT_EQ(textConfig.textSelection.newEnd, config.range.end);
EXPECT_EQ(textConfig.textSelection.oldBegin, 0);
EXPECT_EQ(textConfig.textSelection.oldEnd, 0);
}
/**
* @tc.name: testOnConfigurationChangeWithOutAttach
* @tc.desc: test OnConfigurationChange without attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnConfigurationChangeWithOutAttach, TestSize.Level0)
{
IMSA_HILOGI("InputMethodAttachTest testOnConfigurationChangeWithOutAttach in.");
Configuration config;
EnterKeyType keyType = EnterKeyType::NEXT;
config.SetEnterKeyType(keyType);
TextInputType textInputType = TextInputType::DATETIME;
config.SetTextInputType(textInputType);
auto ret = inputMethodController_->OnConfigurationChange(config);
EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NOT_BOUND);
}
/**
* @tc.name: testOnConfigurationChange
* @tc.desc: test OnConfigurationChange after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnConfigurationChange, TestSize.Level0)
{
IMSA_HILOGI("test OnConfigurationChange after attach.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
Configuration config;
EnterKeyType keyType = EnterKeyType::NEXT;
config.SetEnterKeyType(keyType);
TextInputType textInputType = TextInputType::DATETIME;
config.SetTextInputType(textInputType);
ret = inputMethodController_->OnConfigurationChange(config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int32_t keyType2;
ret = inputMethodAbility_->GetEnterKeyType(keyType2);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(keyType2, (int)keyType);
int32_t inputPattern;
ret = inputMethodAbility_->GetInputPattern(inputPattern);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(inputPattern, (int)textInputType);
}
/**
* @tc.name: testGetTextConfig
* @tc.desc: test GetTextConfig of InputMethodAbility
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testGetTextConfig, TestSize.Level0)
{
IMSA_HILOGI("test OnConfigurationChange001 after attach.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
CursorInfo cursorInfo;
cursorInfo.left = 0;
cursorInfo.top = 1;
cursorInfo.width = 0.5;
cursorInfo.height = 1.2;
config.cursorInfo = cursorInfo;
SelectionRange selectionRange;
selectionRange.start = 0;
selectionRange.end = 2;
config.range = selectionRange;
config.windowId = 10;
auto ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.inputAttribute, attribute);
EXPECT_EQ(totalConfig.cursorInfo, cursorInfo);
EXPECT_EQ(totalConfig.textSelection.newBegin, selectionRange.start);
EXPECT_EQ(totalConfig.textSelection.newEnd, selectionRange.end);
EXPECT_EQ(totalConfig.textSelection.oldBegin, 0);
EXPECT_EQ(totalConfig.textSelection.oldEnd, 0);
EXPECT_EQ(totalConfig.windowId, config.windowId);
}
/**
* @tc.name: testOnCursorUpdateAfterAttach001
* @tc.desc: test OnCursorUpdate after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnCursorUpdateAfterAttach001, TestSize.Level0)
{
IMSA_HILOGI("test testOnCursorUpdateAfterAttach001.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
CursorInfo cursorInfo = { .top = 5, .left = 5, .height = 5, .width = 0.8 };
ret = inputMethodController_->OnCursorUpdate(cursorInfo);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.cursorInfo.height, -1);
EXPECT_EQ(totalConfig.cursorInfo.width, -1);
EXPECT_EQ(totalConfig.cursorInfo.left, -1);
EXPECT_EQ(totalConfig.cursorInfo.top, -1);
}
/**
* @tc.name: testOnCursorUpdateAfterAttach002
* @tc.desc: test OnCursorUpdate after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnCursorUpdateAfterAttach002, TestSize.Level0)
{
IMSA_HILOGI("test testOnCursorUpdateAfterAttach002.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
config.cursorInfo = { .top = 1, .left = 1, .height = 1, .width = 0.4 };
auto ret = inputMethodController_->Attach(textListener, true, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
CursorInfo cursorInfo = { .top = 5, .left = 5, .height = 5, .width = 0.8 };
ret = inputMethodController_->OnCursorUpdate(cursorInfo);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.cursorInfo, config.cursorInfo);
}
/**
* @tc.name: testOnSelectionChangeAfterAttach002
* @tc.desc: test OnSelectionChange after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnSelectionChangeAfterAttach002, TestSize.Level0)
{
IMSA_HILOGI("test testOnSelectionChangeAfterAttach002.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
config.range = { .start = 1, .end = 2 };
auto ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int start = 0;
int end = 1;
ret = inputMethodController_->OnSelectionChange(Str8ToStr16("aaa"), start, end);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.textSelection.newBegin, config.range.start);
EXPECT_EQ(totalConfig.textSelection.newEnd, config.range.end);
EXPECT_EQ(totalConfig.textSelection.oldBegin, 0);
EXPECT_EQ(totalConfig.textSelection.oldEnd, 0);
}
/**
* @tc.name: testOnConfigurationChangeAfterAttach001
* @tc.desc: test OnConfigurationChange after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnConfigurationChangeAfterAttach001, TestSize.Level0)
{
IMSA_HILOGI("test testOnConfigurationChangeAfterAttach001.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
Configuration config;
config.SetTextInputType(TextInputType::DATETIME);
config.SetEnterKeyType(EnterKeyType::NEXT);
ret = inputMethodController_->OnConfigurationChange(config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.inputAttribute.inputPattern, static_cast<int32_t>(TextInputType::DATETIME));
EXPECT_EQ(totalConfig.inputAttribute.enterKeyType, static_cast<int32_t>(EnterKeyType::NEXT));
}
/**
* @tc.name: testOnConfigurationChangeAfterAttach002
* @tc.desc: test OnConfigurationChange after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnConfigurationChangeAfterAttach002, TestSize.Level0)
{
IMSA_HILOGI("test testOnConfigurationChangeAfterAttach002.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
auto ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
Configuration configuration;
configuration.SetTextInputType(TextInputType::DATETIME);
configuration.SetEnterKeyType(EnterKeyType::NEXT);
ret = inputMethodController_->OnConfigurationChange(configuration);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.inputAttribute.inputPattern, static_cast<int32_t>(configuration.GetTextInputType()));
EXPECT_EQ(totalConfig.inputAttribute.enterKeyType, static_cast<int32_t>(configuration.GetEnterKeyType()));
}
/**
* @tc.name: testSetCallingWindowAfterAttach002
* @tc.desc: test SetCallingWindow after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testSetCallingWindowAfterAttach002, TestSize.Level0)
{
IMSA_HILOGI("test testSetCallingWindowAfterAttach002.");
sptr<OnTextChangedListener> textListener = new TextListener();
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
config.windowId = 88;
auto ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
uint32_t windowId = 99;
ret = inputMethodController_->SetCallingWindow(windowId);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.windowId, config.windowId);
}
/**
* @tc.name: testOnCursorUpdate001
* @tc.desc: test OnCursorUpdate after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnCursorUpdate001, TestSize.Level0)
{
IMSA_HILOGI("test testOnCursorUpdate001.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
CursorInfo cursorInfo = { .top = 5, .left = 5, .height = 5, .width = 0.8 };
ret = inputMethodController_->OnCursorUpdate(cursorInfo);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
CursorInfo cursorInfo2 = { .top = 10, .left = 9, .width = 8, .height = 7 };
config.cursorInfo = cursorInfo2;
ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.cursorInfo, cursorInfo2);
}
/**
* @tc.name: testOnSelectionChange
* @tc.desc: test OnSelectionChange after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnSelectionChange, TestSize.Level0)
{
IMSA_HILOGI("test testOnSelectionChange.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
int start = 0;
int end = 1;
ret = inputMethodController_->OnSelectionChange(Str8ToStr16("bbb"), start, end);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
config.range.start = 10;
config.range.end = 20;
ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.textSelection.newBegin, config.range.start);
EXPECT_EQ(totalConfig.textSelection.newEnd, config.range.end);
EXPECT_EQ(totalConfig.textSelection.oldBegin, 0);
EXPECT_EQ(totalConfig.textSelection.oldEnd, 0);
}
/**
* @tc.name: testOnConfigurationChange002
* @tc.desc: test OnConfigurationChange after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testOnConfigurationChange002, TestSize.Level0)
{
IMSA_HILOGI("test testOnConfigurationChange002.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
Configuration configuration;
configuration.SetTextInputType(TextInputType::DATETIME);
configuration.SetEnterKeyType(EnterKeyType::NEXT);
ret = inputMethodController_->OnConfigurationChange(configuration);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.inputAttribute = attribute;
config.inputAttribute.enterKeyType = 5;
config.inputAttribute.inputPattern = 5;
ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.inputAttribute, config.inputAttribute);
}
/**
* @tc.name: testSetCallingWindow
* @tc.desc: test SetCallingWindow after attach
* @tc.type: FUNC
*/
HWTEST_F(InputMethodAttachTest, testSetCallingWindow, TestSize.Level0)
{
IMSA_HILOGI("test testSetCallingWindow.");
sptr<OnTextChangedListener> textListener = new TextListener();
auto ret = inputMethodController_->Attach(textListener);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
uint32_t windowId = 88;
ret = inputMethodController_->SetCallingWindow(windowId);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
InputAttribute attribute;
attribute.inputPattern = 3;
attribute.enterKeyType = 2;
TextConfig config;
config.windowId = 77;
ret = inputMethodController_->Attach(textListener, false, config);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
TextTotalConfig totalConfig;
ret = inputMethodAbility_->GetTextConfig(totalConfig);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
EXPECT_EQ(totalConfig.windowId, config.windowId);
}
} // namespace MiscServices
} // namespace OHOS

View File

@ -315,7 +315,8 @@ constexpr uint32_t KEY_EVENT_DELAY_TIME = 100;
{
IMSA_HILOGI("InputMethodControllerTest::WaitRemoteDiedCallback");
std::unique_lock<std::mutex> lock(onRemoteSaDiedMutex_);
return onRemoteSaDiedCv_.wait_for(lock, std::chrono::seconds(1)) != std::cv_status::timeout;
// 2 means wait 2 seconds.
return onRemoteSaDiedCv_.wait_for(lock, std::chrono::seconds(2)) != std::cv_status::timeout;
}
bool InputMethodControllerTest::CheckKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent)
@ -715,45 +716,6 @@ constexpr uint32_t KEY_EVENT_DELAY_TIME = 100;
&& inputPattern <= static_cast<int32_t>(TextInputType::VISIBLE_PASSWORD));
}
/**
* @tc.name: testIMCOnConfigurationChange
* @tc.desc: IMC testOnConfigurationChange.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F(InputMethodControllerTest, testIMCOnConfigurationChange, TestSize.Level0)
{
IMSA_HILOGI("IMC OnConfigurationChange Test START");
Configuration info;
info.SetEnterKeyType(EnterKeyType::GO);
info.SetTextInputType(TextInputType::NUMBER);
int32_t ret = inputMethodController_->Close();
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
ret = inputMethodController_->OnConfigurationChange(info);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
{
std::unique_lock<std::mutex> lock(InputMethodControllerTest::keyboardListenerMutex_);
ret = InputMethodControllerTest::keyboardListenerCv_.wait_for(
lock, std::chrono::seconds(DEALY_TIME), [&info] {
return (static_cast<OHOS::MiscServices::TextInputType>(
InputMethodControllerTest::inputAttribute_.inputPattern) == info.GetTextInputType()) &&
(static_cast<OHOS::MiscServices::EnterKeyType>(
InputMethodControllerTest::inputAttribute_.enterKeyType) == info.GetEnterKeyType());
});
EXPECT_NE(InputMethodControllerTest::inputAttribute_.inputPattern,
static_cast<int32_t>(info.GetTextInputType()));
EXPECT_NE(
InputMethodControllerTest::inputAttribute_.enterKeyType, static_cast<int32_t>(info.GetEnterKeyType()));
}
auto keyType = static_cast<int32_t>(EnterKeyType::UNSPECIFIED);
auto inputPattern = static_cast<int32_t>(TextInputType::NONE);
ret = inputMethodController_->GetEnterKeyType(keyType);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
ret = inputMethodController_->GetInputPattern(inputPattern);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);
}
/**
* @tc.name: testOnEditorAttributeChanged
* @tc.desc: IMC testOnEditorAttributeChanged.

View File

@ -189,7 +189,7 @@ HWTEST_F(InputMethodPrivateMemberTest, PerUserSessionCoreOrAgentNullptr, TestSiz
auto userSession = std::make_shared<PerUserSession>(MAIN_USER_ID);
userSession->SetImsCore(CURRENT_IME, nullptr);
auto imc = InputMethodController::GetInstance();
int32_t ret = userSession->ShowKeyboard(imc->clientInfo_.channel, imc->clientInfo_.client, false);
int32_t ret = userSession->ShowKeyboard(imc->clientInfo_.channel, imc->clientInfo_.client, false, false);
EXPECT_EQ(ret, ErrorCode::ERROR_IME_NOT_STARTED);
ret = userSession->HideKeyboard(imc->clientInfo_.client);
EXPECT_EQ(ret, ErrorCode::ERROR_IME_NOT_STARTED);
@ -252,11 +252,11 @@ HWTEST_F(InputMethodPrivateMemberTest, PerUserSessionParameterNullptr001, TestSi
{
IMSA_HILOGI("InputMethodPrivateMemberTest PerUserSessionParameterNullptr001 TEST START");
auto userSession = std::make_shared<PerUserSession>(MAIN_USER_ID);
int32_t ret = userSession->OnStartInput(nullptr, true);
int32_t ret = userSession->OnStartInput(nullptr, true, false);
EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NULL_POINTER);
ret = userSession->OnReleaseInput(nullptr);
EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NULL_POINTER);
ret = userSession->ShowKeyboard(nullptr, nullptr, false);
ret = userSession->ShowKeyboard(nullptr, nullptr, false, false);
EXPECT_EQ(ret, ErrorCode::ERROR_CLIENT_NULL_POINTER);
ret = userSession->RemoveClient(nullptr, false);
EXPECT_EQ(ret, ErrorCode::NO_ERROR);