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 "event_handler.h" 21 #include "global.h" 22 #include "js_callback_object.h" 23 #include "js_input_method.h" 24 #include "js_message_handler_info.h" 25 #include "msg_handler_callback_interface.h" 26 27 namespace OHOS { 28 namespace MiscServices { 29 struct HandleContext : public AsyncCall::Context { 30 bool isHandle = false; 31 napi_status status = napi_generic_failure; HandleContextHandleContext32 HandleContext() : Context(nullptr, nullptr){}; HandleContextHandleContext33 HandleContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 34 operatorHandleContext35 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 36 { 37 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 38 return Context::operator()(env, argc, argv, self); 39 } operatorHandleContext40 napi_status operator()(napi_env env, napi_value *result) override 41 { 42 if (status != napi_ok) { 43 output_ = nullptr; 44 return status; 45 } 46 return Context::operator()(env, result); 47 } 48 }; 49 50 struct AttachContext : public AsyncCall::Context { 51 sptr<OnTextChangedListener> textListener; 52 InputAttribute attribute; 53 bool showKeyboard = false; 54 int32_t requestKeyboardReason = 0; 55 TextConfig textConfig; AttachContextAttachContext56 AttachContext() : Context(nullptr, nullptr) {}; AttachContextAttachContext57 AttachContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 58 operatorAttachContext59 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 60 { 61 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 62 return Context::operator()(env, argc, argv, self); 63 } operatorAttachContext64 napi_status operator()(napi_env env, napi_value *result) override 65 { 66 if (status_ != napi_ok) { 67 output_ = nullptr; 68 return status_; 69 } 70 return Context::operator()(env, result); 71 } 72 }; 73 74 struct SetCallingWindowContext : public AsyncCall::Context { 75 int32_t windID = 0; SetCallingWindowContextSetCallingWindowContext76 SetCallingWindowContext() : Context(nullptr, nullptr) {}; SetCallingWindowContextSetCallingWindowContext77 SetCallingWindowContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 78 operatorSetCallingWindowContext79 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 80 { 81 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 82 return Context::operator()(env, argc, argv, self); 83 } operatorSetCallingWindowContext84 napi_status operator()(napi_env env, napi_value *result) override 85 { 86 if (status_ != napi_ok) { 87 output_ = nullptr; 88 return status_; 89 } 90 return Context::operator()(env, result); 91 } 92 }; 93 94 struct UpdateCursorContext : public AsyncCall::Context { 95 CursorInfo cursorInfo; UpdateCursorContextUpdateCursorContext96 UpdateCursorContext() : Context(nullptr, nullptr) {}; UpdateCursorContextUpdateCursorContext97 UpdateCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 98 operatorUpdateCursorContext99 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 100 { 101 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 102 return Context::operator()(env, argc, argv, self); 103 } operatorUpdateCursorContext104 napi_status operator()(napi_env env, napi_value *result) override 105 { 106 if (status_ != napi_ok) { 107 output_ = nullptr; 108 return status_; 109 } 110 return Context::operator()(env, result); 111 } 112 }; 113 114 struct ChangeSelectionContext : public AsyncCall::Context { 115 std::u16string text; 116 int32_t start = 0; 117 int32_t end = 0; ChangeSelectionContextChangeSelectionContext118 ChangeSelectionContext() : Context(nullptr, nullptr) {}; ChangeSelectionContextChangeSelectionContext119 ChangeSelectionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 120 operatorChangeSelectionContext121 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 122 { 123 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 124 return Context::operator()(env, argc, argv, self); 125 } operatorChangeSelectionContext126 napi_status operator()(napi_env env, napi_value *result) override 127 { 128 if (status_ != napi_ok) { 129 output_ = nullptr; 130 return status_; 131 } 132 return Context::operator()(env, result); 133 } 134 }; 135 136 struct UpdateAttributeContext : public AsyncCall::Context { 137 InputAttribute attribute; 138 Configuration configuration; UpdateAttributeContextUpdateAttributeContext139 UpdateAttributeContext() : Context(nullptr, nullptr) {}; UpdateAttributeContextUpdateAttributeContext140 UpdateAttributeContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 141 operatorUpdateAttributeContext142 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 143 { 144 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 145 return Context::operator()(env, argc, argv, self); 146 } operatorUpdateAttributeContext147 napi_status operator()(napi_env env, napi_value *result) override 148 { 149 if (status_ != napi_ok) { 150 output_ = nullptr; 151 return status_; 152 } 153 return Context::operator()(env, result); 154 } 155 }; 156 157 class JsGetInputMethodController : public ControllerListener { 158 public: 159 JsGetInputMethodController() = default; 160 ~JsGetInputMethodController() = default; 161 static napi_value Init(napi_env env, napi_value info); 162 static napi_value GetController(napi_env env, napi_callback_info cbInfo); 163 static napi_value GetInputMethodController(napi_env env, napi_callback_info cbInfo); 164 static std::shared_ptr<JsGetInputMethodController> GetInstance(); 165 static napi_value HandleSoftKeyboard(napi_env env, napi_callback_info info, std::function<int32_t()> callback, 166 bool isOutput, bool needThrowException); 167 static napi_value Attach(napi_env env, napi_callback_info info); 168 static napi_value Detach(napi_env env, napi_callback_info info); 169 static napi_value ShowTextInput(napi_env env, napi_callback_info info); 170 static napi_value HideTextInput(napi_env env, napi_callback_info info); 171 static napi_value SetCallingWindow(napi_env env, napi_callback_info info); 172 static napi_value UpdateCursor(napi_env env, napi_callback_info info); 173 static napi_value ChangeSelection(napi_env env, napi_callback_info info); 174 static napi_value UpdateAttribute(napi_env env, napi_callback_info info); 175 static napi_value HideSoftKeyboard(napi_env env, napi_callback_info info); 176 static napi_value ShowSoftKeyboard(napi_env env, napi_callback_info info); 177 static napi_value StopInputSession(napi_env env, napi_callback_info info); 178 static napi_value StopInput(napi_env env, napi_callback_info info); 179 static napi_value Subscribe(napi_env env, napi_callback_info info); 180 static napi_value UnSubscribe(napi_env env, napi_callback_info info); 181 static napi_value SendMessage(napi_env env, napi_callback_info info); 182 static napi_value RecvMessage(napi_env env, napi_callback_info info); 183 void OnSelectByRange(int32_t start, int32_t end) override; 184 void OnSelectByMovement(int32_t direction) override; 185 void InsertText(const std::u16string &text); 186 void DeleteRight(int32_t length); 187 void DeleteLeft(int32_t length); 188 void SendKeyboardStatus(const KeyboardStatus &status); 189 void SendFunctionKey(const FunctionKey &functionKey); 190 void MoveCursor(const Direction direction); 191 void HandleExtendAction(int32_t action); 192 std::u16string GetText(const std::string &type, int32_t number); 193 int32_t GetTextIndexAtCursor(); 194 195 class JsMessageHandler : public MsgHandlerCallbackInterface { 196 public: JsMessageHandler(napi_env env,napi_value onTerminated,napi_value onMessage)197 explicit JsMessageHandler(napi_env env, napi_value onTerminated, napi_value onMessage) 198 : jsMessageHandler_(std::make_shared<JSMsgHandlerCallbackObject>(env, onTerminated, onMessage)) {}; ~JsMessageHandler()199 virtual ~JsMessageHandler() {}; 200 int32_t OnTerminated() override; 201 int32_t OnMessage(const ArrayBuffer &arrayBuffer) override; 202 private: 203 std::mutex callbackObjectMutex_; 204 std::shared_ptr<JSMsgHandlerCallbackObject> jsMessageHandler_ = nullptr; 205 }; 206 private: 207 static napi_value JsConstructor(napi_env env, napi_callback_info cbinfo); 208 static napi_value GetIMController(napi_env env, napi_callback_info cbInfo, bool needThrowException); 209 static napi_value CreateSelectRange(napi_env env, int32_t start, int32_t end); 210 static napi_value CreateSelectMovement(napi_env env, int32_t direction); 211 static napi_value CreateSendFunctionKey(napi_env env, int32_t functionKey); 212 void RegisterListener(napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj); 213 void UnRegisterListener(napi_value callback, std::string type); 214 static bool GetValue(napi_env env, napi_value in, CursorInfo &out); 215 static bool GetValue(napi_env env, napi_value in, InputAttribute &out); 216 static bool GetValue(napi_env env, napi_value in, TextConfig &out); 217 static bool GetValue(napi_env env, napi_value in, Range &out); 218 static napi_value GetAttachOptionsValue(napi_env env, napi_callback_info cbinfo, AttachOptions &attachOptions); 219 static napi_value GetJsKeyboardStatusProperty(napi_env env); 220 static napi_value GetJsEnterKeyTypeProperty(napi_env env); 221 static napi_value GetJsTextInputTypeProperty(napi_env env); 222 static napi_value GetJsDirectionProperty(napi_env env); 223 static napi_value GetJsExtendActionProperty(napi_env env); 224 static napi_value GetJsEnabledStateProperty(napi_env env); 225 static napi_value GetJsRequestKeyboardReasonProperty(napi_env env); 226 static std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler(); 227 static const std::set<std::string> TEXT_EVENT_TYPE; 228 static constexpr int32_t MAX_TIMEOUT = 2500; 229 struct UvEntry { 230 std::vector<std::shared_ptr<JSCallbackObject>> vecCopy; 231 std::string type; 232 std::string text; 233 int32_t start = 0; 234 int32_t end = 0; 235 int32_t direction = 0; 236 int32_t length = 0; 237 int32_t action = 0; 238 int32_t keyboardStatus = 0; 239 int32_t enterKeyType = 0; 240 int32_t number = 0; 241 std::shared_ptr<BlockData<std::string>> textResultHandler; 242 std::shared_ptr<BlockData<std::int32_t>> indexResultHandler; UvEntryUvEntry243 explicit UvEntry(const std::vector<std::shared_ptr<JSCallbackObject>> &cbVec, const std::string &type) 244 : vecCopy(cbVec), type(type) 245 { 246 } 247 }; 248 using EntrySetter = std::function<void(UvEntry &)>; 249 std::shared_ptr<UvEntry> GetEntry(const std::string &type, EntrySetter entrySetter = nullptr); 250 uv_loop_s *loop_ = nullptr; 251 std::recursive_mutex mutex_; 252 std::map<std::string, std::vector<std::shared_ptr<JSCallbackObject>>> jsCbMap_; 253 static std::mutex controllerMutex_; 254 static std::shared_ptr<JsGetInputMethodController> controller_; 255 static const std::string IMC_CLASS_NAME; 256 static thread_local napi_ref IMCRef_; 257 static std::mutex eventHandlerMutex_; 258 static std::shared_ptr<AppExecFwk::EventHandler> handler_; 259 static constexpr size_t PARAM_POS_ZERO = 0; 260 static constexpr size_t PARAM_POS_ONE = 1; 261 static constexpr size_t PARAM_POS_TWO = 2; 262 static constexpr size_t PARAM_POS_THREE = 3; 263 static BlockQueue<MessageHandlerInfo> messageHandlerQueue_; 264 }; 265 } // namespace MiscServices 266 } // namespace OHOS 267 #endif // INTERFACE_KITS_JS_GET_INPUT_METHOD_CONTROLLER_H 268