1 /* 2 * Copyright (c) 2021-2023 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 #ifndef INTERFACE_KITS_JS_GET_INPUT_METHOD_CONTROLLER_H 16 #define INTERFACE_KITS_JS_GET_INPUT_METHOD_CONTROLLER_H 17 18 #include "async_call.h" 19 #include "controller_listener.h" 20 #include "global.h" 21 #include "js_callback_object.h" 22 #include "js_input_method.h" 23 24 namespace OHOS { 25 namespace MiscServices { 26 struct HandleContext : public AsyncCall::Context { 27 bool isHandle = false; 28 napi_status status = napi_generic_failure; HandleContextHandleContext29 HandleContext() : Context(nullptr, nullptr){}; HandleContextHandleContext30 HandleContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 31 operatorHandleContext32 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 33 { 34 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 35 return Context::operator()(env, argc, argv, self); 36 } operatorHandleContext37 napi_status operator()(napi_env env, napi_value *result) override 38 { 39 if (status != napi_ok) { 40 output_ = nullptr; 41 return status; 42 } 43 return Context::operator()(env, result); 44 } 45 }; 46 47 struct AttachContext : public AsyncCall::Context { 48 sptr<OnTextChangedListener> textListener; 49 InputAttribute attribute; 50 bool showKeyboard = false; 51 TextConfig textConfig; AttachContextAttachContext52 AttachContext() : Context(nullptr, nullptr) {}; AttachContextAttachContext53 AttachContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 54 operatorAttachContext55 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 56 { 57 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 58 return Context::operator()(env, argc, argv, self); 59 } operatorAttachContext60 napi_status operator()(napi_env env, napi_value *result) override 61 { 62 if (status_ != napi_ok) { 63 output_ = nullptr; 64 return status_; 65 } 66 return Context::operator()(env, result); 67 } 68 }; 69 70 struct SetCallingWindowContext : public AsyncCall::Context { 71 int32_t windID = 0; SetCallingWindowContextSetCallingWindowContext72 SetCallingWindowContext() : Context(nullptr, nullptr) {}; SetCallingWindowContextSetCallingWindowContext73 SetCallingWindowContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 74 operatorSetCallingWindowContext75 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 76 { 77 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 78 return Context::operator()(env, argc, argv, self); 79 } operatorSetCallingWindowContext80 napi_status operator()(napi_env env, napi_value *result) override 81 { 82 if (status_ != napi_ok) { 83 output_ = nullptr; 84 return status_; 85 } 86 return Context::operator()(env, result); 87 } 88 }; 89 90 struct UpdateCursorContext : public AsyncCall::Context { 91 CursorInfo cursorInfo; UpdateCursorContextUpdateCursorContext92 UpdateCursorContext() : Context(nullptr, nullptr) {}; UpdateCursorContextUpdateCursorContext93 UpdateCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 94 operatorUpdateCursorContext95 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 96 { 97 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 98 return Context::operator()(env, argc, argv, self); 99 } operatorUpdateCursorContext100 napi_status operator()(napi_env env, napi_value *result) override 101 { 102 if (status_ != napi_ok) { 103 output_ = nullptr; 104 return status_; 105 } 106 return Context::operator()(env, result); 107 } 108 }; 109 110 struct ChangeSelectionContext : public AsyncCall::Context { 111 std::u16string text; 112 int32_t start = 0; 113 int32_t end = 0; ChangeSelectionContextChangeSelectionContext114 ChangeSelectionContext() : Context(nullptr, nullptr) {}; ChangeSelectionContextChangeSelectionContext115 ChangeSelectionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 116 operatorChangeSelectionContext117 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 118 { 119 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 120 return Context::operator()(env, argc, argv, self); 121 } operatorChangeSelectionContext122 napi_status operator()(napi_env env, napi_value *result) override 123 { 124 if (status_ != napi_ok) { 125 output_ = nullptr; 126 return status_; 127 } 128 return Context::operator()(env, result); 129 } 130 }; 131 132 struct UpdateAttributeContext : public AsyncCall::Context { 133 InputAttribute attribute; 134 Configuration configuration; UpdateAttributeContextUpdateAttributeContext135 UpdateAttributeContext() : Context(nullptr, nullptr) {}; UpdateAttributeContextUpdateAttributeContext136 UpdateAttributeContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 137 operatorUpdateAttributeContext138 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 139 { 140 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 141 return Context::operator()(env, argc, argv, self); 142 } operatorUpdateAttributeContext143 napi_status operator()(napi_env env, napi_value *result) override 144 { 145 if (status_ != napi_ok) { 146 output_ = nullptr; 147 return status_; 148 } 149 return Context::operator()(env, result); 150 } 151 }; 152 153 class JsGetInputMethodController : public ControllerListener { 154 public: 155 JsGetInputMethodController() = default; 156 ~JsGetInputMethodController() = default; 157 static napi_value Init(napi_env env, napi_value info); 158 static napi_value GetController(napi_env env, napi_callback_info cbInfo); 159 static napi_value GetInputMethodController(napi_env env, napi_callback_info cbInfo); 160 static std::shared_ptr<JsGetInputMethodController> GetInstance(); 161 static napi_value HandleSoftKeyboard(napi_env env, napi_callback_info info, std::function<int32_t()> callback, 162 bool isOutput, bool needThrowException); 163 static napi_value Attach(napi_env env, napi_callback_info info); 164 static napi_value Detach(napi_env env, napi_callback_info info); 165 static napi_value ShowTextInput(napi_env env, napi_callback_info info); 166 static napi_value HideTextInput(napi_env env, napi_callback_info info); 167 static napi_value SetCallingWindow(napi_env env, napi_callback_info info); 168 static napi_value UpdateCursor(napi_env env, napi_callback_info info); 169 static napi_value ChangeSelection(napi_env env, napi_callback_info info); 170 static napi_value UpdateAttribute(napi_env env, napi_callback_info info); 171 static napi_value HideSoftKeyboard(napi_env env, napi_callback_info info); 172 static napi_value ShowSoftKeyboard(napi_env env, napi_callback_info info); 173 static napi_value StopInputSession(napi_env env, napi_callback_info info); 174 static napi_value StopInput(napi_env env, napi_callback_info info); 175 static napi_value Subscribe(napi_env env, napi_callback_info info); 176 static napi_value UnSubscribe(napi_env env, napi_callback_info info); 177 void OnSelectByRange(int32_t start, int32_t end) override; 178 void OnSelectByMovement(int32_t direction) override; 179 void InsertText(const std::u16string &text); 180 void DeleteRight(int32_t length); 181 void DeleteLeft(int32_t length); 182 void SendKeyboardStatus(const KeyboardStatus &status); 183 void SendFunctionKey(const FunctionKey &functionKey); 184 void MoveCursor(const Direction direction); 185 void HandleExtendAction(int32_t action); 186 std::u16string GetText(const std::string &type, int32_t number); 187 int32_t GetTextIndexAtCursor(); 188 189 private: 190 static napi_value JsConstructor(napi_env env, napi_callback_info cbinfo); 191 static napi_value GetIMController(napi_env env, napi_callback_info cbInfo, bool needThrowException); 192 static napi_value CreateSelectRange(napi_env env, int32_t start, int32_t end); 193 static napi_value CreateSelectMovement(napi_env env, int32_t direction); 194 static napi_value CreateSendFunctionKey(napi_env env, int32_t functionKey); 195 void RegisterListener(napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj); 196 void UnRegisterListener(napi_value callback, std::string type); 197 static bool ParseAttachInput( 198 napi_env env, size_t argc, napi_value *argv, const std::shared_ptr<AttachContext> &ctxt); 199 static bool GetValue(napi_env env, napi_value in, CursorInfo &out); 200 static bool GetValue(napi_env env, napi_value in, InputAttribute &out); 201 static bool GetValue(napi_env env, napi_value in, TextConfig &out); 202 static bool GetValue(napi_env env, napi_value in, SelectionRange &out); 203 static napi_value GetJsKeyboardStatusProperty(napi_env env); 204 static napi_value GetJsEnterKeyTypeProperty(napi_env env); 205 static napi_value GetJsTextInputTypeProperty(napi_env env); 206 static napi_value GetJsDirectionProperty(napi_env env); 207 static napi_value GetJsExtendActionProperty(napi_env env); 208 static const std::set<std::string> TEXT_EVENT_TYPE; 209 static constexpr int32_t MAX_TIMEOUT = 2500; 210 struct UvEntry { 211 std::vector<std::shared_ptr<JSCallbackObject>> vecCopy; 212 std::string type; 213 std::string text; 214 int32_t start = 0; 215 int32_t end = 0; 216 int32_t direction = 0; 217 int32_t length = 0; 218 int32_t action = 0; 219 int32_t keyboardStatus = 0; 220 int32_t enterKeyType = 0; 221 int32_t number = 0; 222 std::shared_ptr<BlockData<std::string>> textResultHandler; 223 std::shared_ptr<BlockData<std::int32_t>> indexResultHandler; UvEntryUvEntry224 explicit UvEntry(const std::vector<std::shared_ptr<JSCallbackObject>> &cbVec, const std::string &type) 225 : vecCopy(cbVec), type(type) 226 { 227 } 228 }; 229 using EntrySetter = std::function<void(UvEntry &)>; 230 uv_work_t *GetUVwork(const std::string &type, EntrySetter entrySetter = nullptr); 231 void FreeWorkIfFail(int ret, uv_work_t *work); 232 uv_loop_s *loop_ = nullptr; 233 std::recursive_mutex mutex_; 234 std::map<std::string, std::vector<std::shared_ptr<JSCallbackObject>>> jsCbMap_; 235 static std::mutex controllerMutex_; 236 static std::shared_ptr<JsGetInputMethodController> controller_; 237 static const std::string IMC_CLASS_NAME; 238 static thread_local napi_ref IMCRef_; 239 static constexpr size_t PARAM_POS_ZERO = 0; 240 static constexpr size_t PARAM_POS_ONE = 1; 241 static constexpr size_t PARAM_POS_TWO = 2; 242 static constexpr size_t PARAM_POS_THREE = 3; 243 }; 244 } // namespace MiscServices 245 } // namespace OHOS 246 #endif // INTERFACE_KITS_JS_GET_INPUT_METHOD_CONTROLLER_H 247