• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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/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/select/select_pattern.h"
33 #include "core/components_ng/pattern/text/text_layout_property.h"
34 #include "core/components_ng/pattern/text_field/text_component_decorator.h"
35 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
36 #include "core/components_ng/property/layout_constraint.h"
37 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
38 
39 #include "base/i18n/localization.h"
40 #include "base/log/dump_log.h"
41 #include "base/log/log_wrapper.h"
42 #include "base/memory/referenced.h"
43 #include "base/utils/string_utils.h"
44 #include "base/utils/utils.h"
45 #include "core/common/clipboard/clipboard_proxy.h"
46 #include "core/common/container_scope.h"
47 #include "core/common/font_manager.h"
48 #include "core/common/ime/input_method_manager.h"
49 #include "core/common/ime/text_edit_controller.h"
50 #include "core/common/ime/text_input_client.h"
51 #include "core/common/ime/text_input_connection.h"
52 #include "core/common/ime/text_input_formatter.h"
53 #include "core/common/ime/text_input_type.h"
54 #include "core/common/ime/text_selection.h"
55 #include "core/common/recorder/event_recorder.h"
56 #include "core/common/recorder/node_data_cache.h"
57 #include "core/common/stylus/stylus_detector_mgr.h"
58 #include "core/common/vibrator/vibrator_utils.h"
59 #include "core/components/common/layout/constants.h"
60 #include "core/components/text_field/textfield_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/pattern/stage/page_pattern.h"
64 #include "core/components_ng/pattern/text/span/span_string.h"
65 #include "core/components_ng/pattern/text/text_pattern.h"
66 #include "core/components_ng/pattern/text_field/text_field_manager.h"
67 #include "core/components_ng/pattern/text_field/text_field_paint_property.h"
68 #include "core/text/text_emoji_processor.h"
69 #ifndef ACE_UNITTEST
70 #ifdef ENABLE_STANDARD_INPUT
71 #include "parameters.h"
72 
73 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
74 #endif
75 #endif
76 #include "core/common/udmf/udmf_client.h"
77 
78 #ifdef WINDOW_SCENE_SUPPORTED
79 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
80 #endif
81 namespace OHOS::Ace::NG {
82 namespace {
83 
84 const BorderRadiusProperty ZERO_BORDER_RADIUS_PROPERTY(0.0_vp);
85 // need to be moved to TextFieldTheme
86 constexpr Dimension BORDER_DEFAULT_WIDTH = 0.0_vp;
87 constexpr Dimension TYPING_UNDERLINE_WIDTH = 2.0_px;
88 constexpr Dimension OVER_COUNT_BORDER_WIDTH = 1.0_vp;
89 constexpr Dimension INLINE_BORDER_WIDTH = 2.0_vp;
90 constexpr Dimension ERROR_UNDERLINE_WIDTH = 2.0_px;
91 constexpr Dimension UNDERLINE_WIDTH = 1.0_px;
92 constexpr uint32_t INLINE_DEFAULT_VIEW_MAXLINE = 3;
93 constexpr Dimension SCROLL_BAR_MIN_HEIGHT = 4.0_vp;
94 constexpr float MINFONTSCALE = 0.85f;
95 constexpr float MAXFONTSCALE = 3.20f;
96 #if defined(ENABLE_STANDARD_INPUT)
97 constexpr Dimension AVOID_OFFSET = 24.0_vp;
98 #endif
99 constexpr Dimension DEFAULT_FONT = Dimension(16, DimensionUnit::FP);
100 constexpr int32_t ILLEGAL_VALUE = 0;
101 constexpr double VELOCITY = -1000;
102 constexpr double MASS = 1.0;
103 constexpr double STIFFNESS = 428.0;
104 constexpr double DAMPING = 10.0;
105 constexpr uint32_t TWINKLING_INTERVAL_MS = 500;
106 constexpr uint32_t RECORD_MAX_LENGTH = 20;
107 constexpr uint32_t OBSCURE_SHOW_TICKS = 1;
108 constexpr int32_t FIND_TEXT_ZERO_INDEX = 1;
109 constexpr char16_t OBSCURING_CHARACTER = u'•';
110 constexpr char16_t OBSCURING_CHARACTER_FOR_AR = u'*';
111 const std::string NEWLINE = "\n";
112 const std::wstring WIDE_NEWLINE = StringUtils::ToWstring(NEWLINE);
113 const std::string INSPECTOR_PREFIX = "__SearchField__";
114 const std::string ERRORNODE_PREFIX = "ErrorNodeField__";
115 const OffsetF DEFAULT_NEGATIVE_CARET_OFFSET {-1.0f, -1.0f};
116 constexpr Dimension FLOATING_CARET_SHOW_ORIGIN_CARET_DISTANCE = 10.0_vp;
117 #if defined(ENABLE_STANDARD_INPUT)
118 constexpr int32_t AUTO_FILL_CANCEL = 2;
119 #endif
120 
121 // need to be moved to formatter
122 const std::string DIGIT_WHITE_LIST = "[0-9]";
123 const std::string PHONE_WHITE_LIST = "[\\d\\-\\+\\*\\#]+";
124 const std::string EMAIL_WHITE_LIST = "[\\w.\\@]";
125 const std::string URL_WHITE_LIST = "[a-zA-z]+://[^\\s]*";
126 const std::string SHOW_PASSWORD_SVG = "SYS_SHOW_PASSWORD_SVG";
127 const std::string HIDE_PASSWORD_SVG = "SYS_HIDE_PASSWORD_SVG";
128 const std::string AUTO_FILL_PARAMS_USERNAME = "com.autofill.params.userName";
129 const std::string AUTO_FILL_PARAMS_NEWPASSWORD = "com.autofill.params.newPassword";
130 constexpr int32_t MAX_FILL_CONTENT_SIZE = 5;
131 constexpr int32_t DEFAULT_MODE = -1;
132 constexpr int32_t PREVIEW_TEXT_RANGE_DEFAULT = -1;
133 const std::string PREVIEW_STYLE_NORMAL = "normal";
134 const std::string PREVIEW_STYLE_UNDERLINE = "underline";
135 
136 constexpr int32_t PREVIEW_NO_ERROR = 0;
137 constexpr int32_t PREVIEW_NULL_POINTER = 1;
138 constexpr int32_t PREVIEW_BAD_PARAMETERS = -1;
139 constexpr double MINIMAL_OFFSET = 0.01f;
140 constexpr int32_t KEYBOARD_DEFAULT_API = 9;
141 constexpr float RICH_DEFAULT_SHADOW_COLOR = 0x33000000;
142 constexpr float RICH_DEFAULT_ELEVATION = 120.0f;
143 constexpr float TIME_UNIT = 1000.0f;
144 constexpr float MAX_DRAG_SCROLL_SPEED = 2400.0f;
145 constexpr Dimension AUTO_SCROLL_HOT_ZONE_HEIGHT = 58.0_vp;
146 constexpr Dimension AUTO_SCROLL_HOT_ZONE_WIDTH = 26.0_vp;
147 constexpr float AUTO_SCROLL_HOT_AREA_LONGPRESS_DURATION = 80.0f;
148 constexpr Dimension AUTO_SCROLL_HOT_AREA_LONGPRESS_DISTANCE = 5.0_vp;
149 constexpr Dimension MOUSE_SCROLL_BAR_REGION_WIDTH = 8.0_vp;
150 constexpr int32_t HOVER_ANIMATION_DURATION = 250;
151 const RefPtr<Curve> MOVE_MAGNIFIER_CURVE =
152     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 228.0f, 30.0f);
153 constexpr int32_t LAND_DURATION = 100;
154 
155 static std::unordered_map<AceAutoFillType, TextInputType> keyBoardMap_ = {
156     { AceAutoFillType::ACE_PASSWORD, TextInputType::VISIBLE_PASSWORD},
157     { AceAutoFillType::ACE_USER_NAME, TextInputType::USER_NAME },
158     { AceAutoFillType::ACE_NEW_PASSWORD, TextInputType::NEW_PASSWORD },
159     { AceAutoFillType::ACE_FULL_STREET_ADDRESS, TextInputType::TEXT },
160     { AceAutoFillType::ACE_HOUSE_NUMBER, TextInputType::TEXT },
161     { AceAutoFillType::ACE_DISTRICT_ADDRESS, TextInputType::TEXT },
162     { AceAutoFillType::ACE_CITY_ADDRESS, TextInputType::TEXT },
163     { AceAutoFillType::ACE_PROVINCE_ADDRESS, TextInputType::TEXT },
164     { AceAutoFillType::ACE_COUNTRY_ADDRESS, TextInputType::TEXT },
165     { AceAutoFillType::ACE_PERSON_FULL_NAME, TextInputType::TEXT },
166     { AceAutoFillType::ACE_PERSON_LAST_NAME, TextInputType::TEXT },
167     { AceAutoFillType::ACE_PERSON_FIRST_NAME, TextInputType::TEXT },
168     { AceAutoFillType::ACE_PHONE_NUMBER, TextInputType::PHONE },
169     { AceAutoFillType::ACE_PHONE_COUNTRY_CODE, TextInputType::PHONE },
170     { AceAutoFillType::ACE_FULL_PHONE_NUMBER, TextInputType::PHONE },
171     { AceAutoFillType::ACE_EMAIL_ADDRESS, TextInputType::EMAIL_ADDRESS },
172     { AceAutoFillType::ACE_BANK_CARD_NUMBER, TextInputType::NUMBER },
173     { AceAutoFillType::ACE_ID_CARD_NUMBER, TextInputType::NUMBER },
174     { AceAutoFillType::ACE_PRECISE_TIME, TextInputType::NUMBER },
175     { AceAutoFillType::ACE_HOUR_AND_MINUTE, TextInputType::NUMBER },
176     { AceAutoFillType::ACE_DATE, TextInputType::NUMBER },
177     { AceAutoFillType::ACE_MONTH, TextInputType::NUMBER },
178     { AceAutoFillType::ACE_YEAR, TextInputType::NUMBER },
179     { AceAutoFillType::ACE_NICKNAME, TextInputType::TEXT },
180     { AceAutoFillType::ACE_DETAIL_INFO_WITHOUT_STREET, TextInputType::TEXT },
181     { AceAutoFillType::ACE_FORMAT_ADDRESS, TextInputType::TEXT },
182     { AceAutoFillType::ACE_PASSPORT_NUMBER, TextInputType::TEXT },
183     { AceAutoFillType::ACE_VALIDITY, TextInputType::TEXT },
184     { AceAutoFillType::ACE_ISSUE_AT, TextInputType::TEXT },
185     { AceAutoFillType::ACE_ORGANIZATION, TextInputType::TEXT },
186     { AceAutoFillType::ACE_TAX_ID, TextInputType::TEXT },
187     { AceAutoFillType::ACE_ADDRESS_CITY_AND_STATE, TextInputType::TEXT },
188     { AceAutoFillType::ACE_FLIGHT_NUMBER, TextInputType::TEXT },
189     { AceAutoFillType::ACE_LICENSE_NUMBER, TextInputType::TEXT },
190     { AceAutoFillType::ACE_LICENSE_FILE_NUMBER, TextInputType::TEXT },
191     { AceAutoFillType::ACE_LICENSE_PLATE, TextInputType::TEXT },
192     { AceAutoFillType::ACE_ENGINE_NUMBER, TextInputType::TEXT },
193     { AceAutoFillType::ACE_LICENSE_CHASSIS_NUMBER, TextInputType::TEXT }};
194 
195 static std::unordered_map<TextContentType, std::pair<AceAutoFillType, std::string>> contentTypeMap_ = {
196     {TextContentType::VISIBLE_PASSWORD,
197         std::make_pair(AceAutoFillType::ACE_PASSWORD, "TextContentType.VISIBLE_PASSWORD")},
198     {TextContentType::USER_NAME, std::make_pair(AceAutoFillType::ACE_USER_NAME, "TextContentType.USER_NAME")},
199     {TextContentType::NEW_PASSWORD, std::make_pair(AceAutoFillType::ACE_NEW_PASSWORD, "TextContentType.NEW_PASSWORD")},
200     {TextContentType::FULL_STREET_ADDRESS,
201         std::make_pair(AceAutoFillType::ACE_FULL_STREET_ADDRESS, "TextContentType.FULL_STREET_ADDRESS")},
202     {TextContentType::HOUSE_NUMBER, std::make_pair(AceAutoFillType::ACE_HOUSE_NUMBER, "TextContentType.HOUSE_NUMBER")},
203     {TextContentType::DISTRICT_ADDRESS,
204         std::make_pair(AceAutoFillType::ACE_DISTRICT_ADDRESS, "TextContentType.DISTRICT_ADDRESS")},
205     {TextContentType::CITY_ADDRESS, std::make_pair(AceAutoFillType::ACE_CITY_ADDRESS, "TextContentType.CITY_ADDRESS")},
206     {TextContentType::PROVINCE_ADDRESS,
207         std::make_pair(AceAutoFillType::ACE_PROVINCE_ADDRESS, "TextContentType.PROVINCE_ADDRESS")},
208     {TextContentType::COUNTRY_ADDRESS,
209         std::make_pair(AceAutoFillType::ACE_COUNTRY_ADDRESS, "TextContentType.COUNTRY_ADDRESS")},
210     {TextContentType::PERSON_FULL_NAME,
211         std::make_pair(AceAutoFillType::ACE_PERSON_FULL_NAME, "TextContentType.PERSON_FULL_NAME")},
212     {TextContentType::PERSON_LAST_NAME,
213         std::make_pair(AceAutoFillType::ACE_PERSON_LAST_NAME, "TextContentType.PERSON_LAST_NAME")},
214     {TextContentType::PERSON_FIRST_NAME,
215         std::make_pair(AceAutoFillType::ACE_PERSON_FIRST_NAME, "TextContentType.PERSON_FIRST_NAME")},
216     {TextContentType::PHONE_NUMBER, std::make_pair(AceAutoFillType::ACE_PHONE_NUMBER, "TextContentType.PHONE_NUMBER")},
217     {TextContentType::PHONE_COUNTRY_CODE,
218         std::make_pair(AceAutoFillType::ACE_PHONE_COUNTRY_CODE, "TextContentType.PHONE_COUNTRY_CODE")},
219     {TextContentType::FULL_PHONE_NUMBER,
220         std::make_pair(AceAutoFillType::ACE_FULL_PHONE_NUMBER, "TextContentType.FULL_PHONE_NUMBER")},
221     {TextContentType::EMAIL_ADDRESS,
222         std::make_pair(AceAutoFillType::ACE_EMAIL_ADDRESS, "TextContentType.EMAIL_ADDRESS")},
223     {TextContentType::BANK_CARD_NUMBER,
224         std::make_pair(AceAutoFillType::ACE_BANK_CARD_NUMBER, "TextContentType.BANK_CARD_NUMBER")},
225     {TextContentType::ID_CARD_NUMBER,
226         std::make_pair(AceAutoFillType::ACE_ID_CARD_NUMBER, "TextContentType.ID_CARD_NUMBER")},
227     {TextContentType::PRECISE_TIME, std::make_pair(AceAutoFillType::ACE_PRECISE_TIME, "TextContentType.PRECISE_TIME")},
228     {TextContentType::HOUR_AND_MINUTE,
229         std::make_pair(AceAutoFillType::ACE_HOUR_AND_MINUTE, "TextContentType.HOUR_AND_MINUTE")},
230     {TextContentType::DATE, std::make_pair(AceAutoFillType::ACE_DATE, "TextContentType.DATE")},
231     {TextContentType::MONTH, std::make_pair(AceAutoFillType::ACE_MONTH, "TextContentType.MONTH")},
232     {TextContentType::YEAR, std::make_pair(AceAutoFillType::ACE_YEAR, "TextContentType.YEAR")},
233     {TextContentType::NICKNAME, std::make_pair(AceAutoFillType::ACE_NICKNAME, "TextContentType.NICKNAME")},
234     {TextContentType::DETAIL_INFO_WITHOUT_STREET,
235         std::make_pair(AceAutoFillType::ACE_DETAIL_INFO_WITHOUT_STREET, "TextContentType.DETAIL_INFO_WITHOUT_STREET")},
236     {TextContentType::FORMAT_ADDRESS,
237         std::make_pair(AceAutoFillType::ACE_FORMAT_ADDRESS, "TextContentType.FORMAT_ADDRESS")},
238     {TextContentType::PASSPORT_NUMBER,
239         std::make_pair(AceAutoFillType::ACE_PASSPORT_NUMBER, "TextContentType.PASSPORT_NUMBER")},
240     {TextContentType::VALIDITY,
241         std::make_pair(AceAutoFillType::ACE_VALIDITY, "TextContentType.VALIDITY")},
242     {TextContentType::ISSUE_AT,
243         std::make_pair(AceAutoFillType::ACE_ISSUE_AT, "TextContentType.ISSUE_AT")},
244     {TextContentType::ORGANIZATION,
245         std::make_pair(AceAutoFillType::ACE_ORGANIZATION, "TextContentType.ORGANIZATION")},
246     {TextContentType::TAX_ID,
247         std::make_pair(AceAutoFillType::ACE_TAX_ID, "TextContentType.TAX_ID")},
248     {TextContentType::ADDRESS_CITY_AND_STATE,
249         std::make_pair(AceAutoFillType::ACE_ADDRESS_CITY_AND_STATE, "TextContentType.ADDRESS_CITY_AND_STATE")},
250     {TextContentType::FLIGHT_NUMBER,
251         std::make_pair(AceAutoFillType::ACE_FLIGHT_NUMBER, "TextContentType.FLIGHT_NUMBER")},
252     {TextContentType::LICENSE_NUMBER,
253         std::make_pair(AceAutoFillType::ACE_LICENSE_NUMBER, "TextContentType.LICENSE_NUMBER")},
254     {TextContentType::LICENSE_FILE_NUMBER,
255         std::make_pair(AceAutoFillType::ACE_LICENSE_FILE_NUMBER, "TextContentType.LICENSE_FILE_NUMBER")},
256     {TextContentType::LICENSE_PLATE,
257         std::make_pair(AceAutoFillType::ACE_LICENSE_PLATE, "TextContentType.LICENSE_PLATE")},
258     {TextContentType::ENGINE_NUMBER,
259         std::make_pair(AceAutoFillType::ACE_ENGINE_NUMBER, "TextContentType.ENGINE_NUMBER")},
260     {TextContentType::LICENSE_CHASSIS_NUMBER,
261         std::make_pair(AceAutoFillType::ACE_LICENSE_CHASSIS_NUMBER, "TextContentType.LICENSE_CHASSIS_NUMBER")},
262     {TextContentType::UNSPECIFIED, std::make_pair(AceAutoFillType::ACE_UNSPECIFIED, "TextContentType.UNSPECIFIED")}};
263 
SwapIfLarger(int32_t & a,int32_t & b)264 void SwapIfLarger(int32_t& a, int32_t& b)
265 {
266     if (a > b) {
267         std::swap(a, b);
268     }
269 }
270 
ConvertFontFamily(const std::vector<std::string> & fontFamily)271 std::string ConvertFontFamily(const std::vector<std::string>& fontFamily)
272 {
273     std::string result;
274     for (const auto& item : fontFamily) {
275         result += item;
276         result += ",";
277     }
278     result = result.substr(0, static_cast<int32_t>(result.length()) - 1);
279     return result;
280 }
281 
282 } // namespace
283 
OnAttachContext(PipelineContext * context)284 void TextFieldPattern::OnAttachContext(PipelineContext* context)
285 {
286     CHECK_NULL_VOID(context);
287     SetInstanceId(context->GetInstanceId());
288 }
289 
OnDetachContext(PipelineContext * context)290 void TextFieldPattern::OnDetachContext(PipelineContext* context)
291 {
292     SetInstanceId(INSTANCE_ID_UNDEFINED);
293 }
294 
CreateNodePaintMethod()295 RefPtr<NodePaintMethod> TextFieldPattern::CreateNodePaintMethod()
296 {
297     if (!textFieldContentModifier_) {
298         textFieldContentModifier_ = AceType::MakeRefPtr<TextFieldContentModifier>(WeakClaim(this));
299     }
300     auto textFieldOverlayModifier = AceType::DynamicCast<TextFieldOverlayModifier>(GetScrollBarOverlayModifier());
301     if (!textFieldOverlayModifier) {
302         textFieldOverlayModifier_ =
303             AceType::MakeRefPtr<TextFieldOverlayModifier>(WeakClaim(this), GetScrollEdgeEffect());
304         SetScrollBarOverlayModifier(textFieldOverlayModifier_);
305     }
306     if (!textFieldForegroundModifier_) {
307         textFieldForegroundModifier_ = AceType::MakeRefPtr<TextFieldForegroundModifier>(WeakClaim(this));
308     }
309     if (isCustomFont_) {
310         textFieldContentModifier_->SetIsCustomFont(true);
311     }
312     auto paint = AceType::MakeRefPtr<TextFieldPaintMethod>(
313         WeakClaim(this), textFieldOverlayModifier_, textFieldContentModifier_, textFieldForegroundModifier_);
314     auto scrollBar = GetScrollBar();
315     if (scrollBar) {
316         paint->SetScrollBar(scrollBar);
317         if (scrollBar->NeedPaint()) {
318             textFieldOverlayModifier_->SetRect(scrollBar->GetActiveRect());
319         } else if (!HasFocus()) {
320             auto scrollRect = scrollBar->GetActiveRect();
321             CalcScrollRect(scrollRect);
322             textFieldOverlayModifier_->SetRect(scrollRect);
323             textFieldOverlayModifier_->SetOpacity(0);
324         }
325     }
326     CalculateBoundsRect();
327     return paint;
328 }
329 
CalculateBoundsRect()330 void TextFieldPattern::CalculateBoundsRect()
331 {
332     auto host = GetHost();
333     CHECK_NULL_VOID(host);
334     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
335     CHECK_NULL_VOID(layoutProperty);
336 
337     auto geometryNode = host->GetGeometryNode();
338     auto frameOffset = geometryNode->GetFrameOffset();
339     auto frameSize = geometryNode->GetFrameSize();
340     bool isShowCount = IsShowCount() && !IsTextArea();
341     bool isShowError = layoutProperty->GetShowErrorTextValue(false) && errorDecorator_;
342     if (isShowCount && isShowError) {
343         auto textWidth = std::max(errorDecorator_ ? errorDecorator_->GetContentWidth() : 0.0f, frameSize.Width());
344         auto errorHeight = errorDecorator_? errorDecorator_->GetBoundHeight() : 0.0f;
345         auto countHeight = counterDecorator_? counterDecorator_->GetBoundHeight() : 0.0f;
346         auto bottomHeight = std::max(errorHeight, countHeight);
347         RectF boundsRect(0.0f, 0.0f, textWidth, bottomHeight + frameSize.Height());
348         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
349         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
350     } else if (isShowCount) {
351         auto countHeight = counterDecorator_? counterDecorator_->GetBoundHeight() : 0.0f;
352         RectF boundsRect(0.0f, 0.0f, frameSize.Width(), countHeight + frameSize.Height());
353         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
354         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
355     } else if (isShowError) {
356         auto textWidth = std::max(errorDecorator_ ? errorDecorator_->GetContentWidth() : 0.0f, frameSize.Width());
357         auto errorHeight = errorDecorator_? errorDecorator_->GetBoundHeight() : 0.0f;
358         RectF boundsRect(0.0f, 0.0f, textWidth, errorHeight + frameSize.Height());
359         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
360         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
361     } else {
362         if (NearEqual(maxFrameOffsetY_, 0.0f) && NearEqual(maxFrameHeight_, 0.0f)) {
363             maxFrameOffsetY_ = frameOffset.GetY();
364             maxFrameHeight_ = frameSize.Height();
365         }
366         maxFrameOffsetY_ = LessOrEqual(frameOffset.GetY(), maxFrameOffsetY_) ? frameOffset.GetY()
367                                                                              : maxFrameOffsetY_ - frameOffset.GetY();
368         maxFrameHeight_ = LessOrEqual(frameSize.Height(), maxFrameHeight_) ? maxFrameHeight_ : frameSize.Height();
369         RectF boundsRect(0.0f, 0.0f, frameSize.Width(), maxFrameHeight_ + UNDERLINE_WIDTH.ConvertToPx());
370         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
371         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
372     }
373 }
374 
CalcScrollRect(Rect & inlineScrollRect)375 void TextFieldPattern::CalcScrollRect(Rect& inlineScrollRect)
376 {
377     if (!IsNormalInlineState()) {
378         // if textfield is not inline, no need to calc rect
379         return;
380     }
381     auto host = GetHost();
382     CHECK_NULL_VOID(host);
383     auto pipeline = host->GetContext();
384     CHECK_NULL_VOID(pipeline);
385     auto scrollBar = GetScrollBar();
386     CHECK_NULL_VOID(scrollBar);
387     Size size(frameRect_.Width(), inlineMeasureItem_.inlineSizeHeight);
388     auto positionMode_ = scrollBar->GetPositionMode();
389     double mainSize = (positionMode_ == PositionMode::BOTTOM ? size.Width() : size.Height());
390     auto barRegionSize = mainSize;
391     double estimatedHeight = inlineMeasureItem_.inlineContentRectHeight;
392     if (NearZero(estimatedHeight) || NearZero(estimatedHeight - mainSize)) {
393         return;
394     }
395     double activeSize = barRegionSize * mainSize / estimatedHeight - scrollBar->GetOutBoundary();
396     auto offsetScale = 0.0f;
397     if (NearEqual(mainSize, estimatedHeight)) {
398         offsetScale = 0.0;
399     } else {
400         offsetScale = (barRegionSize - activeSize) / (estimatedHeight - mainSize);
401     }
402     double lastMainOffset = std::max(
403         static_cast<double>(std::max(inlineMeasureItem_.inlineLastOffsetY, contentRect_.GetY() - textRect_.GetY())),
404         0.0);
405     double activeMainOffset = std::min(offsetScale * lastMainOffset, barRegionSize - activeSize);
406     inlineScrollRect.SetLeft(inlineScrollRect.GetOffset().GetX() - inlineMeasureItem_.inlineScrollRectOffsetX);
407     inlineScrollRect.SetTop(activeMainOffset);
408     inlineScrollRect.SetHeight(activeSize);
409 }
410 
CreateObscuredText(int32_t len)411 std::u16string TextFieldPattern::CreateObscuredText(int32_t len)
412 {
413     std::u16string obscuredText;
414     if (Localization::GetInstance()->GetLanguage() == "ar") { // ar is the abbreviation of Arabic.
415         obscuredText = std::u16string(len, OBSCURING_CHARACTER_FOR_AR);
416     } else {
417         obscuredText = std::u16string(len, OBSCURING_CHARACTER);
418     }
419     return obscuredText;
420 }
421 
CreateDisplayText(const std::u16string & content,int32_t nakedCharPosition,bool needObscureText,bool showPasswordDirectly)422 std::u16string TextFieldPattern::CreateDisplayText(
423     const std::u16string& content, int32_t nakedCharPosition, bool needObscureText, bool showPasswordDirectly)
424 {
425     if (!content.empty() && needObscureText) {
426         auto text =
427             TextFieldPattern::CreateObscuredText(static_cast<int32_t>(content.length()));
428         if (nakedCharPosition >= 0 && nakedCharPosition < static_cast<int32_t>(content.length())) {
429             if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE) || !showPasswordDirectly) {
430                 text[nakedCharPosition] = content[nakedCharPosition];
431             }
432         }
433         return text;
434     }
435     return content;
436 }
437 
GetTextOrPlaceHolderFontSize()438 float TextFieldPattern::GetTextOrPlaceHolderFontSize()
439 {
440     auto tmpHost = GetHost();
441     CHECK_NULL_RETURN(tmpHost, 0.0f);
442     auto textFieldLayoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
443     CHECK_NULL_RETURN(textFieldLayoutProperty, 0.0f);
444     auto textFieldTheme = GetTheme();
445     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
446     Dimension fontSize;
447     if (textFieldLayoutProperty->HasFontSize() &&
448         textFieldLayoutProperty->GetFontSizeValue(Dimension()).IsNonNegative()) {
449         fontSize = textFieldLayoutProperty->GetFontSizeValue(Dimension());
450     } else {
451         return textFieldTheme ? static_cast<float>(textFieldTheme->GetFontSize().ConvertToPx())
452                               : static_cast<float>(DEFAULT_FONT.ConvertToPx());
453     }
454     return std::min(static_cast<float>(fontSize.ConvertToPx()), contentRect_.Height());
455 }
456 
TextFieldPattern()457 TextFieldPattern::TextFieldPattern() : twinklingInterval_(TWINKLING_INTERVAL_MS)
458 {
459     if (PipelineContext::GetCurrentContextSafelyWithCheck() &&
460         // for normal app add version protection, enable keyboard as default start from API 10 or higher
461         PipelineContext::GetCurrentContextSafelyWithCheck()->GetMinPlatformVersion() > KEYBOARD_DEFAULT_API) {
462         needToRequestKeyboardOnFocus_ = !GetIndependentControlKeyboard();
463     }
464     contentController_ = MakeRefPtr<ContentController>(WeakClaim(this));
465     selectController_ = MakeRefPtr<TextSelectController>(WeakClaim(this));
466     selectController_->InitContentController(contentController_);
467     magnifierController_ = MakeRefPtr<MagnifierController>(WeakClaim(this));
468     selectOverlay_ = MakeRefPtr<TextFieldSelectOverlay>(WeakClaim(this));
469     if (SystemProperties::GetDebugEnabled()) {
470         twinklingInterval_ = 3000; // 3000 : for AtuoUITest
471     }
472     ResetOriginCaretPosition();
473     callbackOldPreviewText_.offset = -1;
474 }
475 
GetIndependentControlKeyboard()476 bool TextFieldPattern::GetIndependentControlKeyboard()
477 {
478     auto context = PipelineContext::GetCurrentContextSafelyWithCheck();
479     CHECK_NULL_RETURN(context, false);
480     auto theme = context->GetTheme<TextFieldTheme>();
481     CHECK_NULL_RETURN(theme, false);
482     independentControlKeyboard_ = theme->GetIndependentControlKeyboard();
483     return independentControlKeyboard_;
484 }
485 
~TextFieldPattern()486 TextFieldPattern::~TextFieldPattern()
487 {
488     if (textEditingController_) {
489         textEditingController_->Clear();
490         textEditingController_->RemoveObserver(WeakClaim(this));
491     }
492     CloseSelectOverlay();
493     if (isCustomKeyboardAttached_) {
494         CloseCustomKeyboard();
495     }
496     RemoveTextFieldInfo();
497 }
498 
CheckAndUpdateRecordBeforeOperation()499 void TextFieldPattern::CheckAndUpdateRecordBeforeOperation()
500 {
501     if (operationRecords_.size() == 0 ||
502         operationRecords_.back().caretPosition != selectController_->GetCaretIndex()) {
503         // record the state before the operation
504         // or caret position change
505         UpdateEditingValueToRecord();
506     }
507 }
508 
BeforeCreateLayoutWrapper()509 void TextFieldPattern::BeforeCreateLayoutWrapper()
510 {
511     while (!inputOperations_.empty()) {
512         auto operation = inputOperations_.front();
513         inputOperations_.pop();
514         CheckAndUpdateRecordBeforeOperation();
515         switch (operation) {
516             case InputOperation::INSERT: {
517                 ExecuteInsertValueCommand(insertCommands_.front());
518                 insertCommands_.pop();
519                 break;
520             }
521             case InputOperation::DELETE_BACKWARD: {
522                 DeleteBackwardOperation(deleteBackwardOperations_.front());
523                 deleteBackwardOperations_.pop();
524                 HandleDeleteOnCounterScene();
525                 break;
526             }
527             case InputOperation::DELETE_FORWARD: {
528                 DeleteForwardOperation(deleteForwardOperations_.front());
529                 deleteForwardOperations_.pop();
530                 HandleDeleteOnCounterScene();
531                 break;
532             }
533             case InputOperation::CURSOR_UP: {
534                 CursorMoveUpOperation();
535                 break;
536             }
537             case InputOperation::CURSOR_DOWN: {
538                 CursorMoveDownOperation();
539                 break;
540             }
541             case InputOperation::CURSOR_LEFT: {
542                 CursorMoveLeftOperation();
543                 break;
544             }
545             case InputOperation::CURSOR_RIGHT: {
546                 CursorMoveRightOperation();
547                 break;
548             }
549             case InputOperation::SET_PREVIEW_TEXT:
550                 SetPreviewTextOperation(previewTextOperation_.front());
551                 previewTextOperation_.pop();
552                 break;
553             case InputOperation::SET_PREVIEW_FINISH:
554                 FinishTextPreviewOperation();
555                 break;
556             case InputOperation::INPUT:
557                 ExecuteInputCommand(inputCommands_.front());
558                 inputCommands_.pop();
559                 break;
560         }
561     }
562     selectOverlay_->MarkOverlayDirty();
563 }
564 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)565 bool TextFieldPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
566 {
567     if (config.skipMeasure || dirty->SkipMeasureContent()) {
568         return false;
569     }
570     contentRect_ = dirty->GetGeometryNode()->GetContentRect();
571     frameRect_ = dirty->GetGeometryNode()->GetFrameRect();
572     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
573     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
574     auto textFieldLayoutAlgorithm = DynamicCast<TextFieldLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
575     CHECK_NULL_RETURN(textFieldLayoutAlgorithm, false);
576     auto paragraph = textFieldLayoutAlgorithm->GetParagraph();
577     float paragraphWidth = 0.0f;
578     if (paragraph) {
579         paragraph_ = paragraph;
580         paragraphWidth = std::max(paragraph->GetLongestLine(), 0.0f);
581     }
582     if (!IsDragging()) {
583         do {
584             if (!dragNode_) {
585                 break;
586             }
587             auto dragNodePattern = AceType::DynamicCast<TextDragPattern>(dragNode_->GetPattern());
588             if (!dragNodePattern) {
589                 break;
590             }
591             dragNodePattern->UpdateParagraph(paragraph_);
592         } while (false);
593     }
594     auto textRect = textFieldLayoutAlgorithm->GetTextRect();
595     auto isSameSizeMouseMenu = NearEqual(paragraphWidth, paragraphWidth_) &&
596                                     NearEqual(textRect.GetSize(), textRect_.GetSize()) && IsUsingMouse();
597     needToRefreshSelectOverlay_ = needToRefreshSelectOverlay_ && !isSameSizeMouseMenu;
598     paragraphWidth_ = paragraphWidth;
599     HandleContentSizeChange(textRect);
600     textRect_ = textRect;
601 
602     if (textFieldContentModifier_) {
603         textFieldContentModifier_->ContentChange();
604     }
605 
606     if (textFieldOverlayModifier_) {
607         textFieldOverlayModifier_->ContentChange();
608     }
609 
610     auto oldParentGlobalOffset = parentGlobalOffset_;
611     parentGlobalOffset_ = GetPaintRectGlobalOffset();
612     inlineMeasureItem_ = textFieldLayoutAlgorithm->GetInlineMeasureItem();
613     auto isEditorValueChanged = FireOnTextChangeEvent();
614     UpdateCancelNode();
615     UpdateSelectController();
616     AdjustTextInReasonableArea();
617     UpdateCaretRect(isEditorValueChanged);
618     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
619     UpdateCaretInfoToController();
620     auto hostLayoutProperty =
621         dirty->GetHostNode() ? dirty->GetHostNode()->GetLayoutProperty<TextFieldLayoutProperty>() : nullptr;
622     if (hostLayoutProperty) {
623         hostLayoutProperty->ResetTextAlignChanged();
624     }
625     ProcessOverlayAfterLayout(oldParentGlobalOffset);
626     if (inlineSelectAllFlag_) {
627         HandleOnSelectAll(false, true);
628         inlineSelectAllFlag_ = false;
629         showSelect_ = true;
630     }
631     if (needSelectAll_ && !isLongPress_) {
632         HandleOnSelectAll(false);
633         needSelectAll_ = false;
634     }
635     if (mouseStatus_ == MouseStatus::RELEASED) {
636         mouseStatus_ = MouseStatus::NONE;
637     }
638     StopScrollable();
639     CheckScrollable();
640     UpdateScrollBarOffset();
641     if (config.frameSizeChange) {
642         ScheduleDisappearDelayTask();
643     }
644     SetAccessibilityClearAction();
645     SetAccessibilityPasswordIconAction();
646     SetAccessibilityUnitAction();
647     if (afterDragSelect_) {
648         UpdateSelectionAndHandleVisibility();
649         afterDragSelect_ = false;
650     }
651     releaseInDrop_ = false;
652     textParagraphIndent_ = textFieldLayoutAlgorithm->GetTextIndent();
653     return true;
654 }
655 
UpdateSelectionAndHandleVisibility()656 void TextFieldPattern::UpdateSelectionAndHandleVisibility()
657 {
658     TextFieldRequestFocus(RequestFocusReason::DRAG_SELECT);
659     auto start = dragTextStart_;
660     auto end = dragTextEnd_;
661     if (isMouseOrTouchPad(sourceTool_) && releaseInDrop_) {
662         start = selectController_->GetCaretIndex()
663         - static_cast<int32_t>(contentController_->GetInsertValue().length());
664         end = selectController_->GetCaretIndex();
665     }
666     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "UpdateSelectionAndHandleVisibility range=[%{public}d--%{public}d]",
667         start, end);
668     UpdateSelection(start, end);
669     showSelect_ = true;
670 
671     if (!isMouseOrTouchPad(sourceTool_)) {
672         ProcessOverlay({ .menuIsShow = false });
673     }
674     auto host = GetHost();
675     CHECK_NULL_VOID(host);
676     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
677 }
678 
SetAccessibilityPasswordIconAction()679 void TextFieldPattern::SetAccessibilityPasswordIconAction()
680 {
681     CHECK_NULL_VOID(IsShowPasswordIcon());
682     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
683     CHECK_NULL_VOID(passwordArea);
684     auto node = passwordArea->GetFrameNode();
685     CHECK_NULL_VOID(node);
686     auto textAccessibilityProperty = node->GetAccessibilityProperty<AccessibilityProperty>();
687     CHECK_NULL_VOID(textAccessibilityProperty);
688     textAccessibilityProperty->SetAccessibilityLevel("yes");
689     textAccessibilityProperty->SetAccessibilityText(GetPasswordIconPromptInformation(passwordArea->IsObscured()));
690 }
691 
SetAccessibilityClearAction()692 void TextFieldPattern::SetAccessibilityClearAction()
693 {
694     CHECK_NULL_VOID(IsShowCancelButtonMode());
695     auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
696     CHECK_NULL_VOID(cleanNodeResponseArea);
697     auto stackNode = cleanNodeResponseArea->GetFrameNode();
698     CHECK_NULL_VOID(stackNode);
699     auto textAccessibilityProperty = stackNode->GetAccessibilityProperty<AccessibilityProperty>();
700     CHECK_NULL_VOID(textAccessibilityProperty);
701     textAccessibilityProperty->SetAccessibilityLevel("yes");
702     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
703     CHECK_NULL_VOID(layoutProperty);
704     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyleValue(CleanNodeStyle::INPUT);
705     auto hasContent = cleanNodeStyle == CleanNodeStyle::CONSTANT ||
706                         (cleanNodeStyle == CleanNodeStyle::INPUT && HasText());
707     textAccessibilityProperty->SetAccessibilityText(hasContent ? GetCancelImageText() : "");
708 }
709 
SetAccessibilityUnitAction()710 void TextFieldPattern::SetAccessibilityUnitAction()
711 {
712     if (!unitNode_ || !responseArea_) {
713         return;
714     }
715     auto unitNode = AceType::DynamicCast<FrameNode>(unitNode_);
716     CHECK_NULL_VOID(unitNode);
717     auto unitAccessibilityProperty = unitNode->GetAccessibilityProperty<AccessibilityProperty>();
718     CHECK_NULL_VOID(unitAccessibilityProperty);
719     unitAccessibilityProperty->SetAccessibilityLevel("yes");
720 }
721 
HandleContentSizeChange(const RectF & textRect)722 void TextFieldPattern::HandleContentSizeChange(const RectF& textRect)
723 {
724     if (textRect_ == textRect) {
725         return;
726     }
727     auto host = GetHost();
728     CHECK_NULL_VOID(host);
729     if (!NearEqual(textRect.Height(), textRect_.Height())) {
730         PlayScrollBarAppearAnimation();
731         ScheduleDisappearDelayTask();
732     }
733     auto eventHub = host->GetEventHub<TextFieldEventHub>();
734     CHECK_NULL_VOID(eventHub);
735     if (eventHub->GetOnContentSizeChange()) {
736         auto pipeline = host->GetContext();
737         CHECK_NULL_VOID(pipeline);
738         auto weak = WeakClaim(Referenced::RawPtr(eventHub));
739         pipeline->AddAfterLayoutTask([textRect, weak]() {
740             auto eventHub = weak.Upgrade();
741             CHECK_NULL_VOID(eventHub);
742             eventHub->FireOnContentSizeChange(std::max(0.0f, textRect.Width()), textRect.Height());
743         });
744     }
745 }
746 
ProcessOverlayAfterLayout(const OffsetF & prevOffset)747 void TextFieldPattern::ProcessOverlayAfterLayout(const OffsetF& prevOffset)
748 {
749     auto host = GetHost();
750     CHECK_NULL_VOID(host);
751     auto pipeline = host->GetContext();
752     CHECK_NULL_VOID(pipeline);
753     pipeline->AddAfterLayoutTask([weak = WeakClaim(this), prevOffset]() {
754         auto pattern = weak.Upgrade();
755         CHECK_NULL_VOID(pattern);
756         pattern->parentGlobalOffset_ = pattern->GetPaintRectGlobalOffset();
757         if (pattern->SelectOverlayIsOn()) {
758             if (pattern->IsSelected()) {
759                 pattern->selectOverlay_->UpdateAllHandlesOffset();
760             } else {
761                 pattern->selectOverlay_->UpdateSecondHandleOffset();
762             }
763         }
764         if (pattern->processOverlayDelayTask_) {
765             if (pattern->HasFocus()) {
766                 pattern->processOverlayDelayTask_();
767             }
768             pattern->processOverlayDelayTask_ = nullptr;
769         } else if (prevOffset != pattern->parentGlobalOffset_) {
770             pattern->HandleParentGlobalOffsetChange();
771         } else if (pattern->needToRefreshSelectOverlay_ && pattern->SelectOverlayIsOn()) {
772             if (pattern->IsSelected()) {
773                 pattern->StopTwinkling();
774             } else {
775                 pattern->StartTwinkling();
776             }
777             pattern->selectOverlay_->SetUsingMouse(pattern->selectOverlay_->IsShowMouseMenu());
778             pattern->ProcessOverlay({ .menuIsShow = pattern->selectOverlay_->IsCurrentMenuVisibile() });
779             pattern->selectOverlay_->SetUsingMouse(false);
780         }
781         pattern->needToRefreshSelectOverlay_ = false;
782     });
783 }
784 
HasFocus() const785 bool TextFieldPattern::HasFocus() const
786 {
787     auto focusHub = GetFocusHub();
788 
789     CHECK_NULL_RETURN(focusHub, false);
790     return focusHub->IsCurrentFocus();
791 }
792 
UpdateCaretInfoToController(bool forceUpdate)793 void TextFieldPattern::UpdateCaretInfoToController(bool forceUpdate)
794 {
795     CHECK_NULL_VOID(HasFocus());
796 #if defined(ENABLE_STANDARD_INPUT)
797     auto miscTextConfig = GetMiscTextConfig();
798     CHECK_NULL_VOID(miscTextConfig.has_value());
799     PreviewRange miscTextConfigRange {
800         miscTextConfig.value().range.start,
801         miscTextConfig.value().range.end
802     };
803     if (!forceUpdate && lastCursorRange_ == miscTextConfigRange &&
804         lastTextValue_ == contentController_->GetTextUtf16Value() &&
805         NearEqual(miscTextConfig.value().cursorInfo.top, lastCursorTop_)) {
806         return;
807     }
808     lastCursorRange_.Set(miscTextConfig.value().range.start, miscTextConfig.value().range.end);
809     lastTextValue_ = contentController_->GetTextUtf16Value();
810     lastCursorTop_ = miscTextConfig.value().cursorInfo.top;
811     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
812     MiscServices::InputMethodController::GetInstance()->OnCursorUpdate(cursorInfo);
813     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
814         contentController_->GetTextUtf16Value(), selectController_->GetStartIndex(),
815         selectController_->GetEndIndex());
816     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
817         "UpdateCaretInfoToController, left %{public}f, top %{public}f, width %{public}f, height %{public}f; "
818         "selectController_ start "
819         "%{public}d, end %{public}d",
820         cursorInfo.left, cursorInfo.top, cursorInfo.width, cursorInfo.height, selectController_->GetStartIndex(),
821         selectController_->GetEndIndex());
822 
823 #else
824     if (HasConnection()) {
825         TextEditingValue value;
826         value.text = contentController_->GetTextValue();
827         value.hint = UtfUtils::Str16DebugToStr8(GetPlaceHolder());
828         value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
829         connection_->SetEditingState(value, GetInstanceId());
830     }
831 #endif
832 }
833 
UpdateCaretRect(bool isEditorValueChanged)834 void TextFieldPattern::UpdateCaretRect(bool isEditorValueChanged)
835 {
836     auto focusHub = GetFocusHub();
837     if (IsSelected()) {
838         selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex(), false);
839         selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex(), false);
840         return;
841     }
842     if (focusHub && !focusHub->IsCurrentFocus() && !obscuredChange_) {
843         CloseSelectOverlay(true);
844         return;
845     }
846     selectController_->MoveCaretToContentRect(
847         selectController_->GetCaretIndex(), TextAffinity::DOWNSTREAM, isEditorValueChanged);
848 }
849 
AdjustTextInReasonableArea()850 void TextFieldPattern::AdjustTextInReasonableArea()
851 {
852     // Adjust y.
853     auto contentBottomBoundary = contentRect_.GetY() + contentRect_.GetSize().Height();
854     if (textRect_.Height() > contentRect_.Height()) {
855         if (textRect_.GetY() + textRect_.Height() < contentBottomBoundary) {
856             auto dy = contentBottomBoundary - textRect_.GetY() - textRect_.Height();
857             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
858         }
859         if (GreatNotEqual(textRect_.GetY(), contentRect_.GetY())) {
860             auto dy = textRect_.GetY() - contentRect_.GetY();
861             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() - dy));
862         }
863     } else {
864         if (textRect_.GetY() != contentRect_.GetY()) {
865             auto dy = contentRect_.GetY() - textRect_.GetY();
866             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
867         }
868     }
869 
870     // Adjust x.
871     auto contentRightBoundary = contentRect_.GetX() + contentRect_.GetSize().Width();
872     if (textRect_.Width() > contentRect_.Width()) {
873         if (textRect_.GetX() + textRect_.Width() < contentRightBoundary) {
874             auto dx = contentRightBoundary - textRect_.GetX() - textRect_.Width();
875             textRect_.SetLeft(textRect_.GetX() + dx);
876         }
877         if (GreatNotEqual(textRect_.GetX(), contentRect_.GetX())) {
878             auto dx = textRect_.GetX() - contentRect_.GetX();
879             textRect_.SetOffset(OffsetF(textRect_.GetX() - dx, textRect_.GetY()));
880         }
881     }
882 }
883 
IsTextArea() const884 bool TextFieldPattern::IsTextArea() const
885 {
886     auto tmpHost = GetHost();
887     CHECK_NULL_RETURN(tmpHost, false);
888     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
889     CHECK_NULL_RETURN(layoutProperty, true);
890     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(1) > 1 : true;
891 }
892 
UpdateSelectionOffset()893 void TextFieldPattern::UpdateSelectionOffset()
894 {
895     CHECK_NULL_VOID(IsSelected());
896     selectController_->CalculateHandleOffset();
897 }
898 
CalcCaretMetricsByPosition(int32_t extent,CaretMetricsF & caretCaretMetric,TextAffinity textAffinity)899 void TextFieldPattern::CalcCaretMetricsByPosition(
900     int32_t extent, CaretMetricsF& caretCaretMetric, TextAffinity textAffinity)
901 {
902     CHECK_NULL_VOID(paragraph_);
903     paragraph_->CalcCaretMetricsByPosition(extent, caretCaretMetric, textAffinity);
904     caretCaretMetric.offset.AddX(textRect_.GetX());
905     caretCaretMetric.offset.AddY(textRect_.GetY());
906 }
907 
CursorInContentRegion()908 bool TextFieldPattern::CursorInContentRegion()
909 {
910     if (IsTextArea()) {
911         return GreatOrEqual(selectController_->GetCaretRect().GetY(), contentRect_.GetY()) &&
912                LessOrEqual(selectController_->GetCaretRect().GetY() + GetTextOrPlaceHolderFontSize(),
913                    contentRect_.GetY() + contentRect_.Height());
914     }
915     auto theme = GetTheme();
916     CHECK_NULL_RETURN(theme, false);
917     return GreatOrEqual(selectController_->GetCaretRect().GetX(), contentRect_.GetX()) &&
918            LessOrEqual(selectController_->GetCaretRect().GetX() + theme->GetCursorWidth().ConvertToPx(),
919                contentRect_.GetX() + contentRect_.Width());
920 }
921 
OffsetInContentRegion(const Offset & offset)922 bool TextFieldPattern::OffsetInContentRegion(const Offset& offset)
923 {
924     // real content region will minus basic padding on left and right
925     return GreatOrEqual(offset.GetX(), contentRect_.GetX()) &&
926            LessOrEqual(offset.GetX(), contentRect_.GetX() + contentRect_.Width());
927 }
928 
CheckSelectAreaVisible()929 bool TextFieldPattern::CheckSelectAreaVisible()
930 {
931     auto tmpHost = GetHost();
932     CHECK_NULL_RETURN(tmpHost, false);
933     auto pipeline = tmpHost->GetContextRefPtr();
934     CHECK_NULL_RETURN(pipeline, false);
935     auto keyboardInset = pipeline->GetSafeAreaManager()->GetKeyboardInset();
936     auto selectArea = selectOverlay_->GetSelectArea();
937     auto globalOffset = GetPaintRectGlobalOffset();
938     auto globalContentRect = contentRect_;
939     globalContentRect.SetOffset(globalContentRect.GetOffset() + globalOffset);
940     if (selectArea.Bottom() < 0) {
941         return false;
942     } else if (!globalContentRect.IsInnerIntersectWith(selectArea)) {
943         return false;
944     } else if (keyboardInset.Length() > 0 && selectArea.Top() >= keyboardInset.start) {
945         return false;
946     }
947     return true;
948 }
949 
OnScrollEndCallback()950 void TextFieldPattern::OnScrollEndCallback()
951 {
952     ScheduleDisappearDelayTask();
953     if (!IsUsingMouse() && SelectOverlayIsOn() && isTextSelectionMenuShow_ && CheckSelectAreaVisible()) {
954         selectOverlay_->ShowMenu();
955     }
956 }
957 
OnTextAreaScroll(float offset)958 void TextFieldPattern::OnTextAreaScroll(float offset)
959 {
960     if (!IsTextArea() || textRect_.Height() <= contentRect_.Height()) {
961         return;
962     }
963     if (textRect_.GetY() + offset > contentRect_.GetY()) {
964         offset = contentRect_.GetY() - textRect_.GetY();
965     } else if (textRect_.GetY() + textRect_.Height() + offset < contentRect_.GetY() + contentRect_.Height()) {
966         offset = contentRect_.GetY() + contentRect_.Height() - textRect_.GetY() - textRect_.Height();
967     }
968     currentOffset_ = textRect_.GetY() + offset;
969     textRect_.SetOffset(OffsetF(textRect_.GetX(), currentOffset_));
970     UpdateHandlesOffsetOnScroll(offset);
971     UpdateScrollBarOffset();
972 }
973 
OnTextInputScroll(float offset)974 void TextFieldPattern::OnTextInputScroll(float offset)
975 {
976     if (IsTextArea() || textRect_.Width() <= contentRect_.Width()) {
977         return;
978     }
979     if (textRect_.GetX() + offset > contentRect_.GetX()) {
980         offset = contentRect_.GetX() - textRect_.GetX();
981     } else if (textRect_.GetX() + textRect_.Width() + offset < contentRect_.GetX() + contentRect_.Width()) {
982         offset = contentRect_.GetX() + contentRect_.Width() - textRect_.GetX() - textRect_.Width();
983     }
984     currentOffset_ = textRect_.GetX() + offset;
985     textRect_.SetOffset(OffsetF(currentOffset_, textRect_.GetY()));
986     UpdateHandlesOffsetOnScroll(offset);
987     auto tmpHost = GetHost();
988     CHECK_NULL_VOID(tmpHost);
989     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
990 }
991 
ConvertTouchOffsetToCaretPosition(const Offset & localOffset)992 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPosition(const Offset& localOffset)
993 {
994     CHECK_NULL_RETURN(paragraph_, 0);
995     int32_t caretPositionIndex = 0;
996     if (!contentController_->IsEmpty()) {
997         caretPositionIndex = paragraph_->GetGlyphIndexByCoordinate(localOffset);
998     }
999     return caretPositionIndex;
1000 }
1001 
ConvertTouchOffsetToCaretPositionNG(const Offset & localOffset)1002 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPositionNG(const Offset& localOffset)
1003 {
1004     CHECK_NULL_RETURN(paragraph_, 0);
1005     auto offset = localOffset - Offset(textRect_.GetX(), textRect_.GetY());
1006     return paragraph_->GetGlyphIndexByCoordinate(offset);
1007 }
1008 
1009 #if defined(IOS_PLATFORM)
GetGlobalOffset() const1010 Offset TextFieldPattern::GetGlobalOffset() const
1011 {
1012     Offset offset;
1013     auto host = GetHost();
1014     CHECK_NULL_RETURN(host, {});
1015     auto pipeline = host->GetContext();
1016     CHECK_NULL_RETURN(pipeline, {});
1017     auto rootOffset = pipeline->GetRootRect().GetOffset();
1018     auto globalOffset = host->GetPaintRectOffset(false, true) - rootOffset;
1019     offset = Offset(globalOffset.GetX(), globalOffset.GetY());
1020     return offset;
1021 }
1022 
GetEditingBoxY() const1023 double TextFieldPattern::GetEditingBoxY() const
1024 {
1025     return GetGlobalOffset().GetY() + frameRect_.Height();
1026 };
1027 
GetEditingBoxTopY() const1028 double TextFieldPattern::GetEditingBoxTopY() const
1029 {
1030     return GetGlobalOffset().GetY();
1031 };
1032 
GetEditingBoxModel() const1033 bool TextFieldPattern::GetEditingBoxModel() const
1034 {
1035     bool isDeclarative = false;
1036     auto host = GetHost();
1037     CHECK_NULL_RETURN(host, false);
1038     auto pipeline = host->GetContext();
1039     if (pipeline && pipeline->GetIsDeclarative()) {
1040         isDeclarative = true;
1041     }
1042     return isDeclarative;
1043 };
1044 #endif
1045 
HandleFocusEvent()1046 void TextFieldPattern::HandleFocusEvent()
1047 {
1048     isFocusedBeforeClick_ = true;
1049     focusIndex_ = FocuseIndex::TEXT;
1050     auto host = GetHost();
1051     CHECK_NULL_VOID(host);
1052     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d on focus", host->GetId());
1053     ACE_LAYOUT_SCOPED_TRACE("[TextField:%d] on focus", host->GetId());
1054     auto context = host->GetContextRefPtr();
1055     CHECK_NULL_VOID(context);
1056     context->AddOnAreaChangeNode(host->GetId());
1057     auto globalOffset = host->GetPaintRectOffset(false, true) - context->GetRootRect().GetOffset();
1058     UpdateTextFieldManager(Offset(globalOffset.GetX(), globalOffset.GetY()), frameRect_.Height());
1059     SetNeedToRequestKeyboardInner(!isLongPress_ && (dragRecipientStatus_ != DragStatus::DRAGGING) &&
1060         (dragStatus_ != DragStatus::DRAGGING) && !afterDragSelect_, RequestKeyboardInnerChangeReason::FOCUS);
1061     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
1062     CHECK_NULL_VOID(paintProperty);
1063     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1064     CHECK_NULL_VOID(layoutProperty);
1065     auto isSelectAll = layoutProperty->GetSelectAllValueValue(false);
1066     if (isSelectAll && !contentController_->IsEmpty()) {
1067         needSelectAll_ = !independentControlKeyboard_;
1068     }
1069     SetIsEnableSubWindowMenu();
1070     ProcessFocusStyle();
1071     ProcessAutoFillOnFocus();
1072     RequestKeyboardByFocusSwitch();
1073     ResetFirstClickAfterGetFocus();
1074     SetFocusStyle();
1075     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ?
1076         PROPERTY_UPDATE_MEASURE_SELF : PROPERTY_UPDATE_MEASURE);
1077 }
1078 
SetFocusStyle()1079 void TextFieldPattern::SetFocusStyle()
1080 {
1081     if (IsUnderlineMode() || IsInlineMode()) {
1082         return;
1083     }
1084     auto host = GetHost();
1085     CHECK_NULL_VOID(host);
1086     auto renderContext = host->GetRenderContext();
1087     CHECK_NULL_VOID(renderContext);
1088     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
1089     CHECK_NULL_VOID(paintProperty);
1090     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1091     CHECK_NULL_VOID(layoutProperty);
1092     auto textFieldTheme = GetTheme();
1093     CHECK_NULL_VOID(textFieldTheme);
1094 
1095     if (!paintProperty->HasBackgroundColor()) {
1096         auto defaultBGColor = textFieldTheme->GetBgColor();
1097         if (paintProperty->GetBackgroundColorValue(defaultBGColor) == defaultBGColor) {
1098             renderContext->UpdateBackgroundColor(textFieldTheme->GetFocusBgColor());
1099             isFocusBGColorSet_ = true;
1100         }
1101     }
1102     auto defaultTextColor = textFieldTheme->GetTextColor();
1103     if (layoutProperty->GetTextColorValue(defaultTextColor) == defaultTextColor) {
1104         layoutProperty->UpdateTextColor(textFieldTheme->GetFocusTextColor());
1105         isFocusTextColorSet_ = true;
1106     }
1107     auto defaultPlaceholderColor = textFieldTheme->GetPlaceholderColor();
1108     if (layoutProperty->GetPlaceholderTextColorValue(defaultPlaceholderColor) == defaultPlaceholderColor) {
1109         layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetFocusPlaceholderColor());
1110         isFocusPlaceholderColorSet_ = true;
1111     }
1112 }
1113 
ClearFocusStyle()1114 void TextFieldPattern::ClearFocusStyle()
1115 {
1116     auto host = GetHost();
1117     CHECK_NULL_VOID(host);
1118     auto renderContext = host->GetRenderContext();
1119     CHECK_NULL_VOID(renderContext);
1120     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
1121     CHECK_NULL_VOID(paintProperty);
1122     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1123     CHECK_NULL_VOID(layoutProperty);
1124     auto textFieldTheme = GetTheme();
1125     CHECK_NULL_VOID(textFieldTheme);
1126 
1127     if (isFocusBGColorSet_) {
1128         renderContext->UpdateBackgroundColor(textFieldTheme->GetBgColor());
1129         isFocusBGColorSet_ = false;
1130     }
1131     if (isFocusTextColorSet_) {
1132         layoutProperty->UpdateTextColor(textFieldTheme->GetTextColor());
1133         isFocusTextColorSet_ = false;
1134     }
1135     if (isFocusPlaceholderColorSet_) {
1136         layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetPlaceholderColor());
1137         isFocusPlaceholderColorSet_ = false;
1138     }
1139 }
1140 
ProcessAutoFillOnFocus()1141 void TextFieldPattern::ProcessAutoFillOnFocus()
1142 {
1143     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
1144         return;
1145     }
1146 
1147     auto isIgnoreFocusReason =
1148         requestFocusReason_ == RequestFocusReason::DRAG_ENTER || requestFocusReason_ == RequestFocusReason::DRAG_MOVE ||
1149         requestFocusReason_ == RequestFocusReason::DRAG_END || requestFocusReason_ == RequestFocusReason::AUTO_FILL ||
1150         requestFocusReason_ == RequestFocusReason::CLICK || requestFocusReason_ == RequestFocusReason::MOUSE ||
1151         requestFocusReason_ == RequestFocusReason::DRAG_SELECT;
1152     if (needToRequestKeyboardOnFocus_ && !isIgnoreFocusReason && !IsModalCovered() && IsTriggerAutoFillPassword()) {
1153         DoProcessAutoFill();
1154     }
1155 }
1156 
ProcessFocusStyle()1157 void TextFieldPattern::ProcessFocusStyle()
1158 {
1159     bool needTwinkling = true;
1160     if (IsNormalInlineState()) {
1161         ApplyInlineTheme();
1162         inlineFocusState_ = true;
1163         if (!contentController_->IsEmpty()) {
1164             inlineSelectAllFlag_ = (blurReason_ != BlurReason::WINDOW_BLUR &&
1165             requestFocusReason_ != RequestFocusReason::DRAG_SELECT);
1166             if (inlineSelectAllFlag_) {
1167                 needTwinkling = false;
1168             }
1169         }
1170         ProcessResponseArea();
1171     }
1172     if (needTwinkling) {
1173         StartTwinkling();
1174     }
1175     NotifyOnEditChanged(true);
1176     if (!IsShowError() && IsUnderlineMode()) {
1177         auto textFieldTheme = GetTheme();
1178         CHECK_NULL_VOID(textFieldTheme);
1179         underlineColor_ = userUnderlineColor_.typing.value_or(textFieldTheme->GetUnderlineTypingColor());
1180         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
1181     }
1182 }
1183 
HandleSetSelection(int32_t start,int32_t end,bool showHandle)1184 void TextFieldPattern::HandleSetSelection(int32_t start, int32_t end, bool showHandle)
1185 {
1186     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleSetSelection %{public}d, %{public}d, showOverlay:%{public}d", start, end,
1187         showHandle);
1188     StopTwinkling();
1189     UpdateSelection(start, end);
1190     if (showHandle) {
1191         ProcessOverlay();
1192     } else {
1193         CloseSelectOverlay();
1194     }
1195     UpdateCaretInfoToController();
1196     auto host = GetHost();
1197     CHECK_NULL_VOID(host);
1198     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1199 }
1200 
HandleExtendAction(int32_t action)1201 void TextFieldPattern::HandleExtendAction(int32_t action)
1202 {
1203     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleExtendAction %{public}d", action);
1204     switch (action) {
1205         case ACTION_SELECT_ALL: {
1206             HandleOnSelectAll(false);
1207             break;
1208         }
1209         case ACTION_CUT: {
1210             HandleOnCut();
1211             break;
1212         }
1213         case ACTION_COPY: {
1214             HandleOnCopy();
1215             break;
1216         }
1217         case ACTION_PASTE: {
1218             HandleOnPaste();
1219             break;
1220         }
1221         default: {
1222             break;
1223         }
1224     }
1225 }
1226 
CursorMove(CaretMoveIntent direction)1227 void TextFieldPattern::CursorMove(CaretMoveIntent direction)
1228 {
1229     switch (direction) {
1230         case CaretMoveIntent::Left: {
1231             CursorMoveLeft();
1232             break;
1233         }
1234         case CaretMoveIntent::Right: {
1235             CursorMoveRight();
1236             break;
1237         }
1238         case CaretMoveIntent::Up: {
1239             CursorMoveUp();
1240             break;
1241         }
1242         case CaretMoveIntent::Down: {
1243             CursorMoveDown();
1244             break;
1245         }
1246         case CaretMoveIntent::LineBegin: {
1247             CursorMoveLineBegin();
1248             break;
1249         }
1250         case CaretMoveIntent::LineEnd: {
1251             CursorMoveLineEnd();
1252             break;
1253         }
1254         case CaretMoveIntent::LeftWord: {
1255             CursorMoveLeftWord();
1256             break;
1257         }
1258         case CaretMoveIntent::RightWord: {
1259             CursorMoveRightWord();
1260             break;
1261         }
1262         case CaretMoveIntent::ParagraghBegin: {
1263             CursorMoveToParagraphBegin();
1264             break;
1265         }
1266         case CaretMoveIntent::ParagraghEnd: {
1267             CursorMoveToParagraphEnd();
1268             break;
1269         }
1270         case CaretMoveIntent::Home: {
1271             CursorMoveHome();
1272             break;
1273         }
1274         case CaretMoveIntent::End: {
1275             CursorMoveEnd();
1276             break;
1277         }
1278         default: {
1279             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Unsupported operation of CursorMove for text field");
1280         }
1281     }
1282 }
1283 
HandleSelect(CaretMoveIntent direction)1284 void TextFieldPattern::HandleSelect(CaretMoveIntent direction)
1285 {
1286     CloseSelectOverlay();
1287     switch (direction) {
1288         case CaretMoveIntent::Left: {
1289             HandleSelectionLeft();
1290             break;
1291         }
1292         case CaretMoveIntent::Right: {
1293             HandleSelectionRight();
1294             break;
1295         }
1296         case CaretMoveIntent::Up: {
1297             HandleSelectionUp();
1298             break;
1299         }
1300         case CaretMoveIntent::Down: {
1301             HandleSelectionDown();
1302             break;
1303         }
1304         case CaretMoveIntent::LineBegin: {
1305             HandleSelectionLineBegin();
1306             break;
1307         }
1308         case CaretMoveIntent::LineEnd: {
1309             HandleSelectionLineEnd();
1310             break;
1311         }
1312         case CaretMoveIntent::LeftWord: {
1313             HandleSelectionLeftWord();
1314             break;
1315         }
1316         case CaretMoveIntent::RightWord: {
1317             HandleSelectionRightWord();
1318             break;
1319         }
1320         case CaretMoveIntent::Home: {
1321             HandleSelectionHome();
1322             break;
1323         }
1324         case CaretMoveIntent::End: {
1325             HandleSelectionEnd();
1326             break;
1327         }
1328         // SelectionParagraghBegin/SelectionParagraghEnd not supported yet
1329         default: {
1330             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Unsupported select operation for text field");
1331         }
1332     }
1333 }
1334 
InitDisableColor()1335 void TextFieldPattern::InitDisableColor()
1336 {
1337     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1338     CHECK_NULL_VOID(layoutProperty);
1339     auto theme = GetTheme();
1340     CHECK_NULL_VOID(theme);
1341     if (IsUnderlineMode()) {
1342         underlineWidth_ = HasFocus() ? TYPING_UNDERLINE_WIDTH : UNDERLINE_WIDTH;
1343         Color underlineColor = HasFocus() ? userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor())
1344                                           : userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
1345         if (IsShowError()) {
1346             underlineColor = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
1347         }
1348         if (userUnderlineColor_.disable) {
1349             underlineColor_ = IsDisabled() ? userUnderlineColor_.disable.value() : underlineColor;
1350         } else {
1351             underlineColor_ = IsDisabled() ? theme->GetDisableUnderlineColor() : underlineColor;
1352         }
1353     }
1354     layoutProperty->UpdateIsDisabled(IsDisabled());
1355 }
1356 
InitFocusEvent()1357 void TextFieldPattern::InitFocusEvent()
1358 {
1359     CHECK_NULL_VOID(!focusEventInitialized_);
1360     auto host = GetHost();
1361     CHECK_NULL_VOID(host);
1362     auto focusHub = host->GetOrCreateFocusHub();
1363     auto focusTask = [weak = WeakClaim(this)]() {
1364         auto pattern = weak.Upgrade();
1365         if (pattern) {
1366             pattern->HandleFocusEvent();
1367         }
1368     };
1369     focusHub->SetOnFocusInternal(focusTask);
1370     auto blurTask = [weak = WeakClaim(this)]() {
1371         auto pattern = weak.Upgrade();
1372         CHECK_NULL_VOID(pattern);
1373         pattern->HandleBlurEvent();
1374     };
1375     focusHub->SetOnBlurInternal(blurTask);
1376 
1377     auto keyTask = [weak = WeakClaim(this)](const KeyEvent& keyEvent) -> bool {
1378         auto pattern = weak.Upgrade();
1379         CHECK_NULL_RETURN(pattern, false);
1380         return pattern->OnKeyEvent(keyEvent);
1381     };
1382     focusHub->SetOnKeyEventInternal(keyTask);
1383 
1384     auto getInnerPaintRectCallback = [weak = WeakClaim(this)](RoundRect& paintRect) {
1385         auto pattern = weak.Upgrade();
1386         if (pattern) {
1387             pattern->GetInnerFocusPaintRect(paintRect);
1388         }
1389     };
1390     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
1391     focusEventInitialized_ = true;
1392 }
1393 
CheckBlurReason()1394 bool TextFieldPattern::CheckBlurReason()
1395 {
1396     auto curFocusHub = GetFocusHub();
1397     CHECK_NULL_RETURN(curFocusHub, false);
1398     auto curBlurReason = curFocusHub->GetBlurReason();
1399     if (curBlurReason == BlurReason::FRAME_DESTROY) {
1400         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextFieldPattern CheckBlurReason, Close Keyboard.");
1401         return true;
1402     }
1403     return false;
1404 }
1405 
UpdateBlurReason()1406 void TextFieldPattern::UpdateBlurReason()
1407 {
1408     auto focusHub = GetFocusHub();
1409     CHECK_NULL_VOID(focusHub);
1410     blurReason_ = focusHub->GetBlurReason();
1411 }
1412 
ProcNormalInlineStateInBlurEvent()1413 void TextFieldPattern::ProcNormalInlineStateInBlurEvent()
1414 {
1415     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1416     CHECK_NULL_VOID(layoutProperty);
1417     if (IsNormalInlineState()) {
1418         if (IsTextArea() && isTextInput_) {
1419             layoutProperty->UpdateMaxLines(1);
1420             layoutProperty->UpdatePlaceholderMaxLines(1);
1421         }
1422         layoutProperty->ResetTextOverflowMaxLines();
1423         inlineSelectAllFlag_ = false;
1424         inlineFocusState_ = false;
1425         RestorePreInlineStates();
1426     }
1427 }
1428 
ProcBorderAndUnderlineInBlurEvent()1429 void TextFieldPattern::ProcBorderAndUnderlineInBlurEvent()
1430 {
1431     auto host = GetHost();
1432     CHECK_NULL_VOID(host);
1433     auto textFieldTheme = GetTheme();
1434     CHECK_NULL_VOID(textFieldTheme);
1435     bool isShowError = IsShowError();
1436     bool isUnderlineMode = IsUnderlineMode();
1437     if (!isShowError && isUnderlineMode) {
1438         underlineColor_ = userUnderlineColor_.normal.value_or(textFieldTheme->GetUnderlineColor());
1439         underlineWidth_ = UNDERLINE_WIDTH;
1440     }
1441     if (showCountBorderStyle_) {
1442         showCountBorderStyle_ = false;
1443         if (isShowError) {
1444             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1445         }
1446     }
1447     if (!isShowError || (isShowError && !isUnderlineMode && !IsInPasswordMode())) {
1448         HandleCounterBorder();
1449     }
1450 }
1451 
SetNeedToRequestKeyboardInner(bool needToRequestKeyboardInner,RequestKeyboardInnerChangeReason reason)1452 void TextFieldPattern::SetNeedToRequestKeyboardInner(bool needToRequestKeyboardInner,
1453     RequestKeyboardInnerChangeReason reason)
1454 {
1455     if (needToRequestKeyboardInner_ != needToRequestKeyboardInner) {
1456         TAG_LOGI(ACE_TEXT_FIELD, "Set needToRequestKeyboardInner_ to %{public}d : reason %{public}d",
1457             needToRequestKeyboardInner, static_cast<int32_t>(reason));
1458     }
1459     if (reason == RequestKeyboardInnerChangeReason::FOCUS && !needToRequestKeyboardInner) {
1460         TAG_LOGI(ACE_TEXT_FIELD, "field focus but set needToRequestKeyboardInner to false "
1461             "why: %{public}d %{public}d %{public}d", isLongPress_, dragRecipientStatus_, dragStatus_);
1462     }
1463     needToRequestKeyboardInner_ = needToRequestKeyboardInner;
1464 }
1465 
HandleBlurEvent()1466 void TextFieldPattern::HandleBlurEvent()
1467 {
1468     auto host = GetHost();
1469     CHECK_NULL_VOID(host);
1470     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d OnBlur", host->GetId());
1471     auto context = host->GetContextRefPtr();
1472     CHECK_NULL_VOID(context);
1473     firstClickResetTask_.Cancel();
1474     firstClickAfterLosingFocus_ = true;
1475     UpdateBlurReason();
1476     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
1477     if (textFieldManager) {
1478         textFieldManager->ClearOnFocusTextField(host->GetId());
1479     }
1480     ResetOriginCaretPosition();
1481 
1482     shiftFlag_ = false;
1483     ProcBorderAndUnderlineInBlurEvent();
1484     ProcNormalInlineStateInBlurEvent();
1485     ModifyInnerStateInBlurEvent();
1486     if (magnifierController_) {
1487         magnifierController_->RemoveMagnifierFrameNode();
1488     }
1489     CloseSelectOverlay(!isKeyboardClosedByUser_ && blurReason_ == BlurReason::FOCUS_SWITCH);
1490     StopTwinkling();
1491     if (((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_)) {
1492         CloseKeyboard(true);
1493         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "textfield %{public}d on blur, close custom keyboard", host->GetId());
1494     }
1495     HandleCrossPlatformInBlurEvent();
1496     selectController_->UpdateCaretIndex(selectController_->GetCaretIndex());
1497     NotifyOnEditChanged(false);
1498     ResetFloatingCursorState();
1499     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1500     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1501     CHECK_NULL_VOID(eventHub);
1502     if (!eventHub->HasOnAreaChanged()) {
1503         context->RemoveOnAreaChangeNode(host->GetId());
1504     }
1505     SetNeedToRequestKeyboardInner(false, RequestKeyboardInnerChangeReason::BLUR);
1506     if (isOnHover_) {
1507         RestoreDefaultMouseState();
1508     }
1509     ReportEvent();
1510     ScheduleDisappearDelayTask();
1511     requestFocusReason_ = RequestFocusReason::UNKNOWN;
1512     ClearFocusStyle();
1513 }
1514 
ModifyInnerStateInBlurEvent()1515 void TextFieldPattern::ModifyInnerStateInBlurEvent()
1516 {
1517     isLongPress_ = false;
1518     isMoveCaretAnywhere_ = false;
1519     isFocusedBeforeClick_ = false;
1520 }
1521 
HandleCrossPlatformInBlurEvent()1522 void TextFieldPattern::HandleCrossPlatformInBlurEvent()
1523 {
1524 #ifndef OHOS_PLATFORM
1525     if (HasConnection()) {
1526         CloseKeyboard(true);
1527     }
1528 #endif
1529 }
1530 
OnKeyEvent(const KeyEvent & event)1531 bool TextFieldPattern::OnKeyEvent(const KeyEvent& event)
1532 {
1533     if (event.code == KeyCode::KEY_TAB && !contentController_->IsEmpty()) {
1534         if (isFocusedBeforeClick_) {
1535             isFocusedBeforeClick_ = false;
1536             HandleOnSelectAll(true);
1537         } else {
1538             CloseSelectOverlay(true);
1539         }
1540     }
1541     auto pipeline = GetContext();
1542     CHECK_NULL_RETURN(pipeline, false);
1543     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
1544     if (event.code == KeyCode::KEY_TAB && HasFocus() && !needToRequestKeyboardOnFocus_ && needToRequestKeyboardInner_ &&
1545         textFieldManager->GetImeShow()) {
1546         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::ON_KEY_EVENT);
1547     }
1548     // If independent control keyboard, press Enter to request keyboard.
1549     if (event.code == KeyCode::KEY_ENTER && HasFocus() && independentControlKeyboard_) {
1550         if (RequestKeyboard(false, true, true)) {
1551             NotifyOnEditChanged(true);
1552         }
1553         return true;
1554     }
1555     if (directionKeysMoveFocusOut_ && (IsMoveFocusOutFromLeft(event) || IsMoveFocusOutFromRight(event))) {
1556         TextInputClient::HandleKeyEvent(event);
1557         return false;
1558     }
1559     return TextInputClient::HandleKeyEvent(event);
1560 }
1561 
IsMoveFocusOutFromLeft(const KeyEvent & event)1562 bool TextFieldPattern::IsMoveFocusOutFromLeft(const KeyEvent& event)
1563 {
1564     return (event.code == KeyCode::KEY_DPAD_LEFT || event.code == KeyCode::KEY_DPAD_UP) &&
1565      selectController_->GetCaretIndex() == 0;
1566 }
1567 
IsMoveFocusOutFromRight(const KeyEvent & event)1568 bool TextFieldPattern::IsMoveFocusOutFromRight(const KeyEvent& event)
1569 {
1570     return (event.code == KeyCode::KEY_DPAD_RIGHT || event.code == KeyCode::KEY_DPAD_DOWN) &&
1571      selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
1572 }
1573 
HandleOnEscape()1574 bool TextFieldPattern::HandleOnEscape()
1575 {
1576     if (SelectOverlayIsOn()) {
1577         CloseSelectOverlay(true);
1578         if (!IsSelected() && HasFocus()) {
1579             StartTwinkling();
1580         }
1581         return false;
1582     }
1583     if (GetIsPreviewText()) {
1584         ResetPreviewTextState();
1585         return false;
1586     }
1587     if (HasFocus()) {
1588         StopTwinkling();
1589         TextFieldLostFocusToViewRoot();
1590     }
1591     return false;
1592 }
1593 
HandleOnTab(bool backward)1594 bool TextFieldPattern::HandleOnTab(bool backward)
1595 {
1596     return backward ? UpdateFocusBackward() : UpdateFocusForward();
1597 }
1598 
HandleOnUndoAction()1599 void TextFieldPattern::HandleOnUndoAction()
1600 {
1601     if (operationRecords_.empty()) {
1602         return;
1603     }
1604     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnUndoAction");
1605     if (operationRecords_.size() == 1) {
1606         FireEventHubOnChange(u"");
1607         return;
1608     }
1609     auto value = operationRecords_.back();
1610     operationRecords_.pop_back();
1611     auto textEditingValue = operationRecords_.back(); // each record includes text and caret
1612     bool isWillChange = OnWillChangePreSetValue(textEditingValue.text);
1613     if (!isWillChange) {
1614         operationRecords_.emplace_back(value);
1615         return;
1616     }
1617     if (redoOperationRecords_.size() >= RECORD_MAX_LENGTH) {
1618         redoOperationRecords_.erase(redoOperationRecords_.begin());
1619     }
1620     if (operationRecords_.size() >= 1) {
1621         redoOperationRecords_.emplace_back(value); // the initial status is not recorded
1622     }
1623 
1624     contentController_->SetTextValue(textEditingValue.text);
1625     if (value.beforeCaretPosition != -1) {
1626         selectController_->MoveCaretToContentRect(
1627             value.beforeCaretPosition, TextAffinity::DOWNSTREAM);
1628     } else {
1629         selectController_->MoveCaretToContentRect(
1630             textEditingValue.caretPosition, TextAffinity::DOWNSTREAM);
1631     }
1632     auto tmpHost = GetHost();
1633     CHECK_NULL_VOID(tmpHost);
1634     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1635 }
1636 
HandleOnRedoAction()1637 void TextFieldPattern::HandleOnRedoAction()
1638 {
1639     if (redoOperationRecords_.empty()) {
1640         return;
1641     }
1642     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnRedoAction");
1643     auto textEditingValue = redoOperationRecords_.back();
1644     bool isWillChange = OnWillChangePreSetValue(textEditingValue.text);
1645     if (!isWillChange) {
1646         return;
1647     }
1648     redoOperationRecords_.pop_back();
1649     operationRecords_.emplace_back(textEditingValue);
1650     contentController_->SetTextValue(textEditingValue.text);
1651     selectController_->UpdateCaretIndex(textEditingValue.caretPosition);
1652     auto tmpHost = GetHost();
1653     CHECK_NULL_VOID(tmpHost);
1654     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1655 }
1656 
CanUndo()1657 bool TextFieldPattern::CanUndo()
1658 {
1659     return operationRecords_.size() > 1;
1660 }
1661 
HasOperationRecords()1662 bool TextFieldPattern::HasOperationRecords()
1663 {
1664     return !operationRecords_.empty();
1665 }
1666 
CanRedo()1667 bool TextFieldPattern::CanRedo()
1668 {
1669     return !redoOperationRecords_.empty();
1670 }
1671 
HandleOnSelectAll(bool isKeyEvent,bool inlineStyle,bool showMenu)1672 void TextFieldPattern::HandleOnSelectAll(bool isKeyEvent, bool inlineStyle, bool showMenu)
1673 {
1674     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnSelectAll");
1675     auto textSize = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
1676     if (textSize == 0) {
1677         return; // no content
1678     }
1679     if (inlineStyle) {
1680         auto dotPos = contentController_->GetTextUtf16Value().rfind(u'.');
1681         if (dotPos != std::string::npos && static_cast<int32_t>(dotPos) < textSize - FIND_TEXT_ZERO_INDEX) {
1682             textSize = static_cast<int32_t>(dotPos);
1683         }
1684         UpdateSelection(0, textSize);
1685     } else {
1686         UpdateSelection(0, textSize);
1687     }
1688     if (IsSelected()) {
1689         SetIsSingleHandle(false);
1690     }
1691     ResetObscureTickCountDown();
1692     auto tmpHost = GetHost();
1693     CHECK_NULL_VOID(tmpHost);
1694     parentGlobalOffset_ = GetPaintRectGlobalOffset();
1695     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1696     selectController_->MoveSecondHandleToContentRect(textSize);
1697     StopTwinkling();
1698     showSelect_ = true;
1699     if (isKeyEvent || inlineSelectAllFlag_ || IsUsingMouse()) {
1700         CloseSelectOverlay(true);
1701         if (inlineSelectAllFlag_ && !isKeyEvent && !IsUsingMouse()) {
1702             return;
1703         }
1704         if (IsSelected()) {
1705             selectOverlay_->SetSelectionHoldCallback();
1706         }
1707         return;
1708     }
1709     selectOverlay_->ProcessSelectAllOverlay({ .menuIsShow = showMenu, .animation = true });
1710 }
1711 
HandleOnCopy(bool isUsingExternalKeyboard)1712 void TextFieldPattern::HandleOnCopy(bool isUsingExternalKeyboard)
1713 {
1714     CHECK_NULL_VOID(clipboard_);
1715     auto tmpHost = GetHost();
1716     CHECK_NULL_VOID(tmpHost);
1717     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
1718     CHECK_NULL_VOID(layoutProperty);
1719     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) == CopyOptions::None) {
1720         return;
1721     }
1722     if (!IsSelected() || IsInPasswordMode()) {
1723         return;
1724     }
1725     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "On copy, text selector %{public}s", selectController_->ToString().c_str());
1726     auto start = selectController_->GetStartIndex();
1727     auto end = selectController_->GetEndIndex();
1728     auto value = contentController_->GetSelectedValue(start, end);
1729     if (value.empty()) {
1730         return;
1731     }
1732     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None) {
1733         clipboard_->SetData(UtfUtils::Str16DebugToStr8(value), layoutProperty->GetCopyOptionsValue(CopyOptions::Local));
1734     }
1735 
1736     if (isUsingExternalKeyboard || selectOverlay_->IsShowMouseMenu()) {
1737         CloseSelectOverlay(true);
1738     } else {
1739         selectOverlay_->HideMenu();
1740     }
1741     auto host = GetHost();
1742     CHECK_NULL_VOID(host);
1743     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1744     CHECK_NULL_VOID(eventHub);
1745     eventHub->FireOnCopy(value);
1746 }
1747 
IsShowHandle()1748 bool TextFieldPattern::IsShowHandle()
1749 {
1750     auto theme = GetTheme();
1751     CHECK_NULL_RETURN(theme, false);
1752     return !theme->IsTextFieldShowHandle();
1753 }
1754 
GetCancelButton()1755 std::string TextFieldPattern::GetCancelButton()
1756 {
1757     auto theme = GetTheme();
1758     CHECK_NULL_RETURN(theme, "");
1759     return theme->GetCancelButton();
1760 }
1761 
GetCancelImageText()1762 std::string TextFieldPattern::GetCancelImageText()
1763 {
1764     auto theme = GetTheme();
1765     CHECK_NULL_RETURN(theme, "");
1766     return theme->GetCancelImageText();
1767 }
1768 
GetPasswordIconPromptInformation(bool show)1769 std::string TextFieldPattern::GetPasswordIconPromptInformation(bool show)
1770 {
1771     auto theme = GetTheme();
1772     CHECK_NULL_RETURN(theme, "");
1773     return show ? theme->GetShowPasswordPromptInformation() : theme->GetHiddenPasswordPromptInformation();
1774 }
1775 
UpdateShowCountBorderStyle()1776 void TextFieldPattern::UpdateShowCountBorderStyle()
1777 {
1778     auto host = GetHost();
1779     CHECK_NULL_VOID(host);
1780     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1781     CHECK_NULL_VOID(layoutProperty);
1782     if (layoutProperty->HasMaxLength()) {
1783         auto textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
1784         auto maxLength = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
1785         // if equal, the showCountBorderStyle_ is not changed
1786         if (textLength != maxLength) {
1787             showCountBorderStyle_ = textLength > maxLength;
1788         }
1789     }
1790 }
1791 
HandleOnPaste()1792 void TextFieldPattern::HandleOnPaste()
1793 {
1794     auto pasteCallback = [weak = WeakClaim(this)](const std::string& data) {
1795         if (data.empty()) {
1796             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "HandleOnPaste fail, because data is empty");
1797             return;
1798         }
1799         auto textfield = weak.Upgrade();
1800         CHECK_NULL_VOID(textfield);
1801         auto host = textfield->GetHost();
1802         CHECK_NULL_VOID(host);
1803         auto eventHub = host->GetEventHub<TextFieldEventHub>();
1804         CHECK_NULL_VOID(eventHub);
1805         TextCommonEvent event;
1806         const std::u16string pasteData = UtfUtils::Str8DebugToStr16(data);
1807         eventHub->FireOnPasteWithEvent(pasteData, event);
1808         if (event.IsPreventDefault()) {
1809             textfield->CloseSelectOverlay(true);
1810             textfield->selectController_->ResetHandles();
1811             textfield->StartTwinkling();
1812             return;
1813         }
1814         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnPaste len:%{public}d", static_cast<int32_t>(pasteData.length()));
1815         textfield->AddInsertCommand(pasteData, InputReason::PASTE);
1816     };
1817     CHECK_NULL_VOID(clipboard_);
1818     clipboard_->GetData(pasteCallback);
1819 }
1820 
IsShowTranslate()1821 bool TextFieldPattern::IsShowTranslate()
1822 {
1823     auto container = Container::Current();
1824     if (container && container->IsScenceBoardWindow()) {
1825         return false;
1826     }
1827 
1828     auto host = GetHost();
1829     CHECK_NULL_RETURN(host, false);
1830     auto textFieldTheme = GetTheme();
1831     CHECK_NULL_RETURN(textFieldTheme, false);
1832     return textFieldTheme->GetTranslateIsSupport();
1833 }
1834 
IsShowSearch()1835 bool TextFieldPattern::IsShowSearch()
1836 {
1837     auto container = Container::Current();
1838     if (container && container->IsScenceBoardWindow()) {
1839         return false;
1840     }
1841     auto host = GetHost();
1842     CHECK_NULL_RETURN(host, false);
1843     auto textFieldTheme = GetTheme();
1844     CHECK_NULL_RETURN(textFieldTheme, false);
1845     return textFieldTheme->GetIsSupportSearch();
1846 }
1847 
HandleOnCameraInput()1848 void TextFieldPattern::HandleOnCameraInput()
1849 {
1850     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextFieldPattern::HandleOnCameraInput");
1851 #if defined(ENABLE_STANDARD_INPUT)
1852     if (textChangeListener_ == nullptr) {
1853         textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
1854     }
1855     auto inputMethod = MiscServices::InputMethodController::GetInstance();
1856     if (!inputMethod) {
1857         TAG_LOGE(AceLogTag::ACE_TEXT_FIELD, "HandleOnCameraInput, inputMethod is null");
1858         return;
1859     }
1860 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
1861     if (imeShown_) {
1862         inputMethod->StartInputType(MiscServices::InputType::CAMERA_INPUT);
1863     } else {
1864         auto optionalTextConfig = GetMiscTextConfig();
1865         CHECK_NULL_VOID(optionalTextConfig.has_value());
1866         MiscServices::TextConfig textConfig = optionalTextConfig.value();
1867         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnCameraInput set calling window id is : %{public}u",
1868             textConfig.windowId);
1869 #ifdef WINDOW_SCENE_SUPPORTED
1870         auto systemWindowId = GetSCBSystemWindowId();
1871         if (systemWindowId) {
1872             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "windowId From %{public}u to %{public}u.", textConfig.windowId,
1873                 systemWindowId);
1874             textConfig.windowId = systemWindowId;
1875         }
1876 #endif
1877         auto ret = inputMethod->Attach(textChangeListener_, false, textConfig);
1878         if (ret == MiscServices::ErrorCode::NO_ERROR) {
1879             auto pipeline = GetContext();
1880             CHECK_NULL_VOID(pipeline);
1881             auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
1882             CHECK_NULL_VOID(textFieldManager);
1883             textFieldManager->SetIsImeAttached(true);
1884         }
1885         inputMethod->StartInputType(MiscServices::InputType::CAMERA_INPUT);
1886         inputMethod->ShowTextInput();
1887     }
1888     CloseSelectOverlay(true);
1889     StartTwinkling();
1890 #endif
1891 #endif
1892 }
1893 
StripNextLine(std::wstring & data)1894 void TextFieldPattern::StripNextLine(std::wstring& data)
1895 {
1896     CHECK_NULL_VOID(!(data.empty() || IsTextArea()));
1897     std::wstring result;
1898     bool dataChanged = false;
1899     int32_t dataPtr = 0;
1900     while (dataPtr < static_cast<int32_t>(data.length())) {
1901         if (data[dataPtr] != WIDE_NEWLINE[0]) {
1902             result += data[dataPtr];
1903         } else {
1904             dataChanged = true;
1905         }
1906         dataPtr++;
1907     }
1908     if (!dataChanged) {
1909         return;
1910     }
1911     data = result;
1912 }
1913 
HandleOnCut()1914 void TextFieldPattern::HandleOnCut()
1915 {
1916 #if !defined(PREVIEW)
1917     CHECK_NULL_VOID(clipboard_);
1918 #endif
1919     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1920     CHECK_NULL_VOID(layoutProperty);
1921 
1922     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) == CopyOptions::None) {
1923         return;
1924     }
1925     auto start = selectController_->GetStartIndex();
1926     auto end = selectController_->GetEndIndex();
1927     SwapIfLarger(start, end);
1928     if (!IsSelected() || IsInPasswordMode()) {
1929         return;
1930     }
1931     UpdateEditingValueToRecord();
1932     auto selectedText = contentController_->GetSelectedValue(start, end);
1933     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None) {
1934         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Cut value size is %{private}zu",
1935             UtfUtils::Str16DebugToStr8(selectedText).size());
1936         clipboard_->SetData(UtfUtils::Str16DebugToStr8(selectedText),
1937             layoutProperty->GetCopyOptionsValue(CopyOptions::Local));
1938     }
1939     DeleteRange(start, end, false);
1940     auto host = GetHost();
1941     CHECK_NULL_VOID(host);
1942     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1943     CHECK_NULL_VOID(eventHub);
1944     eventHub->FireOnCut(selectedText);
1945     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
1946                                                                                  : PROPERTY_UPDATE_MEASURE);
1947 }
1948 
UpdateSelection(int32_t both)1949 void TextFieldPattern::UpdateSelection(int32_t both)
1950 {
1951     UpdateSelection(both, both);
1952 }
1953 
UpdateSelection(int32_t start,int32_t end)1954 void TextFieldPattern::UpdateSelection(int32_t start, int32_t end)
1955 {
1956     auto startIndex = std::min(start, end);
1957     auto endIndex = std::max(start, end);
1958     startIndex = std::clamp(startIndex, 0, static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
1959     endIndex = std::clamp(endIndex, 0, static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
1960     if (startIndex != selectController_->GetStartIndex() || endIndex != selectController_->GetEndIndex()) {
1961         selectController_->UpdateHandleIndex(startIndex, endIndex);
1962     }
1963 }
1964 
FireEventHubOnChange(const std::u16string & text)1965 void TextFieldPattern::FireEventHubOnChange(const std::u16string& text)
1966 {
1967     auto host = GetHost();
1968     CHECK_NULL_VOID(host);
1969     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1970     CHECK_NULL_VOID(layoutProperty);
1971     if (!layoutProperty->GetNeedFireOnChangeValue(false)) {
1972         return;
1973     }
1974     auto textFieldTheme = GetTheme();
1975     CHECK_NULL_VOID(textFieldTheme);
1976     auto visible = layoutProperty->GetShowErrorTextValue(false);
1977     if (!visible && IsUnderlineMode()) {
1978         underlineColor_ = userUnderlineColor_.typing.value_or(textFieldTheme->GetUnderlineTypingColor());
1979         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
1980     }
1981 
1982     auto eventHub = host->GetEventHub<TextFieldEventHub>();
1983     CHECK_NULL_VOID(eventHub);
1984     ChangeValueInfo changeValueInfo;
1985     changeValueInfo.value = text;
1986     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
1987     changeValueInfo.previewText.value = GetPreviewTextValue();
1988     changeValueInfo.oldPreviewText = callbackOldPreviewText_;
1989     changeValueInfo.oldContent = callbackOldContent_;
1990     changeValueInfo.rangeBefore = callbackRangeBefore_;
1991     changeValueInfo.rangeAfter = callbackRangeAfter_;
1992     eventHub->FireOnChange(changeValueInfo);
1993 }
1994 
HandleTouchEvent(const TouchEventInfo & info)1995 void TextFieldPattern::HandleTouchEvent(const TouchEventInfo& info)
1996 {
1997     CHECK_NULL_VOID(!IsDragging());
1998     CHECK_NULL_VOID(!info.GetTouches().empty());
1999     if (selectOverlay_->IsTouchAtHandle(info)) {
2000         return;
2001     }
2002     auto touchInfo = GetAcceptedTouchLocationInfo(info);
2003     CHECK_NULL_VOID(touchInfo);
2004     DoGestureSelection(info);
2005     ResetOriginCaretPosition();
2006     auto touchType = touchInfo->GetTouchType();
2007     if (touchType == TouchType::DOWN) {
2008         HandleTouchDown(touchInfo->GetLocalLocation());
2009     } else if (touchType == TouchType::UP) {
2010         OnCaretMoveDone(info);
2011         RequestKeyboardAfterLongPress();
2012         isLongPress_ = false;
2013         isMoveCaretAnywhere_ = false;
2014         HandleTouchUp();
2015     } else if (touchType == TouchType::MOVE) {
2016         if (isMoveCaretAnywhere_) {
2017             // edit + longpress + move, show caret anywhere on fonts.
2018             selectController_->MoveCaretAnywhere(info.GetTouches().front().GetLocalLocation());
2019             ShowCaretAndStopTwinkling();
2020             selectOverlay_->HideMenu();
2021             selectOverlay_->SetIsSingleHandle(false);
2022             return;
2023         }
2024         if (SelectOverlayIsOn() && !moveCaretState_.isTouchCaret) {
2025             return;
2026         }
2027         if (!IsUsingMouse() && HasFocus()) {
2028             HandleTouchMove(touchInfo.value());
2029         }
2030     } else if (touchType == TouchType::CANCEL) {
2031         StopContentScroll();
2032         if (magnifierController_ && magnifierController_->GetMagnifierNodeExist()) {
2033             magnifierController_->RemoveMagnifierFrameNode();
2034         }
2035         ResetTouchAndMoveCaretState();
2036     }
2037 }
2038 
HandleTouchDown(const Offset & offset)2039 void TextFieldPattern::HandleTouchDown(const Offset& offset)
2040 {
2041     UpdatePressStyle(true);
2042     moveCaretState_.touchDownOffset = offset;
2043     if (HasStateStyle(UI_STATE_PRESSED)) {
2044         return;
2045     }
2046 
2047     if (enableTouchAndHoverEffect_ && !isMousePressed_) {
2048         auto lastCaretRect = selectController_->GetCaretRect();
2049         moveCaretState_.isTouchCaret = HasFocus() && !IsSelected() && RepeatClickCaret(offset, lastCaretRect);
2050         isTouchPreviewText_ = GetTouchInnerPreviewText(offset);
2051     }
2052 }
2053 
HandleTouchUp()2054 void TextFieldPattern::HandleTouchUp()
2055 {
2056     UpdatePressStyle(false);
2057     if (GetIsPreviewText() && isTouchPreviewText_) {
2058         StartTwinkling();
2059     }
2060     ResetTouchAndMoveCaretState();
2061     if (isMousePressed_) {
2062         isMousePressed_ = false;
2063     }
2064     if (magnifierController_) {
2065         magnifierController_->RemoveMagnifierFrameNode();
2066     }
2067     ScheduleDisappearDelayTask();
2068 }
2069 
ResetTouchAndMoveCaretState()2070 void TextFieldPattern::ResetTouchAndMoveCaretState()
2071 {
2072     if (moveCaretState_.isTouchCaret) {
2073         moveCaretState_.isTouchCaret = false;
2074         CheckScrollable();
2075         UpdateScrollBarOffset();
2076         StartTwinkling();
2077     }
2078     if (moveCaretState_.isMoveCaret) {
2079         moveCaretState_.isMoveCaret = false;
2080         StopContentScroll();
2081         if (HasFocus()) {
2082             StartTwinkling();
2083         } else {
2084             StopTwinkling();
2085         }
2086     }
2087     FloatingCaretLand();
2088 }
2089 
HandleTouchMove(const TouchLocationInfo & info)2090 void TextFieldPattern::HandleTouchMove(const TouchLocationInfo& info)
2091 {
2092     if (moveCaretState_.isTouchCaret && !moveCaretState_.isMoveCaret) {
2093         auto offset = info.GetLocalLocation();
2094         auto moveDistance = (offset - moveCaretState_.touchDownOffset).GetDistance();
2095         moveCaretState_.isMoveCaret = GreatNotEqual(moveDistance, moveCaretState_.minDinstance.ConvertToPx());
2096         if (moveCaretState_.isMoveCaret) {
2097             moveCaretState_.touchFingerId = info.GetFingerId();
2098         }
2099     }
2100     if (SelectOverlayIsOn() && moveCaretState_.isMoveCaret) {
2101         CloseSelectOverlay(false);
2102     }
2103     if (moveCaretState_.isMoveCaret || (GetIsPreviewText() && isTouchPreviewText_)) {
2104         ShowCaretAndStopTwinkling();
2105         UpdateCaretByTouchMove(info);
2106     }
2107 }
2108 
StartVibratorByIndexChange(int32_t currentIndex,int32_t preIndex)2109 void TextFieldPattern::StartVibratorByIndexChange(int32_t currentIndex, int32_t preIndex)
2110 {
2111     CHECK_NULL_VOID(isEnableHapticFeedback_ && (currentIndex != preIndex));
2112     VibratorUtils::StartVibraFeedback("slide");
2113 }
2114 
UpdateCaretByTouchMove(const TouchLocationInfo & info)2115 void TextFieldPattern::UpdateCaretByTouchMove(const TouchLocationInfo& info)
2116 {
2117     if (contentScroller_.isScrolling) {
2118         CheckScrollable();
2119     } else {
2120         scrollable_ = false;
2121         SetScrollEnabled(scrollable_);
2122     }
2123     // limit move when preview text is shown
2124     auto touchOffset = info.GetLocalLocation();
2125     if (GetIsPreviewText()) {
2126         TAG_LOGI(ACE_TEXT_FIELD, "UpdateCaretByTouchMove when has previewText");
2127         float offsetY = IsTextArea() ? GetTextRect().GetY() : contentRect_.GetY();
2128         std::vector<RectF> previewTextRects = GetPreviewTextRects();
2129         if (previewTextRects.empty()) {
2130             TAG_LOGI(ACE_TEXT_FIELD, "preview text rect error");
2131             return;
2132         }
2133 
2134         double limitL;
2135         double limitR;
2136         double limitT = previewTextRects.front().Top() + offsetY + MINIMAL_OFFSET;
2137         double limitB = previewTextRects.back().Bottom() + offsetY - MINIMAL_OFFSET;
2138 
2139         Offset previewTextTouchOffset;
2140         CalculatePreviewingTextMovingLimit(touchOffset, limitL, limitR);
2141 
2142         previewTextTouchOffset.SetX(std::clamp(touchOffset.GetX(), limitL, limitR));
2143         previewTextTouchOffset.SetY(std::clamp(touchOffset.GetY(), limitT, limitB));
2144         selectController_->UpdateCaretInfoByOffset(previewTextTouchOffset, true, true);
2145     } else {
2146         if (HasText()) {
2147             UpdateContentScroller(touchOffset);
2148         }
2149         auto touchCaretX = std::clamp(
2150             touchOffset.GetX(), static_cast<double>(contentRect_.Left()), static_cast<double>(contentRect_.Right()));
2151         // 1/4 line height.
2152         auto yOffset = PreferredLineHeight() * 0.25f;
2153         auto touchCaretY = std::clamp(touchOffset.GetY(), static_cast<double>(contentRect_.Top()) + yOffset,
2154             static_cast<double>(contentRect_.Bottom()) - yOffset);
2155         selectController_->UpdateCaretInfoByOffset(
2156             !contentScroller_.isScrolling ? Offset(touchCaretX, touchCaretY) : touchOffset,
2157             !contentScroller_.isScrolling, true);
2158         if (magnifierController_ && HasText()) {
2159             SetMagnifierLocalOffsetToFloatingCaretPos();
2160         }
2161     }
2162 
2163     UpdateCaretInfoToController();
2164     auto host = GetHost();
2165     CHECK_NULL_VOID(host);
2166     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2167 }
2168 
SetMagnifierLocalOffsetToFloatingCaretPos()2169 void TextFieldPattern::SetMagnifierLocalOffsetToFloatingCaretPos()
2170 {
2171     auto floatCaretRectCenter = GetFloatingCaretRect().Center();
2172     if (floatCaretState_.lastFloatingCursorY.has_value() && !NearEqual(floatCaretState_.lastFloatingCursorY.value(),
2173         static_cast<float>(floatCaretRectCenter.GetY()))) {
2174         AnimationOption option = AnimationOption();
2175         option.SetCurve(MOVE_MAGNIFIER_CURVE);
2176         option.SetDuration(LAND_DURATION);
2177         AnimationUtils::Animate(option,
2178             [weak = WeakClaim(this), floatCaretRectCenter]() {
2179                 auto pattern = weak.Upgrade();
2180                 CHECK_NULL_VOID(pattern);
2181                 pattern->GetMagnifierController()->SetLocalOffset({ floatCaretRectCenter.GetX(),
2182                     floatCaretRectCenter.GetY() });
2183             });
2184     } else {
2185         magnifierController_->SetLocalOffset({ floatCaretRectCenter.GetX(), floatCaretRectCenter.GetY() });
2186     }
2187     floatCaretState_.lastFloatingCursorY = floatCaretRectCenter.GetY();
2188 }
2189 
InitDragEvent()2190 void TextFieldPattern::InitDragEvent()
2191 {
2192     auto host = GetHost();
2193     CHECK_NULL_VOID(host);
2194     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2195     CHECK_NULL_VOID(layoutProperty);
2196     if (!IsInPasswordMode() && layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None &&
2197         host->IsDraggable()) {
2198         InitDragDropEvent();
2199     } else {
2200         ClearDragDropEvent();
2201         InitDragDropEventWithOutDragStart();
2202     }
2203     AddDragFrameNodeToManager(host);
2204 }
2205 
GetThumbnailCallback()2206 std::function<void(Offset)> TextFieldPattern::GetThumbnailCallback()
2207 {
2208     auto callback = [weak = WeakClaim(this)](const Offset& point) {
2209         auto pattern = weak.Upgrade();
2210         CHECK_NULL_VOID(pattern);
2211         auto frameNode = pattern->GetHost();
2212         CHECK_NULL_VOID(frameNode);
2213         if (pattern->BetweenSelectedPosition(point)) {
2214             auto info = pattern->CreateTextDragInfo();
2215             pattern->dragNode_ = TextDragPattern::CreateDragNode(frameNode);
2216             auto textDragPattern = pattern->dragNode_->GetPattern<TextDragPattern>();
2217             if (textDragPattern) {
2218                 textDragPattern->UpdateHandleAnimationInfo(info);
2219                 auto option = pattern->GetHost()->GetDragPreviewOption();
2220                 option.options.shadowPath = textDragPattern->GetBackgroundPath()->ConvertToSVGString();
2221                 option.options.shadow = Shadow(RICH_DEFAULT_ELEVATION, {0.0, 0.0}, Color(RICH_DEFAULT_SHADOW_COLOR),
2222                     ShadowStyle::OuterFloatingSM);
2223                 pattern->GetHost()->SetDragPreviewOptions(option);
2224             }
2225             FrameNode::ProcessOffscreenNode(pattern->dragNode_);
2226         }
2227         auto gestureHub = frameNode->GetOrCreateGestureEventHub();
2228         CHECK_NULL_VOID(gestureHub);
2229         gestureHub->SetPixelMap(nullptr);
2230     };
2231     return callback;
2232 }
2233 
CreateTextDragInfo() const2234 TextDragInfo TextFieldPattern::CreateTextDragInfo() const
2235 {
2236     TextDragInfo info;
2237     auto manager = selectOverlay_->GetManager<SelectContentOverlayManager>();
2238     CHECK_NULL_RETURN(manager, info);
2239     auto selectOverlayInfo = manager->GetSelectOverlayInfo();
2240     CHECK_NULL_RETURN(selectOverlayInfo, info);
2241     auto textFieldTheme = GetTheme();
2242     CHECK_NULL_RETURN(textFieldTheme, info);
2243     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
2244     CHECK_NULL_RETURN(paintProperty, info);
2245     auto handleColor = paintProperty->GetCursorColorValue(textFieldTheme->GetCursorColor());
2246     auto selectedBackgroundColor = textFieldTheme->GetSelectedColor();
2247     auto firstIndex = selectController_->GetFirstHandleIndex();
2248     auto secondIndex = selectController_->GetSecondHandleIndex();
2249     if (firstIndex > secondIndex) {
2250         info.secondHandle = selectOverlayInfo->firstHandle.paintRect;
2251         info.firstHandle = selectOverlayInfo->secondHandle.paintRect;
2252     } else {
2253         info.firstHandle = selectOverlayInfo->firstHandle.paintRect;
2254         info.secondHandle = selectOverlayInfo->secondHandle.paintRect;
2255     }
2256     auto firstIsShow = selectOverlayInfo->firstHandle.isShow;
2257     auto secondIsShow = selectOverlayInfo->secondHandle.isShow;
2258     if (!firstIsShow) {
2259         info.isFirstHandleAnimation = firstIsShow;
2260     }
2261     if (!secondIsShow) {
2262         info.isSecondHandleAnimation = secondIsShow;
2263     }
2264 
2265     info.selectedBackgroundColor = selectedBackgroundColor;
2266     info.handleColor = handleColor;
2267     return info;
2268 }
2269 
OnDragStart()2270 std::function<DragDropInfo(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragStart()
2271 {
2272     auto onDragStart = [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event,
2273                            const std::string& extraParams) -> NG::DragDropInfo {
2274         NG::DragDropInfo itemInfo;
2275         auto pattern = weakPtr.Upgrade();
2276         CHECK_NULL_RETURN(pattern, itemInfo);
2277         auto host = pattern->GetHost();
2278         CHECK_NULL_RETURN(host, itemInfo);
2279         auto hub = host->GetEventHub<EventHub>();
2280         CHECK_NULL_RETURN(hub, itemInfo);
2281         auto gestureHub = hub->GetOrCreateGestureEventHub();
2282         CHECK_NULL_RETURN(gestureHub, itemInfo);
2283         pattern->sourceTool_ = event ? event->GetSourceTool() : SourceTool::UNKNOWN;
2284         if (!gestureHub->GetIsTextDraggable()) {
2285             return itemInfo;
2286         }
2287         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2288             "%{public}d TextField OnDragStart, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2289             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2290             static_cast<int32_t>(pattern->dragRecipientStatus_));
2291         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2292         CHECK_NULL_RETURN(layoutProperty, itemInfo);
2293 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
2294         pattern->CloseHandleAndSelect();
2295         pattern->CloseKeyboard(true);
2296 #endif
2297         pattern->SetDragMovingScrollback();
2298         pattern->dragStatus_ = DragStatus::DRAGGING;
2299         auto pipeline = pattern->GetContext();
2300         CHECK_NULL_RETURN(pipeline, itemInfo);
2301         auto dragManager = pipeline->GetDragDropManager();
2302         CHECK_NULL_RETURN(dragManager, itemInfo);
2303         if (!pattern->IsNormalInlineState() && dragManager->IsDropAllowed(host)) {
2304             pattern->dragRecipientStatus_ = DragStatus::DRAGGING;
2305         }
2306         auto selectedStr = pattern->GetDragStyledText();
2307         itemInfo.extraInfo = selectedStr;
2308         RefPtr<UnifiedData> unifiedData = UdmfClient::GetInstance()->CreateUnifiedData();
2309         UdmfClient::GetInstance()->AddPlainTextRecord(unifiedData, selectedStr);
2310         event->SetData(unifiedData);
2311         host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
2312                                                                                      : PROPERTY_UPDATE_MEASURE);
2313         return itemInfo;
2314     };
2315     return onDragStart;
2316 }
2317 
GetDragStyledText()2318 std::string TextFieldPattern::GetDragStyledText()
2319 {
2320     showSelect_ = false;
2321     selectionMode_ = SelectionMode::SELECT;
2322     textFieldContentModifier_->ChangeDragStatus();
2323     auto start = selectController_->GetStartIndex();
2324     auto end = selectController_->GetEndIndex();
2325     GetEmojiSubStringRange(start, end);
2326     dragTextStart_ = start;
2327     dragTextEnd_ = end;
2328     std::u16string beforeStr = contentController_->GetValueBeforeIndex(start);
2329     std::u16string selectedStr = contentController_->GetSelectedValue(start, end);
2330     dragValue_ = selectedStr;
2331     std::u16string afterStr = contentController_->GetValueAfterIndex(end);
2332     dragContents_ = { beforeStr, selectedStr, afterStr };
2333     return UtfUtils::Str16DebugToStr8(selectedStr);
2334 }
2335 
OnDragDrop()2336 std::function<void(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragDrop()
2337 {
2338     return [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2339         auto pattern = weakPtr.Upgrade();
2340         CHECK_NULL_VOID(pattern);
2341         pattern->StopContentScroll();
2342         pattern->sourceTool_ = event ? event->GetSourceTool() : SourceTool::UNKNOWN;
2343         auto host = pattern->GetHost();
2344         CHECK_NULL_VOID(host);
2345         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2346         CHECK_NULL_VOID(layoutProperty);
2347 
2348         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2349             "%{public}d TextField OnDragDrop, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2350             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2351             static_cast<int32_t>(pattern->dragRecipientStatus_));
2352         if (layoutProperty->GetIsDisabledValue(false) || pattern->IsNormalInlineState() || !pattern->HasFocus()) {
2353             event->SetResult(DragRet::DRAG_FAIL);
2354             return;
2355         }
2356         if (extraParams.empty()) {
2357             pattern->dragStatus_ = DragStatus::ON_DROP;
2358             pattern->textFieldContentModifier_->ChangeDragStatus();
2359             host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
2360                                                                                          : PROPERTY_UPDATE_MEASURE);
2361             event->SetResult(DragRet::DRAG_FAIL);
2362             return;
2363         }
2364         bool isCopy = false;
2365         if (pattern->dragStatus_ == DragStatus::DRAGGING) {
2366             CHECK_NULL_VOID(event);
2367             auto gesturePressedCodes = event->GetPressedKeyCodes();
2368             if ((gesturePressedCodes.size() == 1) && ((gesturePressedCodes[0] == KeyCode::KEY_CTRL_LEFT) ||
2369                 (gesturePressedCodes[0] == KeyCode::KEY_CTRL_RIGHT))) {
2370                 isCopy = true;
2371             }
2372         }
2373         auto data = event->GetData();
2374         CHECK_NULL_VOID(data);
2375         std::u16string str;
2376         auto arr = UdmfClient::GetInstance()->GetSpanStringEntry(data);
2377         if (arr.size() > 0) {
2378             auto spanStr = SpanString::DecodeTlv(arr);
2379             str += spanStr->GetU16string();
2380         } else {
2381             auto plainText = UdmfClient::GetInstance()->GetPlainTextEntry(data);
2382             if (plainText.empty()) {
2383                 std::string linkUrl;
2384                 std::string linkTitle;
2385                 UdmfClient::GetInstance()->GetLinkEntry(data, linkUrl, linkTitle);
2386                 if (!linkTitle.empty()) {
2387                     str +=  UtfUtils::Str8DebugToStr16(linkTitle);
2388                 } else if (!linkUrl.empty()) {
2389                     str +=  UtfUtils::Str8DebugToStr16(linkUrl);
2390                 }
2391             }
2392             str += UtfUtils::Str8DebugToStr16(plainText);
2393         }
2394         pattern->dragRecipientStatus_ = DragStatus::NONE;
2395         if (str.empty()) {
2396             return;
2397         }
2398         if ((pattern->dragStatus_ == DragStatus::NONE) || isCopy) {
2399             pattern->AddInsertCommand(str, InputReason::DRAG);
2400         } else {
2401             InputCommandInfo inputCommandInfo;
2402             inputCommandInfo.deleteRange = { pattern->dragTextStart_, pattern->dragTextEnd_ };
2403             inputCommandInfo.insertOffset = pattern->selectController_->GetCaretIndex();
2404             inputCommandInfo.insertValue = str;
2405             inputCommandInfo.reason = InputReason::DRAG;
2406             pattern->AddInputCommand(inputCommandInfo);
2407             pattern->dragStatus_ = DragStatus::NONE;
2408             pattern->MarkContentChange();
2409             host->MarkDirtyNode(pattern->IsTextArea() ? PROPERTY_UPDATE_MEASURE : PROPERTY_UPDATE_MEASURE_SELF);
2410         }
2411         pattern->afterDragSelect_ = isMouseOrTouchPad(pattern->sourceTool_);
2412         pattern->releaseInDrop_ = true;
2413         FocusHub::LostFocusToViewRoot();
2414     };
2415 }
2416 
ShowSelectAfterDragEvent()2417 void TextFieldPattern::ShowSelectAfterDragEvent()
2418 {
2419     selectController_->UpdateHandleIndex(dragTextStart_, dragTextEnd_);
2420     showSelect_ = true;
2421     if (!IsUsingMouse()) {
2422         DelayProcessOverlay({ .menuIsShow = false });
2423     }
2424 }
2425 
InitDragDropEventWithOutDragStart()2426 void TextFieldPattern::InitDragDropEventWithOutDragStart()
2427 {
2428     auto host = GetHost();
2429     CHECK_NULL_VOID(host);
2430     auto gestureHub = host->GetOrCreateGestureEventHub();
2431     CHECK_NULL_VOID(gestureHub);
2432     gestureHub->InitDragDropEvent();
2433     auto eventHub = host->GetEventHub<EventHub>();
2434     CHECK_NULL_VOID(eventHub);
2435     InitDragDropCallBack();
2436 }
2437 
InitDragDropEvent()2438 void TextFieldPattern::InitDragDropEvent()
2439 {
2440     auto host = GetHost();
2441     CHECK_NULL_VOID(host);
2442     auto gestureHub = host->GetOrCreateGestureEventHub();
2443     CHECK_NULL_VOID(gestureHub);
2444     gestureHub->InitDragDropEvent();
2445     auto callback = GetThumbnailCallback();
2446     gestureHub->SetThumbnailCallback(std::move(callback));
2447     auto eventHub = host->GetEventHub<EventHub>();
2448     CHECK_NULL_VOID(eventHub);
2449     eventHub->SetDefaultOnDragStart(OnDragStart());
2450     InitDragDropCallBack();
2451     gestureHub->SetTextDraggable(true);
2452 }
2453 
InitDragDropCallBack()2454 void TextFieldPattern::InitDragDropCallBack()
2455 {
2456     auto host = GetHost();
2457     CHECK_NULL_VOID(host);
2458     auto eventHub = host->GetEventHub<EventHub>();
2459     CHECK_NULL_VOID(eventHub);
2460     auto onDragEnter = [weakPtr = WeakClaim(this)](
2461                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2462         auto pattern = weakPtr.Upgrade();
2463         CHECK_NULL_VOID(pattern);
2464         auto host = pattern->GetHost();
2465         CHECK_NULL_VOID(host);
2466         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2467             "%{public}d TextField onDragEnter, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2468             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2469             static_cast<int32_t>(pattern->dragRecipientStatus_));
2470 
2471         auto pipeline = pattern->GetContext();
2472         CHECK_NULL_VOID(pipeline);
2473         auto dragManager = pipeline->GetDragDropManager();
2474         CHECK_NULL_VOID(dragManager);
2475         if (pattern->IsNormalInlineState() || !dragManager->IsDropAllowed(host)) {
2476             return;
2477         }
2478         pattern->SetDragMovingScrollback();
2479         pattern->dragRecipientStatus_ = DragStatus::DRAGGING;
2480         pattern->ResetPreviewTextState();
2481         auto focusHub = pattern->GetFocusHub();
2482         CHECK_NULL_VOID(focusHub);
2483         if (pattern->TextFieldRequestFocus(RequestFocusReason::DRAG_ENTER)) {
2484             pattern->StartTwinkling();
2485             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2486                 "%{public}d TextField onDragEnter Request Focus Success", host->GetId());
2487         }
2488     };
2489     eventHub->SetOnDragEnter(std::move(onDragEnter));
2490 
2491     auto onDragMove = [weakPtr = WeakClaim(this)](
2492                           const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2493         auto pattern = weakPtr.Upgrade();
2494         CHECK_NULL_VOID(pattern);
2495         auto pipeline = pattern->GetContext();
2496         CHECK_NULL_VOID(pipeline);
2497         auto dragManager = pipeline->GetDragDropManager();
2498         CHECK_NULL_VOID(dragManager);
2499         auto host = pattern->GetHost();
2500         CHECK_NULL_VOID(host);
2501 
2502         if (pattern->IsNormalInlineState() || !dragManager->IsDropAllowed(host)) {
2503             return;
2504         }
2505         if (!pattern->HasFocus()) {
2506             auto focusHub = pattern->GetFocusHub();
2507             CHECK_NULL_VOID(focusHub);
2508             if (pattern->TextFieldRequestFocus(RequestFocusReason::DRAG_MOVE)) {
2509                 pattern->StartTwinkling();
2510                 TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2511                     "%{public}d TextField onDragMove Request Focus Success", host->GetId());
2512             }
2513         }
2514         auto textPaintOffset = pattern->GetPaintRectGlobalOffset();
2515         Offset localOffset =
2516             Offset(event->GetX(), event->GetY()) - Offset(textPaintOffset.GetX(), textPaintOffset.GetY());
2517         if (host->GetDragPreviewOption().enableEdgeAutoScroll) {
2518             pattern->UpdateContentScroller(localOffset);
2519         } else {
2520             pattern->contentScroller_.OnBeforeScrollingCallback(localOffset);
2521             pattern->PauseContentScroll();
2522             pattern->contentScroller_.hotAreaOffset.reset();
2523         }
2524     };
2525     eventHub->SetOnDragMove(std::move(onDragMove));
2526 
2527     auto onDragLeave = [weakPtr = WeakClaim(this)](
2528                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2529         auto pattern = weakPtr.Upgrade();
2530         CHECK_NULL_VOID(pattern);
2531         auto host = pattern->GetHost();
2532         CHECK_NULL_VOID(host);
2533         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2534             "%{public}d TextField onDragLeave, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2535             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2536             static_cast<int32_t>(pattern->dragRecipientStatus_));
2537         pattern->dragRecipientStatus_ = DragStatus::NONE;
2538         auto focusHub = pattern->GetFocusHub();
2539         CHECK_NULL_VOID(focusHub);
2540         focusHub->LostFocus();
2541         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2542             "%{public}d TextField onDragLeave Lost Focus", host->GetId());
2543         pattern->StopTwinkling();
2544         pattern->PauseContentScroll();
2545     };
2546     eventHub->SetOnDragLeave(std::move(onDragLeave));
2547 
2548     auto onDragEnd = [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event) {
2549         auto pattern = weakPtr.Upgrade();
2550         CHECK_NULL_VOID(pattern);
2551         auto host = pattern->GetHost();
2552         CHECK_NULL_VOID(host);
2553         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2554             "%{public}d TextField onDragEnd, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2555             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2556             static_cast<int32_t>(pattern->dragRecipientStatus_));
2557         pattern->StopContentScroll();
2558         ContainerScope scope(pattern->GetHostInstanceId());
2559         if (pattern->dragStatus_ == DragStatus::DRAGGING && !pattern->isDetachFromMainTree_) {
2560             pattern->dragStatus_ = DragStatus::NONE;
2561             pattern->MarkContentChange();
2562             // Except for DRAG_SUCCESS, all of rest need to show
2563             auto paintProperty = pattern->GetPaintProperty<TextFieldPaintProperty>();
2564             CHECK_NULL_VOID(paintProperty);
2565             auto newDragValue =
2566                 pattern->contentController_->GetSelectedValue(pattern->dragTextStart_, pattern->dragTextEnd_);
2567             auto focusHub = pattern->GetFocusHub();
2568             CHECK_NULL_VOID(focusHub);
2569             if (event != nullptr && event->GetResult() != DragRet::DRAG_SUCCESS &&
2570                 newDragValue == pattern->dragValue_ &&
2571                 paintProperty->GetInputStyleValue(InputStyle::DEFAULT) != InputStyle::INLINE &&
2572                 focusHub->IsFocusable()) {
2573                 pattern->ShowSelectAfterDragEvent();
2574                 pattern->afterDragSelect_ = true;
2575                 pattern->TextFieldRequestFocus(RequestFocusReason::DRAG_END);
2576             }
2577             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2578         }
2579         if (event != nullptr && event->GetResult() != DragRet::DRAG_SUCCESS) {
2580             pattern->afterDragSelect_ = true;
2581         }
2582         pattern->CloseKeyboard(true);
2583     };
2584     eventHub->SetOnDragEnd(std::move(onDragEnd));
2585 
2586     eventHub->SetOnDrop(OnDragDrop());
2587 }
2588 
ClearDragDropEvent()2589 void TextFieldPattern::ClearDragDropEvent()
2590 {
2591     auto host = GetHost();
2592     CHECK_NULL_VOID(host);
2593     auto gestureHub = host->GetOrCreateGestureEventHub();
2594     CHECK_NULL_VOID(gestureHub);
2595     gestureHub->SetTextDraggable(false);
2596     gestureHub->SetIsTextDraggable(false);
2597     auto eventHub = host->GetEventHub<EventHub>();
2598     CHECK_NULL_VOID(eventHub);
2599     eventHub->SetOnDragStart(nullptr);
2600     eventHub->SetDefaultOnDragStart(nullptr);
2601     eventHub->SetOnDragEnter(nullptr);
2602     eventHub->SetOnDragMove(nullptr);
2603     eventHub->SetOnDragLeave(nullptr);
2604     eventHub->SetOnDragEnd(nullptr);
2605     eventHub->SetOnDrop(nullptr);
2606 }
2607 
HandleOnDragStatusCallback(const DragEventType & dragEventType,const RefPtr<NotifyDragEvent> & notifyDragEvent)2608 void TextFieldPattern::HandleOnDragStatusCallback(
2609     const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent)
2610 {
2611     ScrollablePattern::HandleOnDragStatusCallback(dragEventType, notifyDragEvent);
2612     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnDragStatusCallback dragEventType=%{public}d", dragEventType);
2613     if (dragEventType == DragEventType::DROP && dragRecipientStatus_ == DragStatus::DRAGGING) {
2614         StopContentScroll();
2615         StopTwinkling();
2616     }
2617 }
2618 
InitTouchEvent()2619 void TextFieldPattern::InitTouchEvent()
2620 {
2621     CHECK_NULL_VOID(!touchListener_);
2622     auto host = GetHost();
2623     CHECK_NULL_VOID(host);
2624 
2625     auto gesture = host->GetOrCreateGestureEventHub();
2626     CHECK_NULL_VOID(gesture);
2627     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
2628         auto pattern = weak.Upgrade();
2629         CHECK_NULL_VOID(pattern);
2630         pattern->selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
2631         pattern->selectOverlay_->SetLastSourceType(info.GetSourceDevice());
2632         pattern->HandleTouchEvent(info);
2633     };
2634     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
2635     gesture->AddTouchEvent(touchListener_);
2636 }
2637 
IsHandleDragging()2638 bool TextFieldPattern::IsHandleDragging()
2639 {
2640     CHECK_NULL_RETURN(selectOverlay_, false);
2641     return selectOverlay_->GetIsHandleDragging();
2642 }
2643 
InitClickEvent()2644 void TextFieldPattern::InitClickEvent()
2645 {
2646     CHECK_NULL_VOID(!clickListener_);
2647     auto tmpHost = GetHost();
2648     CHECK_NULL_VOID(tmpHost);
2649     auto gesture = tmpHost->GetOrCreateGestureEventHub();
2650     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
2651         auto pattern = weak.Upgrade();
2652         CHECK_NULL_VOID(pattern);
2653         pattern->HandleClickEvent(info);
2654     };
2655 
2656     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
2657     gesture->AddClickEvent(clickListener_);
2658 }
2659 
HandleClickEvent(GestureEvent & info)2660 void TextFieldPattern::HandleClickEvent(GestureEvent& info)
2661 {
2662     CHECK_NULL_VOID(!IsDragging());
2663     CHECK_NULL_VOID(!IsHandleDragging());
2664     parentGlobalOffset_ = GetPaintRectGlobalOffset();
2665     auto focusHub = GetFocusHub();
2666     CHECK_NULL_VOID(focusHub);
2667     CHECK_NULL_VOID(selectOverlay_);
2668     CHECK_NULL_VOID(multipleClickRecognizer_);
2669     if ((selectOverlay_->IsClickAtHandle(info) && !multipleClickRecognizer_->IsValidClick(info)) ||
2670         !focusHub->IsFocusable()) {
2671         return;
2672     }
2673     focusIndex_ = FocuseIndex::TEXT;
2674     auto firstGetFocus = false;
2675     if (!HasFocus()) {
2676         auto host = GetHost();
2677         CHECK_NULL_VOID(host);
2678         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d request focus currently", host->GetId());
2679         firstGetFocus = true;
2680         if (!focusHub->IsFocusOnTouch().value_or(true) || !TextFieldRequestFocus(RequestFocusReason::CLICK)) {
2681             CloseSelectOverlay(true);
2682             StopTwinkling();
2683             return;
2684         }
2685     }
2686     firstGetFocus = firstGetFocus || firstClickAfterLosingFocus_;
2687     firstClickAfterLosingFocus_ = false;
2688     if (!firstGetFocus && CheckMousePressedOverScrollBar(info)) {
2689         return;
2690     }
2691     selectOverlay_->SetLastSourceType(info.GetSourceDevice());
2692     selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
2693     lastClickTimeStamp_ = info.GetTimeStamp();
2694     multipleClickRecognizer_->StartCounting(info);
2695     // register click event
2696     if (multipleClickRecognizer_->IsTripleClick()) {
2697         HandleTripleClickEvent(info);
2698     } else if (multipleClickRecognizer_->IsDoubleClick()) {
2699         HandleDoubleClickEvent(info);
2700     } else {
2701         HandleSingleClickEvent(info, firstGetFocus);
2702     }
2703     if (ResetObscureTickCountDown()) {
2704         auto host = GetHost();
2705         CHECK_NULL_VOID(host);
2706         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2707     }
2708     isFocusedBeforeClick_ = false;
2709 }
2710 
CheckMousePressedOverScrollBar(GestureEvent & info)2711 bool TextFieldPattern::CheckMousePressedOverScrollBar(GestureEvent& info)
2712 {
2713     if (IsMouseOverScrollBar(&info) && hasMousePressed_) {
2714         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2715         CHECK_NULL_RETURN(layoutProperty, false);
2716         if (layoutProperty->GetDisplayModeValue(DisplayMode::AUTO) != DisplayMode::OFF) {
2717             auto touchRegion = GetScrollBar()->GetTouchRegion();
2718             bool reverse = info.GetLocalLocation().GetY() < touchRegion.Top();
2719             ScrollPage(reverse);
2720             return true;
2721         }
2722     }
2723     return false;
2724 }
2725 
HandleBetweenSelectedPosition(const GestureEvent & info)2726 bool TextFieldPattern::HandleBetweenSelectedPosition(const GestureEvent& info)
2727 {
2728     if (!IsUsingMouse() && SelectOverlayIsOn() && BetweenSelectedPosition(info.GetGlobalLocation())) {
2729         CHECK_NULL_RETURN(selectOverlay_, false);
2730         // click selected area to switch show/hide state
2731         selectOverlay_->ToggleMenu();
2732         return true;
2733     }
2734     return false;
2735 }
2736 
HandleSingleClickEvent(GestureEvent & info,bool firstGetFocus)2737 void TextFieldPattern::HandleSingleClickEvent(GestureEvent& info, bool firstGetFocus)
2738 {
2739     if (mouseStatus_ != MouseStatus::NONE && IsNormalInlineState()) {
2740         return;
2741     }
2742     if (HandleBetweenSelectedPosition(info)) {
2743         selectOverlay_->SwitchToOverlayMode();
2744         return;
2745     }
2746     auto host = GetHost();
2747     CHECK_NULL_VOID(host);
2748     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2749     auto lastCaretIndex = selectController_->GetCaretIndex();
2750     if (mouseStatus_ != MouseStatus::MOVE) {
2751         UpdateCaretByClick(info.GetLocalLocation());
2752     }
2753     StartTwinkling();
2754     SetIsSingleHandle(true);
2755     bool needCloseOverlay = true;
2756     bool isRepeatClickCaret =
2757         RepeatClickCaret(info.GetLocalLocation(), lastCaretIndex) && !firstGetFocus;
2758     bool isInlineSelectAllOrEmpty = inlineSelectAllFlag_ || contentController_->IsEmpty();
2759     auto clickBlank = contentController_->IsEmpty() || selectController_->IsTouchAtLineEnd(info.GetLocalLocation());
2760     auto closeHandleAtBlank =
2761         clickBlank && isRepeatClickCaret && SelectOverlayIsOn() && selectOverlay_->IsSingleHandle();
2762     do {
2763         if (info.GetSourceDevice() == SourceType::MOUSE || (!isRepeatClickCaret && isInlineSelectAllOrEmpty) ||
2764             IsContentRectNonPositive() || closeHandleAtBlank) {
2765             break;
2766         }
2767         if (isRepeatClickCaret) {
2768             if (IsAccessibilityClick()) {
2769                 break;
2770             }
2771             ProcessOverlay({ .animation = true });
2772             needCloseOverlay = false;
2773         } else if (needSelectAll_) {
2774             HandleOnSelectAll(false);
2775         }
2776     } while (false);
2777     if (needCloseOverlay || GetIsPreviewText()) {
2778         CloseSelectOverlay(true);
2779         StartTwinkling();
2780     }
2781     DoProcessAutoFill(info.GetSourceDevice());
2782     // emulate clicking bottom of the textField
2783     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
2784     TriggerAvoidOnCaretChange();
2785     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2786 }
2787 
DoProcessAutoFill(SourceType sourceType)2788 void TextFieldPattern::DoProcessAutoFill(SourceType sourceType)
2789 {
2790     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "DoProcessAutoFill");
2791     if (!IsNeedProcessAutoFill()) {
2792         if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SINGLE_CLICK, sourceType)) {
2793             NotifyOnEditChanged(true);
2794         }
2795         return;
2796     }
2797     bool isPopup = false;
2798     auto isSuccess = ProcessAutoFill(isPopup);
2799     if (!isPopup && isSuccess) {
2800         SetNeedToRequestKeyboardInner(false, RequestKeyboardInnerChangeReason::AUTOFILL_PROCESS);
2801     } else if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SINGLE_CLICK, sourceType)) {
2802         NotifyOnEditChanged(true);
2803     }
2804 }
2805 
IsAutoFillPasswordType(const AceAutoFillType & autoFillType)2806 bool TextFieldPattern::IsAutoFillPasswordType(const AceAutoFillType& autoFillType)
2807 {
2808     return (autoFillType == AceAutoFillType::ACE_USER_NAME || autoFillType == AceAutoFillType::ACE_PASSWORD ||
2809             autoFillType == AceAutoFillType::ACE_NEW_PASSWORD);
2810 }
2811 
GetHintType()2812 HintToTypeWrap TextFieldPattern::GetHintType()
2813 {
2814     HintToTypeWrap hintToTypeWrap;
2815     auto container = Container::Current();
2816     CHECK_NULL_RETURN(container, hintToTypeWrap);
2817     auto onePlaceHolder = UtfUtils::Str16DebugToStr8(GetPlaceHolder());
2818     if (onePlaceHolder.empty()) {
2819         return hintToTypeWrap;
2820     }
2821     return container->PlaceHolderToType(onePlaceHolder);
2822 }
2823 
CheckAutoFillType(const AceAutoFillType & autoFillType,bool isFromKeyBoard)2824 bool TextFieldPattern::CheckAutoFillType(const AceAutoFillType& autoFillType, bool isFromKeyBoard)
2825 {
2826     if (isFromKeyBoard) {
2827         return true;
2828     }
2829 
2830     auto container = Container::Current();
2831     CHECK_NULL_RETURN(container, false);
2832     auto isTriggerPassword = IsTriggerAutoFillPassword();
2833     if (autoFillType == AceAutoFillType::ACE_UNSPECIFIED && !isTriggerPassword) {
2834         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "CheckAutoFillType :autoFillType is ACE_UNSPECIFIED.");
2835         return false;
2836     } else if (isTriggerPassword) {
2837         auto tempAutoFillType = IsAutoFillUserName(autoFillType) ? AceAutoFillType::ACE_USER_NAME : autoFillType;
2838         if (!container->IsNeedToCreatePopupWindow(tempAutoFillType)) {
2839             return GetAutoFillTriggeredStateByType(autoFillType);
2840         }
2841     }
2842     return true;
2843 }
2844 
GetAutoFillTriggeredStateByType(const AceAutoFillType & autoFillType)2845 bool TextFieldPattern::GetAutoFillTriggeredStateByType(const AceAutoFillType& autoFillType)
2846 {
2847     auto host = GetHost();
2848     CHECK_NULL_RETURN(host, false);
2849     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
2850     CHECK_NULL_RETURN(autoFillContainerNode, false);
2851     auto stateHolder = autoFillContainerNode->GetPattern<AutoFillTriggerStateHolder>();
2852     CHECK_NULL_RETURN(stateHolder, false);
2853     if (IsAutoFillUserName(autoFillType) || autoFillType == AceAutoFillType::ACE_PASSWORD) {
2854         return !stateHolder->IsAutoFillPasswordTriggered();
2855     }
2856     if (autoFillType == AceAutoFillType::ACE_NEW_PASSWORD) {
2857         return !stateHolder->IsAutoFillNewPasswordTriggered();
2858     }
2859     return false;
2860 }
2861 
SetAutoFillTriggeredStateByType(const AceAutoFillType & autoFillType)2862 void TextFieldPattern::SetAutoFillTriggeredStateByType(const AceAutoFillType& autoFillType)
2863 {
2864     auto host = GetHost();
2865     CHECK_NULL_VOID(host);
2866     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
2867     CHECK_NULL_VOID(autoFillContainerNode);
2868     auto stateHolder = autoFillContainerNode->GetPattern<AutoFillTriggerStateHolder>();
2869     CHECK_NULL_VOID(stateHolder);
2870     if (IsAutoFillUserName(autoFillType) || autoFillType == AceAutoFillType::ACE_PASSWORD) {
2871         stateHolder->SetAutoFillPasswordTriggered(true);
2872     } else if (autoFillType == AceAutoFillType::ACE_NEW_PASSWORD) {
2873         stateHolder->SetAutoFillNewPasswordTriggered(true);
2874     }
2875 }
2876 
GetAutoFillType(bool isNeedToHitType)2877 AceAutoFillType TextFieldPattern::GetAutoFillType(bool isNeedToHitType)
2878 {
2879     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2880     CHECK_NULL_RETURN(layoutProperty, AceAutoFillType::ACE_UNSPECIFIED);
2881     auto aceContentType =
2882         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
2883     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2884     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
2885         return aceContentType;
2886     }
2887     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
2888         return aceInputType;
2889     }
2890     if (isNeedToHitType && !IsTriggerAutoFillPassword()) {
2891         auto hintToTypeWrap = GetHintType();
2892         return hintToTypeWrap.autoFillType;
2893     }
2894     return AceAutoFillType::ACE_UNSPECIFIED;
2895 }
2896 
GetAutoFillTypeAndMetaData(bool isNeedToHitType)2897 HintToTypeWrap TextFieldPattern::GetAutoFillTypeAndMetaData(bool isNeedToHitType)
2898 {
2899     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2900     HintToTypeWrap hintToTypeWrap;
2901     CHECK_NULL_RETURN(layoutProperty, hintToTypeWrap);
2902     auto aceContentType =
2903         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
2904     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2905     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
2906         hintToTypeWrap.autoFillType = aceContentType;
2907         return hintToTypeWrap;
2908     }
2909     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
2910         hintToTypeWrap.autoFillType = aceInputType;
2911         return hintToTypeWrap;
2912     }
2913     if (isNeedToHitType && !IsTriggerAutoFillPassword()) {
2914         hintToTypeWrap = GetHintType();
2915         return hintToTypeWrap;
2916     }
2917     auto jsonValue = JsonUtil::Create(true);
2918     jsonValue->Put("type", TextInputTypeToString().c_str());
2919     hintToTypeWrap.metadata = jsonValue->ToString();
2920     return hintToTypeWrap;
2921 }
2922 
CheckAutoFill(bool isFromKeyBoard)2923 bool TextFieldPattern::CheckAutoFill(bool isFromKeyBoard)
2924 {
2925     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2926     CHECK_NULL_RETURN(layoutProperty, false);
2927     bool isEnableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
2928     if (!isEnableAutoFill) {
2929         return false;
2930     }
2931     return CheckAutoFillType(GetAutoFillType(), isFromKeyBoard);
2932 }
2933 
ProcessAutoFill(bool & isPopup,bool isFromKeyBoard,bool isNewPassWord)2934 bool TextFieldPattern::ProcessAutoFill(bool& isPopup, bool isFromKeyBoard, bool isNewPassWord)
2935 {
2936     if (!CheckAutoFill(isFromKeyBoard)) {
2937         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "don't need to auto fill.");
2938         return false;
2939     }
2940     auto host = GetHost();
2941     CHECK_NULL_RETURN(host, false);
2942     auto autoFillType = GetAutoFillType();
2943     auto container = Container::Current();
2944     if (container == nullptr) {
2945         TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "Get current container is nullptr.");
2946         return false;
2947     }
2948     if (IsTriggerAutoFillPassword() && autoFillType == AceAutoFillType::ACE_UNSPECIFIED) {
2949         autoFillType = AceAutoFillType::ACE_USER_NAME;
2950     }
2951     auto onUIExtNodeDestroy = [weak = WeakPtr<FrameNode>(host)]() {
2952         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "onUIExtNodeDestroy called.");
2953         auto textFieldNode = weak.Upgrade();
2954         CHECK_NULL_VOID(textFieldNode);
2955         auto pageNode = textFieldNode->GetPageNode();
2956         CHECK_NULL_VOID(pageNode);
2957         auto pagePattern = pageNode->GetPattern<PagePattern>();
2958         CHECK_NULL_VOID(pagePattern);
2959         pagePattern->SetIsModalCovered(false);
2960     };
2961     auto onUIExtNodeBindingCompleted = [weak = WeakPtr<FrameNode>(host)]() {
2962         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "onUIExtNodeBindingCompleted called.");
2963         auto textFieldNode = weak.Upgrade();
2964         CHECK_NULL_VOID(textFieldNode);
2965         auto pageNode = textFieldNode->GetPageNode();
2966         CHECK_NULL_VOID(pageNode);
2967         auto pagePattern = pageNode->GetPattern<PagePattern>();
2968         CHECK_NULL_VOID(pagePattern);
2969         pagePattern->SetIsModalCovered(true);
2970     };
2971 
2972     auto resultCode = container->RequestAutoFill(host, autoFillType, isNewPassWord, isPopup, autoFillSessionId_, true,
2973         onUIExtNodeDestroy, onUIExtNodeBindingCompleted);
2974     if (resultCode != AceAutoFillError::ACE_AUTO_FILL_PREVIOUS_REQUEST_NOT_FINISHED) {
2975         SetAutoFillTriggeredStateByType(autoFillType);
2976         SetFillRequestFinish(false);
2977     }
2978     return resultCode == AceAutoFillError::ACE_AUTO_FILL_SUCCESS;
2979 }
2980 
HandleDoubleClickEvent(GestureEvent & info)2981 void TextFieldPattern::HandleDoubleClickEvent(GestureEvent& info)
2982 {
2983     if (GetIsPreviewText()) {
2984         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "refuse double click when has preview text.");
2985         return;
2986     }
2987 
2988     if (showSelect_) {
2989         SetIsSingleHandle(true);
2990     }
2991     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::DOUBLE_CLICK)) {
2992         NotifyOnEditChanged(true);
2993     }
2994     if (CanChangeSelectState()) {
2995         selectController_->UpdateSelectByOffset(info.GetLocalLocation());
2996         UpdateCaretInfoToController();
2997     }
2998     if (IsSelected()) {
2999         StopTwinkling();
3000         SetIsSingleHandle(false);
3001     }
3002     if (info.GetSourceDevice() != SourceType::MOUSE && !IsContentRectNonPositive()) {
3003         ProcessOverlay({ .animation = true });
3004     }
3005     auto host = GetHost();
3006     CHECK_NULL_VOID(host);
3007     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3008 }
3009 
HandleTripleClickEvent(GestureEvent & info)3010 void TextFieldPattern::HandleTripleClickEvent(GestureEvent& info)
3011 {
3012     if (GetIsPreviewText()) {
3013         return;
3014     }
3015 
3016     if (showSelect_) {
3017         SetIsSingleHandle(true);
3018         CloseSelectOverlay();
3019     }
3020     if (CanChangeSelectState()) {
3021         selectController_->UpdateSelectPragraphByOffset(info.GetLocalLocation());
3022     }
3023     if (IsSelected()) {
3024         StopTwinkling();
3025         SetIsSingleHandle(false);
3026     } else {
3027         StartTwinkling();
3028     }
3029     if (info.GetSourceDevice() != SourceType::MOUSE && !contentController_->IsEmpty() && !IsContentRectNonPositive()) {
3030         ProcessOverlay({ .animation = true });
3031     }
3032     auto host = GetHost();
3033     CHECK_NULL_VOID(host);
3034     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3035 }
3036 
ScheduleCursorTwinkling()3037 void TextFieldPattern::ScheduleCursorTwinkling()
3038 {
3039     if (isTransparent_) {
3040         return;
3041     }
3042     auto host = GetHost();
3043     CHECK_NULL_VOID(host);
3044     auto context = host->GetContext();
3045     CHECK_NULL_VOID(context);
3046 
3047     if (!context->GetTaskExecutor()) {
3048         return;
3049     }
3050 
3051     if (dragRecipientStatus_ == DragStatus::DRAGGING) {
3052         return;
3053     }
3054 
3055     auto weak = WeakClaim(this);
3056     cursorTwinklingTask_.Reset([weak] {
3057         auto client = weak.Upgrade();
3058         CHECK_NULL_VOID(client);
3059         client->OnCursorTwinkling();
3060     });
3061     auto taskExecutor = context->GetTaskExecutor();
3062     CHECK_NULL_VOID(taskExecutor);
3063     taskExecutor->PostDelayedTask(cursorTwinklingTask_, TaskExecutor::TaskType::UI, twinklingInterval_,
3064         "ArkUITextFieldCursorTwinkling");
3065 }
3066 
StartTwinkling()3067 void TextFieldPattern::StartTwinkling()
3068 {
3069     if (isTransparent_ || !HasFocus() || focusIndex_ == FocuseIndex::CANCEL || focusIndex_ == FocuseIndex::UNIT) {
3070         return;
3071     }
3072     // Ignore the result because all ops are called on this same thread (ACE UI).
3073     // The only reason failed is that the task has finished.
3074     cursorTwinklingTask_.Cancel();
3075 
3076     // Show cursor right now.
3077     isCaretTwinkling_ = true;
3078     cursorVisible_ = true;
3079     auto tmpHost = GetHost();
3080     CHECK_NULL_VOID(tmpHost);
3081     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3082     ScheduleCursorTwinkling();
3083 }
3084 
OnCursorTwinkling()3085 void TextFieldPattern::OnCursorTwinkling()
3086 {
3087     cursorTwinklingTask_.Cancel();
3088     cursorVisible_ = !cursorVisible_;
3089     auto shouldMeasure = !IsTextArea() && IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ == 1;
3090     if (IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ > 0) {
3091         --obscureTickCountDown_;
3092     }
3093     auto host = GetHost();
3094     CHECK_NULL_VOID(host);
3095     if (shouldMeasure) {
3096         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3097     } else {
3098         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3099     }
3100     ScheduleCursorTwinkling();
3101 }
3102 
StopTwinkling()3103 void TextFieldPattern::StopTwinkling()
3104 {
3105     cursorTwinklingTask_.Cancel();
3106 
3107     // Repaint only if cursor is visible for now.
3108     isCaretTwinkling_ = false;
3109     auto tmpHost = GetHost();
3110     CHECK_NULL_VOID(tmpHost);
3111     if (cursorVisible_) {
3112         cursorVisible_ = false;
3113         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3114     }
3115     if (ResetObscureTickCountDown()) {
3116         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3117     }
3118 }
3119 
ShowCaretAndStopTwinkling()3120 void TextFieldPattern::ShowCaretAndStopTwinkling()
3121 {
3122     cursorTwinklingTask_.Cancel();
3123 
3124     // Repaint and make cursor visible.
3125     isCaretTwinkling_ = false;
3126     auto tmpHost = GetHost();
3127     CHECK_NULL_VOID(tmpHost);
3128     cursorVisible_ = true;
3129     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3130     if (ResetObscureTickCountDown()) {
3131         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3132     }
3133 }
3134 
CheckIfNeedToResetKeyboard()3135 void TextFieldPattern::CheckIfNeedToResetKeyboard()
3136 {
3137     auto tmpHost = GetHost();
3138     CHECK_NULL_VOID(tmpHost);
3139     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3140     CHECK_NULL_VOID(layoutProperty);
3141     bool needToResetKeyboard = false;
3142     // check unspecified  for first time entrance
3143     if (keyboard_ != layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
3144         auto autoFillType = GetAutoFillType(false);
3145         if (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) != TextInputType::UNSPECIFIED ||
3146             keyBoardMap_.find(autoFillType) == keyBoardMap_.end() || keyboard_ != keyBoardMap_[autoFillType]) {
3147             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Keyboard type %{public}d changed to %{public}d",
3148                 tmpHost->GetId(), (int)keyboard_, layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
3149             keyboard_ = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
3150             ResetPreviewTextState();
3151             needToResetKeyboard = true;
3152         }
3153     }
3154     if (!needToResetKeyboard && action_ != TextInputAction::UNSPECIFIED) {
3155         needToResetKeyboard = action_ != GetTextInputActionValue(GetDefaultTextInputAction());
3156     }
3157     action_ = GetTextInputActionValue(GetDefaultTextInputAction());
3158 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
3159     if (needToResetKeyboard && HasFocus()) {
3160         if (isCustomKeyboardAttached_) {
3161             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::RESET_KEYBOARD);
3162             return;
3163         }
3164 #if defined(ENABLE_STANDARD_INPUT)
3165         auto inputMethod = MiscServices::InputMethodController::GetInstance();
3166         CHECK_NULL_VOID(inputMethod);
3167         MiscServices::Configuration config;
3168         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Keyboard action is %{public}d",
3169             tmpHost->GetId(), action_);
3170         config.SetEnterKeyType(static_cast<MiscServices::EnterKeyType>(action_));
3171         config.SetTextInputType(static_cast<MiscServices::TextInputType>(keyboard_));
3172         inputMethod->OnConfigurationChange(config);
3173 #endif
3174     }
3175 #else
3176     if (needToResetKeyboard && HasConnection()) {
3177         CloseKeyboard(true);
3178         RequestKeyboard(false, true, true);
3179     }
3180 #endif
3181 }
3182 
ProcessScroll()3183 void TextFieldPattern::ProcessScroll()
3184 {
3185     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3186     CHECK_NULL_VOID(layoutProperty);
3187     if (IsTextArea() || IsNormalInlineState()) {
3188         SetAxis(Axis::VERTICAL);
3189         if (!GetScrollableEvent()) {
3190             AddScrollEvent();
3191         }
3192         auto barState = layoutProperty->GetDisplayModeValue(DisplayMode::AUTO);
3193         if (!barState_.has_value()) {
3194             barState_ = barState;
3195         }
3196         scrollBarVisible_ = barState != DisplayMode::OFF;
3197         SetScrollBar(barState == DisplayMode::OFF ? DisplayMode::ON : barState);
3198         auto scrollBar = GetScrollBar();
3199         if (scrollBar) {
3200             scrollBar->SetMinHeight(SCROLL_BAR_MIN_HEIGHT);
3201         }
3202         if (textFieldOverlayModifier_) {
3203             textFieldOverlayModifier_->SetScrollBar(scrollBar);
3204             UpdateScrollBarOffset();
3205         }
3206     } else {
3207         SetAxis(Axis::HORIZONTAL);
3208         SetScrollBar(DisplayMode::OFF);
3209         if (!GetScrollableEvent()) {
3210             AddScrollEvent();
3211             SetScrollEnabled(false);
3212         }
3213     }
3214 }
3215 
HandleDeleteOnCounterScene()3216 void TextFieldPattern::HandleDeleteOnCounterScene()
3217 {
3218     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3219     CHECK_NULL_VOID(layoutProperty);
3220     if (layoutProperty->HasMaxLength()) {
3221         showCountBorderStyle_ = false;
3222         HandleCountStyle();
3223     }
3224 }
3225 
HandleCountStyle()3226 void TextFieldPattern::HandleCountStyle()
3227 {
3228     bool noDeleteOperation = deleteBackwardOperations_.empty() && deleteForwardOperations_.empty();
3229     if (!IsShowCount() || !noDeleteOperation) {
3230         return;
3231     }
3232     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3233     CHECK_NULL_VOID(layoutProperty);
3234     auto inputValue = layoutProperty->GetSetCounterValue(DEFAULT_MODE);
3235     auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
3236     if (inputValue == DEFAULT_MODE) {
3237         if (showBorder) {
3238             HandleCounterBorder();
3239         }
3240         if (showCountBorderStyle_ && !showBorder) {
3241             UltralimitShake();
3242         }
3243     } else if (inputValue != ILLEGAL_VALUE) {
3244         if (showBorder) {
3245             HandleCounterBorder();
3246         }
3247         if (showCountBorderStyle_) {
3248             UltralimitShake();
3249         }
3250     }
3251 }
3252 
ProcessUnderlineColorOnModifierDone()3253 void TextFieldPattern::ProcessUnderlineColorOnModifierDone()
3254 {
3255     if (IsShowError()) {
3256         return;
3257     }
3258     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3259     auto inputValue = layoutProperty->GetSetCounterValue(DEFAULT_MODE);
3260     if (inputValue == ILLEGAL_VALUE) {
3261         return;
3262     }
3263     auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
3264     if (inputValue != DEFAULT_MODE && !showBorder) {
3265         return;
3266     }
3267     if (showCountBorderStyle_ && IsUnderlineMode() && HasFocus()) {
3268         auto theme = GetTheme();
3269         CHECK_NULL_VOID(theme);
3270         SetUnderlineColor(
3271             userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor()));
3272     }
3273 }
3274 
ProcessCounter()3275 void TextFieldPattern::ProcessCounter()
3276 {
3277     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3278     CHECK_NULL_VOID(layoutProperty);
3279     if (IsShowCount()) {
3280         AddCounterNode();
3281         CHECK_NULL_VOID(counterDecorator_);
3282         counterDecorator_->UpdateTextFieldMargin();
3283     } else {
3284         CleanCounterNode();
3285     }
3286 }
3287 
ProcessSelection()3288 void TextFieldPattern::ProcessSelection()
3289 {
3290     auto textWidth = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
3291     if (SelectOverlayIsOn()) {
3292         needToRefreshSelectOverlay_ = textWidth > 0;
3293         UpdateSelection(std::clamp(selectController_->GetStartIndex(), 0, textWidth),
3294             std::clamp(selectController_->GetEndIndex(), 0, textWidth));
3295         SetIsSingleHandle(!IsSelected());
3296         selectOverlay_->UpdateHandleColor();
3297         if (isTextChangedAtCreation_ && textWidth == 0) {
3298             CloseSelectOverlay();
3299             StartTwinkling();
3300         }
3301         if (!isTextChangedAtCreation_ && selectOverlay_->IsShowMouseMenu()) {
3302             needToRefreshSelectOverlay_ = false;
3303         }
3304         return;
3305     }
3306     if (HasFocus()) {
3307         if (IsGestureSelectingText()) {
3308             UpdateSelection(std::clamp(selectController_->GetStartIndex(), 0, textWidth),
3309                 std::clamp(selectController_->GetEndIndex(), 0, textWidth));
3310         }
3311         if (!IsSelected()) {
3312             StartTwinkling();
3313         }
3314         return;
3315     }
3316     needToRefreshSelectOverlay_ = false;
3317 }
3318 
OnModifyDone()3319 void TextFieldPattern::OnModifyDone()
3320 {
3321     Pattern::OnModifyDone();
3322     auto host = GetHost();
3323     CHECK_NULL_VOID(host);
3324     auto context = host->GetContext();
3325     CHECK_NULL_VOID(context);
3326     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3327     CHECK_NULL_VOID(layoutProperty);
3328     auto textFieldTheme = GetTheme();
3329     CHECK_NULL_VOID(textFieldTheme);
3330     directionKeysMoveFocusOut_ = textFieldTheme->GetDirectionKeysMoveFocusOut();
3331     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
3332     CHECK_NULL_VOID(paintProperty);
3333     CheckIfNeedToResetKeyboard();
3334     auto renderContext = host->GetRenderContext();
3335     CHECK_NULL_VOID(renderContext);
3336     auto textFieldPaintProperty = host->GetPaintPropertyPtr<TextFieldPaintProperty>();
3337     if (textFieldPaintProperty && textFieldPaintProperty->HasBorderColorFlagByUser()) {
3338         textFieldPaintProperty->UpdateBorderColorFlagByUser(
3339             renderContext->GetBorderColorValue(BorderColorProperty {}));
3340     }
3341     isTransparent_ = renderContext->GetOpacityValue(1.0f) == 0.0f;
3342     ApplyNormalTheme();
3343     ApplyUnderlineTheme();
3344     ApplyInlineTheme();
3345     ProcessInnerPadding();
3346     ProcessNumberOfLines();
3347 
3348     InitClickEvent();
3349     InitLongPressEvent();
3350     InitFocusEvent();
3351     InitMouseEvent();
3352     InitTouchEvent();
3353 
3354     SetAccessibilityAction();
3355     FilterInitializeText();
3356     InitDisableColor();
3357     ProcessResponseArea();
3358     if (!shiftFlag_) {
3359         InitDragEvent();
3360     }
3361     Register2DragDropManager();
3362     ProcessUnderlineColorOnModifierDone();
3363     if (!clipboard_ && context) {
3364         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
3365     }
3366     if (barState_.has_value() && barState_.value() != layoutProperty->GetDisplayModeValue(DisplayMode::AUTO) &&
3367         HasFocus() && IsNormalInlineState()) {
3368         lastTextRectY_ = textRect_.GetY();
3369     }
3370     if (!IsDisabled() && IsShowError()) {
3371         SetShowError();
3372     } else {
3373         CleanErrorNode();
3374     }
3375     // The textRect position can't be changed by only redraw.
3376     if (!initTextRect_) {
3377         auto border = GetBorderWidthProperty();
3378         textRect_.SetLeft(GetPaddingLeft() + GetBorderLeft(border));
3379         textRect_.SetTop(GetPaddingTop() + GetBorderTop(border));
3380         AdjustTextRectByCleanNode(textRect_);
3381         initTextRect_ = true;
3382     }
3383     CalculateDefaultCursor();
3384 
3385     ProcessSelection();
3386     isTextChangedAtCreation_ = false;
3387     if (layoutProperty->GetTypeChangedValue(false)) {
3388         layoutProperty->ResetTypeChanged();
3389         operationRecords_.clear();
3390         redoOperationRecords_.clear();
3391     }
3392     ProcessScroll();
3393     ProcessCounter();
3394     Register2DragDropManager();
3395     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
3396     if (autoFillContainerNode) {
3397         UpdateTextFieldInfo();
3398     }
3399     TriggerAvoidWhenCaretGoesDown();
3400     selectOverlay_->SetMenuTranslateIsSupport(IsShowTranslate());
3401     selectOverlay_->SetIsSupportMenuSearch(IsShowSearch());
3402     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3403     SetIsEnableSubWindowMenu();
3404     isModifyDone_ = true;
3405     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
3406         InitCancelButtonMouseEvent();
3407         InitPasswordButtonMouseEvent();
3408     }
3409 }
3410 
TriggerAvoidWhenCaretGoesDown()3411 void TextFieldPattern::TriggerAvoidWhenCaretGoesDown()
3412 {
3413     auto host = GetHost();
3414     CHECK_NULL_VOID(host);
3415     auto context = host->GetContext();
3416     CHECK_NULL_VOID(context);
3417     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
3418     if (context->UsingCaretAvoidMode() && HasFocus() && textFieldManager) {
3419         context->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
3420             auto textField = weak.Upgrade();
3421             CHECK_NULL_VOID(textField);
3422             auto textFieldManager = manager.Upgrade();
3423             CHECK_NULL_VOID(textFieldManager);
3424             auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
3425             auto lastCaretPos = textField->GetLastCaretPos();
3426             if (!lastCaretPos.has_value() || caretPos > lastCaretPos.value()) {
3427                 TAG_LOGI(ACE_KEYBOARD, "Caret Position Goes Down, Retrigger Avoid");
3428                 textField->TriggerAvoidOnCaretChange();
3429             }
3430         });
3431     }
3432 }
3433 
ApplyNormalTheme()3434 void TextFieldPattern::ApplyNormalTheme()
3435 {
3436     if (IsUnderlineMode() || IsInlineMode()) {
3437         return;
3438     }
3439     SetThemeAttr();
3440 }
3441 
OnAfterModifyDone()3442 void TextFieldPattern::OnAfterModifyDone()
3443 {
3444     auto host = GetHost();
3445     CHECK_NULL_VOID(host);
3446     auto inspectorId = host->GetInspectorId().value_or("");
3447     if (!inspectorId.empty()) {
3448         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3449         bool isPwdType = false;
3450         if (layoutProperty) {
3451             auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
3452             isPwdType = inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
3453                         inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
3454         }
3455         if (!isPwdType) {
3456             Recorder::NodeDataCache::Get().PutString(host, inspectorId, contentController_->GetTextValue());
3457         }
3458     }
3459 }
3460 
CalculateDefaultCursor()3461 void TextFieldPattern::CalculateDefaultCursor()
3462 {
3463     auto tmpHost = GetHost();
3464     CHECK_NULL_VOID(tmpHost);
3465     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3466     CHECK_NULL_VOID(layoutProperty);
3467     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
3468     CHECK_NULL_VOID(paintProperty);
3469     auto textFieldTheme = GetTheme();
3470     CHECK_NULL_VOID(textFieldTheme);
3471     float caretWidth = paintProperty->GetCursorWidth().has_value()
3472                            ? static_cast<float>(paintProperty->GetCursorWidthValue().ConvertToPx())
3473                            : static_cast<float>(textFieldTheme->GetCursorWidth().ConvertToPx());
3474     selectController_->UpdateCaretWidth(caretWidth);
3475     if (!contentController_->IsEmpty()) {
3476         return;
3477     }
3478     selectController_->UpdateCaretHeight(PreferredLineHeight());
3479 }
3480 
AutoFillValueChanged()3481 void TextFieldPattern::AutoFillValueChanged()
3482 {
3483     if (IsFillRequestFinish()) {
3484         return;
3485     }
3486     auto host = GetHost();
3487     CHECK_NULL_VOID(host);
3488     auto aceContentType = GetAutoFillType();
3489     auto container = Container::Current();
3490     CHECK_NULL_VOID(container);
3491     auto isValidType =
3492         (aceContentType >= AceAutoFillType::ACE_PASSWORD &&
3493         aceContentType <= AceAutoFillType::END) || IsAutoFillUserName(aceContentType);
3494     if (isValidType && CheckAutoFill()) {
3495         container->UpdatePopupUIExtension(host, autoFillSessionId_);
3496     }
3497 }
3498 
FireOnTextChangeEvent()3499 bool TextFieldPattern::FireOnTextChangeEvent()
3500 {
3501     auto host = GetHost();
3502     CHECK_NULL_RETURN(host, false);
3503     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3504     CHECK_NULL_RETURN(layoutProperty, false);
3505     auto textCache = layoutProperty->GetValueValue(u"");
3506     auto previewTextCache = layoutProperty->GetPreviewTextValue({GetPreviewTextStart(), u""});
3507     PreviewText curPreviewText = {GetPreviewTextStart(), GetPreviewTextValue()};
3508     if (textCache == contentController_->GetTextUtf16Value() && previewTextCache.value == curPreviewText.value) {
3509         return false;
3510     }
3511     ResetOriginCaretPosition();
3512     AutoFillValueChanged();
3513     auto pipeline = GetContext();
3514     CHECK_NULL_RETURN(pipeline, false);
3515     AddTextFireOnChange();
3516     auto context = host->GetContextRefPtr();
3517     CHECK_NULL_RETURN(context, false);
3518     auto taskExecutor = context->GetTaskExecutor();
3519     CHECK_NULL_RETURN(taskExecutor, false);
3520     taskExecutor->PostTask(
3521         [weak = WeakClaim(this)] {
3522             auto pattern = weak.Upgrade();
3523             CHECK_NULL_VOID(pattern);
3524             if (!pattern->HasFocus()) {
3525                 return;
3526             }
3527             pattern->ScrollToSafeArea();
3528             pattern->TriggerAvoidOnCaretChange();
3529             if (pattern->customKeyboard_ || pattern->customKeyboardBuilder_) {
3530                 pattern->StartTwinkling();
3531             }
3532         },
3533         TaskExecutor::TaskType::UI, "ArkUITextFieldScrollToSafeArea", PriorityType::VIP);
3534     return true;
3535 }
3536 
AddTextFireOnChange()3537 void TextFieldPattern::AddTextFireOnChange()
3538 {
3539     auto host = GetHost();
3540     CHECK_NULL_VOID(host);
3541     auto context = host->GetContextRefPtr();
3542     CHECK_NULL_VOID(context);
3543     context->AddAfterLayoutTask([weak = AceType::WeakClaim(this)] {
3544         auto pattern = weak.Upgrade();
3545         CHECK_NULL_VOID(pattern);
3546         auto host = pattern->GetHost();
3547         CHECK_NULL_VOID(host);
3548         auto eventHub = host->GetEventHub<TextFieldEventHub>();
3549         CHECK_NULL_VOID(eventHub);
3550         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3551         CHECK_NULL_VOID(layoutProperty);
3552         auto textCache = layoutProperty->GetValueValue(u"");
3553         auto newText = pattern->GetTextContentController()->GetTextUtf16Value();
3554         layoutProperty->UpdateValue(newText);
3555         host->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, UtfUtils::Str16DebugToStr8(textCache),
3556             UtfUtils::Str16DebugToStr8(newText));
3557         ChangeValueInfo changeValueInfo;
3558         changeValueInfo.value = pattern->GetBodyTextValue();
3559         changeValueInfo.previewText.offset = pattern->hasPreviewText_ ? pattern->GetPreviewTextStart() : -1;
3560         changeValueInfo.previewText.value = pattern->GetPreviewTextValue();
3561         changeValueInfo.oldPreviewText = pattern->callbackOldPreviewText_;
3562         changeValueInfo.oldContent = pattern->callbackOldContent_;
3563         changeValueInfo.rangeBefore = pattern->callbackRangeBefore_;
3564         changeValueInfo.rangeAfter = pattern->callbackRangeAfter_;
3565         layoutProperty->UpdatePreviewText(changeValueInfo.previewText);
3566         eventHub->FireOnChange(changeValueInfo);
3567 
3568         pattern->RecordTextInputEvent();
3569     });
3570 }
3571 
RecordTextInputEvent()3572 void TextFieldPattern::RecordTextInputEvent()
3573 {
3574     if (!Recorder::EventRecorder::Get().IsRecordEnable(Recorder::EventCategory::CATEGORY_TEXT_INPUT)) {
3575         return;
3576     }
3577     auto host = GetHost();
3578     CHECK_NULL_VOID(host);
3579     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3580     CHECK_NULL_VOID(layoutProperty);
3581     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
3582     auto isPwdType = inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
3583                      inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
3584     if (isPwdType) {
3585         return;
3586     }
3587     Recorder::EventParamsBuilder builder;
3588     builder.SetEventCategory(Recorder::EventCategory::CATEGORY_TEXT_INPUT)
3589         .SetEventType(Recorder::EventType::TEXT_INPUT)
3590         .SetId(host->GetInspectorId().value_or(""))
3591         .SetType(host->GetTag())
3592         .SetText(UtfUtils::Str16DebugToStr8(GetBodyTextValue()))
3593         .SetDescription(host->GetAutoEventParamValue(""))
3594         .SetHost(host);
3595     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
3596 }
3597 
FilterInitializeText()3598 void TextFieldPattern::FilterInitializeText()
3599 {
3600     if (HasInputOperation()) {
3601         return;
3602     }
3603     if (HasFocus()) {
3604         UpdateShowCountBorderStyle();
3605         if (showCountBorderStyle_) {
3606             HandleCountStyle();
3607         }
3608     }
3609     if (!contentController_->IsEmpty()) {
3610         auto originCaretIndex =
3611             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
3612         ChangeValueInfo changeValueInfo;
3613         changeValueInfo.oldContent = GetBodyTextValue();
3614         changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3615         changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
3616         changeValueInfo.rangeBefore = TextRange { 0, changeValueInfo.oldContent.length() };
3617         auto textChanged = contentController_->FilterValue();
3618         changeValueInfo.value = GetBodyTextValue();
3619         changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3620         changeValueInfo.previewText.value = GetPreviewTextValue();
3621         changeValueInfo.rangeAfter = TextRange { 0, changeValueInfo.value.length() };
3622         if (isFilterChanged_) {
3623             bool isWillChange = FireOnWillChange(changeValueInfo);
3624             isFilterChanged_ = false;
3625             if (!isWillChange) {
3626                 RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
3627                 return;
3628             }
3629         }
3630         if (!isTextChangedAtCreation_) {
3631             isTextChangedAtCreation_ = textChanged;
3632         }
3633     }
3634     if (static_cast<int32_t>(GetTextUtf16Value().length()) < GetCaretIndex()) {
3635         selectController_->UpdateCaretIndex(static_cast<int32_t>(GetTextUtf16Value().length()));
3636     }
3637     UpdateShowCountBorderStyle();
3638 }
3639 
IsDisabled()3640 bool TextFieldPattern::IsDisabled()
3641 {
3642     auto tmpHost = GetHost();
3643     CHECK_NULL_RETURN(tmpHost, true);
3644     auto eventHub = tmpHost->GetEventHub<TextFieldEventHub>();
3645     CHECK_NULL_RETURN(eventHub, true);
3646     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3647     CHECK_NULL_RETURN(layoutProperty, true);
3648     return !eventHub->IsEnabled();
3649 }
3650 
ProcessInnerPadding()3651 void TextFieldPattern::ProcessInnerPadding()
3652 {
3653     auto textFieldTheme = GetTheme();
3654     CHECK_NULL_VOID(textFieldTheme);
3655     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
3656     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3657     CHECK_NULL_VOID(layoutProperty);
3658     PaddingPropertyF utilPadding;
3659     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
3660     auto left = !paddingProperty ? CalcLength(themePadding.Left()).GetDimension()
3661                                  : paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension();
3662     utilPadding.left = left.ConvertToPx();
3663     auto top = !paddingProperty ? CalcLength(themePadding.Top()).GetDimension()
3664                                 : paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension();
3665     utilPadding.top = top.ConvertToPx();
3666     auto bottom = !paddingProperty ? CalcLength(themePadding.Bottom()).GetDimension()
3667                                    : paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension();
3668     utilPadding.bottom = bottom.ConvertToPx();
3669     auto right = !paddingProperty ? CalcLength(themePadding.Right()).GetDimension()
3670                                   : paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension();
3671     utilPadding.right = right.ConvertToPx();
3672     utilPadding_ = utilPadding;
3673     PaddingProperty paddings;
3674     paddings.top = NG::CalcLength(top);
3675     paddings.bottom = NG::CalcLength(bottom);
3676     paddings.left = NG::CalcLength(left);
3677     paddings.right = NG::CalcLength(right);
3678     layoutProperty->UpdatePadding(paddings);
3679 }
3680 
ProcessNumberOfLines()3681 void TextFieldPattern::ProcessNumberOfLines()
3682 {
3683     auto tmpHost = GetHost();
3684     CHECK_NULL_VOID(tmpHost);
3685     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3686     CHECK_NULL_VOID(layoutProperty && layoutProperty->HasNumberOfLines());
3687     auto numberOfLines = layoutProperty->GetNumberOfLines().value();
3688     CHECK_NULL_VOID(numberOfLines > 0);
3689     auto lineHeight = layoutProperty->GetLineHeight().value_or(0.0_vp).ConvertToPx();
3690     if (LessOrEqual(lineHeight, 0.f)) {
3691         lineHeight = PreferredLineHeight(false);
3692     }
3693     auto lineSpacing = layoutProperty->GetLineSpacing().value_or(0.0_vp).ConvertToPx();
3694     auto contentHeight = numberOfLines * lineHeight + numberOfLines * lineSpacing;
3695     auto height = contentHeight + GetVerticalPaddingAndBorderSum();
3696 
3697     // get previously user defined ideal width
3698     std::optional<CalcLength> width = std::nullopt;
3699     auto &&layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
3700     if (layoutConstraint && layoutConstraint->selfIdealSize) {
3701         width = layoutConstraint->selfIdealSize->Width();
3702     }
3703     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(width, CalcLength(height)));
3704 }
3705 
InitLongPressEvent()3706 void TextFieldPattern::InitLongPressEvent()
3707 {
3708     CHECK_NULL_VOID(!longPressEvent_);
3709     auto tmpHost = GetHost();
3710     CHECK_NULL_VOID(tmpHost);
3711     auto gesture = tmpHost->GetOrCreateGestureEventHub();
3712     auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
3713         auto pattern = weak.Upgrade();
3714         CHECK_NULL_VOID(pattern);
3715         pattern->selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
3716         pattern->selectOverlay_->SetLastSourceType(info.GetSourceDevice());
3717         pattern->HandleLongPress(info);
3718     };
3719     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
3720     gesture->SetLongPressEvent(longPressEvent_);
3721 }
3722 
StartVibratorByLongPress()3723 void TextFieldPattern::StartVibratorByLongPress()
3724 {
3725     CHECK_NULL_VOID(isEnableHapticFeedback_);
3726     VibratorUtils::StartVibraFeedback("longPress.light");
3727 }
3728 
HandleLongPress(GestureEvent & info)3729 void TextFieldPattern::HandleLongPress(GestureEvent& info)
3730 {
3731     CHECK_NULL_VOID(!IsDragging());
3732     CHECK_NULL_VOID(!IsHandleDragging());
3733     auto focusHub = GetFocusHub();
3734     CHECK_NULL_VOID(focusHub);
3735     if (!focusHub->IsFocusable() || IsOnUnitByPosition(info.GetLocalLocation()) || GetIsPreviewText() ||
3736         IsOnPasswordByPosition(info.GetLocalLocation()) || IsOnCleanNodeByPosition(info.GetLocalLocation())) {
3737         return;
3738     }
3739     moveCaretState_.isTouchCaret = false;
3740     auto host = GetHost();
3741     CHECK_NULL_VOID(host);
3742     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleLongPress %{public}d", host->GetId());
3743     if (ResetObscureTickCountDown()) {
3744         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3745     }
3746     if (info.GetSourceDevice() == SourceType::MOUSE) {
3747         return;
3748     }
3749     auto hub = host->GetEventHub<EventHub>();
3750     CHECK_NULL_VOID(hub);
3751     auto gestureHub = hub->GetOrCreateGestureEventHub();
3752     CHECK_NULL_VOID(gestureHub);
3753     StartVibratorByLongPress();
3754     if (BetweenSelectedPosition(info)) {
3755         gestureHub->SetIsTextDraggable(true);
3756         return;
3757     }
3758     gestureHub->SetIsTextDraggable(false);
3759     isLongPress_ = true;
3760     if (!focusHub->IsCurrentFocus()) {
3761         TextFieldRequestFocus(RequestFocusReason::LONG_PRESS);
3762     }
3763 
3764     auto localOffset = info.GetLocalLocation();
3765     if (CanChangeSelectState()) {
3766         selectController_->UpdateSelectWithBlank(localOffset);
3767         StopTwinkling();
3768     }
3769     SetIsSingleHandle(!IsSelected());
3770     auto start = selectController_->GetStartIndex();
3771     auto end = selectController_->GetEndIndex();
3772     CloseSelectOverlay();
3773     longPressFingerNum_ = info.GetFingerList().size();
3774     if (magnifierController_ && HasText() && (longPressFingerNum_ == 1)) {
3775         magnifierController_->SetLocalOffset({ localOffset.GetX(), localOffset.GetY() });
3776     }
3777     StartGestureSelection(start, end, localOffset);
3778     TriggerAvoidOnCaretChange();
3779     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3780 }
3781 
BetweenSelectedPosition(GestureEvent & info)3782 bool TextFieldPattern::BetweenSelectedPosition(GestureEvent& info)
3783 {
3784     if (!IsSelected()) {
3785         return false;
3786     }
3787     auto localOffset = info.GetLocalLocation();
3788     auto offsetX = IsTextArea() ? contentRect_.GetX() : textRect_.GetX();
3789     auto offsetY = IsTextArea() ? textRect_.GetY() : contentRect_.GetY();
3790     Offset offset = localOffset - Offset(offsetX, offsetY);
3791     for (const auto& rect : selectController_->GetSelectedRects()) {
3792         bool isInRange = rect.IsInRegion({ offset.GetX(), offset.GetY() });
3793         if (isInRange) {
3794             return true;
3795         }
3796     }
3797     return false;
3798 }
3799 
CanChangeSelectState()3800 bool TextFieldPattern::CanChangeSelectState()
3801 {
3802     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3803     CHECK_NULL_RETURN(layoutProperty, false);
3804     auto theme = GetTheme();
3805     CHECK_NULL_RETURN(theme, false);
3806     Dimension fontSize = layoutProperty->GetFontSizeValue(theme->GetFontSize());
3807     // fontSize == 0 can not change
3808     return !NearZero(fontSize.Value()) && !IsContentRectNonPositive();
3809 }
3810 
IsAccessibilityClick()3811 bool TextFieldPattern::IsAccessibilityClick()
3812 {
3813     auto host = GetHost();
3814     CHECK_NULL_RETURN(host, false);
3815     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
3816     CHECK_NULL_RETURN(accessibilityProperty, false);
3817     return accessibilityProperty->GetAccessibilityFocusState();
3818 }
3819 
IsOnUnitByPosition(const Offset & localOffset)3820 bool TextFieldPattern::IsOnUnitByPosition(const Offset& localOffset)
3821 {
3822     if (!IsShowUnit()) {
3823         return false;
3824     }
3825     auto unitArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
3826     CHECK_NULL_RETURN(unitArea, false);
3827     auto frameNode = unitArea->GetFrameNode();
3828     CHECK_NULL_RETURN(frameNode, false);
3829     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3830 }
3831 
IsOnPasswordByPosition(const Offset & localOffset)3832 bool TextFieldPattern::IsOnPasswordByPosition(const Offset& localOffset)
3833 {
3834     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
3835     CHECK_NULL_RETURN(passwordArea, false);
3836     auto frameNode = passwordArea->GetFrameNode();
3837     CHECK_NULL_RETURN(frameNode, false);
3838     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3839 }
3840 
IsOnCleanNodeByPosition(const Offset & localOffset)3841 bool TextFieldPattern::IsOnCleanNodeByPosition(const Offset& localOffset)
3842 {
3843     auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
3844     CHECK_NULL_RETURN(cleanNodeResponseArea, false);
3845     auto frameNode = cleanNodeResponseArea->GetFrameNode();
3846     CHECK_NULL_RETURN(frameNode, false);
3847     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3848 }
3849 
IsMouseOverScrollBar(const BaseEventInfo * info)3850 bool TextFieldPattern::IsMouseOverScrollBar(const BaseEventInfo* info)
3851 {
3852     CHECK_NULL_RETURN(GetScrollBar(), false);
3853     Point point;
3854     do {
3855         auto gestureEvent = TypeInfoHelper::DynamicCast<GestureEvent>(info);
3856         if (gestureEvent) {
3857             point = Point(gestureEvent->GetLocalLocation().GetX(), gestureEvent->GetLocalLocation().GetY());
3858             break;
3859         }
3860         auto mouseInfo = TypeInfoHelper::DynamicCast<MouseInfo>(info);
3861         if (mouseInfo) {
3862             point = Point(mouseInfo->GetLocalLocation().GetX(), mouseInfo->GetLocalLocation().GetY());
3863             break;
3864         }
3865         return false;
3866     } while (false);
3867     if (GetScrollBar()->NeedPaint() && GetScrollBar()->GetShapeMode() == ShapeMode::RECT) {
3868         auto barRect = GetScrollBar()->GetBarRect();
3869         auto mouseScrollbarRegionWidth = MOUSE_SCROLL_BAR_REGION_WIDTH.ConvertToPx();
3870         barRect.SetLeft(barRect.Left() + (barRect.Width() - mouseScrollbarRegionWidth));
3871         barRect.SetWidth(mouseScrollbarRegionWidth);
3872         barRect.SetHeight(frameRect_.Height());
3873         barRect.SetTop(0.0f);
3874         return barRect.IsInRegion(point);
3875     }
3876     return false;
3877 }
3878 
UpdateCaretPositionWithClamp(const int32_t & pos)3879 void TextFieldPattern::UpdateCaretPositionWithClamp(const int32_t& pos)
3880 {
3881     selectController_->UpdateCaretIndex(
3882         std::clamp(pos, 0, static_cast<int32_t>(contentController_->GetTextUtf16Value().length())));
3883 }
3884 
ProcessOverlay(const OverlayRequest & request)3885 void TextFieldPattern::ProcessOverlay(const OverlayRequest& request)
3886 {
3887     selectOverlay_->ProcessOverlay(request);
3888 }
3889 
DelayProcessOverlay(const OverlayRequest & request)3890 void TextFieldPattern::DelayProcessOverlay(const OverlayRequest& request)
3891 {
3892     processOverlayDelayTask_ = [weak = WeakClaim(this), request]() {
3893         auto pattern = weak.Upgrade();
3894         CHECK_NULL_VOID(pattern);
3895         pattern->ProcessOverlay(request);
3896     };
3897 }
3898 
CancelDelayProcessOverlay()3899 void TextFieldPattern::CancelDelayProcessOverlay()
3900 {
3901     if (processOverlayDelayTask_) {
3902         processOverlayDelayTask_ = nullptr;
3903     }
3904 }
3905 
AllowCopy()3906 bool TextFieldPattern::AllowCopy()
3907 {
3908     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3909     CHECK_NULL_RETURN(layoutProperty, false);
3910     return layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None && !IsInPasswordMode();
3911 }
3912 
OnDetachFromFrameNode(FrameNode * node)3913 void TextFieldPattern::OnDetachFromFrameNode(FrameNode* node)
3914 {
3915     CloseSelectOverlay();
3916     auto pipeline = node->GetContext();
3917     CHECK_NULL_VOID(pipeline);
3918     if (HasSurfaceChangedCallback()) {
3919         pipeline->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
3920     }
3921     if (HasSurfacePositionChangedCallback()) {
3922         pipeline->UnregisterSurfacePositionChangedCallback(surfacePositionChangedCallbackId_.value_or(-1));
3923     }
3924     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
3925     if (textFieldManager) {
3926         textFieldManager->ClearOnFocusTextField(node->GetId());
3927     }
3928     auto frameNode = WeakClaim(node);
3929     pipeline->RemoveFontNodeNG(frameNode);
3930     auto fontManager = pipeline->GetFontManager();
3931     if (fontManager) {
3932         fontManager->UnRegisterCallbackNG(frameNode);
3933         fontManager->RemoveVariationNodeNG(frameNode);
3934     }
3935     pipeline->RemoveWindowSizeChangeCallback(node->GetId());
3936     pipeline->RemoveOnAreaChangeNode(node->GetId());
3937 }
3938 
CloseSelectOverlay()3939 void TextFieldPattern::CloseSelectOverlay()
3940 {
3941     CloseSelectOverlay(false);
3942 }
3943 
CloseSelectOverlay(bool animation)3944 void TextFieldPattern::CloseSelectOverlay(bool animation)
3945 {
3946     selectOverlay_->CloseOverlay(animation, CloseReason::CLOSE_REASON_NORMAL);
3947     auto host = GetHost();
3948     CHECK_NULL_VOID(host);
3949     auto gesture = host->GetOrCreateGestureEventHub();
3950     gesture->AddTouchEvent(GetTouchListener());
3951 }
3952 
InitEditingValueText(std::u16string content)3953 void TextFieldPattern::InitEditingValueText(std::u16string content)
3954 {
3955     if (HasInputOperation()) {
3956         return;
3957     }
3958     contentController_->SetTextValueOnly(std::move(content));
3959     selectController_->UpdateCaretIndex(GetTextUtf16Value().length());
3960     if (GetIsPreviewText() && GetTextUtf16Value().empty()) {
3961         FinishTextPreviewOperation();
3962     }
3963     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
3964 }
3965 
InitValueText(std::u16string content)3966 bool TextFieldPattern::InitValueText(std::u16string content)
3967 {
3968     if (GetIsPreviewText()) {
3969         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Init when has previewText");
3970         return false;
3971     }
3972     if (HasInputOperation() && content != u"") {
3973         return false;
3974     }
3975     ChangeValueInfo changeValueInfo;
3976     changeValueInfo.oldContent = GetBodyTextValue();
3977     changeValueInfo.value = content;
3978     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3979     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
3980     changeValueInfo.previewText = changeValueInfo.oldPreviewText;
3981     changeValueInfo.rangeBefore = TextRange { 0, changeValueInfo.oldContent.length() };
3982     changeValueInfo.rangeAfter = TextRange { 0, content.length() };
3983     bool isWillChange = FireOnWillChange(changeValueInfo);
3984     if (!isWillChange) {
3985         return false;
3986     }
3987     contentController_->SetTextValueOnly(std::move(content));
3988     selectController_->UpdateCaretIndex(GetTextUtf16Value().length());
3989     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
3990     return true;
3991 }
3992 
InitMouseEvent()3993 void TextFieldPattern::InitMouseEvent()
3994 {
3995     CHECK_NULL_VOID(!mouseEvent_ || !hoverEvent_);
3996     auto tmpHost = GetHost();
3997     CHECK_NULL_VOID(tmpHost);
3998     auto eventHub = tmpHost->GetEventHub<TextFieldEventHub>();
3999     auto inputHub = eventHub->GetOrCreateInputEventHub();
4000 
4001     auto mouseTask = [weak = WeakClaim(this)](MouseInfo& info) {
4002         auto pattern = weak.Upgrade();
4003         if (pattern) {
4004             pattern->HandleMouseEvent(info);
4005             if (info.GetButton() == MouseButton::LEFT_BUTTON && info.GetAction() == MouseAction::PRESS) {
4006                 pattern->hasMousePressed_ = true;
4007             } else {
4008                 pattern->hasMousePressed_ = false;
4009             }
4010         }
4011     };
4012     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
4013     inputHub->AddOnMouseEvent(mouseEvent_);
4014 
4015     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
4016         auto pattern = weak.Upgrade();
4017         if (pattern) {
4018             pattern->OnHover(isHover);
4019         }
4020     };
4021     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
4022     inputHub->AddOnHoverEvent(hoverEvent_);
4023     InitPanEvent();
4024 }
4025 
InitPanEvent()4026 void TextFieldPattern::InitPanEvent()
4027 {
4028     auto host = GetHost();
4029     CHECK_NULL_VOID(host);
4030     auto gestureHub = host->GetOrCreateGestureEventHub();
4031     CHECK_NULL_VOID(gestureHub);
4032     if (!boxSelectPanEvent_) {
4033         auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
4034         auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
4035         auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
4036         GestureEventNoParameter actionCancelTask;
4037         boxSelectPanEvent_ = MakeRefPtr<PanEvent>(std::move(actionStartTask), std::move(actionUpdateTask),
4038             std::move(actionEndTask), std::move(actionCancelTask));
4039     }
4040     PanDirection panDirection = { .type = PanDirection::ALL };
4041     gestureHub->AddPanEvent(boxSelectPanEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
4042     gestureHub->SetPanEventType(GestureTypeName::TEXTFIELD_BOXSELECT);
4043     gestureHub->SetOnGestureJudgeNativeBegin([weak = WeakClaim(this)](const RefPtr<NG::GestureInfo>& gestureInfo,
4044                                                  const std::shared_ptr<BaseGestureEvent>& info) -> GestureJudgeResult {
4045         if (gestureInfo->GetType() == GestureTypeName::BOXSELECT &&
4046             gestureInfo->GetInputEventType() == InputEventType::MOUSE_BUTTON) {
4047             return GestureJudgeResult::REJECT;
4048         }
4049         auto pattern = weak.Upgrade();
4050         CHECK_NULL_RETURN(pattern, GestureJudgeResult::CONTINUE);
4051         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
4052             gestureInfo->GetInputEventType() == InputEventType::TOUCH_SCREEN &&
4053             pattern->moveCaretState_.isMoveCaret) {
4054             return GestureJudgeResult::CONTINUE;
4055         }
4056         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
4057             gestureInfo->GetInputEventType() != InputEventType::MOUSE_BUTTON) {
4058             return GestureJudgeResult::REJECT;
4059         }
4060         auto host = pattern->GetHost();
4061         CHECK_NULL_RETURN(host, GestureJudgeResult::CONTINUE);
4062         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
4063             gestureInfo->GetInputEventType() == InputEventType::MOUSE_BUTTON &&
4064             host->IsDraggable() && pattern->IsPressSelectedBox()) {
4065             return GestureJudgeResult::REJECT;
4066         }
4067         if (pattern->GetCancelButtonTouchInfo()) {
4068             return GestureJudgeResult::REJECT;
4069         }
4070         return GestureJudgeResult::CONTINUE;
4071     });
4072 }
4073 
OnHover(bool isHover)4074 void TextFieldPattern::OnHover(bool isHover)
4075 {
4076     auto frame = GetHost();
4077     CHECK_NULL_VOID(frame);
4078     auto frameId = frame->GetId();
4079     auto pipeline = frame->GetContext();
4080     auto textFieldTheme = GetTheme();
4081     if (!pipeline || !textFieldTheme) {
4082         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield %{public}d hover can't get pipeline",
4083             frame->GetId());
4084         return;
4085     }
4086     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield %{public}d %{public}s", frame->GetId(),
4087         isHover ? "on hover" : "exit hover");
4088     pipeline->SetMouseStyleHoldNode(frameId);
4089     if (!isHover) {
4090         int32_t windowId = 0;
4091 #ifdef WINDOW_SCENE_SUPPORTED
4092         windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4093 #endif
4094         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT, windowId);
4095         pipeline->FreeMouseStyleHoldNode(frameId);
4096     }
4097     UpdateHoverStyle(isHover);
4098     isOnHover_ = isHover;
4099 }
4100 
UpdateHoverStyle(bool isHover)4101 void TextFieldPattern::UpdateHoverStyle(bool isHover)
4102 {
4103     if (!hoverAndPressBgColorEnabled_) {
4104         return;
4105     }
4106     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4107     CHECK_NULL_VOID(paintProperty);
4108     auto theme = GetTheme();
4109     CHECK_NULL_VOID(theme);
4110     auto defaultThemeBgColor = theme->GetBgColor();
4111     auto textFieldBgColor = paintProperty->GetBackgroundColorValue(defaultThemeBgColor);
4112     auto bgColor = textFieldBgColor;
4113     if (textFieldBgColor == defaultThemeBgColor) {
4114         bgColor = IsUnderlineMode() ? Color::TRANSPARENT : defaultThemeBgColor;
4115     }
4116     auto hoverColor = bgColor.BlendColor(theme->GetPressColor());
4117     if (!HasFocus()) {
4118         if (isHover) {
4119             PlayAnimationHoverAndPress(hoverColor);
4120         } else {
4121             PlayAnimationHoverAndPress(bgColor);
4122         }
4123     }
4124 }
4125 
UpdatePressStyle(bool isPressed)4126 void TextFieldPattern::UpdatePressStyle(bool isPressed)
4127 {
4128     if (!hoverAndPressBgColorEnabled_) {
4129         return;
4130     }
4131     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4132     CHECK_NULL_VOID(paintProperty);
4133     auto theme = GetTheme();
4134     CHECK_NULL_VOID(theme);
4135     auto defaultThemeBgColor = theme->GetBgColor();
4136     auto textFieldBgColor = paintProperty->GetBackgroundColorValue(defaultThemeBgColor);
4137     auto bgColor = textFieldBgColor;
4138     if (textFieldBgColor == defaultThemeBgColor) {
4139         if (IsUnderlineMode()) {
4140             bgColor = Color::TRANSPARENT;
4141         } else {
4142             bgColor = HasFocus() ? theme->GetFocusBgColor() : defaultThemeBgColor;
4143         }
4144     }
4145     auto pressColor = bgColor.BlendColor(theme->GetHoverColor());
4146     if (isPressed) {
4147         PlayAnimationHoverAndPress(pressColor);
4148     } else {
4149         PlayAnimationHoverAndPress(bgColor);
4150     }
4151 }
4152 
PlayAnimationHoverAndPress(const Color & color)4153 void TextFieldPattern::PlayAnimationHoverAndPress(const Color& color)
4154 {
4155     AnimationOption option = AnimationOption();
4156     option.SetDuration(HOVER_ANIMATION_DURATION);
4157     option.SetCurve(Curves::FRICTION);
4158     AnimationUtils::Animate(option, [weak = AceType::WeakClaim(this), color]() {
4159         auto textFieldPattern = weak.Upgrade();
4160         CHECK_NULL_VOID(textFieldPattern);
4161         textFieldPattern->UpdateTextFieldBgColor(color);
4162     });
4163 }
4164 
UpdateTextFieldBgColor(const Color & color)4165 void TextFieldPattern::UpdateTextFieldBgColor(const Color& color)
4166 {
4167     auto host = GetHost();
4168     CHECK_NULL_VOID(host);
4169     auto renderContext = host->GetRenderContext();
4170     CHECK_NULL_VOID(renderContext);
4171     renderContext->UpdateBackgroundColor(color);
4172     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4173 }
4174 
RestoreDefaultMouseState()4175 void TextFieldPattern::RestoreDefaultMouseState()
4176 {
4177     int32_t windowId = 0;
4178 #ifdef WINDOW_SCENE_SUPPORTED
4179     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4180 #endif
4181     auto host = GetHost();
4182     CHECK_NULL_VOID(host);
4183     auto pipeline = host->GetContextRefPtr();
4184     CHECK_NULL_VOID(pipeline);
4185     auto id = host->GetId();
4186     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "RestoreDefaultMouseState id:%{public}d, winId:%{public}d", id, windowId);
4187     pipeline->SetMouseStyleHoldNode(id);
4188     pipeline->ChangeMouseStyle(id, MouseFormat::DEFAULT, windowId);
4189 }
4190 
ChangeMouseState(const Offset location,int32_t frameId,bool isByPass)4191 void TextFieldPattern::ChangeMouseState(
4192     const Offset location, int32_t frameId, bool isByPass)
4193 {
4194     auto host = GetHost();
4195     CHECK_NULL_VOID(host);
4196     auto pipeline = host->GetContext();
4197     CHECK_NULL_VOID(pipeline);
4198     auto responseAreaWidth = (responseArea_ ? responseArea_->GetAreaRect().Width() : 0.0f) +
4199                              (cleanNodeResponseArea_ ? cleanNodeResponseArea_->GetAreaRect().Width() : 0.0f);
4200     auto x = location.GetX();
4201     auto y = location.GetY();
4202     int32_t windowId = 0;
4203 #ifdef WINDOW_SCENE_SUPPORTED
4204     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4205 #endif
4206     if (GreatNotEqual(x, 0) && LessNotEqual(x, frameRect_.Width()) && GreatNotEqual(y, 0) &&
4207         LessNotEqual(y, frameRect_.Height())) {
4208         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4209         CHECK_NULL_VOID(layoutProperty);
4210         auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
4211         if (!isRTL && GreatNotEqual(location.GetX(), frameRect_.Width() - responseAreaWidth)) {
4212             RestoreDefaultMouseState();
4213         } else if (isRTL && LessNotEqual(location.GetX(), responseAreaWidth)) {
4214             RestoreDefaultMouseState();
4215         } else {
4216             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "ChangeMouseState Id:%{public}d, winId:%{public}d", frameId, windowId);
4217             pipeline->SetMouseStyleHoldNode(frameId);
4218             pipeline->ChangeMouseStyle(frameId, MouseFormat::TEXT_CURSOR, windowId, isByPass);
4219         }
4220     } else {
4221         RestoreDefaultMouseState();
4222     }
4223 }
4224 
HandleMouseEvent(MouseInfo & info)4225 void TextFieldPattern::HandleMouseEvent(MouseInfo& info)
4226 {
4227     CHECK_NULL_VOID(!IsDragging());
4228     auto tmpHost = GetHost();
4229     CHECK_NULL_VOID(tmpHost);
4230     auto frameId = tmpHost->GetId();
4231     auto pipeline = tmpHost->GetContext();
4232     CHECK_NULL_VOID(pipeline);
4233     info.SetStopPropagation(true);
4234     selectOverlay_->SetLastSourceType(info.GetSourceDevice());
4235     auto scrollBar = GetScrollBar();
4236     int32_t windowId = 0;
4237 #ifdef WINDOW_SCENE_SUPPORTED
4238     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4239 #endif
4240     if (scrollBar && (scrollBar->IsPressed() || scrollBar->IsHover() || IsMouseOverScrollBar(&info))) {
4241         pipeline->SetMouseStyleHoldNode(frameId);
4242         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT, windowId);
4243         return;
4244     }
4245     ChangeMouseState(info.GetLocalLocation(), frameId, info.GetAction() == MouseAction::WINDOW_LEAVE);
4246 
4247     if (info.GetAction() == OHOS::Ace::MouseAction::PRESS) {
4248         selectOverlay_->SetUsingMouse(true);
4249     }
4250     if (info.GetButton() == MouseButton::RIGHT_BUTTON) {
4251         HandleRightMouseEvent(info);
4252     } else if (info.GetButton() == MouseButton::LEFT_BUTTON) {
4253         HandleLeftMouseEvent(info);
4254         if (IsSelected()) {
4255             selectOverlay_->SetSelectionHoldCallback();
4256         }
4257     }
4258     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
4259         selectOverlay_->SetUsingMouse(false);
4260     }
4261     if (!IsSelected()) {
4262         ResetOriginCaretPosition();
4263     }
4264 }
4265 
HandleRightMouseEvent(MouseInfo & info)4266 void TextFieldPattern::HandleRightMouseEvent(MouseInfo& info)
4267 {
4268     if (info.GetAction() == OHOS::Ace::MouseAction::PRESS) {
4269         HandleRightMousePressEvent(info);
4270         return;
4271     }
4272     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
4273         HandleRightMouseReleaseEvent(info);
4274     }
4275 }
4276 
HandleRightMousePressEvent(MouseInfo & info)4277 void TextFieldPattern::HandleRightMousePressEvent(MouseInfo& info)
4278 {
4279     if (IsSelected() || GetIsPreviewText()) {
4280         return;
4281     }
4282     auto focusHub = GetFocusHub();
4283     if (!focusHub->IsFocusable()) {
4284         return;
4285     }
4286     FocusAndUpdateCaretByMouse(info);
4287 }
4288 
HandleRightMouseReleaseEvent(MouseInfo & info)4289 void TextFieldPattern::HandleRightMouseReleaseEvent(MouseInfo& info)
4290 {
4291     if (GetIsPreviewText()) {
4292         return;
4293     }
4294     auto focusHub = GetFocusHub();
4295     if (focusHub->IsCurrentFocus()) {
4296         OffsetF rightClickOffset = OffsetF(
4297             static_cast<float>(info.GetGlobalLocation().GetX()), static_cast<float>(info.GetGlobalLocation().GetY()));
4298         selectOverlay_->SetMouseMenuOffset(rightClickOffset);
4299         ProcessOverlay();
4300     }
4301 }
4302 
HandleLeftMouseEvent(MouseInfo & info)4303 void TextFieldPattern::HandleLeftMouseEvent(MouseInfo& info)
4304 {
4305     switch (info.GetAction()) {
4306         case OHOS::Ace::MouseAction::PRESS: {
4307             HandleLeftMousePressEvent(info);
4308             break;
4309         }
4310         case OHOS::Ace::MouseAction::MOVE: {
4311             HandleLeftMouseMoveEvent(info); // 注意鼠标拖拽的滚动效果
4312             break;
4313         }
4314         case OHOS::Ace::MouseAction::RELEASE: {
4315             HandleLeftMouseReleaseEvent(info);
4316             break;
4317         }
4318         default: {
4319         }
4320     }
4321 }
4322 
HandleLeftMousePressEvent(MouseInfo & info)4323 void TextFieldPattern::HandleLeftMousePressEvent(MouseInfo& info)
4324 {
4325     isPressSelectedBox_ =
4326         (IsSelected() && BetweenSelectedPosition(info.GetGlobalLocation()) && !shiftFlag_);
4327     if (isPressSelectedBox_ || GetIsPreviewText()) {
4328         blockPress_ = true;
4329         return;
4330     }
4331     auto focusHub = GetFocusHub();
4332     if (!focusHub->IsFocusable()) {
4333         return;
4334     }
4335     mouseStatus_ = MouseStatus::PRESSED;
4336     blockPress_ = false;
4337     leftMouseCanMove_ = true;
4338     FocusAndUpdateCaretByMouse(info);
4339 }
4340 
FocusAndUpdateCaretByMouse(MouseInfo & info)4341 void TextFieldPattern::FocusAndUpdateCaretByMouse(MouseInfo& info)
4342 {
4343     auto focusHub = GetFocusHub();
4344     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4345     CHECK_NULL_VOID(paintProperty);
4346     if (!focusHub->IsFocusOnTouch().value_or(true) || !TextFieldRequestFocus(RequestFocusReason::MOUSE)) {
4347         StopTwinkling();
4348         return;
4349     }
4350     UpdateCaretByClick(info.GetLocalLocation());
4351     auto tmpHost = GetHost();
4352     CHECK_NULL_VOID(tmpHost);
4353     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4354 }
4355 
UpdateShiftFlag(const KeyEvent & keyEvent)4356 void TextFieldPattern::UpdateShiftFlag(const KeyEvent& keyEvent)
4357 {
4358     bool flag = false;
4359     if (keyEvent.action == KeyAction::DOWN) {
4360         if (keyEvent.HasKey(KeyCode::KEY_SHIFT_LEFT) || keyEvent.HasKey(KeyCode::KEY_SHIFT_RIGHT)) {
4361             flag = true;
4362         }
4363     }
4364     if (flag != shiftFlag_) {
4365         shiftFlag_ = flag;
4366         if (!shiftFlag_) {
4367             // open drag
4368             InitDragEvent();
4369         } else  {
4370             // close drag
4371             ClearDragDropEvent();
4372         }
4373     }
4374 }
4375 
UpdateCaretByClick(const Offset & localOffset)4376 void TextFieldPattern::UpdateCaretByClick(const Offset& localOffset)
4377 {
4378     if (shiftFlag_) {
4379         selectController_->UpdateSecondHandleInfoByMouseOffset(localOffset);
4380         StopTwinkling();
4381     } else {
4382         selectController_->UpdateCaretInfoByOffset(localOffset, true, false);
4383         StartTwinkling();
4384     }
4385 }
4386 
HandleLeftMouseMoveEvent(MouseInfo & info)4387 void TextFieldPattern::HandleLeftMouseMoveEvent(MouseInfo& info)
4388 {
4389     if (!leftMouseCanMove_ || blockPress_) {
4390         return;
4391     }
4392     auto focusHub = GetFocusHub();
4393     if (!focusHub->IsCurrentFocus()) {
4394         return;
4395     }
4396     mouseStatus_ = MouseStatus::MOVE;
4397     if (GetTextUtf16Value().empty()) {
4398         return;
4399     }
4400     selectController_->UpdateSecondHandleInfoByMouseOffset(info.GetLocalLocation()); // 更新时上报事件
4401     showSelect_ = true;
4402     auto tmpHost = GetHost();
4403     CHECK_NULL_VOID(tmpHost);
4404     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4405 }
4406 
HandleLeftMouseReleaseEvent(MouseInfo & info)4407 void TextFieldPattern::HandleLeftMouseReleaseEvent(MouseInfo& info)
4408 {
4409     auto tmpHost = GetHost();
4410     CHECK_NULL_VOID(tmpHost);
4411     if (blockPress_ && mouseStatus_ == MouseStatus::PRESSED) {
4412         selectController_->UpdateCaretInfoByOffset(info.GetLocalLocation(), true, false);
4413         StartTwinkling();
4414         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4415     }
4416     FreeMouseStyleHoldNode(info.GetLocalLocation());
4417     mouseStatus_ = MouseStatus::NONE;
4418     blockPress_ = false;
4419     leftMouseCanMove_ = false;
4420     if (HasFocus() && RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::MOUSE_RELEASE)) {
4421         NotifyOnEditChanged(true);
4422         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4423     }
4424 }
4425 
FreeMouseStyleHoldNode(const Offset location)4426 void TextFieldPattern::FreeMouseStyleHoldNode(const Offset location)
4427 {
4428     auto rect = RectF(0.0f, 0.0f, frameRect_.Width(), frameRect_.Height());
4429     if (!location.IsPositiveOffset() || !rect.IsInRegion({ location.GetX(), location.GetY() })) {
4430         auto tmpHost = GetHost();
4431         CHECK_NULL_VOID(tmpHost);
4432         auto frameId = tmpHost->GetId();
4433         auto pipeline = GetContext();
4434         CHECK_NULL_VOID(pipeline);
4435         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "FreeMouseStyleHoldNode, id:%{public}d", frameId);
4436         pipeline->FreeMouseStyleHoldNode(frameId);
4437     }
4438 }
4439 
UpdateTextFieldManager(const Offset & offset,float height)4440 void TextFieldPattern::UpdateTextFieldManager(const Offset& offset, float height)
4441 {
4442     auto tmpHost = GetHost();
4443     CHECK_NULL_VOID(tmpHost);
4444     auto context = tmpHost->GetContextRefPtr();
4445     CHECK_NULL_VOID(context);
4446     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
4447     CHECK_NULL_VOID(textFieldManager);
4448     auto safeAreaManager = context->GetSafeAreaManager();
4449     CHECK_NULL_VOID(safeAreaManager);
4450     textFieldManager->UpdateScrollableParentViewPort(tmpHost);
4451     if (!HasFocus()) {
4452         return;
4453     }
4454     textFieldManager->SetClickPosition({ offset.GetX() + selectController_->GetCaretRect().GetX(),
4455         offset.GetY() + selectController_->GetCaretRect().GetY() });
4456     textFieldManager->SetHeight(selectController_->GetCaretRect().Height());
4457     textFieldManager->SetClickPositionOffset(safeAreaManager->GetKeyboardOffset());
4458     textFieldManager->SetOnFocusTextField(WeakClaim(this));
4459     textFieldManager->SetUsingCustomKeyboardAvoid(keyboardAvoidance_);
4460     textFieldManager->SetIfFocusTextFieldIsInline(IsNormalInlineState());
4461 }
4462 
GetDefaultTextInputAction() const4463 TextInputAction TextFieldPattern::GetDefaultTextInputAction() const
4464 {
4465     TextInputAction defaultTextInputAction = TextInputAction::DONE;
4466     if (IsTextArea() && !isTextInput_) {
4467         defaultTextInputAction = TextInputAction::NEW_LINE;
4468     } else {
4469         defaultTextInputAction = TextInputAction::DONE;
4470     }
4471     return defaultTextInputAction;
4472 }
4473 
4474 #ifdef WINDOW_SCENE_SUPPORTED
GetSCBSystemWindowId()4475 uint32_t TextFieldPattern::GetSCBSystemWindowId()
4476 {
4477     RefPtr<FrameNode> frameNode = GetHost();
4478     CHECK_NULL_RETURN(frameNode, {});
4479     auto focusSystemWindowId = WindowSceneHelper::GetFocusSystemWindowId(frameNode);
4480     return focusSystemWindowId;
4481 }
4482 #endif
4483 
KeyboardContentTypeToInputType()4484 void TextFieldPattern::KeyboardContentTypeToInputType()
4485 {
4486     if (keyboard_ != TextInputType::UNSPECIFIED) {
4487         return;
4488     }
4489     auto autoFillType = GetAutoFillType(false);
4490     if (keyBoardMap_.find(autoFillType) != keyBoardMap_.end()) {
4491         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
4492             "Set InputType to %{public}d because of contentType", keyBoardMap_[autoFillType]);
4493         keyboard_ = keyBoardMap_[autoFillType];
4494     }
4495 }
4496 
GetRequestKeyboardId()4497 int32_t TextFieldPattern::GetRequestKeyboardId()
4498 {
4499     auto host = GetHost();
4500     CHECK_NULL_RETURN(host, -1);
4501     return host->GetId();
4502 }
4503 
RequestKeyboard(bool isFocusViewChanged,bool needStartTwinkling,bool needShowSoftKeyboard,SourceType sourceType)4504 bool TextFieldPattern::RequestKeyboard(bool isFocusViewChanged, bool needStartTwinkling, bool needShowSoftKeyboard,
4505     SourceType sourceType)
4506 {
4507     bool isFocus = HasFocus();
4508     if (!showKeyBoardOnFocus_ || !isFocus) {
4509         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "showKeyBoardOnFocus:%{public}d, isFocus:%{public}d", showKeyBoardOnFocus_,
4510             isFocus);
4511         return false;
4512     }
4513     auto tmpHost = GetHost();
4514     CHECK_NULL_RETURN(tmpHost, false);
4515     if (customKeyboard_ || customKeyboardBuilder_) {
4516         CHECK_NULL_RETURN(needShowSoftKeyboard, true);
4517         return RequestCustomKeyboard();
4518     }
4519     bool ok = true;
4520     KeyboardContentTypeToInputType();
4521 #if defined(ENABLE_STANDARD_INPUT)
4522     if (textChangeListener_ == nullptr) {
4523         textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
4524     }
4525     auto inputMethod = MiscServices::InputMethodController::GetInstance();
4526     if (!inputMethod) {
4527         TAG_LOGE(AceLogTag::ACE_TEXT_FIELD, "RequestKeyboard, inputMethod is null");
4528         return false;
4529     }
4530     auto optionalTextConfig = GetMiscTextConfig();
4531     CHECK_NULL_RETURN(optionalTextConfig.has_value(), false);
4532     MiscServices::TextConfig textConfig = optionalTextConfig.value();
4533     ACE_LAYOUT_SCOPED_TRACE("RequestKeyboard[id:%d][WId:%u]", tmpHost->GetId(), textConfig.windowId);
4534     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
4535         "node:%{public}d, RequestKeyboard set calling window id:%{public}u"
4536         " inputType:%{public}d, enterKeyType:%{public}d, needKeyboard:%{public}d, sourceType:%{public}u",
4537         tmpHost->GetId(), textConfig.windowId, textConfig.inputAttribute.inputPattern,
4538         textConfig.inputAttribute.enterKeyType, needShowSoftKeyboard, sourceType);
4539 #ifdef WINDOW_SCENE_SUPPORTED
4540     auto systemWindowId = GetSCBSystemWindowId();
4541     if (systemWindowId) {
4542         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "windowId From %{public}u to %{public}u.", textConfig.windowId,
4543             systemWindowId);
4544         textConfig.windowId = systemWindowId;
4545     }
4546 #endif
4547     if ((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_) {
4548         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Request SoftKeyboard, Close CustomKeyboard.");
4549         CloseCustomKeyboard();
4550     }
4551     auto context = tmpHost->GetContextRefPtr();
4552     if (context && context->GetTextFieldManager()) {
4553         auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
4554         textFieldManager->SetImeAttached(true);
4555         textFieldManager->SetLastRequestKeyboardId(GetRequestKeyboardId());
4556     }
4557     OHOS::MiscServices::AttachOptions attachOptions;
4558     attachOptions.isShowKeyboard = needShowSoftKeyboard;
4559     attachOptions.requestKeyboardReason =
4560         static_cast<OHOS::MiscServices::RequestKeyboardReason>(static_cast<int32_t>(sourceType));
4561     auto ret = inputMethod->Attach(textChangeListener_, attachOptions, textConfig);
4562     if (ret == MiscServices::ErrorCode::NO_ERROR) {
4563         auto pipeline = GetContext();
4564         CHECK_NULL_RETURN(pipeline, false);
4565         auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
4566         CHECK_NULL_RETURN(textFieldManager, false);
4567         textFieldManager->SetIsImeAttached(true);
4568     }
4569     UpdateCaretInfoToController(true);
4570     if (!fillContentMap_.empty()) {
4571         inputMethod->SendPrivateCommand(fillContentMap_);
4572         fillContentMap_.clear();
4573     }
4574 #else
4575     ok = RequestKeyboardCrossPlatForm(isFocusViewChanged);
4576 #endif
4577     return ok;
4578 }
4579 
RequestKeyboardCrossPlatForm(bool isFocusViewChanged)4580 bool TextFieldPattern::RequestKeyboardCrossPlatForm(bool isFocusViewChanged)
4581 {
4582 #if !defined(ENABLE_STANDARD_INPUT)
4583     auto tmpHost = GetHost();
4584     CHECK_NULL_RETURN(tmpHost, false);
4585     auto context = tmpHost->GetContextRefPtr();
4586     CHECK_NULL_RETURN(context, false);
4587     if (!HasConnection()) {
4588         TextInputConfiguration config;
4589         config.type = keyboard_;
4590         config.action = GetTextInputActionValue(GetDefaultTextInputAction());
4591         config.inputFilter = GetInputFilter();
4592         config.maxLength = GetMaxLength();
4593         if (keyboard_ == TextInputType::VISIBLE_PASSWORD || keyboard_ == TextInputType::NEW_PASSWORD) {
4594             config.obscureText = textObscured_;
4595         }
4596         connection_ = TextInputProxy::GetInstance().Attach(
4597             WeakClaim(this), config, context->GetTaskExecutor(), GetInstanceId());
4598 
4599         if (!HasConnection()) {
4600             return false;
4601         }
4602     }
4603     TextEditingValue value;
4604     value.text = contentController_->GetTextValue();
4605     value.hint = UtfUtils::Str16DebugToStr8(GetPlaceHolder());
4606     value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
4607     connection_->SetEditingState(value, GetInstanceId());
4608     connection_->Show(isFocusViewChanged, GetInstanceId());
4609 #endif
4610     return true;
4611 }
4612 
4613 #if defined(ENABLE_STANDARD_INPUT)
GetMiscTextConfig() const4614 std::optional<MiscServices::TextConfig> TextFieldPattern::GetMiscTextConfig() const
4615 {
4616     auto tmpHost = GetHost();
4617     CHECK_NULL_RETURN(tmpHost, {});
4618     auto pipeline = tmpHost->GetContextRefPtr();
4619     CHECK_NULL_RETURN(pipeline, {});
4620     auto theme = GetTheme();
4621     CHECK_NULL_RETURN(theme, {});
4622     auto windowRect = pipeline->GetCurrentWindowRect();
4623     double positionY = (tmpHost->GetPaintRectOffset(false, true) - pipeline->GetRootRect().GetOffset()).GetY() + windowRect.Top();
4624     auto offset = AVOID_OFFSET.ConvertToPx();
4625     auto textPaintOffset = GetPaintRectGlobalOffset();
4626     double height = selectController_->GetCaretRect().Bottom() + windowRect.Top() +
4627              textPaintOffset.GetY() + offset - positionY;
4628 
4629     GetInlinePositionYAndHeight(positionY, height);
4630 
4631     auto manager = pipeline->GetSafeAreaManager();
4632     if (manager) {
4633         auto keyboardOffset = manager->GetKeyboardOffset();
4634         positionY -= keyboardOffset;
4635     }
4636 
4637     MiscServices::CursorInfo cursorInfo { .left = selectController_->GetCaretRect().Left() + windowRect.Left() +
4638                                                   textPaintOffset.GetX(),
4639         .top = selectController_->GetCaretRect().Top() + windowRect.Top() + textPaintOffset.GetY(),
4640         .width = theme->GetCursorWidth().ConvertToPx(),
4641         .height = selectController_->GetCaretRect().Height() };
4642     MiscServices::InputAttribute inputAttribute = { .inputPattern = (int32_t)keyboard_,
4643         .enterKeyType = (int32_t)GetTextInputActionValue(GetDefaultTextInputAction()),
4644         .isTextPreviewSupported = hasSupportedPreviewText_,
4645         .immersiveMode = static_cast<int32_t>(keyboardAppearance_)};
4646     MiscServices::TextConfig textConfig = { .inputAttribute = inputAttribute,
4647         .cursorInfo = cursorInfo,
4648         .range = { .start = selectController_->GetStartIndex(), .end = selectController_->GetEndIndex() },
4649         .windowId = pipeline->GetFocusWindowId(),
4650         .positionY = positionY,
4651         .height = height };
4652 
4653     if (keyboard_ == TextInputType::NUMBER_DECIMAL) {
4654         textConfig.inputAttribute.inputPattern = (int32_t)TextInputType::NUMBER;
4655     }
4656     return textConfig;
4657 }
4658 
GetInlinePositionYAndHeight(double & positionY,double & height) const4659 void TextFieldPattern::GetInlinePositionYAndHeight(double& positionY, double& height) const
4660 {
4661     if (IsNormalInlineState()) {
4662         auto theme = GetTheme();
4663         CHECK_NULL_VOID(theme);
4664         auto offset = AVOID_OFFSET.ConvertToPx();
4665         auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4666         PaddingProperty userPadding;
4667         if (paintProperty->HasPaddingByUser()) {
4668             userPadding = paintProperty->GetPaddingByUserValue();
4669         } else {
4670             userPadding.top = CalcLength(theme->GetPadding().Top());
4671         }
4672         auto topPadding = userPadding.top->GetDimension().ConvertToPx();
4673         auto safeBoundary = theme->GetInlineBorderWidth().ConvertToPx() * 2;
4674         positionY += static_cast<double>(inlineMeasureItem_.inlineSizeHeight) + safeBoundary + topPadding;
4675         height = offset;
4676 
4677         auto tmpHost = GetHost();
4678         CHECK_NULL_VOID(tmpHost);
4679         auto pipeline = tmpHost->GetContextRefPtr();
4680         CHECK_NULL_VOID(pipeline);
4681         auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
4682         CHECK_NULL_VOID(textFieldManager);
4683         TAG_LOGI(ACE_TEXT_FIELD, "SetInlineAvoidInfo positionY:%{public}f height:%{public}f sizeHeight:%{public}f",
4684             positionY, height, inlineMeasureItem_.inlineSizeHeight);
4685         textFieldManager->SetInlineTextFieldAvoidPositionYAndHeight(positionY, height);
4686     }
4687 }
4688 
4689 #endif
4690 
ConvertToAceAutoFillType(TextInputType type)4691 AceAutoFillType TextFieldPattern::ConvertToAceAutoFillType(TextInputType type)
4692 {
4693     static std::unordered_map<TextInputType, AceAutoFillType> convertMap = {
4694         { TextInputType::VISIBLE_PASSWORD, AceAutoFillType::ACE_PASSWORD },
4695         { TextInputType::USER_NAME, AceAutoFillType::ACE_USER_NAME },
4696         { TextInputType::NEW_PASSWORD, AceAutoFillType::ACE_NEW_PASSWORD },
4697         { TextInputType::NUMBER_PASSWORD, AceAutoFillType::ACE_PASSWORD } };
4698     auto it = convertMap.find(type);
4699     if (it != convertMap.end()) {
4700         return it->second;
4701     }
4702     return AceAutoFillType::ACE_UNSPECIFIED;
4703 }
4704 
TextContentTypeToAceAutoFillType(const TextContentType & type)4705 AceAutoFillType TextFieldPattern::TextContentTypeToAceAutoFillType(const TextContentType& type)
4706 {
4707     if (contentTypeMap_.find(type) != contentTypeMap_.end()) {
4708         return contentTypeMap_[type].first;
4709     }
4710     return contentTypeMap_[TextContentType::UNSPECIFIED].first;
4711 }
4712 
CloseKeyboard(bool forceClose)4713 bool TextFieldPattern::CloseKeyboard(bool forceClose)
4714 {
4715     return CloseKeyboard(forceClose, forceClose);
4716 }
4717 
CloseKeyboard(bool forceClose,bool isStopTwinkling)4718 bool TextFieldPattern::CloseKeyboard(bool forceClose, bool isStopTwinkling)
4719 {
4720     if (forceClose) {
4721         if (isStopTwinkling) {
4722             StopTwinkling();
4723         }
4724         CloseSelectOverlay(true);
4725         auto host = GetHost();
4726         CHECK_NULL_RETURN(host, false);
4727         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Will Close Soft keyboard.", host->GetId());
4728         if ((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_) {
4729             return CloseCustomKeyboard();
4730         }
4731 #if defined(ENABLE_STANDARD_INPUT)
4732         auto inputMethod = MiscServices::InputMethodController::GetInstance();
4733         if (!inputMethod) {
4734             TAG_LOGE(AceLogTag::ACE_TEXT_FIELD, "CloseKeyboard, inputMethod is null");
4735             return false;
4736         }
4737         inputMethod->Close();
4738 #else
4739         if (HasConnection()) {
4740             connection_->Close(GetInstanceId());
4741             connection_ = nullptr;
4742         }
4743 #endif
4744         return true;
4745     }
4746     return false;
4747 }
4748 
SetCustomKeyboardOption(bool supportAvoidance)4749 void TextFieldPattern::SetCustomKeyboardOption(bool supportAvoidance)
4750 {
4751     keyboardAvoidance_ = supportAvoidance;
4752 }
4753 
RequestCustomKeyboard()4754 bool TextFieldPattern::RequestCustomKeyboard()
4755 {
4756 #if defined(ENABLE_STANDARD_INPUT)
4757     auto inputMethod = MiscServices::InputMethodController::GetInstance();
4758     if (inputMethod) {
4759         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextField Request CustomKeyboard, Close keyboard Successfully.");
4760         inputMethod->RequestHideInput();
4761         inputMethod->Close();
4762     }
4763 #else
4764     if (HasConnection()) {
4765         connection_->Close(GetInstanceId());
4766         connection_ = nullptr;
4767     }
4768 #endif
4769 
4770     if (isCustomKeyboardAttached_) {
4771         return true;
4772     }
4773     CHECK_NULL_RETURN(customKeyboard_ || customKeyboardBuilder_, false);
4774     auto frameNode = GetHost();
4775     CHECK_NULL_RETURN(frameNode, false);
4776     ACE_LAYOUT_SCOPED_TRACE("RequestCustomKeyboard[id:%d]", frameNode->GetId());
4777     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "RequestCustomKeyboard, id:%{public}d", frameNode->GetId());
4778     auto pipeline = frameNode->GetContext();
4779     CHECK_NULL_RETURN(pipeline, false);
4780     auto overlayManager = pipeline->GetOverlayManager();
4781     CHECK_NULL_RETURN(overlayManager, false);
4782     overlayManager->SetCustomKeyboardOption(keyboardAvoidance_);
4783     if (customKeyboardBuilder_) {
4784         overlayManager->BindKeyboard(customKeyboardBuilder_, frameNode->GetId());
4785     } else {
4786         overlayManager->BindKeyboardWithNode(customKeyboard_, frameNode->GetId());
4787     }
4788     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
4789     if (textFieldManager) {
4790         textFieldManager->SetLastRequestKeyboardId(GetRequestKeyboardId());
4791     }
4792     isCustomKeyboardAttached_ = true;
4793     keyboardOverlay_ = overlayManager;
4794     auto caretHeight = selectController_->GetCaretRect().Height();
4795     auto safeHeight = caretHeight + selectController_->GetCaretRect().GetY();
4796     if (selectController_->GetCaretRect().GetY() > caretHeight) {
4797         safeHeight = caretHeight;
4798     }
4799     keyboardOverlay_->AvoidCustomKeyboard(frameNode->GetId(), safeHeight);
4800     return true;
4801 }
4802 
CloseCustomKeyboard()4803 bool TextFieldPattern::CloseCustomKeyboard()
4804 {
4805     auto frameNode = GetHost();
4806     CHECK_NULL_RETURN(frameNode, false);
4807     CHECK_NULL_RETURN(keyboardOverlay_, false);
4808     keyboardOverlay_->CloseKeyboard(frameNode->GetId());
4809     isCustomKeyboardAttached_ = false;
4810     return true;
4811 }
4812 
OnTextInputActionUpdate(TextInputAction value)4813 void TextFieldPattern::OnTextInputActionUpdate(TextInputAction value) {}
4814 
UpdatePasswordIconColor(const Color & color)4815 void TextFieldPattern::UpdatePasswordIconColor(const Color& color)
4816 {
4817     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
4818     CHECK_NULL_VOID(passwordArea);
4819     passwordArea->UpdatePasswordIconColor(color);
4820 }
4821 
OnThemeScopeUpdate(int32_t themeScopeId)4822 bool TextFieldPattern::OnThemeScopeUpdate(int32_t themeScopeId)
4823 {
4824     bool result = false;
4825     bool updateFlag = true;
4826     auto host = GetHost();
4827     CHECK_NULL_RETURN(host, result);
4828     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4829     CHECK_NULL_RETURN(paintProperty, false);
4830     auto textFieldLayoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4831     CHECK_NULL_RETURN(textFieldLayoutProperty, false);
4832     auto pipeline = host->GetContext();
4833     CHECK_NULL_RETURN(pipeline, result);
4834     auto textFieldTheme = pipeline->GetTheme<TextFieldTheme>(themeScopeId);
4835     textFieldTheme_ = textFieldTheme;
4836     CHECK_NULL_RETURN(textFieldTheme, result);
4837 
4838     if (!paintProperty->HasBackgroundColor() && !IsUnderlineMode()) {
4839         auto renderContext = host->GetRenderContext();
4840         CHECK_NULL_RETURN(renderContext, result);
4841         auto bgColor = IsInlineMode() ? textFieldTheme->GetInlineBgColor() : textFieldTheme->GetBgColor();
4842         renderContext->UpdateBackgroundColor(bgColor);
4843         result = true;
4844     }
4845 
4846     if (!paintProperty->HasTextColorFlagByUser()) {
4847         textFieldLayoutProperty->UpdateTextColor(textFieldTheme->GetTextColor());
4848         result = true;
4849     }
4850 
4851     if (!paintProperty->GetCaretColorFlagByUserValue(false)) {
4852         paintProperty->UpdateCursorColor(textFieldTheme->GetCursorColor());
4853         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4854     }
4855 
4856     if (result || !paintProperty->GetPlaceholderColorFlagByUserValue(false)) {
4857         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4858         updateFlag = false;
4859     }
4860     // no interface to set password icon color, should update every time
4861     UpdatePasswordIconColor(textFieldTheme->GetSymbolColor());
4862     return updateFlag;
4863 }
4864 
BeforeIMEInsertValue(const std::u16string & insertValue,int32_t offset)4865 bool TextFieldPattern::BeforeIMEInsertValue(const std::u16string& insertValue, int32_t offset)
4866 {
4867     auto host = GetHost();
4868     CHECK_NULL_RETURN(host, true);
4869     auto eventHub = host->GetEventHub<TextFieldEventHub>();
4870     CHECK_NULL_RETURN(eventHub, true);
4871     InsertValueInfo insertValueInfo;
4872     insertValueInfo.insertOffset = offset;
4873     insertValueInfo.insertValue = insertValue;
4874     return eventHub->FireOnWillInsertValueEvent(insertValueInfo);
4875 }
4876 
AfterIMEInsertValue(const std::u16string & insertValue)4877 void TextFieldPattern::AfterIMEInsertValue(const std::u16string& insertValue)
4878 {
4879     auto host = GetHost();
4880     CHECK_NULL_VOID(host);
4881     auto eventHub = host->GetEventHub<TextFieldEventHub>();
4882     CHECK_NULL_VOID(eventHub);
4883     InsertValueInfo insertValueInfo;
4884     auto offset = selectController_->GetCaretIndex();
4885     insertValueInfo.insertOffset = offset;
4886     insertValueInfo.insertValue = insertValue;
4887     return eventHub->FireOnDidInsertValueEvent(insertValueInfo);
4888 }
4889 
CalcCounterAfterFilterInsertValue(int32_t curLength,const std::u16string insertValue,int32_t maxLength)4890 void TextFieldPattern::CalcCounterAfterFilterInsertValue(
4891     int32_t curLength, const std::u16string insertValue, int32_t maxLength)
4892 {
4893     bool textChange = false;
4894     auto result = insertValue;
4895     contentController_->FilterTextInputStyle(textChange, result);
4896     int32_t sum = curLength + static_cast<int32_t>(result.length());
4897     showCountBorderStyle_ = sum > maxLength;
4898     HandleCountStyle();
4899 }
4900 
NotifyImfFinishTextPreview()4901 void TextFieldPattern::NotifyImfFinishTextPreview()
4902 {
4903     if (!HasFocus()) {
4904         return;
4905     }
4906 #if defined(ENABLE_STANDARD_INPUT)
4907     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
4908         u"", 0, 0);
4909     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "notify imf that textfield exit textPreview");
4910 #endif
4911 }
4912 
InsertValueByController(const std::u16string & insertValue,int32_t offset)4913 int32_t TextFieldPattern::InsertValueByController(const std::u16string& insertValue, int32_t offset)
4914 {
4915     auto host = GetHost();
4916     CHECK_NULL_RETURN(host, offset);
4917     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4918     CHECK_NULL_RETURN(layoutProperty, offset);
4919     ChangeValueInfo changeValueInfo;
4920     changeValueInfo.oldContent = GetBodyTextValue();
4921     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
4922     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
4923     changeValueInfo.rangeBefore = TextRange { offset, offset };
4924     NotifyImfFinishTextPreview();
4925     int32_t originLength =
4926         static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
4927     bool hasInsertValue =
4928         contentController_->InsertValue(offset, insertValue);
4929     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
4930     changeValueInfo.previewText.value = GetPreviewTextValue();
4931     changeValueInfo.value = contentController_->GetTextUtf16Value();
4932     changeValueInfo.rangeAfter =
4933         TextRange { offset, offset + static_cast<int32_t>(contentController_->GetInsertValue().length()) };
4934     bool isWillChange = FireOnWillChange(changeValueInfo);
4935     if (!isWillChange) {
4936         contentController_->SetTextValue(changeValueInfo.oldContent);
4937         return false;
4938     }
4939     int32_t caretMoveLength =
4940         abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength);
4941     if (layoutProperty->HasMaxLength()) {
4942         CalcCounterAfterFilterInsertValue(originLength, insertValue,
4943             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
4944     }
4945     selectController_->UpdateCaretIndex(offset + caretMoveLength);
4946 
4947     auto pipeline = host->GetContext();
4948     CHECK_NULL_RETURN(pipeline, offset);
4949     pipeline->AddAfterLayoutTask([weak = WeakClaim(Referenced::RawPtr(selectController_))]() {
4950         auto selectController = weak.Upgrade();
4951         CHECK_NULL_VOID(selectController);
4952         int32_t index = selectController->GetCaretIndex();
4953         selectController->MoveCaretToContentRect(index);
4954     });
4955 
4956     UpdateObscure(insertValue, hasInsertValue);
4957     UpdateEditingValueToRecord();
4958     focusIndex_ = FocuseIndex::TEXT;
4959     TwinklingByFocus();
4960     CloseSelectOverlay(true);
4961     ScrollToSafeArea();
4962     ProcessResponseArea();
4963     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4964     return selectController_->GetCaretIndex();
4965 }
4966 
ExecuteInsertValueCommand(const InsertCommandInfo & info)4967 void TextFieldPattern::ExecuteInsertValueCommand(const InsertCommandInfo& info)
4968 {
4969     auto insertValue = info.insertValue;
4970     auto isIME = (info.reason == InputReason::IME);
4971     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4972     CHECK_NULL_VOID(layoutProperty);
4973     auto start = selectController_->GetStartIndex();
4974     auto end = selectController_->GetEndIndex();
4975     auto caretStart = IsSelected() ? start : selectController_->GetCaretIndex();
4976     if (isIME) {
4977         auto isInsert = BeforeIMEInsertValue(insertValue, caretStart);
4978         CHECK_NULL_VOID(isInsert);
4979     }
4980     int32_t caretMoveLength = 0;
4981     bool hasInsertValue = false;
4982     int32_t originLength = 0;
4983     auto oldContent = contentController_->GetTextUtf16Value();
4984     auto originCaretIndex =
4985             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
4986     if (IsSelected()) {
4987         auto value = contentController_->GetSelectedValue(start, end);
4988         auto isDelete = true;
4989         if (isIME) {
4990             isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::BACKWARD, end);
4991         }
4992         end = isDelete ? end : start;
4993         originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
4994         hasInsertValue = contentController_->ReplaceSelectedValue(start, end, insertValue);
4995         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength);
4996         bool isWillChange = OnWillChangePreInsert(contentController_->GetInsertValue(), oldContent, start, end);
4997         if (!isWillChange) {
4998             RecoverTextValueAndCaret(oldContent, originCaretIndex);
4999             return;
5000         }
5001         if (isIME && isDelete) {
5002             selectController_->UpdateCaretIndex(start);
5003             AfterIMEDeleteValue(value, TextDeleteDirection::BACKWARD);
5004         }
5005     } else {
5006         originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5007         hasInsertValue = contentController_->InsertValue(selectController_->GetCaretIndex(), insertValue);
5008         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength);
5009         bool isWillChange = OnWillChangePreInsert(contentController_->GetInsertValue(), oldContent, start, end);
5010         if (!isWillChange) {
5011             RecoverTextValueAndCaret(oldContent, originCaretIndex);
5012             return;
5013         }
5014     }
5015     if (layoutProperty->HasMaxLength()) {
5016         CalcCounterAfterFilterInsertValue(originLength, insertValue,
5017             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
5018     }
5019     selectController_->UpdateCaretIndex(caretStart + caretMoveLength);
5020     UpdateObscure(insertValue, hasInsertValue);
5021     UpdateEditingValueToRecord();
5022     if (isIME) {
5023         AfterIMEInsertValue(contentController_->GetInsertValue());
5024     }
5025     TwinklingByFocus();
5026 }
5027 
TwinklingByFocus()5028 void TextFieldPattern::TwinklingByFocus()
5029 {
5030     if (HasFocus() && focusIndex_ == FocuseIndex::TEXT) {
5031         cursorVisible_ = true;
5032         StartTwinkling();
5033     } else {
5034         cursorVisible_ = false;
5035         StopTwinkling();
5036     }
5037 }
5038 
FinishTextPreviewByPreview(const std::u16string & insertValue)5039 bool TextFieldPattern::FinishTextPreviewByPreview(const std::u16string& insertValue)
5040 {
5041     if (GetIsPreviewText()) {
5042         PreviewTextInfo info = {
5043             .text = insertValue,
5044             .range = { -1, -1 },
5045             .isIme = false
5046         };
5047         inputOperations_.emplace(InputOperation::SET_PREVIEW_TEXT);
5048         previewTextOperation_.emplace(info);
5049         FinishTextPreview();
5050         return true;
5051     }
5052     return false;
5053 }
5054 
UpdateObscure(const std::u16string & insertValue,bool hasInsertValue)5055 void TextFieldPattern::UpdateObscure(const std::u16string& insertValue, bool hasInsertValue)
5056 {
5057     if (!IsTextArea() && IsInPasswordMode() && GetTextObscured()) {
5058         auto host = GetHost();
5059         CHECK_NULL_VOID(host);
5060         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5061         CHECK_NULL_VOID(layoutProperty);
5062         if (insertValue.length() == 1 &&
5063             (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) != TextInputType::NUMBER_PASSWORD ||
5064                 std::isdigit(insertValue[0])) &&
5065             hasInsertValue) {
5066             auto content = contentController_->GetTextUtf16Value();
5067             auto insertIndex = selectController_->GetCaretIndex() - 1;
5068             insertIndex = std::clamp(insertIndex, 0, static_cast<int32_t>(content.length()));
5069             auto strBeforeCaret = content.empty() ? u"" : content.substr(insertIndex, 1);
5070             obscureTickCountDown_ = strBeforeCaret == insertValue ? OBSCURE_SHOW_TICKS : 0;
5071             nakedCharPosition_ = strBeforeCaret == insertValue ? insertIndex : -1;
5072         } else {
5073             obscureTickCountDown_ = 0;
5074             nakedCharPosition_ = -1;
5075         }
5076     }
5077 }
5078 
InsertValue(const std::u16string & insertValue,bool isIME)5079 void TextFieldPattern::InsertValue(const std::u16string& insertValue, bool isIME)
5080 {
5081     InputReason reason = isIME ? InputReason::IME : InputReason::NONE;
5082     AddInsertCommand(insertValue, reason);
5083 }
5084 
InsertValue(const std::string & insertValue,bool isIME)5085 void TextFieldPattern::InsertValue(const std::string& insertValue, bool isIME)
5086 {
5087     InsertValue(UtfUtils::Str8DebugToStr16(insertValue), isIME);
5088 }
5089 
UltralimitShake()5090 void TextFieldPattern::UltralimitShake()
5091 {
5092     auto frameNode = GetHost();
5093     CHECK_NULL_VOID(frameNode);
5094     auto context = frameNode->GetRenderContext();
5095     CHECK_NULL_VOID(context);
5096     AnimationOption option;
5097     context->UpdateTranslateInXY({ -1.0, 0.0 });
5098     const RefPtr<InterpolatingSpring> curve =
5099         AceType::MakeRefPtr<InterpolatingSpring>(VELOCITY, MASS, STIFFNESS, DAMPING);
5100     option.SetCurve(curve);
5101     option.SetFillMode(FillMode::FORWARDS);
5102     auto pipelineContext = frameNode->GetContext();
5103     CHECK_NULL_VOID(pipelineContext);
5104     AnimationUtils::Animate(
5105         option,
5106         [weak = WeakClaim(Referenced::RawPtr(context))]() {
5107             auto context = weak.Upgrade();
5108             CHECK_NULL_VOID(context);
5109             context->UpdateTranslateInXY({ 0.0f, 0.0f });
5110         },
5111         option.GetOnFinishEvent());
5112 }
5113 
AdjustFloatingCaretInfo(const Offset & localOffset,const HandleInfoNG & caretInfo,HandleInfoNG & floatingCaretInfo)5114 void TextFieldPattern::AdjustFloatingCaretInfo(const Offset& localOffset,
5115     const HandleInfoNG& caretInfo, HandleInfoNG& floatingCaretInfo)
5116 {
5117     CHECK_NULL_VOID(selectController_);
5118     auto offsetX = localOffset.GetX();
5119     auto offsetY = caretInfo.rect.Top();
5120     floatingCaretInfo.rect.SetHeight(caretInfo.rect.Height());
5121     auto contentRect = GetTextContentRect();
5122     offsetX = std::min(std::max(contentRect.Left(), static_cast<float>(offsetX)),
5123         contentRect.Right() - caretInfo.rect.Width());
5124     offsetY = std::min(std::max(contentRect.Top(), static_cast<float>(offsetY)),
5125         contentRect.Bottom() - floatingCaretInfo.rect.Height());
5126     floatingCaretInfo.UpdateOffset({offsetX, offsetY});
5127     bool reachBoundary = NearEqual(contentRect.Left(), offsetX) ||
5128         NearEqual(contentRect.Right() - caretInfo.rect.Width(), static_cast<float>(offsetX));
5129     bool distanceMoreThenTenVp = floatingCaretInfo.rect.GetOffset().GetDistance(caretInfo.rect.GetOffset())
5130         >= FLOATING_CARET_SHOW_ORIGIN_CARET_DISTANCE.ConvertToPx();
5131     TouchPosition pos = selectController_->GetTouchLinePos(localOffset);
5132     bool FloatCursorOnOriginLeft = floatingCaretInfo.rect.GetX() < caretInfo.rect.GetX();
5133     bool FloatCursorNotInText = ((pos == TouchPosition::LEFT && FloatCursorOnOriginLeft) ||
5134         (pos == TouchPosition::RIGHT && !FloatCursorOnOriginLeft));
5135     SetShowOriginCursor((reachBoundary || distanceMoreThenTenVp) && FloatCursorNotInText);
5136     SetFloatingCursorVisible(true);
5137 }
5138 
FloatingCaretLand()5139 void TextFieldPattern::FloatingCaretLand()
5140 {
5141     CHECK_NULL_VOID(floatCaretState_.FloatingCursorVisible && textFieldOverlayModifier_ && selectController_);
5142     textFieldOverlayModifier_->StartFloatingCaretLand(selectController_->GetCaretRect().GetOffset());
5143 }
5144 
CleanCounterNode()5145 void TextFieldPattern::CleanCounterNode()
5146 {
5147     counterDecorator_.Reset();
5148 }
5149 
CleanErrorNode()5150 void TextFieldPattern::CleanErrorNode()
5151 {
5152     errorDecorator_.Reset();
5153 }
5154 
UpdateEditingValueToRecord(int32_t beforeCaretPosition)5155 void TextFieldPattern::UpdateEditingValueToRecord(int32_t beforeCaretPosition)
5156 {
5157     if (operationRecords_.size() >= RECORD_MAX_LENGTH) {
5158         operationRecords_.erase(operationRecords_.begin());
5159     }
5160     TextEditingValueNG record {
5161         .text = contentController_->GetTextUtf16Value(),
5162         .caretPosition = selectController_->GetCaretIndex(),
5163         .beforeCaretPosition = beforeCaretPosition,
5164     };
5165     operationRecords_.emplace_back(record);
5166 }
5167 
PreferredTextHeight(bool isPlaceholder,bool isAlgorithmMeasure)5168 float TextFieldPattern::PreferredTextHeight(bool isPlaceholder, bool isAlgorithmMeasure)
5169 {
5170     if (!isAlgorithmMeasure && paragraph_ && paragraph_->GetHeight() != 0.0f && paragraph_->GetLineCount() > 0) {
5171         return paragraph_->GetHeight() / paragraph_->GetLineCount();
5172     }
5173     RefPtr<Paragraph> paragraph;
5174     std::u16string textContent;
5175     TextStyle textStyle;
5176     auto tmpHost = GetHost();
5177     CHECK_NULL_RETURN(tmpHost, 0.0f);
5178     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5179     CHECK_NULL_RETURN(layoutProperty, 0.0f);
5180     auto textFieldTheme = GetTheme();
5181     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
5182     // use text or placeHolder value if exists, space otherwise
5183     if (!isPlaceholder) {
5184         TextFieldLayoutAlgorithm::UpdateTextStyle(tmpHost, layoutProperty, textFieldTheme, textStyle, false);
5185         textContent = u"a";
5186     } else {
5187         TextFieldLayoutAlgorithm::UpdatePlaceholderTextStyle(tmpHost, layoutProperty, textFieldTheme, textStyle, false);
5188         textContent = u"b";
5189     }
5190     if (adaptFontSize_.has_value()) {
5191         textStyle.SetFontSize(adaptFontSize_.value());
5192     }
5193     if (textStyle.GetFontSize().IsNonPositive()) {
5194         textStyle.SetFontSize(DEFAULT_FONT);
5195     }
5196     if (textStyle.GetLineHeight().IsNegative()) {
5197         textStyle.SetLineHeight(Dimension(0.0));
5198     }
5199     ParagraphStyle paraStyle { .direction =
5200                                    TextFieldLayoutAlgorithm::GetTextDirection(contentController_->GetTextUtf16Value()),
5201         .align = textStyle.GetTextAlign(),
5202         .maxLines = textStyle.GetMaxLines(),
5203         .fontLocale = Localization::GetInstance()->GetFontLocale(),
5204         .wordBreak = textStyle.GetWordBreak(),
5205         .ellipsisMode = textStyle.GetEllipsisMode(),
5206         .lineBreakStrategy = textStyle.GetLineBreakStrategy(),
5207         .textOverflow = textStyle.GetTextOverflow(),
5208         .fontSize = FontSizeConvertToPx(textStyle.GetFontSize()) };
5209     paragraph = Paragraph::Create(paraStyle, FontCollection::Current());
5210     CHECK_NULL_RETURN(paragraph, 0.0f);
5211     paragraph->PushStyle(textStyle);
5212     UtfUtils::HandleInvalidUTF16(reinterpret_cast<uint16_t*>(textContent.data()), textContent.length(), 0);
5213     paragraph->AddText(textContent);
5214     paragraph->Build();
5215     paragraph->Layout(std::numeric_limits<double>::infinity());
5216     return paragraph->GetHeight();
5217 }
5218 
FontSizeConvertToPx(const Dimension & fontSize)5219 float TextFieldPattern::FontSizeConvertToPx(const Dimension& fontSize)
5220 {
5221     return fontSize.ConvertToPx();
5222 }
5223 
PreferredLineHeight(bool isAlgorithmMeasure)5224 float TextFieldPattern::PreferredLineHeight(bool isAlgorithmMeasure)
5225 {
5226     return PreferredTextHeight(contentController_->IsEmpty(), isAlgorithmMeasure);
5227 }
5228 
OnCursorMoveDone(TextAffinity textAffinity,std::optional<Offset> offset)5229 void TextFieldPattern::OnCursorMoveDone(TextAffinity textAffinity, std::optional<Offset> offset)
5230 {
5231     auto tmpHost = GetHost();
5232     CHECK_NULL_VOID(tmpHost);
5233     StartTwinkling();
5234     CloseSelectOverlay();
5235     if (offset.has_value()) {
5236         selectController_->UpdateCaretInfoByOffset(offset.value());
5237     } else {
5238         selectController_->MoveCaretToContentRect(GetCaretIndex(), textAffinity);
5239     }
5240     if (ResetObscureTickCountDown()) {
5241         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5242     } else {
5243         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5244     }
5245     UpdateCaretInfoToController();
5246 }
5247 
GetWordLength(int32_t originCaretPosition,int32_t directionMove,bool skipNewLineChar)5248 int32_t TextFieldPattern::GetWordLength(int32_t originCaretPosition, int32_t directionMove, bool skipNewLineChar)
5249 {
5250     if (contentController_->IsEmpty()) {
5251         return 0;
5252     }
5253     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5254     if (originCaretPosition < 0 || originCaretPosition > textLength) {
5255         return 0;
5256     }
5257     // directionMove == 0 left, directionMove == 1 right
5258     // cannot get word length by current caret position and direction
5259     if ((directionMove == 0 && originCaretPosition == 0) || (directionMove == 1 && originCaretPosition == textLength)) {
5260         return 0;
5261     }
5262     int32_t offset = 0;
5263     int32_t strIndex = directionMove == 0 ? (originCaretPosition - 1) : originCaretPosition;
5264     auto wideTextValue = contentController_->GetTextUtf16Value();
5265     int32_t wordStart = 0;
5266     int32_t wordEnd = 0;
5267     while (directionMove == 0 ? strIndex >= 0 : strIndex <= textLength) {
5268         auto chr = wideTextValue[strIndex];
5269         // skip the special character
5270         if (chr == L' ' || (chr == L'\n' && skipNewLineChar)) {
5271             if (directionMove == 0) {
5272                 strIndex--;
5273             } else {
5274                 strIndex++;
5275             }
5276             offset++;
5277             continue;
5278         }
5279         // cal word length
5280         if (paragraph_ && paragraph_->GetWordBoundary(strIndex, wordStart, wordEnd)) {
5281             if (directionMove == 1) {
5282                 offset += (wordEnd - strIndex);
5283             } else {
5284                 offset += (strIndex - wordStart + 1); // when move left, actual offset should add 1
5285             }
5286             return std::clamp(offset, 0, textLength);
5287         }
5288         // GetWordBoundary fail
5289         return 0;
5290     }
5291     return std::clamp(offset, 0, textLength);
5292 }
5293 
GetLineBeginPosition(int32_t originCaretPosition,bool needToCheckLineChanged)5294 int32_t TextFieldPattern::GetLineBeginPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
5295 {
5296     if (contentController_->IsEmpty()) {
5297         return 0;
5298     }
5299     auto wideTextValue = contentController_->GetTextUtf16Value();
5300     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
5301     if (originCaretPosition < 0 || originCaretPosition > textLength) {
5302         return 0;
5303     }
5304     if (originCaretPosition == 0) {
5305         return originCaretPosition;
5306     }
5307     int32_t moveLineBeginOffset = 0;
5308     int32_t strIndex = originCaretPosition;
5309     do {
5310         moveLineBeginOffset++;
5311         strIndex--;
5312         // stop moving caret if reaches \n, text head or caret line changed
5313     } while (((strIndex > 0) && (wideTextValue[strIndex] != u'\n')) &&
5314              (needToCheckLineChanged ? !CharLineChanged(strIndex) : true));
5315     if (strIndex < 0 || strIndex >= static_cast<int32_t>(wideTextValue.length())) {
5316         return 0;
5317     }
5318     if (strIndex > 0) {
5319         moveLineBeginOffset--;
5320     }
5321     if (moveLineBeginOffset > originCaretPosition) {
5322         return 0;
5323     }
5324     return originCaretPosition - moveLineBeginOffset;
5325 }
5326 
GetLineEndPosition(int32_t originCaretPosition,bool needToCheckLineChanged)5327 int32_t TextFieldPattern::GetLineEndPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
5328 {
5329     if (contentController_->IsEmpty()) {
5330         return 0;
5331     }
5332     auto wideTextValue = contentController_->GetTextUtf16Value();
5333     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
5334     if (originCaretPosition < 0 || originCaretPosition > textLength) {
5335         return originCaretPosition;
5336     }
5337     if (originCaretPosition == textLength) {
5338         return originCaretPosition;
5339     }
5340     int32_t moveLineEndOffset = 0;
5341     int32_t strIndex = 0;
5342     for (strIndex = originCaretPosition; (strIndex <= textLength && wideTextValue[strIndex] != u'\n') &&
5343                                          (needToCheckLineChanged ? !CharLineChanged(strIndex) : true);
5344          strIndex++) {
5345         moveLineEndOffset++;
5346     }
5347     if (moveLineEndOffset > textLength - originCaretPosition) {
5348         return textLength;
5349     }
5350     return originCaretPosition + moveLineEndOffset;
5351 }
5352 
CharLineChanged(int32_t caretPosition)5353 bool TextFieldPattern::CharLineChanged(int32_t caretPosition)
5354 {
5355     if (caretPosition < 0 || caretPosition > static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5356         return true;
5357     }
5358     CaretMetricsF caretMetrics;
5359     CalcCaretMetricsByPosition(caretPosition, caretMetrics);
5360     // the cursor is aligned with the text at the bottom
5361     return !NearEqual(caretMetrics.offset.GetY() + caretMetrics.height,
5362         selectController_->GetCaretRect().GetY() + selectController_->GetCaretRect().Height());
5363 }
5364 
CursorMoveLeftOperation()5365 bool TextFieldPattern::CursorMoveLeftOperation()
5366 {
5367     if (focusIndex_ != FocuseIndex::TEXT) {
5368         return UpdateFocusBackward();
5369     }
5370     auto originCaretPosition = selectController_->GetCaretIndex();
5371     if (IsSelected()) {
5372         selectController_->UpdateCaretIndex(selectController_->GetStartIndex());
5373         CloseSelectOverlay();
5374     } else {
5375         UpdateCaretPositionWithClamp(
5376             selectController_->GetCaretIndex() -
5377             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetCaretIndex(),
5378                 true));
5379     }
5380     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5381     return originCaretPosition != selectController_->GetCaretIndex();
5382 }
5383 
CursorMoveLeft()5384 bool TextFieldPattern::CursorMoveLeft()
5385 {
5386     if (inputOperations_.empty()) {
5387         return CursorMoveLeftOperation();
5388     }
5389 
5390     inputOperations_.emplace(InputOperation::CURSOR_LEFT);
5391     return false;
5392 }
5393 
CursorMoveLeftWord()5394 bool TextFieldPattern::CursorMoveLeftWord()
5395 {
5396     if (selectController_->GetCaretIndex() == 0) {
5397         return true;
5398     }
5399     int32_t originCaretPosition = selectController_->GetCaretIndex();
5400     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5401     int32_t leftWordLength = GetWordLength(originCaretPosition, 0);
5402     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
5403         return false;
5404     }
5405     if (IsSelected()) {
5406         selectController_->UpdateCaretIndex(selectController_->GetSecondHandleIndex() - leftWordLength);
5407         CloseSelectOverlay();
5408     } else {
5409         UpdateCaretPositionWithClamp(originCaretPosition - leftWordLength);
5410     }
5411     OnCursorMoveDone();
5412     return originCaretPosition != selectController_->GetCaretIndex();
5413 }
5414 
CursorMoveLineBegin()5415 bool TextFieldPattern::CursorMoveLineBegin()
5416 {
5417     if (selectController_->GetCaretIndex() == 0 && !IsSelected()) {
5418         return true;
5419     }
5420     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5421     int32_t originCaretPosition = selectController_->GetCaretIndex();
5422     int32_t lineBeginPosition = GetLineBeginPosition(originCaretPosition);
5423     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
5424         return false;
5425     }
5426     if (selectController_->IsSelectedAll()) {
5427         selectController_->UpdateCaretIndex(0);
5428     } else if (IsTextArea()) {
5429         UpdateCaretPositionWithClamp(lineBeginPosition);
5430     } else {
5431         UpdateCaretPositionWithClamp(0);
5432     }
5433     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5434     return originCaretPosition != selectController_->GetCaretIndex();
5435 }
5436 
CursorMoveToParagraphBegin()5437 bool TextFieldPattern::CursorMoveToParagraphBegin()
5438 {
5439     if (selectController_->GetCaretIndex() == 0) {
5440         return true;
5441     }
5442     auto originCaretPosition = selectController_->GetCaretIndex();
5443     auto newPos = GetLineBeginPosition(originCaretPosition, false);
5444     if (newPos == originCaretPosition && originCaretPosition > 0) {
5445         newPos = GetLineBeginPosition(originCaretPosition - 1, false);
5446     }
5447     UpdateCaretPositionWithClamp(newPos);
5448     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5449     return originCaretPosition != selectController_->GetCaretIndex();
5450 }
5451 
CursorMoveHome()5452 bool TextFieldPattern::CursorMoveHome()
5453 {
5454     // ctrl + home, caret move to position 0
5455     if (selectController_->GetCaretIndex() == 0) {
5456         return true;
5457     }
5458     int32_t originCaretPosition = selectController_->GetCaretIndex();
5459     UpdateCaretPositionWithClamp(0);
5460     OnCursorMoveDone();
5461     return originCaretPosition != selectController_->GetCaretIndex();
5462 }
5463 
CursorMoveRightOperation()5464 bool TextFieldPattern::CursorMoveRightOperation()
5465 {
5466     if (focusIndex_ != FocuseIndex::TEXT) {
5467         return UpdateFocusForward();
5468     }
5469     auto originCaretPosition = selectController_->GetCaretIndex();
5470     if (IsSelected()) {
5471         CloseSelectOverlay();
5472         selectController_->UpdateCaretIndex(selectController_->GetEndIndex());
5473     } else {
5474         UpdateCaretPositionWithClamp(
5475             selectController_->GetCaretIndex() +
5476             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetCaretIndex()));
5477     }
5478     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5479     return originCaretPosition != selectController_->GetCaretIndex();
5480 }
5481 
CursorMoveRight()5482 bool TextFieldPattern::CursorMoveRight()
5483 {
5484     if (inputOperations_.empty()) {
5485         return CursorMoveRightOperation();
5486     }
5487     inputOperations_.emplace(InputOperation::CURSOR_RIGHT);
5488     return false;
5489 }
5490 
CursorMoveRightWord()5491 bool TextFieldPattern::CursorMoveRightWord()
5492 {
5493     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5494         return true;
5495     }
5496     int32_t originCaretPosition = selectController_->GetCaretIndex();
5497     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5498     int32_t rightWordLength = GetWordLength(originCaretPosition, 1);
5499     if (rightWordLength < 0 || rightWordLength > textLength ||
5500         rightWordLength + selectController_->GetCaretIndex() > textLength) {
5501         return false;
5502     }
5503     if (selectController_->IsSelectedAll()) {
5504         selectController_->UpdateCaretIndex(textLength);
5505     } else {
5506         UpdateCaretPositionWithClamp(originCaretPosition + rightWordLength);
5507     }
5508     OnCursorMoveDone();
5509     return originCaretPosition != selectController_->GetCaretIndex();
5510 }
5511 
CursorMoveLineEnd()5512 bool TextFieldPattern::CursorMoveLineEnd()
5513 {
5514     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) &&
5515         !IsSelected()) {
5516         return true;
5517     }
5518     int32_t originCaretPosition = selectController_->GetCaretIndex();
5519     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5520     int32_t lineEndPosition = GetLineEndPosition(originCaretPosition);
5521     if (lineEndPosition < 0 || lineEndPosition > textLength) {
5522         return false;
5523     }
5524     if (selectController_->IsSelectedAll()) {
5525         selectController_->UpdateCaretIndex(textLength);
5526     } else if (IsTextArea()) {
5527         UpdateCaretPositionWithClamp(lineEndPosition);
5528     } else {
5529         UpdateCaretPositionWithClamp(textLength);
5530     }
5531     OnCursorMoveDone();
5532     return originCaretPosition != selectController_->GetCaretIndex();
5533 }
5534 
CursorMoveToParagraphEnd()5535 bool TextFieldPattern::CursorMoveToParagraphEnd()
5536 {
5537     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5538         return true;
5539     }
5540     auto originCaretPosition = selectController_->GetCaretIndex();
5541     auto newPos = GetLineEndPosition(originCaretPosition, false);
5542     if (newPos == originCaretPosition && originCaretPosition > 0) {
5543         newPos = GetLineEndPosition(originCaretPosition + 1, false);
5544     }
5545     UpdateCaretPositionWithClamp(newPos);
5546     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5547     return originCaretPosition != selectController_->GetCaretIndex();
5548 }
5549 
CursorMoveEnd()5550 bool TextFieldPattern::CursorMoveEnd()
5551 {
5552     // ctrl end, caret to the very end
5553     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5554         return true;
5555     }
5556     int32_t originCaretPosition = selectController_->GetCaretIndex();
5557     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5558     UpdateCaretPositionWithClamp(textLength);
5559     OnCursorMoveDone();
5560     return originCaretPosition != selectController_->GetCaretIndex();
5561 }
5562 
CursorMoveUpOperation()5563 bool TextFieldPattern::CursorMoveUpOperation()
5564 {
5565     if (!IsTextArea() && !IsSelected()) {
5566         return CursorMoveToParagraphBegin();
5567     }
5568     auto originCaretPosition = selectController_->GetCaretIndex();
5569     auto offsetX = selectController_->GetCaretRect().GetX();
5570     // multiply by 0.5f to convert to the grapheme center point of the previous line.
5571     float lineHeight = PreferredLineHeight() * 0.5f;
5572     auto offsetY = selectController_->GetCaretRect().GetY() - lineHeight;
5573     if (offsetY < textRect_.GetY() && !IsSelected()) {
5574         return CursorMoveToParagraphBegin();
5575     }
5576     std::optional<Offset> offset;
5577     offset.emplace(Offset(offsetX, offsetY));
5578     OnCursorMoveDone(TextAffinity::DOWNSTREAM, offset);
5579     return originCaretPosition != selectController_->GetCaretIndex();
5580 }
5581 
CursorMoveUp()5582 bool TextFieldPattern::CursorMoveUp()
5583 {
5584     if (inputOperations_.empty()) {
5585         return CursorMoveUpOperation();
5586     }
5587 
5588     inputOperations_.emplace(InputOperation::CURSOR_UP);
5589     return false;
5590 }
5591 
CursorMoveDownOperation()5592 bool TextFieldPattern::CursorMoveDownOperation()
5593 {
5594     if (!IsTextArea() && !IsSelected()) {
5595         return CursorMoveToParagraphEnd();
5596     }
5597     auto originCaretPosition = selectController_->GetCaretIndex();
5598     auto offsetX = selectController_->GetCaretRect().GetX();
5599     // multiply by 1.5f to convert to the grapheme center point of the next line.
5600     float lineHeight = PreferredLineHeight() * 1.5f;
5601     auto offsetY = selectController_->GetCaretRect().GetY() + lineHeight;
5602     if (offsetY > textRect_.GetY() + textRect_.Height() && !IsSelected()) {
5603         return CursorMoveToParagraphEnd();
5604     }
5605     std::optional<Offset> offset;
5606     offset.emplace(Offset(offsetX, offsetY));
5607     OnCursorMoveDone(TextAffinity::DOWNSTREAM, offset);
5608     return originCaretPosition != selectController_->GetCaretIndex();
5609 }
5610 
CursorMoveDown()5611 bool TextFieldPattern::CursorMoveDown()
5612 {
5613     if (inputOperations_.empty()) {
5614         return CursorMoveDownOperation();
5615     }
5616 
5617     inputOperations_.emplace(InputOperation::CURSOR_DOWN);
5618     return false;
5619 }
5620 
Delete(int32_t start,int32_t end)5621 void TextFieldPattern::Delete(int32_t start, int32_t end)
5622 {
5623     SwapIfLarger(start, end);
5624     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Handle Delete within [%{public}d, %{public}d]", start, end);
5625     contentController_->erase(start, end - start);
5626     UpdateSelection(start);
5627     selectController_->MoveCaretToContentRect(start);
5628     if (isLongPress_) {
5629         CancelGestureSelection();
5630     }
5631     CloseSelectOverlay(true);
5632     StartTwinkling();
5633     UpdateEditingValueToRecord();
5634     auto tmpHost = GetHost();
5635     CHECK_NULL_VOID(tmpHost);
5636     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5637 }
5638 
HandleCounterBorder()5639 void TextFieldPattern::HandleCounterBorder()
5640 {
5641     auto theme = GetTheme();
5642     CHECK_NULL_VOID(theme);
5643     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5644     CHECK_NULL_VOID(paintProperty);
5645     auto host = GetHost();
5646     CHECK_NULL_VOID(host);
5647     auto renderContext = host->GetRenderContext();
5648     CHECK_NULL_VOID(renderContext);
5649     if (showCountBorderStyle_) {
5650         if (IsUnderlineMode()) {
5651             underlineWidth_ = ERROR_UNDERLINE_WIDTH;
5652             SetUnderlineColor(userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor()));
5653         } else {
5654             if (!paintProperty->HasBorderWidthFlagByUser()) {
5655                 paintProperty->UpdateInnerBorderWidth(OVER_COUNT_BORDER_WIDTH);
5656                 paintProperty->UpdateInnerBorderColor(theme->GetOverCounterColor());
5657             } else {
5658                 BorderColorProperty overCountBorderColor;
5659                 overCountBorderColor.SetColor(theme->GetOverCounterColor());
5660                 renderContext->UpdateBorderColor(overCountBorderColor);
5661             }
5662         }
5663     } else {
5664         if (IsUnderlineMode() && !IsShowError()) {
5665             ApplyUnderlineTheme();
5666             CHECK_NULL_VOID(counterDecorator_);
5667             counterDecorator_->UpdateTextFieldMargin();
5668         } else {
5669             SetThemeBorderAttr();
5670         }
5671     }
5672 }
5673 
ProcessFocusIndexAction()5674 bool TextFieldPattern::ProcessFocusIndexAction()
5675 {
5676     if (focusIndex_ == FocuseIndex::CANCEL) {
5677         CleanNodeResponseKeyEvent();
5678         return false;
5679     }
5680     if (focusIndex_ == FocuseIndex::UNIT) {
5681         if (IsShowPasswordIcon()) {
5682             PasswordResponseKeyEvent();
5683         }
5684         if (IsShowUnit()) {
5685             UnitResponseKeyEvent();
5686         }
5687         return false;
5688     }
5689     return true;
5690 }
5691 
PerformAction(TextInputAction action,bool forceCloseKeyboard)5692 void TextFieldPattern::PerformAction(TextInputAction action, bool forceCloseKeyboard)
5693 {
5694     if (!ProcessFocusIndexAction()) {
5695         return;
5696     }
5697     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField PerformAction %{public}d", static_cast<int32_t>(action));
5698     auto host = GetHost();
5699     CHECK_NULL_VOID(host);
5700     // If the parent node is a Search, the Search callback is executed.
5701     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5702     CHECK_NULL_VOID(paintProperty);
5703     auto eventHub = host->GetEventHub<TextFieldEventHub>();
5704     CHECK_NULL_VOID(eventHub);
5705     TextFieldCommonEvent event;
5706     event.SetText(contentController_->GetTextUtf16Value());
5707     if (IsNormalInlineState() && action != TextInputAction::NEW_LINE) {
5708         RecordSubmitEvent();
5709         eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
5710         if (event.IsKeepEditable()) {
5711             return;
5712         }
5713         TextFieldLostFocusToViewRoot();
5714         return;
5715     }
5716     if (IsTextArea() && action == TextInputAction::NEW_LINE) {
5717         if (!textAreaBlurOnSubmit_) {
5718             if (GetInputFilter() != "\n") {
5719                 InsertValue(u"\n", true);
5720             }
5721         } else {
5722             CloseKeyboard(forceCloseKeyboard, false);
5723             TextFieldLostFocusToViewRoot();
5724         }
5725         return;
5726     }
5727     eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
5728     RecordSubmitEvent();
5729     if (event.IsKeepEditable()) {
5730         return;
5731     }
5732     // LostFocusToViewRoot may not cause current lost focus, only stop twinkling when it is truly lost focus,
5733     // which will call StopTwinkling on HandleBlurEvent method.
5734     if (textInputBlurOnSubmit_) {
5735         HandleCloseKeyboard(forceCloseKeyboard);
5736     }
5737     UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "Textfield.onSubmit");
5738 }
5739 
TextFieldLostFocusToViewRoot()5740 void TextFieldPattern::TextFieldLostFocusToViewRoot()
5741 {
5742     CHECK_NULL_VOID(HasFocus());
5743     FocusHub::LostFocusToViewRoot();
5744 }
5745 
RecordSubmitEvent() const5746 void TextFieldPattern::RecordSubmitEvent() const
5747 {
5748     if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
5749         return;
5750     }
5751     auto host = GetHost();
5752     CHECK_NULL_VOID(host);
5753     auto inspectorId = host->GetInspectorId().value_or("");
5754     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5755     bool isPwdType = layoutProperty ? layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) ==
5756                                           TextInputType::VISIBLE_PASSWORD
5757                                     : false;
5758     Recorder::EventParamsBuilder builder;
5759     builder.SetId(inspectorId)
5760         .SetType(host->GetTag())
5761         .SetEventType(Recorder::EventType::SEARCH_SUBMIT)
5762         .SetHost(host)
5763         .SetDescription(host->GetAutoEventParamValue(""));
5764     if (!isPwdType) {
5765         builder.SetText(contentController_->GetTextValue());
5766     }
5767     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
5768 }
5769 
UpdateEditingValue(const std::shared_ptr<TextEditingValue> & value,bool needFireChangeEvent)5770 void TextFieldPattern::UpdateEditingValue(const std::shared_ptr<TextEditingValue>& value, bool needFireChangeEvent)
5771 {
5772 #if !defined(ENABLE_STANDARD_INPUT)
5773     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5774     if (layoutProperty && layoutProperty->HasMaxLength()) {
5775         bool textChange = false;
5776         auto result = UtfUtils::Str8DebugToStr16(value->text);
5777         contentController_->FilterTextInputStyle(textChange, result);
5778         auto resultLen = static_cast<int32_t>(result.length());
5779         auto maxLen = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
5780         if (resultLen != maxLen) {
5781             showCountBorderStyle_ = resultLen > maxLen;
5782             HandleCountStyle();
5783         }
5784     }
5785 #endif
5786 
5787     UpdateEditingValueToRecord();
5788     contentController_->SetTextValue(UtfUtils::Str8DebugToStr16(value->text));
5789     selectController_->UpdateCaretIndex(value->selection.baseOffset);
5790     ContainerScope scope(GetInstanceId());
5791     CloseSelectOverlay();
5792     StartTwinkling();
5793     auto host = GetHost();
5794     CHECK_NULL_VOID(host);
5795 
5796     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5797 }
5798 
UpdateInputFilterErrorText(const std::u16string & errorText)5799 void TextFieldPattern::UpdateInputFilterErrorText(const std::u16string& errorText)
5800 {
5801     if (!errorText.empty()) {
5802         auto tmpHost = GetHost();
5803         CHECK_NULL_VOID(tmpHost);
5804         auto textFieldEventHub = tmpHost->GetEventHub<TextFieldEventHub>();
5805         CHECK_NULL_VOID(textFieldEventHub);
5806         textFieldEventHub->FireOnInputFilterError(errorText);
5807     }
5808 }
5809 
UpdateInputFilterErrorText(const std::string & errorText)5810 void TextFieldPattern::UpdateInputFilterErrorText(const std::string& errorText)
5811 {
5812     UpdateInputFilterErrorText(UtfUtils::Str8DebugToStr16(errorText));
5813 }
5814 
OnValueChanged(bool needFireChangeEvent,bool needFireSelectChangeEvent)5815 void TextFieldPattern::OnValueChanged(bool needFireChangeEvent, bool needFireSelectChangeEvent) {}
5816 
OnHandleAreaChanged()5817 void TextFieldPattern::OnHandleAreaChanged()
5818 {
5819     auto parentGlobalOffset = GetPaintRectGlobalOffset();
5820     if (parentGlobalOffset != parentGlobalOffset_) {
5821         parentGlobalOffset_ = parentGlobalOffset;
5822         UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
5823         HandleParentGlobalOffsetChange();
5824     }
5825 }
5826 
HandleParentGlobalOffsetChange()5827 void TextFieldPattern::HandleParentGlobalOffsetChange()
5828 {
5829     selectController_->CalculateHandleOffset();
5830     CHECK_NULL_VOID(SelectOverlayIsOn() || selectOverlay_->SelectOverlayIsCreating());
5831     if (selectOverlay_->IsShowMouseMenu()) {
5832         CloseSelectOverlay();
5833         return;
5834     }
5835     if (selectOverlay_->IsHiddenHandle() && selectOverlay_->IsSingleHandle()) {
5836         selectOverlay_->ProcessOverlayOnAreaChanged({ .menuIsShow = false });
5837     } else {
5838         selectOverlay_->ProcessOverlay({ .menuIsShow = false });
5839     }
5840 }
5841 
RequestKeyboardByFocusSwitch()5842 void TextFieldPattern::RequestKeyboardByFocusSwitch()
5843 {
5844     auto host = GetHost();
5845     CHECK_NULL_VOID(host);
5846     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
5847         "%{public}d RequestKeyboardByFocusSwitch: onFocus_: %{public}d Inner: %{public}d modalCovered: %{public}d",
5848         host->GetId(), needToRequestKeyboardOnFocus_, needToRequestKeyboardInner_, IsModalCovered());
5849     if (!needToRequestKeyboardInner_ || IsModalCovered()) {
5850         return;
5851     }
5852     auto pipeline = host->GetContextRefPtr();
5853     CHECK_NULL_VOID(pipeline);
5854     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
5855     CHECK_NULL_VOID(textFieldManager);
5856     textFieldManager->SetNeedToRequestKeyboard(true);
5857     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d add requestkeyboard task", host->GetId());
5858     pipeline->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)]() {
5859         auto textField = weak.Upgrade();
5860         CHECK_NULL_VOID(textField);
5861         auto textFieldManager = manager.Upgrade();
5862         if (textFieldManager && !textFieldManager->GetNeedToRequestKeyboard()) {
5863             // already call close/attach keyboard after text field get focus, so dont request keyboard now
5864             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Already call close/attach before attach, no need attach this time");
5865             return;
5866         }
5867         if (!textField->needToRequestKeyboardInner_) {
5868             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Not need to requestKeyboard inner");
5869             return;
5870         }
5871         if (!textField->RequestKeyboard(false, true, textField->needToRequestKeyboardOnFocus_)) {
5872             return;
5873         }
5874         textField->NotifyOnEditChanged(true);
5875         textField->SetNeedToRequestKeyboardInner(false, RequestKeyboardInnerChangeReason::REQUEST_KEYBOARD_SUCCESS);
5876     });
5877 }
5878 
5879 // to distiguish request keyboard not by focus switching
RequestKeyboardNotByFocusSwitch(RequestKeyboardReason reason,SourceType sourceType)5880 bool TextFieldPattern::RequestKeyboardNotByFocusSwitch(RequestKeyboardReason reason, SourceType sourceType)
5881 {
5882     auto tmpHost = GetHost();
5883     CHECK_NULL_RETURN(tmpHost, false);
5884     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d requestKeyboard With Reason %{public}s",
5885         tmpHost->GetId(), TextFieldPattern::RequestKeyboardReasonToString(reason).c_str());
5886     if (!RequestKeyboard(false, true, true, sourceType)) {
5887         return false;
5888     }
5889     auto context = tmpHost->GetContextRefPtr();
5890     CHECK_NULL_RETURN(context, true);
5891     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
5892     CHECK_NULL_RETURN(textFieldManager, true);
5893     textFieldManager->SetNeedToRequestKeyboard(false);
5894     return true;
5895 }
5896 
TextFieldRequestFocus(RequestFocusReason reason)5897 bool TextFieldPattern::TextFieldRequestFocus(RequestFocusReason reason)
5898 {
5899     if (HasFocus()) {
5900         return true;
5901     }
5902     auto host = GetHost();
5903     CHECK_NULL_RETURN(host, false);
5904     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d Request Focus With Reason %{public}s",
5905         host->GetId(), TextFieldPattern::RequestFocusReasonToString(reason).c_str());
5906     auto focusHub = GetFocusHub();
5907     CHECK_NULL_RETURN(focusHub, false);
5908     requestFocusReason_ = reason;
5909     return focusHub->RequestFocusImmediately();
5910 }
5911 
RequestFocusReasonToString(RequestFocusReason reason)5912 std::string TextFieldPattern::RequestFocusReasonToString(RequestFocusReason reason)
5913 {
5914     switch (reason) {
5915         case RequestFocusReason::DRAG_END: {
5916             return "DragEnd";
5917         }
5918         case RequestFocusReason::DRAG_MOVE: {
5919             return "DragMove";
5920         }
5921         case RequestFocusReason::DRAG_ENTER: {
5922             return "DragEnter";
5923         }
5924         case RequestFocusReason::CLICK: {
5925             return "Click";
5926         }
5927         case RequestFocusReason::LONG_PRESS: {
5928             return "LongPress";
5929         }
5930         case RequestFocusReason::AUTO_FILL: {
5931             return "AutoFill";
5932         }
5933         case RequestFocusReason::CLEAN_NODE: {
5934             return "CleanNode";
5935         }
5936         case RequestFocusReason::MOUSE: {
5937             return "Mouse";
5938         }
5939         case RequestFocusReason::UNKNOWN:
5940         default: {
5941             break;
5942         }
5943     }
5944     return "Unknown";
5945 }
5946 
RequestKeyboardReasonToString(RequestKeyboardReason reason)5947 std::string TextFieldPattern::RequestKeyboardReasonToString(RequestKeyboardReason reason)
5948 {
5949     switch (reason) {
5950         case RequestKeyboardReason::ON_KEY_EVENT: {
5951             return "KeyEvent";
5952         }
5953         case RequestKeyboardReason::SINGLE_CLICK: {
5954             return "SingleClick";
5955         }
5956         case RequestKeyboardReason::DOUBLE_CLICK: {
5957             return "DoubleClick";
5958         }
5959         case RequestKeyboardReason::LONG_PRESS: {
5960             return "LongPress";
5961         }
5962         case RequestKeyboardReason::RESET_KEYBOARD: {
5963             return "ResetKeyboard";
5964         }
5965         case RequestKeyboardReason::MOUSE_RELEASE: {
5966             return "MouseRelease";
5967         }
5968         case RequestKeyboardReason::SET_SELECTION: {
5969             return "SetSelection";
5970         }
5971         case RequestKeyboardReason::SEARCH_REQUEST: {
5972             return "SearchRequest";
5973         }
5974         case RequestKeyboardReason::AUTO_FILL_REQUEST_FAIL: {
5975             return "AutoFillRequestFail";
5976         }
5977         case RequestKeyboardReason::SHOW_KEYBOARD_ON_FOCUS: {
5978             return "ShowKeyboardOnFocus";
5979         }
5980         case RequestKeyboardReason::STYLUS_DETECTOR: {
5981             return "StylusDetector";
5982         }
5983         case RequestKeyboardReason::CUSTOM_KEYBOARD: {
5984             return "CustomKeyboard";
5985         }
5986         case RequestKeyboardReason::UNKNOWN:
5987         default: {
5988             break;
5989         }
5990     }
5991     return "Unknown";
5992 }
5993 
IsModalCovered()5994 bool TextFieldPattern::IsModalCovered()
5995 {
5996     auto host = GetHost();
5997     CHECK_NULL_RETURN(host, false);
5998     auto pageNode = host->GetPageNode();
5999     CHECK_NULL_RETURN(pageNode, false);
6000     auto pagePattern = pageNode->GetPattern<PagePattern>();
6001     CHECK_NULL_RETURN(pagePattern, false);
6002     return pagePattern->GetIsModalCovered();
6003 }
6004 
OnVisibleChange(bool isVisible)6005 void TextFieldPattern::OnVisibleChange(bool isVisible)
6006 {
6007     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "visible change to %{public}d", isVisible);
6008     if (!isVisible && HasFocus()) {
6009         CloseKeyboard(true);
6010         if (SelectOverlayIsOn()) {
6011             StartTwinkling();
6012         }
6013     }
6014 }
6015 
HandleSurfaceChanged(int32_t newWidth,int32_t newHeight,int32_t prevWidth,int32_t prevHeight)6016 void TextFieldPattern::HandleSurfaceChanged(int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight)
6017 {
6018     if (newWidth == prevWidth && newHeight == prevHeight) {
6019         return;
6020     }
6021     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
6022         "Textfield handleSurface change, new width %{public}d, new height %{public}d, prev width %{public}d, prev "
6023         "height %{public}d",
6024         newWidth, newHeight, prevWidth, prevHeight);
6025     if (SelectOverlayIsOn()) {
6026         if (selectOverlay_->IsShowMouseMenu()) {
6027             CloseSelectOverlay();
6028         } else if (newWidth != prevWidth || newHeight != prevHeight) {
6029             DelayProcessOverlay({ .menuIsShow = false });
6030         }
6031         selectOverlay_->RemoveAvoidKeyboardCallback();
6032     }
6033     auto tmpHost = GetHost();
6034     CHECK_NULL_VOID(tmpHost);
6035     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
6036     UpdateCaretInfoToController(true);
6037     if (magnifierController_->GetShowMagnifier()) {
6038         magnifierController_->RemoveMagnifierFrameNode();
6039     }
6040 }
6041 
HandleSurfacePositionChanged(int32_t posX,int32_t posY)6042 void TextFieldPattern::HandleSurfacePositionChanged(int32_t posX, int32_t posY)
6043 {
6044     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield handleSurface position change, posX %{public}d, posY %{public}d",
6045         posX, posY);
6046     UpdateCaretInfoToController();
6047 }
6048 
InitSurfaceChangedCallback()6049 void TextFieldPattern::InitSurfaceChangedCallback()
6050 {
6051     auto host = GetHost();
6052     CHECK_NULL_VOID(host);
6053     auto pipeline = host->GetContext();
6054     CHECK_NULL_VOID(pipeline);
6055     if (!HasSurfaceChangedCallback()) {
6056         auto callbackId = pipeline->RegisterSurfaceChangedCallback(
6057             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
6058                 WindowSizeChangeReason type) {
6059                 auto pattern = weak.Upgrade();
6060                 if (pattern) {
6061                     pattern->HandleSurfaceChanged(newWidth, newHeight, prevWidth, prevHeight);
6062                 }
6063             });
6064         UpdateSurfaceChangedCallbackId(callbackId);
6065     }
6066 }
6067 
InitSurfacePositionChangedCallback()6068 void TextFieldPattern::InitSurfacePositionChangedCallback()
6069 {
6070     auto host = GetHost();
6071     CHECK_NULL_VOID(host);
6072     auto pipeline = host->GetContext();
6073     CHECK_NULL_VOID(pipeline);
6074     if (!HasSurfacePositionChangedCallback()) {
6075         auto callbackId =
6076             pipeline->RegisterSurfacePositionChangedCallback([weak = WeakClaim(this)](int32_t posX, int32_t posY) {
6077                 auto pattern = weak.Upgrade();
6078                 if (pattern) {
6079                     pattern->HandleSurfacePositionChanged(posX, posY);
6080                 }
6081             });
6082         UpdateSurfacePositionChangedCallbackId(callbackId);
6083     }
6084 }
6085 
HandleOnDelete(bool backward)6086 void TextFieldPattern::HandleOnDelete(bool backward)
6087 {
6088     if (backward) {
6089 #if defined(PREVIEW)
6090         DeleteForward(1);
6091 #else
6092         DeleteBackward(1);
6093 #endif
6094     } else {
6095 #if defined(PREVIEW)
6096         DeleteBackward(1);
6097 #else
6098         DeleteForward(1);
6099 #endif
6100     }
6101 }
6102 
HandleOnDeleteComb(bool backward)6103 bool TextFieldPattern::HandleOnDeleteComb(bool backward)
6104 {
6105     if (backward) {
6106         DeleteBackwardWord(); // LTR is left word,RTL is right word
6107     } else {
6108         DeleteForwardWord(); // LTR is right word,RTL is left word
6109     }
6110     return true;
6111 }
6112 
DeleteBackwardWord()6113 void TextFieldPattern::DeleteBackwardWord()
6114 {
6115     int32_t originCaretPosition = selectController_->GetCaretIndex();
6116     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6117     int32_t leftWordLength = GetWordLength(originCaretPosition, 0, false);
6118     if (leftWordLength < 0) {
6119         // delete 1 char
6120         leftWordLength = 1;
6121     }
6122     if (leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
6123         // delete left
6124         leftWordLength = std::max(1, originCaretPosition);
6125     }
6126     DeleteBackward(leftWordLength);
6127 }
6128 
DeleteForwardWord()6129 void TextFieldPattern::DeleteForwardWord()
6130 {
6131     int32_t originCaretPosition = selectController_->GetCaretIndex();
6132     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6133     int32_t rightWordLength = GetWordLength(originCaretPosition, 1, false);
6134     if (rightWordLength < 0) {
6135         // delete 1 char
6136         rightWordLength = 1;
6137     }
6138     if (rightWordLength > textLength || rightWordLength + selectController_->GetCaretIndex() > textLength) {
6139         // delete right
6140         rightWordLength = std::max(1, textLength - originCaretPosition);
6141     }
6142     DeleteForward(rightWordLength);
6143 }
6144 
HandleOnPageUp()6145 void TextFieldPattern::HandleOnPageUp()
6146 {
6147     if (!IsTextArea()) {
6148         return;
6149     }
6150     auto border = GetBorderWidthProperty();
6151     float frameRectHeight = std::max(frameRect_.Height(), PreferredLineHeight());
6152     float maxFrameHeight =
6153         frameRectHeight - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
6154     OnScrollCallback(maxFrameHeight, SCROLL_FROM_JUMP);
6155     auto caretRectOffset = selectController_->GetCaretRect().GetOffset();
6156     Offset offset(caretRectOffset.GetX(), GetPaddingTop() + GetBorderTop(border));
6157     selectController_->UpdateCaretInfoByOffset(offset, true);
6158     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
6159 }
6160 
HandleOnPageDown()6161 void TextFieldPattern::HandleOnPageDown()
6162 {
6163     if (!IsTextArea()) {
6164         return;
6165     }
6166     auto border = GetBorderWidthProperty();
6167     float frameRectHeight = std::max(frameRect_.Height(), PreferredLineHeight());
6168     float maxFrameHeight =
6169         frameRectHeight - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
6170     OnScrollCallback(-maxFrameHeight, SCROLL_FROM_JUMP);
6171     auto caretRectOffset = selectController_->GetCaretRect().GetOffset();
6172     Offset offset(caretRectOffset.GetX(), maxFrameHeight);
6173     selectController_->UpdateCaretInfoByOffset(offset, true);
6174     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
6175 }
6176 
GetEmojiSubStringRange(int32_t & start,int32_t & end)6177 void TextFieldPattern::GetEmojiSubStringRange(int32_t& start, int32_t& end)
6178 {
6179     TextEmojiSubStringRange range = TextEmojiProcessor::CalSubU16stringRange(
6180         start, end - start, GetTextUtf16Value(), false, true);
6181     start = range.startIndex;
6182     end = range.endIndex;
6183 }
6184 
DeleteBackward(int32_t length)6185 void TextFieldPattern::DeleteBackward(int32_t length)
6186 {
6187     CHECK_NULL_VOID(!IsDragging());
6188     CHECK_NULL_VOID(focusIndex_ == FocuseIndex::TEXT);
6189     ResetObscureTickCountDown();
6190     if (IsSelected()) {
6191         auto start = selectController_->GetStartIndex();
6192         auto end = selectController_->GetEndIndex();
6193         DeleteTextRange(start, end, TextDeleteDirection::BACKWARD);
6194         return;
6195     }
6196     if (selectController_->GetCaretIndex() <= 0) {
6197         auto isDelete = BeforeIMEDeleteValue(u"", TextDeleteDirection::BACKWARD, 0);
6198         CHECK_NULL_VOID(isDelete);
6199         AfterIMEDeleteValue(u"", TextDeleteDirection::BACKWARD);
6200         return;
6201     }
6202     inputOperations_.emplace(InputOperation::DELETE_BACKWARD);
6203     deleteBackwardOperations_.emplace(length);
6204     CloseSelectOverlay();
6205     ScrollToSafeArea();
6206     auto tmpHost = GetHost();
6207     CHECK_NULL_VOID(tmpHost);
6208     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
6209 }
6210 
DeleteBackwardOperation(int32_t length)6211 void TextFieldPattern::DeleteBackwardOperation(int32_t length)
6212 {
6213     int32_t idx = selectController_->GetCaretIndex();
6214     auto willDeleteLength = contentController_->GetDeleteLength(idx, length, true);
6215     auto value = contentController_->GetSelectedValue(idx - willDeleteLength, idx);
6216     auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::BACKWARD, idx);
6217     CHECK_NULL_VOID(isDelete);
6218     auto oldContent = contentController_->GetTextUtf16Value();
6219     int32_t count = contentController_->Delete(selectController_->GetCaretIndex(), length, true);
6220     auto isOnWillChange = OnWillChangePreDelete(oldContent, std::max(idx - count, 0), idx);
6221     if (!isOnWillChange) {
6222         contentController_->SetTextValue(oldContent);
6223         return;
6224     }
6225     selectController_->UpdateCaretIndex(std::max(idx - count, 0));
6226     if (GetIsPreviewText()) {
6227         UpdatePreviewIndex(GetPreviewTextStart(), GetPreviewTextEnd() - length);
6228     }
6229     AfterIMEDeleteValue(value, TextDeleteDirection::BACKWARD);
6230     StartTwinkling();
6231     focusIndex_ = FocuseIndex::TEXT;
6232     UpdateEditingValueToRecord();
6233 }
6234 
DeleteForwardOperation(int32_t length)6235 void TextFieldPattern::DeleteForwardOperation(int32_t length)
6236 {
6237     auto caretIndex = selectController_->GetCaretIndex();
6238     auto willDeleteLength = contentController_->GetDeleteLength(caretIndex, length, false);
6239     auto value = contentController_->GetSelectedValue(caretIndex, caretIndex + willDeleteLength);
6240     auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::FORWARD, caretIndex);
6241     CHECK_NULL_VOID(isDelete);
6242     ResetObscureTickCountDown();
6243     auto oldContent = contentController_->GetTextUtf16Value();
6244     contentController_->Delete(caretIndex, length, false);
6245     if (GetIsPreviewText()) {
6246         UpdatePreviewIndex(GetPreviewTextStart(), GetPreviewTextEnd() - length);
6247     }
6248     auto isOnWillChange = OnWillChangePreDelete(oldContent, caretIndex, caretIndex + willDeleteLength);
6249     if (!isOnWillChange) {
6250         contentController_->SetTextValue(oldContent);
6251         return;
6252     }
6253     AfterIMEDeleteValue(value, TextDeleteDirection::FORWARD);
6254     StartTwinkling();
6255     focusIndex_ = FocuseIndex::TEXT;
6256     UpdateEditingValueToRecord();
6257 }
6258 
DeleteForward(int32_t length)6259 void TextFieldPattern::DeleteForward(int32_t length)
6260 {
6261     CHECK_NULL_VOID(!IsDragging());
6262     CHECK_NULL_VOID(focusIndex_ == FocuseIndex::TEXT);
6263     if (IsSelected()) {
6264         auto start = selectController_->GetStartIndex();
6265         auto end = selectController_->GetEndIndex();
6266         DeleteRange(start, end);
6267         return;
6268     }
6269     auto contentLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6270     if (selectController_->GetCaretIndex() >= contentLength) {
6271         auto isDelete = BeforeIMEDeleteValue(u"", TextDeleteDirection::FORWARD, contentLength);
6272         CHECK_NULL_VOID(isDelete);
6273         AfterIMEDeleteValue(u"", TextDeleteDirection::FORWARD);
6274         return;
6275     }
6276     inputOperations_.emplace(InputOperation::DELETE_FORWARD);
6277     deleteForwardOperations_.emplace(length);
6278     CloseSelectOverlay();
6279     auto tmpHost = GetHost();
6280     CHECK_NULL_VOID(tmpHost);
6281     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
6282 }
6283 
BeforeIMEDeleteValue(const std::u16string & deleteValue,TextDeleteDirection direction,int32_t offset)6284 bool TextFieldPattern::BeforeIMEDeleteValue(
6285     const std::u16string& deleteValue, TextDeleteDirection direction, int32_t offset)
6286 {
6287     auto host = GetHost();
6288     CHECK_NULL_RETURN(host, true);
6289     auto eventHub = host->GetEventHub<TextFieldEventHub>();
6290     CHECK_NULL_RETURN(eventHub, true);
6291     DeleteValueInfo deleteValueInfo;
6292     deleteValueInfo.deleteOffset = offset;
6293     deleteValueInfo.deleteValue = deleteValue;
6294     deleteValueInfo.direction = direction;
6295     return eventHub->FireOnWillDeleteEvent(deleteValueInfo);
6296 }
6297 
AfterIMEDeleteValue(const std::u16string & deleteValue,TextDeleteDirection direction)6298 void TextFieldPattern::AfterIMEDeleteValue(const std::u16string& deleteValue, TextDeleteDirection direction)
6299 {
6300     auto host = GetHost();
6301     CHECK_NULL_VOID(host);
6302     auto eventHub = host->GetEventHub<TextFieldEventHub>();
6303     CHECK_NULL_VOID(eventHub);
6304     DeleteValueInfo deleteValueInfo;
6305     deleteValueInfo.deleteOffset = selectController_->GetCaretIndex();
6306     deleteValueInfo.deleteValue = deleteValue;
6307     deleteValueInfo.direction = direction;
6308     return eventHub->FireOnDidDeleteValueEvent(deleteValueInfo);
6309 }
6310 
GetLeftTextOfCursor(int32_t number)6311 std::u16string TextFieldPattern::GetLeftTextOfCursor(int32_t number)
6312 {
6313     auto start = selectController_->GetCaretIndex();
6314     if (IsSelected()) {
6315         start = selectController_->GetStartIndex();
6316     }
6317     return contentController_->GetSelectedValue(start - number, start);
6318 }
6319 
GetRightTextOfCursor(int32_t number)6320 std::u16string TextFieldPattern::GetRightTextOfCursor(int32_t number)
6321 {
6322     auto end = selectController_->GetCaretIndex();
6323     if (IsSelected()) {
6324         end = selectController_->GetEndIndex();
6325     }
6326     return contentController_->GetSelectedValue(end, end + number);
6327 }
6328 
GetTextIndexAtCursor()6329 int32_t TextFieldPattern::GetTextIndexAtCursor()
6330 {
6331     return selectController_->GetCaretIndex();
6332 }
6333 
AfterSelection()6334 void TextFieldPattern::AfterSelection()
6335 {
6336     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Selection %{public}s, caret position %{public}d",
6337         selectController_->ToString().c_str(), selectController_->GetCaretIndex());
6338     ResetObscureTickCountDown();
6339     auto tmpHost = GetHost();
6340     CHECK_NULL_VOID(tmpHost);
6341     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6342     showSelect_ = IsSelected();
6343 }
6344 
HandleSelectionUp()6345 void TextFieldPattern::HandleSelectionUp()
6346 {
6347     if (!IsSelected()) {
6348         UpdateSelection(selectController_->GetCaretIndex());
6349     }
6350     auto newOffsetY = selectController_->GetCaretRect().GetY() - PreferredLineHeight() * 0.5 - textRect_.GetY();
6351     if (GreatOrEqual(newOffsetY, 0.0)) {
6352         OffsetF originCaretPosition;
6353         auto caretXPosition = GetOriginCaretPosition(originCaretPosition) &&
6354             GreatNotEqual(selectController_->GetCaretRect().GetX() - contentRect_.GetX(), 0) ? // handle when line head
6355             originCaretPosition.GetX() : selectController_->GetCaretRect().GetX();
6356         selectController_->MoveSecondHandleByKeyBoard(paragraph_->GetGlyphIndexByCoordinate(
6357             Offset(caretXPosition - contentRect_.GetX(), newOffsetY)));
6358     } else {
6359         selectController_->MoveSecondHandleByKeyBoard(0);
6360     }
6361     AfterSelection();
6362 }
6363 
HandleSelectionDown()6364 void TextFieldPattern::HandleSelectionDown()
6365 {
6366     if (!IsSelected()) {
6367         UpdateSelection(selectController_->GetCaretIndex());
6368     }
6369     auto newOffsetY = selectController_->GetCaretRect().GetY() + PreferredLineHeight() * 1.5 - textRect_.GetY();
6370     if (LessOrEqual(newOffsetY, textRect_.Height())) {
6371         OffsetF originCaretPosition;
6372         auto caretXPosition = GetOriginCaretPosition(originCaretPosition) ?
6373             originCaretPosition.GetX() : selectController_->GetCaretRect().GetX();
6374         selectController_->MoveSecondHandleByKeyBoard(paragraph_->GetGlyphIndexByCoordinate(
6375             Offset(caretXPosition - contentRect_.GetX(), newOffsetY)), TextAffinity::DOWNSTREAM);
6376     } else {
6377         selectController_->MoveSecondHandleByKeyBoard(
6378             static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
6379     }
6380     AfterSelection();
6381 }
6382 
HandleSelectionLeft()6383 void TextFieldPattern::HandleSelectionLeft()
6384 {
6385     if (!IsSelected()) {
6386         if (selectController_->GetCaretIndex() == 0) {
6387             return;
6388         }
6389         UpdateSelection(selectController_->GetCaretIndex());
6390         selectController_->MoveSecondHandleByKeyBoard(
6391             selectController_->GetSecondHandleIndex() -
6392             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetCaretIndex(),
6393                 true));
6394     } else {
6395         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() -
6396             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetSecondHandleIndex(),
6397                 true));
6398     }
6399     AfterSelection();
6400 }
6401 
HandleSelectionLeftWord()6402 void TextFieldPattern::HandleSelectionLeftWord()
6403 {
6404     if (selectController_->GetCaretIndex() == 0) {
6405         return;
6406     }
6407     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6408     int32_t leftWordLength = GetWordLength(selectController_->GetCaretIndex(), 0);
6409     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
6410         return;
6411     }
6412     if (!IsSelected()) {
6413         UpdateSelection(selectController_->GetCaretIndex());
6414         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
6415     } else {
6416         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
6417     }
6418     AfterSelection();
6419 }
6420 
HandleSelectionLineBegin()6421 void TextFieldPattern::HandleSelectionLineBegin()
6422 {
6423     if (selectController_->GetCaretIndex() == 0) {
6424         return;
6425     }
6426     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6427     int32_t lineBeginPosition = GetLineBeginPosition(selectController_->GetCaretIndex());
6428     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
6429         return;
6430     }
6431     if (!IsSelected()) {
6432         UpdateSelection(selectController_->GetCaretIndex());
6433         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
6434     } else {
6435         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
6436     }
6437     AfterSelection();
6438 }
6439 
HandleSelectionHome()6440 void TextFieldPattern::HandleSelectionHome()
6441 {
6442     if (selectController_->GetCaretIndex() == 0) {
6443         return;
6444     }
6445     if (!IsSelected()) {
6446         UpdateSelection(selectController_->GetCaretIndex());
6447         selectController_->MoveSecondHandleByKeyBoard(0);
6448     } else {
6449         selectController_->MoveSecondHandleByKeyBoard(0);
6450     }
6451     AfterSelection();
6452 }
6453 
HandleSelectionRight()6454 void TextFieldPattern::HandleSelectionRight()
6455 {
6456     // if currently not in select mode, reset baseOffset and move destinationOffset and caret position
6457     if (!IsSelected()) {
6458         if (selectController_->GetCaretIndex() ==
6459             static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
6460             return;
6461         }
6462         UpdateSelection(selectController_->GetCaretIndex());
6463         selectController_->MoveSecondHandleByKeyBoard(
6464             selectController_->GetSecondHandleIndex() +
6465             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(),
6466                 selectController_->GetSecondHandleIndex()));
6467     } else {
6468         // if currently not in select mode, move destinationOffset and caret position only
6469         selectController_->MoveSecondHandleByKeyBoard(
6470             selectController_->GetSecondHandleIndex() +
6471             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(),
6472                 selectController_->GetSecondHandleIndex()));
6473     }
6474     AfterSelection();
6475 }
6476 
HandleSelectionRightWord()6477 void TextFieldPattern::HandleSelectionRightWord()
6478 {
6479     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6480     if (selectController_->GetCaretIndex() == textLength) {
6481         return;
6482     }
6483     int32_t rightWordLength = GetWordLength(selectController_->GetCaretIndex(), 1);
6484     if (rightWordLength < 0 || rightWordLength > textLength ||
6485         rightWordLength + selectController_->GetCaretIndex() > textLength) {
6486         return;
6487     }
6488     if (!IsSelected()) {
6489         UpdateSelection(selectController_->GetCaretIndex());
6490         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
6491     } else {
6492         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
6493         AfterSelection();
6494     }
6495 }
6496 
HandleSelectionLineEnd()6497 void TextFieldPattern::HandleSelectionLineEnd()
6498 {
6499     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6500     if (selectController_->GetCaretIndex() == textLength) {
6501         return;
6502     }
6503     int32_t lineEndPosition = GetLineEndPosition(selectController_->GetCaretIndex());
6504     if (lineEndPosition < 0 || lineEndPosition > textLength) {
6505         return;
6506     }
6507     if (!IsSelected()) {
6508         UpdateSelection(selectController_->GetCaretIndex());
6509         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
6510     } else {
6511         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
6512     }
6513     AfterSelection();
6514 }
6515 
HandleSelectionEnd()6516 void TextFieldPattern::HandleSelectionEnd()
6517 {
6518     // shift end, select to the end of current line
6519     int32_t endPos = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6520     if (selectController_->GetCaretIndex() == endPos) {
6521         return;
6522     }
6523     if (!IsSelected()) {
6524         UpdateSelection(selectController_->GetCaretIndex());
6525         selectController_->MoveSecondHandleByKeyBoard(endPos);
6526     } else {
6527         selectController_->MoveSecondHandleByKeyBoard(endPos);
6528     }
6529     AfterSelection();
6530 }
6531 
SetCaretPosition(int32_t position,bool moveContent)6532 void TextFieldPattern::SetCaretPosition(int32_t position, bool moveContent)
6533 {
6534     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Set caret position to %{public}d", position);
6535     selectController_->MoveCaretToContentRect(position, TextAffinity::DOWNSTREAM, true, moveContent);
6536     UpdateCaretInfoToController();
6537     if (HasFocus() && !magnifierController_->GetShowMagnifier()) {
6538         StartTwinkling();
6539     }
6540     CloseSelectOverlay();
6541     CancelDelayProcessOverlay();
6542     TriggerAvoidOnCaretChange();
6543     auto tmpHost = GetHost();
6544     CHECK_NULL_VOID(tmpHost);
6545     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6546 }
6547 
SetCaretOffset(int32_t caretPostion)6548 bool TextFieldPattern::SetCaretOffset(int32_t caretPostion)
6549 {
6550     SetCaretPosition(caretPostion);
6551     return true;
6552 }
6553 
SetSelectionFlag(int32_t selectionStart,int32_t selectionEnd,const std::optional<SelectionOptions> & options,bool isForward)6554 void TextFieldPattern::SetSelectionFlag(
6555     int32_t selectionStart, int32_t selectionEnd, const std::optional<SelectionOptions>& options, bool isForward)
6556 {
6557     if (!HasFocus() || GetIsPreviewText()) {
6558         return;
6559     }
6560     auto length = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6561     selectionStart = std::clamp(selectionStart, 0, length);
6562     selectionEnd = std::clamp(selectionEnd, 0, length);
6563     moveCaretState_.isTouchCaret = false;
6564     bool isShowMenu = selectOverlay_->IsCurrentMenuVisibile();
6565     isTouchPreviewText_ = false;
6566     if (selectionStart == selectionEnd) {
6567         selectController_->MoveCaretToContentRect(selectionEnd, TextAffinity::DOWNSTREAM);
6568         StartTwinkling();
6569     } else {
6570         cursorVisible_ = false;
6571         showSelect_ = true;
6572         HandleSetSelection(selectionStart, selectionEnd, false);
6573         if (isForward) {
6574             selectController_->MoveSecondHandleToContentRect(selectionEnd);
6575             selectController_->MoveFirstHandleToContentRect(selectionStart, false);
6576         } else {
6577             selectController_->MoveFirstHandleToContentRect(selectionStart);
6578             selectController_->MoveSecondHandleToContentRect(selectionEnd);
6579         }
6580     }
6581     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SET_SELECTION)) {
6582         NotifyOnEditChanged(true);
6583     }
6584     SetIsSingleHandle(!IsSelected());
6585     if (!IsShowHandle()) {
6586         CloseSelectOverlay(true);
6587     } else {
6588         isShowMenu = IsShowMenu(options, isShowMenu);
6589         if (!isShowMenu && IsUsingMouse()) {
6590             CloseSelectOverlay();
6591         } else {
6592             ProcessOverlay({ .menuIsShow = isShowMenu, .animation = true });
6593         }
6594     }
6595     TriggerAvoidWhenCaretGoesDown();
6596     auto host = GetHost();
6597     CHECK_NULL_VOID(host);
6598     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6599 }
6600 
SetSelection(int32_t start,int32_t end,const std::optional<SelectionOptions> & options,bool isForward)6601 void TextFieldPattern::SetSelection(int32_t start, int32_t end,
6602     const std::optional<SelectionOptions>& options, bool isForward)
6603 {
6604     SetSelectionFlag(start, end, options, isForward);
6605 }
6606 
IsShowMenu(const std::optional<SelectionOptions> & options,bool defaultValue)6607 bool TextFieldPattern::IsShowMenu(const std::optional<SelectionOptions>& options, bool defaultValue)
6608 {
6609     if (!options.has_value()) {
6610         return false;
6611     }
6612     if (options.value().menuPolicy == MenuPolicy::HIDE) {
6613         return false;
6614     }
6615     if (options.value().menuPolicy == MenuPolicy::SHOW) {
6616         return true;
6617     }
6618     return defaultValue;
6619 }
6620 
OnBackPressed()6621 bool TextFieldPattern::OnBackPressed()
6622 {
6623     auto tmpHost = GetHost();
6624     CHECK_NULL_RETURN(tmpHost, false);
6625     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d receives back press event, %{public}d",
6626         tmpHost->GetId(), isCustomKeyboardAttached_);
6627     if (SelectOverlayIsOn()) {
6628         selectController_->UpdateCaretIndex(
6629             std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
6630         bool closeKeyboard = !selectOverlay_->IsCurrentMenuVisibile();
6631         CloseSelectOverlay();
6632         StartTwinkling();
6633         if (!closeKeyboard) {
6634             return IsStopBackPress();
6635         }
6636     }
6637 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
6638     if (!imeShown_ && !isCustomKeyboardAttached_) {
6639 #else
6640     if (!isCustomKeyboardAttached_) {
6641 #endif
6642         return false;
6643     }
6644 
6645     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6646     HandleCloseKeyboard(true);
6647 #if defined(ANDROID_PLATFORM)
6648     return false;
6649 #else
6650     return IsStopBackPress();
6651 #endif
6652 }
6653 
6654 bool TextFieldPattern::IsStopBackPress() const
6655 {
6656     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6657     CHECK_NULL_RETURN(layoutProperty, true);
6658     return layoutProperty->GetStopBackPressValue(true);
6659 }
6660 
6661 void TextFieldPattern::HandleCloseKeyboard(bool forceClose)
6662 {
6663     if (independentControlKeyboard_) {
6664         CloseKeyboard(true, false);
6665     } else {
6666         CloseKeyboard(forceClose);
6667         if (HasFocus()) {
6668             FocusHub::LostFocusToViewRoot();
6669         }
6670     }
6671 }
6672 
6673 int32_t TextFieldPattern::GetNakedCharPosition() const
6674 {
6675     if (IsTextArea() || !IsInPasswordMode() || obscureTickCountDown_ <= 0 || !GetTextObscured()) {
6676         return -1;
6677     }
6678     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6679     CHECK_NULL_RETURN(layoutProperty, -1);
6680     auto content = contentController_->GetTextUtf16Value();
6681     if (content.empty()) {
6682         return -1;
6683     }
6684     return nakedCharPosition_;
6685 }
6686 
6687 std::string TextFieldPattern::TextInputTypeToString() const
6688 {
6689     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6690     CHECK_NULL_RETURN(layoutProperty, "");
6691     switch (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
6692         case TextInputType::NUMBER:
6693             return IsTextArea() ? "TextAreaType.NUMBER" : "InputType.Number";
6694         case TextInputType::EMAIL_ADDRESS:
6695             return IsTextArea() ? "TextAreaType.EMAIL" : "InputType.Email";
6696         case TextInputType::PHONE:
6697             return IsTextArea() ? "TextAreaType.PHONE_NUMBER" : "InputType.PhoneNumber";
6698         case TextInputType::URL:
6699             return IsTextArea() ? "TextAreaType.URL" : "InputType.URL";
6700         case TextInputType::VISIBLE_PASSWORD:
6701             return "InputType.Password";
6702         case TextInputType::USER_NAME:
6703             return "InputType.USER_NAME";
6704         case TextInputType::NEW_PASSWORD:
6705             return "InputType.NEW_PASSWORD";
6706         case TextInputType::NUMBER_PASSWORD:
6707             return "InputType.NUMBER_PASSWORD";
6708         case TextInputType::NUMBER_DECIMAL:
6709             return IsTextArea() ? "TextAreaType.NUMBER_DECIMAL" : "InputType.NUMBER_DECIMAL";
6710         default:
6711             return isTextInput_ ? "InputType.Normal" : "TextAreaType.NORMAL";
6712     }
6713 }
6714 
6715 std::string TextFieldPattern::TextContentTypeToString() const
6716 {
6717     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6718     CHECK_NULL_RETURN(layoutProperty, "");
6719     auto contentType = layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED);
6720     if (contentTypeMap_.find(contentType) != contentTypeMap_.end()) {
6721         return contentTypeMap_[contentType].second;
6722     }
6723     return contentTypeMap_[TextContentType::UNSPECIFIED].second;
6724 }
6725 
6726 std::string TextFieldPattern::TextInputActionToString() const
6727 {
6728     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6729     CHECK_NULL_RETURN(layoutProperty, "");
6730     switch (GetTextInputActionValue(GetDefaultTextInputAction())) {
6731         case TextInputAction::GO:
6732             return "EnterKeyType.Go";
6733         case TextInputAction::SEARCH:
6734             return "EnterKeyType.Search";
6735         case TextInputAction::SEND:
6736             return "EnterKeyType.Send";
6737         case TextInputAction::NEXT:
6738             return "EnterKeyType.Next";
6739         default:
6740             return "EnterKeyType.Done";
6741     }
6742 }
6743 
6744 std::string TextFieldPattern::GetPlaceholderFont() const
6745 {
6746     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6747     CHECK_NULL_RETURN(layoutProperty, "");
6748     auto theme = GetTheme();
6749     CHECK_NULL_RETURN(theme, "");
6750     auto jsonValue = JsonUtil::Create(true);
6751     if (layoutProperty->GetPlaceholderItalicFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL) {
6752         jsonValue->Put("style", "FontStyle.Normal");
6753     } else {
6754         jsonValue->Put("style", "FontStyle.Italic");
6755     }
6756     // placeholder font size not exist in theme, use normal font size by default
6757     if (!layoutProperty->GetPlaceholderFontSize()) {
6758         jsonValue->Put("size", GetFontSize().c_str());
6759     } else {
6760         jsonValue->Put("size", layoutProperty->GetPlaceholderFontSize()->ToString().c_str());
6761     }
6762     auto weight = layoutProperty->GetPlaceholderFontWeightValue(theme->GetFontWeight());
6763     switch (weight) {
6764         case FontWeight::W100:
6765             jsonValue->Put("weight", "100");
6766             break;
6767         case FontWeight::W200:
6768             jsonValue->Put("weight", "200");
6769             break;
6770         case FontWeight::W300:
6771             jsonValue->Put("weight", "300");
6772             break;
6773         case FontWeight::W400:
6774             jsonValue->Put("weight", "400");
6775             break;
6776         case FontWeight::W500:
6777             jsonValue->Put("weight", "500");
6778             break;
6779         case FontWeight::W600:
6780             jsonValue->Put("weight", "600");
6781             break;
6782         case FontWeight::W700:
6783             jsonValue->Put("weight", "700");
6784             break;
6785         case FontWeight::W800:
6786             jsonValue->Put("weight", "800");
6787             break;
6788         case FontWeight::W900:
6789             jsonValue->Put("weight", "900");
6790             break;
6791         default:
6792             jsonValue->Put("fontWeight", V2::ConvertWrapFontWeightToStirng(weight).c_str());
6793     }
6794     auto family = layoutProperty->GetPlaceholderFontFamilyValue({ "sans-serif" });
6795     std::string jsonFamily = ConvertFontFamily(family);
6796     jsonValue->Put("fontFamily", jsonFamily.c_str());
6797     return jsonValue->ToString();
6798 }
6799 
6800 RefPtr<TextFieldTheme> TextFieldPattern::GetTheme() const
6801 {
6802     if (textFieldTheme_.Upgrade()) {
6803         return textFieldTheme_.Upgrade();
6804     }
6805     auto tmpHost = GetHost();
6806     CHECK_NULL_RETURN(tmpHost, nullptr);
6807     auto context = tmpHost->GetContext();
6808     CHECK_NULL_RETURN(context, nullptr);
6809     auto theme = context->GetTheme<TextFieldTheme>(tmpHost->GetThemeScopeId());
6810     return theme;
6811 }
6812 
6813 void TextFieldPattern::InitTheme()
6814 {
6815     auto tmpHost = GetHost();
6816     CHECK_NULL_VOID(tmpHost);
6817     auto context = tmpHost->GetContext();
6818     CHECK_NULL_VOID(context);
6819     textFieldTheme_ = context->GetTheme<TextFieldTheme>(tmpHost->GetThemeScopeId());
6820 }
6821 
6822 std::string TextFieldPattern::GetTextColor() const
6823 {
6824     auto theme = GetTheme();
6825     CHECK_NULL_RETURN(theme, "");
6826     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6827     CHECK_NULL_RETURN(layoutProperty, "");
6828     return layoutProperty->GetTextColorValue(theme->GetTextColor()).ColorToString();
6829 }
6830 
6831 std::string TextFieldPattern::GetCaretColor() const
6832 {
6833     auto theme = GetTheme();
6834     CHECK_NULL_RETURN(theme, "");
6835     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6836     CHECK_NULL_RETURN(paintProperty, "");
6837     return paintProperty->GetCursorColorValue(theme->GetCursorColor()).ColorToString();
6838 }
6839 
6840 std::string TextFieldPattern::GetPlaceholderColor() const
6841 {
6842     auto theme = GetTheme();
6843     CHECK_NULL_RETURN(theme, "");
6844     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6845     CHECK_NULL_RETURN(layoutProperty, "");
6846     return layoutProperty->GetPlaceholderTextColorValue(theme->GetPlaceholderColor()).ColorToString();
6847 }
6848 
6849 std::string TextFieldPattern::GetFontSize() const
6850 {
6851     auto theme = GetTheme();
6852     CHECK_NULL_RETURN(theme, "");
6853     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6854     CHECK_NULL_RETURN(layoutProperty, "");
6855     return layoutProperty->GetFontSizeValue(theme->GetFontSize()).ToString();
6856 }
6857 
6858 std::string TextFieldPattern::GetMinFontSize() const
6859 {
6860     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6861     CHECK_NULL_RETURN(layoutProperty, "");
6862     auto minFontSize = layoutProperty->GetAdaptMinFontSize();
6863     return minFontSize.has_value() ? minFontSize->ToString() : "";
6864 }
6865 
6866 std::string TextFieldPattern::GetMaxFontSize() const
6867 {
6868     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6869     CHECK_NULL_RETURN(layoutProperty, "");
6870     auto maxFontSize = layoutProperty->GetAdaptMaxFontSize();
6871     return maxFontSize.has_value() ? maxFontSize->ToString() : "";
6872 }
6873 
6874 std::string TextFieldPattern::GetMinFontScale() const
6875 {
6876     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6877     CHECK_NULL_RETURN(layoutProperty, std::to_string(MINFONTSCALE));
6878     return std::to_string(layoutProperty->GetMinFontScale().value_or(MINFONTSCALE));
6879 }
6880 
6881 std::string TextFieldPattern::GetMaxFontScale() const
6882 {
6883     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6884     CHECK_NULL_RETURN(layoutProperty, std::to_string(MAXFONTSCALE));
6885     return std::to_string(layoutProperty->GetMaxFontScale().value_or(MAXFONTSCALE));
6886 }
6887 
6888 std::string TextFieldPattern::GetEllipsisMode() const
6889 {
6890     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6891     CHECK_NULL_RETURN(layoutProperty, V2::ConvertEllipsisModeToString(EllipsisMode::TAIL));
6892     return V2::ConvertEllipsisModeToString(layoutProperty->GetEllipsisMode().value_or(
6893         EllipsisMode::TAIL));
6894 }
6895 
6896 std::string TextFieldPattern::GetTextIndent() const
6897 {
6898     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6899     CHECK_NULL_RETURN(layoutProperty, "");
6900     auto textIndent = layoutProperty->GetTextIndent();
6901     return textIndent.has_value() ? textIndent->ToString() : "";
6902 }
6903 
6904 Ace::FontStyle TextFieldPattern::GetItalicFontStyle() const
6905 {
6906     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6907     CHECK_NULL_RETURN(layoutProperty, Ace::FontStyle::NORMAL);
6908     return layoutProperty->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL);
6909 }
6910 
6911 std::string TextFieldPattern::GetShowPasswordIconString() const
6912 {
6913     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6914     CHECK_NULL_RETURN(layoutProperty, "false");
6915     return layoutProperty->GetShowPasswordIconValue(false) ? "true" : "false";
6916 }
6917 
6918 std::string TextFieldPattern::GetInputStyleString() const
6919 {
6920     std::string result = isTextInput_ ? "TextInputStyle.Default" : "TextContentStyle.DEFAULT";
6921     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6922     CHECK_NULL_RETURN(paintProperty, result);
6923     switch (paintProperty->GetInputStyleValue(InputStyle::DEFAULT)) {
6924         case InputStyle::INLINE:
6925             result = isTextInput_ ? "TextInputStyle.Inline" : "TextContentStyle.INLINE";
6926             break;
6927         case InputStyle::DEFAULT:
6928         default:
6929             break;
6930     }
6931     return result;
6932 }
6933 
6934 FontWeight TextFieldPattern::GetFontWeight() const
6935 {
6936     auto theme = GetTheme();
6937     CHECK_NULL_RETURN(theme, FontWeight::NORMAL);
6938     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6939     CHECK_NULL_RETURN(layoutProperty, FontWeight::NORMAL);
6940     return layoutProperty->GetFontWeightValue(theme->GetFontWeight());
6941 }
6942 
6943 std::string TextFieldPattern::GetFontFamily() const
6944 {
6945     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6946     CHECK_NULL_RETURN(layoutProperty, "HarmonyOS Sans");
6947     auto family = layoutProperty->GetFontFamilyValue({ "HarmonyOS Sans" });
6948     return ConvertFontFamily(family);
6949 }
6950 
6951 TextAlign TextFieldPattern::GetTextAlign() const
6952 {
6953     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6954     CHECK_NULL_RETURN(layoutProperty, TextAlign::START);
6955     return layoutProperty->GetTextAlign().value_or(TextAlign::START);
6956 }
6957 
6958 uint32_t TextFieldPattern::GetMaxLength() const
6959 {
6960     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6961     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
6962     return layoutProperty->HasMaxLength() ? layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())
6963                                           : Infinity<uint32_t>();
6964 }
6965 
6966 uint32_t TextFieldPattern::GetMaxLines() const
6967 {
6968     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6969     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
6970     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
6971     CHECK_NULL_RETURN(paintProperty, Infinity<uint32_t>());
6972     if (IsNormalInlineState()) {
6973         return layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE);
6974     }
6975     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(Infinity<uint32_t>())
6976                                          : Infinity<uint32_t>();
6977 }
6978 
6979 std::u16string TextFieldPattern::GetPlaceHolder() const
6980 {
6981     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6982     CHECK_NULL_RETURN(layoutProperty, u"");
6983     return layoutProperty->GetPlaceholderValue(u"");
6984 }
6985 
6986 std::string TextFieldPattern::GetInputFilter() const
6987 {
6988     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6989     CHECK_NULL_RETURN(layoutProperty, "");
6990     return layoutProperty->GetInputFilterValue("");
6991 }
6992 
6993 std::u16string TextFieldPattern::GetErrorTextString() const
6994 {
6995     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6996     CHECK_NULL_RETURN(layoutProperty, u"");
6997     return layoutProperty->GetErrorTextValue(u"");
6998 }
6999 
7000 bool TextFieldPattern::GetErrorTextState() const
7001 {
7002     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7003     CHECK_NULL_RETURN(layoutProperty, false);
7004     return layoutProperty->GetShowErrorTextValue(false);
7005 }
7006 
7007 void TextFieldPattern::SearchRequestKeyboard()
7008 {
7009     StartTwinkling();
7010     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SEARCH_REQUEST)) {
7011         NotifyOnEditChanged(true);
7012     }
7013 }
7014 
7015 std::string TextFieldPattern::GetCopyOptionString() const
7016 {
7017     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7018     CHECK_NULL_RETURN(layoutProperty, "");
7019     std::string copyOptionString = "CopyOptions.Local";
7020     switch (layoutProperty->GetCopyOptionsValue(CopyOptions::Local)) {
7021         case CopyOptions::InApp:
7022             copyOptionString = "CopyOptions.InApp";
7023             break;
7024         case CopyOptions::Local:
7025             copyOptionString = "CopyOptions.Local";
7026             break;
7027         case CopyOptions::Distributed:
7028             copyOptionString = "CopyOptions.Distributed";
7029             break;
7030         case CopyOptions::None:
7031             copyOptionString = "CopyOptions.None";
7032             break;
7033         default:
7034             break;
7035     }
7036     return copyOptionString;
7037 }
7038 
7039 std::string TextFieldPattern::GetBarStateString() const
7040 {
7041     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7042     CHECK_NULL_RETURN(layoutProperty, "");
7043     std::string displayModeString;
7044     switch (layoutProperty->GetDisplayModeValue(DisplayMode::AUTO)) {
7045         case DisplayMode::OFF:
7046             displayModeString = "BarState.OFF";
7047             break;
7048         case DisplayMode::ON:
7049             displayModeString = "BarState.ON";
7050             break;
7051         case DisplayMode::AUTO:
7052         default:
7053             displayModeString = "BarState.AUTO";
7054             break;
7055     }
7056     return displayModeString;
7057 }
7058 
7059 void TextFieldPattern::UpdateScrollBarOffset()
7060 {
7061     if (!GetScrollBar() && !GetScrollBarProxy()) {
7062         return;
7063     }
7064     auto paddingHeight = GetPaddingTop() + GetPaddingBottom();
7065     auto contentHeight = contentRect_.Height();
7066     if (inlineFocusState_) {
7067         paddingHeight = 0.0f;
7068         contentHeight = GetSingleLineHeight() * GetMaxLines();
7069     }
7070     Size size(frameRect_.Width(), contentHeight + paddingHeight);
7071     UpdateScrollBarRegion(
7072         contentRect_.GetY() - textRect_.GetY(), textRect_.Height() + paddingHeight, size, Offset(0.0, 0.0));
7073     auto tmpHost = GetHost();
7074     CHECK_NULL_VOID(tmpHost);
7075     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
7076 }
7077 
7078 void TextFieldPattern::PlayScrollBarAppearAnimation()
7079 {
7080     auto scrollBar = GetScrollBar();
7081     if (scrollBar) {
7082         scrollBar->PlayScrollBarAppearAnimation();
7083     }
7084 }
7085 
7086 void TextFieldPattern::ScheduleDisappearDelayTask()
7087 {
7088     auto scrollBar = GetScrollBar();
7089     if (scrollBar) {
7090         scrollBar->SetPressed(false);
7091         scrollBar->PlayScrollBarShrinkAnimation();
7092         scrollBar->ScheduleDisappearDelayTask();
7093     }
7094 }
7095 
7096 bool TextFieldPattern::OnScrollCallback(float offset, int32_t source)
7097 {
7098     if (source == SCROLL_FROM_START) {
7099         PlayScrollBarAppearAnimation();
7100         if (selectOverlay_->IsCurrentMenuVisibile()) {
7101             isTextSelectionMenuShow_ = true;
7102         } else if (CheckSelectAreaVisible()) {
7103             isTextSelectionMenuShow_ = false;
7104         }
7105         selectOverlay_->HideMenu(true);
7106         return true;
7107     }
7108     if (IsReachedBoundary(offset)) {
7109         return false;
7110     }
7111     PlayScrollBarAppearAnimation();
7112     OnTextInputScroll(offset);
7113     OnTextAreaScroll(offset);
7114     return true;
7115 }
7116 
7117 void TextFieldPattern::CheckScrollable()
7118 {
7119     if (IsTextArea()) {
7120         if (contentController_->IsEmpty()) {
7121             scrollable_ = false;
7122         } else {
7123             scrollable_ = GreatNotEqual(textRect_.Height(), contentRect_.Height());
7124         }
7125         SetScrollEnabled(scrollable_);
7126     } else {
7127         SetScrollEnabled(GreatNotEqual(textRect_.Width(), contentRect_.Width()));
7128     }
7129 }
7130 
7131 bool TextFieldPattern::HasStateStyle(UIState state) const
7132 {
7133     auto host = GetHost();
7134     CHECK_NULL_RETURN(host, false);
7135     auto hub = host->GetEventHub<EventHub>();
7136     CHECK_NULL_RETURN(hub, false);
7137     return hub->HasStateStyle(state);
7138 }
7139 
7140 double TextFieldPattern::GetScrollBarWidth()
7141 {
7142     auto scrollBar = GetScrollBar();
7143     double scrollBarWidth = 0.0;
7144     if (scrollBar) {
7145         scrollBarWidth = scrollBar->GetBarRect().Width();
7146     }
7147     return scrollBarWidth;
7148 }
7149 
7150 void TextFieldPattern::AddCounterNode()
7151 {
7152     auto host = GetHost();
7153     CHECK_NULL_VOID(host);
7154     if (counterDecorator_ && (IsShowPasswordIcon() || IsNormalInlineState())) {
7155         CleanCounterNode();
7156         return;
7157     }
7158     if (!counterDecorator_) {
7159         auto counterDecorator = MakeRefPtr<CounterDecorator>(host);
7160         counterDecorator_ = counterDecorator;
7161     }
7162 }
7163 
7164 void TextFieldPattern::SetShowError()
7165 {
7166     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7167     CHECK_NULL_VOID(layoutProperty);
7168     auto passWordMode = IsInPasswordMode();
7169     auto textFieldTheme = GetTheme();
7170     CHECK_NULL_VOID(textFieldTheme);
7171     auto tmpHost = GetHost();
7172     CHECK_NULL_VOID(tmpHost);
7173     auto renderContext = tmpHost->GetRenderContext();
7174     CHECK_NULL_VOID(renderContext);
7175     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7176     CHECK_NULL_VOID(paintProperty);
7177     auto isUnderLine = IsUnderlineMode();
7178     auto errorText = layoutProperty->GetErrorTextValue(u"");
7179     if (IsShowError()) { // update error state
7180         if (isUnderLine) {
7181             underlineColor_ = userUnderlineColor_.error.value_or(textFieldTheme->GetErrorUnderlineColor());
7182             underlineWidth_ = ERROR_UNDERLINE_WIDTH;
7183         } else if (passWordMode) {
7184             if (!paintProperty->HasBorderWidthFlagByUser()) {
7185                 paintProperty->UpdateInnerBorderWidth(textFieldTheme->GetErrorTextInputBorderWidth());
7186                 paintProperty->UpdateInnerBorderColor(textFieldTheme->GetPasswordErrorBorderColor());
7187             } else {
7188                 BorderColorProperty borderColor;
7189                 borderColor.SetColor(textFieldTheme->GetPasswordErrorBorderColor());
7190                 renderContext->UpdateBorderColor(borderColor);
7191             }
7192             renderContext->UpdateBackgroundColor(textFieldTheme->GetPasswordErrorInputColor());
7193             layoutProperty->UpdateTextColor(textFieldTheme->GetPasswordErrorTextColor());
7194             if (!layoutProperty->HasPlaceholderTextColor()) {
7195                 layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetPlaceholderColor());
7196             }
7197         }
7198     }
7199     UpdateErrorTextMargin();
7200 }
7201 
7202 float TextFieldPattern::CalcDecoratorWidth(const RefPtr<FrameNode>& decoratorNode)
7203 {
7204     float decoratorWidth = 0.0f;
7205     CHECK_NULL_RETURN(decoratorNode, 0.0f);
7206     auto textPattern = decoratorNode->GetPattern<TextPattern>();
7207     CHECK_NULL_RETURN(textPattern, 0.0f);
7208     auto paragraphs = textPattern->GetParagraphs();
7209     for (auto &&info : paragraphs) {
7210         if (info.paragraph) {
7211             float width = info.paragraph->GetLongestLine();
7212             decoratorWidth = std::max(decoratorWidth, width);
7213         }
7214     }
7215     return decoratorWidth;
7216 }
7217 
7218 float TextFieldPattern::CalcDecoratorHeight(const RefPtr<FrameNode>& decoratorNode)
7219 {
7220     CHECK_NULL_RETURN(decoratorNode, 0.0f);
7221     auto geometryNode = decoratorNode->GetGeometryNode();
7222     CHECK_NULL_RETURN(geometryNode, 0.0f);
7223     return geometryNode->GetFrameRect().Height();
7224 }
7225 
7226 void TextFieldPattern::UpdateErrorTextMargin()
7227 {
7228     auto tmpHost = GetHost();
7229     CHECK_NULL_VOID(tmpHost);
7230     if (IsShowError()) {
7231         if (!errorDecorator_) {
7232             auto errorDecorator = MakeRefPtr<ErrorDecorator>(tmpHost);
7233             errorDecorator_ = errorDecorator;
7234         }
7235         errorDecorator_->UpdateTextFieldMargin();
7236     } else {
7237         errorDecorator_.Reset();
7238     }
7239 }
7240 
7241 void TextFieldPattern::ApplyUnderlineTheme()
7242 {
7243     if (!IsUnderlineMode()) {
7244         return;
7245     }
7246     SetThemeAttr();
7247     auto theme = GetTheme();
7248     CHECK_NULL_VOID(theme);
7249     if (IsShowError()) {
7250         underlineColor_ = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
7251     } else {
7252         underlineColor_ = HasFocus() ? userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor())
7253             : userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
7254     }
7255     underlineWidth_ = HasFocus() ? TYPING_UNDERLINE_WIDTH : UNDERLINE_WIDTH;
7256 }
7257 
7258 float TextFieldPattern::GetMarginBottom() const
7259 {
7260     auto tmpHost = GetHost();
7261     CHECK_NULL_RETURN(tmpHost, 0.0f);
7262     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7263     CHECK_NULL_RETURN(layoutProperty, 0.0f);
7264     const auto& getMargin = layoutProperty->GetMarginProperty();
7265     if (getMargin && getMargin->bottom.has_value()) {
7266         return getMargin->bottom->GetDimension().ConvertToPx();
7267     }
7268     return 0.0f;
7269 }
7270 
7271 std::string TextFieldPattern::GetShowResultImageSrc() const
7272 {
7273     auto tmpHost = GetHost();
7274     CHECK_NULL_RETURN(tmpHost, "");
7275     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7276     CHECK_NULL_RETURN(layoutProperty, "");
7277     auto showImageSource = layoutProperty->GetShowPasswordSourceInfo();
7278     if (showImageSource && !showImageSource->GetSrc().empty()) {
7279         return showImageSource->GetSrc();
7280     }
7281     return SHOW_PASSWORD_SVG;
7282 }
7283 
7284 std::string TextFieldPattern::GetNormalUnderlineColorStr() const
7285 {
7286     auto theme = GetTheme();
7287     CHECK_NULL_RETURN(theme, "");
7288     Color normal = userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
7289     return normal.ColorToString();
7290 }
7291 
7292 std::string TextFieldPattern::GetTypingUnderlineColorStr() const
7293 {
7294     auto theme = GetTheme();
7295     CHECK_NULL_RETURN(theme, "");
7296     Color typing = userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor());
7297     return typing.ColorToString();
7298 }
7299 
7300 std::string TextFieldPattern::GetDisableUnderlineColorStr() const
7301 {
7302     auto theme = GetTheme();
7303     CHECK_NULL_RETURN(theme, "");
7304     Color disable = userUnderlineColor_.disable.value_or(theme->GetDisableUnderlineColor());
7305     return disable.ColorToString();
7306 }
7307 
7308 std::string TextFieldPattern::GetErrorUnderlineColorStr() const
7309 {
7310     auto theme = GetTheme();
7311     CHECK_NULL_RETURN(theme, "");
7312     Color error = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
7313     return error.ColorToString();
7314 }
7315 
7316 std::string TextFieldPattern::GetHideResultImageSrc() const
7317 {
7318     auto tmpHost = GetHost();
7319     CHECK_NULL_RETURN(tmpHost, "");
7320     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7321     CHECK_NULL_RETURN(layoutProperty, "");
7322     auto hideSourceInfo = layoutProperty->GetHidePasswordSourceInfo();
7323     if (hideSourceInfo && !hideSourceInfo->GetSrc().empty()) {
7324         return hideSourceInfo->GetSrc();
7325     }
7326     return HIDE_PASSWORD_SVG;
7327 }
7328 
7329 void TextFieldPattern::RestorePreInlineStates()
7330 {
7331     ResetContextAttr();
7332     ApplyNormalTheme();
7333     ApplyUnderlineTheme();
7334     ProcessInnerPadding();
7335     ProcessResponseArea();
7336     ProcessRectPadding();
7337 }
7338 
7339 void TextFieldPattern::ProcessRectPadding()
7340 {
7341     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7342     CHECK_NULL_VOID(layoutProperty);
7343     auto& paddingProperty = layoutProperty->GetPaddingProperty();
7344     CHECK_NULL_VOID(paddingProperty);
7345     auto top = paddingProperty->top.has_value() ? paddingProperty->top->GetDimension().ConvertToPx() : 0.0f;
7346     textRect_.SetTop(top);
7347 }
7348 
7349 void TextFieldPattern::TextAreaInputRectUpdate(RectF& rect)
7350 {
7351     auto tmpHost = GetHost();
7352     CHECK_NULL_VOID(tmpHost);
7353     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7354     CHECK_NULL_VOID(layoutProperty);
7355     auto theme = GetTheme();
7356     CHECK_NULL_VOID(theme);
7357     if (IsTextArea() && !contentController_->IsEmpty()) {
7358         auto inputContentWidth = GetParagraph()->GetMaxIntrinsicWidth();
7359         switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
7360             case TextAlign::START:
7361                 if (inputContentWidth < contentRect_.Width()) {
7362                     rect.SetWidth(inputContentWidth);
7363                 }
7364                 break;
7365             case TextAlign::CENTER:
7366                 if (inputContentWidth < contentRect_.Width()) {
7367                     rect.SetLeft(
7368                         static_cast<float>(rect.GetX()) + contentRect_.Width() / 2.0f - inputContentWidth / 2.0f);
7369                     rect.SetWidth(inputContentWidth);
7370                 }
7371                 break;
7372             case TextAlign::END:
7373                 if (inputContentWidth < contentRect_.Width()) {
7374                     rect.SetLeft(static_cast<float>(rect.GetX()) + contentRect_.Width() -
7375                                  static_cast<float>(theme->GetCursorWidth().ConvertToPx()) - inputContentWidth);
7376                     rect.SetWidth(inputContentWidth);
7377                 }
7378                 break;
7379             default:
7380                 break;
7381         }
7382     }
7383 }
7384 
7385 void TextFieldPattern::TextIsEmptyRect(RectF& rect)
7386 {
7387     rect = selectController_->CalculateEmptyValueCaretRect();
7388 }
7389 
7390 void TextFieldPattern::UpdateRectByTextAlign(RectF& rect)
7391 {
7392     auto tmpHost = GetHost();
7393     CHECK_NULL_VOID(tmpHost);
7394     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7395     CHECK_NULL_VOID(layoutProperty);
7396     if (!layoutProperty->HasTextAlign()) {
7397         return;
7398     }
7399     switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
7400         case TextAlign::START:
7401             return;
7402         case TextAlign::CENTER:
7403             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()) * 0.5f);
7404             return;
7405         case TextAlign::END:
7406             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()));
7407             return;
7408         default:
7409             return;
7410     }
7411 }
7412 
7413 void TextFieldPattern::ProcessInlinePaddingAndMargin()
7414 {
7415     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7416     CHECK_NULL_VOID(layoutProperty);
7417     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7418     auto theme = GetTheme();
7419     CHECK_NULL_VOID(theme);
7420     PaddingProperty userPadding;
7421     MarginProperty userMargin;
7422     if (paintProperty->HasPaddingByUser()) {
7423         userPadding = paintProperty->GetPaddingByUserValue();
7424     } else {
7425         auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
7426         userPadding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
7427         userPadding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
7428         userPadding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
7429         userPadding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
7430     }
7431     if (paintProperty->HasMarginByUser()) {
7432         userMargin = paintProperty->GetMarginByUserValue();
7433     }
7434     MarginProperty margin;
7435     margin.bottom = CalcLength(userMargin.bottom->GetDimension() + userPadding.bottom->GetDimension());
7436     margin.right = CalcLength(userMargin.right->GetDimension() + userPadding.right->GetDimension());
7437     margin.left = CalcLength(userMargin.left->GetDimension() + userPadding.left->GetDimension());
7438     margin.top = CalcLength(userMargin.top->GetDimension() + userPadding.top->GetDimension());
7439     layoutProperty->UpdateMargin(margin);
7440     if (!IsTextArea()) {
7441         layoutProperty->UpdatePlaceholderMaxLines(layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
7442         layoutProperty->ResetMaxLines();
7443     }
7444     if (layoutProperty->HasTextOverflow()) {
7445         layoutProperty->UpdateTextOverflowMaxLines(layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
7446     }
7447 }
7448 
7449 void TextFieldPattern::ApplyInlineTheme()
7450 {
7451     if (!IsInlineMode()) {
7452         return;
7453     }
7454     auto tmpHost = GetHost();
7455     CHECK_NULL_VOID(tmpHost);
7456     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7457     CHECK_NULL_VOID(layoutProperty);
7458     auto renderContext = tmpHost->GetRenderContext();
7459     CHECK_NULL_VOID(renderContext);
7460     auto theme = GetTheme();
7461     CHECK_NULL_VOID(theme);
7462     layoutProperty->UpdateTextColor(theme->GetInlineTextColor());
7463     auto radius = theme->GetInlineRadiusSize();
7464     renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
7465     renderContext->UpdateBackgroundColor(theme->GetInlineBgColor());
7466     BorderWidthProperty inlineBorderWidth;
7467     inlineBorderWidth.SetBorderWidth(INLINE_BORDER_WIDTH);
7468     layoutProperty->UpdateBorderWidth(inlineBorderWidth);
7469     renderContext->UpdateBorderWidth(inlineBorderWidth);
7470     BorderColorProperty inlineBorderColor;
7471     inlineBorderColor.SetColor(theme->GetInlineBorderColor());
7472     renderContext->UpdateBorderColor(inlineBorderColor);
7473 
7474     if (layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL) {
7475         layoutProperty->UpdatePadding({ CalcLength(theme->getInlinePaddingRight()),
7476             CalcLength(theme->getInlinePaddingLeft()), CalcLength(0.0f), CalcLength(0.0f) });
7477     } else {
7478         layoutProperty->UpdatePadding({ CalcLength(theme->getInlinePaddingLeft()),
7479             CalcLength(theme->getInlinePaddingRight()), CalcLength(0.0f), CalcLength(0.0f)});
7480     }
7481     ProcessInnerPadding();
7482     ProcessInlinePaddingAndMargin();
7483 }
7484 
7485 bool TextFieldPattern::ResetObscureTickCountDown()
7486 {
7487     auto oldTickCountDown_ = obscureTickCountDown_;
7488     if (!IsTextArea() && GetTextObscured() && IsInPasswordMode()) {
7489         obscureTickCountDown_ = 0;
7490     }
7491     return oldTickCountDown_ != obscureTickCountDown_;
7492 }
7493 
7494 bool TextFieldPattern::IsInPasswordMode() const
7495 {
7496     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7497     CHECK_NULL_RETURN(layoutProperty, false);
7498     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
7499     return inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
7500            inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
7501 }
7502 
7503 bool TextFieldPattern::IsNormalInlineState() const
7504 {
7505     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7506     CHECK_NULL_RETURN(paintProperty, false);
7507     auto tmpHost = GetHost();
7508     CHECK_NULL_RETURN(tmpHost, false);
7509     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7510     CHECK_NULL_RETURN(layoutProperty, false);
7511     return paintProperty->GetInputStyleValue(InputStyle::DEFAULT) == InputStyle::INLINE &&
7512            (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::UNSPECIFIED ||
7513                layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::TEXT);
7514 }
7515 
7516 bool TextFieldPattern::IsUnspecifiedOrTextType() const
7517 {
7518     auto tmpHost = GetHost();
7519     CHECK_NULL_RETURN(tmpHost, false);
7520     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7521     CHECK_NULL_RETURN(layoutProperty, false);
7522     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
7523     return inputType == TextInputType::UNSPECIFIED || inputType == TextInputType::TEXT;
7524 }
7525 
7526 void TextFieldPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7527 {
7528     /* no fixed attr below, just return */
7529     if (filter.IsFastFilter()) {
7530         return;
7531     }
7532     json->PutExtAttr("placeholder", UtfUtils::Str16DebugToStr8(GetPlaceHolder()).c_str(), filter);
7533     json->PutExtAttr("text", contentController_->GetTextValue().c_str(), filter);
7534     json->PutExtAttr("fontSize", GetFontSize().c_str(), filter);
7535     json->PutExtAttr("fontColor", GetTextColor().c_str(), filter);
7536     json->PutExtAttr("fontStyle",
7537         GetItalicFontStyle() == Ace::FontStyle::NORMAL ? "FontStyle.Normal" : "FontStyle.Italic", filter);
7538     json->PutExtAttr("fontWeight", V2::ConvertWrapFontWeightToStirng(GetFontWeight()).c_str(), filter);
7539     json->PutExtAttr("fontFamily", GetFontFamily().c_str(), filter);
7540     json->PutExtAttr("textAlign", V2::ConvertWrapTextAlignToString(GetTextAlign()).c_str(), filter);
7541     json->PutExtAttr("caretColor", GetCaretColor().c_str(), filter);
7542     json->PutExtAttr("type", TextInputTypeToString().c_str(), filter);
7543     json->PutExtAttr("contentType", TextContentTypeToString().c_str(), filter);
7544     json->PutExtAttr("placeholderColor", GetPlaceholderColor().c_str(), filter);
7545     json->PutExtAttr("placeholderFont", GetPlaceholderFont().c_str(), filter);
7546     json->PutExtAttr("enterKeyType", TextInputActionToString().c_str(), filter);
7547     json->PutExtAttr("maxLength", GreatOrEqual(GetMaxLength(),
7548         Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLength()).c_str(), filter);
7549     json->PutExtAttr("inputFilter", GetInputFilter().c_str(), filter);
7550     json->PutExtAttr("copyOption", GetCopyOptionString().c_str(), filter);
7551     json->PutExtAttr("style", GetInputStyleString().c_str(), filter);
7552 
7553     auto jsonValue = JsonUtil::Create(true);
7554     if (IsShowPasswordSymbol()) {
7555         jsonValue->Put("onIconSrc", static_cast<int64_t>(GetTheme()->GetShowSymbolId()));
7556         jsonValue->Put("offIconSrc", static_cast<int64_t>(GetTheme()->GetHideSymbolId()));
7557     } else {
7558         jsonValue->Put("onIconSrc", GetShowResultImageSrc().c_str());
7559         jsonValue->Put("offIconSrc", GetHideResultImageSrc().c_str());
7560     }
7561     json->PutExtAttr("passwordIcon", jsonValue->ToString().c_str(), filter);
7562     json->PutExtAttr("showError", GetErrorTextState() ? UtfUtils::Str16DebugToStr8(GetErrorTextString()).c_str() :
7563         "undefined", filter);
7564     json->PutExtAttr("maxLines", GreatOrEqual(GetMaxLines(),
7565         Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLines()).c_str(), filter);
7566     json->PutExtAttr("barState", GetBarStateString().c_str(), filter);
7567     json->PutExtAttr("caretPosition", std::to_string(GetCaretIndex()).c_str(), filter);
7568     json->PutExtAttr("enablePreviewText", GetSupportPreviewText(), filter);
7569     json->PutExtAttr("minFontScale", GetMinFontScale().c_str(), filter);
7570     json->PutExtAttr("maxFontScale", GetMaxFontScale().c_str(), filter);
7571     json->PutExtAttr("ellipsisMode",GetEllipsisMode().c_str(), filter);
7572     ToJsonValueForOption(json, filter);
7573     ToJsonValueSelectOverlay(json, filter);
7574 }
7575 
7576 void TextFieldPattern::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
7577 {
7578     Pattern::ToTreeJson(json, config);
7579     json->Put(TreeKey::CONTENT, contentController_->GetTextValue().c_str());
7580     json->Put(TreeKey::PLACEHOLDER, GetPlaceHolder().c_str());
7581 }
7582 
7583 void TextFieldPattern::ToJsonValueForOption(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7584 {
7585     auto underlineColorJsonValue = JsonUtil::Create(true);
7586     underlineColorJsonValue->Put("normal", GetNormalUnderlineColorStr().c_str());
7587     underlineColorJsonValue->Put("typing", GetTypingUnderlineColorStr().c_str());
7588     underlineColorJsonValue->Put("error", GetErrorUnderlineColorStr().c_str());
7589     underlineColorJsonValue->Put("disable", GetDisableUnderlineColorStr().c_str());
7590     json->PutExtAttr("underlineColor", underlineColorJsonValue->ToString().c_str(), filter);
7591 
7592     auto host = GetHost();
7593     CHECK_NULL_VOID(host);
7594     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7595     CHECK_NULL_VOID(layoutProperty);
7596     auto jsonShowCounter = JsonUtil::Create(true);
7597     jsonShowCounter->Put("value", layoutProperty->GetShowCounterValue(false));
7598     auto jsonShowCounterOptions = JsonUtil::Create(true);
7599     jsonShowCounterOptions->Put("thresholdPercentage", layoutProperty->GetSetCounterValue(DEFAULT_MODE));
7600     jsonShowCounterOptions->Put("highlightBorder", layoutProperty->GetShowHighlightBorderValue(true));
7601     jsonShowCounter->Put("options", jsonShowCounterOptions);
7602     json->PutExtAttr("showCounter", jsonShowCounter, filter);
7603     json->PutExtAttr("keyboardAppearance", static_cast<int32_t>(keyboardAppearance_), filter);
7604     json->PutExtAttr("enableHapticFeedback", isEnableHapticFeedback_ ? "true" : "false", filter);
7605 }
7606 
7607 void TextFieldPattern::ToJsonValueSelectOverlay(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7608 {
7609     json->PutExtAttr("CaretStatus", cursorVisible_ ? "show" : "hide", filter);
7610     json->PutExtAttr("CaretTwinkling", isCaretTwinkling_ ? "true" : "false", filter);
7611     json->PutExtAttr("caretRect", selectController_->GetCaretRect().ToString().c_str(), filter);
7612     json->PutExtAttr("caretWidth", std::to_string(selectController_->GetCaretRect().Width()).c_str(), filter);
7613     json->PutExtAttr("isShowMagnifier", magnifierController_->GetShowMagnifier() ? "true" : "false", filter);
7614     json->PutExtAttr("MagnifierPosition", magnifierController_->GetLocalOffset().ToString().c_str(), filter);
7615 
7616     auto manager = selectOverlay_->GetManager<SelectContentOverlayManager>();
7617     CHECK_NULL_VOID(manager);
7618     auto selectOverlayInfo = manager->GetSelectOverlayInfo();
7619     CHECK_NULL_VOID(selectOverlayInfo);
7620 
7621     //handle info
7622     json->PutExtAttr("IsSingleHandle", selectOverlayInfo->isSingleHandle ? "true" : "false", filter);
7623     json->PutExtAttr("IsHandleReverse", selectOverlayInfo->handleReverse ? "true" : "false", filter);
7624     json->PutExtAttr("FirstHandleRect", selectOverlayInfo->firstHandle.paintRect.ToString().c_str(), filter);
7625     json->PutExtAttr("FirstHandleStartPoint",
7626         selectOverlayInfo->firstHandle.paintInfo.startPoint.ToString().c_str(), filter);
7627     json->PutExtAttr("FirstHandleEndPoint",
7628         selectOverlayInfo->firstHandle.paintInfo.endPoint.ToString().c_str(), filter);
7629     json->PutExtAttr("IsFirstHandlePaintByPoints",
7630         selectOverlayInfo->firstHandle.isPaintHandleWithPoints ? "true" : "false", filter);
7631     json->PutExtAttr("SecondHandleRect", selectOverlayInfo->secondHandle.paintRect.ToString().c_str(), filter);
7632     json->PutExtAttr("SecondHandleStartPoint",
7633         selectOverlayInfo->secondHandle.paintInfo.startPoint.ToString().c_str(), filter);
7634     json->PutExtAttr("SecondHandleEndPoint",
7635         selectOverlayInfo->secondHandle.paintInfo.endPoint.ToString().c_str(), filter);
7636     json->PutExtAttr("IsSecondHandlePaintByPoints",
7637         selectOverlayInfo->secondHandle.isPaintHandleWithPoints ? "true" : "false", filter);
7638 
7639     //menu
7640     auto menuNode = manager->GetSelectOverlayNode();
7641     CHECK_NULL_VOID(menuNode);
7642     json->PutExtAttr("MenuNode", menuNode->GetTag().c_str(), filter);
7643     if (menuNode->GetAncestorNodeOfFrame(true)) {
7644         json->PutExtAttr("MountOn", menuNode->GetAncestorNodeOfFrame(true)->GetTag().c_str(), filter);
7645     }
7646     auto menuLayoutProperty = menuNode->GetLayoutProperty();
7647     CHECK_NULL_VOID(menuLayoutProperty);
7648     auto menuVisible = static_cast<int32_t>(menuLayoutProperty->GetVisibility().value_or(VisibleType::VISIBLE));
7649     json->PutExtAttr("Visible", std::to_string(menuVisible).c_str(), filter);
7650     auto menuGeometryNode = menuNode->GetGeometryNode();
7651     CHECK_NULL_VOID(menuGeometryNode);
7652     json->PutExtAttr("MenuFrameRect", menuGeometryNode->GetFrameRect().ToString().c_str(), filter);
7653     json->PutExtAttr("MenuItemCount", std::to_string(selectOverlayInfo->menuOptionItems.size()).c_str(), filter);
7654     for (auto menuItme : selectOverlayInfo->menuOptionItems) {
7655         json->PutExtAttr("MenuItme", menuItme.content.value_or("").c_str(), filter);
7656     }
7657 }
7658 
7659 void TextFieldPattern::FromJson(const std::unique_ptr<JsonValue>& json)
7660 {
7661     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7662     layoutProperty->UpdatePlaceholder(UtfUtils::Str8DebugToStr16(json->GetString("placeholder")));
7663     UpdateEditingValue(json->GetString("text"), StringUtils::StringToInt(json->GetString("caretPosition")));
7664     FireOnTextChangeEvent();
7665     UpdateSelection(GetCaretIndex());
7666     auto maxLines = json->GetString("maxLines");
7667     if (!maxLines.empty() && maxLines != "INF") {
7668         layoutProperty->UpdateMaxLines(StringUtils::StringToUint(maxLines));
7669     }
7670     static const std::unordered_map<std::string, CopyOptions> uMap = {
7671         { "CopyOptions.None", CopyOptions::None },
7672         { "CopyOptions.InApp", CopyOptions::InApp },
7673         { "CopyOptions.Local", CopyOptions::Local },
7674         { "CopyOptions.Distributed", CopyOptions::Distributed },
7675     };
7676     auto copyOption = json->GetString("copyOption");
7677     CopyOptions copyOptionsEnum = CopyOptions::Local;
7678     auto iter = uMap.find(copyOption);
7679     if (iter != uMap.end()) {
7680         copyOptionsEnum = iter->second;
7681     }
7682     layoutProperty->UpdateCopyOptions(copyOptionsEnum);
7683     Pattern::FromJson(json);
7684 }
7685 
7686 void TextFieldPattern::SetAccessibilityAction()
7687 {
7688     auto host = GetHost();
7689     CHECK_NULL_VOID(host);
7690     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7691     CHECK_NULL_VOID(accessibilityProperty);
7692     accessibilityProperty->SetAccessibilityGroup(true);
7693     SetAccessibilityActionOverlayAndSelection();
7694     SetAccessibilityActionGetAndSetCaretPosition();
7695     SetAccessibilityMoveTextAction();
7696     SetAccessibilityErrotText();
7697 }
7698 
7699 void TextFieldPattern::SetAccessibilityActionOverlayAndSelection()
7700 {
7701     auto host = GetHost();
7702     CHECK_NULL_VOID(host);
7703     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7704     CHECK_NULL_VOID(accessibilityProperty);
7705     accessibilityProperty->SetActionSetText([weakPtr = WeakClaim(this)](const std::string& value) {
7706         const auto& pattern = weakPtr.Upgrade();
7707         CHECK_NULL_VOID(pattern);
7708         pattern->InsertValue(UtfUtils::Str8DebugToStr16(value));
7709     });
7710 
7711     accessibilityProperty->SetActionSetSelection([weakPtr = WeakClaim(this)](int32_t start,
7712                                                                              int32_t end, bool isForward) {
7713             const auto& pattern = weakPtr.Upgrade();
7714             CHECK_NULL_VOID(pattern);
7715             pattern->SetSelectionFlag(start, end, std::nullopt, isForward);
7716         });
7717 
7718     accessibilityProperty->SetActionCopy([weakPtr = WeakClaim(this)]() {
7719         const auto& pattern = weakPtr.Upgrade();
7720         CHECK_NULL_VOID(pattern);
7721         if (pattern->AllowCopy()) {
7722             pattern->HandleOnCopy();
7723             pattern->CloseSelectOverlay(true);
7724         }
7725     });
7726 
7727     accessibilityProperty->SetActionCut([weakPtr = WeakClaim(this)]() {
7728         const auto& pattern = weakPtr.Upgrade();
7729         CHECK_NULL_VOID(pattern);
7730         if (pattern->AllowCopy()) {
7731             pattern->HandleOnCut();
7732             pattern->CloseSelectOverlay(true);
7733         }
7734     });
7735 
7736     accessibilityProperty->SetActionPaste([weakPtr = WeakClaim(this)]() {
7737         const auto& pattern = weakPtr.Upgrade();
7738         CHECK_NULL_VOID(pattern);
7739         pattern->HandleOnPaste();
7740         pattern->CloseSelectOverlay(true);
7741     });
7742 
7743     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
7744         const auto& pattern = weakPtr.Upgrade();
7745         CHECK_NULL_VOID(pattern);
7746         auto current = pattern->selectController_->GetEndIndex();
7747         pattern->SetInSelectMode(SelectionMode::NONE);
7748         pattern->UpdateSelection(current);
7749         pattern->SetSelectionFlag(current, current, std::nullopt);
7750         pattern->CloseSelectOverlay(true);
7751         pattern->StartTwinkling();
7752     });
7753 }
7754 
7755 void TextFieldPattern::SetAccessibilityActionGetAndSetCaretPosition()
7756 {
7757     auto host = GetHost();
7758     CHECK_NULL_VOID(host);
7759     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7760     CHECK_NULL_VOID(accessibilityProperty);
7761     accessibilityProperty->SetActionSetIndex([weakPtr = WeakClaim(this)](int32_t index) {
7762         const auto& pattern = weakPtr.Upgrade();
7763         CHECK_NULL_VOID(pattern);
7764         pattern->SetCaretPosition(index);
7765     });
7766 
7767     accessibilityProperty->SetActionGetIndex([weakPtr = WeakClaim(this)]() -> int32_t {
7768         const auto& pattern = weakPtr.Upgrade();
7769         CHECK_NULL_RETURN(pattern, -1);
7770         auto index = pattern->selectController_->GetCaretIndex();
7771         return index;
7772     });
7773 }
7774 
7775 void TextFieldPattern::SetAccessibilityMoveTextAction()
7776 {
7777     auto host = GetHost();
7778     CHECK_NULL_VOID(host);
7779     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
7780     CHECK_NULL_VOID(accessibilityProperty);
7781     accessibilityProperty->SetActionMoveText([weakPtr = WeakClaim(this)](int32_t moveUnit, bool forward) {
7782         const auto& pattern = weakPtr.Upgrade();
7783         CHECK_NULL_VOID(pattern);
7784         auto host = pattern->GetHost();
7785         CHECK_NULL_VOID(host);
7786         if (pattern->contentController_->IsEmpty()) {
7787             return;
7788         }
7789         int range = 0;
7790         if (moveUnit == 1) {
7791             range = 1;
7792         }
7793         auto caretPosition = forward ? pattern->selectController_->GetCaretIndex() + range
7794                                      : pattern->selectController_->GetCaretIndex() - range;
7795         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7796         pattern->SetCaretPosition(caretPosition);
7797     });
7798 }
7799 
7800 void TextFieldPattern::SetAccessibilityErrotText()
7801 {
7802     auto host = GetHost();
7803     CHECK_NULL_VOID(host);
7804     auto accessibilityProperty = host->GetAccessibilityProperty<TextFieldAccessibilityProperty>();
7805     CHECK_NULL_VOID(accessibilityProperty);
7806     accessibilityProperty->SetErrorText(UtfUtils::Str16DebugToStr8(GetErrorTextString()));
7807 }
7808 
7809 void TextFieldPattern::StopEditing()
7810 {
7811     if (!HasFocus()) {
7812         return;
7813     }
7814     auto host = GetHost();
7815     CHECK_NULL_VOID(host);
7816     ContainerScope scope(host->GetInstanceId());
7817     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Stop Editing", host->GetId());
7818     FocusHub::LostFocusToViewRoot();
7819     UpdateSelection(selectController_->GetCaretIndex());
7820     StopTwinkling();
7821     CloseKeyboard(true);
7822     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
7823 }
7824 
7825 void TextFieldPattern::DumpInfo()
7826 {
7827     auto host = GetHost();
7828     CHECK_NULL_VOID(host);
7829     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7830     CHECK_NULL_VOID(layoutProperty);
7831     auto& dumpLog = DumpLog::GetInstance();
7832     dumpLog.AddDesc(std::string("Content:").append(GetDumpTextValue()));
7833     dumpLog.AddDesc(std::string("autoWidth: ").append(std::to_string(layoutProperty->GetWidthAutoValue(false))));
7834     dumpLog.AddDesc(std::string("MaxLength:").append(std::to_string(GetMaxLength())));
7835     dumpLog.AddDesc(std::string("fontSize:").append(GetFontSize()));
7836     dumpLog.AddDesc(std::string("fontWeight:").append(V2::ConvertWrapFontWeightToStirng(GetFontWeight())));
7837     dumpLog.AddDesc(std::string("fontFamily:").append(GetFontFamily()));
7838     auto flag = GetItalicFontStyle() == Ace::FontStyle::NORMAL;
7839     dumpLog.AddDesc(std::string("fontStyle:").append(flag ? "FontStyle.Normal" : "FontStyle.Italic"));
7840     dumpLog.AddDesc(std::string("InputFilter:").append(GetInputFilter()));
7841     auto lineHeight = layoutProperty->GetLineHeight().value_or(0.0_vp).ConvertToPx();
7842     dumpLog.AddDesc(std::string("lineHeight:").append(std::to_string(lineHeight)));
7843     auto maxLines = GreatOrEqual(GetMaxLines(), Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLines());
7844     dumpLog.AddDesc(std::string("MaxLines:").append(maxLines));
7845     dumpLog.AddDesc(std::string("TextIndent:").append(GetTextIndent()));
7846     dumpLog.AddDesc(std::string("showError:").append(GetErrorTextState() ?
7847         UtfUtils::Str16DebugToStr8(GetErrorTextString()) : "undefined"));
7848     dumpLog.AddDesc(std::string("CopyOption:").append(GetCopyOptionString()));
7849     dumpLog.AddDesc(std::string("TextAlign:").append(V2::ConvertWrapTextAlignToString(GetTextAlign())));
7850     dumpLog.AddDesc(std::string("CaretPosition:").append(std::to_string(GetCaretIndex())));
7851     dumpLog.AddDesc(std::string("type:").append(TextInputTypeToString()));
7852     dumpLog.AddDesc(std::string("enterKeyType:").append(TextInputActionToString()));
7853     dumpLog.AddDesc(std::string("HasFocus:").append(std::to_string(HasFocus())));
7854     dumpLog.AddDesc(std::string("enableKeyboardOnFocus:").append(std::to_string(needToRequestKeyboardOnFocus_)));
7855     dumpLog.AddDesc(std::string("supportPreviewText:").append(std::to_string(GetSupportPreviewText())));
7856     dumpLog.AddDesc(
7857         std::string("enableAutoFill:").append(std::to_string(layoutProperty->GetEnableAutoFillValue(true))));
7858     dumpLog.AddDesc(std::string("contentType:").append(TextContentTypeToString()));
7859     dumpLog.AddDesc(std::string("style:").append(GetInputStyleString()));
7860     dumpLog.AddDesc(std::string("PreviewTextStart:").append(std::to_string(GetPreviewTextStart())));
7861     dumpLog.AddDesc(std::string("PreviewTextEnd:").append(std::to_string(GetPreviewTextEnd())));
7862     dumpLog.AddDesc(std::string("PreTextValue:").append(UtfUtils::Str16DebugToStr8(GetPreviewTextValue())));
7863     dumpLog.AddDesc(textSelector_.ToString());
7864     dumpLog.AddDesc(std::string("wordBreak:")
7865             .append(V2::ConvertWrapWordBreakToString(layoutProperty->GetWordBreak().value_or(WordBreak::BREAK_WORD))));
7866     dumpLog.AddDesc(std::string("HeightAdaptivePolicy: ").append(V2::ConvertWrapTextHeightAdaptivePolicyToString(
7867         layoutProperty->GetHeightAdaptivePolicy().value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST))));
7868     dumpLog.AddDesc(std::string("IsAIWrite: ").append(std::to_string(IsShowAIWrite())));
7869     DumpPlaceHolderInfo();
7870     DumpScaleInfo();
7871     DumpTextEngineInfo();
7872     DumpAdvanceInfo();
7873 }
7874 
7875 void TextFieldPattern::DumpTextEngineInfo()
7876 {
7877     auto& dumpLog = DumpLog::GetInstance();
7878     dumpLog.AddDesc(std::string("-----TextEngine paragraphs_ info-----"));
7879     CHECK_NULL_VOID(paragraph_);
7880     dumpLog.AddDesc(std::string("GetTextWidth:")
7881         .append(std::to_string(paragraph_->GetTextWidth()))
7882         .append(" GetHeight:")
7883         .append(std::to_string(paragraph_->GetHeight()))
7884         .append(" GetMaxWidth:")
7885         .append(std::to_string(paragraph_->GetMaxWidth()))
7886         .append(" GetMaxIntrinsicWidth:")
7887         .append(std::to_string(paragraph_->GetMaxIntrinsicWidth())));
7888     dumpLog.AddDesc(std::string("GetLineCount:")
7889         .append(std::to_string(paragraph_->GetLineCount()))
7890         .append(" GetLongestLine:")
7891         .append(std::to_string(paragraph_->GetLongestLine()))
7892         .append(" GetLongestLineWithIndent:")
7893         .append(std::to_string(paragraph_->GetLongestLineWithIndent())));
7894 }
7895 
7896 void TextFieldPattern::DumpAdvanceInfo()
7897 {
7898     if (customKeyboard_ || customKeyboardBuilder_) {
7899         DumpLog::GetInstance().AddDesc(
7900             std::string("CustomKeyboard: true, Attached:").append(std::to_string(isCustomKeyboardAttached_)));
7901     }
7902     DumpLog::GetInstance().AddDesc(std::string("FontColor: ").append(GetTextColor()));
7903 #if defined(ENABLE_STANDARD_INPUT)
7904     auto miscTextConfig = GetMiscTextConfig();
7905     CHECK_NULL_VOID(miscTextConfig.has_value());
7906     MiscServices::TextConfig textConfig = miscTextConfig.value();
7907     DumpLog::GetInstance().AddDesc(
7908         std::string("RequestKeyboard calling window :").append(std::to_string(textConfig.windowId)));
7909     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
7910     DumpLog::GetInstance().AddDesc(std::string("cursorInfo, left:")
7911                                        .append(std::to_string(cursorInfo.left))
7912                                        .append(", top:")
7913                                        .append(std::to_string(cursorInfo.top))
7914                                        .append(", width:")
7915                                        .append(std::to_string(cursorInfo.width))
7916                                        .append(", height:")
7917                                        .append(std::to_string(cursorInfo.height)));
7918 #endif
7919     DumpLog::GetInstance().AddDesc(std::string("textRect: ").append(contentRect_.ToString()));
7920     DumpLog::GetInstance().AddDesc(std::string("contentRect: ").append(contentRect_.ToString()));
7921 }
7922 
7923 void TextFieldPattern::DumpPlaceHolderInfo()
7924 {
7925     DumpLog::GetInstance().AddDesc(std::string("placeholder: ").append(UtfUtils::Str16DebugToStr8(GetPlaceHolder())));
7926     DumpLog::GetInstance().AddDesc(std::string("placeholderColor: ").append(GetPlaceholderColor()));
7927     DumpLog::GetInstance().AddDesc(std::string("placeholderFont: ").append(GetPlaceholderFont()));
7928 }
7929 
7930 void TextFieldPattern::DumpScaleInfo()
7931 {
7932     auto& dumpLog = DumpLog::GetInstance();
7933     dumpLog.AddDesc(std::string("-----DumpScaleInfo-----"));
7934     dumpLog.AddDesc(std::string("MinFontSize:").append(GetMinFontSize()));
7935     dumpLog.AddDesc(std::string("MaxFontSize:").append(GetMaxFontSize()));
7936     auto textLayoutProp = GetLayoutProperty<TextFieldLayoutProperty>();
7937     auto minFontScale = textLayoutProp->GetMinFontScale().value_or(0.0f);
7938     dumpLog.AddDesc(std::string("minFontScale: ").append(std::to_string(minFontScale)));
7939     auto maxfontScale = textLayoutProp->GetMaxFontScale().value_or(static_cast<float>(INT32_MAX));
7940     dumpLog.AddDesc(std::string("maxFontScale1: ").append(std::to_string(maxfontScale)));
7941     auto host = GetHost();
7942     CHECK_NULL_VOID(host);
7943     auto pipeline = host->GetContext();
7944     CHECK_NULL_VOID(pipeline);
7945     auto fontScale = pipeline->GetFontScale();
7946     auto fontWeightScale = pipeline->GetFontWeightScale();
7947     auto followSystem = pipeline->IsFollowSystem();
7948     float maxFontScale = pipeline->GetMaxAppFontScale();
7949     auto halfLeading = pipeline->GetHalfLeading();
7950     dumpLog.AddDesc(std::string("fontScale: ").append(std::to_string(fontScale)));
7951     dumpLog.AddDesc(std::string("fontWeightScale: ").append(std::to_string(fontWeightScale)));
7952     dumpLog.AddDesc(std::string("IsFollowSystem: ").append(std::to_string(followSystem)));
7953     dumpLog.AddDesc(std::string("maxFontScale: ").append(std::to_string(maxFontScale)));
7954     dumpLog.AddDesc(std::string("halfLeading: ").append(std::to_string(halfLeading)));
7955 }
7956 
7957 std::string TextFieldPattern::GetDumpTextValue() const
7958 {
7959     if (IsInPasswordMode()) {
7960         auto len = GetTextValue().length();
7961         auto passwordLen = "passwordLen:" + std::to_string(len);
7962         return passwordLen;
7963     } else {
7964         return GetTextValue();
7965     }
7966 }
7967 
7968 void TextFieldPattern::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap, bool needsRecordData)
7969 {
7970     CHECK_NULL_VOID(viewDataWrap);
7971     auto host = GetHost();
7972     CHECK_NULL_VOID(host);
7973     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7974     CHECK_NULL_VOID(layoutProperty);
7975     auto autoFillTypeAndMetaData = GetAutoFillTypeAndMetaData();
7976     auto info = PageNodeInfoWrap::CreatePageNodeInfoWrap();
7977     CHECK_NULL_VOID(info);
7978     info->SetId(host->GetId());
7979     info->SetDepth(host->GetDepth());
7980     info->SetAutoFillType(autoFillTypeAndMetaData.autoFillType);
7981     info->SetMetadata(autoFillTypeAndMetaData.metadata);
7982     info->SetTag(host->GetTag());
7983     auto utf8TextValue = UtfUtils::Str16DebugToStr8(contentController_->GetTextUtf16Value());
7984     if (autoFillOtherAccount_) {
7985         viewDataWrap->SetOtherAccount(true);
7986         info->SetValue(utf8TextValue);
7987         autoFillOtherAccount_ = false;
7988     } else {
7989         info->SetValue(utf8TextValue);
7990     }
7991     if (needsRecordData) {
7992         lastAutoFillTextValue_ = utf8TextValue;
7993     }
7994     info->SetPlaceholder(UtfUtils::Str16DebugToStr8(GetPlaceHolder()));
7995     info->SetPasswordRules(layoutProperty->GetPasswordRulesValue(""));
7996     info->SetEnableAutoFill(layoutProperty->GetEnableAutoFillValue(true));
7997     auto offsetToWindow = host->GetTransformRelativeOffset();
7998     auto geometryNode = host->GetGeometryNode();
7999     CHECK_NULL_VOID(geometryNode);
8000     auto pageNodeRect = geometryNode->GetFrameRect();
8001     pageNodeRect.SetLeft(offsetToWindow.GetX());
8002     pageNodeRect.SetTop(offsetToWindow.GetY());
8003     info->SetPageNodeRect(pageNodeRect);
8004     info->SetIsFocus(HasFocus());
8005     viewDataWrap->AddPageNodeInfoWrap(info);
8006 }
8007 
8008 void TextFieldPattern::NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,
8009     RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
8010 {
8011     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "autoFillType:%{public}d", static_cast<int32_t>(autoFillType));
8012     SetFillRequestFinish(true);
8013     auto host = GetHost();
8014     CHECK_NULL_VOID(host);
8015     CHECK_NULL_VOID(viewDataWrap);
8016     CHECK_NULL_VOID(nodeWrap);
8017     auto isFocus = nodeWrap->GetIsFocus();
8018     if (isFocus && !HasFocus()) {
8019         TextFieldRequestFocus(RequestFocusReason::AUTO_FILL);
8020         DoProcessAutoFill();
8021     }
8022     auto type = GetAutoFillType();
8023     bool fromOtherAccount = viewDataWrap->GetOtherAccount();
8024     if (!(type == AceAutoFillType::ACE_NEW_PASSWORD && type == autoFillType) && !fromOtherAccount) {
8025         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "Set last auto fill text value.");
8026         lastAutoFillTextValue_ = nodeWrap->GetValue();
8027     }
8028 
8029     if (!contentController_ || contentController_->GetTextValue() == nodeWrap->GetValue()) {
8030         return;
8031     }
8032     bool isWillChange = OnWillChangePreSetValue(UtfUtils::Str8DebugToStr16(nodeWrap->GetValue()));
8033     if (!isWillChange) {
8034         return;
8035     }
8036     contentController_->SetTextValue(UtfUtils::Str8DebugToStr16(nodeWrap->GetValue()));
8037     auto textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
8038     selectController_->UpdateCaretIndex(textLength);
8039     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
8040 }
8041 
8042 bool TextFieldPattern::ParseFillContentJsonValue(const std::unique_ptr<JsonValue>& jsonObject,
8043     std::unordered_map<std::string, std::variant<std::string, bool, int32_t>>& map)
8044 {
8045     if (!jsonObject->IsValid() || jsonObject->IsArray() || !jsonObject->IsObject()) {
8046         TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "fillContent format is not right");
8047         return false;
8048     }
8049     auto child = jsonObject->GetChild();
8050 
8051     while (child && child->IsValid()) {
8052         if (!child->IsObject() && child->IsString()) {
8053             std::string strKey = child->GetKey();
8054             std::string strVal = child->GetString();
8055             if (strKey.empty()) {
8056                 continue;
8057             }
8058             if (map.size() < MAX_FILL_CONTENT_SIZE) {
8059                 map.insert(std::pair<std::string, std::variant<std::string, bool, int32_t> >(strKey, strVal));
8060             } else {
8061                 TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "fillContent is more than 5");
8062                 break;
8063             }
8064         }
8065         child = child->GetNext();
8066     }
8067     return true;
8068 }
8069 
8070 void TextFieldPattern::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
8071 {
8072     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "NotifyFillRequestFailed errCode:%{public}d", errCode);
8073     SetFillRequestFinish(true);
8074 
8075 #if defined(ENABLE_STANDARD_INPUT)
8076     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "fillContent size is : %{public}zu", fillContent.size());
8077     if (errCode == AUTO_FILL_CANCEL) {
8078         if (!fillContent.empty() && IsTriggerAutoFillPassword()) {
8079             auto jsonObject = JsonUtil::ParseJsonString(fillContent);
8080             CHECK_NULL_VOID(jsonObject);
8081             fillContentMap_.clear();
8082             ParseFillContentJsonValue(jsonObject, fillContentMap_);
8083         }
8084     }
8085     if (!isPopup || (isPopup && errCode == AUTO_FILL_CANCEL)) {
8086         if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::AUTO_FILL_REQUEST_FAIL)) {
8087             NotifyOnEditChanged(true);
8088         }
8089     }
8090 #endif
8091 }
8092 
8093 bool TextFieldPattern::CheckAutoSave()
8094 {
8095     auto host = GetHost();
8096     CHECK_NULL_RETURN(host, false);
8097     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8098     CHECK_NULL_RETURN(layoutProperty, false);
8099     if (!layoutProperty->GetEnableAutoFillValue(true)) {
8100         return false;
8101     }
8102     if (!contentController_ || contentController_->GetTextUtf16Value().empty()) {
8103         return false;
8104     }
8105     auto autoFillType = GetAutoFillType();
8106     if (IsAutoFillUserName(autoFillType)) {
8107         if (!lastAutoFillTextValue_.empty() &&
8108             contentController_->GetTextValue() != lastAutoFillTextValue_) {
8109             return true;
8110         }
8111     }
8112     if (AceAutoFillType::ACE_UNSPECIFIED < autoFillType && autoFillType <= AceAutoFillType::END &&
8113         !IsAutoFillUserName(autoFillType)) {
8114         if (contentController_->GetTextValue() != lastAutoFillTextValue_) {
8115             return true;
8116         }
8117     }
8118     return false;
8119 }
8120 
8121 bool TextFieldPattern::IsTouchAtLeftOffset(float currentOffsetX)
8122 {
8123     return LessNotEqual(currentOffsetX, contentRect_.GetX() + contentRect_.Width() * 0.5);
8124 }
8125 
8126 OffsetF TextFieldPattern::GetDragUpperLeftCoordinates()
8127 {
8128     if (!IsSelected()) {
8129         return { 0.0f, 0.0f };
8130     }
8131     auto selectRects = selectController_->GetSelectedRects();
8132     auto startY = selectRects.front().Top();
8133     auto startX = selectRects.front().Left();
8134     auto endY = selectRects.back().Top();
8135     OffsetF startOffset;
8136     if (NearEqual(startY, endY)) {
8137         startOffset = { (IsTextArea() ? contentRect_.GetX() : textRect_.GetX()) + startX,
8138             startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
8139     } else {
8140         startOffset = { contentRect_.GetX(), startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
8141     }
8142 
8143     if (startOffset.GetY() < contentRect_.GetY()) {
8144         startOffset.SetY(contentRect_.GetY());
8145     }
8146     if (startOffset.GetX() < contentRect_.GetX()) {
8147         startOffset.SetX(contentRect_.GetX());
8148     }
8149     return startOffset + GetPaintRectGlobalOffset();
8150 }
8151 
8152 void TextFieldPattern::OnColorConfigurationUpdate()
8153 {
8154     ScrollablePattern::OnColorConfigurationUpdate();
8155     auto host = GetHost();
8156     CHECK_NULL_VOID(host);
8157     auto theme = GetTheme();
8158     CHECK_NULL_VOID(theme);
8159     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8160     CHECK_NULL_VOID(layoutProperty);
8161     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8162     CHECK_NULL_VOID(paintProperty);
8163     if (!paintProperty->HasTextColorFlagByUser()) {
8164         layoutProperty->UpdateTextColor(theme->GetTextColor());
8165     }
8166     if (magnifierController_) {
8167         magnifierController_->SetColorModeChange(true);
8168     }
8169     auto context = host->GetContext();
8170     CHECK_NULL_VOID(context);
8171     auto colorMode = context->GetColorMode();
8172     SetOriginCursorColor(colorMode == ColorMode::DARK ? Color(0x4DFFFFFF) : Color(0x4D000000));
8173     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8174 }
8175 
8176 bool TextFieldPattern::IsReachedBoundary(float offset)
8177 {
8178     if (IsTextArea()) {
8179         return (NearEqual(textRect_.GetY(), contentRect_.GetY()) && GreatNotEqual(offset, 0.0f)) ||
8180                (NearEqual(textRect_.GetY() + textRect_.Height(), contentRect_.GetY() + contentRect_.Height()) &&
8181                    LessNotEqual(offset, 0.0f));
8182     }
8183 
8184     return (NearEqual(textRect_.GetX(), contentRect_.GetX()) && GreatNotEqual(offset, 0.0f)) ||
8185            (NearEqual(textRect_.GetX() + textRect_.Width(), contentRect_.GetX() + contentRect_.Width()) &&
8186                LessNotEqual(offset, 0.0f));
8187 }
8188 
8189 OffsetF TextFieldPattern::GetTextPaintOffset() const
8190 {
8191     if (selectOverlay_->HasRenderTransform()) {
8192         return selectOverlay_->GetPaintRectOffsetWithTransform();
8193     }
8194     return GetPaintRectGlobalOffset();
8195 }
8196 
8197 OffsetF TextFieldPattern::GetPaintRectGlobalOffset() const
8198 {
8199     auto host = GetHost();
8200     CHECK_NULL_RETURN(host, OffsetF(0.0f, 0.0f));
8201     auto pipeline = host->GetContextRefPtr();
8202     CHECK_NULL_RETURN(pipeline, OffsetF(0.0f, 0.0f));
8203     auto rootOffset = pipeline->GetRootRect().GetOffset();
8204     OffsetF textPaintOffset;
8205     textPaintOffset = host->GetPaintRectOffset(false, true);
8206     return textPaintOffset - rootOffset;
8207 }
8208 
8209 void TextFieldPattern::UpdateSelectController()
8210 {
8211     selectController_->UpdateContentRect(contentRect_);
8212     selectController_->UpdateParagraph(paragraph_);
8213 }
8214 
8215 bool TextFieldPattern::RepeatClickCaret(const Offset& offset, int32_t lastCaretIndex)
8216 {
8217     auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset);
8218     return lastCaretIndex == touchDownIndex && HasFocus();
8219 }
8220 
8221 bool TextFieldPattern::RepeatClickCaret(const Offset& offset, const RectF& lastCaretRect)
8222 {
8223     auto caretRect = lastCaretRect;
8224     caretRect.SetLeft(caretRect.GetX() - caretRect.Height() / 2);
8225     caretRect.SetWidth(caretRect.Height());
8226     return caretRect.IsInRegion(PointF(offset.GetX(), offset.GetY()));
8227 }
8228 
8229 void TextFieldPattern::OnAttachToFrameNode()
8230 {
8231     auto frameNode = GetHost();
8232     CHECK_NULL_VOID(frameNode);
8233     StylusDetectorMgr::GetInstance()->AddTextFieldFrameNode(frameNode, WeakClaim(this));
8234 
8235     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8236     CHECK_NULL_VOID(layoutProperty);
8237     layoutProperty->UpdateCopyOptions(CopyOptions::Local);
8238     auto pipeline = frameNode->GetContext();
8239     CHECK_NULL_VOID(pipeline);
8240     auto fontManager = pipeline->GetFontManager();
8241     if (fontManager) {
8242         auto host = GetHost();
8243         fontManager->AddFontNodeNG(host);
8244     }
8245     auto onTextSelectorChange = [weak = WeakClaim(this)]() {
8246         auto pattern = weak.Upgrade();
8247         CHECK_NULL_VOID(pattern);
8248         auto frameNode = pattern->GetHost();
8249         CHECK_NULL_VOID(frameNode);
8250         frameNode->OnAccessibilityEvent(AccessibilityEventType::TEXT_SELECTION_UPDATE);
8251     };
8252     selectController_->SetOnAccessibility(std::move(onTextSelectorChange));
8253 }
8254 
8255 bool TextFieldPattern::NeedPaintSelect()
8256 {
8257     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8258     CHECK_NULL_RETURN(paintProperty, false);
8259     auto firstHandle = paintProperty->GetFirstHandleInfo();
8260     auto secondHandle = paintProperty->GetSecondHandleInfo();
8261     auto caretInfo = selectController_->GetCaretInfo();
8262     if (!IsSelected()) {
8263         if (!firstHandle.has_value() || !secondHandle.has_value()) {
8264             paintProperty->UpdateFirstHandleInfo(caretInfo);
8265             paintProperty->UpdateSecondHandleInfo(caretInfo);
8266             return false;
8267         }
8268 
8269         if (firstHandle->index != secondHandle->index || firstHandle->index != caretInfo.index) {
8270             paintProperty->UpdateFirstHandleInfo(caretInfo);
8271             paintProperty->UpdateSecondHandleInfo(caretInfo);
8272             return true;
8273         }
8274         return false;
8275     }
8276     auto needPaint = firstHandle != selectController_->GetFirstHandleInfo() ||
8277                      secondHandle != selectController_->GetSecondHandleInfo();
8278     paintProperty->UpdateFirstHandleInfo(selectController_->GetFirstHandleInfo());
8279     paintProperty->UpdateSecondHandleInfo(selectController_->GetSecondHandleInfo());
8280     return needPaint;
8281 }
8282 
8283 RefPtr<FocusHub> TextFieldPattern::GetFocusHub() const
8284 {
8285     auto host = GetHost();
8286     CHECK_NULL_RETURN(host, nullptr);
8287     auto focusHub = host->GetOrCreateFocusHub();
8288     return focusHub;
8289 }
8290 
8291 void TextFieldPattern::OnObscuredChanged(bool isObscured)
8292 {
8293     ResetObscureTickCountDown();
8294     obscuredChange_ = textObscured_ != isObscured;
8295     textObscured_ = isObscured;
8296     CloseSelectOverlay(false);
8297     StartTwinkling();
8298     if (obscuredChange_) {
8299         selectController_->UpdateCaretIndex(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
8300     }
8301     auto host = GetHost();
8302     CHECK_NULL_VOID(host);
8303     if (obscuredChange_) {
8304         auto eventHub = host->GetEventHub<TextFieldEventHub>();
8305         CHECK_NULL_VOID(eventHub);
8306         eventHub->FireOnSecurityStateChanged(!isObscured);
8307     }
8308     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
8309 }
8310 
8311 void TextFieldPattern::CreateHandles()
8312 {
8313     if (IsDragging() || !HasFocus()) {
8314         return;
8315     }
8316     auto host = GetHost();
8317     CHECK_NULL_VOID(host);
8318     showSelect_ = true;
8319     if (selectOverlay_->IsUseTouchAtLast()) {
8320         SetIsSingleHandle(!IsSelected());
8321         ProcessOverlay({ .menuIsShow = false });
8322     }
8323     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8324 }
8325 
8326 void TextFieldPattern::NotifyOnEditChanged(bool isChanged)
8327 {
8328     auto host = GetHost();
8329     CHECK_NULL_VOID(host);
8330     auto eventHub = host->GetEventHub<TextFieldEventHub>();
8331     CHECK_NULL_VOID(eventHub);
8332     if (isChanged != isEdit_) {
8333         isEdit_ = isChanged;
8334         eventHub->FireOnEditChanged(isChanged);
8335     }
8336 }
8337 
8338 size_t TextFieldPattern::GetLineCount() const
8339 {
8340     return paragraph_ ? paragraph_->GetLineCount() : 0;
8341 }
8342 
8343 void TextFieldPattern::UpdateHandlesOffsetOnScroll(float offset)
8344 {
8345     if (SelectOverlayIsOn()) {
8346         selectController_->UpdateSecondHandleOffset();
8347         if (!selectOverlay_->IsSingleHandle()) {
8348             selectController_->UpdateFirstHandleOffset();
8349             selectController_->UpdateCaretOffset(TextAffinity::DOWNSTREAM, false);
8350             selectOverlay_->UpdateAllHandlesOffset();
8351         } else {
8352             selectController_->UpdateCaretOffset(IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
8353             selectOverlay_->UpdateSecondHandleOffset();
8354         }
8355     } else {
8356         selectController_->UpdateCaretOffset(IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
8357     }
8358 }
8359 
8360 void TextFieldPattern::CloseHandleAndSelect()
8361 {
8362     CloseSelectOverlay(true);
8363     showSelect_ = false;
8364 }
8365 
8366 bool TextFieldPattern::IsShowUnit() const
8367 {
8368     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8369     CHECK_NULL_RETURN(layoutProperty, false);
8370     auto typeValue = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
8371     return layoutProperty->GetShowUnderlineValue(false) &&
8372            (typeValue == TextInputType::UNSPECIFIED || typeValue == TextInputType::TEXT);
8373 }
8374 
8375 bool TextFieldPattern::IsShowPasswordIcon() const
8376 {
8377     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8378     CHECK_NULL_RETURN(layoutProperty, false);
8379     auto textfieldTheme = GetTheme();
8380     CHECK_NULL_RETURN(textfieldTheme, false);
8381     bool isShowPasswordIcon = textfieldTheme->IsShowPasswordIcon();
8382     return layoutProperty->GetShowPasswordIconValue(isShowPasswordIcon) && IsInPasswordMode();
8383 }
8384 
8385 std::optional<bool> TextFieldPattern::IsShowPasswordText() const
8386 {
8387     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8388     CHECK_NULL_RETURN(layoutProperty, false);
8389     return layoutProperty->GetShowPasswordText();
8390 }
8391 
8392 bool TextFieldPattern::IsShowCancelButtonMode() const
8393 {
8394     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8395     CHECK_NULL_RETURN(layoutProperty, false);
8396     return !IsNormalInlineState() && !IsTextArea() && layoutProperty->GetIsShowCancelButton().value_or(false);
8397 }
8398 
8399 void TextFieldPattern::CheckPasswordAreaState()
8400 {
8401     auto showPasswordState = IsShowPasswordText();
8402     if (!showPasswordState.has_value()) {
8403         return;
8404     }
8405     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
8406     CHECK_NULL_VOID(passwordArea);
8407     if (!showPasswordState_.has_value() || showPasswordState_.value() != showPasswordState.value()) {
8408         passwordArea->SetObscured(!showPasswordState.value());
8409         showPasswordState_ = showPasswordState.value();
8410     }
8411 }
8412 
8413 void TextFieldPattern::AfterLayoutProcessCleanResponse(
8414     const RefPtr<CleanNodeResponseArea>& cleanNodeResponseArea)
8415 {
8416     CHECK_NULL_VOID(cleanNodeResponseArea);
8417     auto host = GetHost();
8418     CHECK_NULL_VOID(host);
8419     auto pipeline = host->GetContext();
8420     CHECK_NULL_VOID(pipeline);
8421     pipeline->AddAfterLayoutTask([weak = WeakClaim(Referenced::RawPtr(cleanNodeResponseArea))]() {
8422         auto cleanNodeResponseArea = weak.Upgrade();
8423         CHECK_NULL_VOID(cleanNodeResponseArea);
8424         cleanNodeResponseArea->UpdateCleanNode(cleanNodeResponseArea->IsShow());
8425     });
8426 }
8427 
8428 void TextFieldPattern::ProcessCancelButton()
8429 {
8430     if (IsShowCancelButtonMode()) {
8431         auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8432         if (cleanNodeResponseArea) {
8433             cleanNodeResponseArea->Refresh();
8434             if (cleanNodeResponseArea->IsShow()) {
8435                 AfterLayoutProcessCleanResponse(cleanNodeResponseArea);
8436             } else {
8437                 UpdateCancelNode();
8438             }
8439         } else {
8440             cleanNodeResponseArea_ = AceType::MakeRefPtr<CleanNodeResponseArea>(WeakClaim(this));
8441             cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8442             cleanNodeResponseArea->InitResponseArea();
8443             UpdateCancelNode();
8444             AfterLayoutProcessCleanResponse(cleanNodeResponseArea);
8445         }
8446     } else {
8447         if (cleanNodeResponseArea_) {
8448             cleanNodeResponseArea_->ClearArea();
8449             cleanNodeResponseArea_.Reset();
8450         }
8451     }
8452 }
8453 
8454 void TextFieldPattern::ProcessResponseArea()
8455 {
8456     ProcessCancelButton();
8457     if (IsInPasswordMode()) {
8458         auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
8459         if (passwordArea) {
8460             if (IsShowPasswordIcon()) {
8461                 passwordArea->Refresh();
8462             } else {
8463                 passwordArea->ClearArea();
8464             }
8465             CheckPasswordAreaState();
8466             return;
8467         }
8468         // responseArea_ may not be a password area.
8469         responseArea_ = AceType::MakeRefPtr<PasswordResponseArea>(WeakClaim(this), GetTextObscured());
8470         if (IsShowPasswordIcon()) {
8471             responseArea_->InitResponseArea();
8472         } else {
8473             responseArea_->ClearArea();
8474         }
8475         CheckPasswordAreaState();
8476         return;
8477     }
8478 
8479     if (IsUnderlineMode()) {
8480         responseArea_ = AceType::MakeRefPtr<UnitResponseArea>(WeakClaim(this), unitNode_);
8481         responseArea_->InitResponseArea();
8482         auto host = GetHost();
8483         CHECK_NULL_VOID(host);
8484         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
8485         return;
8486     }
8487 
8488     if (responseArea_) {
8489         responseArea_->ClearArea();
8490     }
8491 }
8492 
8493 void TextFieldPattern::AdjustTextRectByCleanNode(RectF& textRect)
8494 {
8495     auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8496     CHECK_NULL_VOID(cleanNodeResponseArea);
8497     auto host = GetHost();
8498     CHECK_NULL_VOID(host);
8499     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8500     CHECK_NULL_VOID(layoutProperty);
8501     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
8502     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
8503     if (isRTL && (cleanNodeStyle == CleanNodeStyle::CONSTANT ||
8504                      (cleanNodeStyle == CleanNodeStyle::INPUT && !contentController_->IsEmpty()))) {
8505         auto textFieldTheme = GetTheme();
8506         CHECK_NULL_VOID(textFieldTheme);
8507         auto themePadding = textFieldTheme->GetPadding();
8508         auto rightOffset = static_cast<float>(themePadding.Left().ConvertToPx());
8509         textRect.SetLeft(textRect.GetX() + cleanNodeResponseArea->GetIconSize() + rightOffset);
8510     }
8511 }
8512 
8513 void TextFieldPattern::UpdateCancelNode()
8514 {
8515     auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8516     CHECK_NULL_VOID(cleanNodeResponseArea);
8517     auto host = GetHost();
8518     CHECK_NULL_VOID(host);
8519     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8520     CHECK_NULL_VOID(layoutProperty);
8521     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
8522     if (cleanNodeStyle == CleanNodeStyle::CONSTANT ||
8523         (cleanNodeStyle == CleanNodeStyle::INPUT && !contentController_->IsEmpty())) {
8524         if (!cleanNodeResponseArea->IsShow() || cleanNodeResponseArea->CheckUpdateCleanNode()) {
8525             cleanNodeResponseArea->UpdateCleanNode(true);
8526         }
8527     } else if (cleanNodeStyle == CleanNodeStyle::INVISIBLE ||
8528                (cleanNodeStyle == CleanNodeStyle::INPUT && contentController_->IsEmpty())) {
8529         if (cleanNodeResponseArea->IsShow()) {
8530             cleanNodeResponseArea->UpdateCleanNode(false);
8531         }
8532     }
8533 }
8534 
8535 bool TextFieldPattern::HasInputOperation()
8536 {
8537     return !deleteBackwardOperations_.empty() || !deleteForwardOperations_.empty() || !insertCommands_.empty();
8538 }
8539 
8540 void TextFieldPattern::FocusForwardStopTwinkling()
8541 {
8542     auto host = GetHost();
8543     CHECK_NULL_VOID(host);
8544     UpdateSelection(selectController_->GetCaretIndex());
8545     StopTwinkling();
8546     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8547 }
8548 
8549 bool TextFieldPattern::UpdateFocusForward()
8550 {
8551     if (focusIndex_ == FocuseIndex::TEXT && HasFocus()) {
8552         FocusForwardStopTwinkling();
8553         if (!CancelNodeIsShow()) {
8554             if (responseArea_ == nullptr || (!IsShowUnit() && !IsShowPasswordIcon())) {
8555                 return false;
8556             }
8557             focusIndex_ = FocuseIndex::UNIT;
8558             PaintResponseAreaRect();
8559             return true;
8560         }
8561         focusIndex_ = FocuseIndex::CANCEL;
8562         PaintCancelRect();
8563         return true;
8564     }
8565     if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
8566         FocusForwardStopTwinkling();
8567         if (responseArea_ == nullptr || (!IsShowUnit() && !IsShowPasswordIcon())) {
8568             return false;
8569         }
8570         focusIndex_ = FocuseIndex::UNIT;
8571         PaintResponseAreaRect();
8572         return true;
8573     }
8574     return false;
8575 }
8576 
8577 bool TextFieldPattern::UpdateFocusBackward()
8578 {
8579     if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
8580         focusIndex_ = FocuseIndex::TEXT;
8581         PaintTextRect();
8582         StartTwinkling();
8583         return true;
8584     } else if (focusIndex_ == FocuseIndex::UNIT && HasFocus()) {
8585         if (!CancelNodeIsShow()) {
8586             focusIndex_ = FocuseIndex::TEXT;
8587             PaintTextRect();
8588             StartTwinkling();
8589             return true;
8590         }
8591         focusIndex_ = FocuseIndex::CANCEL;
8592         PaintCancelRect();
8593         return true;
8594     }
8595     return false;
8596 }
8597 
8598 bool TextFieldPattern::HandleSpaceEvent()
8599 {
8600     if (focusIndex_ == FocuseIndex::CANCEL) {
8601         CleanNodeResponseKeyEvent();
8602         return true;
8603     } else if (focusIndex_ == FocuseIndex::UNIT) {
8604         if (IsShowPasswordIcon()) {
8605             PasswordResponseKeyEvent();
8606         }
8607         if (IsShowUnit()) {
8608             UnitResponseKeyEvent();
8609         }
8610         return true;
8611     }
8612     return false;
8613 }
8614 
8615 void TextFieldPattern::PaintTextRect()
8616 {
8617     RoundRect focusRect;
8618     auto host = GetHost();
8619     CHECK_NULL_VOID(host);
8620     auto focusHub = host->GetFocusHub();
8621     CHECK_NULL_VOID(focusHub);
8622     focusHub->PaintInnerFocusState(focusRect);
8623 }
8624 
8625 void TextFieldPattern::GetIconPaintRect(const RefPtr<TextInputResponseArea>& responseArea, RoundRect& paintRect)
8626 {
8627     auto stackNode = responseArea->GetFrameNode();
8628     CHECK_NULL_VOID(stackNode);
8629     auto stackRect = stackNode->GetGeometryNode()->GetFrameRect();
8630     auto imageNode = stackNode->GetFirstChild();
8631     CHECK_NULL_VOID(imageNode);
8632     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
8633     CHECK_NULL_VOID(imageFrameNode);
8634     auto imageRect = imageFrameNode->GetGeometryNode()->GetFrameRect();
8635     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8636     CHECK_NULL_VOID(layoutProperty);
8637     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
8638     RectF rect;
8639     if (isRTL) {
8640         rect = RectF(stackRect.GetX() + stackRect.Width() - imageRect.Width(),
8641             stackRect.GetY(), imageRect.Width(), imageRect.Height());
8642     } else {
8643         rect = RectF(stackRect.GetX(), stackRect.GetY(), imageRect.Width(), imageRect.Height());
8644     }
8645     paintRect.SetRect(rect);
8646 }
8647 
8648 void TextFieldPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
8649 {
8650     if (focusIndex_ == FocuseIndex::CANCEL) {
8651         CHECK_NULL_VOID(cleanNodeResponseArea_);
8652         GetIconPaintRect(cleanNodeResponseArea_, paintRect);
8653         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
8654             cleanNodeResponseArea_->CreateIconRect(paintRect, true);
8655             float cornerRadius = paintRect.GetRect().Width() / 2;
8656             paintRect.SetCornerRadius(cornerRadius);
8657         }
8658     } else if (focusIndex_ == FocuseIndex::UNIT) {
8659         if (IsShowPasswordIcon()) {
8660             CHECK_NULL_VOID(responseArea_);
8661             GetIconPaintRect(responseArea_, paintRect);
8662             if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
8663                 responseArea_->CreateIconRect(paintRect, true);
8664             }
8665             float cornerRadius = paintRect.GetRect().Width() / 2;
8666             paintRect.SetCornerRadius(cornerRadius);
8667         }
8668         if (IsShowUnit()) {
8669             CHECK_NULL_VOID(responseArea_);
8670             auto unitResponseArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
8671             CHECK_NULL_VOID(unitResponseArea);
8672             auto unitNode = unitResponseArea->GetFrameNode();
8673             CHECK_NULL_VOID(unitNode);
8674             auto unitRect = unitNode->GetGeometryNode()->GetFrameRect();
8675             paintRect.SetRect(unitRect);
8676         }
8677     } else {
8678         GetTextInputFocusPaintRect(paintRect);
8679     }
8680 }
8681 
8682 void TextFieldPattern::GetTextInputFocusPaintRect(RoundRect& paintRect)
8683 {
8684     auto textfieldTheme = GetTheme();
8685     CHECK_NULL_VOID(textfieldTheme);
8686     auto isNeedFocusBox = textfieldTheme->NeedFocusBox();
8687     if (!isNeedFocusBox) {
8688         return;
8689     }
8690     auto host = GetHost();
8691     CHECK_NULL_VOID(host);
8692     auto geometryNode = host->GetGeometryNode();
8693     CHECK_NULL_VOID(geometryNode);
8694     auto textInputSize = geometryNode->GetFrameSize();
8695     auto focusPaintPadding = textfieldTheme->GetFocusPadding().ConvertToPx();
8696     float width = textInputSize.Width() + 2 * focusPaintPadding;
8697     float height = textInputSize.Height() + 2 * focusPaintPadding;
8698     paintRect.SetRect({ -focusPaintPadding, -focusPaintPadding, width, height });
8699     auto renderContext = host->GetRenderContext();
8700     CHECK_NULL_VOID(renderContext);
8701     auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
8702     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS,
8703         static_cast<float>(radius.radiusTopLeft->ConvertToPx() + focusPaintPadding),
8704         static_cast<float>(radius.radiusTopLeft->ConvertToPx() + focusPaintPadding));
8705     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS,
8706         static_cast<float>(radius.radiusTopRight->ConvertToPx() + focusPaintPadding),
8707         static_cast<float>(radius.radiusTopRight->ConvertToPx() + focusPaintPadding));
8708     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS,
8709         static_cast<float>(radius.radiusBottomLeft->ConvertToPx() + focusPaintPadding),
8710         static_cast<float>(radius.radiusBottomLeft->ConvertToPx() + focusPaintPadding));
8711     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS,
8712         static_cast<float>(radius.radiusBottomRight->ConvertToPx() + focusPaintPadding),
8713         static_cast<float>(radius.radiusBottomRight->ConvertToPx() + focusPaintPadding));
8714 }
8715 
8716 void TextFieldPattern::PaintCancelRect()
8717 {
8718     RoundRect focusRect;
8719     GetInnerFocusPaintRect(focusRect);
8720     auto host = GetHost();
8721     CHECK_NULL_VOID(host);
8722     auto focusHub = host->GetFocusHub();
8723     CHECK_NULL_VOID(focusHub);
8724     focusHub->PaintInnerFocusState(focusRect);
8725 }
8726 
8727 void TextFieldPattern::PaintResponseAreaRect()
8728 {
8729     if (IsShowPasswordIcon()) {
8730         PaintPasswordRect();
8731     }
8732     if (IsShowUnit()) {
8733         PaintUnitRect();
8734     }
8735 }
8736 
8737 void TextFieldPattern::PaintPasswordRect()
8738 {
8739     RoundRect focusRect;
8740     GetInnerFocusPaintRect(focusRect);
8741     auto host = GetHost();
8742     CHECK_NULL_VOID(host);
8743     auto focusHub = host->GetFocusHub();
8744     CHECK_NULL_VOID(focusHub);
8745     focusHub->PaintInnerFocusState(focusRect);
8746 }
8747 
8748 void TextFieldPattern::PaintUnitRect()
8749 {
8750     RoundRect focusRect;
8751     GetInnerFocusPaintRect(focusRect);
8752     auto host = GetHost();
8753     CHECK_NULL_VOID(host);
8754     auto focusHub = host->GetFocusHub();
8755     CHECK_NULL_VOID(focusHub);
8756     focusHub->PaintInnerFocusState(focusRect);
8757 }
8758 
8759 void TextFieldPattern::CleanNodeResponseKeyEvent()
8760 {
8761     CHECK_NULL_VOID(!IsDragging());
8762     auto host = GetHost();
8763     CHECK_NULL_VOID(host);
8764     ClearTextContent();
8765     CloseSelectOverlay();
8766     SetFloatingCursorVisible(false);
8767     StartTwinkling();
8768     UpdateCaretInfoToController();
8769     if (!HasFocus()) {
8770         auto focusHub = host->GetOrCreateFocusHub();
8771         TextFieldRequestFocus(RequestFocusReason::CLEAN_NODE);
8772     }
8773     host->MarkModifyDone();
8774     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8775 
8776     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8777     CHECK_NULL_VOID(layoutProperty);
8778     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
8779     if (cleanNodeStyle == CleanNodeStyle::INPUT) {
8780         focusIndex_ = FocuseIndex::TEXT;
8781     }
8782 }
8783 
8784 void TextFieldPattern::RegisterWindowSizeCallback()
8785 {
8786     if (isOritationListenerRegisted_) {
8787         return;
8788     }
8789     isOritationListenerRegisted_ = true;
8790     auto host = GetHost();
8791     CHECK_NULL_VOID(host);
8792     auto pipeline = host->GetContext();
8793     CHECK_NULL_VOID(pipeline);
8794     pipeline->AddWindowSizeChangeCallback(host->GetId());
8795 }
8796 
8797 void TextFieldPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
8798 {
8799     if (selectOverlay_) {
8800         selectOverlay_->UpdateMenuOnWindowSizeChanged(type);
8801     }
8802     if (type != WindowSizeChangeReason::ROTATION) {
8803         return;
8804     }
8805     if (SelectOverlayIsOn()) {
8806         selectController_->CalculateHandleOffset();
8807         selectOverlay_->ProcessOverlayOnAreaChanged({ .menuIsShow = false});
8808     }
8809     auto host = GetHost();
8810     CHECK_NULL_VOID(host);
8811     auto context = host->GetContextRefPtr();
8812     CHECK_NULL_VOID(context);
8813     auto taskExecutor = context->GetTaskExecutor();
8814     CHECK_NULL_VOID(taskExecutor);
8815     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
8816     CHECK_NULL_VOID(textFieldManager);
8817     textFieldManager->ResetOptionalClickPosition();
8818     lastCaretPos_ = std::nullopt;
8819     taskExecutor->PostTask(
8820         [weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
8821             auto textField = weak.Upgrade();
8822             CHECK_NULL_VOID(textField);
8823             auto host = textField->GetHost();
8824             CHECK_NULL_VOID(host);
8825             auto nodeId = host->GetId();
8826             textField->parentGlobalOffset_ = textField->GetPaintRectGlobalOffset();
8827             textField->UpdateTextFieldManager(Offset(textField->parentGlobalOffset_.GetX(),
8828                 textField->parentGlobalOffset_.GetY()), textField->frameRect_.Height());
8829             if (textField->HasFocus()) {
8830                 textField->UpdateCaretInfoToController(true);
8831                 TAG_LOGI(ACE_TEXT_FIELD, "%{public}d OnWindowSizeChanged change parentGlobalOffset to: %{public}s",
8832                     nodeId, textField->parentGlobalOffset_.ToString().c_str());
8833                 auto textFieldManager = manager.Upgrade();
8834                 CHECK_NULL_VOID(textFieldManager);
8835                 auto container = Container::Current();
8836                 CHECK_NULL_VOID(container);
8837                 auto displayInfo = container->GetDisplayInfo();
8838                 if (displayInfo) {
8839                     auto dmRotation = static_cast<int32_t>(displayInfo->GetRotation());
8840                     textFieldManager->SetFocusFieldOrientation(dmRotation);
8841                     textFieldManager->SetFocusFieldAlreadyTriggerWsCallback(true);
8842                 }
8843             }
8844         },
8845         TaskExecutor::TaskType::UI, "ArkUITextFieldOnWindowSizeChangedRotation");
8846 }
8847 
8848 void TextFieldPattern::PasswordResponseKeyEvent()
8849 {
8850     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
8851     CHECK_NULL_VOID(passwordArea);
8852     passwordArea->OnPasswordIconClicked();
8853 }
8854 
8855 void TextFieldPattern::UnitResponseKeyEvent()
8856 {
8857 #ifndef ARKUI_WEARABLE
8858     auto unitArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
8859     CHECK_NULL_VOID(unitArea);
8860     auto frameNode = unitArea->GetFrameNode();
8861     CHECK_NULL_VOID(frameNode);
8862     if (frameNode->GetTag() == V2::SELECT_ETS_TAG) {
8863         auto selectPattern = frameNode->GetPattern<SelectPattern>();
8864         CHECK_NULL_VOID(selectPattern);
8865         selectPattern->ShowSelectMenu();
8866     }
8867 #endif
8868 }
8869 
8870 void TextFieldPattern::ScrollToSafeArea() const
8871 {
8872     auto host = GetHost();
8873     CHECK_NULL_VOID(host);
8874     auto pipeline = host->GetContext();
8875     CHECK_NULL_VOID(pipeline);
8876     if (pipeline->UsingCaretAvoidMode()) {
8877         // using TriggerAvoidOnCaretChange instead in CaretAvoidMode
8878         return;
8879     }
8880     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8881     CHECK_NULL_VOID(textFieldManager);
8882     textFieldManager->ScrollTextFieldToSafeArea();
8883 }
8884 
8885 void TextFieldPattern::TriggerAvoidOnCaretChange()
8886 {
8887     CHECK_NULL_VOID(HasFocus());
8888     auto host = GetHost();
8889     CHECK_NULL_VOID(host);
8890     auto pipeline = host->GetContext();
8891     CHECK_NULL_VOID(pipeline);
8892     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
8893     CHECK_NULL_VOID(textFieldManager);
8894     CHECK_NULL_VOID(pipeline->UsingCaretAvoidMode());
8895     auto safeAreaManager = pipeline->GetSafeAreaManager();
8896     if (!safeAreaManager || NearEqual(safeAreaManager->GetKeyboardInset().Length(), 0)) {
8897         return;
8898     }
8899     if (selectOverlay_) {
8900         selectOverlay_->AddAvoidKeyboardCallback(isCustomKeyboardAttached_);
8901     }
8902     textFieldManager->TriggerAvoidOnCaretChange();
8903     auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
8904     SetLastCaretPos(caretPos);
8905 }
8906 
8907 void TextFieldPattern::CheckTextAlignByDirection(TextAlign& textAlign, TextDirection direction)
8908 {
8909     if (direction == TextDirection::RTL) {
8910         if (textAlign == TextAlign::START) {
8911             textAlign = TextAlign::END;
8912         } else if (textAlign == TextAlign::END) {
8913             textAlign = TextAlign::START;
8914         }
8915     }
8916 }
8917 
8918 void TextFieldPattern::RequestKeyboardAfterLongPress()
8919 {
8920 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
8921     if (isLongPress_ && HasFocus() && RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::LONG_PRESS)) {
8922         NotifyOnEditChanged(true);
8923         if (!isCustomKeyboardAttached_ || keyboardAvoidance_) {
8924             selectOverlay_->AddAvoidKeyboardCallback(isCustomKeyboardAttached_);
8925         }
8926     }
8927     isLongPress_ = false;
8928 #endif
8929 }
8930 
8931 void TextFieldPattern::GetCaretMetrics(CaretMetricsF& caretCaretMetric)
8932 {
8933     OffsetF offset = selectController_->GetCaretRect().GetOffset();
8934     float height = selectController_->GetCaretRect().Height();
8935     float width = selectController_->GetCaretRect().Width();
8936     auto host = GetHost();
8937     CHECK_NULL_VOID(host);
8938     auto textPaintOffset = host->GetPaintRectOffset(false, true);
8939     caretCaretMetric.offset = offset + textPaintOffset + OffsetF(width / 2.0f, 0.0f);
8940     caretCaretMetric.height = height;
8941 }
8942 
8943 void TextFieldPattern::ScrollPage(bool reverse, bool smooth, AccessibilityScrollType scrollType)
8944 {
8945     auto border = GetBorderWidthProperty();
8946     float maxFrameHeight =
8947         frameRect_.Height() - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
8948     float distance = reverse ? maxFrameHeight : -maxFrameHeight;
8949     if (scrollType == AccessibilityScrollType::SCROLL_HALF) {
8950         distance = distance / 2.f;
8951     }
8952     OnScrollCallback(distance, SCROLL_FROM_JUMP);
8953 }
8954 
8955 // correct after OnModifyDone
8956 bool TextFieldPattern::IsUnderlineMode() const
8957 {
8958     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8959     CHECK_NULL_RETURN(layoutProperty, false);
8960     return layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType() && !IsInlineMode();
8961 }
8962 
8963 // correct after OnModifyDone
8964 bool TextFieldPattern::IsInlineMode() const
8965 {
8966     return HasFocus() && IsNormalInlineState();
8967 }
8968 
8969 bool TextFieldPattern::IsShowError()
8970 {
8971     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8972     CHECK_NULL_RETURN(layoutProperty, false);
8973     auto errorText = layoutProperty->GetErrorTextValue(u"");
8974     return layoutProperty->GetShowErrorTextValue(false) && !errorText.empty() && !IsNormalInlineState();
8975 }
8976 
8977 bool TextFieldPattern::IsShowCount()
8978 {
8979     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8980     CHECK_NULL_RETURN(layoutProperty, false);
8981     return layoutProperty->GetShowCounterValue(false) && !IsNormalInlineState() && !IsInPasswordMode() &&
8982            layoutProperty->HasMaxLength();
8983 }
8984 
8985 void TextFieldPattern::ResetContextAttr()
8986 {
8987     auto host = GetHost();
8988     CHECK_NULL_VOID(host);
8989     auto renderContext = host->GetRenderContext();
8990     CHECK_NULL_VOID(renderContext);
8991     renderContext->ResetBorder();
8992     BorderWidthProperty borderWidth;
8993     borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
8994     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8995     CHECK_NULL_VOID(layoutProperty);
8996     layoutProperty->UpdateBorderWidth(borderWidth);
8997 }
8998 
8999 void TextFieldPattern::SetThemeBorderAttr()
9000 {
9001     auto host = GetHost();
9002     CHECK_NULL_VOID(host);
9003     auto renderContext = host->GetRenderContext();
9004     CHECK_NULL_VOID(renderContext);
9005     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9006     CHECK_NULL_VOID(layoutProperty);
9007     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9008     CHECK_NULL_VOID(paintProperty);
9009     auto theme = GetTheme();
9010     CHECK_NULL_VOID(theme);
9011 
9012     paintProperty->ResetInnerBorderColor();
9013     paintProperty->ResetInnerBorderWidth();
9014     if (!paintProperty->HasBorderColorFlagByUser()) {
9015         BorderColorProperty borderColor;
9016         borderColor.SetColor(theme->GetTextInputColor());
9017         renderContext->UpdateBorderColor(borderColor);
9018     } else {
9019         renderContext->UpdateBorderColor(paintProperty->GetBorderColorFlagByUserValue());
9020     }
9021 
9022     if (!paintProperty->HasBorderRadiusFlagByUser()) {
9023         auto radius = theme->GetBorderRadius();
9024         BorderRadiusProperty borderRadius(radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX());
9025         auto ultimatelyRadius = IsUnderlineMode() ?  ZERO_BORDER_RADIUS_PROPERTY : borderRadius;
9026         renderContext->UpdateBorderRadius(ultimatelyRadius);
9027     } else {
9028         renderContext->UpdateBorderRadius(paintProperty->GetBorderRadiusFlagByUserValue());
9029     }
9030 
9031     if (!paintProperty->HasBorderWidthFlagByUser()) {
9032         BorderWidthProperty borderWidth;
9033         if (IsTextArea() || IsUnderlineMode()) {
9034             borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
9035         } else {
9036             borderWidth.SetBorderWidth(theme->GetTextInputWidth());
9037         }
9038         renderContext->UpdateBorderWidth(borderWidth);
9039         layoutProperty->UpdateBorderWidth(borderWidth);
9040     } else {
9041         renderContext->UpdateBorderWidth(paintProperty->GetBorderWidthFlagByUserValue());
9042         layoutProperty->UpdateBorderWidth(paintProperty->GetBorderWidthFlagByUserValue());
9043     }
9044 }
9045 
9046 PaddingProperty TextFieldPattern::GetPaddingByUserValue()
9047 {
9048     PaddingProperty padding;
9049     auto theme = GetTheme();
9050     CHECK_NULL_RETURN(theme, padding);
9051     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9052     CHECK_NULL_RETURN(paintProperty, padding);
9053     padding = paintProperty->GetPaddingByUserValue();
9054     auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
9055     if (!padding.top.has_value()) {
9056         padding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
9057     }
9058     if (!padding.bottom.has_value()) {
9059         padding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
9060     }
9061     if (!padding.left.has_value()) {
9062         padding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
9063     }
9064     if (!padding.right.has_value()) {
9065         padding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
9066     }
9067     return padding;
9068 }
9069 
9070 void TextFieldPattern::SetThemeAttr()
9071 {
9072     auto host = GetHost();
9073     CHECK_NULL_VOID(host);
9074     auto renderContext = host->GetRenderContext();
9075     CHECK_NULL_VOID(renderContext);
9076     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9077     CHECK_NULL_VOID(layoutProperty);
9078     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9079     CHECK_NULL_VOID(paintProperty);
9080     auto theme = GetTheme();
9081     CHECK_NULL_VOID(theme);
9082     SetThemeBorderAttr();
9083     if (!paintProperty->HasBackgroundColor()) {
9084         auto backgroundColor = isFocusBGColorSet_ ? theme->GetFocusBgColor() : theme->GetBgColor();
9085         backgroundColor = IsUnderlineMode() ? Color::TRANSPARENT : backgroundColor;
9086         renderContext->UpdateBackgroundColor(backgroundColor);
9087     } else {
9088         renderContext->UpdateBackgroundColor(paintProperty->GetBackgroundColorValue());
9089     }
9090 
9091     if (!paintProperty->HasMarginByUser()) {
9092         MarginProperty margin;
9093         margin.SetEdges(CalcLength(0.0_vp));
9094         layoutProperty->UpdateMargin(margin);
9095     } else {
9096         layoutProperty->UpdateMargin(paintProperty->GetMarginByUserValue());
9097     }
9098 
9099     if (!paintProperty->HasPaddingByUser()) {
9100         auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
9101         PaddingProperty padding;
9102         padding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
9103         padding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
9104         padding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
9105         padding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
9106         layoutProperty->UpdatePadding(padding);
9107     } else {
9108         layoutProperty->UpdatePadding(GetPaddingByUserValue());
9109     }
9110 
9111     if (!paintProperty->HasTextColorFlagByUser()) {
9112         auto textColor = isFocusTextColorSet_ ? theme->GetFocusTextColor() : theme->GetTextColor();
9113         layoutProperty->UpdateTextColor(textColor);
9114     } else {
9115         layoutProperty->UpdateTextColor(paintProperty->GetTextColorFlagByUserValue());
9116     }
9117     inlineFocusState_ = false;
9118 }
9119 
9120 const Dimension& TextFieldPattern::GetAvoidSoftKeyboardOffset() const
9121 {
9122     auto textfieldTheme = GetTheme();
9123     if (!textfieldTheme) {
9124         return TextBase::GetAvoidSoftKeyboardOffset();
9125     }
9126     return textfieldTheme->GetAvoidKeyboardOffset();
9127 }
9128 
9129 Offset TextFieldPattern::ConvertGlobalToLocalOffset(const Offset& globalOffset)
9130 {
9131     parentGlobalOffset_ = GetPaintRectGlobalOffset();
9132     auto localOffset = globalOffset - Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY());
9133     if (selectOverlay_->HasRenderTransform()) {
9134         auto localOffsetF = OffsetF(globalOffset.GetX(), globalOffset.GetY());
9135         selectOverlay_->RevertLocalPointWithTransform(localOffsetF);
9136         localOffset.SetX(localOffsetF.GetX());
9137         localOffset.SetY(localOffsetF.GetY());
9138     }
9139     return localOffset;
9140 }
9141 
9142 int32_t TextFieldPattern::SetPreviewText(const std::u16string &previewValue, const PreviewRange range)
9143 {
9144     PreviewTextInfo info = {
9145         .text = previewValue,
9146         .range = range,
9147         .isIme = true
9148     };
9149     auto host = GetHost();
9150     CHECK_NULL_RETURN(host, PREVIEW_NULL_POINTER);
9151     inputOperations_.emplace(InputOperation::SET_PREVIEW_TEXT);
9152     previewTextOperation_.emplace(info);
9153     CloseSelectOverlay(true);
9154     ScrollToSafeArea();
9155     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9156     return PREVIEW_NO_ERROR;
9157 }
9158 
9159 int32_t TextFieldPattern::SetPreviewText(const std::string &previewValue, const PreviewRange range)
9160 {
9161     return SetPreviewText(UtfUtils::Str8DebugToStr16(previewValue), range);
9162 }
9163 
9164 void TextFieldPattern::SetPreviewTextOperation(PreviewTextInfo info)
9165 {
9166     auto host = GetHost();
9167     CHECK_NULL_VOID(host);
9168     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9169     CHECK_NULL_VOID(layoutProperty);
9170     if (!hasPreviewText_) {
9171         bodyTextInPreivewing_ = GetTextUtf16Value();
9172     }
9173     auto rangeStart = info.range.start;
9174     auto rangeEnd = info.range.end;
9175     auto start = GetPreviewTextStart();
9176     auto end = GetPreviewTextEnd();
9177     if (IsSelected()) {
9178         start = selectController_->GetStartIndex();
9179         end = selectController_->GetEndIndex();
9180     } else {
9181         start = (rangeStart == PREVIEW_TEXT_RANGE_DEFAULT) ? start : rangeStart;
9182         end = (rangeEnd == PREVIEW_TEXT_RANGE_DEFAULT) ? end : rangeEnd;
9183     }
9184 
9185     auto oldHasPreviewText = hasPreviewText_;
9186     ChangeValueInfo changeValueInfo;
9187     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9188     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
9189     changeValueInfo.oldContent = GetBodyTextValue();
9190     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
9191     changeValueInfo.rangeAfter = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
9192     auto originCaretIndex =
9193             TextRange { changeValueInfo.oldPreviewText.offset, changeValueInfo.oldPreviewText.offset };
9194     bool hasInsertValue = false;
9195     auto originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
9196     auto attemptInsertLength = static_cast<int32_t>(info.text.length()) - (end - start);
9197     if (layoutProperty->HasMaxLength() &&
9198         attemptInsertLength + static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) >
9199         static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()))) {
9200         isPreviewTextOverCount_ = true;
9201     }
9202     hasInsertValue = contentController_->ReplaceSelectedValue(start, end, info.text);
9203     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) -
9204         originLength);
9205 
9206     int32_t delta =
9207             static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength - (end - start);
9208     int32_t newCaretPosition = std::max(end, GetPreviewTextEnd()) + delta;
9209     newCaretPosition = std::clamp(newCaretPosition, 0,
9210         static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
9211     selectController_->UpdateCaretIndex(start + caretMoveLength);
9212 
9213     UpdatePreviewIndex(start, newCaretPosition);
9214     hasPreviewText_ = true;
9215     changeValueInfo.value = GetBodyTextValue();
9216     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9217     changeValueInfo.previewText.value = GetPreviewTextValue();
9218     bool isWillChange = FireOnWillChange(changeValueInfo);
9219     if (!isWillChange && !info.isIme) {
9220         RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
9221         hasPreviewText_ = oldHasPreviewText;
9222         return;
9223     }
9224     if (HasFocus()) {
9225         cursorVisible_ = true;
9226         StartTwinkling();
9227     } else {
9228         cursorVisible_ = false;
9229         StopTwinkling();
9230     }
9231 }
9232 
9233 void TextFieldPattern::FinishTextPreview()
9234 {
9235     inputOperations_.emplace(InputOperation::SET_PREVIEW_FINISH);
9236     auto host = GetHost();
9237     CHECK_NULL_VOID(host);
9238     ScrollToSafeArea();
9239     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9240 }
9241 
9242 void TextFieldPattern::FinishTextPreviewOperation()
9243 {
9244     if (!hasPreviewText_) {
9245         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "input state now is not at previewing text");
9246         return;
9247     }
9248     auto host = GetHost();
9249     CHECK_NULL_VOID(host);
9250     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9251     CHECK_NULL_VOID(layoutProperty);
9252     if (layoutProperty->HasMaxLength()) {
9253         int32_t len = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
9254         showCountBorderStyle_ = isPreviewTextOverCount_ || (len >
9255             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
9256         isPreviewTextOverCount_ = false;
9257         HandleCountStyle();
9258     }
9259 
9260     auto oldValue = contentController_->GetTextUtf16Value();
9261     auto originCaretIndex =
9262             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
9263     ChangeValueInfo changeValueInfo;
9264     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9265     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
9266     changeValueInfo.oldContent = GetBodyTextValue();
9267     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
9268     auto start = GetPreviewTextStart();
9269     auto end = GetPreviewTextEnd();
9270     auto previewValue = GetPreviewTextValue();
9271     hasPreviewText_ = false;
9272     auto originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
9273     contentController_->ReplaceSelectedValue(start, end, previewValue);
9274     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) -
9275         originLength);
9276     selectController_->UpdateCaretIndex(start + caretMoveLength);
9277     UpdateEditingValueToRecord();
9278     changeValueInfo.rangeAfter =
9279         TextRange { changeValueInfo.oldPreviewText.offset, selectController_->GetCaretIndex() };
9280     changeValueInfo.value = GetBodyTextValue();
9281     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9282     changeValueInfo.previewText.value = GetPreviewTextValue();
9283     bool isWillChange = FireOnWillChange(changeValueInfo);
9284     if (!isWillChange) {
9285         RecoverTextValueAndCaret(oldValue, originCaretIndex);
9286         return;
9287     }
9288     if (HasFocus()) {
9289         cursorVisible_ = true;
9290         StartTwinkling();
9291     } else {
9292         cursorVisible_ = false;
9293         StopTwinkling();
9294     }
9295     bodyTextInPreivewing_ = u"";
9296     previewTextStart_ = PREVIEW_TEXT_RANGE_DEFAULT;
9297     previewTextEnd_ = PREVIEW_TEXT_RANGE_DEFAULT;
9298     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9299 }
9300 
9301 std::vector<RectF> TextFieldPattern::GetPreviewTextRects() const
9302 {
9303     if (!GetIsPreviewText()) {
9304         return {};
9305     }
9306     std::vector<RectF> boxes;
9307     std::vector<RectF> previewTextRects;
9308     CHECK_NULL_RETURN(paragraph_, boxes);
9309     paragraph_->GetRectsForRange(GetPreviewTextStart(), GetPreviewTextEnd(), boxes);
9310     if (boxes.empty()) {
9311         return {};
9312     }
9313     RectF linerRect(boxes.front().GetOffset(), SizeF(0, boxes.front().GetSize().Height()));
9314     float checkedTop = boxes.front().Top();
9315 
9316     for (const auto& drawRect : boxes) {
9317         if (drawRect.Top() == checkedTop) {
9318             linerRect += SizeF(drawRect.GetSize().Width(), 0);
9319         } else {
9320             previewTextRects.emplace_back(linerRect);
9321             checkedTop = drawRect.Top();
9322             linerRect = drawRect;
9323         }
9324     }
9325     previewTextRects.emplace_back(linerRect);
9326     return previewTextRects;
9327 }
9328 
9329 bool TextFieldPattern::NeedDrawPreviewText()
9330 {
9331     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9332     CHECK_NULL_RETURN(paintProperty, false);
9333 
9334     auto caretInfo = selectController_->GetCaretInfo();
9335     if (!paintProperty->HasPreviewTextStart() || !paintProperty->HasPreviewTextEnd()) {
9336         paintProperty->UpdatePreviewTextStart(caretInfo.index);
9337         paintProperty->UpdatePreviewTextEnd(caretInfo.index);
9338     }
9339 
9340     auto paintStart = paintProperty->GetPreviewTextStart();
9341     auto paintEnd =paintProperty->GetPreviewTextEnd();
9342     if (!GetIsPreviewText()) {
9343         if (!paintStart.has_value() || !paintEnd.has_value()) {
9344             paintProperty->UpdatePreviewTextStart(caretInfo.index);
9345             paintProperty->UpdatePreviewTextEnd(caretInfo.index);
9346             return false;
9347         }
9348 
9349         // end paint
9350         if (paintStart != paintEnd || paintStart.value() != caretInfo.index) {
9351             paintProperty->UpdatePreviewTextStart(caretInfo.index);
9352             paintProperty->UpdatePreviewTextEnd(caretInfo.index);
9353             return true;
9354         }
9355         return false;
9356     }
9357     auto needDraw = paintStart.value() != GetPreviewTextStart() ||
9358                      paintEnd.value() != GetPreviewTextEnd();
9359     paintProperty->UpdatePreviewTextStart(GetPreviewTextStart());
9360     paintProperty->UpdatePreviewTextEnd(GetPreviewTextEnd());
9361     return needDraw;
9362 }
9363 
9364 int32_t TextFieldPattern::CheckPreviewTextValidate(const std::u16string& previewValue, const PreviewRange range)
9365 {
9366     auto start = range.start;
9367     auto end = range.end;
9368     if (start != end && (start == PREVIEW_TEXT_RANGE_DEFAULT || end == PREVIEW_TEXT_RANGE_DEFAULT)) {
9369         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "range is not [-1,-1] or legal range");
9370         return PREVIEW_BAD_PARAMETERS;
9371     }
9372 
9373     if (start != PREVIEW_TEXT_RANGE_DEFAULT && IsSelected()) {
9374         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "unsupported insert preview text when IsSelected");
9375         return PREVIEW_BAD_PARAMETERS;
9376     }
9377     return PREVIEW_NO_ERROR;
9378 }
9379 
9380 int32_t TextFieldPattern::CheckPreviewTextValidate(const std::string& previewValue, const PreviewRange range)
9381 {
9382     return CheckPreviewTextValidate(UtfUtils::Str8DebugToStr16(previewValue), range);
9383 }
9384 
9385 PreviewTextStyle TextFieldPattern::GetPreviewTextStyle() const
9386 {
9387     auto defaultStyle = PreviewTextStyle::NORMAL;
9388     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9389     CHECK_NULL_RETURN(paintProperty, defaultStyle);
9390     if (paintProperty->HasPreviewTextStyle()) {
9391         auto style = paintProperty->GetPreviewTextStyle();
9392         if (style.value() == PREVIEW_STYLE_NORMAL) {
9393             return PreviewTextStyle::NORMAL;
9394         } else if (style.value() == PREVIEW_STYLE_UNDERLINE) {
9395             return PreviewTextStyle::UNDERLINE;
9396         }
9397     }
9398     return defaultStyle;
9399 }
9400 
9401 void TextFieldPattern::ReceivePreviewTextStyle(const std::string& style)
9402 {
9403     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9404     CHECK_NULL_VOID(paintProperty);
9405     if (!style.empty()) {
9406         paintProperty->UpdatePreviewTextStyle(style);
9407     }
9408 }
9409 
9410 void TextFieldPattern::CalculatePreviewingTextMovingLimit(const Offset& touchOffset, double& limitL, double& limitR)
9411 {
9412     float offsetX = IsTextArea() ? contentRect_.GetX() : GetTextRect().GetX();
9413     float offsetY = IsTextArea() ? GetTextRect().GetY() : contentRect_.GetY();
9414     std::vector<RectF> previewTextRects = GetPreviewTextRects();
9415     if (GreatNotEqual(touchOffset.GetY(), previewTextRects.back().Bottom() + offsetY)) {
9416         limitL = previewTextRects.back().Left() + offsetX + MINIMAL_OFFSET;
9417         limitR = previewTextRects.back().Right() + offsetX - MINIMAL_OFFSET;
9418     } else if (LessNotEqual(touchOffset.GetY(), previewTextRects.front().Top() + offsetY)) {
9419         limitL = previewTextRects.front().Left() + offsetX + MINIMAL_OFFSET;
9420         limitR = previewTextRects.front().Right() + offsetX - MINIMAL_OFFSET;
9421     } else {
9422         for (const auto& drawRect : previewTextRects) {
9423             if (GreatOrEqual(touchOffset.GetY(), drawRect.Top() + offsetY)
9424                 && LessOrEqual(touchOffset.GetY(), drawRect.Bottom() + offsetY)) {
9425                 limitL = drawRect.Left() + offsetX + MINIMAL_OFFSET;
9426                 limitR = drawRect.Right() + offsetX - MINIMAL_OFFSET;
9427                 break;
9428             }
9429         }
9430     }
9431 }
9432 
9433 void TextFieldPattern::ResetPreviewTextState()
9434 {
9435     if (!GetIsPreviewText()) {
9436         return;
9437     }
9438 #if defined(ENABLE_STANDARD_INPUT)
9439     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
9440         StringUtils::Str8ToStr16(""), 0, 0);
9441     UpdateCaretInfoToController(true);
9442 #endif
9443     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield onDragEnter when has previewText");
9444     FinishTextPreview();
9445 }
9446 
9447 void TextFieldPattern::SetShowKeyBoardOnFocus(bool value)
9448 {
9449     if (showKeyBoardOnFocus_ == value) {
9450         return;
9451     }
9452     showKeyBoardOnFocus_ = value;
9453 
9454     if (!HasFocus()) {
9455         return;
9456     }
9457 
9458     if (value) {
9459         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SHOW_KEYBOARD_ON_FOCUS);
9460     } else {
9461         CloseKeyboard(true, false);
9462     }
9463 }
9464 
9465 void TextFieldPattern::OnCaretMoveDone(const TouchEventInfo& info)
9466 {
9467     if (isMoveCaretAnywhere_) {
9468         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "isMoveCaretAnywhere_=1, so restore caret");
9469         selectController_->UpdateCaretInfoByOffset(info.GetTouches().front().GetLocalLocation());
9470         StartTwinkling();
9471     }
9472 }
9473 
9474 void TextFieldPattern::HiddenMenu()
9475 {
9476     selectOverlay_->HideMenu();
9477 }
9478 
9479 void TextFieldPattern::OnSelectionMenuOptionsUpdate(
9480     const NG::OnCreateMenuCallback&& onCreateMenuCallback, const NG::OnMenuItemClickCallback&& onMenuItemClick)
9481 {
9482     selectOverlay_->OnSelectionMenuOptionsUpdate(std::move(onCreateMenuCallback), std::move(onMenuItemClick));
9483 }
9484 
9485 bool TextFieldPattern::GetTouchInnerPreviewText(const Offset& offset) const
9486 {
9487     auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset);
9488     return GetPreviewTextStart() <= touchDownIndex && touchDownIndex <= GetPreviewTextEnd() && HasFocus();
9489 }
9490 
9491 bool TextFieldPattern::IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const
9492 {
9493     if (touchEvent.sourceTool != SourceTool::PEN || touchEvent.type != TouchType::DOWN) {
9494         return false;
9495     }
9496     auto host = GetHost();
9497     CHECK_NULL_RETURN(host, false);
9498     auto focusHub = host->GetFocusHub();
9499     CHECK_NULL_RETURN(focusHub, false);
9500     if (!focusHub->IsFocusable() || !host->IsVisible()) {
9501         return false;
9502     }
9503     auto renderContext = host->GetRenderContext();
9504     CHECK_NULL_RETURN(renderContext, false);
9505     auto opacity = renderContext->GetOpacity();
9506     // if opacity is 0.0f, no need to hit frameNode.
9507     if (NearZero(opacity.value_or(1.0f))) {
9508         return false;
9509     }
9510     return !IsInPasswordMode();
9511 }
9512 
9513 RectF TextFieldPattern::ExpandDefaultResponseRegion(RectF& rect)
9514 {
9515     return rect + NG::SizeF(0, OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx() * OHOS::Ace::HOT_AREA_EXPAND_TIME) +
9516            NG::OffsetF(0, -OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx());
9517 }
9518 
9519 bool TextFieldPattern::IsContentRectNonPositive()
9520 {
9521     return NonPositive(contentRect_.Width());
9522 }
9523 
9524 void TextFieldPattern::ReportEvent()
9525 {
9526 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
9527     if (UiSessionManager::GetInstance()->GetSearchEventRegistered()) {
9528         auto host = GetHost();
9529         CHECK_NULL_VOID(host);
9530         auto data = JsonUtil::Create();
9531         data->Put("event", "onTextSearch");
9532         data->Put("id", host->GetId());
9533         data->Put("$type", host->GetTag().data());
9534         data->Put("inputType", static_cast<int16_t>(GetKeyboard()));
9535         data->Put("text", GetTextValue().data());
9536         data->Put("position", host->GetGeometryNode()->GetFrameRect().ToString().data());
9537         // report all use textfield component unfocus event,more than just the search box
9538         UiSessionManager::GetInstance()->ReportSearchEvent(data->ToString());
9539     }
9540 #endif
9541 }
9542 
9543 int32_t TextFieldPattern::GetTouchIndex(const OffsetF& offset)
9544 {
9545     return selectOverlay_->GetCaretPositionOnHandleMove(offset, true);
9546 }
9547 
9548 void TextFieldPattern::StartGestureSelection(int32_t start, int32_t end, const Offset& startOffset)
9549 {
9550     TextGestureSelector::StartGestureSelection(start, end, startOffset);
9551     StopContentScroll();
9552     contentScroller_.scrollingCallback = [weak = WeakClaim(this), start, end](const Offset& localOffset) {
9553         auto pattern = weak.Upgrade();
9554         CHECK_NULL_VOID(pattern);
9555         auto index = pattern->GetTouchIndex({ localOffset.GetX(), localOffset.GetY() });
9556         auto startIndex = std::min(index, start);
9557         auto endIndex = std::max(index, end);
9558         pattern->UpdateSelectionByLongPress(startIndex, endIndex, localOffset);
9559     };
9560 }
9561 
9562 void TextFieldPattern::OnTextGestureSelectionUpdate(int32_t start, int32_t end, const TouchEventInfo& info)
9563 {
9564     if (!HasText()) {
9565         return;
9566     }
9567     auto localOffset = info.GetTouches().front().GetLocalLocation();
9568     UpdateContentScroller(localOffset);
9569     if (contentScroller_.isScrolling) {
9570         return;
9571     }
9572     if (start != selectController_->GetStartIndex()) {
9573         StartVibratorByIndexChange(start, selectController_->GetStartIndex());
9574     } else if (end != selectController_->GetEndIndex()) {
9575         StartVibratorByIndexChange(end, selectController_->GetEndIndex());
9576     }
9577     UpdateSelectionByLongPress(start, end, localOffset);
9578 }
9579 
9580 void TextFieldPattern::UpdateSelectionByLongPress(int32_t start, int32_t end, const Offset& localOffset)
9581 {
9582     if (magnifierController_ && HasText() && (longPressFingerNum_ == 1)) {
9583         contentScroller_.updateMagniferEpsilon = 0.0f - contentScroller_.updateMagniferEpsilon;
9584         magnifierController_->SetLocalOffset(
9585             { localOffset.GetX(), localOffset.GetY() + contentScroller_.updateMagniferEpsilon });
9586     }
9587     auto firstIndex = selectController_->GetFirstHandleIndex();
9588     auto secondIndex = selectController_->GetSecondHandleIndex();
9589     bool changed = false;
9590     if (start != firstIndex) {
9591         selectController_->MoveFirstHandleToContentRect(start, false, false);
9592         changed = true;
9593     }
9594     if (secondIndex != end) {
9595         selectController_->MoveSecondHandleToContentRect(end, false, false);
9596         changed = true;
9597     }
9598     if (!changed) {
9599         return;
9600     }
9601     auto host = GetHost();
9602     CHECK_NULL_VOID(host);
9603     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
9604 }
9605 
9606 void TextFieldPattern::OnTextGenstureSelectionEnd(const TouchLocationInfo& locationInfo)
9607 {
9608     SetIsSingleHandle(!IsSelected());
9609     bool isScrolling = contentScroller_.isScrolling;
9610     StopContentScroll();
9611     if (IsContentRectNonPositive()) {
9612         return;
9613     }
9614     if (!isScrolling) {
9615         auto localLocation = locationInfo.GetLocalLocation();
9616         if (LessNotEqual(localLocation.GetX(), contentRect_.Left()) ||
9617             LessNotEqual(localLocation.GetY(), contentRect_.Top())) {
9618             selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex(), false);
9619         } else if (GreatNotEqual(localLocation.GetX(), contentRect_.Right()) ||
9620                    GreatNotEqual(localLocation.GetY(), contentRect_.Bottom())) {
9621             selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex(), false);
9622         }
9623     } else {
9624         if (Positive(contentScroller_.stepOffset)) {
9625             selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex(), false);
9626         } else if (Negative(contentScroller_.stepOffset)) {
9627             selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex(), false);
9628         }
9629     }
9630     if (HasFocus()) {
9631         ProcessOverlay({ .animation = true });
9632     }
9633 }
9634 
9635 PositionWithAffinity TextFieldPattern::GetGlyphPositionAtCoordinate(int32_t x, int32_t y)
9636 {
9637     PositionWithAffinity finalResult(0, TextAffinity::UPSTREAM);
9638     CHECK_NULL_RETURN(paragraph_, finalResult);
9639     Offset offset(x, y);
9640     return paragraph_->GetGlyphPositionAtCoordinate(ConvertTouchOffsetToTextOffset(offset));
9641 }
9642 
9643 Offset TextFieldPattern::ConvertTouchOffsetToTextOffset(const Offset& touchOffset)
9644 {
9645     return touchOffset - Offset(textRect_.GetX(), textRect_.GetY());
9646 }
9647 
9648 bool TextFieldPattern::InsertOrDeleteSpace(int32_t index)
9649 {
9650     // delete or insert space.
9651     auto wtext = GetTextUtf16Value();
9652     if (index >= 0 && index < static_cast<int32_t>(wtext.length())) {
9653         auto ret = SetCaretOffset(index);
9654         if (!ret) {
9655             return false;
9656         }
9657         if (wtext[index] == u' ') {
9658             DeleteForward(1);
9659         } else if (index > 0 && wtext[index - 1] == u' ') {
9660             DeleteBackward(1);
9661         } else {
9662             InsertValue(u" ", true);
9663         }
9664         return true;
9665     }
9666     return false;
9667 }
9668 
9669 void TextFieldPattern::DeleteRange(int32_t start, int32_t end, bool isIME)
9670 {
9671     auto length = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
9672     if (start > end) {
9673         std::swap(start, end);
9674     }
9675     start = std::max(0, start);
9676     end = std::min(length, end);
9677     if (start > length || end < 0 || start == end) {
9678         return;
9679     }
9680     auto value = contentController_->GetSelectedValue(start, end);
9681     auto originCaretIndex =
9682             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
9683     if (isIME) {
9684         auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::FORWARD, start);
9685         CHECK_NULL_VOID(isDelete);
9686     }
9687     ResetObscureTickCountDown();
9688     CheckAndUpdateRecordBeforeOperation();
9689     auto oldContent = contentController_->GetTextUtf16Value();
9690     Delete(start, end);
9691     auto isOnWillChange = OnWillChangePreDelete(oldContent, start, end);
9692     if (!isOnWillChange) {
9693         RecoverTextValueAndCaret(oldContent, originCaretIndex);
9694         return;
9695     }
9696     if (isIME) {
9697         AfterIMEDeleteValue(value, TextDeleteDirection::FORWARD);
9698     }
9699     showCountBorderStyle_ = false;
9700     HandleCountStyle();
9701 }
9702 
9703 void TextFieldPattern::DeleteTextRange(int32_t start, int32_t end, TextDeleteDirection direction)
9704 {
9705     auto length = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
9706     if (start > end) {
9707         std::swap(start, end);
9708     }
9709     start = std::max(0, start);
9710     end = std::min(length, end);
9711     if (start > length || end < 0 || start == end) {
9712         return;
9713     }
9714     auto value = contentController_->GetSelectedValue(start, end);
9715     auto originCaretIndex =
9716             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
9717     auto isDelete = BeforeIMEDeleteValue(value, direction, start);
9718     CHECK_NULL_VOID(isDelete);
9719     ResetObscureTickCountDown();
9720     CheckAndUpdateRecordBeforeOperation();
9721     auto oldContent = contentController_->GetTextUtf16Value();
9722     Delete(start, end);
9723     auto isOnWillChange = OnWillChangePreDelete(oldContent, start, end);
9724     if (!isOnWillChange) {
9725         RecoverTextValueAndCaret(oldContent, originCaretIndex);
9726         return;
9727     }
9728     AfterIMEDeleteValue(value, direction);
9729     showCountBorderStyle_ = false;
9730     HandleCountStyle();
9731 }
9732 
9733 bool TextFieldPattern::IsShowAIWrite()
9734 {
9735     auto container = Container::Current();
9736     if (container && container->IsScenceBoardWindow()) {
9737         return false;
9738     }
9739 
9740     auto host = GetHost();
9741     CHECK_NULL_RETURN(host, false);
9742     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9743     CHECK_NULL_RETURN(layoutProperty, false);
9744     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) == CopyOptions::None ||
9745         !IsUnspecifiedOrTextType()) {
9746         return false;
9747     }
9748 
9749     auto textFieldTheme = GetTheme();
9750     CHECK_NULL_RETURN(textFieldTheme, false);
9751     auto bundleName = textFieldTheme->GetAIWriteBundleName();
9752     auto abilityName = textFieldTheme->GetAIWriteAbilityName();
9753     if (bundleName.empty() || abilityName.empty()) {
9754         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Failed to obtain AI write package name!");
9755         return false;
9756     }
9757     aiWriteAdapter_->SetBundleName(bundleName);
9758     aiWriteAdapter_->SetAbilityName(abilityName);
9759 
9760     auto isAISupport = false;
9761     if (textFieldTheme->GetAIWriteIsSupport() == "true") {
9762         isAISupport = true;
9763     }
9764     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Whether the device supports AI write: %{public}d, nodeId: %{public}d",
9765         isAISupport, host->GetId());
9766     return isAISupport;
9767 }
9768 
9769 void TextFieldPattern::GetAIWriteInfo(AIWriteInfo& info)
9770 {
9771     // serialize the selected text
9772     info.selectStart = selectController_->GetStartIndex();
9773     info.selectEnd = selectController_->GetEndIndex();
9774     auto selectContent = contentController_->GetSelectedValue(info.selectStart, info.selectEnd);
9775     RefPtr<SpanString> spanString = AceType::MakeRefPtr<SpanString>(selectContent);
9776     spanString->EncodeTlv(info.selectBuffer);
9777     info.selectLength = static_cast<int32_t>(aiWriteAdapter_->GetSelectLengthOnlyText(spanString->GetU16string()));
9778     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "Selected range=[%{public}d--%{public}d], content size=%{public}zu",
9779         info.selectStart, info.selectEnd, spanString->GetString().size());
9780 
9781     // serialize the sentenced-level text
9782     auto textSize = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
9783     auto contentAll = contentController_->GetTextUtf16Value();
9784     auto sentenceStart = 0;
9785     auto sentenceEnd = textSize;
9786     for (int32_t i = info.selectStart; i >= 0; --i) {
9787         if (aiWriteAdapter_->IsSentenceBoundary(contentAll[i])) {
9788             sentenceStart = i + 1;
9789             break;
9790         }
9791     }
9792     for (int32_t i = info.selectEnd; i < textSize; i++) {
9793         if (aiWriteAdapter_->IsSentenceBoundary(contentAll[i])) {
9794             sentenceEnd = i;
9795             break;
9796         }
9797     }
9798     info.start = info.selectStart - sentenceStart;
9799     info.end = info.selectEnd - sentenceStart;
9800     auto sentenceContent = contentController_->GetSelectedValue(sentenceStart, sentenceEnd);
9801     spanString = AceType::MakeRefPtr<SpanString>(sentenceContent);
9802     spanString->EncodeTlv(info.sentenceBuffer);
9803     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "Sentence range=[%{public}d--%{public}d], content size=%{public}zu",
9804         sentenceStart, sentenceEnd, spanString->GetString().size());
9805 
9806     auto host = GetHost();
9807     CHECK_NULL_VOID(host);
9808     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9809     CHECK_NULL_VOID(layoutProperty);
9810     info.maxLength = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
9811     info.firstHandle = selectController_->GetFirstHandleRect().ToString();
9812     info.secondHandle = selectController_->GetSecondHandleRect().ToString();
9813     info.componentType = host->GetTag();
9814 }
9815 
9816 void TextFieldPattern::HandleOnAIWrite()
9817 {
9818     AIWriteInfo info;
9819     GetAIWriteInfo(info);
9820     CloseSelectOverlay();
9821     CloseKeyboard(true);
9822 
9823     auto callback = [weak = WeakClaim(this), info](std::vector<uint8_t>& buffer) {
9824         auto pattern = weak.Upgrade();
9825         CHECK_NULL_VOID(pattern);
9826         pattern->HandleAIWriteResult(info.selectStart, info.selectEnd, buffer);
9827         auto aiWriteAdapter = pattern->aiWriteAdapter_;
9828         CHECK_NULL_VOID(aiWriteAdapter);
9829         aiWriteAdapter->CloseModalUIExtension();
9830     };
9831     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
9832     CHECK_NULL_VOID(pipeline);
9833     aiWriteAdapter_->SetPipelineContext(pipeline);
9834     aiWriteAdapter_->ShowModalUIExtension(info, callback);
9835 }
9836 
9837 void TextFieldPattern::HandleAIWriteResult(int32_t start, int32_t end, std::vector<uint8_t>& buffer)
9838 {
9839     RefPtr<SpanString> spanString = SpanString::DecodeTlv(buffer);
9840     auto resultText = spanString->GetU16string();
9841     TAG_LOGD(AceLogTag::ACE_RICH_TEXT, "Backfilling results range=[%{public}d--%{public}d], content size=%{public}zu",
9842         start, end, spanString->GetString().size());
9843     if (spanString->GetSpanItems().empty()) {
9844         return;
9845     }
9846 
9847     auto host = GetHost();
9848     CHECK_NULL_VOID(host);
9849     auto value = contentController_->GetSelectedValue(start, end);
9850     InputCommandInfo inputCommandInfo;
9851     inputCommandInfo.deleteRange = { start, end };
9852     inputCommandInfo.insertOffset = start;
9853     inputCommandInfo.insertValue = resultText;
9854     inputCommandInfo.reason = InputReason::AI_WRITE;
9855     AddInputCommand(inputCommandInfo);
9856 }
9857 
9858 bool TextFieldPattern::IsTextEditableForStylus() const
9859 {
9860     CHECK_NULL_RETURN(!HasCustomKeyboard(), false);
9861     auto host = GetHost();
9862     CHECK_NULL_RETURN(host, false);
9863     auto focusHub = host->GetFocusHub();
9864     CHECK_NULL_RETURN(focusHub, false);
9865     if (!focusHub->IsFocusable() || !host->IsVisible()) {
9866         return false;
9867     }
9868     auto renderContext = host->GetRenderContext();
9869     CHECK_NULL_RETURN(renderContext, false);
9870     auto opacity = renderContext->GetOpacity();
9871     // if opacity is 0.0f, no need to hit frameNode.
9872     if (NearZero(opacity.value_or(1.0f))) {
9873         return false;
9874     }
9875     return !IsInPasswordMode();
9876 }
9877 
9878 void TextFieldPattern::UpdateContentScroller(const Offset& localOffset)
9879 {
9880     auto scrollStep = CalcAutoScrollStepOffset(localOffset);
9881     // 在热区外移动
9882     if (!scrollStep || (!GetScrollEnabled() && !moveCaretState_.isMoveCaret)) {
9883         contentScroller_.OnBeforeScrollingCallback(localOffset);
9884         PauseContentScroll();
9885         contentScroller_.hotAreaOffset.reset();
9886         return;
9887     }
9888     contentScroller_.stepOffset = scrollStep.value();
9889     contentScroller_.localOffset = localOffset;
9890     if (contentScroller_.isScrolling) {
9891         return;
9892     }
9893     contentScroller_.OnBeforeScrollingCallback(localOffset);
9894     if (!contentScroller_.hotAreaOffset) {
9895         contentScroller_.hotAreaOffset = localOffset;
9896         ScheduleContentScroll(AUTO_SCROLL_HOT_AREA_LONGPRESS_DURATION);
9897     } else {
9898         auto hotAreaMoveDistance = (localOffset - contentScroller_.hotAreaOffset.value()).GetDistance();
9899         if (GreatOrEqual(hotAreaMoveDistance, AUTO_SCROLL_HOT_AREA_LONGPRESS_DISTANCE.ConvertToPx())) {
9900             contentScroller_.hotAreaOffset = localOffset;
9901             contentScroller_.autoScrollTask.Cancel();
9902             ScheduleContentScroll(AUTO_SCROLL_HOT_AREA_LONGPRESS_DURATION);
9903         }
9904     }
9905 }
9906 
9907 std::optional<float> TextFieldPattern::CalcAutoScrollStepOffset(const Offset& localOffset)
9908 {
9909     auto contentRect = GetContentRect();
9910     auto axis = GetAxis();
9911     auto isVertical = (axis == Axis::VERTICAL);
9912     auto hotArea = isVertical ? AUTO_SCROLL_HOT_ZONE_HEIGHT.ConvertToPx() : AUTO_SCROLL_HOT_ZONE_WIDTH.ConvertToPx();
9913     if (isVertical) {
9914         if (LessOrEqual(contentRect.Height(), hotArea)) {
9915             hotArea = contentRect.Height() / 3.0f;
9916         }
9917     } else {
9918         if (LessOrEqual(contentRect.Width(), hotArea)) {
9919             hotArea = contentRect.Width() / 3.0f;
9920         }
9921     }
9922     struct HotEdge {
9923         float start = 0.0f;
9924         float end = 0.0f;
9925         float scrollDirection = 1.0f;
9926     };
9927     std::vector<HotEdge> hotEdges = { { contentRect.Top() + hotArea, contentRect.Top(), 1.0f },
9928         { contentRect.Bottom() - hotArea, contentRect.Bottom(), -1.0f },
9929         { contentRect.Left() + hotArea, contentRect.Left(), 1.0f },
9930         { contentRect.Right() - hotArea, contentRect.Right(), -1.0f } };
9931     auto itStart = isVertical ? hotEdges.begin() : hotEdges.begin() + 2;
9932     auto point = isVertical ? localOffset.GetY() : localOffset.GetX();
9933     std::optional<float> scrollStep;
9934     for (auto it = itStart; it != (itStart + 2); ++it) {
9935         auto speed = CalcScrollSpeed(it->start, it->end, point);
9936         if (!NearZero(speed)) {
9937             scrollStep = speed * it->scrollDirection;
9938             break;
9939         }
9940     }
9941     return scrollStep;
9942 }
9943 
9944 float TextFieldPattern::CalcScrollSpeed(float hotAreaStart, float hotAreaEnd, float point)
9945 {
9946     auto minHotArea = std::min(hotAreaStart, hotAreaEnd);
9947     auto maxHotArea = std::max(hotAreaStart, hotAreaEnd);
9948     if (GreatNotEqual(point, minHotArea) && LessNotEqual(point, maxHotArea)) {
9949         auto distanceRatio = (point - hotAreaStart) / (hotAreaEnd - hotAreaStart);
9950         auto speedFactor = Curves::SHARP->MoveInternal(distanceRatio);
9951         return ((MAX_DRAG_SCROLL_SPEED * speedFactor) / TIME_UNIT) * contentScroller_.scrollInterval;
9952     }
9953     return 0.0f;
9954 }
9955 
9956 void TextFieldPattern::StopContentScroll()
9957 {
9958     PauseContentScroll();
9959     contentScroller_.scrollingCallback = nullptr;
9960     contentScroller_.beforeScrollingCallback = nullptr;
9961 }
9962 
9963 void TextFieldPattern::PauseContentScroll()
9964 {
9965     contentScroller_.autoScrollTask.Cancel();
9966     contentScroller_.isScrolling = false;
9967     ScheduleDisappearDelayTask();
9968 }
9969 
9970 void TextFieldPattern::ScheduleContentScroll(float delay)
9971 {
9972     auto host = GetHost();
9973     CHECK_NULL_VOID(host);
9974     auto context = host->GetContext();
9975     CHECK_NULL_VOID(context);
9976     auto taskExecutor = context->GetTaskExecutor();
9977     CHECK_NULL_VOID(taskExecutor);
9978     contentScroller_.autoScrollTask.Reset([weak = WeakClaim(this)]() {
9979         auto pattern = weak.Upgrade();
9980         CHECK_NULL_VOID(pattern);
9981         pattern->contentScroller_.isScrolling = true;
9982         pattern->contentScroller_.hotAreaOffset = std::nullopt;
9983         pattern->OnScrollCallback(pattern->contentScroller_.stepOffset, SCROLL_FROM_UPDATE);
9984         if (pattern->contentScroller_.scrollingCallback) {
9985             pattern->contentScroller_.scrollingCallback(pattern->contentScroller_.localOffset);
9986         }
9987         pattern->ScheduleContentScroll(pattern->contentScroller_.scrollInterval);
9988     });
9989     taskExecutor->PostDelayedTask(contentScroller_.autoScrollTask, TaskExecutor::TaskType::UI, delay,
9990         "ArkUIAutoScrollControllerScheduleAutoScroll");
9991 }
9992 
9993 void TextFieldPattern::SetDragMovingScrollback()
9994 {
9995     StopContentScroll();
9996     contentScroller_.scrollingCallback = [weak = WeakClaim(this)](const Offset& localOffset) {
9997         auto pattern = weak.Upgrade();
9998         CHECK_NULL_VOID(pattern);
9999         auto host = pattern->GetHost();
10000         CHECK_NULL_VOID(host);
10001         auto pipeline = host->GetContext();
10002         CHECK_NULL_VOID(pipeline);
10003         auto theme = pipeline->GetTheme<TextFieldTheme>();
10004         CHECK_NULL_VOID(theme);
10005         Offset offset = localOffset - Offset(pattern->textRect_.GetX(), pattern->textRect_.GetY()) -
10006                         Offset(0, theme->GetInsertCursorOffset().ConvertToPx());
10007         auto position = pattern->ConvertTouchOffsetToCaretPosition(offset);
10008         pattern->SetCaretPosition(position, false);
10009         pattern->ShowCaretAndStopTwinkling();
10010     };
10011     contentScroller_.beforeScrollingCallback = contentScroller_.scrollingCallback;
10012 }
10013 
10014 void TextFieldPattern::OnAttachToMainTree()
10015 {
10016     isDetachFromMainTree_ = false;
10017     auto host = GetHost();
10018     CHECK_NULL_VOID(host);
10019     auto autoFillContainerNode = host->GetFirstAutoFillContainerNode();
10020     CHECK_NULL_VOID(autoFillContainerNode);
10021     firstAutoFillContainerNode_ = WeakClaim(RawPtr(autoFillContainerNode));
10022     AddTextFieldInfo();
10023 }
10024 
10025 void TextFieldPattern::OnDetachFromMainTree()
10026 {
10027     isDetachFromMainTree_ = true;
10028     RemoveTextFieldInfo();
10029 }
10030 
10031 TextFieldInfo TextFieldPattern::GenerateTextFieldInfo()
10032 {
10033     TextFieldInfo textFieldInfo;
10034     auto host = GetHost();
10035     CHECK_NULL_RETURN(host, textFieldInfo);
10036     textFieldInfo.nodeId = host->GetId();
10037     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
10038     CHECK_NULL_RETURN(autoFillContainerNode, textFieldInfo);
10039     textFieldInfo.autoFillContainerNodeId = autoFillContainerNode->GetId();
10040     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10041     CHECK_NULL_RETURN(layoutProperty, textFieldInfo);
10042     textFieldInfo.enableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
10043     textFieldInfo.inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
10044     textFieldInfo.contentType = layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED);
10045     return textFieldInfo;
10046 }
10047 
10048 void TextFieldPattern::AddTextFieldInfo()
10049 {
10050     CHECK_NULL_VOID(IsNeedProcessAutoFill());
10051     auto host = GetHost();
10052     CHECK_NULL_VOID(host);
10053     auto pipeline = host->GetContext();
10054     CHECK_NULL_VOID(pipeline);
10055     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10056     CHECK_NULL_VOID(textFieldManager);
10057     auto textFieldInfo = GenerateTextFieldInfo();
10058     textFieldManager->AddTextFieldInfo(textFieldInfo);
10059 }
10060 
10061 void TextFieldPattern::RemoveTextFieldInfo()
10062 {
10063     CHECK_NULL_VOID(IsNeedProcessAutoFill());
10064     auto host = GetHost();
10065     CHECK_NULL_VOID(host);
10066     auto pipeline = host->GetContext();
10067     CHECK_NULL_VOID(pipeline);
10068     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10069     CHECK_NULL_VOID(textFieldManager);
10070     auto nodeId = host->GetId();
10071     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
10072     CHECK_NULL_VOID(autoFillContainerNode);
10073     auto autoFillContainerNodeId = autoFillContainerNode->GetId();
10074     textFieldManager->RemoveTextFieldInfo(autoFillContainerNodeId, nodeId);
10075 }
10076 
10077 void TextFieldPattern::UpdateTextFieldInfo()
10078 {
10079     CHECK_NULL_VOID(IsNeedProcessAutoFill());
10080     auto host = GetHost();
10081     CHECK_NULL_VOID(host);
10082     auto pipeline = host->GetContext();
10083     CHECK_NULL_VOID(pipeline);
10084     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10085     CHECK_NULL_VOID(textFieldManager);
10086     auto textFieldInfo = GenerateTextFieldInfo();
10087     textFieldManager->UpdateTextFieldInfo(textFieldInfo);
10088 }
10089 
10090 bool TextFieldPattern::IsAutoFillUserName(const AceAutoFillType& autoFillType)
10091 {
10092     auto isUserName =
10093         autoFillType == AceAutoFillType::ACE_USER_NAME || autoFillType == AceAutoFillType::ACE_UNSPECIFIED;
10094     return isUserName && HasAutoFillPasswordNode();
10095 }
10096 
10097 bool TextFieldPattern::HasAutoFillPasswordNode()
10098 {
10099     auto host = GetHost();
10100     CHECK_NULL_RETURN(host, false);
10101     auto pipeline = host->GetContext();
10102     CHECK_NULL_RETURN(pipeline, false);
10103     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10104     CHECK_NULL_RETURN(textFieldManager, false);
10105     auto nodeId = host->GetId();
10106     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
10107     CHECK_NULL_RETURN(autoFillContainerNode, false);
10108     auto autoFillContainerNodeId = autoFillContainerNode->GetId();
10109     return textFieldManager->HasAutoFillPasswordNodeInContainer(autoFillContainerNodeId, nodeId);
10110 }
10111 
10112 bool TextFieldPattern::IsTriggerAutoFillPassword()
10113 {
10114     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10115     CHECK_NULL_RETURN(layoutProperty, false);
10116     auto aceContentType =
10117         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
10118     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
10119         if (!IsAutoFillPasswordType(aceContentType)) {
10120             return false;
10121         } else {
10122             if (aceContentType == AceAutoFillType::ACE_PASSWORD ||
10123                 aceContentType == AceAutoFillType::ACE_NEW_PASSWORD) {
10124                 return true;
10125             }
10126             return HasAutoFillPasswordNode();
10127         }
10128     }
10129 
10130     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
10131     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
10132         if (aceInputType == AceAutoFillType::ACE_PASSWORD || aceInputType == AceAutoFillType::ACE_NEW_PASSWORD) {
10133             return true;
10134         }
10135     }
10136     return HasAutoFillPasswordNode();
10137 }
10138 
10139 bool TextFieldPattern::IsNeedProcessAutoFill()
10140 {
10141     return true;
10142 }
10143 
10144 std::vector<RectF> TextFieldPattern::GetTextBoxesForSelect()
10145 {
10146     auto selectedRects = GetTextBoxes();
10147     CHECK_NULL_RETURN(paragraph_, selectedRects);
10148     auto paragraphStyle = paragraph_->GetParagraphStyle();
10149     auto textAlign = TextBase::CheckTextAlignByDirection(paragraphStyle.align, paragraphStyle.direction);
10150     const float blankWidth = TextBase::GetSelectedBlankLineWidth();
10151     auto contentWidth = GetTextContentRect().Width();
10152     TextBase::CalculateSelectedRectEx(selectedRects, -1.0f);
10153     for (auto& rect : selectedRects) {
10154         TextBase::UpdateSelectedBlankLineRect(rect, blankWidth, textAlign, contentWidth);
10155     }
10156     return selectedRects;
10157 }
10158 
10159 void TextFieldPattern::AdjustSelectedBlankLineWidth(RectF& rect)
10160 {
10161     CHECK_NULL_VOID(paragraph_);
10162     auto paragraphStyle = paragraph_->GetParagraphStyle();
10163     auto textAlign = TextBase::CheckTextAlignByDirection(paragraphStyle.align, paragraphStyle.direction);
10164     const float blankWidth = TextBase::GetSelectedBlankLineWidth();
10165     auto contentWidth = GetTextContentRect().Width();
10166     TextBase::UpdateSelectedBlankLineRect(rect, blankWidth, textAlign, contentWidth);
10167 }
10168 
10169 std::optional<TouchLocationInfo> TextFieldPattern::GetAcceptedTouchLocationInfo(const TouchEventInfo& info)
10170 {
10171     auto touchInfos = info.GetChangedTouches();
10172     if (touchInfos.empty()) {
10173         return std::nullopt;
10174     }
10175     if (!moveCaretState_.isMoveCaret && !IsGestureSelectingText()) {
10176         return touchInfos.front();
10177     }
10178     auto fingerId = moveCaretState_.isMoveCaret ? moveCaretState_.touchFingerId : GetSelectingFingerId();
10179     for (auto touchInfo : touchInfos) {
10180         if (touchInfo.GetFingerId() == fingerId) {
10181             return touchInfo;
10182         }
10183     }
10184     return std::nullopt;
10185 }
10186 
10187 void TextFieldPattern::DoTextSelectionTouchCancel()
10188 {
10189     CHECK_NULL_VOID(magnifierController_);
10190     magnifierController_->RemoveMagnifierFrameNode();
10191     selectController_->UpdateCaretIndex(selectController_->GetCaretIndex());
10192     StopContentScroll();
10193     StartTwinkling();
10194 }
10195 
10196 float TextFieldPattern::GetVerticalPaddingAndBorderSum() const
10197 {
10198     auto border = GetBorderWidthProperty();
10199     if (utilPadding_.has_value()) {
10200         return utilPadding_.value().top.value_or(0.0f) + utilPadding_.value().bottom.value_or(0.0f) +
10201                GetBorderTop(border) + GetBorderBottom(border);
10202     }
10203     auto textFieldTheme = GetTheme();
10204     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10205     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10206     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10207     CHECK_NULL_RETURN(layoutProperty, themePadding.Top().ConvertToPx() + themePadding.Bottom().ConvertToPx());
10208     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10209     CHECK_NULL_RETURN(paddingProperty, themePadding.Top().ConvertToPx() + themePadding.Bottom().ConvertToPx());
10210 
10211     auto result = static_cast<float>(
10212         paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension().ConvertToPx() +
10213         paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension().ConvertToPx());
10214     return result + GetBorderTop(border) + GetBorderBottom(border);
10215 }
10216 
10217 float TextFieldPattern::GetHorizontalPaddingAndBorderSum() const
10218 {
10219     auto border = GetBorderWidthProperty();
10220     if (utilPadding_.has_value()) {
10221         return utilPadding_.value().left.value_or(0.0f) + utilPadding_.value().right.value_or(0.0f) +
10222                GetBorderLeft(border) + GetBorderRight(border);
10223     }
10224     auto textFieldTheme = GetTheme();
10225     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10226     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10227     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10228     CHECK_NULL_RETURN(layoutProperty, themePadding.Left().ConvertToPx() + themePadding.Right().ConvertToPx());
10229     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10230     CHECK_NULL_RETURN(paddingProperty, themePadding.Left().ConvertToPx() + themePadding.Right().ConvertToPx());
10231     auto padding = static_cast<float>(
10232         paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension().ConvertToPx() +
10233         paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension().ConvertToPx());
10234     return padding + GetBorderLeft(border) + GetBorderRight(border);
10235 }
10236 
10237 float TextFieldPattern::GetPaddingTop() const
10238 {
10239     if (utilPadding_.has_value()) {
10240         return utilPadding_.value().top.value_or(0.0f);
10241     }
10242     auto textFieldTheme = GetTheme();
10243     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10244     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10245     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10246     CHECK_NULL_RETURN(layoutProperty, themePadding.Top().ConvertToPx());
10247     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10248     CHECK_NULL_RETURN(paddingProperty, themePadding.Top().ConvertToPx());
10249     return static_cast<float>(
10250         paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension().ConvertToPx());
10251 }
10252 
10253 float TextFieldPattern::GetPaddingBottom() const
10254 {
10255     if (utilPadding_.has_value()) {
10256         return utilPadding_.value().bottom.value_or(0.0f);
10257     }
10258     auto textFieldTheme = GetTheme();
10259     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10260     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10261     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10262     CHECK_NULL_RETURN(layoutProperty, themePadding.Bottom().ConvertToPx());
10263     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10264     CHECK_NULL_RETURN(paddingProperty, themePadding.Bottom().ConvertToPx());
10265     return static_cast<float>(
10266         paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension().ConvertToPx());
10267 }
10268 
10269 float TextFieldPattern::GetPaddingLeft() const
10270 {
10271     if (utilPadding_.has_value()) {
10272         return utilPadding_.value().left.value_or(0.0f);
10273     }
10274     auto textFieldTheme = GetTheme();
10275     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10276     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10277     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10278     CHECK_NULL_RETURN(layoutProperty, themePadding.Left().ConvertToPx());
10279     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10280     CHECK_NULL_RETURN(paddingProperty, themePadding.Left().ConvertToPx());
10281     return static_cast<float>(
10282         paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension().ConvertToPx());
10283 }
10284 
10285 float TextFieldPattern::GetPaddingRight() const
10286 {
10287     if (utilPadding_.has_value()) {
10288         return utilPadding_.value().right.value_or(0.0f);
10289     }
10290     auto textFieldTheme = GetTheme();
10291     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10292     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10293     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10294     CHECK_NULL_RETURN(layoutProperty, themePadding.Right().ConvertToPx());
10295     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10296     CHECK_NULL_RETURN(paddingProperty, themePadding.Right().ConvertToPx());
10297     return static_cast<float>(
10298         paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension().ConvertToPx());
10299 }
10300 
10301 BorderWidthProperty TextFieldPattern::GetBorderWidthProperty() const
10302 {
10303     BorderWidthProperty currentBorderWidth;
10304     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10305     CHECK_NULL_RETURN(layoutProperty, currentBorderWidth);
10306     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
10307         currentBorderWidth = *(layoutProperty->GetBorderWidthProperty());
10308     } else {
10309         currentBorderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
10310     }
10311     return currentBorderWidth;
10312 }
10313 
10314 float TextFieldPattern::GetBorderLeft(BorderWidthProperty border) const
10315 {
10316     auto leftBorderWidth = border.leftDimen.value_or(Dimension(0.0f));
10317     auto percentReferenceWidth = GetPercentReferenceWidth();
10318     if (leftBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10319         return leftBorderWidth.Value() * percentReferenceWidth;
10320     }
10321     return leftBorderWidth.ConvertToPx();
10322 }
10323 
10324 float TextFieldPattern::GetBorderTop(BorderWidthProperty border) const
10325 {
10326     auto topBorderWidth = border.topDimen.value_or(Dimension(0.0f));
10327     auto percentReferenceWidth = GetPercentReferenceWidth();
10328     if (topBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10329         return topBorderWidth.Value() * percentReferenceWidth;
10330     }
10331     return topBorderWidth.ConvertToPx();
10332 }
10333 
10334 float TextFieldPattern::GetBorderBottom(BorderWidthProperty border) const
10335 {
10336     auto bottomBorderWidth = border.bottomDimen.value_or(Dimension(0.0f));
10337     auto percentReferenceWidth = GetPercentReferenceWidth();
10338     if (bottomBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10339         return bottomBorderWidth.Value() * percentReferenceWidth;
10340     }
10341     return bottomBorderWidth.ConvertToPx();
10342 }
10343 
10344 float TextFieldPattern::GetBorderRight(BorderWidthProperty border) const
10345 {
10346     auto rightBorderWidth = border.rightDimen.value_or(Dimension(0.0f));
10347     auto percentReferenceWidth = GetPercentReferenceWidth();
10348     if (rightBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10349         return rightBorderWidth.Value() * percentReferenceWidth;
10350     }
10351     return rightBorderWidth.ConvertToPx();
10352 }
10353 
10354 void TextFieldPattern::ResetFirstClickAfterGetFocus()
10355 {
10356     if (!firstClickAfterLosingFocus_) {
10357         return;
10358     }
10359     auto host = GetHost();
10360     CHECK_NULL_VOID(host);
10361     auto pipeline = host->GetContext();
10362     CHECK_NULL_VOID(pipeline);
10363     auto taskExecutor = pipeline->GetTaskExecutor();
10364     CHECK_NULL_VOID(taskExecutor);
10365     firstClickResetTask_.Cancel();
10366     firstClickResetTask_.Reset([weak = WeakClaim(this)]() {
10367         auto pattern = weak.Upgrade();
10368         CHECK_NULL_VOID(pattern);
10369         pattern->firstClickAfterLosingFocus_ = false;
10370     });
10371     taskExecutor->PostDelayedTask(
10372         firstClickResetTask_, TaskExecutor::TaskType::UI, TWINKLING_INTERVAL_MS, "ResetFirstClickAfterGetFocusTask");
10373 }
10374 
10375 SelectionInfo TextFieldPattern::GetSelection()
10376 {
10377     SelectionInfo selection;
10378     selection.SetSelectionStart(selectController_->GetStartIndex());
10379     selection.SetSelectionEnd(selectController_->GetEndIndex());
10380     return selection;
10381 }
10382 
10383 FocusPattern TextFieldPattern::GetFocusPattern() const
10384 {
10385     FocusPattern focusPattern = { FocusType::NODE, true, FocusStyleType::FORCE_NONE };
10386     focusPattern.SetIsFocusActiveWhenFocused(true);
10387     auto host = GetHost();
10388     CHECK_NULL_RETURN(host, focusPattern);
10389     auto pipelineContext = host->GetContext();
10390     CHECK_NULL_RETURN(pipelineContext, focusPattern);
10391     auto theme = pipelineContext->GetTheme<TextFieldTheme>();
10392     CHECK_NULL_RETURN(theme, focusPattern);
10393     if (theme->NeedFocusBox()) {
10394         focusPattern.SetStyleType(FocusStyleType::OUTER_BORDER);
10395     }
10396     return focusPattern;
10397 }
10398 
10399 bool TextFieldPattern::FireOnWillChange(const ChangeValueInfo& changeValueInfo)
10400 {
10401     auto host = GetHost();
10402     CHECK_NULL_RETURN(host, true);
10403     auto eventHub = host->GetEventHub<TextFieldEventHub>();
10404     CHECK_NULL_RETURN(eventHub, true);
10405     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10406     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10407     callbackOldContent_ = changeValueInfo.oldContent;
10408     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10409     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10410 }
10411 
10412 bool TextFieldPattern::OnWillChangePreInsert(const std::u16string& insertValue, const std::u16string& oldContent,
10413     uint32_t start, uint32_t end)
10414 {
10415     auto host = GetHost();
10416     CHECK_NULL_RETURN(host, true);
10417     auto eventHub = host->GetEventHub<TextFieldEventHub>();
10418     CHECK_NULL_RETURN(eventHub, true);
10419     ChangeValueInfo changeValueInfo;
10420     PreviewText previewText {.offset = -1, .value = u""};
10421     if (hasPreviewText_) {
10422         previewText.offset = GetPreviewTextStart();
10423         previewText.value = GetPreviewTextValue();
10424     }
10425     changeValueInfo.oldPreviewText = previewText;
10426     changeValueInfo.previewText = previewText;
10427 
10428     auto insertLength = insertValue.length();
10429     changeValueInfo.rangeBefore = TextRange { start, end };
10430     changeValueInfo.rangeAfter = TextRange { start, start + insertLength };
10431 
10432     changeValueInfo.oldContent = oldContent;
10433     changeValueInfo.value = contentController_->GetTextUtf16Value();
10434     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10435     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10436     callbackOldContent_ = changeValueInfo.oldContent;
10437     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10438     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10439 }
10440 
10441 bool TextFieldPattern::OnWillChangePreDelete(const std::u16string& oldContent, uint32_t start, uint32_t end)
10442 {
10443     auto host = GetHost();
10444     CHECK_NULL_RETURN(host, true);
10445     auto eventHub = host->GetEventHub<TextFieldEventHub>();
10446     CHECK_NULL_RETURN(eventHub, true);
10447     ChangeValueInfo changeValueInfo;
10448     PreviewText previewText {.offset = -1, .value = u""};
10449     if (hasPreviewText_) {
10450         previewText.offset = GetPreviewTextStart();
10451         previewText.value = GetPreviewTextValue();
10452     }
10453     changeValueInfo.oldPreviewText = previewText;
10454     changeValueInfo.previewText = previewText;
10455 
10456     changeValueInfo.rangeBefore = TextRange { start, end };
10457     changeValueInfo.rangeAfter = TextRange { start, start };
10458 
10459     changeValueInfo.oldContent = oldContent;
10460     changeValueInfo.value = contentController_->GetTextUtf16Value();
10461     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10462     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10463     callbackOldContent_ = changeValueInfo.oldContent;
10464     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10465     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10466 }
10467 
10468 bool TextFieldPattern::OnWillChangePreSetValue(const std::u16string& newValue)
10469 {
10470     auto host = GetHost();
10471     CHECK_NULL_RETURN(host, true);
10472     auto eventHub = host->GetEventHub<TextFieldEventHub>();
10473     CHECK_NULL_RETURN(eventHub, true);
10474     ChangeValueInfo changeValueInfo;
10475     changeValueInfo.oldContent = contentController_->GetTextUtf16Value();
10476     changeValueInfo.value = newValue;
10477     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10478     changeValueInfo.previewText.value = GetPreviewTextValue();
10479     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10480     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
10481     changeValueInfo.rangeBefore = TextRange { 0, contentController_->GetTextUtf16Value().length() };
10482     changeValueInfo.rangeAfter = TextRange { 0, newValue.length() };
10483     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10484     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10485     callbackOldContent_ = changeValueInfo.oldContent;
10486     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10487     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10488 }
10489 
10490 void TextFieldPattern::RecoverTextValueAndCaret(const std::u16string& oldValue, TextRange caretIndex)
10491 {
10492     contentController_->SetTextValueOnly(oldValue);
10493     selectController_->UpdateHandleIndex(caretIndex.start, caretIndex.end);
10494     if (IsSelected()) {
10495         ProcessOverlay({ .menuIsShow = false });
10496     }
10497 }
10498 
10499 void TextFieldPattern::AddInsertCommand(const std::u16string& insertValue, InputReason reason)
10500 {
10501     auto host = GetHost();
10502     CHECK_NULL_VOID(host);
10503     if (reason != InputReason::PASTE) {
10504         if (!HasFocus()) {
10505             int32_t frameId = host->GetId();
10506             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d on blur, can't insert value", frameId);
10507             int32_t depth = host->GetDepth();
10508             std::string errorType = "textfield on blur, can't insert value";
10509             EventReport::ReportTextFieldErrorEvent(frameId, depth, errorType);
10510             auto currentFocusNode = InputMethodManager::GetInstance()->GetCurFocusNode();
10511             auto curFocusNode = currentFocusNode.Upgrade();
10512             CHECK_NULL_VOID(curFocusNode);
10513             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "curFocusNode:%{public}s, ", curFocusNode->GetTag().c_str());
10514             return;
10515         }
10516         if (!isEdit_ || (reason == InputReason::IME && IsDragging())) {
10517             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
10518                 "textfield %{public}d NOT allow input, isEdit_ = %{public}d, IsDragging = %{public}d", host->GetId(),
10519                 isEdit_, IsDragging());
10520             return;
10521         }
10522     }
10523     if (focusIndex_ != FocuseIndex::TEXT) {
10524         if (insertValue == u" ") {
10525             HandleSpaceEvent();
10526         }
10527         return;
10528     }
10529     if (FinishTextPreviewByPreview(insertValue)) {
10530         return;
10531     }
10532     inputOperations_.emplace(InputOperation::INSERT);
10533     InsertCommandInfo info;
10534     info.insertValue = insertValue;
10535     info.reason = reason;
10536     insertCommands_.emplace(info);
10537     CloseSelectOverlay(true);
10538     ScrollToSafeArea();
10539     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
10540 }
10541 
10542 void TextFieldPattern::AddInputCommand(const InputCommandInfo& inputCommandInfo)
10543 {
10544     auto host = GetHost();
10545     CHECK_NULL_VOID(host);
10546     inputOperations_.emplace(InputOperation::INPUT);
10547     inputCommands_.emplace(inputCommandInfo);
10548     CloseSelectOverlay(true);
10549     ScrollToSafeArea();
10550     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
10551 }
10552 
10553 void TextFieldPattern::ExecuteInputCommand(const InputCommandInfo& info)
10554 {
10555     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10556     CHECK_NULL_VOID(layoutProperty);
10557     auto start = info.deleteRange.start;
10558     auto end = info.deleteRange.end;
10559     auto insertValue = info.insertValue;
10560     auto caretIndex = info.insertOffset;
10561     auto originCaretIndex =
10562             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
10563     if ((info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) && !insertValue.empty()) {
10564         auto isInsert = BeforeIMEInsertValue(insertValue, caretIndex - (end - start));
10565         CHECK_NULL_VOID(isInsert);
10566     }
10567 
10568     ChangeValueInfo changeValueInfo;
10569     changeValueInfo.oldContent = contentController_->GetTextUtf16Value();
10570     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10571     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
10572     changeValueInfo.rangeBefore = TextRange { start, end };
10573 
10574     auto isDelete = true;
10575     if (start != end) {
10576         auto deleteValue = contentController_->GetSelectedValue(start, end);
10577         if (info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) {
10578             isDelete = BeforeIMEDeleteValue(deleteValue, TextDeleteDirection::BACKWARD, end);
10579         }
10580         contentController_->erase(start, end - start);
10581         selectController_->UpdateCaretIndex(start);
10582         if ((info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) && isDelete) {
10583             AfterIMEDeleteValue(deleteValue, TextDeleteDirection::BACKWARD);
10584         }
10585     }
10586 
10587     int32_t insertLength = 0;
10588     if (!insertValue.empty()) {
10589         if (info.insertOffset >= end && isDelete) {
10590             caretIndex = caretIndex - (end - start);
10591         }
10592         auto originLength = contentController_->GetTextUtf16Value().length();
10593         auto hasInsertValue = contentController_->InsertValue(caretIndex, info.insertValue);
10594         insertLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length() - originLength);
10595         caretIndex += insertLength;
10596 
10597         if (layoutProperty->HasMaxLength()) {
10598             CalcCounterAfterFilterInsertValue(originLength, insertValue,
10599                 static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
10600         }
10601         selectController_->UpdateCaretIndex(caretIndex);
10602         UpdateObscure(insertValue, hasInsertValue);
10603         if (info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) {
10604             AfterIMEInsertValue(contentController_->GetInsertValue());
10605         }
10606     }
10607 
10608     changeValueInfo.value = contentController_->GetTextUtf16Value();
10609     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10610     changeValueInfo.previewText.value = GetPreviewTextValue();
10611     changeValueInfo.rangeAfter = TextRange { caretIndex - insertLength, caretIndex };
10612 
10613     bool isWillChange = FireOnWillChange(changeValueInfo);
10614     if (!isWillChange) {
10615         RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
10616         return;
10617     }
10618     UpdateEditingValueToRecord();
10619     TwinklingByFocus();
10620 }
10621 
10622 void TextFieldPattern::ClearTextContent()
10623 {
10624     if (GetIsPreviewText()) {
10625         PreviewTextInfo info = {
10626             .text = u"",
10627             .range = {-1, -1}
10628         };
10629         SetPreviewTextOperation(info);
10630         hasPreviewText_ = false;
10631     }
10632     if (contentController_->IsEmpty()) {
10633         return;
10634     }
10635     showCountBorderStyle_ = false;
10636     InputCommandInfo inputCommandInfo;
10637     inputCommandInfo.deleteRange = { 0, contentController_->GetTextUtf16Value().length() };
10638     inputCommandInfo.insertOffset = 0;
10639     inputCommandInfo.insertValue = u"";
10640     inputCommandInfo.reason = InputReason::CANCEL_BUTTON;
10641     AddInputCommand(inputCommandInfo);
10642 }
10643 
10644 // return: whether the offset is valid, return false if invalid
10645 bool TextFieldPattern::GetOriginCaretPosition(OffsetF& offset) const
10646 {
10647     if (!originCaretPosition_.NonNegative()) {
10648         return false;
10649     }
10650     offset = originCaretPosition_;
10651     return true;
10652 }
10653 
10654 void TextFieldPattern::ResetOriginCaretPosition()
10655 {
10656     originCaretPosition_ = DEFAULT_NEGATIVE_CARET_OFFSET;
10657 }
10658 
10659 // Record current caret position if originCaretPosition_ is invalid
10660 // return: whether the current offset is recorded and valid
10661 bool TextFieldPattern::RecordOriginCaretPosition()
10662 {
10663     if (originCaretPosition_.NonNegative()) {
10664         return false;
10665     }
10666     originCaretPosition_ = selectController_->GetCaretRect().GetOffset();
10667     return originCaretPosition_.NonNegative();
10668 }
10669 
10670 void TextFieldPattern::SetIsEnableSubWindowMenu()
10671 {
10672     if (selectOverlay_) {
10673         auto enable = !IsNeedProcessAutoFill() || !CheckAutoFill();
10674         selectOverlay_->SetIsHostNodeEnableSubWindowMenu(enable);
10675         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetIsEnableSubWindowMenu enable=%{public}d", enable);
10676     }
10677 }
10678 
10679 void TextFieldPattern::InitCancelButtonMouseEvent()
10680 {
10681     CHECK_NULL_VOID(cleanNodeResponseArea_);
10682     auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
10683     CHECK_NULL_VOID(cleanNodeResponseArea);
10684     auto stackNode = cleanNodeResponseArea->GetFrameNode();
10685     CHECK_NULL_VOID(stackNode);
10686     auto imageTouchHub = stackNode->GetOrCreateGestureEventHub();
10687     CHECK_NULL_VOID(imageTouchHub);
10688     auto imageInputHub = stackNode->GetOrCreateInputEventHub();
10689     CHECK_NULL_VOID(imageInputHub);
10690     auto imageHoverTask = [weak = WeakClaim(this),
10691         cleanNodeResponseAreaWeak = WeakPtr<TextInputResponseArea>(cleanNodeResponseArea_)](bool isHover) {
10692             auto cleanNodeResponseArea = cleanNodeResponseAreaWeak.Upgrade();
10693             CHECK_NULL_VOID(cleanNodeResponseArea);
10694             auto pattern = weak.Upgrade();
10695             if (pattern) {
10696                 pattern->OnHover(isHover);
10697                 pattern->HandleButtonMouseEvent(cleanNodeResponseArea, isHover);
10698             }
10699     };
10700     imageHoverEvent_ = MakeRefPtr<InputEvent>(std::move(imageHoverTask));
10701     imageInputHub->AddOnHoverEvent(imageHoverEvent_);
10702 
10703     auto imageTouchTask = [weak = WeakClaim(this), cleanNodeResponseAreaWeak =
10704         WeakPtr<TextInputResponseArea>(cleanNodeResponseArea_)](const TouchEventInfo& info) {
10705             auto cleanNodeResponseArea = cleanNodeResponseAreaWeak.Upgrade();
10706             CHECK_NULL_VOID(cleanNodeResponseArea);
10707             auto pattern = weak.Upgrade();
10708             CHECK_NULL_VOID(pattern);
10709             auto touchType = info.GetTouches().front().GetTouchType();
10710             if (touchType == TouchType::DOWN) {
10711                 pattern->HandleCancelButtonTouchDown(cleanNodeResponseArea);
10712             }
10713             if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
10714                 pattern->HandleCancelButtonTouchUp();
10715             }
10716     };
10717 
10718     imageTouchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(imageTouchTask));
10719     imageTouchHub->AddTouchEvent(imageTouchEvent_);
10720 }
10721 
10722 void TextFieldPattern::InitPasswordButtonMouseEvent()
10723 {
10724     CHECK_NULL_VOID(responseArea_);
10725     auto passwordResponseArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
10726     CHECK_NULL_VOID(passwordResponseArea);
10727     auto stackNode = passwordResponseArea->GetFrameNode();
10728     CHECK_NULL_VOID(stackNode);
10729     auto imageTouchHub = stackNode->GetOrCreateGestureEventHub();
10730     CHECK_NULL_VOID(imageTouchHub);
10731     auto imageInputHub = stackNode->GetOrCreateInputEventHub();
10732     CHECK_NULL_VOID(imageInputHub);
10733     auto imageHoverTask =
10734         [weak = WeakClaim(this), responseAreaWeak = WeakPtr<TextInputResponseArea>(responseArea_)](bool isHover) {
10735             auto responseArea = responseAreaWeak.Upgrade();
10736             CHECK_NULL_VOID(responseArea);
10737             auto pattern = weak.Upgrade();
10738             if (pattern) {
10739                 pattern->OnHover(isHover);
10740                 pattern->HandleButtonMouseEvent(responseArea, isHover);
10741             }
10742     };
10743     imageHoverEvent_ = MakeRefPtr<InputEvent>(std::move(imageHoverTask));
10744     imageInputHub->AddOnHoverEvent(imageHoverEvent_);
10745 
10746     auto imageTouchTask = [weak = WeakClaim(this), responseAreaWeak = WeakPtr<TextInputResponseArea>(responseArea_)]
10747         (const TouchEventInfo& info) {
10748             auto responseArea = responseAreaWeak.Upgrade();
10749             CHECK_NULL_VOID(responseArea);
10750             auto pattern = weak.Upgrade();
10751             CHECK_NULL_VOID(pattern);
10752             auto touchType = info.GetTouches().front().GetTouchType();
10753             if (touchType == TouchType::DOWN) {
10754                 pattern->HandleCancelButtonTouchDown(responseArea);
10755             }
10756             if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
10757                 pattern->HandleCancelButtonTouchUp();
10758             }
10759     };
10760     imageTouchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(imageTouchTask));
10761     imageTouchHub->AddTouchEvent(imageTouchEvent_);
10762 }
10763 
10764 void TextFieldPattern::HandleCancelButtonTouchDown(const RefPtr<TextInputResponseArea>& responseArea)
10765 {
10766     auto host = GetHost();
10767     CHECK_NULL_VOID(host);
10768     RoundRect mouseRect;
10769     CHECK_NULL_VOID(responseArea);
10770     responseArea->CreateIconRect(mouseRect, false);
10771     float cornerRadius = mouseRect.GetRect().Width() / 2;
10772     mouseRect.SetCornerRadius(cornerRadius);
10773     auto textFieldTheme = GetTheme();
10774     CHECK_NULL_VOID(textFieldTheme);
10775     auto touchColor = textFieldTheme->GetPressColor();
10776     std::vector<RoundRect> roundRectVector;
10777     roundRectVector.push_back(mouseRect);
10778     CHECK_NULL_VOID(textFieldOverlayModifier_);
10779     textFieldOverlayModifier_->SetHoverColorAndRects(roundRectVector, touchColor.GetValue());
10780     cancelButtonTouched_ = true;
10781     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
10782 }
10783 
10784 void TextFieldPattern::HandleCancelButtonTouchUp()
10785 {
10786     auto host = GetHost();
10787     CHECK_NULL_VOID(host);
10788     CHECK_NULL_VOID(textFieldOverlayModifier_);
10789     textFieldOverlayModifier_->ClearHoverColorAndRects();
10790     cancelButtonTouched_ = false;
10791     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
10792 }
10793 
10794 void TextFieldPattern::HandleButtonMouseEvent(const RefPtr<TextInputResponseArea>& responseArea, bool isHover)
10795 {
10796     auto host = GetHost();
10797     CHECK_NULL_VOID(host);
10798     CHECK_NULL_VOID(textFieldOverlayModifier_);
10799     if (isHover) {
10800         RoundRect mouseRect;
10801         CHECK_NULL_VOID(responseArea);
10802         responseArea->CreateIconRect(mouseRect, false);
10803         float cornerRadius = mouseRect.GetRect().Width() / 2;
10804         mouseRect.SetCornerRadius(cornerRadius);
10805         auto textFieldTheme = GetTheme();
10806         CHECK_NULL_VOID(textFieldTheme);
10807         auto touchColor = textFieldTheme->GetHoverColor();
10808         std::vector<RoundRect> roundRectVector;
10809         roundRectVector.push_back(mouseRect);
10810         textFieldOverlayModifier_->SetHoverColorAndRects(roundRectVector, touchColor.GetValue());
10811         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
10812     } else {
10813         textFieldOverlayModifier_->ClearHoverColorAndRects();
10814         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
10815     }
10816 }
10817 
10818 double TextFieldPattern::GetPercentReferenceWidth() const
10819 {
10820     auto host = GetHost();
10821     if (host && host->GetGeometryNode() && host->GetGeometryNode()->GetParentLayoutConstraint().has_value()) {
10822         return host->GetGeometryNode()->GetParentLayoutConstraint()->percentReference.Width();
10823     }
10824     return 0.0f;
10825 }
10826 
10827 void TextFieldPattern::NotifyKeyboardClosedByUser()
10828 {
10829     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "NotifyKeyboardClosedByUser");
10830     isKeyboardClosedByUser_ = true;
10831     FocusHub::LostFocusToViewRoot();
10832     isKeyboardClosedByUser_ = false;
10833 }
10834 
10835 void TextFieldPattern::NotifyKeyboardClosed()
10836 {
10837     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "NotifyKeyboardClosed");
10838     CHECK_NULL_VOID(IsStopEditWhenCloseKeyboard()); // false when specified product
10839     if (HasFocus() && !(customKeyboard_ || customKeyboardBuilder_)) {
10840         FocusHub::LostFocusToViewRoot();
10841     }
10842 }
10843 
10844 void TextFieldPattern::AddDragFrameNodeToManager(const RefPtr<FrameNode>& frameNode)
10845 {
10846     auto context = PipelineContext::GetCurrentContextSafelyWithCheck();
10847     CHECK_NULL_VOID(context);
10848     auto dragDropManager = context->GetDragDropManager();
10849     CHECK_NULL_VOID(dragDropManager);
10850     dragDropManager->AddDragFrameNode(frameNode->GetId(), AceType::WeakClaim(AceType::RawPtr(frameNode)));
10851 }
10852 
10853 void TextFieldPattern::RemoveDragFrameNodeFromManager(const RefPtr<FrameNode>& frameNode)
10854 {
10855     auto context = PipelineContext::GetCurrentContextSafelyWithCheck();
10856     CHECK_NULL_VOID(context);
10857     auto dragDropManager = context->GetDragDropManager();
10858     CHECK_NULL_VOID(dragDropManager);
10859     dragDropManager->RemoveDragFrameNode(frameNode->GetId());
10860 }
10861 
10862 bool TextFieldPattern::BetweenSelectedPosition(const Offset& globalOffset)
10863 {
10864     if (!IsSelected()) {
10865         return false;
10866     }
10867     auto localOffset = ConvertGlobalToLocalOffset(globalOffset);
10868     auto offsetX = IsTextArea() ? contentRect_.GetX() : textRect_.GetX();
10869     auto offsetY = IsTextArea() ? textRect_.GetY() : contentRect_.GetY();
10870     Offset offset = localOffset - Offset(offsetX, offsetY);
10871     for (const auto& rect : selectController_->GetSelectedRects()) {
10872         bool isInRange = rect.IsInRegion({ offset.GetX(), offset.GetY() });
10873         if (isInRange) {
10874             return true;
10875         }
10876     }
10877     return false;
10878 }
10879 
10880 void TextFieldPattern::SetUnitNode(const RefPtr<NG::UINode>& unitNode)
10881 {
10882     if (unitNode_ && responseArea_) {
10883         // clear old node
10884         auto unitResponseArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
10885         CHECK_NULL_VOID(unitResponseArea);
10886         unitResponseArea->ClearArea();
10887         responseArea_ = nullptr;
10888     }
10889     unitNode_ = unitNode;
10890 }
10891 
10892 void TextFieldPattern::SetCustomKeyboard(const std::function<void()>&& keyboardBuilder)
10893 {
10894     if (customKeyboardBuilder_ && isCustomKeyboardAttached_ && !keyboardBuilder) {
10895         // close customKeyboard and request system keyboard
10896         CloseCustomKeyboard();
10897         customKeyboardBuilder_ = keyboardBuilder; // refresh current keyboard
10898         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
10899         StartTwinkling();
10900         return;
10901     }
10902     if (!customKeyboardBuilder_ && keyboardBuilder) {
10903         // close system keyboard and request custom keyboard
10904 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
10905         if (imeShown_) {
10906             CloseKeyboard(true);
10907             customKeyboardBuilder_ = keyboardBuilder; // refresh current keyboard
10908             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
10909             StartTwinkling();
10910             return;
10911         }
10912 #endif
10913     }
10914     customKeyboardBuilder_ = keyboardBuilder;
10915 }
10916 
10917 void TextFieldPattern::SetCustomKeyboardWithNode(const RefPtr<UINode>& keyboardBuilder)
10918 {
10919     if (customKeyboard_ && isCustomKeyboardAttached_ && !keyboardBuilder) {
10920         // close customKeyboard and request system keyboard
10921         CloseCustomKeyboard();
10922         customKeyboard_ = keyboardBuilder; // refresh current keyboard
10923         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
10924         StartTwinkling();
10925         return;
10926     }
10927     if (!customKeyboard_ && keyboardBuilder) {
10928         // close system keyboard and request custom keyboard
10929 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
10930         if (imeShown_) {
10931             CloseKeyboard(true);
10932             customKeyboard_ = keyboardBuilder; // refresh current keyboard
10933             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
10934             StartTwinkling();
10935             return;
10936         }
10937 #endif
10938     }
10939     customKeyboard_ = keyboardBuilder;
10940 }
10941 
10942 bool TextFieldPattern::IsStopEditWhenCloseKeyboard()
10943 {
10944     auto host = GetHost();
10945     CHECK_NULL_RETURN(host, true);
10946     auto context = host->GetContext();
10947     CHECK_NULL_RETURN(context, true);
10948     return !(context->GetIsFocusActive() && independentControlKeyboard_);
10949 }
10950 
10951 } // namespace OHOS::Ace::NG
10952