• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 
16 #include <string>
17 #include <locale>
18 #include <codecvt>
19 
20 #include "cj_input_method_controller.h"
21 #include "cj_input_method_textchanged_listener.h"
22 #include "cj_lambda.h"
23 #include "utils.h"
24 #include "string_ex.h"
25 
26 namespace OHOS {
27 namespace MiscServices {
28 std::mutex CjInputMethodController::controllerMutex_;
29 std::shared_ptr<CjInputMethodController> CjInputMethodController::controller_{ nullptr };
30 const int8_t INSERT_TEXT = 0;
31 const int8_t DELETE_LEFT = 1;
32 const int8_t DELETE_RIGHT = 2;
33 const int8_t SEND_KEYBOARD_STATUS = 3;
34 const int8_t SEND_FUNCTION_KEY = 4;
35 const int8_t MOVE_CURSOR = 5;
36 const int8_t HANDLE_EXTEND_ACTION = 6;
37 const int8_t GET_LEFT_TEXT = 7;
38 const int8_t GET_RIGHT_TEXT = 8;
39 const int8_t GET_TEXT_INDEX = 9;
40 const int8_t SELECT_BY_MOVEMENT = 10;
41 const int8_t SELECT_BY_RANGE = 11;
42 
GetInstance()43 std::shared_ptr<CjInputMethodController> CjInputMethodController::GetInstance()
44 {
45     if (controller_ == nullptr) {
46         std::lock_guard<std::mutex> lock(controllerMutex_);
47         if (controller_ == nullptr) {
48             auto controller = std::make_shared<CjInputMethodController>();
49             controller_ = controller;
50             auto inputMethodController = InputMethodController::GetInstance();
51             if (inputMethodController != nullptr) {
52                 inputMethodController->SetControllerListener(controller_);
53             }
54         }
55     }
56     return controller_;
57 }
58 
Attach(const CTextConfig & txtCfg,const AttachOptions & attachOptions)59 int32_t CjInputMethodController::Attach(const CTextConfig &txtCfg, const AttachOptions &attachOptions)
60 {
61     auto textListener = CjInputMethodTextChangedListener::GetInstance();
62     if (textListener == nullptr) {
63         IMSA_HILOGE("failed to create CjInputMethodTextChangedListener!");
64         return ERR_NO_MEMORY;
65     }
66     TextConfig textCfg;
67     textCfg.inputAttribute.inputPattern = txtCfg.inputAttrbute.textInputType;
68     textCfg.inputAttribute.enterKeyType = txtCfg.inputAttrbute.enterKeyType;
69     textCfg.cursorInfo.left = txtCfg.cursor.left;
70     textCfg.cursorInfo.top = txtCfg.cursor.top;
71     textCfg.cursorInfo.width = txtCfg.cursor.width;
72     textCfg.cursorInfo.height = txtCfg.cursor.height;
73     textCfg.range.start = txtCfg.range.start;
74     textCfg.range.end = txtCfg.range.end;
75     textCfg.windowId = txtCfg.windowId;
76 
77     auto controller = InputMethodController::GetInstance();
78     if (controller == nullptr) {
79         return ERR_NO_MEMORY;
80     }
81     return controller->Attach(textListener, attachOptions, textCfg, ClientType::CJ);
82 }
83 
Detach()84 int32_t CjInputMethodController::Detach()
85 {
86     auto controller = InputMethodController::GetInstance();
87     if (controller == nullptr) {
88         return ERR_NO_MEMORY;
89     }
90     return controller->Close();
91 }
92 
ShowTextInput(const AttachOptions & attachOptions)93 int32_t CjInputMethodController::ShowTextInput(const AttachOptions &attachOptions)
94 {
95     auto controller = InputMethodController::GetInstance();
96     if (controller == nullptr) {
97         return ERR_NO_MEMORY;
98     }
99     return controller->ShowTextInput(attachOptions, ClientType::CJ);
100 }
101 
HideTextInput()102 int32_t CjInputMethodController::HideTextInput()
103 {
104     auto controller = InputMethodController::GetInstance();
105     if (controller == nullptr) {
106         return ERR_NO_MEMORY;
107     }
108     return controller->HideTextInput();
109 }
110 
SetCallingWindow(uint32_t windowId)111 int32_t CjInputMethodController::SetCallingWindow(uint32_t windowId)
112 {
113     auto controller = InputMethodController::GetInstance();
114     if (controller == nullptr) {
115         return ERR_NO_MEMORY;
116     }
117     return controller->SetCallingWindow(windowId);
118 }
119 
UpdateCursor(const CCursorInfo & cursor)120 int32_t CjInputMethodController::UpdateCursor(const CCursorInfo &cursor)
121 {
122     auto controller = InputMethodController::GetInstance();
123     if (controller == nullptr) {
124         return ERR_NO_MEMORY;
125     }
126     CursorInfo cursorInfo;
127     cursorInfo.left = cursor.left;
128     cursorInfo.top = cursor.top;
129     cursorInfo.width = cursor.width;
130     cursorInfo.height = cursor.height;
131     return controller->OnCursorUpdate(cursorInfo);
132 }
133 
ChangeSelection(const std::string & text,int32_t start,int32_t end)134 int32_t CjInputMethodController::ChangeSelection(const std::string &text, int32_t start, int32_t end)
135 {
136     auto controller = InputMethodController::GetInstance();
137     if (controller == nullptr) {
138         return ERR_NO_MEMORY;
139     }
140     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
141     std::u16string txt = converter.from_bytes(text);
142     return controller->OnSelectionChange(txt, start, end);
143 }
144 
UpdateAttribute(const CInputAttribute & inputAttribute)145 int32_t CjInputMethodController::UpdateAttribute(const CInputAttribute &inputAttribute)
146 {
147     auto controller = InputMethodController::GetInstance();
148     if (controller == nullptr) {
149         return ERR_NO_MEMORY;
150     }
151     Configuration config = Configuration();
152     config.SetTextInputType(static_cast<TextInputType>(inputAttribute.textInputType));
153     config.SetEnterKeyType(static_cast<EnterKeyType>(inputAttribute.enterKeyType));
154     return controller->OnConfigurationChange(config);
155 }
156 
ShowSoftKeyboard()157 int32_t CjInputMethodController::ShowSoftKeyboard()
158 {
159     auto controller = InputMethodController::GetInstance();
160     if (controller == nullptr) {
161         return ERR_NO_MEMORY;
162     }
163     return controller->ShowSoftKeyboard(ClientType::CJ);
164 }
165 
HideSoftKeyboard()166 int32_t CjInputMethodController::HideSoftKeyboard()
167 {
168     auto controller = InputMethodController::GetInstance();
169     if (controller == nullptr) {
170         return ERR_NO_MEMORY;
171     }
172     return controller->HideSoftKeyboard();
173 }
174 
StopInputSession()175 int32_t CjInputMethodController::StopInputSession()
176 {
177     auto controller = InputMethodController::GetInstance();
178     if (controller == nullptr) {
179         return ERR_NO_MEMORY;
180     }
181     return controller->StopInputSession();
182 }
183 
RegisterListener(int8_t type,int64_t id)184 void CjInputMethodController::RegisterListener(int8_t type, int64_t id)
185 {
186     std::lock_guard<std::recursive_mutex> lock(mutex_);
187     switch (type) {
188         case INSERT_TEXT:
189             InitInsertText(id);
190             break;
191         case DELETE_LEFT:
192             InitDeleteRight(id);
193             break;
194         case DELETE_RIGHT:
195             InitDeleteLeft(id);
196             break;
197         case SEND_KEYBOARD_STATUS:
198             InitSendKeyboardStatus(id);
199             break;
200         case SEND_FUNCTION_KEY:
201             InitSendFunctionKey(id);
202             break;
203         case MOVE_CURSOR:
204             InitMoveCursor(id);
205             break;
206         case HANDLE_EXTEND_ACTION:
207             InitHandleExtendAction(id);
208             break;
209         case GET_LEFT_TEXT:
210             InitGetLeftText(id);
211             break;
212         case GET_RIGHT_TEXT:
213             InitGetRightText(id);
214             break;
215         case GET_TEXT_INDEX:
216             InitGetTextIndexAtCursor(id);
217             break;
218         case SELECT_BY_MOVEMENT:
219             InitSelectByMovement(id);
220             break;
221         case SELECT_BY_RANGE:
222             InitSelectByRange(id);
223             break;
224         default:
225             return;
226     }
227 }
228 
UnRegisterListener(int8_t type)229 void CjInputMethodController::UnRegisterListener(int8_t type)
230 {
231     std::lock_guard<std::recursive_mutex> lock(mutex_);
232     switch (type) {
233         case INSERT_TEXT:
234             insertText = nullptr;
235             break;
236         case DELETE_LEFT:
237             deleteLeft = nullptr;
238             break;
239         case DELETE_RIGHT:
240             deleteRight = nullptr;
241             break;
242         case SEND_KEYBOARD_STATUS:
243             sendKeyboardStatus = nullptr;
244             break;
245         case SEND_FUNCTION_KEY:
246             sendFunctionKey = nullptr;
247             break;
248         case MOVE_CURSOR:
249             moveCursor = nullptr;
250             break;
251         case HANDLE_EXTEND_ACTION:
252             handleExtendAction = nullptr;
253             break;
254         case GET_LEFT_TEXT:
255             getLeftText = nullptr;
256             break;
257         case GET_RIGHT_TEXT:
258             getRightText = nullptr;
259             break;
260         case GET_TEXT_INDEX:
261             getTextIndexAtCursor = nullptr;
262             break;
263         case SELECT_BY_MOVEMENT:
264             onSelectByMovement = nullptr;
265             break;
266         case SELECT_BY_RANGE:
267             onSelectByRange = nullptr;
268             break;
269         default:
270             return;
271     }
272 }
273 
Subscribe(int8_t type,int64_t id)274 int32_t CjInputMethodController::Subscribe(int8_t type, int64_t id)
275 {
276     auto controller = CjInputMethodController::GetInstance();
277     if (controller == nullptr) {
278         return ERR_NO_MEMORY;
279     }
280     controller->RegisterListener(type, id);
281     return SUCCESS_CODE;
282 }
283 
Unsubscribe(int8_t type)284 int32_t CjInputMethodController::Unsubscribe(int8_t type)
285 {
286     auto controller = CjInputMethodController::GetInstance();
287     if (controller == nullptr) {
288         return ERR_NO_MEMORY;
289     }
290     controller->UnRegisterListener(type);
291     return SUCCESS_CODE;
292 }
293 
OnSelectByRange(int32_t start,int32_t end)294 void CjInputMethodController::OnSelectByRange(int32_t start, int32_t end)
295 {
296     if (onSelectByRange == nullptr) {
297         IMSA_HILOGD("onSelelctByRange null");
298         return;
299     }
300     IMSA_HILOGD("onSelelctByRange runs");
301     Range range;
302     range.start = start;
303     range.end = end;
304     return onSelectByRange(range);
305 }
306 
OnSelectByMovement(int32_t direction)307 void CjInputMethodController::OnSelectByMovement(int32_t direction)
308 {
309     if (onSelectByMovement == nullptr) {
310         IMSA_HILOGD("onSelectByMovement null");
311         return;
312     }
313     IMSA_HILOGD("onSelectByMovement runs");
314     return onSelectByMovement(direction);
315 }
316 
InsertText(const std::u16string & text)317 void CjInputMethodController::InsertText(const std::u16string &text)
318 {
319     char *insertTxt = Utils::MallocCString(Str16ToStr8(text));
320     if (insertTxt == nullptr) {
321         IMSA_HILOGE("Failed to excute InsertText callback: out of memory.");
322         return;
323     }
324     if (insertText == nullptr) {
325         IMSA_HILOGD("insertText null");
326         free(insertTxt);
327         return;
328     }
329     IMSA_HILOGD("insertText runs");
330     insertText(insertTxt);
331     free(insertTxt);
332     return;
333 }
334 
DeleteRight(int32_t length)335 void CjInputMethodController::DeleteRight(int32_t length)
336 {
337     if (deleteRight == nullptr) {
338         IMSA_HILOGD("deleteRight null");
339         return;
340     }
341     IMSA_HILOGD("deleteRight runs");
342     deleteRight(length);
343     return;
344 }
345 
DeleteLeft(int32_t length)346 void CjInputMethodController::DeleteLeft(int32_t length)
347 {
348     if (deleteLeft == nullptr) {
349         IMSA_HILOGD("deleteLeft null");
350         return;
351     }
352     IMSA_HILOGD("deleteLeft runs");
353     deleteLeft(length);
354     return;
355 }
356 
SendKeyboardStatus(const KeyboardStatus & status)357 void CjInputMethodController::SendKeyboardStatus(const KeyboardStatus &status)
358 {
359     if (sendKeyboardStatus == nullptr) {
360         IMSA_HILOGD("sendKeyboardStatus null");
361         return;
362     }
363     IMSA_HILOGD("sendKeyboardStatus runs");
364     auto statusNum = static_cast<int32_t>(status);
365     sendKeyboardStatus(statusNum);
366     return;
367 }
368 
SendFunctionKey(const FunctionKey & functionKey)369 void CjInputMethodController::SendFunctionKey(const FunctionKey &functionKey)
370 {
371     if (sendFunctionKey == nullptr) {
372         IMSA_HILOGD("sendFunctionKey null");
373         return;
374     }
375     IMSA_HILOGD("sendFunctionKey runs");
376     auto type = static_cast<int32_t>(functionKey.GetEnterKeyType());
377     sendFunctionKey(type);
378     return;
379 }
380 
MoveCursor(const Direction direction)381 void CjInputMethodController::MoveCursor(const Direction direction)
382 {
383     if (moveCursor == nullptr) {
384         IMSA_HILOGD("moveCursor null");
385         return;
386     }
387     IMSA_HILOGD("moveCursor runs");
388     auto dir = static_cast<int32_t>(direction);
389     moveCursor(dir);
390     return;
391 }
392 
HandleExtendAction(int32_t action)393 void CjInputMethodController::HandleExtendAction(int32_t action)
394 {
395     if (handleExtendAction == nullptr) {
396         IMSA_HILOGD("handleExtendAction null");
397         return;
398     }
399     IMSA_HILOGD("handleExtendAction runs");
400     handleExtendAction(action);
401     return;
402 }
403 
GetLeftText(int32_t number)404 std::u16string CjInputMethodController::GetLeftText(int32_t number)
405 {
406     if (getLeftText == nullptr) {
407         IMSA_HILOGD("getLeftText null");
408         return u"";
409     }
410     IMSA_HILOGD("getLeftText runs");
411     char *text = getLeftText(number);
412     if (text == nullptr) {
413         IMSA_HILOGD("text is nullptr");
414         return u"";
415     }
416     auto ret = Str8ToStr16(std::string(text));
417     free(text);
418     return ret;
419 }
420 
GetRightText(int32_t number)421 std::u16string CjInputMethodController::GetRightText(int32_t number)
422 {
423     if (getRightText == nullptr) {
424         IMSA_HILOGD("getRightText null");
425         return u"";
426     }
427     IMSA_HILOGD("getRightText runs");
428     char *text = getRightText(number);
429     if (text == nullptr) {
430         IMSA_HILOGD("text is nullptr");
431         return u"";
432     }
433     auto ret = Str8ToStr16(std::string(text));
434     free(text);
435     return ret;
436 }
437 
GetTextIndexAtCursor()438 int32_t CjInputMethodController::GetTextIndexAtCursor()
439 {
440     if (getTextIndexAtCursor == nullptr) {
441         IMSA_HILOGD("getTextIndexAtCursor null");
442         return -1;
443     }
444     IMSA_HILOGD("getTextIndexAtCursor runs");
445     return getTextIndexAtCursor();
446 }
447 
InitInsertText(int64_t id)448 void CjInputMethodController::InitInsertText(int64_t id)
449 {
450     auto callback = reinterpret_cast<void(*)(const char*)>(id);
451     insertText = [lambda = CJLambda::Create(callback)](const char* text) -> void {
452         lambda(text);
453     };
454 }
455 
InitDeleteRight(int64_t id)456 void CjInputMethodController::InitDeleteRight(int64_t id)
457 {
458     auto callback = reinterpret_cast<void(*)(int32_t)>(id);
459     deleteLeft = [lambda = CJLambda::Create(callback)](int32_t length) -> void {
460         lambda(length);
461     };
462 }
463 
InitDeleteLeft(int64_t id)464 void CjInputMethodController::InitDeleteLeft(int64_t id)
465 {
466     auto callback = reinterpret_cast<void(*)(int32_t)>(id);
467     deleteRight = [lambda = CJLambda::Create(callback)](int32_t length) -> void {
468         lambda(length);
469     };
470 }
471 
InitSendKeyboardStatus(int64_t id)472 void CjInputMethodController::InitSendKeyboardStatus(int64_t id)
473 {
474     auto callback = reinterpret_cast<void(*)(int32_t)>(id);
475     sendKeyboardStatus = [lambda = CJLambda::Create(callback)](int32_t status) -> void {
476         lambda(status);
477     };
478 }
479 
InitSendFunctionKey(int64_t id)480 void CjInputMethodController::InitSendFunctionKey(int64_t id)
481 {
482     auto callback = reinterpret_cast<void(*)(int32_t)>(id);
483     sendFunctionKey = [lambda = CJLambda::Create(callback)](int32_t functionKey) -> void {
484         lambda(functionKey);
485     };
486 }
487 
InitMoveCursor(int64_t id)488 void CjInputMethodController::InitMoveCursor(int64_t id)
489 {
490     auto callback = reinterpret_cast<void(*)(int32_t)>(id);
491     moveCursor = [lambda = CJLambda::Create(callback)](int32_t direction) -> void {
492         lambda(direction);
493     };
494 }
495 
InitHandleExtendAction(int64_t id)496 void CjInputMethodController::InitHandleExtendAction(int64_t id)
497 {
498     auto callback = reinterpret_cast<void(*)(int32_t)>(id);
499     handleExtendAction = [lambda = CJLambda::Create(callback)](int32_t action) -> void {
500         lambda(action);
501     };
502 }
503 
InitGetLeftText(int64_t id)504 void CjInputMethodController::InitGetLeftText(int64_t id)
505 {
506     auto callback = reinterpret_cast<char*(*)(int32_t)>(id);
507     getLeftText = [lambda = CJLambda::Create(callback)](int32_t number) -> char* {
508         return lambda(number);
509     };
510 }
511 
InitGetRightText(int64_t id)512 void CjInputMethodController::InitGetRightText(int64_t id)
513 {
514     auto callback = reinterpret_cast<char*(*)(int32_t)>(id);
515     getRightText = [lambda = CJLambda::Create(callback)](int32_t number) -> char* {
516         return lambda(number);
517     };
518 }
519 
InitGetTextIndexAtCursor(int64_t id)520 void CjInputMethodController::InitGetTextIndexAtCursor(int64_t id)
521 {
522     auto callback = reinterpret_cast<int32_t(*)()>(id);
523     getTextIndexAtCursor = [lambda = CJLambda::Create(callback)](void) -> int32_t {
524         return lambda();
525     };
526 }
527 
InitSelectByMovement(int64_t id)528 void CjInputMethodController::InitSelectByMovement(int64_t id)
529 {
530     auto callback = reinterpret_cast<void(*)(int32_t)>(id);
531     onSelectByMovement = [lambda = CJLambda::Create(callback)](int32_t direction) -> void {
532         lambda(direction);
533     };
534 }
535 
InitSelectByRange(int64_t id)536 void CjInputMethodController::InitSelectByRange(int64_t id)
537 {
538     auto callback = reinterpret_cast<void(*)(Range)>(id);
539     onSelectByRange = [lambda = CJLambda::Create(callback)](Range range) -> void {
540         lambda(range);
541     };
542 }
543 
544 } // namespace MiscServices
545 } // namespace OHOS
546