1 /*
2 * Copyright (c) 2024 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
17 #include "interfaces/napi/kits/utils/napi_utils.h"
18
19 #include "frameworks/bridge/common/utils/engine_helper.h"
20
21 namespace OHOS::Ace::Napi {
22 namespace {
23 constexpr size_t STR_BUFFER_SIZE = 1024;
24 constexpr size_t ARGC_ACTIVATE_PARAMTER = 2;
25 }
26
JSClearFocus(napi_env env,napi_callback_info info)27 static napi_value JSClearFocus(napi_env env, napi_callback_info info)
28 {
29 auto delegate = EngineHelper::GetCurrentDelegateSafely();
30 if (!delegate) {
31 return nullptr;
32 }
33 delegate->ResetFocus();
34 return nullptr;
35 }
36
JSRequestFocus(napi_env env,napi_callback_info info)37 static napi_value JSRequestFocus(napi_env env, napi_callback_info info)
38 {
39 size_t argc = 1;
40 napi_value argv = nullptr;
41 napi_value thisVar = nullptr;
42 void* data = nullptr;
43 napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data);
44 NAPI_ASSERT(env, argc == 1, "requires 1 parameter");
45 napi_valuetype type = napi_undefined;
46 napi_typeof(env, argv, &type);
47 NAPI_ASSERT(env, type == napi_string, "the type of arg is not string");
48 char outBuffer[STR_BUFFER_SIZE] = { 0 };
49 size_t outSize = 0;
50 napi_get_value_string_utf8(env, argv, outBuffer, STR_BUFFER_SIZE, &outSize);
51 std::string key = std::string(outBuffer);
52
53 napi_value obj = nullptr;
54 auto delegate = EngineHelper::GetCurrentDelegateSafely();
55 if (!delegate) {
56 napi_get_boolean(env, false, &obj);
57 return obj;
58 }
59 auto focusCallback = [env](NG::RequestFocusResult result) {
60 switch (result) {
61 case NG::RequestFocusResult::NON_FOCUSABLE:
62 NapiThrow(env, "This component is not focusable.", ERROR_CODE_NON_FOCUSABLE);
63 break;
64 case NG::RequestFocusResult::NON_FOCUSABLE_ANCESTOR:
65 NapiThrow(env, "This component has unfocusable ancestor.", ERROR_CODE_NON_FOCUSABLE_ANCESTOR);
66 break;
67 case NG::RequestFocusResult::NON_EXIST:
68 NapiThrow(env,
69 "The component doesn't exist, is currently invisible, or has been disabled.",
70 ERROR_CODE_NON_EXIST);
71 break;
72 default:
73 NapiThrow(env, "An internal error occurred.", ERROR_CODE_INTERNAL_ERROR);
74 break;
75 }
76 };
77 delegate->SetRequestFocusCallback(focusCallback);
78 delegate->RequestFocus(key, true);
79 delegate->ResetRequestFocusCallback();
80 napi_get_null(env, &obj);
81 return obj;
82 }
83
JsSetAutoFocusTransfer(napi_env env,napi_callback_info info)84 static napi_value JsSetAutoFocusTransfer(napi_env env, napi_callback_info info)
85 {
86 auto delegate = EngineHelper::GetCurrentDelegateSafely();
87 if (!delegate) {
88 return nullptr;
89 }
90 napi_value argv[1] = { 0 };
91 napi_valuetype valueType = napi_undefined;
92 if (!GetSingleParam(env, info, argv, valueType) || (valueType != napi_boolean)) {
93 return nullptr;
94 }
95 bool isAutoFocusTransfer = true;
96 napi_get_value_bool(env, argv[0], &isAutoFocusTransfer);
97 delegate->SetAutoFocusTransfer(isAutoFocusTransfer);
98 return nullptr;
99 }
100
JsConfigWindowMask(napi_env env,napi_callback_info info)101 static napi_value JsConfigWindowMask(napi_env env, napi_callback_info info)
102 {
103 auto delegate = EngineHelper::GetCurrentDelegateSafely();
104 if (!delegate) {
105 return nullptr;
106 }
107 napi_value argv[1] = { 0 };
108 napi_valuetype valueType = napi_undefined;
109 if (!GetSingleParam(env, info, argv, valueType) || (valueType != napi_boolean)) {
110 return nullptr;
111 }
112 bool enable = true;
113 napi_get_value_bool(env, argv[0], &enable);
114 delegate->ConfigWindowMask(enable);
115 return nullptr;
116 }
117
JSActivate(napi_env env,napi_callback_info info)118 static napi_value JSActivate(napi_env env, napi_callback_info info)
119 {
120 size_t argc = ARGC_ACTIVATE_PARAMTER;
121 napi_value argv[ARGC_ACTIVATE_PARAMTER] = { nullptr };
122 napi_value thisVar = nullptr;
123 void* data = nullptr;
124 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
125 NAPI_ASSERT(env, argc >= 1, "requires at least 1 parameter");
126 napi_valuetype type = napi_undefined;
127 napi_typeof(env, argv[0], &type);
128 NAPI_ASSERT(env, type == napi_boolean, "the type of argv[0] is not bool");
129 bool isActive = false;
130 napi_get_value_bool(env, argv[0], &isActive);
131
132 bool autoInactive = true;
133 if (argc == ARGC_ACTIVATE_PARAMTER) {
134 napi_typeof(env, argv[1], &type);
135 NAPI_ASSERT(env, type == napi_boolean, "the type of argv[1] is not bool");
136 napi_get_value_bool(env, argv[1], &autoInactive);
137 }
138
139 napi_value obj = nullptr;
140 auto delegate = EngineHelper::GetCurrentDelegateSafely();
141 if (!delegate) {
142 napi_get_boolean(env, false, &obj);
143 return obj;
144 }
145 delegate->Activate(isActive, autoInactive);
146 napi_get_null(env, &obj);
147 return obj;
148 }
149
JsSetKeyProcessingMode(napi_env env,napi_callback_info info)150 static napi_value JsSetKeyProcessingMode(napi_env env, napi_callback_info info)
151 {
152 auto delegate = EngineHelper::GetCurrentDelegateSafely();
153 if (!delegate) {
154 return nullptr;
155 }
156 napi_value argv[1] = { 0 };
157 napi_valuetype valueType = napi_undefined;
158 if (!GetSingleParam(env, info, argv, valueType) || (valueType != napi_number)) {
159 return nullptr;
160 }
161 int32_t keyProcessingMode = 0;
162 napi_get_value_int32(env, argv[0], &keyProcessingMode);
163 delegate->SetKeyProcessingMode(keyProcessingMode);
164 return nullptr;
165 }
166
registerFunc(napi_env env,napi_value exports)167 static napi_value registerFunc(napi_env env, napi_value exports)
168 {
169 napi_property_descriptor animatorDesc[] = {
170 DECLARE_NAPI_FUNCTION("clearFocus", JSClearFocus),
171 DECLARE_NAPI_FUNCTION("requestFocus", JSRequestFocus),
172 DECLARE_NAPI_FUNCTION("activate", JSActivate),
173 DECLARE_NAPI_FUNCTION("setAutoFocusTransfer", JsSetAutoFocusTransfer),
174 DECLARE_NAPI_FUNCTION("configWindowMask", JsConfigWindowMask),
175 DECLARE_NAPI_FUNCTION("setKeyProcessingMode", JsSetKeyProcessingMode),
176 };
177 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(animatorDesc) / sizeof(animatorDesc[0]), animatorDesc));
178 return exports;
179 }
180
181 static napi_module focusControllerModule = {
182 .nm_version = 1,
183 .nm_flags = 0,
184 .nm_filename = nullptr,
185 .nm_register_func = registerFunc,
186 .nm_modname = "arkui.focusController",
187 .nm_priv = ((void*)0),
188 .reserved = { 0 },
189 };
190
FocusControllerRegister()191 extern "C" __attribute__((constructor)) void FocusControllerRegister()
192 {
193 napi_module_register(&focusControllerModule);
194 }
195 } // namespace OHOS::Ace::Napi