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 } operatorSelectContext242 napi_status operator()(napi_env env, napi_value *result) override 243 { 244 if (status != napi_ok) { 245 output_ = nullptr; 246 return status; 247 } 248 return Context::operator()(env, result); 249 } 250 }; 251 252 struct GetTextIndexAtCursorContext : public AsyncCall::Context { 253 int32_t index = 0; 254 EditorEventInfo info; 255 napi_status status = napi_generic_failure; GetTextIndexAtCursorContextGetTextIndexAtCursorContext256 GetTextIndexAtCursorContext() : Context(nullptr, nullptr){}; GetTextIndexAtCursorContextGetTextIndexAtCursorContext257 GetTextIndexAtCursorContext(InputAction input, OutputAction output) 258 : Context(std::move(input), std::move(output)){}; 259 operatorGetTextIndexAtCursorContext260 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 261 { 262 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 263 return Context::operator()(env, argc, argv, self); 264 } operatorGetTextIndexAtCursorContext265 napi_status operator()(napi_env env, napi_value *result) override 266 { 267 if (status != napi_ok) { 268 output_ = nullptr; 269 return status; 270 } 271 return Context::operator()(env, result); 272 } 273 }; 274 275 struct SendExtendActionContext : public AsyncCall::Context { 276 int32_t action = 0; 277 EditorEventInfo info; SendExtendActionContextSendExtendActionContext278 SendExtendActionContext() : Context(nullptr, nullptr) {}; SendExtendActionContextSendExtendActionContext279 SendExtendActionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; 280 operatorSendExtendActionContext281 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 282 { 283 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 284 return Context::operator()(env, argc, argv, self); 285 } operatorSendExtendActionContext286 napi_status operator()(napi_env env, napi_value *result) override 287 { 288 if (status_ != napi_ok) { 289 output_ = nullptr; 290 return status_; 291 } 292 return Context::operator()(env, result); 293 } 294 }; 295 296 class JsTextInputClientEngine { 297 public: 298 JsTextInputClientEngine() = default; 299 ~JsTextInputClientEngine() = default; 300 static napi_value Init(napi_env env, napi_value info); 301 static napi_value SendKeyFunction(napi_env env, napi_callback_info info); 302 static napi_value DeleteForward(napi_env env, napi_callback_info info); 303 static napi_value DeleteBackward(napi_env env, napi_callback_info info); 304 static napi_value InsertText(napi_env env, napi_callback_info info); 305 static napi_value GetForward(napi_env env, napi_callback_info info); 306 static napi_value GetBackward(napi_env env, napi_callback_info info); 307 static napi_value MoveCursor(napi_env env, napi_callback_info info); 308 static napi_value GetEditorAttribute(napi_env env, napi_callback_info info); 309 static napi_value GetTextIndexAtCursor(napi_env env, napi_callback_info info); 310 static napi_value GetTextInputClientInstance(napi_env env); 311 static napi_value SelectByRange(napi_env env, napi_callback_info info); 312 static napi_value SelectByMovement(napi_env env, napi_callback_info info); 313 static napi_value SendExtendAction(napi_env env, napi_callback_info info); 314 static napi_value InsertTextSync(napi_env env, napi_callback_info info); 315 static napi_value MoveCursorSync(napi_env env, napi_callback_info info); 316 static napi_value GetEditorAttributeSync(napi_env env, napi_callback_info info); 317 static napi_value SelectByRangeSync(napi_env env, napi_callback_info info); 318 static napi_value SelectByMovementSync(napi_env env, napi_callback_info info); 319 static napi_value GetTextIndexAtCursorSync(napi_env env, napi_callback_info info); 320 static napi_value DeleteForwardSync(napi_env env, napi_callback_info info); 321 static napi_value DeleteBackwardSync(napi_env env, napi_callback_info info); 322 static napi_value GetForwardSync(napi_env env, napi_callback_info info); 323 static napi_value GetBackwardSync(napi_env env, napi_callback_info info); 324 325 private: 326 static napi_status GetSelectRange(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt); 327 static napi_status GetSelectMovement(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt); 328 329 static napi_value JsConstructor(napi_env env, napi_callback_info cbinfo); 330 static napi_value GetResult(napi_env env, std::string &text); 331 static napi_value GetResultEditorAttribute( 332 napi_env env, std::shared_ptr<GetEditorAttributeContext> getEditorAttribute); 333 static void PrintEditorQueueInfoIfTimeout(int64_t start, const EditorEventInfo ¤tInfo); 334 335 static const std::string TIC_CLASS_NAME; 336 static thread_local napi_ref TICRef_; 337 static constexpr std::int32_t MAX_VALUE_LEN = 4096; 338 static BlockQueue<EditorEventInfo> editorQueue_; 339 }; 340 } // namespace MiscServices 341 } // namespace OHOS 342 #endif // INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H