diff --git a/common/include/global.h b/common/include/global.h index a26b8594a7b44382fbc92ce49ef71f8900906cbf..8fb98c87dec93db8aefd2bf4da08ad56130dd3be 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -119,6 +119,7 @@ enum { ERROR_SECURITY_MODE_OFF = 50, ERROR_MESSAGE_HANDLER = 51, ERROR_INVALID_ARRAY_BUFFER_SIZE = 52, + ERROR_DEVICE_UNSUPPORTED = 53, }; }; // namespace ErrorCode diff --git a/common/src/itypes_util.cpp b/common/src/itypes_util.cpp index ccbcbf8937e1d35481059078aa6cc2dc7b0fc726..c54568d80fa0236460496bfb06313a44a5f99017 100644 --- a/common/src/itypes_util.cpp +++ b/common/src/itypes_util.cpp @@ -210,6 +210,10 @@ bool ITypesUtil::Marshalling(const TextTotalConfig &input, MessageParcel &data) IMSA_HILOGE("write privateCommand to message parcel failed."); return false; } + if (!Marshal(data, input.requestKeyboardReason)) { + IMSA_HILOGE("write requestKeyboardReason to message parcel failed."); + return false; + } return true; } @@ -245,6 +249,10 @@ bool ITypesUtil::Unmarshalling(TextTotalConfig &output, MessageParcel &data) IMSA_HILOGE("read privateCommand from message parcel failed."); return false; } + if (!Unmarshal(data, output.requestKeyboardReason)) { + IMSA_HILOGE("read requestKeyboardReason from message parcel failed."); + return false; + } return true; } diff --git a/frameworks/js/napi/common/event_checker.cpp b/frameworks/js/napi/common/event_checker.cpp index 30fc026a3c56119235ba3b7f506bb2cdf6519a47..f8b03a77acb53fdc845e866297a54b5a9a2f727c 100644 --- a/frameworks/js/napi/common/event_checker.cpp +++ b/frameworks/js/napi/common/event_checker.cpp @@ -28,7 +28,8 @@ const std::unordered_set EVENT_TYPES[static_cast(EventSub [static_cast(EventSubscribeModule::KEYBOARD_DELEGATE)] = { "editorAttributeChanged", "keyDown", "keyUp", "keyEvent", "cursorContextChange", "selectionChange", "textChange" }, [static_cast(EventSubscribeModule::KEYBOARD_PANEL_MANAGER)] = { "panelPrivateCommand", "isPanelShow" }, - [static_cast(EventSubscribeModule::PANEL)] = { "show", "hide", "sizeChange", "sizeUpdate" } + [static_cast(EventSubscribeModule::PANEL)] = { "show", "hide", "sizeChange", "sizeUpdate" }, + [static_cast(EventSubscribeModule::TEXT_INPUT_CLIENT)] = { "attachOptionsDidChange" } }; bool EventChecker::IsValidEventType(EventSubscribeModule module, const std::string &type) diff --git a/frameworks/js/napi/common/event_checker.h b/frameworks/js/napi/common/event_checker.h index 0c98424ccf4cea86cb6b8a6f9e0593bd88546de7..74e2ec24ed589ac5196120f148b1b71076b00466 100644 --- a/frameworks/js/napi/common/event_checker.h +++ b/frameworks/js/napi/common/event_checker.h @@ -27,6 +27,7 @@ enum class EventSubscribeModule : uint32_t { KEYBOARD_DELEGATE, KEYBOARD_PANEL_MANAGER, PANEL, + TEXT_INPUT_CLIENT, MODULE_END, }; class EventChecker { diff --git a/frameworks/js/napi/common/js_callback_object.cpp b/frameworks/js/napi/common/js_callback_object.cpp index 8502306c43d12b01646c2fc377cd5ac0595028fb..a555b302282e28010547f3d1f80dcc6b07a372dc 100644 --- a/frameworks/js/napi/common/js_callback_object.cpp +++ b/frameworks/js/napi/common/js_callback_object.cpp @@ -21,8 +21,9 @@ namespace OHOS { namespace MiscServices { constexpr int32_t MAX_TIMEOUT = 2000; -JSCallbackObject::JSCallbackObject(napi_env env, napi_value callback, std::thread::id threadId) - : env_(env), threadId_(threadId) +JSCallbackObject::JSCallbackObject(napi_env env, napi_value callback, std::thread::id threadId, + std::shared_ptr jsHandler) + : env_(env), threadId_(threadId), jsHandler_(jsHandler) { napi_create_reference(env, callback, 1, &callback_); } diff --git a/frameworks/js/napi/common/js_callback_object.h b/frameworks/js/napi/common/js_callback_object.h index 5663a1c89628cd6ef5b527fbca624393bf9179c8..47af5512ecdf15c97d96939a4bfc8c0bb1be3e9b 100644 --- a/frameworks/js/napi/common/js_callback_object.h +++ b/frameworks/js/napi/common/js_callback_object.h @@ -27,12 +27,14 @@ namespace OHOS { namespace MiscServices { class JSCallbackObject { public: - JSCallbackObject(napi_env env, napi_value callback, std::thread::id threadId); + JSCallbackObject(napi_env env, napi_value callback, std::thread::id threadId, + std::shared_ptr jsHandler); ~JSCallbackObject(); napi_ref callback_ = nullptr; napi_env env_{}; std::thread::id threadId_; std::shared_ptr> isDone_; + std::shared_ptr jsHandler_; }; // Ensure this object abstract in constract thread. diff --git a/frameworks/js/napi/inputmethodability/BUILD.gn b/frameworks/js/napi/inputmethodability/BUILD.gn index 72aba36e5619c637fb4905298ebff914b7daa27c..f67967e42001223937f3e85a5b599f478a160f96 100644 --- a/frameworks/js/napi/inputmethodability/BUILD.gn +++ b/frameworks/js/napi/inputmethodability/BUILD.gn @@ -78,6 +78,7 @@ ohos_shared_library("inputmethodengine") { "ability_base:configuration", "ability_runtime:ability_context_native", "ability_runtime:abilitykit_native", + "ability_runtime:app_context", "ability_runtime:napi_base_context", "c_utils:utils", "eventhandler:libeventhandler", @@ -87,6 +88,7 @@ ohos_shared_library("inputmethodengine") { "input:libmmi-napi", "ipc:ipc_core", "napi:ace_napi", + "resource_management:global_resmgr", "window_manager:libwm_lite", ] diff --git a/frameworks/js/napi/inputmethodability/js_input_method_engine_setting.cpp b/frameworks/js/napi/inputmethodability/js_input_method_engine_setting.cpp index 3d14259f5e3f7449162621ee83f1f45fb2b9d858..cfe07c42b47698e91656eaf4096864f7cc623867 100644 --- a/frameworks/js/napi/inputmethodability/js_input_method_engine_setting.cpp +++ b/frameworks/js/napi/inputmethodability/js_input_method_engine_setting.cpp @@ -373,7 +373,8 @@ napi_value JsInputMethodEngineSetting::Subscribe(napi_env env, napi_callback_inf return nullptr; } std::shared_ptr callback = - std::make_shared(env, argv[ARGC_ONE], std::this_thread::get_id()); + std::make_shared(env, argv[ARGC_ONE], std::this_thread::get_id(), + AppExecFwk::EventHandler::Current()); engine->RegisterListener(argv[ARGC_ONE], type, callback); napi_value result = nullptr; diff --git a/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp b/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp index bb2fc575809e87450858bf6f2140e7a528b9f836..be8e959064bcc349ae5b4179fe636a72d888d6a8 100644 --- a/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp +++ b/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp @@ -236,7 +236,8 @@ napi_value JsKeyboardDelegateSetting::Subscribe(napi_env env, napi_callback_info return nullptr; } std::shared_ptr callback = - std::make_shared(env, argv[1], std::this_thread::get_id()); + std::make_shared(env, argv[1], std::this_thread::get_id(), + AppExecFwk::EventHandler::Current()); engine->RegisterListener(argv[ARGC_ONE], type, callback); napi_value result = nullptr; diff --git a/frameworks/js/napi/inputmethodability/js_panel.cpp b/frameworks/js/napi/inputmethodability/js_panel.cpp index ac5fffbf9c9833d928359a2447e388705885afdc..3a8130a2e389dafe4dedc104c26b66ac0c444d0e 100644 --- a/frameworks/js/napi/inputmethodability/js_panel.cpp +++ b/frameworks/js/napi/inputmethodability/js_panel.cpp @@ -439,7 +439,8 @@ napi_value JsPanel::Subscribe(napi_env env, napi_callback_info info) auto inputMethodPanel = UnwrapPanel(env, thisVar); // 1 means the second param callback. std::shared_ptr cbObject = - std::make_shared(env, argv[1], std::this_thread::get_id()); + std::make_shared(env, argv[1], std::this_thread::get_id(), + AppExecFwk::EventHandler::Current()); observer->Subscribe(inputMethodPanel->windowId_, type, cbObject); bool ret = inputMethodPanel->SetPanelStatusListener(observer, type); if (!ret) { diff --git a/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp b/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp index 854979108571c6531b124f8468594d9fbe3b61ac..7e06503174474c4da24c32fdf87d1e0534e60167 100644 --- a/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp +++ b/frameworks/js/napi/inputmethodability/js_text_input_client_engine.cpp @@ -15,14 +15,18 @@ #include "js_text_input_client_engine.h" +#include "event_checker.h" #include "input_method_ability.h" #include "inputmethod_trace.h" +#include "js_callback_handler.h" #include "js_util.h" #include "js_utils.h" #include "napi/native_api.h" #include "napi/native_node_api.h" #include "string_ex.h" #include "wm_common.h" +#include "res_config.h" +#include "resource_manager.h" namespace OHOS { namespace MiscServices { @@ -30,6 +34,7 @@ namespace MiscServices { using namespace std::chrono; thread_local napi_ref JsTextInputClientEngine::TICRef_ = nullptr; const std::string JsTextInputClientEngine::TIC_CLASS_NAME = "TextInputClient"; +constexpr int32_t DEVICE_TYPE_2IN1 = 7; constexpr int32_t MAX_WAIT_TIME = 5000; constexpr int32_t MAX_WAIT_TIME_PRIVATE_COMMAND = 2000; constexpr int32_t MAX_WAIT_TIME_MESSAGE_HANDLER = 2000; @@ -38,7 +43,12 @@ constexpr size_t ARGC_ONE = 1; std::shared_ptr JsTextInputClientEngine::taskQueue_ = std::make_shared(); BlockQueue JsTextInputClientEngine::privateCommandQueue_{ MAX_WAIT_TIME_PRIVATE_COMMAND }; BlockQueue JsTextInputClientEngine::messageHandlerQueue_{ MAX_WAIT_TIME_MESSAGE_HANDLER }; +std::mutex JsTextInputClientEngine::engineMutex_; +std::shared_ptr JsTextInputClientEngine::textInputClientEngine_{ nullptr }; +std::mutex JsTextInputClientEngine::eventHandlerMutex_; +std::shared_ptr JsTextInputClientEngine::handler_{ nullptr }; uint32_t JsTextInputClientEngine::traceId_{ 0 }; +int32_t JsTextInputClientEngine::deviceTypeCache_{ -1 }; napi_value JsTextInputClientEngine::Init(napi_env env, napi_value info) { IMSA_HILOGD("JsTextInputClientEngine init"); @@ -73,6 +83,9 @@ napi_value JsTextInputClientEngine::Init(napi_env env, napi_value info) DECLARE_NAPI_FUNCTION("finishTextPreviewSync", FinishTextPreviewSync), DECLARE_NAPI_FUNCTION("sendMessage", SendMessage), DECLARE_NAPI_FUNCTION("recvMessage", RecvMessage), + DECLARE_NAPI_FUNCTION("getAttachOptions", GetAttachOptions), + DECLARE_NAPI_FUNCTION("on", Subscribe), + DECLARE_NAPI_FUNCTION("off", UnSubscribe) }; napi_value cons = nullptr; NAPI_CALL(env, napi_define_class(env, TIC_CLASS_NAME.c_str(), TIC_CLASS_NAME.size(), JsConstructor, nullptr, @@ -83,6 +96,34 @@ napi_value JsTextInputClientEngine::Init(napi_env env, napi_value info) return info; } +bool JsTextInputClientEngine::IsTargetDeviceType(int32_t resDeviceType) +{ + if (deviceTypeCache_ != -1) { + if (deviceTypeCache_ == resDeviceType) { + return true; + } + return false; + } + std::shared_ptr context = + AbilityRuntime::ApplicationContext::GetApplicationContext(); + if (context == nullptr) { + return false; + } + auto resourceManager = context->GetResourceManager(); + auto resConfig = std::unique_ptr(Global::Resource::CreateResConfig()); + if (resourceManager == nullptr || resConfig == nullptr) { + return false; + } + resourceManager->GetResConfig(*resConfig); + + Global::Resource::DeviceType deviceType = resConfig->GetDeviceType(); + deviceTypeCache_ = static_cast(deviceType); + if (static_cast(deviceType) == resDeviceType) { + return true; + } + return false; +} + napi_value JsTextInputClientEngine::MoveCursor(napi_env env, napi_callback_info info) { auto ctxt = std::make_shared(); @@ -138,29 +179,55 @@ napi_value JsTextInputClientEngine::JsConstructor(napi_env env, napi_callback_in napi_value thisVar = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); - JsTextInputClientEngine *clientObject = new (std::nothrow) JsTextInputClientEngine(); - if (clientObject == nullptr) { + auto clientObject = GetTextInputClientEngine(); + if (clientObject == nullptr || !InitTextInputClientEngine()) { IMSA_HILOGE("clientObject is nullptr!"); napi_value result = nullptr; napi_get_null(env, &result); return result; } - auto finalize = [](napi_env env, void *data, void *hint) { - IMSA_HILOGD("finalize."); - auto *objInfo = reinterpret_cast(data); - if (objInfo != nullptr) { - delete objInfo; - } - }; - napi_status status = napi_wrap(env, thisVar, clientObject, finalize, nullptr, nullptr); + napi_status status = + napi_wrap(env, thisVar, clientObject.get(), [](napi_env env, void *data, void *hint) { }, nullptr, nullptr); if (status != napi_ok) { IMSA_HILOGE("failed to wrap: %{public}d!", status); - delete clientObject; return nullptr; } return thisVar; } +std::shared_ptr JsTextInputClientEngine::GetTextInputClientEngine() +{ + if (textInputClientEngine_ == nullptr) { + std::lock_guard lock(engineMutex_); + if (textInputClientEngine_ == nullptr) { + auto engine = std::make_shared(); + if (engine == nullptr) { + IMSA_HILOGE("create engine failed!"); + return nullptr; + } + textInputClientEngine_ = engine; + } + } + return textInputClientEngine_; +} + +bool JsTextInputClientEngine::InitTextInputClientEngine() +{ + if (!InputMethodAbility::GetInstance()->IsCurrentIme()) { + return false; + } + auto engine = GetTextInputClientEngine(); + if (engine == nullptr) { + return false; + } + InputMethodAbility::GetInstance()->SetTextInputClientListener(engine); + { + std::lock_guard lock(eventHandlerMutex_); + handler_ = AppExecFwk::EventHandler::Current(); + } + return true; +} + napi_value JsTextInputClientEngine::GetTextInputClientInstance(napi_env env) { napi_value instance = nullptr; @@ -906,6 +973,54 @@ napi_status JsTextInputClientEngine::GetPreviewTextParam( return napi_ok; } +void JsTextInputClientEngine::RegisterListener(napi_value callback, std::string type, + std::shared_ptr callbackObj) +{ + IMSA_HILOGD("register listener: %{public}s.", type.c_str()); + std::lock_guard lock(mutex_); + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + IMSA_HILOGD("methodName: %{public}s not registered!", type.c_str()); + } + auto callbacks = jsCbMap_[type]; + bool ret = std::any_of(callbacks.begin(), callbacks.end(), [&callback](std::shared_ptr cb) { + return JsUtils::Equals(cb->env_, callback, cb->callback_, cb->threadId_); + }); + if (ret) { + IMSA_HILOGD("JsTextInputClientEngine callback already registered!"); + return; + } + + IMSA_HILOGI("add %{public}s callbackObj into jsCbMap_.", type.c_str()); + jsCbMap_[type].push_back(std::move(callbackObj)); +} + +void JsTextInputClientEngine::UnRegisterListener(napi_value callback, std::string type) +{ + IMSA_HILOGI("unregister listener: %{public}s.", type.c_str()); + std::lock_guard lock(mutex_); + if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) { + IMSA_HILOGE("methodName: %{public}s already unregistered!", type.c_str()); + return; + } + + if (callback == nullptr) { + jsCbMap_.erase(type); + IMSA_HILOGE("callback is nullptr."); + return; + } + + for (auto item = jsCbMap_[type].begin(); item != jsCbMap_[type].end(); item++) { + if (JsUtils::Equals((*item)->env_, callback, (*item)->callback_, (*item)->threadId_)) { + jsCbMap_[type].erase(item); + break; + } + } + + if (jsCbMap_[type].empty()) { + jsCbMap_.erase(type); + } +} + napi_value JsRect::Write(napi_env env, const Rosen::Rect &nativeObject) { napi_value jsObject = nullptr; @@ -994,6 +1109,23 @@ bool JsInputAttribute::Read(napi_env env, napi_value jsObject, InputAttribute &n return ret; } +napi_value JsAttachOptions::Write(napi_env env, const AttachOptions &attachOptions) +{ + napi_value jsObject = nullptr; + napi_create_object(env, &jsObject); + bool ret = JsUtil::Object::WriteProperty( + env, jsObject, "requestKeyboardReason", static_cast(attachOptions.requestKeyboardReason)); + return ret ? jsObject : JsUtil::Const::Null(env); +} + +bool JsAttachOptions::Read(napi_env env, napi_value jsObject, AttachOptions &attachOptions) +{ + uint32_t requestKeyboardReason = static_cast(RequestKeyboardReason::NONE); + auto ret = JsUtil::Object::ReadProperty(env, jsObject, "requestKeyboardReason", requestKeyboardReason); + attachOptions.requestKeyboardReason = static_cast(requestKeyboardReason); + return ret; +} + napi_value JsTextInputClientEngine::SendMessage(napi_env env, napi_callback_info info) { auto ctxt = std::make_shared(); @@ -1082,6 +1214,145 @@ napi_value JsTextInputClientEngine::RecvMessage(napi_env env, napi_callback_info return result; } +void JsTextInputClientEngine::OnAttachOptionsChanged(const AttachOptions &attachOptions) +{ + IMSA_HILOGD("OnAttachOptionsChanged requestKeyboardReason:%{public}d.", attachOptions.requestKeyboardReason); + std::string type = "attachOptionsDidChange"; + auto entry = GetEntry(type, [&attachOptions](UvEntry &entry) { + entry.attachOptions.requestKeyboardReason = attachOptions.requestKeyboardReason; + }); + if (entry == nullptr) { + IMSA_HILOGE("failed to get uv entry!"); + return; + } + auto eventHandler = GetEventHandler(); + if (eventHandler == nullptr) { + IMSA_HILOGE("eventHandler is nullptr!"); + return; + } + auto task = [entry]() { + auto gitAttachOptionsParams = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc == 0) { + return false; + } + napi_value attachOptions = JsAttachOptions::Write(env, entry->attachOptions); + // 0 means the first param of callback. + args[0] = { attachOptions }; + return true; + }; + JsCallbackHandler::Traverse({ entry->vecCopy }, { 1, gitAttachOptionsParams }); + }; + eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::VIP); +} + +napi_value JsTextInputClientEngine::GetAttachOptions(napi_env env, napi_callback_info info) +{ + IMSA_HILOGD("GetAttachOptions requestKeyboardReason:%{public}d.", + InputMethodAbility::GetInstance()->GetRequestKeyboardReason()); + bool flag = IsTargetDeviceType(DEVICE_TYPE_2IN1); + if (!flag) { + JsUtils::ThrowException( + env, JsUtils::Convert(ErrorCode::ERROR_DEVICE_UNSUPPORTED), "", TYPE_NONE); + return JsUtil::Const::Null(env); + } + AttachOptions attachOptions; + attachOptions.requestKeyboardReason = InputMethodAbility::GetInstance()->GetRequestKeyboardReason(); + return JsAttachOptions::Write(env, attachOptions); +} + +napi_value JsTextInputClientEngine::Subscribe(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_TWO; + napi_value argv[ARGC_TWO] = { nullptr }; + napi_value thisVar = nullptr; + void *data = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)); + std::string type; + // 2 means least param num. + if (argc < ARGC_TWO || !JsUtil::GetValue(env, argv[0], type) || + !EventChecker::IsValidEventType(EventSubscribeModule::TEXT_INPUT_CLIENT, type) || + JsUtil::GetType(env, argv[1]) != napi_function) { + IMSA_HILOGE("subscribe failed, type: %{public}s.", type.c_str()); + return nullptr; + } + if (type == "attachOptionsDidChange" && !IsTargetDeviceType(DEVICE_TYPE_2IN1)) { + JsUtils::ThrowException( + env, JsUtils::Convert(ErrorCode::ERROR_DEVICE_UNSUPPORTED), "", TYPE_NONE); + return JsUtil::Const::Null(env); + } + IMSA_HILOGD("subscribe type:%{public}s.", type.c_str()); + auto engine = reinterpret_cast(JsUtils::GetNativeSelf(env, info)); + if (engine == nullptr) { + return nullptr; + } + std::shared_ptr callback = + std::make_shared(env, argv[ARGC_ONE], std::this_thread::get_id(), + AppExecFwk::EventHandler::Current()); + engine->RegisterListener(argv[ARGC_ONE], type, callback); + + napi_value result = nullptr; + napi_get_null(env, &result); + return result; +} + +napi_value JsTextInputClientEngine::UnSubscribe(napi_env env, napi_callback_info info) +{ + size_t argc = ARGC_TWO; + napi_value argv[ARGC_TWO] = { nullptr }; + napi_value thisVar = nullptr; + void *data = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)); + std::string type; + // 1 means least param num. + if (argc < ARGC_ONE || !JsUtil::GetValue(env, argv[0], type) || + !EventChecker::IsValidEventType(EventSubscribeModule::TEXT_INPUT_CLIENT, type)) { + IMSA_HILOGE("unsubscribe failed, type: %{public}s!", type.c_str()); + return nullptr; + } + // if the second param is not napi_function/napi_null/napi_undefined, return + auto paramType = JsUtil::GetType(env, argv[1]); + if (paramType != napi_function && paramType != napi_null && paramType != napi_undefined) { + return nullptr; + } + // if the second param is napi_function, delete it, else delete all + argv[1] = paramType == napi_function ? argv[1] : nullptr; + + IMSA_HILOGD("unsubscribe type: %{public}s.", type.c_str()); + auto setting = reinterpret_cast(JsUtils::GetNativeSelf(env, info)); + if (setting == nullptr) { + return nullptr; + } + setting->UnRegisterListener(argv[ARGC_ONE], type); + napi_value result = nullptr; + napi_get_null(env, &result); + return result; +} + +std::shared_ptr JsTextInputClientEngine::GetEventHandler() +{ + std::lock_guard lock(eventHandlerMutex_); + return handler_; +} + +std::shared_ptr JsTextInputClientEngine::GetEntry( + const std::string &type, EntrySetter entrySetter) +{ + IMSA_HILOGD("type: %{public}s.", type.c_str()); + std::shared_ptr entry = nullptr; + { + std::lock_guard lock(mutex_); + if (jsCbMap_[type].empty()) { + IMSA_HILOGD("%{public}s cb-vector is empty", type.c_str()); + return nullptr; + } + entry = std::make_shared(jsCbMap_[type], type); + } + if (entrySetter != nullptr) { + entrySetter(*entry); + } + return entry; +} + int32_t JsTextInputClientEngine::JsMessageHandler::OnTerminated() { std::lock_guard lock(callbackObjectMutex_); diff --git a/frameworks/js/napi/inputmethodability/js_text_input_client_engine.h b/frameworks/js/napi/inputmethodability/js_text_input_client_engine.h index 69a5ad5d54e24ac704ca20c5ba5bb8f1ca224c82..ac723f5cd5adfa2e7e3f1926474517fc01fc1d60 100644 --- a/frameworks/js/napi/inputmethodability/js_text_input_client_engine.h +++ b/frameworks/js/napi/inputmethodability/js_text_input_client_engine.h @@ -16,17 +16,21 @@ #define INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H #include +#include #include "async_call.h" #include "block_queue.h" #include "calling_window_info.h" #include "global.h" +#include "js_callback_object.h" #include "js_message_handler_info.h" #include "js_util.h" #include "msg_handler_callback_interface.h" #include "native_engine/native_engine.h" #include "native_engine/native_value.h" #include "wm_common.h" +#include "text_input_client_listener.h" +#include "input_method_utils.h" namespace OHOS { namespace MiscServices { @@ -59,6 +63,11 @@ struct JsInputAttribute { static bool Read(napi_env env, napi_value jsObject, InputAttribute &nativeObject); }; +struct JsAttachOptions { + static napi_value Write(napi_env env, const AttachOptions &attachOptions); + static bool Read(napi_env env, napi_value jsObject, AttachOptions &attachOptions); +}; + struct SendKeyFunctionContext : public AsyncCall::Context { bool isSendKeyFunction = false; int32_t action = 0; @@ -362,7 +371,7 @@ struct FinishTextPreviewContext : public AsyncCall::Context { } }; -class JsTextInputClientEngine { +class JsTextInputClientEngine : public TextInputClientListener { public: JsTextInputClientEngine() = default; ~JsTextInputClientEngine() = default; @@ -398,6 +407,10 @@ public: static napi_value FinishTextPreviewSync(napi_env env, napi_callback_info info); static napi_value SendMessage(napi_env env, napi_callback_info info); static napi_value RecvMessage(napi_env env, napi_callback_info info); + static napi_value GetAttachOptions(napi_env env, napi_callback_info info); + static napi_value Subscribe(napi_env env, napi_callback_info info); + static napi_value UnSubscribe(napi_env env, napi_callback_info info); + void OnAttachOptionsChanged(const AttachOptions &attachOptions) override; class JsMessageHandler : public MsgHandlerCallbackInterface { public: explicit JsMessageHandler(napi_env env, napi_value onTerminated, napi_value onMessage) @@ -415,12 +428,32 @@ private: static napi_status GetSelectMovement(napi_env env, napi_value argv, std::shared_ptr ctxt); static napi_value JsConstructor(napi_env env, napi_callback_info info); + static std::shared_ptr GetTextInputClientEngine(); + static bool InitTextInputClientEngine(); static napi_value GetResult(napi_env env, std::string &text); static napi_value GetResultEditorAttribute( napi_env env, std::shared_ptr getEditorAttribute); static napi_value HandleParamCheckFailure(napi_env env); static napi_status GetPreviewTextParam(napi_env env, size_t argc, napi_value *argv, std::string &text, Range &range); + static bool IsTargetDeviceType(int32_t resDeviceType); + void RegisterListener(napi_value callback, std::string type, std::shared_ptr callbackObj); + void UnRegisterListener(napi_value callback, std::string type); + + struct UvEntry { + std::vector> vecCopy; + std::string type; + AttachOptions attachOptions; + explicit UvEntry(const std::vector> &cbVec, const std::string &type) + : vecCopy(cbVec), type(type) + { + } + }; + using EntrySetter = std::function; + static std::shared_ptr GetEventHandler(); + std::shared_ptr GetEntry(const std::string &type, EntrySetter entrySetter = nullptr); + std::recursive_mutex mutex_; + std::map>> jsCbMap_; static const std::string TIC_CLASS_NAME; static thread_local napi_ref TICRef_; @@ -434,6 +467,11 @@ private: static uint32_t traceId_; static BlockQueue messageHandlerQueue_; + static std::mutex engineMutex_; + static std::shared_ptr textInputClientEngine_; + static std::mutex eventHandlerMutex_; + static std::shared_ptr handler_; + static int32_t deviceTypeCache_; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp b/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp index a57fd320707312c14b9d086e4cf3e660e2eec405..c83398306397ee33656cdc3c19ed55bdcfe2ca5c 100644 --- a/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp +++ b/frameworks/js/napi/inputmethodclient/js_get_input_method_controller.cpp @@ -408,7 +408,8 @@ napi_value JsGetInputMethodController::Subscribe(napi_env env, napi_callback_inf return nullptr; } std::shared_ptr callback = - std::make_shared(env, argv[ARGC_ONE], std::this_thread::get_id()); + std::make_shared(env, argv[ARGC_ONE], std::this_thread::get_id(), + AppExecFwk::EventHandler::Current()); engine->RegisterListener(argv[ARGC_ONE], type, callback); napi_value result = nullptr; diff --git a/frameworks/js/napi/inputmethodclient/js_get_input_method_setting.cpp b/frameworks/js/napi/inputmethodclient/js_get_input_method_setting.cpp index f2e9766b38959be8d3e15a83671e2bf4ed286d88..49a16a40c8ad0836a99c99a037dcc716fc9f72e3 100644 --- a/frameworks/js/napi/inputmethodclient/js_get_input_method_setting.cpp +++ b/frameworks/js/napi/inputmethodclient/js_get_input_method_setting.cpp @@ -499,7 +499,8 @@ napi_value JsGetInputMethodSetting::Subscribe(napi_env env, napi_callback_info i return nullptr; } std::shared_ptr callback = - std::make_shared(env, argv[ARGC_ONE], std::this_thread::get_id()); + std::make_shared(env, argv[ARGC_ONE], std::this_thread::get_id(), + AppExecFwk::EventHandler::Current()); auto ret = ImeEventMonitorManagerImpl::GetInstance().RegisterImeEventListener(iter->second, inputMethod_); if (ret == ErrorCode::NO_ERROR) { engine->RegisterListener(argv[ARGC_ONE], type, callback); diff --git a/frameworks/js/napi/inputmethodclient/js_utils.cpp b/frameworks/js/napi/inputmethodclient/js_utils.cpp index f7d149a68539e0a562cfe14365a1cd34fed468d5..57b022d0fd713ac34c04827e9977dd382886feeb 100644 --- a/frameworks/js/napi/inputmethodclient/js_utils.cpp +++ b/frameworks/js/napi/inputmethodclient/js_utils.cpp @@ -69,6 +69,7 @@ const std::map JsUtils::ERROR_CODE_MAP = { { ErrorCode::ERROR_INVALID_ARRAY_BUFFER_SIZE, EXCEPTION_PARAMCHECK }, { ErrorCode::ERROR_INVALID_PANEL_TYPE, EXCEPTION_INVALID_PANEL_TYPE_FLAG }, { ErrorCode::ERROR_INVALID_PANEL_FLAG, EXCEPTION_INVALID_PANEL_TYPE_FLAG }, + { ErrorCode::ERROR_DEVICE_UNSUPPORTED, EXCEPTION_UNSUPPORTED }, }; const std::map JsUtils::ERROR_CODE_CONVERT_MESSAGE_MAP = { diff --git a/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp b/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp index 8a8022588d3d6407bbf66620b7150c1bfb9b0544..45e35ed41566c6cb3f8d0cdbb8837dbdaee2d80c 100644 --- a/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp +++ b/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp @@ -105,7 +105,8 @@ napi_value JsKeyboardPanelManager::Subscribe(napi_env env, napi_callback_info in auto manager = JsKeyboardPanelManager::GetInstance(); IMSA_HILOGD("subscribe type: %{public}s.", type.c_str()); std::shared_ptr callback = - std::make_shared(env, argv[1], std::this_thread::get_id()); + std::make_shared(env, argv[1], std::this_thread::get_id(), + AppExecFwk::EventHandler::Current()); manager->RegisterListener(argv[1], type, callback); return JsUtil::Const::Null(env); } diff --git a/frameworks/native/inputmethod_ability/include/i_input_method_core.h b/frameworks/native/inputmethod_ability/include/i_input_method_core.h index fb035c53f44208370750219121696d928676f682..7d331a5dbeb25f2f64c38cdb6e8583a4655b797c 100644 --- a/frameworks/native/inputmethod_ability/include/i_input_method_core.h +++ b/frameworks/native/inputmethod_ability/include/i_input_method_core.h @@ -54,7 +54,7 @@ public: virtual int32_t StartInput(const InputClientInfo &clientInfo, bool isBindFromClient) = 0; virtual int32_t StopInput(const sptr &channel) = 0; - virtual int32_t ShowKeyboard() = 0; + virtual int32_t ShowKeyboard(int32_t requestKeyboardReason) = 0; virtual int32_t HideKeyboard() = 0; virtual int32_t InitInputControlChannel(const sptr &inputControlChannel) = 0; virtual int32_t StopInputService(bool isTerminateIme) = 0; diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index 7571510940130a7ca74a24b19391450bcb157ec8..507147831e2bd9e7b26e7c01aba0a51ed7297656 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -34,6 +34,8 @@ #include "iremote_object.h" #include "keyboard_listener.h" #include "keyevent_consumer_proxy.h" +#include "input_method_utils.h" +#include "text_input_client_listener.h" #include "msg_handler_callback_interface.h" #include "message.h" #include "message_handler.h" @@ -57,12 +59,13 @@ public: void SetImeListener(std::shared_ptr imeListener); std::shared_ptr GetImeListener(); void SetKdListener(std::shared_ptr kdListener); + void SetTextInputClientListener(std::shared_ptr textInputClientListener); int32_t DeleteForward(int32_t length); int32_t DeleteBackward(int32_t length); int32_t HideKeyboardSelf(); int32_t StartInput(const InputClientInfo &clientInfo, bool isBindFromClient); int32_t StopInput(const sptr &channelObject); - int32_t ShowKeyboard(); + int32_t ShowKeyboard(int32_t requestKeyboardReason); int32_t HideKeyboard(); int32_t SendExtendAction(int32_t action); int32_t GetTextBeforeCursor(int32_t number, std::u16string &text); @@ -101,6 +104,7 @@ public: int32_t NotifyPanelStatus(const std::shared_ptr &inputMethodPanel, SysPanelStatus &sysPanelStatus); InputAttribute GetInputAttribute(); + RequestKeyboardReason GetRequestKeyboardReason(); int32_t OnStopInputService(bool isTerminateIme); int32_t SendMessage(const ArrayBuffer &arrayBuffer); int32_t RecvMessage(const ArrayBuffer &arrayBuffer); @@ -123,6 +127,7 @@ private: std::shared_ptr imeListener_; std::shared_ptr kdListener_; + std::shared_ptr textInputClientListener_; static std::mutex instanceLock_; static sptr instance_; @@ -154,7 +159,7 @@ private: void OnCursorUpdate(Message *msg); void OnSelectionChange(Message *msg); void OnAttributeChange(Message *msg); - + bool IsInputClientAttachOptionsChanged(RequestKeyboardReason requestKeyboardReason); int32_t HideKeyboard(Trigger trigger); std::shared_ptr GetSoftKeyboardPanel(); /* param flag: ShowPanel is async, show/hide softkeyboard in alphabet keyboard attached, @@ -163,6 +168,8 @@ private: int32_t HidePanel(const std::shared_ptr &inputMethodPanel, PanelFlag flag, Trigger trigger); void SetInputAttribute(const InputAttribute &inputAttribute); void ClearInputAttribute(); + void SetRequestKeyboardReason(RequestKeyboardReason requestKeyboardReason); + void ClearRequestKeyboardReason(); void NotifyPanelStatusInfo(const PanelStatusInfo &info); int32_t HideKeyboardImplWithoutLock(int32_t cmdId); int32_t ShowKeyboardImplWithLock(int32_t cmdId); @@ -187,6 +194,8 @@ private: bool isDefaultIme_ = false; std::mutex inputAttrLock_; InputAttribute inputAttribute_{}; + std::mutex requestKeyboardReasonLock_; + RequestKeyboardReason requestKeyboardReason_ = RequestKeyboardReason::NONE; std::recursive_mutex keyboardCmdLock_; int32_t cmdId_ = 0; std::atomic isImeTerminating_ = false; diff --git a/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h b/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h index 1388fa968985ef24e72ee04e21b777570ba905b6..613e20ede1acf9403a6afbcc793489cbaf014e58 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h +++ b/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h @@ -35,7 +35,7 @@ public: int32_t StartInput(const InputClientInfo &clientInfo, bool isBindFromClient) override; int32_t StopInput(const sptr &channel) override; - int32_t ShowKeyboard() override; + int32_t ShowKeyboard(int32_t requestKeyboardReason) override; int32_t HideKeyboard() override; int32_t InitInputControlChannel(const sptr &inputControlChannel) override; int32_t StopInputService(bool isTerminateIme) override; diff --git a/frameworks/native/inputmethod_ability/include/input_method_core_stub.h b/frameworks/native/inputmethod_ability/include/input_method_core_stub.h index aaa8e78581d0323208a5f4e4e31d33f38d3a6f90..c451fe13f80d70a67a4f6b30b088751658931d95 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_core_stub.h +++ b/frameworks/native/inputmethod_ability/include/input_method_core_stub.h @@ -37,7 +37,7 @@ public: int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; int32_t StartInput(const InputClientInfo &clientInfo, bool isBindFromClient) override; int32_t StopInput(const sptr &channel) override; - int32_t ShowKeyboard() override; + int32_t ShowKeyboard(int32_t requestKeyboardReason) override; int32_t HideKeyboard() override; int32_t InitInputControlChannel(const sptr &inputControlChannel) override; int32_t StopInputService(bool isTerminateIme) override; diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index 0c6c1d64b82d238486468b398f7d5adf40502a5c..247ec248924abdf21113dc05fb981e6316e4d545 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -215,6 +215,14 @@ void InputMethodAbility::SetKdListener(std::shared_ptr kdListe } } +void InputMethodAbility::SetTextInputClientListener(std::shared_ptr textInputClientListener) +{ + IMSA_HILOGD("InputMethodAbility start."); + if (textInputClientListener_ == nullptr) { + textInputClientListener_ = std::move(textInputClientListener); + } +} + void InputMethodAbility::WorkThread() { prctl(PR_SET_NAME, "OS_IMAWorkThread start."); @@ -346,6 +354,7 @@ int32_t InputMethodAbility::StopInput(const sptr &channelObject) HideKeyboardImplWithoutLock(cmdCount); ClearDataChannel(channelObject); ClearInputAttribute(); + ClearRequestKeyboardReason(); if (imeListener_ != nullptr) { imeListener_->OnInputFinish(); } @@ -474,10 +483,11 @@ int32_t InputMethodAbility::HideKeyboardImplWithoutLock(int32_t cmdId) return HideKeyboard(Trigger::IMF); } -int32_t InputMethodAbility::ShowKeyboard() +int32_t InputMethodAbility::ShowKeyboard(int32_t requestKeyboardReason) { std::lock_guard lock(keyboardCmdLock_); int32_t cmdCount = ++cmdId_; + IsInputClientAttachOptionsChanged(static_cast(requestKeyboardReason)); return ShowKeyboardImplWithoutLock(cmdCount); } @@ -560,6 +570,7 @@ int32_t InputMethodAbility::InvokeStartInputCallback(const TextTotalConfig &text if (kdListener_ != nullptr) { kdListener_->OnEditorAttributeChange(textConfig.inputAttribute); } + IsInputClientAttachOptionsChanged(textConfig.requestKeyboardReason); if (TextConfig::IsPrivateCommandValid(textConfig.privateCommand) && IsDefaultIme()) { IMSA_HILOGI("notify privateCommand."); imeListener_->ReceivePrivateCommand(textConfig.privateCommand); @@ -594,6 +605,22 @@ int32_t InputMethodAbility::InvokeStartInputCallback(const TextTotalConfig &text return ErrorCode::NO_ERROR; } +bool InputMethodAbility::IsInputClientAttachOptionsChanged(RequestKeyboardReason requestKeyboardReason) +{ + IMSA_HILOGD("AttachOptionsChanged newReason:%{public}d, oldReason:%{public}d", requestKeyboardReason, + GetRequestKeyboardReason()); + if (requestKeyboardReason != GetRequestKeyboardReason()) { + SetRequestKeyboardReason(requestKeyboardReason); + if (textInputClientListener_ != nullptr) { + AttachOptions attachOptions; + attachOptions.requestKeyboardReason = requestKeyboardReason; + textInputClientListener_->OnAttachOptionsChanged(attachOptions); + return true; + } + } + return false; +} + int32_t InputMethodAbility::InsertText(const std::string text) { InputMethodSyncTrace tracer("IMA_InsertText"); @@ -933,7 +960,7 @@ int32_t InputMethodAbility::CreatePanel(const std::shared_ptr(RequestKeyboardReason::NONE)); isPendingShowKeyboard_ = false; } return flag ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL; @@ -1059,6 +1086,24 @@ InputAttribute InputMethodAbility::GetInputAttribute() return inputAttribute_; } +void InputMethodAbility::SetRequestKeyboardReason(RequestKeyboardReason requestKeyboardReason) +{ + std::lock_guard lock(requestKeyboardReasonLock_); + requestKeyboardReason_ = requestKeyboardReason; +} + +void InputMethodAbility::ClearRequestKeyboardReason() +{ + std::lock_guard lock(requestKeyboardReasonLock_); + requestKeyboardReason_ = RequestKeyboardReason::NONE; +} + +RequestKeyboardReason InputMethodAbility::GetRequestKeyboardReason() +{ + std::lock_guard lock(requestKeyboardReasonLock_); + return requestKeyboardReason_; +} + int32_t InputMethodAbility::HideKeyboard(Trigger trigger) { InputMethodSyncTrace tracer("IMA_HideKeyboard"); @@ -1248,6 +1293,7 @@ void InputMethodAbility::OnClientInactive(const sptr &channel) return false; }); ClearDataChannel(channel); + ClearRequestKeyboardReason(); } void InputMethodAbility::NotifyKeyboardHeight(uint32_t panelHeight, PanelFlag panelFlag) diff --git a/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp b/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp index c335b20f343c9a2f62f8923e69db0f56b8de41d3..4ea77a832affcfdd43b7ba4de055e1fd0b444136 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp @@ -66,9 +66,11 @@ int32_t InputMethodCoreProxy::StopInputService(bool isTerminateIme) [isTerminateIme](MessageParcel &data) { return ITypesUtil::Marshal(data, isTerminateIme); }); } -int32_t InputMethodCoreProxy::ShowKeyboard() +int32_t InputMethodCoreProxy::ShowKeyboard(int32_t requestKeyboardReason) { - return SendRequest(SHOW_KEYBOARD); + return SendRequest(SHOW_KEYBOARD, [requestKeyboardReason](MessageParcel &data) { + return ITypesUtil::Marshal(data, requestKeyboardReason); + }); } int32_t InputMethodCoreProxy::HideKeyboard() diff --git a/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp b/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp index 6e5fc7661af096622ccc5fbcad1b6088599aac73..6a7d43b9e0097c8c94e5897e8b03e6ac9e8aafba 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp @@ -64,9 +64,9 @@ int32_t InputMethodCoreStub::InitInputControlChannel(const sptrShowKeyboard(); + return InputMethodAbility::GetInstance()->ShowKeyboard(requestKeyboardReason); } int32_t InputMethodCoreStub::HideKeyboard() @@ -173,7 +173,12 @@ int32_t InputMethodCoreStub::IsEnableOnRemote(MessageParcel &data, MessageParcel int32_t InputMethodCoreStub::ShowKeyboardOnRemote(MessageParcel &data, MessageParcel &reply) { - auto ret = ShowKeyboard(); + int32_t requestKeyboardReason = static_cast(RequestKeyboardReason::NONE); + if (!ITypesUtil::Unmarshal(data, requestKeyboardReason)) { + IMSA_HILOGE("Unmarshal failed!"); + return ErrorCode::ERROR_EX_PARCELABLE; + } + auto ret = ShowKeyboard(requestKeyboardReason); return ITypesUtil::Marshal(reply, ret) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; } diff --git a/frameworks/native/inputmethod_controller/include/input_method_utils.h b/frameworks/native/inputmethod_controller/include/input_method_utils.h index 8d70359df5170572914df00e925d5a4257df2c7f..5ef9f8d97addc26e278717c6fa12779b8788ca4d 100644 --- a/frameworks/native/inputmethod_controller/include/input_method_utils.h +++ b/frameworks/native/inputmethod_controller/include/input_method_utils.h @@ -193,6 +193,13 @@ struct TextSelection { enum PrivateDataValueType : int32_t { VALUE_TYPE_STRING = 0, VALUE_TYPE_BOOL, VALUE_TYPE_NUMBER }; using PrivateDataValue = std::variant; +enum class RequestKeyboardReason : int32_t { + NONE = 0, // no event reason + MOUSE = 1, // user triggered mouse event + TOUCH = 2, // user triggered touch event + OTHER = 20 // other reason +}; + struct TextTotalConfig { public: InputAttribute inputAttribute = {}; @@ -202,6 +209,7 @@ public: double positionY = 0; double height = 0; std::unordered_map privateCommand = {}; + RequestKeyboardReason requestKeyboardReason = RequestKeyboardReason::NONE; std::string ToString() const { @@ -306,13 +314,6 @@ enum class InputType : int32_t { NONE = -1, CAMERA_INPUT = 0, SECURITY_INPUT, VO enum class SwitchTrigger : uint32_t { CURRENT_IME = 0, SYSTEM_APP, IMSA, NATIVE_SA}; -enum class RequestKeyboardReason : int32_t { - NONE = 0, // no event reason - MOUSE = 1, // user triggered mouse event - TOUCH = 2, // user triggered touch event - OTHER = 20 // other reason -}; - struct AttachOptions { bool isShowKeyboard = false; RequestKeyboardReason requestKeyboardReason { RequestKeyboardReason::NONE }; diff --git a/interfaces/inner_api/inputmethod_ability/include/text_input_client_listener.h b/interfaces/inner_api/inputmethod_ability/include/text_input_client_listener.h new file mode 100644 index 0000000000000000000000000000000000000000..e353b9d315d5f7a51b1a44230084bb8876efb82e --- /dev/null +++ b/interfaces/inner_api/inputmethod_ability/include/text_input_client_listener.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2025 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. + */ + +#ifndef INPUTMETHOD_IMF_TEXT_INPUT_CLIENT_LISTENER_H +#define INPUTMETHOD_IMF_TEXT_INPUT_CLIENT_LISTENER_H + +namespace OHOS { +namespace MiscServices { +class TextInputClientListener { +public: + virtual ~TextInputClientListener() = default; + virtual void OnAttachOptionsChanged(const AttachOptions &attachOptions) = 0; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // INPUTMETHOD_IMF_TEXT_INPUT_CLIENT_LISTENER_H diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 1df02501253337e1efd9f7ec4d31320f08f2fc06..0f1b71e74c97ae7e4c1849c6826d5e057566671f 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -219,7 +219,9 @@ int32_t PerUserSession::ShowKeyboard(const sptr ¤tClient, in IMSA_HILOGE("ime: %{public}d is not exist!", clientInfo->bindImeType); return ErrorCode::ERROR_IME_NOT_STARTED; } - auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); }); + auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data, requestKeyboardReason] { + return data->core->ShowKeyboard(requestKeyboardReason); + }); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret); return ErrorCode::ERROR_KBD_SHOW_FAILED; @@ -389,7 +391,9 @@ int32_t PerUserSession::OnRequestShowInput() IMSA_HILOGE("ime: %{public}d doesn't exist!", ImeType::IME); return ErrorCode::ERROR_IME_NOT_STARTED; } - auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { return data->core->ShowKeyboard(); }); + auto ret = RequestIme(data, RequestType::REQUEST_SHOW, [&data] { + return data->core->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); + }); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to show keyboard, ret: %{public}d!", ret); return ErrorCode::ERROR_KBD_SHOW_FAILED; @@ -569,7 +573,9 @@ int32_t PerUserSession::OnStartInput(const InputClientInfo &inputClientInfo, spt infoTemp.isNotifyInputStart = inputClientInfo.isNotifyInputStart; infoTemp.needHide = inputClientInfo.needHide; infoTemp.requestKeyboardReason = inputClientInfo.requestKeyboardReason; + auto imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME; + infoTemp.config.requestKeyboardReason = inputClientInfo.requestKeyboardReason; int32_t ret = BindClientWithIme(std::make_shared(infoTemp), imeType, true); if (ret != ErrorCode::NO_ERROR) { IMSA_HILOGE("bind failed, ret: %{public}d!", ret); diff --git a/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp b/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp index 7d0214378d52b2a88250b7eeefc58abf66629e95..8571ecb3420d012401df736b700f1afa5ce16d90 100644 --- a/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp +++ b/test/unittest/cpp_test/src/input_method_ability_exception_test.cpp @@ -249,7 +249,7 @@ HWTEST_F(InputMethodAbilityExceptionTest, testShowKeyboard_001, TestSize.Level0) { IMSA_HILOGI("InputMethodAbilityExceptionTest testShowKeyboard_001 START"); // channelObject == nullptr - auto ret = inputMethodAbility_->ShowKeyboard(); + auto ret = inputMethodAbility_->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); EXPECT_EQ(ret, ErrorCode::ERROR_IME); ResetMemberVar(); @@ -266,7 +266,7 @@ HWTEST_F(InputMethodAbilityExceptionTest, testShowKeyboard_002, TestSize.Level0) { IMSA_HILOGI("InputMethodAbilityExceptionTest testShowKeyboard_002 START"); // imeListener_ == nullptr - auto ret = inputMethodAbility_->ShowKeyboard(); + auto ret = inputMethodAbility_->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); EXPECT_EQ(ret, ErrorCode::ERROR_IME); auto imeListener = std::make_shared(); @@ -278,11 +278,11 @@ HWTEST_F(InputMethodAbilityExceptionTest, testShowKeyboard_002, TestSize.Level0) panel->panelFlag_ = FLG_CANDIDATE_COLUMN; panel->windowId_ = 2; inputMethodAbility_->panels_.Insert(SOFT_KEYBOARD, panel); - ret = inputMethodAbility_->ShowKeyboard(); + ret = inputMethodAbility_->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); EXPECT_EQ(ret, ErrorCode::NO_ERROR); // panel not exist inputMethodAbility_->panels_.Clear(); - ret = inputMethodAbility_->ShowKeyboard(); + ret = inputMethodAbility_->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); EXPECT_EQ(ret, ErrorCode::NO_ERROR); ResetMemberVar(); diff --git a/test/unittest/cpp_test/src/input_method_ability_test.cpp b/test/unittest/cpp_test/src/input_method_ability_test.cpp index 1189d07a17c40751888698b422be536ca01c3f34..d0269fe5c56710c59744d728ac1169a53c3f566c 100644 --- a/test/unittest/cpp_test/src/input_method_ability_test.cpp +++ b/test/unittest/cpp_test/src/input_method_ability_test.cpp @@ -297,7 +297,7 @@ HWTEST_F(InputMethodAbilityTest, testShowKeyboardInputMethodCoreProxy, TestSize. sptr coreProxy = new InputMethodCoreProxy(coreObject); sptr channelProxy = new InputDataChannelProxy(channelObject); - auto ret = coreProxy->ShowKeyboard(); + auto ret = coreProxy->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); EXPECT_EQ(ret, ErrorCode::ERROR_IME); delete msgHandler; } @@ -311,7 +311,7 @@ HWTEST_F(InputMethodAbilityTest, testShowKeyboardInputMethodCoreProxy, TestSize. HWTEST_F(InputMethodAbilityTest, testShowKeyboardWithoutImeListener, TestSize.Level0) { IMSA_HILOGI("InputMethodAbilityTest testShowKeyboardWithoutImeListener start."); - auto ret = inputMethodAbility_->ShowKeyboard(); + auto ret = inputMethodAbility_->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); EXPECT_EQ(ret, ErrorCode::ERROR_IME); } @@ -831,7 +831,7 @@ HWTEST_F(InputMethodAbilityTest, testNotifyPanelStatusInfo_001, TestSize.Level0) EXPECT_EQ(ret, ErrorCode::NO_ERROR); TextListener::ResetParam(); - ret = inputMethodAbility_->ShowKeyboard(); + ret = inputMethodAbility_->ShowKeyboard(static_cast(RequestKeyboardReason::NONE)); EXPECT_EQ(ret, ErrorCode::NO_ERROR); EXPECT_TRUE(TextListener::WaitSendKeyboardStatusCallback(KeyboardStatus::SHOW)); EXPECT_TRUE(TextListener::WaitNotifyPanelStatusInfoCallback({ info1, true, Trigger::IMF }));