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