1 /*
2  * Copyright (c) 2021-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 "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
17 
18 #include "base/input_manager/input_manager.h"
19 #include "base/log/ace_trace.h"
20 #include "base/memory/ace_type.h"
21 #include "core/common/container.h"
22 #include "core/common/container_scope.h"
23 #include "core/common/ime/text_input_client.h"
24 #include "core/components_ng/pattern/text_field/text_field_manager.h"
25 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
26 #include "core/event/key_event.h"
27 #include "core/pipeline/pipeline_base.h"
28 
29 namespace OHOS::Ace::NG {
30 const std::string AUTO_FILL_PARAMS_USERNAME = "com.autofill.params.userName";
31 const std::string AUTO_FILL_PARAMS_NEWPASSWORD = "com.autofill.params.newPassword";
32 const std::string AUTO_FILL_PARAMS_OTHERACCOUNT = "com.autofill.params.otherAccount";
InsertText(const std::u16string & text)33 void OnTextChangedListenerImpl::InsertText(const std::u16string& text)
34 {
35     if (text.empty()) {
36         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "the text is null");
37         return;
38     }
39     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "InsertText length:%{public}d", static_cast<int32_t>(text.length()));
40     auto task = [textFieldPattern = pattern_, text] {
41         ACE_SCOPED_TRACE("InsertText [length:%d]", static_cast<int32_t>(text.length()));
42         auto client = textFieldPattern.Upgrade();
43         CHECK_NULL_VOID(client);
44         ContainerScope scope(client->GetInstanceId());
45         client->InsertValue(StringUtils::Str16ToStr8(text), true);
46     };
47     PostTaskToUI(task, "ArkUITextFieldInsertText");
48 }
49 
DeleteBackward(int32_t length)50 void OnTextChangedListenerImpl::DeleteBackward(int32_t length)
51 {
52     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "DeleteBackward length: %{public}d", length);
53     if (length <= 0) {
54         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Delete nothing.");
55         return;
56     }
57 
58     auto task = [textFieldPattern = pattern_, length] {
59         auto client = textFieldPattern.Upgrade();
60         CHECK_NULL_VOID(client);
61         ContainerScope scope(client->GetInstanceId());
62         client->DeleteBackward(length);
63     };
64     PostTaskToUI(task, "ArkUITextFieldDeleteBackward");
65 }
66 
DeleteForward(int32_t length)67 void OnTextChangedListenerImpl::DeleteForward(int32_t length)
68 {
69     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "DeleteForward length: %{public}d", length);
70     if (length <= 0) {
71         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Delete nothing.");
72         return;
73     }
74 
75     auto task = [textFieldPattern = pattern_, length] {
76         auto client = textFieldPattern.Upgrade();
77         CHECK_NULL_VOID(client);
78         ContainerScope scope(client->GetInstanceId());
79         client->DeleteForward(length);
80     };
81     PostTaskToUI(task, "ArkUITextFieldDeleteForward");
82 }
83 
SetKeyboardStatus(bool status)84 void OnTextChangedListenerImpl::SetKeyboardStatus(bool status)
85 {
86     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetKeyboardStatus status: %{public}d", status);
87     auto task = [textField = pattern_, status] {
88         auto client = textField.Upgrade();
89         CHECK_NULL_VOID(client);
90         ContainerScope scope(client->GetInstanceId());
91         client->SetInputMethodStatus(status);
92     };
93     PostTaskToUI(task, "ArkUITextFieldSetKeyboardStatus");
94 }
95 
GetLeftTextOfCursor(int32_t number)96 std::u16string OnTextChangedListenerImpl::GetLeftTextOfCursor(int32_t number)
97 {
98     ACE_SCOPED_TRACE("GetLeftTextOfCursor[%d]", number);
99     std::u16string leftResult;
100     auto task = [textField = pattern_, &leftResult, number] {
101         auto client = textField.Upgrade();
102         CHECK_NULL_VOID(client);
103         ContainerScope scope(client->GetInstanceId());
104         leftResult = client->GetLeftTextOfCursor(number);
105     };
106     PostSyncTaskToUI(task, "ArkUITextFieldGetLeftTextOfCursor");
107     return leftResult;
108 }
109 
GetRightTextOfCursor(int32_t number)110 std::u16string OnTextChangedListenerImpl::GetRightTextOfCursor(int32_t number)
111 {
112     ACE_SCOPED_TRACE("GetRightTextOfCursor[%d]", number);
113     std::u16string rightResult;
114     auto task = [textField = pattern_, &rightResult, number] {
115         auto client = textField.Upgrade();
116         CHECK_NULL_VOID(client);
117         ContainerScope scope(client->GetInstanceId());
118         rightResult = client->GetRightTextOfCursor(number);
119     };
120     PostSyncTaskToUI(task, "ArkUITextFieldGetRightTextOfCursor");
121     return rightResult;
122 }
123 
GetTextIndexAtCursor()124 int32_t OnTextChangedListenerImpl::GetTextIndexAtCursor()
125 {
126     ACE_SCOPED_TRACE("GetTextIndexAtCursor");
127     int32_t index = 0;
128     auto task = [textField = pattern_, &index] {
129         auto client = textField.Upgrade();
130         CHECK_NULL_VOID(client);
131         ContainerScope scope(client->GetInstanceId());
132         index = client->GetTextIndexAtCursor();
133     };
134     PostSyncTaskToUI(task, "ArkUITextFieldGetTextIndexAtCursor");
135     return index;
136 }
137 
SendKeyEventFromInputMethod(const MiscServices::KeyEvent & event)138 void OnTextChangedListenerImpl::SendKeyEventFromInputMethod(const MiscServices::KeyEvent& event) {}
139 
SendKeyboardStatus(const MiscServices::KeyboardStatus & keyboardStatus)140 void OnTextChangedListenerImpl::SendKeyboardStatus(const MiscServices::KeyboardStatus& keyboardStatus)
141 {
142     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SendKeyboardStatus status: %{public}d", static_cast<int>(keyboardStatus));
143     // this keyboard status means shown or hidden but attachment is not closed, should be distinguished from
144     // imeAttached_
145     HandleKeyboardStatus(keyboardStatus);
146 }
147 
NotifyKeyboardHeight(uint32_t height)148 void OnTextChangedListenerImpl::NotifyKeyboardHeight(uint32_t height)
149 {
150     auto task = [textField = pattern_, height] {
151         ACE_SCOPED_TRACE("NotifyKeyboardHeight");
152         auto client = textField.Upgrade();
153         CHECK_NULL_VOID(client);
154         ContainerScope scope(client->GetInstanceId());
155         client->NotifyKeyboardHeight(height);
156     };
157     PostTaskToUI(task, "ArkUITextFieldNotifyKeyboardHeight");
158 }
159 
SendFunctionKey(const MiscServices::FunctionKey & functionKey)160 void OnTextChangedListenerImpl::SendFunctionKey(const MiscServices::FunctionKey& functionKey)
161 {
162     HandleFunctionKey(functionKey);
163 }
164 
HandleKeyboardStatus(MiscServices::KeyboardStatus status)165 void OnTextChangedListenerImpl::HandleKeyboardStatus(MiscServices::KeyboardStatus status)
166 {
167     SetKeyboardStatus(status == MiscServices::KeyboardStatus::SHOW);
168 }
169 
HandleFunctionKey(MiscServices::FunctionKey functionKey)170 void OnTextChangedListenerImpl::HandleFunctionKey(MiscServices::FunctionKey functionKey)
171 {
172     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Handle function key %{public}d",
173         static_cast<int32_t>(functionKey.GetEnterKeyType()));
174     auto task = [textField = pattern_, functionKey] {
175         auto client = textField.Upgrade();
176         CHECK_NULL_VOID(client);
177         ContainerScope scope(client->GetInstanceId());
178         auto action = static_cast<TextInputAction>(functionKey.GetEnterKeyType());
179         switch (action) {
180             case TextInputAction::DONE:
181             case TextInputAction::NEXT:
182             case TextInputAction::SEARCH:
183             case TextInputAction::SEND:
184             case TextInputAction::GO:
185             case TextInputAction::PREVIOUS:
186             case TextInputAction::NEW_LINE:
187                 client->PerformAction(action, true);
188                 break;
189             default:
190                 TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "TextInputAction  is not support: %{public}d", action);
191                 break;
192         }
193     };
194     PostTaskToUI(task, "ArkUITextFieldHandleFunctionKey");
195 }
196 
MoveCursor(MiscServices::Direction direction)197 void OnTextChangedListenerImpl::MoveCursor(MiscServices::Direction direction)
198 {
199     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "move cursor direction %{public}d", static_cast<int32_t>(direction));
200     auto task = [textField = pattern_, direction] {
201         auto client = textField.Upgrade();
202         CHECK_NULL_VOID(client);
203         ContainerScope scope(client->GetInstanceId());
204         client->ResetTouchAtLeftOffsetFlag();
205         switch (direction) {
206             case MiscServices::Direction::UP:
207                 client->CursorMove(CaretMoveIntent::Up);
208                 break;
209             case MiscServices::Direction::DOWN:
210                 client->CursorMove(CaretMoveIntent::Down);
211                 break;
212             case MiscServices::Direction::LEFT:
213                 client->CursorMove(CaretMoveIntent::Left);
214                 break;
215             case MiscServices::Direction::RIGHT:
216                 client->CursorMove(CaretMoveIntent::Right);
217                 break;
218             default:
219                 TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "direction is not support: %{public}d", direction);
220                 break;
221         }
222     };
223     PostTaskToUI(task, "ArkUITextFieldMoveCursor");
224 }
225 
HandleSetSelection(int32_t start,int32_t end)226 void OnTextChangedListenerImpl::HandleSetSelection(int32_t start, int32_t end)
227 {
228     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleSetSelection, start %{public}d, end %{public}d", start, end);
229     auto task = [textField = pattern_, start, end] {
230         auto client = textField.Upgrade();
231         if (!client) {
232             return;
233         }
234         ContainerScope scope(client->GetInstanceId());
235         client->HandleSetSelection(start, end);
236     };
237     PostTaskToUI(task, "ArkUITextFieldHandleSetSelection");
238 }
239 
HandleExtendAction(int32_t action)240 void OnTextChangedListenerImpl::HandleExtendAction(int32_t action)
241 {
242     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleExtendAction %{public}d", action);
243     auto task = [textField = pattern_, action] {
244         auto client = textField.Upgrade();
245         if (!client) {
246             return;
247         }
248         ContainerScope scope(client->GetInstanceId());
249         client->HandleExtendAction(action);
250     };
251     PostTaskToUI(task, "ArkUITextFieldHandleExtendAction");
252 }
253 
HandleSelect(int32_t keyCode,int32_t cursorMoveSkip)254 void OnTextChangedListenerImpl::HandleSelect(int32_t keyCode, int32_t cursorMoveSkip)
255 {
256     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleSelect, keycode %{public}d, cursor move skip %{public}d(ignored)",
257         keyCode, cursorMoveSkip);
258     auto task = [textField = pattern_, keyCode, cursorMoveSkip] {
259         auto client = textField.Upgrade();
260         if (!client) {
261             return;
262         }
263         CaretMoveIntent direction;
264         switch (static_cast<KeyCode>(keyCode)) {
265             case KeyCode::KEY_DPAD_LEFT:
266                 direction = CaretMoveIntent::Left;
267                 break;
268             case KeyCode::KEY_DPAD_RIGHT:
269                 direction = CaretMoveIntent::Right;
270                 break;
271             case KeyCode::KEY_DPAD_UP:
272                 direction = CaretMoveIntent::Up;
273                 break;
274             case KeyCode::KEY_DPAD_DOWN:
275                 direction = CaretMoveIntent::Down;
276                 break;
277             default:
278                 TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "keyCode is not support: %{public}d", keyCode);
279                 return;
280         }
281         ContainerScope scope(client->GetInstanceId());
282         client->HandleSelect(direction);
283     };
284     PostTaskToUI(task, "ArkUITextFieldHandleSelect");
285 }
286 
PostSyncTaskToUI(const std::function<void ()> & task,const std::string & name)287 void OnTextChangedListenerImpl::PostSyncTaskToUI(const std::function<void()>& task, const std::string& name)
288 {
289     CHECK_NULL_VOID(task);
290     ContainerScope scope(patternInstanceId_);
291     auto context = PipelineBase::GetCurrentContext();
292     CHECK_NULL_VOID(context);
293     auto taskExecutor = context->GetTaskExecutor();
294     CHECK_NULL_VOID(taskExecutor);
295     taskExecutor->PostSyncTask(task, TaskExecutor::TaskType::UI, name);
296 }
297 
PostTaskToUI(const std::function<void ()> & task,const std::string & name)298 void OnTextChangedListenerImpl::PostTaskToUI(const std::function<void()>& task, const std::string& name)
299 {
300     CHECK_NULL_VOID(task);
301     ContainerScope scope(patternInstanceId_);
302     auto context = PipelineBase::GetCurrentContext();
303     if (!context) {
304         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "When name:%{public}s PostTaskToUI, context is null", name.c_str());
305     }
306     CHECK_NULL_VOID(context);
307     auto taskExecutor = context->GetTaskExecutor();
308     CHECK_NULL_VOID(taskExecutor);
309     taskExecutor->PostTask(task, TaskExecutor::TaskType::UI, name);
310 }
311 
NotifyPanelStatusInfo(const MiscServices::PanelStatusInfo & info)312 void OnTextChangedListenerImpl::NotifyPanelStatusInfo(const MiscServices::PanelStatusInfo& info)
313 {
314     bool isHardKeyboardConnected = InputManager::IsKeyboardConnected();
315     MiscServices::PanelType panelType = info.panelInfo.panelType;
316     bool panelVisible = info.visible;
317     MiscServices::Trigger triggerFrom = info.trigger;
318     if (!isHardKeyboardConnected && panelType == MiscServices::PanelType::SOFT_KEYBOARD && !panelVisible) {
319         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "NotifyPanelStatusInfo soft keyboard is closed by user, trigger=%{public}d",
320             triggerFrom);
321         auto task = [textField = pattern_, triggerFrom] {
322             auto client = textField.Upgrade();
323             CHECK_NULL_VOID(client);
324             ContainerScope scope(client->GetInstanceId());
325             if (triggerFrom == MiscServices::Trigger::IME_APP) {
326                 client->NotifyKeyboardClosedByUser();
327             }
328             client->NotifyKeyboardClosed();
329             client->NotifyKeyboardHeight(0);
330         };
331         PostTaskToUI(task, "ArkUITextFieldKeyboardClosedByUser");
332     }
333     KeyBoardInfo keyboardInfo;
334     if (info.panelInfo.panelType == MiscServices::PanelType::SOFT_KEYBOARD) {
335         keyboardInfo.keyBoardType = KeyBoardType::SOFT_KEYBOARD;
336     } else if (info.panelInfo.panelType == MiscServices::PanelType::STATUS_BAR) {
337         keyboardInfo.keyBoardType = KeyBoardType::STATUS_BAR;
338     }
339     keyboardInfo.visible = info.visible;
340     auto task = [weak = pattern_, keyboardInfo, id = Container::CurrentId()] {
341         auto textClient = weak.Upgrade();
342         CHECK_NULL_VOID(textClient);
343         auto pattern = AceType::DynamicCast<Pattern>(textClient);
344         CHECK_NULL_VOID(pattern);
345         auto host = pattern->GetHost();
346         CHECK_NULL_VOID(host);
347         auto pipeline = host->GetContextRefPtr();
348         CHECK_NULL_VOID(pipeline);
349         ContainerScope scope(id);
350         auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
351         CHECK_NULL_VOID(textFieldManager);
352         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "NotifyPanelStatusInfo SetImeShow:%{public}d", keyboardInfo.visible);
353         textFieldManager->SetImeShow(keyboardInfo.visible);
354     };
355     PostTaskToUI(task, "ArkUITextFieldSetImeShow");
356 }
357 
AutoFillReceivePrivateCommand(const std::unordered_map<std::string,MiscServices::PrivateDataValue> & privateCommand,const WeakPtr<TextInputClient> & pattern)358 void OnTextChangedListenerImpl::AutoFillReceivePrivateCommand(
359     const std::unordered_map<std::string, MiscServices::PrivateDataValue>& privateCommand,
360     const WeakPtr<TextInputClient>& pattern)
361 {
362     auto patternPtr = pattern.Upgrade();
363     CHECK_NULL_VOID(patternPtr);
364     auto textFieldPattern = AceType::DynamicCast<TextFieldPattern>(patternPtr);
365     CHECK_NULL_VOID(textFieldPattern);
366     bool isPopup = false;
367     if (privateCommand.find(AUTO_FILL_PARAMS_USERNAME) != privateCommand.end()) {
368         auto userName = privateCommand.find(AUTO_FILL_PARAMS_USERNAME);
369         textFieldPattern->SetAutoFillUserName(std::get<std::string>(userName->second));
370         textFieldPattern->ProcessAutoFill(isPopup, true);
371         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "com.autofill.params.userName : %{private}s",
372             std::get<std::string>(userName->second).c_str());
373     } else if (privateCommand.find(AUTO_FILL_PARAMS_NEWPASSWORD) != privateCommand.end()) {
374         auto newPassword = privateCommand.find(AUTO_FILL_PARAMS_NEWPASSWORD);
375         textFieldPattern->SetAutoFillNewPassword(std::get<std::string>(newPassword->second));
376         textFieldPattern->ProcessAutoFill(isPopup, true, true);
377         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "com.autofill.params.newPassword : %{private}s",
378             std::get<std::string>(newPassword->second).c_str());
379     } else if (privateCommand.find(AUTO_FILL_PARAMS_OTHERACCOUNT) != privateCommand.end()) {
380         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "com.autofill.params.otherAccount");
381         textFieldPattern->SetAutoFillOtherAccount(true);
382         textFieldPattern->ProcessAutoFill(isPopup, true);
383     } else {
384         TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "invalid autofill data privateCommand");
385     }
386 }
387 
SetPreviewText(const std::u16string & text,const MiscServices::Range & range)388 int32_t OnTextChangedListenerImpl::SetPreviewText(const std::u16string &text, const MiscServices::Range &range)
389 {
390     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetPreviewText length :%{public}d in range (%{public}d, %{public}d)",
391         static_cast<int32_t>(text.length()), range.start, range.end);
392     int32_t ret = CheckPreviewTextParams(text, {range.start, range.end});
393     if (ret != MiscServices::ErrorCode::NO_ERROR) {
394         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetPreviewText result is %{public}d}", ret);
395         return ret;
396     }
397     auto task = [textFieldPattern = pattern_, text, range] {
398         ACE_SCOPED_TRACE("SetPreviewText");
399         auto client = textFieldPattern.Upgrade();
400         CHECK_NULL_VOID(client);
401         ContainerScope scope(client->GetInstanceId());
402         client->SetPreviewText(StringUtils::Str16ToStr8(text), {range.start, range.end});
403     };
404     PostTaskToUI(task, "ArkUITextFieldSetPreviewText");
405     return ret;
406 }
407 
FinishTextPreview()408 void OnTextChangedListenerImpl::FinishTextPreview()
409 {
410     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "FinishTextPreview");
411     auto task = [textFieldPattern = pattern_] {
412         ACE_SCOPED_TRACE("FinishTextPreview");
413         auto client = textFieldPattern.Upgrade();
414         CHECK_NULL_VOID(client);
415         ContainerScope scope(client->GetInstanceId());
416         client->FinishTextPreview();
417     };
418     PostTaskToUI(task, "ArkUITextFieldFinishTextPreview");
419 }
420 
ReceivePrivateCommand(const std::unordered_map<std::string,MiscServices::PrivateDataValue> & privateCommand)421 int32_t OnTextChangedListenerImpl::ReceivePrivateCommand(
422     const std::unordered_map<std::string, MiscServices::PrivateDataValue>& privateCommand)
423 {
424     auto uiTask = [textFieldPattern = pattern_, privateCommand] {
425         auto textInputClient = textFieldPattern.Upgrade();
426         CHECK_NULL_VOID(textInputClient);
427         ContainerScope scope(textInputClient->GetInstanceId());
428         OnTextChangedListenerImpl::AutoFillReceivePrivateCommand(privateCommand, textFieldPattern);
429     };
430     PostTaskToUI(uiTask, "ArkUITextFieldAutoFillReceivePrivateCommand");
431 
432     int32_t ret = MiscServices::ErrorCode::NO_ERROR;
433     if (privateCommand.empty()) {
434         return ret;
435     }
436     for (const auto& item : privateCommand) {
437         if (item.first != PRIVATE_DATA_KEY) {
438             continue;
439         }
440         size_t idx = item.second.index();
441         if (idx != static_cast<size_t>(MiscServices::PrivateDataValueType::VALUE_TYPE_STRING)) {
442             continue;
443         }
444         auto stringValue = std::get_if<std::string>(&item.second);
445         if (stringValue != nullptr) {
446             std::string style = *stringValue;
447             auto task = [textFieldPattern = pattern_, style] {
448                 ACE_SCOPED_TRACE("ReceivePrivateCommand");
449                 auto client = textFieldPattern.Upgrade();
450                 CHECK_NULL_VOID(client);
451                 ContainerScope scope(client->GetInstanceId());
452                 client->ReceivePreviewTextStyle(style);
453             };
454             PostTaskToUI(task, "ArkUITextFieldReceivePrivateCommand");
455             ret = MiscServices::ErrorCode::NO_ERROR;
456         }
457     }
458     return ret;
459 }
460 
CheckPreviewTextParams(const std::u16string & text,const MiscServices::Range & range)461 int32_t OnTextChangedListenerImpl::CheckPreviewTextParams(const std::u16string &text, const MiscServices::Range &range)
462 {
463     int32_t ret = MiscServices::ErrorCode::NO_ERROR;
464     auto task = [textFieldPattern = pattern_, text, range, &ret] {
465         ACE_SCOPED_TRACE("SetPreviewText");
466         auto client = textFieldPattern.Upgrade();
467         CHECK_NULL_VOID(client);
468         ContainerScope scope(client->GetInstanceId());
469         ret = client->CheckPreviewTextValidate(StringUtils::Str16ToStr8(text), {range.start, range.end});
470     };
471     PostSyncTaskToUI(task, "ArkUICheckPreviewTextParams");
472     return ret;
473 }
474 
OnDetach()475 void OnTextChangedListenerImpl::OnDetach()
476 {
477     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "OnDetach");
478     auto pipeline = PipelineContext::GetCurrentContextSafely();
479     CHECK_NULL_VOID(pipeline);
480     auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
481     CHECK_NULL_VOID(textFieldManager);
482     textFieldManager->SetIsImeAttached(false);
483 }
484 } // namespace OHOS::Ace::NG
485