1 /* 2 * Copyright (c) 2022-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_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H 16 #define INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H 17 18 #include "async_call.h" 19 #include "global.h" 20 #include "native_engine/native_engine.h" 21 #include "native_engine/native_value.h" 22 #include "block_queue.h" 23 24 namespace OHOS { 25 namespace MiscServices { 26 enum class EditorEvent : uint32_t { 27 INSERT_TEXT = 0, 28 DELETE_FORWARD, 29 DELETE_BACKWARD, 30 MOVE_CURSOR, 31 SELECT_BY_RANGE, 32 SELECT_BY_MOVEMENT, 33 SEND_EXTEND_ACTION, 34 GET_FORWARD, 35 GET_BACKWARD, 36 GET_TEXT_INDEX_AT_CURSOR, 37 EVENT_END, 38 }; 39 struct EditorEventInfo { 40 std::chrono::system_clock::time_point timestamp{}; 41 EditorEvent event{ EditorEvent::EVENT_END }; 42 bool operator==(const EditorEventInfo &info) const 43 { 44 return (timestamp == info.timestamp && event == info.event); 45 } 46 }; 47 struct SendKeyFunctionContext : public AsyncCall::Context { 48 bool isSendKeyFunction = false; 49 int32_t action = 0; 50 napi_status status = napi_generic_failure; SendKeyFunctionContextSendKeyFunctionContext51 SendKeyFunctionContext() : Context(nullptr, nullptr){}; SendKeyFunctionContextSendKeyFunctionContext52 SendKeyFunctionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 53 operatorSendKeyFunctionContext54 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 55 { 56 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 57 return Context::operator()(env, argc, argv, self); 58 } 59 operatorSendKeyFunctionContext60 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 MoveCursorContext : public AsyncCall::Context { 71 int32_t num = 0; 72 EditorEventInfo info; 73 napi_status status = napi_generic_failure; MoveCursorContextMoveCursorContext74 MoveCursorContext() : Context(nullptr, nullptr){}; MoveCursorContextMoveCursorContext75 MoveCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 76 operatorMoveCursorContext77 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 78 { 79 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 80 return Context::operator()(env, argc, argv, self); 81 } operatorMoveCursorContext82 napi_status operator()(napi_env env, napi_value *result) override 83 { 84 if (status != napi_ok) { 85 output_ = nullptr; 86 return status; 87 } 88 return Context::operator()(env, result); 89 } 90 }; 91 92 struct DeleteForwardContext : public AsyncCall::Context { 93 bool isDeleteForward = false; 94 int32_t length = 0; 95 EditorEventInfo info; 96 napi_status status = napi_generic_failure; DeleteForwardContextDeleteForwardContext97 DeleteForwardContext() : Context(nullptr, nullptr){}; DeleteForwardContextDeleteForwardContext98 DeleteForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 99 operatorDeleteForwardContext100 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 101 { 102 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 103 return Context::operator()(env, argc, argv, self); 104 } operatorDeleteForwardContext105 napi_status operator()(napi_env env, napi_value *result) override 106 { 107 if (status != napi_ok) { 108 output_ = nullptr; 109 return status; 110 } 111 return Context::operator()(env, result); 112 } 113 }; 114 115 struct DeleteBackwardContext : public AsyncCall::Context { 116 bool isDeleteBackward = false; 117 int32_t length = 0; 118 EditorEventInfo info; 119 napi_status status = napi_generic_failure; DeleteBackwardContextDeleteBackwardContext120 DeleteBackwardContext() : Context(nullptr, nullptr){}; DeleteBackwardContextDeleteBackwardContext121 DeleteBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 122 operatorDeleteBackwardContext123 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 124 { 125 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 126 return Context::operator()(env, argc, argv, self); 127 } operatorDeleteBackwardContext128 napi_status operator()(napi_env env, napi_value *result) override 129 { 130 if (status != napi_ok) { 131 output_ = nullptr; 132 return status; 133 } 134 return Context::operator()(env, result); 135 } 136 }; 137 138 struct InsertTextContext : public AsyncCall::Context { 139 bool isInsertText = false; 140 std::string text; 141 EditorEventInfo info; 142 napi_status status = napi_generic_failure; InsertTextContextInsertTextContext143 InsertTextContext() : Context(nullptr, nullptr){}; InsertTextContextInsertTextContext144 InsertTextContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 145 operatorInsertTextContext146 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 147 { 148 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 149 return Context::operator()(env, argc, argv, self); 150 } operatorInsertTextContext151 napi_status operator()(napi_env env, napi_value *result) override 152 { 153 if (status != napi_ok) { 154 output_ = nullptr; 155 return status; 156 } 157 return Context::operator()(env, result); 158 } 159 }; 160 161 struct GetForwardContext : public AsyncCall::Context { 162 int32_t length = 0; 163 std::string text; 164 EditorEventInfo info; 165 napi_status status = napi_generic_failure; GetForwardContextGetForwardContext166 GetForwardContext() : Context(nullptr, nullptr){}; GetForwardContextGetForwardContext167 GetForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 168 operatorGetForwardContext169 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 170 { 171 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 172 return Context::operator()(env, argc, argv, self); 173 } operatorGetForwardContext174 napi_status operator()(napi_env env, napi_value *result) override 175 { 176 if (status != napi_ok) { 177 output_ = nullptr; 178 return status; 179 } 180 return Context::operator()(env, result); 181 } 182 }; 183 184 struct GetBackwardContext : public AsyncCall::Context { 185 int32_t length = 0; 186 std::string text; 187 EditorEventInfo info; 188 napi_status status = napi_generic_failure; GetBackwardContextGetBackwardContext189 GetBackwardContext() : Context(nullptr, nullptr){}; GetBackwardContextGetBackwardContext190 GetBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 191 operatorGetBackwardContext192 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 193 { 194 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 195 return Context::operator()(env, argc, argv, self); 196 } operatorGetBackwardContext197 napi_status operator()(napi_env env, napi_value *result) override 198 { 199 if (status != napi_ok) { 200 output_ = nullptr; 201 return status; 202 } 203 return Context::operator()(env, result); 204 } 205 }; 206 207 struct GetEditorAttributeContext : public AsyncCall::Context { 208 int32_t inputPattern = 0; 209 int32_t enterKeyType = 0; 210 napi_status status = napi_generic_failure; GetEditorAttributeContextGetEditorAttributeContext211 GetEditorAttributeContext() : Context(nullptr, nullptr){}; GetEditorAttributeContextGetEditorAttributeContext212 GetEditorAttributeContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 213 operatorGetEditorAttributeContext214 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 215 { 216 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 217 return Context::operator()(env, argc, argv, self); 218 } operatorGetEditorAttributeContext219 napi_status operator()(napi_env env, napi_value *result) override 220 { 221 if (status != napi_ok) { 222 output_ = nullptr; 223 return status; 224 } 225 return Context::operator()(env, result); 226 } 227 }; 228 229 struct SelectContext : public AsyncCall::Context { 230 int32_t start = 0; 231 int32_t end = 0; 232 int32_t direction = 0; 233 EditorEventInfo info; 234 napi_status status = napi_generic_failure; SelectContextSelectContext235 SelectContext() : Context(nullptr, nullptr){}; SelectContextSelectContext236 SelectContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; operatorSelectContext237 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 238 { 239 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 240 return Context::operator()(env, argc, argv, self); 241 } 242 }; 243 244 struct GetTextIndexAtCursorContext : public AsyncCall::Context { 245 int32_t index = 0; 246 EditorEventInfo info; 247 napi_status status = napi_generic_failure; GetTextIndexAtCursorContextGetTextIndexAtCursorContext248 GetTextIndexAtCursorContext() : Context(nullptr, nullptr){}; GetTextIndexAtCursorContextGetTextIndexAtCursorContext249 GetTextIndexAtCursorContext(InputAction input, OutputAction output) 250 : Context(std::move(input), std::move(output)){}; 251 operatorGetTextIndexAtCursorContext252 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 253 { 254 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 255 return Context::operator()(env, argc, argv, self); 256 } operatorGetTextIndexAtCursorContext257 napi_status operator()(napi_env env, napi_value *result) override 258 { 259 if (status != napi_ok) { 260 output_ = nullptr; 261 return status; 262 } 263 return Context::operator()(env, result); 264 } 265 }; 266 267 struct SendExtendActionContext : public AsyncCall::Context { 268 int32_t action = 0; 269 EditorEventInfo info; SendExtendActionContextSendExtendActionContext270 SendExtendActionContext() : Context(nullptr, nullptr) {}; SendExtendActionContextSendExtendActionContext271 SendExtendActionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 272 operatorSendExtendActionContext273 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 274 { 275 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 276 return Context::operator()(env, argc, argv, self); 277 } operatorSendExtendActionContext278 napi_status operator()(napi_env env, napi_value *result) override 279 { 280 if (status_ != napi_ok) { 281 output_ = nullptr; 282 return status_; 283 } 284 return Context::operator()(env, result); 285 } 286 }; 287 288 class JsTextInputClientEngine { 289 public: 290 JsTextInputClientEngine() = default; 291 ~JsTextInputClientEngine() = default; 292 static napi_value Init(napi_env env, napi_value info); 293 static napi_value SendKeyFunction(napi_env env, napi_callback_info info); 294 static napi_value DeleteForward(napi_env env, napi_callback_info info); 295 static napi_value DeleteBackward(napi_env env, napi_callback_info info); 296 static napi_value InsertText(napi_env env, napi_callback_info info); 297 static napi_value GetForward(napi_env env, napi_callback_info info); 298 static napi_value GetBackward(napi_env env, napi_callback_info info); 299 static napi_value MoveCursor(napi_env env, napi_callback_info info); 300 static napi_value GetEditorAttribute(napi_env env, napi_callback_info info); 301 static napi_value GetTextIndexAtCursor(napi_env env, napi_callback_info info); 302 static napi_value GetTextInputClientInstance(napi_env env); 303 static napi_value SelectByRange(napi_env env, napi_callback_info info); 304 static napi_value SelectByMovement(napi_env env, napi_callback_info info); 305 static napi_value SendExtendAction(napi_env env, napi_callback_info info); 306 static napi_value InsertTextSync(napi_env env, napi_callback_info info); 307 static napi_value MoveCursorSync(napi_env env, napi_callback_info info); 308 static napi_value GetEditorAttributeSync(napi_env env, napi_callback_info info); 309 static napi_value SelectByRangeSync(napi_env env, napi_callback_info info); 310 static napi_value SelectByMovementSync(napi_env env, napi_callback_info info); 311 static napi_value GetTextIndexAtCursorSync(napi_env env, napi_callback_info info); 312 static napi_value DeleteForwardSync(napi_env env, napi_callback_info info); 313 static napi_value DeleteBackwardSync(napi_env env, napi_callback_info info); 314 static napi_value GetForwardSync(napi_env env, napi_callback_info info); 315 static napi_value GetBackwardSync(napi_env env, napi_callback_info info); 316 317 private: 318 static napi_status GetSelectRange(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt); 319 static napi_status GetSelectMovement(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt); 320 321 static napi_value JsConstructor(napi_env env, napi_callback_info cbinfo); 322 static napi_value GetResult(napi_env env, std::string &text); 323 static napi_value GetResultEditorAttribute( 324 napi_env env, std::shared_ptr<GetEditorAttributeContext> getEditorAttribute); 325 326 static const std::string TIC_CLASS_NAME; 327 static thread_local napi_ref TICRef_; 328 static constexpr std::int32_t MAX_VALUE_LEN = 4096; 329 static BlockQueue<EditorEventInfo> editorQueue_; 330 }; 331 } // namespace MiscServices 332 } // namespace OHOS 333 #endif // INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H