• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "pointer.h"
17 #include <iostream>
18 
19 #include "define_multimodal.h"
20 #include "input_manager.h"
21 #include "mmi_log.h"
22 
23 #include <cstdint>
24 #include <cmath>
25 #include <limits>
26 
27 #undef MMI_LOG_TAG
28 #define MMI_LOG_TAG "AniPointer"
29 
30 using namespace OHOS::MMI;
31 
32 namespace {
33 constexpr int32_t ANI_SCOPE_SIZE = 16;
34 constexpr int32_t MILLISECOND_FACTOR = 1000;
35 constexpr size_t EVENT_NAME_LEN { 64 };
36 constexpr size_t PRE_KEYS_SIZE { 4 };
37 constexpr size_t INPUT_PARAMETER_MIDDLE { 2 };
38 constexpr size_t INPUT_PARAMETER_MAX { 3 };
39 constexpr int32_t OCCUPIED_BY_SYSTEM = -3;
40 constexpr int32_t OCCUPIED_BY_OTHER = -4;
41 const double INT32_MAX_D = static_cast<double>(std::numeric_limits<int32_t>::max());
42 } // namespace
43 
44 enum AniErrorCode : int32_t {
45     COMMON_PARAMETER_ERROR = 401,
46     COMMON_USE_SYSAPI_ERROR = 202,
47 };
48 
ThrowBusinessError(ani_env * env,int errCode,std::string && errMsg)49 static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg)
50 {
51     MMI_HILOGD("Begin ThrowBusinessError.");
52     static const char *errorClsName = "L@ohos/base/BusinessError;";
53     ani_class cls {};
54     if (ANI_OK != env->FindClass(errorClsName, &cls)) {
55         MMI_HILOGE("find class BusinessError %{public}s failed", errorClsName);
56         return;
57     }
58     ani_method ctor;
59     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
60         MMI_HILOGE("find method BusinessError.constructor failed");
61         return;
62     }
63     ani_object errorObject;
64     if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) {
65         MMI_HILOGE("create BusinessError object failed");
66         return;
67     }
68     ani_double aniErrCode = static_cast<ani_double>(errCode);
69     ani_string errMsgStr;
70     if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) {
71         MMI_HILOGE("convert errMsg to ani_string failed");
72         return;
73     }
74     if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) {
75         MMI_HILOGE("set error code failed");
76         return;
77     }
78     if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) {
79         MMI_HILOGE("set error message failed");
80         return;
81     }
82     env->ThrowError(static_cast<ani_error>(errorObject));
83     return;
84 }
85 
ToInt32ECMAScript(double value)86 static int32_t ToInt32ECMAScript(double value)
87 {
88     if (std::isnan(value) || std::isinf(value)) {
89         return 0;
90     }
91 
92     double truncated = std::trunc(value);
93     double modValue = std::fmod(truncated, 4294967296.0);
94     uint32_t uint32Val = static_cast<uint32_t>(modValue);
95     return static_cast<int32_t>(uint32Val);
96 }
97 
ParseEnumToInt(ani_env * env,ani_enum_item enumItem)98 static ani_int ParseEnumToInt(ani_env *env, ani_enum_item enumItem)
99 {
100     ani_int intValue = -1;
101     if (ANI_OK != env->EnumItem_GetValue_Int(enumItem, &intValue)) {
102         MMI_HILOGE("%{public}s: EnumItem_GetValue_Int FAILD.", __func__);
103         return -1;
104     }
105     MMI_HILOGD("%{public}s: Enum Value: %{public}d.", __func__, intValue);
106     return intValue;
107 }
108 
SetPointerStyleInner(ani_env * env,ani_double windowid,ani_enum_item pointerStyle)109 static int SetPointerStyleInner(ani_env *env, ani_double windowid, ani_enum_item pointerStyle)
110 {
111     int32_t windowID = ToInt32ECMAScript(static_cast<double>(windowid));
112     if (windowID < 0 && windowID != GLOBAL_WINDOW_ID) {
113         MMI_HILOGE("Invalid windowid");
114         ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "Windowid is invalid");
115         return 0;
116     }
117 
118     int32_t pointerStyleID = ParseEnumToInt(env, pointerStyle);
119     if ((pointerStyleID < DEFAULT && pointerStyleID != DEVELOPER_DEFINED_ICON) || pointerStyleID > RUNNING) {
120         MMI_HILOGE("Undefined pointer style");
121         ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "Pointer style does not exist");
122         return 0;
123     }
124 
125     PointerStyle style;
126     style.id = pointerStyleID;
127     int32_t errorCode = InputManager::GetInstance()->SetPointerStyle(windowid, style);
128     if (errorCode == COMMON_USE_SYSAPI_ERROR) {
129         MMI_HILOGE("The windowId is negative number and no system applications use system API");
130         ThrowBusinessError(env, COMMON_USE_SYSAPI_ERROR,
131             "windowId is negative number and no system applications use system API");
132         return 0;
133     }
134     MMI_HILOGD(" SetPointerStyleInner end.");
135     return 0;
136 }
137 
ANI_Constructor(ani_vm * vm,uint32_t * result)138 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
139 {
140     ani_env *env;
141     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
142         MMI_HILOGE("%{public}s: Unsupported ANI_VERSION_1", __func__);
143         return ANI_ERROR;
144     }
145 
146     static const char *name = "L@ohos/multimodalInput/pointer/pointer;";
147     ani_namespace ns;
148     if (ANI_OK != env->FindNamespace(name, &ns)) {
149         MMI_HILOGE("%{public}s: Not found %{public}s", __func__, name);
150         return ANI_NOT_FOUND;
151     }
152 
153     std::array methods = {
154         ani_native_function {"setPointerStyleInner", nullptr, reinterpret_cast<void *>(SetPointerStyleInner)},
155     };
156 
157     if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
158         MMI_HILOGE("%{public}s:Cannot bind native methods to '%{public}s'", __func__, name);
159         return ANI_ERROR;
160     };
161 
162     *result = ANI_VERSION_1;
163     return ANI_OK;
164 }