From 4ec234ce79e797e3532a6262e08edc1afcfdaded Mon Sep 17 00:00:00 2001 From: guojin31 Date: Thu, 25 Apr 2024 08:54:49 +0800 Subject: [PATCH] add keyboardpanelmanager Signed-off-by: guojin31 --- BUILD.gn | 1 + bundle.json | 5 +- frameworks/js/napi/common/event_checker.cpp | 3 +- frameworks/js/napi/common/event_checker.h | 1 + .../js/napi/keyboardpanelmanager/BUILD.gn | 67 ++++ .../js_keyboard_panel_manager.cpp | 314 ++++++++++++++++++ .../js_keyboard_panel_manager.h | 109 ++++++ .../keyboard_panel_manager_module.cpp | 44 +++ .../include/ime_system_channel.h | 27 +- .../src/ime_system_channel.cpp | 52 ++- .../inner_api/inputmethod_controller/BUILD.gn | 4 + 11 files changed, 602 insertions(+), 25 deletions(-) create mode 100644 frameworks/js/napi/keyboardpanelmanager/BUILD.gn create mode 100644 frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp create mode 100644 frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.h create mode 100644 frameworks/js/napi/keyboardpanelmanager/keyboard_panel_manager_module.cpp rename {interfaces/inner_api => frameworks/native}/inputmethod_controller/include/ime_system_channel.h (84%) diff --git a/BUILD.gn b/BUILD.gn index 9fdd1213..90512289 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -24,6 +24,7 @@ group("imf_packages") { "frameworks/js/napi/inputmethodability:inputmethodengine", "frameworks/js/napi/inputmethodclient:inputmethod", "frameworks/js/napi/inputmethodlist:inputmethodlist", + "frameworks/js/napi/keyboardpanelmanager:keyboardpanelmanager", "interfaces/inner_api/inputmethod_ability:inputmethod_ability", "interfaces/inner_api/inputmethod_controller:inputmethod_client", "profile:inputmethod_inputmethod_sa_profiles", diff --git a/bundle.json b/bundle.json index 9d401dae..fb0d1e20 100644 --- a/bundle.json +++ b/bundle.json @@ -75,7 +75,8 @@ "//base/inputmethod/imf/frameworks/kits/extension:inputmethod_extension_module", "//base/inputmethod/imf/frameworks/js/napi/inputmethodability:inputmethodengine", "//base/inputmethod/imf/frameworks/js/napi/inputmethod_extension_ability:inputmethodextensionability_napi", - "//base/inputmethod/imf/frameworks/js/napi/inputmethod_extension_context:inputmethodextensioncontext_napi" + "//base/inputmethod/imf/frameworks/js/napi/inputmethod_extension_context:inputmethodextensioncontext_napi", + "//base/inputmethod/imf/frameworks/js/napi/keyboardpanelmanager:keyboardpanelmanager" ] }, "inner_api": [ @@ -88,10 +89,8 @@ "../../../../frameworks/native/inputmethod_controller/include/input_method_property.h", "../../../../frameworks/native/inputmethod_controller/include/input_method_utils.h", "../../../../frameworks/native/inputmethod_controller/include/input_window_info.h", - "../../../../frameworks/native/inputmethod_controller/include/i_system_cmd_channel.h", "ime_event_listener.h", "ime_event_monitor_manager.h", - "ime_system_channel.h", "input_method_controller.h" ], "header_base": "//base/inputmethod/imf/interfaces/inner_api/inputmethod_controller/include" diff --git a/frameworks/js/napi/common/event_checker.cpp b/frameworks/js/napi/common/event_checker.cpp index 00161cb7..aac77c5e 100644 --- a/frameworks/js/napi/common/event_checker.cpp +++ b/frameworks/js/napi/common/event_checker.cpp @@ -28,7 +28,8 @@ const std::unordered_map> "securityModeChange", "privateCommand" } }, { EventSubscribeModule::KEYBOARD_DELEGATE, { "editorAttributeChanged", "keyDown", "keyUp", "keyEvent", "cursorContextChange", "selectionChange", "textChange" } }, - { EventSubscribeModule::PANEL, { "show", "hide" } } + { EventSubscribeModule::PANEL, { "show", "hide" } }, + { EventSubscribeModule::KEYBOARD_PANEL_MANAGER, { "panelPrivateCommand", "isPanelShow" } } }; 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 f5ebbbd9..bee76cdd 100644 --- a/frameworks/js/napi/common/event_checker.h +++ b/frameworks/js/napi/common/event_checker.h @@ -26,6 +26,7 @@ enum class EventSubscribeModule : uint32_t { INPUT_METHOD_SETTING, INPUT_METHOD_ABILITY, KEYBOARD_DELEGATE, + KEYBOARD_PANEL_MANAGER, PANEL, }; class EventChecker { diff --git a/frameworks/js/napi/keyboardpanelmanager/BUILD.gn b/frameworks/js/napi/keyboardpanelmanager/BUILD.gn new file mode 100644 index 00000000..81e30e81 --- /dev/null +++ b/frameworks/js/napi/keyboardpanelmanager/BUILD.gn @@ -0,0 +1,67 @@ +# Copyright (C) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//base/inputmethod/imf/inputmethod.gni") +import("//build/ohos.gni") + +config("keyboard_panel_manager_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +config("keyboard_panel_manager_public_config") { + visibility = [ "./*" ] + include_dirs = [ + "include", + "${inputmethod_path}/common", + "${inputmethod_path}/frameworks/common", + "${inputmethod_path}/frameworks/js/napi/inputmethodclient", + ] +} + +ohos_shared_library("keyboardpanelmanager") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ + "${inputmethod_path}/frameworks/js/napi/inputmethodclient/async_call.cpp", + "${inputmethod_path}/frameworks/js/napi/inputmethodclient/js_utils.cpp", + "js_keyboard_panel_manager.cpp", + "keyboard_panel_manager_module.cpp", + ] + + configs = [ ":keyboard_panel_manager_config" ] + + deps = [ + "${inputmethod_path}/frameworks/js/napi/common:inputmethod_js_common", + "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:inputmethod_client", + ] + + external_deps = [ + "ability_runtime:abilitykit_native", + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "input:libmmi-client", + "napi:ace_napi", + ] + + public_configs = [ ":keyboard_panel_manager_public_config" ] + + relative_install_dir = "module" + subsystem_name = "inputmethod" + part_name = "imf" +} diff --git a/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp b/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp new file mode 100644 index 00000000..04d6ce9f --- /dev/null +++ b/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_keyboard_panel_manager.h" + +#include "event_checker.h" +#include "input_method_utils.h" +#include "js_callback_handler.h" +#include "js_util.h" +#include "js_utils.h" + +namespace OHOS { +namespace MiscServices { +constexpr int32_t MAX_WAIT_TIME_PRIVATE_COMMAND = 2000; +BlockQueue JsKeyboardPanelManager::privateCommandQueue_{ MAX_WAIT_TIME_PRIVATE_COMMAND }; +std::mutex JsKeyboardPanelManager::managerMutex_; +sptr JsKeyboardPanelManager::keyboardPanelManager_{ nullptr }; + +JsKeyboardPanelManager::JsKeyboardPanelManager() +{ + std::lock_guard lock(eventHandlerMutex_); + handler_ = AppExecFwk::EventHandler::Current(); +} + +napi_value JsKeyboardPanelManager::Init(napi_env env, napi_value info) +{ + napi_property_descriptor descriptor[] = { + DECLARE_NAPI_FUNCTION("sendPrivateCommand", SendPrivateCommand), + DECLARE_NAPI_FUNCTION("getSmartMenuCfg", GetSmartMenuCfg), + DECLARE_NAPI_FUNCTION("on", Subscribe), + DECLARE_NAPI_FUNCTION("off", UnSubscribe), + }; + NAPI_CALL( + env, napi_define_properties(env, info, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor)); + return info; +} + +sptr JsKeyboardPanelManager::GetInstance() +{ + if (keyboardPanelManager_ == nullptr) { + std::lock_guard lock(managerMutex_); + if (keyboardPanelManager_ == nullptr) { + keyboardPanelManager_ = new (std::nothrow) JsKeyboardPanelManager(); + } + } + return keyboardPanelManager_; +} + +napi_value JsKeyboardPanelManager::Subscribe(napi_env env, napi_callback_info info) +{ + size_t argc = 2; // has 2 param + napi_value argv[2] = { 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 < 2 || !JsUtil::GetValue(env, argv[0], type) + || !EventChecker::IsValidEventType(EventSubscribeModule::KEYBOARD_PANEL_MANAGER, type) + || JsUtil::GetType(env, argv[1]) != napi_function) { + IMSA_HILOGE("Subscribe failed, type:%{public}s", type.c_str()); + return nullptr; + } + auto manager = JsKeyboardPanelManager::GetInstance(); + auto ret = ImeSystemCmdChannel::GetInstance()->ConnectSystemCmd(manager); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("Subscribe failed, type:%{public}s", type.c_str()); + return nullptr; + } + IMSA_HILOGD("Subscribe type:%{public}s.", type.c_str()); + std::shared_ptr callback = + std::make_shared(env, argv[1], std::this_thread::get_id()); + manager->RegisterListener(argv[1], type, callback); + return JsUtil::Const::Null(env); +} + +napi_value JsKeyboardPanelManager::UnSubscribe(napi_env env, napi_callback_info info) +{ + size_t argc = 2; // has 2 param + napi_value argv[2] = { 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 < 1 || !JsUtil::GetValue(env, argv[0], type) + || !EventChecker::IsValidEventType(EventSubscribeModule::KEYBOARD_PANEL_MANAGER, type)) { + IMSA_HILOGE("UnSubscribe failed, type:%{public}s", type.c_str()); + return nullptr; + } + auto manager = JsKeyboardPanelManager::GetInstance(); + auto ret = ImeSystemCmdChannel::GetInstance()->ConnectSystemCmd(manager); + if (ret != ErrorCode::NO_ERROR) { + 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()); + manager->UnRegisterListener(argv[1], type); + return JsUtil::Const::Null(env); +} + +void JsKeyboardPanelManager::RegisterListener( + napi_value callback, std::string type, std::shared_ptr callbackObj) +{ + IMSA_HILOGD("RegisterListener %{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("JsKeyboardPanelManagerListener callback already registered!"); + return; + } + + IMSA_HILOGI("Add %{public}s callbackObj into jsCbMap_", type.c_str()); + jsCbMap_[type].push_back(std::move(callbackObj)); +} + +void JsKeyboardPanelManager::UnRegisterListener(napi_value callback, std::string type) +{ + IMSA_HILOGI("event: %{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_HILOGI("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 JsKeyboardPanelManager::GetSmartMenuCfg(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { + *result = JsUtil::GetValue(env, ctxt->smartMenu); + return napi_ok; + }; + auto exec = [ctxt](AsyncCall::Context *ctx) { + ctxt->smartMenu = ImeSystemCmdChannel::GetInstance()->GetSmartMenuCfg(); + ctxt->SetState(napi_ok); + }; + ctxt->SetAction(nullptr, std::move(output)); + // 1 means JsAPI:displayOptionalInputMethod has 1 params at most. + AsyncCall asyncCall(env, info, ctxt, 1); + return asyncCall.Call(env, exec, "GetSmartMenuCfg"); +} + + +napi_value JsKeyboardPanelManager::SendPrivateCommand(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + PARAM_CHECK_RETURN(env, argc > 0, "should 1 parameter!", TYPE_NONE, napi_generic_failure); + CHECK_RETURN(JsUtils::GetValue(env, argv[0], ctxt->privateCommand) == napi_ok, + "GetValue privateCommand error", napi_generic_failure); + if (!TextConfig::IsPrivateCommandValid(ctxt->privateCommand)) { + PARAM_CHECK_RETURN( + env, false, "privateCommand size limit 32KB, count limit 5.", TYPE_NONE, napi_generic_failure); + } + ctxt->info = { std::chrono::system_clock::now(), ctxt->privateCommand }; + privateCommandQueue_.Push(ctxt->info); + return napi_ok; + }; + auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { return napi_ok; }; + auto exec = [ctxt](AsyncCall::Context *ctx) { + privateCommandQueue_.Wait(ctxt->info); + int32_t code = ImeSystemCmdChannel::GetInstance()->SendPrivateCommand(ctxt->privateCommand); + privateCommandQueue_.Pop(); + if (code == ErrorCode::NO_ERROR) { + ctxt->SetState(napi_ok); + } else { + ctxt->SetErrorCode(code); + } + }; + ctxt->SetAction(std::move(input), std::move(output)); + // 1 means JsAPI:SendPrivateCommand has 1 params at most. + AsyncCall asyncCall(env, info, ctxt, 1); + return asyncCall.Call(env, exec, "SendPrivateCommand"); +} + +void JsKeyboardPanelManager::ReceivePrivateCommand( + const std::unordered_map &privateCommand) +{ + IMSA_HILOGD("JsKeyboardPanelManager, run in"); + std::string type = "panelPrivateCommand"; + auto entry = GetEntry(type, [&privateCommand](UvEntry &entry) { entry.privateCommand = privateCommand; }); + if (entry == nullptr) { + return; + } + auto eventHandler = GetEventHandler(); + if (eventHandler == nullptr) { + IMSA_HILOGE("eventHandler is nullptr!"); + return; + } + auto task = [entry]() { + auto paramGetter = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc < 1) { + return false; + } + napi_value jsObject = JsUtils::GetJsPrivateCommand(env, entry->privateCommand); + if (jsObject == nullptr) { + IMSA_HILOGE("GetJsPrivateCommand failed: jsObject is nullptr"); + return false; + } + // 0 means the first param of callback. + args[0] = { jsObject }; + return true; + }; + // 1 means callback has 1 params. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, paramGetter }); + }; + eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE); +} + +void JsKeyboardPanelManager::NotifyIsShowSysPanel(bool shouldSysPanelShow) +{ + IMSA_HILOGD("JsKeyboardPanelManager, run in"); + std::string type = "isPanelShow"; + auto entry = + GetEntry(type, [shouldSysPanelShow](UvEntry &entry) { entry.shouldSysPanelShow = shouldSysPanelShow; }); + if (entry == nullptr) { + return; + } + auto eventHandler = GetEventHandler(); + if (eventHandler == nullptr) { + IMSA_HILOGE("eventHandler is nullptr!"); + return; + } + auto task = [entry]() { + auto paramGetter = [entry](napi_env env, napi_value *args, uint8_t argc) -> bool { + if (argc < 1) { + return false; + } + napi_value jsObject = JsUtil::GetValue(env, entry->shouldSysPanelShow); + args[0] = { jsObject }; + return true; + }; + // 1 means callback has 1 params. + JsCallbackHandler::Traverse(entry->vecCopy, { 1, paramGetter }); + }; + eventHandler->PostTask(task, type, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE); +} + +std::shared_ptr JsKeyboardPanelManager::GetEventHandler() +{ + if (handler_ != nullptr) { + return handler_; + } + std::lock_guard lock(eventHandlerMutex_); + if (handler_ == nullptr) { + handler_ = AppExecFwk::EventHandler::Current(); + } + return handler_; +} + +std::shared_ptr JsKeyboardPanelManager::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; +} +} // namespace MiscServices +} // namespace OHOS diff --git a/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.h b/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.h new file mode 100644 index 00000000..45de8e44 --- /dev/null +++ b/frameworks/js/napi/keyboardpanelmanager/js_keyboard_panel_manager.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_JS_NAPI_JS_KEYBOARD_PANEL_MANAGER_H +#define FRAMEWORKS_JS_NAPI_JS_KEYBOARD_PANEL_MANAGER_H + +#include "async_call.h" +#include "block_queue.h" +#include "event_handler.h" +#include "js_callback_object.h" +#include "ime_system_channel.h" + +namespace OHOS { +namespace MiscServices { +struct PrivateCommandInfo { + std::chrono::system_clock::time_point timestamp{}; + std::unordered_map privateCommand; + bool operator==(const PrivateCommandInfo &info) const + { + return (timestamp == info.timestamp && privateCommand == info.privateCommand); + } +}; + +struct SendPrivateCommandContext : public AsyncCall::Context { + std::unordered_map privateCommand; + PrivateCommandInfo info; + SendPrivateCommandContext() : Context(nullptr, nullptr){}; + + napi_status operator()(napi_env env, napi_value *result) override + { + if (status_ != napi_ok) { + output_ = nullptr; + return status_; + } + return Context::operator()(env, result); + } +}; + +struct SmartMenuContext : public AsyncCall::Context { + std::string smartMenu; + SmartMenuContext() : Context(nullptr, nullptr){}; + + napi_status operator()(napi_env env, napi_value *result) override + { + if (status_ != napi_ok) { + output_ = nullptr; + return status_; + } + return Context::operator()(env, result); + } +}; + +class JsKeyboardPanelManager : public OnSystemCmdListener { +public: + JsKeyboardPanelManager(); + ~JsKeyboardPanelManager() = default; + + static napi_value Init(napi_env env, napi_value info); + static sptr GetInstance(); + static napi_value SendPrivateCommand(napi_env env, napi_callback_info info); + static napi_value GetSmartMenuCfg(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 ReceivePrivateCommand(const std::unordered_map &privateCommand) override; + void NotifyIsShowSysPanel(bool shouldSysPanelShow) override; + +private: + 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; + bool shouldSysPanelShow; + std::string smartMenu; + std::unordered_map privateCommand; + explicit UvEntry(const std::vector> &cbVec, const std::string &type) + : vecCopy(cbVec), type(type) + { + } + }; + using EntrySetter = std::function; + std::shared_ptr GetEventHandler(); + std::shared_ptr GetEntry(const std::string &type, EntrySetter entrySetter = nullptr); + + std::recursive_mutex mutex_; + std::map>> jsCbMap_; + std::mutex eventHandlerMutex_; + std::shared_ptr handler_; + static std::mutex managerMutex_; + static sptr keyboardPanelManager_; + static BlockQueue privateCommandQueue_; +}; +} // namespace MiscServices +} // namespace OHOS +#endif // FRAMEWORKS_JS_NAPI_JS_KEYBOARD_PANEL_MANAGER_H \ No newline at end of file diff --git a/frameworks/js/napi/keyboardpanelmanager/keyboard_panel_manager_module.cpp b/frameworks/js/napi/keyboardpanelmanager/keyboard_panel_manager_module.cpp new file mode 100644 index 00000000..3e0d175c --- /dev/null +++ b/frameworks/js/napi/keyboardpanelmanager/keyboard_panel_manager_module.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_keyboard_panel_manager.h" + +EXTERN_C_START +/* + * function for module exports + */ +static napi_value Init(napi_env env, napi_value exports) +{ + OHOS::MiscServices::JsKeyboardPanelManager::Init(env, exports); + return exports; +} +EXTERN_C_END +/* + * module define + */ +static napi_module _module = { .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "keyboardPanelManager", + .nm_priv = ((void *)0), + .reserved = { 0 } }; +/* + * module register + */ +extern "C" __attribute__((constructor)) void Register() +{ + napi_module_register(&_module); +} \ No newline at end of file diff --git a/interfaces/inner_api/inputmethod_controller/include/ime_system_channel.h b/frameworks/native/inputmethod_controller/include/ime_system_channel.h similarity index 84% rename from interfaces/inner_api/inputmethod_controller/include/ime_system_channel.h rename to frameworks/native/inputmethod_controller/include/ime_system_channel.h index dcff6716..ce9e6705 100644 --- a/interfaces/inner_api/inputmethod_controller/include/ime_system_channel.h +++ b/frameworks/native/inputmethod_controller/include/ime_system_channel.h @@ -13,10 +13,10 @@ * limitations under the License. */ -#ifndef FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_IME_SYSTEM_CHANNEL_H -#define FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_IME_SYSTEM_CHANNEL_H +#ifndef INPUTMETHOD_CONTROLLER_IME_SYSTEM_CHANNEL_H +#define INPUTMETHOD_CONTROLLER_IME_SYSTEM_CHANNEL_H -#include "global.h" +#include "bundle_mgr_client.h" #include "i_input_method_agent.h" #include "i_input_method_system_ability.h" #include "input_method_utils.h" @@ -28,11 +28,11 @@ namespace OHOS { namespace MiscServices { +using namespace OHOS::AppExecFwk; class OnSystemCmdListener : public virtual RefBase { public: - virtual int32_t ReceivePrivateCommand(const std::unordered_map &privateCommand) + virtual void ReceivePrivateCommand(const std::unordered_map &privateCommand) { - return ErrorCode::NO_ERROR; } virtual void NotifyIsShowSysPanel(bool shouldSysPanelShow) { @@ -49,7 +49,7 @@ public: * @return The instance of ImeSystemCmdChannel. * @since 12 */ - IMF_API static sptr GetInstance(); + static sptr GetInstance(); /** * @brief Connect system channel, set listener and bind IMSA. @@ -60,7 +60,7 @@ public: * @return Returns 0 for success, others for failure. * @since 12 */ - IMF_API int32_t ConnectSystemCmd(const sptr &listener); + int32_t ConnectSystemCmd(const sptr &listener); /** * @brief Send private command to ime. @@ -71,28 +71,25 @@ public: * @return Returns 0 for success, others for failure. * @since 12 */ - IMF_API int32_t SendPrivateCommand( + int32_t SendPrivateCommand( const std::unordered_map &privateCommand) override; - + std::string GetSmartMenuCfg(); int32_t ReceivePrivateCommand( const std::unordered_map &privateCommand) override; - int32_t ShowSysPanel(bool shouldSysPanelShow); - void OnConnectCmdReady(const sptr &agentObject); - int32_t RunConnectSystemCmd(); - private: ImeSystemCmdChannel(); ~ImeSystemCmdChannel(); + int32_t RunConnectSystemCmd(); sptr GetSystemAbilityProxy(); void OnRemoteSaDied(const wptr &object); - void SetSystemCmdListener(const sptr &listener); sptr GetSystemCmdAgent(); sptr GetSystemCmdListener(); void ClearSystemCmdAgent(); + void GetExtensionInfo(std::vector extensionInfos, ExtensionAbilityInfo &extInfo); static std::mutex instanceLock_; static sptr instance_; @@ -110,4 +107,4 @@ private: }; } // namespace MiscServices } // namespace OHOS -#endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_IME_SYSTEM_CHANNEL_H \ No newline at end of file +#endif // INPUTMETHOD_CONTROLLER_IME_SYSTEM_CHANNEL_H \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp b/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp index da41add9..bcb7ae7d 100644 --- a/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp +++ b/frameworks/native/inputmethod_controller/src/ime_system_channel.cpp @@ -25,6 +25,7 @@ namespace OHOS { namespace MiscServices { +constexpr const char *SMART_MENU_METADATA_NAME = "ohos.extension.smart_menu"; std::mutex ImeSystemCmdChannel::instanceLock_; sptr ImeSystemCmdChannel::instance_; ImeSystemCmdChannel::ImeSystemCmdChannel() @@ -34,6 +35,7 @@ ImeSystemCmdChannel::ImeSystemCmdChannel() ImeSystemCmdChannel::~ImeSystemCmdChannel() { } + sptr ImeSystemCmdChannel::GetInstance() { if (instance_ == nullptr) { @@ -154,7 +156,7 @@ sptr ImeSystemCmdChannel::GetSystemCmdAgent() void ImeSystemCmdChannel::SetSystemCmdListener(const sptr &listener) { std::lock_guard lock(systemCmdListenerLock_); - systemCmdListener_ = listener; + systemCmdListener_ = std::move(listener); } sptr ImeSystemCmdChannel::GetSystemCmdListener() @@ -180,11 +182,7 @@ int32_t ImeSystemCmdChannel::ReceivePrivateCommand( IMSA_HILOGE("cmdlistener is nullptr"); return ErrorCode::ERROR_EX_NULL_POINTER; } - auto ret = cmdlistener->ReceivePrivateCommand(privateCommand); - if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("ReceivePrivateCommand err, ret %{public}d", ret); - return ErrorCode::ERROR_CMD_LISTENER_ERROR; - } + cmdlistener->ReceivePrivateCommand(privateCommand); return ErrorCode::NO_ERROR; } @@ -224,5 +222,47 @@ int32_t ImeSystemCmdChannel::ShowSysPanel(bool shouldSysPanelShow) listener->NotifyIsShowSysPanel(shouldSysPanelShow); return ErrorCode::NO_ERROR; } + +std::string ImeSystemCmdChannel::GetSmartMenuCfg() +{ + auto inputMethodController = InputMethodController::GetInstance(); + if (inputMethodController == nullptr) { + return ""; + } + std::shared_ptr defaultIme = nullptr; + int32_t ret = inputMethodController->GetDefaultInputMethod(defaultIme); + if (ret != ErrorCode::NO_ERROR || defaultIme == nullptr) { + IMSA_HILOGE("GetDefaultInputMethod failed"); + return ""; + } + BundleMgrClient client; + BundleInfo bundleInfo; + if (!client.GetBundleInfo(defaultIme->name, BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo)) { + IMSA_HILOGE("GetBundleInfo failed"); + return ""; + } + ExtensionAbilityInfo extInfo; + GetExtensionInfo(bundleInfo.extensionInfos, extInfo); + std::vector profiles; + if (!client.GetResConfigFile(extInfo, SMART_MENU_METADATA_NAME, profiles) || profiles.empty()) { + IMSA_HILOGE("GetResConfigFile failed"); + return ""; + } + return profiles[0]; +} + +void ImeSystemCmdChannel::GetExtensionInfo(std::vector extensionInfos, + ExtensionAbilityInfo &extInfo) +{ + for (size_t i = 0; i < extensionInfos.size(); i++) { + auto metadata = extensionInfos[i].metadata; + for (size_t j = 0; j < metadata.size(); j++) { + if (metadata[j].name == SMART_MENU_METADATA_NAME) { + extInfo = extensionInfos[i]; + return; + } + } + } +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/interfaces/inner_api/inputmethod_controller/BUILD.gn b/interfaces/inner_api/inputmethod_controller/BUILD.gn index ba9d0461..b9835b35 100644 --- a/interfaces/inner_api/inputmethod_controller/BUILD.gn +++ b/interfaces/inner_api/inputmethod_controller/BUILD.gn @@ -86,6 +86,8 @@ ohos_shared_library("inputmethod_client") { external_deps = [ "ability_base:want", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "c_utils:utils", "eventhandler:libeventhandler", "hilog:libhilog", @@ -137,6 +139,8 @@ ohos_static_library("inputmethod_client_static") { external_deps = [ "ability_base:want", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "c_utils:utils", "eventhandler:libeventhandler", "hilog:libhilog",