• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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/text_field_pattern.h"
17 
18 #include <algorithm>
19 #include <atomic>
20 #include <cstdint>
21 #include <optional>
22 #include <ratio>
23 #include <regex>
24 #include <string>
25 #include <utility>
26 #include "base/geometry/dimension.h"
27 #include "base/log/event_report.h"
28 #include "base/memory/type_info_base.h"
29 #include "base/utils/utf_helper.h"
30 #include "core/common/ime/constant.h"
31 #include "core/components/common/properties/text_style.h"
32 #include "core/components_ng/pattern/text/text_layout_property.h"
33 #include "core/components_ng/pattern/text_field/text_component_decorator.h"
34 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
35 #include "core/components_ng/property/layout_constraint.h"
36 #include "core/pipeline/pipeline_base.h"
37 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
38 #include "base/i18n/localization.h"
39 #include "base/log/dump_log.h"
40 #include "base/log/log_wrapper.h"
41 #include "base/memory/referenced.h"
42 #include "base/utils/string_utils.h"
43 #include "base/utils/utils.h"
44 #include "core/common/clipboard/clipboard_proxy.h"
45 #include "core/common/container_scope.h"
46 #include "core/common/font_manager.h"
47 #include "core/common/ime/input_method_manager.h"
48 #include "core/common/ime/text_edit_controller.h"
49 #include "core/common/ime/text_input_client.h"
50 #include "core/common/ime/text_input_connection.h"
51 #include "core/common/ime/text_input_formatter.h"
52 #include "core/common/ime/text_input_type.h"
53 #include "core/common/ime/text_selection.h"
54 #include "core/common/recorder/event_recorder.h"
55 #include "core/common/recorder/node_data_cache.h"
56 #include "core/common/stylus/stylus_detector_mgr.h"
57 #include "core/common/vibrator/vibrator_utils.h"
58 #include "core/components/common/layout/constants.h"
59 #include "core/components/text_field/textfield_theme.h"
60 #include "core/components/theme/icon_theme.h"
61 #include "core/components_ng/base/inspector_filter.h"
62 #include "core/components_ng/event/focus_hub.h"
63 #include "core/components_ng/image_provider/image_loading_context.h"
64 #include "core/components_ng/layout/layout_property.h"
65 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
66 #include "core/components_ng/pattern/overlay/modal_style.h"
67 #include "core/components_ng/pattern/stage/page_pattern.h"
68 #include "core/components_ng/pattern/search/search_event_hub.h"
69 #include "core/components_ng/pattern/search/search_pattern.h"
70 #include "core/components_ng/pattern/stage/page_pattern.h"
71 #include "core/components_ng/pattern/text/span/span_string.h"
72 #include "core/components_ng/pattern/text/text_pattern.h"
73 #include "core/components_ng/pattern/text_field/text_field_manager.h"
74 #include "core/components_ng/pattern/text_field/text_field_paint_property.h"
75 #include "core/text/text_emoji_processor.h"
76 #ifndef ACE_UNITTEST
77 #ifdef ENABLE_STANDARD_INPUT
78 #include "parameters.h"
79 
80 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
81 #endif
82 #endif
83 #include "core/common/udmf/udmf_client.h"
84 #ifdef WINDOW_SCENE_SUPPORTED
85 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
86 #endif
87 
88 namespace OHOS::Ace::NG {
89 namespace {
90 constexpr int32_t PREVIEW_TEXT_RANGE_DEFAULT = -1;
91 const std::string DROP_TYPE_STYLED_STRING = "ApplicationDefinedType";
92 } // namespace
93 
OnAttachToFrameNodeMultiThread()94 void TextFieldPattern::OnAttachToFrameNodeMultiThread()
95 {
96     // nothing, thread unsafe
97 }
98 
OnDetachFromFrameNodeMultiThread(FrameNode * node)99 void TextFieldPattern::OnDetachFromFrameNodeMultiThread(FrameNode* node)
100 {
101     // nothing, thread unsafe
102 }
103 
OnAttachToMainTreeMultiThread()104 void TextFieldPattern::OnAttachToMainTreeMultiThread()
105 {
106     auto host = GetHost();
107     CHECK_NULL_VOID(host);
108 
109     StylusDetectorMgr::GetInstance()->AddTextFieldFrameNode(host, WeakClaim(this));
110 
111     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
112     CHECK_NULL_VOID(layoutProperty);
113     layoutProperty->UpdateCopyOptions(CopyOptions::Local);
114     auto pipeline = host->GetContext();
115     CHECK_NULL_VOID(pipeline);
116     auto fontManager = pipeline->GetFontManager();
117     if (fontManager) {
118         auto host = GetHost();
119         fontManager->AddFontNodeNG(host);
120     }
121     auto onTextSelectorChange = [weak = WeakClaim(this)]() {
122         auto pattern = weak.Upgrade();
123         CHECK_NULL_VOID(pattern);
124         auto host = pattern->GetHost();
125         CHECK_NULL_VOID(host);
126         host->OnAccessibilityEvent(AccessibilityEventType::TEXT_SELECTION_UPDATE);
127     };
128     selectController_->SetOnAccessibility(std::move(onTextSelectorChange));
129     isDetachFromMainTree_ = false;
130     auto autoFillContainerNode = host->GetFirstAutoFillContainerNode();
131     CHECK_NULL_VOID(autoFillContainerNode);
132     firstAutoFillContainerNode_ = WeakClaim(RawPtr(autoFillContainerNode));
133     AddTextFieldInfo();
134     OnAttachToMainTreeMultiThreadAddition();
135 }
136 
OnAttachToMainTreeMultiThreadAddition()137 void TextFieldPattern::OnAttachToMainTreeMultiThreadAddition()
138 {
139     auto host = GetHost();
140     CHECK_NULL_VOID(host);
141 
142     if (initSurfacePositionChangedCallbackMultiThread_) {
143         initSurfacePositionChangedCallbackMultiThread_ = false;
144         InitSurfacePositionChangedCallbackMultiThreadAction();
145     }
146     if (initSurfaceChangedCallbackMultiThread_) {
147         initSurfaceChangedCallbackMultiThread_ = false;
148         InitSurfaceChangedCallbackMultiThreadAction();
149     }
150     if (registerWindowSizeCallbackMultiThread_) {
151         registerWindowSizeCallbackMultiThread_ = false;
152         RegisterWindowSizeCallbackMultiThreadAction();
153     }
154     if (processDefaultStyleAndBehaviorsMultiThread_) {
155         processDefaultStyleAndBehaviorsMultiThread_ = false;
156         ProcessDefaultStyleAndBehaviorsMultiThread();
157     }
158     MultiThreadDelayedExecution(); // Delayed operation
159 }
160 
OnDetachFromMainTreeMultiThread()161 void TextFieldPattern::OnDetachFromMainTreeMultiThread()
162 {
163     auto host = GetHost();
164     CHECK_NULL_VOID(host);
165     FrameNode* node = RawPtr(host);
166     CHECK_NULL_VOID(node);
167     isDetachFromMainTree_ = true;
168     RemoveTextFieldInfo();
169     RemoveFillContentMap();
170     if (selectOverlay_) {
171         CloseSelectOverlay();
172     }
173     auto pipeline = GetContext();
174     CHECK_NULL_VOID(pipeline);
175     if (HasSurfaceChangedCallback()) {
176         pipeline->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
177     }
178     if (HasSurfacePositionChangedCallback()) {
179         pipeline->UnregisterSurfacePositionChangedCallback(surfacePositionChangedCallbackId_.value_or(-1));
180     }
181     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
182     if (textFieldManager) {
183         textFieldManager->ClearOnFocusTextField(node->GetId());
184     }
185     auto frameNode = WeakClaim(node);
186     pipeline->RemoveFontNodeNG(frameNode);
187     auto fontManager = pipeline->GetFontManager();
188     if (fontManager) {
189         fontManager->UnRegisterCallbackNG(frameNode);
190         fontManager->RemoveVariationNodeNG(frameNode);
191     }
192     pipeline->RemoveWindowSizeChangeCallback(node->GetId());
193     pipeline->RemoveOnAreaChangeNode(node->GetId());
194 }
195 
HandleSetSelectionMultiThread(int32_t start,int32_t end,bool showHandle)196 void TextFieldPattern::HandleSetSelectionMultiThread(int32_t start, int32_t end, bool showHandle)
197 {
198     auto host = GetHost();
199     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleSetSelection %{public}d, %{public}d, showOverlay:%{public}d", start, end,
200         showHandle);
201     StopTwinkling();
202     UpdateSelection(start, end);
203     if (showHandle) {
204         ProcessOverlay();
205     } else {
206         CloseSelectOverlay();
207     }
208     updateCaretInfoToControllerMultiThread_ = true;
209     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
210 }
211 
MultiThreadDelayedExecution()212 void TextFieldPattern::MultiThreadDelayedExecution()
213 {
214     if (setShowKeyBoardOnFocusMultiThread_) {
215         setShowKeyBoardOnFocusMultiThread_ = false;
216         if (setShowKeyBoardOnFocusMultiThreadValue_) {
217             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SHOW_KEYBOARD_ON_FOCUS);
218         } else {
219             CloseKeyboard(true, false);
220         }
221     }
222     if (setSelectionFlagMultiThread_) {
223         setSelectionFlagMultiThread_ = false;
224         if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SET_SELECTION)) {
225             NotifyOnEditChanged(true);
226         }
227         TriggerAvoidWhenCaretGoesDown();
228     }
229     if (updateCaretInfoToControllerMultiThread_) {
230         updateCaretInfoToControllerMultiThread_ = false;
231         UpdateCaretInfoToController();
232     }
233     if (startTwinklingMultiThread_) {
234         startTwinklingMultiThread_ = false;
235         StartTwinkling();
236     }
237     if (stopEditingMultiThread_) {
238         stopEditingMultiThread_ = false;
239         StopEditingMultiThreadAction();
240     }
241     if (triggerAvoidOnCaretChangeMultiThread_) {
242         triggerAvoidOnCaretChangeMultiThread_ = false;
243         TriggerAvoidOnCaretChange();
244     }
245     if (handleCountStyleMultiThread_) {
246         handleCountStyleMultiThread_ = false;
247         HandleCountStyle();
248     }
249     if (setCustomKeyboardWithNodeMultiThread_) {
250         setCustomKeyboardWithNodeMultiThread_ = false;
251         SetCustomKeyboardWithNodeMultiThreadAction(setCustomKeyboardWithNodeMultiThreadValue_);
252         setCustomKeyboardWithNodeMultiThreadValue_.Reset();
253     }
254     if (moveCaretToContentRectMultiThread_) {
255         moveCaretToContentRectMultiThread_ = false;
256         MoveCaretToContentRectMultiThread(moveCaretToContentRectMultiThreadValue_);
257     }
258 }
259 
InitSurfaceChangedCallbackMultiThread()260 void TextFieldPattern::InitSurfaceChangedCallbackMultiThread()
261 {
262     initSurfaceChangedCallbackMultiThread_ = true;
263 }
264 
InitSurfaceChangedCallbackMultiThreadAction()265 void TextFieldPattern::InitSurfaceChangedCallbackMultiThreadAction()
266 {
267     auto host = GetHost();
268     CHECK_NULL_VOID(host);
269     auto pipeline = host->GetContext();
270     CHECK_NULL_VOID(pipeline);
271     if (!HasSurfaceChangedCallback()) {
272         auto callbackId = pipeline->RegisterSurfaceChangedCallback(
273             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
274                 WindowSizeChangeReason type) {
275                 auto pattern = weak.Upgrade();
276                 if (pattern) {
277                     pattern->HandleSurfaceChanged(newWidth, newHeight, prevWidth, prevHeight);
278                 }
279             });
280         UpdateSurfaceChangedCallbackId(callbackId);
281     }
282 }
283 
InitSurfacePositionChangedCallbackMultiThread()284 void TextFieldPattern::InitSurfacePositionChangedCallbackMultiThread()
285 {
286     initSurfacePositionChangedCallbackMultiThread_ = true;
287 }
288 
InitSurfacePositionChangedCallbackMultiThreadAction()289 void TextFieldPattern::InitSurfacePositionChangedCallbackMultiThreadAction()
290 {
291     auto host = GetHost();
292     CHECK_NULL_VOID(host);
293     auto pipeline = host->GetContext();
294     CHECK_NULL_VOID(pipeline);
295     if (!HasSurfacePositionChangedCallback()) {
296         auto callbackId =
297             pipeline->RegisterSurfacePositionChangedCallback([weak = WeakClaim(this)](int32_t posX, int32_t posY) {
298                 auto pattern = weak.Upgrade();
299                 if (pattern) {
300                     pattern->HandleSurfacePositionChanged(posX, posY);
301                 }
302             });
303         UpdateSurfacePositionChangedCallbackId(callbackId);
304     }
305 }
306 
SetCaretPositionMultiThread(int32_t position,bool moveContent)307 void TextFieldPattern::SetCaretPositionMultiThread(int32_t position, bool moveContent)
308 {
309     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Set caret position to %{public}d", position);
310     moveCaretToContentRectMultiThread_ = true;
311     moveCaretToContentRectMultiThreadValue_ = {
312         .index = position,
313         .textAffinity = TextAffinity::DOWNSTREAM,
314         .isEditorValueChanged = true,
315         .moveContent = moveContent
316     };
317     updateCaretInfoToControllerMultiThread_ = true;
318     if (HasFocus() && !magnifierController_->GetShowMagnifier()) {
319         startTwinklingMultiThread_ = true;
320     }
321     CloseSelectOverlay();
322     CancelDelayProcessOverlay();
323     triggerAvoidOnCaretChangeMultiThread_ = true;
324     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
325 }
326 
MoveCaretToContentRectMultiThread(const MoveCaretToContentRectData & value)327 void TextFieldPattern::MoveCaretToContentRectMultiThread(const MoveCaretToContentRectData& value)
328 {
329     selectController_->MoveCaretToContentRect(
330         value.index, value.textAffinity, value.isEditorValueChanged, value.moveContent);
331 }
332 
SetSelectionFlagMultiThread(int32_t selectionStart,int32_t selectionEnd,const std::optional<SelectionOptions> & options,bool isForward)333 void TextFieldPattern::SetSelectionFlagMultiThread(
334     int32_t selectionStart, int32_t selectionEnd, const std::optional<SelectionOptions>& options, bool isForward)
335 {
336     auto host = GetHost();
337     CHECK_NULL_VOID(host);
338     if (!HasFocus() || GetIsPreviewText()) {
339         return;
340     }
341     auto length = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
342     selectionStart = std::clamp(selectionStart, 0, length);
343     selectionEnd = std::clamp(selectionEnd, 0, length);
344     moveCaretState_.isTouchCaret = false;
345     bool isShowMenu = selectOverlay_->IsCurrentMenuVisibile();
346     isTouchPreviewText_ = false;
347     if (selectionStart == selectionEnd) {
348         moveCaretToContentRectMultiThread_ = true;
349         moveCaretToContentRectMultiThreadValue_ = {
350             .index = selectionEnd,
351             .textAffinity = TextAffinity::DOWNSTREAM,
352         };
353         startTwinklingMultiThread_ = true;
354     } else {
355         cursorVisible_ = false;
356         showSelect_ = true;
357         HandleSetSelection(selectionStart, selectionEnd, false);
358         if (isForward) {
359             selectController_->MoveSecondHandleToContentRect(selectionEnd);
360             selectController_->MoveFirstHandleToContentRect(selectionStart, false);
361         } else {
362             selectController_->MoveFirstHandleToContentRect(selectionStart);
363             selectController_->MoveSecondHandleToContentRect(selectionEnd);
364         }
365     }
366 
367     SetIsSingleHandle(!IsSelected());
368     if (!IsShowHandle()) {
369         CloseSelectOverlay(true);
370     } else {
371         isShowMenu = IsShowMenu(options, isShowMenu);
372         if (!isShowMenu && IsUsingMouse()) {
373             CloseSelectOverlay();
374         } else {
375             ProcessOverlay({ .menuIsShow = isShowMenu, .animation = true });
376         }
377     }
378     setSelectionFlagMultiThread_ = true;
379     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
380 }
381 
StopEditingMultiThread()382 void TextFieldPattern::StopEditingMultiThread()
383 {
384     if (!HasFocus()) {
385         return;
386     }
387     stopEditingMultiThread_ = true;
388 }
389 
StopEditingMultiThreadAction()390 void TextFieldPattern::StopEditingMultiThreadAction()
391 {
392     auto host = GetHost();
393     CHECK_NULL_VOID(host);
394     ContainerScope scope(host->GetInstanceId());
395     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Stop Editing", host->GetId());
396     FocusHub::LostFocusToViewRoot();
397     UpdateSelection(selectController_->GetCaretIndex());
398     StopTwinkling();
399     CloseKeyboard(true);
400     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
401 }
402 
RegisterWindowSizeCallbackMultiThread()403 void TextFieldPattern::RegisterWindowSizeCallbackMultiThread()
404 {
405     auto host = GetHost();
406     CHECK_NULL_VOID(host);
407     if (isOritationListenerRegisted_) {
408         return;
409     }
410     isOritationListenerRegisted_ = true;
411     registerWindowSizeCallbackMultiThread_ = true;
412 }
413 
RegisterWindowSizeCallbackMultiThreadAction()414 void TextFieldPattern::RegisterWindowSizeCallbackMultiThreadAction()
415 {
416     auto host = GetHost();
417     CHECK_NULL_VOID(host);
418     auto pipeline = host->GetContext();
419     CHECK_NULL_VOID(pipeline);
420     pipeline->AddWindowSizeChangeCallback(host->GetId());
421 }
422 
SetPreviewTextOperationMultiThread(PreviewTextInfo info)423 void TextFieldPattern::SetPreviewTextOperationMultiThread(PreviewTextInfo info)
424 {
425     auto host = GetHost();
426     CHECK_NULL_VOID(host);
427     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
428     CHECK_NULL_VOID(layoutProperty);
429     if (!hasPreviewText_) {
430         auto fullStr = GetTextUtf16Value();
431         if (host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWENTY) && IsSelected()) {
432             uint32_t startIndex = static_cast<uint32_t>(selectController_->GetStartIndex());
433             uint32_t endIndex = static_cast<uint32_t>(selectController_->GetEndIndex());
434             if (startIndex < fullStr.length() && endIndex <= fullStr.length()) {
435                 fullStr.erase(startIndex, endIndex - startIndex);
436             }
437         }
438         bodyTextInPreivewing_ = fullStr;
439     }
440     auto rangeStart = info.range.start;
441     auto rangeEnd = info.range.end;
442     auto start = GetPreviewTextStart();
443     auto end = GetPreviewTextEnd();
444     if (IsSelected()) {
445         start = selectController_->GetStartIndex();
446         end = selectController_->GetEndIndex();
447     } else {
448         start = (rangeStart == PREVIEW_TEXT_RANGE_DEFAULT) ? start : rangeStart;
449         end = (rangeEnd == PREVIEW_TEXT_RANGE_DEFAULT) ? end : rangeEnd;
450     }
451 
452     SetPreviewTextOperationMultiThreadPart(info, start, end);
453 
454     if (HasFocus()) {
455         cursorVisible_ = true;
456         startTwinklingMultiThread_ = true;
457     } else {
458         cursorVisible_ = false;
459         StopTwinkling();
460     }
461 }
462 
SetPreviewTextOperationMultiThreadPart(PreviewTextInfo info,int32_t start,int32_t end)463 void TextFieldPattern::SetPreviewTextOperationMultiThreadPart(PreviewTextInfo info, int32_t start, int32_t end)
464 {
465     auto host = GetHost();
466     CHECK_NULL_VOID(host);
467     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
468     CHECK_NULL_VOID(layoutProperty);
469     auto oldHasPreviewText = hasPreviewText_;
470     ChangeValueInfo changeValueInfo;
471     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
472     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
473     changeValueInfo.oldContent = GetBodyTextValue();
474     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
475     changeValueInfo.rangeAfter = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
476     auto originCaretIndex =
477             TextRange { changeValueInfo.oldPreviewText.offset, changeValueInfo.oldPreviewText.offset };
478     auto originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
479     contentController_->ReplaceSelectedValue(start, end, info.text);
480     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) -
481         originLength);
482 
483     int32_t delta =
484             static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength - (end - start);
485     int32_t newCaretPosition = std::max(end, GetPreviewTextEnd()) + delta;
486     newCaretPosition = std::clamp(newCaretPosition, 0,
487         static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
488     selectController_->UpdateCaretIndex(start + caretMoveLength);
489 
490     UpdatePreviewIndex(start, newCaretPosition);
491     hasPreviewText_ = true;
492     changeValueInfo.value = GetBodyTextValue();
493     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
494     changeValueInfo.previewText.value = GetPreviewTextValue();
495     bool isWillChange = FireOnWillChange(changeValueInfo);
496     if (!isWillChange && !info.isIme) {
497         RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
498         hasPreviewText_ = oldHasPreviewText;
499         return;
500     }
501 }
502 
FinishTextPreviewOperationMultiThread(bool triggerOnWillChange)503 void TextFieldPattern::FinishTextPreviewOperationMultiThread(bool triggerOnWillChange)
504 {
505     auto host = GetHost();
506     CHECK_NULL_VOID(host);
507     if (!hasPreviewText_) {
508         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "input state now is not at previewing text");
509         return;
510     }
511     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
512     CHECK_NULL_VOID(layoutProperty);
513 
514     if (layoutProperty->HasMaxLength()) {
515         int32_t len = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
516         showCountBorderStyle_ = len >
517             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
518         handleCountStyleMultiThread_ = true;
519     }
520 
521     FinishTextPreviewOperationMultiThreadPart(triggerOnWillChange);
522 
523     if (HasFocus()) {
524         cursorVisible_ = true;
525         StartTwinkling();
526     } else {
527         cursorVisible_ = false;
528         StopTwinkling();
529     }
530 
531     bodyTextInPreivewing_ = u"";
532     previewTextStart_ = PREVIEW_TEXT_RANGE_DEFAULT;
533     previewTextEnd_ = PREVIEW_TEXT_RANGE_DEFAULT;
534 
535     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
536 }
537 
FinishTextPreviewOperationMultiThreadPart(bool triggerOnWillChange)538 void TextFieldPattern::FinishTextPreviewOperationMultiThreadPart(bool triggerOnWillChange)
539 {
540     auto oldValue = contentController_->GetTextUtf16Value();
541     auto originCaretIndex =
542             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
543     ChangeValueInfo changeValueInfo;
544     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
545     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
546     changeValueInfo.oldContent = GetBodyTextValue();
547     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
548     auto start = GetPreviewTextStart();
549     auto end = GetPreviewTextEnd();
550     auto previewValue = GetPreviewTextValue();
551     hasPreviewText_ = false;
552 
553     auto originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
554     contentController_->ReplaceSelectedValue(start, end, previewValue);
555     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) -
556         originLength);
557     selectController_->UpdateCaretIndex(start + caretMoveLength);
558     UpdateEditingValueToRecord();
559     changeValueInfo.rangeAfter =
560         TextRange { changeValueInfo.oldPreviewText.offset, start + caretMoveLength };
561     changeValueInfo.value = GetBodyTextValue();
562     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
563     changeValueInfo.previewText.value = GetPreviewTextValue();
564     bool isWillChange = true;
565     if (triggerOnWillChange) {
566         isWillChange = FireOnWillChange(changeValueInfo);
567     }
568     if (!isWillChange) {
569         RecoverTextValueAndCaret(oldValue, originCaretIndex);
570         return;
571     }
572 }
573 
SetShowKeyBoardOnFocusMultiThread(bool value)574 void TextFieldPattern::SetShowKeyBoardOnFocusMultiThread(bool value)
575 {
576     if (showKeyBoardOnFocus_ == value) {
577         return;
578     }
579     showKeyBoardOnFocus_ = value;
580 
581     if (!HasFocus()) {
582         return;
583     }
584 
585     setShowKeyBoardOnFocusMultiThread_ = true;
586     setShowKeyBoardOnFocusMultiThreadValue_ = value;
587 }
588 
SetCustomKeyboardWithNodeMultiThread(const RefPtr<UINode> & keyboardBuilder)589 void TextFieldPattern::SetCustomKeyboardWithNodeMultiThread(const RefPtr<UINode>& keyboardBuilder)
590 {
591     setCustomKeyboardWithNodeMultiThread_ = true;
592     setCustomKeyboardWithNodeMultiThreadValue_ = keyboardBuilder;
593 }
594 
SetCustomKeyboardWithNodeMultiThreadAction(const RefPtr<UINode> & keyboardBuilder)595 void TextFieldPattern::SetCustomKeyboardWithNodeMultiThreadAction(const RefPtr<UINode>& keyboardBuilder)
596 {
597     if (customKeyboard_ && isCustomKeyboardAttached_ && !keyboardBuilder) {
598         // close customKeyboard and request system keyboard
599         CloseCustomKeyboard();
600         customKeyboard_ = keyboardBuilder; // refresh current keyboard
601         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
602         StartTwinkling();
603         return;
604     }
605     if (!customKeyboard_ && keyboardBuilder) {
606         // close system keyboard and request custom keyboard
607 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
608         if (imeShown_) {
609             CloseKeyboard(true);
610             customKeyboard_ = keyboardBuilder; // refresh current keyboard
611             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
612             StartTwinkling();
613             return;
614         }
615 #endif
616     }
617     customKeyboard_ = keyboardBuilder;
618 }
619 
ProcessDefaultStyleAndBehaviors()620 void TextFieldPattern::ProcessDefaultStyleAndBehaviors()
621 {
622     processDefaultStyleAndBehaviorsMultiThread_ = true;
623 }
624 
ProcessDefaultStyleAndBehaviorsMultiThread()625 void TextFieldPattern::ProcessDefaultStyleAndBehaviorsMultiThread()
626 {
627     auto frameNode = GetHost();
628     CHECK_NULL_VOID(frameNode);
629     auto pipeline = frameNode->GetContext();
630     CHECK_NULL_VOID(pipeline);
631     auto themeManager = pipeline->GetThemeManager();
632     CHECK_NULL_VOID(themeManager);
633     auto textFieldTheme = themeManager->GetTheme<TextFieldTheme>();
634     CHECK_NULL_VOID(textFieldTheme);
635     auto textfieldPaintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
636     CHECK_NULL_VOID(textfieldPaintProperty);
637     std::set<std::string> allowDropSet({ DROP_TYPE_PLAIN_TEXT, DROP_TYPE_HYPERLINK, DROP_TYPE_STYLED_STRING });
638     frameNode->SetAllowDrop(allowDropSet);
639     textfieldPaintProperty->UpdatePressBgColor(textFieldTheme->GetPressColor());
640     textfieldPaintProperty->UpdateHoverBgColor(textFieldTheme->GetHoverColor());
641     auto renderContext = frameNode->GetRenderContext();
642     renderContext->UpdateBackgroundColor(textFieldTheme->GetBgColor());
643     auto radius = textFieldTheme->GetBorderRadius();
644     textfieldPaintProperty->UpdateCursorColor(textFieldTheme->GetCursorColor());
645     BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
646     renderContext->UpdateBorderRadius(borderRadius);
647     auto dragDropManager = pipeline->GetDragDropManager();
648     CHECK_NULL_VOID(dragDropManager);
649     dragDropManager->AddTextFieldDragFrameNode(frameNode->GetId(), AceType::WeakClaim(AceType::RawPtr(frameNode)));
650     PaddingProperty paddings;
651     auto themePadding = textFieldTheme->GetPadding();
652     paddings.top = NG::CalcLength(themePadding.Top().ConvertToPx());
653     paddings.bottom = NG::CalcLength(themePadding.Bottom().ConvertToPx());
654     paddings.left = NG::CalcLength(themePadding.Left().ConvertToPx());
655     paddings.right = NG::CalcLength(themePadding.Right().ConvertToPx());
656     auto layoutProperty = frameNode->GetLayoutProperty<LayoutProperty>();
657     layoutProperty->UpdatePadding(paddings);
658     if (frameNode->IsFirstBuilding()) {
659         auto draggable = pipeline->GetDraggable<TextFieldTheme>();
660         frameNode->SetDraggable(draggable);
661         auto gestureHub = frameNode->GetOrCreateGestureEventHub();
662         CHECK_NULL_VOID(gestureHub);
663         gestureHub->SetTextDraggable(true);
664     }
665 }
666 } // namespace OHOS::Ace::NG
667