From 20381f35402df248bf62d05060a2df0c60cd36f6 Mon Sep 17 00:00:00 2001 From: fanzhe Date: Thu, 3 Apr 2025 15:04:46 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E5=A4=9A=E6=A8=A1=E8=BE=93=E5=85=A5ANI?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: fanzhe Change-Id: I73a869ed3c10222cf4069874e2d1dcec5c98a99e --- BUILD.gn | 11 +- bundle.json | 3 +- frameworks/ani/input_consumer/BUILD.gn | 84 ++ .../@ohos.multimodalInput.inputConsumer.ets | 31 + .../input_consumer/include/input_consumer.h | 87 ++ .../ani/input_consumer/src/input_consumer.cpp | 618 ++++++++++++++ frameworks/ani/input_device/BUILD.gn | 90 ++ .../ets/@ohos.multimodalInput.inputDevice.ets | 425 ++++++++++ .../input_device/include/ani_event_target.h | 50 ++ .../include/ani_input_device_context.h | 37 + .../include/ani_input_device_manager.h | 36 + .../ani/input_device/include/ani_util.h | 89 ++ .../ani/input_device/src/ani_event_target.cpp | 240 ++++++ .../src/ani_input_device_context.cpp | 786 ++++++++++++++++++ .../src/ani_input_device_manager.cpp | 38 + frameworks/ani/input_device/src/ani_util.cpp | 129 +++ frameworks/ani/pointer/BUILD.gn | 84 ++ .../ets/@ohos.multimodalInput.pointer.ets | 399 +++++++++ frameworks/ani/pointer/include/ani_utils.h | 497 +++++++++++ frameworks/ani/pointer/include/pointer.h | 32 + frameworks/ani/pointer/src/pointer.cpp | 149 ++++ 21 files changed, 3912 insertions(+), 3 deletions(-) create mode 100644 frameworks/ani/input_consumer/BUILD.gn create mode 100644 frameworks/ani/input_consumer/ets/@ohos.multimodalInput.inputConsumer.ets create mode 100644 frameworks/ani/input_consumer/include/input_consumer.h create mode 100644 frameworks/ani/input_consumer/src/input_consumer.cpp create mode 100644 frameworks/ani/input_device/BUILD.gn create mode 100644 frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets create mode 100644 frameworks/ani/input_device/include/ani_event_target.h create mode 100644 frameworks/ani/input_device/include/ani_input_device_context.h create mode 100644 frameworks/ani/input_device/include/ani_input_device_manager.h create mode 100644 frameworks/ani/input_device/include/ani_util.h create mode 100644 frameworks/ani/input_device/src/ani_event_target.cpp create mode 100644 frameworks/ani/input_device/src/ani_input_device_context.cpp create mode 100644 frameworks/ani/input_device/src/ani_input_device_manager.cpp create mode 100644 frameworks/ani/input_device/src/ani_util.cpp create mode 100644 frameworks/ani/pointer/BUILD.gn create mode 100644 frameworks/ani/pointer/ets/@ohos.multimodalInput.pointer.ets create mode 100644 frameworks/ani/pointer/include/ani_utils.h create mode 100644 frameworks/ani/pointer/include/pointer.h create mode 100644 frameworks/ani/pointer/src/pointer.cpp diff --git a/BUILD.gn b/BUILD.gn index 97c5960f76..312c3af36f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -116,16 +116,23 @@ group("input_jsapi_group") { deps += [ "frameworks/napi/input_monitor:inputmonitor" ] } if (input_feature_mouse) { - deps += [ "frameworks/napi/pointer:pointer" ] + deps += [ + "frameworks/ani/pointer:ani_pointer_package", + "frameworks/napi/pointer:pointer", + ] } if (input_feature_keyboard) { deps += [ + "frameworks/ani/input_consumer:input_consumer_package", "frameworks/napi/input_consumer:inputconsumer", "frameworks/napi/input_event_client:inputeventclient", ] } if (input_feature_input_device) { - deps += [ "frameworks/napi/input_device:inputdevice" ] + deps += [ + "frameworks/ani/input_device:ani_input_device_package", + "frameworks/napi/input_device:inputdevice", + ] } if (input_feature_short_key) { deps += [ "frameworks/napi/short_key:shortkey" ] diff --git a/bundle.json b/bundle.json index 2980e0e867..ca80070e07 100644 --- a/bundle.json +++ b/bundle.json @@ -98,7 +98,8 @@ "qos_manager", "audio_framework", "graphic_surface", - "ipc" + "ipc", + "runtime_core" ], "third_party": [ "libuv", diff --git a/frameworks/ani/input_consumer/BUILD.gn b/frameworks/ani/input_consumer/BUILD.gn new file mode 100644 index 0000000000..ca555c3cea --- /dev/null +++ b/frameworks/ani/input_consumer/BUILD.gn @@ -0,0 +1,84 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("../../../multimodalinput_mini.gni") + +ohos_shared_library("input_consumer") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + configs = [ "${mmi_path}:coverage_flags" ] + + cflags_cc = [ + "-Wno-unused-function", + "-Wno-unused-const-variable", + ] + sources = [ "src/input_consumer.cpp" ] + + include_dirs = [ + "include", + "${mmi_path}/util/common/include", + "${mmi_path}/tools/event_inject/include", + "${mmi_path}/interfaces/native/innerkits/proxy/include", + ] + + deps = [ + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + + external_deps = [ + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "runtime_core:ani", + ] + + subsystem_name = "multimodalinput" + part_name = "input" + output_extension = "so" +} + +generate_static_abc("input_consumer_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.multimodalInput.inputConsumer.ets" ] + dst_file = "$target_out_dir/input_consumer.abc" + out_puts = [ "$target_out_dir/input_consumer.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/input_consumer.abc" +} + +ohos_prebuilt_etc("input_consumer_abc_etc") { + source = "$target_out_dir/input_consumer.abc" + module_install_dir = "framework" + subsystem_name = "multimodalinput" + part_name = "input" + deps = [ ":input_consumer_abc" ] +} + +group("input_consumer_package") { + deps = [ + ":input_consumer", + ":input_consumer_abc_etc", + ] +} diff --git a/frameworks/ani/input_consumer/ets/@ohos.multimodalInput.inputConsumer.ets b/frameworks/ani/input_consumer/ets/@ohos.multimodalInput.inputConsumer.ets new file mode 100644 index 0000000000..6a179a1455 --- /dev/null +++ b/frameworks/ani/input_consumer/ets/@ohos.multimodalInput.inputConsumer.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +import { Callback } from '@ohos.base'; + +export namespace inputConsumer { + loadLibrary("input_consumer") + + export interface KeyOptions { + finalKey: number; + finalKeyDownDuration: number; + isFinalKeyDown: boolean; + preKeys: Array; + isRepeat?: boolean; + } + + export native function on(type: 'key', keyOptions: KeyOptions, callback: Callback): void; + export native function off(type: 'key', keyOptions: KeyOptions, callback?: Callback): void; +} diff --git a/frameworks/ani/input_consumer/include/input_consumer.h b/frameworks/ani/input_consumer/include/input_consumer.h new file mode 100644 index 0000000000..2ec895ce4f --- /dev/null +++ b/frameworks/ani/input_consumer/include/input_consumer.h @@ -0,0 +1,87 @@ + /* + * 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 ANI_INPUT_CONSUMER_H +#define ANI_INPUT_CONSUMER_H + +#include +#include +#include +#include +#include +#include + +#include "key_option.h" + +#define SUCCESS_CODE 0 +#define ERROR_CODE (-1) +#define UNREGISTERED_CODE (-2) +#define PRE_KEY_MAX_COUNT 4 + +enum JS_CALLBACK_EVENT { + JS_CALLBACK_EVENT_FAILED = -1, + JS_CALLBACK_EVENT_SUCCESS = 1, + JS_CALLBACK_EVENT_EXIST = 2, + JS_CALLBACK_EVENT_NOT_EXIST = 3, +}; + +namespace OHOS { +namespace MMI { + +struct KeyEventMonitorInfo { + ani_env* env = nullptr; + std::string eventType; + std::string name; + ani_ref callback = nullptr; + int32_t subscribeId = 0; + ani_ref keyOptionsObj = nullptr; + std::shared_ptr keyOption = nullptr; + ~KeyEventMonitorInfo(); +}; + +class AniLocalScopeGuard { +public: + AniLocalScopeGuard(ani_env *env, size_t nrRefs) : env_(env) + { + status_ = env_->CreateLocalScope(nrRefs); + } + + ~AniLocalScopeGuard() + { + if (ANI_OK != status_) { + return; + } + env_->DestroyLocalScope(); + } + + bool IsStatusOK() + { + return ANI_OK == status_; + } + + ani_status GetStatus() + { + return status_; + } + +private: + ani_env *env_ = nullptr; + ani_status status_ = ANI_ERROR; +}; +typedef std::map>> Callbacks; +} // namespace MMI +} // namespace OHOS + +#endif // ANI_INPUT_CONSUMER_H diff --git a/frameworks/ani/input_consumer/src/input_consumer.cpp b/frameworks/ani/input_consumer/src/input_consumer.cpp new file mode 100644 index 0000000000..1bd3174fbc --- /dev/null +++ b/frameworks/ani/input_consumer/src/input_consumer.cpp @@ -0,0 +1,618 @@ + /* + * 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. + */ + +#include "input_consumer.h" +#include + +#include "define_multimodal.h" +#include "napi_constants.h" +#include "mmi_log.h" +#include "input_manager.h" + + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "AniInputConsumer" + +using namespace OHOS::MMI; + +namespace { +constexpr int32_t ANI_SCOPE_SIZE = 16; +constexpr int32_t MILLISECOND_FACTOR = 1000; +constexpr size_t PRE_KEYS_SIZE { 4 }; +const double INT32_MAX_D = static_cast(std::numeric_limits::max()); +} // namespace + +static Callbacks callbacks = {}; +std::mutex sCallBacksMutex; + +KeyEventMonitorInfo::~KeyEventMonitorInfo() +{ + if (env == nullptr) { + return; + } + if (callback != nullptr) { + env->GlobalReference_Delete(callback); + } + if (keyOptionsObj != nullptr) { + env->GlobalReference_Delete(keyOptionsObj); + } + callback = nullptr; + keyOptionsObj = nullptr; +} + +static ani_error CreateAniError(ani_env *env, std::string &&errMsg) +{ + static const char *errorClsName = "Lescompat/Error;"; + ani_class cls {}; + if (ANI_OK != env->FindClass(errorClsName, &cls)) { + MMI_HILOGE("%{public}s: Not found namespace %{public}s.", __func__, errorClsName); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;:V", &ctor)) { + MMI_HILOGE("%{public}s: Not found in %{public}s.", __func__, errorClsName); + return nullptr; + } + ani_string error_msg; + env->String_NewUTF8(errMsg.c_str(), 17U, &error_msg); + ani_object errorObject; + env->Object_New(cls, ctor, &errorObject, error_msg); + return static_cast(errorObject); +} + +static std::optional GetIsRepeat(ani_env *env, ani_object keyOptionsObj) +{ + ani_ref aniRef; + if (ANI_OK != env->Object_GetPropertyByName_Ref(keyOptionsObj, "isRepeat", &aniRef)) { + MMI_HILOGE("%{public}s: Object_GetPropertyByName_Ref isRepeat failed.", __func__); + return std::nullopt; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(aniRef, &isUndefined)) { + MMI_HILOGE("%{public}s: Object_GetFieldByName_Ref isRepeat failed.", __func__); + return std::nullopt; + } + + if (isUndefined) { + MMI_HILOGE("%{public}s: Param 'isRepeat' is undefined.", __func__); + return std::nullopt; + } + + ani_boolean isRepeat; + auto ret = env->Object_CallMethodByName_Boolean(static_cast(aniRef), "unboxed", nullptr, &isRepeat); + if (ret != ANI_OK) { + MMI_HILOGE("%{public}s: Object_CallMethodByName_Boolean failed.", __func__); + return std::nullopt; + } + return static_cast(isRepeat); +} + +static std::string AniStringToString(ani_env *env, ani_string aniStr) +{ + ani_size strSize; + env->String_GetUTF8Size(aniStr, &strSize); + + std::vector buffer(strSize + 1); + char* utf8Buffer = buffer.data(); + + ani_size bytes_written = 0; + env->String_GetUTF8(aniStr, utf8Buffer, strSize + 1, &bytes_written); + + utf8Buffer[bytes_written] = '\0'; + std::string content = std::string(utf8Buffer); + return content; +} + +static bool GetPreKeys(ani_env *env, ani_object keyOptionsObj, std::set &preKeys) +{ + CALL_DEBUG_ENTER; + ani_ref ref; + if (ANI_OK != env->Object_GetPropertyByName_Ref(keyOptionsObj, "preKeys", &ref)) { + MMI_HILOGE("Object_GetPropertyByName_Ref Failed"); + return false; + } + ani_object arrayObj = static_cast(ref); + ani_double length; + if (ANI_OK != env->Object_GetPropertyByName_Double(arrayObj, "length", &length)) { + MMI_HILOGE("Object_GetPropertyByName_Double length Failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref intArrayRef; + if (ANI_OK != env->Object_CallMethodByName_Ref(arrayObj, "$_get", "I:Lstd/core/Object;", &intArrayRef, + (ani_int)i)) { + MMI_HILOGE("Object_GetPropertyByName_Ref Failed"); + return false; + } + ani_double doubleEntry; + if (ANI_OK != env->Object_CallMethodByName_Double(static_cast(intArrayRef), "unboxed", nullptr, + &doubleEntry)) { + MMI_HILOGE("Object_CallMethodByName_Double unbox Failed"); + return false; + } + if (doubleEntry > INT32_MAX_D || doubleEntry < 0) { + ani_error error = CreateAniError(env, "preKeys must be between 0 and INT32_MAX"); + env->ThrowError(error); + MMI_HILOGE("preKey:%{public}f is less 0 or greater than INT32_MAX, can not process", doubleEntry); + return false; + } + if (!preKeys.insert(static_cast(doubleEntry)).second) { + MMI_HILOGE("Params insert value failed"); + return false; + } + } + return true; +} + +static std::string GenerateEventType(std::shared_ptr &keyOptionPtr) +{ + CALL_DEBUG_ENTER; + std::string eventType; + for (const auto &preKey : keyOptionPtr->GetPreKeys()) { + eventType = eventType + std::to_string(preKey) + ","; + } + eventType = eventType + std::to_string(keyOptionPtr->GetFinalKey()) + "," + + std::to_string(keyOptionPtr->IsFinalKeyDown()) + "," + + std::to_string(keyOptionPtr->GetFinalKeyDownDuration()) + "," + + std::to_string(keyOptionPtr->IsRepeat()); + return eventType; +} + +static std::shared_ptr ParseKeyOptions(ani_env *env, ani_object keyOptionsObj) +{ + CALL_DEBUG_ENTER; + std::shared_ptr keyOptionPtr = std::make_shared(); + + std::set preKeys; + if (!GetPreKeys(env, keyOptionsObj, preKeys) || preKeys.size() > PRE_KEYS_SIZE) { + MMI_HILOGE("PreKeys is invalid"); + ani_error error = CreateAniError(env, "PreKeys is invalid"); + env->ThrowError(error); + return nullptr; + } + keyOptionPtr->SetPreKeys(preKeys); + + ani_double finalKey; + if (ANI_OK != env->Object_GetPropertyByName_Double(keyOptionsObj, "finalKey", &finalKey)) { + MMI_HILOGE("Object_GetPropertyByName_Double finalKey Failed"); + return nullptr; + } + if (finalKey > INT32_MAX_D || finalKey < 0) { + MMI_HILOGE("finalKey:%{private}f is less 0 or greater than INT32_MAX, can not process", finalKey); + ani_error error = CreateAniError(env, "finalKey must be between 0 and INT32_MAX"); + env->ThrowError(error); + return nullptr; + } + keyOptionPtr->SetFinalKey(static_cast(finalKey)); + + ani_boolean isFinalKeyDown; + if (ANI_OK != env->Object_GetPropertyByName_Boolean(keyOptionsObj, "isFinalKeyDown", &isFinalKeyDown)) { + MMI_HILOGE("Object_GetPropertyByName_Boolean isFinalKeyDown Failed"); + return nullptr; + } + keyOptionPtr->SetFinalKeyDown(static_cast(isFinalKeyDown)); + + ani_double finalKeyDownDuration; + if (ANI_OK != env->Object_GetPropertyByName_Double(keyOptionsObj, "finalKeyDownDuration", &finalKeyDownDuration)) { + MMI_HILOGE("Object_GetPropertyByName_Double finalKeyDownDuration Failed"); + return nullptr; + } + if (finalKeyDownDuration > INT32_MAX_D || finalKeyDownDuration < 0) { + MMI_HILOGE("finalKeyDownDuration:%{public}f is less 0 or greater INT32_MAX", finalKeyDownDuration); + ani_error error = CreateAniError(env, "finalKeyDownDuration must be between 0 and INT32_MAX"); + env->ThrowError(error); + return nullptr; + } + keyOptionPtr->SetFinalKeyDownDuration(static_cast(finalKeyDownDuration)); + + bool isRepeat = true; + auto isRepeatOpt = GetIsRepeat(env, keyOptionsObj); + if (isRepeatOpt.has_value()) { + isRepeat = isRepeatOpt.value(); + } + keyOptionPtr->SetRepeat(isRepeat); + + return keyOptionPtr; +} + +static bool IsMatchKeyAction(bool isFinalKeydown, int32_t keyAction) +{ + CALL_DEBUG_ENTER; + MMI_HILOGD("isFinalKeydown:%{public}d, keyAction:%{public}d", isFinalKeydown, keyAction); + if (isFinalKeydown && keyAction == KeyEvent::KEY_ACTION_DOWN) { + return true; + } + if (!isFinalKeydown && keyAction == KeyEvent::KEY_ACTION_UP) { + return true; + } + MMI_HILOGE("isFinalKeydown not matched with keyAction"); + return false; +} + +static bool MatchCombinationKey(KeyOption &combinationKeyOption, KeyEvent &keyEvent) +{ + CALL_DEBUG_ENTER; + std::vector items = keyEvent.GetKeyItems(); + int32_t infoFinalKey = combinationKeyOption.GetFinalKey(); + int32_t keyEventFinalKey = keyEvent.GetKeyCode(); + bool isFinalKeydown = combinationKeyOption.IsFinalKeyDown(); + MMI_HILOGD("InfoFinalKey:%{public}d,keyEventFinalKey:%{public}d,isFinalKeydown:%{public}d", + infoFinalKey, keyEventFinalKey, isFinalKeydown); + if (infoFinalKey != keyEventFinalKey || items.size() > PRE_KEYS_SIZE || + !IsMatchKeyAction(isFinalKeydown, keyEvent.GetKeyAction())) { + MMI_HILOGD("key Param invalid"); + return false; + } + + std::set preKeys = combinationKeyOption.GetPreKeys(); + int32_t infoSize = std::count_if(preKeys.begin(), preKeys.end(), [](int32_t preKey) { return preKey >= 0; }); + int32_t count = 0; + for (const auto &item : items) { + if (item.GetKeyCode() == keyEventFinalKey) { + continue; + } + auto iter = find(preKeys.begin(), preKeys.end(), item.GetKeyCode()); + if (iter == preKeys.end()) { + MMI_HILOGW("No keyCode in preKeys"); + return false; + } + count++; + } + MMI_HILOGD("kevEventSize:%{public}d, infoSize:%{public}d", count, infoSize); + std::optional keyItem = keyEvent.GetKeyItem(); + if (!keyItem) { + MMI_HILOGE("The keyItem is nullopt"); + return false; + } + auto downTime = keyItem->GetDownTime(); + auto upTime = keyEvent.GetActionTime(); + auto curDurationTime = combinationKeyOption.GetFinalKeyDownDuration(); + if (curDurationTime > 0 && (upTime - downTime >= (static_cast(curDurationTime) * MILLISECOND_FACTOR))) { + MMI_HILOGE("Skip, upTime - downTime >= duration"); + return false; + } + return count == infoSize; +} + +static bool SendEventToMainThread(const std::function func) +{ + CALL_DEBUG_ENTER; + if (func == nullptr) { + MMI_HILOGE("%{public}s: func == nullptr", __func__); + return false; + } + auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + MMI_HILOGE("%{public}s: runner == nullptr", __func__); + return false; + } + auto handler = std::make_shared(runner); + handler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {}); + MMI_HILOGD("%{public}s: PostTask success", __func__); + return true; +} + +static ani_boolean IsInstanceOf(ani_env *env, const std::string &cls_name, ani_object obj) +{ + ani_class cls; + if (ANI_OK != env->FindClass(cls_name.c_str(), &cls)) { + MMI_HILOGE("%{public}s: FindClass failed", __func__); + return ANI_FALSE; + } + + ani_boolean ret; + env->Object_InstanceOf(obj, cls, &ret); + return ret; +} + +static void EmitAsyncCallbackWork(std::shared_ptr reportEvent) +{ + CALL_DEBUG_ENTER; + CHKPV(reportEvent); + auto task = [reportEvent]() { + MMI_HILOGD("%{public}s: Begin to call task", __func__); + ani_size nrRefs = ANI_SCOPE_SIZE; + AniLocalScopeGuard aniLocalScopeGuard(reportEvent->env, nrRefs); + if (!aniLocalScopeGuard.IsStatusOK()) { + MMI_HILOGE("%{public}s: CreateLocalScope failed", __func__); + return; + } + auto fnObj = reinterpret_cast(reportEvent->callback); + std::vector args = {reportEvent->keyOptionsObj}; + ani_ref result; + MMI_HILOGD("%{public}s: Begin to call FunctionalObject_Call", __func__); + if (fnObj == nullptr || args.size() == 0) { + MMI_HILOGE("%{public}s: fnObj == nullptr", __func__); + return; + } + if (IsInstanceOf(reportEvent->env, "Lstd/core/Function1;", fnObj) == 0) { + MMI_HILOGE("%{public}s: fnObj is not instance Of function ", __func__); + return; + } + const std::string className = "L@ohos/multimodalInput/inputConsumer/inputConsumer/KeyOptions;"; + if (IsInstanceOf(reportEvent->env, className, static_cast(reportEvent->keyOptionsObj)) == 0) { + MMI_HILOGE("%{public}s: keyOptionsObj is not instance Of KeyOptions class", __func__); + return; + } + + if (ANI_OK != reportEvent->env->FunctionalObject_Call(fnObj, 1, args.data(), &result)) { + MMI_HILOGE("%{public}s: FunctionalObject_Call failed", __func__); + return; + } + MMI_HILOGD("%{public}s: FunctionalObject_Call success", __func__); + }; + if (!SendEventToMainThread(task)) { + MMI_HILOGE("%{public}s: failed to send event", __func__); + } +} + +static void SubKeyEventCallback(std::shared_ptr keyEvent) +{ + CALL_DEBUG_ENTER; + CHKPV(keyEvent); + std::lock_guard guard(sCallBacksMutex); + auto iter = callbacks.begin(); + while (iter != callbacks.end()) { + auto &list = iter->second; + ++iter; + MMI_HILOGD("list size:%{public}zu", list.size()); + auto infoIter = list.begin(); + while (infoIter != list.end()) { + auto monitorInfo = *infoIter; + if (MatchCombinationKey(*(monitorInfo->keyOption), *keyEvent)) { + MMI_HILOGD("MatchCombinationKey success"); + EmitAsyncCallbackWork(monitorInfo); + } + ++infoIter; + } + } +} + +static int32_t GetPreSubscribeId(const std::shared_ptr &event) +{ + CHKPR(event, ERROR_NULL_POINTER); + std::lock_guard guard(sCallBacksMutex); + auto it = callbacks.find(event->eventType); + if (it == callbacks.end() || it->second.empty()) { + MMI_HILOGE("The callbacks is empty"); + return JS_CALLBACK_EVENT_FAILED; + } + CHKPR(it->second.front(), ERROR_NULL_POINTER); + return it->second.front()->subscribeId; +} + +static bool CheckCallbackEqual(ani_env *env, ani_ref fnRef, ani_env *iterEnv, ani_ref iterFn) +{ + if (env != iterEnv) { + MMI_HILOGD("%{public}s: not the same env", __func__); + return false; + } + ani_boolean isEquals = false; + if (ANI_OK != env->Reference_StrictEquals(fnRef, iterFn, &isEquals)) { + MMI_HILOGD("%{public}s: check observer equal failed!", __func__); + return false; + } + return isEquals; +} + +static int32_t AddEventCallback(std::shared_ptr event) +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(sCallBacksMutex); + CHKPR(event, ERROR_NULL_POINTER); + if (callbacks.find(event->eventType) == callbacks.end()) { + MMI_HILOGD("No callback in %{public}s", event->eventType.c_str()); + callbacks[event->eventType] = {}; + } + + auto it = callbacks.find(event->eventType); + for (const auto &iter: it->second) { + if (CheckCallbackEqual(event->env, event->callback, iter->env, iter->callback)) { + MMI_HILOGE("Callback already exist"); + return JS_CALLBACK_EVENT_FAILED; + } + } + it->second.push_back(event); + return JS_CALLBACK_EVENT_SUCCESS; +} + +static int32_t SubscribeKey(ani_env *env, std::shared_ptr &event) +{ + CALL_DEBUG_ENTER; + std::string subKeyNames = ""; + auto keyOptionsPtr = ParseKeyOptions(env, static_cast(event->keyOptionsObj)); + if (keyOptionsPtr == nullptr) { + MMI_HILOGE("keyOptionsPtr is nullptr"); + return ERROR_CODE; + } + event->keyOption = keyOptionsPtr; + event->eventType = GenerateEventType(keyOptionsPtr); + + int32_t preSubscribeId = GetPreSubscribeId(event); + if (preSubscribeId >= 0) { + event->subscribeId = preSubscribeId; + return AddEventCallback(event); + } + + MMI_HILOGD("EventType:%{private}s, eventName:%{public}s", event->eventType.c_str(), event->name.c_str()); + int32_t subscribeId = -1; + subscribeId = InputManager::GetInstance()->SubscribeKeyEvent(event->keyOption, SubKeyEventCallback); + if (subscribeId < 0) { + MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId); + return subscribeId; + } + MMI_HILOGD("SubscribeId:%{public}d", subscribeId); + event->subscribeId = subscribeId; + return AddEventCallback(event); +} + +static void On([[maybe_unused]] ani_env *env, ani_string strObj, ani_object keyOptionsObj, ani_object callback) +{ + CALL_DEBUG_ENTER; + std::shared_ptr event = std::make_shared(); + event->env = env; + if (ANI_OK != env->GlobalReference_Create(callback, &event->callback)) { + MMI_HILOGE("Create global reference 'callback' failed"); + return; + } + if (ANI_OK != env->GlobalReference_Create(keyOptionsObj, &event->keyOptionsObj)) { + MMI_HILOGE("Create global reference 'keyOptionsObj' failed"); + return; + } + + std::string keyType = AniStringToString(env, strObj); + event->name = keyType; + + if (keyType == HOTKEY_SUBSCRIBE_TYPE) { + MMI_HILOGD("%{public}s: Enter Hotkey.", __func__); + } else if (keyType == SUBSCRIBE_TYPE) { + int32_t ret = SubscribeKey(env, event); + MMI_HILOGD("%{public}s: Call SubscribeKey end ret = %{public}d", __func__, ret); + } else { + MMI_HILOGE("Type is not key or hotkey"); + ani_error error = CreateAniError(env, "Type must be key or hotkeyChange"); + env->ThrowError(error); + } +} + +static int32_t DelEventCallbackRef(ani_env *env, std::list> &info, + ani_ref handler, int32_t &subscribeId) +{ + CALL_DEBUG_ENTER; + for (auto iter = info.begin(); iter != info.end();) { + if (*iter == nullptr) { + info.erase(iter++); + continue; + } + if (handler != nullptr) { + if (!CheckCallbackEqual(env, handler, (*iter)->env, (*iter)->callback)) { + ++iter; + continue; + } + std::shared_ptr monitorInfo = *iter; + info.erase(iter++); + if (info.empty()) { + subscribeId = monitorInfo->subscribeId; + } + MMI_HILOGD("Callback has deleted, size:%{public}zu", info.size()); + return JS_CALLBACK_EVENT_SUCCESS; + } + std::shared_ptr monitorInfo = *iter; + info.erase(iter++); + if (info.empty()) { + subscribeId = monitorInfo->subscribeId; + } + MMI_HILOGD("Callback has deleted, size:%{public}zu", info.size()); + } + MMI_HILOGD("Callback size:%{public}zu", info.size()); + return JS_CALLBACK_EVENT_SUCCESS; +} + +static int32_t DelEventCallback(std::shared_ptr &event, int32_t &subscribeId) +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(sCallBacksMutex); + CHKPR(event, ERROR_NULL_POINTER); + if (callbacks.count(event->eventType) <= 0) { + MMI_HILOGE("Callback doesn't exists, eventType:%{private}s", event->eventType.c_str()); + return JS_CALLBACK_EVENT_FAILED; + } + auto &info = callbacks[event->eventType]; + MMI_HILOGD("EventType:%{public}s, keyEventMonitorInfos:%{public}zu", event->eventType.c_str(), info.size()); + + return DelEventCallbackRef(event->env, info, event->callback, subscribeId); +} + +static void Off([[maybe_unused]] ani_env *env, ani_string strObj, ani_object keyOptionsObj, ani_object callback) +{ + CALL_DEBUG_ENTER; + std::shared_ptr event = std::make_shared(); + event->env = env; + if (ANI_OK != env->GlobalReference_Create(keyOptionsObj, &event->keyOptionsObj)) { + MMI_HILOGE("Call GlobalReference_Create failed"); + return; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(callback, &isUndefined)) { + MMI_HILOGE("Call Reference_IsUndefined failed"); + return; + } + if (isUndefined) { + MMI_HILOGD("%{public}s: callback is undefined", __func__); + event->callback = nullptr; + } else { + if (ANI_OK != env->GlobalReference_Create(callback, &event->callback)) { + MMI_HILOGE("%{public}s: Create global reference 'callback' failed", __func__); + return; + } + } + + std::string keyType = AniStringToString(env, strObj); + event->name = keyType; + int32_t subscribeId = -1; + if (keyType == HOTKEY_SUBSCRIBE_TYPE) { + MMI_HILOGD("%{public}s: Enter Hotkey.", __func__); + } else if (keyType == SUBSCRIBE_TYPE) { + std::string subKeyNames = ""; + auto keyOptionsPtr = ParseKeyOptions(env, static_cast(event->keyOptionsObj)); + if (keyOptionsPtr == nullptr) { + MMI_HILOGE("%{public}s: ParseKeyOptions failed", __func__); + return; + } + event->keyOption = keyOptionsPtr; + event->eventType = GenerateEventType(keyOptionsPtr); + if (DelEventCallback(event, subscribeId) < 0) { + MMI_HILOGE("DelEventCallback failed"); + return; + } + MMI_HILOGI("Unsubscribe key event(%{public}d)", subscribeId); + InputManager::GetInstance()->UnsubscribeKeyEvent(subscribeId); + } else { + MMI_HILOGE("Type is not key or hotkey"); + ani_error error = CreateAniError(env, "Type must be key or hotkeyChange"); + env->ThrowError(error); + } +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + MMI_HILOGE("%{public}s: Unsupported ANI_VERSION_1", __func__); + return ANI_ERROR; + } + + static const char *name = "L@ohos/multimodalInput/inputConsumer/inputConsumer;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(name, &ns)) { + MMI_HILOGE("%{public}s: Not found %{public}s", __func__, name); + return ANI_NOT_FOUND; + } + + std::array methods = { + ani_native_function {"on", nullptr, reinterpret_cast(On)}, + ani_native_function {"off", nullptr, reinterpret_cast(Off)}, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { + MMI_HILOGE("%{public}s:Cannot bind native methods to '%{public}s'", __func__, name); + return ANI_ERROR; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ani/input_device/BUILD.gn b/frameworks/ani/input_device/BUILD.gn new file mode 100644 index 0000000000..335f4d2f5a --- /dev/null +++ b/frameworks/ani/input_device/BUILD.gn @@ -0,0 +1,90 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("../../../multimodalinput_mini.gni") + +ohos_shared_library("ani_input_device") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + configs = [ "${mmi_path}:coverage_flags" ] + + cflags_cc = [ + "-Wno-unused-function", + "-Wno-unused-const-variable", + ] + sources = [ + "src/ani_event_target.cpp", + "src/ani_input_device_context.cpp", + "src/ani_input_device_manager.cpp", + "src/ani_util.cpp", + ] + + include_dirs = [ + "include", + "${mmi_path}/util/common/include", + "${mmi_path}/tools/event_inject/include", + "${mmi_path}/interfaces/native/innerkits/proxy/include", + ] + + deps = [ + "${mmi_path}/frameworks/native/input:oh_input_manager", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + + external_deps = [ + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "runtime_core:ani", + ] + + subsystem_name = "multimodalinput" + part_name = "input" + output_extension = "so" +} + +generate_static_abc("input_device_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.multimodalInput.inputDevice.ets" ] + dst_file = "$target_out_dir/input_device.abc" + out_puts = [ "$target_out_dir/input_device.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/input_device.abc" +} + +ohos_prebuilt_etc("input_device_abc_etc") { + source = "$target_out_dir/input_device.abc" + module_install_dir = "framework" + subsystem_name = "multimodalinput" + part_name = "input" + deps = [ ":input_device_abc" ] +} + +group("ani_input_device_package") { + deps = [ + ":ani_input_device", + ":input_device_abc_etc", + ] +} diff --git a/frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets b/frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets new file mode 100644 index 0000000000..1bc3719902 --- /dev/null +++ b/frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets @@ -0,0 +1,425 @@ +/* + * 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. + */ + +import hilog from '@ohos.hilog' +import { Callback, AsyncCallback } from '@ohos.base'; +import { BusinessError } from "@ohos.base" + +export namespace inputDevice { + loadLibrary("ani_input_device"); + + export native function getDeviceListInner(): Array; + export native function getDeviceInfoInner(deviceId: number): InputDeviceData; + + export native function on(type: 'change', listener: Callback): void; + + /** + * Add or remove device + * @typedef { 'add' | 'remove' } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + type ChangedType = 'add' | 'remove'; + + /** + * The type of input device + * @typedef { 'keyboard' | 'mouse' | 'touchpad' | 'touchscreen' | 'joystick' | 'trackball' } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + type SourceType = 'keyboard' | 'mouse' | 'touchpad' | 'touchscreen' | 'joystick' | 'trackball'; + + /** + * Axis Type of the input event + * @typedef { 'touchmajor'| 'touchminor' | 'orientation' | 'x' | 'y' | 'pressure' | 'toolminor' | 'toolmajor' | 'null' } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + type AxisType = + 'touchmajor' + | 'touchminor' + | 'orientation' + | 'x' + | 'y' + | 'pressure' + | 'toolminor' + | 'toolmajor' + | 'null'; + + /** + * @enum { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + enum KeyboardType { + /** + * None + * + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + NONE = 0, + + /** + * Unknown key + * + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + UNKNOWN = 1, + + /** + * Alphabetical keyboard + * + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + ALPHABETIC_KEYBOARD = 2, + + /** + * Digital keyboard + * + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + DIGITAL_KEYBOARD = 3, + + /** + * Stylus + * + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + HANDWRITING_PEN = 4, + + /** + * Remote control + * + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + REMOTE_CONTROL = 5 + } + + /** + * Enumerates function keys. + * + * @enum { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 15 + */ + enum FunctionKey { + /** + * CapsLock key. Enabling or disabling the CapsLock key is allowed only for input keyboard extensions. + * + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 15 + */ + CAPS_LOCK = 1 + } + + /** + * Defines the listener for input device events. + * + * @interface DeviceListener + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + interface DeviceListener { + /** + * Type of the input device event. The options are add and remove. + * + * @type { ChangedType } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + type: ChangedType; + + /** + * ID of the input device for the reported input device event. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + deviceId: number; + } + + interface AxisRange { + /** + * Input source type of the axis. For example, if a mouse reports an x-axis event, + * the source of the x-axis is the mouse. + * + * @type { SourceType } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + source: SourceType; + + /** + * Type of the axis. for example, the x-axis, y-axis, and pressure axis. + * + * @type { AxisType } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + axis: AxisType; + + /** + * Maximum value of the data reported on this axis. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + max: number; + + /** + * Minimum value of the data reported on this axis. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + min: number; + + /** + * Fuzz value of the data reported on this axis. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + fuzz: number; + + /** + * Flat value of the data reported on this axis. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + flat: number; + + /** + * Resolution value of the data reported on this axis. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + resolution: number; + } + + /** + * Defines the information about an input device. + * + * @interface InputDeviceData + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + interface InputDeviceData { + /** + * Id of the input device. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + id: number; + + /** + * Name of the input device. + * + * @type { string } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + name: string; + + /** + * Source type supported by the input device. For example, if a keyboard is attached with a touchpad, + * the device has two input sources: keyboard and touchpad. + * + * @type { Array } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + sources: Array; + + /** + * Axis range of the input device. + * + * @type { Array } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 8 + */ + axisRanges: Array; + + /** + * Bus of the input device. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + bus: number; + + /** + * Product of the input device. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + product: number; + + /** + * Vendor of the input device. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + vendor: number; + + /** + * Version of the input device. + * + * @type { number } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + version: number; + + /** + * Physical path of the input device. + * + * @type { string } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + phys: string; + + /** + * Unique identifier of the input device. + * + * @type { string } + * @syscap SystemCapability.MultimodalInput.Input.InputDevice + * @since 9 + */ + uniq: string; + } + + class InputDeviceDataImpl implements InputDeviceData { + private nativePtr:long = 0; + constructor(context:long) { + hilog.info(0x0000, 'input_device', "in constructor, context is ", context) + this.nativePtr = context; + } + + setEmptyAxisRanges(): void { + this.axisRanges = new Array(); + } + + id: number; + name: string; + sources: Array; + axisRanges: Array; + bus: number; + product: number; + vendor: number; + version: number; + phys: string; + uniq: string; + } + + class AxisRangeImpl implements AxisRange { + private nativePtr:long = 0; + constructor(context:long) { + hilog.info(0x0000, 'input_device', "in constructor, context is ", context) + this.nativePtr = context; + } + + source: SourceType; + axis: AxisType; + max: number; + min: number; + fuzz: number; + flat: number; + resolution: number; + } + + class DeviceListenerImpl implements DeviceListener { + type: ChangedType; + deviceId: number; + } + + function getDeviceList(callback: AsyncCallback>): void { + let p1 = taskpool.execute(getDeviceListInner); + p1.then((data: NullishType) => { + let r = data as Array; + let err : BusinessError + callback(err, r); + }).catch((error: NullishType) => { + let err = error as BusinessError; + let data = new Array; + callback(err, data); + }); + } + + function getDeviceList(): Promise> { + let p = new Promise>((resolve: (v: Array) => void, + reject: (error: Object) => void) => { + let p1 = taskpool.execute(getDeviceListInner); + p1.then((e :NullishType)=>{ + let r = e as Array; + resolve(r); + }).catch((error: Error) : Array => { + reject(error); + }); + }); + return p; + } + + function getDeviceInfo(deviceId: number, callback: AsyncCallback): void { + let p1 = taskpool.execute(getDeviceInfoInner, deviceId); + p1.then((data: NullishType) => { + let r = data as InputDeviceData; + let err : BusinessError + callback(err, r); + }).catch((error: NullishType) => { + let err = error as BusinessError; + let data = new InputDeviceDataImpl(0); + callback(err, data); + }); + } + function getDeviceInfo(deviceId: number): Promise { + let p = new Promise((resolve: (v: InputDeviceData) => void, + reject: (error: Object) => void) => { + let p1 = taskpool.execute(getDeviceInfoInner, deviceId); + p1.then((e :NullishType)=>{ + let r = e as InputDeviceData; + resolve(r); + }).catch((error: Error) : InputDeviceData => { + reject(error); + }); + }); + return p; + } + function getDeviceInfoSync(deviceId: number): InputDeviceData { + return getDeviceInfoInner(deviceId); + } +} diff --git a/frameworks/ani/input_device/include/ani_event_target.h b/frameworks/ani/input_device/include/ani_event_target.h new file mode 100644 index 0000000000..6fff77042f --- /dev/null +++ b/frameworks/ani/input_device/include/ani_event_target.h @@ -0,0 +1,50 @@ +/* + * 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 ANI_EVENT_TARGET_H +#define ANI_EVENT_TARGET_H + +#include + +#include "define_multimodal.h" +#include "error_multimodal.h" +#include "input_manager.h" +#include "ani_util.h" + +namespace OHOS { +namespace MMI { +class AniEventTarget : public IInputDeviceListener, public std::enable_shared_from_this { +public: + AniEventTarget(); + virtual ~AniEventTarget() = default; + DISALLOW_COPY_AND_MOVE(AniEventTarget); + void AddListener(ani_env *env, const std::string &type, ani_object handle); + void ResetEnv(); + void OnDeviceAdded(int32_t deviceId, const std::string &type) override; + void OnDeviceRemoved(int32_t deviceId, const std::string &type) override; + +private: + static void EmitAddedDeviceEvent(std::shared_ptr reportData); + static void EmitRemoveDeviceEvent(std::shared_ptr reportData); + static bool EmitCallbackWork(ani_env *env, std::shared_ptr &reportData, + const std::string &type); + +private: + inline static std::map>> devListener_ {}; + bool isListeningProcess_ { false }; +}; +} // namespace MMI +} // namespace OHOS +#endif // ANI_EVENT_TARGET_H \ No newline at end of file diff --git a/frameworks/ani/input_device/include/ani_input_device_context.h b/frameworks/ani/input_device/include/ani_input_device_context.h new file mode 100644 index 0000000000..4e64b3ff63 --- /dev/null +++ b/frameworks/ani/input_device/include/ani_input_device_context.h @@ -0,0 +1,37 @@ + /* + * 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 ANI_MULTI_MODAL_INPUT_DEVICE_H +#define ANI_MULTI_MODAL_INPUT_DEVICE_H + +#include "ani_input_device_manager.h" + +namespace OHOS { +namespace MMI { +class AniInputDeviceContext final { +public: + AniInputDeviceContext(); + DISALLOW_COPY_AND_MOVE(AniInputDeviceContext); + ~AniInputDeviceContext(); + + void On(ani_env *env, ani_string info, ani_object callback); + +private: + std::shared_ptr mgr_ { nullptr }; + std::mutex mtx_; +}; +} // namespace MMI +} // namespace OHOS +#endif // ANI_MULTI_MODAL_INPUT_DEVICE_H diff --git a/frameworks/ani/input_device/include/ani_input_device_manager.h b/frameworks/ani/input_device/include/ani_input_device_manager.h new file mode 100644 index 0000000000..fc82212cfb --- /dev/null +++ b/frameworks/ani/input_device/include/ani_input_device_manager.h @@ -0,0 +1,36 @@ +/* + * 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 ANI_INPUT_DEVICE_MANAGER_H +#define ANI_INPUT_DEVICE_MANAGER_H + +#include + +#include "ani_event_target.h" + +namespace OHOS { +namespace MMI { +class AniInputDeviceManager : public AniEventTarget { +public: + AniInputDeviceManager() = default; + DISALLOW_COPY_AND_MOVE(AniInputDeviceManager); + ~AniInputDeviceManager() = default; + + void ResetEnv(); + void RegisterDevListener(ani_env *env, const std::string &type, ani_object handle); +}; +} // namespace MMI +} // namespace OHOS +#endif // ANI_INPUT_DEVICE_MANAGER_H \ No newline at end of file diff --git a/frameworks/ani/input_device/include/ani_util.h b/frameworks/ani/input_device/include/ani_util.h new file mode 100644 index 0000000000..8fa0d0970c --- /dev/null +++ b/frameworks/ani/input_device/include/ani_util.h @@ -0,0 +1,89 @@ +/* + * 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 ANI_UTIL_H +#define ANI_UTIL_H +#include +#include "input_device.h" + +namespace OHOS { +namespace MMI { +class AniUtil { +public: + struct CallbackData { + std::vector ids; + std::shared_ptr device { nullptr }; + std::vector keystrokeAbility; + int32_t deviceId { 0 }; + int32_t keyboardType { 0 }; + int32_t keyboardRepeatDelay { 0 }; + int32_t keyboardRepeatRate { 0 }; + int64_t IntervalSinceLastInput { 0 }; + }; + struct ReportData { + ani_ref ref { nullptr }; + int32_t deviceId { 0 }; + }; + struct CallbackInfo { + ani_env *env { nullptr }; + ani_ref ref { nullptr }; + int32_t errCode { -1 }; + CallbackData data; + // UserData uData; + }; + struct DeviceType { + std::string sourceTypeName; + uint32_t typeBit { 0 }; + }; + + static bool IsSameHandle(ani_env *env, ani_ref handle, ani_env *iterEnv, ani_ref iterhandle); + static ani_string StdStringToANIString(ani_env* env, const std::string& str); + static bool SendEventToMainThread(const std::function func); + static ani_boolean IsInstanceOf(ani_env *env, const std::string &cls_name, ani_object obj); + static ani_object CreateAniObject(ani_env *env, const char *nsName, const char *className); +}; + +class AniLocalScopeGuard { +public: + AniLocalScopeGuard(ani_env *env, size_t nrRefs) : env_(env) + { + status_ = env_->CreateLocalScope(nrRefs); + } + + ~AniLocalScopeGuard() + { + if (ANI_OK != status_) { + return; + } + env_->DestroyLocalScope(); + } + + bool IsStatusOK() + { + return ANI_OK == status_; + } + + ani_status GetStatus() + { + return status_; + } + +private: + ani_env *env_ = nullptr; + ani_status status_ = ANI_ERROR; +}; +} // namespace MMI +} // namespace OHOS +#endif // ANI_UTIL_H \ No newline at end of file diff --git a/frameworks/ani/input_device/src/ani_event_target.cpp b/frameworks/ani/input_device/src/ani_event_target.cpp new file mode 100644 index 0000000000..c02cbc20ae --- /dev/null +++ b/frameworks/ani/input_device/src/ani_event_target.cpp @@ -0,0 +1,240 @@ +/* + * 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. + */ + +#include "ani_event_target.h" +#include "ani_util.h" +#include "bytrace_adapter.h" + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "AniEventTarget" + +namespace OHOS { +namespace MMI { +namespace { +constexpr int32_t INPUT_PARAMETER_MIDDLE { 2 }; + +std::mutex mutex_; +const std::string ADD_EVENT = "add"; +const std::string REMOVE_EVENT = "remove"; +const std::string CHANGED_TYPE = "change"; +constexpr int32_t ANI_SCOPE_SIZE = 16; + +struct DeviceItem { + int32_t deviceId; + void *item; +}; + +} // namespace + +AniEventTarget::AniEventTarget() +{ + CALL_DEBUG_ENTER; + std::lock_guard lock(mutex_); + auto ret = devListener_.insert({ CHANGED_TYPE, std::vector>() }); + CK(ret.second, VAL_NOT_EXP); +} + +bool AniEventTarget::EmitCallbackWork(ani_env *env, std::shared_ptr &reportData, + const std::string &type) +{ + CALL_DEBUG_ENTER; + AniLocalScopeGuard aniLocalScopeGuard(env, ANI_SCOPE_SIZE); + if (!aniLocalScopeGuard.IsStatusOK()) { + MMI_HILOGE("%{public}s: CreateLocalScope failed", __func__); + return false; + } + std::vector args; + const char *nsName = "L@ohos/multimodalInput/inputDevice/inputDevice;"; + const char *className = "LDeviceListenerImpl;"; + auto obj = AniUtil::CreateAniObject(env, nsName, className); + if (obj == nullptr) { + MMI_HILOGE("%{public}s: CreateAniObject DeviceListenerObj failed", __func__); + return false; + } + ani_string stringValue = AniUtil::StdStringToANIString(env, type); + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "type", stringValue)) { + MMI_HILOGE("%{public}s: Object_SetPropertyByName_Ref failed", __func__); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "deviceId", reportData->deviceId)) { + MMI_HILOGE("%{public}s: SetPropertyByName deviceId:%{public}d failed", __func__, reportData->deviceId); + return false; + } + + MMI_HILOGE("%{public}s: type:%{public}s, deviceId:%{public}d", __func__, type.c_str(), reportData->deviceId); + args.push_back(obj); + + auto fnObj = reinterpret_cast(reportData->ref); + if (AniUtil::IsInstanceOf(env, "Lstd/core/Function1;", fnObj) == 0) { + MMI_HILOGE("%{public}s: fnObj is not instance Of function", __func__); + return false; + } + + ani_ref result; + if (ANI_OK != env->FunctionalObject_Call(fnObj, 1, args.data(), &result)) { + MMI_HILOGE("%{public}s: FunctionalObject_Call failed", __func__); + return false; + } + MMI_HILOGD("FunctionalObject_Call success"); + return true; +} + +void AniEventTarget::EmitAddedDeviceEvent(std::shared_ptr reportData) +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(mutex_); + auto addEvent = devListener_.find(CHANGED_TYPE); + if (addEvent == devListener_.end()) { + MMI_HILOGE("%{public}s: Find change event failed", __func__); + return; + } + for (const auto &item : addEvent->second) { + CHKPC(item->env); + if (item->ref != reportData->ref) { + continue; + } + + if (!EmitCallbackWork(item->env, reportData, ADD_EVENT)) { + continue; + } + + BytraceAdapter::StartDevListener(ADD_EVENT, reportData->deviceId); + MMI_HILOGI("Report device change task, event type:%{public}s, deviceid:%{public}d", + ADD_EVENT.c_str(), reportData->deviceId); + BytraceAdapter::StopDevListener(); + } +} + +void AniEventTarget::EmitRemoveDeviceEvent(std::shared_ptr reportData) +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(mutex_); + auto removeEvent = devListener_.find(CHANGED_TYPE); + if (removeEvent == devListener_.end()) { + MMI_HILOGE("%{public}s: Find change event failed", __func__); + return; + } + for (const auto &item : removeEvent->second) { + CHKPC(item->env); + if (item->ref != reportData->ref) { + continue; + } + + if (!EmitCallbackWork(item->env, reportData, REMOVE_EVENT)) { + continue; + } + + BytraceAdapter::StartDevListener(REMOVE_EVENT, reportData->deviceId); + MMI_HILOGI("Report device change task, event type:%{public}s, deviceid:%{public}d", + REMOVE_EVENT.c_str(), reportData->deviceId); + BytraceAdapter::StopDevListener(); + } +} + +void AniEventTarget::OnDeviceAdded(int32_t deviceId, const std::string &type) +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(mutex_); + auto changeEvent = devListener_.find(CHANGED_TYPE); + if (changeEvent == devListener_.end()) { + MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, CHANGED_TYPE.c_str()); + return; + } + + for (auto &item : changeEvent->second) { + CHKPC(item); + CHKPC(item->env); + auto reportData = std::make_shared(); + if (reportData == nullptr) { + MMI_HILOGE("%{public}s: Memory allocation failed", __func__); + return; + } + reportData->deviceId = deviceId; + reportData->ref = item->ref; + auto task = [reportData, this] () { EmitAddedDeviceEvent(reportData); }; + if (!AniUtil::SendEventToMainThread(task)) { + MMI_HILOGE("%{public}s: failed to send event", __func__); + } + } +} + +void AniEventTarget::OnDeviceRemoved(int32_t deviceId, const std::string &type) +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(mutex_); + auto changeEvent = devListener_.find(CHANGED_TYPE); + if (changeEvent == devListener_.end()) { + MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, CHANGED_TYPE.c_str()); + return; + } + for (auto &item : changeEvent->second) { + CHKPC(item); + CHKPC(item->env); + std::shared_ptr reportData = std::make_shared(); + if (reportData == nullptr) { + MMI_HILOGE("%{public}s: Memory allocation failed", __func__); + return; + } + reportData->deviceId = deviceId; + reportData->ref = item->ref; + auto task = [reportData, this] () { EmitRemoveDeviceEvent(reportData); }; + if (!AniUtil::SendEventToMainThread(task)) { + MMI_HILOGE("%{public}s: failed to send event", __func__); + } + } +} + +void AniEventTarget::AddListener(ani_env *env, const std::string &type, ani_object handle) +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(mutex_); + auto it = devListener_.find(type); + if (it == devListener_.end()) { + MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, CHANGED_TYPE.c_str()); + return; + } + + auto monitor = std::make_unique(); + monitor->env = env; + if (ANI_OK != env->GlobalReference_Create(handle, &monitor->ref)) { + MMI_HILOGE("%{public}s: Create global callback failed", __func__); + return; + } + + for (const auto &iter : it->second) { + CHKPC(iter); + if (AniUtil::IsSameHandle(env, monitor->ref, iter->env, iter->ref)) { + MMI_HILOGW("The handle already exists"); + return; + } + } + + it->second.push_back(std::move(monitor)); + if (!isListeningProcess_) { + isListeningProcess_ = true; + InputManager::GetInstance()->RegisterDevListener("change", shared_from_this()); + } +} + +void AniEventTarget::ResetEnv() +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(mutex_); + devListener_.clear(); + InputManager::GetInstance()->UnregisterDevListener("change", shared_from_this()); +} +} // namespace MMI +} // namespace OHOS diff --git a/frameworks/ani/input_device/src/ani_input_device_context.cpp b/frameworks/ani/input_device/src/ani_input_device_context.cpp new file mode 100644 index 0000000000..40a641c7e4 --- /dev/null +++ b/frameworks/ani/input_device/src/ani_input_device_context.cpp @@ -0,0 +1,786 @@ +/* + * 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. + */ + +#include "ani_input_device_context.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "define_multimodal.h" +#include "input_device.h" +#include "input_manager.h" +#include "mmi_log.h" +#include "napi_constants.h" +#include "oh_input_manager.h" + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "AniInputDeviceContext" + +using namespace OHOS::MMI; + +std::unordered_map axisType = { + { ABS_MT_TOUCH_MAJOR, "touchmajor" }, { ABS_MT_TOUCH_MINOR, "touchminor" }, { ABS_MT_ORIENTATION, "orientation" }, + { ABS_MT_POSITION_X, "x" }, { ABS_MT_POSITION_Y, "y" }, { ABS_MT_PRESSURE, "pressure" }, + { ABS_MT_WIDTH_MAJOR, "toolmajor" }, { ABS_MT_WIDTH_MINOR, "toolminor" }, +}; + + +constexpr uint32_t EVDEV_UDEV_TAG_TOUCHSCREEN = (1 << 4); +constexpr uint32_t EVDEV_UDEV_TAG_JOYSTICK = (1 << 6); +constexpr uint32_t EVDEV_UDEV_TAG_TRACKBALL = (1 << 10); + +AniUtil::DeviceType g_deviceType[] = { + { "keyboard", EVDEV_UDEV_TAG_KEYBOARD }, + { "mouse", EVDEV_UDEV_TAG_MOUSE }, + { "touchpad", EVDEV_UDEV_TAG_TOUCHPAD }, + { "touchscreen", EVDEV_UDEV_TAG_TOUCHSCREEN }, + { "joystick", EVDEV_UDEV_TAG_JOYSTICK }, + { "trackball", EVDEV_UDEV_TAG_TRACKBALL }, +}; + +static ani_error CreateAniError(ani_env *env, std::string &&errMsg) +{ + static const char *errorClsName = "Lescompat/Error;"; + ani_class cls{}; + if (ANI_OK != env->FindClass(errorClsName, &cls)) { + MMI_HILOGE("%{public}s: Not found namespace %{public}s.", __func__, errorClsName); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;:V", &ctor)) { + MMI_HILOGE("%{public}s: Not found in %{public}s.", __func__, errorClsName); + return nullptr; + } + ani_string error_msg; + env->String_NewUTF8(errMsg.c_str(), 17U, &error_msg); + ani_object errorObject; + env->Object_New(cls, ctor, &errorObject, error_msg); + return static_cast(errorObject); +} + +static bool SetID(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + double id = inputDevice->GetId(); + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "id", id)) { + MMI_HILOGE("Set id Failed"); + return false; + } + return true; +} + +static bool SetDeviceName(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + std::string name = inputDevice->GetName(); + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(name.data(), name.size(), &aniStr)) { + MMI_HILOGE("Create aniStr Failed"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "name", aniStr)) { + MMI_HILOGE("Set deviceName Failed"); + return false; + } + return true; +} + +static bool SetDeviceBus(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + int32_t bus = inputDevice->GetBus(); + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "bus", bus)) { + MMI_HILOGE("Set deviceBus Failed"); + return false; + } + return true; +} + +static bool SetDeviceVendor(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + int32_t vendor = inputDevice->GetVendor(); + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "vendor", vendor)) { + MMI_HILOGE("Set deviceVendor Failed"); + return false; + } + return true; +} + +static bool SetDeviceProduct(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + int32_t product = inputDevice->GetProduct(); + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "product", product)) { + MMI_HILOGE("Set deviceProduct Failed"); + return false; + } + return true; +} + +static bool SetDeviceVersion(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + int32_t version = inputDevice->GetVersion(); + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "version", version)) { + MMI_HILOGE("Set deviceVersion Failed"); + return false; + } + return true; +} + +static bool SetDeviceUniq(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + std::string uniq = inputDevice->GetUniq(); + ani_string aniUniq = nullptr; + if (ANI_OK != env->String_NewUTF8(uniq.data(), uniq.size(), &aniUniq)) { + MMI_HILOGE("Create aniUniq Failed"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "uniq", aniUniq)) { + MMI_HILOGE("Set uniq Failed"); + return false; + } + return true; +} + +static bool SetDevicePhys(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + std::string phys = inputDevice->GetPhys(); + ani_string aniPhys = nullptr; + if (ANI_OK != env->String_NewUTF8(phys.data(), phys.size(), &aniPhys)) { + MMI_HILOGE("Create aniUniq Failed"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "phys", aniPhys)) { + MMI_HILOGE("Set uniq Failed"); + return false; + } + return true; +} + +static ani_object StringArrayToObject(ani_env *env, const std::vector &values) +{ + ani_object arrayObj = nullptr; + ani_class arrayCls = nullptr; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + MMI_HILOGE("FindClass Lescompat/Array; Failed"); + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor)) { + MMI_HILOGE("Class_FindMethod Failed"); + return arrayObj; + } + + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size())) { + MMI_HILOGE("Object_New Array Faild"); + return arrayObj; + } + ani_size index = 0; + for (auto value : values) { + ani_string ani_str; + if (ANI_OK != env->String_NewUTF8(value.c_str(), value.size(), &ani_str)) { + MMI_HILOGE("String_NewUTF8 Faild "); + break; + } + if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_str)) { + MMI_HILOGE("Object_CallMethodByName_Void $_set Faild "); + break; + } + index++; + } + return arrayObj; +} + +static bool SetDeviceSources(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + ani_object arrayStringObj = nullptr; + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return false; + } + + uint32_t types = static_cast(inputDevice->GetType()); + std::vector sources; + for (const auto &item : g_deviceType) { + if (types & item.typeBit) { + sources.push_back(item.sourceTypeName); + } + } + + arrayStringObj = StringArrayToObject(env, sources); + if (arrayStringObj == nullptr) { + MMI_HILOGE("Create Sources arrayStringObj Failed"); + return false; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "sources", arrayStringObj)) { + MMI_HILOGE("Set uniq Failed"); + return false; + } + return true; +} + +static std::string EmptyAxisRangesSource(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return ""; + } + + if (inputDevice == nullptr) { + MMI_HILOGE("inputDevice is nullptr"); + return ""; + } + + std::string sourceType = nullptr; + uint32_t types = static_cast(inputDevice->GetType()); + for (const auto &item : g_deviceType) { + if (types & item.typeBit) { + sourceType = item.sourceTypeName; + break; + } + } + + if (sourceType.empty()) { + MMI_HILOGD("SourceType not found"); + ani_object arrayObj = nullptr; + ani_class arrayCls = nullptr; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + MMI_HILOGE("FindClass Lescompat/Array; Failed"); + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "", ":V", &arrayCtor)) { + MMI_HILOGE("Class_FindMethod Failed"); + return ""; + } + + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj)) { + MMI_HILOGE("Object_New Array Faild"); + return ""; + } + + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "axisRanges", arrayObj)) { + MMI_HILOGE("Set axisRanges Failed"); + } + } + return sourceType; +} + +static bool SetAxisRangesResolution(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "resolution", axisInfo.GetResolution())) { + MMI_HILOGE("Set AxisResolution Failed"); + return false; + } + return true; +} + +static bool SetAxisRangesFlat(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "flat", axisInfo.GetFlat())) { + MMI_HILOGE("Set AxisFlat Failed"); + return false; + } + return true; +} + +static bool SetAxisRangesFuzz(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "fuzz", axisInfo.GetFuzz())) { + MMI_HILOGE("Set AxisFuzz Failed"); + return false; + } + return true; +} + +static bool SetAxisRangesMax(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "max", axisInfo.GetMaximum())) { + MMI_HILOGE("Set AxisMax Failed"); + return false; + } + return true; +} + +static bool SetAxisRangesMin(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "min", axisInfo.GetMinimum())) { + MMI_HILOGE("Set AxisMin Failed"); + return false; + } + return true; +} + +static bool SetAxisRangesAxis(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + auto iter = axisType.find(axisInfo.GetAxisType()); + std::string axis = iter->second; + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(axis.data(), axis.size(), &aniStr)) { + MMI_HILOGE("Create aniStr Failed"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "axis", aniStr)) { + MMI_HILOGE("Set AxisRangesAxis Failed"); + return false; + } + return true; +} + +static bool SetAxisRangesSource(ani_env *env, ani_object obj, const std::string &sourceType) +{ + if (obj == nullptr) { + MMI_HILOGE("obj is nullptr"); + return false; + } + + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(sourceType.data(), sourceType.size(), &aniStr)) { + MMI_HILOGE("Create aniStr Failed"); + return false; + } + + if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "source", aniStr)) { + MMI_HILOGE("Set AxisRangesSource Failed"); + return false; + } + return true; +} + +static ani_object CreatAxisRangesObj(ani_env *env, const std::string &sourceType, const InputDevice::AxisInfo &axisInfo) +{ + ani_object AxisRangesObj = nullptr; + + ani_namespace ns{}; + if (ANI_OK != env->FindNamespace("L@ohos/multimodalInput/inputDevice/inputDevice;", &ns)) { + MMI_HILOGE("Not found namespace 'LinputDevice'"); + return AxisRangesObj; + } + + static const char *className = "LAxisRangeImpl;"; + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + MMI_HILOGE("Not found className %{public}s.", className); + return AxisRangesObj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", "J:V", &ctor)) { + MMI_HILOGE("get ctor Failed %{public}s.'", className); + return AxisRangesObj; + } + + int64_t nativePtr = 0; + if (ANI_OK != env->Object_New(cls, ctor, &AxisRangesObj, reinterpret_cast(nativePtr))) { + MMI_HILOGE("Create Object Failed %{public}s.", className); + return AxisRangesObj; + } + + if (!SetAxisRangesAxis(env, AxisRangesObj, axisInfo) || !SetAxisRangesSource(env, AxisRangesObj, sourceType) || + !SetAxisRangesMax(env, AxisRangesObj, axisInfo) || !SetAxisRangesMin(env, AxisRangesObj, axisInfo) || + !SetAxisRangesFuzz(env, AxisRangesObj, axisInfo) || !SetAxisRangesResolution(env, AxisRangesObj, axisInfo) || + !SetAxisRangesFlat(env, AxisRangesObj, axisInfo)) { + MMI_HILOGE("Set AxisRanges Failed"); + return AxisRangesObj; + } + return AxisRangesObj; +} + +static ani_object SetCreateArrayAxisRangesObj(ani_env *env, std::shared_ptr &inputDevice, + const std::string &sourceType) +{ + ani_object arrayAxisRangesObj = nullptr; + ani_class arrayCls = nullptr; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + MMI_HILOGE("FindClass Lescompat/Array; Failed"); + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "", ":V", &arrayCtor)) { + MMI_HILOGE("Class_FindMethod Failed"); + return arrayAxisRangesObj; + } + + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayAxisRangesObj)) { + MMI_HILOGE("Object_New Array Faild"); + return arrayAxisRangesObj; + } + + ani_size index = 0; + for (const auto &item : inputDevice->GetAxisInfo()) { + auto iter = axisType.find(item.GetAxisType()); + if (iter == axisType.end()) { + MMI_HILOGD("Find axisType failed"); + continue; + } + ani_object objAxisRanges = CreatAxisRangesObj(env, sourceType, item); + if (ANI_OK != env->Object_CallMethodByName_Void(arrayAxisRangesObj, "$_set", "ILstd/core/Object;:V", index, + objAxisRanges)) { + MMI_HILOGE("%{public}s Object_CallMethodByName_Void $_set Faild", __FUNCTION__); + return arrayAxisRangesObj; + } + index++; + } + MMI_HILOGI("Create CreateAxisRangesObj succeed."); + return arrayAxisRangesObj; +} + +static ani_object CreateDeviceInfoObj(ani_env *env, std::shared_ptr &inputDevice) +{ + ani_namespace ns{}; + if (ANI_OK != env->FindNamespace("L@ohos/multimodalInput/inputDevice/inputDevice;", &ns)) { + MMI_HILOGE("Not found namespace 'LinputDevice'"); + return nullptr; + } + + static const char *className = "LInputDeviceDataImpl;"; + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + MMI_HILOGE("Not found className %{public}s.", className); + return nullptr; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", "J:V", &ctor)) { + MMI_HILOGE("get ctor Failed %{public}s.'", className); + return nullptr; + } + ani_object inputDeviceDataObj = nullptr; + int64_t nativePtr = 0; + if (ANI_OK != env->Object_New(cls, ctor, &inputDeviceDataObj, reinterpret_cast(nativePtr))) { + MMI_HILOGE("Create Object Failed %{public}s.", className); + return nullptr; + } + + if (!SetID(env, inputDeviceDataObj, inputDevice) || !SetDeviceName(env, inputDeviceDataObj, inputDevice) || + !SetDeviceBus(env, inputDeviceDataObj, inputDevice) || !SetDeviceVendor(env, inputDeviceDataObj, inputDevice) || + !SetDeviceProduct(env, inputDeviceDataObj, inputDevice) || + !SetDeviceVersion(env, inputDeviceDataObj, inputDevice) || + !SetDeviceUniq(env, inputDeviceDataObj, inputDevice) || !SetDevicePhys(env, inputDeviceDataObj, inputDevice) || + !SetDeviceSources(env, inputDeviceDataObj, inputDevice)) { + MMI_HILOGE("Set DeviceInfoObj Failed"); + return nullptr; + } + + std::string sourceType = EmptyAxisRangesSource(env, inputDeviceDataObj, inputDevice); + if (!sourceType.empty()) { + MMI_HILOGD("Set Empty AxisRanges to axisRanges"); + SetCreateArrayAxisRangesObj(env, inputDevice, sourceType); + } + MMI_HILOGI("Create DeviceInfoObj succeed."); + return inputDeviceDataObj; +} + +static ani_object DoubleToObject(ani_env *env, double value) +{ + ani_object aniObject = nullptr; + ani_double doubleValue = static_cast(value); + static const char *className = "Lstd/core/Double;"; + ani_class aniClass; + if (ANI_OK != env->FindClass(className, &aniClass)) { + MMI_HILOGE("Not found '%{public}s'.", className); + return aniObject; + } + ani_method objCtor; + if (ANI_OK != env->Class_FindMethod(aniClass, "", "D:V", &objCtor)) { + MMI_HILOGE("Class_GetMethod Failed '%{public}s .'", className); + return aniObject; + } + + if (ANI_OK != env->Object_New(aniClass, objCtor, &aniObject, doubleValue)) { + MMI_HILOGE("Object_New Failed '%{public}s. ", className); + return aniObject; + } + return aniObject; +} + +static ani_object DoubleArrayToObject(ani_env *env, const std::shared_ptr> &ids) +{ + ani_object arrayObj = nullptr; + ani_class arrayCls = nullptr; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + MMI_HILOGE("FindClass Lescompat/Array; Failed"); + return arrayObj; + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor)) { + MMI_HILOGE("Class_FindMethod Failed"); + return arrayObj; + } + + if (ids == nullptr) { + MMI_HILOGE("ids is null"); + return arrayObj; + } + size_t size = ids->size(); + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, size)) { + MMI_HILOGE("Object_New Array Faild"); + return arrayObj; + } + ani_int index = 0; + for (auto id : *ids) { + ani_object aniValue = DoubleToObject(env, id); + if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniValue)) { + MMI_HILOGI("Object_CallMethodByName_Void $_set Faild "); + break; + } + index++; + } + return arrayObj; +} + +static std::string AniStringToString(ani_env *env, ani_string aniStr) +{ + ani_size strSize; + env->String_GetUTF8Size(aniStr, &strSize); + + std::vector buffer(strSize + 1); + char *utf8Buffer = buffer.data(); + + ani_size bytes_written = 0; + env->String_GetUTF8(aniStr, utf8Buffer, strSize + 1, &bytes_written); + + utf8Buffer[bytes_written] = '\0'; + std::string content = std::string(utf8Buffer); + return content; +} + +static ani_object GetDeviceList(ani_env *env) +{ + std::shared_ptr> deviceIds = std::make_shared>(); + auto callback = [deviceIds](std::vector &ids) { deviceIds->assign(ids.begin(), ids.end()); }; + InputManager::GetInstance()->GetDeviceIds(callback); + + ani_object object = DoubleArrayToObject(env, deviceIds); + return object; +} + +static ani_object GetDeviceInfo(ani_env *env, ani_double deviceId) +{ + std::shared_ptr inputDevice = nullptr; + InputManager::GetInstance()->GetDevice(deviceId, [&](std::shared_ptr device) { + inputDevice = device; + }); + + if (inputDevice == nullptr) { + MMI_HILOGE("Get DeviceInfo Failed"); + return nullptr; + } + + ani_object object = CreateDeviceInfoObj(env, inputDevice); + return object; +} + +std::shared_ptr g_inputDeviceContext = nullptr; + +AniInputDeviceContext::AniInputDeviceContext() +{ + CALL_DEBUG_ENTER; + mgr_ = std::make_shared(); +} + +AniInputDeviceContext::~AniInputDeviceContext() +{ + CALL_DEBUG_ENTER; + std::lock_guard guard(mtx_); + auto aniInputDeviceMgr = mgr_; + mgr_.reset(); + if (aniInputDeviceMgr) { + aniInputDeviceMgr->ResetEnv(); + } +} + +void AniInputDeviceContext::On(ani_env *env, ani_string aniStr, ani_object callback) +{ + CALL_DEBUG_ENTER; + std::string type = AniStringToString(env, aniStr); + if (type != CHANGED_TYPE) { + MMI_HILOGE("%{public}s: Type is not change", __func__); + ani_error error = CreateAniError(env, "type must be change"); + env->ThrowError(error); + return; + } + if (mgr_ == nullptr) { + MMI_HILOGE("%{public}s: aniInputDeviceMgr is nullptr", __func__); + ani_error error = CreateAniError(env, "aniInputDeviceMgr must be created"); + env->ThrowError(error); + return; + } + mgr_->RegisterDevListener(env, type, callback); +} + +static void OnChange(ani_env *env, ani_string aniStr, ani_object callback) +{ + CALL_DEBUG_ENTER; + if (g_inputDeviceContext == nullptr) { + MMI_HILOGE("%{public}s: g_inputDeviceContext is nullptr", __func__); + return; + } + g_inputDeviceContext->On(env, aniStr, callback); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + MMI_HILOGD("%{public}s: enter ANI_Constructor", __func__); + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + MMI_HILOGE("%{public}s: Unsupported ANI_VERSION_1", __func__); + return ANI_ERROR; + } + + static const char *name = "L@ohos/multimodalInput/inputDevice/inputDevice;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(name, &ns)) { + MMI_HILOGE("%{public}s: Not found %{public}s", __func__, name); + return ANI_NOT_FOUND; + } + + std::array methods = { + ani_native_function{ "getDeviceListInner", nullptr, reinterpret_cast(GetDeviceList) }, + ani_native_function{ "getDeviceInfoInner", nullptr, reinterpret_cast(GetDeviceInfo) }, + ani_native_function{ "on", nullptr, reinterpret_cast(OnChange) }, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { + MMI_HILOGE("%{public}s:Cannot bind native methods to '%{public}s'", __func__, name); + return ANI_ERROR; + }; + + g_inputDeviceContext = std::make_shared(); + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ani/input_device/src/ani_input_device_manager.cpp b/frameworks/ani/input_device/src/ani_input_device_manager.cpp new file mode 100644 index 0000000000..6a9f6a39a7 --- /dev/null +++ b/frameworks/ani/input_device/src/ani_input_device_manager.cpp @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#include "ani_input_device_manager.h" + +#include "input_device_impl.h" + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "AniInputDeviceManager" + +namespace OHOS { +namespace MMI { + +void AniInputDeviceManager::RegisterDevListener(ani_env *env, const std::string &type, ani_object handle) +{ + CALL_DEBUG_ENTER; + AddListener(env, type, handle); +} + +void AniInputDeviceManager::ResetEnv() +{ + CALL_DEBUG_ENTER; + AniEventTarget::ResetEnv(); +} +} // namespace MMI +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ani/input_device/src/ani_util.cpp b/frameworks/ani/input_device/src/ani_util.cpp new file mode 100644 index 0000000000..7cb0a77097 --- /dev/null +++ b/frameworks/ani/input_device/src/ani_util.cpp @@ -0,0 +1,129 @@ +/* + * 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. + */ + +#include "ani_util.h" + +#include +#include + +#include "event_handler.h" +#include "mmi_log.h" +#include "napi_constants.h" + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "AniUtil" + +namespace OHOS { +namespace MMI { +namespace { + +constexpr uint32_t EVDEV_UDEV_TAG_TOUCHSCREEN = (1 << 4); +constexpr uint32_t EVDEV_UDEV_TAG_JOYSTICK = (1 << 6); +constexpr uint32_t EVDEV_UDEV_TAG_TRACKBALL = (1 << 10); + +AniUtil::DeviceType g_deviceType[] = { + { "keyboard", EVDEV_UDEV_TAG_KEYBOARD }, + { "mouse", EVDEV_UDEV_TAG_MOUSE }, + { "touchpad", EVDEV_UDEV_TAG_TOUCHPAD }, + { "touchscreen", EVDEV_UDEV_TAG_TOUCHSCREEN }, + { "joystick", EVDEV_UDEV_TAG_JOYSTICK }, + { "trackball", EVDEV_UDEV_TAG_TRACKBALL }, +}; +} // namespace + +bool AniUtil::IsSameHandle(ani_env *env, ani_ref handle, ani_env *iterEnv, ani_ref iterhandle) +{ + if (env != iterEnv) { + MMI_HILOGD("%{public}s: not the same env", __func__); + return false; + } + ani_boolean isEquals = false; + if (ANI_OK != env->Reference_StrictEquals(handle, iterhandle, &isEquals)) { + MMI_HILOGD("%{public}s: check observer equal failed!", __func__); + return false; + } + return isEquals; +} + +ani_string AniUtil::StdStringToANIString(ani_env* env, const std::string& str) +{ + ani_string stringAni = nullptr; + if (ANI_OK != env->String_NewUTF8(str.c_str(), str.size(), &stringAni)) { + MMI_HILOGD("%{public}s: String_NewUTF8 Failed", __func__); + } + return stringAni; +} + +ani_boolean AniUtil::IsInstanceOf(ani_env *env, const std::string &cls_name, ani_object obj) +{ + ani_class cls; + if (ANI_OK != env->FindClass(cls_name.c_str(), &cls)) { + MMI_HILOGE("%{public}s: FindClass failed", __func__); + return ANI_FALSE; + } + + ani_boolean ret; + env->Object_InstanceOf(obj, cls, &ret); + return ret; +} + +bool AniUtil::SendEventToMainThread(const std::function func) +{ + CALL_DEBUG_ENTER; + if (func == nullptr) { + MMI_HILOGE("%{public}s: func == nullptr", __func__); + return false; + } + std::shared_ptr runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + MMI_HILOGE("%{public}s: runner == nullptr", __func__); + return false; + } + std::shared_ptr handler = std::make_shared(runner); + handler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {}); + MMI_HILOGD("%{public}s: PostTask success", __func__); + return true; +} + +ani_object AniUtil::CreateAniObject(ani_env *env, const char *nsName, const char *className) +{ + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + MMI_HILOGE("%{public}s: Not found %{public}s", __func__, nsName); + return nullptr; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + MMI_HILOGE("%{public}s: Namespace_FindClass %{public}s failed", __func__, className); + return nullptr; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + MMI_HILOGE("%{public}s: Class_FindMethod 'constructor' failed", __func__); + return nullptr; + } + + ani_object obj; + if (ANI_OK != env->Object_New(cls, ctor, &obj)) { + MMI_HILOGE("%{public}s: Object_New ani_object failed", __func__); + return nullptr; + } + return obj; +} + +} // namespace MMI +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/ani/pointer/BUILD.gn b/frameworks/ani/pointer/BUILD.gn new file mode 100644 index 0000000000..00439159fe --- /dev/null +++ b/frameworks/ani/pointer/BUILD.gn @@ -0,0 +1,84 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("../../../multimodalinput_mini.gni") + +ohos_shared_library("ani_pointer") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + configs = [ "${mmi_path}:coverage_flags" ] + + cflags_cc = [ + "-Wno-unused-function", + "-Wno-unused-const-variable", + ] + sources = [ "src/pointer.cpp" ] + + include_dirs = [ + "include", + "${mmi_path}/util/common/include", + "${mmi_path}/tools/event_inject/include", + "${mmi_path}/interfaces/native/innerkits/proxy/include", + ] + + deps = [ + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + + external_deps = [ + "c_utils:utils", + "eventhandler:libeventhandler", + "hilog:libhilog", + "ipc:ipc_core", + "runtime_core:ani", + ] + + subsystem_name = "multimodalinput" + part_name = "input" + output_extension = "so" +} + +generate_static_abc("pointer_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.multimodalInput.pointer.ets" ] + dst_file = "$target_out_dir/pointer.abc" + out_puts = [ "$target_out_dir/pointer.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/pointer.abc" +} + +ohos_prebuilt_etc("pointer_abc_etc") { + source = "$target_out_dir/pointer.abc" + module_install_dir = "framework" + subsystem_name = "multimodalinput" + part_name = "input" + deps = [ ":pointer_abc" ] +} + +group("ani_pointer_package") { + deps = [ + ":ani_pointer", + ":pointer_abc_etc", + ] +} diff --git a/frameworks/ani/pointer/ets/@ohos.multimodalInput.pointer.ets b/frameworks/ani/pointer/ets/@ohos.multimodalInput.pointer.ets new file mode 100644 index 0000000000..7e20f0bfea --- /dev/null +++ b/frameworks/ani/pointer/ets/@ohos.multimodalInput.pointer.ets @@ -0,0 +1,399 @@ +/* + * 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. + */ + +import hilog from '@ohos.hilog' +import { AsyncCallback } from "@ohos.base" +import { BusinessError } from "@ohos.base" + +export namespace pointer { + loadLibrary("ani_pointer"); + + export native function setPointerStyleInner(windowId: number, pointerStyle: PointerStyle): int; + + export enum PointerStyle { + DEFAULT, + EAST, + WEST, + SOUTH, + NORTH, + + /** + * East-west arrow + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + WEST_EAST, + + /** + * North-south arrow + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + NORTH_SOUTH, + + /** + * North-east arrow + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + NORTH_EAST, + + /** + * North-west arrow + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + NORTH_WEST, + + /** + * South-east arrow + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + SOUTH_EAST, + + /** + * South-west arrow + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + SOUTH_WEST, + + /** + * Northeast and southwest adjustment + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + NORTH_EAST_SOUTH_WEST, + + /** + * Northwest and southeast adjustment + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + NORTH_WEST_SOUTH_EAST, + + /** + * Cross (accurate selection) + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + CROSS, + + /** + * Copy + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + CURSOR_COPY, + + /** + * Forbid + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + CURSOR_FORBID, + + /** + * Sucker + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + COLOR_SUCKER, + + /** + * Grabbing hand + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + HAND_GRABBING, + + /** + * Opening hand + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + HAND_OPEN, + + /** + * Hand-shaped pointer + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + HAND_POINTING, + + /** + * Help + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + HELP, + + /** + * Move + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MOVE, + + /** + * Left and right resizing + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + RESIZE_LEFT_RIGHT, + + /** + * Up and down resizing + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + RESIZE_UP_DOWN, + + /** + * Screenshot crosshair + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + SCREENSHOT_CHOOSE, + + /** + * Screenshot + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + SCREENSHOT_CURSOR, + + /** + * Text selection + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + TEXT_CURSOR, + + /** + * Zoom in + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + ZOOM_IN, + + /** + * Zoom out + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + ZOOM_OUT, + + /** + * Scrolling east + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_EAST, + + /** + * Scrolling west + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_WEST, + + /** + * Scrolling south + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_SOUTH, + + /** + * Scrolling north + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_NORTH, + + /** + * Scrolling north and south + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_NORTH_SOUTH, + + /** + * Scrolling northeast + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_NORTH_EAST, + + /** + * Scrolling northwest + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_NORTH_WEST, + + /** + * Scrolling southeast + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_SOUTH_EAST, + + /** + * Scrolling southwest + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_SOUTH_WEST, + + /** + * Moving as a cone in four directions + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 9 + */ + MIDDLE_BTN_NORTH_SOUTH_WEST_EAST, + + /** + * Horizontal text selection + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 10 + */ + HORIZONTAL_TEXT_CURSOR, + + /** + * Precise selection + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 10 + */ + CURSOR_CROSS, + + /** + * Cursor with circle style + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 10 + */ + CURSOR_CIRCLE, + + /** + * Loading state with dynamic cursor + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 10 + */ + /** + * Loading state with dynamic cursor + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @atomicservice + * @since 12 + */ + LOADING, + + /** + * Running state with dynamic cursor + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 10 + */ + /** + * Running state with dynamic cursor + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @atomicservice + * @since 12 + */ + RUNNING, + + /** + * Scrolling east and west + * + * @syscap SystemCapability.MultimodalInput.Input.Pointer + * @since 16 + */ + MIDDLE_BTN_EAST_WEST + } + + export function setPointerStyle(windowId: number, pointerStyle: PointerStyle, callback: AsyncCallback): void { + let p1 = taskpool.execute(setPointerStyleInner, windowId, pointerStyle); + p1.then((data: NullishType) => { + let ret = data as int; + hilog.info(0x0000, 'pointer', "setPointerStyleInner callback then. ret is " + ret); + let err : BusinessError + callback(err, undefined); + }).catch((error: NullishType) => { + let err = error as BusinessError; + hilog.info(0x0000, 'pointer', "setPointerStyleInner err is " + err); + callback(err, undefined); + }); + } + + export function setPointerStyle(windowId: number, pointerStyle: PointerStyle): Promise { + let p = new Promise((resolve: (v: undefined) => void, + reject: (error: Object) => void) : void => { + let p1 = taskpool.execute(setPointerStyleInner, windowId, pointerStyle); + p1.then((e :NullishType) : void=>{ + let r = e as int; + hilog.info(0x0000, 'pointer', "setPointerStyleInner Promise, ret is: " + r); + resolve(undefined); + }).catch((err: Error) : void => { + reject(err); + }); + }); + return p; + } + + export function setPointerStyleSync(windowId: number, pointerStyle: PointerStyle): void { + setPointerStyleInner(windowId, pointerStyle); + } +} \ No newline at end of file diff --git a/frameworks/ani/pointer/include/ani_utils.h b/frameworks/ani/pointer/include/ani_utils.h new file mode 100644 index 0000000000..790c86f936 --- /dev/null +++ b/frameworks/ani/pointer/include/ani_utils.h @@ -0,0 +1,497 @@ +/* +* 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +class AniObjectUtils { +public: + // 创建一个ani_object对象,使用命名空间和类名 + static ani_object Create(ani_env *env, const char* nsName, const char* clsName, ...) + { + // 创建一个空的对象 + ani_object nullobj{}; + + // 查找命名空间 + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + return nullobj; + } + + // 查找类 + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, const char* clsName, ...) + { + ani_object nullobj{}; + // 查找类 + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + return nullobj; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, ani_class cls, ...) + { + ani_object nullobj{}; + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_object From(ani_env *env, bool value) + { + return Create(env, "Lstd/core/Boolean;", static_cast(value)); + } + + template + static ani_status Wrap(ani_env *env, ani_object object, T* nativePtr, const char* propName = "nativePtr") + { + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast(nativePtr)); + } + + template + static T* Unwrap(ani_env *env, ani_object object, const char* propName = "nativePtr") + { + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + if (nativePtr == 0) { + return nullptr; + } + return reinterpret_cast(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str) + { + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector buffer(strSize + 1); // +1 for null terminator + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; + } + + static ani_string ToAni(ani_env* env, const std::string& str) + { + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + return nullptr; + } + return aniStr; + } +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + } + + bool IsInstanceOf(const std::string& cls_name) + { + ani_class cls; + env_->FindClass(cls_name.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + return ret; + } + + template + bool IsInstanceOfType(); + + template + bool TryConvert(T &value); + + template + bool TryConvertArray(std::vector &value); + +private: + ani_env *env_; + ani_object obj_; +}; + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template<> +bool UnionAccessor::TryConvert(bool &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert(int &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert(double &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert(std::string &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast(obj_)); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + return false; + } + ani_boolean val; + if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast(ref), "unboxed", nullptr, &val)) { + return false; + } + value.push_back(static_cast(val)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + return false; + } + ani_int intValue; + if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast(ref), "unboxed", nullptr, &intValue)) { + return false; + } + value.push_back(static_cast(intValue)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + return false; + } + ani_double val; + if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast(ref), "unboxed", nullptr, &val)) { + return false; + } + value.push_back(static_cast(val)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + return false; + } + void* data; + size_t length; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &length)) { + return false; + } + + for (size_t i = 0; i < length; i++) { + value.push_back(static_cast(data)[i]); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + return false; + } + value.push_back(AniStringUtils::ToStd(env_, static_cast(ref))); + } + return true; +} + +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + } + + bool IsUndefined() + { + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + return isUndefined; + } + + template + std::optional Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + auto value = static_cast(aniValue); + return value; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_size strSize; + env_->String_GetUTF8Size(static_cast(obj_), &strSize); + + std::vector buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env_->String_GetUTF8(static_cast(obj_), utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; +} + + +class EnumAccessor { +public: + EnumAccessor(ani_env *env, const char* className, ani_int index) : env_(env), className_(className), index_(index) + { + } + + ani_status ToInt(int32_t &value) + { + ani_status status = ANI_ERROR; + ani_enum_item item; + status = GetItem(item); + if (ANI_OK != status) { + return status; + } + + status = env_->EnumItem_GetValue_Int(item, &value); + if (ANI_OK != status) { + return status; + } + return ANI_OK; + } + + ani_status ToString(std::string &value) + { + ani_status status = ANI_ERROR; + ani_enum_item item; + status = GetItem(item); + if (ANI_OK != status) { + return status; + } + + ani_string strValue; + status = env_->EnumItem_GetValue_String(item, &strValue); + if (ANI_OK != status) { + return status; + } + value = AniStringUtils::ToStd(env_, strValue); + + return ANI_OK; + } + +private: + ani_status GetItem(ani_enum_item &item) + { + ani_status status = ANI_ERROR; + ani_enum enumType; + status = env_->FindEnum(className_.c_str(), &enumType); + if (ANI_OK != status) { + return status; + } + + status = env_->Enum_GetEnumItemByIndex(enumType, index_, &item); + if (ANI_OK != status) { + return status; + } + return ANI_OK; + } + +private: + ani_env *env_; + std::string className_; + ani_int index_; +}; +#endif diff --git a/frameworks/ani/pointer/include/pointer.h b/frameworks/ani/pointer/include/pointer.h new file mode 100644 index 0000000000..d33ff877eb --- /dev/null +++ b/frameworks/ani/pointer/include/pointer.h @@ -0,0 +1,32 @@ + /* + * 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 ANI_MULTI_MODAL_INPUT_POINTER_H +#define ANI_MULTI_MODAL_INPUT_POINTER_H + +#include +#include +#include +#include +#include +#include + +#define SUCCESS_CODE 0 +#define ERROR_CODE (-1) +#define UNREGISTERED_CODE (-2) +#define PRE_KEY_MAX_COUNT 4 + + +#endif // ANI_MULTI_MODAL_INPUT_POINTER_H diff --git a/frameworks/ani/pointer/src/pointer.cpp b/frameworks/ani/pointer/src/pointer.cpp new file mode 100644 index 0000000000..4c6cca56ea --- /dev/null +++ b/frameworks/ani/pointer/src/pointer.cpp @@ -0,0 +1,149 @@ + /* + * 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. + */ + +#include "pointer.h" +#include + +#include "define_multimodal.h" +#include "input_manager.h" +#include "mmi_log.h" + +#include +#include +#include + +#undef MMI_LOG_TAG +#define MMI_LOG_TAG "AniPointer" + +using namespace OHOS::MMI; + +namespace { +constexpr int32_t ANI_SCOPE_SIZE = 16; +constexpr int32_t MILLISECOND_FACTOR = 1000; +constexpr size_t EVENT_NAME_LEN { 64 }; +constexpr size_t PRE_KEYS_SIZE { 4 }; +constexpr size_t INPUT_PARAMETER_MIDDLE { 2 }; +constexpr size_t INPUT_PARAMETER_MAX { 3 }; +constexpr int32_t OCCUPIED_BY_SYSTEM = -3; +constexpr int32_t OCCUPIED_BY_OTHER = -4; +const double INT32_MAX_D = static_cast(std::numeric_limits::max()); +} // namespace + +enum NapiErrorCode : int32_t { + COMMON_PARAMETER_ERROR = 401, + COMMON_USE_SYSAPI_ERROR = 202, +}; + +static ani_error CreateAniError(ani_env *env, std::string&& errMsg) +{ + static const char *errorClsName = "Lescompat/Error;"; + ani_class cls {}; + if (ANI_OK != env->FindClass(errorClsName, &cls)) { + MMI_HILOGE("%{public}s: Not found namespace %{public}s.", __func__, errorClsName); + return nullptr; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;:V", &ctor)) { + MMI_HILOGE("%{public}s: Not found in %{public}s.", __func__, errorClsName); + return nullptr; + } + ani_string error_msg; + env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &error_msg); + ani_object errorObject; + env->Object_New(cls, ctor, &errorObject, error_msg); + return static_cast(errorObject); +} + +int32_t ToInt32ECMAScript(double value) +{ + if (std::isnan(value) || std::isinf(value)) { + return 0; + } + + double truncated = std::trunc(value); + double modValue = std::fmod(truncated, 4294967296.0); + uint32_t uint32Val = static_cast(modValue); + return static_cast(uint32Val); +} + +static ani_int ParseEnumToInt(ani_env *env, ani_enum_item enumItem) +{ + ani_int intValue = -1; + if (ANI_OK != env->EnumItem_GetValue_Int(enumItem, &intValue)) { + MMI_HILOGE("%{public}s: EnumItem_GetValue_Int FAILD.", __func__); + return -1; + } + MMI_HILOGD("%{public}s: Enum Value: %{public}d.", __func__, intValue); + return intValue; +} + +static int SetPointerStyleInner(ani_env *env, ani_double windowid, ani_enum_item pointerStyle) +{ + int32_t windowID = ToInt32ECMAScript(static_cast(windowid)); + if (windowID < 0 && windowID != GLOBAL_WINDOW_ID) { + MMI_HILOGE("Invalid windowid"); + ani_error err = CreateAniError(env, "Windowid is invalid"); + env->ThrowError(err); + return COMMON_PARAMETER_ERROR; + } + + int32_t pointerStyleID = ParseEnumToInt(env, pointerStyle); + if ((pointerStyleID < DEFAULT && pointerStyleID != DEVELOPER_DEFINED_ICON) || pointerStyleID > RUNNING) { + MMI_HILOGE("Undefined pointer style"); + ani_error err = CreateAniError(env, "Pointer style does not exist"); + env->ThrowError(err); + return COMMON_PARAMETER_ERROR; + } + + PointerStyle style; + style.id = pointerStyleID; + int32_t errorCode = InputManager::GetInstance()->SetPointerStyle(windowid, style); + if (errorCode == COMMON_USE_SYSAPI_ERROR) { + MMI_HILOGE("The windowId is negative number and no system applications use system API"); + ani_error err = CreateAniError(env, "windowId is negative number and no system applications use system API"); + env->ThrowError(err); + return COMMON_USE_SYSAPI_ERROR; + } + MMI_HILOGD(" SetPointerStyleInner end."); + return 0; +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + MMI_HILOGE("%{public}s: Unsupported ANI_VERSION_1", __func__); + return ANI_ERROR; + } + + static const char *name = "L@ohos/multimodalInput/pointer/pointer;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(name, &ns)) { + MMI_HILOGE("%{public}s: Not found %{public}s", __func__, name); + return ANI_NOT_FOUND; + } + + std::array methods = { + ani_native_function {"setPointerStyleInner", nullptr, reinterpret_cast(SetPointerStyleInner)}, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { + MMI_HILOGE("%{public}s:Cannot bind native methods to '%{public}s'", __func__, name); + return ANI_ERROR; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file -- Gitee From b4aa8becb2e36bc9705dba39e79b37f767d2465b Mon Sep 17 00:00:00 2001 From: Philipp Shemetov Date: Thu, 17 Apr 2025 18:16:42 +0300 Subject: [PATCH 02/13] Change interface of Promise Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/IC1PKR Testing: All required pre-merge tests passed. Results are available in the ggwatcher. Change-Id: Idd2199f305d78b682b1f0272fa732bb0af561c78 Signed-off-by: Philipp Shemetov --- .../input_device/ets/@ohos.multimodalInput.inputDevice.ets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets b/frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets index 1bc3719902..b7a5bb9915 100644 --- a/frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets +++ b/frameworks/ani/input_device/ets/@ohos.multimodalInput.inputDevice.ets @@ -382,7 +382,7 @@ export namespace inputDevice { function getDeviceList(): Promise> { let p = new Promise>((resolve: (v: Array) => void, - reject: (error: Object) => void) => { + reject: (error: Error) => void) => { let p1 = taskpool.execute(getDeviceListInner); p1.then((e :NullishType)=>{ let r = e as Array; @@ -408,7 +408,7 @@ export namespace inputDevice { } function getDeviceInfo(deviceId: number): Promise { let p = new Promise((resolve: (v: InputDeviceData) => void, - reject: (error: Object) => void) => { + reject: (error: Error) => void) => { let p1 = taskpool.execute(getDeviceInfoInner, deviceId); p1.then((e :NullishType)=>{ let r = e as InputDeviceData; -- Gitee From e9c4d1d5482bb03bd1a993bba52a9120c2032863 Mon Sep 17 00:00:00 2001 From: xying6 Date: Thu, 17 Apr 2025 17:33:37 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E6=A8=A1?= =?UTF-8?q?=E8=BE=93=E5=85=A5input=5Fconsumer=E5=9B=9E=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xying6 Change-Id: Ia5e45820c69d3bebbd0f48d7a036bd177d7a8ace --- .../input_consumer/include/ani_util_common.h | 189 ++++++++++++++++ .../input_consumer/include/input_consumer.h | 77 ++++++- .../ani/input_consumer/src/input_consumer.cpp | 208 ++++++++++-------- 3 files changed, 376 insertions(+), 98 deletions(-) create mode 100644 frameworks/ani/input_consumer/include/ani_util_common.h diff --git a/frameworks/ani/input_consumer/include/ani_util_common.h b/frameworks/ani/input_consumer/include/ani_util_common.h new file mode 100644 index 0000000000..c398acf0a0 --- /dev/null +++ b/frameworks/ani/input_consumer/include/ani_util_common.h @@ -0,0 +1,189 @@ +/* + * 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 ANI_UTIL_COMMON_H +#define ANI_UTIL_COMMON_H + +#include +#include +#include +#include +#include + +template +class expected { +private: + std::variant data_; + bool has_value_; + +public: + expected(const T &value) + : data_(value), has_value_(true) + { + } + + expected(T &&value) + : data_(std::move(value)), has_value_(true) + { + } + + expected(const E &error) + : data_(error), has_value_(false) + { + } + + expected(E &&error) + : data_(std::move(error)), has_value_(false) + { + } + + bool has_value() const noexcept + { + return has_value_; + } + + explicit operator bool() const noexcept + { + return has_value(); + } + + T &value() & + { + if (!has_value()) { + std::terminate(); + } + return std::get(data_); + } + + const T &value() const & + { + if (!has_value()) { + std::terminate(); + } + return std::get(data_); + } + + T &&value() && + { + if (!has_value()) { + std::terminate(); + } + return std::get(std::move(data_)); + } + + E &error() & + { + if (has_value()) { + std::terminate(); + } + return std::get(data_); + } + + const E &error() const & + { + if (has_value()) { + std::terminate(); + } + return std::get(data_); + } + + E &&error() && + { + if (has_value()) { + std::terminate(); + } + return std::get(std::move(data_)); + } + + T &operator*() & + { + return value(); + } + + const T &operator*() const & + { + return value(); + } + + T &&operator*() && + { + return std::move(*this).value(); + } + + T *operator->() + { + return &value(); + } + + const T *operator->() const + { + return &value(); + } + + template + T value_or(U &&default_value) const & + { + return has_value() ? value() : static_cast(std::forward(default_value)); + } + + template + T value_or(U &&default_value) && + { + return has_value() ? std::move(*this).value() : static_cast(std::forward(default_value)); + } +}; + + +template +class FinalAction { +public: + explicit FinalAction(F func) : func_(std::move(func)) + { + } + + ~FinalAction() noexcept(noexcept(func_())) + { + if (!dismissed_) { + func_(); + } + } + + FinalAction(const FinalAction&) = delete; + FinalAction& operator=(const FinalAction&) = delete; + + FinalAction(FinalAction&& other) noexcept + : func_(std::move(other.func_)), + dismissed_(other.dismissed_) + { + other.dismissed_ = true; + } + + void dismiss() noexcept + { + dismissed_ = true; + } + +private: + F func_; + bool dismissed_ = false; +}; + +template +inline FinalAction finally(F&& func) +{ + return FinalAction(std::forward(func)); +} + +#endif diff --git a/frameworks/ani/input_consumer/include/input_consumer.h b/frameworks/ani/input_consumer/include/input_consumer.h index 2ec895ce4f..7be3a535cd 100644 --- a/frameworks/ani/input_consumer/include/input_consumer.h +++ b/frameworks/ani/input_consumer/include/input_consumer.h @@ -23,6 +23,7 @@ #include #include +#include "ani_util_common.h" #include "key_option.h" #define SUCCESS_CODE 0 @@ -42,15 +43,35 @@ namespace MMI { struct KeyEventMonitorInfo { ani_env* env = nullptr; + ani_vm *vm = nullptr; std::string eventType; std::string name; ani_ref callback = nullptr; int32_t subscribeId = 0; ani_ref keyOptionsObj = nullptr; std::shared_ptr keyOption = nullptr; + bool setCallback(ani_object callback); + bool SetKeyOptionsObj(ani_object keyOptionsObj); ~KeyEventMonitorInfo(); }; +enum AniErrorCode : int32_t { + OTHER_ERROR = -1, + COMMON_PERMISSION_CHECK_ERROR = 201, + COMMON_PARAMETER_ERROR = 401, + COMMON_USE_SYSAPI_ERROR = 202, + INPUT_DEVICE_NOT_SUPPORTED = 801, + INPUT_OCCUPIED_BY_SYSTEM = 4200002, + INPUT_OCCUPIED_BY_OTHER = 4200003, + PRE_KEY_NOT_SUPPORTED = 4100001, + COMMON_DEVICE_NOT_EXIST = 3900001, + COMMON_KEYBOARD_DEVICE_NOT_EXIST = 3900002, + COMMON_NON_INPUT_APPLICATION = 3900003, + ERROR_WINDOW_ID_PERMISSION_DENIED = 26500001, +}; + +typedef std::map>> Callbacks; + class AniLocalScopeGuard { public: AniLocalScopeGuard(ani_env *env, size_t nrRefs) : env_(env) @@ -80,7 +101,61 @@ private: ani_env *env_ = nullptr; ani_status status_ = ANI_ERROR; }; -typedef std::map>> Callbacks; + +class ScopedAniEnv { +public: + static expected, ani_status> Create(ani_vm *vm) + { + ani_env *env = nullptr; + ani_options aniArgs {0, nullptr}; + auto status = vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env); + if (ANI_OK != status) { + status = vm->GetEnv(ANI_VERSION_1, &env); + if (ANI_OK != status) { + return status; + } + } + + auto scopedAniEnv = new ScopedAniEnv(vm, env); + return std::unique_ptr(scopedAniEnv); + } + + static expected, ani_status> Create(ani_env *env) + { + ani_vm *vm = nullptr; + auto status = env->GetVM(&vm); + if (ANI_OK != status) { + return status; + } + return Create(vm); + } + + ~ScopedAniEnv() + { + if (vm_) { + vm_->DetachCurrentThread(); + vm_ = nullptr; + } + env_ = nullptr; + } + + ani_env *GetEnv() + { + return env_; + } + + ScopedAniEnv(const ScopedAniEnv&) = delete; + ScopedAniEnv& operator=(const ScopedAniEnv&) = delete; + +private: + ScopedAniEnv(ani_vm *vm, ani_env *env) : vm_(vm), env_(env) + { + } + +private: + ani_vm *vm_ = nullptr; + ani_env *env_ = nullptr; +}; } // namespace MMI } // namespace OHOS diff --git a/frameworks/ani/input_consumer/src/input_consumer.cpp b/frameworks/ani/input_consumer/src/input_consumer.cpp index 1bd3174fbc..5252efd42c 100644 --- a/frameworks/ani/input_consumer/src/input_consumer.cpp +++ b/frameworks/ani/input_consumer/src/input_consumer.cpp @@ -21,7 +21,6 @@ #include "mmi_log.h" #include "input_manager.h" - #undef MMI_LOG_TAG #define MMI_LOG_TAG "AniInputConsumer" @@ -52,24 +51,59 @@ KeyEventMonitorInfo::~KeyEventMonitorInfo() keyOptionsObj = nullptr; } -static ani_error CreateAniError(ani_env *env, std::string &&errMsg) +bool KeyEventMonitorInfo::setCallback(ani_object callbackObj) { - static const char *errorClsName = "Lescompat/Error;"; + if (ANI_OK != env->GlobalReference_Create(callbackObj, &callback)) { + MMI_HILOGE("Create global reference 'callback' failed"); + return false; + } + return true; +} + +bool KeyEventMonitorInfo::SetKeyOptionsObj(ani_object keyOptions) +{ + if (ANI_OK != env->GlobalReference_Create(keyOptions, &keyOptionsObj)) { + MMI_HILOGE("Create global reference 'keyOptionsObj' failed"); + return false; + } + return true; +} + +static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) +{ + MMI_HILOGD("Begin ThrowBusinessError."); + static const char *errorClsName = "L@ohos/base/BusinessError;"; ani_class cls {}; if (ANI_OK != env->FindClass(errorClsName, &cls)) { - MMI_HILOGE("%{public}s: Not found namespace %{public}s.", __func__, errorClsName); - return nullptr; + MMI_HILOGE("find class BusinessError %{public}s failed", errorClsName); + return; } ani_method ctor; - if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;:V", &ctor)) { - MMI_HILOGE("%{public}s: Not found in %{public}s.", __func__, errorClsName); - return nullptr; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + MMI_HILOGE("find method BusinessError.constructor failed"); + return; } - ani_string error_msg; - env->String_NewUTF8(errMsg.c_str(), 17U, &error_msg); ani_object errorObject; - env->Object_New(cls, ctor, &errorObject, error_msg); - return static_cast(errorObject); + if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { + MMI_HILOGE("create BusinessError object failed"); + return; + } + ani_double aniErrCode = static_cast(errCode); + ani_string errMsgStr; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { + MMI_HILOGE("convert errMsg to ani_string failed"); + return; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { + MMI_HILOGE("set error code failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { + MMI_HILOGE("set error message failed"); + return; + } + env->ThrowError(static_cast(errorObject)); + return; } static std::optional GetIsRepeat(ani_env *env, ani_object keyOptionsObj) @@ -122,6 +156,7 @@ static bool GetPreKeys(ani_env *env, ani_object keyOptionsObj, std::set ani_ref ref; if (ANI_OK != env->Object_GetPropertyByName_Ref(keyOptionsObj, "preKeys", &ref)) { MMI_HILOGE("Object_GetPropertyByName_Ref Failed"); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "preKeys not found"); return false; } ani_object arrayObj = static_cast(ref); @@ -144,9 +179,8 @@ static bool GetPreKeys(ani_env *env, ani_object keyOptionsObj, std::set return false; } if (doubleEntry > INT32_MAX_D || doubleEntry < 0) { - ani_error error = CreateAniError(env, "preKeys must be between 0 and INT32_MAX"); - env->ThrowError(error); MMI_HILOGE("preKey:%{public}f is less 0 or greater than INT32_MAX, can not process", doubleEntry); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "element of preKeys must be greater than or equal to 0"); return false; } if (!preKeys.insert(static_cast(doubleEntry)).second) { @@ -177,10 +211,13 @@ static std::shared_ptr ParseKeyOptions(ani_env *env, ani_object keyOp std::shared_ptr keyOptionPtr = std::make_shared(); std::set preKeys; - if (!GetPreKeys(env, keyOptionsObj, preKeys) || preKeys.size() > PRE_KEYS_SIZE) { - MMI_HILOGE("PreKeys is invalid"); - ani_error error = CreateAniError(env, "PreKeys is invalid"); - env->ThrowError(error); + if (!GetPreKeys(env, keyOptionsObj, preKeys)) { + MMI_HILOGE("Get preKeys failed"); + return nullptr; + } + if (preKeys.size() > PRE_KEYS_SIZE) { + MMI_HILOGE("PreKeys size invalid"); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "preKeys size invalid"); return nullptr; } keyOptionPtr->SetPreKeys(preKeys); @@ -192,8 +229,7 @@ static std::shared_ptr ParseKeyOptions(ani_env *env, ani_object keyOp } if (finalKey > INT32_MAX_D || finalKey < 0) { MMI_HILOGE("finalKey:%{private}f is less 0 or greater than INT32_MAX, can not process", finalKey); - ani_error error = CreateAniError(env, "finalKey must be between 0 and INT32_MAX"); - env->ThrowError(error); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "finalKey must be greater than or equal to 0"); return nullptr; } keyOptionPtr->SetFinalKey(static_cast(finalKey)); @@ -212,8 +248,7 @@ static std::shared_ptr ParseKeyOptions(ani_env *env, ani_object keyOp } if (finalKeyDownDuration > INT32_MAX_D || finalKeyDownDuration < 0) { MMI_HILOGE("finalKeyDownDuration:%{public}f is less 0 or greater INT32_MAX", finalKeyDownDuration); - ani_error error = CreateAniError(env, "finalKeyDownDuration must be between 0 and INT32_MAX"); - env->ThrowError(error); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "finalKeyDownDuration must be greater than or equal to 0"); return nullptr; } keyOptionPtr->SetFinalKeyDownDuration(static_cast(finalKeyDownDuration)); @@ -287,24 +322,6 @@ static bool MatchCombinationKey(KeyOption &combinationKeyOption, KeyEvent &keyEv return count == infoSize; } -static bool SendEventToMainThread(const std::function func) -{ - CALL_DEBUG_ENTER; - if (func == nullptr) { - MMI_HILOGE("%{public}s: func == nullptr", __func__); - return false; - } - auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); - if (!runner) { - MMI_HILOGE("%{public}s: runner == nullptr", __func__); - return false; - } - auto handler = std::make_shared(runner); - handler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {}); - MMI_HILOGD("%{public}s: PostTask success", __func__); - return true; -} - static ani_boolean IsInstanceOf(ani_env *env, const std::string &cls_name, ani_object obj) { ani_class cls; @@ -318,66 +335,66 @@ static ani_boolean IsInstanceOf(ani_env *env, const std::string &cls_name, ani_o return ret; } -static void EmitAsyncCallbackWork(std::shared_ptr reportEvent) +static void EmitAsyncCallbackWork(const std::shared_ptr &reportEvent) { CALL_DEBUG_ENTER; CHKPV(reportEvent); - auto task = [reportEvent]() { - MMI_HILOGD("%{public}s: Begin to call task", __func__); - ani_size nrRefs = ANI_SCOPE_SIZE; - AniLocalScopeGuard aniLocalScopeGuard(reportEvent->env, nrRefs); - if (!aniLocalScopeGuard.IsStatusOK()) { - MMI_HILOGE("%{public}s: CreateLocalScope failed", __func__); - return; - } - auto fnObj = reinterpret_cast(reportEvent->callback); - std::vector args = {reportEvent->keyOptionsObj}; - ani_ref result; - MMI_HILOGD("%{public}s: Begin to call FunctionalObject_Call", __func__); - if (fnObj == nullptr || args.size() == 0) { - MMI_HILOGE("%{public}s: fnObj == nullptr", __func__); - return; - } - if (IsInstanceOf(reportEvent->env, "Lstd/core/Function1;", fnObj) == 0) { - MMI_HILOGE("%{public}s: fnObj is not instance Of function ", __func__); - return; - } - const std::string className = "L@ohos/multimodalInput/inputConsumer/inputConsumer/KeyOptions;"; - if (IsInstanceOf(reportEvent->env, className, static_cast(reportEvent->keyOptionsObj)) == 0) { - MMI_HILOGE("%{public}s: keyOptionsObj is not instance Of KeyOptions class", __func__); - return; - } + auto envResult = ScopedAniEnv::Create(reportEvent->vm); + if (!envResult.has_value()) { + MMI_HILOGE("%{public}s: get env failed.", __func__); + return; + } + std::unique_ptr scopedAniEnv = std::move(envResult.value()); + ani_env *workerEnv = scopedAniEnv->GetEnv(); + reportEvent->env = workerEnv; - if (ANI_OK != reportEvent->env->FunctionalObject_Call(fnObj, 1, args.data(), &result)) { - MMI_HILOGE("%{public}s: FunctionalObject_Call failed", __func__); - return; - } - MMI_HILOGD("%{public}s: FunctionalObject_Call success", __func__); - }; - if (!SendEventToMainThread(task)) { - MMI_HILOGE("%{public}s: failed to send event", __func__); + AniLocalScopeGuard aniLocalScopeGuard(workerEnv, ANI_SCOPE_SIZE); + if (!aniLocalScopeGuard.IsStatusOK()) { + MMI_HILOGE("%{public}s: CreateLocalScope failed", __func__); + return; + } + auto fnObj = reinterpret_cast(reportEvent->callback); + std::vector args = {reportEvent->keyOptionsObj}; + ani_ref result; + MMI_HILOGD("%{public}s: Begin to call FunctionalObject_Call", __func__); + if (fnObj == nullptr || args.size() == 0) { + MMI_HILOGE("%{public}s: fnObj == nullptr", __func__); + return; + } + if (IsInstanceOf(workerEnv, "Lstd/core/Function1;", fnObj) == 0) { + MMI_HILOGE("%{public}s: fnObj is not instance Of function ", __func__); + return; + } + const std::string className = "L@ohos/multimodalInput/inputConsumer/inputConsumer/KeyOptions;"; + if (IsInstanceOf(workerEnv, className, static_cast(reportEvent->keyOptionsObj)) == 0) { + MMI_HILOGE("%{public}s: keyOptionsObj is not instance Of KeyOptions class", __func__); + return; + } + + if (ANI_OK != workerEnv->FunctionalObject_Call(fnObj, 1, args.data(), &result)) { + MMI_HILOGE("%{public}s: FunctionalObject_Call failed", __func__); + return; } + MMI_HILOGD("%{public}s: FunctionalObject_Call success", __func__); } -static void SubKeyEventCallback(std::shared_ptr keyEvent) +static void SubKeyEventCallback(std::shared_ptr keyEvent, const std::string& keyOptionKey) { CALL_DEBUG_ENTER; CHKPV(keyEvent); std::lock_guard guard(sCallBacksMutex); - auto iter = callbacks.begin(); - while (iter != callbacks.end()) { + auto iter = callbacks.find(keyOptionKey); + if (iter != callbacks.end()) { auto &list = iter->second; - ++iter; MMI_HILOGD("list size:%{public}zu", list.size()); - auto infoIter = list.begin(); - while (infoIter != list.end()) { - auto monitorInfo = *infoIter; + for (auto monitorInfo : list) { if (MatchCombinationKey(*(monitorInfo->keyOption), *keyEvent)) { MMI_HILOGD("MatchCombinationKey success"); EmitAsyncCallbackWork(monitorInfo); } - ++infoIter; } + } else { + MMI_HILOGE("No Matches found for SubKeyEventCallback"); } } @@ -408,7 +425,7 @@ static bool CheckCallbackEqual(ani_env *env, ani_ref fnRef, ani_env *iterEnv, an return isEquals; } -static int32_t AddEventCallback(std::shared_ptr event) +static int32_t AddEventCallback(const std::shared_ptr &event) { CALL_DEBUG_ENTER; std::lock_guard guard(sCallBacksMutex); @@ -439,7 +456,8 @@ static int32_t SubscribeKey(ani_env *env, std::shared_ptr & return ERROR_CODE; } event->keyOption = keyOptionsPtr; - event->eventType = GenerateEventType(keyOptionsPtr); + auto keyOptionKey = GenerateEventType(keyOptionsPtr); + event->eventType = keyOptionKey; int32_t preSubscribeId = GetPreSubscribeId(event); if (preSubscribeId >= 0) { @@ -449,7 +467,10 @@ static int32_t SubscribeKey(ani_env *env, std::shared_ptr & MMI_HILOGD("EventType:%{private}s, eventName:%{public}s", event->eventType.c_str(), event->name.c_str()); int32_t subscribeId = -1; - subscribeId = InputManager::GetInstance()->SubscribeKeyEvent(event->keyOption, SubKeyEventCallback); + subscribeId = InputManager::GetInstance()->SubscribeKeyEvent(event->keyOption, + [keyOptionKey](std::shared_ptr keyEvent) { + SubKeyEventCallback(keyEvent, keyOptionKey); + }); if (subscribeId < 0) { MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId); return subscribeId; @@ -464,12 +485,8 @@ static void On([[maybe_unused]] ani_env *env, ani_string strObj, ani_object keyO CALL_DEBUG_ENTER; std::shared_ptr event = std::make_shared(); event->env = env; - if (ANI_OK != env->GlobalReference_Create(callback, &event->callback)) { - MMI_HILOGE("Create global reference 'callback' failed"); - return; - } - if (ANI_OK != env->GlobalReference_Create(keyOptionsObj, &event->keyOptionsObj)) { - MMI_HILOGE("Create global reference 'keyOptionsObj' failed"); + env->GetVM(&event->vm); + if (!event->setCallback(callback) || !event->SetKeyOptionsObj(keyOptionsObj)) { return; } @@ -483,8 +500,7 @@ static void On([[maybe_unused]] ani_env *env, ani_string strObj, ani_object keyO MMI_HILOGD("%{public}s: Call SubscribeKey end ret = %{public}d", __func__, ret); } else { MMI_HILOGE("Type is not key or hotkey"); - ani_error error = CreateAniError(env, "Type must be key or hotkeyChange"); - env->ThrowError(error); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "Type must be key or hotkeyChange"); } } @@ -555,8 +571,7 @@ static void Off([[maybe_unused]] ani_env *env, ani_string strObj, ani_object key MMI_HILOGD("%{public}s: callback is undefined", __func__); event->callback = nullptr; } else { - if (ANI_OK != env->GlobalReference_Create(callback, &event->callback)) { - MMI_HILOGE("%{public}s: Create global reference 'callback' failed", __func__); + if (!event->setCallback(callback)) { return; } } @@ -583,8 +598,7 @@ static void Off([[maybe_unused]] ani_env *env, ani_string strObj, ani_object key InputManager::GetInstance()->UnsubscribeKeyEvent(subscribeId); } else { MMI_HILOGE("Type is not key or hotkey"); - ani_error error = CreateAniError(env, "Type must be key or hotkeyChange"); - env->ThrowError(error); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "Type must be key or hotkeyChange"); } } -- Gitee From 2f759956012f13696b264eeb5818a932fcf64a30 Mon Sep 17 00:00:00 2001 From: fanzhe Date: Fri, 25 Apr 2025 15:50:01 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9throwError?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: fanzhe Change-Id: I21b81a65944b20c5cf8275a5a1d1c9721b7233f2 --- .../input_device/include/ani_event_target.h | 11 +-- .../ani/input_device/include/ani_util.h | 21 ++---- .../ani/input_device/src/ani_event_target.cpp | 71 ++++++++++++------- .../src/ani_input_device_context.cpp | 53 +++++++++----- frameworks/ani/input_device/src/ani_util.cpp | 40 ++++++----- frameworks/ani/pointer/src/pointer.cpp | 57 +++++++++------ 6 files changed, 152 insertions(+), 101 deletions(-) diff --git a/frameworks/ani/input_device/include/ani_event_target.h b/frameworks/ani/input_device/include/ani_event_target.h index 6fff77042f..37ff3c5822 100644 --- a/frameworks/ani/input_device/include/ani_event_target.h +++ b/frameworks/ani/input_device/include/ani_event_target.h @@ -28,7 +28,7 @@ namespace MMI { class AniEventTarget : public IInputDeviceListener, public std::enable_shared_from_this { public: AniEventTarget(); - virtual ~AniEventTarget() = default; + virtual ~AniEventTarget(); DISALLOW_COPY_AND_MOVE(AniEventTarget); void AddListener(ani_env *env, const std::string &type, ani_object handle); void ResetEnv(); @@ -36,14 +36,17 @@ public: void OnDeviceRemoved(int32_t deviceId, const std::string &type) override; private: - static void EmitAddedDeviceEvent(std::shared_ptr reportData); - static void EmitRemoveDeviceEvent(std::shared_ptr reportData); - static bool EmitCallbackWork(ani_env *env, std::shared_ptr &reportData, + static void EmitAddedDeviceEvent(const std::shared_ptr &reportData); + static void EmitRemoveDeviceEvent(const std::shared_ptr &reportData); + static bool EmitCallbackWork(ani_env *env, const std::shared_ptr &reportData, const std::string &type); + void GetMainEventHandler(); + void PostMainThreadTask(const std::function task); private: inline static std::map>> devListener_ {}; bool isListeningProcess_ { false }; + std::shared_ptr handler_ = nullptr; }; } // namespace MMI } // namespace OHOS diff --git a/frameworks/ani/input_device/include/ani_util.h b/frameworks/ani/input_device/include/ani_util.h index 8fa0d0970c..9697f2611b 100644 --- a/frameworks/ani/input_device/include/ani_util.h +++ b/frameworks/ani/input_device/include/ani_util.h @@ -16,32 +16,22 @@ #ifndef ANI_UTIL_H #define ANI_UTIL_H #include + #include "input_device.h" namespace OHOS { namespace MMI { class AniUtil { public: - struct CallbackData { - std::vector ids; - std::shared_ptr device { nullptr }; - std::vector keystrokeAbility; - int32_t deviceId { 0 }; - int32_t keyboardType { 0 }; - int32_t keyboardRepeatDelay { 0 }; - int32_t keyboardRepeatRate { 0 }; - int64_t IntervalSinceLastInput { 0 }; - }; struct ReportData { ani_ref ref { nullptr }; int32_t deviceId { 0 }; }; struct CallbackInfo { - ani_env *env { nullptr }; - ani_ref ref { nullptr }; - int32_t errCode { -1 }; - CallbackData data; - // UserData uData; + ani_env *env_ { nullptr }; + ani_ref callback_ { nullptr }; + bool SetCallback(ani_object handle); + ~CallbackInfo(); }; struct DeviceType { std::string sourceTypeName; @@ -50,7 +40,6 @@ public: static bool IsSameHandle(ani_env *env, ani_ref handle, ani_env *iterEnv, ani_ref iterhandle); static ani_string StdStringToANIString(ani_env* env, const std::string& str); - static bool SendEventToMainThread(const std::function func); static ani_boolean IsInstanceOf(ani_env *env, const std::string &cls_name, ani_object obj); static ani_object CreateAniObject(ani_env *env, const char *nsName, const char *className); }; diff --git a/frameworks/ani/input_device/src/ani_event_target.cpp b/frameworks/ani/input_device/src/ani_event_target.cpp index c02cbc20ae..072044609f 100644 --- a/frameworks/ani/input_device/src/ani_event_target.cpp +++ b/frameworks/ani/input_device/src/ani_event_target.cpp @@ -44,9 +44,23 @@ AniEventTarget::AniEventTarget() std::lock_guard lock(mutex_); auto ret = devListener_.insert({ CHANGED_TYPE, std::vector>() }); CK(ret.second, VAL_NOT_EXP); + GetMainEventHandler(); } -bool AniEventTarget::EmitCallbackWork(ani_env *env, std::shared_ptr &reportData, +AniEventTarget::~AniEventTarget() +{ + CALL_DEBUG_ENTER; + handler_ = nullptr; +} + +void AniEventTarget::GetMainEventHandler() +{ + CALL_DEBUG_ENTER; + auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + handler_ = std::make_shared(runner); +} + +bool AniEventTarget::EmitCallbackWork(ani_env *env, const std::shared_ptr &reportData, const std::string &type) { CALL_DEBUG_ENTER; @@ -92,7 +106,7 @@ bool AniEventTarget::EmitCallbackWork(ani_env *env, std::shared_ptr reportData) +void AniEventTarget::EmitAddedDeviceEvent(const std::shared_ptr &reportData) { CALL_DEBUG_ENTER; std::lock_guard guard(mutex_); @@ -102,12 +116,12 @@ void AniEventTarget::EmitAddedDeviceEvent(std::shared_ptr r return; } for (const auto &item : addEvent->second) { - CHKPC(item->env); - if (item->ref != reportData->ref) { + CHKPC(item->env_); + if (item->callback_ != reportData->ref) { continue; } - if (!EmitCallbackWork(item->env, reportData, ADD_EVENT)) { + if (!EmitCallbackWork(item->env_, reportData, ADD_EVENT)) { continue; } @@ -118,7 +132,7 @@ void AniEventTarget::EmitAddedDeviceEvent(std::shared_ptr r } } -void AniEventTarget::EmitRemoveDeviceEvent(std::shared_ptr reportData) +void AniEventTarget::EmitRemoveDeviceEvent(const std::shared_ptr &reportData) { CALL_DEBUG_ENTER; std::lock_guard guard(mutex_); @@ -128,12 +142,12 @@ void AniEventTarget::EmitRemoveDeviceEvent(std::shared_ptr return; } for (const auto &item : removeEvent->second) { - CHKPC(item->env); - if (item->ref != reportData->ref) { + CHKPC(item->env_); + if (item->callback_ != reportData->ref) { continue; } - if (!EmitCallbackWork(item->env, reportData, REMOVE_EVENT)) { + if (!EmitCallbackWork(item->env_, reportData, REMOVE_EVENT)) { continue; } @@ -144,6 +158,20 @@ void AniEventTarget::EmitRemoveDeviceEvent(std::shared_ptr } } +void AniEventTarget::PostMainThreadTask(const std::function task) +{ + if (!handler_) { + auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + MMI_HILOGE("get main event runner failed!"); + return; + } + handler_ = std::make_shared(runner); + } + bool ret = handler_->PostTask(task, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {}); + MMI_HILOGI("%{public}s: PostTask %{public}s", __func__, (ret? "success" : "failed")); +} + void AniEventTarget::OnDeviceAdded(int32_t deviceId, const std::string &type) { CALL_DEBUG_ENTER; @@ -156,18 +184,16 @@ void AniEventTarget::OnDeviceAdded(int32_t deviceId, const std::string &type) for (auto &item : changeEvent->second) { CHKPC(item); - CHKPC(item->env); + CHKPC(item->env_); auto reportData = std::make_shared(); if (reportData == nullptr) { MMI_HILOGE("%{public}s: Memory allocation failed", __func__); return; } reportData->deviceId = deviceId; - reportData->ref = item->ref; + reportData->ref = item->callback_; auto task = [reportData, this] () { EmitAddedDeviceEvent(reportData); }; - if (!AniUtil::SendEventToMainThread(task)) { - MMI_HILOGE("%{public}s: failed to send event", __func__); - } + PostMainThreadTask(task); } } @@ -182,18 +208,16 @@ void AniEventTarget::OnDeviceRemoved(int32_t deviceId, const std::string &type) } for (auto &item : changeEvent->second) { CHKPC(item); - CHKPC(item->env); + CHKPC(item->env_); std::shared_ptr reportData = std::make_shared(); if (reportData == nullptr) { MMI_HILOGE("%{public}s: Memory allocation failed", __func__); return; } reportData->deviceId = deviceId; - reportData->ref = item->ref; + reportData->ref = item->callback_; auto task = [reportData, this] () { EmitRemoveDeviceEvent(reportData); }; - if (!AniUtil::SendEventToMainThread(task)) { - MMI_HILOGE("%{public}s: failed to send event", __func__); - } + PostMainThreadTask(task); } } @@ -203,20 +227,19 @@ void AniEventTarget::AddListener(ani_env *env, const std::string &type, ani_obje std::lock_guard guard(mutex_); auto it = devListener_.find(type); if (it == devListener_.end()) { - MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, CHANGED_TYPE.c_str()); + MMI_HILOGE("%{public}s: Find %{public}s failed", __func__, type.c_str()); return; } auto monitor = std::make_unique(); - monitor->env = env; - if (ANI_OK != env->GlobalReference_Create(handle, &monitor->ref)) { - MMI_HILOGE("%{public}s: Create global callback failed", __func__); + monitor->env_ = env; + if (!monitor->SetCallback(handle)) { return; } for (const auto &iter : it->second) { CHKPC(iter); - if (AniUtil::IsSameHandle(env, monitor->ref, iter->env, iter->ref)) { + if (AniUtil::IsSameHandle(env, monitor->callback_, iter->env_, iter->callback_)) { MMI_HILOGW("The handle already exists"); return; } diff --git a/frameworks/ani/input_device/src/ani_input_device_context.cpp b/frameworks/ani/input_device/src/ani_input_device_context.cpp index 40a641c7e4..b804abc437 100644 --- a/frameworks/ani/input_device/src/ani_input_device_context.cpp +++ b/frameworks/ani/input_device/src/ani_input_device_context.cpp @@ -36,6 +36,10 @@ using namespace OHOS::MMI; +enum AniErrorCode : int32_t { + COMMON_PARAMETER_ERROR = 401, +}; + std::unordered_map axisType = { { ABS_MT_TOUCH_MAJOR, "touchmajor" }, { ABS_MT_TOUCH_MINOR, "touchminor" }, { ABS_MT_ORIENTATION, "orientation" }, { ABS_MT_POSITION_X, "x" }, { ABS_MT_POSITION_Y, "y" }, { ABS_MT_PRESSURE, "pressure" }, @@ -56,24 +60,41 @@ AniUtil::DeviceType g_deviceType[] = { { "trackball", EVDEV_UDEV_TAG_TRACKBALL }, }; -static ani_error CreateAniError(ani_env *env, std::string &&errMsg) +static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) { - static const char *errorClsName = "Lescompat/Error;"; - ani_class cls{}; + MMI_HILOGD("Begin ThrowBusinessError."); + static const char *errorClsName = "L@ohos/base/BusinessError;"; + ani_class cls {}; if (ANI_OK != env->FindClass(errorClsName, &cls)) { - MMI_HILOGE("%{public}s: Not found namespace %{public}s.", __func__, errorClsName); - return nullptr; + MMI_HILOGE("find class BusinessError %{public}s failed", errorClsName); + return; } ani_method ctor; - if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;:V", &ctor)) { - MMI_HILOGE("%{public}s: Not found in %{public}s.", __func__, errorClsName); - return nullptr; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + MMI_HILOGE("find method BusinessError.constructor failed"); + return; } - ani_string error_msg; - env->String_NewUTF8(errMsg.c_str(), 17U, &error_msg); ani_object errorObject; - env->Object_New(cls, ctor, &errorObject, error_msg); - return static_cast(errorObject); + if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { + MMI_HILOGE("create BusinessError object failed"); + return; + } + ani_double aniErrCode = static_cast(errCode); + ani_string errMsgStr; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { + MMI_HILOGE("convert errMsg to ani_string failed"); + return; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { + MMI_HILOGE("set error code failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { + MMI_HILOGE("set error message failed"); + return; + } + env->ThrowError(static_cast(errorObject)); + return; } static bool SetID(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) @@ -181,7 +202,7 @@ static bool SetDeviceProduct(ani_env *env, ani_object obj, std::shared_ptr &inputDevice) +static bool SetDeviceVersion(ani_env *env, ani_object obj, std::shared_ptr inputDevice) { if (obj == nullptr) { MMI_HILOGE("obj is nullptr"); @@ -729,14 +750,12 @@ void AniInputDeviceContext::On(ani_env *env, ani_string aniStr, ani_object callb std::string type = AniStringToString(env, aniStr); if (type != CHANGED_TYPE) { MMI_HILOGE("%{public}s: Type is not change", __func__); - ani_error error = CreateAniError(env, "type must be change"); - env->ThrowError(error); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "type must be change"); return; } if (mgr_ == nullptr) { MMI_HILOGE("%{public}s: aniInputDeviceMgr is nullptr", __func__); - ani_error error = CreateAniError(env, "aniInputDeviceMgr must be created"); - env->ThrowError(error); + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "aniInputDeviceMgr is nullptr"); return; } mgr_->RegisterDevListener(env, type, callback); diff --git a/frameworks/ani/input_device/src/ani_util.cpp b/frameworks/ani/input_device/src/ani_util.cpp index 7cb0a77097..83bd28ad40 100644 --- a/frameworks/ani/input_device/src/ani_util.cpp +++ b/frameworks/ani/input_device/src/ani_util.cpp @@ -18,7 +18,6 @@ #include #include -#include "event_handler.h" #include "mmi_log.h" #include "napi_constants.h" @@ -43,6 +42,27 @@ AniUtil::DeviceType g_deviceType[] = { }; } // namespace +bool AniUtil::CallbackInfo::SetCallback(ani_object handle) +{ + if (ANI_OK != env_->GlobalReference_Create(handle, &callback_)) { + MMI_HILOGE("%{public}s: Create global callback failed", __func__); + return false; + } + return true; +} + +AniUtil::CallbackInfo::~CallbackInfo() +{ + CALL_DEBUG_ENTER; + if (env_ == nullptr) { + return; + } + if (callback_ != nullptr) { + env_->GlobalReference_Delete(callback_); + } + callback_ = nullptr; +} + bool AniUtil::IsSameHandle(ani_env *env, ani_ref handle, ani_env *iterEnv, ani_ref iterhandle) { if (env != iterEnv) { @@ -79,24 +99,6 @@ ani_boolean AniUtil::IsInstanceOf(ani_env *env, const std::string &cls_name, ani return ret; } -bool AniUtil::SendEventToMainThread(const std::function func) -{ - CALL_DEBUG_ENTER; - if (func == nullptr) { - MMI_HILOGE("%{public}s: func == nullptr", __func__); - return false; - } - std::shared_ptr runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); - if (!runner) { - MMI_HILOGE("%{public}s: runner == nullptr", __func__); - return false; - } - std::shared_ptr handler = std::make_shared(runner); - handler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {}); - MMI_HILOGD("%{public}s: PostTask success", __func__); - return true; -} - ani_object AniUtil::CreateAniObject(ani_env *env, const char *nsName, const char *className) { ani_namespace ns; diff --git a/frameworks/ani/pointer/src/pointer.cpp b/frameworks/ani/pointer/src/pointer.cpp index 4c6cca56ea..55bfe859b9 100644 --- a/frameworks/ani/pointer/src/pointer.cpp +++ b/frameworks/ani/pointer/src/pointer.cpp @@ -41,29 +41,46 @@ constexpr int32_t OCCUPIED_BY_OTHER = -4; const double INT32_MAX_D = static_cast(std::numeric_limits::max()); } // namespace -enum NapiErrorCode : int32_t { +enum AniErrorCode : int32_t { COMMON_PARAMETER_ERROR = 401, COMMON_USE_SYSAPI_ERROR = 202, }; -static ani_error CreateAniError(ani_env *env, std::string&& errMsg) +static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) { - static const char *errorClsName = "Lescompat/Error;"; + MMI_HILOGD("Begin ThrowBusinessError."); + static const char *errorClsName = "L@ohos/base/BusinessError;"; ani_class cls {}; if (ANI_OK != env->FindClass(errorClsName, &cls)) { - MMI_HILOGE("%{public}s: Not found namespace %{public}s.", __func__, errorClsName); - return nullptr; + MMI_HILOGE("find class BusinessError %{public}s failed", errorClsName); + return; } ani_method ctor; - if (ANI_OK != env->Class_FindMethod(cls, "", "Lstd/core/String;:V", &ctor)) { - MMI_HILOGE("%{public}s: Not found in %{public}s.", __func__, errorClsName); - return nullptr; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + MMI_HILOGE("find method BusinessError.constructor failed"); + return; } - ani_string error_msg; - env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &error_msg); ani_object errorObject; - env->Object_New(cls, ctor, &errorObject, error_msg); - return static_cast(errorObject); + if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { + MMI_HILOGE("create BusinessError object failed"); + return; + } + ani_double aniErrCode = static_cast(errCode); + ani_string errMsgStr; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { + MMI_HILOGE("convert errMsg to ani_string failed"); + return; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { + MMI_HILOGE("set error code failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { + MMI_HILOGE("set error message failed"); + return; + } + env->ThrowError(static_cast(errorObject)); + return; } int32_t ToInt32ECMAScript(double value) @@ -94,17 +111,15 @@ static int SetPointerStyleInner(ani_env *env, ani_double windowid, ani_enum_item int32_t windowID = ToInt32ECMAScript(static_cast(windowid)); if (windowID < 0 && windowID != GLOBAL_WINDOW_ID) { MMI_HILOGE("Invalid windowid"); - ani_error err = CreateAniError(env, "Windowid is invalid"); - env->ThrowError(err); - return COMMON_PARAMETER_ERROR; + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "Windowid is invalid"); + return 0; } int32_t pointerStyleID = ParseEnumToInt(env, pointerStyle); if ((pointerStyleID < DEFAULT && pointerStyleID != DEVELOPER_DEFINED_ICON) || pointerStyleID > RUNNING) { MMI_HILOGE("Undefined pointer style"); - ani_error err = CreateAniError(env, "Pointer style does not exist"); - env->ThrowError(err); - return COMMON_PARAMETER_ERROR; + ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "Pointer style does not exist"); + return 0; } PointerStyle style; @@ -112,9 +127,9 @@ static int SetPointerStyleInner(ani_env *env, ani_double windowid, ani_enum_item int32_t errorCode = InputManager::GetInstance()->SetPointerStyle(windowid, style); if (errorCode == COMMON_USE_SYSAPI_ERROR) { MMI_HILOGE("The windowId is negative number and no system applications use system API"); - ani_error err = CreateAniError(env, "windowId is negative number and no system applications use system API"); - env->ThrowError(err); - return COMMON_USE_SYSAPI_ERROR; + ThrowBusinessError(env, COMMON_USE_SYSAPI_ERROR, + "windowId is negative number and no system applications use system API"); + return 0; } MMI_HILOGD(" SetPointerStyleInner end."); return 0; -- Gitee From d689ec81af9ecdf09ee4d9e3273a443bc6abca2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=AD=E6=97=AD?= Date: Thu, 22 May 2025 02:05:48 +0000 Subject: [PATCH 05/13] update frameworks/proxy/events/test/input_event_test.cpp. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 郭旭 --- frameworks/proxy/events/test/input_event_test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frameworks/proxy/events/test/input_event_test.cpp b/frameworks/proxy/events/test/input_event_test.cpp index d2cf3841b7..92345b0a3c 100644 --- a/frameworks/proxy/events/test/input_event_test.cpp +++ b/frameworks/proxy/events/test/input_event_test.cpp @@ -196,6 +196,12 @@ HWTEST_F(InputEventTest, InputEventTest_operator_001, TestSize.Level1) destination = std::move(source1); LogTracer source2(400, 7, 8); destination = std::move(source2); + auto InputEvent = InputEvent::Create(); + ASSERT_NE(InputEvent, nullptr); + Parcel in; + InputEvent->extraDataLength_ = 0; + bool ret = InputEvent->ReadFromParcel(in); + ASSERT_FALSE(ret); } } // namespace MMI } // namespace OHOS \ No newline at end of file -- Gitee From 4c5a526fda8b8ebe3493ab4d7daca23ea120e1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=AD=E6=97=AD?= Date: Thu, 22 May 2025 02:09:22 +0000 Subject: [PATCH 06/13] update libudev/test/custom_udev_test.cpp. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 郭旭 --- libudev/test/custom_udev_test.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libudev/test/custom_udev_test.cpp b/libudev/test/custom_udev_test.cpp index a3c7beb772..33bd59d4dd 100644 --- a/libudev/test/custom_udev_test.cpp +++ b/libudev/test/custom_udev_test.cpp @@ -183,9 +183,7 @@ HWTEST_F(CustomUdevTest, TestIsInitialized, TestSize.Level1) EXPECT_EQ(udev_device_get_is_initialized(device), 1); - errno = 0; EXPECT_LT(udev_device_get_is_initialized(nullptr), 0); - EXPECT_EQ(errno, 0); } /* @@ -199,9 +197,7 @@ HWTEST_F(CustomUdevTest, TestGetDevnode, TestSize.Level1) EXPECT_STREQ(udev_device_get_devnode(device), testDevice_.GetDevNode()); - errno = 0; EXPECT_EQ(udev_device_get_devnode(nullptr), nullptr); - EXPECT_NE(errno, 0); } /* @@ -215,9 +211,7 @@ HWTEST_F(CustomUdevTest, TestGetSysname, TestSize.Level1) EXPECT_EQ(std::string("/dev/input/") + udev_device_get_sysname(device), testDevice_.GetDevNode()); - errno = 0; EXPECT_EQ(udev_device_get_sysname(nullptr), nullptr); - EXPECT_NE(errno, 0); } /* @@ -232,9 +226,7 @@ HWTEST_F(CustomUdevTest, TestGetSyspath, TestSize.Level1) EXPECT_EQ(udev_device_get_syspath(device), testDevice_.GetSysPath() + std::string("/") + udev_device_get_sysname(device)); - errno = 0; EXPECT_EQ(udev_device_get_syspath(nullptr), nullptr); - EXPECT_NE(errno, 0); } /* @@ -268,21 +260,13 @@ HWTEST_F(CustomUdevTest, TestGetParent2, TestSize.Level1) ASSERT_EQ(parent, nullptr); EXPECT_NE(udev_device_get_syspath(parent), testDevice_.GetSysPath()); - errno = 0; EXPECT_EQ(udev_device_get_parent_with_subsystem_devtype(nullptr, "input", nullptr), nullptr); - EXPECT_NE(errno, 0); - errno = 0; EXPECT_NE(udev_device_get_parent_with_subsystem_devtype(device, "input", ""), nullptr); - EXPECT_NE(errno, EINVAL); - errno = 0; EXPECT_EQ(udev_device_get_parent_with_subsystem_devtype(device, nullptr, nullptr), nullptr); - EXPECT_EQ(errno, EINVAL); - errno = 0; EXPECT_EQ(udev_device_get_parent_with_subsystem_devtype(device, "unknown", nullptr), nullptr); - EXPECT_EQ(errno, 0); } HWTEST_F(CustomUdevTest, TestUdevPropsDefault, TestSize.Level1) -- Gitee From 6ae5826cc61352c12449eeb869ade7277aee373f Mon Sep 17 00:00:00 2001 From: ninghejuan Date: Fri, 23 May 2025 10:56:12 +0800 Subject: [PATCH 07/13] fix qiangji test bug Signed-off-by: ninghejuan --- .../test/input_manager_filter_manual_test.cpp | 2 +- .../multimodal_input_connect_stub_ex_test.cpp | 4 ++-- .../key_event_value_transformation_test.cpp | 2 +- .../test/key_subscriber_handler_test.cpp | 22 ------------------- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/frameworks/proxy/events/test/input_manager_filter_manual_test.cpp b/frameworks/proxy/events/test/input_manager_filter_manual_test.cpp index e60fb0cae8..f498ddff48 100644 --- a/frameworks/proxy/events/test/input_manager_filter_manual_test.cpp +++ b/frameworks/proxy/events/test/input_manager_filter_manual_test.cpp @@ -296,7 +296,7 @@ void WaitPointerEnd(sem_t &sem) int32_t waitForSeconds = 3; ts.tv_sec += waitForSeconds; ret = sem_timedwait(&sem, &ts); - ASSERT_NE(ret, 0); + ASSERT_EQ(ret, 0); } HWTEST_F(InputManagerFilterManualTest, HandlePointerEventFilter_001, TestSize.Level1) { diff --git a/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp b/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp index ed45bfc923..b5197d9db0 100644 --- a/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp +++ b/service/connect_manager/test/multimodal_input_connect_stub_ex_test.cpp @@ -8500,8 +8500,8 @@ HWTEST_F(MultimodalInputConnectStubTest, StubGetTouchpadDoubleTapAndDragState_00 { CALL_TEST_DEBUG; EXPECT_CALL(*messageParcelMock_, VerifySystemApp()).WillOnce(Return(true)).WillOnce(Return(true)); - EXPECT_CALL(*messageParcelMock_, ReadBool(_)).WillOnce(DoAll(SetArgReferee<0>(false), Return(true))); - EXPECT_CALL(*messageParcelMock_, WriteBool(_)).WillOnce(Return(true)); + EXPECT_CALL(*messageParcelMock_, ReadBool(_)).WillRepeatedly(DoAll(SetArgReferee<0>(false), Return(true))); + EXPECT_CALL(*messageParcelMock_, WriteBool(_)).WillRepeatedly(Return(true)); std::shared_ptr stub = std::make_shared(); ASSERT_NE(stub, nullptr); std::shared_ptr service = std::static_pointer_cast(stub); diff --git a/service/event_handler/test/key_event_value_transformation_test.cpp b/service/event_handler/test/key_event_value_transformation_test.cpp index 37bb8106db..ff05c51c61 100644 --- a/service/event_handler/test/key_event_value_transformation_test.cpp +++ b/service/event_handler/test/key_event_value_transformation_test.cpp @@ -904,7 +904,7 @@ HWTEST_F(KeyEventValueTransformationTest, KeyEventValueTransformationTest_InputT auto KeyEvent = KeyEvent::Create(); ASSERT_NE(KeyEvent, nullptr); int32_t result = InputTransformationKeyValue(0); - ASSERT_EQ(result, 240); + ASSERT_EQ(result, -1); } } // namespace MMI } // namespace OHOS diff --git a/service/subscriber/test/key_subscriber_handler_test.cpp b/service/subscriber/test/key_subscriber_handler_test.cpp index ed5ad0bbb2..ee58c35a76 100644 --- a/service/subscriber/test/key_subscriber_handler_test.cpp +++ b/service/subscriber/test/key_subscriber_handler_test.cpp @@ -448,28 +448,6 @@ HWTEST_F(KeySubscriberHandlerTest, KeySubscriberHandlerTest_RemoveKeyCode_001, T ASSERT_EQ(keyCodes, (std::vector{1, 2, 3})); } -/** - * @tc.name: KeySubscriberHandlerTest_AddSubscriber_001 - * @tc.desc: Test add subscriber - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F(KeySubscriberHandlerTest, KeySubscriberHandlerTest_AddSubscriber_001, TestSize.Level1) -{ - CALL_TEST_DEBUG; - KeySubscriberHandler handler; - SessionPtr sess; - std::shared_ptr keyOption; - auto subscriber = std::make_shared(1, sess, keyOption); - std::shared_ptr option = std::make_shared(); - handler.AddSubscriber(subscriber, option, true); - auto it = handler.subscriberMap_.find(option); - ASSERT_NE(it->second.front(), subscriber); - auto newSubscriber = std::make_shared(1, sess, keyOption); - handler.AddSubscriber(newSubscriber, option, true); - ASSERT_NE(it->second.back(), newSubscriber); -} - /** * @tc.name: KeySubscriberHandlerTest_IsFunctionKey_001 * @tc.desc: Test is function key -- Gitee From a8422594c5620cbc3a9ee35f21e2eff46475a9a5 Mon Sep 17 00:00:00 2001 From: li-yaoyao777 Date: Wed, 28 May 2025 11:41:10 +0800 Subject: [PATCH 08/13] input pure data arkts Signed-off-by: li-yaoyao777 --- BUILD.gn | 21 + bundle.json | 30 ++ frameworks/ets/gesture_event/BUILD.gn | 92 +++++ .../ohos.multimodalInput.gestureEvent.taihe | 67 ++++ .../ets/gesture_event/src/ani_constructor.cpp | 30 ++ ...ohos.multimodalInput.gestureEvent.impl.cpp | 30 ++ frameworks/ets/input_consumer/BUILD.gn | 91 +++++ .../ohos.multimodalInput.inputConsumer.taihe | 24 ++ .../input_consumer/src/ani_constructor.cpp | 29 ++ ...hos.multimodalInput.inputConsumer.impl.cpp | 30 ++ frameworks/ets/input_event/BUILD.gn | 48 +++ .../idl/ohos.multimodalInput.inputEvent.taihe | 24 ++ .../ets/input_event/src/ani_constructor.cpp | 29 ++ .../ohos.multimodalInput.inputEvent.impl.cpp | 30 ++ frameworks/ets/input_moniter/BUILD.gn | 98 +++++ .../ohos.multimodalInput.inputMoniter.taihe | 22 ++ .../ets/input_moniter/src/ani_constructor.cpp | 30 ++ ...ohos.multimodalInput.inputMoniter.impl.cpp | 30 ++ frameworks/ets/intention_code/BUILD.gn | 91 +++++ .../ohos.multimodalInput.intentionCode.taihe | 33 ++ .../intention_code/src/ani_constructor.cpp | 29 ++ ...hos.multimodalInput.intentionCode.impl.cpp | 30 ++ frameworks/ets/key_code/BUILD.gn | 92 +++++ .../idl/ohos.multimodalInput.keyCode.taihe | 366 ++++++++++++++++++ .../ets/key_code/src/ani_constructor.cpp | 29 ++ .../src/ohos.multimodalInput.keyCode.impl.cpp | 30 ++ frameworks/ets/key_event/BUILD.gn | 95 +++++ .../idl/ohos.multimodalInput.keyEvent.taihe | 46 +++ .../ets/key_event/src/ani_constructor.cpp | 29 ++ .../ohos.multimodalInput.keyEvent.impl.cpp | 30 ++ frameworks/ets/mouse_event/BUILD.gn | 90 +++++ .../idl/ohos.multimodalInput.mouseEvent.taihe | 83 ++++ .../ets/mouse_event/src/ani_constructor.cpp | 29 ++ .../ohos.multimodalInput.mouseEvent.impl.cpp | 30 ++ frameworks/ets/short_key/BUILD.gn | 89 +++++ .../idl/ohos.multimodalInput.shortKey.taihe | 30 ++ .../ets/short_key/src/ani_constructor.cpp | 29 ++ .../ohos.multimodalInput.shortKey.impl.cpp | 30 ++ frameworks/ets/touch_event/BUILD.gn | 90 +++++ .../idl/ohos.multimodalInput.touchEvent.taihe | 78 ++++ .../ets/touch_event/src/ani_constructor.cpp | 29 ++ .../ohos.multimodalInput.touchEvent.impl.cpp | 30 ++ 42 files changed, 2292 insertions(+) create mode 100644 frameworks/ets/gesture_event/BUILD.gn create mode 100644 frameworks/ets/gesture_event/idl/ohos.multimodalInput.gestureEvent.taihe create mode 100644 frameworks/ets/gesture_event/src/ani_constructor.cpp create mode 100644 frameworks/ets/gesture_event/src/ohos.multimodalInput.gestureEvent.impl.cpp create mode 100644 frameworks/ets/input_consumer/BUILD.gn create mode 100644 frameworks/ets/input_consumer/idl/ohos.multimodalInput.inputConsumer.taihe create mode 100644 frameworks/ets/input_consumer/src/ani_constructor.cpp create mode 100644 frameworks/ets/input_consumer/src/ohos.multimodalInput.inputConsumer.impl.cpp create mode 100644 frameworks/ets/input_event/BUILD.gn create mode 100644 frameworks/ets/input_event/idl/ohos.multimodalInput.inputEvent.taihe create mode 100644 frameworks/ets/input_event/src/ani_constructor.cpp create mode 100644 frameworks/ets/input_event/src/ohos.multimodalInput.inputEvent.impl.cpp create mode 100644 frameworks/ets/input_moniter/BUILD.gn create mode 100644 frameworks/ets/input_moniter/idl/ohos.multimodalInput.inputMoniter.taihe create mode 100644 frameworks/ets/input_moniter/src/ani_constructor.cpp create mode 100644 frameworks/ets/input_moniter/src/ohos.multimodalInput.inputMoniter.impl.cpp create mode 100644 frameworks/ets/intention_code/BUILD.gn create mode 100644 frameworks/ets/intention_code/idl/ohos.multimodalInput.intentionCode.taihe create mode 100644 frameworks/ets/intention_code/src/ani_constructor.cpp create mode 100644 frameworks/ets/intention_code/src/ohos.multimodalInput.intentionCode.impl.cpp create mode 100644 frameworks/ets/key_code/BUILD.gn create mode 100644 frameworks/ets/key_code/idl/ohos.multimodalInput.keyCode.taihe create mode 100644 frameworks/ets/key_code/src/ani_constructor.cpp create mode 100644 frameworks/ets/key_code/src/ohos.multimodalInput.keyCode.impl.cpp create mode 100644 frameworks/ets/key_event/BUILD.gn create mode 100644 frameworks/ets/key_event/idl/ohos.multimodalInput.keyEvent.taihe create mode 100644 frameworks/ets/key_event/src/ani_constructor.cpp create mode 100644 frameworks/ets/key_event/src/ohos.multimodalInput.keyEvent.impl.cpp create mode 100644 frameworks/ets/mouse_event/BUILD.gn create mode 100644 frameworks/ets/mouse_event/idl/ohos.multimodalInput.mouseEvent.taihe create mode 100644 frameworks/ets/mouse_event/src/ani_constructor.cpp create mode 100644 frameworks/ets/mouse_event/src/ohos.multimodalInput.mouseEvent.impl.cpp create mode 100644 frameworks/ets/short_key/BUILD.gn create mode 100644 frameworks/ets/short_key/idl/ohos.multimodalInput.shortKey.taihe create mode 100644 frameworks/ets/short_key/src/ani_constructor.cpp create mode 100644 frameworks/ets/short_key/src/ohos.multimodalInput.shortKey.impl.cpp create mode 100644 frameworks/ets/touch_event/BUILD.gn create mode 100644 frameworks/ets/touch_event/idl/ohos.multimodalInput.touchEvent.taihe create mode 100644 frameworks/ets/touch_event/src/ani_constructor.cpp create mode 100644 frameworks/ets/touch_event/src/ohos.multimodalInput.touchEvent.impl.cpp diff --git a/BUILD.gn b/BUILD.gn index 312c3af36f..ca00dc9926 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -141,6 +141,27 @@ group("input_jsapi_group") { } } +group("cryptoframework_taihe") { + deps = [ + "frameworks/ets/input_event:inputEvent", + "frameworks/ets/key_code:keyCode", + "frameworks/ets/key_event:keyEvent", + "frameworks/ets/mouse_event:mouseEvent", + "frameworks/ets/touch_event:touchEvent", + "frameworks/ets/input_moniter:inputMoniter", + "frameworks/ets/intention_code:intentionCode", + "frameworks/ets/gesture_event:gestureEvent", + ] + if (input_feature_short_key) { + deps += [ "frameworks/ets/short_key:shortKey" ] + } + if (input_feature_keyboard) { + deps += [ + "frameworks/ets/input_consumer:inputConsumer", + ] + } +} + group("mmi_tests") { testonly = true deps = [ diff --git a/bundle.json b/bundle.json index ca80070e07..903980a294 100644 --- a/bundle.json +++ b/bundle.json @@ -167,6 +167,36 @@ }, { "name": "//foundation/multimodalinput/input/libudev:mmi_libudev" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/input_event:input_event_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/intention_code:intention_code_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/key_code:key_code_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/key_event:key_event_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/mouse_event:mouse_event_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/short_key:short_key_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/touch_event:touch_event_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/gesture_event:gesture_event_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/input_consumer:input_consumer_taihe" + }, + { + "name": "//foundation/multimodalinput/input/frameworks/ets/input_moniter:input_moniter_taihe" } ], "test": [ diff --git a/frameworks/ets/gesture_event/BUILD.gn b/frameworks/ets/gesture_event/BUILD.gn new file mode 100644 index 0000000000..b23dca8161 --- /dev/null +++ b/frameworks/ets/gesture_event/BUILD.gn @@ -0,0 +1,92 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("gesture_event_taihe") { + sources = [ "idl/ohos.multimodalInput.gestureEvent.taihe" ] + deps = [ + "${mmi_path}/frameworks/ets/touch_event:touch_event_taihe", + ] +} +config("gestureEvent_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${mmi_path}/util/common/include", + "${mmi_path}/util/network/include", + ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":gesture_event_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.gestureEvent.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.gestureEvent.abi.c", + ] +} +taihe_shared_library("GestureEvent") { + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + configs = [ + "${mmi_path}:coverage_flags", + ":gestureEvent_config", + ] + sources += [ + "src/ani_constructor.cpp", + "src/ohos.multimodalInput.gestureEvent.impl.cpp", + ] + deps = [ + ":run_taihe", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.gestureEvent.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("gestureEvent") { + deps = [ + ":crypto_framework_etc", + ":GestureEvent", + ] +} \ No newline at end of file diff --git a/frameworks/ets/gesture_event/idl/ohos.multimodalInput.gestureEvent.taihe b/frameworks/ets/gesture_event/idl/ohos.multimodalInput.gestureEvent.taihe new file mode 100644 index 0000000000..44c0989d6f --- /dev/null +++ b/frameworks/ets/gesture_event/idl/ohos.multimodalInput.gestureEvent.taihe @@ -0,0 +1,67 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.gestureEvent", "gestureEvent") +from ohos.multimodalInput.touchEvent use Touch; + +struct Pinch { + type: ActionType; + x: i32; + y: i32; +} + +struct ThreeFingersSwipe { + type: ActionType; + x: i32; + y: i32; +} + +struct FourFingersSwipe { + type: ActionType; + x: i32; + y: i32; +} + +struct SwipeInward { + type: ActionType; + x: i32; + y: i32; +} + +struct ThreeFingersTap { + type: ActionType; +} + +struct TouchGestureEvent { + action: TouchGestureAction; + touches: Array; +} + +enum TouchGestureAction : i32 { + SWIPE_DOWN = 0, + SWIPE_UP, + SWIPE_LEFT, + SWIPE_RIGHT, + PINCH_CLOSED, + PINCH_OPENED, + GESTURE_END +} + +enum ActionType : i32 { + CANCEL = 0, + BEGIN = 1, + UPDATE = 2, + END = 3 +} \ No newline at end of file diff --git a/frameworks/ets/gesture_event/src/ani_constructor.cpp b/frameworks/ets/gesture_event/src/ani_constructor.cpp new file mode 100644 index 0000000000..f8f030c08a --- /dev/null +++ b/frameworks/ets/gesture_event/src/ani_constructor.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.gestureEvent.ani.hpp" + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::gestureEvent::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::gestureEvent::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/gesture_event/src/ohos.multimodalInput.gestureEvent.impl.cpp b/frameworks/ets/gesture_event/src/ohos.multimodalInput.gestureEvent.impl.cpp new file mode 100644 index 0000000000..54d5132e9d --- /dev/null +++ b/frameworks/ets/gesture_event/src/ohos.multimodalInput.gestureEvent.impl.cpp @@ -0,0 +1,30 @@ +/* + * 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. +*/ + +#include "ohos.multimodalInput.gestureEvent.proj.hpp" +#include "ohos.multimodalInput.gestureEvent.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +using namespace taihe; +using namespace ohos::multimodalInput::gestureEvent; + +namespace { +// To be implemented. +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND \ No newline at end of file diff --git a/frameworks/ets/input_consumer/BUILD.gn b/frameworks/ets/input_consumer/BUILD.gn new file mode 100644 index 0000000000..93d1abc7c2 --- /dev/null +++ b/frameworks/ets/input_consumer/BUILD.gn @@ -0,0 +1,91 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("input_consumer_taihe") { + sources = [ + "idl/ohos.multimodalInput.inputConsumer.taihe" + ] +} +config("inputConsumer_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${mmi_path}/util/common/include", + "${mmi_path}/util/network/include", + ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":input_consumer_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.inputConsumer.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.inputConsumer.abi.c", + ] +} +taihe_shared_library("InputConsumer") { + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + configs = [ + "${mmi_path}:coverage_flags", + ":inputConsumer_config", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + sources += [ + "src/ani_constructor.cpp", + "src/ohos.multimodalInput.inputConsumer.impl.cpp", + ] + deps = [ + ":run_taihe", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.inputConsumer.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("inputConsumer") { + deps = [ + ":crypto_framework_etc", + ":InputConsumer", + ] +} \ No newline at end of file diff --git a/frameworks/ets/input_consumer/idl/ohos.multimodalInput.inputConsumer.taihe b/frameworks/ets/input_consumer/idl/ohos.multimodalInput.inputConsumer.taihe new file mode 100644 index 0000000000..7c7484ee7d --- /dev/null +++ b/frameworks/ets/input_consumer/idl/ohos.multimodalInput.inputConsumer.taihe @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.inputConsumer", "inputConsumer") + +struct KeyOptions { + preKeys: Array; + finalKey: i32; + isFinalKeyDown: bool; + finalKeyDownDuration: i32; + isRepeat: Optional; +} \ No newline at end of file diff --git a/frameworks/ets/input_consumer/src/ani_constructor.cpp b/frameworks/ets/input_consumer/src/ani_constructor.cpp new file mode 100644 index 0000000000..22bbf49dfd --- /dev/null +++ b/frameworks/ets/input_consumer/src/ani_constructor.cpp @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.inputConsumer.ani.hpp" +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::inputConsumer::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::inputConsumer::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/input_consumer/src/ohos.multimodalInput.inputConsumer.impl.cpp b/frameworks/ets/input_consumer/src/ohos.multimodalInput.inputConsumer.impl.cpp new file mode 100644 index 0000000000..34528f21d5 --- /dev/null +++ b/frameworks/ets/input_consumer/src/ohos.multimodalInput.inputConsumer.impl.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.inputConsumer.proj.hpp" +#include "ohos.multimodalInput.inputConsumer.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +using namespace taihe; +using namespace ohos::multimodalInput::inputConsumer; + +namespace { +// To be implemented. +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND \ No newline at end of file diff --git a/frameworks/ets/input_event/BUILD.gn b/frameworks/ets/input_event/BUILD.gn new file mode 100644 index 0000000000..c3ec660a5c --- /dev/null +++ b/frameworks/ets/input_event/BUILD.gn @@ -0,0 +1,48 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("input_event_taihe") { + sources = [ "idl/ohos.multimodalInput.inputEvent.taihe" ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":input_event_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.inputEvent.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.inputEvent.abi.c", + ] +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.inputEvent.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("inputEvent") { + deps = [ + ":crypto_framework_etc", + ] +} \ No newline at end of file diff --git a/frameworks/ets/input_event/idl/ohos.multimodalInput.inputEvent.taihe b/frameworks/ets/input_event/idl/ohos.multimodalInput.inputEvent.taihe new file mode 100644 index 0000000000..fcf0582661 --- /dev/null +++ b/frameworks/ets/input_event/idl/ohos.multimodalInput.inputEvent.taihe @@ -0,0 +1,24 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.inputEvent", "inputEvent") + +struct InputEvent { + id: i32; + deviceId: i32; + actionTime: i32; + screenId: i32; + windowId: i32; +} \ No newline at end of file diff --git a/frameworks/ets/input_event/src/ani_constructor.cpp b/frameworks/ets/input_event/src/ani_constructor.cpp new file mode 100644 index 0000000000..39e9cd1ceb --- /dev/null +++ b/frameworks/ets/input_event/src/ani_constructor.cpp @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.inputEvent.ani.hpp" +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::inputEvent::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::inputEvent::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/input_event/src/ohos.multimodalInput.inputEvent.impl.cpp b/frameworks/ets/input_event/src/ohos.multimodalInput.inputEvent.impl.cpp new file mode 100644 index 0000000000..1b4afbc062 --- /dev/null +++ b/frameworks/ets/input_event/src/ohos.multimodalInput.inputEvent.impl.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.inputEvent.proj.hpp" +#include "ohos.multimodalInput.inputEvent.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +using namespace taihe; +using namespace ohos::multimodalInput::inputEvent; + +namespace { +// To be implemented. +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND \ No newline at end of file diff --git a/frameworks/ets/input_moniter/BUILD.gn b/frameworks/ets/input_moniter/BUILD.gn new file mode 100644 index 0000000000..3f4197a4a8 --- /dev/null +++ b/frameworks/ets/input_moniter/BUILD.gn @@ -0,0 +1,98 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("input_moniter_taihe") { + sources = [ "idl/ohos.multimodalInput.inputMoniter.taihe" ] + deps = [ +# "${mmi_path}/frameworks/ets/gestrue_event:gestrue_event_taihe", +# "${mmi_path}/frameworks/ets/input_consumer:input_consumer_taihe", +# "${mmi_path}/frameworks/ets/key_event:key_event_taihe", +# "${mmi_path}/frameworks/ets/key_code:key_code_taihe", + "${mmi_path}/frameworks/ets/mouse_event:mouse_event_taihe", + "${mmi_path}/frameworks/ets/touch_event:touch_event_taihe", + ] +} +config("inputMoniter_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${mmi_path}/interfaces/native/innerkits/proxy/include", + "${mmi_path}/service/permission_helper/include", + "${mmi_path}/util/common/include", + ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":input_moniter_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.inputMoniter.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.inputMoniter.abi.c", + ] +} +taihe_shared_library("InputMoniter") { + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + configs = [ + "${mmi_path}:coverage_flags", + ":inputMoniter_config", + ] + sources += [ + "src/ani_constructor.cpp", + "src/ohos.multimodalInput.inputMoniter.impl.cpp", + ] + deps = [ + ":run_taihe", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.inputMoniter.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("inputMoniter") { + deps = [ + ":crypto_framework_etc", + ":InputMoniter", + ] +} \ No newline at end of file diff --git a/frameworks/ets/input_moniter/idl/ohos.multimodalInput.inputMoniter.taihe b/frameworks/ets/input_moniter/idl/ohos.multimodalInput.inputMoniter.taihe new file mode 100644 index 0000000000..4d8089d1a8 --- /dev/null +++ b/frameworks/ets/input_moniter/idl/ohos.multimodalInput.inputMoniter.taihe @@ -0,0 +1,22 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.inputMoniter", "inputMoniter") +from ohos.multimodalInput.touchEvent use TouchEvent; +from ohos.multimodalInput.mouseEvent use MouseEvent; + +struct TouchEventReceiver { + filter: (touchEvent: TouchEvent) => bool; +} \ No newline at end of file diff --git a/frameworks/ets/input_moniter/src/ani_constructor.cpp b/frameworks/ets/input_moniter/src/ani_constructor.cpp new file mode 100644 index 0000000000..78dc832cb3 --- /dev/null +++ b/frameworks/ets/input_moniter/src/ani_constructor.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.inputMoniter.ani.hpp" + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::inputMoniter::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::inputMoniter::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/input_moniter/src/ohos.multimodalInput.inputMoniter.impl.cpp b/frameworks/ets/input_moniter/src/ohos.multimodalInput.inputMoniter.impl.cpp new file mode 100644 index 0000000000..f4744b54db --- /dev/null +++ b/frameworks/ets/input_moniter/src/ohos.multimodalInput.inputMoniter.impl.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.inputMoniter.proj.hpp" +#include "ohos.multimodalInput.inputMoniter.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +using namespace taihe; +using namespace ohos::multimodalInput::inputMoniter; + +namespace { +// To be implemented. +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND \ No newline at end of file diff --git a/frameworks/ets/intention_code/BUILD.gn b/frameworks/ets/intention_code/BUILD.gn new file mode 100644 index 0000000000..23bbbad2be --- /dev/null +++ b/frameworks/ets/intention_code/BUILD.gn @@ -0,0 +1,91 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("intention_code_taihe") { + sources = [ + "idl/ohos.multimodalInput.intentionCode.taihe" + ] +} +config("intentionCode_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${mmi_path}/util/common/include", + "${mmi_path}/util/network/include", + ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":intention_code_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.intentionCode.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.intentionCode.abi.c", + ] +} +taihe_shared_library("IntentionCode") { + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + configs = [ + "${mmi_path}:coverage_flags", + ":intentionCode_config", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + sources += [ + "src/ani_constructor.cpp", + "src/ohos.multimodalInput.intentionCode.impl.cpp", + ] + deps = [ + ":run_taihe", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.intentionCode.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("intentionCode") { + deps = [ + ":crypto_framework_etc", + ":IntentionCode", + ] +} \ No newline at end of file diff --git a/frameworks/ets/intention_code/idl/ohos.multimodalInput.intentionCode.taihe b/frameworks/ets/intention_code/idl/ohos.multimodalInput.intentionCode.taihe new file mode 100644 index 0000000000..cea0d7b0e1 --- /dev/null +++ b/frameworks/ets/intention_code/idl/ohos.multimodalInput.intentionCode.taihe @@ -0,0 +1,33 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.intentionCode", "intentionCode") + +enum IntentionCode : i32 { + INTENTION_UNKNOWN = -1, + INTENTION_UP = 1, + INTENTION_DOWN = 2, + INTENTION_LEFT = 3, + INTENTION_RIGHT = 4, + INTENTION_SELECT = 5, + INTENTION_ESCAPE = 6, + INTENTION_BACK = 7, + INTENTION_FORWARD = 8, + INTENTION_MENU = 9, + INTENTION_PAGE_UP = 11, + INTENTION_PAGE_DOWN = 12, + INTENTION_ZOOM_OUT = 13, + INTENTION_ZOOM_IN = 14 +} \ No newline at end of file diff --git a/frameworks/ets/intention_code/src/ani_constructor.cpp b/frameworks/ets/intention_code/src/ani_constructor.cpp new file mode 100644 index 0000000000..45f23be42b --- /dev/null +++ b/frameworks/ets/intention_code/src/ani_constructor.cpp @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.intentionCode.ani.hpp" +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::intentionCode::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::intentionCode::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/intention_code/src/ohos.multimodalInput.intentionCode.impl.cpp b/frameworks/ets/intention_code/src/ohos.multimodalInput.intentionCode.impl.cpp new file mode 100644 index 0000000000..679dd7b3a3 --- /dev/null +++ b/frameworks/ets/intention_code/src/ohos.multimodalInput.intentionCode.impl.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.intentionCode.proj.hpp" +#include "ohos.multimodalInput.intentionCode.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +using namespace taihe; +using namespace ohos::multimodalInput::intentionCode; + +namespace { +// To be implemented. +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND \ No newline at end of file diff --git a/frameworks/ets/key_code/BUILD.gn b/frameworks/ets/key_code/BUILD.gn new file mode 100644 index 0000000000..37108a3f9c --- /dev/null +++ b/frameworks/ets/key_code/BUILD.gn @@ -0,0 +1,92 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("key_code_taihe") { + sources = [ + "idl/ohos.multimodalInput.keyCode.taihe" + ] +} +config("keyCode_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${mmi_path}/util/common/include", + "${mmi_path}/tools/event_inject/include", + "${mmi_path}/interfaces/native/innerkits/proxy/include", + ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":key_code_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.keyCode.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.keyCode.abi.c", + ] +} +taihe_shared_library("KeyCode") { + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + configs = [ + "${mmi_path}:coverage_flags", + ":keyCode_config", + ] + sources += [ + "src/ani_constructor.cpp", + "src/ohos.multimodalInput.keyCode.impl.cpp", + ] + deps = [ + ":run_taihe", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.keyCode.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("keyCode") { + deps = [ + ":crypto_framework_etc", + ":KeyCode", + ] +} \ No newline at end of file diff --git a/frameworks/ets/key_code/idl/ohos.multimodalInput.keyCode.taihe b/frameworks/ets/key_code/idl/ohos.multimodalInput.keyCode.taihe new file mode 100644 index 0000000000..be90910e0b --- /dev/null +++ b/frameworks/ets/key_code/idl/ohos.multimodalInput.keyCode.taihe @@ -0,0 +1,366 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.keyCode", "keyCode") + +enum KeyCode : i32 { + KEYCODE_FN = 0, + KEYCODE_UNKNOWN = -1, + KEYCODE_HOME = 1, + KEYCODE_BACK = 2, + KEYCODE_SEARCH = 9, + KEYCODE_MEDIA_PLAY_PAUSE = 10, + KEYCODE_MEDIA_STOP = 11, + KEYCODE_MEDIA_NEXT = 12, + KEYCODE_MEDIA_PREVIOUS = 13, + KEYCODE_MEDIA_REWIND = 14, + KEYCODE_MEDIA_FAST_FORWARD = 15, + KEYCODE_VOLUME_UP = 16, + KEYCODE_VOLUME_DOWN = 17, + KEYCODE_POWER = 18, + KEYCODE_CAMERA = 19, + KEYCODE_VOLUME_MUTE = 22, + KEYCODE_MUTE = 23, + KEYCODE_BRIGHTNESS_UP = 40, + KEYCODE_BRIGHTNESS_DOWN = 41, + KEYCODE_0 = 2000, + KEYCODE_1 = 2001, + KEYCODE_2 = 2002, + KEYCODE_3 = 2003, + KEYCODE_4 = 2004, + KEYCODE_5 = 2005, + KEYCODE_6 = 2006, + KEYCODE_7 = 2007, + KEYCODE_8 = 2008, + KEYCODE_9 = 2009, + KEYCODE_STAR = 2010, + KEYCODE_POUND = 2011, + KEYCODE_DPAD_UP = 2012, + KEYCODE_DPAD_DOWN = 2013, + KEYCODE_DPAD_LEFT = 2014, + KEYCODE_DPAD_RIGHT = 2015, + KEYCODE_DPAD_CENTER = 2016, + KEYCODE_A = 2017, + KEYCODE_B = 2018, + KEYCODE_C = 2019, + KEYCODE_D = 2020, + KEYCODE_E = 2021, + KEYCODE_F = 2022, + KEYCODE_G = 2023, + KEYCODE_H = 2024, + KEYCODE_I = 2025, + KEYCODE_J = 2026, + KEYCODE_K = 2027, + KEYCODE_L = 2028, + KEYCODE_M = 2029, + KEYCODE_N = 2030, + KEYCODE_O = 2031, + KEYCODE_P = 2032, + KEYCODE_Q = 2033, + KEYCODE_R = 2034, + KEYCODE_S = 2035, + KEYCODE_T = 2036, + KEYCODE_U = 2037, + KEYCODE_V = 2038, + KEYCODE_W = 2039, + KEYCODE_X = 2040, + KEYCODE_Y = 2041, + KEYCODE_Z = 2042, + KEYCODE_COMMA = 2043, + KEYCODE_PERIOD = 2044, + KEYCODE_ALT_LEFT = 2045, + KEYCODE_ALT_RIGHT = 2046, + KEYCODE_SHIFT_LEFT = 2047, + KEYCODE_SHIFT_RIGHT = 2048, + KEYCODE_TAB = 2049, + KEYCODE_SPACE = 2050, + KEYCODE_SYM = 2051, + KEYCODE_EXPLORER = 2052, + KEYCODE_ENVELOPE = 2053, + KEYCODE_ENTER = 2054, + KEYCODE_DEL = 2055, + KEYCODE_GRAVE = 2056, + KEYCODE_MINUS = 2057, + KEYCODE_EQUALS = 2058, + KEYCODE_LEFT_BRACKET = 2059, + KEYCODE_RIGHT_BRACKET = 2060, + KEYCODE_BACKSLASH = 2061, + KEYCODE_SEMICOLON = 2062, + KEYCODE_APOSTROPHE = 2063, + KEYCODE_SLASH = 2064, + KEYCODE_AT = 2065, + KEYCODE_PLUS = 2066, + KEYCODE_MENU = 2067, + KEYCODE_PAGE_UP = 2068, + KEYCODE_PAGE_DOWN = 2069, + KEYCODE_ESCAPE = 2070, + KEYCODE_FORWARD_DEL = 2071, + KEYCODE_CTRL_LEFT = 2072, + KEYCODE_CTRL_RIGHT = 2073, + KEYCODE_CAPS_LOCK = 2074, + KEYCODE_SCROLL_LOCK = 2075, + KEYCODE_META_LEFT = 2076, + KEYCODE_META_RIGHT = 2077, + KEYCODE_FUNCTION = 2078, + KEYCODE_SYSRQ = 2079, + KEYCODE_BREAK = 2080, + KEYCODE_MOVE_HOME = 2081, + KEYCODE_MOVE_END = 2082, + KEYCODE_INSERT = 2083, + KEYCODE_FORWARD = 2084, + KEYCODE_MEDIA_PLAY = 2085, + KEYCODE_MEDIA_PAUSE = 2086, + KEYCODE_MEDIA_CLOSE = 2087, + KEYCODE_MEDIA_EJECT = 2088, + KEYCODE_MEDIA_RECORD = 2089, + KEYCODE_F1 = 2090, + KEYCODE_F2 = 2091, + KEYCODE_F3 = 2092, + KEYCODE_F4 = 2093, + KEYCODE_F5 = 2094, + KEYCODE_F6 = 2095, + KEYCODE_F7 = 2096, + KEYCODE_F8 = 2097, + KEYCODE_F9 = 2098, + KEYCODE_F10 = 2099, + KEYCODE_F11 = 2100, + KEYCODE_F12 = 2101, + KEYCODE_NUM_LOCK = 2102, + KEYCODE_NUMPAD_0 = 2103, + KEYCODE_NUMPAD_1 = 2104, + KEYCODE_NUMPAD_2 = 2105, + KEYCODE_NUMPAD_3 = 2106, + KEYCODE_NUMPAD_4 = 2107, + KEYCODE_NUMPAD_5 = 2108, + KEYCODE_NUMPAD_6 = 2109, + KEYCODE_NUMPAD_7 = 2110, + KEYCODE_NUMPAD_8 = 2111, + KEYCODE_NUMPAD_9 = 2112, + KEYCODE_NUMPAD_DIVIDE = 2113, + KEYCODE_NUMPAD_MULTIPLY = 2114, + KEYCODE_NUMPAD_SUBTRACT = 2115, + KEYCODE_NUMPAD_ADD = 2116, + KEYCODE_NUMPAD_DOT = 2117, + KEYCODE_NUMPAD_COMMA = 2118, + KEYCODE_NUMPAD_ENTER = 2119, + KEYCODE_NUMPAD_EQUALS = 2120, + KEYCODE_NUMPAD_LEFT_PAREN = 2121, + KEYCODE_NUMPAD_RIGHT_PAREN = 2122, + KEYCODE_VIRTUAL_MULTITASK = 2210, + KEYCODE_BUTTON_A = 2301, + KEYCODE_BUTTON_B = 2302, + KEYCODE_BUTTON_X = 2304, + KEYCODE_BUTTON_Y = 2305, + KEYCODE_BUTTON_L1 = 2307, + KEYCODE_BUTTON_R1 = 2308, + KEYCODE_BUTTON_L2 = 2309, + KEYCODE_BUTTON_R2 = 2310, + KEYCODE_BUTTON_SELECT = 2311, + KEYCODE_BUTTON_START = 2312, + KEYCODE_BUTTON_MODE = 2313, + KEYCODE_BUTTON_THUMBL = 2314, + KEYCODE_BUTTON_THUMBR = 2315, + KEYCODE_SLEEP = 2600, + KEYCODE_ZENKAKU_HANKAKU = 2601, + KEYCODE_102ND = 2602, + KEYCODE_RO = 2603, + KEYCODE_KATAKANA = 2604, + KEYCODE_HIRAGANA = 2605, + KEYCODE_HENKAN = 2606, + KEYCODE_KATAKANA_HIRAGANA = 2607, + KEYCODE_MUHENKAN = 2608, + KEYCODE_LINEFEED = 2609, + KEYCODE_MACRO = 2610, + KEYCODE_NUMPAD_PLUSMINUS = 2611, + KEYCODE_SCALE = 2612, + KEYCODE_HANGUEL = 2613, + KEYCODE_HANJA = 2614, + KEYCODE_YEN = 2615, + KEYCODE_STOP = 2616, + KEYCODE_AGAIN = 2617, + KEYCODE_PROPS = 2618, + KEYCODE_UNDO = 2619, + KEYCODE_COPY = 2620, + KEYCODE_OPEN = 2621, + KEYCODE_PASTE = 2622, + KEYCODE_FIND = 2623, + KEYCODE_CUT = 2624, + KEYCODE_HELP = 2625, + KEYCODE_CALC = 2626, + KEYCODE_FILE = 2627, + KEYCODE_BOOKMARKS = 2628, + KEYCODE_NEXT = 2629, + KEYCODE_PLAYPAUSE = 2630, + KEYCODE_PREVIOUS = 2631, + KEYCODE_STOPCD = 2632, + KEYCODE_CONFIG = 2634, + KEYCODE_REFRESH = 2635, + KEYCODE_EXIT = 2636, + KEYCODE_EDIT = 2637, + KEYCODE_SCROLLUP = 2638, + KEYCODE_SCROLLDOWN = 2639, + KEYCODE_NEW = 2640, + KEYCODE_REDO = 2641, + KEYCODE_CLOSE = 2642, + KEYCODE_PLAY = 2643, + KEYCODE_BASSBOOST = 2644, + KEYCODE_PRINT = 2645, + KEYCODE_CHAT = 2646, + KEYCODE_FINANCE = 2647, + KEYCODE_CANCEL = 2648, + KEYCODE_KBDILLUM_TOGGLE = 2649, + KEYCODE_KBDILLUM_DOWN = 2650, + KEYCODE_KBDILLUM_UP = 2651, + KEYCODE_SEND = 2652, + KEYCODE_REPLY = 2653, + KEYCODE_FORWARDMAIL = 2654, + KEYCODE_SAVE = 2655, + KEYCODE_DOCUMENTS = 2656, + KEYCODE_VIDEO_NEXT = 2657, + KEYCODE_VIDEO_PREV = 2658, + KEYCODE_BRIGHTNESS_CYCLE = 2659, + KEYCODE_BRIGHTNESS_ZERO = 2660, + KEYCODE_DISPLAY_OFF = 2661, + KEYCODE_BTN_MISC = 2662, + KEYCODE_GOTO = 2663, + KEYCODE_INFO = 2664, + KEYCODE_PROGRAM = 2665, + KEYCODE_PVR = 2666, + KEYCODE_SUBTITLE = 2667, + KEYCODE_FULL_SCREEN = 2668, + KEYCODE_KEYBOARD = 2669, + KEYCODE_ASPECT_RATIO = 2670, + KEYCODE_PC = 2671, + KEYCODE_TV = 2672, + KEYCODE_TV2 = 2673, + KEYCODE_VCR = 2674, + KEYCODE_VCR2 = 2675, + KEYCODE_SAT = 2676, + KEYCODE_CD = 2677, + KEYCODE_TAPE = 2678, + KEYCODE_TUNER = 2679, + KEYCODE_PLAYER = 2680, + KEYCODE_DVD = 2681, + KEYCODE_AUDIO = 2682, + KEYCODE_VIDEO = 2683, + KEYCODE_MEMO = 2684, + KEYCODE_CALENDAR = 2685, + KEYCODE_RED = 2686, + KEYCODE_GREEN = 2687, + KEYCODE_YELLOW = 2688, + KEYCODE_BLUE = 2689, + KEYCODE_CHANNELUP = 2690, + KEYCODE_CHANNELDOWN = 2691, + KEYCODE_LAST = 2692, + KEYCODE_RESTART = 2693, + KEYCODE_SLOW = 2694, + KEYCODE_SHUFFLE = 2695, + KEYCODE_VIDEOPHONE = 2696, + KEYCODE_GAMES = 2697, + KEYCODE_ZOOMIN = 2698, + KEYCODE_ZOOMOUT = 2699, + KEYCODE_ZOOMRESET = 2700, + KEYCODE_WORDPROCESSOR = 2701, + KEYCODE_EDITOR = 2702, + KEYCODE_SPREADSHEET = 2703, + KEYCODE_GRAPHICSEDITOR = 2704, + KEYCODE_PRESENTATION = 2705, + KEYCODE_DATABASE = 2706, + KEYCODE_NEWS = 2707, + KEYCODE_VOICEMAIL = 2708, + KEYCODE_ADDRESSBOOK = 2709, + KEYCODE_MESSENGER = 2710, + KEYCODE_BRIGHTNESS_TOGGLE = 2711, + KEYCODE_SPELLCHECK = 2712, + KEYCODE_COFFEE = 2713, + KEYCODE_MEDIA_REPEAT = 2714, + KEYCODE_IMAGES = 2715, + KEYCODE_BUTTONCONFIG = 2716, + KEYCODE_TASKMANAGER = 2717, + KEYCODE_JOURNAL = 2718, + KEYCODE_CONTROLPANEL = 2719, + KEYCODE_APPSELECT = 2720, + KEYCODE_SCREENSAVER = 2721, + KEYCODE_ASSISTANT = 2722, + KEYCODE_KBD_LAYOUT_NEXT = 2723, + KEYCODE_BRIGHTNESS_MIN = 2724, + KEYCODE_BRIGHTNESS_MAX = 2725, + KEYCODE_KBDINPUTASSIST_PREV = 2726, + KEYCODE_KBDINPUTASSIST_NEXT = 2727, + KEYCODE_KBDINPUTASSIST_PREVGROUP = 2728, + KEYCODE_KBDINPUTASSIST_NEXTGROUP = 2729, + KEYCODE_KBDINPUTASSIST_ACCEPT = 2730, + KEYCODE_KBDINPUTASSIST_CANCEL = 2731, + KEYCODE_FRONT = 2800, + KEYCODE_SETUP = 2801, + KEYCODE_WAKEUP = 2802, + KEYCODE_SENDFILE = 2803, + KEYCODE_DELETEFILE = 2804, + KEYCODE_XFER = 2805, + KEYCODE_PROG1 = 2806, + KEYCODE_PROG2 = 2807, + KEYCODE_MSDOS = 2808, + KEYCODE_SCREENLOCK = 2809, + KEYCODE_DIRECTION_ROTATE_DISPLAY = 2810, + KEYCODE_CYCLEWINDOWS = 2811, + KEYCODE_COMPUTER = 2812, + KEYCODE_EJECTCLOSECD = 2813, + KEYCODE_ISO = 2814, + KEYCODE_MOVE = 2815, + KEYCODE_F13 = 2816, + KEYCODE_F14 = 2817, + KEYCODE_F15 = 2818, + KEYCODE_F16 = 2819, + KEYCODE_F17 = 2820, + KEYCODE_F18 = 2821, + KEYCODE_F19 = 2822, + KEYCODE_F20 = 2823, + KEYCODE_F21 = 2824, + KEYCODE_F22 = 2825, + KEYCODE_F23 = 2826, + KEYCODE_F24 = 2827, + KEYCODE_PROG3 = 2828, + KEYCODE_PROG4 = 2829, + KEYCODE_DASHBOARD = 2830, + KEYCODE_SUSPEND = 2831, + KEYCODE_HP = 2832, + KEYCODE_SOUND = 2833, + KEYCODE_QUESTION = 2834, + KEYCODE_CONNECT = 2836, + KEYCODE_SPORT = 2837, + KEYCODE_SHOP = 2838, + KEYCODE_ALTERASE = 2839, + KEYCODE_SWITCHVIDEOMODE = 2841, + KEYCODE_BATTERY = 2842, + KEYCODE_BLUETOOTH = 2843, + KEYCODE_WLAN = 2844, + KEYCODE_UWB = 2845, + KEYCODE_WWAN_WIMAX = 2846, + KEYCODE_RFKILL = 2847, + KEYCODE_CHANNEL = 3001, + KEYCODE_BTN_0 = 3100, + KEYCODE_BTN_1 = 3101, + KEYCODE_BTN_2 = 3102, + KEYCODE_BTN_3 = 3103, + KEYCODE_BTN_4 = 3104, + KEYCODE_BTN_5 = 3105, + KEYCODE_BTN_6 = 3106, + KEYCODE_BTN_7 = 3107, + KEYCODE_BTN_8 = 3108, + KEYCODE_BTN_9 = 3109, + KEYCODE_DAGGER_CLICK = 3211, + KEYCODE_DAGGER_DOUBLE_CLICK = 3212, + KEYCODE_DAGGER_LONG_PRESS = 3213 +} \ No newline at end of file diff --git a/frameworks/ets/key_code/src/ani_constructor.cpp b/frameworks/ets/key_code/src/ani_constructor.cpp new file mode 100644 index 0000000000..bed80b9d8c --- /dev/null +++ b/frameworks/ets/key_code/src/ani_constructor.cpp @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.keyCode.ani.hpp" +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::keyCode::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::keyCode::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/key_code/src/ohos.multimodalInput.keyCode.impl.cpp b/frameworks/ets/key_code/src/ohos.multimodalInput.keyCode.impl.cpp new file mode 100644 index 0000000000..5ed9186a42 --- /dev/null +++ b/frameworks/ets/key_code/src/ohos.multimodalInput.keyCode.impl.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.keyCode.proj.hpp" +#include "ohos.multimodalInput.keyCode.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +using namespace taihe; +using namespace ohos::multimodalInput::keyCode; + +namespace { +// To be implemented. +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND \ No newline at end of file diff --git a/frameworks/ets/key_event/BUILD.gn b/frameworks/ets/key_event/BUILD.gn new file mode 100644 index 0000000000..cd75bf3a61 --- /dev/null +++ b/frameworks/ets/key_event/BUILD.gn @@ -0,0 +1,95 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("key_event_taihe") { + sources = [ "idl/ohos.multimodalInput.keyEvent.taihe" ] + deps = [ + "${mmi_path}/frameworks/ets/input_event:input_event_taihe", + "${mmi_path}/frameworks/ets/key_code:key_code_taihe", + ] +} +config("keyEvent_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${mmi_path}/util/common/include", + "${mmi_path}/tools/event_inject/include", + "${mmi_path}/interfaces/kits/c/input", + "${mmi_path}/interfaces/native/innerkits/proxy/include", + ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":key_event_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.keyEvent.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.keyEvent.abi.c", + ] +} +taihe_shared_library("KeyEvent") { + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + configs = [ + "${mmi_path}:coverage_flags", + ":keyEvent_config", + ] + sources += [ + "src/ani_constructor.cpp", + "src/ohos.multimodalInput.keyEvent.impl.cpp", + ] + deps = [ + ":run_taihe", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.keyEvent.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("keyEvent") { + deps = [ + ":crypto_framework_etc", + ":KeyEvent", + ] +} \ No newline at end of file diff --git a/frameworks/ets/key_event/idl/ohos.multimodalInput.keyEvent.taihe b/frameworks/ets/key_event/idl/ohos.multimodalInput.keyEvent.taihe new file mode 100644 index 0000000000..4f1ddf85a8 --- /dev/null +++ b/frameworks/ets/key_event/idl/ohos.multimodalInput.keyEvent.taihe @@ -0,0 +1,46 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.keyEvent", "keyEvent") +from ohos.multimodalInput.keyCode use KeyCode; +from ohos.multimodalInput.inputEvent use InputEvent; + +enum Action : i32 { + CANCEL = 0, + DOWN = 1, + UP = 2 +} + +struct Key { + code: KeyCode; + pressedTime: i32; + deviceId: i32; +} + +struct KeyEvent { + @extends base: InputEvent; + action: Action; + key: Key; + unicodeChar: i32; + keys: Array; + ctrlKey: bool; + altKey: bool; + shiftKey: bool; + logoKey: bool; + fnKey: bool; + capsLock: bool; + numLock: bool; + scrollLock: bool; +} \ No newline at end of file diff --git a/frameworks/ets/key_event/src/ani_constructor.cpp b/frameworks/ets/key_event/src/ani_constructor.cpp new file mode 100644 index 0000000000..de0a5c11be --- /dev/null +++ b/frameworks/ets/key_event/src/ani_constructor.cpp @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.keyEvent.ani.hpp" +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimodalInput::keyEvent::ANIRegister(env)) { + std::cerr << "Error from ohos::multimodalInput::keyEvent::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/frameworks/ets/key_event/src/ohos.multimodalInput.keyEvent.impl.cpp b/frameworks/ets/key_event/src/ohos.multimodalInput.keyEvent.impl.cpp new file mode 100644 index 0000000000..47dfc38294 --- /dev/null +++ b/frameworks/ets/key_event/src/ohos.multimodalInput.keyEvent.impl.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "ohos.multimodalInput.keyEvent.proj.hpp" +#include "ohos.multimodalInput.keyEvent.impl.hpp" +#include "taihe/runtime.hpp" +#include "stdexcept" + +using namespace taihe; +using namespace ohos::multimodalInput::keyEvent; + +namespace { +// To be implemented. +} // namespace + +// Since these macros are auto-generate, lint will cause false positive. +// NOLINTBEGIN +// NOLINTEND \ No newline at end of file diff --git a/frameworks/ets/mouse_event/BUILD.gn b/frameworks/ets/mouse_event/BUILD.gn new file mode 100644 index 0000000000..451151611c --- /dev/null +++ b/frameworks/ets/mouse_event/BUILD.gn @@ -0,0 +1,90 @@ +# 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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimodalinput/input/multimodalinput_mini.gni") +copy_taihe_idl("mouse_event_taihe") { + sources = [ "idl/ohos.multimodalInput.mouseEvent.taihe" ] + deps = [ "${mmi_path}/frameworks/ets/input_event:input_event_taihe" ] +} +config("mouseEvent_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${mmi_path}/util/common/include", + "${mmi_path}/util/network/include", + ] +} +subsystem_name = "multimodalinput" +part_name = "input" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":mouse_event_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimodalInput.mouseEvent.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimodalInput.mouseEvent.abi.c", + ] +} +taihe_shared_library("MouseEvent") { + taihe_generated_file_path = "$taihe_generated_file_path" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + sources = get_target_outputs(":run_taihe") + configs = [ + "${mmi_path}:coverage_flags", + ":mouseEvent_config", + ] + sources += [ + "src/ani_constructor.cpp", + "src/ohos.multimodalInput.mouseEvent.impl.cpp", + ] + deps = [ + ":run_taihe", + "${mmi_path}/frameworks/proxy:libmmi-client", + "${mmi_path}/util:libmmi-util", + ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } +} +generate_static_abc("crypto_framework_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimodalInput.mouseEvent.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/crypto_framework_abc.abc" + dependencies = [ ":run_taihe" ] +} +ohos_prebuilt_etc("crypto_framework_etc") { + source = "$target_out_dir/crypto_framework_abc.abc" + module_install_dir = "frameworks" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ ":crypto_framework_abc" ] +} +group("mouseEvent") { + deps = [ + ":crypto_framework_etc", + ":MouseEvent", + ] +} \ No newline at end of file diff --git a/frameworks/ets/mouse_event/idl/ohos.multimodalInput.mouseEvent.taihe b/frameworks/ets/mouse_event/idl/ohos.multimodalInput.mouseEvent.taihe new file mode 100644 index 0000000000..342d6daaba --- /dev/null +++ b/frameworks/ets/mouse_event/idl/ohos.multimodalInput.mouseEvent.taihe @@ -0,0 +1,83 @@ +/* + * 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. + */ + +@!namespace("@ohos.multimodalInput.mouseEvent", "mouseEvent") +from ohos.multimodalInput.inputEvent use InputEvent; +from ohos.multimodalInput.keyCode use KeyCode; + +enum Action : i32 { + CANCEL = 0, + MOVE = 1, + BUTTON_DOWN = 2, + BUTTON_UP = 3, + AXIS_BEGIN = 4, + AXIS_UPDATE = 5, + AXIS_END = 6, + ACTION_DOWN = 7, + ACTION_UP = 8, +} + +enum Button : i32 { + LEFT = 0, + MIDDLE = 1, + RIGHT = 2, + SIDE = 3, + EXTRA = 4, + FORWARD = 5, + BACK = 6, + TASK = 7 +} + +enum Axis : i32 { + SCROLL_VERTICAL = 0, + SCROLL_HORIZONTAL = 1, + PINCH = 2 +} + +struct AxisValue { + axis: Axis; + value: i32; +} + +enum ToolType : i32 { + UNKNOWN = 0, + MOUSE = 1, + JOYSTICK = 2, + TOUCHPAD = 3, +} + +struct MouseEvent { + @extends base:InputEvent; + action: Action; + screenX: i32; + screenY: i32; + windowX: i32; + windowY: i32; + rawDeltaX: i32; + rawDeltaY: i32; + button: Button; + pressedButtons: Array