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 int32_t SetPreviewText(const std::u16string &text, const Range &range); 195 void FinishTextPreview(); 196 197 class JsMessageHandler : public MsgHandlerCallbackInterface { 198 public: JsMessageHandler(napi_env env,napi_value onTerminated,napi_value onMessage)199 explicit JsMessageHandler(napi_env env, napi_value onTerminated, napi_value onMessage) 200 : jsMessageHandler_(std::make_shared<JSMsgHandlerCallbackObject>(env, onTerminated, onMessage)) {}; ~JsMessageHandler()201 virtual ~JsMessageHandler() {}; 202 int32_t OnTerminated() override; 203 int32_t OnMessage(const ArrayBuffer &arrayBuffer) override; 204 private: 205 std::mutex callbackObjectMutex_; 206 std::shared_ptr<JSMsgHandlerCallbackObject> jsMessageHandler_ = nullptr; 207 }; 208 private: 209 static napi_value JsConstructor(napi_env env, napi_callback_info cbinfo); 210 static napi_value GetIMController(napi_env env, napi_callback_info cbInfo, bool needThrowException); 211 static napi_value CreateSelectRange(napi_env env, int32_t start, int32_t end); 212 static napi_value CreateSelectMovement(napi_env env, int32_t direction); 213 static napi_value CreateSendFunctionKey(napi_env env, int32_t functionKey); 214 void RegisterListener(napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj); 215 void UnRegisterListener(napi_value callback, std::string type); 216 bool IsRegister(const std::string &type); 217 void UpdateTextPreviewState(const std::string &type); 218 static bool GetValue(napi_env env, napi_value in, CursorInfo &out); 219 static bool GetValue(napi_env env, napi_value in, InputAttribute &out); 220 static bool GetValue(napi_env env, napi_value in, TextConfig &out); 221 static bool GetValue(napi_env env, napi_value in, Range &out); 222 static napi_value GetAttachOptionsValue(napi_env env, napi_callback_info cbinfo, AttachOptions &attachOptions); 223 static napi_value GetJsKeyboardStatusProperty(napi_env env); 224 static napi_value GetJsEnterKeyTypeProperty(napi_env env); 225 static napi_value GetJsTextInputTypeProperty(napi_env env); 226 static napi_value GetJsDirectionProperty(napi_env env); 227 static napi_value GetJsExtendActionProperty(napi_env env); 228 static napi_value GetJsEnabledStateProperty(napi_env env); 229 static napi_value GetJsRequestKeyboardReasonProperty(napi_env env); 230 static std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler(); 231 static bool IsTextPreviewSupported(); 232 static const std::set<std::string> TEXT_EVENT_TYPE; 233 static constexpr int32_t MAX_TIMEOUT = 2500; 234 struct UvEntry { 235 std::vector<std::shared_ptr<JSCallbackObject>> vecCopy; 236 std::string type; 237 std::string text; 238 int32_t start = 0; 239 int32_t end = 0; 240 int32_t direction = 0; 241 int32_t length = 0; 242 int32_t action = 0; 243 int32_t keyboardStatus = 0; 244 int32_t enterKeyType = 0; 245 int32_t number = 0; 246 std::shared_ptr<BlockData<std::string>> textResultHandler; 247 std::shared_ptr<BlockData<std::int32_t>> indexResultHandler; UvEntryUvEntry248 explicit UvEntry(const std::vector<std::shared_ptr<JSCallbackObject>> &cbVec, const std::string &type) 249 : vecCopy(cbVec), type(type) 250 { 251 } 252 }; 253 using EntrySetter = std::function<void(UvEntry &)>; 254 std::shared_ptr<UvEntry> GetEntry(const std::string &type, EntrySetter entrySetter = nullptr); 255 uv_loop_s *loop_ = nullptr; 256 std::recursive_mutex mutex_; 257 std::map<std::string, std::vector<std::shared_ptr<JSCallbackObject>>> jsCbMap_; 258 static std::mutex controllerMutex_; 259 static std::shared_ptr<JsGetInputMethodController> controller_; 260 static const std::string IMC_CLASS_NAME; 261 static thread_local napi_ref IMCRef_; 262 static std::mutex eventHandlerMutex_; 263 static std::shared_ptr<AppExecFwk::EventHandler> handler_; 264 static constexpr size_t PARAM_POS_ZERO = 0; 265 static constexpr size_t PARAM_POS_ONE = 1; 266 static constexpr size_t PARAM_POS_TWO = 2; 267 static constexpr size_t PARAM_POS_THREE = 3; 268 static BlockQueue<MessageHandlerInfo> messageHandlerQueue_; 269 }; 270 } // namespace MiscServices 271 } // namespace OHOS 272 #endif // INTERFACE_KITS_JS_GET_INPUT_METHOD_CONTROLLER_H