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