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
JSActivate(napi_env env, napi_callback_info info)84 static napi_value JSActivate(napi_env env, napi_callback_info info)
85 {
86 size_t argc = ARGC_ACTIVATE_PARAMTER;
87 napi_value argv[ARGC_ACTIVATE_PARAMTER] = { nullptr };
88 napi_value thisVar = nullptr;
89 void* data = nullptr;
90 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
91 NAPI_ASSERT(env, argc >= 1, "requires at least 1 parameter");
92 napi_valuetype type = napi_undefined;
93 napi_typeof(env, argv[0], &type);
94 NAPI_ASSERT(env, type == napi_boolean, "the type of argv[0] is not bool");
95 bool isActive = false;
96 napi_get_value_bool(env, argv[0], &isActive);
97
98 bool autoInactive = true;
99 if (argc == ARGC_ACTIVATE_PARAMTER) {
100 napi_typeof(env, argv[1], &type);
101 NAPI_ASSERT(env, type == napi_boolean, "the type of argv[1] is not bool");
102 napi_get_value_bool(env, argv[1], &autoInactive);
103 }
104
105 napi_value obj = nullptr;
106 auto delegate = EngineHelper::GetCurrentDelegateSafely();
107 if (!delegate) {
108 napi_get_boolean(env, false, &obj);
109 return obj;
110 }
111 delegate->Activate(isActive, autoInactive);
112 napi_get_null(env, &obj);
113 return obj;
114 }
115
registerFunc(napi_env env, napi_value exports)116 static napi_value registerFunc(napi_env env, napi_value exports)
117 {
118 napi_property_descriptor animatorDesc[] = {
119 DECLARE_NAPI_FUNCTION("clearFocus", JSClearFocus),
120 DECLARE_NAPI_FUNCTION("requestFocus", JSRequestFocus),
121 DECLARE_NAPI_FUNCTION("activate", JSActivate),
122 };
123 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(animatorDesc) / sizeof(animatorDesc[0]), animatorDesc));
124 return exports;
125 }
126
127 static napi_module focusControllerModule = {
128 .nm_version = 1,
129 .nm_flags = 0,
130 .nm_filename = nullptr,
131 .nm_register_func = registerFunc,
132 .nm_modname = "arkui.focusController",
133 .nm_priv = ((void*)0),
134 .reserved = { 0 },
135 };
136
FocusControllerRegister()137 extern "C" __attribute__((constructor)) void FocusControllerRegister()
138 {
139 napi_module_register(&focusControllerModule);
140 }
141 } // namespace OHOS::Ace::Napi