1 /*
2 * Copyright (c) 2021-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 #include "js_get_input_method_controller.h"
16
17 #include "input_method_controller.h"
18 #include "napi/native_api.h"
19 #include "napi/native_node_api.h"
20 #include "string_ex.h"
21
22 namespace OHOS {
23 namespace MiscServices {
24 thread_local napi_ref JsGetInputMethodController::IMCRef_ = nullptr;
25 const std::string JsGetInputMethodController::IMC_CLASS_NAME = "InputMethodController";
Init(napi_env env,napi_value info)26 napi_value JsGetInputMethodController::Init(napi_env env, napi_value info)
27 {
28 napi_property_descriptor descriptor[] = {
29 DECLARE_NAPI_FUNCTION("getInputMethodController", GetInputMethodController),
30 DECLARE_NAPI_FUNCTION("getController", GetController),
31 };
32 NAPI_CALL(
33 env, napi_define_properties(env, info, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor));
34
35 napi_property_descriptor properties[] = {
36 DECLARE_NAPI_FUNCTION("stopInput", StopInput),
37 DECLARE_NAPI_FUNCTION("stopInputSession", StopInputSession),
38 DECLARE_NAPI_FUNCTION("hideSoftKeyboard", HideSoftKeyboard),
39 DECLARE_NAPI_FUNCTION("showSoftKeyboard", ShowSoftKeyboard),
40 };
41 napi_value cons = nullptr;
42 NAPI_CALL(env, napi_define_class(env, IMC_CLASS_NAME.c_str(), IMC_CLASS_NAME.size(),
43 JsConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &cons));
44 NAPI_CALL(env, napi_create_reference(env, cons, 1, &IMCRef_));
45 NAPI_CALL(env, napi_set_named_property(env, info, IMC_CLASS_NAME.c_str(), cons));
46
47 return info;
48 }
49
JsConstructor(napi_env env,napi_callback_info cbinfo)50 napi_value JsGetInputMethodController::JsConstructor(napi_env env, napi_callback_info cbinfo)
51 {
52 napi_value thisVar = nullptr;
53 NAPI_CALL(env, napi_get_cb_info(env, cbinfo, nullptr, nullptr, &thisVar, nullptr));
54
55 JsGetInputMethodController *controllerObject = new (std::nothrow) JsGetInputMethodController();
56 if (controllerObject == nullptr) {
57 IMSA_HILOGE("controllerObject is nullptr");
58 napi_value result = nullptr;
59 napi_get_null(env, &result);
60 return result;
61 }
62 auto finalize = [](napi_env env, void *data, void *hint) {
63 IMSA_HILOGE("JsGetInputMethodController finalize");
64 auto *objInfo = reinterpret_cast<JsGetInputMethodController *>(data);
65 if (objInfo != nullptr) {
66 IMSA_HILOGE("objInfo is nullptr");
67 delete objInfo;
68 }
69 };
70 napi_status status = napi_wrap(env, thisVar, controllerObject, finalize, nullptr, nullptr);
71 if (status != napi_ok) {
72 IMSA_HILOGE("JsGetInputMethodController napi_wrap failed:%{public}d", status);
73 delete controllerObject;
74 return nullptr;
75 }
76
77 return thisVar;
78 }
79
GetInputMethodController(napi_env env,napi_callback_info cbInfo)80 napi_value JsGetInputMethodController::GetInputMethodController(napi_env env, napi_callback_info cbInfo)
81 {
82 return GetIMController(env, cbInfo, false);
83 }
84
GetController(napi_env env,napi_callback_info cbInfo)85 napi_value JsGetInputMethodController::GetController(napi_env env, napi_callback_info cbInfo)
86 {
87 return GetIMController(env, cbInfo, true);
88 }
89
GetIMController(napi_env env,napi_callback_info cbInfo,bool needThrowException)90 napi_value JsGetInputMethodController::GetIMController(napi_env env, napi_callback_info cbInfo, bool needThrowException)
91 {
92 napi_value instance = nullptr;
93 napi_value cons = nullptr;
94 if (napi_get_reference_value(env, IMCRef_, &cons) != napi_ok) {
95 IMSA_HILOGE("GetInputMethodSetting::napi_get_reference_value not ok");
96 if (needThrowException) {
97 JsUtils::ThrowException(env, IMFErrorCode::EXCEPTION_CONTROLLER, "", TYPE_OBJECT);
98 }
99 return nullptr;
100 }
101
102 if (napi_new_instance(env, cons, 0, nullptr, &instance) != napi_ok) {
103 IMSA_HILOGE("GetInputMethodSetting::napi_new_instance not ok");
104 if (needThrowException) {
105 JsUtils::ThrowException(env, IMFErrorCode::EXCEPTION_CONTROLLER, "", TYPE_OBJECT);
106 }
107 return nullptr;
108 }
109 return instance;
110 }
111
HandleSoftKeyboard(napi_env env,napi_callback_info info,std::function<int32_t ()> callback,bool isOutput,bool needThrowException)112 napi_value JsGetInputMethodController::HandleSoftKeyboard(
113 napi_env env, napi_callback_info info, std::function<int32_t()> callback, bool isOutput, bool needThrowException)
114 {
115 auto ctxt = std::make_shared<HandleContext>();
116 auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
117 return napi_ok;
118 };
119 auto output = [ctxt, isOutput](napi_env env, napi_value *result) -> napi_status {
120 if (!isOutput) {
121 return napi_ok;
122 }
123 napi_status status = napi_get_boolean(env, ctxt->isHandle, result);
124 IMSA_HILOGE("output napi_get_boolean != nullptr[%{public}d]", result != nullptr);
125 return status;
126 };
127 auto exec = [ctxt, callback, needThrowException](AsyncCall::Context *ctx) {
128 int errCode = callback();
129 if (errCode == ErrorCode::NO_ERROR) {
130 IMSA_HILOGI("exec success");
131 ctxt->status = napi_ok;
132 ctxt->isHandle = true;
133 ctxt->SetState(ctxt->status);
134 return;
135 }
136 IMSA_HILOGI("exec %{public}d", errCode);
137 if (needThrowException) {
138 ctxt->SetErrorCode(errCode);
139 }
140 };
141 ctxt->SetAction(std::move(input), std::move(output));
142 AsyncCall asyncCall(env, info, std::dynamic_pointer_cast<AsyncCall::Context>(ctxt), 0);
143 return asyncCall.Call(env, exec);
144 }
145
ShowSoftKeyboard(napi_env env,napi_callback_info info)146 napi_value JsGetInputMethodController::ShowSoftKeyboard(napi_env env, napi_callback_info info)
147 {
148 return HandleSoftKeyboard(
149 env, info, [] { return InputMethodController::GetInstance()->ShowSoftKeyboard(); }, false, true);
150 }
151
HideSoftKeyboard(napi_env env,napi_callback_info info)152 napi_value JsGetInputMethodController::HideSoftKeyboard(napi_env env, napi_callback_info info)
153 {
154 return HandleSoftKeyboard(
155 env, info, [] { return InputMethodController::GetInstance()->HideSoftKeyboard(); }, false, true);
156 }
157
StopInputSession(napi_env env,napi_callback_info info)158 napi_value JsGetInputMethodController::StopInputSession(napi_env env, napi_callback_info info)
159 {
160 return HandleSoftKeyboard(
161 env, info, [] { return InputMethodController::GetInstance()->StopInputSession(); }, true, true);
162 }
163
StopInput(napi_env env,napi_callback_info info)164 napi_value JsGetInputMethodController::StopInput(napi_env env, napi_callback_info info)
165 {
166 return HandleSoftKeyboard(
167 env, info, [] { return InputMethodController::GetInstance()->HideCurrentInput(); }, true, false);
168 }
169 } // namespace MiscServices
170 } // namespace OHOS