• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     std::optional<NG::RequestFocusResult> result;
60     auto focusCallback = [&result](NG::RequestFocusResult requestResult) {
61         result = requestResult;
62     }; // After ResetRequestFocusCallback, the reference to 'result' is no longer valid.
63     delegate->SetRequestFocusCallback(focusCallback);
64     delegate->RequestFocus(key, true);
65     delegate->ResetRequestFocusCallback();
66     if (result.has_value()) {
67         switch (result.value()) {
68             case NG::RequestFocusResult::NON_FOCUSABLE:
69                 NapiThrow(env, "This component is not focusable.", ERROR_CODE_NON_FOCUSABLE);
70                 break;
71             case NG::RequestFocusResult::NON_FOCUSABLE_ANCESTOR:
72                 NapiThrow(env, "This component has unfocusable ancestor.", ERROR_CODE_NON_FOCUSABLE_ANCESTOR);
73                 break;
74             case NG::RequestFocusResult::NON_EXIST:
75                 NapiThrow(env, "The component doesn't exist, is currently invisible, or has been disabled.",
76                     ERROR_CODE_NON_EXIST);
77                 break;
78             default:
79                 NapiThrow(env, "An internal error occurred.", ERROR_CODE_INTERNAL_ERROR);
80                 break;
81         }
82     }
83     napi_get_null(env, &obj);
84     return obj;
85 }
86 
JsSetAutoFocusTransfer(napi_env env,napi_callback_info info)87 static napi_value JsSetAutoFocusTransfer(napi_env env, napi_callback_info info)
88 {
89     auto delegate = EngineHelper::GetCurrentDelegateSafely();
90     if (!delegate) {
91         return nullptr;
92     }
93     napi_value argv[1] = { 0 };
94     napi_valuetype valueType = napi_undefined;
95     if (!GetSingleParam(env, info, argv, valueType) || (valueType != napi_boolean)) {
96         return nullptr;
97     }
98     bool isAutoFocusTransfer = true;
99     napi_get_value_bool(env, argv[0], &isAutoFocusTransfer);
100     delegate->SetAutoFocusTransfer(isAutoFocusTransfer);
101     return nullptr;
102 }
103 
JsConfigWindowMask(napi_env env,napi_callback_info info)104 static napi_value JsConfigWindowMask(napi_env env, napi_callback_info info)
105 {
106     auto delegate = EngineHelper::GetCurrentDelegateSafely();
107     if (!delegate) {
108         return nullptr;
109     }
110     napi_value argv[1] = { 0 };
111     napi_valuetype valueType = napi_undefined;
112     if (!GetSingleParam(env, info, argv, valueType) || (valueType != napi_boolean)) {
113         return nullptr;
114     }
115     bool enable = true;
116     napi_get_value_bool(env, argv[0], &enable);
117     delegate->ConfigWindowMask(enable);
118     return nullptr;
119 }
120 
JSActivate(napi_env env,napi_callback_info info)121 static napi_value JSActivate(napi_env env, napi_callback_info info)
122 {
123     size_t argc = ARGC_ACTIVATE_PARAMTER;
124     napi_value argv[ARGC_ACTIVATE_PARAMTER] = { nullptr };
125     napi_value thisVar = nullptr;
126     void* data = nullptr;
127     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
128     NAPI_ASSERT(env, argc >= 1, "requires at least 1 parameter");
129     napi_valuetype type = napi_undefined;
130     napi_typeof(env, argv[0], &type);
131     NAPI_ASSERT(env, type == napi_boolean, "the type of argv[0] is not bool");
132     bool isActive = false;
133     napi_get_value_bool(env, argv[0], &isActive);
134 
135     bool autoInactive = true;
136     if (argc == ARGC_ACTIVATE_PARAMTER) {
137         napi_typeof(env, argv[1], &type);
138         NAPI_ASSERT(env, type == napi_boolean, "the type of argv[1] is not bool");
139         napi_get_value_bool(env, argv[1], &autoInactive);
140     }
141 
142     napi_value obj = nullptr;
143     auto delegate = EngineHelper::GetCurrentDelegateSafely();
144     if (!delegate) {
145         napi_get_boolean(env, false, &obj);
146         return obj;
147     }
148     delegate->Activate(isActive, autoInactive);
149     napi_get_null(env, &obj);
150     return obj;
151 }
152 
JSIsActive(napi_env env,napi_callback_info info)153 static napi_value JSIsActive(napi_env env, napi_callback_info info)
154 {
155     auto delegate = EngineHelper::GetCurrentDelegateSafely();
156     if (!delegate) {
157         return nullptr;
158     }
159 
160     bool isActive = delegate->GetFocusActive();
161     napi_value result = nullptr;
162     napi_get_boolean(env, isActive, &result);
163     return result;
164 }
165 
JsSetKeyProcessingMode(napi_env env,napi_callback_info info)166 static napi_value JsSetKeyProcessingMode(napi_env env, napi_callback_info info)
167 {
168     auto delegate = EngineHelper::GetCurrentDelegateSafely();
169     if (!delegate) {
170         return nullptr;
171     }
172     napi_value argv[1] = { 0 };
173     napi_valuetype valueType = napi_undefined;
174     if (!GetSingleParam(env, info, argv, valueType) || (valueType != napi_number)) {
175         return nullptr;
176     }
177     int32_t keyProcessingMode = 0;
178     napi_get_value_int32(env, argv[0], &keyProcessingMode);
179     delegate->SetKeyProcessingMode(keyProcessingMode);
180     return nullptr;
181 }
182 
registerFunc(napi_env env,napi_value exports)183 static napi_value registerFunc(napi_env env, napi_value exports)
184 {
185     napi_property_descriptor animatorDesc[] = {
186         DECLARE_NAPI_FUNCTION("clearFocus", JSClearFocus),
187         DECLARE_NAPI_FUNCTION("requestFocus", JSRequestFocus),
188         DECLARE_NAPI_FUNCTION("activate", JSActivate),
189         DECLARE_NAPI_FUNCTION("isActive", JSIsActive),
190         DECLARE_NAPI_FUNCTION("setAutoFocusTransfer", JsSetAutoFocusTransfer),
191         DECLARE_NAPI_FUNCTION("configWindowMask", JsConfigWindowMask),
192         DECLARE_NAPI_FUNCTION("setKeyProcessingMode", JsSetKeyProcessingMode),
193     };
194     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(animatorDesc) / sizeof(animatorDesc[0]), animatorDesc));
195     return exports;
196 }
197 
198 static napi_module focusControllerModule = {
199     .nm_version = 1,
200     .nm_flags = 0,
201     .nm_filename = nullptr,
202     .nm_register_func = registerFunc,
203     .nm_modname = "arkui.focusController",
204     .nm_priv = ((void*)0),
205     .reserved = { 0 },
206 };
207 
FocusControllerRegister()208 extern "C" __attribute__((constructor)) void FocusControllerRegister()
209 {
210     napi_module_register(&focusControllerModule);
211 }
212 } // namespace OHOS::Ace::Napi