• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "js_keyboard_delegate_setting.h"
17 
18 #include "input_method_ability.h"
19 #include "js_keyboard_controller_engine.h"
20 #include "js_text_input_client_engine.h"
21 #include "js_utils.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 
25 namespace OHOS {
26 namespace MiscServices {
27 constexpr size_t ARGC_ZERO = 0;
28 constexpr size_t ARGC_ONE = 1;
29 constexpr size_t ARGC_TWO = 2;
30 constexpr size_t ARGC_THREE = 3;
31 constexpr size_t ARGC_FOUR = 4;
32 constexpr int32_t V9_FLAG = 1;
33 constexpr int32_t ORIGINAL_FLAG = 2;
34 const std::string JsKeyboardDelegateSetting::KDS_CLASS_NAME = "KeyboardDelegate";
35 thread_local napi_ref JsKeyboardDelegateSetting::KDSRef_ = nullptr;
36 
37 std::mutex JsKeyboardDelegateSetting::keyboardMutex_;
38 std::shared_ptr<JsKeyboardDelegateSetting> JsKeyboardDelegateSetting::keyboardDelegate_ { nullptr };
39 
Init(napi_env env,napi_value exports)40 napi_value JsKeyboardDelegateSetting::Init(napi_env env, napi_value exports)
41 {
42     napi_property_descriptor descriptor[] = {
43         DECLARE_NAPI_PROPERTY("OPTION_ASCII", GetJsConstProperty(env, static_cast<uint32_t>(20))),
44         DECLARE_NAPI_PROPERTY("OPTION_NONE", GetJsConstProperty(env, static_cast<uint32_t>(0))),
45         DECLARE_NAPI_PROPERTY("OPTION_AUTO_CAP_CHARACTERS", GetJsConstProperty(env, static_cast<uint32_t>(2))),
46         DECLARE_NAPI_PROPERTY("OPTION_AUTO_CAP_SENTENCES", GetJsConstProperty(env, static_cast<uint32_t>(8))),
47         DECLARE_NAPI_PROPERTY("OPTION_AUTO_WORDS", GetJsConstProperty(env, static_cast<uint32_t>(4))),
48         DECLARE_NAPI_PROPERTY("OPTION_MULTI_LINE", GetJsConstProperty(env, static_cast<uint32_t>(1))),
49         DECLARE_NAPI_PROPERTY("OPTION_NO_FULLSCREEN", GetJsConstProperty(env, static_cast<uint32_t>(10))),
50         DECLARE_NAPI_PROPERTY("CURSOR_UP", GetJsConstProperty(env, static_cast<uint32_t>(1))),
51         DECLARE_NAPI_PROPERTY("CURSOR_DOWN", GetJsConstProperty(env, static_cast<uint32_t>(2))),
52         DECLARE_NAPI_PROPERTY("CURSOR_LEFT", GetJsConstProperty(env, static_cast<uint32_t>(3))),
53         DECLARE_NAPI_PROPERTY("CURSOR_RIGHT", GetJsConstProperty(env, static_cast<uint32_t>(4))),
54 
55         DECLARE_NAPI_PROPERTY("FLAG_SELECTING", GetJsConstProperty(env, static_cast<uint32_t>(2))),
56         DECLARE_NAPI_PROPERTY("FLAG_SINGLE_LINE", GetJsConstProperty(env, static_cast<uint32_t>(1))),
57 
58         DECLARE_NAPI_PROPERTY("DISPLAY_MODE_PART", GetJsConstProperty(env, static_cast<uint32_t>(0))),
59         DECLARE_NAPI_PROPERTY("DISPLAY_MODE_FULL", GetJsConstProperty(env, static_cast<uint32_t>(1))),
60         DECLARE_NAPI_PROPERTY("WINDOW_TYPE_INPUT_METHOD_FLOAT", GetJsConstProperty(env, static_cast<uint32_t>(2105))),
61 
62         DECLARE_NAPI_FUNCTION("createKeyboardDelegate", CreateKeyboardDelegate),
63         DECLARE_NAPI_FUNCTION("getKeyboardDelegate", GetKeyboardDelegate),
64     };
65     NAPI_CALL(
66         env, napi_define_properties(env, exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor));
67 
68     napi_property_descriptor properties[] = {
69         DECLARE_NAPI_FUNCTION("on", Subscribe),
70         DECLARE_NAPI_FUNCTION("off", UnSubscribe),
71     };
72     napi_value cons = nullptr;
73     NAPI_CALL(env, napi_define_class(env, KDS_CLASS_NAME.c_str(), KDS_CLASS_NAME.size(), JsConstructor, nullptr,
74                        sizeof(properties) / sizeof(napi_property_descriptor), properties, &cons));
75     NAPI_CALL(env, napi_create_reference(env, cons, 1, &KDSRef_));
76     NAPI_CALL(env, napi_set_named_property(env, exports, KDS_CLASS_NAME.c_str(), cons));
77     return exports;
78 };
79 
GetJsConstProperty(napi_env env,uint32_t num)80 napi_value JsKeyboardDelegateSetting::GetJsConstProperty(napi_env env, uint32_t num)
81 {
82     napi_value jsNumber = nullptr;
83     napi_create_int32(env, num, &jsNumber);
84     return jsNumber;
85 };
86 
GetKeyboardDelegateSetting()87 std::shared_ptr<JsKeyboardDelegateSetting> JsKeyboardDelegateSetting::GetKeyboardDelegateSetting()
88 {
89     if (keyboardDelegate_ == nullptr) {
90         std::lock_guard<std::mutex> lock(keyboardMutex_);
91         if (keyboardDelegate_ == nullptr) {
92             auto delegate = std::make_shared<JsKeyboardDelegateSetting>();
93             if (delegate == nullptr) {
94                 IMSA_HILOGE("keyboard delegate nullptr");
95                 return nullptr;
96             }
97             keyboardDelegate_ = delegate;
98             InputMethodAbility::GetInstance()->setKdListener(keyboardDelegate_);
99         }
100     }
101     return keyboardDelegate_;
102 }
103 
JsConstructor(napi_env env,napi_callback_info info)104 napi_value JsKeyboardDelegateSetting::JsConstructor(napi_env env, napi_callback_info info)
105 {
106     IMSA_HILOGI("run in JsConstructor");
107     napi_value thisVar = nullptr;
108     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
109     auto delegate = GetKeyboardDelegateSetting();
110     if (delegate == nullptr) {
111         IMSA_HILOGE("get delegate nullptr");
112         napi_value result = nullptr;
113         napi_get_null(env, &result);
114         return result;
115     }
116     napi_status status = napi_wrap(
117         env, thisVar, delegate.get(), [](napi_env env, void *nativeObject, void *hint) {}, nullptr, nullptr);
118     if (status != napi_ok) {
119         IMSA_HILOGE("JsKeyboardDelegateSetting napi_wrap failed: %{public}d", status);
120         return nullptr;
121     }
122     if (delegate->loop_ == nullptr) {
123         napi_get_uv_event_loop(env, &delegate->loop_);
124     }
125     return thisVar;
126 };
127 
CreateKeyboardDelegate(napi_env env,napi_callback_info info)128 napi_value JsKeyboardDelegateSetting::CreateKeyboardDelegate(napi_env env, napi_callback_info info)
129 {
130     return GetKDInstance(env, info, ORIGINAL_FLAG);
131 }
132 
GetKeyboardDelegate(napi_env env,napi_callback_info info)133 napi_value JsKeyboardDelegateSetting::GetKeyboardDelegate(napi_env env, napi_callback_info info)
134 {
135     return GetKDInstance(env, info, V9_FLAG);
136 }
137 
GetKDInstance(napi_env env,napi_callback_info info,int flag)138 napi_value JsKeyboardDelegateSetting::GetKDInstance(napi_env env, napi_callback_info info, int flag)
139 {
140     napi_value instance = nullptr;
141     napi_value cons = nullptr;
142     if (flag == V9_FLAG) {
143         size_t argc = AsyncCall::ARGC_MAX;
144         napi_value argv[AsyncCall::ARGC_MAX] = { nullptr };
145 
146         NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
147         if (argc != ARGC_ZERO) {
148             JsUtils::ThrowException(
149                 env, IMFErrorCode::EXCEPTION_PARAMCHECK, "Wrong number of arguments, requires 0", TypeCode::TYPE_NONE);
150         }
151     }
152 
153     if (napi_get_reference_value(env, KDSRef_, &cons) != napi_ok) {
154         IMSA_HILOGE("napi_get_reference_value(env, KDSRef_, &cons) != napi_ok");
155         return nullptr;
156     }
157     IMSA_HILOGE("Get a reference to the global variable appAccountRef_ complete");
158     if (napi_new_instance(env, cons, 0, nullptr, &instance) != napi_ok) {
159         IMSA_HILOGE("napi_new_instance(env, cons, 0, nullptr, &instance) != napi_ok");
160         return nullptr;
161     }
162     return instance;
163 }
164 
GetStringProperty(napi_env env,napi_value jsString)165 std::string JsKeyboardDelegateSetting::GetStringProperty(napi_env env, napi_value jsString)
166 {
167     char propValue[MAX_VALUE_LEN] = { 0 };
168     size_t propLen;
169     if (napi_get_value_string_utf8(env, jsString, propValue, MAX_VALUE_LEN, &propLen) != napi_ok) {
170         IMSA_HILOGE("GetStringProperty error");
171     }
172     return std::string(propValue);
173 }
174 
RegisterListener(napi_value callback,std::string type,std::shared_ptr<JSCallbackObject> callbackObj)175 void JsKeyboardDelegateSetting::RegisterListener(
176     napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj)
177 {
178     IMSA_HILOGI("RegisterListener %{public}s", type.c_str());
179     std::lock_guard<std::recursive_mutex> lock(mutex_);
180     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
181         IMSA_HILOGE("methodName %{public}s not registered!", type.c_str());
182     }
183     auto callbacks = jsCbMap_[type];
184     bool ret = std::any_of(callbacks.begin(), callbacks.end(), [&callback](std::shared_ptr<JSCallbackObject> cb) {
185         return Equals(cb->env_, callback, cb->callback_, cb->threadId_);
186     });
187     if (ret) {
188         IMSA_HILOGE("JsKeyboardDelegateSetting::RegisterListener callback already registered!");
189         return;
190     }
191 
192     IMSA_HILOGI("Add %{public}s callbackObj into jsCbMap_", type.c_str());
193     jsCbMap_[type].push_back(std::move(callbackObj));
194 }
195 
UnRegisterListener(napi_value callback,std::string type)196 void JsKeyboardDelegateSetting::UnRegisterListener(napi_value callback, std::string type)
197 {
198     IMSA_HILOGI("UnRegisterListener %{public}s", type.c_str());
199     std::lock_guard<std::recursive_mutex> lock(mutex_);
200     if (jsCbMap_.empty() || jsCbMap_.find(type) == jsCbMap_.end()) {
201         IMSA_HILOGE("methodName %{public}s not unRegisterted!", type.c_str());
202         return;
203     }
204 
205     if (callback == nullptr) {
206         jsCbMap_.erase(type);
207         IMSA_HILOGE("callback is nullptr");
208         return;
209     }
210 
211     for (auto item = jsCbMap_[type].begin(); item != jsCbMap_[type].end(); item++) {
212         if ((callback != nullptr) && (Equals((*item)->env_, callback, (*item)->callback_, (*item)->threadId_))) {
213             jsCbMap_[type].erase(item);
214             break;
215         }
216     }
217     if (jsCbMap_[type].empty()) {
218         jsCbMap_.erase(type);
219     }
220 }
221 
GetNative(napi_env env,napi_callback_info info)222 JsKeyboardDelegateSetting *JsKeyboardDelegateSetting::GetNative(napi_env env, napi_callback_info info)
223 {
224     size_t argc = AsyncCall::ARGC_MAX;
225     void *native = nullptr;
226     napi_value self = nullptr;
227     napi_value argv[AsyncCall::ARGC_MAX] = { nullptr };
228     napi_status status = napi_invalid_arg;
229     status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr);
230     if (self == nullptr && argc >= AsyncCall::ARGC_MAX) {
231         IMSA_HILOGE("napi_get_cb_info failed");
232         return nullptr;
233     }
234 
235     status = napi_unwrap(env, self, &native);
236     NAPI_ASSERT(env, (status == napi_ok && native != nullptr), "napi_unwrap failed!");
237     return reinterpret_cast<JsKeyboardDelegateSetting *>(native);
238 }
239 
Subscribe(napi_env env,napi_callback_info info)240 napi_value JsKeyboardDelegateSetting::Subscribe(napi_env env, napi_callback_info info)
241 {
242     size_t argc = ARGC_TWO;
243     napi_value argv[ARGC_TWO] = { nullptr };
244     napi_value thisVar = nullptr;
245     void *data = nullptr;
246     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
247     if (argc != ARGC_TWO) {
248         JsUtils::ThrowException(
249             env, IMFErrorCode::EXCEPTION_PARAMCHECK, "Wrong number of arguments, requires 2", TypeCode::TYPE_NONE);
250     }
251 
252     napi_valuetype valuetype;
253     NAPI_CALL(env, napi_typeof(env, argv[ARGC_ZERO], &valuetype));
254     if (valuetype != napi_string) {
255         JsUtils::ThrowException(env, IMFErrorCode::EXCEPTION_PARAMCHECK, "'type'", TypeCode::TYPE_STRING);
256         return nullptr;
257     }
258     std::string type = GetStringProperty(env, argv[ARGC_ZERO]);
259     IMSA_HILOGE("event type is: %{public}s", type.c_str());
260 
261     valuetype = napi_undefined;
262     napi_typeof(env, argv[ARGC_ONE], &valuetype);
263     if (valuetype != napi_function) {
264         JsUtils::ThrowException(env, IMFErrorCode::EXCEPTION_PARAMCHECK, "'callback'", TypeCode::TYPE_FUNCTION);
265         return nullptr;
266     }
267 
268     auto engine = GetNative(env, info);
269     if (engine == nullptr) {
270         return nullptr;
271     }
272     std::shared_ptr<JSCallbackObject> callback =
273         std::make_shared<JSCallbackObject>(env, argv[1], std::this_thread::get_id());
274     engine->RegisterListener(argv[ARGC_ONE], type, callback);
275 
276     napi_value result = nullptr;
277     napi_get_null(env, &result);
278     return result;
279 }
280 
UnSubscribe(napi_env env,napi_callback_info info)281 napi_value JsKeyboardDelegateSetting::UnSubscribe(napi_env env, napi_callback_info info)
282 {
283     size_t argc = ARGC_TWO;
284     napi_value argv[ARGC_TWO] = { nullptr };
285     napi_value thisVar = nullptr;
286     void *data = nullptr;
287     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
288     if (argc != ARGC_ONE && argc != ARGC_TWO) {
289         JsUtils::ThrowException(env, IMFErrorCode::EXCEPTION_PARAMCHECK, "Wrong number of arguments, requires 1 or 2",
290             TypeCode::TYPE_NONE);
291         return nullptr;
292     }
293 
294     napi_valuetype valuetype;
295     NAPI_CALL(env, napi_typeof(env, argv[ARGC_ZERO], &valuetype));
296     if (valuetype != napi_string) {
297         JsUtils::ThrowException(env, IMFErrorCode::EXCEPTION_PARAMCHECK, "'type'", TypeCode::TYPE_STRING);
298         return nullptr;
299     }
300     std::string type = GetStringProperty(env, argv[ARGC_ZERO]);
301 
302     auto delegate = GetNative(env, info);
303     if (delegate == nullptr) {
304         return nullptr;
305     }
306 
307     if (argc == ARGC_TWO) {
308         valuetype = napi_undefined;
309         napi_typeof(env, argv[ARGC_ONE], &valuetype);
310         if (valuetype != napi_function) {
311             JsUtils::ThrowException(env, IMFErrorCode::EXCEPTION_PARAMCHECK, "'callback'", TypeCode::TYPE_FUNCTION);
312             return nullptr;
313         }
314     }
315     delegate->UnRegisterListener(argv[ARGC_ONE], type);
316     napi_value result = nullptr;
317     napi_get_null(env, &result);
318     return result;
319 }
320 
Equals(napi_env env,napi_value value,napi_ref copy,std::thread::id threadId)321 bool JsKeyboardDelegateSetting::Equals(napi_env env, napi_value value, napi_ref copy, std::thread::id threadId)
322 {
323     if (copy == nullptr) {
324         return (value == nullptr);
325     }
326 
327     if (threadId != std::this_thread::get_id()) {
328         IMSA_HILOGD("napi_value can not be compared");
329         return false;
330     }
331 
332     napi_value copyValue = nullptr;
333     napi_get_reference_value(env, copy, &copyValue);
334 
335     bool isEquals = false;
336     napi_strict_equals(env, value, copyValue, &isEquals);
337     IMSA_HILOGD("value compare result: %{public}d", isEquals);
338     return isEquals;
339 }
340 
GetResultOnKeyEvent(napi_env env,int32_t keyCode,int32_t keyStatus)341 napi_value JsKeyboardDelegateSetting::GetResultOnKeyEvent(napi_env env, int32_t keyCode, int32_t keyStatus)
342 {
343     napi_value KeyboardDelegate = nullptr;
344     napi_create_object(env, &KeyboardDelegate);
345 
346     napi_value jsKeyCode = nullptr;
347     napi_create_int32(env, keyCode, &jsKeyCode);
348     napi_set_named_property(env, KeyboardDelegate, "keyCode", jsKeyCode);
349 
350     napi_value jsKeyAction = nullptr;
351     napi_create_int32(env, keyStatus, &jsKeyAction);
352     napi_set_named_property(env, KeyboardDelegate, "keyAction", jsKeyAction);
353 
354     return KeyboardDelegate;
355 }
356 
OnKeyEvent(int32_t keyCode,int32_t keyStatus)357 bool JsKeyboardDelegateSetting::OnKeyEvent(int32_t keyCode, int32_t keyStatus)
358 {
359     IMSA_HILOGD("run in");
360     KeyEventPara para{ keyCode, keyStatus, false };
361     std::string type = (keyStatus == ARGC_TWO ? "keyDown" : "keyUp");
362     auto isDone = std::make_shared<BlockData<bool>>(MAX_TIMEOUT, false);
363     uv_work_t *work = GetUVwork(type, [&para, isDone](UvEntry &entry) {
364         entry.keyEventPara = { para.keyCode, para.keyStatus, para.isOnKeyEvent };
365         entry.isDone = isDone;
366     });
367     if (work == nullptr) {
368         IMSA_HILOGE("failed to get uv work");
369         return false;
370     }
371     uv_queue_work(
372         loop_, work, [](uv_work_t *work) {},
373         [](uv_work_t *work, int status) {
374             std::shared_ptr<UvEntry> entry(static_cast<UvEntry *>(work->data), [work](UvEntry *data) {
375                 delete data;
376                 delete work;
377             });
378             auto getKeyEventProperty = [entry](napi_value *args, uint8_t argc,
379                                            std::shared_ptr<JSCallbackObject> item) -> bool {
380                 if (argc == 0) {
381                     return false;
382                 }
383                 napi_value jsObject =
384                     GetResultOnKeyEvent(item->env_, entry->keyEventPara.keyCode, entry->keyEventPara.keyStatus);
385                 if (jsObject == nullptr) {
386                     IMSA_HILOGE("get GetResultOnKeyEvent failed: jsObject is nullptr");
387                     return false;
388                 }
389                 args[ARGC_ZERO] = { jsObject };
390                 return true;
391             };
392             bool isOnKeyEvent = JsUtils::TraverseCallback(entry->vecCopy, ARGC_ONE, getKeyEventProperty);
393             entry->isDone->SetValue(isOnKeyEvent);
394         });
395     return isDone->GetValue();
396 }
397 
OnCursorUpdate(int32_t positionX,int32_t positionY,int32_t height)398 void JsKeyboardDelegateSetting::OnCursorUpdate(int32_t positionX, int32_t positionY, int32_t height)
399 {
400     IMSA_HILOGD("run in");
401     CursorPara para{ positionX, positionY, height };
402     std::string type = "cursorContextChange";
403     uv_work_t *work = GetUVwork(type, [&para](UvEntry &entry) {
404         entry.curPara.positionX = para.positionX;
405         entry.curPara.positionY = para.positionY;
406         entry.curPara.height = para.height;
407     });
408     if (work == nullptr) {
409         IMSA_HILOGD("failed to get uv entry");
410         return;
411     }
412     uv_queue_work(
413         loop_, work, [](uv_work_t *work) {},
414         [](uv_work_t *work, int status) {
415             std::shared_ptr<UvEntry> entry(static_cast<UvEntry *>(work->data), [work](UvEntry *data) {
416                 delete data;
417                 delete work;
418             });
419 
420             auto getCursorUpdateProperty = [entry](napi_value *args, uint8_t argc,
421                                                std::shared_ptr<JSCallbackObject> item) -> bool {
422                 if (argc < 3) {
423                     return false;
424                 }
425                 napi_create_int32(item->env_, entry->curPara.positionX, &args[ARGC_ZERO]);
426                 napi_create_int32(item->env_, entry->curPara.positionY, &args[ARGC_ONE]);
427                 napi_create_int32(item->env_, entry->curPara.height, &args[ARGC_TWO]);
428                 return true;
429             };
430             JsUtils::TraverseCallback(entry->vecCopy, ARGC_THREE, getCursorUpdateProperty);
431         });
432 }
433 
OnSelectionChange(int32_t oldBegin,int32_t oldEnd,int32_t newBegin,int32_t newEnd)434 void JsKeyboardDelegateSetting::OnSelectionChange(int32_t oldBegin, int32_t oldEnd, int32_t newBegin, int32_t newEnd)
435 {
436     IMSA_HILOGD("run in");
437     SelectionPara para{ oldBegin, oldEnd, newBegin, newEnd };
438     std::string type = "selectionChange";
439     uv_work_t *work = GetUVwork(type, [&para](UvEntry &entry) {
440         entry.selPara.oldBegin = para.oldBegin;
441         entry.selPara.oldEnd = para.oldEnd;
442         entry.selPara.newBegin = para.newBegin;
443         entry.selPara.newEnd = para.newEnd;
444     });
445     if (work == nullptr) {
446         IMSA_HILOGD("failed to get uv entry");
447         return;
448     }
449     uv_queue_work(
450         loop_, work, [](uv_work_t *work) {},
451         [](uv_work_t *work, int status) {
452             std::shared_ptr<UvEntry> entry(static_cast<UvEntry *>(work->data), [work](UvEntry *data) {
453                 delete data;
454                 delete work;
455             });
456 
457             auto getSelectionChangeProperty = [entry](napi_value *args, uint8_t argc,
458                                                   std::shared_ptr<JSCallbackObject> item) -> bool {
459                 if (argc < 4) {
460                     return false;
461                 }
462                 napi_create_int32(item->env_, entry->selPara.oldBegin, &args[ARGC_ZERO]);
463                 napi_create_int32(item->env_, entry->selPara.oldEnd, &args[ARGC_ONE]);
464                 napi_create_int32(item->env_, entry->selPara.newBegin, &args[ARGC_TWO]);
465                 napi_create_int32(item->env_, entry->selPara.newEnd, &args[ARGC_THREE]);
466                 return true;
467             };
468             JsUtils::TraverseCallback(entry->vecCopy, ARGC_FOUR, getSelectionChangeProperty);
469         });
470 }
471 
OnTextChange(const std::string & text)472 void JsKeyboardDelegateSetting::OnTextChange(const std::string &text)
473 {
474     IMSA_HILOGD("run in");
475     std::string type = "textChange";
476     uv_work_t *work = GetUVwork(type, [&text](UvEntry &entry) { entry.text = text; });
477     if (work == nullptr) {
478         IMSA_HILOGD("failed to get uv entry");
479         return;
480     }
481     uv_queue_work(
482         loop_, work, [](uv_work_t *work) {},
483         [](uv_work_t *work, int status) {
484             std::shared_ptr<UvEntry> entry(static_cast<UvEntry *>(work->data), [work](UvEntry *data) {
485                 delete data;
486                 delete work;
487             });
488 
489             auto getTextChangeProperty = [entry](napi_value *args, uint8_t argc,
490                                              std::shared_ptr<JSCallbackObject> item) -> bool {
491                 if (argc == 0) {
492                     return false;
493                 }
494                 napi_create_string_utf8(item->env_, entry->text.c_str(), NAPI_AUTO_LENGTH, &args[ARGC_ZERO]);
495                 return true;
496             };
497             JsUtils::TraverseCallback(entry->vecCopy, ARGC_ONE, getTextChangeProperty);
498         });
499 }
500 
GetUVwork(const std::string & type,EntrySetter entrySetter)501 uv_work_t *JsKeyboardDelegateSetting::GetUVwork(const std::string &type, EntrySetter entrySetter)
502 {
503     IMSA_HILOGD("run in, type: %{public}s", type.c_str());
504     UvEntry *entry = nullptr;
505     {
506         std::lock_guard<std::recursive_mutex> lock(mutex_);
507 
508         if (jsCbMap_[type].empty()) {
509             IMSA_HILOGE("%{public}s cb-vector is empty", type.c_str());
510             return nullptr;
511         }
512         entry = new (std::nothrow) UvEntry(jsCbMap_[type], type);
513         if (entry == nullptr) {
514             IMSA_HILOGE("entry ptr is nullptr!");
515             return nullptr;
516         }
517         if (entrySetter != nullptr) {
518             entrySetter(*entry);
519         }
520     }
521     uv_work_t *work = new (std::nothrow) uv_work_t;
522     if (work == nullptr) {
523         IMSA_HILOGE("entry ptr is nullptr!");
524         return nullptr;
525     }
526     work->data = entry;
527     return work;
528 }
529 } // namespace MiscServices
530 } // namespace OHOS