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 25 namespace OHOS { 26 namespace MiscServices { 27 struct HandleContext : public AsyncCall::Context { 28 bool isHandle = false; 29 napi_status status = napi_generic_failure; HandleContextHandleContext30 HandleContext() : Context(nullptr, nullptr){}; HandleContextHandleContext31 HandleContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 32 operatorHandleContext33 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 34 { 35 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 36 return Context::operator()(env, argc, argv, self); 37 } operatorHandleContext38 napi_status operator()(napi_env env, napi_value *result) override 39 { 40 if (status != napi_ok) { 41 output_ = nullptr; 42 return status; 43 } 44 return Context::operator()(env, result); 45 } 46 }; 47 48 struct AttachContext : public AsyncCall::Context { 49 sptr<OnTextChangedListener> textListener; 50 InputAttribute attribute; 51 bool showKeyboard = false; 52 TextConfig textConfig; AttachContextAttachContext53 AttachContext() : Context(nullptr, nullptr) {}; AttachContextAttachContext54 AttachContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 55 operatorAttachContext56 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 57 { 58 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 59 return Context::operator()(env, argc, argv, self); 60 } operatorAttachContext61 napi_status operator()(napi_env env, napi_value *result) override 62 { 63 if (status_ != napi_ok) { 64 output_ = nullptr; 65 return status_; 66 } 67 return Context::operator()(env, result); 68 } 69 }; 70 71 struct SetCallingWindowContext : public AsyncCall::Context { 72 int32_t windID = 0; SetCallingWindowContextSetCallingWindowContext73 SetCallingWindowContext() : Context(nullptr, nullptr) {}; SetCallingWindowContextSetCallingWindowContext74 SetCallingWindowContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 75 operatorSetCallingWindowContext76 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 77 { 78 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 79 return Context::operator()(env, argc, argv, self); 80 } operatorSetCallingWindowContext81 napi_status operator()(napi_env env, napi_value *result) override 82 { 83 if (status_ != napi_ok) { 84 output_ = nullptr; 85 return status_; 86 } 87 return Context::operator()(env, result); 88 } 89 }; 90 91 struct UpdateCursorContext : public AsyncCall::Context { 92 CursorInfo cursorInfo; UpdateCursorContextUpdateCursorContext93 UpdateCursorContext() : Context(nullptr, nullptr) {}; UpdateCursorContextUpdateCursorContext94 UpdateCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 95 operatorUpdateCursorContext96 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 97 { 98 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 99 return Context::operator()(env, argc, argv, self); 100 } operatorUpdateCursorContext101 napi_status operator()(napi_env env, napi_value *result) override 102 { 103 if (status_ != napi_ok) { 104 output_ = nullptr; 105 return status_; 106 } 107 return Context::operator()(env, result); 108 } 109 }; 110 111 struct ChangeSelectionContext : public AsyncCall::Context { 112 std::u16string text; 113 int32_t start = 0; 114 int32_t end = 0; ChangeSelectionContextChangeSelectionContext115 ChangeSelectionContext() : Context(nullptr, nullptr) {}; ChangeSelectionContextChangeSelectionContext116 ChangeSelectionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 117 operatorChangeSelectionContext118 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 119 { 120 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 121 return Context::operator()(env, argc, argv, self); 122 } operatorChangeSelectionContext123 napi_status operator()(napi_env env, napi_value *result) override 124 { 125 if (status_ != napi_ok) { 126 output_ = nullptr; 127 return status_; 128 } 129 return Context::operator()(env, result); 130 } 131 }; 132 133 struct UpdateAttributeContext : public AsyncCall::Context { 134 InputAttribute attribute; 135 Configuration configuration; UpdateAttributeContextUpdateAttributeContext136 UpdateAttributeContext() : Context(nullptr, nullptr) {}; UpdateAttributeContextUpdateAttributeContext137 UpdateAttributeContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 138 operatorUpdateAttributeContext139 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 140 { 141 CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg); 142 return Context::operator()(env, argc, argv, self); 143 } operatorUpdateAttributeContext144 napi_status operator()(napi_env env, napi_value *result) override 145 { 146 if (status_ != napi_ok) { 147 output_ = nullptr; 148 return status_; 149 } 150 return Context::operator()(env, result); 151 } 152 }; 153 154 class JsGetInputMethodController : public ControllerListener { 155 public: 156 JsGetInputMethodController() = default; 157 ~JsGetInputMethodController() = default; 158 static napi_value Init(napi_env env, napi_value info); 159 static napi_value GetController(napi_env env, napi_callback_info cbInfo); 160 static napi_value GetInputMethodController(napi_env env, napi_callback_info cbInfo); 161 static std::shared_ptr<JsGetInputMethodController> GetInstance(); 162 static napi_value HandleSoftKeyboard(napi_env env, napi_callback_info info, std::function<int32_t()> callback, 163 bool isOutput, bool needThrowException); 164 static napi_value Attach(napi_env env, napi_callback_info info); 165 static napi_value Detach(napi_env env, napi_callback_info info); 166 static napi_value ShowTextInput(napi_env env, napi_callback_info info); 167 static napi_value HideTextInput(napi_env env, napi_callback_info info); 168 static napi_value SetCallingWindow(napi_env env, napi_callback_info info); 169 static napi_value UpdateCursor(napi_env env, napi_callback_info info); 170 static napi_value ChangeSelection(napi_env env, napi_callback_info info); 171 static napi_value UpdateAttribute(napi_env env, napi_callback_info info); 172 static napi_value HideSoftKeyboard(napi_env env, napi_callback_info info); 173 static napi_value ShowSoftKeyboard(napi_env env, napi_callback_info info); 174 static napi_value StopInputSession(napi_env env, napi_callback_info info); 175 static napi_value StopInput(napi_env env, napi_callback_info info); 176 static napi_value Subscribe(napi_env env, napi_callback_info info); 177 static napi_value UnSubscribe(napi_env env, napi_callback_info info); 178 void OnSelectByRange(int32_t start, int32_t end) override; 179 void OnSelectByMovement(int32_t direction) override; 180 void InsertText(const std::u16string &text); 181 void DeleteRight(int32_t length); 182 void DeleteLeft(int32_t length); 183 void SendKeyboardStatus(const KeyboardStatus &status); 184 void SendFunctionKey(const FunctionKey &functionKey); 185 void MoveCursor(const Direction direction); 186 void HandleExtendAction(int32_t action); 187 std::u16string GetText(const std::string &type, int32_t number); 188 int32_t GetTextIndexAtCursor(); 189 190 private: 191 static napi_value JsConstructor(napi_env env, napi_callback_info cbinfo); 192 static napi_value GetIMController(napi_env env, napi_callback_info cbInfo, bool needThrowException); 193 static napi_value CreateSelectRange(napi_env env, int32_t start, int32_t end); 194 static napi_value CreateSelectMovement(napi_env env, int32_t direction); 195 static napi_value CreateSendFunctionKey(napi_env env, int32_t functionKey); 196 void RegisterListener(napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj); 197 void UnRegisterListener(napi_value callback, std::string type); 198 static bool GetValue(napi_env env, napi_value in, CursorInfo &out); 199 static bool GetValue(napi_env env, napi_value in, InputAttribute &out); 200 static bool GetValue(napi_env env, napi_value in, TextConfig &out); 201 static bool GetValue(napi_env env, napi_value in, Range &out); 202 static napi_value GetJsKeyboardStatusProperty(napi_env env); 203 static napi_value GetJsEnterKeyTypeProperty(napi_env env); 204 static napi_value GetJsTextInputTypeProperty(napi_env env); 205 static napi_value GetJsDirectionProperty(napi_env env); 206 static napi_value GetJsExtendActionProperty(napi_env env); 207 static std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler(); 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 std::shared_ptr<UvEntry> GetEntry(const std::string &type, EntrySetter entrySetter = nullptr); 231 uv_loop_s *loop_ = nullptr; 232 std::recursive_mutex mutex_; 233 std::map<std::string, std::vector<std::shared_ptr<JSCallbackObject>>> jsCbMap_; 234 static std::mutex controllerMutex_; 235 static std::shared_ptr<JsGetInputMethodController> controller_; 236 static const std::string IMC_CLASS_NAME; 237 static thread_local napi_ref IMCRef_; 238 static std::mutex eventHandlerMutex_; 239 static std::shared_ptr<AppExecFwk::EventHandler> handler_; 240 static constexpr size_t PARAM_POS_ZERO = 0; 241 static constexpr size_t PARAM_POS_ONE = 1; 242 static constexpr size_t PARAM_POS_TWO = 2; 243 static constexpr size_t PARAM_POS_THREE = 3; 244 }; 245 } // namespace MiscServices 246 } // namespace OHOS 247 #endif // INTERFACE_KITS_JS_GET_INPUT_METHOD_CONTROLLER_H 248