• 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 "js_ui_effect_controller.h"
16 
17 #include "js_runtime_utils.h"
18 #include "js_window_animation_utils.h"
19 #include "js_window.h"
20 #include "js_err_utils.h"
21 #include "ui_effect_controller_common.h"
22 #include "window_adapter.h"
23 #include "window_manager_hilog.h"
24 
25 namespace OHOS::Rosen {
26 constexpr size_t ARGC_ONE = 1;
27 constexpr size_t ARGC_TWO = 2;
28 constexpr size_t ARGC_THREE = 3;
29 constexpr size_t INDEX_ZERO = 0;
30 constexpr size_t INDEX_ONE = 1;
31 constexpr size_t INDEX_TWO = 2;
32 constexpr size_t FOUR_PARAMS_SIZE = 4;
33 using namespace AbilityRuntime;
34 
CreateJsObject(napi_env env,JsUIEffectController * filter,napi_value & obj)35 napi_status JsUIEffectController::CreateJsObject(napi_env env, JsUIEffectController* filter, napi_value& obj)
36 {
37     NAPI_CHECK(napi_create_object(env, &obj), "ui effect obj");
38     napi_status status = napi_wrap(env, obj, filter, JsUIEffectController::Finalizer, nullptr, nullptr);
39     if (status != napi_status::napi_ok) {
40         TLOGE(WmsLogTag::WMS_ANIMATION, "napi func failed, with reason %{public}d", status);
41         delete filter;
42         return status;
43     }
44     BindNativeFunctions(env, obj, "JsUIEffectController");
45     return napi_status::napi_ok;
46 }
47 
Finalizer(napi_env env,void * data,void * hint)48 void JsUIEffectController::Finalizer(napi_env env, void* data, void* hint)
49 {
50     JsUIEffectController* controller = static_cast<JsUIEffectController*>(data);
51     if (controller != nullptr) {
52         delete controller;
53     }
54 }
55 
JsUIEffectController()56 JsUIEffectController::JsUIEffectController(): client_(sptr<UIEffectControllerClient>::MakeSptr())
57 {
58     TLOGI(WmsLogTag::WMS_ANIMATION, "Constructor");
59 };
60 
~JsUIEffectController()61 JsUIEffectController::~JsUIEffectController()
62 {
63     SingletonContainer::Get<WindowAdapter>().UnregisterUIEffectRecoverCallbackFunc(client_->GetId());
64     TLOGI(WmsLogTag::WMS_ANIMATION, "Destrutor, id: %{public}d", client_->GetId());
65 }
66 
Init()67 WMError JsUIEffectController::Init()
68 {
69     WMError err = InitClientAndServer();
70     if (err != WMError::WM_OK) {
71         TLOGI(WmsLogTag::WMS_ANIMATION, "failed to init");
72         return err;
73     }
74     SingletonContainer::Get<WindowAdapter>().RegisterUIEffectRecoverCallbackFunc(client_->GetId(), [this]()-> WMError {
75         return InitClientAndServer();
76     });
77     return WMError::WM_OK;
78 }
79 
InitClientAndServer()80 WMError JsUIEffectController::InitClientAndServer()
81 {
82     int32_t controllerId = UIEFFECT_INVALID_ID;
83     WMError err = SingletonContainer::Get<WindowAdapter>().CreateUIEffectController(client_, server_, controllerId);
84     if (err != WMError::WM_OK) {
85         return err;
86     }
87     client_->SetId(controllerId);
88     return WMError::WM_OK;
89 }
90 
BindNativeFunctions(napi_env env,napi_value object,const char * moduleName)91 void JsUIEffectController::BindNativeFunctions(napi_env env, napi_value object, const char* moduleName)
92 {
93     BindNativeFunction(env, object, "setParams", moduleName, JsUIEffectController::SetParams);
94     BindNativeFunction(env, object, "animateToUIEffect", moduleName, JsUIEffectController::AnimateTo);
95 }
96 
SetParams(napi_env env,napi_callback_info info)97 napi_value JsUIEffectController::SetParams(napi_env env, napi_callback_info info)
98 {
99     TLOGI(WmsLogTag::WMS_ANIMATION, "NapiFunc");
100     JsUIEffectController* me = CheckParamsAndGetThis<JsUIEffectController>(env, info);
101     return (me != nullptr) ? me->OnSetParams(env, info) : nullptr;
102 }
103 
AnimateTo(napi_env env,napi_callback_info info)104 napi_value JsUIEffectController::AnimateTo(napi_env env, napi_callback_info info)
105 {
106     TLOGI(WmsLogTag::WMS_ANIMATION, "NapiFunc");
107     JsUIEffectController* me = CheckParamsAndGetThis<JsUIEffectController>(env, info);
108     return (me != nullptr) ? me->OnAnimateTo(env, info) : nullptr;
109 }
110 
OnSetParams(napi_env env,napi_callback_info info)111 napi_value JsUIEffectController::OnSetParams(napi_env env, napi_callback_info info)
112 {
113     size_t argc = FOUR_PARAMS_SIZE;
114     napi_value argv[FOUR_PARAMS_SIZE] = {nullptr};
115     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
116     if (argc != ARGC_ONE) {
117         TLOGE(WmsLogTag::WMS_ATTRIBUTE, "Argc is invalid: %{public}zu", argc);
118         return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
119     }
120     sptr<UIEffectParams> params = sptr<UIEffectParams>::MakeSptr();
121     if (params->ConvertFromJsValue(env, argv[INDEX_ZERO]) != napi_status::napi_ok) {
122         TLOGE(WmsLogTag::WMS_ATTRIBUTE, "parse ui effect params failed");
123         return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
124     }
125     if (params->IsEmpty()) {
126         TLOGE(WmsLogTag::WMS_ANIMATION, "do not have any parameters");
127         return NapiThrowError(env, WmErrorCode::WM_ERROR_ILLEGAL_PARAM);
128     }
129     std::shared_ptr<WmErrorCode> errCodePtr = std::make_shared<WmErrorCode>(WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY);
130     NapiAsyncTask::ExecuteCallback execute = [params, client = client_, server = server_, errCodePtr] {
131         if (errCodePtr == nullptr || client == nullptr || server == nullptr || params == nullptr) {
132             return;
133         }
134         WMError ret = server->SetParams(params);
135         *errCodePtr = WM_JS_TO_ERROR_CODE_MAP.at(ret);
136         TLOGI(WmsLogTag::WMS_ANIMATION, "ui effect %{public}d set filter params exec end with err code %{public}d",
137             client->GetId(), ret);
138     };
139     NapiAsyncTask::CompleteCallback complete =
140         [errCodePtr](napi_env env, NapiAsyncTask& task, int32_t status) {
141             if (errCodePtr == nullptr) {
142                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
143                     "System abnormal."));
144                 return;
145             }
146             if (*errCodePtr == WmErrorCode::WM_OK) {
147                 task.Resolve(env, NapiGetUndefined(env));
148             } else {
149                 task.Reject(env, JsErrUtils::CreateJsError(env, *errCodePtr));
150             }
151         };
152     napi_value result = nullptr;
153     NapiAsyncTask::Schedule("JsUIEffect::SetParams",
154         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
155     return result;
156 }
157 
OnAnimateTo(napi_env env,napi_callback_info info)158 napi_value JsUIEffectController::OnAnimateTo(napi_env env, napi_callback_info info)
159 {
160     size_t argc = FOUR_PARAMS_SIZE;
161     napi_value argv[FOUR_PARAMS_SIZE] = {nullptr};
162     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
163     if (argc > ARGC_THREE || argc < ARGC_TWO) {
164         TLOGE(WmsLogTag::WMS_ANIMATION, "Argc is invalid: %{public}zu", argc);
165         return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
166     }
167     struct AnimationInfoList {
168         sptr<UIEffectParams> params = sptr<UIEffectParams>::MakeSptr();
169         sptr<WindowAnimationOption> option = sptr<WindowAnimationOption>::MakeSptr();
170         sptr<WindowAnimationOption> interruptOption = nullptr;
171         WmErrorCode errCode = WmErrorCode::WM_OK;
172     };
173     std::shared_ptr<AnimationInfoList> lists = std::make_shared<AnimationInfoList>();
174     WmErrorCode err = WmErrorCode::WM_OK;
175     if (!ConvertWindowAnimationOptionFromJsValue(env, argv[INDEX_ZERO], *lists->option, err)) {
176         TLOGE(WmsLogTag::WMS_ANIMATION, "parse window animation config failed");
177         return NapiThrowError(env, err);
178     }
179     if (!CheckWindowAnimationOption(env, *lists->option, err)) {
180         TLOGE(WmsLogTag::WMS_ANIMATION, "check window animation config failed");
181         return NapiThrowError(env, err);
182     }
183     if (lists->params->ConvertFromJsValue(env, argv[INDEX_ONE]) != napi_status::napi_ok) {
184         TLOGE(WmsLogTag::WMS_ANIMATION, "parse ui effect params failed");
185         return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM);
186     }
187     if (lists->params->IsEmpty()) {
188         TLOGE(WmsLogTag::WMS_ANIMATION, "do not have any parameters");
189         return NapiThrowError(env, WmErrorCode::WM_ERROR_ILLEGAL_PARAM);
190     }
191     if (argc == ARGC_THREE) {
192         lists->interruptOption = sptr<WindowAnimationOption>::MakeSptr();
193         if (!ConvertWindowAnimationOptionFromJsValue(env, argv[INDEX_TWO], *lists->interruptOption, err)) {
194             TLOGE(WmsLogTag::WMS_ANIMATION, "parse window animation config failed");
195             return NapiThrowError(env, err);
196         }
197         if (!CheckWindowAnimationOption(env, *lists->interruptOption, err)) {
198             TLOGE(WmsLogTag::WMS_ANIMATION, "check window animation config failed");
199             return NapiThrowError(env, err);
200         }
201     }
202     NapiAsyncTask::ExecuteCallback execute = [lists, client = client_, server = server_] {
203         if (lists == nullptr) {
204             return;
205         }
206         WMError ret = server->AnimateTo(lists->params, lists->option, lists->interruptOption);
207         lists->errCode = WM_JS_TO_ERROR_CODE_MAP.at(ret);
208         TLOGI(WmsLogTag::WMS_ANIMATION, "ui effect %{public}d animateTo, err code %{public}d",
209             client->GetId(), ret);
210     };
211     NapiAsyncTask::CompleteCallback complete =
212         [lists](napi_env env, NapiAsyncTask& task, int32_t status) {
213             if (lists == nullptr) {
214                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
215                     "System abnormal."));
216                 return;
217             }
218             if (lists->errCode == WmErrorCode::WM_OK) {
219                 task.Resolve(env, NapiGetUndefined(env));
220             } else {
221                 task.Reject(env, JsErrUtils::CreateJsError(env, lists->errCode));
222             }
223         };
224     napi_value result = nullptr;
225     NapiAsyncTask::Schedule("JsUIEffect::SetParams",
226         env, CreateAsyncTaskWithLastParam(env, nullptr, std::move(execute), std::move(complete), &result));
227     return result;
228 }
229 }