• 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 #include <ani.h>
16 #include <array>
17 #include <iostream>
18 
19 #include "base/log/log_wrapper.h"
20 #include "base/memory/referenced.h"
21 #include "core/components_ng/event/focus_hub.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 #include "frameworks/bridge/common/utils/engine_helper.h"
24 #include "frameworks/core/common/container.h"
25 
26 namespace {
ANIUtils_ANIStringToStdString(ani_env * env,ani_string ani_str)27 std::string ANIUtils_ANIStringToStdString(ani_env* env, ani_string ani_str)
28 {
29     ani_size strSize;
30     env->String_GetUTF8Size(ani_str, &strSize);
31 
32     std::vector<char> buffer(strSize + 1); // +1 for null terminator
33     char* utf8Buffer = buffer.data();
34 
35     ani_size bytes_written = 0;
36     env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytes_written);
37 
38     utf8Buffer[bytes_written] = '\0';
39     std::string content = std::string(utf8Buffer);
40     return content;
41 }
42 } // namespace
43 
GetBooleanValue(ani_env * env,ani_object object,bool & value)44 static bool GetBooleanValue(ani_env* env, ani_object object, bool& value)
45 {
46     ani_boolean isUndefined;
47     env->Reference_IsUndefined(object, &isUndefined);
48     if (!isUndefined) {
49         return false;
50     }
51     ani_boolean aniValue;
52     if (ANI_OK != env->Object_CallMethodByName_Boolean(object, "unboxed", nullptr, &aniValue)) {
53         return false;
54     }
55     value = static_cast<bool>(aniValue);
56     return true;
57 }
58 
clearFocus(ani_env * env,ani_object object)59 static void clearFocus(ani_env* env, [[maybe_unused]] ani_object object)
60 {
61     OHOS::Ace::NG::FocusHub::LostFocusToViewRoot();
62 }
63 
requestFocus(ani_env * env,ani_string key)64 static void requestFocus([[maybe_unused]] ani_env* env, ani_string key)
65 {
66     auto keyStr = ANIUtils_ANIStringToStdString(env, key);
67     auto focusCallback = [env](OHOS::Ace::NG::RequestFocusResult result) {
68         switch (result) {
69             case OHOS::Ace::NG::RequestFocusResult::NON_FOCUSABLE:
70                 LOGI("This component is not focusable");
71                 break;
72             case OHOS::Ace::NG::RequestFocusResult::NON_FOCUSABLE_ANCESTOR:
73                 LOGI("This component has unfocusable ancestor.");
74                 break;
75             case OHOS::Ace::NG::RequestFocusResult::NON_EXIST:
76                 LOGI("The component doesn't exist, is currently invisible, or has been disabled.");
77                 break;
78             default:
79                 LOGI("An internal error occurred.");
80                 break;
81         }
82     };
83     LOGI("focuscontroller requestFocus key %{public}s", keyStr.c_str());
84     auto pipeline = OHOS::Ace::NG::PipelineContext::GetCurrentContext();
85     CHECK_NULL_VOID(pipeline);
86     auto focusManager = pipeline->GetOrCreateFocusManager();
87     CHECK_NULL_VOID(focusManager);
88     focusManager->SetRequestFocusCallback(focusCallback);
89     pipeline->RequestFocus(keyStr, true);
90     focusManager->ResetRequestFocusCallback();
91 }
92 
activate(ani_env * env,ani_object isActive,ani_object autoInactive)93 static void activate(ani_env* env, ani_object isActive, ani_object autoInactive)
94 {
95     bool isActiveValue = false;
96     bool autoInactiveValue = true;
97 
98     GetBooleanValue(env, isActive, isActiveValue);
99     GetBooleanValue(env, autoInactive, autoInactiveValue);
100 
101     auto pipeline = OHOS::Ace::NG::PipelineContext::GetCurrentContext();
102     CHECK_NULL_VOID(pipeline);
103     pipeline->SetIsFocusActive(isActiveValue, OHOS::Ace::NG::FocusActiveReason::USE_API, autoInactiveValue);
104 }
105 
setAutoFocusTransfer(ani_env * env,ani_object isAutoFocusTransfer)106 static void setAutoFocusTransfer(ani_env* env, ani_object isAutoFocusTransfer)
107 {
108     bool isAutoFocusTransferValue = true;
109     if (!GetBooleanValue(env, isAutoFocusTransfer, isAutoFocusTransferValue)) {
110         return;
111     }
112     auto pipeline = OHOS::Ace::NG::PipelineContext::GetCurrentContext();
113     CHECK_NULL_VOID(pipeline);
114     auto focusManager = pipeline->GetOrCreateFocusManager();
115     CHECK_NULL_VOID(focusManager);
116     focusManager->SetIsAutoFocusTransfer(isAutoFocusTransferValue);
117 }
118 
setKeyProcessingMode(ani_env * env,ani_enum_item mode)119 static void setKeyProcessingMode(ani_env* env, ani_enum_item mode)
120 {
121     ani_int keyProcessingMode;
122     if (ANI_OK != env->EnumItem_GetValue_Int(mode, &keyProcessingMode)) {
123         LOGE("focuscontroller setKeyProcessingMode get modeType failed");
124         return;
125     }
126     auto pipeline = OHOS::Ace::NG::PipelineContext::GetCurrentContext();
127     CHECK_NULL_VOID(pipeline);
128     auto focusManager = pipeline->GetOrCreateFocusManager();
129     CHECK_NULL_VOID(focusManager);
130     focusManager->SetKeyProcessingMode(static_cast<OHOS::Ace::NG::KeyProcessingMode>(keyProcessingMode));
131 }
132 
ANI_Constructor(ani_vm * vm,uint32_t * result)133 ANI_EXPORT ani_status ANI_Constructor(ani_vm* vm, uint32_t* result)
134 {
135     if (vm == nullptr) {
136         return ANI_ERROR;
137     }
138     ani_env* env;
139     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
140         return ANI_ERROR;
141     }
142 
143     ani_namespace ns;
144     if (ANI_OK != env->FindNamespace("L@ohos/arkui/focusController/focusController;", &ns)) {
145         return ANI_ERROR;
146     }
147     std::array methods = {
148         ani_native_function { "clearFocus", nullptr, reinterpret_cast<void*>(clearFocus) },
149         ani_native_function { "requestFocus", nullptr, reinterpret_cast<void*>(requestFocus) },
150         ani_native_function { "activate", nullptr, reinterpret_cast<void*>(activate) },
151         ani_native_function { "setAutoFocusTransfer", nullptr, reinterpret_cast<void*>(setAutoFocusTransfer) },
152         ani_native_function { "setKeyProcessingMode", nullptr, reinterpret_cast<void*>(setKeyProcessingMode) },
153     };
154     if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
155         return ANI_ERROR;
156     }
157 
158     *result = ANI_VERSION_1;
159     return ANI_OK;
160 }