• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 AttachInfo {
30     std::chrono::system_clock::time_point timestamp{};
31     InputAttribute attribute;
32     bool operator==(const AttachInfo &info) const
33     {
34         return (timestamp == info.timestamp && attribute == info.attribute);
35     }
36 };
37 
38 struct HandleContext : public AsyncCall::Context {
39     bool isHandle = false;
40     napi_status status = napi_generic_failure;
HandleContextHandleContext41     HandleContext() : Context(nullptr, nullptr){};
HandleContextHandleContext42     HandleContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
43 
operatorHandleContext44     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
45     {
46         CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg);
47         return Context::operator()(env, argc, argv, self);
48     }
operatorHandleContext49     napi_status operator()(napi_env env, napi_value *result) override
50     {
51         if (status != napi_ok) {
52             output_ = nullptr;
53             return status;
54         }
55         return Context::operator()(env, result);
56     }
57 };
58 
59 struct AttachContext : public AsyncCall::Context {
60     sptr<OnTextChangedListener> textListener;
61     InputAttribute attribute;
62     bool showKeyboard = false;
63     int32_t requestKeyboardReason = 0;
64     TextConfig textConfig;
65     AttachInfo info;
AttachContextAttachContext66     AttachContext() : Context(nullptr, nullptr){};
AttachContextAttachContext67     AttachContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
68 
operatorAttachContext69     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
70     {
71         CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg);
72         return Context::operator()(env, argc, argv, self);
73     }
operatorAttachContext74     napi_status operator()(napi_env env, napi_value *result) override
75     {
76         if (status_ != napi_ok) {
77             output_ = nullptr;
78             return status_;
79         }
80         return Context::operator()(env, result);
81     }
82 };
83 
84 struct SetCallingWindowContext : public AsyncCall::Context {
85     int32_t windID = 0;
SetCallingWindowContextSetCallingWindowContext86     SetCallingWindowContext() : Context(nullptr, nullptr){};
SetCallingWindowContextSetCallingWindowContext87     SetCallingWindowContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
88 
operatorSetCallingWindowContext89     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
90     {
91         CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg);
92         return Context::operator()(env, argc, argv, self);
93     }
operatorSetCallingWindowContext94     napi_status operator()(napi_env env, napi_value *result) override
95     {
96         if (status_ != napi_ok) {
97             output_ = nullptr;
98             return status_;
99         }
100         return Context::operator()(env, result);
101     }
102 };
103 
104 struct UpdateCursorContext : public AsyncCall::Context {
105     CursorInfo cursorInfo;
UpdateCursorContextUpdateCursorContext106     UpdateCursorContext() : Context(nullptr, nullptr){};
UpdateCursorContextUpdateCursorContext107     UpdateCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
108 
operatorUpdateCursorContext109     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
110     {
111         CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg);
112         return Context::operator()(env, argc, argv, self);
113     }
operatorUpdateCursorContext114     napi_status operator()(napi_env env, napi_value *result) override
115     {
116         if (status_ != napi_ok) {
117             output_ = nullptr;
118             return status_;
119         }
120         return Context::operator()(env, result);
121     }
122 };
123 
124 struct ChangeSelectionContext : public AsyncCall::Context {
125     std::u16string text;
126     int32_t start = 0;
127     int32_t end = 0;
ChangeSelectionContextChangeSelectionContext128     ChangeSelectionContext() : Context(nullptr, nullptr){};
ChangeSelectionContextChangeSelectionContext129     ChangeSelectionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
130 
operatorChangeSelectionContext131     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
132     {
133         CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg);
134         return Context::operator()(env, argc, argv, self);
135     }
operatorChangeSelectionContext136     napi_status operator()(napi_env env, napi_value *result) override
137     {
138         if (status_ != napi_ok) {
139             output_ = nullptr;
140             return status_;
141         }
142         return Context::operator()(env, result);
143     }
144 };
145 
146 struct UpdateAttributeContext : public AsyncCall::Context {
147     InputAttribute attribute;
148     Configuration configuration;
UpdateAttributeContextUpdateAttributeContext149     UpdateAttributeContext() : Context(nullptr, nullptr){};
UpdateAttributeContextUpdateAttributeContext150     UpdateAttributeContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
151 
operatorUpdateAttributeContext152     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
153     {
154         CHECK_RETURN(self != nullptr, "self is nullptr!", napi_invalid_arg);
155         return Context::operator()(env, argc, argv, self);
156     }
operatorUpdateAttributeContext157     napi_status operator()(napi_env env, napi_value *result) override
158     {
159         if (status_ != napi_ok) {
160             output_ = nullptr;
161             return status_;
162         }
163         return Context::operator()(env, result);
164     }
165 };
166 
167 class JsGetInputMethodController : public ControllerListener {
168 public:
169     JsGetInputMethodController() = default;
170     ~JsGetInputMethodController() = default;
171     static napi_value Init(napi_env env, napi_value info);
172     static napi_value GetController(napi_env env, napi_callback_info cbInfo);
173     static napi_value GetInputMethodController(napi_env env, napi_callback_info cbInfo);
174     static std::shared_ptr<JsGetInputMethodController> GetInstance();
175     static napi_value HandleSoftKeyboard(napi_env env, napi_callback_info info, std::function<int32_t()> callback,
176         bool isOutput, bool needThrowException);
177     static napi_value Attach(napi_env env, napi_callback_info info);
178     static napi_value Detach(napi_env env, napi_callback_info info);
179     static napi_value ShowTextInput(napi_env env, napi_callback_info info);
180     static napi_value HideTextInput(napi_env env, napi_callback_info info);
181     static napi_value DiscardTypingText(napi_env env, napi_callback_info info);
182     static napi_value SetCallingWindow(napi_env env, napi_callback_info info);
183     static napi_value UpdateCursor(napi_env env, napi_callback_info info);
184     static napi_value ChangeSelection(napi_env env, napi_callback_info info);
185     static napi_value UpdateAttribute(napi_env env, napi_callback_info info);
186     static napi_value HideSoftKeyboard(napi_env env, napi_callback_info info);
187     static napi_value ShowSoftKeyboard(napi_env env, napi_callback_info info);
188     static napi_value StopInputSession(napi_env env, napi_callback_info info);
189     static napi_value StopInput(napi_env env, napi_callback_info info);
190     static napi_value Subscribe(napi_env env, napi_callback_info info);
191     static napi_value UnSubscribe(napi_env env, napi_callback_info info);
192     static napi_value SendMessage(napi_env env, napi_callback_info info);
193     static napi_value RecvMessage(napi_env env, napi_callback_info info);
194     void OnSelectByRange(int32_t start, int32_t end) override;
195     void OnSelectByMovement(int32_t direction) override;
196     void InsertText(const std::u16string &text);
197     void DeleteRight(int32_t length);
198     void DeleteLeft(int32_t length);
199     void SendKeyboardStatus(const KeyboardStatus &status);
200     void SendFunctionKey(const FunctionKey &functionKey);
201     void MoveCursor(const Direction direction);
202     void HandleExtendAction(int32_t action);
203     std::u16string GetText(const std::string &type, int32_t number);
204     int32_t GetTextIndexAtCursor();
205     int32_t SetPreviewText(const std::u16string &text, const Range &range);
206     void FinishTextPreview();
207 
208     class JsMessageHandler : public MsgHandlerCallbackInterface {
209     public:
JsMessageHandler(napi_env env,napi_value onTerminated,napi_value onMessage)210         explicit JsMessageHandler(napi_env env, napi_value onTerminated, napi_value onMessage)
211             : jsMessageHandler_(std::make_shared<JSMsgHandlerCallbackObject>(env, onTerminated, onMessage)) {};
~JsMessageHandler()212         virtual ~JsMessageHandler() {};
213         int32_t OnTerminated() override;
214         int32_t OnMessage(const ArrayBuffer &arrayBuffer) override;
215     private:
216         std::mutex callbackObjectMutex_;
217         std::shared_ptr<JSMsgHandlerCallbackObject> jsMessageHandler_ = nullptr;
218     };
219 private:
220     static napi_value JsConstructor(napi_env env, napi_callback_info cbinfo);
221     static napi_value GetIMController(napi_env env, napi_callback_info cbInfo, bool needThrowException);
222     static napi_value CreateSelectRange(napi_env env, int32_t start, int32_t end);
223     static napi_value CreateSelectMovement(napi_env env, int32_t direction);
224     static napi_value CreateSendFunctionKey(napi_env env, int32_t functionKey);
225     void RegisterListener(napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj);
226     void UnRegisterListener(napi_value callback, std::string type);
227     bool IsRegister(const std::string &type);
228     void UpdateTextPreviewState(const std::string &type);
229     static bool GetValue(napi_env env, napi_value in, CursorInfo &out);
230     static bool GetValue(napi_env env, napi_value in, InputAttribute &out);
231     static bool GetValue(napi_env env, napi_value in, TextConfig &out);
232     static bool GetValue(napi_env env, napi_value in, Range &out);
233     static napi_value GetAttachOptionsValue(napi_env env, napi_callback_info cbinfo, AttachOptions &attachOptions);
234     static napi_value GetJsKeyboardStatusProperty(napi_env env);
235     static napi_value GetJsEnterKeyTypeProperty(napi_env env);
236     static napi_value GetJsTextInputTypeProperty(napi_env env);
237     static napi_value GetJsDirectionProperty(napi_env env);
238     static napi_value GetJsExtendActionProperty(napi_env env);
239     static napi_value GetJsEnabledStateProperty(napi_env env);
240     static napi_value GetJsCapitalizeModeProperty(napi_env env);
241     static napi_value GetJsRequestKeyboardReasonProperty(napi_env env);
242     static std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler();
243     static bool IsTextPreviewSupported();
244     static const std::set<std::string> TEXT_EVENT_TYPE;
245     static constexpr int32_t MAX_TIMEOUT = 2500;
246     struct UvEntry {
247         std::vector<std::shared_ptr<JSCallbackObject>> vecCopy;
248         std::string type;
249         std::string text;
250         int32_t start = 0;
251         int32_t end = 0;
252         int32_t direction = 0;
253         int32_t length = 0;
254         int32_t action = 0;
255         int32_t keyboardStatus = 0;
256         int32_t enterKeyType = 0;
257         int32_t number = 0;
258         std::shared_ptr<BlockData<std::string>> textResultHandler;
259         std::shared_ptr<BlockData<std::int32_t>> indexResultHandler;
UvEntryUvEntry260         explicit UvEntry(const std::vector<std::shared_ptr<JSCallbackObject>> &cbVec, const std::string &type)
261             : vecCopy(cbVec), type(type)
262         {
263         }
264     };
265     using EntrySetter = std::function<void(UvEntry &)>;
266     std::shared_ptr<UvEntry> GetEntry(const std::string &type, EntrySetter entrySetter = nullptr);
267     std::recursive_mutex mutex_;
268     std::map<std::string, std::vector<std::shared_ptr<JSCallbackObject>>> jsCbMap_;
269     static std::mutex controllerMutex_;
270     static std::shared_ptr<JsGetInputMethodController> controller_;
271     static const std::string IMC_CLASS_NAME;
272     static thread_local napi_ref IMCRef_;
273     static std::mutex eventHandlerMutex_;
274     static std::shared_ptr<AppExecFwk::EventHandler> handler_;
275     static constexpr size_t PARAM_POS_ZERO = 0;
276     static constexpr size_t PARAM_POS_ONE = 1;
277     static constexpr size_t PARAM_POS_TWO = 2;
278     static constexpr size_t PARAM_POS_THREE = 3;
279     static BlockQueue<MessageHandlerInfo> messageHandlerQueue_;
280     static BlockQueue<AttachInfo> attachQueue_;
281 };
282 } // namespace MiscServices
283 } // namespace OHOS
284 #endif // INTERFACE_KITS_JS_GET_INPUT_METHOD_CONTROLLER_H