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