• 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 #define NAPI_VERSION 8
17 
18 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
19 
20 #include <algorithm>
21 #include <atomic>
22 #include <cstdint>
23 #include <optional>
24 #include <ratio>
25 #include <regex>
26 #include <string>
27 #include <utility>
28 #include "base/geometry/dimension.h"
29 #include "base/log/event_report.h"
30 #include "base/memory/type_info_base.h"
31 #include "base/utils/multi_thread.h"
32 #include "base/utils/utf_helper.h"
33 #include "core/common/ime/constant.h"
34 #include "core/components/common/properties/text_style.h"
35 #include "core/components_ng/pattern/select/select_pattern.h"
36 #include "core/components_ng/pattern/text/text_layout_property.h"
37 #include "core/components_ng/pattern/text_field/text_component_decorator.h"
38 #include "core/components_ng/pattern/text_field/text_field_layout_property.h"
39 #include "core/components_ng/property/layout_constraint.h"
40 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
41 
42 #include "base/i18n/localization.h"
43 #include "base/log/dump_log.h"
44 #include "base/log/log_wrapper.h"
45 #include "base/memory/referenced.h"
46 #include "base/utils/string_utils.h"
47 #include "base/utils/utils.h"
48 #include "core/common/clipboard/clipboard_proxy.h"
49 #include "core/common/container_scope.h"
50 #include "core/common/font_manager.h"
51 #include "core/common/ime/input_method_manager.h"
52 #include "core/common/ime/text_edit_controller.h"
53 #include "core/common/ime/text_input_client.h"
54 #include "core/common/ime/text_input_connection.h"
55 #include "core/common/ime/text_input_formatter.h"
56 #include "core/common/ime/text_input_type.h"
57 #include "core/common/ime/text_selection.h"
58 #include "core/common/recorder/event_recorder.h"
59 #include "core/common/recorder/node_data_cache.h"
60 #include "core/common/stylus/stylus_detector_mgr.h"
61 #include "core/common/vibrator/vibrator_utils.h"
62 #include "core/components/common/layout/constants.h"
63 #include "core/components/text_field/textfield_theme.h"
64 #include "core/components_ng/base/inspector_filter.h"
65 #include "core/components_ng/event/focus_hub.h"
66 #include "core/components_ng/pattern/stage/page_pattern.h"
67 #include "core/components_ng/pattern/text/span/span_string.h"
68 #include "core/components_ng/pattern/text/text_pattern.h"
69 #include "core/components_ng/pattern/text_field/text_field_manager.h"
70 #include "core/components_ng/pattern/text_field/text_field_paint_property.h"
71 #include "core/text/text_emoji_processor.h"
72 #ifndef ACE_UNITTEST
73 #ifdef ENABLE_STANDARD_INPUT
74 #include "parameters.h"
75 #include "adapter/ohos/entrance/ace_container.h"
76 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
77 #endif
78 #endif
79 #include "core/common/udmf/udmf_client.h"
80 
81 #ifdef WINDOW_SCENE_SUPPORTED
82 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
83 #endif
84 namespace OHOS::Ace::NG {
85 namespace {
86 
87 const BorderRadiusProperty ZERO_BORDER_RADIUS_PROPERTY(0.0_vp);
88 // need to be moved to TextFieldTheme
89 constexpr Dimension BORDER_DEFAULT_WIDTH = 0.0_vp;
90 constexpr Dimension TYPING_UNDERLINE_WIDTH = 2.0_px;
91 constexpr Dimension OVER_COUNT_BORDER_WIDTH = 1.0_vp;
92 constexpr Dimension INLINE_BORDER_WIDTH = 2.0_vp;
93 constexpr Dimension ERROR_UNDERLINE_WIDTH = 2.0_px;
94 constexpr Dimension UNDERLINE_WIDTH = 1.0_px;
95 constexpr uint32_t INLINE_DEFAULT_VIEW_MAXLINE = 3;
96 constexpr Dimension SCROLL_BAR_MIN_HEIGHT = 4.0_vp;
97 constexpr float MINFONTSCALE = 0.85f;
98 constexpr float MAXFONTSCALE = 3.20f;
99 #if defined(ENABLE_STANDARD_INPUT)
100 constexpr Dimension AVOID_OFFSET = 24.0_vp;
101 #endif
102 constexpr Dimension DEFAULT_FONT = Dimension(16, DimensionUnit::FP);
103 constexpr int32_t ILLEGAL_VALUE = 0;
104 constexpr double VELOCITY = -1000;
105 constexpr double MASS = 1.0;
106 constexpr double STIFFNESS = 428.0;
107 constexpr double DAMPING = 10.0;
108 constexpr uint32_t TWINKLING_INTERVAL_MS = 500;
109 constexpr uint32_t RECORD_MAX_LENGTH = 20;
110 constexpr uint32_t OBSCURE_SHOW_TICKS = 1;
111 constexpr int32_t FIND_TEXT_ZERO_INDEX = 1;
112 constexpr char16_t OBSCURING_CHARACTER = u'•';
113 constexpr char16_t OBSCURING_CHARACTER_FOR_AR = u'*';
114 const std::string NEWLINE = "\n";
115 const std::wstring WIDE_NEWLINE = StringUtils::ToWstring(NEWLINE);
116 const std::string INSPECTOR_PREFIX = "__SearchField__";
117 const std::string ERRORNODE_PREFIX = "ErrorNodeField__";
118 const OffsetF DEFAULT_NEGATIVE_CARET_OFFSET {-1.0f, -1.0f};
119 constexpr Dimension FLOATING_CARET_SHOW_ORIGIN_CARET_DISTANCE = 10.0_vp;
120 #if defined(ENABLE_STANDARD_INPUT)
121 constexpr int32_t AUTO_FILL_CANCEL = 2;
122 constexpr size_t MAX_PLACEHOLDER_SIZE = 255;
123 constexpr size_t MAX_ABILITY_NAME_SIZE = 127;
124 #endif
125 
126 // need to be moved to formatter
127 const std::string DIGIT_WHITE_LIST = "[0-9]";
128 const std::string PHONE_WHITE_LIST = "[\\d\\-\\+\\*\\#]+";
129 const std::string EMAIL_WHITE_LIST = "[\\w.\\@]";
130 const std::string URL_WHITE_LIST = "[a-zA-z]+://[^\\s]*";
131 const std::string SHOW_PASSWORD_SVG = "SYS_SHOW_PASSWORD_SVG";
132 const std::string HIDE_PASSWORD_SVG = "SYS_HIDE_PASSWORD_SVG";
133 const std::string AUTO_FILL_PARAMS_USERNAME = "com.autofill.params.userName";
134 const std::string AUTO_FILL_PARAMS_NEWPASSWORD = "com.autofill.params.newPassword";
135 constexpr int32_t DEFAULT_MODE = -1;
136 constexpr int32_t PREVIEW_TEXT_RANGE_DEFAULT = -1;
137 const std::string PREVIEW_STYLE_NORMAL = "normal";
138 const std::string PREVIEW_STYLE_UNDERLINE = "underline";
139 
140 constexpr int32_t PREVIEW_NO_ERROR = 0;
141 constexpr int32_t PREVIEW_NULL_POINTER = 1;
142 constexpr int32_t DEFAULT_MIN_LINES = 1;
143 constexpr int32_t PREVIEW_BAD_PARAMETERS = -1;
144 constexpr double MINIMAL_OFFSET = 0.01f;
145 constexpr int32_t KEYBOARD_DEFAULT_API = 9;
146 constexpr float RICH_DEFAULT_SHADOW_COLOR = 0x33000000;
147 constexpr float RICH_DEFAULT_ELEVATION = 120.0f;
148 constexpr float TIME_UNIT = 1000.0f;
149 constexpr float MAX_DRAG_SCROLL_SPEED = 2400.0f;
150 constexpr Dimension AUTO_SCROLL_HOT_ZONE_HEIGHT = 58.0_vp;
151 constexpr Dimension AUTO_SCROLL_HOT_ZONE_WIDTH = 26.0_vp;
152 constexpr float AUTO_SCROLL_HOT_AREA_LONGPRESS_DURATION = 80.0f;
153 constexpr Dimension AUTO_SCROLL_HOT_AREA_LONGPRESS_DISTANCE = 5.0_vp;
154 constexpr Dimension MOUSE_SCROLL_BAR_REGION_WIDTH = 8.0_vp;
155 constexpr int32_t HOVER_ANIMATION_DURATION = 250;
156 const RefPtr<Curve> MOVE_MAGNIFIER_CURVE =
157     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 228.0f, 30.0f);
158 constexpr int32_t LAND_DURATION = 100;
159 constexpr int32_t ENTER_OFFSET = 1;
160 
161 static std::unordered_map<AceAutoFillType, TextInputType> keyBoardMap_ = {
162     { AceAutoFillType::ACE_PASSWORD, TextInputType::VISIBLE_PASSWORD},
163     { AceAutoFillType::ACE_USER_NAME, TextInputType::USER_NAME },
164     { AceAutoFillType::ACE_NEW_PASSWORD, TextInputType::NEW_PASSWORD },
165     { AceAutoFillType::ACE_FULL_STREET_ADDRESS, TextInputType::TEXT },
166     { AceAutoFillType::ACE_HOUSE_NUMBER, TextInputType::TEXT },
167     { AceAutoFillType::ACE_DISTRICT_ADDRESS, TextInputType::TEXT },
168     { AceAutoFillType::ACE_CITY_ADDRESS, TextInputType::TEXT },
169     { AceAutoFillType::ACE_PROVINCE_ADDRESS, TextInputType::TEXT },
170     { AceAutoFillType::ACE_COUNTRY_ADDRESS, TextInputType::TEXT },
171     { AceAutoFillType::ACE_PERSON_FULL_NAME, TextInputType::TEXT },
172     { AceAutoFillType::ACE_PERSON_LAST_NAME, TextInputType::TEXT },
173     { AceAutoFillType::ACE_PERSON_FIRST_NAME, TextInputType::TEXT },
174     { AceAutoFillType::ACE_PHONE_NUMBER, TextInputType::PHONE },
175     { AceAutoFillType::ACE_PHONE_COUNTRY_CODE, TextInputType::PHONE },
176     { AceAutoFillType::ACE_FULL_PHONE_NUMBER, TextInputType::PHONE },
177     { AceAutoFillType::ACE_EMAIL_ADDRESS, TextInputType::EMAIL_ADDRESS },
178     { AceAutoFillType::ACE_BANK_CARD_NUMBER, TextInputType::NUMBER },
179     { AceAutoFillType::ACE_ID_CARD_NUMBER, TextInputType::NUMBER },
180     { AceAutoFillType::ACE_PRECISE_TIME, TextInputType::NUMBER },
181     { AceAutoFillType::ACE_HOUR_AND_MINUTE, TextInputType::NUMBER },
182     { AceAutoFillType::ACE_DATE, TextInputType::NUMBER },
183     { AceAutoFillType::ACE_MONTH, TextInputType::NUMBER },
184     { AceAutoFillType::ACE_YEAR, TextInputType::NUMBER },
185     { AceAutoFillType::ACE_NICKNAME, TextInputType::TEXT },
186     { AceAutoFillType::ACE_DETAIL_INFO_WITHOUT_STREET, TextInputType::TEXT },
187     { AceAutoFillType::ACE_FORMAT_ADDRESS, TextInputType::TEXT },
188     { AceAutoFillType::ACE_PASSPORT_NUMBER, TextInputType::TEXT },
189     { AceAutoFillType::ACE_VALIDITY, TextInputType::TEXT },
190     { AceAutoFillType::ACE_ISSUE_AT, TextInputType::TEXT },
191     { AceAutoFillType::ACE_ORGANIZATION, TextInputType::TEXT },
192     { AceAutoFillType::ACE_TAX_ID, TextInputType::TEXT },
193     { AceAutoFillType::ACE_ADDRESS_CITY_AND_STATE, TextInputType::TEXT },
194     { AceAutoFillType::ACE_FLIGHT_NUMBER, TextInputType::TEXT },
195     { AceAutoFillType::ACE_LICENSE_NUMBER, TextInputType::TEXT },
196     { AceAutoFillType::ACE_LICENSE_FILE_NUMBER, TextInputType::TEXT },
197     { AceAutoFillType::ACE_LICENSE_PLATE, TextInputType::TEXT },
198     { AceAutoFillType::ACE_ENGINE_NUMBER, TextInputType::TEXT },
199     { AceAutoFillType::ACE_LICENSE_CHASSIS_NUMBER, TextInputType::TEXT }};
200 
201 static std::unordered_map<TextContentType, std::pair<AceAutoFillType, std::string>> contentTypeMap_ = {
202     {TextContentType::VISIBLE_PASSWORD,
203         std::make_pair(AceAutoFillType::ACE_PASSWORD, "TextContentType.VISIBLE_PASSWORD")},
204     {TextContentType::USER_NAME, std::make_pair(AceAutoFillType::ACE_USER_NAME, "TextContentType.USER_NAME")},
205     {TextContentType::NEW_PASSWORD, std::make_pair(AceAutoFillType::ACE_NEW_PASSWORD, "TextContentType.NEW_PASSWORD")},
206     {TextContentType::FULL_STREET_ADDRESS,
207         std::make_pair(AceAutoFillType::ACE_FULL_STREET_ADDRESS, "TextContentType.FULL_STREET_ADDRESS")},
208     {TextContentType::HOUSE_NUMBER, std::make_pair(AceAutoFillType::ACE_HOUSE_NUMBER, "TextContentType.HOUSE_NUMBER")},
209     {TextContentType::DISTRICT_ADDRESS,
210         std::make_pair(AceAutoFillType::ACE_DISTRICT_ADDRESS, "TextContentType.DISTRICT_ADDRESS")},
211     {TextContentType::CITY_ADDRESS, std::make_pair(AceAutoFillType::ACE_CITY_ADDRESS, "TextContentType.CITY_ADDRESS")},
212     {TextContentType::PROVINCE_ADDRESS,
213         std::make_pair(AceAutoFillType::ACE_PROVINCE_ADDRESS, "TextContentType.PROVINCE_ADDRESS")},
214     {TextContentType::COUNTRY_ADDRESS,
215         std::make_pair(AceAutoFillType::ACE_COUNTRY_ADDRESS, "TextContentType.COUNTRY_ADDRESS")},
216     {TextContentType::PERSON_FULL_NAME,
217         std::make_pair(AceAutoFillType::ACE_PERSON_FULL_NAME, "TextContentType.PERSON_FULL_NAME")},
218     {TextContentType::PERSON_LAST_NAME,
219         std::make_pair(AceAutoFillType::ACE_PERSON_LAST_NAME, "TextContentType.PERSON_LAST_NAME")},
220     {TextContentType::PERSON_FIRST_NAME,
221         std::make_pair(AceAutoFillType::ACE_PERSON_FIRST_NAME, "TextContentType.PERSON_FIRST_NAME")},
222     {TextContentType::PHONE_NUMBER, std::make_pair(AceAutoFillType::ACE_PHONE_NUMBER, "TextContentType.PHONE_NUMBER")},
223     {TextContentType::PHONE_COUNTRY_CODE,
224         std::make_pair(AceAutoFillType::ACE_PHONE_COUNTRY_CODE, "TextContentType.PHONE_COUNTRY_CODE")},
225     {TextContentType::FULL_PHONE_NUMBER,
226         std::make_pair(AceAutoFillType::ACE_FULL_PHONE_NUMBER, "TextContentType.FULL_PHONE_NUMBER")},
227     {TextContentType::EMAIL_ADDRESS,
228         std::make_pair(AceAutoFillType::ACE_EMAIL_ADDRESS, "TextContentType.EMAIL_ADDRESS")},
229     {TextContentType::BANK_CARD_NUMBER,
230         std::make_pair(AceAutoFillType::ACE_BANK_CARD_NUMBER, "TextContentType.BANK_CARD_NUMBER")},
231     {TextContentType::ID_CARD_NUMBER,
232         std::make_pair(AceAutoFillType::ACE_ID_CARD_NUMBER, "TextContentType.ID_CARD_NUMBER")},
233     {TextContentType::PRECISE_TIME, std::make_pair(AceAutoFillType::ACE_PRECISE_TIME, "TextContentType.PRECISE_TIME")},
234     {TextContentType::HOUR_AND_MINUTE,
235         std::make_pair(AceAutoFillType::ACE_HOUR_AND_MINUTE, "TextContentType.HOUR_AND_MINUTE")},
236     {TextContentType::DATE, std::make_pair(AceAutoFillType::ACE_DATE, "TextContentType.DATE")},
237     {TextContentType::MONTH, std::make_pair(AceAutoFillType::ACE_MONTH, "TextContentType.MONTH")},
238     {TextContentType::YEAR, std::make_pair(AceAutoFillType::ACE_YEAR, "TextContentType.YEAR")},
239     {TextContentType::NICKNAME, std::make_pair(AceAutoFillType::ACE_NICKNAME, "TextContentType.NICKNAME")},
240     {TextContentType::DETAIL_INFO_WITHOUT_STREET,
241         std::make_pair(AceAutoFillType::ACE_DETAIL_INFO_WITHOUT_STREET, "TextContentType.DETAIL_INFO_WITHOUT_STREET")},
242     {TextContentType::FORMAT_ADDRESS,
243         std::make_pair(AceAutoFillType::ACE_FORMAT_ADDRESS, "TextContentType.FORMAT_ADDRESS")},
244     {TextContentType::PASSPORT_NUMBER,
245         std::make_pair(AceAutoFillType::ACE_PASSPORT_NUMBER, "TextContentType.PASSPORT_NUMBER")},
246     {TextContentType::VALIDITY,
247         std::make_pair(AceAutoFillType::ACE_VALIDITY, "TextContentType.VALIDITY")},
248     {TextContentType::ISSUE_AT,
249         std::make_pair(AceAutoFillType::ACE_ISSUE_AT, "TextContentType.ISSUE_AT")},
250     {TextContentType::ORGANIZATION,
251         std::make_pair(AceAutoFillType::ACE_ORGANIZATION, "TextContentType.ORGANIZATION")},
252     {TextContentType::TAX_ID,
253         std::make_pair(AceAutoFillType::ACE_TAX_ID, "TextContentType.TAX_ID")},
254     {TextContentType::ADDRESS_CITY_AND_STATE,
255         std::make_pair(AceAutoFillType::ACE_ADDRESS_CITY_AND_STATE, "TextContentType.ADDRESS_CITY_AND_STATE")},
256     {TextContentType::FLIGHT_NUMBER,
257         std::make_pair(AceAutoFillType::ACE_FLIGHT_NUMBER, "TextContentType.FLIGHT_NUMBER")},
258     {TextContentType::LICENSE_NUMBER,
259         std::make_pair(AceAutoFillType::ACE_LICENSE_NUMBER, "TextContentType.LICENSE_NUMBER")},
260     {TextContentType::LICENSE_FILE_NUMBER,
261         std::make_pair(AceAutoFillType::ACE_LICENSE_FILE_NUMBER, "TextContentType.LICENSE_FILE_NUMBER")},
262     {TextContentType::LICENSE_PLATE,
263         std::make_pair(AceAutoFillType::ACE_LICENSE_PLATE, "TextContentType.LICENSE_PLATE")},
264     {TextContentType::ENGINE_NUMBER,
265         std::make_pair(AceAutoFillType::ACE_ENGINE_NUMBER, "TextContentType.ENGINE_NUMBER")},
266     {TextContentType::LICENSE_CHASSIS_NUMBER,
267         std::make_pair(AceAutoFillType::ACE_LICENSE_CHASSIS_NUMBER, "TextContentType.LICENSE_CHASSIS_NUMBER")},
268     {TextContentType::UNSPECIFIED, std::make_pair(AceAutoFillType::ACE_UNSPECIFIED, "TextContentType.UNSPECIFIED")}};
269 
SwapIfLarger(int32_t & a,int32_t & b)270 void SwapIfLarger(int32_t& a, int32_t& b)
271 {
272     if (a > b) {
273         std::swap(a, b);
274     }
275 }
276 
ConvertFontFamily(const std::vector<std::string> & fontFamily)277 std::string ConvertFontFamily(const std::vector<std::string>& fontFamily)
278 {
279     std::string result;
280     for (const auto& item : fontFamily) {
281         result += item;
282         result += ",";
283     }
284     result = result.substr(0, static_cast<int32_t>(result.length()) - 1);
285     return result;
286 }
287 
288 } // namespace
289 
OnAttachContext(PipelineContext * context)290 void TextFieldPattern::OnAttachContext(PipelineContext* context)
291 {
292     CHECK_NULL_VOID(context);
293     SetInstanceId(context->GetInstanceId());
294 }
295 
OnDetachContext(PipelineContext * context)296 void TextFieldPattern::OnDetachContext(PipelineContext* context)
297 {
298     SetInstanceId(INSTANCE_ID_UNDEFINED);
299 }
300 
CreateNodePaintMethod()301 RefPtr<NodePaintMethod> TextFieldPattern::CreateNodePaintMethod()
302 {
303     if (!textFieldContentModifier_) {
304         textFieldContentModifier_ = AceType::MakeRefPtr<TextFieldContentModifier>(WeakClaim(this));
305     }
306     auto textFieldOverlayModifier = AceType::DynamicCast<TextFieldOverlayModifier>(GetScrollBarOverlayModifier());
307     if (!textFieldOverlayModifier) {
308         textFieldOverlayModifier_ =
309             AceType::MakeRefPtr<TextFieldOverlayModifier>(WeakClaim(this), GetScrollEdgeEffect());
310         SetScrollBarOverlayModifier(textFieldOverlayModifier_);
311     }
312     if (!textFieldForegroundModifier_) {
313         textFieldForegroundModifier_ = AceType::MakeRefPtr<TextFieldForegroundModifier>(WeakClaim(this));
314     }
315     if (isCustomFont_) {
316         textFieldContentModifier_->SetIsCustomFont(true);
317     }
318     auto paint = AceType::MakeRefPtr<TextFieldPaintMethod>(
319         WeakClaim(this), textFieldOverlayModifier_, textFieldContentModifier_, textFieldForegroundModifier_);
320     auto scrollBar = GetScrollBar();
321     if (scrollBar) {
322         paint->SetScrollBar(scrollBar);
323         if (scrollBar->NeedPaint()) {
324             textFieldOverlayModifier_->SetRect(scrollBar->GetActiveRect());
325         } else if (!HasFocus() && NeedSetScrollRect()) {
326             auto scrollRect = scrollBar->GetActiveRect();
327             CalcScrollRect(scrollRect);
328             textFieldOverlayModifier_->SetRect(scrollRect);
329             textFieldOverlayModifier_->SetOpacity(0);
330         }
331     }
332     CalculateBoundsRect();
333     return paint;
334 }
335 
NeedSetScrollRect()336 bool TextFieldPattern::NeedSetScrollRect()
337 {
338     auto textFieldLayoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
339     CHECK_NULL_RETURN(textFieldLayoutProperty, false);
340     bool needSetScrollRect = true;
341     if (!IsNormalInlineState() && textFieldLayoutProperty->HasOverflowMode() &&
342         lastOverflowMode_ != textFieldLayoutProperty->GetOverflowMode().value()) {
343         lastOverflowMode_ = textFieldLayoutProperty->GetOverflowMode().value();
344         needSetScrollRect = false;
345     }
346     if (!IsNormalInlineState() && textFieldLayoutProperty->HasTextOverflow() &&
347         lastTextOverflow_ != textFieldLayoutProperty->GetTextOverflow().value()) {
348         lastTextOverflow_ = textFieldLayoutProperty->GetTextOverflow().value();
349         needSetScrollRect = false;
350     }
351     if (IsNormalInlineState() && textFieldLayoutProperty->HasOverflowMode()) {
352         needSetScrollRect = false;
353     }
354     return needSetScrollRect;
355 }
356 
CalculateBoundsRect()357 void TextFieldPattern::CalculateBoundsRect()
358 {
359     auto host = GetHost();
360     CHECK_NULL_VOID(host);
361     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
362     CHECK_NULL_VOID(layoutProperty);
363 
364     auto geometryNode = host->GetGeometryNode();
365     auto frameOffset = geometryNode->GetFrameOffset();
366     auto frameSize = geometryNode->GetFrameSize();
367     bool isShowCount = IsShowCount() && !IsTextArea();
368     bool isShowError = layoutProperty->GetShowErrorTextValue(false) && errorDecorator_;
369     if (isShowCount && isShowError) {
370         auto textWidth = std::max(errorDecorator_ ? errorDecorator_->GetContentWidth() : 0.0f, frameSize.Width());
371         auto errorHeight = errorDecorator_? errorDecorator_->GetBoundHeight() : 0.0f;
372         auto countHeight = counterDecorator_? counterDecorator_->GetBoundHeight() : 0.0f;
373         auto bottomHeight = std::max(errorHeight, countHeight);
374         RectF boundsRect(0.0f, 0.0f, textWidth, bottomHeight + frameSize.Height());
375         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
376         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
377     } else if (isShowCount) {
378         auto countHeight = counterDecorator_? counterDecorator_->GetBoundHeight() : 0.0f;
379         RectF boundsRect(0.0f, 0.0f, frameSize.Width(), countHeight + frameSize.Height());
380         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
381         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
382     } else if (isShowError) {
383         auto textWidth = std::max(errorDecorator_ ? errorDecorator_->GetContentWidth() : 0.0f, frameSize.Width());
384         auto errorHeight = errorDecorator_? errorDecorator_->GetBoundHeight() : 0.0f;
385         RectF boundsRect(0.0f, 0.0f, textWidth, errorHeight + frameSize.Height());
386         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
387         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
388     } else {
389         if (NearEqual(maxFrameOffsetY_, 0.0f) && NearEqual(maxFrameHeight_, 0.0f)) {
390             maxFrameOffsetY_ = frameOffset.GetY();
391             maxFrameHeight_ = frameSize.Height();
392         }
393         maxFrameOffsetY_ = LessOrEqual(frameOffset.GetY(), maxFrameOffsetY_) ? frameOffset.GetY()
394                                                                              : maxFrameOffsetY_ - frameOffset.GetY();
395         maxFrameHeight_ = LessOrEqual(frameSize.Height(), maxFrameHeight_) ? maxFrameHeight_ : frameSize.Height();
396         RectF boundsRect(0.0f, 0.0f, frameSize.Width(), maxFrameHeight_ + UNDERLINE_WIDTH.ConvertToPx());
397         textFieldOverlayModifier_->SetBoundsRect(boundsRect);
398         textFieldForegroundModifier_->SetBoundsRect(boundsRect);
399     }
400 }
401 
CalcScrollRect(Rect & inlineScrollRect)402 void TextFieldPattern::CalcScrollRect(Rect& inlineScrollRect)
403 {
404     if (!IsNormalInlineState()) {
405         // if textfield is not inline, no need to calc rect
406         return;
407     }
408     auto host = GetHost();
409     CHECK_NULL_VOID(host);
410     auto pipeline = host->GetContext();
411     CHECK_NULL_VOID(pipeline);
412     auto scrollBar = GetScrollBar();
413     CHECK_NULL_VOID(scrollBar);
414     Size size(frameRect_.Width(), inlineMeasureItem_.inlineSizeHeight);
415     auto positionMode_ = scrollBar->GetPositionMode();
416     double mainSize = (positionMode_ == PositionMode::BOTTOM ? size.Width() : size.Height());
417     auto barRegionSize = mainSize;
418     double estimatedHeight = inlineMeasureItem_.inlineContentRectHeight;
419     if (NearZero(estimatedHeight) || NearZero(estimatedHeight - mainSize)) {
420         return;
421     }
422     double activeSize = barRegionSize * mainSize / estimatedHeight - scrollBar->GetOutBoundary();
423     auto offsetScale = 0.0f;
424     if (NearEqual(mainSize, estimatedHeight)) {
425         offsetScale = 0.0;
426     } else {
427         offsetScale = (barRegionSize - activeSize) / (estimatedHeight - mainSize);
428     }
429     double lastMainOffset = std::max(
430         static_cast<double>(std::max(inlineMeasureItem_.inlineLastOffsetY, contentRect_.GetY() - textRect_.GetY())),
431         0.0);
432     double activeMainOffset = std::min(offsetScale * lastMainOffset, barRegionSize - activeSize);
433     inlineScrollRect.SetLeft(inlineScrollRect.GetOffset().GetX() - inlineMeasureItem_.inlineScrollRectOffsetX);
434     inlineScrollRect.SetTop(activeMainOffset);
435     inlineScrollRect.SetHeight(activeSize);
436 }
437 
CreateObscuredText(int32_t len)438 std::u16string TextFieldPattern::CreateObscuredText(int32_t len)
439 {
440     std::u16string obscuredText;
441     if (Localization::GetInstance()->GetLanguage() == "ar") { // ar is the abbreviation of Arabic.
442         obscuredText = std::u16string(len, OBSCURING_CHARACTER_FOR_AR);
443     } else {
444         obscuredText = std::u16string(len, OBSCURING_CHARACTER);
445     }
446     return obscuredText;
447 }
448 
CreateDisplayText(const std::u16string & content,int32_t nakedCharPosition,bool needObscureText,bool showPasswordDirectly)449 std::u16string TextFieldPattern::CreateDisplayText(
450     const std::u16string& content, int32_t nakedCharPosition, bool needObscureText, bool showPasswordDirectly)
451 {
452     if (!content.empty() && needObscureText) {
453         auto text =
454             TextFieldPattern::CreateObscuredText(static_cast<int32_t>(content.length()));
455         if (nakedCharPosition >= 0 && nakedCharPosition < static_cast<int32_t>(content.length())) {
456             if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE) || !showPasswordDirectly) {
457                 text[nakedCharPosition] = content[nakedCharPosition];
458             }
459         }
460         return text;
461     }
462     return content;
463 }
464 
GetTextOrPlaceHolderFontSize()465 float TextFieldPattern::GetTextOrPlaceHolderFontSize()
466 {
467     auto tmpHost = GetHost();
468     CHECK_NULL_RETURN(tmpHost, 0.0f);
469     auto textFieldLayoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
470     CHECK_NULL_RETURN(textFieldLayoutProperty, 0.0f);
471     auto textFieldTheme = GetTheme();
472     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
473     Dimension fontSize;
474     if (textFieldLayoutProperty->HasFontSize() &&
475         textFieldLayoutProperty->GetFontSizeValue(Dimension()).IsNonNegative()) {
476         fontSize = textFieldLayoutProperty->GetFontSizeValue(Dimension());
477     } else {
478         return textFieldTheme ? static_cast<float>(textFieldTheme->GetFontSize().ConvertToPx())
479                               : static_cast<float>(DEFAULT_FONT.ConvertToPx());
480     }
481     return std::min(static_cast<float>(fontSize.ConvertToPx()), contentRect_.Height());
482 }
483 
TextFieldPattern()484 TextFieldPattern::TextFieldPattern() : twinklingInterval_(TWINKLING_INTERVAL_MS)
485 {
486     contentController_ = MakeRefPtr<ContentController>(WeakClaim(this));
487     selectController_ = MakeRefPtr<TextSelectController>(WeakClaim(this));
488     selectController_->InitContentController(contentController_);
489     magnifierController_ = MakeRefPtr<MagnifierController>(WeakClaim(this));
490     selectOverlay_ = MakeRefPtr<TextFieldSelectOverlay>(WeakClaim(this));
491     if (SystemProperties::GetDebugEnabled()) {
492         twinklingInterval_ = 3000; // 3000 : for AtuoUITest
493     }
494     ResetOriginCaretPosition();
495     callbackOldPreviewText_.offset = -1;
496 }
497 
GetIndependentControlKeyboard()498 bool TextFieldPattern::GetIndependentControlKeyboard()
499 {
500     auto context = PipelineContext::GetCurrentContextSafelyWithCheck();
501     CHECK_NULL_RETURN(context, false);
502     auto theme = context->GetTheme<TextFieldTheme>();
503     CHECK_NULL_RETURN(theme, false);
504     independentControlKeyboard_ = theme->GetIndependentControlKeyboard();
505     return independentControlKeyboard_;
506 }
507 
~TextFieldPattern()508 TextFieldPattern::~TextFieldPattern()
509 {
510     CloseSelectOverlay();
511     if (isCustomKeyboardAttached_) {
512         CloseCustomKeyboard();
513     }
514     RemoveTextFieldInfo();
515 }
516 
CheckAndUpdateRecordBeforeOperation()517 void TextFieldPattern::CheckAndUpdateRecordBeforeOperation()
518 {
519     if (operationRecords_.size() == 0 ||
520         operationRecords_.back().caretPosition != selectController_->GetCaretIndex()) {
521         // record the state before the operation
522         // or caret position change
523         UpdateEditingValueToRecord();
524     }
525 }
526 
BeforeCreateLayoutWrapper()527 void TextFieldPattern::BeforeCreateLayoutWrapper()
528 {
529     while (!inputOperations_.empty()) {
530         auto operation = inputOperations_.front();
531         inputOperations_.pop();
532         CheckAndUpdateRecordBeforeOperation();
533         switch (operation) {
534             case InputOperation::INSERT: {
535                 ExecuteInsertValueCommand(insertCommands_.front());
536                 insertCommands_.pop();
537                 break;
538             }
539             case InputOperation::DELETE_BACKWARD: {
540                 DeleteBackwardOperation(deleteBackwardOperations_.front());
541                 deleteBackwardOperations_.pop();
542                 HandleDeleteOnCounterScene();
543                 break;
544             }
545             case InputOperation::DELETE_FORWARD: {
546                 DeleteForwardOperation(deleteForwardOperations_.front());
547                 deleteForwardOperations_.pop();
548                 HandleDeleteOnCounterScene();
549                 break;
550             }
551             case InputOperation::CURSOR_UP: {
552                 CursorMoveUpOperation();
553                 break;
554             }
555             case InputOperation::CURSOR_DOWN: {
556                 CursorMoveDownOperation();
557                 break;
558             }
559             case InputOperation::CURSOR_LEFT: {
560                 CursorMoveLeftOperation();
561                 break;
562             }
563             case InputOperation::CURSOR_RIGHT: {
564                 CursorMoveRightOperation();
565                 break;
566             }
567             case InputOperation::SET_PREVIEW_TEXT:
568                 SetPreviewTextOperation(previewTextOperation_.front());
569                 previewTextOperation_.pop();
570                 break;
571             case InputOperation::SET_PREVIEW_FINISH:
572                 FinishTextPreviewOperation();
573                 break;
574             case InputOperation::INPUT:
575                 ExecuteInputCommand(inputCommands_.front());
576                 inputCommands_.pop();
577                 break;
578         }
579     }
580     selectOverlay_->MarkOverlayDirty();
581 }
582 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)583 bool TextFieldPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
584 {
585     if (config.skipMeasure || dirty->SkipMeasureContent()) {
586         return false;
587     }
588     contentRect_ = dirty->GetGeometryNode()->GetContentRect();
589     frameRect_ = dirty->GetGeometryNode()->GetFrameRect();
590     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
591     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
592     auto textFieldLayoutAlgorithm = DynamicCast<TextFieldLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
593     CHECK_NULL_RETURN(textFieldLayoutAlgorithm, false);
594     auto paragraph = textFieldLayoutAlgorithm->GetParagraph();
595     float paragraphWidth = 0.0f;
596     bool skipUpdateParagraph = false;
597     if (paragraph) {
598         skipUpdateParagraph = ShouldSkipUpdateParagraph();
599         paragraph_ = paragraph;
600         paragraphWidth = std::max(paragraph->GetLongestLine(), 0.0f);
601     }
602     UpdateParagraphForDragNode(skipUpdateParagraph);
603     auto textRect = textFieldLayoutAlgorithm->GetTextRect();
604     auto isSameSizeMouseMenu = NearEqual(paragraphWidth, paragraphWidth_) &&
605                                     NearEqual(textRect.GetSize(), textRect_.GetSize()) && IsUsingMouse();
606     needToRefreshSelectOverlay_ = needToRefreshSelectOverlay_ && !isSameSizeMouseMenu;
607     paragraphWidth_ = paragraphWidth;
608     HandleContentSizeChange(textRect);
609     textRect_ = textRect;
610 
611     if (textFieldContentModifier_) {
612         textFieldContentModifier_->ContentChange();
613     }
614 
615     if (textFieldOverlayModifier_) {
616         textFieldOverlayModifier_->ContentChange();
617     }
618 
619     auto oldParentGlobalOffset = parentGlobalOffset_;
620     parentGlobalOffset_ = GetPaintRectGlobalOffset();
621     inlineMeasureItem_ = textFieldLayoutAlgorithm->GetInlineMeasureItem();
622     auto isEditorValueChanged = FireOnTextChangeEvent();
623     UpdateCancelNode();
624     UpdateSelectController();
625     AdjustTextInReasonableArea();
626     UpdateCaretRect(isEditorValueChanged);
627     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
628     UpdateCaretInfoToController();
629     auto hostLayoutProperty =
630         dirty->GetHostNode() ? dirty->GetHostNode()->GetLayoutProperty<TextFieldLayoutProperty>() : nullptr;
631     if (hostLayoutProperty) {
632         hostLayoutProperty->ResetTextAlignChanged();
633     }
634     ProcessOverlayAfterLayout(oldParentGlobalOffset);
635     if (inlineSelectAllFlag_) {
636         HandleOnSelectAll(false, true);
637         inlineSelectAllFlag_ = false;
638         showSelect_ = true;
639     }
640     if (needSelectAll_ && !isLongPress_) {
641         HandleOnSelectAll(false);
642         needSelectAll_ = false;
643     }
644     if (mouseStatus_ == MouseStatus::RELEASED) {
645         mouseStatus_ = MouseStatus::NONE;
646     }
647     StopScrollable();
648     CheckScrollable();
649     UpdateScrollBarOffset();
650     if (config.frameSizeChange) {
651         ScheduleDisappearDelayTask();
652     }
653     SetAccessibilityClearAction();
654     SetAccessibilityPasswordIconAction();
655     SetAccessibilityUnitAction();
656     if (afterDragSelect_) {
657         UpdateSelectionAndHandleVisibility();
658         afterDragSelect_ = false;
659     }
660     releaseInDrop_ = false;
661     textParagraphIndent_ = textFieldLayoutAlgorithm->GetTextIndent();
662     return true;
663 }
664 
OnSyncGeometryNode(const DirtySwapConfig & config)665 void TextFieldPattern::OnSyncGeometryNode(const DirtySwapConfig& config)
666 {
667     CHECK_NULL_VOID(HasFocus());
668     parentGlobalOffset_ = GetPaintRectGlobalOffset();
669     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
670 }
671 
UpdateSelectionAndHandleVisibility()672 void TextFieldPattern::UpdateSelectionAndHandleVisibility()
673 {
674     TextFieldRequestFocus(RequestFocusReason::DRAG_SELECT);
675     auto start = dragTextStart_;
676     auto end = dragTextEnd_;
677     if (isMouseOrTouchPad(sourceTool_) && releaseInDrop_) {
678         start = selectController_->GetCaretIndex()
679         - static_cast<int32_t>(contentController_->GetInsertValue().length());
680         end = selectController_->GetCaretIndex();
681     }
682     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "UpdateSelectionAndHandleVisibility range=[%{public}d--%{public}d]",
683         start, end);
684     UpdateSelection(start, end);
685     showSelect_ = true;
686 
687     if (!isMouseOrTouchPad(sourceTool_)) {
688         ProcessOverlay({ .menuIsShow = false });
689     }
690     auto host = GetHost();
691     CHECK_NULL_VOID(host);
692     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
693 }
694 
SetAccessibilityPasswordIconAction()695 void TextFieldPattern::SetAccessibilityPasswordIconAction()
696 {
697     CHECK_NULL_VOID(IsShowPasswordIcon());
698     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
699     CHECK_NULL_VOID(passwordArea);
700     auto node = passwordArea->GetFrameNode();
701     CHECK_NULL_VOID(node);
702     auto textAccessibilityProperty = node->GetAccessibilityProperty<AccessibilityProperty>();
703     CHECK_NULL_VOID(textAccessibilityProperty);
704     textAccessibilityProperty->SetAccessibilityLevel("yes");
705     textAccessibilityProperty->SetAccessibilityText(GetPasswordIconPromptInformation(passwordArea->IsObscured()));
706     textAccessibilityProperty->SetAccessibilityCustomRole("button");
707 }
708 
SetAccessibilityClearAction()709 void TextFieldPattern::SetAccessibilityClearAction()
710 {
711     CHECK_NULL_VOID(IsShowCancelButtonMode());
712     auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
713     CHECK_NULL_VOID(cleanNodeResponseArea);
714     auto stackNode = cleanNodeResponseArea->GetFrameNode();
715     CHECK_NULL_VOID(stackNode);
716     auto textAccessibilityProperty = stackNode->GetAccessibilityProperty<AccessibilityProperty>();
717     CHECK_NULL_VOID(textAccessibilityProperty);
718     textAccessibilityProperty->SetAccessibilityLevel("yes");
719     auto layoutProperty = GetHost()->GetLayoutProperty<TextFieldLayoutProperty>();
720     CHECK_NULL_VOID(layoutProperty);
721     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyleValue(CleanNodeStyle::INPUT);
722     auto hasContent = cleanNodeStyle == CleanNodeStyle::CONSTANT ||
723                         (cleanNodeStyle == CleanNodeStyle::INPUT && HasText());
724     textAccessibilityProperty->SetAccessibilityText(hasContent ? GetCancelButton() : "");
725     textAccessibilityProperty->SetAccessibilityCustomRole("button");
726 }
727 
SetAccessibilityUnitAction()728 void TextFieldPattern::SetAccessibilityUnitAction()
729 {
730     if (!unitNode_ || !responseArea_) {
731         return;
732     }
733     auto unitNode = AceType::DynamicCast<FrameNode>(unitNode_);
734     CHECK_NULL_VOID(unitNode);
735     auto unitAccessibilityProperty = unitNode->GetAccessibilityProperty<AccessibilityProperty>();
736     CHECK_NULL_VOID(unitAccessibilityProperty);
737     unitAccessibilityProperty->SetAccessibilityLevel("yes");
738 }
739 
HandleContentSizeChange(const RectF & textRect)740 void TextFieldPattern::HandleContentSizeChange(const RectF& textRect)
741 {
742     if (textRect_ == textRect) {
743         return;
744     }
745     auto host = GetHost();
746     CHECK_NULL_VOID(host);
747     if (!NearEqual(textRect.Height(), textRect_.Height())) {
748         PlayScrollBarAppearAnimation();
749         ScheduleDisappearDelayTask();
750     }
751     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
752     CHECK_NULL_VOID(eventHub);
753     if (eventHub->GetOnContentSizeChange()) {
754         auto pipeline = host->GetContext();
755         CHECK_NULL_VOID(pipeline);
756         auto weak = WeakClaim(Referenced::RawPtr(eventHub));
757         pipeline->AddAfterLayoutTask([textRect, weak]() {
758             auto eventHub = weak.Upgrade();
759             CHECK_NULL_VOID(eventHub);
760             eventHub->FireOnContentSizeChange(std::max(0.0f, textRect.Width()), textRect.Height());
761         });
762     }
763 }
764 
ProcessOverlayAfterLayout(const OffsetF & prevOffset)765 void TextFieldPattern::ProcessOverlayAfterLayout(const OffsetF& prevOffset)
766 {
767     auto host = GetHost();
768     CHECK_NULL_VOID(host);
769     auto pipeline = host->GetContext();
770     CHECK_NULL_VOID(pipeline);
771     pipeline->AddAfterLayoutTask([weak = WeakClaim(this), prevOffset]() {
772         auto pattern = weak.Upgrade();
773         CHECK_NULL_VOID(pattern);
774         pattern->parentGlobalOffset_ = pattern->GetPaintRectGlobalOffset();
775         if (pattern->SelectOverlayIsOn()) {
776             pattern->selectOverlay_->UpdateIsSingleHandle(!pattern->IsSelected());
777             if (pattern->IsSelected()) {
778                 pattern->selectOverlay_->UpdateAllHandlesOffset();
779             } else {
780                 pattern->selectOverlay_->UpdateSecondHandleOffset();
781             }
782         }
783         if (pattern->processOverlayDelayTask_) {
784             if (pattern->HasFocus()) {
785                 pattern->processOverlayDelayTask_();
786             }
787             pattern->processOverlayDelayTask_ = nullptr;
788         } else if (prevOffset != pattern->parentGlobalOffset_) {
789             pattern->HandleParentGlobalOffsetChange();
790         } else if (pattern->needToRefreshSelectOverlay_ && pattern->SelectOverlayIsOn()) {
791             if (pattern->IsSelected()) {
792                 pattern->StopTwinkling();
793             } else {
794                 pattern->StartTwinkling();
795             }
796             pattern->selectOverlay_->SetUsingMouse(pattern->selectOverlay_->IsShowMouseMenu());
797             pattern->ProcessOverlay({ .menuIsShow = pattern->selectOverlay_->IsCurrentMenuVisibile() });
798             pattern->selectOverlay_->SetUsingMouse(false);
799         }
800         pattern->needToRefreshSelectOverlay_ = false;
801     });
802 }
803 
HasFocus() const804 bool TextFieldPattern::HasFocus() const
805 {
806     auto focusHub = GetFocusHub();
807     CHECK_NULL_RETURN(focusHub, false);
808     return focusHub->IsCurrentFocus();
809 }
810 
CheckAttachInput()811 bool TextFieldPattern::CheckAttachInput()
812 {
813     auto context = GetContext();
814     CHECK_NULL_RETURN(context, true);
815     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
816     CHECK_NULL_RETURN(textFieldManager, true);
817     return textFieldManager->GetAttachInputId() == GetRequestKeyboardId();
818 }
819 
UpdateCaretInfoToController(bool forceUpdate)820 void TextFieldPattern::UpdateCaretInfoToController(bool forceUpdate)
821 {
822     CHECK_NULL_VOID(HasFocus());
823 #if defined(ENABLE_STANDARD_INPUT)
824     CHECK_NULL_VOID(CheckAttachInput());
825     auto miscTextConfig = GetMiscTextConfig();
826     CHECK_NULL_VOID(miscTextConfig.has_value());
827     PreviewRange miscTextConfigRange {
828         miscTextConfig.value().range.start,
829         miscTextConfig.value().range.end
830     };
831     if (!forceUpdate && lastCursorRange_ == miscTextConfigRange &&
832         lastTextValue_ == contentController_->GetTextUtf16Value() &&
833         NearEqual(miscTextConfig.value().cursorInfo.top, lastCursorTop_) &&
834         NearEqual(miscTextConfig.value().cursorInfo.left, lastCursorLeft_)) {
835         return;
836     }
837     lastCursorRange_.Set(miscTextConfig.value().range.start, miscTextConfig.value().range.end);
838     lastTextValue_ = contentController_->GetTextUtf16Value();
839     lastCursorTop_ = miscTextConfig.value().cursorInfo.top;
840     lastCursorLeft_ = miscTextConfig.value().cursorInfo.left;
841     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
842     MiscServices::InputMethodController::GetInstance()->OnCursorUpdate(cursorInfo);
843     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
844         contentController_->GetTextUtf16Value(), selectController_->GetStartIndex(),
845         selectController_->GetEndIndex());
846     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
847         "UpdateCaretInfoToController, left %{public}f, top %{public}f, width %{public}f, height %{public}f; "
848         "selectController_ start "
849         "%{public}d, end %{public}d",
850         cursorInfo.left, cursorInfo.top, cursorInfo.width, cursorInfo.height, selectController_->GetStartIndex(),
851         selectController_->GetEndIndex());
852 
853 #else
854     if (HasConnection()) {
855         TextEditingValue value;
856         value.text = contentController_->GetTextValue();
857         value.hint = UtfUtils::Str16DebugToStr8(GetPlaceHolder());
858         value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
859         connection_->SetEditingState(value, GetInstanceId());
860     }
861 #endif
862 }
863 
UpdateCaretRect(bool isEditorValueChanged)864 void TextFieldPattern::UpdateCaretRect(bool isEditorValueChanged)
865 {
866     auto focusHub = GetFocusHub();
867     if (IsSelected()) {
868         selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex(), false);
869         selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex(), false);
870         return;
871     }
872     if (focusHub && !focusHub->IsCurrentFocus() && !obscuredChange_) {
873         CloseSelectOverlay(true);
874         return;
875     }
876     selectController_->MoveCaretToContentRect(
877         selectController_->GetCaretIndex(), TextAffinity::DOWNSTREAM, isEditorValueChanged);
878 }
879 
AdjustTextInReasonableArea()880 void TextFieldPattern::AdjustTextInReasonableArea()
881 {
882     // Adjust y.
883     auto contentBottomBoundary = contentRect_.GetY() + contentRect_.GetSize().Height();
884     if (textRect_.Height() > contentRect_.Height()) {
885         if (textRect_.GetY() + textRect_.Height() < contentBottomBoundary) {
886             auto dy = contentBottomBoundary - textRect_.GetY() - textRect_.Height();
887             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
888         }
889         if (GreatNotEqual(textRect_.GetY(), contentRect_.GetY())) {
890             auto dy = textRect_.GetY() - contentRect_.GetY();
891             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() - dy));
892         }
893     } else {
894         if (textRect_.GetY() != contentRect_.GetY()) {
895             auto dy = contentRect_.GetY() - textRect_.GetY();
896             textRect_.SetOffset(OffsetF(textRect_.GetX(), textRect_.GetY() + dy));
897         }
898     }
899 
900     // Adjust x.
901     auto contentRightBoundary = contentRect_.GetX() + contentRect_.GetSize().Width();
902     if (textRect_.Width() > contentRect_.Width()) {
903         if (textRect_.GetX() + textRect_.Width() < contentRightBoundary) {
904             auto dx = contentRightBoundary - textRect_.GetX() - textRect_.Width();
905             textRect_.SetLeft(textRect_.GetX() + dx);
906         }
907         if (GreatNotEqual(textRect_.GetX(), contentRect_.GetX())) {
908             auto dx = textRect_.GetX() - contentRect_.GetX();
909             textRect_.SetOffset(OffsetF(textRect_.GetX() - dx, textRect_.GetY()));
910         }
911     }
912 }
913 
IsTextArea() const914 bool TextFieldPattern::IsTextArea() const
915 {
916     auto tmpHost = GetHost();
917     CHECK_NULL_RETURN(tmpHost, false);
918     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
919     CHECK_NULL_RETURN(layoutProperty, true);
920     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(1) > 1 : true;
921 }
922 
UpdateSelectionOffset()923 void TextFieldPattern::UpdateSelectionOffset()
924 {
925     CHECK_NULL_VOID(IsSelected());
926     selectController_->CalculateHandleOffset();
927 }
928 
CalcCaretMetricsByPosition(int32_t extent,CaretMetricsF & caretCaretMetric,TextAffinity textAffinity)929 void TextFieldPattern::CalcCaretMetricsByPosition(
930     int32_t extent, CaretMetricsF& caretCaretMetric, TextAffinity textAffinity)
931 {
932     CHECK_NULL_VOID(paragraph_);
933     paragraph_->CalcCaretMetricsByPosition(extent, caretCaretMetric, textAffinity);
934     caretCaretMetric.offset.AddX(textRect_.GetX());
935     caretCaretMetric.offset.AddY(textRect_.GetY());
936 }
937 
CursorInContentRegion()938 bool TextFieldPattern::CursorInContentRegion()
939 {
940     if (IsTextArea()) {
941         return GreatOrEqual(selectController_->GetCaretRect().GetY(), contentRect_.GetY()) &&
942                LessOrEqual(selectController_->GetCaretRect().GetY() + GetTextOrPlaceHolderFontSize(),
943                    contentRect_.GetY() + contentRect_.Height());
944     }
945     auto theme = GetTheme();
946     CHECK_NULL_RETURN(theme, false);
947     return GreatOrEqual(selectController_->GetCaretRect().GetX(), contentRect_.GetX()) &&
948            LessOrEqual(selectController_->GetCaretRect().GetX() + theme->GetCursorWidth().ConvertToPx(),
949                contentRect_.GetX() + contentRect_.Width());
950 }
951 
OffsetInContentRegion(const Offset & offset)952 bool TextFieldPattern::OffsetInContentRegion(const Offset& offset)
953 {
954     // real content region will minus basic padding on left and right
955     return GreatOrEqual(offset.GetX(), contentRect_.GetX()) &&
956            LessOrEqual(offset.GetX(), contentRect_.GetX() + contentRect_.Width());
957 }
958 
CheckSelectAreaVisible()959 bool TextFieldPattern::CheckSelectAreaVisible()
960 {
961     auto tmpHost = GetHost();
962     CHECK_NULL_RETURN(tmpHost, false);
963     auto pipeline = tmpHost->GetContextRefPtr();
964     CHECK_NULL_RETURN(pipeline, false);
965     auto keyboardInset = pipeline->GetSafeAreaManager()->GetKeyboardInset();
966     auto selectArea = selectOverlay_->GetSelectArea();
967     auto globalOffset = GetPaintRectGlobalOffset();
968     auto globalContentRect = contentRect_;
969     globalContentRect.SetOffset(globalContentRect.GetOffset() + globalOffset);
970     if (selectArea.Bottom() < 0) {
971         return false;
972     } else if (!globalContentRect.IsInnerIntersectWith(selectArea)) {
973         return false;
974     } else if (keyboardInset.Length() > 0 && selectArea.Top() >= keyboardInset.start) {
975         return false;
976     }
977     return true;
978 }
979 
OnScrollEndCallback()980 void TextFieldPattern::OnScrollEndCallback()
981 {
982     ScheduleDisappearDelayTask();
983     if (!IsUsingMouse() && SelectOverlayIsOn() && isTextSelectionMenuShow_ && CheckSelectAreaVisible()) {
984         selectOverlay_->ShowMenu();
985     }
986 }
987 
OnTextAreaScroll(float offset)988 void TextFieldPattern::OnTextAreaScroll(float offset)
989 {
990     if (!IsTextArea() || textRect_.Height() <= contentRect_.Height()) {
991         return;
992     }
993     if (textRect_.GetY() + offset > contentRect_.GetY()) {
994         offset = contentRect_.GetY() - textRect_.GetY();
995     } else if (textRect_.GetY() + textRect_.Height() + offset < contentRect_.GetY() + contentRect_.Height()) {
996         offset = contentRect_.GetY() + contentRect_.Height() - textRect_.GetY() - textRect_.Height();
997     }
998     currentOffset_ = textRect_.GetY() + offset;
999     textRect_.SetOffset(OffsetF(textRect_.GetX(), currentOffset_));
1000     UpdateHandlesOffsetOnScroll(offset);
1001     UpdateScrollBarOffset();
1002 }
1003 
OnTextInputScroll(float offset)1004 void TextFieldPattern::OnTextInputScroll(float offset)
1005 {
1006     if (IsTextArea() || textRect_.Width() <= contentRect_.Width()) {
1007         return;
1008     }
1009     if (textRect_.GetX() + offset > contentRect_.GetX()) {
1010         offset = contentRect_.GetX() - textRect_.GetX();
1011     } else if (textRect_.GetX() + textRect_.Width() + offset < contentRect_.GetX() + contentRect_.Width()) {
1012         offset = contentRect_.GetX() + contentRect_.Width() - textRect_.GetX() - textRect_.Width();
1013     }
1014     currentOffset_ = textRect_.GetX() + offset;
1015     textRect_.SetOffset(OffsetF(currentOffset_, textRect_.GetY()));
1016     UpdateHandlesOffsetOnScroll(offset);
1017     auto tmpHost = GetHost();
1018     CHECK_NULL_VOID(tmpHost);
1019     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1020 }
1021 
ConvertTouchOffsetToCaretPosition(const Offset & localOffset)1022 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPosition(const Offset& localOffset)
1023 {
1024     CHECK_NULL_RETURN(paragraph_, 0);
1025     int32_t caretPositionIndex = 0;
1026     if (!contentController_->IsEmpty()) {
1027         caretPositionIndex = paragraph_->GetGlyphIndexByCoordinate(localOffset);
1028     }
1029     return caretPositionIndex;
1030 }
1031 
ConvertTouchOffsetToCaretPositionNG(const Offset & localOffset)1032 int32_t TextFieldPattern::ConvertTouchOffsetToCaretPositionNG(const Offset& localOffset)
1033 {
1034     CHECK_NULL_RETURN(paragraph_, 0);
1035     auto offset = localOffset - Offset(textRect_.GetX(), textRect_.GetY());
1036     return paragraph_->GetGlyphIndexByCoordinate(offset);
1037 }
1038 
1039 #if defined(IOS_PLATFORM)
GetGlobalOffset() const1040 Offset TextFieldPattern::GetGlobalOffset() const
1041 {
1042     Offset offset;
1043     auto host = GetHost();
1044     CHECK_NULL_RETURN(host, {});
1045     auto pipeline = host->GetContext();
1046     CHECK_NULL_RETURN(pipeline, {});
1047     auto rootOffset = pipeline->GetRootRect().GetOffset();
1048     auto globalOffset = host->GetPaintRectOffset(false, true) - rootOffset;
1049     offset = Offset(globalOffset.GetX(), globalOffset.GetY());
1050     return offset;
1051 }
1052 
GetEditingBoxY() const1053 double TextFieldPattern::GetEditingBoxY() const
1054 {
1055     return GetGlobalOffset().GetY() + frameRect_.Height();
1056 };
1057 
GetEditingBoxTopY() const1058 double TextFieldPattern::GetEditingBoxTopY() const
1059 {
1060     return GetGlobalOffset().GetY();
1061 };
1062 
GetEditingBoxModel() const1063 bool TextFieldPattern::GetEditingBoxModel() const
1064 {
1065     bool isDeclarative = false;
1066     auto host = GetHost();
1067     CHECK_NULL_RETURN(host, false);
1068     auto pipeline = host->GetContext();
1069     if (pipeline && pipeline->GetIsDeclarative()) {
1070         isDeclarative = true;
1071     }
1072     return isDeclarative;
1073 };
1074 #endif
1075 
HandleFocusEvent()1076 void TextFieldPattern::HandleFocusEvent()
1077 {
1078     isFocusedBeforeClick_ = true;
1079     focusIndex_ = FocuseIndex::TEXT;
1080     auto host = GetHost();
1081     CHECK_NULL_VOID(host);
1082     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d on focus", host->GetId());
1083     ACE_LAYOUT_SCOPED_TRACE("[TextField:%d] on focus", host->GetId());
1084     auto context = host->GetContextRefPtr();
1085     CHECK_NULL_VOID(context);
1086     context->AddOnAreaChangeNode(host->GetId());
1087     auto globalOffset = host->GetPaintRectOffset(false, true) - context->GetRootRect().GetOffset();
1088     UpdateTextFieldManager(Offset(globalOffset.GetX(), globalOffset.GetY()), frameRect_.Height());
1089     SetNeedToRequestKeyboardInner(!isLongPress_ && (dragRecipientStatus_ != DragStatus::DRAGGING) &&
1090         (dragStatus_ != DragStatus::DRAGGING) && !afterDragSelect_, RequestKeyboardInnerChangeReason::FOCUS);
1091     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
1092     CHECK_NULL_VOID(paintProperty);
1093     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1094     CHECK_NULL_VOID(layoutProperty);
1095     auto isSelectAll = layoutProperty->GetSelectAllValueValue(false);
1096     if (isSelectAll && !contentController_->IsEmpty()) {
1097         needSelectAll_ = !independentControlKeyboard_;
1098     }
1099     SetIsEnableSubWindowMenu();
1100     ProcessFocusStyle();
1101     ProcessAutoFillOnFocus();
1102     RequestKeyboardByFocusSwitch();
1103     ResetFirstClickAfterGetFocus();
1104     SetFocusStyle();
1105     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ?
1106         PROPERTY_UPDATE_MEASURE_SELF : PROPERTY_UPDATE_MEASURE);
1107 }
1108 
SetFocusStyle()1109 void TextFieldPattern::SetFocusStyle()
1110 {
1111     if (IsUnderlineMode() || IsInlineMode()) {
1112         return;
1113     }
1114     auto host = GetHost();
1115     CHECK_NULL_VOID(host);
1116     auto renderContext = host->GetRenderContext();
1117     CHECK_NULL_VOID(renderContext);
1118     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
1119     CHECK_NULL_VOID(paintProperty);
1120     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1121     CHECK_NULL_VOID(layoutProperty);
1122     auto textFieldTheme = GetTheme();
1123     CHECK_NULL_VOID(textFieldTheme);
1124 
1125     if (!paintProperty->HasBackgroundColor()) {
1126         auto defaultBGColor = textFieldTheme->GetBgColor();
1127         if (paintProperty->GetBackgroundColorValue(defaultBGColor) == defaultBGColor) {
1128             renderContext->UpdateBackgroundColor(textFieldTheme->GetFocusBgColor());
1129             isFocusBGColorSet_ = true;
1130         }
1131     }
1132     auto defaultTextColor = textFieldTheme->GetTextColor();
1133     if (layoutProperty->GetTextColorValue(defaultTextColor) == defaultTextColor &&
1134         !paintProperty->HasTextColorFlagByUser()) {
1135         layoutProperty->UpdateTextColor(textFieldTheme->GetFocusTextColor());
1136         isFocusTextColorSet_ = true;
1137     }
1138     auto defaultPlaceholderColor = textFieldTheme->GetPlaceholderColor();
1139     if (layoutProperty->GetPlaceholderTextColorValue(defaultPlaceholderColor) == defaultPlaceholderColor) {
1140         layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetFocusPlaceholderColor());
1141         isFocusPlaceholderColorSet_ = true;
1142     }
1143 }
1144 
ClearFocusStyle()1145 void TextFieldPattern::ClearFocusStyle()
1146 {
1147     auto host = GetHost();
1148     CHECK_NULL_VOID(host);
1149     auto renderContext = host->GetRenderContext();
1150     CHECK_NULL_VOID(renderContext);
1151     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
1152     CHECK_NULL_VOID(paintProperty);
1153     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1154     CHECK_NULL_VOID(layoutProperty);
1155     auto textFieldTheme = GetTheme();
1156     CHECK_NULL_VOID(textFieldTheme);
1157 
1158     if (isFocusBGColorSet_ && !paintProperty->HasBackgroundColor()) {
1159         renderContext->UpdateBackgroundColor(textFieldTheme->GetBgColor());
1160     }
1161     if (isFocusTextColorSet_ && !paintProperty->HasTextColorFlagByUser()) {
1162         layoutProperty->UpdateTextColor(textFieldTheme->GetTextColor());
1163     }
1164     if (isFocusPlaceholderColorSet_ && !paintProperty->GetPlaceholderColorFlagByUserValue(false)) {
1165         layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetPlaceholderColor());
1166     }
1167     isFocusBGColorSet_ = false;
1168     isFocusTextColorSet_ = false;
1169     isFocusPlaceholderColorSet_ = false;
1170 }
1171 
ProcessAutoFillOnFocus()1172 void TextFieldPattern::ProcessAutoFillOnFocus()
1173 {
1174     auto host = GetHost();
1175     CHECK_NULL_VOID(host);
1176     if (host->LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
1177         return;
1178     }
1179 
1180     auto isIgnoreFocusReason =
1181         requestFocusReason_ == RequestFocusReason::DRAG_ENTER || requestFocusReason_ == RequestFocusReason::DRAG_MOVE ||
1182         requestFocusReason_ == RequestFocusReason::DRAG_END || requestFocusReason_ == RequestFocusReason::AUTO_FILL ||
1183         requestFocusReason_ == RequestFocusReason::CLICK || requestFocusReason_ == RequestFocusReason::MOUSE ||
1184         requestFocusReason_ == RequestFocusReason::DRAG_SELECT;
1185     if (needToRequestKeyboardOnFocus_ && !isIgnoreFocusReason && !IsModalCovered() && IsTriggerAutoFillPassword()) {
1186         DoProcessAutoFill();
1187     }
1188 }
1189 
ProcessFocusStyle()1190 void TextFieldPattern::ProcessFocusStyle()
1191 {
1192     bool needTwinkling = true;
1193     if (IsNormalInlineState()) {
1194         ApplyInlineTheme();
1195         inlineFocusState_ = true;
1196         if (!contentController_->IsEmpty()) {
1197             inlineSelectAllFlag_ = (blurReason_ != BlurReason::WINDOW_BLUR &&
1198             requestFocusReason_ != RequestFocusReason::DRAG_SELECT);
1199             if (inlineSelectAllFlag_) {
1200                 needTwinkling = false;
1201             }
1202         }
1203         ProcessResponseArea();
1204     }
1205     if (needTwinkling) {
1206         StartTwinkling();
1207     }
1208     NotifyOnEditChanged(true);
1209     if (!IsShowError() && IsUnderlineMode()) {
1210         auto textFieldTheme = GetTheme();
1211         CHECK_NULL_VOID(textFieldTheme);
1212         underlineColor_ = userUnderlineColor_.typing.value_or(textFieldTheme->GetUnderlineTypingColor());
1213         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
1214     }
1215 }
1216 
HandleSetSelection(int32_t start,int32_t end,bool showHandle)1217 void TextFieldPattern::HandleSetSelection(int32_t start, int32_t end, bool showHandle)
1218 {
1219     auto host = GetHost();
1220     FREE_NODE_CHECK(host, HandleSetSelection,
1221         start, end, showHandle);  // call HandleSetSelectionMultiThread() by multi thread
1222     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleSetSelection %{public}d, %{public}d, showOverlay:%{public}d", start, end,
1223         showHandle);
1224     StopTwinkling();
1225     UpdateSelection(start, end);
1226     if (showHandle) {
1227         ProcessOverlay();
1228     } else {
1229         CloseSelectOverlay();
1230     }
1231     UpdateCaretInfoToController();
1232     CHECK_NULL_VOID(host);
1233     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1234 }
1235 
HandleExtendAction(int32_t action)1236 void TextFieldPattern::HandleExtendAction(int32_t action)
1237 {
1238     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleExtendAction %{public}d", action);
1239     switch (action) {
1240         case ACTION_SELECT_ALL: {
1241             HandleOnSelectAll(false);
1242             break;
1243         }
1244         case ACTION_CUT: {
1245             HandleOnCut();
1246             break;
1247         }
1248         case ACTION_COPY: {
1249             HandleOnCopy();
1250             break;
1251         }
1252         case ACTION_PASTE: {
1253             HandleOnPaste();
1254             break;
1255         }
1256         default: {
1257             break;
1258         }
1259     }
1260 }
1261 
CursorMove(CaretMoveIntent direction)1262 void TextFieldPattern::CursorMove(CaretMoveIntent direction)
1263 {
1264     switch (direction) {
1265         case CaretMoveIntent::Left: {
1266             CursorMoveLeft();
1267             break;
1268         }
1269         case CaretMoveIntent::Right: {
1270             CursorMoveRight();
1271             break;
1272         }
1273         case CaretMoveIntent::Up: {
1274             CursorMoveUp();
1275             break;
1276         }
1277         case CaretMoveIntent::Down: {
1278             CursorMoveDown();
1279             break;
1280         }
1281         case CaretMoveIntent::LineBegin: {
1282             CursorMoveLineBegin();
1283             break;
1284         }
1285         case CaretMoveIntent::LineEnd: {
1286             CursorMoveLineEnd();
1287             break;
1288         }
1289         case CaretMoveIntent::LeftWord: {
1290             CursorMoveLeftWord();
1291             break;
1292         }
1293         case CaretMoveIntent::RightWord: {
1294             CursorMoveRightWord();
1295             break;
1296         }
1297         case CaretMoveIntent::ParagraghBegin: {
1298             CursorMoveToParagraphBegin();
1299             break;
1300         }
1301         case CaretMoveIntent::ParagraghEnd: {
1302             CursorMoveToParagraphEnd();
1303             break;
1304         }
1305         case CaretMoveIntent::Home: {
1306             CursorMoveHome();
1307             break;
1308         }
1309         case CaretMoveIntent::End: {
1310             CursorMoveEnd();
1311             break;
1312         }
1313         default: {
1314             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Unsupported operation of CursorMove for text field");
1315         }
1316     }
1317 }
1318 
HandleSelect(CaretMoveIntent direction)1319 void TextFieldPattern::HandleSelect(CaretMoveIntent direction)
1320 {
1321     CloseSelectOverlay();
1322     switch (direction) {
1323         case CaretMoveIntent::Left: {
1324             HandleSelectionLeft();
1325             break;
1326         }
1327         case CaretMoveIntent::Right: {
1328             HandleSelectionRight();
1329             break;
1330         }
1331         case CaretMoveIntent::Up: {
1332             HandleSelectionUp();
1333             break;
1334         }
1335         case CaretMoveIntent::Down: {
1336             HandleSelectionDown();
1337             break;
1338         }
1339         case CaretMoveIntent::LineBegin: {
1340             HandleSelectionLineBegin();
1341             break;
1342         }
1343         case CaretMoveIntent::LineEnd: {
1344             HandleSelectionLineEnd();
1345             break;
1346         }
1347         case CaretMoveIntent::LeftWord: {
1348             HandleSelectionLeftWord();
1349             break;
1350         }
1351         case CaretMoveIntent::RightWord: {
1352             HandleSelectionRightWord();
1353             break;
1354         }
1355         case CaretMoveIntent::Home: {
1356             HandleSelectionHome();
1357             break;
1358         }
1359         case CaretMoveIntent::End: {
1360             HandleSelectionEnd();
1361             break;
1362         }
1363         case CaretMoveIntent::ParagraghBegin: {
1364             HandleSelectionParagraghBegin();
1365             break;
1366         }
1367         case CaretMoveIntent::ParagraghEnd: {
1368             HandleSelectionParagraghEnd();
1369             break;
1370         }
1371         default: {
1372             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Unsupported select operation for text field");
1373         }
1374     }
1375 }
1376 
InitDisableColor()1377 void TextFieldPattern::InitDisableColor()
1378 {
1379     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1380     CHECK_NULL_VOID(layoutProperty);
1381     auto theme = GetTheme();
1382     CHECK_NULL_VOID(theme);
1383     if (IsUnderlineMode()) {
1384         underlineWidth_ = HasFocus() ? TYPING_UNDERLINE_WIDTH : UNDERLINE_WIDTH;
1385         Color underlineColor = HasFocus() ? userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor())
1386                                           : userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
1387         if (IsShowError()) {
1388             underlineColor = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
1389         }
1390         if (userUnderlineColor_.disable) {
1391             underlineColor_ = IsDisabled() ? userUnderlineColor_.disable.value() : underlineColor;
1392         } else {
1393             underlineColor_ = IsDisabled() ? theme->GetDisableUnderlineColor() : underlineColor;
1394         }
1395     }
1396     layoutProperty->UpdateIsDisabled(IsDisabled());
1397 }
1398 
InitFocusEvent()1399 void TextFieldPattern::InitFocusEvent()
1400 {
1401     CHECK_NULL_VOID(!focusEventInitialized_);
1402     auto host = GetHost();
1403     CHECK_NULL_VOID(host);
1404     auto focusHub = host->GetOrCreateFocusHub();
1405     auto focusTask = [weak = WeakClaim(this)](FocusReason reason) {
1406         auto pattern = weak.Upgrade();
1407         if (pattern) {
1408             pattern->HandleFocusEvent();
1409         }
1410     };
1411     focusHub->SetOnFocusInternal(focusTask);
1412     auto blurTask = [weak = WeakClaim(this)]() {
1413         auto pattern = weak.Upgrade();
1414         CHECK_NULL_VOID(pattern);
1415         pattern->HandleBlurEvent();
1416     };
1417     focusHub->SetOnBlurInternal(blurTask);
1418 
1419     auto keyTask = [weak = WeakClaim(this)](const KeyEvent& keyEvent) -> bool {
1420         auto pattern = weak.Upgrade();
1421         CHECK_NULL_RETURN(pattern, false);
1422         return pattern->OnKeyEvent(keyEvent);
1423     };
1424     focusHub->SetOnKeyEventInternal(keyTask);
1425 
1426     auto getInnerPaintRectCallback = [weak = WeakClaim(this)](RoundRect& paintRect) {
1427         auto pattern = weak.Upgrade();
1428         if (pattern) {
1429             pattern->GetInnerFocusPaintRect(paintRect);
1430         }
1431     };
1432     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
1433     focusEventInitialized_ = true;
1434 }
1435 
CheckBlurReason()1436 bool TextFieldPattern::CheckBlurReason()
1437 {
1438     auto curFocusHub = GetFocusHub();
1439     CHECK_NULL_RETURN(curFocusHub, false);
1440     auto curBlurReason = curFocusHub->GetBlurReason();
1441     if (curBlurReason == BlurReason::FRAME_DESTROY) {
1442         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextFieldPattern CheckBlurReason, Close Keyboard.");
1443         return true;
1444     }
1445     return false;
1446 }
1447 
UpdateBlurReason()1448 void TextFieldPattern::UpdateBlurReason()
1449 {
1450     auto focusHub = GetFocusHub();
1451     CHECK_NULL_VOID(focusHub);
1452     blurReason_ = focusHub->GetBlurReason();
1453 }
1454 
ProcNormalInlineStateInBlurEvent()1455 void TextFieldPattern::ProcNormalInlineStateInBlurEvent()
1456 {
1457     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1458     CHECK_NULL_VOID(layoutProperty);
1459     if (IsNormalInlineState()) {
1460         if (IsTextArea() && isTextInput_) {
1461             layoutProperty->UpdateMaxLines(1);
1462             layoutProperty->UpdatePlaceholderMaxLines(1);
1463         }
1464         layoutProperty->ResetTextOverflowMaxLines();
1465         inlineSelectAllFlag_ = false;
1466         inlineFocusState_ = false;
1467         RestorePreInlineStates();
1468     }
1469 }
1470 
ProcBorderAndUnderlineInBlurEvent()1471 void TextFieldPattern::ProcBorderAndUnderlineInBlurEvent()
1472 {
1473     auto host = GetHost();
1474     CHECK_NULL_VOID(host);
1475     auto textFieldTheme = GetTheme();
1476     CHECK_NULL_VOID(textFieldTheme);
1477     bool isShowError = IsShowError();
1478     bool isUnderlineMode = IsUnderlineMode();
1479     if (!isShowError && isUnderlineMode) {
1480         underlineColor_ = userUnderlineColor_.normal.value_or(textFieldTheme->GetUnderlineColor());
1481         underlineWidth_ = UNDERLINE_WIDTH;
1482     }
1483     if (showCountBorderStyle_) {
1484         showCountBorderStyle_ = false;
1485         if (isShowError) {
1486             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1487         }
1488     }
1489     if (!isShowError || (isShowError && !isUnderlineMode && !IsInPasswordMode())) {
1490         HandleCounterBorder();
1491     }
1492 }
1493 
SetNeedToRequestKeyboardInner(bool needToRequestKeyboardInner,RequestKeyboardInnerChangeReason reason)1494 void TextFieldPattern::SetNeedToRequestKeyboardInner(bool needToRequestKeyboardInner,
1495     RequestKeyboardInnerChangeReason reason)
1496 {
1497     if (needToRequestKeyboardInner_ != needToRequestKeyboardInner) {
1498         TAG_LOGI(ACE_TEXT_FIELD, "Set needToRequestKeyboardInner_ to %{public}d : reason %{public}d",
1499             needToRequestKeyboardInner, static_cast<int32_t>(reason));
1500     }
1501     if (reason == RequestKeyboardInnerChangeReason::FOCUS && !needToRequestKeyboardInner) {
1502         TAG_LOGI(ACE_TEXT_FIELD, "field focus but set needToRequestKeyboardInner to false "
1503             "why: %{public}d %{public}d %{public}d", isLongPress_, dragRecipientStatus_, dragStatus_);
1504     }
1505     needToRequestKeyboardInner_ = needToRequestKeyboardInner;
1506 }
1507 
HandleBlurEvent()1508 void TextFieldPattern::HandleBlurEvent()
1509 {
1510     auto host = GetHost();
1511     CHECK_NULL_VOID(host);
1512     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField %{public}d OnBlur", host->GetId());
1513     auto context = host->GetContextRefPtr();
1514     CHECK_NULL_VOID(context);
1515     firstClickResetTask_.Cancel();
1516     firstClickAfterLosingFocus_ = true;
1517     UpdateBlurReason();
1518     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
1519     if (textFieldManager) {
1520         textFieldManager->ClearOnFocusTextField(host->GetId());
1521     }
1522     ResetOriginCaretPosition();
1523 
1524     shiftFlag_ = false;
1525     ProcBorderAndUnderlineInBlurEvent();
1526     ProcNormalInlineStateInBlurEvent();
1527     ModifyInnerStateInBlurEvent();
1528     if (magnifierController_) {
1529         magnifierController_->RemoveMagnifierFrameNode();
1530     }
1531     CloseSelectOverlay(!isKeyboardClosedByUser_ && blurReason_ == BlurReason::FOCUS_SWITCH);
1532     StopTwinkling();
1533     if (((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_)) {
1534         CloseKeyboard(true);
1535         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "textfield %{public}d on blur, close custom keyboard", host->GetId());
1536     }
1537     HandleCrossPlatformInBlurEvent();
1538     selectController_->UpdateCaretIndex(selectController_->GetCaretIndex());
1539     NotifyOnEditChanged(false);
1540     ResetFloatingCursorState();
1541     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1542     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
1543     CHECK_NULL_VOID(eventHub);
1544     if (!eventHub->HasOnAreaChanged()) {
1545         context->RemoveOnAreaChangeNode(host->GetId());
1546     }
1547     SetNeedToRequestKeyboardInner(false, RequestKeyboardInnerChangeReason::BLUR);
1548     if (isOnHover_) {
1549         RestoreDefaultMouseState();
1550     }
1551     ReportEvent();
1552     ScheduleDisappearDelayTask();
1553     requestFocusReason_ = RequestFocusReason::UNKNOWN;
1554     ClearFocusStyle();
1555 }
1556 
ModifyInnerStateInBlurEvent()1557 void TextFieldPattern::ModifyInnerStateInBlurEvent()
1558 {
1559     isLongPress_ = false;
1560     isMoveCaretAnywhere_ = false;
1561     isFocusedBeforeClick_ = false;
1562 }
1563 
HandleCrossPlatformInBlurEvent()1564 void TextFieldPattern::HandleCrossPlatformInBlurEvent()
1565 {
1566 #ifndef OHOS_PLATFORM
1567     if (HasConnection()) {
1568         CloseKeyboard(true);
1569     }
1570 #endif
1571 }
1572 
OnKeyEvent(const KeyEvent & event)1573 bool TextFieldPattern::OnKeyEvent(const KeyEvent& event)
1574 {
1575     if (event.code == KeyCode::KEY_TAB && !contentController_->IsEmpty()) {
1576         if (isFocusedBeforeClick_) {
1577             isFocusedBeforeClick_ = false;
1578             HandleOnSelectAll(true);
1579         } else {
1580             CloseSelectOverlay(true);
1581         }
1582     }
1583     auto pipeline = GetContext();
1584     CHECK_NULL_RETURN(pipeline, false);
1585     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
1586     if (event.code == KeyCode::KEY_TAB && HasFocus() && !needToRequestKeyboardOnFocus_ && needToRequestKeyboardInner_ &&
1587         textFieldManager->GetImeShow()) {
1588         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::ON_KEY_EVENT);
1589     }
1590     // If independent control keyboard, press Enter to request keyboard.
1591     if (event.code == KeyCode::KEY_ENTER && HasFocus() && independentControlKeyboard_) {
1592         if (RequestKeyboard(false, true, true)) {
1593             NotifyOnEditChanged(true);
1594         }
1595         return true;
1596     }
1597     if (directionKeysMoveFocusOut_ && (IsMoveFocusOutFromLeft(event) || IsMoveFocusOutFromRight(event))) {
1598         TextInputClient::HandleKeyEvent(event);
1599         return false;
1600     }
1601     return TextInputClient::HandleKeyEvent(event);
1602 }
1603 
IsMoveFocusOutFromLeft(const KeyEvent & event)1604 bool TextFieldPattern::IsMoveFocusOutFromLeft(const KeyEvent& event)
1605 {
1606     return (event.code == KeyCode::KEY_DPAD_LEFT || event.code == KeyCode::KEY_DPAD_UP) &&
1607      selectController_->GetCaretIndex() == 0;
1608 }
1609 
IsMoveFocusOutFromRight(const KeyEvent & event)1610 bool TextFieldPattern::IsMoveFocusOutFromRight(const KeyEvent& event)
1611 {
1612     return (event.code == KeyCode::KEY_DPAD_RIGHT || event.code == KeyCode::KEY_DPAD_DOWN) &&
1613      selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
1614 }
1615 
HandleOnEscape()1616 bool TextFieldPattern::HandleOnEscape()
1617 {
1618     if (SelectOverlayIsOn()) {
1619         CloseSelectOverlay(true);
1620         if (!IsSelected() && HasFocus()) {
1621             StartTwinkling();
1622         }
1623         return false;
1624     }
1625     if (GetIsPreviewText()) {
1626         ResetPreviewTextState();
1627         return false;
1628     }
1629     if (HasFocus()) {
1630         StopTwinkling();
1631         TextFieldLostFocusToViewRoot();
1632     }
1633     return false;
1634 }
1635 
HandleOnTab(bool backward)1636 bool TextFieldPattern::HandleOnTab(bool backward)
1637 {
1638     return backward ? UpdateFocusBackward() : UpdateFocusForward();
1639 }
1640 
HandleOnUndoAction()1641 void TextFieldPattern::HandleOnUndoAction()
1642 {
1643     if (operationRecords_.empty()) {
1644         return;
1645     }
1646     CHECK_NULL_VOID(!GetIsPreviewText());
1647     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnUndoAction");
1648     if (operationRecords_.size() == 1) {
1649         FireEventHubOnChange(u"");
1650         return;
1651     }
1652     auto value = operationRecords_.back();
1653     operationRecords_.pop_back();
1654     auto textEditingValue = operationRecords_.back(); // each record includes text and caret
1655     bool isWillChange = OnWillChangePreSetValue(textEditingValue.text);
1656     if (!isWillChange) {
1657         operationRecords_.emplace_back(value);
1658         return;
1659     }
1660     if (redoOperationRecords_.size() >= RECORD_MAX_LENGTH) {
1661         redoOperationRecords_.erase(redoOperationRecords_.begin());
1662     }
1663     if (operationRecords_.size() >= 1) {
1664         redoOperationRecords_.emplace_back(value); // the initial status is not recorded
1665     }
1666 
1667     contentController_->SetTextValue(textEditingValue.text);
1668     if (value.beforeCaretPosition != -1) {
1669         selectController_->MoveCaretToContentRect(
1670             value.beforeCaretPosition, TextAffinity::DOWNSTREAM);
1671     } else {
1672         selectController_->MoveCaretToContentRect(
1673             textEditingValue.caretPosition, TextAffinity::DOWNSTREAM);
1674     }
1675 
1676     CloseSelectOverlay();
1677     StartTwinkling();
1678 
1679     auto tmpHost = GetHost();
1680     CHECK_NULL_VOID(tmpHost);
1681     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1682 }
1683 
HandleOnRedoAction()1684 void TextFieldPattern::HandleOnRedoAction()
1685 {
1686     if (redoOperationRecords_.empty()) {
1687         return;
1688     }
1689     CHECK_NULL_VOID(!GetIsPreviewText());
1690     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnRedoAction");
1691     auto textEditingValue = redoOperationRecords_.back();
1692     bool isWillChange = OnWillChangePreSetValue(textEditingValue.text);
1693     if (!isWillChange) {
1694         return;
1695     }
1696     redoOperationRecords_.pop_back();
1697     operationRecords_.emplace_back(textEditingValue);
1698     contentController_->SetTextValue(textEditingValue.text);
1699     selectController_->UpdateCaretIndex(textEditingValue.caretPosition);
1700     auto tmpHost = GetHost();
1701     CHECK_NULL_VOID(tmpHost);
1702     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1703 }
1704 
CanUndo()1705 bool TextFieldPattern::CanUndo()
1706 {
1707     return operationRecords_.size() > 1;
1708 }
1709 
HasOperationRecords()1710 bool TextFieldPattern::HasOperationRecords()
1711 {
1712     return !operationRecords_.empty();
1713 }
1714 
CanRedo()1715 bool TextFieldPattern::CanRedo()
1716 {
1717     return !redoOperationRecords_.empty();
1718 }
1719 
HandleOnSelectAll(bool isKeyEvent,bool inlineStyle,bool showMenu)1720 void TextFieldPattern::HandleOnSelectAll(bool isKeyEvent, bool inlineStyle, bool showMenu)
1721 {
1722     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnSelectAll");
1723     CHECK_NULL_VOID(!GetIsPreviewText());
1724     auto textSize = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
1725     if (textSize == 0) {
1726         return; // no content
1727     }
1728     if (inlineStyle) {
1729         auto dotPos = contentController_->GetTextUtf16Value().rfind(u'.');
1730         if (dotPos != std::string::npos && static_cast<int32_t>(dotPos) < textSize - FIND_TEXT_ZERO_INDEX) {
1731             textSize = static_cast<int32_t>(dotPos);
1732         }
1733         UpdateSelection(0, textSize);
1734     } else {
1735         UpdateSelection(0, textSize);
1736     }
1737     if (IsSelected()) {
1738         SetIsSingleHandle(false);
1739     }
1740     ResetObscureTickCountDown();
1741     auto tmpHost = GetHost();
1742     CHECK_NULL_VOID(tmpHost);
1743     parentGlobalOffset_ = GetPaintRectGlobalOffset();
1744     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1745     selectController_->MoveSecondHandleToContentRect(textSize);
1746     StopTwinkling();
1747     showSelect_ = true;
1748     if (isKeyEvent || inlineSelectAllFlag_ || IsUsingMouse()) {
1749         CloseSelectOverlay(true);
1750         if (inlineSelectAllFlag_ && !isKeyEvent && !IsUsingMouse()) {
1751             return;
1752         }
1753         if (IsSelected()) {
1754             selectOverlay_->SetSelectionHoldCallback();
1755         }
1756         return;
1757     }
1758     selectOverlay_->ProcessSelectAllOverlay({ .menuIsShow = showMenu, .animation = true });
1759 }
1760 
HandleOnCopy(bool isUsingExternalKeyboard)1761 void TextFieldPattern::HandleOnCopy(bool isUsingExternalKeyboard)
1762 {
1763     CHECK_NULL_VOID(GetClipboard());
1764     auto tmpHost = GetHost();
1765     CHECK_NULL_VOID(tmpHost);
1766     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
1767     CHECK_NULL_VOID(layoutProperty);
1768     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) == CopyOptions::None) {
1769         return;
1770     }
1771     if (!IsSelected() || IsInPasswordMode()) {
1772         return;
1773     }
1774     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "On copy, text selector %{public}s", selectController_->ToString().c_str());
1775     auto start = selectController_->GetStartIndex();
1776     auto end = selectController_->GetEndIndex();
1777     auto value = contentController_->GetSelectedValue(start, end);
1778     if (value.empty()) {
1779         return;
1780     }
1781     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None) {
1782         clipboard_->SetData(UtfUtils::Str16DebugToStr8(value), layoutProperty->GetCopyOptionsValue(CopyOptions::Local));
1783     }
1784 
1785     if (isUsingExternalKeyboard || selectOverlay_->IsShowMouseMenu()) {
1786         CloseSelectOverlay(true);
1787     } else {
1788         selectOverlay_->HideMenu();
1789     }
1790     auto host = GetHost();
1791     CHECK_NULL_VOID(host);
1792     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
1793     CHECK_NULL_VOID(eventHub);
1794     eventHub->FireOnCopy(value);
1795 }
1796 
IsShowHandle()1797 bool TextFieldPattern::IsShowHandle()
1798 {
1799     auto theme = GetTheme();
1800     CHECK_NULL_RETURN(theme, false);
1801     return !theme->IsTextFieldShowHandle();
1802 }
1803 
GetCancelButton()1804 std::string TextFieldPattern::GetCancelButton()
1805 {
1806     auto theme = GetTheme();
1807     CHECK_NULL_RETURN(theme, "");
1808     return theme->GetCancelButton();
1809 }
1810 
GetCancelImageText()1811 std::string TextFieldPattern::GetCancelImageText()
1812 {
1813     auto theme = GetTheme();
1814     CHECK_NULL_RETURN(theme, "");
1815     return theme->GetCancelImageText();
1816 }
1817 
GetPasswordIconPromptInformation(bool show)1818 std::string TextFieldPattern::GetPasswordIconPromptInformation(bool show)
1819 {
1820     auto theme = GetTheme();
1821     CHECK_NULL_RETURN(theme, "");
1822     return show ? theme->GetShowPasswordPromptInformation() : theme->GetHiddenPasswordPromptInformation();
1823 }
1824 
UpdateShowCountBorderStyle()1825 void TextFieldPattern::UpdateShowCountBorderStyle()
1826 {
1827     auto host = GetHost();
1828     CHECK_NULL_VOID(host);
1829     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
1830     CHECK_NULL_VOID(layoutProperty);
1831     if (layoutProperty->HasMaxLength()) {
1832         auto textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
1833         auto maxLength = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
1834         // if equal, the showCountBorderStyle_ is not changed
1835         if (textLength != maxLength) {
1836             showCountBorderStyle_ = textLength > maxLength;
1837         }
1838     }
1839 }
1840 
HandleOnPaste()1841 void TextFieldPattern::HandleOnPaste()
1842 {
1843     auto pasteCallback = [weak = WeakClaim(this)](const std::string& data) {
1844         auto textfield = weak.Upgrade();
1845         CHECK_NULL_VOID(textfield);
1846         if (data.empty()) {
1847             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "HandleOnPaste fail, because data is empty");
1848             textfield->suppressAccessibilityEvent_ = true;
1849             return;
1850         }
1851 
1852         CHECK_NULL_VOID(!textfield->GetIsPreviewText());
1853         auto host = textfield->GetHost();
1854         CHECK_NULL_VOID(host);
1855         auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
1856         CHECK_NULL_VOID(eventHub);
1857         TextCommonEvent event;
1858         const std::u16string pasteData = UtfUtils::Str8DebugToStr16(data);
1859         eventHub->FireOnPasteWithEvent(pasteData, event);
1860         textfield->OnReportPasteEvent(host);
1861         if (event.IsPreventDefault()) {
1862             textfield->CloseSelectOverlay(true);
1863             textfield->selectController_->ResetHandles();
1864             textfield->StartTwinkling();
1865             textfield->suppressAccessibilityEvent_ = true;
1866             return;
1867         }
1868         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnPaste len:%{public}d", static_cast<int32_t>(pasteData.length()));
1869         textfield->AddInsertCommand(pasteData, InputReason::PASTE);
1870     };
1871     CHECK_NULL_VOID(GetClipboard());
1872     clipboard_->GetData(pasteCallback);
1873 }
1874 
IsShowTranslate()1875 bool TextFieldPattern::IsShowTranslate()
1876 {
1877     auto container = Container::Current();
1878     if (container && container->IsSceneBoardWindow()) {
1879         return false;
1880     }
1881 
1882     auto host = GetHost();
1883     CHECK_NULL_RETURN(host, false);
1884     auto textFieldTheme = GetTheme();
1885     CHECK_NULL_RETURN(textFieldTheme, false);
1886     return textFieldTheme->GetTranslateIsSupport();
1887 }
1888 
IsShowSearch()1889 bool TextFieldPattern::IsShowSearch()
1890 {
1891     auto container = Container::Current();
1892     if (container && container->IsSceneBoardWindow()) {
1893         return false;
1894     }
1895     auto host = GetHost();
1896     CHECK_NULL_RETURN(host, false);
1897     auto textFieldTheme = GetTheme();
1898     CHECK_NULL_RETURN(textFieldTheme, false);
1899     return textFieldTheme->GetIsSupportSearch();
1900 }
1901 
HandleOnCameraInput()1902 void TextFieldPattern::HandleOnCameraInput()
1903 {
1904     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextFieldPattern::HandleOnCameraInput");
1905 #if defined(ENABLE_STANDARD_INPUT)
1906     if (textChangeListener_ == nullptr) {
1907         textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
1908     }
1909     auto inputMethod = MiscServices::InputMethodController::GetInstance();
1910     if (!inputMethod) {
1911         TAG_LOGE(AceLogTag::ACE_TEXT_FIELD, "HandleOnCameraInput, inputMethod is null");
1912         return;
1913     }
1914 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
1915     if (imeShown_) {
1916         inputMethod->StartInputTypeAsync(MiscServices::InputType::CAMERA_INPUT);
1917     } else {
1918         FireOnWillAttachIME();
1919         auto optionalTextConfig = GetMiscTextConfig();
1920         CHECK_NULL_VOID(optionalTextConfig.has_value());
1921         MiscServices::TextConfig textConfig = optionalTextConfig.value();
1922         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnCameraInput set calling window id is : %{public}u",
1923             textConfig.windowId);
1924 #ifdef WINDOW_SCENE_SUPPORTED
1925         auto systemWindowId = GetSCBSystemWindowId();
1926         if (systemWindowId) {
1927             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "windowId From %{public}u to %{public}u.", textConfig.windowId,
1928                 systemWindowId);
1929             textConfig.windowId = systemWindowId;
1930         }
1931 #endif
1932         auto ret = inputMethod->Attach(textChangeListener_, false, textConfig);
1933         if (ret == MiscServices::ErrorCode::NO_ERROR) {
1934             auto pipeline = GetContext();
1935             CHECK_NULL_VOID(pipeline);
1936             auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
1937             CHECK_NULL_VOID(textFieldManager);
1938             textFieldManager->SetIsImeAttached(true);
1939         }
1940         inputMethod->StartInputType(MiscServices::InputType::CAMERA_INPUT);
1941         inputMethod->ShowTextInput();
1942     }
1943     CloseSelectOverlay(true);
1944     StartTwinkling();
1945 #endif
1946 #endif
1947 }
1948 
StripNextLine(std::wstring & data)1949 void TextFieldPattern::StripNextLine(std::wstring& data)
1950 {
1951     CHECK_NULL_VOID(!(data.empty() || IsTextArea()));
1952     std::wstring result;
1953     bool dataChanged = false;
1954     int32_t dataPtr = 0;
1955     while (dataPtr < static_cast<int32_t>(data.length())) {
1956         if (data[dataPtr] != WIDE_NEWLINE[0]) {
1957             result += data[dataPtr];
1958         } else {
1959             dataChanged = true;
1960         }
1961         dataPtr++;
1962     }
1963     if (!dataChanged) {
1964         return;
1965     }
1966     data = result;
1967 }
1968 
HandleOnCut()1969 void TextFieldPattern::HandleOnCut()
1970 {
1971     CHECK_NULL_VOID(GetClipboard());
1972     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
1973     CHECK_NULL_VOID(layoutProperty);
1974 
1975     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) == CopyOptions::None) {
1976         suppressAccessibilityEvent_ = true;
1977         return;
1978     }
1979     auto start = selectController_->GetStartIndex();
1980     auto end = selectController_->GetEndIndex();
1981     SwapIfLarger(start, end);
1982     if (!IsSelected() || IsInPasswordMode()) {
1983         suppressAccessibilityEvent_ = true;
1984         return;
1985     }
1986     UpdateEditingValueToRecord();
1987     auto selectedText = contentController_->GetSelectedValue(start, end);
1988     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None) {
1989         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Cut value size is %{private}zu",
1990             UtfUtils::Str16DebugToStr8(selectedText).size());
1991         clipboard_->SetData(UtfUtils::Str16DebugToStr8(selectedText),
1992             layoutProperty->GetCopyOptionsValue(CopyOptions::Local));
1993     }
1994     DeleteRange(start, end, false);
1995     auto host = GetHost();
1996     CHECK_NULL_VOID(host);
1997     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
1998     CHECK_NULL_VOID(eventHub);
1999     eventHub->FireOnCut(selectedText);
2000     host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
2001                                                                                  : PROPERTY_UPDATE_MEASURE);
2002 }
2003 
UpdateSelection(int32_t both)2004 void TextFieldPattern::UpdateSelection(int32_t both)
2005 {
2006     UpdateSelection(both, both);
2007 }
2008 
UpdateSelection(int32_t start,int32_t end)2009 void TextFieldPattern::UpdateSelection(int32_t start, int32_t end)
2010 {
2011     auto startIndex = std::min(start, end);
2012     auto endIndex = std::max(start, end);
2013     startIndex = std::clamp(startIndex, 0, static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
2014     endIndex = std::clamp(endIndex, 0, static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
2015     if (startIndex != selectController_->GetStartIndex() || endIndex != selectController_->GetEndIndex()) {
2016         selectController_->UpdateHandleIndex(startIndex, endIndex);
2017     }
2018 }
2019 
FireEventHubOnChange(const std::u16string & text)2020 void TextFieldPattern::FireEventHubOnChange(const std::u16string& text)
2021 {
2022     auto host = GetHost();
2023     CHECK_NULL_VOID(host);
2024     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2025     CHECK_NULL_VOID(layoutProperty);
2026     if (!layoutProperty->GetNeedFireOnChangeValue(false)) {
2027         return;
2028     }
2029     auto textFieldTheme = GetTheme();
2030     CHECK_NULL_VOID(textFieldTheme);
2031     auto visible = layoutProperty->GetShowErrorTextValue(false);
2032     if (!visible && IsUnderlineMode()) {
2033         underlineColor_ = userUnderlineColor_.typing.value_or(textFieldTheme->GetUnderlineTypingColor());
2034         underlineWidth_ = TYPING_UNDERLINE_WIDTH;
2035     }
2036 
2037     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
2038     CHECK_NULL_VOID(eventHub);
2039     ChangeValueInfo changeValueInfo;
2040     changeValueInfo.value = text;
2041     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
2042     changeValueInfo.previewText.value = GetPreviewTextValue();
2043     changeValueInfo.oldPreviewText = callbackOldPreviewText_;
2044     changeValueInfo.oldContent = callbackOldContent_;
2045     changeValueInfo.rangeBefore = callbackRangeBefore_;
2046     changeValueInfo.rangeAfter = callbackRangeAfter_;
2047     eventHub->FireOnChange(changeValueInfo);
2048 }
2049 
HandleTouchEvent(const TouchEventInfo & info)2050 void TextFieldPattern::HandleTouchEvent(const TouchEventInfo& info)
2051 {
2052     CHECK_NULL_VOID(!IsDragging());
2053     CHECK_NULL_VOID(!info.GetTouches().empty());
2054     if (selectOverlay_->IsTouchAtHandle(info)) {
2055         return;
2056     }
2057     auto touchInfo = GetAcceptedTouchLocationInfo(info);
2058     CHECK_NULL_VOID(touchInfo);
2059     DoGestureSelection(info);
2060     ResetOriginCaretPosition();
2061     auto touchType = touchInfo->GetTouchType();
2062     if (touchType == TouchType::DOWN) {
2063         HandleTouchDown(touchInfo->GetLocalLocation());
2064     } else if (touchType == TouchType::UP) {
2065         OnCaretMoveDone(info);
2066         RequestKeyboardAfterLongPress();
2067         isLongPress_ = false;
2068         isMoveCaretAnywhere_ = false;
2069         HandleTouchUp();
2070     } else if (touchType == TouchType::MOVE) {
2071         if (isMoveCaretAnywhere_) {
2072             // edit + longpress + move, show caret anywhere on fonts.
2073             selectController_->MoveCaretAnywhere(info.GetTouches().front().GetLocalLocation());
2074             ShowCaretAndStopTwinkling();
2075             selectOverlay_->HideMenu();
2076             selectOverlay_->SetIsSingleHandle(false);
2077             return;
2078         }
2079         if (SelectOverlayIsOn() && !moveCaretState_.isTouchCaret) {
2080             return;
2081         }
2082         if (!IsUsingMouse() && HasFocus()) {
2083             HandleTouchMove(touchInfo.value());
2084         }
2085     } else if (touchType == TouchType::CANCEL) {
2086         StopContentScroll();
2087         if (magnifierController_ && magnifierController_->GetMagnifierNodeExist()) {
2088             magnifierController_->RemoveMagnifierFrameNode();
2089         }
2090         ResetTouchAndMoveCaretState();
2091     }
2092 }
2093 
HandleTouchDown(const Offset & offset)2094 void TextFieldPattern::HandleTouchDown(const Offset& offset)
2095 {
2096     UpdatePressStyle(true);
2097     moveCaretState_.touchDownOffset = offset;
2098     if (HasStateStyle(UI_STATE_PRESSED)) {
2099         return;
2100     }
2101 
2102     if (enableTouchAndHoverEffect_ && !isMousePressed_) {
2103         auto lastCaretRect = selectController_->GetCaretRect();
2104         moveCaretState_.isTouchCaret = HasFocus() && !IsSelected() && RepeatClickCaret(offset, lastCaretRect);
2105         isTouchPreviewText_ = GetTouchInnerPreviewText(offset);
2106     }
2107 }
2108 
HandleTouchUp()2109 void TextFieldPattern::HandleTouchUp()
2110 {
2111     UpdatePressStyle(false);
2112     if (GetIsPreviewText() && isTouchPreviewText_) {
2113         StartTwinkling();
2114     }
2115     ResetTouchAndMoveCaretState();
2116     if (isMousePressed_) {
2117         isMousePressed_ = false;
2118     }
2119     if (magnifierController_) {
2120         magnifierController_->RemoveMagnifierFrameNode();
2121     }
2122     ScheduleDisappearDelayTask();
2123 }
2124 
ResetTouchAndMoveCaretState()2125 void TextFieldPattern::ResetTouchAndMoveCaretState()
2126 {
2127     if (moveCaretState_.isTouchCaret) {
2128         moveCaretState_.isTouchCaret = false;
2129         CheckScrollable();
2130         UpdateScrollBarOffset();
2131         StartTwinkling();
2132     }
2133     if (moveCaretState_.isMoveCaret) {
2134         moveCaretState_.isMoveCaret = false;
2135         auto isAutoScrolling = contentScroller_.isScrolling;
2136         StopContentScroll();
2137         if (isAutoScrolling) {
2138             UpdateCaretRect(false);
2139         }
2140         if (HasFocus()) {
2141             StartTwinkling();
2142         } else {
2143             StopTwinkling();
2144         }
2145     }
2146     FloatingCaretLand();
2147 }
2148 
HandleTouchMove(const TouchLocationInfo & info)2149 void TextFieldPattern::HandleTouchMove(const TouchLocationInfo& info)
2150 {
2151     if (moveCaretState_.isTouchCaret && !moveCaretState_.isMoveCaret) {
2152         auto offset = info.GetLocalLocation();
2153         auto moveDistance = (offset - moveCaretState_.touchDownOffset).GetDistance();
2154         moveCaretState_.isMoveCaret = GreatNotEqual(moveDistance, moveCaretState_.minDinstance.ConvertToPx());
2155         if (moveCaretState_.isMoveCaret) {
2156             moveCaretState_.touchFingerId = info.GetFingerId();
2157             contentScroller_.scrollingCallback = [weak = WeakClaim(this)](const Offset& localOffset) {
2158                 auto pattern = weak.Upgrade();
2159                 CHECK_NULL_VOID(pattern);
2160                 pattern->UpdateMagnifierWithFloatingCaretPos();
2161             };
2162         }
2163     }
2164     if (SelectOverlayIsOn() && moveCaretState_.isMoveCaret) {
2165         CloseSelectOverlay(false);
2166     }
2167     if (moveCaretState_.isMoveCaret || (GetIsPreviewText() && isTouchPreviewText_)) {
2168         ShowCaretAndStopTwinkling();
2169         UpdateCaretByTouchMove(info);
2170     }
2171 }
2172 
StartVibratorByIndexChange(int32_t currentIndex,int32_t preIndex)2173 void TextFieldPattern::StartVibratorByIndexChange(int32_t currentIndex, int32_t preIndex)
2174 {
2175     CHECK_NULL_VOID(isEnableHapticFeedback_ && (currentIndex != preIndex));
2176     VibratorUtils::StartVibraFeedback("slide");
2177 }
2178 
UpdateCaretByTouchMove(const TouchLocationInfo & info)2179 void TextFieldPattern::UpdateCaretByTouchMove(const TouchLocationInfo& info)
2180 {
2181     if (contentScroller_.isScrolling) {
2182         CheckScrollable();
2183     } else {
2184         scrollable_ = false;
2185         SetScrollEnabled(scrollable_);
2186     }
2187     // limit move when preview text is shown
2188     auto touchOffset = info.GetLocalLocation();
2189     if (GetIsPreviewText()) {
2190         TAG_LOGI(ACE_TEXT_FIELD, "UpdateCaretByTouchMove when has previewText");
2191         float offsetY = IsTextArea() ? GetTextRect().GetY() : contentRect_.GetY();
2192         std::vector<RectF> previewTextRects = GetPreviewTextRects();
2193         if (previewTextRects.empty()) {
2194             TAG_LOGI(ACE_TEXT_FIELD, "preview text rect error");
2195             return;
2196         }
2197 
2198         double limitL;
2199         double limitR;
2200         double limitT = previewTextRects.front().Top() + offsetY + MINIMAL_OFFSET;
2201         double limitB = previewTextRects.back().Bottom() + offsetY - MINIMAL_OFFSET;
2202 
2203         Offset previewTextTouchOffset;
2204         CalculatePreviewingTextMovingLimit(touchOffset, limitL, limitR);
2205 
2206         previewTextTouchOffset.SetX(std::clamp(touchOffset.GetX(), limitL, limitR));
2207         previewTextTouchOffset.SetY(std::clamp(touchOffset.GetY(), limitT, limitB));
2208         selectController_->UpdateCaretInfoByOffset(previewTextTouchOffset, true, true);
2209     } else {
2210         if (HasText()) {
2211             UpdateContentScroller(touchOffset);
2212         }
2213         auto touchCaretX = std::clamp(
2214             touchOffset.GetX(), static_cast<double>(contentRect_.Left()), static_cast<double>(contentRect_.Right()));
2215         // 1/4 line height.
2216         auto yOffset = PreferredLineHeight() * 0.25f;
2217         auto touchCaretY = std::clamp(touchOffset.GetY(), static_cast<double>(contentRect_.Top()) + yOffset,
2218             static_cast<double>(contentRect_.Bottom()) - yOffset);
2219         selectController_->UpdateCaretInfoByOffset(
2220             !contentScroller_.isScrolling ? Offset(touchCaretX, touchCaretY) : touchOffset,
2221             !contentScroller_.isScrolling, true);
2222         if (!contentScroller_.isScrolling) {
2223             UpdateMagnifierWithFloatingCaretPos();
2224         }
2225     }
2226 
2227     UpdateCaretInfoToController();
2228     auto host = GetHost();
2229     CHECK_NULL_VOID(host);
2230     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2231 }
2232 
SetMagnifierLocalOffsetToFloatingCaretPos()2233 void TextFieldPattern::SetMagnifierLocalOffsetToFloatingCaretPos()
2234 {
2235     auto floatCaretRectCenter = GetFloatingCaretRect().Center();
2236     if (floatCaretState_.lastFloatingCursorY.has_value() && !NearEqual(floatCaretState_.lastFloatingCursorY.value(),
2237         static_cast<float>(floatCaretRectCenter.GetY()))) {
2238         AnimationOption option = AnimationOption();
2239         option.SetCurve(MOVE_MAGNIFIER_CURVE);
2240         option.SetDuration(LAND_DURATION);
2241         AnimationUtils::Animate(option,
2242             [weak = WeakClaim(this), floatCaretRectCenter]() {
2243                 auto pattern = weak.Upgrade();
2244                 CHECK_NULL_VOID(pattern);
2245                 pattern->GetMagnifierController()->SetLocalOffset({ floatCaretRectCenter.GetX(),
2246                     floatCaretRectCenter.GetY() });
2247             });
2248     } else {
2249         magnifierController_->SetLocalOffset({ floatCaretRectCenter.GetX(), floatCaretRectCenter.GetY() });
2250     }
2251     floatCaretState_.lastFloatingCursorY = floatCaretRectCenter.GetY();
2252 }
2253 
UpdateMagnifierWithFloatingCaretPos()2254 void TextFieldPattern::UpdateMagnifierWithFloatingCaretPos()
2255 {
2256     if (magnifierController_ && HasText()) {
2257         SetMagnifierLocalOffsetToFloatingCaretPos();
2258     }
2259 }
2260 
InitDragEvent()2261 void TextFieldPattern::InitDragEvent()
2262 {
2263     auto host = GetHost();
2264     CHECK_NULL_VOID(host);
2265     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2266     CHECK_NULL_VOID(layoutProperty);
2267     if (!IsInPasswordMode() && layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None &&
2268         host->IsDraggable()) {
2269         InitDragDropEvent();
2270     } else {
2271         ClearDragDropEvent();
2272         InitDragDropEventWithOutDragStart();
2273     }
2274 }
2275 
GetThumbnailCallback()2276 std::function<void(Offset)> TextFieldPattern::GetThumbnailCallback()
2277 {
2278     auto callback = [weak = WeakClaim(this)](const Offset& point) {
2279         auto pattern = weak.Upgrade();
2280         CHECK_NULL_VOID(pattern);
2281         auto frameNode = pattern->GetHost();
2282         CHECK_NULL_VOID(frameNode);
2283         if (pattern->BetweenSelectedPosition(point)) {
2284             auto info = pattern->CreateTextDragInfo();
2285             pattern->dragNode_ = TextDragPattern::CreateDragNode(frameNode);
2286             auto textDragPattern = pattern->dragNode_->GetPattern<TextDragPattern>();
2287             if (textDragPattern) {
2288                 textDragPattern->UpdateHandleAnimationInfo(info);
2289                 auto option = pattern->GetHost()->GetDragPreviewOption();
2290                 option.options.shadowPath = textDragPattern->GetBackgroundPath()->ConvertToSVGString();
2291                 option.options.shadow = Shadow(RICH_DEFAULT_ELEVATION, {0.0, 0.0}, Color(RICH_DEFAULT_SHADOW_COLOR),
2292                     ShadowStyle::OuterFloatingSM);
2293                 pattern->GetHost()->SetDragPreviewOptions(option);
2294             }
2295             FrameNode::ProcessOffscreenNode(pattern->dragNode_);
2296         }
2297         auto gestureHub = frameNode->GetOrCreateGestureEventHub();
2298         CHECK_NULL_VOID(gestureHub);
2299         gestureHub->SetPixelMap(nullptr);
2300     };
2301     return callback;
2302 }
2303 
OnDragNodeDetachFromMainTree()2304 void TextFieldPattern::OnDragNodeDetachFromMainTree()
2305 {
2306     auto host = GetHost();
2307     CHECK_NULL_VOID(host);
2308     if (dragStatus_ == DragStatus::NONE) {
2309         selectOverlay_->ProcessOverlay( { .menuIsShow = false } );
2310         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2311     }
2312 }
2313 
CreateTextDragInfo() const2314 TextDragInfo TextFieldPattern::CreateTextDragInfo() const
2315 {
2316     TextDragInfo info;
2317     auto manager = selectOverlay_->GetManager<SelectContentOverlayManager>();
2318     CHECK_NULL_RETURN(manager, info);
2319     auto selectOverlayInfo = manager->GetSelectOverlayInfo();
2320     CHECK_NULL_RETURN(selectOverlayInfo, info);
2321     auto textFieldTheme = GetTheme();
2322     CHECK_NULL_RETURN(textFieldTheme, info);
2323     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
2324     CHECK_NULL_RETURN(paintProperty, info);
2325     auto handleColor = paintProperty->GetCursorColorValue(textFieldTheme->GetCursorColor());
2326     auto selectedBackgroundColor = textFieldTheme->GetSelectedColor();
2327     auto firstIndex = selectController_->GetFirstHandleIndex();
2328     auto secondIndex = selectController_->GetSecondHandleIndex();
2329     auto firstIsShow = selectOverlayInfo->firstHandle.isShow;
2330     auto secondIsShow = selectOverlayInfo->secondHandle.isShow;
2331     if (firstIndex > secondIndex) {
2332         selectOverlay_->GetDragViewHandleRects(info.secondHandle, info.firstHandle);
2333         info.isFirstHandleAnimation = secondIsShow;
2334         info.isSecondHandleAnimation = firstIsShow;
2335     } else {
2336         selectOverlay_->GetDragViewHandleRects(info.firstHandle, info.secondHandle);
2337         info.isFirstHandleAnimation = firstIsShow;
2338         info.isSecondHandleAnimation = secondIsShow;
2339     }
2340     info.selectedBackgroundColor = selectedBackgroundColor;
2341     info.handleColor = handleColor;
2342     return info;
2343 }
2344 
OnDragStart()2345 std::function<DragDropInfo(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragStart()
2346 {
2347     auto onDragStart = [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event,
2348                            const std::string& extraParams) -> NG::DragDropInfo {
2349         NG::DragDropInfo itemInfo;
2350         auto pattern = weakPtr.Upgrade();
2351         CHECK_NULL_RETURN(pattern, itemInfo);
2352         auto host = pattern->GetHost();
2353         CHECK_NULL_RETURN(host, itemInfo);
2354         auto hub = host->GetOrCreateEventHub<EventHub>();
2355         CHECK_NULL_RETURN(hub, itemInfo);
2356         auto gestureHub = hub->GetOrCreateGestureEventHub();
2357         CHECK_NULL_RETURN(gestureHub, itemInfo);
2358         pattern->sourceTool_ = event ? event->GetSourceTool() : SourceTool::UNKNOWN;
2359         if (!gestureHub->GetIsTextDraggable()) {
2360             return itemInfo;
2361         }
2362         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2363             "%{public}d TextField OnDragStart, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2364             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2365             static_cast<int32_t>(pattern->dragRecipientStatus_));
2366         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2367         CHECK_NULL_RETURN(layoutProperty, itemInfo);
2368 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
2369         pattern->CloseHandleAndSelect();
2370         pattern->CloseKeyboard(true);
2371 #endif
2372         pattern->SetDragMovingScrollback();
2373         pattern->dragStatus_ = DragStatus::DRAGGING;
2374         auto pipeline = pattern->GetContext();
2375         CHECK_NULL_RETURN(pipeline, itemInfo);
2376         auto dragManager = pipeline->GetDragDropManager();
2377         CHECK_NULL_RETURN(dragManager, itemInfo);
2378         if (!pattern->IsNormalInlineState() && dragManager->IsDropAllowed(host)) {
2379             pattern->dragRecipientStatus_ = DragStatus::DRAGGING;
2380         }
2381         auto selectedStr = pattern->GetDragStyledText();
2382         itemInfo.extraInfo = selectedStr;
2383         RefPtr<UnifiedData> unifiedData = UdmfClient::GetInstance()->CreateUnifiedData();
2384         UdmfClient::GetInstance()->AddPlainTextRecord(unifiedData, selectedStr);
2385         event->SetData(unifiedData);
2386         host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
2387                                                                                      : PROPERTY_UPDATE_MEASURE);
2388         return itemInfo;
2389     };
2390     return onDragStart;
2391 }
2392 
GetDragStyledText()2393 std::string TextFieldPattern::GetDragStyledText()
2394 {
2395     showSelect_ = false;
2396     selectionMode_ = SelectionMode::SELECT;
2397     textFieldContentModifier_->ChangeDragStatus();
2398     auto start = selectController_->GetStartIndex();
2399     auto end = selectController_->GetEndIndex();
2400     GetEmojiSubStringRange(start, end);
2401     dragTextStart_ = start;
2402     dragTextEnd_ = end;
2403     std::u16string beforeStr = contentController_->GetValueBeforeIndex(start);
2404     std::u16string selectedStr = contentController_->GetSelectedValue(start, end);
2405     dragValue_ = selectedStr;
2406     std::u16string afterStr = contentController_->GetValueAfterIndex(end);
2407     dragContents_ = { beforeStr, selectedStr, afterStr };
2408     return UtfUtils::Str16DebugToStr8(selectedStr);
2409 }
2410 
OnDragDrop()2411 std::function<void(const RefPtr<OHOS::Ace::DragEvent>&, const std::string&)> TextFieldPattern::OnDragDrop()
2412 {
2413     return [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2414         auto pattern = weakPtr.Upgrade();
2415         CHECK_NULL_VOID(pattern);
2416         pattern->StopContentScroll();
2417         pattern->sourceTool_ = event ? event->GetSourceTool() : SourceTool::UNKNOWN;
2418         auto host = pattern->GetHost();
2419         CHECK_NULL_VOID(host);
2420         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
2421         CHECK_NULL_VOID(layoutProperty);
2422 
2423         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2424             "%{public}d TextField OnDragDrop, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2425             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2426             static_cast<int32_t>(pattern->dragRecipientStatus_));
2427         if (layoutProperty->GetIsDisabledValue(false) || pattern->IsNormalInlineState() || !pattern->HasFocus()) {
2428             event->SetResult(DragRet::DRAG_FAIL);
2429             return;
2430         }
2431         if (extraParams.empty()) {
2432             pattern->dragStatus_ = DragStatus::ON_DROP;
2433             pattern->textFieldContentModifier_->ChangeDragStatus();
2434             host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF
2435                                                                                          : PROPERTY_UPDATE_MEASURE);
2436             event->SetResult(DragRet::DRAG_FAIL);
2437             return;
2438         }
2439         bool isCopy = false;
2440         if (pattern->dragStatus_ == DragStatus::DRAGGING) {
2441             CHECK_NULL_VOID(event);
2442             auto gesturePressedCodes = event->GetPressedKeyCodes();
2443             if ((gesturePressedCodes.size() == 1) && ((gesturePressedCodes[0] == KeyCode::KEY_CTRL_LEFT) ||
2444                 (gesturePressedCodes[0] == KeyCode::KEY_CTRL_RIGHT))) {
2445                 isCopy = true;
2446             }
2447         }
2448         auto data = event->GetData();
2449         CHECK_NULL_VOID(data);
2450         std::u16string str;
2451         auto arr = UdmfClient::GetInstance()->GetSpanStringEntry(data);
2452         if (arr.size() > 0) {
2453             auto spanStr = SpanString::DecodeTlv(arr);
2454             str += spanStr->GetU16string();
2455         } else {
2456             auto plainText = UdmfClient::GetInstance()->GetPlainTextEntry(data);
2457             if (plainText.empty()) {
2458                 std::string linkUrl;
2459                 std::string linkTitle;
2460                 UdmfClient::GetInstance()->GetLinkEntry(data, linkUrl, linkTitle);
2461                 if (!linkTitle.empty()) {
2462                     str +=  UtfUtils::Str8DebugToStr16(linkTitle);
2463                 } else if (!linkUrl.empty()) {
2464                     str +=  UtfUtils::Str8DebugToStr16(linkUrl);
2465                 }
2466             }
2467             str += UtfUtils::Str8DebugToStr16(plainText);
2468         }
2469         pattern->dragRecipientStatus_ = DragStatus::NONE;
2470         if (str.empty()) {
2471             return;
2472         }
2473         if ((pattern->dragStatus_ == DragStatus::NONE) || isCopy) {
2474             pattern->AddInsertCommand(str, InputReason::DRAG);
2475         } else {
2476             InputCommandInfo inputCommandInfo;
2477             inputCommandInfo.deleteRange = { pattern->dragTextStart_, pattern->dragTextEnd_ };
2478             inputCommandInfo.insertOffset = pattern->selectController_->GetCaretIndex();
2479             inputCommandInfo.insertValue = str;
2480             inputCommandInfo.reason = InputReason::DRAG;
2481             pattern->AddInputCommand(inputCommandInfo);
2482             pattern->dragStatus_ = DragStatus::NONE;
2483             pattern->MarkContentChange();
2484             host->MarkDirtyNode(pattern->IsTextArea() ? PROPERTY_UPDATE_MEASURE : PROPERTY_UPDATE_MEASURE_SELF);
2485         }
2486         pattern->afterDragSelect_ = isMouseOrTouchPad(pattern->sourceTool_);
2487         pattern->releaseInDrop_ = true;
2488         FocusHub::LostFocusToViewRoot();
2489     };
2490 }
2491 
ShowSelectAfterDragEvent()2492 void TextFieldPattern::ShowSelectAfterDragEvent()
2493 {
2494     selectController_->UpdateHandleIndex(dragTextStart_, dragTextEnd_);
2495     showSelect_ = true;
2496     if (!IsUsingMouse()) {
2497         DelayProcessOverlay({ .menuIsShow = false });
2498     }
2499 }
2500 
InitDragDropEventWithOutDragStart()2501 void TextFieldPattern::InitDragDropEventWithOutDragStart()
2502 {
2503     auto host = GetHost();
2504     CHECK_NULL_VOID(host);
2505     auto gestureHub = host->GetOrCreateGestureEventHub();
2506     CHECK_NULL_VOID(gestureHub);
2507     gestureHub->InitDragDropEvent();
2508     auto eventHub = host->GetOrCreateEventHub<EventHub>();
2509     CHECK_NULL_VOID(eventHub);
2510     InitDragDropCallBack();
2511 }
2512 
InitDragDropEvent()2513 void TextFieldPattern::InitDragDropEvent()
2514 {
2515     auto host = GetHost();
2516     CHECK_NULL_VOID(host);
2517     auto gestureHub = host->GetOrCreateGestureEventHub();
2518     CHECK_NULL_VOID(gestureHub);
2519     gestureHub->InitDragDropEvent();
2520     auto callback = GetThumbnailCallback();
2521     gestureHub->SetThumbnailCallback(std::move(callback));
2522     auto eventHub = host->GetOrCreateEventHub<EventHub>();
2523     CHECK_NULL_VOID(eventHub);
2524     eventHub->SetDefaultOnDragStart(OnDragStart());
2525     InitDragDropCallBack();
2526     gestureHub->SetTextDraggable(true);
2527 }
2528 
InitDragDropCallBack()2529 void TextFieldPattern::InitDragDropCallBack()
2530 {
2531     auto host = GetHost();
2532     CHECK_NULL_VOID(host);
2533     auto eventHub = host->GetOrCreateEventHub<EventHub>();
2534     CHECK_NULL_VOID(eventHub);
2535     auto onDragEnter = [weakPtr = WeakClaim(this)](
2536                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2537         auto pattern = weakPtr.Upgrade();
2538         CHECK_NULL_VOID(pattern);
2539         auto host = pattern->GetHost();
2540         CHECK_NULL_VOID(host);
2541         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2542             "%{public}d TextField onDragEnter, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2543             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2544             static_cast<int32_t>(pattern->dragRecipientStatus_));
2545         CHECK_NULL_VOID(!pattern->IsDisabled());
2546         auto pipeline = pattern->GetContext();
2547         CHECK_NULL_VOID(pipeline);
2548         auto dragManager = pipeline->GetDragDropManager();
2549         CHECK_NULL_VOID(dragManager);
2550         if (pattern->IsNormalInlineState() || !dragManager->IsDropAllowed(host)) {
2551             return;
2552         }
2553         pattern->SetDragMovingScrollback();
2554         pattern->dragRecipientStatus_ = DragStatus::DRAGGING;
2555         pattern->ResetPreviewTextState();
2556         auto focusHub = pattern->GetFocusHub();
2557         CHECK_NULL_VOID(focusHub);
2558         if (pattern->dragStatus_ != DragStatus::DRAGGING) {
2559             pattern->CloseKeyboard(true, false);
2560         }
2561         if (pattern->TextFieldRequestFocus(RequestFocusReason::DRAG_ENTER)) {
2562             pattern->StartTwinkling();
2563             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2564                 "%{public}d TextField onDragEnter Request Focus Success", host->GetId());
2565         }
2566     };
2567     eventHub->SetOnDragEnter(std::move(onDragEnter));
2568 
2569     auto onDragMove = [weakPtr = WeakClaim(this)](
2570                           const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2571         auto pattern = weakPtr.Upgrade();
2572         CHECK_NULL_VOID(pattern);
2573         auto pipeline = pattern->GetContext();
2574         CHECK_NULL_VOID(pipeline);
2575         auto dragManager = pipeline->GetDragDropManager();
2576         CHECK_NULL_VOID(dragManager);
2577         auto host = pattern->GetHost();
2578         CHECK_NULL_VOID(host);
2579         CHECK_NULL_VOID(!pattern->IsDisabled());
2580 
2581         if (pattern->IsNormalInlineState() || !dragManager->IsDropAllowed(host)) {
2582             return;
2583         }
2584         if (!pattern->HasFocus()) {
2585             auto focusHub = pattern->GetFocusHub();
2586             CHECK_NULL_VOID(focusHub);
2587             if (pattern->TextFieldRequestFocus(RequestFocusReason::DRAG_MOVE)) {
2588                 pattern->StartTwinkling();
2589                 TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2590                     "%{public}d TextField onDragMove Request Focus Success", host->GetId());
2591             }
2592         }
2593         auto textPaintOffset = pattern->GetPaintRectGlobalOffset();
2594         Offset localOffset =
2595             Offset(event->GetX(), event->GetY()) - Offset(textPaintOffset.GetX(), textPaintOffset.GetY());
2596         if (host->GetDragPreviewOption().enableEdgeAutoScroll) {
2597             pattern->UpdateContentScroller(localOffset, AUTO_SCROLL_HOT_AREA_LONGPRESS_DURATION, false);
2598         } else {
2599             pattern->contentScroller_.OnBeforeScrollingCallback(localOffset);
2600             pattern->PauseContentScroll();
2601             pattern->contentScroller_.hotAreaOffset.reset();
2602         }
2603     };
2604     eventHub->SetOnDragMove(std::move(onDragMove));
2605 
2606     auto onDragLeave = [weakPtr = WeakClaim(this)](
2607                            const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
2608         auto pattern = weakPtr.Upgrade();
2609         CHECK_NULL_VOID(pattern);
2610         auto host = pattern->GetHost();
2611         CHECK_NULL_VOID(host);
2612         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2613             "%{public}d TextField onDragLeave, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2614             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2615             static_cast<int32_t>(pattern->dragRecipientStatus_));
2616         pattern->dragRecipientStatus_ = DragStatus::NONE;
2617         auto focusHub = pattern->GetFocusHub();
2618         CHECK_NULL_VOID(focusHub);
2619         focusHub->LostFocus();
2620         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2621             "%{public}d TextField onDragLeave Lost Focus", host->GetId());
2622         pattern->StopTwinkling();
2623         pattern->PauseContentScroll();
2624     };
2625     eventHub->SetOnDragLeave(std::move(onDragLeave));
2626 
2627     auto onDragEnd = [weakPtr = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event) {
2628         auto pattern = weakPtr.Upgrade();
2629         CHECK_NULL_VOID(pattern);
2630         auto host = pattern->GetHost();
2631         CHECK_NULL_VOID(host);
2632         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
2633             "%{public}d TextField onDragEnd, dragStatus_ is %{public}d, dragRecipientStatus_ is %{public}d",
2634             host->GetId(), static_cast<int32_t>(pattern->dragStatus_),
2635             static_cast<int32_t>(pattern->dragRecipientStatus_));
2636         pattern->StopContentScroll();
2637         ContainerScope scope(pattern->GetHostInstanceId());
2638         if (pattern->dragStatus_ == DragStatus::DRAGGING && !pattern->isDetachFromMainTree_) {
2639             pattern->dragStatus_ = DragStatus::NONE;
2640             pattern->MarkContentChange();
2641             // Except for DRAG_SUCCESS, all of rest need to show
2642             auto paintProperty = pattern->GetPaintProperty<TextFieldPaintProperty>();
2643             CHECK_NULL_VOID(paintProperty);
2644             auto newDragValue =
2645                 pattern->contentController_->GetSelectedValue(pattern->dragTextStart_, pattern->dragTextEnd_);
2646             auto focusHub = pattern->GetFocusHub();
2647             CHECK_NULL_VOID(focusHub);
2648             if (event != nullptr && event->GetResult() != DragRet::DRAG_SUCCESS &&
2649                 newDragValue == pattern->dragValue_ &&
2650                 paintProperty->GetInputStyleValue(InputStyle::DEFAULT) != InputStyle::INLINE &&
2651                 focusHub->IsFocusable()) {
2652                 pattern->ShowSelectAfterDragEvent();
2653                 pattern->afterDragSelect_ = true;
2654                 pattern->TextFieldRequestFocus(RequestFocusReason::DRAG_END);
2655             }
2656             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2657         }
2658         if (event != nullptr && event->GetResult() != DragRet::DRAG_SUCCESS) {
2659             pattern->afterDragSelect_ = true;
2660         }
2661         pattern->CloseKeyboard(true);
2662     };
2663     eventHub->SetOnDragEnd(std::move(onDragEnd));
2664 
2665     eventHub->SetOnDrop(OnDragDrop());
2666 }
2667 
ClearDragDropEvent()2668 void TextFieldPattern::ClearDragDropEvent()
2669 {
2670     auto host = GetHost();
2671     CHECK_NULL_VOID(host);
2672     auto gestureHub = host->GetOrCreateGestureEventHub();
2673     CHECK_NULL_VOID(gestureHub);
2674     gestureHub->SetTextDraggable(false);
2675     gestureHub->SetIsTextDraggable(false);
2676     auto eventHub = host->GetOrCreateEventHub<EventHub>();
2677     CHECK_NULL_VOID(eventHub);
2678     eventHub->SetOnDragStart(nullptr);
2679     eventHub->SetDefaultOnDragStart(nullptr);
2680     eventHub->SetOnDragEnter(nullptr);
2681     eventHub->SetOnDragMove(nullptr);
2682     eventHub->SetOnDragLeave(nullptr);
2683     eventHub->SetOnDragEnd(nullptr);
2684     eventHub->SetOnDrop(nullptr);
2685 }
2686 
HandleOnDragStatusCallback(const DragEventType & dragEventType,const RefPtr<NotifyDragEvent> & notifyDragEvent)2687 void TextFieldPattern::HandleOnDragStatusCallback(
2688     const DragEventType& dragEventType, const RefPtr<NotifyDragEvent>& notifyDragEvent)
2689 {
2690     ScrollablePattern::HandleOnDragStatusCallback(dragEventType, notifyDragEvent);
2691     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleOnDragStatusCallback dragEventType=%{public}d", dragEventType);
2692     if (dragEventType == DragEventType::DROP) {
2693         if (dragRecipientStatus_ == DragStatus::DRAGGING) {
2694             StopContentScroll();
2695             StopTwinkling();
2696         }
2697         dragRecipientStatus_ = DragStatus::NONE;
2698     }
2699 }
2700 
InitTouchEvent()2701 void TextFieldPattern::InitTouchEvent()
2702 {
2703     CHECK_NULL_VOID(!touchListener_);
2704     auto host = GetHost();
2705     CHECK_NULL_VOID(host);
2706 
2707     auto gesture = host->GetOrCreateGestureEventHub();
2708     CHECK_NULL_VOID(gesture);
2709     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
2710         auto pattern = weak.Upgrade();
2711         CHECK_NULL_VOID(pattern);
2712         pattern->selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
2713         pattern->selectOverlay_->SetLastSourceType(info.GetSourceDevice());
2714         pattern->HandleTouchEvent(info);
2715     };
2716     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
2717     gesture->AddTouchEvent(touchListener_);
2718 }
2719 
IsHandleDragging()2720 bool TextFieldPattern::IsHandleDragging()
2721 {
2722     CHECK_NULL_RETURN(selectOverlay_, false);
2723     return selectOverlay_->GetIsHandleDragging();
2724 }
2725 
InitClickEvent()2726 void TextFieldPattern::InitClickEvent()
2727 {
2728     CHECK_NULL_VOID(!clickListener_);
2729     auto tmpHost = GetHost();
2730     CHECK_NULL_VOID(tmpHost);
2731     auto gesture = tmpHost->GetOrCreateGestureEventHub();
2732     auto clickCallback = [weak = WeakClaim(this)](GestureEvent& info) {
2733         auto pattern = weak.Upgrade();
2734         CHECK_NULL_VOID(pattern);
2735         pattern->HandleClickEvent(info);
2736     };
2737 
2738     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
2739     gesture->AddClickEvent(clickListener_);
2740 }
2741 
HandleClickEvent(GestureEvent & info)2742 void TextFieldPattern::HandleClickEvent(GestureEvent& info)
2743 {
2744     CHECK_NULL_VOID(!IsDragging());
2745     CHECK_NULL_VOID(!IsHandleDragging());
2746     parentGlobalOffset_ = GetPaintRectGlobalOffset();
2747     auto focusHub = GetFocusHub();
2748     CHECK_NULL_VOID(focusHub);
2749     CHECK_NULL_VOID(selectOverlay_);
2750     auto multipleClickRecognizer = GetOrCreateMultipleClickRecognizer();
2751     CHECK_NULL_VOID(multipleClickRecognizer);
2752     if ((selectOverlay_->IsClickAtHandle(info) && !multipleClickRecognizer->IsValidClick(info)) ||
2753         !focusHub->IsFocusable()) {
2754         return;
2755     }
2756     focusIndex_ = FocuseIndex::TEXT;
2757     auto firstGetFocus = false;
2758     if (!HasFocus()) {
2759         auto host = GetHost();
2760         CHECK_NULL_VOID(host);
2761         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d request focus currently", host->GetId());
2762         firstGetFocus = true;
2763         if (!focusHub->IsFocusOnTouch().value_or(true) || !TextFieldRequestFocus(RequestFocusReason::CLICK)) {
2764             CloseSelectOverlay(true);
2765             StopTwinkling();
2766             return;
2767         }
2768     }
2769     firstGetFocus = firstGetFocus || firstClickAfterLosingFocus_;
2770     firstClickAfterLosingFocus_ = false;
2771     if (!firstGetFocus && CheckMousePressedOverScrollBar(info)) {
2772         return;
2773     }
2774     selectOverlay_->SetLastSourceType(info.GetSourceDevice());
2775     selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
2776     lastClickTimeStamp_ = info.GetTimeStamp();
2777     multipleClickRecognizer->StartCounting(info);
2778     // register click event
2779     if (multipleClickRecognizer->IsTripleClick()) {
2780         HandleTripleClickEvent(info);
2781     } else if (multipleClickRecognizer->IsDoubleClick()) {
2782         HandleDoubleClickEvent(info);
2783     } else {
2784         HandleSingleClickEvent(info, firstGetFocus);
2785     }
2786     if (ResetObscureTickCountDown()) {
2787         auto host = GetHost();
2788         CHECK_NULL_VOID(host);
2789         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2790     }
2791     isFocusedBeforeClick_ = false;
2792 }
2793 
CheckMousePressedOverScrollBar(GestureEvent & info)2794 bool TextFieldPattern::CheckMousePressedOverScrollBar(GestureEvent& info)
2795 {
2796     if (IsMouseOverScrollBar(&info) && hasMousePressed_) {
2797         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2798         CHECK_NULL_RETURN(layoutProperty, false);
2799         if (layoutProperty->GetDisplayModeValue(DisplayMode::AUTO) != DisplayMode::OFF) {
2800             auto touchRegion = GetScrollBar()->GetTouchRegion();
2801             bool reverse = info.GetLocalLocation().GetY() < touchRegion.Top();
2802             ScrollPage(reverse);
2803             return true;
2804         }
2805     }
2806     return false;
2807 }
2808 
HandleBetweenSelectedPosition(const GestureEvent & info)2809 bool TextFieldPattern::HandleBetweenSelectedPosition(const GestureEvent& info)
2810 {
2811     if (!IsUsingMouse() && SelectOverlayIsOn() && BetweenSelectedPosition(info.GetGlobalLocation())) {
2812         CHECK_NULL_RETURN(selectOverlay_, false);
2813         // click selected area to switch show/hide state
2814         selectOverlay_->ToggleMenu();
2815         return true;
2816     }
2817     return false;
2818 }
2819 
HandleSingleClickEvent(GestureEvent & info,bool firstGetFocus)2820 void TextFieldPattern::HandleSingleClickEvent(GestureEvent& info, bool firstGetFocus)
2821 {
2822     if (mouseStatus_ != MouseStatus::NONE && IsNormalInlineState()) {
2823         return;
2824     }
2825     if (HandleBetweenSelectedPosition(info)) {
2826         selectOverlay_->SwitchToOverlayMode();
2827         return;
2828     }
2829     auto host = GetHost();
2830     CHECK_NULL_VOID(host);
2831     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2832     auto lastCaretIndex = selectController_->GetCaretIndex();
2833     auto clickLocalOffset = GetCaretClickLocalOffset(info.GetLocalLocation());
2834     if (mouseStatus_ != MouseStatus::MOVE) {
2835         UpdateCaretByClick(clickLocalOffset);
2836     }
2837     StartTwinkling();
2838     SetIsSingleHandle(true);
2839     bool needCloseOverlay = true;
2840     bool isRepeatClickCaret = RepeatClickCaret(clickLocalOffset, lastCaretIndex) && !firstGetFocus;
2841     bool isInlineSelectAllOrEmpty = inlineSelectAllFlag_ || contentController_->IsEmpty();
2842     auto clickBlank = contentController_->IsEmpty() || selectController_->IsTouchAtLineEnd(info.GetLocalLocation());
2843     auto closeHandleAtBlank =
2844         clickBlank && isRepeatClickCaret && SelectOverlayIsOn() && selectOverlay_->IsSingleHandle();
2845     do {
2846         if (info.GetSourceDevice() == SourceType::MOUSE || (!isRepeatClickCaret && isInlineSelectAllOrEmpty) ||
2847             IsContentRectNonPositive() || closeHandleAtBlank) {
2848             break;
2849         }
2850         if (isRepeatClickCaret) {
2851             if (IsAccessibilityClick()) {
2852                 break;
2853             }
2854             ProcessOverlay({ .animation = true });
2855             needCloseOverlay = false;
2856         } else if (needSelectAll_) {
2857             HandleOnSelectAll(false);
2858         }
2859     } while (false);
2860     if (needCloseOverlay || GetIsPreviewText()) {
2861         CloseSelectOverlay(true);
2862         StartTwinkling();
2863     }
2864     DoProcessAutoFill(info.GetSourceDevice());
2865     // emulate clicking bottom of the textField
2866     UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
2867     TriggerAvoidOnCaretChange();
2868     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2869 }
2870 
DoProcessAutoFill(SourceType sourceType)2871 void TextFieldPattern::DoProcessAutoFill(SourceType sourceType)
2872 {
2873     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "DoProcessAutoFill");
2874     if (!IsNeedProcessAutoFill()) {
2875         if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SINGLE_CLICK, sourceType)) {
2876             NotifyOnEditChanged(true);
2877         }
2878         return;
2879     }
2880     bool isPopup = false;
2881     auto isSuccess = ProcessAutoFill(isPopup);
2882     if (!isPopup && isSuccess) {
2883         SetNeedToRequestKeyboardInner(false, RequestKeyboardInnerChangeReason::AUTOFILL_PROCESS);
2884     } else if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SINGLE_CLICK, sourceType)) {
2885         NotifyOnEditChanged(true);
2886     }
2887 }
2888 
IsAutoFillPasswordType(const AceAutoFillType & autoFillType)2889 bool TextFieldPattern::IsAutoFillPasswordType(const AceAutoFillType& autoFillType)
2890 {
2891     return (autoFillType == AceAutoFillType::ACE_USER_NAME || autoFillType == AceAutoFillType::ACE_PASSWORD ||
2892             autoFillType == AceAutoFillType::ACE_NEW_PASSWORD);
2893 }
2894 
GetHintType()2895 HintToTypeWrap TextFieldPattern::GetHintType()
2896 {
2897     HintToTypeWrap hintToTypeWrap;
2898     auto container = Container::Current();
2899     CHECK_NULL_RETURN(container, hintToTypeWrap);
2900     auto onePlaceHolder = UtfUtils::Str16DebugToStr8(GetPlaceHolder());
2901     if (onePlaceHolder.empty()) {
2902         return hintToTypeWrap;
2903     }
2904     return container->PlaceHolderToType(onePlaceHolder);
2905 }
2906 
CheckAutoFillType(const AceAutoFillType & autoFillType,bool isFromKeyBoard)2907 bool TextFieldPattern::CheckAutoFillType(const AceAutoFillType& autoFillType, bool isFromKeyBoard)
2908 {
2909     if (isFromKeyBoard) {
2910         return true;
2911     }
2912 
2913     auto container = Container::Current();
2914     CHECK_NULL_RETURN(container, false);
2915     auto isTriggerPassword = IsTriggerAutoFillPassword();
2916     if (autoFillType == AceAutoFillType::ACE_UNSPECIFIED && !isTriggerPassword) {
2917         return false;
2918     } else if (isTriggerPassword) {
2919         auto tempAutoFillType = IsAutoFillUserName(autoFillType) ? AceAutoFillType::ACE_USER_NAME : autoFillType;
2920         if (!container->IsNeedToCreatePopupWindow(tempAutoFillType)) {
2921             return GetAutoFillTriggeredStateByType(autoFillType);
2922         }
2923     }
2924     return true;
2925 }
2926 
GetAutoFillTriggeredStateByType(const AceAutoFillType & autoFillType)2927 bool TextFieldPattern::GetAutoFillTriggeredStateByType(const AceAutoFillType& autoFillType)
2928 {
2929     auto host = GetHost();
2930     CHECK_NULL_RETURN(host, false);
2931     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
2932     CHECK_NULL_RETURN(autoFillContainerNode, false);
2933     auto stateHolder = autoFillContainerNode->GetPattern<AutoFillTriggerStateHolder>();
2934     CHECK_NULL_RETURN(stateHolder, false);
2935     if (IsAutoFillUserName(autoFillType) || autoFillType == AceAutoFillType::ACE_PASSWORD) {
2936         return !stateHolder->IsAutoFillPasswordTriggered();
2937     }
2938     if (autoFillType == AceAutoFillType::ACE_NEW_PASSWORD) {
2939         return !stateHolder->IsAutoFillNewPasswordTriggered();
2940     }
2941     return false;
2942 }
2943 
SetAutoFillTriggeredStateByType(const AceAutoFillType & autoFillType)2944 void TextFieldPattern::SetAutoFillTriggeredStateByType(const AceAutoFillType& autoFillType)
2945 {
2946     auto host = GetHost();
2947     CHECK_NULL_VOID(host);
2948     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
2949     CHECK_NULL_VOID(autoFillContainerNode);
2950     auto stateHolder = autoFillContainerNode->GetPattern<AutoFillTriggerStateHolder>();
2951     CHECK_NULL_VOID(stateHolder);
2952     if (IsAutoFillUserName(autoFillType) || autoFillType == AceAutoFillType::ACE_PASSWORD) {
2953         stateHolder->SetAutoFillPasswordTriggered(true);
2954     } else if (autoFillType == AceAutoFillType::ACE_NEW_PASSWORD) {
2955         stateHolder->SetAutoFillNewPasswordTriggered(true);
2956     }
2957 }
2958 
GetAutoFillType(bool isNeedToHitType)2959 AceAutoFillType TextFieldPattern::GetAutoFillType(bool isNeedToHitType)
2960 {
2961     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2962     CHECK_NULL_RETURN(layoutProperty, AceAutoFillType::ACE_UNSPECIFIED);
2963     auto aceContentType =
2964         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
2965     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2966     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
2967         return aceContentType;
2968     }
2969     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
2970         return aceInputType;
2971     }
2972     if (isNeedToHitType && !IsTriggerAutoFillPassword()) {
2973         auto hintToTypeWrap = GetHintType();
2974         return hintToTypeWrap.autoFillType;
2975     }
2976     return AceAutoFillType::ACE_UNSPECIFIED;
2977 }
2978 
GetAutoFillTypeAndMetaData(bool isNeedToHitType)2979 HintToTypeWrap TextFieldPattern::GetAutoFillTypeAndMetaData(bool isNeedToHitType)
2980 {
2981     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
2982     HintToTypeWrap hintToTypeWrap;
2983     CHECK_NULL_RETURN(layoutProperty, hintToTypeWrap);
2984     auto aceContentType =
2985         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
2986     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
2987     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
2988         hintToTypeWrap.autoFillType = aceContentType;
2989         return hintToTypeWrap;
2990     }
2991     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
2992         hintToTypeWrap.autoFillType = aceInputType;
2993         return hintToTypeWrap;
2994     }
2995     if (isNeedToHitType && !IsTriggerAutoFillPassword()) {
2996         hintToTypeWrap = GetHintType();
2997         return hintToTypeWrap;
2998     }
2999     auto jsonValue = JsonUtil::Create(true);
3000     jsonValue->Put("type", TextInputTypeToString().c_str());
3001     hintToTypeWrap.metadata = jsonValue->ToString();
3002     return hintToTypeWrap;
3003 }
3004 
CheckAutoFill(bool isFromKeyBoard)3005 bool TextFieldPattern::CheckAutoFill(bool isFromKeyBoard)
3006 {
3007     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3008     CHECK_NULL_RETURN(layoutProperty, false);
3009     bool isEnableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
3010     if (!isEnableAutoFill) {
3011         return false;
3012     }
3013     return CheckAutoFillType(GetAutoFillType(), isFromKeyBoard);
3014 }
3015 
ProcessAutoFill(bool & isPopup,bool isFromKeyBoard,bool isNewPassWord)3016 bool TextFieldPattern::ProcessAutoFill(bool& isPopup, bool isFromKeyBoard, bool isNewPassWord)
3017 {
3018     if (!CheckAutoFill(isFromKeyBoard)) {
3019         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "don't need to auto fill.");
3020         return false;
3021     }
3022     auto host = GetHost();
3023     CHECK_NULL_RETURN(host, false);
3024     auto autoFillType = GetAutoFillType();
3025     auto container = Container::Current();
3026     if (container == nullptr) {
3027         TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "Get current container is nullptr.");
3028         return false;
3029     }
3030     if (IsTriggerAutoFillPassword() && autoFillType == AceAutoFillType::ACE_UNSPECIFIED) {
3031         autoFillType = AceAutoFillType::ACE_USER_NAME;
3032     }
3033     auto onUIExtNodeDestroy = [weak = WeakPtr<FrameNode>(host)]() {
3034         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "onUIExtNodeDestroy called.");
3035         auto textFieldNode = weak.Upgrade();
3036         CHECK_NULL_VOID(textFieldNode);
3037         auto pageNode = textFieldNode->GetPageNode();
3038         CHECK_NULL_VOID(pageNode);
3039         auto pagePattern = pageNode->GetPattern<PagePattern>();
3040         CHECK_NULL_VOID(pagePattern);
3041         pagePattern->SetIsModalCovered(false);
3042     };
3043     auto onUIExtNodeBindingCompleted = [weak = WeakPtr<FrameNode>(host)]() {
3044         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "onUIExtNodeBindingCompleted called.");
3045         auto textFieldNode = weak.Upgrade();
3046         CHECK_NULL_VOID(textFieldNode);
3047         auto pageNode = textFieldNode->GetPageNode();
3048         CHECK_NULL_VOID(pageNode);
3049         auto pagePattern = pageNode->GetPattern<PagePattern>();
3050         CHECK_NULL_VOID(pagePattern);
3051         pagePattern->SetIsModalCovered(true);
3052     };
3053 
3054     auto resultCode = container->RequestAutoFill(host, autoFillType, isNewPassWord, isPopup, autoFillSessionId_, true,
3055         onUIExtNodeDestroy, onUIExtNodeBindingCompleted);
3056     if (resultCode != AceAutoFillError::ACE_AUTO_FILL_PREVIOUS_REQUEST_NOT_FINISHED) {
3057         SetAutoFillTriggeredStateByType(autoFillType);
3058         SetFillRequestFinish(false);
3059     }
3060     return resultCode == AceAutoFillError::ACE_AUTO_FILL_SUCCESS;
3061 }
3062 
HandleDoubleClickEvent(GestureEvent & info)3063 void TextFieldPattern::HandleDoubleClickEvent(GestureEvent& info)
3064 {
3065     if (GetIsPreviewText()) {
3066         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "refuse double click when has preview text.");
3067         return;
3068     }
3069 
3070     if (showSelect_) {
3071         SetIsSingleHandle(true);
3072     }
3073     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::DOUBLE_CLICK)) {
3074         NotifyOnEditChanged(true);
3075     }
3076     if (CanChangeSelectState()) {
3077         selectController_->UpdateSelectByOffset(info.GetLocalLocation());
3078         UpdateCaretInfoToController();
3079     }
3080     if (IsSelected()) {
3081         StopTwinkling();
3082         SetIsSingleHandle(false);
3083     }
3084     if (info.GetSourceDevice() != SourceType::MOUSE && !IsContentRectNonPositive()) {
3085         ProcessOverlay({ .animation = true });
3086     }
3087     auto host = GetHost();
3088     CHECK_NULL_VOID(host);
3089     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3090 }
3091 
HandleTripleClickEvent(GestureEvent & info)3092 void TextFieldPattern::HandleTripleClickEvent(GestureEvent& info)
3093 {
3094     if (GetIsPreviewText()) {
3095         return;
3096     }
3097 
3098     if (showSelect_) {
3099         SetIsSingleHandle(true);
3100         CloseSelectOverlay();
3101     }
3102     if (CanChangeSelectState()) {
3103         selectController_->UpdateSelectPragraphByOffset(info.GetLocalLocation());
3104         UpdateCaretInfoToController();
3105     }
3106     if (IsSelected()) {
3107         StopTwinkling();
3108         SetIsSingleHandle(false);
3109     } else {
3110         StartTwinkling();
3111     }
3112     if (info.GetSourceDevice() != SourceType::MOUSE && !contentController_->IsEmpty() && !IsContentRectNonPositive()) {
3113         ProcessOverlay({ .animation = true });
3114     }
3115     auto host = GetHost();
3116     CHECK_NULL_VOID(host);
3117     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3118 }
3119 
ScheduleCursorTwinkling()3120 void TextFieldPattern::ScheduleCursorTwinkling()
3121 {
3122     if (isTransparent_) {
3123         return;
3124     }
3125     auto host = GetHost();
3126     CHECK_NULL_VOID(host);
3127     auto context = host->GetContext();
3128     CHECK_NULL_VOID(context);
3129 
3130     if (!context->GetTaskExecutor()) {
3131         return;
3132     }
3133 
3134     if (dragRecipientStatus_ == DragStatus::DRAGGING) {
3135         return;
3136     }
3137 
3138     auto weak = WeakClaim(this);
3139     cursorTwinklingTask_.Reset([weak] {
3140         auto client = weak.Upgrade();
3141         CHECK_NULL_VOID(client);
3142         client->OnCursorTwinkling();
3143     });
3144     auto taskExecutor = context->GetTaskExecutor();
3145     CHECK_NULL_VOID(taskExecutor);
3146     taskExecutor->PostDelayedTask(cursorTwinklingTask_, TaskExecutor::TaskType::UI, twinklingInterval_,
3147         "ArkUITextFieldCursorTwinkling");
3148 }
3149 
StartTwinkling()3150 void TextFieldPattern::StartTwinkling()
3151 {
3152     auto autoFillController = GetOrCreateAutoFillController();
3153     auto autoFillAnimationStatus =
3154         autoFillController ? autoFillController->GetAutoFillAnimationStatus() : AutoFillAnimationStatus::INIT;
3155     if (isTransparent_ || !HasFocus() || focusIndex_ == FocuseIndex::CANCEL || focusIndex_ == FocuseIndex::UNIT ||
3156         autoFillAnimationStatus != AutoFillAnimationStatus::INIT) {
3157         return;
3158     }
3159     // Ignore the result because all ops are called on this same thread (ACE UI).
3160     // The only reason failed is that the task has finished.
3161     cursorTwinklingTask_.Cancel();
3162 
3163     // Show cursor right now.
3164     isCaretTwinkling_ = true;
3165     cursorVisible_ = true;
3166     auto tmpHost = GetHost();
3167     CHECK_NULL_VOID(tmpHost);
3168     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3169     ScheduleCursorTwinkling();
3170 }
3171 
OnCursorTwinkling()3172 void TextFieldPattern::OnCursorTwinkling()
3173 {
3174     cursorTwinklingTask_.Cancel();
3175     cursorVisible_ = !cursorVisible_;
3176     auto shouldMeasure = !IsTextArea() && IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ == 1;
3177     if (IsInPasswordMode() && GetTextObscured() && obscureTickCountDown_ > 0) {
3178         --obscureTickCountDown_;
3179     }
3180     auto host = GetHost();
3181     CHECK_NULL_VOID(host);
3182     if (shouldMeasure) {
3183         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3184     } else {
3185         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3186     }
3187     ScheduleCursorTwinkling();
3188 }
3189 
StopTwinkling()3190 void TextFieldPattern::StopTwinkling()
3191 {
3192     cursorTwinklingTask_.Cancel();
3193 
3194     // Repaint only if cursor is visible for now.
3195     isCaretTwinkling_ = false;
3196     auto tmpHost = GetHost();
3197     CHECK_NULL_VOID(tmpHost);
3198     if (cursorVisible_) {
3199         cursorVisible_ = false;
3200         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3201     }
3202     if (ResetObscureTickCountDown()) {
3203         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3204     }
3205 }
3206 
ShowCaretAndStopTwinkling()3207 void TextFieldPattern::ShowCaretAndStopTwinkling()
3208 {
3209     cursorTwinklingTask_.Cancel();
3210 
3211     // Repaint and make cursor visible.
3212     isCaretTwinkling_ = false;
3213     auto tmpHost = GetHost();
3214     CHECK_NULL_VOID(tmpHost);
3215     cursorVisible_ = true;
3216     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3217     if (ResetObscureTickCountDown()) {
3218         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3219     }
3220 }
3221 
CheckIfNeedToResetKeyboard()3222 void TextFieldPattern::CheckIfNeedToResetKeyboard()
3223 {
3224     auto tmpHost = GetHost();
3225     CHECK_NULL_VOID(tmpHost);
3226     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3227     CHECK_NULL_VOID(layoutProperty);
3228     bool needToResetKeyboard = false;
3229     // check unspecified for first time entrance
3230     if (keyboard_ != layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
3231         auto autoFillType = GetAutoFillType(false);
3232         if (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) != TextInputType::UNSPECIFIED ||
3233             keyBoardMap_.find(autoFillType) == keyBoardMap_.end() || keyboard_ != keyBoardMap_[autoFillType]) {
3234             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Keyboard type %{public}d changed to %{public}d",
3235                 tmpHost->GetId(), (int)keyboard_, layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
3236             keyboard_ = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
3237             ResetPreviewTextState();
3238             needToResetKeyboard = true;
3239         }
3240     }
3241     if (!needToResetKeyboard && action_ != TextInputAction::UNSPECIFIED) {
3242         needToResetKeyboard = action_ != GetTextInputActionValue(GetDefaultTextInputAction());
3243     }
3244     action_ = GetTextInputActionValue(GetDefaultTextInputAction());
3245 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
3246     if (needToResetKeyboard && HasFocus()) {
3247         if (isCustomKeyboardAttached_ || keyboard_ == TextInputType::ONE_TIME_CODE) {
3248             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::RESET_KEYBOARD);
3249             return;
3250         }
3251 #if defined(ENABLE_STANDARD_INPUT)
3252         auto inputMethod = MiscServices::InputMethodController::GetInstance();
3253         CHECK_NULL_VOID(inputMethod);
3254         MiscServices::Configuration config;
3255         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Keyboard action is %{public}d",
3256             tmpHost->GetId(), action_);
3257         config.SetEnterKeyType(static_cast<MiscServices::EnterKeyType>(action_));
3258         config.SetTextInputType(static_cast<MiscServices::TextInputType>(keyboard_));
3259         inputMethod->OnConfigurationChange(config);
3260 #endif
3261     }
3262 #else
3263     if (needToResetKeyboard && HasConnection()) {
3264         CloseKeyboard(true);
3265         RequestKeyboard(false, true, true);
3266     }
3267 #endif
3268 }
3269 
ProcessScroll()3270 void TextFieldPattern::ProcessScroll()
3271 {
3272     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3273     CHECK_NULL_VOID(layoutProperty);
3274     if (IsTextArea() || IsNormalInlineState()) {
3275         SetAxis(Axis::VERTICAL);
3276         if (!GetScrollableEvent()) {
3277             AddScrollEvent();
3278         }
3279         auto barState = layoutProperty->GetDisplayModeValue(DisplayMode::AUTO);
3280         if (!barState_.has_value()) {
3281             barState_ = barState;
3282         }
3283         scrollBarVisible_ = barState != DisplayMode::OFF;
3284         SetScrollBar(barState == DisplayMode::OFF ? DisplayMode::ON : barState);
3285         auto scrollBar = GetScrollBar();
3286         if (scrollBar) {
3287             scrollBar->SetMinHeight(SCROLL_BAR_MIN_HEIGHT);
3288         }
3289         if (textFieldOverlayModifier_) {
3290             textFieldOverlayModifier_->SetScrollBar(scrollBar);
3291             UpdateScrollBarOffset();
3292         }
3293     } else {
3294         SetAxis(Axis::HORIZONTAL);
3295         SetScrollBar(DisplayMode::OFF);
3296         if (!GetScrollableEvent()) {
3297             AddScrollEvent();
3298             SetScrollEnabled(false);
3299         }
3300     }
3301 }
3302 
HandleDeleteOnCounterScene()3303 void TextFieldPattern::HandleDeleteOnCounterScene()
3304 {
3305     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3306     CHECK_NULL_VOID(layoutProperty);
3307     if (layoutProperty->HasMaxLength()) {
3308         showCountBorderStyle_ = false;
3309         HandleCountStyle();
3310     }
3311 }
3312 
HandleCountStyle()3313 void TextFieldPattern::HandleCountStyle()
3314 {
3315     bool noDeleteOperation = deleteBackwardOperations_.empty() && deleteForwardOperations_.empty();
3316     if (!IsShowCount() || !noDeleteOperation) {
3317         return;
3318     }
3319     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3320     CHECK_NULL_VOID(layoutProperty);
3321     auto inputValue = layoutProperty->GetSetCounterValue(DEFAULT_MODE);
3322     auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
3323     if (inputValue == DEFAULT_MODE) {
3324         if (showBorder) {
3325             HandleCounterBorder();
3326         }
3327         if (showCountBorderStyle_ && !showBorder) {
3328             UltralimitShake();
3329         }
3330     } else if (inputValue != ILLEGAL_VALUE) {
3331         if (showBorder) {
3332             HandleCounterBorder();
3333         }
3334         if (showCountBorderStyle_) {
3335             UltralimitShake();
3336         }
3337     }
3338 }
3339 
ProcessUnderlineColorOnModifierDone()3340 void TextFieldPattern::ProcessUnderlineColorOnModifierDone()
3341 {
3342     if (IsShowError()) {
3343         return;
3344     }
3345     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3346     auto inputValue = layoutProperty->GetSetCounterValue(DEFAULT_MODE);
3347     if (inputValue == ILLEGAL_VALUE) {
3348         return;
3349     }
3350     auto showBorder = layoutProperty->GetShowHighlightBorderValue(true);
3351     if (inputValue != DEFAULT_MODE && !showBorder) {
3352         return;
3353     }
3354     if (showCountBorderStyle_ && IsUnderlineMode() && HasFocus()) {
3355         auto theme = GetTheme();
3356         CHECK_NULL_VOID(theme);
3357         SetUnderlineColor(
3358             userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor()));
3359     }
3360 }
3361 
ProcessCounter()3362 void TextFieldPattern::ProcessCounter()
3363 {
3364     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3365     CHECK_NULL_VOID(layoutProperty);
3366     if (IsShowCount()) {
3367         AddCounterNode();
3368         CHECK_NULL_VOID(counterDecorator_);
3369         counterDecorator_->UpdateTextFieldMargin();
3370     } else {
3371         CleanCounterNode();
3372     }
3373 }
3374 
ProcessSelection()3375 void TextFieldPattern::ProcessSelection()
3376 {
3377     auto textWidth = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
3378     if (SelectOverlayIsOn()) {
3379         needToRefreshSelectOverlay_ = textWidth > 0;
3380         UpdateSelection(std::clamp(selectController_->GetStartIndex(), 0, textWidth),
3381             std::clamp(selectController_->GetEndIndex(), 0, textWidth));
3382         SetIsSingleHandle(!IsSelected());
3383         selectOverlay_->UpdateHandleColor();
3384         if (isTextChangedAtCreation_ && textWidth == 0) {
3385             CloseSelectOverlay();
3386             StartTwinkling();
3387         }
3388         if (!isTextChangedAtCreation_ && selectOverlay_->IsShowMouseMenu()) {
3389             needToRefreshSelectOverlay_ = false;
3390         }
3391         return;
3392     }
3393     if (HasFocus()) {
3394         if (IsGestureSelectingText()) {
3395             UpdateSelection(std::clamp(selectController_->GetStartIndex(), 0, textWidth),
3396                 std::clamp(selectController_->GetEndIndex(), 0, textWidth));
3397         }
3398         if (!IsSelected()) {
3399             StartTwinkling();
3400         }
3401         return;
3402     }
3403     needToRefreshSelectOverlay_ = false;
3404 }
3405 
UpdateSelectOverlay(const RefPtr<OHOS::Ace::TextFieldTheme> & textFieldTheme)3406 void TextFieldPattern::UpdateSelectOverlay(const RefPtr<OHOS::Ace::TextFieldTheme>& textFieldTheme)
3407 {
3408     CHECK_NULL_VOID(textFieldTheme);
3409     auto container = Container::Current();
3410     if (container && container->IsSceneBoardWindow()) {
3411         return;
3412     }
3413     selectOverlay_->SetMenuTranslateIsSupport(textFieldTheme->GetTranslateIsSupport());
3414     selectOverlay_->SetIsSupportMenuSearch(textFieldTheme->GetIsSupportSearch());
3415 }
3416 
OnModifyDone()3417 void TextFieldPattern::OnModifyDone()
3418 {
3419     auto host = GetHost();
3420     Pattern::OnModifyDone();
3421     CHECK_NULL_VOID(host);
3422     auto context = host->GetContext();
3423     CHECK_NULL_VOID(context);
3424     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3425     CHECK_NULL_VOID(layoutProperty);
3426     auto textFieldTheme = GetTheme();
3427     CHECK_NULL_VOID(textFieldTheme);
3428     directionKeysMoveFocusOut_ = textFieldTheme->GetDirectionKeysMoveFocusOut();
3429     CheckIfNeedToResetKeyboard();
3430     auto renderContext = host->GetRenderContext();
3431     CHECK_NULL_VOID(renderContext);
3432     auto textFieldPaintProperty = host->GetPaintPropertyPtr<TextFieldPaintProperty>();
3433     if (textFieldPaintProperty && textFieldPaintProperty->HasBorderColorFlagByUser()) {
3434         textFieldPaintProperty->UpdateBorderColorFlagByUser(
3435             renderContext->GetBorderColorValue(BorderColorProperty {}));
3436     }
3437     isTransparent_ = renderContext->GetOpacityValue(1.0f) == 0.0f;
3438     ApplyNormalTheme();
3439     ApplyUnderlineTheme();
3440     ApplyInlineTheme();
3441     ProcessInnerPadding();
3442     ProcessNumberOfLines();
3443 
3444     InitClickEvent();
3445     InitLongPressEvent();
3446     InitFocusEvent();
3447     InitMouseEvent();
3448     InitTouchEvent();
3449 
3450     SetAccessibilityAction();
3451     FilterInitializeText();
3452     InitDisableColor();
3453     ProcessResponseArea();
3454     if (!shiftFlag_) {
3455         InitDragEvent();
3456     }
3457     Register2DragDropManager();
3458     ProcessUnderlineColorOnModifierDone();
3459     if (barState_.has_value() && barState_.value() != layoutProperty->GetDisplayModeValue(DisplayMode::AUTO) &&
3460         HasFocus() && IsNormalInlineState()) {
3461         lastTextRectY_ = textRect_.GetY();
3462     }
3463     if (!IsDisabled() && IsShowError()) {
3464         SetShowError();
3465     } else {
3466         CleanErrorNode();
3467     }
3468     // The textRect position can't be changed by only redraw.
3469     if (!initTextRect_) {
3470         auto border = GetBorderWidthProperty();
3471         textRect_.SetLeft(GetPaddingLeft() + GetBorderLeft(border));
3472         textRect_.SetTop(GetPaddingTop() + GetBorderTop(border));
3473         AdjustTextRectByCleanNode(textRect_);
3474         initTextRect_ = true;
3475     }
3476     CalculateDefaultCursor();
3477 
3478     ProcessSelection();
3479     isTextChangedAtCreation_ = false;
3480     if (layoutProperty->GetTypeChangedValue(false)) {
3481         layoutProperty->ResetTypeChanged();
3482         ClearOperationRecords();
3483     }
3484     ProcessScroll();
3485     ProcessCounter();
3486     Register2DragDropManager();
3487     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
3488     if (autoFillContainerNode) {
3489         UpdateTextFieldInfo();
3490     }
3491     TriggerAvoidWhenCaretGoesDown();
3492     UpdateSelectOverlay(textFieldTheme);
3493     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3494     SetIsEnableSubWindowMenu();
3495     isModifyDone_ = true;
3496     if (host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
3497         InitCancelButtonMouseEvent();
3498         InitPasswordButtonMouseEvent();
3499     }
3500 }
3501 
TriggerAvoidWhenCaretGoesDown()3502 void TextFieldPattern::TriggerAvoidWhenCaretGoesDown()
3503 {
3504     auto host = GetHost();
3505     CHECK_NULL_VOID(host);
3506     auto context = host->GetContext();
3507     CHECK_NULL_VOID(context);
3508     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
3509     if (context->UsingCaretAvoidMode() && HasFocus() && textFieldManager) {
3510         context->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
3511             auto textField = weak.Upgrade();
3512             CHECK_NULL_VOID(textField);
3513             auto textFieldManager = manager.Upgrade();
3514             CHECK_NULL_VOID(textFieldManager);
3515             auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
3516             auto lastCaretPos = textField->GetLastCaretPos();
3517             if (!lastCaretPos.has_value() ||
3518                 (caretPos > lastCaretPos.value() && textField->CheckIfNeedAvoidOnCaretChange(caretPos))) {
3519                 TAG_LOGI(ACE_KEYBOARD, "Caret Position Goes Down, Retrigger Avoid");
3520                 textField->TriggerAvoidOnCaretChange();
3521             }
3522         });
3523     }
3524 }
3525 
CheckIfNeedAvoidOnCaretChange(float caretPos)3526 bool TextFieldPattern::CheckIfNeedAvoidOnCaretChange(float caretPos)
3527 {
3528 #if defined(ENABLE_STANDARD_INPUT)
3529     auto host = GetHost();
3530     CHECK_NULL_RETURN(host, true);
3531     auto pipeline = host->GetContext();
3532     CHECK_NULL_RETURN(pipeline, true);
3533     auto safeAreaMgr = pipeline->GetSafeAreaManager();
3534     CHECK_NULL_RETURN(safeAreaMgr, true);
3535     auto keyboard = safeAreaMgr->GetKeyboardInset();
3536     return keyboard.Length() > 0 && GreatNotEqual(caretPos, keyboard.start - AVOID_OFFSET.ConvertToPx());
3537 #else
3538     return true;
3539 #endif
3540 }
3541 
ApplyNormalTheme()3542 void TextFieldPattern::ApplyNormalTheme()
3543 {
3544     if (IsUnderlineMode() || IsInlineMode()) {
3545         return;
3546     }
3547     SetThemeAttr();
3548 }
3549 
OnAfterModifyDone()3550 void TextFieldPattern::OnAfterModifyDone()
3551 {
3552     auto host = GetHost();
3553     CHECK_NULL_VOID(host);
3554     auto inspectorId = host->GetInspectorId().value_or("");
3555     if (!inspectorId.empty()) {
3556         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3557         bool isPwdType = false;
3558         if (layoutProperty) {
3559             auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
3560             isPwdType = inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
3561                         inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
3562         }
3563         if (!isPwdType) {
3564             Recorder::NodeDataCache::Get().PutString(host, inspectorId, contentController_->GetTextValue());
3565         }
3566     }
3567 }
3568 
CalculateDefaultCursor()3569 void TextFieldPattern::CalculateDefaultCursor()
3570 {
3571     auto tmpHost = GetHost();
3572     CHECK_NULL_VOID(tmpHost);
3573     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3574     CHECK_NULL_VOID(layoutProperty);
3575     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
3576     CHECK_NULL_VOID(paintProperty);
3577     auto textFieldTheme = GetTheme();
3578     CHECK_NULL_VOID(textFieldTheme);
3579     float caretWidth = paintProperty->GetCursorWidth().has_value()
3580                            ? static_cast<float>(paintProperty->GetCursorWidthValue().ConvertToPx())
3581                            : static_cast<float>(textFieldTheme->GetCursorWidth().ConvertToPx());
3582     selectController_->UpdateCaretWidth(caretWidth);
3583     if (!contentController_->IsEmpty()) {
3584         return;
3585     }
3586     selectController_->UpdateCaretHeight(PreferredLineHeight());
3587 }
3588 
AutoFillValueChanged()3589 void TextFieldPattern::AutoFillValueChanged()
3590 {
3591     if (IsFillRequestFinish()) {
3592         return;
3593     }
3594     auto host = GetHost();
3595     CHECK_NULL_VOID(host);
3596     auto aceContentType = GetAutoFillType();
3597     auto container = Container::Current();
3598     CHECK_NULL_VOID(container);
3599     auto isValidType =
3600         (aceContentType >= AceAutoFillType::ACE_PASSWORD &&
3601         aceContentType <= AceAutoFillType::END) || IsAutoFillUserName(aceContentType);
3602     if (isValidType && CheckAutoFill()) {
3603         container->UpdatePopupUIExtension(host, autoFillSessionId_);
3604     }
3605 }
3606 
FireOnTextChangeEvent()3607 bool TextFieldPattern::FireOnTextChangeEvent()
3608 {
3609     auto host = GetHost();
3610     CHECK_NULL_RETURN(host, false);
3611     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3612     CHECK_NULL_RETURN(layoutProperty, false);
3613     auto textCache = layoutProperty->GetValueValue(u"");
3614     auto previewTextCache = layoutProperty->GetPreviewTextValue({GetPreviewTextStart(), u""});
3615     PreviewText curPreviewText = {GetPreviewTextStart(), GetPreviewTextValue()};
3616     if (textCache == contentController_->GetTextUtf16Value() && previewTextCache.value == curPreviewText.value) {
3617         return false;
3618     }
3619     ResetOriginCaretPosition();
3620     AutoFillValueChanged();
3621     auto pipeline = GetContext();
3622     CHECK_NULL_RETURN(pipeline, false);
3623     AddTextFireOnChange();
3624     auto context = host->GetContextRefPtr();
3625     CHECK_NULL_RETURN(context, false);
3626     auto taskExecutor = context->GetTaskExecutor();
3627     CHECK_NULL_RETURN(taskExecutor, false);
3628     taskExecutor->PostTask(
3629         [weak = WeakClaim(this)] {
3630             auto pattern = weak.Upgrade();
3631             CHECK_NULL_VOID(pattern);
3632             if (!pattern->HasFocus()) {
3633                 return;
3634             }
3635             pattern->ScrollToSafeArea();
3636             pattern->TriggerAvoidOnCaretChange();
3637             if (pattern->customKeyboard_ || pattern->customKeyboardBuilder_) {
3638                 pattern->StartTwinkling();
3639             }
3640         },
3641         TaskExecutor::TaskType::UI, "ArkUITextFieldScrollToSafeArea", PriorityType::VIP);
3642     return true;
3643 }
3644 
AddTextFireOnChange()3645 void TextFieldPattern::AddTextFireOnChange()
3646 {
3647     auto host = GetHost();
3648     CHECK_NULL_VOID(host);
3649     auto context = host->GetContextRefPtr();
3650     CHECK_NULL_VOID(context);
3651     context->AddAfterLayoutTask([weak = AceType::WeakClaim(this)] {
3652         auto pattern = weak.Upgrade();
3653         CHECK_NULL_VOID(pattern);
3654         auto host = pattern->GetHost();
3655         CHECK_NULL_VOID(host);
3656         auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
3657         CHECK_NULL_VOID(eventHub);
3658         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3659         CHECK_NULL_VOID(layoutProperty);
3660         auto textCache = layoutProperty->GetValueValue(u"");
3661         auto newText = pattern->GetTextContentController()->GetTextUtf16Value();
3662         layoutProperty->UpdateValue(newText);
3663         host->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, UtfUtils::Str16DebugToStr8(textCache),
3664             UtfUtils::Str16DebugToStr8(newText));
3665         ChangeValueInfo changeValueInfo;
3666         changeValueInfo.value = pattern->GetBodyTextValue();
3667         changeValueInfo.previewText.offset = pattern->hasPreviewText_ ? pattern->GetPreviewTextStart() : -1;
3668         changeValueInfo.previewText.value = pattern->GetPreviewTextValue();
3669         changeValueInfo.oldPreviewText = pattern->callbackOldPreviewText_;
3670         changeValueInfo.oldContent = pattern->callbackOldContent_;
3671         changeValueInfo.rangeBefore = pattern->callbackRangeBefore_;
3672         changeValueInfo.rangeAfter = pattern->callbackRangeAfter_;
3673         layoutProperty->UpdatePreviewText(changeValueInfo.previewText);
3674         eventHub->FireOnChange(changeValueInfo);
3675 
3676         pattern->RecordTextInputEvent();
3677         auto callback = [weakPattern = weak](const std::string& type, const std::string& content) {
3678             auto strongPattern = weakPattern.Upgrade();
3679             CHECK_NULL_VOID(strongPattern);
3680             strongPattern->OnAccessibilityEventTextChange(type, content);
3681         };
3682 
3683         pattern->ProcessAccessibilityTextChange(
3684             UtfUtils::Str16DebugToStr8(newText),
3685             std::move(callback),
3686             AceLogTag::ACE_TEXT_FIELD
3687         );
3688     });
3689 }
3690 
RecordTextInputEvent()3691 void TextFieldPattern::RecordTextInputEvent()
3692 {
3693     if (!Recorder::EventRecorder::Get().IsRecordEnable(Recorder::EventCategory::CATEGORY_TEXT_INPUT)) {
3694         return;
3695     }
3696     auto host = GetHost();
3697     CHECK_NULL_VOID(host);
3698     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
3699     CHECK_NULL_VOID(layoutProperty);
3700     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
3701     auto isPwdType = inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
3702                      inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
3703     if (isPwdType) {
3704         return;
3705     }
3706     Recorder::EventParamsBuilder builder;
3707     builder.SetEventCategory(Recorder::EventCategory::CATEGORY_TEXT_INPUT)
3708         .SetEventType(Recorder::EventType::TEXT_INPUT)
3709         .SetId(host->GetInspectorId().value_or(""))
3710         .SetType(host->GetTag())
3711         .SetText(UtfUtils::Str16DebugToStr8(GetBodyTextValue()))
3712         .SetDescription(host->GetAutoEventParamValue(""))
3713         .SetHost(host);
3714     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
3715 }
3716 
FilterInitializeText()3717 void TextFieldPattern::FilterInitializeText()
3718 {
3719     if (HasInputOperation()) {
3720         return;
3721     }
3722     if (HasFocus()) {
3723         UpdateShowCountBorderStyle();
3724         if (showCountBorderStyle_) {
3725             HandleCountStyle();
3726         }
3727     }
3728     if (!contentController_->IsEmpty()) {
3729         auto originCaretIndex =
3730             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
3731         ChangeValueInfo changeValueInfo;
3732         changeValueInfo.oldContent = GetBodyTextValue();
3733         changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3734         changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
3735         changeValueInfo.rangeBefore = TextRange { 0, changeValueInfo.oldContent.length() };
3736         auto textChanged = contentController_->FilterValue();
3737         if (isFilterChanged_) {
3738             changeValueInfo.value = GetBodyTextValue();
3739             changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
3740             changeValueInfo.previewText.value = GetPreviewTextValue();
3741             changeValueInfo.rangeAfter = TextRange { 0, changeValueInfo.value.length() };
3742             bool isWillChange = FireOnWillChange(changeValueInfo);
3743             isFilterChanged_ = false;
3744             if (!isWillChange) {
3745                 RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
3746                 return;
3747             }
3748         }
3749         if (!isTextChangedAtCreation_) {
3750             isTextChangedAtCreation_ = textChanged;
3751         }
3752     }
3753     if (static_cast<int32_t>(GetTextUtf16Value().length()) < GetCaretIndex()) {
3754         selectController_->UpdateCaretIndex(static_cast<int32_t>(GetTextUtf16Value().length()));
3755     }
3756     UpdateShowCountBorderStyle();
3757 }
3758 
IsDisabled()3759 bool TextFieldPattern::IsDisabled()
3760 {
3761     auto tmpHost = GetHost();
3762     CHECK_NULL_RETURN(tmpHost, true);
3763     auto eventHub = tmpHost->GetOrCreateEventHub<TextFieldEventHub>();
3764     CHECK_NULL_RETURN(eventHub, true);
3765     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3766     CHECK_NULL_RETURN(layoutProperty, true);
3767     return !eventHub->IsEnabled();
3768 }
3769 
GetUnderlinePadding(const RefPtr<TextFieldTheme> & theme,bool processLeftPadding,bool processRightPadding) const3770 Edge TextFieldPattern::GetUnderlinePadding(const RefPtr<TextFieldTheme>& theme,
3771     bool processLeftPadding, bool processRightPadding) const
3772 {
3773     auto themePadding = theme->GetUnderlinePadding();
3774     auto host = GetHost();
3775     CHECK_NULL_RETURN(host, themePadding);
3776     if (!IsUnderlineAndButtonMode() || host->LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
3777         return themePadding;
3778     }
3779     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3780     CHECK_NULL_RETURN(layoutProperty, themePadding);
3781     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
3782     if (isRTL) {
3783         themePadding.SetLeft(theme->GetPadding().Left());
3784     } else {
3785         themePadding.SetRight(theme->GetPadding().Right());
3786     }
3787     if (processLeftPadding) {
3788         themePadding.SetLeft(theme->GetPadding().Left());
3789     }
3790     if (processRightPadding) {
3791         themePadding.SetRight(theme->GetPadding().Right());
3792     }
3793     return themePadding;
3794 }
3795 
ProcessInnerPadding()3796 void TextFieldPattern::ProcessInnerPadding()
3797 {
3798     auto textFieldTheme = GetTheme();
3799     CHECK_NULL_VOID(textFieldTheme);
3800     auto themePadding = IsUnderlineMode() ? GetUnderlinePadding(textFieldTheme, false, false) :
3801         textFieldTheme->GetPadding();
3802     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3803     CHECK_NULL_VOID(layoutProperty);
3804     PaddingPropertyF utilPadding;
3805     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
3806     auto left = !paddingProperty ? CalcLength(themePadding.Left()).GetDimension()
3807                                  : paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension();
3808     utilPadding.left = left.ConvertToPx();
3809     auto top = !paddingProperty ? CalcLength(themePadding.Top()).GetDimension()
3810                                 : paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension();
3811     utilPadding.top = top.ConvertToPx();
3812     auto bottom = !paddingProperty ? CalcLength(themePadding.Bottom()).GetDimension()
3813                                    : paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension();
3814     utilPadding.bottom = bottom.ConvertToPx();
3815     auto right = !paddingProperty ? CalcLength(themePadding.Right()).GetDimension()
3816                                   : paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension();
3817     utilPadding.right = right.ConvertToPx();
3818     utilPadding_ = utilPadding;
3819     PaddingProperty paddings;
3820     paddings.top = NG::CalcLength(top);
3821     paddings.bottom = NG::CalcLength(bottom);
3822     paddings.left = NG::CalcLength(left);
3823     paddings.right = NG::CalcLength(right);
3824     layoutProperty->UpdatePadding(paddings);
3825 }
3826 
ProcessNumberOfLines()3827 void TextFieldPattern::ProcessNumberOfLines()
3828 {
3829     auto tmpHost = GetHost();
3830     CHECK_NULL_VOID(tmpHost);
3831     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
3832     CHECK_NULL_VOID(layoutProperty && layoutProperty->HasNumberOfLines());
3833     auto numberOfLines = layoutProperty->GetNumberOfLines().value();
3834     CHECK_NULL_VOID(numberOfLines > 0);
3835     auto lineHeight = layoutProperty->GetLineHeight().value_or(0.0_vp).ConvertToPx();
3836     if (LessOrEqual(lineHeight, 0.f)) {
3837         lineHeight = PreferredLineHeight(false);
3838     }
3839     auto lineSpacing = layoutProperty->GetLineSpacing().value_or(0.0_vp).ConvertToPx();
3840     auto contentHeight = numberOfLines * lineHeight + numberOfLines * lineSpacing;
3841     auto height = contentHeight + GetVerticalPaddingAndBorderSum();
3842 
3843     // get previously user defined ideal width
3844     std::optional<CalcLength> width = std::nullopt;
3845     auto &&layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
3846     if (layoutConstraint && layoutConstraint->selfIdealSize) {
3847         width = layoutConstraint->selfIdealSize->Width();
3848     }
3849     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(width, CalcLength(height)));
3850 }
3851 
InitLongPressEvent()3852 void TextFieldPattern::InitLongPressEvent()
3853 {
3854     CHECK_NULL_VOID(!longPressEvent_);
3855     auto tmpHost = GetHost();
3856     CHECK_NULL_VOID(tmpHost);
3857     auto gesture = tmpHost->GetOrCreateGestureEventHub();
3858     auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
3859         auto pattern = weak.Upgrade();
3860         CHECK_NULL_VOID(pattern);
3861         pattern->selectOverlay_->SetUsingMouse(info.GetSourceDevice() == SourceType::MOUSE);
3862         pattern->selectOverlay_->SetLastSourceType(info.GetSourceDevice());
3863         pattern->HandleLongPress(info);
3864     };
3865     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
3866     gesture->SetLongPressEvent(longPressEvent_);
3867 }
3868 
StartVibratorByLongPress()3869 void TextFieldPattern::StartVibratorByLongPress()
3870 {
3871     CHECK_NULL_VOID(isEnableHapticFeedback_);
3872     VibratorUtils::StartVibraFeedback("longPress.light");
3873 }
3874 
IsInResponseArea(const Offset & location)3875 bool TextFieldPattern::IsInResponseArea(const Offset& location)
3876 {
3877     return cancelButtonTouched_ || IsOnUnitByPosition(location) || IsOnPasswordByPosition(location) ||
3878     IsOnCleanNodeByPosition(location);
3879 }
3880 
HandleLongPress(GestureEvent & info)3881 void TextFieldPattern::HandleLongPress(GestureEvent& info)
3882 {
3883     CHECK_NULL_VOID(!IsDragging());
3884     CHECK_NULL_VOID(!IsHandleDragging());
3885     auto focusHub = GetFocusHub();
3886     CHECK_NULL_VOID(focusHub);
3887     if (!focusHub->IsFocusable() || IsInResponseArea(info.GetLocalLocation()) || GetIsPreviewText()) {
3888         return;
3889     }
3890     moveCaretState_.isTouchCaret = false;
3891     auto host = GetHost();
3892     CHECK_NULL_VOID(host);
3893     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HandleLongPress %{public}d", host->GetId());
3894     if (ResetObscureTickCountDown()) {
3895         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3896     }
3897     if (info.GetSourceDevice() == SourceType::MOUSE) {
3898         return;
3899     }
3900     auto hub = host->GetOrCreateEventHub<EventHub>();
3901     CHECK_NULL_VOID(hub);
3902     auto gestureHub = hub->GetOrCreateGestureEventHub();
3903     CHECK_NULL_VOID(gestureHub);
3904     StartVibratorByLongPress();
3905     if (BetweenSelectedPosition(info)) {
3906         gestureHub->SetIsTextDraggable(true);
3907         return;
3908     }
3909     gestureHub->SetIsTextDraggable(false);
3910     isLongPress_ = true;
3911     if (!focusHub->IsCurrentFocus()) {
3912         TextFieldRequestFocus(RequestFocusReason::LONG_PRESS);
3913     }
3914 
3915     auto localOffset = info.GetLocalLocation();
3916     if (CanChangeSelectState()) {
3917         selectController_->UpdateSelectWithBlank(localOffset);
3918         StopTwinkling();
3919     }
3920     SetIsSingleHandle(!IsSelected());
3921     auto start = selectController_->GetStartIndex();
3922     auto end = selectController_->GetEndIndex();
3923     CloseSelectOverlay();
3924     longPressFingerNum_ = info.GetFingerList().size();
3925     if (magnifierController_ && HasText() && (longPressFingerNum_ == 1)) {
3926         magnifierController_->SetLocalOffset({ localOffset.GetX(), localOffset.GetY() });
3927     }
3928     StartGestureSelection(start, end, localOffset);
3929     TriggerAvoidOnCaretChange();
3930     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3931 }
3932 
BetweenSelectedPosition(GestureEvent & info)3933 bool TextFieldPattern::BetweenSelectedPosition(GestureEvent& info)
3934 {
3935     if (!IsSelected()) {
3936         return false;
3937     }
3938     auto localOffset = info.GetLocalLocation();
3939     auto offsetX = IsTextArea() ? contentRect_.GetX() : textRect_.GetX();
3940     auto offsetY = IsTextArea() ? textRect_.GetY() : contentRect_.GetY();
3941     Offset offset = localOffset - Offset(offsetX, offsetY);
3942     for (const auto& rect : selectController_->GetSelectedRects()) {
3943         bool isInRange = rect.IsInRegion({ offset.GetX(), offset.GetY() });
3944         if (isInRange) {
3945             return true;
3946         }
3947     }
3948     return false;
3949 }
3950 
CanChangeSelectState()3951 bool TextFieldPattern::CanChangeSelectState()
3952 {
3953     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
3954     CHECK_NULL_RETURN(layoutProperty, false);
3955     auto theme = GetTheme();
3956     CHECK_NULL_RETURN(theme, false);
3957     Dimension fontSize = layoutProperty->GetFontSizeValue(theme->GetFontSize());
3958     // fontSize == 0 can not change
3959     return !NearZero(fontSize.Value()) && !IsContentRectNonPositive();
3960 }
3961 
IsAccessibilityClick()3962 bool TextFieldPattern::IsAccessibilityClick()
3963 {
3964     auto host = GetHost();
3965     CHECK_NULL_RETURN(host, false);
3966     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
3967     CHECK_NULL_RETURN(accessibilityProperty, false);
3968     return accessibilityProperty->GetAccessibilityFocusState();
3969 }
3970 
IsOnUnitByPosition(const Offset & localOffset)3971 bool TextFieldPattern::IsOnUnitByPosition(const Offset& localOffset)
3972 {
3973     if (!IsShowUnit()) {
3974         return false;
3975     }
3976     auto unitArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
3977     CHECK_NULL_RETURN(unitArea, false);
3978     auto frameNode = unitArea->GetFrameNode();
3979     CHECK_NULL_RETURN(frameNode, false);
3980     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3981 }
3982 
IsOnPasswordByPosition(const Offset & localOffset)3983 bool TextFieldPattern::IsOnPasswordByPosition(const Offset& localOffset)
3984 {
3985     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
3986     CHECK_NULL_RETURN(passwordArea, false);
3987     auto frameNode = passwordArea->GetFrameNode();
3988     CHECK_NULL_RETURN(frameNode, false);
3989     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3990 }
3991 
IsOnCleanNodeByPosition(const Offset & localOffset)3992 bool TextFieldPattern::IsOnCleanNodeByPosition(const Offset& localOffset)
3993 {
3994     auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
3995     CHECK_NULL_RETURN(cleanNodeResponseArea, false);
3996     auto frameNode = cleanNodeResponseArea->GetFrameNode();
3997     CHECK_NULL_RETURN(frameNode, false);
3998     return frameNode->GetGeometryNode()->GetFrameRect().IsInRegion({ localOffset.GetX(), localOffset.GetY() });
3999 }
4000 
IsMouseOverScrollBar(const BaseEventInfo * info)4001 bool TextFieldPattern::IsMouseOverScrollBar(const BaseEventInfo* info)
4002 {
4003     CHECK_NULL_RETURN(GetScrollBar(), false);
4004     Point point;
4005     do {
4006         auto gestureEvent = TypeInfoHelper::DynamicCast<GestureEvent>(info);
4007         if (gestureEvent) {
4008             point = Point(gestureEvent->GetLocalLocation().GetX(), gestureEvent->GetLocalLocation().GetY());
4009             break;
4010         }
4011         auto mouseInfo = TypeInfoHelper::DynamicCast<MouseInfo>(info);
4012         if (mouseInfo) {
4013             point = Point(mouseInfo->GetLocalLocation().GetX(), mouseInfo->GetLocalLocation().GetY());
4014             break;
4015         }
4016         return false;
4017     } while (false);
4018     if (GetScrollBar()->NeedPaint() && GetScrollBar()->GetShapeMode() == ShapeMode::RECT) {
4019         auto barRect = GetScrollBar()->GetBarRect();
4020         auto mouseScrollbarRegionWidth = MOUSE_SCROLL_BAR_REGION_WIDTH.ConvertToPx();
4021         barRect.SetLeft(barRect.Left() + (barRect.Width() - mouseScrollbarRegionWidth));
4022         barRect.SetWidth(mouseScrollbarRegionWidth);
4023         barRect.SetHeight(frameRect_.Height());
4024         barRect.SetTop(0.0f);
4025         return barRect.IsInRegion(point);
4026     }
4027     return false;
4028 }
4029 
UpdateCaretPositionWithClamp(const int32_t & pos)4030 void TextFieldPattern::UpdateCaretPositionWithClamp(const int32_t& pos)
4031 {
4032     selectController_->UpdateCaretIndex(
4033         std::clamp(pos, 0, static_cast<int32_t>(contentController_->GetTextUtf16Value().length())));
4034 }
4035 
ProcessOverlay(const OverlayRequest & request)4036 void TextFieldPattern::ProcessOverlay(const OverlayRequest& request)
4037 {
4038     selectOverlay_->ProcessOverlay(request);
4039 }
4040 
DelayProcessOverlay(const OverlayRequest & request)4041 void TextFieldPattern::DelayProcessOverlay(const OverlayRequest& request)
4042 {
4043     processOverlayDelayTask_ = [weak = WeakClaim(this), request]() {
4044         auto pattern = weak.Upgrade();
4045         CHECK_NULL_VOID(pattern);
4046         pattern->ProcessOverlay(request);
4047     };
4048 }
4049 
CancelDelayProcessOverlay()4050 void TextFieldPattern::CancelDelayProcessOverlay()
4051 {
4052     if (processOverlayDelayTask_) {
4053         processOverlayDelayTask_ = nullptr;
4054     }
4055 }
4056 
AllowCopy()4057 bool TextFieldPattern::AllowCopy()
4058 {
4059     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4060     CHECK_NULL_RETURN(layoutProperty, false);
4061     return layoutProperty->GetCopyOptionsValue(CopyOptions::Local) != CopyOptions::None && !IsInPasswordMode();
4062 }
4063 
OnDetachFromFrameNode(FrameNode * node)4064 void TextFieldPattern::OnDetachFromFrameNode(FrameNode* node)
4065 {
4066     THREAD_SAFE_NODE_CHECK(node, OnDetachFromFrameNode, node);  // call OnDetachFromFrameNodeMultiThread() by multi thread
4067     selectOverlay_->CloseOverlay(false, CloseReason::CLOSE_REASON_NORMAL);
4068     auto pipeline = node->GetContext();
4069     CHECK_NULL_VOID(pipeline);
4070     if (HasSurfaceChangedCallback()) {
4071         pipeline->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
4072     }
4073     if (HasSurfacePositionChangedCallback()) {
4074         pipeline->UnregisterSurfacePositionChangedCallback(surfacePositionChangedCallbackId_.value_or(-1));
4075     }
4076     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
4077     if (textFieldManager) {
4078         textFieldManager->ClearOnFocusTextField(node->GetId());
4079     }
4080     auto frameNode = WeakClaim(node);
4081     pipeline->RemoveFontNodeNG(frameNode);
4082     auto fontManager = pipeline->GetFontManager();
4083     if (fontManager) {
4084         fontManager->UnRegisterCallbackNG(frameNode);
4085         fontManager->RemoveVariationNodeNG(frameNode);
4086     }
4087     pipeline->RemoveWindowSizeChangeCallback(node->GetId());
4088     pipeline->RemoveOnAreaChangeNode(node->GetId());
4089 }
4090 
CloseSelectOverlay()4091 void TextFieldPattern::CloseSelectOverlay()
4092 {
4093     CloseSelectOverlay(false);
4094 }
4095 
CloseSelectOverlay(bool animation)4096 void TextFieldPattern::CloseSelectOverlay(bool animation)
4097 {
4098     selectOverlay_->CloseOverlay(animation, CloseReason::CLOSE_REASON_NORMAL);
4099     auto host = GetHost();
4100     CHECK_NULL_VOID(host);
4101     auto gesture = host->GetOrCreateGestureEventHub();
4102     gesture->AddTouchEvent(GetTouchListener());
4103 }
4104 
InitEditingValueText(std::u16string content)4105 void TextFieldPattern::InitEditingValueText(std::u16string content)
4106 {
4107     if (HasInputOperation()) {
4108         return;
4109     }
4110     textCache_ = UtfUtils::Str16DebugToStr8(content);
4111     contentController_->SetTextValueOnly(std::move(content));
4112     selectController_->UpdateCaretIndex(GetTextUtf16Value().length());
4113     if (GetIsPreviewText() && GetTextUtf16Value().empty()) {
4114         FinishTextPreviewOperation();
4115     }
4116     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4117 }
4118 
InitValueText(std::u16string content)4119 bool TextFieldPattern::InitValueText(std::u16string content)
4120 {
4121     if (GetIsPreviewText()) {
4122         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Init when has previewText");
4123         return false;
4124     }
4125     if (HasInputOperation() && content != u"") {
4126         return false;
4127     }
4128     textCache_ = UtfUtils::Str16DebugToStr8(content);
4129     ChangeValueInfo changeValueInfo;
4130     changeValueInfo.oldContent = GetBodyTextValue();
4131     changeValueInfo.value = content;
4132     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
4133     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
4134     changeValueInfo.previewText = changeValueInfo.oldPreviewText;
4135     changeValueInfo.rangeBefore = TextRange { 0, changeValueInfo.oldContent.length() };
4136     changeValueInfo.rangeAfter = TextRange { 0, content.length() };
4137     bool isWillChange = FireOnWillChange(changeValueInfo);
4138     if (!isWillChange) {
4139         return false;
4140     }
4141     contentController_->SetTextValueOnly(std::move(content));
4142     selectController_->UpdateCaretIndex(GetTextUtf16Value().length());
4143     GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
4144     return true;
4145 }
4146 
InitMouseEvent()4147 void TextFieldPattern::InitMouseEvent()
4148 {
4149     CHECK_NULL_VOID(!mouseEvent_ || !hoverEvent_);
4150     auto tmpHost = GetHost();
4151     CHECK_NULL_VOID(tmpHost);
4152     auto eventHub = tmpHost->GetOrCreateEventHub<TextFieldEventHub>();
4153     auto inputHub = eventHub->GetOrCreateInputEventHub();
4154 
4155     auto mouseTask = [weak = WeakClaim(this)](MouseInfo& info) {
4156         auto pattern = weak.Upgrade();
4157         if (pattern) {
4158             pattern->HandleMouseEvent(info);
4159             if (info.GetButton() == MouseButton::LEFT_BUTTON && info.GetAction() == MouseAction::PRESS) {
4160                 pattern->hasMousePressed_ = true;
4161             } else {
4162                 pattern->hasMousePressed_ = false;
4163             }
4164         }
4165     };
4166     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
4167     inputHub->AddOnMouseEvent(mouseEvent_);
4168 
4169     auto hoverTask = [weak = WeakClaim(this)](bool isHover, const HoverInfo& info) {
4170         auto pattern = weak.Upgrade();
4171         if (pattern) {
4172             pattern->OnHover(isHover, info);
4173         }
4174     };
4175     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
4176     inputHub->AddOnHoverEvent(hoverEvent_);
4177     InitPanEvent();
4178 }
4179 
InitPanEvent()4180 void TextFieldPattern::InitPanEvent()
4181 {
4182     auto host = GetHost();
4183     CHECK_NULL_VOID(host);
4184     auto gestureHub = host->GetOrCreateGestureEventHub();
4185     CHECK_NULL_VOID(gestureHub);
4186     if (!boxSelectPanEvent_) {
4187         auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
4188         auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
4189         auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {};
4190         GestureEventNoParameter actionCancelTask;
4191         boxSelectPanEvent_ = MakeRefPtr<PanEvent>(std::move(actionStartTask), std::move(actionUpdateTask),
4192             std::move(actionEndTask), std::move(actionCancelTask));
4193     }
4194     PanDirection panDirection = { .type = PanDirection::ALL };
4195     PanDistanceMap distanceMap = { { SourceTool::UNKNOWN, DEFAULT_PAN_DISTANCE.ConvertToPx() },
4196         { SourceTool::PEN, DEFAULT_PEN_PAN_DISTANCE.ConvertToPx() } };
4197     gestureHub->AddPanEvent(boxSelectPanEvent_, panDirection, 1, distanceMap);
4198     gestureHub->SetPanEventType(GestureTypeName::TEXTFIELD_BOXSELECT);
4199     gestureHub->SetOnGestureJudgeNativeBegin([weak = WeakClaim(this)](const RefPtr<NG::GestureInfo>& gestureInfo,
4200                                                  const std::shared_ptr<BaseGestureEvent>& info) -> GestureJudgeResult {
4201         if (gestureInfo->GetType() == GestureTypeName::BOXSELECT &&
4202             gestureInfo->GetInputEventType() == InputEventType::MOUSE_BUTTON) {
4203             return GestureJudgeResult::REJECT;
4204         }
4205         auto pattern = weak.Upgrade();
4206         CHECK_NULL_RETURN(pattern, GestureJudgeResult::CONTINUE);
4207         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
4208             gestureInfo->GetInputEventType() == InputEventType::TOUCH_SCREEN &&
4209             pattern->moveCaretState_.isMoveCaret) {
4210             return GestureJudgeResult::CONTINUE;
4211         }
4212         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
4213             gestureInfo->GetInputEventType() != InputEventType::MOUSE_BUTTON) {
4214             return GestureJudgeResult::REJECT;
4215         }
4216         auto host = pattern->GetHost();
4217         CHECK_NULL_RETURN(host, GestureJudgeResult::CONTINUE);
4218         if (gestureInfo->GetType() == GestureTypeName::TEXTFIELD_BOXSELECT &&
4219             gestureInfo->GetInputEventType() == InputEventType::MOUSE_BUTTON &&
4220             host->IsDraggable() && pattern->IsPressSelectedBox()) {
4221             return GestureJudgeResult::REJECT;
4222         }
4223         if (pattern->GetCancelButtonTouchInfo()) {
4224             return GestureJudgeResult::REJECT;
4225         }
4226         return GestureJudgeResult::CONTINUE;
4227     });
4228 }
4229 
OnHover(bool isHover,const HoverInfo & info)4230 void TextFieldPattern::OnHover(bool isHover, const HoverInfo& info)
4231 {
4232     auto frame = GetHost();
4233     CHECK_NULL_VOID(frame);
4234     auto frameId = frame->GetId();
4235     auto pipeline = frame->GetContext();
4236     auto textFieldTheme = GetTheme();
4237     if (!pipeline || !textFieldTheme) {
4238         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield %{public}d hover can't get pipeline",
4239             frame->GetId());
4240         return;
4241     }
4242     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield %{public}d %{public}s", frame->GetId(),
4243         isHover ? "on hover" : "exit hover");
4244     if (isHover) {
4245         pipeline->SetMouseStyleHoldNode(frameId);
4246         ChangeMouseState(info.GetLocalLocation(), frameId);
4247     } else {
4248         int32_t windowId = 0;
4249 #ifdef WINDOW_SCENE_SUPPORTED
4250         windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4251 #endif
4252         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT, windowId);
4253         pipeline->FreeMouseStyleHoldNode(frameId);
4254     }
4255     UpdateHoverStyle(isHover);
4256     isOnHover_ = isHover;
4257 }
4258 
UpdateHoverStyle(bool isHover)4259 void TextFieldPattern::UpdateHoverStyle(bool isHover)
4260 {
4261     if (!hoverAndPressBgColorEnabled_) {
4262         return;
4263     }
4264     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4265     CHECK_NULL_VOID(paintProperty);
4266     auto theme = GetTheme();
4267     CHECK_NULL_VOID(theme);
4268     auto defaultThemeBgColor = theme->GetBgColor();
4269     auto textFieldBgColor = paintProperty->GetBackgroundColorValue(defaultThemeBgColor);
4270     auto bgColor = textFieldBgColor;
4271     if (textFieldBgColor == defaultThemeBgColor) {
4272         bgColor = IsUnderlineMode() ? Color::TRANSPARENT : defaultThemeBgColor;
4273     }
4274     auto hoverColor = bgColor.BlendColor(theme->GetPressColor());
4275     if (!HasFocus()) {
4276         if (isHover) {
4277             PlayAnimationHoverAndPress(hoverColor);
4278         } else {
4279             PlayAnimationHoverAndPress(bgColor);
4280         }
4281     }
4282 }
4283 
UpdatePressStyle(bool isPressed)4284 void TextFieldPattern::UpdatePressStyle(bool isPressed)
4285 {
4286     if (!hoverAndPressBgColorEnabled_) {
4287         return;
4288     }
4289     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4290     CHECK_NULL_VOID(paintProperty);
4291     auto theme = GetTheme();
4292     CHECK_NULL_VOID(theme);
4293     auto defaultThemeBgColor = theme->GetBgColor();
4294     auto textFieldBgColor = paintProperty->GetBackgroundColorValue(defaultThemeBgColor);
4295     auto bgColor = textFieldBgColor;
4296     if (textFieldBgColor == defaultThemeBgColor) {
4297         if (IsUnderlineMode()) {
4298             bgColor = Color::TRANSPARENT;
4299         } else {
4300             bgColor = HasFocus() ? theme->GetFocusBgColor() : defaultThemeBgColor;
4301         }
4302     }
4303     auto pressColor = bgColor.BlendColor(theme->GetHoverColor());
4304     if (isPressed) {
4305         PlayAnimationHoverAndPress(pressColor);
4306     } else {
4307         PlayAnimationHoverAndPress(bgColor);
4308     }
4309 }
4310 
PlayAnimationHoverAndPress(const Color & color)4311 void TextFieldPattern::PlayAnimationHoverAndPress(const Color& color)
4312 {
4313     AnimationOption option = AnimationOption();
4314     option.SetDuration(HOVER_ANIMATION_DURATION);
4315     option.SetCurve(Curves::FRICTION);
4316     AnimationUtils::Animate(option, [weak = AceType::WeakClaim(this), color]() {
4317         auto textFieldPattern = weak.Upgrade();
4318         CHECK_NULL_VOID(textFieldPattern);
4319         textFieldPattern->UpdateTextFieldBgColor(color);
4320     });
4321 }
4322 
UpdateTextFieldBgColor(const Color & color)4323 void TextFieldPattern::UpdateTextFieldBgColor(const Color& color)
4324 {
4325     auto host = GetHost();
4326     CHECK_NULL_VOID(host);
4327     auto renderContext = host->GetRenderContext();
4328     CHECK_NULL_VOID(renderContext);
4329     renderContext->UpdateBackgroundColor(color);
4330     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4331 }
4332 
RestoreDefaultMouseState()4333 void TextFieldPattern::RestoreDefaultMouseState()
4334 {
4335     int32_t windowId = 0;
4336 #ifdef WINDOW_SCENE_SUPPORTED
4337     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4338 #endif
4339     auto host = GetHost();
4340     CHECK_NULL_VOID(host);
4341     auto pipeline = host->GetContextRefPtr();
4342     CHECK_NULL_VOID(pipeline);
4343     auto id = host->GetId();
4344     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "RestoreDefaultMouseState id:%{public}d, winId:%{public}d", id, windowId);
4345     pipeline->SetMouseStyleHoldNode(id);
4346     pipeline->ChangeMouseStyle(id, MouseFormat::DEFAULT, windowId);
4347 }
4348 
ChangeMouseState(const Offset location,int32_t frameId)4349 void TextFieldPattern::ChangeMouseState(const Offset location, int32_t frameId)
4350 {
4351     auto host = GetHost();
4352     CHECK_NULL_VOID(host);
4353     auto pipeline = host->GetContext();
4354     CHECK_NULL_VOID(pipeline);
4355     auto responseAreaWidth = (responseArea_ ? responseArea_->GetAreaRect().Width() : 0.0f) +
4356                              (cleanNodeResponseArea_ ? cleanNodeResponseArea_->GetAreaRect().Width() : 0.0f);
4357     auto x = location.GetX();
4358     auto y = location.GetY();
4359     int32_t windowId = 0;
4360 #ifdef WINDOW_SCENE_SUPPORTED
4361     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4362 #endif
4363     if (GreatNotEqual(x, 0) && LessNotEqual(x, frameRect_.Width()) && GreatNotEqual(y, 0) &&
4364         LessNotEqual(y, frameRect_.Height())) {
4365         auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
4366         CHECK_NULL_VOID(layoutProperty);
4367         auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
4368         if (!isRTL && GreatNotEqual(location.GetX(), frameRect_.Width() - responseAreaWidth)) {
4369             RestoreDefaultMouseState();
4370         } else if (isRTL && LessNotEqual(location.GetX(), responseAreaWidth)) {
4371             RestoreDefaultMouseState();
4372         } else {
4373             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "ChangeMouseState Id:%{public}d, winId:%{public}d", frameId, windowId);
4374             pipeline->SetMouseStyleHoldNode(frameId);
4375             pipeline->ChangeMouseStyle(frameId, MouseFormat::TEXT_CURSOR, windowId);
4376         }
4377     } else {
4378         RestoreDefaultMouseState();
4379     }
4380 }
4381 
HandleMouseEvent(MouseInfo & info)4382 void TextFieldPattern::HandleMouseEvent(MouseInfo& info)
4383 {
4384     CHECK_NULL_VOID(!IsDragging());
4385     auto tmpHost = GetHost();
4386     CHECK_NULL_VOID(tmpHost);
4387     auto frameId = tmpHost->GetId();
4388     auto pipeline = tmpHost->GetContext();
4389     CHECK_NULL_VOID(pipeline);
4390     info.SetStopPropagation(true);
4391     selectOverlay_->SetLastSourceType(info.GetSourceDevice());
4392     auto scrollBar = GetScrollBar();
4393     int32_t windowId = 0;
4394 #ifdef WINDOW_SCENE_SUPPORTED
4395     windowId = static_cast<int32_t>(GetSCBSystemWindowId());
4396 #endif
4397     if (scrollBar && (scrollBar->IsPressed() || scrollBar->IsHover() || IsMouseOverScrollBar(&info))) {
4398         pipeline->SetMouseStyleHoldNode(frameId);
4399         pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT, windowId);
4400         return;
4401     }
4402     if (info.GetAction() != MouseAction::WINDOW_LEAVE) {
4403         ChangeMouseState(info.GetLocalLocation(), frameId);
4404     }
4405 
4406     if (info.GetAction() == OHOS::Ace::MouseAction::PRESS) {
4407         selectOverlay_->SetUsingMouse(true);
4408     }
4409     if (info.GetButton() == MouseButton::RIGHT_BUTTON) {
4410         HandleRightMouseEvent(info);
4411     } else if (info.GetButton() == MouseButton::LEFT_BUTTON) {
4412         HandleLeftMouseEvent(info);
4413         if (IsSelected()) {
4414             selectOverlay_->SetSelectionHoldCallback();
4415         }
4416     }
4417     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
4418         selectOverlay_->SetUsingMouse(false);
4419     }
4420     if (!IsSelected()) {
4421         ResetOriginCaretPosition();
4422     }
4423 }
4424 
HandleRightMouseEvent(MouseInfo & info)4425 void TextFieldPattern::HandleRightMouseEvent(MouseInfo& info)
4426 {
4427     if (info.GetAction() == OHOS::Ace::MouseAction::PRESS) {
4428         HandleRightMousePressEvent(info);
4429         return;
4430     }
4431     if (info.GetAction() == OHOS::Ace::MouseAction::RELEASE) {
4432         HandleRightMouseReleaseEvent(info);
4433     }
4434 }
4435 
HandleRightMousePressEvent(MouseInfo & info)4436 void TextFieldPattern::HandleRightMousePressEvent(MouseInfo& info)
4437 {
4438     if (IsSelected() || GetIsPreviewText()) {
4439         return;
4440     }
4441     auto focusHub = GetFocusHub();
4442     if (!focusHub->IsFocusable()) {
4443         return;
4444     }
4445     FocusAndUpdateCaretByMouse(info);
4446 }
4447 
HandleRightMouseReleaseEvent(MouseInfo & info)4448 void TextFieldPattern::HandleRightMouseReleaseEvent(MouseInfo& info)
4449 {
4450     if (GetIsPreviewText()) {
4451         return;
4452     }
4453     auto focusHub = GetFocusHub();
4454     if (focusHub->IsCurrentFocus()) {
4455         OffsetF rightClickOffset = OffsetF(
4456             static_cast<float>(info.GetGlobalLocation().GetX()), static_cast<float>(info.GetGlobalLocation().GetY()));
4457         selectOverlay_->SetMouseMenuOffset(rightClickOffset);
4458         ProcessOverlay();
4459     }
4460 }
4461 
HandleLeftMouseEvent(MouseInfo & info)4462 void TextFieldPattern::HandleLeftMouseEvent(MouseInfo& info)
4463 {
4464     switch (info.GetAction()) {
4465         case OHOS::Ace::MouseAction::PRESS: {
4466             HandleLeftMousePressEvent(info);
4467             break;
4468         }
4469         case OHOS::Ace::MouseAction::MOVE: {
4470             HandleLeftMouseMoveEvent(info); // 注意鼠标拖拽的滚动效果
4471             break;
4472         }
4473         case OHOS::Ace::MouseAction::RELEASE: {
4474             HandleLeftMouseReleaseEvent(info);
4475             break;
4476         }
4477         default: {
4478         }
4479     }
4480 }
4481 
HandleLeftMousePressEvent(MouseInfo & info)4482 void TextFieldPattern::HandleLeftMousePressEvent(MouseInfo& info)
4483 {
4484     isPressSelectedBox_ =
4485         (IsSelected() && BetweenSelectedPosition(info.GetGlobalLocation()) && !shiftFlag_);
4486     if (isPressSelectedBox_ || GetIsPreviewText()) {
4487         blockPress_ = true;
4488         return;
4489     }
4490     auto focusHub = GetFocusHub();
4491     if (!focusHub->IsFocusable()) {
4492         return;
4493     }
4494     mouseStatus_ = MouseStatus::PRESSED;
4495     blockPress_ = false;
4496     leftMouseCanMove_ = true;
4497     FocusAndUpdateCaretByMouse(info);
4498 }
4499 
FocusAndUpdateCaretByMouse(MouseInfo & info)4500 void TextFieldPattern::FocusAndUpdateCaretByMouse(MouseInfo& info)
4501 {
4502     auto focusHub = GetFocusHub();
4503     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4504     CHECK_NULL_VOID(paintProperty);
4505     if (!focusHub->IsFocusOnTouch().value_or(true) || !TextFieldRequestFocus(RequestFocusReason::MOUSE)) {
4506         StopTwinkling();
4507         return;
4508     }
4509     UpdateCaretByClick(GetCaretClickLocalOffset(info.GetLocalLocation()));
4510     auto tmpHost = GetHost();
4511     CHECK_NULL_VOID(tmpHost);
4512     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4513 }
4514 
UpdateShiftFlag(const KeyEvent & keyEvent)4515 void TextFieldPattern::UpdateShiftFlag(const KeyEvent& keyEvent)
4516 {
4517     bool flag = false;
4518     if (keyEvent.action == KeyAction::DOWN) {
4519         if (keyEvent.HasKey(KeyCode::KEY_SHIFT_LEFT) || keyEvent.HasKey(KeyCode::KEY_SHIFT_RIGHT)) {
4520             flag = true;
4521         }
4522     }
4523     if (flag != shiftFlag_) {
4524         shiftFlag_ = flag;
4525         if (!shiftFlag_) {
4526             // open drag
4527             InitDragEvent();
4528         } else  {
4529             // close drag
4530             ClearDragDropEvent();
4531         }
4532     }
4533 }
4534 
UpdateCaretByClick(const Offset & localOffset)4535 void TextFieldPattern::UpdateCaretByClick(const Offset& localOffset)
4536 {
4537     if (shiftFlag_) {
4538         selectController_->UpdateSecondHandleInfoByMouseOffset(localOffset);
4539         StopTwinkling();
4540     } else {
4541         selectController_->UpdateCaretInfoByOffset(localOffset, true, false);
4542         StartTwinkling();
4543     }
4544 }
4545 
HandleLeftMouseMoveEvent(MouseInfo & info)4546 void TextFieldPattern::HandleLeftMouseMoveEvent(MouseInfo& info)
4547 {
4548     if (!leftMouseCanMove_ || blockPress_) {
4549         return;
4550     }
4551     auto focusHub = GetFocusHub();
4552     if (!focusHub->IsCurrentFocus()) {
4553         return;
4554     }
4555     mouseStatus_ = MouseStatus::MOVE;
4556     if (GetTextUtf16Value().empty()) {
4557         return;
4558     }
4559     selectController_->UpdateSecondHandleInfoByMouseOffset(info.GetLocalLocation()); // 更新时上报事件
4560     showSelect_ = true;
4561     auto tmpHost = GetHost();
4562     CHECK_NULL_VOID(tmpHost);
4563     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4564 }
4565 
HandleLeftMouseReleaseEvent(MouseInfo & info)4566 void TextFieldPattern::HandleLeftMouseReleaseEvent(MouseInfo& info)
4567 {
4568     auto tmpHost = GetHost();
4569     CHECK_NULL_VOID(tmpHost);
4570     if (blockPress_ && mouseStatus_ == MouseStatus::PRESSED) {
4571         selectController_->UpdateCaretInfoByOffset(info.GetLocalLocation(), true, false);
4572         StartTwinkling();
4573         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4574     }
4575     FreeMouseStyleHoldNode(info.GetLocalLocation());
4576     mouseStatus_ = MouseStatus::NONE;
4577     blockPress_ = false;
4578     leftMouseCanMove_ = false;
4579     if (HasFocus() && RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::MOUSE_RELEASE)) {
4580         NotifyOnEditChanged(true);
4581         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
4582     }
4583 }
4584 
FreeMouseStyleHoldNode(const Offset location)4585 void TextFieldPattern::FreeMouseStyleHoldNode(const Offset location)
4586 {
4587     auto rect = RectF(0.0f, 0.0f, frameRect_.Width(), frameRect_.Height());
4588     if (!location.IsPositiveOffset() || !rect.IsInRegion({ location.GetX(), location.GetY() })) {
4589         auto tmpHost = GetHost();
4590         CHECK_NULL_VOID(tmpHost);
4591         auto frameId = tmpHost->GetId();
4592         auto pipeline = GetContext();
4593         CHECK_NULL_VOID(pipeline);
4594         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "FreeMouseStyleHoldNode, id:%{public}d", frameId);
4595         pipeline->FreeMouseStyleHoldNode(frameId);
4596     }
4597 }
4598 
UpdateTextFieldManager(const Offset & offset,float height)4599 void TextFieldPattern::UpdateTextFieldManager(const Offset& offset, float height)
4600 {
4601     auto tmpHost = GetHost();
4602     CHECK_NULL_VOID(tmpHost);
4603     auto context = tmpHost->GetContextRefPtr();
4604     CHECK_NULL_VOID(context);
4605     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
4606     CHECK_NULL_VOID(textFieldManager);
4607     auto safeAreaManager = context->GetSafeAreaManager();
4608     CHECK_NULL_VOID(safeAreaManager);
4609     textFieldManager->UpdateScrollableParentViewPort(tmpHost);
4610     if (!HasFocus()) {
4611         return;
4612     }
4613     textFieldManager->SetClickPosition({ offset.GetX() + selectController_->GetCaretRect().GetX(),
4614         offset.GetY() + selectController_->GetCaretRect().GetY() });
4615     textFieldManager->SetHeight(selectController_->GetCaretRect().Height());
4616     textFieldManager->SetClickPositionOffset(safeAreaManager->GetKeyboardOffset());
4617     textFieldManager->SetOnFocusTextField(WeakClaim(this));
4618     textFieldManager->SetUsingCustomKeyboardAvoid(keyboardAvoidance_);
4619     textFieldManager->SetIfFocusTextFieldIsInline(IsNormalInlineState());
4620 }
4621 
GetDefaultTextInputAction() const4622 TextInputAction TextFieldPattern::GetDefaultTextInputAction() const
4623 {
4624     TextInputAction defaultTextInputAction = TextInputAction::DONE;
4625     if (IsTextArea() && !isTextInput_) {
4626         defaultTextInputAction = TextInputAction::NEW_LINE;
4627     } else {
4628         defaultTextInputAction = TextInputAction::DONE;
4629     }
4630     return defaultTextInputAction;
4631 }
4632 
4633 #ifdef WINDOW_SCENE_SUPPORTED
GetSCBSystemWindowId()4634 uint32_t TextFieldPattern::GetSCBSystemWindowId()
4635 {
4636     RefPtr<FrameNode> frameNode = GetHost();
4637     CHECK_NULL_RETURN(frameNode, {});
4638     auto focusSystemWindowId = WindowSceneHelper::GetFocusSystemWindowId(frameNode);
4639     return focusSystemWindowId;
4640 }
4641 #endif
4642 
KeyboardContentTypeToInputType()4643 void TextFieldPattern::KeyboardContentTypeToInputType()
4644 {
4645     if (keyboard_ != TextInputType::UNSPECIFIED) {
4646         return;
4647     }
4648     auto autoFillType = GetAutoFillType(false);
4649     if (keyBoardMap_.find(autoFillType) != keyBoardMap_.end()) {
4650         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
4651             "Set InputType to %{public}d because of contentType", keyBoardMap_[autoFillType]);
4652         keyboard_ = keyBoardMap_[autoFillType];
4653     }
4654 }
4655 
GetRequestKeyboardId()4656 int32_t TextFieldPattern::GetRequestKeyboardId()
4657 {
4658     auto host = GetHost();
4659     CHECK_NULL_RETURN(host, -1);
4660     return host->GetId();
4661 }
4662 
RequestKeyboard(bool isFocusViewChanged,bool needStartTwinkling,bool needShowSoftKeyboard,SourceType sourceType)4663 bool TextFieldPattern::RequestKeyboard(bool isFocusViewChanged, bool needStartTwinkling, bool needShowSoftKeyboard,
4664     SourceType sourceType)
4665 {
4666     bool isFocus = HasFocus();
4667     if (!showKeyBoardOnFocus_ || !isFocus) {
4668         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "showKeyBoardOnFocus:%{public}d, isFocus:%{public}d", showKeyBoardOnFocus_,
4669             isFocus);
4670         return false;
4671     }
4672     auto tmpHost = GetHost();
4673     CHECK_NULL_RETURN(tmpHost, false);
4674     if (customKeyboard_ || customKeyboardBuilder_) {
4675         CHECK_NULL_RETURN(needShowSoftKeyboard, true);
4676         return RequestCustomKeyboard();
4677     }
4678     bool ok = true;
4679     KeyboardContentTypeToInputType();
4680 #if defined(ENABLE_STANDARD_INPUT)
4681     if (textChangeListener_ == nullptr) {
4682         textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this));
4683     }
4684     auto inputMethod = MiscServices::InputMethodController::GetInstance();
4685     if (!inputMethod) {
4686         TAG_LOGE(AceLogTag::ACE_TEXT_FIELD, "RequestKeyboard, inputMethod is null");
4687         return false;
4688     }
4689     FireOnWillAttachIME();
4690     auto optionalTextConfig = GetMiscTextConfig();
4691     CHECK_NULL_RETURN(optionalTextConfig.has_value(), false);
4692     MiscServices::TextConfig textConfig = optionalTextConfig.value();
4693     ACE_LAYOUT_SCOPED_TRACE("RequestKeyboard[id:%d][WId:%u]", tmpHost->GetId(), textConfig.windowId);
4694     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
4695         "node:%{public}d, RequestKeyboard set calling window id:%{public}u"
4696         " inputType:%{public}d, enterKeyType:%{public}d, needKeyboard:%{public}d, sourceType:%{public}u"
4697         " placeholderLength:%{public}zu",
4698         tmpHost->GetId(), textConfig.windowId, textConfig.inputAttribute.inputPattern,
4699         textConfig.inputAttribute.enterKeyType, needShowSoftKeyboard, sourceType,
4700         CountUtf16Chars(textConfig.inputAttribute.placeholder));
4701 #ifdef WINDOW_SCENE_SUPPORTED
4702     auto systemWindowId = GetSCBSystemWindowId();
4703     if (systemWindowId) {
4704         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "windowId From %{public}u to %{public}u.", textConfig.windowId,
4705             systemWindowId);
4706         textConfig.windowId = systemWindowId;
4707     }
4708 #endif
4709     if ((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_) {
4710         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Request SoftKeyboard, Close CustomKeyboard.");
4711         CloseCustomKeyboard();
4712     }
4713     auto context = GetContext();
4714     if (context && context->GetTextFieldManager()) {
4715         auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
4716         textFieldManager->SetImeAttached(true);
4717         textFieldManager->SetLastRequestKeyboardId(GetRequestKeyboardId());
4718     }
4719     OHOS::MiscServices::AttachOptions attachOptions;
4720     attachOptions.isShowKeyboard = needShowSoftKeyboard;
4721     attachOptions.requestKeyboardReason =
4722         static_cast<OHOS::MiscServices::RequestKeyboardReason>(static_cast<int32_t>(sourceType));
4723     auto ret = inputMethod->Attach(textChangeListener_, attachOptions, textConfig);
4724     CHECK_NULL_RETURN(context, false);
4725     auto textFieldManager = AceType::DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
4726     CHECK_NULL_RETURN(textFieldManager, false);
4727     if (ret == MiscServices::ErrorCode::NO_ERROR) {
4728         textFieldManager->SetIsImeAttached(true);
4729         textFieldManager->SetAttachInputId(GetRequestKeyboardId());
4730     }
4731     UpdateCaretInfoToController(true);
4732     auto fillContentMap = textFieldManager->GetFillContentMap(tmpHost->GetId());
4733     if (!fillContentMap.empty() && NeedsSendFillContent()) {
4734         inputMethod->SendPrivateCommand(fillContentMap);
4735     }
4736 #else
4737     ok = RequestKeyboardCrossPlatForm(isFocusViewChanged);
4738 #endif
4739     return ok;
4740 }
4741 
RequestKeyboardCrossPlatForm(bool isFocusViewChanged)4742 bool TextFieldPattern::RequestKeyboardCrossPlatForm(bool isFocusViewChanged)
4743 {
4744 #if !defined(ENABLE_STANDARD_INPUT)
4745     auto tmpHost = GetHost();
4746     CHECK_NULL_RETURN(tmpHost, false);
4747     auto context = tmpHost->GetContextRefPtr();
4748     CHECK_NULL_RETURN(context, false);
4749     if (!HasConnection()) {
4750         TextInputConfiguration config;
4751         config.type = keyboard_;
4752         config.action = GetTextInputActionValue(GetDefaultTextInputAction());
4753         config.inputFilter = GetInputFilter();
4754         config.maxLength = GetMaxLength();
4755         if (keyboard_ == TextInputType::VISIBLE_PASSWORD || keyboard_ == TextInputType::NEW_PASSWORD) {
4756             config.obscureText = textObscured_;
4757         }
4758         connection_ = TextInputProxy::GetInstance().Attach(
4759             WeakClaim(this), config, context->GetTaskExecutor(), GetInstanceId());
4760 
4761         if (!HasConnection()) {
4762             return false;
4763         }
4764     }
4765     TextEditingValue value;
4766     value.text = contentController_->GetTextValue();
4767     value.hint = UtfUtils::Str16DebugToStr8(GetPlaceHolder());
4768     value.selection.Update(selectController_->GetStartIndex(), selectController_->GetEndIndex());
4769     connection_->SetEditingState(value, GetInstanceId());
4770     connection_->Show(isFocusViewChanged, GetInstanceId());
4771 #endif
4772     return true;
4773 }
4774 
4775 #if defined(ENABLE_STANDARD_INPUT)
GetMiscTextConfig() const4776 std::optional<MiscServices::TextConfig> TextFieldPattern::GetMiscTextConfig() const
4777 {
4778     auto tmpHost = GetHost();
4779     CHECK_NULL_RETURN(tmpHost, {});
4780     auto pipeline = tmpHost->GetContext();
4781     CHECK_NULL_RETURN(pipeline, {});
4782     auto theme = GetTheme();
4783     CHECK_NULL_RETURN(theme, {});
4784     auto windowRect = pipeline->GetCurrentWindowRect();
4785     double positionY = (tmpHost->GetPaintRectOffset(false, true) - pipeline->GetRootRect().GetOffset()).GetY() + windowRect.Top();
4786     auto offset = AVOID_OFFSET.ConvertToPx();
4787     auto textPaintOffset = GetPaintRectGlobalOffset();
4788     double height = selectController_->GetCaretRect().Bottom() + windowRect.Top() +
4789              textPaintOffset.GetY() + offset - positionY;
4790     std::u16string placeholder = TruncateText(GetPlaceHolder(), MAX_PLACEHOLDER_SIZE);
4791     std::u16string abilityName = TruncateText(UtfUtils::Str8ToStr16(AceApplicationInfo::GetInstance()
4792         .GetAbilityName()), MAX_ABILITY_NAME_SIZE);
4793 
4794     GetInlinePositionYAndHeight(positionY, height);
4795 
4796     auto manager = pipeline->GetSafeAreaManager();
4797     if (manager) {
4798         auto keyboardOffset = manager->GetKeyboardOffset();
4799         positionY -= keyboardOffset;
4800     }
4801 
4802     ContainerScope scope(GetInstanceId());
4803     auto container = AceType::DynamicCast<Platform::AceContainer>(Container::Current());
4804 
4805     MiscServices::CursorInfo cursorInfo { .left = selectController_->GetCaretRect().Left() + windowRect.Left() +
4806                                                   textPaintOffset.GetX(),
4807         .top = selectController_->GetCaretRect().Top() + windowRect.Top() + textPaintOffset.GetY(),
4808         .width = theme->GetCursorWidth().ConvertToPx(),
4809         .height = selectController_->GetCaretRect().Height() };
4810     TAG_LOGI(ACE_TEXT_FIELD, "gradientMode = %{public}d fluidLightMode = %{public}d", imeGradientMode_, imeFluidLightMode_);
4811     MiscServices::InputAttribute inputAttribute = { .inputPattern = (int32_t)keyboard_,
4812         .enterKeyType = (int32_t)GetTextInputActionValue(GetDefaultTextInputAction()),
4813         .isTextPreviewSupported = hasSupportedPreviewText_,
4814         .immersiveMode = static_cast<int32_t>(keyboardAppearance_),
4815         .placeholder = placeholder,
4816         .abilityName = abilityName,
4817         .capitalizeMode = static_cast<MiscServices::CapitalizeMode>(GetAutoCapitalizationModeValue(AutoCapitalizationMode::NONE)),
4818         .gradientMode = static_cast<int32_t>(imeGradientMode_),
4819         .fluidLightMode = static_cast<int32_t>(imeFluidLightMode_)
4820     };
4821     MiscServices::TextConfig textConfig = { .inputAttribute = inputAttribute,
4822         .cursorInfo = cursorInfo,
4823         .range = { .start = selectController_->GetStartIndex(), .end = selectController_->GetEndIndex() },
4824         .windowId = pipeline->GetFocusWindowId(),
4825         .positionY = positionY,
4826         .height = height,
4827         .abilityToken = container ? container->GetToken() : nullptr
4828     };
4829 
4830     return textConfig;
4831 }
4832 
GetInlinePositionYAndHeight(double & positionY,double & height) const4833 void TextFieldPattern::GetInlinePositionYAndHeight(double& positionY, double& height) const
4834 {
4835     if (IsNormalInlineState()) {
4836         auto theme = GetTheme();
4837         CHECK_NULL_VOID(theme);
4838         auto offset = AVOID_OFFSET.ConvertToPx();
4839         auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4840         PaddingProperty userPadding;
4841         if (paintProperty->HasPaddingByUser()) {
4842             userPadding = paintProperty->GetPaddingByUserValue();
4843         } else {
4844             userPadding.top = CalcLength(theme->GetPadding().Top());
4845         }
4846         auto topPadding = userPadding.top->GetDimension().ConvertToPx();
4847         auto safeBoundary = theme->GetInlineBorderWidth().ConvertToPx() * 2;
4848         positionY += static_cast<double>(inlineMeasureItem_.inlineSizeHeight) + safeBoundary + topPadding;
4849         height = offset;
4850 
4851         auto tmpHost = GetHost();
4852         CHECK_NULL_VOID(tmpHost);
4853         auto pipeline = tmpHost->GetContextRefPtr();
4854         CHECK_NULL_VOID(pipeline);
4855         auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
4856         CHECK_NULL_VOID(textFieldManager);
4857         TAG_LOGI(ACE_TEXT_FIELD, "SetInlineAvoidInfo positionY:%{public}f height:%{public}f sizeHeight:%{public}f",
4858             positionY, height, inlineMeasureItem_.inlineSizeHeight);
4859         textFieldManager->SetInlineTextFieldAvoidPositionYAndHeight(positionY, height);
4860     }
4861 }
4862 
4863 #endif
4864 
ConvertToAceAutoFillType(TextInputType type)4865 AceAutoFillType TextFieldPattern::ConvertToAceAutoFillType(TextInputType type)
4866 {
4867     static std::unordered_map<TextInputType, AceAutoFillType> convertMap = {
4868         { TextInputType::VISIBLE_PASSWORD, AceAutoFillType::ACE_PASSWORD },
4869         { TextInputType::USER_NAME, AceAutoFillType::ACE_USER_NAME },
4870         { TextInputType::NEW_PASSWORD, AceAutoFillType::ACE_NEW_PASSWORD },
4871         { TextInputType::NUMBER_PASSWORD, AceAutoFillType::ACE_PASSWORD } };
4872     auto it = convertMap.find(type);
4873     if (it != convertMap.end()) {
4874         return it->second;
4875     }
4876     return AceAutoFillType::ACE_UNSPECIFIED;
4877 }
4878 
TextContentTypeToAceAutoFillType(const TextContentType & type)4879 AceAutoFillType TextFieldPattern::TextContentTypeToAceAutoFillType(const TextContentType& type)
4880 {
4881     if (contentTypeMap_.find(type) != contentTypeMap_.end()) {
4882         return contentTypeMap_[type].first;
4883     }
4884     return contentTypeMap_[TextContentType::UNSPECIFIED].first;
4885 }
4886 
CloseKeyboard(bool forceClose)4887 bool TextFieldPattern::CloseKeyboard(bool forceClose)
4888 {
4889     return CloseKeyboard(forceClose, forceClose);
4890 }
4891 
CloseKeyboard(bool forceClose,bool isStopTwinkling)4892 bool TextFieldPattern::CloseKeyboard(bool forceClose, bool isStopTwinkling)
4893 {
4894     if (forceClose) {
4895         if (isStopTwinkling) {
4896             StopTwinkling();
4897         }
4898         CloseSelectOverlay(true);
4899         auto host = GetHost();
4900         CHECK_NULL_RETURN(host, false);
4901         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Will Close Soft keyboard.", host->GetId());
4902         if ((customKeyboard_ || customKeyboardBuilder_) && isCustomKeyboardAttached_) {
4903             return CloseCustomKeyboard();
4904         }
4905 #if defined(ENABLE_STANDARD_INPUT)
4906         auto inputMethod = MiscServices::InputMethodController::GetInstance();
4907         if (!inputMethod) {
4908             TAG_LOGE(AceLogTag::ACE_TEXT_FIELD, "CloseKeyboard, inputMethod is null");
4909             return false;
4910         }
4911         inputMethod->Close();
4912 #else
4913         if (HasConnection()) {
4914             connection_->Close(GetInstanceId());
4915             connection_ = nullptr;
4916         }
4917 #endif
4918         return true;
4919     }
4920     return false;
4921 }
4922 
SetCustomKeyboardOption(bool supportAvoidance)4923 void TextFieldPattern::SetCustomKeyboardOption(bool supportAvoidance)
4924 {
4925     keyboardAvoidance_ = supportAvoidance;
4926 }
4927 
RequestCustomKeyboard()4928 bool TextFieldPattern::RequestCustomKeyboard()
4929 {
4930 #if defined(ENABLE_STANDARD_INPUT)
4931     auto inputMethod = MiscServices::InputMethodController::GetInstance();
4932     if (inputMethod) {
4933         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "TextField Request CustomKeyboard, Close keyboard Successfully.");
4934         inputMethod->RequestHideInput();
4935         inputMethod->Close();
4936     }
4937 #else
4938     if (HasConnection()) {
4939         connection_->Close(GetInstanceId());
4940         connection_ = nullptr;
4941     }
4942 #endif
4943 
4944     if (isCustomKeyboardAttached_) {
4945         return true;
4946     }
4947     CHECK_NULL_RETURN(customKeyboard_ || customKeyboardBuilder_, false);
4948     auto frameNode = GetHost();
4949     CHECK_NULL_RETURN(frameNode, false);
4950     ACE_LAYOUT_SCOPED_TRACE("RequestCustomKeyboard[id:%d]", frameNode->GetId());
4951     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "RequestCustomKeyboard, id:%{public}d", frameNode->GetId());
4952     auto pipeline = frameNode->GetContext();
4953     CHECK_NULL_RETURN(pipeline, false);
4954     auto overlayManager = pipeline->GetOverlayManager();
4955     CHECK_NULL_RETURN(overlayManager, false);
4956     overlayManager->SetCustomKeyboardOption(keyboardAvoidance_);
4957     if (customKeyboardBuilder_) {
4958         overlayManager->BindKeyboard(customKeyboardBuilder_, frameNode->GetId());
4959     } else {
4960         overlayManager->BindKeyboardWithNode(customKeyboard_, frameNode->GetId());
4961     }
4962     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
4963     if (textFieldManager) {
4964         textFieldManager->SetLastRequestKeyboardId(GetRequestKeyboardId());
4965     }
4966     isCustomKeyboardAttached_ = true;
4967     keyboardOverlay_ = overlayManager;
4968     auto caretHeight = selectController_->GetCaretRect().Height();
4969     auto safeHeight = caretHeight + selectController_->GetCaretRect().GetY();
4970     if (selectController_->GetCaretRect().GetY() > caretHeight) {
4971         safeHeight = caretHeight;
4972     }
4973     keyboardOverlay_->AvoidCustomKeyboard(frameNode->GetId(), safeHeight);
4974     return true;
4975 }
4976 
CloseCustomKeyboard()4977 bool TextFieldPattern::CloseCustomKeyboard()
4978 {
4979     auto frameNode = GetHost();
4980     CHECK_NULL_RETURN(frameNode, false);
4981     CHECK_NULL_RETURN(keyboardOverlay_, false);
4982     keyboardOverlay_->CloseKeyboard(frameNode->GetId());
4983     isCustomKeyboardAttached_ = false;
4984     return true;
4985 }
4986 
OnTextInputActionUpdate(TextInputAction value)4987 void TextFieldPattern::OnTextInputActionUpdate(TextInputAction value) {}
4988 
OnAutoCapitalizationModeUpdate(AutoCapitalizationMode value)4989 void TextFieldPattern::OnAutoCapitalizationModeUpdate(AutoCapitalizationMode value) {}
4990 
OnThemeScopeUpdate(int32_t themeScopeId)4991 bool TextFieldPattern::OnThemeScopeUpdate(int32_t themeScopeId)
4992 {
4993     bool result = false;
4994     bool updateFlag = true;
4995     auto host = GetHost();
4996     CHECK_NULL_RETURN(host, result);
4997     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
4998     CHECK_NULL_RETURN(paintProperty, false);
4999     auto textFieldLayoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5000     CHECK_NULL_RETURN(textFieldLayoutProperty, false);
5001     auto pipeline = host->GetContext();
5002     CHECK_NULL_RETURN(pipeline, result);
5003     auto textFieldTheme = pipeline->GetTheme<TextFieldTheme>(themeScopeId);
5004     textFieldTheme_ = textFieldTheme;
5005     CHECK_NULL_RETURN(textFieldTheme, result);
5006 
5007     if (!paintProperty->HasBackgroundColor() && !IsUnderlineMode()) {
5008         auto renderContext = host->GetRenderContext();
5009         CHECK_NULL_RETURN(renderContext, result);
5010         auto bgColor = IsInlineMode() ? textFieldTheme->GetInlineBgColor() : textFieldTheme->GetBgColor();
5011         renderContext->UpdateBackgroundColor(bgColor);
5012         result = true;
5013     }
5014 
5015     if (!paintProperty->HasTextColorFlagByUser()) {
5016         textFieldLayoutProperty->UpdateTextColor(textFieldTheme->GetTextColor());
5017         result = true;
5018     }
5019 
5020     if (!paintProperty->GetCaretColorFlagByUserValue(false)) {
5021         paintProperty->UpdateCursorColor(textFieldTheme->GetCursorColor());
5022         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5023     }
5024 
5025     if (result || !paintProperty->GetPlaceholderColorFlagByUserValue(false)) {
5026         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5027         updateFlag = false;
5028     }
5029     if (responseArea_) {
5030         responseArea_->OnThemeScopeUpdate(textFieldTheme);
5031     }
5032     if (cleanNodeResponseArea_) {
5033         cleanNodeResponseArea_->OnThemeScopeUpdate(textFieldTheme);
5034     }
5035     return updateFlag;
5036 }
5037 
BeforeIMEInsertValue(const std::u16string & insertValue,int32_t offset)5038 bool TextFieldPattern::BeforeIMEInsertValue(const std::u16string& insertValue, int32_t offset)
5039 {
5040     auto host = GetHost();
5041     CHECK_NULL_RETURN(host, true);
5042     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
5043     CHECK_NULL_RETURN(eventHub, true);
5044     InsertValueInfo insertValueInfo;
5045     insertValueInfo.insertOffset = offset;
5046     insertValueInfo.insertValue = insertValue;
5047     return eventHub->FireOnWillInsertValueEvent(insertValueInfo);
5048 }
5049 
AfterIMEInsertValue(const std::u16string & insertValue)5050 void TextFieldPattern::AfterIMEInsertValue(const std::u16string& insertValue)
5051 {
5052     auto host = GetHost();
5053     CHECK_NULL_VOID(host);
5054     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
5055     CHECK_NULL_VOID(eventHub);
5056     InsertValueInfo insertValueInfo;
5057     auto offset = selectController_->GetCaretIndex();
5058     insertValueInfo.insertOffset = offset;
5059     insertValueInfo.insertValue = insertValue;
5060     return eventHub->FireOnDidInsertValueEvent(insertValueInfo);
5061 }
5062 
CalcCounterAfterFilterInsertValue(int32_t curLength,const std::u16string insertValue,int32_t maxLength)5063 void TextFieldPattern::CalcCounterAfterFilterInsertValue(
5064     int32_t curLength, const std::u16string insertValue, int32_t maxLength)
5065 {
5066     bool textChange = false;
5067     auto result = insertValue;
5068     contentController_->FilterTextInputStyle(textChange, result);
5069     int32_t sum = curLength + static_cast<int32_t>(result.length());
5070     showCountBorderStyle_ = sum > maxLength;
5071     HandleCountStyle();
5072 }
5073 
NotifyImfFinishTextPreview()5074 void TextFieldPattern::NotifyImfFinishTextPreview()
5075 {
5076     if (!HasFocus()) {
5077         return;
5078     }
5079 #if defined(ENABLE_STANDARD_INPUT)
5080     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
5081         u"", 0, 0);
5082     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "notify imf that textfield exit textPreview");
5083 #endif
5084 }
5085 
InsertValueByController(const std::u16string & insertValue,int32_t offset)5086 int32_t TextFieldPattern::InsertValueByController(const std::u16string& insertValue, int32_t offset)
5087 {
5088     auto host = GetHost();
5089     CHECK_NULL_RETURN(host, offset);
5090     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5091     CHECK_NULL_RETURN(layoutProperty, offset);
5092     ChangeValueInfo changeValueInfo;
5093     changeValueInfo.oldContent = GetBodyTextValue();
5094     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
5095     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
5096     changeValueInfo.rangeBefore = TextRange { offset, offset };
5097     NotifyImfFinishTextPreview();
5098     int32_t originLength =
5099         static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5100     bool hasInsertValue =
5101         contentController_->InsertValue(offset, insertValue);
5102     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
5103     changeValueInfo.previewText.value = GetPreviewTextValue();
5104     changeValueInfo.value = contentController_->GetTextUtf16Value();
5105     changeValueInfo.rangeAfter =
5106         TextRange { offset, offset + static_cast<int32_t>(contentController_->GetInsertValue().length()) };
5107     bool isWillChange = FireOnWillChange(changeValueInfo);
5108     if (!isWillChange) {
5109         contentController_->SetTextValue(changeValueInfo.oldContent);
5110         return false;
5111     }
5112     int32_t caretMoveLength =
5113         abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength);
5114     if (layoutProperty->HasMaxLength()) {
5115         CalcCounterAfterFilterInsertValue(originLength, insertValue,
5116             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
5117     }
5118     selectController_->UpdateCaretIndex(offset + caretMoveLength);
5119 
5120     auto pipeline = host->GetContext();
5121     CHECK_NULL_RETURN(pipeline, offset);
5122     pipeline->AddAfterLayoutTask([weak = WeakClaim(Referenced::RawPtr(selectController_))]() {
5123         auto selectController = weak.Upgrade();
5124         CHECK_NULL_VOID(selectController);
5125         int32_t index = selectController->GetCaretIndex();
5126         selectController->MoveCaretToContentRect(index);
5127     });
5128 
5129     UpdateObscure(insertValue, hasInsertValue);
5130     UpdateEditingValueToRecord();
5131     focusIndex_ = FocuseIndex::TEXT;
5132     TwinklingByFocus();
5133     CloseSelectOverlay(true);
5134     ScrollToSafeArea();
5135     ProcessResponseArea();
5136     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5137     return selectController_->GetCaretIndex();
5138 }
5139 
ExecuteInsertValueCommand(const InsertCommandInfo & info)5140 void TextFieldPattern::ExecuteInsertValueCommand(const InsertCommandInfo& info)
5141 {
5142     auto insertValue = info.insertValue;
5143     auto isIME = (info.reason == InputReason::IME);
5144     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5145     CHECK_NULL_VOID(layoutProperty);
5146     TwinklingByFocus();
5147     auto start = selectController_->GetStartIndex();
5148     auto end = selectController_->GetEndIndex();
5149     auto caretStart = IsSelected() ? start : selectController_->GetCaretIndex();
5150     if (isIME) {
5151         auto isInsert = BeforeIMEInsertValue(insertValue, caretStart);
5152         CHECK_NULL_VOID(isInsert);
5153     }
5154     int32_t caretMoveLength = 0;
5155     bool hasInsertValue = false;
5156     int32_t originLength = 0;
5157     auto oldContent = contentController_->GetTextUtf16Value();
5158     auto originCaretIndex =
5159             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
5160     if (IsSelected()) {
5161         auto value = contentController_->GetSelectedValue(start, end);
5162         auto isDelete = true;
5163         if (isIME) {
5164             isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::BACKWARD, end);
5165         }
5166         end = isDelete ? end : start;
5167         originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
5168         hasInsertValue = contentController_->ReplaceSelectedValue(start, end, insertValue);
5169         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength);
5170         bool isWillChange = OnWillChangePreInsert(contentController_->GetInsertValue(), oldContent, start, end);
5171         if (!isWillChange) {
5172             RecoverTextValueAndCaret(oldContent, originCaretIndex);
5173             return;
5174         }
5175         if (isIME && isDelete) {
5176             selectController_->UpdateCaretIndex(start);
5177             AfterIMEDeleteValue(value, TextDeleteDirection::BACKWARD);
5178         }
5179     } else {
5180         originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5181         hasInsertValue = contentController_->InsertValue(selectController_->GetCaretIndex(), insertValue);
5182         caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength);
5183         bool isWillChange = OnWillChangePreInsert(contentController_->GetInsertValue(), oldContent, start, end);
5184         if (!isWillChange) {
5185             RecoverTextValueAndCaret(oldContent, originCaretIndex);
5186             return;
5187         }
5188     }
5189     if (layoutProperty->HasMaxLength()) {
5190         CalcCounterAfterFilterInsertValue(originLength, insertValue,
5191             static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
5192     }
5193     selectController_->UpdateCaretIndex(caretStart + caretMoveLength);
5194     UpdateObscure(insertValue, hasInsertValue);
5195     UpdateEditingValueToRecord();
5196     if (isIME) {
5197         AfterIMEInsertValue(contentController_->GetInsertValue());
5198     }
5199 }
5200 
TwinklingByFocus()5201 void TextFieldPattern::TwinklingByFocus()
5202 {
5203     if (HasFocus() && focusIndex_ == FocuseIndex::TEXT) {
5204         cursorVisible_ = true;
5205         StartTwinkling();
5206     } else {
5207         cursorVisible_ = false;
5208         StopTwinkling();
5209     }
5210 }
5211 
FinishTextPreviewByPreview(const std::u16string & insertValue)5212 bool TextFieldPattern::FinishTextPreviewByPreview(const std::u16string& insertValue)
5213 {
5214     if (GetIsPreviewText()) {
5215         PreviewTextInfo info = {
5216             .text = insertValue,
5217             .range = { -1, -1 },
5218             .isIme = false
5219         };
5220         inputOperations_.emplace(InputOperation::SET_PREVIEW_TEXT);
5221         previewTextOperation_.emplace(info);
5222         FinishTextPreview();
5223         return true;
5224     }
5225     return false;
5226 }
5227 
UpdateObscure(const std::u16string & insertValue,bool hasInsertValue)5228 void TextFieldPattern::UpdateObscure(const std::u16string& insertValue, bool hasInsertValue)
5229 {
5230     if (!IsTextArea() && IsInPasswordMode() && GetTextObscured()) {
5231         auto host = GetHost();
5232         CHECK_NULL_VOID(host);
5233         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
5234         CHECK_NULL_VOID(layoutProperty);
5235         if (insertValue.length() == 1 &&
5236             (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) != TextInputType::NUMBER_PASSWORD ||
5237                 std::isdigit(insertValue[0])) &&
5238             hasInsertValue) {
5239             auto content = contentController_->GetTextUtf16Value();
5240             auto insertIndex = selectController_->GetCaretIndex() - 1;
5241             insertIndex = std::clamp(insertIndex, 0, static_cast<int32_t>(content.length()));
5242             auto strBeforeCaret = content.empty() ? u"" : content.substr(insertIndex, 1);
5243             obscureTickCountDown_ = strBeforeCaret == insertValue ? OBSCURE_SHOW_TICKS : 0;
5244             nakedCharPosition_ = strBeforeCaret == insertValue ? insertIndex : -1;
5245         } else {
5246             obscureTickCountDown_ = 0;
5247             nakedCharPosition_ = -1;
5248         }
5249     }
5250 }
5251 
InsertValue(const std::u16string & insertValue,bool isIME)5252 void TextFieldPattern::InsertValue(const std::u16string& insertValue, bool isIME)
5253 {
5254     InputReason reason = isIME ? InputReason::IME : InputReason::NONE;
5255     AddInsertCommand(insertValue, reason);
5256 }
5257 
InsertValue(const std::string & insertValue,bool isIME)5258 void TextFieldPattern::InsertValue(const std::string& insertValue, bool isIME)
5259 {
5260     InsertValue(UtfUtils::Str8DebugToStr16(insertValue), isIME);
5261 }
5262 
UltralimitShake()5263 void TextFieldPattern::UltralimitShake()
5264 {
5265     auto frameNode = GetHost();
5266     CHECK_NULL_VOID(frameNode);
5267     auto context = frameNode->GetRenderContext();
5268     CHECK_NULL_VOID(context);
5269     AnimationOption option;
5270     context->UpdateTranslateInXY({ -1.0, 0.0 });
5271     const RefPtr<InterpolatingSpring> curve =
5272         AceType::MakeRefPtr<InterpolatingSpring>(VELOCITY, MASS, STIFFNESS, DAMPING);
5273     option.SetCurve(curve);
5274     option.SetFillMode(FillMode::FORWARDS);
5275     auto pipelineContext = frameNode->GetContext();
5276     CHECK_NULL_VOID(pipelineContext);
5277     AnimationUtils::Animate(
5278         option,
5279         [weak = WeakClaim(Referenced::RawPtr(context))]() {
5280             auto context = weak.Upgrade();
5281             CHECK_NULL_VOID(context);
5282             context->UpdateTranslateInXY({ 0.0f, 0.0f });
5283         },
5284         option.GetOnFinishEvent());
5285 }
5286 
AdjustFloatingCaretInfo(const Offset & localOffset,const HandleInfoNG & caretInfo,HandleInfoNG & floatingCaretInfo)5287 void TextFieldPattern::AdjustFloatingCaretInfo(const Offset& localOffset,
5288     const HandleInfoNG& caretInfo, HandleInfoNG& floatingCaretInfo)
5289 {
5290     CHECK_NULL_VOID(selectController_);
5291     auto offsetX = localOffset.GetX();
5292     auto offsetY = caretInfo.rect.Top();
5293     floatingCaretInfo.rect.SetHeight(caretInfo.rect.Height());
5294     auto contentRect = GetTextContentRect();
5295     offsetX = std::min(std::max(contentRect.Left(), static_cast<float>(offsetX)),
5296         contentRect.Right() - caretInfo.rect.Width());
5297     offsetY = std::min(std::max(contentRect.Top(), static_cast<float>(offsetY)),
5298         contentRect.Bottom() - floatingCaretInfo.rect.Height());
5299     floatingCaretInfo.UpdateOffset({offsetX, offsetY});
5300     bool reachBoundary = NearEqual(contentRect.Left(), offsetX) ||
5301         NearEqual(contentRect.Right() - caretInfo.rect.Width(), static_cast<float>(offsetX));
5302     bool distanceMoreThenTenVp = floatingCaretInfo.rect.GetOffset().GetDistance(caretInfo.rect.GetOffset())
5303         >= FLOATING_CARET_SHOW_ORIGIN_CARET_DISTANCE.ConvertToPx();
5304     TouchPosition pos = selectController_->GetTouchLinePos(localOffset);
5305     bool FloatCursorOnOriginLeft = floatingCaretInfo.rect.GetX() < caretInfo.rect.GetX();
5306     bool FloatCursorNotInText = ((pos == TouchPosition::LEFT && FloatCursorOnOriginLeft) ||
5307         (pos == TouchPosition::RIGHT && !FloatCursorOnOriginLeft));
5308     SetShowOriginCursor((reachBoundary || distanceMoreThenTenVp) && FloatCursorNotInText);
5309     SetFloatingCursorVisible(true);
5310 }
5311 
FloatingCaretLand()5312 void TextFieldPattern::FloatingCaretLand()
5313 {
5314     CHECK_NULL_VOID(floatCaretState_.FloatingCursorVisible && textFieldOverlayModifier_ && selectController_);
5315     textFieldOverlayModifier_->StartFloatingCaretLand(selectController_->GetCaretRect().GetOffset());
5316 }
5317 
CleanCounterNode()5318 void TextFieldPattern::CleanCounterNode()
5319 {
5320     counterDecorator_.Reset();
5321 }
5322 
CleanErrorNode()5323 void TextFieldPattern::CleanErrorNode()
5324 {
5325     errorDecorator_.Reset();
5326 }
5327 
UpdateEditingValueToRecord(int32_t beforeCaretPosition)5328 void TextFieldPattern::UpdateEditingValueToRecord(int32_t beforeCaretPosition)
5329 {
5330     if (operationRecords_.size() >= RECORD_MAX_LENGTH) {
5331         operationRecords_.erase(operationRecords_.begin());
5332     }
5333     TextEditingValueNG record {
5334         .text = contentController_->GetTextUtf16Value(),
5335         .caretPosition = selectController_->GetCaretIndex(),
5336         .beforeCaretPosition = beforeCaretPosition,
5337     };
5338     operationRecords_.emplace_back(record);
5339 }
5340 
PreferredTextHeight(bool isPlaceholder,bool isAlgorithmMeasure)5341 float TextFieldPattern::PreferredTextHeight(bool isPlaceholder, bool isAlgorithmMeasure)
5342 {
5343     if (!isAlgorithmMeasure && paragraph_ && paragraph_->GetHeight() != 0.0f && paragraph_->GetLineCount() > 0) {
5344         return paragraph_->GetHeight() / paragraph_->GetLineCount();
5345     }
5346     RefPtr<Paragraph> paragraph;
5347     std::u16string textContent;
5348     TextStyle textStyle;
5349     auto tmpHost = GetHost();
5350     CHECK_NULL_RETURN(tmpHost, 0.0f);
5351     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
5352     CHECK_NULL_RETURN(layoutProperty, 0.0f);
5353     auto textFieldTheme = GetTheme();
5354     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
5355     // use text or placeHolder value if exists, space otherwise
5356     if (!isPlaceholder) {
5357         TextFieldLayoutAlgorithm::UpdateTextStyle(tmpHost, layoutProperty, textFieldTheme, textStyle, false);
5358         textContent = u"a";
5359     } else {
5360         TextFieldLayoutAlgorithm::UpdatePlaceholderTextStyle(tmpHost, layoutProperty, textFieldTheme, textStyle, false);
5361         textContent = u"b";
5362     }
5363     if (adaptFontSize_.has_value()) {
5364         textStyle.SetFontSize(adaptFontSize_.value());
5365     }
5366     if (textStyle.GetFontSize().IsNonPositive()) {
5367         textStyle.SetFontSize(DEFAULT_FONT);
5368     }
5369     if (textStyle.GetLineHeight().IsNegative()) {
5370         textStyle.SetLineHeight(Dimension(0.0));
5371     }
5372     ParagraphStyle paraStyle { .direction =
5373                                    TextFieldLayoutAlgorithm::GetTextDirection(contentController_->GetTextUtf16Value()),
5374         .align = textStyle.GetTextAlign(),
5375         .maxLines = textStyle.GetMaxLines(),
5376         .fontLocale = Localization::GetInstance()->GetFontLocale(),
5377         .wordBreak = textStyle.GetWordBreak(),
5378         .ellipsisMode = textStyle.GetEllipsisMode(),
5379         .lineBreakStrategy = textStyle.GetLineBreakStrategy(),
5380         .textOverflow = textStyle.GetTextOverflow(),
5381         .fontSize = FontSizeConvertToPx(textStyle.GetFontSize()) };
5382     paragraph = Paragraph::Create(paraStyle, FontCollection::Current());
5383     CHECK_NULL_RETURN(paragraph, 0.0f);
5384     paragraph->PushStyle(textStyle);
5385     UtfUtils::HandleInvalidUTF16(reinterpret_cast<uint16_t*>(textContent.data()), textContent.length(), 0);
5386     paragraph->AddText(textContent);
5387     paragraph->Build();
5388     paragraph->Layout(std::numeric_limits<double>::infinity());
5389     return paragraph->GetHeight();
5390 }
5391 
FontSizeConvertToPx(const Dimension & fontSize)5392 float TextFieldPattern::FontSizeConvertToPx(const Dimension& fontSize)
5393 {
5394     return fontSize.ConvertToPx();
5395 }
5396 
PreferredLineHeight(bool isAlgorithmMeasure)5397 float TextFieldPattern::PreferredLineHeight(bool isAlgorithmMeasure)
5398 {
5399     return PreferredTextHeight(contentController_->IsEmpty(), isAlgorithmMeasure);
5400 }
5401 
OnCursorMoveDone(TextAffinity textAffinity,std::optional<Offset> offset)5402 void TextFieldPattern::OnCursorMoveDone(TextAffinity textAffinity, std::optional<Offset> offset)
5403 {
5404     auto tmpHost = GetHost();
5405     CHECK_NULL_VOID(tmpHost);
5406     StartTwinkling();
5407     CloseSelectOverlay();
5408     if (offset.has_value()) {
5409         selectController_->UpdateCaretInfoByOffset(offset.value());
5410     } else {
5411         selectController_->MoveCaretToContentRect(GetCaretIndex(), textAffinity);
5412     }
5413     if (ResetObscureTickCountDown()) {
5414         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5415     } else {
5416         tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
5417     }
5418     UpdateCaretInfoToController();
5419 }
5420 
GetWordLength(int32_t originCaretPosition,int32_t directionMove,bool skipNewLineChar)5421 int32_t TextFieldPattern::GetWordLength(int32_t originCaretPosition, int32_t directionMove, bool skipNewLineChar)
5422 {
5423     if (contentController_->IsEmpty()) {
5424         return 0;
5425     }
5426     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5427     if (originCaretPosition < 0 || originCaretPosition > textLength) {
5428         return 0;
5429     }
5430     // directionMove == 0 left, directionMove == 1 right
5431     // cannot get word length by current caret position and direction
5432     if ((directionMove == 0 && originCaretPosition == 0) || (directionMove == 1 && originCaretPosition == textLength)) {
5433         return 0;
5434     }
5435     int32_t offset = 0;
5436     int32_t strIndex = directionMove == 0 ? (originCaretPosition - 1) : originCaretPosition;
5437     auto wideTextValue = contentController_->GetTextUtf16Value();
5438     int32_t wordStart = 0;
5439     int32_t wordEnd = 0;
5440     while (directionMove == 0 ? strIndex >= 0 : strIndex <= textLength) {
5441         auto chr = wideTextValue[strIndex];
5442         // skip the special character
5443         if (chr == L' ' || (chr == L'\n' && skipNewLineChar)) {
5444             if (directionMove == 0) {
5445                 strIndex--;
5446             } else {
5447                 strIndex++;
5448             }
5449             offset++;
5450             continue;
5451         }
5452         // cal word length
5453         if (paragraph_ && paragraph_->GetWordBoundary(strIndex, wordStart, wordEnd)) {
5454             if (directionMove == 1) {
5455                 offset += (wordEnd - strIndex);
5456             } else {
5457                 offset += (strIndex - wordStart + 1); // when move left, actual offset should add 1
5458             }
5459             return std::clamp(offset, 0, textLength);
5460         }
5461         // GetWordBoundary fail
5462         return 0;
5463     }
5464     return std::clamp(offset, 0, textLength);
5465 }
5466 
GetLineBeginPosition(int32_t originCaretPosition,bool needToCheckLineChanged)5467 int32_t TextFieldPattern::GetLineBeginPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
5468 {
5469     if (contentController_->IsEmpty()) {
5470         return 0;
5471     }
5472     auto wideTextValue = contentController_->GetTextUtf16Value();
5473     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
5474     if (originCaretPosition < 0 || originCaretPosition > textLength) {
5475         return 0;
5476     }
5477     if (originCaretPosition == 0) {
5478         return originCaretPosition;
5479     }
5480     int32_t moveLineBeginOffset = 0;
5481     int32_t strIndex = originCaretPosition;
5482     do {
5483         moveLineBeginOffset++;
5484         strIndex--;
5485         // stop moving caret if reaches \n, text head or caret line changed
5486     } while (((strIndex > 0) && (wideTextValue[strIndex] != u'\n')) &&
5487              (needToCheckLineChanged ? !CharLineChanged(strIndex) : true));
5488     if (strIndex < 0 || strIndex >= static_cast<int32_t>(wideTextValue.length())) {
5489         return 0;
5490     }
5491     if (strIndex > 0) {
5492         moveLineBeginOffset--;
5493     }
5494     if (moveLineBeginOffset > originCaretPosition) {
5495         return 0;
5496     }
5497     return originCaretPosition - moveLineBeginOffset;
5498 }
5499 
GetLineEndPosition(int32_t originCaretPosition,bool needToCheckLineChanged)5500 int32_t TextFieldPattern::GetLineEndPosition(int32_t originCaretPosition, bool needToCheckLineChanged)
5501 {
5502     if (contentController_->IsEmpty()) {
5503         return 0;
5504     }
5505     auto wideTextValue = contentController_->GetTextUtf16Value();
5506     int32_t textLength = static_cast<int32_t>(wideTextValue.length());
5507     if (originCaretPosition < 0 || originCaretPosition > textLength) {
5508         return originCaretPosition;
5509     }
5510     if (originCaretPosition == textLength) {
5511         return originCaretPosition;
5512     }
5513     int32_t moveLineEndOffset = 0;
5514     int32_t strIndex = 0;
5515     for (strIndex = originCaretPosition; (strIndex <= textLength && wideTextValue[strIndex] != u'\n') &&
5516                                          (needToCheckLineChanged ? !CharLineChanged(strIndex) : true);
5517          strIndex++) {
5518         moveLineEndOffset++;
5519     }
5520     if (moveLineEndOffset > textLength - originCaretPosition) {
5521         return textLength;
5522     }
5523     return originCaretPosition + moveLineEndOffset;
5524 }
5525 
CharLineChanged(int32_t caretPosition)5526 bool TextFieldPattern::CharLineChanged(int32_t caretPosition)
5527 {
5528     if (caretPosition < 0 || caretPosition > static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5529         return true;
5530     }
5531     CaretMetricsF caretMetrics;
5532     CalcCaretMetricsByPosition(caretPosition, caretMetrics);
5533     // the cursor is aligned with the text at the bottom
5534     return !NearEqual(caretMetrics.offset.GetY() + caretMetrics.height,
5535         selectController_->GetCaretRect().GetY() + selectController_->GetCaretRect().Height());
5536 }
5537 
CursorMoveLeftOperation()5538 bool TextFieldPattern::CursorMoveLeftOperation()
5539 {
5540     if (focusIndex_ != FocuseIndex::TEXT) {
5541         return UpdateFocusBackward();
5542     }
5543     auto originCaretPosition = selectController_->GetCaretIndex();
5544     if (IsSelected()) {
5545         selectController_->UpdateCaretIndex(selectController_->GetStartIndex());
5546         CloseSelectOverlay();
5547     } else {
5548         UpdateCaretPositionWithClamp(
5549             selectController_->GetCaretIndex() -
5550             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetCaretIndex(),
5551                 true));
5552     }
5553     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5554     return originCaretPosition != selectController_->GetCaretIndex();
5555 }
5556 
CursorMoveLeft()5557 bool TextFieldPattern::CursorMoveLeft()
5558 {
5559     if (inputOperations_.empty()) {
5560         return CursorMoveLeftOperation();
5561     }
5562 
5563     inputOperations_.emplace(InputOperation::CURSOR_LEFT);
5564     return false;
5565 }
5566 
CursorMoveLeftWord()5567 bool TextFieldPattern::CursorMoveLeftWord()
5568 {
5569     if (selectController_->GetCaretIndex() == 0) {
5570         return true;
5571     }
5572     int32_t originCaretPosition = selectController_->GetCaretIndex();
5573     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5574     int32_t leftWordLength = GetWordLength(originCaretPosition, 0);
5575     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
5576         return false;
5577     }
5578     if (IsSelected()) {
5579         selectController_->UpdateCaretIndex(selectController_->GetSecondHandleIndex() - leftWordLength);
5580         CloseSelectOverlay();
5581     } else {
5582         UpdateCaretPositionWithClamp(originCaretPosition - leftWordLength);
5583     }
5584     OnCursorMoveDone();
5585     return originCaretPosition != selectController_->GetCaretIndex();
5586 }
5587 
CursorMoveLineBegin()5588 bool TextFieldPattern::CursorMoveLineBegin()
5589 {
5590     if (selectController_->GetCaretIndex() == 0 && !IsSelected()) {
5591         return true;
5592     }
5593     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5594     int32_t originCaretPosition = selectController_->GetCaretIndex();
5595     int32_t lineBeginPosition = GetLineBeginPosition(originCaretPosition);
5596     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
5597         return false;
5598     }
5599     if (selectController_->IsSelectedAll()) {
5600         selectController_->UpdateCaretIndex(0);
5601     } else if (IsTextArea()) {
5602         UpdateCaretPositionWithClamp(lineBeginPosition);
5603     } else {
5604         UpdateCaretPositionWithClamp(0);
5605     }
5606     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5607     return originCaretPosition != selectController_->GetCaretIndex();
5608 }
5609 
CursorMoveToParagraphBegin()5610 bool TextFieldPattern::CursorMoveToParagraphBegin()
5611 {
5612     if (selectController_->GetCaretIndex() == 0) {
5613         return true;
5614     }
5615     auto originCaretPosition = selectController_->GetCaretIndex();
5616     auto newPos = GetLineBeginPosition(originCaretPosition, false);
5617     if (newPos == originCaretPosition && originCaretPosition > 0) {
5618         newPos = GetLineBeginPosition(originCaretPosition - 1, false);
5619     }
5620     UpdateCaretPositionWithClamp(newPos);
5621     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5622     return originCaretPosition != selectController_->GetCaretIndex();
5623 }
5624 
CursorMoveHome()5625 bool TextFieldPattern::CursorMoveHome()
5626 {
5627     // ctrl + home, caret move to position 0
5628     if (selectController_->GetCaretIndex() == 0) {
5629         return true;
5630     }
5631     int32_t originCaretPosition = selectController_->GetCaretIndex();
5632     UpdateCaretPositionWithClamp(0);
5633     OnCursorMoveDone();
5634     return originCaretPosition != selectController_->GetCaretIndex();
5635 }
5636 
CursorMoveRightOperation()5637 bool TextFieldPattern::CursorMoveRightOperation()
5638 {
5639     if (focusIndex_ != FocuseIndex::TEXT) {
5640         return UpdateFocusForward();
5641     }
5642     auto originCaretPosition = selectController_->GetCaretIndex();
5643     if (IsSelected()) {
5644         CloseSelectOverlay();
5645         selectController_->UpdateCaretIndex(selectController_->GetEndIndex());
5646     } else {
5647         UpdateCaretPositionWithClamp(
5648             selectController_->GetCaretIndex() +
5649             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetCaretIndex()));
5650     }
5651     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5652     return originCaretPosition != selectController_->GetCaretIndex();
5653 }
5654 
CursorMoveRight()5655 bool TextFieldPattern::CursorMoveRight()
5656 {
5657     if (inputOperations_.empty()) {
5658         return CursorMoveRightOperation();
5659     }
5660     inputOperations_.emplace(InputOperation::CURSOR_RIGHT);
5661     return false;
5662 }
5663 
CursorMoveRightWord()5664 bool TextFieldPattern::CursorMoveRightWord()
5665 {
5666     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5667         return true;
5668     }
5669     int32_t originCaretPosition = selectController_->GetCaretIndex();
5670     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5671     int32_t rightWordLength = GetWordLength(originCaretPosition, 1);
5672     if (rightWordLength < 0 || rightWordLength > textLength ||
5673         rightWordLength + selectController_->GetCaretIndex() > textLength) {
5674         return false;
5675     }
5676     if (selectController_->IsSelectedAll()) {
5677         selectController_->UpdateCaretIndex(textLength);
5678     } else {
5679         UpdateCaretPositionWithClamp(originCaretPosition + rightWordLength);
5680     }
5681     OnCursorMoveDone();
5682     return originCaretPosition != selectController_->GetCaretIndex();
5683 }
5684 
CursorMoveLineEnd()5685 bool TextFieldPattern::CursorMoveLineEnd()
5686 {
5687     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) &&
5688         !IsSelected()) {
5689         return true;
5690     }
5691     int32_t originCaretPosition = selectController_->GetCaretIndex();
5692     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5693     int32_t lineEndPosition = GetLineEndPosition(originCaretPosition);
5694     if (lineEndPosition < 0 || lineEndPosition > textLength) {
5695         return false;
5696     }
5697     if (selectController_->IsSelectedAll()) {
5698         selectController_->UpdateCaretIndex(textLength);
5699     } else if (IsTextArea()) {
5700         UpdateCaretPositionWithClamp(lineEndPosition);
5701     } else {
5702         UpdateCaretPositionWithClamp(textLength);
5703     }
5704     OnCursorMoveDone();
5705     return originCaretPosition != selectController_->GetCaretIndex();
5706 }
5707 
CursorMoveToParagraphEnd()5708 bool TextFieldPattern::CursorMoveToParagraphEnd()
5709 {
5710     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5711         return true;
5712     }
5713     auto originCaretPosition = selectController_->GetCaretIndex();
5714     auto newPos = GetLineEndPosition(originCaretPosition, false);
5715     if (newPos == originCaretPosition && originCaretPosition > 0) {
5716         newPos = GetLineEndPosition(originCaretPosition + 1, false);
5717     }
5718     UpdateCaretPositionWithClamp(newPos);
5719     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
5720     return originCaretPosition != selectController_->GetCaretIndex();
5721 }
5722 
CursorMoveEnd()5723 bool TextFieldPattern::CursorMoveEnd()
5724 {
5725     // ctrl end, caret to the very end
5726     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
5727         return true;
5728     }
5729     int32_t originCaretPosition = selectController_->GetCaretIndex();
5730     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
5731     UpdateCaretPositionWithClamp(textLength);
5732     OnCursorMoveDone();
5733     return originCaretPosition != selectController_->GetCaretIndex();
5734 }
5735 
CursorMoveUpOperation()5736 bool TextFieldPattern::CursorMoveUpOperation()
5737 {
5738     if (!IsTextArea() && !IsSelected()) {
5739         return CursorMoveToParagraphBegin();
5740     }
5741     auto originCaretPosition = selectController_->GetCaretIndex();
5742     auto offsetX = selectController_->GetCaretRect().GetX();
5743     // multiply by 0.5f to convert to the grapheme center point of the previous line.
5744     float lineHeight = PreferredLineHeight() * 0.5f;
5745     auto offsetY = selectController_->GetCaretRect().GetY() - lineHeight;
5746     if (offsetY < textRect_.GetY() && !IsSelected()) {
5747         return CursorMoveToParagraphBegin();
5748     }
5749     std::optional<Offset> offset;
5750     offset.emplace(Offset(offsetX, offsetY));
5751     OnCursorMoveDone(TextAffinity::DOWNSTREAM, offset);
5752     return originCaretPosition != selectController_->GetCaretIndex();
5753 }
5754 
CursorMoveUp()5755 bool TextFieldPattern::CursorMoveUp()
5756 {
5757     if (inputOperations_.empty()) {
5758         return CursorMoveUpOperation();
5759     }
5760 
5761     inputOperations_.emplace(InputOperation::CURSOR_UP);
5762     return false;
5763 }
5764 
CursorMoveDownOperation()5765 bool TextFieldPattern::CursorMoveDownOperation()
5766 {
5767     if (!IsTextArea() && !IsSelected()) {
5768         return CursorMoveToParagraphEnd();
5769     }
5770     auto originCaretPosition = selectController_->GetCaretIndex();
5771     auto offsetX = selectController_->GetCaretRect().GetX();
5772     // multiply by 1.5f to convert to the grapheme center point of the next line.
5773     float lineHeight = PreferredLineHeight() * 1.5f;
5774     auto offsetY = selectController_->GetCaretRect().GetY() + lineHeight;
5775     if (offsetY > textRect_.GetY() + textRect_.Height() && !IsSelected()) {
5776         return CursorMoveToParagraphEnd();
5777     }
5778     std::optional<Offset> offset;
5779     offset.emplace(Offset(offsetX, offsetY));
5780     OnCursorMoveDone(TextAffinity::DOWNSTREAM, offset);
5781     return originCaretPosition != selectController_->GetCaretIndex();
5782 }
5783 
CursorMoveDown()5784 bool TextFieldPattern::CursorMoveDown()
5785 {
5786     if (inputOperations_.empty()) {
5787         return CursorMoveDownOperation();
5788     }
5789 
5790     inputOperations_.emplace(InputOperation::CURSOR_DOWN);
5791     return false;
5792 }
5793 
Delete(int32_t start,int32_t end)5794 void TextFieldPattern::Delete(int32_t start, int32_t end)
5795 {
5796     SwapIfLarger(start, end);
5797     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Handle Delete within [%{public}d, %{public}d]", start, end);
5798     contentController_->erase(start, end - start);
5799     UpdateSelection(start);
5800     selectController_->MoveCaretToContentRect(start);
5801     if (isLongPress_) {
5802         CancelGestureSelection();
5803     }
5804     CloseSelectOverlay(true);
5805     StartTwinkling();
5806     auto beforeCaretPosition = end - start + selectController_->GetCaretIndex();
5807     UpdateEditingValueToRecord(beforeCaretPosition);
5808     auto tmpHost = GetHost();
5809     CHECK_NULL_VOID(tmpHost);
5810     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5811 }
5812 
HandleCounterBorder()5813 void TextFieldPattern::HandleCounterBorder()
5814 {
5815     auto theme = GetTheme();
5816     CHECK_NULL_VOID(theme);
5817     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5818     CHECK_NULL_VOID(paintProperty);
5819     auto host = GetHost();
5820     CHECK_NULL_VOID(host);
5821     auto renderContext = host->GetRenderContext();
5822     CHECK_NULL_VOID(renderContext);
5823     if (showCountBorderStyle_) {
5824         if (IsUnderlineMode()) {
5825             underlineWidth_ = ERROR_UNDERLINE_WIDTH;
5826             SetUnderlineColor(userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor()));
5827         } else {
5828             if (!paintProperty->HasBorderWidthFlagByUser()) {
5829                 paintProperty->UpdateInnerBorderWidth(OVER_COUNT_BORDER_WIDTH);
5830                 paintProperty->UpdateInnerBorderColor(theme->GetOverCounterColor());
5831             } else {
5832                 BorderColorProperty overCountBorderColor;
5833                 overCountBorderColor.SetColor(theme->GetOverCounterColor());
5834                 renderContext->UpdateBorderColor(overCountBorderColor);
5835             }
5836         }
5837     } else {
5838         if (IsUnderlineMode() && !IsShowError()) {
5839             ApplyUnderlineTheme();
5840             CHECK_NULL_VOID(counterDecorator_);
5841             counterDecorator_->UpdateTextFieldMargin();
5842         } else {
5843             SetThemeBorderAttr();
5844         }
5845     }
5846 }
5847 
ProcessFocusIndexAction()5848 bool TextFieldPattern::ProcessFocusIndexAction()
5849 {
5850     if (focusIndex_ == FocuseIndex::CANCEL) {
5851         CleanNodeResponseKeyEvent();
5852         return false;
5853     }
5854     if (focusIndex_ == FocuseIndex::UNIT) {
5855         if (IsShowPasswordIcon()) {
5856             PasswordResponseKeyEvent();
5857         }
5858         if (IsShowUnit()) {
5859             UnitResponseKeyEvent();
5860         }
5861         return false;
5862     }
5863     return true;
5864 }
5865 
PerformAction(TextInputAction action,bool forceCloseKeyboard)5866 void TextFieldPattern::PerformAction(TextInputAction action, bool forceCloseKeyboard)
5867 {
5868     if (!HasFocus()) {
5869         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Not Trigger OnSubmit because field blur");
5870         return;
5871     }
5872     if (!ProcessFocusIndexAction()) {
5873         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Not Trigger OnSubmit because focus index not on text");
5874         return;
5875     }
5876     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "TextField PerformAction %{public}d", static_cast<int32_t>(action));
5877     auto host = GetHost();
5878     CHECK_NULL_VOID(host);
5879     // If the parent node is a Search, the Search callback is executed.
5880     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
5881     CHECK_NULL_VOID(paintProperty);
5882     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
5883     CHECK_NULL_VOID(eventHub);
5884     TextFieldCommonEvent event;
5885     event.SetText(contentController_->GetTextUtf16Value());
5886     if (IsNormalInlineState() && action != TextInputAction::NEW_LINE) {
5887         RecordSubmitEvent();
5888         eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
5889         OnReportSubmitEvent(host);
5890         CHECK_NULL_VOID(!event.IsKeepEditable());
5891         TextFieldLostFocusToViewRoot();
5892         return;
5893     }
5894     if (IsTextArea() && action == TextInputAction::NEW_LINE) {
5895         if (!textAreaBlurOnSubmit_) {
5896             if (GetInputFilter() != "\n") {
5897                 InsertValue(u"\n", true);
5898             }
5899         } else {
5900             CloseKeyboard(forceCloseKeyboard, false);
5901             TextFieldLostFocusToViewRoot();
5902         }
5903         return;
5904     }
5905     eventHub->FireOnSubmit(static_cast<int32_t>(action), event);
5906     OnReportSubmitEvent(host);
5907     RecordSubmitEvent();
5908     CHECK_NULL_VOID(!event.IsKeepEditable());
5909     // LostFocusToViewRoot may not cause current lost focus, only stop twinkling when it is truly lost focus,
5910     // which will call StopTwinkling on HandleBlurEvent method.
5911     if (textInputBlurOnSubmit_) {
5912         HandleCloseKeyboard(forceCloseKeyboard);
5913     }
5914     UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "Textfield.onSubmit");
5915 }
5916 
TextFieldLostFocusToViewRoot()5917 void TextFieldPattern::TextFieldLostFocusToViewRoot()
5918 {
5919     CHECK_NULL_VOID(HasFocus());
5920     FocusHub::LostFocusToViewRoot();
5921 }
5922 
RecordSubmitEvent() const5923 void TextFieldPattern::RecordSubmitEvent() const
5924 {
5925     if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
5926         return;
5927     }
5928     auto host = GetHost();
5929     CHECK_NULL_VOID(host);
5930     auto inspectorId = host->GetInspectorId().value_or("");
5931     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5932     bool isPwdType = layoutProperty ? layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) ==
5933                                           TextInputType::VISIBLE_PASSWORD
5934                                     : false;
5935     Recorder::EventParamsBuilder builder;
5936     builder.SetId(inspectorId)
5937         .SetType(host->GetTag())
5938         .SetEventType(Recorder::EventType::SEARCH_SUBMIT)
5939         .SetHost(host)
5940         .SetDescription(host->GetAutoEventParamValue(""));
5941     if (!isPwdType) {
5942         builder.SetText(contentController_->GetTextValue());
5943     }
5944     Recorder::EventRecorder::Get().OnEvent(std::move(builder));
5945 }
5946 
UpdateEditingValue(const std::shared_ptr<TextEditingValue> & value,bool needFireChangeEvent)5947 void TextFieldPattern::UpdateEditingValue(const std::shared_ptr<TextEditingValue>& value, bool needFireChangeEvent)
5948 {
5949     auto result = UtfUtils::Str8DebugToStr16(value->text);
5950 #if !defined(ENABLE_STANDARD_INPUT)
5951     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
5952     if (layoutProperty && layoutProperty->HasMaxLength()) {
5953         bool textChange = false;
5954         contentController_->FilterTextInputStyle(textChange, result);
5955         auto resultLen = static_cast<int32_t>(result.length());
5956         auto maxLen = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
5957         if (resultLen != maxLen) {
5958             showCountBorderStyle_ = resultLen > maxLen;
5959             HandleCountStyle();
5960         }
5961         auto deleteSize = resultLen - maxLen;
5962         if (resultLen > maxLen && value->selection.baseOffset >= deleteSize) {
5963             result.erase(value->selection.baseOffset - deleteSize, deleteSize);
5964             value->selection.baseOffset -= deleteSize;
5965         }
5966     }
5967 #endif
5968     UpdateEditingValueToRecord();
5969     contentController_->SetTextValue(result);
5970     selectController_->UpdateCaretIndex(value->selection.baseOffset);
5971     ContainerScope scope(GetInstanceId());
5972     CloseSelectOverlay();
5973     StartTwinkling();
5974     auto host = GetHost();
5975     CHECK_NULL_VOID(host);
5976 
5977     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
5978 }
5979 
UpdateInputFilterErrorText(const std::u16string & errorText)5980 void TextFieldPattern::UpdateInputFilterErrorText(const std::u16string& errorText)
5981 {
5982     if (!errorText.empty()) {
5983         auto tmpHost = GetHost();
5984         CHECK_NULL_VOID(tmpHost);
5985         auto textFieldEventHub = tmpHost->GetOrCreateEventHub<TextFieldEventHub>();
5986         CHECK_NULL_VOID(textFieldEventHub);
5987         textFieldEventHub->FireOnInputFilterError(errorText);
5988     }
5989 }
5990 
UpdateInputFilterErrorText(const std::string & errorText)5991 void TextFieldPattern::UpdateInputFilterErrorText(const std::string& errorText)
5992 {
5993     UpdateInputFilterErrorText(UtfUtils::Str8DebugToStr16(errorText));
5994 }
5995 
OnValueChanged(bool needFireChangeEvent,bool needFireSelectChangeEvent)5996 void TextFieldPattern::OnValueChanged(bool needFireChangeEvent, bool needFireSelectChangeEvent) {}
5997 
OnHandleAreaChanged()5998 void TextFieldPattern::OnHandleAreaChanged()
5999 {
6000     auto parentGlobalOffset = GetPaintRectGlobalOffset();
6001     if (parentGlobalOffset != parentGlobalOffset_) {
6002         parentGlobalOffset_ = parentGlobalOffset;
6003         UpdateTextFieldManager(Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY()), frameRect_.Height());
6004         HandleParentGlobalOffsetChange();
6005     }
6006 }
6007 
HandleParentGlobalOffsetChange()6008 void TextFieldPattern::HandleParentGlobalOffsetChange()
6009 {
6010     selectController_->CalculateHandleOffset();
6011     CHECK_NULL_VOID(SelectOverlayIsOn() || selectOverlay_->SelectOverlayIsCreating());
6012     if (selectOverlay_->IsShowMouseMenu()) {
6013         CloseSelectOverlay();
6014         return;
6015     }
6016     if (selectOverlay_->IsHiddenHandle() && selectOverlay_->IsSingleHandle()) {
6017         selectOverlay_->ProcessOverlayOnAreaChanged({ .menuIsShow = false });
6018     } else {
6019         selectOverlay_->ProcessOverlay({ .menuIsShow = false });
6020     }
6021 }
6022 
RequestKeyboardByFocusSwitch()6023 void TextFieldPattern::RequestKeyboardByFocusSwitch()
6024 {
6025     auto host = GetHost();
6026     CHECK_NULL_VOID(host);
6027     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
6028         "%{public}d RequestKeyboardByFocusSwitch: onFocus_: %{public}d Inner: %{public}d modalCovered: %{public}d",
6029         host->GetId(), needToRequestKeyboardOnFocus_, needToRequestKeyboardInner_, IsModalCovered());
6030     if (!needToRequestKeyboardInner_ || IsModalCovered()) {
6031         return;
6032     }
6033     auto pipeline = host->GetContextRefPtr();
6034     CHECK_NULL_VOID(pipeline);
6035     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
6036     CHECK_NULL_VOID(textFieldManager);
6037     textFieldManager->SetNeedToRequestKeyboard(true);
6038     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d add requestkeyboard task", host->GetId());
6039     pipeline->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)]() {
6040         auto textField = weak.Upgrade();
6041         CHECK_NULL_VOID(textField);
6042         auto textFieldManager = manager.Upgrade();
6043         if (textFieldManager && !textFieldManager->GetNeedToRequestKeyboard()) {
6044             // already call close/attach keyboard after text field get focus, so dont request keyboard now
6045             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Already call close/attach before attach, no need attach this time");
6046             return;
6047         }
6048         if (!textField->needToRequestKeyboardInner_) {
6049             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Not need to requestKeyboard inner");
6050             return;
6051         }
6052         if (!textField->RequestKeyboard(false, true, textField->needToRequestKeyboardOnFocus_)) {
6053             return;
6054         }
6055         textField->NotifyOnEditChanged(true);
6056         textField->SetNeedToRequestKeyboardInner(false, RequestKeyboardInnerChangeReason::REQUEST_KEYBOARD_SUCCESS);
6057     });
6058 }
6059 
6060 // to distiguish request keyboard not by focus switching
RequestKeyboardNotByFocusSwitch(RequestKeyboardReason reason,SourceType sourceType)6061 bool TextFieldPattern::RequestKeyboardNotByFocusSwitch(RequestKeyboardReason reason, SourceType sourceType)
6062 {
6063     auto tmpHost = GetHost();
6064     CHECK_NULL_RETURN(tmpHost, false);
6065     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d requestKeyboard With Reason %{public}s",
6066         tmpHost->GetId(), TextFieldPattern::RequestKeyboardReasonToString(reason).c_str());
6067     if (!RequestKeyboard(false, true, true, sourceType)) {
6068         return false;
6069     }
6070     auto context = tmpHost->GetContextRefPtr();
6071     CHECK_NULL_RETURN(context, true);
6072     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
6073     CHECK_NULL_RETURN(textFieldManager, true);
6074     textFieldManager->SetNeedToRequestKeyboard(false);
6075     return true;
6076 }
6077 
TextFieldRequestFocus(RequestFocusReason reason)6078 bool TextFieldPattern::TextFieldRequestFocus(RequestFocusReason reason)
6079 {
6080     if (HasFocus()) {
6081         return true;
6082     }
6083     auto host = GetHost();
6084     CHECK_NULL_RETURN(host, false);
6085     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d Request Focus With Reason %{public}s",
6086         host->GetId(), TextFieldPattern::RequestFocusReasonToString(reason).c_str());
6087     auto focusHub = GetFocusHub();
6088     CHECK_NULL_RETURN(focusHub, false);
6089     requestFocusReason_ = reason;
6090     return focusHub->RequestFocusImmediately();
6091 }
6092 
RequestFocusReasonToString(RequestFocusReason reason)6093 std::string TextFieldPattern::RequestFocusReasonToString(RequestFocusReason reason)
6094 {
6095     switch (reason) {
6096         case RequestFocusReason::DRAG_END: {
6097             return "DragEnd";
6098         }
6099         case RequestFocusReason::DRAG_MOVE: {
6100             return "DragMove";
6101         }
6102         case RequestFocusReason::DRAG_ENTER: {
6103             return "DragEnter";
6104         }
6105         case RequestFocusReason::CLICK: {
6106             return "Click";
6107         }
6108         case RequestFocusReason::LONG_PRESS: {
6109             return "LongPress";
6110         }
6111         case RequestFocusReason::AUTO_FILL: {
6112             return "AutoFill";
6113         }
6114         case RequestFocusReason::CLEAN_NODE: {
6115             return "CleanNode";
6116         }
6117         case RequestFocusReason::MOUSE: {
6118             return "Mouse";
6119         }
6120         case RequestFocusReason::UNKNOWN:
6121         default: {
6122             break;
6123         }
6124     }
6125     return "Unknown";
6126 }
6127 
RequestKeyboardReasonToString(RequestKeyboardReason reason)6128 std::string TextFieldPattern::RequestKeyboardReasonToString(RequestKeyboardReason reason)
6129 {
6130     switch (reason) {
6131         case RequestKeyboardReason::ON_KEY_EVENT: {
6132             return "KeyEvent";
6133         }
6134         case RequestKeyboardReason::SINGLE_CLICK: {
6135             return "SingleClick";
6136         }
6137         case RequestKeyboardReason::DOUBLE_CLICK: {
6138             return "DoubleClick";
6139         }
6140         case RequestKeyboardReason::LONG_PRESS: {
6141             return "LongPress";
6142         }
6143         case RequestKeyboardReason::RESET_KEYBOARD: {
6144             return "ResetKeyboard";
6145         }
6146         case RequestKeyboardReason::MOUSE_RELEASE: {
6147             return "MouseRelease";
6148         }
6149         case RequestKeyboardReason::SET_SELECTION: {
6150             return "SetSelection";
6151         }
6152         case RequestKeyboardReason::SEARCH_REQUEST: {
6153             return "SearchRequest";
6154         }
6155         case RequestKeyboardReason::AUTO_FILL_REQUEST_FAIL: {
6156             return "AutoFillRequestFail";
6157         }
6158         case RequestKeyboardReason::SHOW_KEYBOARD_ON_FOCUS: {
6159             return "ShowKeyboardOnFocus";
6160         }
6161         case RequestKeyboardReason::STYLUS_DETECTOR: {
6162             return "StylusDetector";
6163         }
6164         case RequestKeyboardReason::CUSTOM_KEYBOARD: {
6165             return "CustomKeyboard";
6166         }
6167         case RequestKeyboardReason::UNKNOWN:
6168         default: {
6169             break;
6170         }
6171     }
6172     return "Unknown";
6173 }
6174 
IsModalCovered()6175 bool TextFieldPattern::IsModalCovered()
6176 {
6177     auto host = GetHost();
6178     CHECK_NULL_RETURN(host, false);
6179     auto pageNode = host->GetPageNode();
6180     CHECK_NULL_RETURN(pageNode, false);
6181     auto pagePattern = pageNode->GetPattern<PagePattern>();
6182     CHECK_NULL_RETURN(pagePattern, false);
6183     return pagePattern->GetIsModalCovered();
6184 }
6185 
HandleSurfaceChanged(int32_t newWidth,int32_t newHeight,int32_t prevWidth,int32_t prevHeight)6186 void TextFieldPattern::HandleSurfaceChanged(int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight)
6187 {
6188     if (newWidth == prevWidth && newHeight == prevHeight) {
6189         return;
6190     }
6191     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
6192         "Textfield handleSurface change, new width %{public}d, new height %{public}d, prev width %{public}d, prev "
6193         "height %{public}d",
6194         newWidth, newHeight, prevWidth, prevHeight);
6195     if (SelectOverlayIsOn()) {
6196         if (selectOverlay_->IsShowMouseMenu()) {
6197             CloseSelectOverlay();
6198         } else if (newWidth != prevWidth || newHeight != prevHeight) {
6199             DelayProcessOverlay({ .menuIsShow = false });
6200         }
6201         selectOverlay_->RemoveAvoidKeyboardCallback();
6202     }
6203     auto tmpHost = GetHost();
6204     CHECK_NULL_VOID(tmpHost);
6205     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
6206     UpdateCaretInfoToController(true);
6207     if (magnifierController_->GetShowMagnifier()) {
6208         magnifierController_->RemoveMagnifierFrameNode();
6209     }
6210 }
6211 
HandleSurfacePositionChanged(int32_t posX,int32_t posY)6212 void TextFieldPattern::HandleSurfacePositionChanged(int32_t posX, int32_t posY)
6213 {
6214     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Textfield handleSurface position change, posX %{public}d, posY %{public}d",
6215         posX, posY);
6216     UpdateCaretInfoToController();
6217 }
6218 
InitSurfaceChangedCallback()6219 void TextFieldPattern::InitSurfaceChangedCallback()
6220 {
6221     auto host = GetHost();
6222     CHECK_NULL_VOID(host);
6223     FREE_NODE_CHECK(host, InitSurfaceChangedCallback);  // call InitSurfaceChangedCallbackMultiThread() by multi thread
6224     auto pipeline = host->GetContext();
6225     CHECK_NULL_VOID(pipeline);
6226     if (!HasSurfaceChangedCallback()) {
6227         auto callbackId = pipeline->RegisterSurfaceChangedCallback(
6228             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
6229                 WindowSizeChangeReason type) {
6230                 auto pattern = weak.Upgrade();
6231                 if (pattern) {
6232                     pattern->HandleSurfaceChanged(newWidth, newHeight, prevWidth, prevHeight);
6233                 }
6234             });
6235         UpdateSurfaceChangedCallbackId(callbackId);
6236     }
6237 }
6238 
InitSurfacePositionChangedCallback()6239 void TextFieldPattern::InitSurfacePositionChangedCallback()
6240 {
6241     auto host = GetHost();
6242     CHECK_NULL_VOID(host);
6243     FREE_NODE_CHECK(host,
6244         InitSurfacePositionChangedCallback);  // call InitSurfacePositionChangedCallbackMultiThread() by multi thread
6245     auto pipeline = host->GetContext();
6246     CHECK_NULL_VOID(pipeline);
6247     if (!HasSurfacePositionChangedCallback()) {
6248         auto callbackId =
6249             pipeline->RegisterSurfacePositionChangedCallback([weak = WeakClaim(this)](int32_t posX, int32_t posY) {
6250                 auto pattern = weak.Upgrade();
6251                 if (pattern) {
6252                     pattern->HandleSurfacePositionChanged(posX, posY);
6253                 }
6254             });
6255         UpdateSurfacePositionChangedCallbackId(callbackId);
6256     }
6257 }
6258 
HandleOnDelete(bool backward)6259 void TextFieldPattern::HandleOnDelete(bool backward)
6260 {
6261     if (backward) {
6262 #if defined(PREVIEW)
6263         DeleteForward(1);
6264 #else
6265         DeleteBackward(1);
6266 #endif
6267     } else {
6268 #if defined(PREVIEW)
6269         DeleteBackward(1);
6270 #else
6271         DeleteForward(1);
6272 #endif
6273     }
6274 }
6275 
HandleOnDeleteComb(bool backward)6276 bool TextFieldPattern::HandleOnDeleteComb(bool backward)
6277 {
6278     if (backward) {
6279         DeleteBackwardWord(); // LTR is left word,RTL is right word
6280     } else {
6281         DeleteForwardWord(); // LTR is right word,RTL is left word
6282     }
6283     return true;
6284 }
6285 
DeleteBackwardWord()6286 void TextFieldPattern::DeleteBackwardWord()
6287 {
6288     int32_t originCaretPosition = selectController_->GetCaretIndex();
6289     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6290     int32_t leftWordLength = GetWordLength(originCaretPosition, 0, false);
6291     if (leftWordLength < 0) {
6292         // delete 1 char
6293         leftWordLength = 1;
6294     }
6295     if (leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
6296         // delete left
6297         leftWordLength = std::max(1, originCaretPosition);
6298     }
6299     DeleteBackward(leftWordLength);
6300 }
6301 
DeleteForwardWord()6302 void TextFieldPattern::DeleteForwardWord()
6303 {
6304     int32_t originCaretPosition = selectController_->GetCaretIndex();
6305     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6306     int32_t rightWordLength = GetWordLength(originCaretPosition, 1, false);
6307     if (rightWordLength < 0) {
6308         // delete 1 char
6309         rightWordLength = 1;
6310     }
6311     if (rightWordLength > textLength || rightWordLength + selectController_->GetCaretIndex() > textLength) {
6312         // delete right
6313         rightWordLength = std::max(1, textLength - originCaretPosition);
6314     }
6315     DeleteForward(rightWordLength);
6316 }
6317 
HandleOnPageUp()6318 void TextFieldPattern::HandleOnPageUp()
6319 {
6320     if (!IsTextArea()) {
6321         return;
6322     }
6323     auto border = GetBorderWidthProperty();
6324     float frameRectHeight = std::max(frameRect_.Height(), PreferredLineHeight());
6325     float maxFrameHeight =
6326         frameRectHeight - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
6327     OnScrollCallback(maxFrameHeight, SCROLL_FROM_JUMP);
6328     auto caretRectOffset = selectController_->GetCaretRect().GetOffset();
6329     Offset offset(caretRectOffset.GetX(), GetPaddingTop() + GetBorderTop(border));
6330     selectController_->UpdateCaretInfoByOffset(offset, true);
6331     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
6332 }
6333 
HandleOnPageDown()6334 void TextFieldPattern::HandleOnPageDown()
6335 {
6336     if (!IsTextArea()) {
6337         return;
6338     }
6339     auto border = GetBorderWidthProperty();
6340     float frameRectHeight = std::max(frameRect_.Height(), PreferredLineHeight());
6341     float maxFrameHeight =
6342         frameRectHeight - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
6343     OnScrollCallback(-maxFrameHeight, SCROLL_FROM_JUMP);
6344     auto caretRectOffset = selectController_->GetCaretRect().GetOffset();
6345     Offset offset(caretRectOffset.GetX(), maxFrameHeight);
6346     selectController_->UpdateCaretInfoByOffset(offset, true);
6347     OnCursorMoveDone(TextAffinity::DOWNSTREAM);
6348 }
6349 
GetEmojiSubStringRange(int32_t & start,int32_t & end)6350 void TextFieldPattern::GetEmojiSubStringRange(int32_t& start, int32_t& end)
6351 {
6352     TextEmojiSubStringRange range = TextEmojiProcessor::CalSubU16stringRange(
6353         start, end - start, GetTextUtf16Value(), false, true);
6354     start = range.startIndex;
6355     end = range.endIndex;
6356 }
6357 
DeleteBackward(int32_t length)6358 void TextFieldPattern::DeleteBackward(int32_t length)
6359 {
6360     CHECK_NULL_VOID(!IsDragging());
6361     CHECK_NULL_VOID(focusIndex_ == FocuseIndex::TEXT);
6362     ResetObscureTickCountDown();
6363     if (IsSelected()) {
6364         auto start = selectController_->GetStartIndex();
6365         auto end = selectController_->GetEndIndex();
6366         DeleteTextRange(start, end, TextDeleteDirection::BACKWARD);
6367         return;
6368     }
6369     if (selectController_->GetCaretIndex() <= 0) {
6370         auto isDelete = BeforeIMEDeleteValue(u"", TextDeleteDirection::BACKWARD, 0);
6371         CHECK_NULL_VOID(isDelete);
6372         AfterIMEDeleteValue(u"", TextDeleteDirection::BACKWARD);
6373         return;
6374     }
6375     inputOperations_.emplace(InputOperation::DELETE_BACKWARD);
6376     deleteBackwardOperations_.emplace(length);
6377     CloseSelectOverlay();
6378     ScrollToSafeArea();
6379     auto tmpHost = GetHost();
6380     CHECK_NULL_VOID(tmpHost);
6381     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
6382 }
6383 
DeleteBackwardOperation(int32_t length)6384 void TextFieldPattern::DeleteBackwardOperation(int32_t length)
6385 {
6386     int32_t idx = selectController_->GetCaretIndex();
6387     auto willDeleteLength = contentController_->GetDeleteLength(idx, length, true);
6388     auto value = contentController_->GetSelectedValue(idx - willDeleteLength, idx);
6389     auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::BACKWARD, idx);
6390     CHECK_NULL_VOID(isDelete);
6391     auto oldContent = contentController_->GetTextUtf16Value();
6392     int32_t count = contentController_->Delete(selectController_->GetCaretIndex(), length, true);
6393     auto isOnWillChange = OnWillChangePreDelete(oldContent, std::max(idx - count, 0), idx);
6394     if (!isOnWillChange) {
6395         contentController_->SetTextValue(oldContent);
6396         return;
6397     }
6398     selectController_->UpdateCaretIndex(std::max(idx - count, 0));
6399     if (GetIsPreviewText()) {
6400         UpdatePreviewIndex(GetPreviewTextStart(), GetPreviewTextEnd() - length);
6401     }
6402     AfterIMEDeleteValue(value, TextDeleteDirection::BACKWARD);
6403     StartTwinkling();
6404     focusIndex_ = FocuseIndex::TEXT;
6405     UpdateEditingValueToRecord();
6406 }
6407 
DeleteForwardOperation(int32_t length)6408 void TextFieldPattern::DeleteForwardOperation(int32_t length)
6409 {
6410     auto caretIndex = selectController_->GetCaretIndex();
6411     auto willDeleteLength = contentController_->GetDeleteLength(caretIndex, length, false);
6412     auto value = contentController_->GetSelectedValue(caretIndex, caretIndex + willDeleteLength);
6413     auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::FORWARD, caretIndex);
6414     CHECK_NULL_VOID(isDelete);
6415     ResetObscureTickCountDown();
6416     auto oldContent = contentController_->GetTextUtf16Value();
6417     contentController_->Delete(caretIndex, length, false);
6418     if (GetIsPreviewText()) {
6419         UpdatePreviewIndex(GetPreviewTextStart(), GetPreviewTextEnd() - length);
6420     }
6421     auto isOnWillChange = OnWillChangePreDelete(oldContent, caretIndex, caretIndex + willDeleteLength);
6422     if (!isOnWillChange) {
6423         contentController_->SetTextValue(oldContent);
6424         return;
6425     }
6426     AfterIMEDeleteValue(value, TextDeleteDirection::FORWARD);
6427     StartTwinkling();
6428     focusIndex_ = FocuseIndex::TEXT;
6429     UpdateEditingValueToRecord();
6430 }
6431 
DeleteForward(int32_t length)6432 void TextFieldPattern::DeleteForward(int32_t length)
6433 {
6434     CHECK_NULL_VOID(!IsDragging());
6435     CHECK_NULL_VOID(focusIndex_ == FocuseIndex::TEXT);
6436     if (IsSelected()) {
6437         auto start = selectController_->GetStartIndex();
6438         auto end = selectController_->GetEndIndex();
6439         DeleteRange(start, end);
6440         return;
6441     }
6442     auto contentLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6443     if (selectController_->GetCaretIndex() >= contentLength) {
6444         auto isDelete = BeforeIMEDeleteValue(u"", TextDeleteDirection::FORWARD, contentLength);
6445         CHECK_NULL_VOID(isDelete);
6446         AfterIMEDeleteValue(u"", TextDeleteDirection::FORWARD);
6447         return;
6448     }
6449     inputOperations_.emplace(InputOperation::DELETE_FORWARD);
6450     deleteForwardOperations_.emplace(length);
6451     CloseSelectOverlay();
6452     auto tmpHost = GetHost();
6453     CHECK_NULL_VOID(tmpHost);
6454     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
6455 }
6456 
BeforeIMEDeleteValue(const std::u16string & deleteValue,TextDeleteDirection direction,int32_t offset)6457 bool TextFieldPattern::BeforeIMEDeleteValue(
6458     const std::u16string& deleteValue, TextDeleteDirection direction, int32_t offset)
6459 {
6460     auto host = GetHost();
6461     CHECK_NULL_RETURN(host, true);
6462     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
6463     CHECK_NULL_RETURN(eventHub, true);
6464     DeleteValueInfo deleteValueInfo;
6465     deleteValueInfo.deleteOffset = offset;
6466     deleteValueInfo.deleteValue = deleteValue;
6467     deleteValueInfo.direction = direction;
6468     return eventHub->FireOnWillDeleteEvent(deleteValueInfo);
6469 }
6470 
AfterIMEDeleteValue(const std::u16string & deleteValue,TextDeleteDirection direction)6471 void TextFieldPattern::AfterIMEDeleteValue(const std::u16string& deleteValue, TextDeleteDirection direction)
6472 {
6473     auto host = GetHost();
6474     CHECK_NULL_VOID(host);
6475     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
6476     CHECK_NULL_VOID(eventHub);
6477     DeleteValueInfo deleteValueInfo;
6478     deleteValueInfo.deleteOffset = selectController_->GetCaretIndex();
6479     deleteValueInfo.deleteValue = deleteValue;
6480     deleteValueInfo.direction = direction;
6481     return eventHub->FireOnDidDeleteValueEvent(deleteValueInfo);
6482 }
6483 
GetLeftTextOfCursor(int32_t number)6484 std::u16string TextFieldPattern::GetLeftTextOfCursor(int32_t number)
6485 {
6486     auto start = selectController_->GetCaretIndex();
6487     if (IsSelected()) {
6488         start = selectController_->GetStartIndex();
6489     }
6490     return contentController_->GetSelectedValue(start - number, start);
6491 }
6492 
GetRightTextOfCursor(int32_t number)6493 std::u16string TextFieldPattern::GetRightTextOfCursor(int32_t number)
6494 {
6495     auto end = selectController_->GetCaretIndex();
6496     if (IsSelected()) {
6497         end = selectController_->GetEndIndex();
6498     }
6499     return contentController_->GetSelectedValue(end, end + number);
6500 }
6501 
GetTextIndexAtCursor()6502 int32_t TextFieldPattern::GetTextIndexAtCursor()
6503 {
6504     return selectController_->GetCaretIndex();
6505 }
6506 
AfterSelection()6507 void TextFieldPattern::AfterSelection()
6508 {
6509     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Selection %{public}s, caret position %{public}d",
6510         selectController_->ToString().c_str(), selectController_->GetCaretIndex());
6511     ResetObscureTickCountDown();
6512     auto tmpHost = GetHost();
6513     CHECK_NULL_VOID(tmpHost);
6514     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6515     showSelect_ = IsSelected();
6516     UpdateCaretInfoToController();
6517 }
6518 
HandleSelectionUp()6519 void TextFieldPattern::HandleSelectionUp()
6520 {
6521     if (!IsSelected()) {
6522         UpdateSelection(selectController_->GetCaretIndex());
6523     }
6524     auto newOffsetY = selectController_->GetCaretRect().GetY() - PreferredLineHeight() * 0.5 - textRect_.GetY();
6525     if (GreatOrEqual(newOffsetY, 0.0)) {
6526         OffsetF originCaretPosition;
6527         auto caretXPosition = GetOriginCaretPosition(originCaretPosition) &&
6528             GreatNotEqual(selectController_->GetCaretRect().GetX() - contentRect_.GetX(), 0) ? // handle when line head
6529             originCaretPosition.GetX() : selectController_->GetCaretRect().GetX();
6530         auto offset = Offset(caretXPosition - contentRect_.GetX(), newOffsetY);
6531         auto index = paragraph_->GetGlyphIndexByCoordinate(offset);
6532         bool isAtLineBegin = false;
6533         LineMetrics lineMetrics;
6534         if (paragraph_->GetLineMetricsByCoordinate(offset, lineMetrics) && LessOrEqual(offset.GetX(), lineMetrics.x)) {
6535             isAtLineBegin = true;
6536         }
6537         selectController_->MoveSecondHandleByKeyBoard(index, isAtLineBegin ?
6538             std::make_optional<TextAffinity>(TextAffinity::DOWNSTREAM) : std::nullopt);
6539     } else {
6540         selectController_->MoveSecondHandleByKeyBoard(0);
6541     }
6542     AfterSelection();
6543 }
6544 
HandleSelectionDown()6545 void TextFieldPattern::HandleSelectionDown()
6546 {
6547     if (!IsSelected()) {
6548         UpdateSelection(selectController_->GetCaretIndex());
6549     }
6550     auto newOffsetY = selectController_->GetCaretRect().GetY() + PreferredLineHeight() * 1.5 - textRect_.GetY();
6551     if (LessOrEqual(newOffsetY, textRect_.Height())) {
6552         OffsetF originCaretPosition;
6553         auto caretXPosition = GetOriginCaretPosition(originCaretPosition) ?
6554             originCaretPosition.GetX() : selectController_->GetCaretRect().GetX();
6555         selectController_->MoveSecondHandleByKeyBoard(paragraph_->GetGlyphIndexByCoordinate(
6556             Offset(caretXPosition - contentRect_.GetX(), newOffsetY)), TextAffinity::DOWNSTREAM);
6557     } else {
6558         selectController_->MoveSecondHandleByKeyBoard(
6559             static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
6560     }
6561     AfterSelection();
6562 }
6563 
HandleSelectionLeft()6564 void TextFieldPattern::HandleSelectionLeft()
6565 {
6566     if (!IsSelected()) {
6567         if (selectController_->GetCaretIndex() == 0) {
6568             return;
6569         }
6570         UpdateSelection(selectController_->GetCaretIndex());
6571         selectController_->MoveSecondHandleByKeyBoard(
6572             selectController_->GetSecondHandleIndex() -
6573             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetCaretIndex(),
6574                 true));
6575     } else {
6576         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() -
6577             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(), selectController_->GetSecondHandleIndex(),
6578                 true));
6579     }
6580     AfterSelection();
6581 }
6582 
HandleSelectionLeftWord()6583 void TextFieldPattern::HandleSelectionLeftWord()
6584 {
6585     if (selectController_->GetCaretIndex() == 0) {
6586         return;
6587     }
6588     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6589     int32_t leftWordLength = GetWordLength(selectController_->GetCaretIndex(), 0);
6590     if (leftWordLength < 0 || leftWordLength > textLength || selectController_->GetCaretIndex() - leftWordLength < 0) {
6591         return;
6592     }
6593     if (!IsSelected()) {
6594         UpdateSelection(selectController_->GetCaretIndex());
6595         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
6596     } else {
6597         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() - leftWordLength);
6598     }
6599     AfterSelection();
6600 }
6601 
HandleSelectionLineBegin()6602 void TextFieldPattern::HandleSelectionLineBegin()
6603 {
6604     if (selectController_->GetCaretIndex() == 0) {
6605         return;
6606     }
6607     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6608     int32_t lineBeginPosition = GetLineBeginPosition(selectController_->GetCaretIndex());
6609     if (lineBeginPosition < 0 || lineBeginPosition > textLength) {
6610         return;
6611     }
6612     if (!IsSelected()) {
6613         UpdateSelection(selectController_->GetCaretIndex());
6614         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
6615     } else {
6616         selectController_->MoveSecondHandleByKeyBoard(lineBeginPosition);
6617     }
6618     AfterSelection();
6619 }
6620 
HandleSelectionHome()6621 void TextFieldPattern::HandleSelectionHome()
6622 {
6623     if (selectController_->GetCaretIndex() == 0) {
6624         return;
6625     }
6626     if (!IsSelected()) {
6627         UpdateSelection(selectController_->GetCaretIndex());
6628         selectController_->MoveSecondHandleByKeyBoard(0);
6629     } else {
6630         selectController_->MoveSecondHandleByKeyBoard(0);
6631     }
6632     AfterSelection();
6633 }
6634 
HandleSelectionParagraghBegin()6635 void TextFieldPattern::HandleSelectionParagraghBegin()
6636 {
6637     CHECK_NULL_VOID(selectController_);
6638     if (selectController_->GetCaretIndex() == 0) {
6639         return;
6640     }
6641     auto originCaretPosition = selectController_->GetCaretIndex();
6642     auto newPos = GetLineBeginPosition(originCaretPosition, false);
6643     if (newPos == originCaretPosition && originCaretPosition > 0) {
6644         newPos = GetLineBeginPosition(originCaretPosition - 1, false);
6645     }
6646     if (!IsSelected()) {
6647         UpdateSelection(selectController_->GetCaretIndex());
6648         selectController_->MoveSecondHandleByKeyBoard(newPos);
6649     } else {
6650         selectController_->MoveSecondHandleByKeyBoard(newPos);
6651     }
6652     AfterSelection();
6653 }
6654 
HandleSelectionRight()6655 void TextFieldPattern::HandleSelectionRight()
6656 {
6657     // if currently not in select mode, reset baseOffset and move destinationOffset and caret position
6658     if (!IsSelected()) {
6659         if (selectController_->GetCaretIndex() ==
6660             static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
6661             return;
6662         }
6663         UpdateSelection(selectController_->GetCaretIndex());
6664         selectController_->MoveSecondHandleByKeyBoard(
6665             selectController_->GetSecondHandleIndex() +
6666             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(),
6667                 selectController_->GetSecondHandleIndex()));
6668     } else {
6669         // if currently not in select mode, move destinationOffset and caret position only
6670         selectController_->MoveSecondHandleByKeyBoard(
6671             selectController_->GetSecondHandleIndex() +
6672             GetGraphemeClusterLength(contentController_->GetTextUtf16Value(),
6673                 selectController_->GetSecondHandleIndex()));
6674     }
6675     AfterSelection();
6676 }
6677 
HandleSelectionRightWord()6678 void TextFieldPattern::HandleSelectionRightWord()
6679 {
6680     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6681     if (selectController_->GetCaretIndex() == textLength) {
6682         return;
6683     }
6684     int32_t rightWordLength = GetWordLength(selectController_->GetCaretIndex(), 1);
6685     if (rightWordLength < 0 || rightWordLength > textLength ||
6686         rightWordLength + selectController_->GetCaretIndex() > textLength) {
6687         return;
6688     }
6689     if (!IsSelected()) {
6690         UpdateSelection(selectController_->GetCaretIndex());
6691         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
6692     } else {
6693         selectController_->MoveSecondHandleByKeyBoard(selectController_->GetSecondHandleIndex() + rightWordLength);
6694         AfterSelection();
6695     }
6696 }
6697 
HandleSelectionLineEnd()6698 void TextFieldPattern::HandleSelectionLineEnd()
6699 {
6700     int32_t textLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6701     if (selectController_->GetCaretIndex() == textLength) {
6702         return;
6703     }
6704     int32_t lineEndPosition = GetLineEndPosition(selectController_->GetCaretIndex());
6705     if (lineEndPosition < 0 || lineEndPosition > textLength) {
6706         return;
6707     }
6708     if (!IsSelected()) {
6709         UpdateSelection(selectController_->GetCaretIndex());
6710         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
6711     } else {
6712         selectController_->MoveSecondHandleByKeyBoard(lineEndPosition);
6713     }
6714     AfterSelection();
6715 }
6716 
HandleSelectionEnd()6717 void TextFieldPattern::HandleSelectionEnd()
6718 {
6719     // shift end, select to the end of current line
6720     int32_t endPos = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6721     if (selectController_->GetCaretIndex() == endPos) {
6722         return;
6723     }
6724     if (!IsSelected()) {
6725         UpdateSelection(selectController_->GetCaretIndex());
6726         selectController_->MoveSecondHandleByKeyBoard(endPos);
6727     } else {
6728         selectController_->MoveSecondHandleByKeyBoard(endPos);
6729     }
6730     AfterSelection();
6731 }
6732 
HandleSelectionParagraghEnd()6733 void TextFieldPattern::HandleSelectionParagraghEnd()
6734 {
6735     CHECK_NULL_VOID(selectController_);
6736     if (selectController_->GetCaretIndex() == static_cast<int32_t>(contentController_->GetTextUtf16Value().length())) {
6737         return;
6738     }
6739     auto originCaretPosition = selectController_->GetCaretIndex();
6740     auto newPos = GetLineEndPosition(originCaretPosition, false) + ENTER_OFFSET;
6741     if (!IsSelected()) {
6742         UpdateSelection(selectController_->GetCaretIndex());
6743         selectController_->MoveSecondHandleByKeyBoard(newPos);
6744     } else {
6745         selectController_->MoveSecondHandleByKeyBoard(newPos);
6746     }
6747     AfterSelection();
6748 }
6749 
SetCaretPosition(int32_t position,bool moveContent)6750 void TextFieldPattern::SetCaretPosition(int32_t position, bool moveContent)
6751 {
6752     auto host = GetHost();
6753     FREE_NODE_CHECK(host, SetCaretPosition, position, moveContent);  // call SetCaretPositionMultiThread() by multi thread
6754     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Set caret position to %{public}d", position);
6755     selectController_->MoveCaretToContentRect(position, TextAffinity::DOWNSTREAM, true, moveContent);
6756     UpdateCaretInfoToController();
6757     if (HasFocus() && !magnifierController_->GetShowMagnifier()) {
6758         StartTwinkling();
6759     }
6760     CloseSelectOverlay();
6761     CancelDelayProcessOverlay();
6762     TriggerAvoidOnCaretChange();
6763     auto tmpHost = GetHost();
6764     CHECK_NULL_VOID(tmpHost);
6765     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6766 }
6767 
SetCaretOffset(int32_t caretPostion)6768 bool TextFieldPattern::SetCaretOffset(int32_t caretPostion)
6769 {
6770     SetCaretPosition(caretPostion);
6771     return true;
6772 }
6773 
SetSelectionFlag(int32_t selectionStart,int32_t selectionEnd,const std::optional<SelectionOptions> & options,bool isForward)6774 void TextFieldPattern::SetSelectionFlag(
6775     int32_t selectionStart, int32_t selectionEnd, const std::optional<SelectionOptions>& options, bool isForward)
6776 {
6777     auto host = GetHost();
6778     FREE_NODE_CHECK(host, SetSelectionFlag, selectionStart,
6779         selectionEnd, options, isForward);  // call SetSelectionFlagMultiThread() by multi thread
6780     if (!HasFocus() || GetIsPreviewText()) {
6781         return;
6782     }
6783     auto length = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
6784     selectionStart = std::clamp(selectionStart, 0, length);
6785     selectionEnd = std::clamp(selectionEnd, 0, length);
6786     moveCaretState_.isTouchCaret = false;
6787     bool isShowMenu = selectOverlay_->IsCurrentMenuVisibile();
6788     isTouchPreviewText_ = false;
6789     if (selectionStart == selectionEnd) {
6790         selectController_->MoveCaretToContentRect(selectionEnd, TextAffinity::DOWNSTREAM);
6791         StartTwinkling();
6792     } else {
6793         cursorVisible_ = false;
6794         showSelect_ = true;
6795         HandleSetSelection(selectionStart, selectionEnd, false);
6796         if (isForward) {
6797             selectController_->MoveSecondHandleToContentRect(selectionEnd);
6798             selectController_->MoveFirstHandleToContentRect(selectionStart, false);
6799         } else {
6800             selectController_->MoveFirstHandleToContentRect(selectionStart);
6801             selectController_->MoveSecondHandleToContentRect(selectionEnd);
6802         }
6803     }
6804     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SET_SELECTION)) {
6805         NotifyOnEditChanged(true);
6806     }
6807     SetIsSingleHandle(!IsSelected());
6808     if (!IsShowHandle()) {
6809         CloseSelectOverlay(true);
6810     } else {
6811         isShowMenu = IsShowMenu(options, isShowMenu);
6812         if (!isShowMenu && IsUsingMouse()) {
6813             CloseSelectOverlay();
6814         } else {
6815             ProcessOverlay({ .menuIsShow = isShowMenu, .animation = true });
6816         }
6817     }
6818     TriggerAvoidWhenCaretGoesDown();
6819     CHECK_NULL_VOID(host);
6820     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6821 }
6822 
SetSelection(int32_t start,int32_t end,const std::optional<SelectionOptions> & options,bool isForward)6823 void TextFieldPattern::SetSelection(int32_t start, int32_t end,
6824     const std::optional<SelectionOptions>& options, bool isForward)
6825 {
6826     SetSelectionFlag(start, end, options, isForward);
6827 }
6828 
IsShowMenu(const std::optional<SelectionOptions> & options,bool defaultValue)6829 bool TextFieldPattern::IsShowMenu(const std::optional<SelectionOptions>& options, bool defaultValue)
6830 {
6831     if (!options.has_value()) {
6832         return false;
6833     }
6834     if (options.value().menuPolicy == MenuPolicy::HIDE) {
6835         return false;
6836     }
6837     if (options.value().menuPolicy == MenuPolicy::SHOW) {
6838         return true;
6839     }
6840     return defaultValue;
6841 }
6842 
OnBackPressed()6843 bool TextFieldPattern::OnBackPressed()
6844 {
6845     auto tmpHost = GetHost();
6846     CHECK_NULL_RETURN(tmpHost, false);
6847     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "%{public}d receives back press event, %{public}d",
6848         tmpHost->GetId(), isCustomKeyboardAttached_);
6849     if (SelectOverlayIsOn()) {
6850         selectController_->UpdateCaretIndex(
6851             std::max(selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex()));
6852         bool closeKeyboard = !selectOverlay_->IsCurrentMenuVisibile();
6853         CloseSelectOverlay();
6854         StartTwinkling();
6855         if (!closeKeyboard) {
6856             return IsStopBackPress();
6857         }
6858     }
6859 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
6860     if (!imeShown_ && !isCustomKeyboardAttached_) {
6861 #else
6862     if (!isCustomKeyboardAttached_) {
6863 #endif
6864         return false;
6865     }
6866 
6867     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6868     HandleCloseKeyboard(true);
6869 #if defined(ANDROID_PLATFORM)
6870     return false;
6871 #else
6872     return IsStopBackPress();
6873 #endif
6874 }
6875 
6876 bool TextFieldPattern::IsStopBackPress() const
6877 {
6878     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6879     CHECK_NULL_RETURN(layoutProperty, true);
6880     return layoutProperty->GetStopBackPressValue(true);
6881 }
6882 
6883 void TextFieldPattern::HandleCloseKeyboard(bool forceClose)
6884 {
6885     if (independentControlKeyboard_) {
6886         CloseKeyboard(true, false);
6887     } else {
6888         CloseKeyboard(forceClose);
6889         if (HasFocus()) {
6890             FocusHub::LostFocusToViewRoot();
6891         }
6892     }
6893 }
6894 
6895 int32_t TextFieldPattern::GetNakedCharPosition() const
6896 {
6897     if (IsTextArea() || !IsInPasswordMode() || obscureTickCountDown_ <= 0 || !GetTextObscured()) {
6898         return -1;
6899     }
6900     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6901     CHECK_NULL_RETURN(layoutProperty, -1);
6902     auto content = contentController_->GetTextUtf16Value();
6903     if (content.empty()) {
6904         return -1;
6905     }
6906     return nakedCharPosition_;
6907 }
6908 
6909 std::string TextFieldPattern::TextInputTypeToString() const
6910 {
6911     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6912     CHECK_NULL_RETURN(layoutProperty, "");
6913     switch (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED)) {
6914         case TextInputType::NUMBER:
6915             return IsTextArea() ? "TextAreaType.NUMBER" : "InputType.Number";
6916         case TextInputType::EMAIL_ADDRESS:
6917             return IsTextArea() ? "TextAreaType.EMAIL" : "InputType.Email";
6918         case TextInputType::PHONE:
6919             return IsTextArea() ? "TextAreaType.PHONE_NUMBER" : "InputType.PhoneNumber";
6920         case TextInputType::URL:
6921             return IsTextArea() ? "TextAreaType.URL" : "InputType.URL";
6922         case TextInputType::VISIBLE_PASSWORD:
6923             return "InputType.Password";
6924         case TextInputType::USER_NAME:
6925             return "InputType.USER_NAME";
6926         case TextInputType::NEW_PASSWORD:
6927             return "InputType.NEW_PASSWORD";
6928         case TextInputType::NUMBER_PASSWORD:
6929             return "InputType.NUMBER_PASSWORD";
6930         case TextInputType::NUMBER_DECIMAL:
6931             return IsTextArea() ? "TextAreaType.NUMBER_DECIMAL" : "InputType.NUMBER_DECIMAL";
6932         case TextInputType::ONE_TIME_CODE:
6933             return IsTextArea() ? "TextAreaType.ONE_TIME_CODE" : "InputType.ONE_TIME_CODE";
6934         default:
6935             return isTextInput_ ? "InputType.Normal" : "TextAreaType.NORMAL";
6936     }
6937 }
6938 
6939 std::string TextFieldPattern::TextContentTypeToString() const
6940 {
6941     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6942     CHECK_NULL_RETURN(layoutProperty, "");
6943     auto contentType = layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED);
6944     if (contentTypeMap_.find(contentType) != contentTypeMap_.end()) {
6945         return contentTypeMap_[contentType].second;
6946     }
6947     return contentTypeMap_[TextContentType::UNSPECIFIED].second;
6948 }
6949 
6950 std::string TextFieldPattern::TextInputActionToString() const
6951 {
6952     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6953     CHECK_NULL_RETURN(layoutProperty, "");
6954     switch (GetTextInputActionValue(GetDefaultTextInputAction())) {
6955         case TextInputAction::GO:
6956             return "EnterKeyType.Go";
6957         case TextInputAction::SEARCH:
6958             return "EnterKeyType.Search";
6959         case TextInputAction::SEND:
6960             return "EnterKeyType.Send";
6961         case TextInputAction::NEXT:
6962             return "EnterKeyType.Next";
6963         default:
6964             return "EnterKeyType.Done";
6965     }
6966 }
6967 
6968 std::string TextFieldPattern::AutoCapTypeToString() const
6969 {
6970     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6971     CHECK_NULL_RETURN(layoutProperty, "");
6972     switch (GetAutoCapitalizationModeValue(AutoCapitalizationMode::NONE)) {
6973         case AutoCapitalizationMode::NONE:
6974             return "AutoCapitalizationMode.NONE";
6975         case AutoCapitalizationMode::WORDS:
6976             return "AutoCapitalizationMode.WORDS";
6977         case AutoCapitalizationMode::SENTENCES:
6978             return "AutoCapitalizationMode.SENTENCES";
6979         case AutoCapitalizationMode::ALL_CHARACTERS:
6980             return "AutoCapitalizationMode.ALL_CHARACTERS";
6981         default:
6982             return "AutoCapitalizationMode.NONE";
6983     }
6984 }
6985 
6986 std::string TextFieldPattern::GetPlaceholderFont() const
6987 {
6988     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
6989     CHECK_NULL_RETURN(layoutProperty, "");
6990     auto theme = GetTheme();
6991     CHECK_NULL_RETURN(theme, "");
6992     auto jsonValue = JsonUtil::Create(true);
6993     if (layoutProperty->GetPlaceholderItalicFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL) {
6994         jsonValue->Put("style", "FontStyle.Normal");
6995     } else {
6996         jsonValue->Put("style", "FontStyle.Italic");
6997     }
6998     // placeholder font size not exist in theme, use normal font size by default
6999     if (!layoutProperty->GetPlaceholderFontSize()) {
7000         jsonValue->Put("size", GetFontSize().c_str());
7001     } else {
7002         jsonValue->Put("size", layoutProperty->GetPlaceholderFontSize()->ToString().c_str());
7003     }
7004     auto weight = layoutProperty->GetPlaceholderFontWeightValue(theme->GetFontWeight());
7005     switch (weight) {
7006         case FontWeight::W100:
7007             jsonValue->Put("weight", "100");
7008             break;
7009         case FontWeight::W200:
7010             jsonValue->Put("weight", "200");
7011             break;
7012         case FontWeight::W300:
7013             jsonValue->Put("weight", "300");
7014             break;
7015         case FontWeight::W400:
7016             jsonValue->Put("weight", "400");
7017             break;
7018         case FontWeight::W500:
7019             jsonValue->Put("weight", "500");
7020             break;
7021         case FontWeight::W600:
7022             jsonValue->Put("weight", "600");
7023             break;
7024         case FontWeight::W700:
7025             jsonValue->Put("weight", "700");
7026             break;
7027         case FontWeight::W800:
7028             jsonValue->Put("weight", "800");
7029             break;
7030         case FontWeight::W900:
7031             jsonValue->Put("weight", "900");
7032             break;
7033         default:
7034             jsonValue->Put("fontWeight", V2::ConvertWrapFontWeightToStirng(weight).c_str());
7035     }
7036     auto family = layoutProperty->GetPlaceholderFontFamilyValue({ "sans-serif" });
7037     std::string jsonFamily = ConvertFontFamily(family);
7038     jsonValue->Put("fontFamily", jsonFamily.c_str());
7039     return jsonValue->ToString();
7040 }
7041 
7042 RefPtr<TextFieldTheme> TextFieldPattern::GetTheme() const
7043 {
7044     if (textFieldTheme_.Upgrade()) {
7045         return textFieldTheme_.Upgrade();
7046     }
7047     auto tmpHost = GetHost();
7048     CHECK_NULL_RETURN(tmpHost, nullptr);
7049     auto context = tmpHost->GetContext();
7050     CHECK_NULL_RETURN(context, nullptr);
7051     auto theme = context->GetTheme<TextFieldTheme>(tmpHost->GetThemeScopeId());
7052     return theme;
7053 }
7054 
7055 void TextFieldPattern::InitTheme()
7056 {
7057     auto tmpHost = GetHost();
7058     CHECK_NULL_VOID(tmpHost);
7059     auto context = tmpHost->GetContext();
7060     CHECK_NULL_VOID(context);
7061     auto theme = context->GetTheme<TextFieldTheme>(tmpHost->GetThemeScopeId());
7062     textFieldTheme_ = theme;
7063     // for normal app add version protection, enable keyboard as default start from API 10 or higher
7064     if (context->GetMinPlatformVersion() > KEYBOARD_DEFAULT_API) {
7065         if (theme) {
7066             independentControlKeyboard_ = theme->GetIndependentControlKeyboard();
7067             needToRequestKeyboardOnFocus_ = !independentControlKeyboard_;
7068         } else {
7069             needToRequestKeyboardOnFocus_ = true;
7070         }
7071     }
7072 }
7073 
7074 std::string TextFieldPattern::GetTextColor() const
7075 {
7076     auto theme = GetTheme();
7077     CHECK_NULL_RETURN(theme, "");
7078     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7079     CHECK_NULL_RETURN(layoutProperty, "");
7080     return layoutProperty->GetTextColorValue(theme->GetTextColor()).ColorToString();
7081 }
7082 
7083 std::string TextFieldPattern::GetCaretColor() const
7084 {
7085     auto theme = GetTheme();
7086     CHECK_NULL_RETURN(theme, "");
7087     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7088     CHECK_NULL_RETURN(paintProperty, "");
7089     return paintProperty->GetCursorColorValue(theme->GetCursorColor()).ColorToString();
7090 }
7091 
7092 std::string TextFieldPattern::GetPlaceholderColor() const
7093 {
7094     auto theme = GetTheme();
7095     CHECK_NULL_RETURN(theme, "");
7096     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7097     CHECK_NULL_RETURN(layoutProperty, "");
7098     return layoutProperty->GetPlaceholderTextColorValue(theme->GetPlaceholderColor()).ColorToString();
7099 }
7100 
7101 std::string TextFieldPattern::GetFontSize() const
7102 {
7103     auto theme = GetTheme();
7104     CHECK_NULL_RETURN(theme, "");
7105     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7106     CHECK_NULL_RETURN(layoutProperty, "");
7107     return layoutProperty->GetFontSizeValue(theme->GetFontSize()).ToString();
7108 }
7109 
7110 std::string TextFieldPattern::GetMinFontSize() const
7111 {
7112     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7113     CHECK_NULL_RETURN(layoutProperty, "");
7114     auto minFontSize = layoutProperty->GetAdaptMinFontSize();
7115     return minFontSize.has_value() ? minFontSize->ToString() : "";
7116 }
7117 
7118 std::string TextFieldPattern::GetMaxFontSize() const
7119 {
7120     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7121     CHECK_NULL_RETURN(layoutProperty, "");
7122     auto maxFontSize = layoutProperty->GetAdaptMaxFontSize();
7123     return maxFontSize.has_value() ? maxFontSize->ToString() : "";
7124 }
7125 
7126 std::string TextFieldPattern::GetMinFontScale() const
7127 {
7128     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7129     CHECK_NULL_RETURN(layoutProperty, std::to_string(MINFONTSCALE));
7130     return std::to_string(layoutProperty->GetMinFontScale().value_or(MINFONTSCALE));
7131 }
7132 
7133 std::string TextFieldPattern::GetMaxFontScale() const
7134 {
7135     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7136     CHECK_NULL_RETURN(layoutProperty, std::to_string(MAXFONTSCALE));
7137     return std::to_string(layoutProperty->GetMaxFontScale().value_or(MAXFONTSCALE));
7138 }
7139 
7140 std::string TextFieldPattern::GetEllipsisMode() const
7141 {
7142     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7143     CHECK_NULL_RETURN(layoutProperty, V2::ConvertEllipsisModeToString(EllipsisMode::TAIL));
7144     return V2::ConvertEllipsisModeToString(layoutProperty->GetEllipsisMode().value_or(
7145         EllipsisMode::TAIL));
7146 }
7147 
7148 std::string TextFieldPattern::GetTextIndent() const
7149 {
7150     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7151     CHECK_NULL_RETURN(layoutProperty, "");
7152     auto textIndent = layoutProperty->GetTextIndent();
7153     return textIndent.has_value() ? textIndent->ToString() : "";
7154 }
7155 
7156 Ace::FontStyle TextFieldPattern::GetItalicFontStyle() const
7157 {
7158     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7159     CHECK_NULL_RETURN(layoutProperty, Ace::FontStyle::NORMAL);
7160     return layoutProperty->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL);
7161 }
7162 
7163 std::string TextFieldPattern::GetShowPasswordIconString() const
7164 {
7165     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7166     CHECK_NULL_RETURN(layoutProperty, "false");
7167     return layoutProperty->GetShowPasswordIconValue(false) ? "true" : "false";
7168 }
7169 
7170 std::string TextFieldPattern::GetInputStyleString() const
7171 {
7172     std::string result = isTextInput_ ? "TextInputStyle.Default" : "TextContentStyle.DEFAULT";
7173     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7174     CHECK_NULL_RETURN(paintProperty, result);
7175     switch (paintProperty->GetInputStyleValue(InputStyle::DEFAULT)) {
7176         case InputStyle::INLINE:
7177             result = isTextInput_ ? "TextInputStyle.Inline" : "TextContentStyle.INLINE";
7178             break;
7179         case InputStyle::DEFAULT:
7180         default:
7181             break;
7182     }
7183     return result;
7184 }
7185 
7186 FontWeight TextFieldPattern::GetFontWeight() const
7187 {
7188     auto theme = GetTheme();
7189     CHECK_NULL_RETURN(theme, FontWeight::NORMAL);
7190     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7191     CHECK_NULL_RETURN(layoutProperty, FontWeight::NORMAL);
7192     return layoutProperty->GetFontWeightValue(theme->GetFontWeight());
7193 }
7194 
7195 std::string TextFieldPattern::GetFontFamily() const
7196 {
7197     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7198     CHECK_NULL_RETURN(layoutProperty, "HarmonyOS Sans");
7199     auto family = layoutProperty->GetFontFamilyValue({ "HarmonyOS Sans" });
7200     return ConvertFontFamily(family);
7201 }
7202 
7203 TextAlign TextFieldPattern::GetTextAlign() const
7204 {
7205     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7206     CHECK_NULL_RETURN(layoutProperty, TextAlign::START);
7207     return layoutProperty->GetTextAlign().value_or(TextAlign::START);
7208 }
7209 
7210 uint32_t TextFieldPattern::GetMaxLength() const
7211 {
7212     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7213     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
7214     return layoutProperty->HasMaxLength() ? layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())
7215                                           : Infinity<uint32_t>();
7216 }
7217 
7218 uint32_t TextFieldPattern::GetMaxLines() const
7219 {
7220     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7221     CHECK_NULL_RETURN(layoutProperty, Infinity<uint32_t>());
7222     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7223     CHECK_NULL_RETURN(paintProperty, Infinity<uint32_t>());
7224     if (IsNormalInlineState()) {
7225         return layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE);
7226     }
7227     return layoutProperty->HasMaxLines() ? layoutProperty->GetMaxLinesValue(Infinity<uint32_t>())
7228                                          : Infinity<uint32_t>();
7229 }
7230 
7231 uint32_t TextFieldPattern::GetMinLines() const
7232 {
7233     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7234     CHECK_NULL_RETURN(layoutProperty, DEFAULT_MIN_LINES);
7235     return layoutProperty->GetMinLines().value_or(DEFAULT_MIN_LINES);
7236 }
7237 
7238 std::u16string TextFieldPattern::GetPlaceHolder() const
7239 {
7240     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7241     CHECK_NULL_RETURN(layoutProperty, u"");
7242     return layoutProperty->GetPlaceholderValue(u"");
7243 }
7244 
7245 std::string TextFieldPattern::GetInputFilter() const
7246 {
7247     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7248     CHECK_NULL_RETURN(layoutProperty, "");
7249     return layoutProperty->GetInputFilterValue("");
7250 }
7251 
7252 std::u16string TextFieldPattern::GetErrorTextString() const
7253 {
7254     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7255     CHECK_NULL_RETURN(layoutProperty, u"");
7256     return layoutProperty->GetErrorTextValue(u"");
7257 }
7258 
7259 bool TextFieldPattern::GetErrorTextState() const
7260 {
7261     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7262     CHECK_NULL_RETURN(layoutProperty, false);
7263     return layoutProperty->GetShowErrorTextValue(false);
7264 }
7265 
7266 void TextFieldPattern::SearchRequestKeyboard()
7267 {
7268     StartTwinkling();
7269     if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SEARCH_REQUEST)) {
7270         NotifyOnEditChanged(true);
7271     }
7272 }
7273 
7274 std::string TextFieldPattern::GetCopyOptionString() const
7275 {
7276     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7277     CHECK_NULL_RETURN(layoutProperty, "");
7278     std::string copyOptionString = "CopyOptions.Local";
7279     switch (layoutProperty->GetCopyOptionsValue(CopyOptions::Local)) {
7280         case CopyOptions::InApp:
7281             copyOptionString = "CopyOptions.InApp";
7282             break;
7283         case CopyOptions::Local:
7284             copyOptionString = "CopyOptions.Local";
7285             break;
7286         case CopyOptions::Distributed:
7287             copyOptionString = "CopyOptions.Distributed";
7288             break;
7289         case CopyOptions::None:
7290             copyOptionString = "CopyOptions.None";
7291             break;
7292         default:
7293             break;
7294     }
7295     return copyOptionString;
7296 }
7297 
7298 std::string TextFieldPattern::GetBarStateString() const
7299 {
7300     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7301     CHECK_NULL_RETURN(layoutProperty, "");
7302     std::string displayModeString;
7303     switch (layoutProperty->GetDisplayModeValue(DisplayMode::AUTO)) {
7304         case DisplayMode::OFF:
7305             displayModeString = "BarState.OFF";
7306             break;
7307         case DisplayMode::ON:
7308             displayModeString = "BarState.ON";
7309             break;
7310         case DisplayMode::AUTO:
7311         default:
7312             displayModeString = "BarState.AUTO";
7313             break;
7314     }
7315     return displayModeString;
7316 }
7317 
7318 void TextFieldPattern::UpdateScrollBarOffset()
7319 {
7320     if (!GetScrollBar() && !GetScrollBarProxy()) {
7321         return;
7322     }
7323     auto paddingHeight = GetPaddingTop() + GetPaddingBottom();
7324     auto contentHeight = contentRect_.Height();
7325     if (inlineFocusState_) {
7326         paddingHeight = 0.0f;
7327         contentHeight = GetSingleLineHeight() * GetMaxLines();
7328     }
7329     Size size(frameRect_.Width(), contentHeight + paddingHeight);
7330     UpdateScrollBarRegion(
7331         contentRect_.GetY() - textRect_.GetY(), textRect_.Height() + paddingHeight, size, Offset(0.0, 0.0));
7332     auto tmpHost = GetHost();
7333     CHECK_NULL_VOID(tmpHost);
7334     tmpHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
7335 }
7336 
7337 void TextFieldPattern::PlayScrollBarAppearAnimation()
7338 {
7339     auto scrollBar = GetScrollBar();
7340     if (scrollBar) {
7341         scrollBar->PlayScrollBarAppearAnimation();
7342     }
7343 }
7344 
7345 void TextFieldPattern::ScheduleDisappearDelayTask()
7346 {
7347     auto scrollBar = GetScrollBar();
7348     if (scrollBar) {
7349         scrollBar->SetPressed(false);
7350         scrollBar->PlayScrollBarShrinkAnimation();
7351         scrollBar->ScheduleDisappearDelayTask();
7352     }
7353 }
7354 
7355 bool TextFieldPattern::OnScrollCallback(float offset, int32_t source)
7356 {
7357     if (source == SCROLL_FROM_START) {
7358         PlayScrollBarAppearAnimation();
7359         if (selectOverlay_->IsCurrentMenuVisibile()) {
7360             isTextSelectionMenuShow_ = true;
7361         } else if (CheckSelectAreaVisible()) {
7362             isTextSelectionMenuShow_ = false;
7363         }
7364         selectOverlay_->HideMenu(true);
7365         return true;
7366     }
7367     if (IsReachedBoundary(offset)) {
7368         return false;
7369     }
7370     PlayScrollBarAppearAnimation();
7371     OnTextInputScroll(offset);
7372     OnTextAreaScroll(offset);
7373     return true;
7374 }
7375 
7376 void TextFieldPattern::CheckScrollable()
7377 {
7378     if (IsTextArea()) {
7379         if (contentController_->IsEmpty()) {
7380             scrollable_ = false;
7381         } else {
7382             scrollable_ = GreatNotEqual(textRect_.Height(), contentRect_.Height());
7383         }
7384         SetScrollEnabled(scrollable_);
7385     } else {
7386         SetScrollEnabled(GreatNotEqual(textRect_.Width(), contentRect_.Width()));
7387     }
7388 }
7389 
7390 bool TextFieldPattern::HasStateStyle(UIState state) const
7391 {
7392     auto host = GetHost();
7393     CHECK_NULL_RETURN(host, false);
7394     auto hub = host->GetOrCreateEventHub<EventHub>();
7395     CHECK_NULL_RETURN(hub, false);
7396     return hub->HasStateStyle(state);
7397 }
7398 
7399 double TextFieldPattern::GetScrollBarWidth()
7400 {
7401     auto scrollBar = GetScrollBar();
7402     double scrollBarWidth = 0.0;
7403     if (scrollBar) {
7404         scrollBarWidth = scrollBar->GetBarRect().Width();
7405     }
7406     return scrollBarWidth;
7407 }
7408 
7409 void TextFieldPattern::AddCounterNode()
7410 {
7411     auto host = GetHost();
7412     CHECK_NULL_VOID(host);
7413     if (counterDecorator_ && (IsShowPasswordIcon() || IsNormalInlineState())) {
7414         CleanCounterNode();
7415         return;
7416     }
7417     if (!counterDecorator_) {
7418         auto counterDecorator = MakeRefPtr<CounterDecorator>(host);
7419         counterDecorator_ = counterDecorator;
7420     }
7421 }
7422 
7423 void TextFieldPattern::SetShowError()
7424 {
7425     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7426     CHECK_NULL_VOID(layoutProperty);
7427     auto passWordMode = IsInPasswordMode();
7428     auto textFieldTheme = GetTheme();
7429     CHECK_NULL_VOID(textFieldTheme);
7430     auto tmpHost = GetHost();
7431     CHECK_NULL_VOID(tmpHost);
7432     auto renderContext = tmpHost->GetRenderContext();
7433     CHECK_NULL_VOID(renderContext);
7434     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7435     CHECK_NULL_VOID(paintProperty);
7436     auto isUnderLine = IsUnderlineMode();
7437     auto errorText = layoutProperty->GetErrorTextValue(u"");
7438     if (IsShowError()) { // update error state
7439         if (isUnderLine) {
7440             underlineColor_ = userUnderlineColor_.error.value_or(textFieldTheme->GetErrorUnderlineColor());
7441             underlineWidth_ = ERROR_UNDERLINE_WIDTH;
7442         } else if (passWordMode) {
7443             if (!paintProperty->HasBorderWidthFlagByUser()) {
7444                 paintProperty->UpdateInnerBorderWidth(textFieldTheme->GetErrorTextInputBorderWidth());
7445                 paintProperty->UpdateInnerBorderColor(textFieldTheme->GetPasswordErrorBorderColor());
7446             } else {
7447                 BorderColorProperty borderColor;
7448                 borderColor.SetColor(textFieldTheme->GetPasswordErrorBorderColor());
7449                 renderContext->UpdateBorderColor(borderColor);
7450             }
7451             renderContext->UpdateBackgroundColor(textFieldTheme->GetPasswordErrorInputColor());
7452             layoutProperty->UpdateTextColor(textFieldTheme->GetPasswordErrorTextColor());
7453             if (!layoutProperty->HasPlaceholderTextColor()) {
7454                 layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetPlaceholderColor());
7455             }
7456         }
7457     }
7458     UpdateErrorTextMargin();
7459 }
7460 
7461 float TextFieldPattern::CalcDecoratorWidth(const RefPtr<FrameNode>& decoratorNode)
7462 {
7463     float decoratorWidth = 0.0f;
7464     CHECK_NULL_RETURN(decoratorNode, 0.0f);
7465     auto textPattern = decoratorNode->GetPattern<TextPattern>();
7466     CHECK_NULL_RETURN(textPattern, 0.0f);
7467     auto paragraphs = textPattern->GetParagraphs();
7468     for (auto &&info : paragraphs) {
7469         if (info.paragraph) {
7470             float width = info.paragraph->GetLongestLine();
7471             decoratorWidth = std::max(decoratorWidth, width);
7472         }
7473     }
7474     return decoratorWidth;
7475 }
7476 
7477 float TextFieldPattern::CalcDecoratorHeight(const RefPtr<FrameNode>& decoratorNode)
7478 {
7479     CHECK_NULL_RETURN(decoratorNode, 0.0f);
7480     auto geometryNode = decoratorNode->GetGeometryNode();
7481     CHECK_NULL_RETURN(geometryNode, 0.0f);
7482     return geometryNode->GetFrameRect().Height();
7483 }
7484 
7485 void TextFieldPattern::UpdateErrorTextMargin()
7486 {
7487     auto tmpHost = GetHost();
7488     CHECK_NULL_VOID(tmpHost);
7489     if (IsShowError()) {
7490         if (!errorDecorator_) {
7491             auto errorDecorator = MakeRefPtr<ErrorDecorator>(tmpHost);
7492             errorDecorator_ = errorDecorator;
7493         }
7494         errorDecorator_->UpdateTextFieldMargin();
7495     } else {
7496         errorDecorator_.Reset();
7497     }
7498 }
7499 
7500 void TextFieldPattern::ApplyUnderlineTheme()
7501 {
7502     if (!IsUnderlineMode()) {
7503         return;
7504     }
7505     SetThemeAttr();
7506     auto theme = GetTheme();
7507     CHECK_NULL_VOID(theme);
7508     if (IsShowError()) {
7509         underlineColor_ = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
7510     } else {
7511         underlineColor_ = HasFocus() ? userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor())
7512             : userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
7513     }
7514     underlineWidth_ = HasFocus() ? TYPING_UNDERLINE_WIDTH : UNDERLINE_WIDTH;
7515 }
7516 
7517 float TextFieldPattern::GetMarginBottom() const
7518 {
7519     auto tmpHost = GetHost();
7520     CHECK_NULL_RETURN(tmpHost, 0.0f);
7521     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7522     CHECK_NULL_RETURN(layoutProperty, 0.0f);
7523     const auto& getMargin = layoutProperty->GetMarginProperty();
7524     if (getMargin && getMargin->bottom.has_value()) {
7525         return getMargin->bottom->GetDimension().ConvertToPx();
7526     }
7527     return 0.0f;
7528 }
7529 
7530 std::string TextFieldPattern::GetShowResultImageSrc() const
7531 {
7532     auto tmpHost = GetHost();
7533     CHECK_NULL_RETURN(tmpHost, "");
7534     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7535     CHECK_NULL_RETURN(layoutProperty, "");
7536     auto showImageSource = layoutProperty->GetShowPasswordSourceInfo();
7537     if (showImageSource && !showImageSource->GetSrc().empty()) {
7538         return showImageSource->GetSrc();
7539     }
7540     return SHOW_PASSWORD_SVG;
7541 }
7542 
7543 std::string TextFieldPattern::GetNormalUnderlineColorStr() const
7544 {
7545     auto theme = GetTheme();
7546     CHECK_NULL_RETURN(theme, "");
7547     Color normal = userUnderlineColor_.normal.value_or(theme->GetUnderlineColor());
7548     return normal.ColorToString();
7549 }
7550 
7551 std::string TextFieldPattern::GetTypingUnderlineColorStr() const
7552 {
7553     auto theme = GetTheme();
7554     CHECK_NULL_RETURN(theme, "");
7555     Color typing = userUnderlineColor_.typing.value_or(theme->GetUnderlineTypingColor());
7556     return typing.ColorToString();
7557 }
7558 
7559 std::string TextFieldPattern::GetDisableUnderlineColorStr() const
7560 {
7561     auto theme = GetTheme();
7562     CHECK_NULL_RETURN(theme, "");
7563     Color disable = userUnderlineColor_.disable.value_or(theme->GetDisableUnderlineColor());
7564     return disable.ColorToString();
7565 }
7566 
7567 std::string TextFieldPattern::GetErrorUnderlineColorStr() const
7568 {
7569     auto theme = GetTheme();
7570     CHECK_NULL_RETURN(theme, "");
7571     Color error = userUnderlineColor_.error.value_or(theme->GetErrorUnderlineColor());
7572     return error.ColorToString();
7573 }
7574 
7575 std::string TextFieldPattern::GetHideResultImageSrc() const
7576 {
7577     auto tmpHost = GetHost();
7578     CHECK_NULL_RETURN(tmpHost, "");
7579     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7580     CHECK_NULL_RETURN(layoutProperty, "");
7581     auto hideSourceInfo = layoutProperty->GetHidePasswordSourceInfo();
7582     if (hideSourceInfo && !hideSourceInfo->GetSrc().empty()) {
7583         return hideSourceInfo->GetSrc();
7584     }
7585     return HIDE_PASSWORD_SVG;
7586 }
7587 
7588 void TextFieldPattern::RestorePreInlineStates()
7589 {
7590     ResetContextAttr();
7591     ApplyNormalTheme();
7592     ApplyUnderlineTheme();
7593     ProcessInnerPadding();
7594     ProcessResponseArea();
7595     ProcessRectPadding();
7596 }
7597 
7598 void TextFieldPattern::ProcessRectPadding()
7599 {
7600     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7601     CHECK_NULL_VOID(layoutProperty);
7602     auto& paddingProperty = layoutProperty->GetPaddingProperty();
7603     CHECK_NULL_VOID(paddingProperty);
7604     auto top = paddingProperty->top.has_value() ? paddingProperty->top->GetDimension().ConvertToPx() : 0.0f;
7605     textRect_.SetTop(top);
7606 }
7607 
7608 void TextFieldPattern::TextAreaInputRectUpdate(RectF& rect)
7609 {
7610     auto tmpHost = GetHost();
7611     CHECK_NULL_VOID(tmpHost);
7612     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7613     CHECK_NULL_VOID(layoutProperty);
7614     auto theme = GetTheme();
7615     CHECK_NULL_VOID(theme);
7616     if (IsTextArea() && !contentController_->IsEmpty()) {
7617         auto inputContentWidth = GetParagraph()->GetMaxIntrinsicWidth();
7618         switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
7619             case TextAlign::START:
7620                 if (inputContentWidth < contentRect_.Width()) {
7621                     rect.SetWidth(inputContentWidth);
7622                 }
7623                 break;
7624             case TextAlign::CENTER:
7625                 if (inputContentWidth < contentRect_.Width()) {
7626                     rect.SetLeft(
7627                         static_cast<float>(rect.GetX()) + contentRect_.Width() / 2.0f - inputContentWidth / 2.0f);
7628                     rect.SetWidth(inputContentWidth);
7629                 }
7630                 break;
7631             case TextAlign::END:
7632                 if (inputContentWidth < contentRect_.Width()) {
7633                     rect.SetLeft(static_cast<float>(rect.GetX()) + contentRect_.Width() -
7634                                  static_cast<float>(theme->GetCursorWidth().ConvertToPx()) - inputContentWidth);
7635                     rect.SetWidth(inputContentWidth);
7636                 }
7637                 break;
7638             default:
7639                 break;
7640         }
7641     }
7642 }
7643 
7644 void TextFieldPattern::TextIsEmptyRect(RectF& rect)
7645 {
7646     rect = selectController_->CalculateEmptyValueCaretRect();
7647 }
7648 
7649 void TextFieldPattern::UpdateRectByTextAlign(RectF& rect)
7650 {
7651     auto tmpHost = GetHost();
7652     CHECK_NULL_VOID(tmpHost);
7653     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7654     CHECK_NULL_VOID(layoutProperty);
7655     if (!layoutProperty->HasTextAlign()) {
7656         return;
7657     }
7658     switch (layoutProperty->GetTextAlignValue(TextAlign::START)) {
7659         case TextAlign::START:
7660             return;
7661         case TextAlign::CENTER:
7662             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()) * 0.5f);
7663             return;
7664         case TextAlign::END:
7665             rect.SetLeft(rect.GetOffset().GetX() + (contentRect_.Width() - textRect_.Width()));
7666             return;
7667         default:
7668             return;
7669     }
7670 }
7671 
7672 void TextFieldPattern::ProcessInlinePaddingAndMargin()
7673 {
7674     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7675     CHECK_NULL_VOID(layoutProperty);
7676     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7677     auto theme = GetTheme();
7678     CHECK_NULL_VOID(theme);
7679     PaddingProperty userPadding;
7680     MarginProperty userMargin;
7681     if (paintProperty->HasPaddingByUser()) {
7682         userPadding = paintProperty->GetPaddingByUserValue();
7683     } else {
7684         auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
7685         userPadding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
7686         userPadding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
7687         userPadding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
7688         userPadding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
7689     }
7690     if (paintProperty->HasMarginByUser()) {
7691         userMargin = paintProperty->GetMarginByUserValue();
7692     }
7693     MarginProperty margin;
7694     margin.bottom = CalcLength(userMargin.bottom->GetDimension() + userPadding.bottom->GetDimension());
7695     margin.right = CalcLength(userMargin.right->GetDimension() + userPadding.right->GetDimension());
7696     margin.left = CalcLength(userMargin.left->GetDimension() + userPadding.left->GetDimension());
7697     margin.top = CalcLength(userMargin.top->GetDimension() + userPadding.top->GetDimension());
7698     layoutProperty->UpdateMargin(margin);
7699     if (!IsTextArea()) {
7700         layoutProperty->UpdatePlaceholderMaxLines(layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
7701         layoutProperty->ResetMaxLines();
7702     }
7703     if (layoutProperty->HasTextOverflow()) {
7704         layoutProperty->UpdateTextOverflowMaxLines(layoutProperty->GetMaxViewLinesValue(INLINE_DEFAULT_VIEW_MAXLINE));
7705     }
7706 }
7707 
7708 void TextFieldPattern::ApplyInlineTheme()
7709 {
7710     if (!IsInlineMode()) {
7711         return;
7712     }
7713     auto tmpHost = GetHost();
7714     CHECK_NULL_VOID(tmpHost);
7715     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7716     CHECK_NULL_VOID(layoutProperty);
7717     auto renderContext = tmpHost->GetRenderContext();
7718     CHECK_NULL_VOID(renderContext);
7719     auto theme = GetTheme();
7720     CHECK_NULL_VOID(theme);
7721     layoutProperty->UpdateTextColor(theme->GetInlineTextColor());
7722     auto radius = theme->GetInlineRadiusSize();
7723     renderContext->UpdateBorderRadius({ radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() });
7724     renderContext->UpdateBackgroundColor(theme->GetInlineBgColor());
7725     BorderWidthProperty inlineBorderWidth;
7726     inlineBorderWidth.SetBorderWidth(INLINE_BORDER_WIDTH);
7727     layoutProperty->UpdateBorderWidth(inlineBorderWidth);
7728     renderContext->UpdateBorderWidth(inlineBorderWidth);
7729     BorderColorProperty inlineBorderColor;
7730     inlineBorderColor.SetColor(theme->GetInlineBorderColor());
7731     renderContext->UpdateBorderColor(inlineBorderColor);
7732 
7733     if (layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL) {
7734         layoutProperty->UpdatePadding({ CalcLength(theme->getInlinePaddingRight()),
7735             CalcLength(theme->getInlinePaddingLeft()), CalcLength(0.0f), CalcLength(0.0f) });
7736     } else {
7737         layoutProperty->UpdatePadding({ CalcLength(theme->getInlinePaddingLeft()),
7738             CalcLength(theme->getInlinePaddingRight()), CalcLength(0.0f), CalcLength(0.0f)});
7739     }
7740     ProcessInnerPadding();
7741     ProcessInlinePaddingAndMargin();
7742 }
7743 
7744 bool TextFieldPattern::ResetObscureTickCountDown()
7745 {
7746     auto oldTickCountDown_ = obscureTickCountDown_;
7747     if (!IsTextArea() && GetTextObscured() && IsInPasswordMode()) {
7748         obscureTickCountDown_ = 0;
7749     }
7750     return oldTickCountDown_ != obscureTickCountDown_;
7751 }
7752 
7753 bool TextFieldPattern::IsInPasswordMode() const
7754 {
7755     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7756     CHECK_NULL_RETURN(layoutProperty, false);
7757     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
7758     return inputType == TextInputType::VISIBLE_PASSWORD || inputType == TextInputType::NUMBER_PASSWORD ||
7759            inputType == TextInputType::SCREEN_LOCK_PASSWORD || inputType == TextInputType::NEW_PASSWORD;
7760 }
7761 
7762 bool TextFieldPattern::IsNormalInlineState() const
7763 {
7764     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
7765     CHECK_NULL_RETURN(paintProperty, false);
7766     auto tmpHost = GetHost();
7767     CHECK_NULL_RETURN(tmpHost, false);
7768     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7769     CHECK_NULL_RETURN(layoutProperty, false);
7770     return paintProperty->GetInputStyleValue(InputStyle::DEFAULT) == InputStyle::INLINE &&
7771            (layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::UNSPECIFIED ||
7772                layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::TEXT);
7773 }
7774 
7775 bool TextFieldPattern::IsUnspecifiedOrTextType() const
7776 {
7777     auto tmpHost = GetHost();
7778     CHECK_NULL_RETURN(tmpHost, false);
7779     auto layoutProperty = tmpHost->GetLayoutProperty<TextFieldLayoutProperty>();
7780     CHECK_NULL_RETURN(layoutProperty, false);
7781     auto inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
7782     return inputType == TextInputType::UNSPECIFIED || inputType == TextInputType::TEXT;
7783 }
7784 
7785 void TextFieldPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7786 {
7787     /* no fixed attr below, just return */
7788     if (filter.IsFastFilter()) {
7789         return;
7790     }
7791     json->PutExtAttr("placeholder", UtfUtils::Str16DebugToStr8(GetPlaceHolder()).c_str(), filter);
7792     json->PutExtAttr("text", contentController_->GetTextValue().c_str(), filter);
7793     json->PutExtAttr("fontSize", GetFontSize().c_str(), filter);
7794     json->PutExtAttr("fontColor", GetTextColor().c_str(), filter);
7795     json->PutExtAttr("fontStyle",
7796         GetItalicFontStyle() == Ace::FontStyle::NORMAL ? "FontStyle.Normal" : "FontStyle.Italic", filter);
7797     json->PutExtAttr("fontWeight", V2::ConvertWrapFontWeightToStirng(GetFontWeight()).c_str(), filter);
7798     json->PutExtAttr("fontFamily", GetFontFamily().c_str(), filter);
7799     json->PutExtAttr("textAlign", V2::ConvertWrapTextAlignToString(GetTextAlign()).c_str(), filter);
7800     json->PutExtAttr("caretColor", GetCaretColor().c_str(), filter);
7801     json->PutExtAttr("type", TextInputTypeToString().c_str(), filter);
7802     json->PutExtAttr("contentType", TextContentTypeToString().c_str(), filter);
7803     json->PutExtAttr("placeholderColor", GetPlaceholderColor().c_str(), filter);
7804     json->PutExtAttr("placeholderFont", GetPlaceholderFont().c_str(), filter);
7805     json->PutExtAttr("enterKeyType", TextInputActionToString().c_str(), filter);
7806     json->PutExtAttr("maxLength", GreatOrEqual(GetMaxLength(),
7807         Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLength()).c_str(), filter);
7808     json->PutExtAttr("inputFilter", GetInputFilter().c_str(), filter);
7809     json->PutExtAttr("copyOption", GetCopyOptionString().c_str(), filter);
7810     json->PutExtAttr("style", GetInputStyleString().c_str(), filter);
7811 
7812     auto jsonValue = JsonUtil::Create(true);
7813     if (IsShowPasswordSymbol()) {
7814         jsonValue->Put("onIconSrc", static_cast<int64_t>(GetTheme()->GetShowSymbolId()));
7815         jsonValue->Put("offIconSrc", static_cast<int64_t>(GetTheme()->GetHideSymbolId()));
7816     } else {
7817         jsonValue->Put("onIconSrc", GetShowResultImageSrc().c_str());
7818         jsonValue->Put("offIconSrc", GetHideResultImageSrc().c_str());
7819     }
7820     json->PutExtAttr("passwordIcon", jsonValue->ToString().c_str(), filter);
7821     json->PutExtAttr("showError", GetErrorTextState() ? UtfUtils::Str16DebugToStr8(GetErrorTextString()).c_str() :
7822         "undefined", filter);
7823     json->PutExtAttr("maxLines", GreatOrEqual(GetMaxLines(),
7824         Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLines()).c_str(), filter);
7825     json->PutExtAttr("minLines", std::to_string(GetMinLines()).c_str(), filter);
7826     json->PutExtAttr("barState", GetBarStateString().c_str(), filter);
7827     json->PutExtAttr("caretPosition", std::to_string(GetCaretIndex()).c_str(), filter);
7828     json->PutExtAttr("enablePreviewText", GetSupportPreviewText(), filter);
7829     json->PutExtAttr("minFontScale", GetMinFontScale().c_str(), filter);
7830     json->PutExtAttr("maxFontScale", GetMaxFontScale().c_str(), filter);
7831     json->PutExtAttr("ellipsisMode",GetEllipsisMode().c_str(), filter);
7832     json->PutExtAttr("autoCapitalizationMode", AutoCapTypeToString().c_str(), filter);
7833     ToJsonValueForOption(json, filter);
7834     ToJsonValueForFontFeature(json, filter);
7835     ToJsonValueSelectOverlay(json, filter);
7836     ToJsonValueForStroke(json, filter);
7837 }
7838 
7839 void TextFieldPattern::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
7840 {
7841     Pattern::ToTreeJson(json, config);
7842     json->Put(TreeKey::CONTENT, contentController_->GetTextValue().c_str());
7843     json->Put(TreeKey::PLACEHOLDER, GetPlaceHolder().c_str());
7844 }
7845 
7846 void TextFieldPattern::ToJsonValueForFontFeature(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7847 {
7848     auto host = GetHost();
7849     CHECK_NULL_VOID(host);
7850     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7851     CHECK_NULL_VOID(layoutProperty);
7852     if (!layoutProperty->HasFontFeature()) {
7853         json->PutExtAttr("fontFeature", "", filter);
7854         return;
7855     }
7856     auto fontFeature = layoutProperty->GetFontFeature().value();
7857     std::string fontFeatureString = "";
7858     for (const auto& fontFeatureItem : fontFeature) {
7859         fontFeatureString += fontFeatureItem.first;
7860         fontFeatureString += " ";
7861         fontFeatureString += fontFeatureItem.second ? "on" : "off";
7862         fontFeatureString += ",";
7863     }
7864     if (!fontFeatureString.empty()) {
7865         fontFeatureString.pop_back();
7866     }
7867     json->PutExtAttr("fontFeature", fontFeatureString.c_str(), filter);
7868 }
7869 
7870 void TextFieldPattern::ToJsonValueForOption(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7871 {
7872     auto underlineColorJsonValue = JsonUtil::Create(true);
7873     underlineColorJsonValue->Put("normal", GetNormalUnderlineColorStr().c_str());
7874     underlineColorJsonValue->Put("typing", GetTypingUnderlineColorStr().c_str());
7875     underlineColorJsonValue->Put("error", GetErrorUnderlineColorStr().c_str());
7876     underlineColorJsonValue->Put("disable", GetDisableUnderlineColorStr().c_str());
7877     json->PutExtAttr("underlineColor", underlineColorJsonValue->ToString().c_str(), filter);
7878 
7879     auto host = GetHost();
7880     CHECK_NULL_VOID(host);
7881     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
7882     CHECK_NULL_VOID(layoutProperty);
7883     auto jsonShowCounter = JsonUtil::Create(true);
7884     jsonShowCounter->Put("value", layoutProperty->GetShowCounterValue(false));
7885     auto jsonShowCounterOptions = JsonUtil::Create(true);
7886     jsonShowCounterOptions->Put("thresholdPercentage", layoutProperty->GetSetCounterValue(DEFAULT_MODE));
7887     jsonShowCounterOptions->Put("highlightBorder", layoutProperty->GetShowHighlightBorderValue(true));
7888     jsonShowCounter->Put("options", jsonShowCounterOptions);
7889     json->PutExtAttr("showCounter", jsonShowCounter, filter);
7890     json->PutExtAttr("keyboardAppearance", static_cast<int32_t>(keyboardAppearance_), filter);
7891     json->PutExtAttr("enableHapticFeedback", isEnableHapticFeedback_ ? "true" : "false", filter);
7892 }
7893 
7894 void TextFieldPattern::ToJsonValueSelectOverlay(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7895 {
7896     json->PutExtAttr("CaretStatus", cursorVisible_ ? "show" : "hide", filter);
7897     json->PutExtAttr("CaretTwinkling", isCaretTwinkling_ ? "true" : "false", filter);
7898     json->PutExtAttr("caretRect", selectController_->GetCaretRect().ToString().c_str(), filter);
7899     json->PutExtAttr("caretWidth", std::to_string(selectController_->GetCaretRect().Width()).c_str(), filter);
7900     json->PutExtAttr("isShowMagnifier", magnifierController_->GetShowMagnifier() ? "true" : "false", filter);
7901     json->PutExtAttr("MagnifierPosition", magnifierController_->GetLocalOffset().ToString().c_str(), filter);
7902 
7903     auto manager = selectOverlay_->GetManager<SelectContentOverlayManager>();
7904     CHECK_NULL_VOID(manager);
7905     auto selectOverlayInfo = manager->GetSelectOverlayInfo();
7906     CHECK_NULL_VOID(selectOverlayInfo);
7907 
7908     //handle info
7909     json->PutExtAttr("IsSingleHandle", selectOverlayInfo->isSingleHandle ? "true" : "false", filter);
7910     json->PutExtAttr("IsHandleReverse", selectOverlayInfo->handleReverse ? "true" : "false", filter);
7911     json->PutExtAttr("FirstHandleRect", selectOverlayInfo->firstHandle.paintRect.ToString().c_str(), filter);
7912     json->PutExtAttr("FirstHandleStartPoint",
7913         selectOverlayInfo->firstHandle.paintInfo.startPoint.ToString().c_str(), filter);
7914     json->PutExtAttr("FirstHandleEndPoint",
7915         selectOverlayInfo->firstHandle.paintInfo.endPoint.ToString().c_str(), filter);
7916     json->PutExtAttr("IsFirstHandlePaintByPoints",
7917         selectOverlayInfo->firstHandle.isPaintHandleWithPoints ? "true" : "false", filter);
7918     json->PutExtAttr("SecondHandleRect", selectOverlayInfo->secondHandle.paintRect.ToString().c_str(), filter);
7919     json->PutExtAttr("SecondHandleStartPoint",
7920         selectOverlayInfo->secondHandle.paintInfo.startPoint.ToString().c_str(), filter);
7921     json->PutExtAttr("SecondHandleEndPoint",
7922         selectOverlayInfo->secondHandle.paintInfo.endPoint.ToString().c_str(), filter);
7923     json->PutExtAttr("IsSecondHandlePaintByPoints",
7924         selectOverlayInfo->secondHandle.isPaintHandleWithPoints ? "true" : "false", filter);
7925 
7926     //menu
7927     auto menuNode = manager->GetSelectOverlayNode();
7928     CHECK_NULL_VOID(menuNode);
7929     json->PutExtAttr("MenuNode", menuNode->GetTag().c_str(), filter);
7930     if (menuNode->GetAncestorNodeOfFrame(true)) {
7931         json->PutExtAttr("MountOn", menuNode->GetAncestorNodeOfFrame(true)->GetTag().c_str(), filter);
7932     }
7933     auto menuLayoutProperty = menuNode->GetLayoutProperty();
7934     CHECK_NULL_VOID(menuLayoutProperty);
7935     auto menuVisible = static_cast<int32_t>(menuLayoutProperty->GetVisibility().value_or(VisibleType::VISIBLE));
7936     json->PutExtAttr("Visible", std::to_string(menuVisible).c_str(), filter);
7937     auto menuGeometryNode = menuNode->GetGeometryNode();
7938     CHECK_NULL_VOID(menuGeometryNode);
7939     json->PutExtAttr("MenuFrameRect", menuGeometryNode->GetFrameRect().ToString().c_str(), filter);
7940     json->PutExtAttr("MenuItemCount", std::to_string(selectOverlayInfo->menuOptionItems.size()).c_str(), filter);
7941     for (auto menuItme : selectOverlayInfo->menuOptionItems) {
7942         json->PutExtAttr("MenuItme", menuItme.content.value_or("").c_str(), filter);
7943     }
7944 }
7945 
7946 std::string TextFieldPattern::GetStrokeWidth() const
7947 {
7948     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7949     CHECK_NULL_RETURN(layoutProperty, "");
7950     return (layoutProperty->GetStrokeWidth().value_or(Dimension())).ToString();
7951 }
7952 
7953 std::string TextFieldPattern::GetStrokeColor() const
7954 {
7955     auto theme = GetTheme();
7956     CHECK_NULL_RETURN(theme, "");
7957     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7958     CHECK_NULL_RETURN(layoutProperty, "");
7959 
7960     if (layoutProperty->HasStrokeColor() && layoutProperty->GetStrokeColor().has_value()) {
7961         auto strokeColor = layoutProperty->GetStrokeColor().value().ColorToString();
7962         if (!strokeColor.empty()) {
7963             return strokeColor;
7964         }
7965     }
7966 
7967     auto textColor = layoutProperty->GetTextColor();
7968     if (textColor.has_value()) {
7969         return textColor.value().ColorToString();
7970     }
7971 
7972     return theme->GetTextColor().ColorToString();
7973 }
7974 
7975 void TextFieldPattern::ToJsonValueForStroke(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7976 {
7977     json->PutExtAttr("strokeWidth", GetStrokeWidth().c_str(), filter);
7978     json->PutExtAttr("strokeColor", GetStrokeColor().c_str(), filter);
7979 }
7980 
7981 void TextFieldPattern::FromJson(const std::unique_ptr<JsonValue>& json)
7982 {
7983     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
7984     layoutProperty->UpdatePlaceholder(UtfUtils::Str8DebugToStr16(json->GetString("placeholder")));
7985     UpdateEditingValue(json->GetString("text"), StringUtils::StringToInt(json->GetString("caretPosition")));
7986     FireOnTextChangeEvent();
7987     UpdateSelection(GetCaretIndex());
7988     auto maxLines = json->GetString("maxLines");
7989     if (!maxLines.empty() && maxLines != "INF") {
7990         layoutProperty->UpdateMaxLines(StringUtils::StringToUint(maxLines));
7991     }
7992     static const std::unordered_map<std::string, CopyOptions> uMap = {
7993         { "CopyOptions.None", CopyOptions::None },
7994         { "CopyOptions.InApp", CopyOptions::InApp },
7995         { "CopyOptions.Local", CopyOptions::Local },
7996         { "CopyOptions.Distributed", CopyOptions::Distributed },
7997     };
7998     auto copyOption = json->GetString("copyOption");
7999     CopyOptions copyOptionsEnum = CopyOptions::Local;
8000     auto iter = uMap.find(copyOption);
8001     if (iter != uMap.end()) {
8002         copyOptionsEnum = iter->second;
8003     }
8004     layoutProperty->UpdateCopyOptions(copyOptionsEnum);
8005     Pattern::FromJson(json);
8006 }
8007 
8008 void TextFieldPattern::SetAccessibilityAction()
8009 {
8010     SetAccessibilityActionOverlayAndSelection();
8011     SetAccessibilityActionGetAndSetCaretPosition();
8012     SetAccessibilityMoveTextAction();
8013     SetAccessibilityErrorText();
8014 }
8015 
8016 void TextFieldPattern::SetAccessibilityActionOverlayAndSelection()
8017 {
8018     auto host = GetHost();
8019     CHECK_NULL_VOID(host);
8020     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
8021     CHECK_NULL_VOID(accessibilityProperty);
8022     accessibilityProperty->SetActionSetText([weakPtr = WeakClaim(this)](const std::string& value) {
8023         const auto& pattern = weakPtr.Upgrade();
8024         CHECK_NULL_VOID(pattern);
8025         pattern->InsertValue(UtfUtils::Str8DebugToStr16(value));
8026     });
8027 
8028     accessibilityProperty->SetActionSetSelection([weakPtr = WeakClaim(this)](int32_t start,
8029                                                                              int32_t end, bool isForward) {
8030             const auto& pattern = weakPtr.Upgrade();
8031             CHECK_NULL_VOID(pattern);
8032             pattern->SetSelectionFlag(start, end, std::nullopt, isForward);
8033         });
8034 
8035     accessibilityProperty->SetActionClearSelection([weakPtr = WeakClaim(this)]() {
8036         const auto& pattern = weakPtr.Upgrade();
8037         CHECK_NULL_VOID(pattern);
8038         auto current = pattern->selectController_->GetEndIndex();
8039         pattern->SetInSelectMode(SelectionMode::NONE);
8040         pattern->UpdateSelection(current);
8041         pattern->SetSelectionFlag(current, current, std::nullopt);
8042         pattern->CloseSelectOverlay(true);
8043         pattern->StartTwinkling();
8044     });
8045     SetAccessibilityEditAction();
8046 }
8047 
8048 void TextFieldPattern::SetAccessibilityEditAction()
8049 {
8050     auto host = GetHost();
8051     CHECK_NULL_VOID(host);
8052     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
8053     CHECK_NULL_VOID(accessibilityProperty);
8054 
8055     accessibilityProperty->SetActionCopy([weakPtr = WeakClaim(this)]() {
8056         const auto& pattern = weakPtr.Upgrade();
8057         CHECK_NULL_VOID(pattern);
8058         if (pattern->AllowCopy()) {
8059             pattern->HandleOnCopy();
8060             pattern->CloseSelectOverlay(true);
8061         }
8062     });
8063 
8064     accessibilityProperty->SetActionCut([weakPtr = WeakClaim(this)]() {
8065         const auto& pattern = weakPtr.Upgrade();
8066         CHECK_NULL_VOID(pattern);
8067         if (pattern->AllowCopy()) {
8068             pattern->suppressAccessibilityEvent_ = false;
8069             pattern->HandleOnCut();
8070             pattern->CloseSelectOverlay(true);
8071         }
8072     });
8073 
8074     accessibilityProperty->SetActionPaste([weakPtr = WeakClaim(this)]() {
8075         const auto& pattern = weakPtr.Upgrade();
8076         CHECK_NULL_VOID(pattern);
8077         pattern->suppressAccessibilityEvent_ = false;
8078         pattern->HandleOnPaste();
8079         pattern->CloseSelectOverlay(true);
8080     });
8081 }
8082 
8083 void TextFieldPattern::SetAccessibilityActionGetAndSetCaretPosition()
8084 {
8085     auto host = GetHost();
8086     CHECK_NULL_VOID(host);
8087     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
8088     CHECK_NULL_VOID(accessibilityProperty);
8089     accessibilityProperty->SetActionSetIndex([weakPtr = WeakClaim(this)](int32_t index) {
8090         const auto& pattern = weakPtr.Upgrade();
8091         CHECK_NULL_VOID(pattern);
8092         pattern->SetCaretPosition(index);
8093     });
8094 
8095     accessibilityProperty->SetActionGetIndex([weakPtr = WeakClaim(this)]() -> int32_t {
8096         const auto& pattern = weakPtr.Upgrade();
8097         CHECK_NULL_RETURN(pattern, -1);
8098         auto index = pattern->selectController_->GetCaretIndex();
8099         return index;
8100     });
8101 }
8102 
8103 void TextFieldPattern::SetAccessibilityMoveTextAction()
8104 {
8105     auto host = GetHost();
8106     CHECK_NULL_VOID(host);
8107     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
8108     CHECK_NULL_VOID(accessibilityProperty);
8109     accessibilityProperty->SetActionMoveText([weakPtr = WeakClaim(this)](int32_t moveUnit, bool forward) {
8110         const auto& pattern = weakPtr.Upgrade();
8111         CHECK_NULL_VOID(pattern);
8112         auto host = pattern->GetHost();
8113         CHECK_NULL_VOID(host);
8114         if (pattern->contentController_->IsEmpty()) {
8115             return;
8116         }
8117         int range = 0;
8118         if (moveUnit == 1) {
8119             range = 1;
8120         }
8121         auto caretPosition = forward ? pattern->selectController_->GetCaretIndex() + range
8122                                      : pattern->selectController_->GetCaretIndex() - range;
8123         auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8124         pattern->SetCaretPosition(caretPosition);
8125     });
8126 }
8127 
8128 void TextFieldPattern::SetAccessibilityErrorText()
8129 {
8130     auto host = GetHost();
8131     CHECK_NULL_VOID(host);
8132     auto accessibilityProperty = host->GetAccessibilityProperty<TextFieldAccessibilityProperty>();
8133     CHECK_NULL_VOID(accessibilityProperty);
8134     if (!IsDisabled() && IsShowError()) {
8135         accessibilityProperty->SetErrorText(UtfUtils::Str16DebugToStr8(GetErrorTextString()));
8136     } else {
8137         accessibilityProperty->SetErrorText("");
8138     }
8139 }
8140 
8141 void TextFieldPattern::StopEditing()
8142 {
8143     auto host = GetHost();
8144     FREE_NODE_CHECK(host, StopEditing);  // call StopEditingMultiThread() by multi thread
8145     if (!HasFocus()) {
8146         return;
8147     }
8148     CHECK_NULL_VOID(host);
8149     ContainerScope scope(host->GetInstanceId());
8150     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d Stop Editing", host->GetId());
8151     FocusHub::LostFocusToViewRoot();
8152     UpdateSelection(selectController_->GetCaretIndex());
8153     StopTwinkling();
8154     CloseKeyboard(true);
8155     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8156 }
8157 
8158 void TextFieldPattern::DumpInfo()
8159 {
8160     auto host = GetHost();
8161     CHECK_NULL_VOID(host);
8162     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8163     CHECK_NULL_VOID(layoutProperty);
8164     auto& dumpLog = DumpLog::GetInstance();
8165     dumpLog.AddDesc(std::string("Content:").append(GetDumpTextValue()));
8166     dumpLog.AddDesc(std::string("AutocapitalizationMode:").append(AutoCapTypeToString()));
8167     dumpLog.AddDesc(std::string("autoWidth: ").append(std::to_string(layoutProperty->GetWidthAutoValue(false))));
8168     dumpLog.AddDesc(std::string("MaxLength:").append(std::to_string(GetMaxLength())));
8169     dumpLog.AddDesc(std::string("fontSize:").append(GetFontSize()));
8170     dumpLog.AddDesc(std::string("fontWeight:").append(V2::ConvertWrapFontWeightToStirng(GetFontWeight())));
8171     dumpLog.AddDesc(std::string("fontFamily:").append(GetFontFamily()));
8172     auto flag = GetItalicFontStyle() == Ace::FontStyle::NORMAL;
8173     dumpLog.AddDesc(std::string("fontStyle:").append(flag ? "FontStyle.Normal" : "FontStyle.Italic"));
8174     dumpLog.AddDesc(std::string("InputFilter:").append(GetInputFilter()));
8175     auto lineHeight = layoutProperty->GetLineHeight().value_or(0.0_vp).ConvertToPx();
8176     dumpLog.AddDesc(std::string("lineHeight:").append(std::to_string(lineHeight)));
8177     auto maxLines = GreatOrEqual(GetMaxLines(), Infinity<uint32_t>()) ? "INF" : std::to_string(GetMaxLines());
8178     dumpLog.AddDesc(std::string("MaxLines:").append(maxLines));
8179     dumpLog.AddDesc(std::string("TextIndent:").append(GetTextIndent()));
8180     dumpLog.AddDesc(std::string("showError:").append(GetErrorTextState() ?
8181         UtfUtils::Str16DebugToStr8(GetErrorTextString()) : "undefined"));
8182     dumpLog.AddDesc(std::string("CopyOption:").append(GetCopyOptionString()));
8183     dumpLog.AddDesc(std::string("TextAlign:").append(V2::ConvertWrapTextAlignToString(GetTextAlign())));
8184     dumpLog.AddDesc(std::string("CaretPosition:").append(std::to_string(GetCaretIndex())));
8185     dumpLog.AddDesc(std::string("type:").append(TextInputTypeToString()));
8186     dumpLog.AddDesc(std::string("enterKeyType:").append(TextInputActionToString()));
8187     dumpLog.AddDesc(std::string("HasFocus:").append(std::to_string(HasFocus())));
8188     dumpLog.AddDesc(std::string("enableKeyboardOnFocus:").append(std::to_string(needToRequestKeyboardOnFocus_)));
8189     dumpLog.AddDesc(std::string("supportPreviewText:").append(std::to_string(GetSupportPreviewText())));
8190     dumpLog.AddDesc(
8191         std::string("enableAutoFill:").append(std::to_string(layoutProperty->GetEnableAutoFillValue(true))));
8192     dumpLog.AddDesc(std::string("contentType:").append(TextContentTypeToString()));
8193     dumpLog.AddDesc(std::string("style:").append(GetInputStyleString()));
8194     dumpLog.AddDesc(std::string("PreviewTextStart:").append(std::to_string(GetPreviewTextStart())));
8195     dumpLog.AddDesc(std::string("PreviewTextEnd:").append(std::to_string(GetPreviewTextEnd())));
8196     dumpLog.AddDesc(std::string("PreTextValue:").append(UtfUtils::Str16DebugToStr8(GetPreviewTextValue())));
8197     dumpLog.AddDesc(textSelector_.ToString());
8198     dumpLog.AddDesc(std::string("wordBreak:")
8199             .append(V2::ConvertWrapWordBreakToString(layoutProperty->GetWordBreak().value_or(WordBreak::BREAK_WORD))));
8200     dumpLog.AddDesc(std::string("HeightAdaptivePolicy: ").append(V2::ConvertWrapTextHeightAdaptivePolicyToString(
8201         layoutProperty->GetHeightAdaptivePolicy().value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST))));
8202     dumpLog.AddDesc(std::string("IsAIWrite: ").append(std::to_string(IsShowAIWrite())));
8203     DumpPlaceHolderInfo();
8204     DumpScaleInfo();
8205     DumpTextEngineInfo();
8206     DumpAdvanceInfo();
8207 }
8208 
8209 void TextFieldPattern::DumpTextEngineInfo()
8210 {
8211     auto& dumpLog = DumpLog::GetInstance();
8212     dumpLog.AddDesc(std::string("-----TextEngine paragraphs_ info-----"));
8213     CHECK_NULL_VOID(paragraph_);
8214     dumpLog.AddDesc(std::string("GetTextWidth:")
8215         .append(std::to_string(paragraph_->GetTextWidth()))
8216         .append(" GetHeight:")
8217         .append(std::to_string(paragraph_->GetHeight()))
8218         .append(" GetMaxWidth:")
8219         .append(std::to_string(paragraph_->GetMaxWidth()))
8220         .append(" GetMaxIntrinsicWidth:")
8221         .append(std::to_string(paragraph_->GetMaxIntrinsicWidth())));
8222     dumpLog.AddDesc(std::string("GetLineCount:")
8223         .append(std::to_string(paragraph_->GetLineCount()))
8224         .append(" GetLongestLine:")
8225         .append(std::to_string(paragraph_->GetLongestLine()))
8226         .append(" GetLongestLineWithIndent:")
8227         .append(std::to_string(paragraph_->GetLongestLineWithIndent())));
8228 }
8229 
8230 void TextFieldPattern::DumpAdvanceInfo()
8231 {
8232     if (customKeyboard_ || customKeyboardBuilder_) {
8233         DumpLog::GetInstance().AddDesc(
8234             std::string("CustomKeyboard: true, Attached:").append(std::to_string(isCustomKeyboardAttached_)));
8235     }
8236     DumpLog::GetInstance().AddDesc(std::string("FontColor: ").append(GetTextColor()));
8237 #if defined(ENABLE_STANDARD_INPUT)
8238     auto miscTextConfig = GetMiscTextConfig();
8239     CHECK_NULL_VOID(miscTextConfig.has_value());
8240     MiscServices::TextConfig textConfig = miscTextConfig.value();
8241     DumpLog::GetInstance().AddDesc(
8242         std::string("RequestKeyboard calling window :").append(std::to_string(textConfig.windowId)));
8243     MiscServices::CursorInfo cursorInfo = miscTextConfig.value().cursorInfo;
8244     DumpLog::GetInstance().AddDesc(std::string("cursorInfo, left:")
8245                                        .append(std::to_string(cursorInfo.left))
8246                                        .append(", top:")
8247                                        .append(std::to_string(cursorInfo.top))
8248                                        .append(", width:")
8249                                        .append(std::to_string(cursorInfo.width))
8250                                        .append(", height:")
8251                                        .append(std::to_string(cursorInfo.height)));
8252 #endif
8253     DumpLog::GetInstance().AddDesc(std::string("textRect: ").append(contentRect_.ToString()));
8254     DumpLog::GetInstance().AddDesc(std::string("contentRect: ").append(contentRect_.ToString()));
8255 }
8256 
8257 void TextFieldPattern::DumpPlaceHolderInfo()
8258 {
8259     DumpLog::GetInstance().AddDesc(std::string("placeholder: ").append(UtfUtils::Str16DebugToStr8(GetPlaceHolder())));
8260     DumpLog::GetInstance().AddDesc(std::string("placeholderColor: ").append(GetPlaceholderColor()));
8261     DumpLog::GetInstance().AddDesc(std::string("placeholderFont: ").append(GetPlaceholderFont()));
8262 }
8263 
8264 void TextFieldPattern::DumpScaleInfo()
8265 {
8266     auto& dumpLog = DumpLog::GetInstance();
8267     dumpLog.AddDesc(std::string("-----DumpScaleInfo-----"));
8268     dumpLog.AddDesc(std::string("MinFontSize:").append(GetMinFontSize()));
8269     dumpLog.AddDesc(std::string("MaxFontSize:").append(GetMaxFontSize()));
8270     auto textLayoutProp = GetLayoutProperty<TextFieldLayoutProperty>();
8271     auto minFontScale = textLayoutProp->GetMinFontScale().value_or(0.0f);
8272     dumpLog.AddDesc(std::string("minFontScale: ").append(std::to_string(minFontScale)));
8273     auto maxfontScale = textLayoutProp->GetMaxFontScale().value_or(static_cast<float>(INT32_MAX));
8274     dumpLog.AddDesc(std::string("maxFontScale1: ").append(std::to_string(maxfontScale)));
8275     auto host = GetHost();
8276     CHECK_NULL_VOID(host);
8277     auto pipeline = host->GetContext();
8278     CHECK_NULL_VOID(pipeline);
8279     auto fontScale = pipeline->GetFontScale();
8280     auto fontWeightScale = pipeline->GetFontWeightScale();
8281     auto followSystem = pipeline->IsFollowSystem();
8282     float maxFontScale = pipeline->GetMaxAppFontScale();
8283     auto halfLeading = pipeline->GetHalfLeading();
8284     dumpLog.AddDesc(std::string("fontScale: ").append(std::to_string(fontScale)));
8285     dumpLog.AddDesc(std::string("fontWeightScale: ").append(std::to_string(fontWeightScale)));
8286     dumpLog.AddDesc(std::string("IsFollowSystem: ").append(std::to_string(followSystem)));
8287     dumpLog.AddDesc(std::string("maxFontScale: ").append(std::to_string(maxFontScale)));
8288     dumpLog.AddDesc(std::string("halfLeading: ").append(std::to_string(halfLeading)));
8289 }
8290 
8291 std::string TextFieldPattern::GetDumpTextValue() const
8292 {
8293     if (IsInPasswordMode()) {
8294         auto len = GetTextValue().length();
8295         auto passwordLen = "passwordLen:" + std::to_string(len);
8296         return passwordLen;
8297     } else {
8298         return GetTextValue();
8299     }
8300 }
8301 
8302 void TextFieldPattern::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap, bool needsRecordData)
8303 {
8304     CHECK_NULL_VOID(viewDataWrap);
8305     auto host = GetHost();
8306     CHECK_NULL_VOID(host);
8307     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8308     CHECK_NULL_VOID(layoutProperty);
8309     auto autoFillTypeAndMetaData = GetAutoFillTypeAndMetaData();
8310     auto info = PageNodeInfoWrap::CreatePageNodeInfoWrap();
8311     CHECK_NULL_VOID(info);
8312     info->SetId(host->GetId());
8313     info->SetDepth(host->GetDepth());
8314     info->SetAutoFillType(autoFillTypeAndMetaData.autoFillType);
8315     info->SetMetadata(autoFillTypeAndMetaData.metadata);
8316     info->SetTag(host->GetTag());
8317     auto utf8TextValue = UtfUtils::Str16DebugToStr8(contentController_->GetTextUtf16Value());
8318     if (autoFillOtherAccount_) {
8319         viewDataWrap->SetOtherAccount(true);
8320         info->SetValue(utf8TextValue);
8321         autoFillOtherAccount_ = false;
8322     } else {
8323         info->SetValue(utf8TextValue);
8324     }
8325     if (needsRecordData) {
8326         lastAutoFillTextValue_ = utf8TextValue;
8327     }
8328     info->SetPlaceholder(UtfUtils::Str16DebugToStr8(GetPlaceHolder()));
8329     info->SetPasswordRules(layoutProperty->GetPasswordRulesValue(""));
8330     info->SetEnableAutoFill(layoutProperty->GetEnableAutoFillValue(true));
8331     auto offsetToWindow = host->GetTransformRelativeOffset();
8332     auto geometryNode = host->GetGeometryNode();
8333     CHECK_NULL_VOID(geometryNode);
8334     auto pageNodeRect = geometryNode->GetFrameRect();
8335     pageNodeRect.SetLeft(offsetToWindow.GetX());
8336     pageNodeRect.SetTop(offsetToWindow.GetY());
8337     info->SetPageNodeRect(pageNodeRect);
8338     info->SetIsFocus(HasFocus());
8339     viewDataWrap->AddPageNodeInfoWrap(info);
8340 }
8341 
8342 void TextFieldPattern::NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,
8343     RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
8344 {
8345     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "autoFillType:%{public}d", static_cast<int32_t>(autoFillType));
8346     SetFillRequestFinish(true);
8347     auto host = GetHost();
8348     CHECK_NULL_VOID(host);
8349     CHECK_NULL_VOID(viewDataWrap);
8350     CHECK_NULL_VOID(nodeWrap);
8351     auto isFocus = nodeWrap->GetIsFocus();
8352     if (isFocus && !HasFocus()) {
8353         TextFieldRequestFocus(RequestFocusReason::AUTO_FILL);
8354         DoProcessAutoFill();
8355     }
8356     auto type = GetAutoFillType();
8357     bool fromOtherAccount = viewDataWrap->GetOtherAccount();
8358     if (!(type == AceAutoFillType::ACE_NEW_PASSWORD && type == autoFillType) && !fromOtherAccount) {
8359         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "Set last auto fill text value.");
8360         lastAutoFillTextValue_ = nodeWrap->GetValue();
8361     }
8362     if (!contentController_ || contentController_->GetTextValue() == nodeWrap->GetValue()) {
8363         return;
8364     }
8365     RemoveFillContentMap();
8366     BeforeAutoFillAnimation(UtfUtils::Str8DebugToStr16(nodeWrap->GetValue()), type);
8367 }
8368 
8369 void TextFieldPattern::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
8370 {
8371     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "NotifyFillRequestFailed errCode:%{public}d", errCode);
8372     SetFillRequestFinish(true);
8373 
8374 #if defined(ENABLE_STANDARD_INPUT)
8375     TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "fillContent size is : %{public}zu", fillContent.size());
8376     if (errCode == AUTO_FILL_CANCEL) {
8377         if (!fillContent.empty() && IsTriggerAutoFillPassword()) {
8378             auto jsonObject = JsonUtil::ParseJsonString(fillContent);
8379             CHECK_NULL_VOID(jsonObject);
8380             auto host = GetHost();
8381             CHECK_NULL_VOID(host);
8382             auto context = host->GetContext();
8383             CHECK_NULL_VOID(context);
8384             auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
8385             CHECK_NULL_VOID(textFieldManager);
8386             textFieldManager->ParseFillContentJsonValue(jsonObject);
8387         }
8388     }
8389     if (!isPopup || (isPopup && errCode == AUTO_FILL_CANCEL)) {
8390         if (RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::AUTO_FILL_REQUEST_FAIL)) {
8391             NotifyOnEditChanged(true);
8392         }
8393     }
8394 #endif
8395 }
8396 
8397 bool TextFieldPattern::CheckAutoSave()
8398 {
8399     auto host = GetHost();
8400     CHECK_NULL_RETURN(host, false);
8401     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8402     CHECK_NULL_RETURN(layoutProperty, false);
8403     if (!layoutProperty->GetEnableAutoFillValue(true)) {
8404         return false;
8405     }
8406     if (!contentController_ || contentController_->GetTextUtf16Value().empty()) {
8407         return false;
8408     }
8409     auto autoFillType = GetAutoFillType();
8410     if (IsAutoFillUserName(autoFillType)) {
8411         if (!lastAutoFillTextValue_.empty() &&
8412             contentController_->GetTextValue() != lastAutoFillTextValue_) {
8413             return true;
8414         }
8415     }
8416     if (AceAutoFillType::ACE_UNSPECIFIED < autoFillType && autoFillType <= AceAutoFillType::END &&
8417         !IsAutoFillUserName(autoFillType)) {
8418         if (contentController_->GetTextValue() != lastAutoFillTextValue_) {
8419             return true;
8420         }
8421     }
8422     return false;
8423 }
8424 
8425 bool TextFieldPattern::IsTouchAtLeftOffset(float currentOffsetX)
8426 {
8427     return LessNotEqual(currentOffsetX, contentRect_.GetX() + contentRect_.Width() * 0.5);
8428 }
8429 
8430 OffsetF TextFieldPattern::GetDragUpperLeftCoordinates()
8431 {
8432     if (!IsSelected()) {
8433         return { 0.0f, 0.0f };
8434     }
8435     auto selectRects = selectController_->GetSelectedRects();
8436     auto startY = selectRects.front().Top();
8437     auto startX = selectRects.front().Left();
8438     auto endY = selectRects.back().Top();
8439     OffsetF startOffset;
8440     if (NearEqual(startY, endY)) {
8441         startOffset = { (IsTextArea() ? contentRect_.GetX() : textRect_.GetX()) + startX,
8442             startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
8443     } else {
8444         startOffset = { contentRect_.GetX(), startY + (IsTextArea() ? textRect_.GetY() : contentRect_.GetY()) };
8445     }
8446 
8447     if (startOffset.GetY() < contentRect_.GetY()) {
8448         startOffset.SetY(contentRect_.GetY());
8449     }
8450     if (startOffset.GetX() < contentRect_.GetX()) {
8451         startOffset.SetX(contentRect_.GetX());
8452     }
8453     return startOffset + GetPaintRectGlobalOffset();
8454 }
8455 
8456 void TextFieldPattern::OnColorConfigurationUpdate()
8457 {
8458     ScrollablePattern::OnColorConfigurationUpdate();
8459     auto host = GetHost();
8460     CHECK_NULL_VOID(host);
8461     auto theme = GetTheme();
8462     CHECK_NULL_VOID(theme);
8463     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8464     CHECK_NULL_VOID(layoutProperty);
8465     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8466     CHECK_NULL_VOID(paintProperty);
8467     if (!paintProperty->HasTextColorFlagByUser()) {
8468         layoutProperty->UpdateTextColor(theme->GetTextColor());
8469     }
8470     if (magnifierController_) {
8471         magnifierController_->SetColorModeChange(true);
8472     }
8473     auto context = host->GetContext();
8474     CHECK_NULL_VOID(context);
8475     auto colorMode = context->GetColorMode();
8476     SetOriginCursorColor(colorMode == ColorMode::DARK ? Color(0x4DFFFFFF) : Color(0x4D000000));
8477     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8478 }
8479 
8480 bool TextFieldPattern::IsReachedBoundary(float offset)
8481 {
8482     if (IsTextArea()) {
8483         return (NearEqual(textRect_.GetY(), contentRect_.GetY()) && GreatNotEqual(offset, 0.0f)) ||
8484                (NearEqual(textRect_.GetY() + textRect_.Height(), contentRect_.GetY() + contentRect_.Height()) &&
8485                    LessNotEqual(offset, 0.0f));
8486     }
8487 
8488     return (NearEqual(textRect_.GetX(), contentRect_.GetX()) && GreatNotEqual(offset, 0.0f)) ||
8489            (NearEqual(textRect_.GetX() + textRect_.Width(), contentRect_.GetX() + contentRect_.Width()) &&
8490                LessNotEqual(offset, 0.0f));
8491 }
8492 
8493 OffsetF TextFieldPattern::GetTextPaintOffset() const
8494 {
8495     return GetPaintRectGlobalOffset();
8496 }
8497 
8498 OffsetF TextFieldPattern::GetPaintRectGlobalOffset() const
8499 {
8500     auto host = GetHost();
8501     CHECK_NULL_RETURN(host, OffsetF(0.0f, 0.0f));
8502     auto pipeline = host->GetContextRefPtr();
8503     CHECK_NULL_RETURN(pipeline, OffsetF(0.0f, 0.0f));
8504     auto rootOffset = pipeline->GetRootRect().GetOffset();
8505     OffsetF textPaintOffset;
8506     textPaintOffset = host->GetPaintRectOffsetNG(false, true);
8507     return textPaintOffset - rootOffset;
8508 }
8509 
8510 void TextFieldPattern::UpdateSelectController()
8511 {
8512     selectController_->UpdateContentRect(contentRect_);
8513     selectController_->UpdateParagraph(paragraph_);
8514 }
8515 
8516 bool TextFieldPattern::RepeatClickCaret(const Offset& offset, int32_t lastCaretIndex)
8517 {
8518     auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset);
8519     return lastCaretIndex == touchDownIndex && HasFocus();
8520 }
8521 
8522 bool TextFieldPattern::RepeatClickCaret(const Offset& offset, const RectF& lastCaretRect)
8523 {
8524     auto caretRect = lastCaretRect;
8525     caretRect.SetLeft(caretRect.GetX() - caretRect.Height() / 2);
8526     caretRect.SetWidth(caretRect.Height());
8527     return caretRect.IsInRegion(PointF(offset.GetX(), offset.GetY()));
8528 }
8529 
8530 void TextFieldPattern::OnAttachToFrameNode()
8531 {
8532     auto frameNode = GetHost();
8533     CHECK_NULL_VOID(frameNode);
8534     THREAD_SAFE_NODE_CHECK(frameNode, OnAttachToFrameNode);  // call OnAttachToFrameNodeMultiThread() by multi thread
8535     StylusDetectorMgr::GetInstance()->AddTextFieldFrameNode(frameNode, WeakClaim(this));
8536 
8537     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8538     CHECK_NULL_VOID(layoutProperty);
8539     layoutProperty->UpdateCopyOptions(CopyOptions::Local);
8540     auto pipeline = frameNode->GetContext();
8541     CHECK_NULL_VOID(pipeline);
8542     auto fontManager = pipeline->GetFontManager();
8543     if (fontManager) {
8544         auto host = GetHost();
8545         fontManager->AddFontNodeNG(host);
8546     }
8547     auto onTextSelectorChange = [weak = WeakClaim(this)]() {
8548         auto pattern = weak.Upgrade();
8549         CHECK_NULL_VOID(pattern);
8550         auto frameNode = pattern->GetHost();
8551         CHECK_NULL_VOID(frameNode);
8552         frameNode->OnAccessibilityEvent(AccessibilityEventType::TEXT_SELECTION_UPDATE);
8553     };
8554     selectController_->SetOnAccessibility(std::move(onTextSelectorChange));
8555 }
8556 
8557 bool TextFieldPattern::NeedPaintSelect()
8558 {
8559     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
8560     CHECK_NULL_RETURN(paintProperty, false);
8561     auto firstHandle = paintProperty->GetFirstHandleInfo();
8562     auto secondHandle = paintProperty->GetSecondHandleInfo();
8563     auto caretInfo = selectController_->GetCaretInfo();
8564     if (!IsSelected()) {
8565         if (!firstHandle.has_value() || !secondHandle.has_value()) {
8566             paintProperty->UpdateFirstHandleInfo(caretInfo);
8567             paintProperty->UpdateSecondHandleInfo(caretInfo);
8568             return false;
8569         }
8570 
8571         if (firstHandle->index != secondHandle->index || firstHandle->index != caretInfo.index) {
8572             paintProperty->UpdateFirstHandleInfo(caretInfo);
8573             paintProperty->UpdateSecondHandleInfo(caretInfo);
8574             return true;
8575         }
8576         return false;
8577     }
8578     auto needPaint = firstHandle != selectController_->GetFirstHandleInfo() ||
8579                      secondHandle != selectController_->GetSecondHandleInfo();
8580     paintProperty->UpdateFirstHandleInfo(selectController_->GetFirstHandleInfo());
8581     paintProperty->UpdateSecondHandleInfo(selectController_->GetSecondHandleInfo());
8582     return needPaint;
8583 }
8584 
8585 RefPtr<FocusHub> TextFieldPattern::GetFocusHub() const
8586 {
8587     auto host = GetHost();
8588     CHECK_NULL_RETURN(host, nullptr);
8589     auto focusHub = host->GetOrCreateFocusHub();
8590     return focusHub;
8591 }
8592 
8593 void TextFieldPattern::OnObscuredChanged(bool isObscured)
8594 {
8595     ResetObscureTickCountDown();
8596     obscuredChange_ = textObscured_ != isObscured;
8597     textObscured_ = isObscured;
8598     CloseSelectOverlay(false);
8599     StartTwinkling();
8600     if (obscuredChange_) {
8601         selectController_->UpdateCaretIndex(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
8602     }
8603     auto host = GetHost();
8604     CHECK_NULL_VOID(host);
8605     if (obscuredChange_) {
8606         auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
8607         CHECK_NULL_VOID(eventHub);
8608         eventHub->FireOnSecurityStateChanged(!isObscured);
8609     }
8610     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
8611 }
8612 
8613 void TextFieldPattern::CreateHandles()
8614 {
8615     if (IsDragging() || !HasFocus()) {
8616         return;
8617     }
8618     auto host = GetHost();
8619     CHECK_NULL_VOID(host);
8620     showSelect_ = true;
8621     if (selectOverlay_->IsUseTouchAtLast()) {
8622         SetIsSingleHandle(!IsSelected());
8623         ProcessOverlay({ .menuIsShow = false });
8624     }
8625     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8626 }
8627 
8628 void TextFieldPattern::NotifyOnEditChanged(bool isChanged)
8629 {
8630     auto host = GetHost();
8631     CHECK_NULL_VOID(host);
8632     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
8633     CHECK_NULL_VOID(eventHub);
8634     if (isChanged != isEdit_) {
8635         isEdit_ = isChanged;
8636         eventHub->FireOnEditChanged(isChanged);
8637     }
8638 }
8639 
8640 size_t TextFieldPattern::GetLineCount() const
8641 {
8642     return paragraph_ ? paragraph_->GetLineCount() : 0;
8643 }
8644 
8645 void TextFieldPattern::UpdateHandlesOffsetOnScroll(float offset)
8646 {
8647     if (SelectOverlayIsOn()) {
8648         selectController_->UpdateSecondHandleOffset();
8649         if (!selectOverlay_->IsSingleHandle()) {
8650             selectController_->UpdateFirstHandleOffset();
8651             selectController_->UpdateCaretOffset(TextAffinity::DOWNSTREAM, false);
8652             selectOverlay_->UpdateAllHandlesOffset();
8653         } else {
8654             selectController_->UpdateCaretOffset(IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
8655             selectOverlay_->UpdateSecondHandleOffset();
8656         }
8657     } else {
8658         selectController_->UpdateCaretOffset(IsTextArea() ? OffsetF(0.0f, offset) : OffsetF(offset, 0.0f));
8659     }
8660 }
8661 
8662 void TextFieldPattern::CloseHandleAndSelect()
8663 {
8664     CloseSelectOverlay(true);
8665     showSelect_ = false;
8666 }
8667 
8668 bool TextFieldPattern::IsShowUnit() const
8669 {
8670     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8671     CHECK_NULL_RETURN(layoutProperty, false);
8672     auto typeValue = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
8673     return layoutProperty->GetShowUnderlineValue(false) &&
8674            (typeValue == TextInputType::UNSPECIFIED || typeValue == TextInputType::TEXT) &&
8675            unitNode_ != nullptr;
8676 }
8677 
8678 bool TextFieldPattern::IsShowPasswordIcon() const
8679 {
8680     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8681     CHECK_NULL_RETURN(layoutProperty, false);
8682     auto textfieldTheme = GetTheme();
8683     CHECK_NULL_RETURN(textfieldTheme, false);
8684     bool isShowPasswordIcon = textfieldTheme->IsShowPasswordIcon();
8685     return layoutProperty->GetShowPasswordIconValue(isShowPasswordIcon) && IsInPasswordMode();
8686 }
8687 
8688 std::optional<bool> TextFieldPattern::IsShowPasswordText() const
8689 {
8690     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8691     CHECK_NULL_RETURN(layoutProperty, false);
8692     return layoutProperty->GetShowPasswordText();
8693 }
8694 
8695 bool TextFieldPattern::IsShowCancelButtonMode() const
8696 {
8697     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8698     CHECK_NULL_RETURN(layoutProperty, false);
8699     return !IsNormalInlineState() && !IsTextArea() && layoutProperty->GetIsShowCancelButton().value_or(false);
8700 }
8701 
8702 void TextFieldPattern::CheckPasswordAreaState()
8703 {
8704     auto showPasswordState = IsShowPasswordText();
8705     if (!showPasswordState.has_value()) {
8706         return;
8707     }
8708     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
8709     CHECK_NULL_VOID(passwordArea);
8710     if (!showPasswordState_.has_value() || showPasswordState_.value() != showPasswordState.value()) {
8711         passwordArea->SetObscured(!showPasswordState.value());
8712         showPasswordState_ = showPasswordState.value();
8713     }
8714 }
8715 
8716 void TextFieldPattern::AfterLayoutProcessCleanResponse(
8717     const RefPtr<CleanNodeResponseArea>& cleanNodeResponseArea)
8718 {
8719     CHECK_NULL_VOID(cleanNodeResponseArea);
8720     auto host = GetHost();
8721     CHECK_NULL_VOID(host);
8722     auto pipeline = host->GetContext();
8723     CHECK_NULL_VOID(pipeline);
8724     pipeline->AddAfterLayoutTask([weak = WeakClaim(Referenced::RawPtr(cleanNodeResponseArea))]() {
8725         auto cleanNodeResponseArea = weak.Upgrade();
8726         CHECK_NULL_VOID(cleanNodeResponseArea);
8727         cleanNodeResponseArea->UpdateCleanNode(cleanNodeResponseArea->IsShow());
8728     });
8729 }
8730 
8731 void TextFieldPattern::ProcessCancelButton()
8732 {
8733     if (IsShowCancelButtonMode()) {
8734         auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8735         if (cleanNodeResponseArea) {
8736             cleanNodeResponseArea->Refresh();
8737             if (cleanNodeResponseArea->IsShow()) {
8738                 AfterLayoutProcessCleanResponse(cleanNodeResponseArea);
8739             } else {
8740                 UpdateCancelNode();
8741             }
8742         } else {
8743             cleanNodeResponseArea_ = AceType::MakeRefPtr<CleanNodeResponseArea>(WeakClaim(this));
8744             cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8745             cleanNodeResponseArea->InitResponseArea();
8746             UpdateCancelNode();
8747             AfterLayoutProcessCleanResponse(cleanNodeResponseArea);
8748         }
8749     } else {
8750         if (cleanNodeResponseArea_) {
8751             cleanNodeResponseArea_->ClearArea();
8752             cleanNodeResponseArea_.Reset();
8753         }
8754     }
8755 }
8756 
8757 void TextFieldPattern::ProcessResponseArea()
8758 {
8759     ProcessCancelButton();
8760     if (IsInPasswordMode()) {
8761         auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
8762         if (passwordArea) {
8763             if (IsShowPasswordIcon()) {
8764                 passwordArea->Refresh();
8765             } else {
8766                 passwordArea->ClearArea();
8767             }
8768             CheckPasswordAreaState();
8769             return;
8770         }
8771         // responseArea_ may not be a password area.
8772         if (responseArea_) {
8773             responseArea_->ClearArea();
8774         }
8775         responseArea_ = AceType::MakeRefPtr<PasswordResponseArea>(WeakClaim(this), GetTextObscured());
8776         if (IsShowPasswordIcon()) {
8777             responseArea_->InitResponseArea();
8778         } else {
8779             responseArea_->ClearArea();
8780         }
8781         CheckPasswordAreaState();
8782         return;
8783     }
8784 
8785     if (IsUnderlineMode()) {
8786         if (responseArea_) {
8787             responseArea_->ClearArea();
8788         }
8789         responseArea_ = AceType::MakeRefPtr<UnitResponseArea>(WeakClaim(this), unitNode_);
8790         responseArea_->InitResponseArea();
8791         auto host = GetHost();
8792         CHECK_NULL_VOID(host);
8793         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
8794         return;
8795     }
8796 
8797     if (responseArea_) {
8798         responseArea_->ClearArea();
8799     }
8800 }
8801 
8802 void TextFieldPattern::AdjustTextRectByCleanNode(RectF& textRect)
8803 {
8804     auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8805     CHECK_NULL_VOID(cleanNodeResponseArea);
8806     auto host = GetHost();
8807     CHECK_NULL_VOID(host);
8808     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8809     CHECK_NULL_VOID(layoutProperty);
8810     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
8811     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
8812     if (isRTL && (cleanNodeStyle == CleanNodeStyle::CONSTANT ||
8813                      (cleanNodeStyle == CleanNodeStyle::INPUT && !contentController_->IsEmpty()))) {
8814         auto textFieldTheme = GetTheme();
8815         CHECK_NULL_VOID(textFieldTheme);
8816         auto themePadding = textFieldTheme->GetPadding();
8817         auto rightOffset = static_cast<float>(themePadding.Left().ConvertToPx());
8818         textRect.SetLeft(textRect.GetX() + cleanNodeResponseArea->GetIconSize() + rightOffset);
8819     }
8820 }
8821 
8822 void TextFieldPattern::UpdateCancelNode()
8823 {
8824     auto cleanNodeResponseArea = DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
8825     CHECK_NULL_VOID(cleanNodeResponseArea);
8826     auto host = GetHost();
8827     CHECK_NULL_VOID(host);
8828     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
8829     CHECK_NULL_VOID(layoutProperty);
8830     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
8831     if (cleanNodeStyle == CleanNodeStyle::CONSTANT ||
8832         (cleanNodeStyle == CleanNodeStyle::INPUT && !contentController_->IsEmpty())) {
8833         if (!cleanNodeResponseArea->IsShow() || cleanNodeResponseArea->CheckUpdateCleanNode()) {
8834             cleanNodeResponseArea->UpdateCleanNode(true);
8835         }
8836     } else if (cleanNodeStyle == CleanNodeStyle::INVISIBLE ||
8837                (cleanNodeStyle == CleanNodeStyle::INPUT && contentController_->IsEmpty())) {
8838         if (cleanNodeResponseArea->IsShow()) {
8839             cleanNodeResponseArea->UpdateCleanNode(false);
8840         }
8841     }
8842 }
8843 
8844 bool TextFieldPattern::HasInputOperation()
8845 {
8846     return !deleteBackwardOperations_.empty() || !deleteForwardOperations_.empty() || !insertCommands_.empty();
8847 }
8848 
8849 void TextFieldPattern::FocusForwardStopTwinkling()
8850 {
8851     auto host = GetHost();
8852     CHECK_NULL_VOID(host);
8853     UpdateSelection(selectController_->GetCaretIndex());
8854     StopTwinkling();
8855     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
8856 }
8857 
8858 bool TextFieldPattern::UpdateFocusForward()
8859 {
8860     if (focusIndex_ == FocuseIndex::TEXT && HasFocus()) {
8861         FocusForwardStopTwinkling();
8862         if (!CancelNodeIsShow()) {
8863             if (responseArea_ == nullptr || (!IsShowUnit() && !IsShowPasswordIcon())) {
8864                 return false;
8865             }
8866             focusIndex_ = FocuseIndex::UNIT;
8867             PaintResponseAreaRect();
8868             return true;
8869         }
8870         focusIndex_ = FocuseIndex::CANCEL;
8871         PaintCancelRect();
8872         return true;
8873     }
8874     if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
8875         FocusForwardStopTwinkling();
8876         if (responseArea_ == nullptr || (!IsShowUnit() && !IsShowPasswordIcon())) {
8877             return false;
8878         }
8879         focusIndex_ = FocuseIndex::UNIT;
8880         PaintResponseAreaRect();
8881         return true;
8882     }
8883     return false;
8884 }
8885 
8886 bool TextFieldPattern::UpdateFocusBackward()
8887 {
8888     if (focusIndex_ == FocuseIndex::CANCEL && HasFocus()) {
8889         focusIndex_ = FocuseIndex::TEXT;
8890         PaintTextRect();
8891         StartTwinkling();
8892         return true;
8893     } else if (focusIndex_ == FocuseIndex::UNIT && HasFocus()) {
8894         if (!CancelNodeIsShow()) {
8895             focusIndex_ = FocuseIndex::TEXT;
8896             PaintTextRect();
8897             StartTwinkling();
8898             return true;
8899         }
8900         focusIndex_ = FocuseIndex::CANCEL;
8901         PaintCancelRect();
8902         return true;
8903     }
8904     return false;
8905 }
8906 
8907 bool TextFieldPattern::HandleSpaceEvent()
8908 {
8909     if (focusIndex_ == FocuseIndex::CANCEL) {
8910         CleanNodeResponseKeyEvent();
8911         return true;
8912     } else if (focusIndex_ == FocuseIndex::UNIT) {
8913         if (IsShowPasswordIcon()) {
8914             PasswordResponseKeyEvent();
8915         }
8916         if (IsShowUnit()) {
8917             UnitResponseKeyEvent();
8918         }
8919         return true;
8920     }
8921     return false;
8922 }
8923 
8924 void TextFieldPattern::PaintTextRect()
8925 {
8926     RoundRect focusRect;
8927     auto host = GetHost();
8928     CHECK_NULL_VOID(host);
8929     auto focusHub = host->GetFocusHub();
8930     CHECK_NULL_VOID(focusHub);
8931     focusHub->PaintInnerFocusState(focusRect);
8932 }
8933 
8934 void TextFieldPattern::GetIconPaintRect(const RefPtr<TextInputResponseArea>& responseArea, RoundRect& paintRect)
8935 {
8936     auto stackNode = responseArea->GetFrameNode();
8937     CHECK_NULL_VOID(stackNode);
8938     auto stackRect = stackNode->GetGeometryNode()->GetFrameRect();
8939     auto imageNode = stackNode->GetFirstChild();
8940     CHECK_NULL_VOID(imageNode);
8941     auto imageFrameNode = AceType::DynamicCast<FrameNode>(imageNode);
8942     CHECK_NULL_VOID(imageFrameNode);
8943     auto imageRect = imageFrameNode->GetGeometryNode()->GetFrameRect();
8944     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
8945     CHECK_NULL_VOID(layoutProperty);
8946     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
8947     RectF rect;
8948     if (isRTL) {
8949         rect = RectF(stackRect.GetX() + stackRect.Width() - imageRect.Width(),
8950             stackRect.GetY(), imageRect.Width(), imageRect.Height());
8951     } else {
8952         rect = RectF(stackRect.GetX(), stackRect.GetY(), imageRect.Width(), imageRect.Height());
8953     }
8954     paintRect.SetRect(rect);
8955 }
8956 
8957 void TextFieldPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
8958 {
8959     auto host = GetHost();
8960     CHECK_NULL_VOID(host);
8961     if (focusIndex_ == FocuseIndex::CANCEL) {
8962         CHECK_NULL_VOID(cleanNodeResponseArea_);
8963         GetIconPaintRect(cleanNodeResponseArea_, paintRect);
8964         if (host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
8965             cleanNodeResponseArea_->CreateIconRect(paintRect, true);
8966             float cornerRadius = paintRect.GetRect().Width() / 2;
8967             paintRect.SetCornerRadius(cornerRadius);
8968         }
8969     } else if (focusIndex_ == FocuseIndex::UNIT) {
8970         if (IsShowPasswordIcon()) {
8971             CHECK_NULL_VOID(responseArea_);
8972             GetIconPaintRect(responseArea_, paintRect);
8973             if (host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
8974                 responseArea_->CreateIconRect(paintRect, true);
8975             }
8976             float cornerRadius = paintRect.GetRect().Width() / 2;
8977             paintRect.SetCornerRadius(cornerRadius);
8978         }
8979         if (IsShowUnit()) {
8980             CHECK_NULL_VOID(responseArea_);
8981             auto unitResponseArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
8982             CHECK_NULL_VOID(unitResponseArea);
8983             auto unitNode = unitResponseArea->GetFrameNode();
8984             CHECK_NULL_VOID(unitNode);
8985             auto unitRect = unitNode->GetGeometryNode()->GetFrameRect();
8986             paintRect.SetRect(unitRect);
8987         }
8988     } else {
8989         GetTextInputFocusPaintRect(paintRect);
8990     }
8991 }
8992 
8993 void TextFieldPattern::GetTextInputFocusPaintRect(RoundRect& paintRect)
8994 {
8995     auto textfieldTheme = GetTheme();
8996     CHECK_NULL_VOID(textfieldTheme);
8997     auto isNeedFocusBox = textfieldTheme->NeedFocusBox();
8998     if (!isNeedFocusBox) {
8999         return;
9000     }
9001     auto host = GetHost();
9002     CHECK_NULL_VOID(host);
9003     auto geometryNode = host->GetGeometryNode();
9004     CHECK_NULL_VOID(geometryNode);
9005     auto textInputSize = geometryNode->GetFrameSize();
9006     auto focusPaintPadding = textfieldTheme->GetFocusPadding().ConvertToPx();
9007     float width = textInputSize.Width() + 2 * focusPaintPadding;
9008     float height = textInputSize.Height() + 2 * focusPaintPadding;
9009     paintRect.SetRect({ -focusPaintPadding, -focusPaintPadding, width, height });
9010     auto renderContext = host->GetRenderContext();
9011     CHECK_NULL_VOID(renderContext);
9012     auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
9013     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS,
9014         static_cast<float>(radius.radiusTopLeft->ConvertToPx() + focusPaintPadding),
9015         static_cast<float>(radius.radiusTopLeft->ConvertToPx() + focusPaintPadding));
9016     paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS,
9017         static_cast<float>(radius.radiusTopRight->ConvertToPx() + focusPaintPadding),
9018         static_cast<float>(radius.radiusTopRight->ConvertToPx() + focusPaintPadding));
9019     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS,
9020         static_cast<float>(radius.radiusBottomLeft->ConvertToPx() + focusPaintPadding),
9021         static_cast<float>(radius.radiusBottomLeft->ConvertToPx() + focusPaintPadding));
9022     paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS,
9023         static_cast<float>(radius.radiusBottomRight->ConvertToPx() + focusPaintPadding),
9024         static_cast<float>(radius.radiusBottomRight->ConvertToPx() + focusPaintPadding));
9025 }
9026 
9027 void TextFieldPattern::PaintCancelRect()
9028 {
9029     RoundRect focusRect;
9030     GetInnerFocusPaintRect(focusRect);
9031     auto host = GetHost();
9032     CHECK_NULL_VOID(host);
9033     auto focusHub = host->GetFocusHub();
9034     CHECK_NULL_VOID(focusHub);
9035     focusHub->PaintInnerFocusState(focusRect);
9036 }
9037 
9038 void TextFieldPattern::PaintResponseAreaRect()
9039 {
9040     if (IsShowPasswordIcon()) {
9041         PaintPasswordRect();
9042     }
9043     if (IsShowUnit()) {
9044         PaintUnitRect();
9045     }
9046 }
9047 
9048 void TextFieldPattern::PaintPasswordRect()
9049 {
9050     RoundRect focusRect;
9051     GetInnerFocusPaintRect(focusRect);
9052     auto host = GetHost();
9053     CHECK_NULL_VOID(host);
9054     auto focusHub = host->GetFocusHub();
9055     CHECK_NULL_VOID(focusHub);
9056     focusHub->PaintInnerFocusState(focusRect);
9057 }
9058 
9059 void TextFieldPattern::PaintUnitRect()
9060 {
9061     RoundRect focusRect;
9062     GetInnerFocusPaintRect(focusRect);
9063     auto host = GetHost();
9064     CHECK_NULL_VOID(host);
9065     auto focusHub = host->GetFocusHub();
9066     CHECK_NULL_VOID(focusHub);
9067     focusHub->PaintInnerFocusState(focusRect);
9068 }
9069 
9070 void TextFieldPattern::CleanNodeResponseKeyEvent()
9071 {
9072     CHECK_NULL_VOID(!IsDragging());
9073     auto host = GetHost();
9074     CHECK_NULL_VOID(host);
9075     ClearTextContent();
9076     CloseSelectOverlay();
9077     SetFloatingCursorVisible(false);
9078     StartTwinkling();
9079     UpdateCaretInfoToController();
9080     if (!HasFocus()) {
9081         auto focusHub = host->GetOrCreateFocusHub();
9082         TextFieldRequestFocus(RequestFocusReason::CLEAN_NODE);
9083     }
9084     host->MarkModifyDone();
9085     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
9086 
9087     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9088     CHECK_NULL_VOID(layoutProperty);
9089     auto cleanNodeStyle = layoutProperty->GetCleanNodeStyle().value_or(CleanNodeStyle::INPUT);
9090     if (cleanNodeStyle == CleanNodeStyle::INPUT) {
9091         focusIndex_ = FocuseIndex::TEXT;
9092     }
9093 }
9094 
9095 void TextFieldPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
9096 {
9097     if (selectOverlay_) {
9098         selectOverlay_->UpdateMenuOnWindowSizeChanged(type);
9099     }
9100     if (type != WindowSizeChangeReason::ROTATION) {
9101         return;
9102     }
9103     if (SelectOverlayIsOn()) {
9104         selectController_->CalculateHandleOffset();
9105         selectOverlay_->ProcessOverlayOnAreaChanged({ .menuIsShow = false});
9106     }
9107     auto host = GetHost();
9108     CHECK_NULL_VOID(host);
9109     auto context = host->GetContextRefPtr();
9110     CHECK_NULL_VOID(context);
9111     auto taskExecutor = context->GetTaskExecutor();
9112     CHECK_NULL_VOID(taskExecutor);
9113     auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
9114     CHECK_NULL_VOID(textFieldManager);
9115     textFieldManager->ResetOptionalClickPosition();
9116     lastCaretPos_ = std::nullopt;
9117     taskExecutor->PostTask(
9118         [weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
9119             auto textField = weak.Upgrade();
9120             CHECK_NULL_VOID(textField);
9121             auto host = textField->GetHost();
9122             CHECK_NULL_VOID(host);
9123             auto nodeId = host->GetId();
9124             textField->parentGlobalOffset_ = textField->GetPaintRectGlobalOffset();
9125             textField->UpdateTextFieldManager(Offset(textField->parentGlobalOffset_.GetX(),
9126                 textField->parentGlobalOffset_.GetY()), textField->frameRect_.Height());
9127             if (textField->HasFocus()) {
9128                 textField->UpdateCaretInfoToController(true);
9129                 TAG_LOGI(ACE_TEXT_FIELD, "%{public}d OnWindowSizeChanged change parentGlobalOffset to: %{public}s",
9130                     nodeId, textField->parentGlobalOffset_.ToString().c_str());
9131                 auto textFieldManager = manager.Upgrade();
9132                 CHECK_NULL_VOID(textFieldManager);
9133                 auto container = Container::Current();
9134                 CHECK_NULL_VOID(container);
9135                 auto displayInfo = container->GetDisplayInfo();
9136                 if (displayInfo) {
9137                     auto dmRotation = static_cast<int32_t>(displayInfo->GetRotation());
9138                     textFieldManager->SetFocusFieldOrientation(dmRotation);
9139                 }
9140             }
9141         },
9142         TaskExecutor::TaskType::UI, "ArkUITextFieldOnWindowSizeChangedRotation");
9143 }
9144 
9145 void TextFieldPattern::PasswordResponseKeyEvent()
9146 {
9147     auto passwordArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
9148     CHECK_NULL_VOID(passwordArea);
9149     passwordArea->OnPasswordIconClicked();
9150 }
9151 
9152 void TextFieldPattern::UnitResponseKeyEvent()
9153 {
9154     auto unitArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
9155     CHECK_NULL_VOID(unitArea);
9156     auto frameNode = unitArea->GetFrameNode();
9157     CHECK_NULL_VOID(frameNode);
9158     if (frameNode->GetTag() == V2::SELECT_ETS_TAG) {
9159         auto selectPattern = frameNode->GetPattern<SelectPattern>();
9160         CHECK_NULL_VOID(selectPattern);
9161         selectPattern->ShowSelectMenu();
9162     }
9163 }
9164 
9165 void TextFieldPattern::ScrollToSafeArea() const
9166 {
9167     auto host = GetHost();
9168     CHECK_NULL_VOID(host);
9169     auto pipeline = host->GetContext();
9170     CHECK_NULL_VOID(pipeline);
9171     if (pipeline->UsingCaretAvoidMode()) {
9172         // using TriggerAvoidOnCaretChange instead in CaretAvoidMode
9173         return;
9174     }
9175     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
9176     CHECK_NULL_VOID(textFieldManager);
9177     textFieldManager->ScrollTextFieldToSafeArea();
9178 }
9179 
9180 void TextFieldPattern::TriggerAvoidOnCaretChange()
9181 {
9182     CHECK_NULL_VOID(HasFocus());
9183     auto host = GetHost();
9184     CHECK_NULL_VOID(host);
9185     auto pipeline = host->GetContext();
9186     CHECK_NULL_VOID(pipeline);
9187     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
9188     CHECK_NULL_VOID(textFieldManager);
9189     CHECK_NULL_VOID(pipeline->UsingCaretAvoidMode());
9190     auto safeAreaManager = pipeline->GetSafeAreaManager();
9191     if (!safeAreaManager || NearEqual(safeAreaManager->GetKeyboardInset().Length(), 0)) {
9192         return;
9193     }
9194     if (selectOverlay_) {
9195         selectOverlay_->AddAvoidKeyboardCallback(isCustomKeyboardAttached_);
9196     }
9197     textFieldManager->TriggerAvoidOnCaretChange();
9198     auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
9199     SetLastCaretPos(caretPos);
9200 }
9201 
9202 void TextFieldPattern::CheckTextAlignByDirection(TextAlign& textAlign, TextDirection direction)
9203 {
9204     if (direction == TextDirection::RTL) {
9205         if (textAlign == TextAlign::START) {
9206             textAlign = TextAlign::END;
9207         } else if (textAlign == TextAlign::END) {
9208             textAlign = TextAlign::START;
9209         }
9210     }
9211 }
9212 
9213 void TextFieldPattern::RequestKeyboardAfterLongPress()
9214 {
9215 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
9216     if (isLongPress_ && HasFocus() && RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::LONG_PRESS)) {
9217         NotifyOnEditChanged(true);
9218         if (!isCustomKeyboardAttached_ || keyboardAvoidance_) {
9219             selectOverlay_->AddAvoidKeyboardCallback(isCustomKeyboardAttached_);
9220         }
9221     }
9222     isLongPress_ = false;
9223 #endif
9224 }
9225 
9226 void TextFieldPattern::GetCaretMetrics(CaretMetricsF& caretCaretMetric)
9227 {
9228     OffsetF offset = selectController_->GetCaretRect().GetOffset();
9229     float height = selectController_->GetCaretRect().Height();
9230     float width = selectController_->GetCaretRect().Width();
9231     auto host = GetHost();
9232     CHECK_NULL_VOID(host);
9233     auto textPaintOffset = host->GetPaintRectOffset(false, true);
9234     caretCaretMetric.offset = offset + textPaintOffset + OffsetF(width / 2.0f, 0.0f);
9235     caretCaretMetric.height = height;
9236 }
9237 
9238 void TextFieldPattern::ScrollPage(bool reverse, bool smooth, AccessibilityScrollType scrollType)
9239 {
9240     auto border = GetBorderWidthProperty();
9241     float maxFrameHeight =
9242         frameRect_.Height() - GetPaddingTop() - GetPaddingBottom() - GetBorderTop(border) - GetBorderBottom(border);
9243     float distance = reverse ? maxFrameHeight : -maxFrameHeight;
9244     if (scrollType == AccessibilityScrollType::SCROLL_HALF) {
9245         distance = distance / 2.f;
9246     }
9247     OnScrollCallback(distance, SCROLL_FROM_JUMP);
9248 }
9249 
9250 // correct after OnModifyDone
9251 bool TextFieldPattern::IsUnderlineMode() const
9252 {
9253     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9254     CHECK_NULL_RETURN(layoutProperty, false);
9255     return layoutProperty->GetShowUnderlineValue(false) && IsUnspecifiedOrTextType() && !IsInlineMode();
9256 }
9257 
9258 // correct after OnModifyDone
9259 bool TextFieldPattern::IsInlineMode() const
9260 {
9261     return HasFocus() && IsNormalInlineState();
9262 }
9263 
9264 bool TextFieldPattern::IsShowError()
9265 {
9266     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9267     CHECK_NULL_RETURN(layoutProperty, false);
9268     auto errorText = layoutProperty->GetErrorTextValue(u"");
9269     return layoutProperty->GetShowErrorTextValue(false) && !errorText.empty() && !IsNormalInlineState();
9270 }
9271 
9272 bool TextFieldPattern::IsShowCount()
9273 {
9274     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9275     CHECK_NULL_RETURN(layoutProperty, false);
9276     return layoutProperty->GetShowCounterValue(false) && !IsNormalInlineState() && !IsInPasswordMode() &&
9277            layoutProperty->HasMaxLength();
9278 }
9279 
9280 void TextFieldPattern::ResetContextAttr()
9281 {
9282     auto host = GetHost();
9283     CHECK_NULL_VOID(host);
9284     auto renderContext = host->GetRenderContext();
9285     CHECK_NULL_VOID(renderContext);
9286     renderContext->ResetBorder();
9287     BorderWidthProperty borderWidth;
9288     borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
9289     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9290     CHECK_NULL_VOID(layoutProperty);
9291     layoutProperty->UpdateBorderWidth(borderWidth);
9292 }
9293 
9294 void TextFieldPattern::SetThemeBorderAttr()
9295 {
9296     auto host = GetHost();
9297     CHECK_NULL_VOID(host);
9298     auto renderContext = host->GetRenderContext();
9299     CHECK_NULL_VOID(renderContext);
9300     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9301     CHECK_NULL_VOID(layoutProperty);
9302     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9303     CHECK_NULL_VOID(paintProperty);
9304     auto theme = GetTheme();
9305     CHECK_NULL_VOID(theme);
9306 
9307     paintProperty->ResetInnerBorderColor();
9308     paintProperty->ResetInnerBorderWidth();
9309     if (!paintProperty->HasBorderColorFlagByUser()) {
9310         BorderColorProperty borderColor;
9311         borderColor.SetColor(theme->GetTextInputColor());
9312         renderContext->UpdateBorderColor(borderColor);
9313     } else {
9314         renderContext->UpdateBorderColor(paintProperty->GetBorderColorFlagByUserValue());
9315     }
9316 
9317     if (!paintProperty->HasBorderRadiusFlagByUser()) {
9318         auto radius = theme->GetBorderRadius();
9319         BorderRadiusProperty borderRadius(radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX());
9320         auto ultimatelyRadius = IsUnderlineMode() ?  ZERO_BORDER_RADIUS_PROPERTY : borderRadius;
9321         renderContext->UpdateBorderRadius(ultimatelyRadius);
9322     } else {
9323         renderContext->UpdateBorderRadius(paintProperty->GetBorderRadiusFlagByUserValue());
9324     }
9325 
9326     if (!paintProperty->HasBorderWidthFlagByUser()) {
9327         BorderWidthProperty borderWidth;
9328         if (IsTextArea() || IsUnderlineMode()) {
9329             borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
9330         } else {
9331             borderWidth.SetBorderWidth(theme->GetTextInputWidth());
9332         }
9333         renderContext->UpdateBorderWidth(borderWidth);
9334         layoutProperty->UpdateBorderWidth(borderWidth);
9335     } else {
9336         renderContext->UpdateBorderWidth(paintProperty->GetBorderWidthFlagByUserValue());
9337         layoutProperty->UpdateBorderWidth(paintProperty->GetBorderWidthFlagByUserValue());
9338     }
9339 }
9340 
9341 PaddingProperty TextFieldPattern::GetPaddingByUserValue()
9342 {
9343     PaddingProperty padding;
9344     auto theme = GetTheme();
9345     CHECK_NULL_RETURN(theme, padding);
9346     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9347     CHECK_NULL_RETURN(paintProperty, padding);
9348     padding = paintProperty->GetPaddingByUserValue();
9349     auto themePadding = IsUnderlineMode() ? theme->GetUnderlinePadding() : theme->GetPadding();
9350     if (!padding.top.has_value()) {
9351         padding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
9352     }
9353     if (!padding.bottom.has_value()) {
9354         padding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
9355     }
9356     if (!padding.left.has_value()) {
9357         padding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
9358     }
9359     if (!padding.right.has_value()) {
9360         padding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
9361     }
9362     return padding;
9363 }
9364 
9365 void TextFieldPattern::SetThemeAttr()
9366 {
9367     auto host = GetHost();
9368     CHECK_NULL_VOID(host);
9369     auto renderContext = host->GetRenderContext();
9370     CHECK_NULL_VOID(renderContext);
9371     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
9372     CHECK_NULL_VOID(layoutProperty);
9373     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9374     CHECK_NULL_VOID(paintProperty);
9375     auto theme = GetTheme();
9376     CHECK_NULL_VOID(theme);
9377     SetThemeBorderAttr();
9378     if (!paintProperty->HasBackgroundColor()) {
9379         auto backgroundColor = isFocusBGColorSet_ ? theme->GetFocusBgColor() : theme->GetBgColor();
9380         backgroundColor = IsUnderlineMode() ? Color::TRANSPARENT : backgroundColor;
9381         renderContext->UpdateBackgroundColor(backgroundColor);
9382     } else {
9383         renderContext->UpdateBackgroundColor(paintProperty->GetBackgroundColorValue());
9384     }
9385 
9386     if (!paintProperty->HasMarginByUser()) {
9387         MarginProperty margin;
9388         margin.SetEdges(CalcLength(0.0_vp));
9389         layoutProperty->UpdateMargin(margin);
9390     } else {
9391         layoutProperty->UpdateMargin(paintProperty->GetMarginByUserValue());
9392     }
9393 
9394     if (!paintProperty->HasPaddingByUser()) {
9395         auto themePadding = IsUnderlineMode() ? GetUnderlinePadding(theme, false, false) : theme->GetPadding();
9396         PaddingProperty padding;
9397         padding.top = CalcLength(CalcLength(themePadding.Top()).GetDimension());
9398         padding.bottom = CalcLength(CalcLength(themePadding.Bottom()).GetDimension());
9399         padding.left = CalcLength(CalcLength(themePadding.Left()).GetDimension());
9400         padding.right = CalcLength(CalcLength(themePadding.Right()).GetDimension());
9401         layoutProperty->UpdatePadding(padding);
9402     } else {
9403         layoutProperty->UpdatePadding(GetPaddingByUserValue());
9404     }
9405 
9406     if (!paintProperty->HasTextColorFlagByUser()) {
9407         auto textColor = isFocusTextColorSet_ ? theme->GetFocusTextColor() : theme->GetTextColor();
9408         layoutProperty->UpdateTextColor(textColor);
9409     } else {
9410         layoutProperty->UpdateTextColor(paintProperty->GetTextColorFlagByUserValue());
9411     }
9412     inlineFocusState_ = false;
9413 }
9414 
9415 const Dimension& TextFieldPattern::GetAvoidSoftKeyboardOffset() const
9416 {
9417     auto textfieldTheme = GetTheme();
9418     if (!textfieldTheme) {
9419         return TextBase::GetAvoidSoftKeyboardOffset();
9420     }
9421     return textfieldTheme->GetAvoidKeyboardOffset();
9422 }
9423 
9424 Offset TextFieldPattern::ConvertGlobalToLocalOffset(const Offset& globalOffset)
9425 {
9426     parentGlobalOffset_ = GetPaintRectGlobalOffset();
9427     auto localOffset = globalOffset - Offset(parentGlobalOffset_.GetX(), parentGlobalOffset_.GetY());
9428     if (selectOverlay_->HasRenderTransform()) {
9429         auto localOffsetF = OffsetF(globalOffset.GetX(), globalOffset.GetY());
9430         selectOverlay_->RevertLocalPointWithTransform(localOffsetF);
9431         localOffset.SetX(localOffsetF.GetX());
9432         localOffset.SetY(localOffsetF.GetY());
9433     }
9434     return localOffset;
9435 }
9436 
9437 int32_t TextFieldPattern::SetPreviewText(const std::u16string &previewValue, const PreviewRange range)
9438 {
9439     PreviewTextInfo info = {
9440         .text = previewValue,
9441         .range = range,
9442         .isIme = true
9443     };
9444     auto host = GetHost();
9445     CHECK_NULL_RETURN(host, PREVIEW_NULL_POINTER);
9446     inputOperations_.emplace(InputOperation::SET_PREVIEW_TEXT);
9447     previewTextOperation_.emplace(info);
9448     CloseSelectOverlay(true);
9449     ScrollToSafeArea();
9450     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9451     return PREVIEW_NO_ERROR;
9452 }
9453 
9454 int32_t TextFieldPattern::SetPreviewText(const std::string &previewValue, const PreviewRange range)
9455 {
9456     return SetPreviewText(UtfUtils::Str8DebugToStr16(previewValue), range);
9457 }
9458 
9459 void TextFieldPattern::SetPreviewTextOperation(PreviewTextInfo info)
9460 {
9461     auto host = GetHost();
9462     CHECK_NULL_VOID(host);
9463     FREE_NODE_CHECK(host, SetPreviewTextOperation, info);  // call SetPreviewTextOperationMultiThread() by multi thread
9464     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9465     CHECK_NULL_VOID(layoutProperty);
9466     if (!hasPreviewText_) {
9467         auto fullStr = GetTextUtf16Value();
9468         if (IsSelected()) {
9469             uint32_t startIndex = static_cast<uint32_t>(selectController_->GetStartIndex());
9470             uint32_t endIndex = static_cast<uint32_t>(selectController_->GetEndIndex());
9471             if (startIndex < fullStr.length() && endIndex <= fullStr.length()) {
9472                 fullStr.erase(startIndex, endIndex - startIndex);
9473             }
9474         }
9475         bodyTextInPreivewing_ = fullStr;
9476     }
9477     auto rangeStart = info.range.start;
9478     auto rangeEnd = info.range.end;
9479     auto start = GetPreviewTextStart();
9480     auto end = GetPreviewTextEnd();
9481     if (IsSelected()) {
9482         start = selectController_->GetStartIndex();
9483         end = selectController_->GetEndIndex();
9484     } else {
9485         start = (rangeStart == PREVIEW_TEXT_RANGE_DEFAULT) ? start : rangeStart;
9486         end = (rangeEnd == PREVIEW_TEXT_RANGE_DEFAULT) ? end : rangeEnd;
9487     }
9488 
9489     ChangeValueInfo changeValueInfo;
9490     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9491     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
9492     changeValueInfo.oldContent = GetBodyTextValue();
9493     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
9494     changeValueInfo.rangeAfter = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
9495     bool hasInsertValue = false;
9496     auto originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
9497     hasInsertValue = contentController_->ReplaceSelectedValue(start, end, info.text);
9498     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) -
9499         originLength);
9500 
9501     int32_t delta =
9502             static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - originLength - (end - start);
9503     int32_t newCaretPosition = std::max(end, GetPreviewTextEnd()) + delta;
9504     newCaretPosition = std::clamp(newCaretPosition, 0,
9505         static_cast<int32_t>(contentController_->GetTextUtf16Value().length()));
9506     selectController_->UpdateCaretIndex(start + caretMoveLength);
9507 
9508     UpdatePreviewIndex(start, newCaretPosition);
9509     hasPreviewText_ = true;
9510     changeValueInfo.value = GetBodyTextValue();
9511     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9512     changeValueInfo.previewText.value = GetPreviewTextValue();
9513     FireOnWillChange(changeValueInfo);
9514     if (HasFocus()) {
9515         cursorVisible_ = true;
9516         StartTwinkling();
9517     } else {
9518         cursorVisible_ = false;
9519         StopTwinkling();
9520     }
9521 }
9522 
9523 void TextFieldPattern::FinishTextPreview()
9524 {
9525     inputOperations_.emplace(InputOperation::SET_PREVIEW_FINISH);
9526     auto host = GetHost();
9527     CHECK_NULL_VOID(host);
9528     ScrollToSafeArea();
9529     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9530 }
9531 
9532 void TextFieldPattern::FinishTextPreviewOperation(bool triggerOnWillChange)
9533 {
9534     auto host = GetHost();
9535     FREE_NODE_CHECK(host, FinishTextPreviewOperation,
9536         triggerOnWillChange);  // call FinishTextPreviewOperationMultiThread() by multi thread
9537     if (!hasPreviewText_) {
9538         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "input state now is not at previewing text");
9539         return;
9540     }
9541     CHECK_NULL_VOID(host);
9542     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
9543     CHECK_NULL_VOID(layoutProperty);
9544     if (layoutProperty->HasMaxLength()) {
9545         int32_t len = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
9546         showCountBorderStyle_ = len > static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
9547         HandleCountStyle();
9548     }
9549 
9550     ChangeValueInfo changeValueInfo;
9551     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9552     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
9553     changeValueInfo.oldContent = GetBodyTextValue();
9554     changeValueInfo.rangeBefore = TextRange { GetPreviewTextStart(), GetPreviewTextStart() };
9555     auto start = GetPreviewTextStart();
9556     auto end = GetPreviewTextEnd();
9557     auto previewValue = GetPreviewTextValue();
9558     hasPreviewText_ = false;
9559     auto originLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) - (end - start);
9560     contentController_->ReplaceSelectedValue(start, end, previewValue);
9561     int32_t caretMoveLength = abs(static_cast<int32_t>(contentController_->GetTextUtf16Value().length()) -
9562         originLength);
9563     selectController_->UpdateCaretIndex(start + caretMoveLength);
9564     UpdateEditingValueToRecord();
9565     changeValueInfo.rangeAfter =
9566         TextRange { changeValueInfo.oldPreviewText.offset, selectController_->GetCaretIndex() };
9567     changeValueInfo.value = GetBodyTextValue();
9568     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
9569     changeValueInfo.previewText.value = GetPreviewTextValue();
9570     bool isWillChange = true;
9571     if (triggerOnWillChange) {
9572         isWillChange = FireOnWillChange(changeValueInfo);
9573     }
9574     if (!isWillChange) {
9575         contentController_->SetTextValueOnly(changeValueInfo.oldContent);
9576         selectController_->UpdateHandleIndex(start, start);
9577         return;
9578     }
9579     if (HasFocus()) {
9580         cursorVisible_ = true;
9581         StartTwinkling();
9582     } else {
9583         cursorVisible_ = false;
9584         StopTwinkling();
9585     }
9586     bodyTextInPreivewing_ = u"";
9587     previewTextStart_ = PREVIEW_TEXT_RANGE_DEFAULT;
9588     previewTextEnd_ = PREVIEW_TEXT_RANGE_DEFAULT;
9589     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
9590 }
9591 
9592 std::vector<RectF> TextFieldPattern::GetPreviewTextRects() const
9593 {
9594     if (!GetIsPreviewText()) {
9595         return {};
9596     }
9597     std::vector<RectF> boxes;
9598     std::vector<RectF> previewTextRects;
9599     CHECK_NULL_RETURN(paragraph_, boxes);
9600     paragraph_->GetRectsForRange(GetPreviewTextStart(), GetPreviewTextEnd(), boxes);
9601     if (boxes.empty()) {
9602         return {};
9603     }
9604     RectF linerRect(boxes.front().GetOffset(), SizeF(0, boxes.front().GetSize().Height()));
9605     float checkedTop = boxes.front().Top();
9606 
9607     for (const auto& drawRect : boxes) {
9608         if (drawRect.Top() == checkedTop) {
9609             linerRect += SizeF(drawRect.GetSize().Width(), 0);
9610         } else {
9611             previewTextRects.emplace_back(linerRect);
9612             checkedTop = drawRect.Top();
9613             linerRect = drawRect;
9614         }
9615     }
9616     previewTextRects.emplace_back(linerRect);
9617     return previewTextRects;
9618 }
9619 
9620 bool TextFieldPattern::NeedDrawPreviewText()
9621 {
9622     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9623     CHECK_NULL_RETURN(paintProperty, false);
9624 
9625     auto caretInfo = selectController_->GetCaretInfo();
9626     if (!paintProperty->HasPreviewTextStart() || !paintProperty->HasPreviewTextEnd()) {
9627         paintProperty->UpdatePreviewTextStart(caretInfo.index);
9628         paintProperty->UpdatePreviewTextEnd(caretInfo.index);
9629     }
9630 
9631     auto paintStart = paintProperty->GetPreviewTextStart();
9632     auto paintEnd =paintProperty->GetPreviewTextEnd();
9633     if (!GetIsPreviewText()) {
9634         if (!paintStart.has_value() || !paintEnd.has_value()) {
9635             paintProperty->UpdatePreviewTextStart(caretInfo.index);
9636             paintProperty->UpdatePreviewTextEnd(caretInfo.index);
9637             return false;
9638         }
9639 
9640         // end paint
9641         if (paintStart != paintEnd || paintStart.value() != caretInfo.index) {
9642             paintProperty->UpdatePreviewTextStart(caretInfo.index);
9643             paintProperty->UpdatePreviewTextEnd(caretInfo.index);
9644             return true;
9645         }
9646         return false;
9647     }
9648     auto needDraw = paintStart.value() != GetPreviewTextStart() ||
9649                      paintEnd.value() != GetPreviewTextEnd();
9650     paintProperty->UpdatePreviewTextStart(GetPreviewTextStart());
9651     paintProperty->UpdatePreviewTextEnd(GetPreviewTextEnd());
9652     return needDraw;
9653 }
9654 
9655 int32_t TextFieldPattern::CheckPreviewTextValidate(const std::u16string& previewValue, const PreviewRange range)
9656 {
9657     auto start = range.start;
9658     auto end = range.end;
9659     if (start != end && (start == PREVIEW_TEXT_RANGE_DEFAULT || end == PREVIEW_TEXT_RANGE_DEFAULT)) {
9660         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "range is not [-1,-1] or legal range");
9661         return PREVIEW_BAD_PARAMETERS;
9662     }
9663 
9664     if (start != PREVIEW_TEXT_RANGE_DEFAULT && IsSelected()) {
9665         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "unsupported insert preview text when IsSelected");
9666         return PREVIEW_BAD_PARAMETERS;
9667     }
9668     return PREVIEW_NO_ERROR;
9669 }
9670 
9671 int32_t TextFieldPattern::CheckPreviewTextValidate(const std::string& previewValue, const PreviewRange range)
9672 {
9673     return CheckPreviewTextValidate(UtfUtils::Str8DebugToStr16(previewValue), range);
9674 }
9675 
9676 PreviewTextStyle TextFieldPattern::GetPreviewTextStyle() const
9677 {
9678     auto defaultStyle = PreviewTextStyle::NORMAL;
9679     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9680     CHECK_NULL_RETURN(paintProperty, defaultStyle);
9681     if (paintProperty->HasPreviewTextStyle()) {
9682         auto style = paintProperty->GetPreviewTextStyle();
9683         CHECK_NULL_RETURN(style, defaultStyle);
9684         if (style.value() == PREVIEW_STYLE_NORMAL) {
9685             return PreviewTextStyle::NORMAL;
9686         } else if (style.value() == PREVIEW_STYLE_UNDERLINE) {
9687             return PreviewTextStyle::UNDERLINE;
9688         }
9689     }
9690     return defaultStyle;
9691 }
9692 
9693 void TextFieldPattern::ReceivePreviewTextStyle(const std::string& style)
9694 {
9695     auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
9696     CHECK_NULL_VOID(paintProperty);
9697     if (!style.empty()) {
9698         paintProperty->UpdatePreviewTextStyle(style);
9699     }
9700 }
9701 
9702 void TextFieldPattern::CalculatePreviewingTextMovingLimit(const Offset& touchOffset, double& limitL, double& limitR)
9703 {
9704     float offsetX = IsTextArea() ? contentRect_.GetX() : GetTextRect().GetX();
9705     float offsetY = IsTextArea() ? GetTextRect().GetY() : contentRect_.GetY();
9706     std::vector<RectF> previewTextRects = GetPreviewTextRects();
9707     if (GreatNotEqual(touchOffset.GetY(), previewTextRects.back().Bottom() + offsetY)) {
9708         limitL = previewTextRects.back().Left() + offsetX + MINIMAL_OFFSET;
9709         limitR = previewTextRects.back().Right() + offsetX - MINIMAL_OFFSET;
9710     } else if (LessNotEqual(touchOffset.GetY(), previewTextRects.front().Top() + offsetY)) {
9711         limitL = previewTextRects.front().Left() + offsetX + MINIMAL_OFFSET;
9712         limitR = previewTextRects.front().Right() + offsetX - MINIMAL_OFFSET;
9713     } else {
9714         for (const auto& drawRect : previewTextRects) {
9715             if (GreatOrEqual(touchOffset.GetY(), drawRect.Top() + offsetY)
9716                 && LessOrEqual(touchOffset.GetY(), drawRect.Bottom() + offsetY)) {
9717                 limitL = drawRect.Left() + offsetX + MINIMAL_OFFSET;
9718                 limitR = drawRect.Right() + offsetX - MINIMAL_OFFSET;
9719                 break;
9720             }
9721         }
9722     }
9723 }
9724 
9725 void TextFieldPattern::ResetPreviewTextState()
9726 {
9727     if (!GetIsPreviewText()) {
9728         return;
9729     }
9730 #if defined(ENABLE_STANDARD_INPUT)
9731     MiscServices::InputMethodController::GetInstance()->OnSelectionChange(
9732         StringUtils::Str8ToStr16(""), 0, 0);
9733     UpdateCaretInfoToController(true);
9734 #endif
9735     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "textfield onDragEnter when has previewText");
9736     FinishTextPreview();
9737 }
9738 
9739 void TextFieldPattern::SetShowKeyBoardOnFocus(bool value)
9740 {
9741     auto host = GetHost();
9742     FREE_NODE_CHECK(host, SetShowKeyBoardOnFocus, value);  // call SetShowKeyBoardOnFocusMultiThread() by multi thread
9743     if (showKeyBoardOnFocus_ == value) {
9744         return;
9745     }
9746     showKeyBoardOnFocus_ = value;
9747 
9748     if (!HasFocus()) {
9749         return;
9750     }
9751 
9752     if (value) {
9753         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::SHOW_KEYBOARD_ON_FOCUS);
9754     } else {
9755         CloseKeyboard(true, false);
9756     }
9757 }
9758 
9759 void TextFieldPattern::OnCaretMoveDone(const TouchEventInfo& info)
9760 {
9761     if (isMoveCaretAnywhere_) {
9762         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "isMoveCaretAnywhere_=1, so restore caret");
9763         selectController_->UpdateCaretInfoByOffset(info.GetTouches().front().GetLocalLocation());
9764         StartTwinkling();
9765     }
9766 }
9767 
9768 void TextFieldPattern::HiddenMenu()
9769 {
9770     selectOverlay_->HideMenu();
9771 }
9772 
9773 void TextFieldPattern::OnSelectionMenuOptionsUpdate(const NG::OnCreateMenuCallback&& onCreateMenuCallback,
9774     const NG::OnMenuItemClickCallback&& onMenuItemClick, const NG::OnPrepareMenuCallback&& onPrepareMenuCallback)
9775 {
9776     selectOverlay_->OnSelectionMenuOptionsUpdate(
9777         std::move(onCreateMenuCallback), std::move(onMenuItemClick), std::move(onPrepareMenuCallback));
9778 }
9779 
9780 bool TextFieldPattern::GetTouchInnerPreviewText(const Offset& offset) const
9781 {
9782     auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset);
9783     return GetPreviewTextStart() <= touchDownIndex && touchDownIndex <= GetPreviewTextEnd() && HasFocus();
9784 }
9785 
9786 bool TextFieldPattern::IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const
9787 {
9788     if (touchEvent.sourceTool != SourceTool::PEN || touchEvent.type != TouchType::DOWN) {
9789         return false;
9790     }
9791     auto host = GetHost();
9792     CHECK_NULL_RETURN(host, false);
9793     auto focusHub = host->GetFocusHub();
9794     CHECK_NULL_RETURN(focusHub, false);
9795     if (!focusHub->IsFocusable() || !host->IsVisible()) {
9796         return false;
9797     }
9798     auto renderContext = host->GetRenderContext();
9799     CHECK_NULL_RETURN(renderContext, false);
9800     auto opacity = renderContext->GetOpacity();
9801     // if opacity is 0.0f, no need to hit frameNode.
9802     if (NearZero(opacity.value_or(1.0f))) {
9803         return false;
9804     }
9805     return !IsInPasswordMode();
9806 }
9807 
9808 RectF TextFieldPattern::ExpandDefaultResponseRegion(RectF& rect)
9809 {
9810     return rect + NG::SizeF(0, OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx() * OHOS::Ace::HOT_AREA_EXPAND_TIME) +
9811            NG::OffsetF(0, -OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx());
9812 }
9813 
9814 bool TextFieldPattern::IsContentRectNonPositive()
9815 {
9816     return NonPositive(contentRect_.Width());
9817 }
9818 
9819 void TextFieldPattern::ReportEvent()
9820 {
9821 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
9822     auto host = GetHost();
9823     CHECK_NULL_VOID(host);
9824     if (UiSessionManager::GetInstance()->GetSearchEventRegistered()) {
9825         auto data = JsonUtil::Create();
9826         data->Put("event", "onTextSearch");
9827         data->Put("id", host->GetId());
9828         data->Put("$type", host->GetTag().data());
9829         data->Put("inputType", static_cast<int16_t>(GetKeyboard()));
9830         data->Put("text", GetTextValue().data());
9831         data->Put("position", host->GetGeometryNode()->GetFrameRect().ToString().data());
9832         // report all use textfield component unfocus event,more than just the search box
9833         UiSessionManager::GetInstance()->ReportSearchEvent(data->ToString());
9834     }
9835     if (!IsInPasswordMode()) {
9836         auto value = InspectorJsonUtil::Create();
9837         CHECK_NULL_VOID(value);
9838         auto textString = GetTextValue();
9839         value->Put("text", textString.c_str());
9840         UiSessionManager::GetInstance()->ReportComponentChangeEvent(host->GetId(), "event", value);
9841         SEC_TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "nodeId:[%{public}d] TextField reportComponentChangeEvent %{public}zu",
9842             host->GetId(), textString.length());
9843     }
9844 #endif
9845 }
9846 
9847 int32_t TextFieldPattern::GetTouchIndex(const OffsetF& offset)
9848 {
9849     return selectOverlay_->GetCaretPositionOnHandleMove(offset, true);
9850 }
9851 
9852 void TextFieldPattern::StartGestureSelection(int32_t start, int32_t end, const Offset& startOffset)
9853 {
9854     TextGestureSelector::StartGestureSelection(start, end, startOffset);
9855     StopContentScroll();
9856     contentScroller_.scrollingCallback = [weak = WeakClaim(this), start, end](const Offset& localOffset) {
9857         auto pattern = weak.Upgrade();
9858         CHECK_NULL_VOID(pattern);
9859         auto index = pattern->GetTouchIndex({ localOffset.GetX(), localOffset.GetY() });
9860         auto startIndex = std::min(index, start);
9861         auto endIndex = std::max(index, end);
9862         pattern->UpdateSelectionByLongPress(startIndex, endIndex, localOffset);
9863     };
9864 }
9865 
9866 void TextFieldPattern::OnTextGestureSelectionUpdate(int32_t start, int32_t end, const TouchEventInfo& info)
9867 {
9868     if (!HasText()) {
9869         return;
9870     }
9871     auto localOffset = info.GetTouches().front().GetLocalLocation();
9872     UpdateContentScroller(localOffset);
9873     if (contentScroller_.isScrolling) {
9874         return;
9875     }
9876     if (start != selectController_->GetStartIndex()) {
9877         StartVibratorByIndexChange(start, selectController_->GetStartIndex());
9878     } else if (end != selectController_->GetEndIndex()) {
9879         StartVibratorByIndexChange(end, selectController_->GetEndIndex());
9880     }
9881     UpdateSelectionByLongPress(start, end, localOffset);
9882 }
9883 
9884 void TextFieldPattern::UpdateSelectionByLongPress(int32_t start, int32_t end, const Offset& localOffset)
9885 {
9886     if (magnifierController_ && HasText() && (longPressFingerNum_ == 1)) {
9887         magnifierController_->SetLocalOffset({ localOffset.GetX(), localOffset.GetY() });
9888     }
9889     auto firstIndex = selectController_->GetFirstHandleIndex();
9890     auto secondIndex = selectController_->GetSecondHandleIndex();
9891     bool changed = false;
9892     if (start != firstIndex) {
9893         selectController_->MoveFirstHandleToContentRect(start, false, false);
9894         changed = true;
9895     }
9896     if (secondIndex != end) {
9897         selectController_->MoveSecondHandleToContentRect(end, false, false);
9898         changed = true;
9899     }
9900     if (!changed) {
9901         return;
9902     }
9903     auto host = GetHost();
9904     CHECK_NULL_VOID(host);
9905     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
9906 }
9907 
9908 void TextFieldPattern::OnTextGestureSelectionEnd(const TouchLocationInfo& locationInfo)
9909 {
9910     SetIsSingleHandle(!IsSelected());
9911     bool isScrolling = contentScroller_.isScrolling;
9912     StopContentScroll();
9913     if (IsContentRectNonPositive()) {
9914         return;
9915     }
9916     auto needRender = false;
9917     do {
9918         if (!isScrolling) {
9919             auto localLocation = locationInfo.GetLocalLocation();
9920             if (LessNotEqual(localLocation.GetX(), contentRect_.Left()) ||
9921                 LessNotEqual(localLocation.GetY(), contentRect_.Top())) {
9922                 selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex(), false);
9923                 needRender = true;
9924                 break;
9925             } else if (GreatNotEqual(localLocation.GetX(), contentRect_.Right()) ||
9926                        GreatNotEqual(localLocation.GetY(), contentRect_.Bottom())) {
9927                 selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex(), false);
9928                 needRender = true;
9929                 break;
9930             }
9931         }
9932         if (Positive(contentScroller_.stepOffset)) {
9933             selectController_->MoveFirstHandleToContentRect(selectController_->GetFirstHandleIndex(), false);
9934             needRender = true;
9935         } else if (Negative(contentScroller_.stepOffset)) {
9936             selectController_->MoveSecondHandleToContentRect(selectController_->GetSecondHandleIndex(), false);
9937             needRender = true;
9938         }
9939     } while (false);
9940     if (HasFocus()) {
9941         ProcessOverlay({ .animation = true });
9942     }
9943     if (needRender) {
9944         auto host = GetHost();
9945         CHECK_NULL_VOID(host);
9946         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
9947     }
9948 }
9949 
9950 PositionWithAffinity TextFieldPattern::GetGlyphPositionAtCoordinate(int32_t x, int32_t y)
9951 {
9952     PositionWithAffinity finalResult(0, TextAffinity::UPSTREAM);
9953     CHECK_NULL_RETURN(paragraph_, finalResult);
9954     Offset offset(x, y);
9955     return paragraph_->GetGlyphPositionAtCoordinate(ConvertTouchOffsetToTextOffset(offset));
9956 }
9957 
9958 Offset TextFieldPattern::ConvertTouchOffsetToTextOffset(const Offset& touchOffset)
9959 {
9960     return touchOffset - Offset(textRect_.GetX(), textRect_.GetY());
9961 }
9962 
9963 bool TextFieldPattern::InsertOrDeleteSpace(int32_t index)
9964 {
9965     // delete or insert space.
9966     auto wtext = GetTextUtf16Value();
9967     if (index >= 0 && index < static_cast<int32_t>(wtext.length())) {
9968         auto ret = SetCaretOffset(index);
9969         if (!ret) {
9970             return false;
9971         }
9972         if (wtext[index] == u' ') {
9973             DeleteForward(1);
9974         } else if (index > 0 && wtext[index - 1] == u' ') {
9975             DeleteBackward(1);
9976         } else {
9977             InsertValue(u" ", true);
9978         }
9979         return true;
9980     }
9981     return false;
9982 }
9983 
9984 void TextFieldPattern::DeleteRange(int32_t start, int32_t end, bool isIME)
9985 {
9986     auto length = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
9987     if (start > end) {
9988         std::swap(start, end);
9989     }
9990     start = std::max(0, start);
9991     end = std::min(length, end);
9992     if (start > length || end < 0 || start == end) {
9993         return;
9994     }
9995     auto value = contentController_->GetSelectedValue(start, end);
9996     auto originCaretIndex =
9997             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
9998     if (isIME) {
9999         auto isDelete = BeforeIMEDeleteValue(value, TextDeleteDirection::FORWARD, start);
10000         CHECK_NULL_VOID(isDelete);
10001     }
10002     ResetObscureTickCountDown();
10003     CheckAndUpdateRecordBeforeOperation();
10004     auto oldContent = contentController_->GetTextUtf16Value();
10005     Delete(start, end);
10006     auto isOnWillChange = OnWillChangePreDelete(oldContent, start, end);
10007     if (!isOnWillChange) {
10008         RecoverTextValueAndCaret(oldContent, originCaretIndex);
10009         return;
10010     }
10011     if (isIME) {
10012         AfterIMEDeleteValue(value, TextDeleteDirection::FORWARD);
10013     }
10014     showCountBorderStyle_ = false;
10015     HandleCountStyle();
10016 }
10017 
10018 void TextFieldPattern::DeleteTextRange(int32_t start, int32_t end, TextDeleteDirection direction)
10019 {
10020     auto length = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
10021     if (start > end) {
10022         std::swap(start, end);
10023     }
10024     start = std::max(0, start);
10025     end = std::min(length, end);
10026     if (start > length || end < 0 || start == end) {
10027         return;
10028     }
10029     auto value = contentController_->GetSelectedValue(start, end);
10030     auto originCaretIndex =
10031             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
10032     auto isDelete = BeforeIMEDeleteValue(value, direction, start);
10033     CHECK_NULL_VOID(isDelete);
10034     ResetObscureTickCountDown();
10035     CheckAndUpdateRecordBeforeOperation();
10036     auto oldContent = contentController_->GetTextUtf16Value();
10037     Delete(start, end);
10038     auto isOnWillChange = OnWillChangePreDelete(oldContent, start, end);
10039     if (!isOnWillChange) {
10040         RecoverTextValueAndCaret(oldContent, originCaretIndex);
10041         return;
10042     }
10043     AfterIMEDeleteValue(value, direction);
10044     showCountBorderStyle_ = false;
10045     HandleCountStyle();
10046 }
10047 
10048 bool TextFieldPattern::IsShowAIWrite()
10049 {
10050     auto container = Container::Current();
10051     if (container && container->IsSceneBoardWindow()) {
10052         return false;
10053     }
10054 
10055     auto host = GetHost();
10056     CHECK_NULL_RETURN(host, false);
10057     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
10058     CHECK_NULL_RETURN(layoutProperty, false);
10059     if (layoutProperty->GetCopyOptionsValue(CopyOptions::Local) == CopyOptions::None ||
10060         !IsUnspecifiedOrTextType()) {
10061         return false;
10062     }
10063 
10064     auto textFieldTheme = GetTheme();
10065     CHECK_NULL_RETURN(textFieldTheme, false);
10066     auto bundleName = textFieldTheme->GetAIWriteBundleName();
10067     auto abilityName = textFieldTheme->GetAIWriteAbilityName();
10068     if (bundleName.empty() || abilityName.empty()) {
10069         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "Failed to obtain AI write package name!");
10070         return false;
10071     }
10072 
10073     auto isAISupport = false;
10074     if (textFieldTheme->GetAIWriteIsSupport() == "true") {
10075         isAISupport = true;
10076     }
10077     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Whether the device supports AI write: %{public}d, nodeId: %{public}d",
10078         isAISupport, host->GetId());
10079     if (isAISupport) {
10080         auto pipeline = host->GetContext();
10081         CHECK_NULL_RETURN(pipeline, false);
10082         aiWriteAdapter_ = pipeline->GetOrCreateAIWriteAdapter(); // initialize TextFieldPattern's aiWriteAdapter_ here.
10083         auto aiWriteAdapter = aiWriteAdapter_.Upgrade();
10084         CHECK_NULL_RETURN(aiWriteAdapter, false);
10085         aiWriteAdapter->SetBundleName(bundleName);
10086         aiWriteAdapter->SetAbilityName(abilityName);
10087     }
10088 
10089     return isAISupport;
10090 }
10091 
10092 void TextFieldPattern::GetAIWriteInfo(AIWriteInfo& info)
10093 {
10094     auto aiWriteAdapter = aiWriteAdapter_.Upgrade();
10095     CHECK_NULL_VOID(aiWriteAdapter);
10096     // serialize the selected text
10097     info.selectStart = selectController_->GetStartIndex();
10098     info.selectEnd = selectController_->GetEndIndex();
10099     auto selectContent = contentController_->GetSelectedValue(info.selectStart, info.selectEnd);
10100     RefPtr<SpanString> spanString = AceType::MakeRefPtr<SpanString>(selectContent);
10101     spanString->EncodeTlv(info.selectBuffer);
10102     info.selectLength = static_cast<int32_t>(aiWriteAdapter->GetSelectLengthOnlyText(spanString->GetU16string()));
10103     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "Selected range=[%{public}d--%{public}d], content size=%{public}zu",
10104         info.selectStart, info.selectEnd, spanString->GetString().size());
10105 
10106     // serialize the sentenced-level text
10107     auto textSize = static_cast<int32_t>(contentController_->GetTextUtf16Value().length());
10108     auto contentAll = contentController_->GetTextUtf16Value();
10109     auto sentenceStart = 0;
10110     auto sentenceEnd = textSize;
10111     for (int32_t i = info.selectStart; i >= 0; --i) {
10112         if (aiWriteAdapter->IsSentenceBoundary(contentAll[i])) {
10113             sentenceStart = i + 1;
10114             break;
10115         }
10116     }
10117     for (int32_t i = info.selectEnd; i < textSize; i++) {
10118         if (aiWriteAdapter->IsSentenceBoundary(contentAll[i])) {
10119             sentenceEnd = i;
10120             break;
10121         }
10122     }
10123     info.start = info.selectStart - sentenceStart;
10124     info.end = info.selectEnd - sentenceStart;
10125     auto sentenceContent = contentController_->GetSelectedValue(sentenceStart, sentenceEnd);
10126     spanString = AceType::MakeRefPtr<SpanString>(sentenceContent);
10127     spanString->EncodeTlv(info.sentenceBuffer);
10128     TAG_LOGD(AceLogTag::ACE_TEXT_FIELD, "Sentence range=[%{public}d--%{public}d], content size=%{public}zu",
10129         sentenceStart, sentenceEnd, spanString->GetString().size());
10130 
10131     auto host = GetHost();
10132     CHECK_NULL_VOID(host);
10133     auto layoutProperty = host->GetLayoutProperty<TextFieldLayoutProperty>();
10134     CHECK_NULL_VOID(layoutProperty);
10135     info.maxLength = static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>()));
10136     info.firstHandle = selectController_->GetFirstHandleRect().ToString();
10137     info.secondHandle = selectController_->GetSecondHandleRect().ToString();
10138     info.componentType = host->GetTag();
10139 }
10140 
10141 void TextFieldPattern::HandleOnAIWrite()
10142 {
10143     auto aiWriteAdapter = aiWriteAdapter_.Upgrade();
10144     CHECK_NULL_VOID(aiWriteAdapter);
10145     AIWriteInfo info;
10146     GetAIWriteInfo(info);
10147     CloseSelectOverlay();
10148     CloseKeyboard(true);
10149 
10150     auto callback = [weak = WeakClaim(this), info](std::vector<uint8_t>& buffer) {
10151         auto pattern = weak.Upgrade();
10152         CHECK_NULL_VOID(pattern);
10153         pattern->HandleAIWriteResult(info.selectStart, info.selectEnd, buffer);
10154         auto weakAiWriteAdapter = pattern->aiWriteAdapter_;
10155         auto aiWriteAdapter = weakAiWriteAdapter.Upgrade();
10156         CHECK_NULL_VOID(aiWriteAdapter);
10157         aiWriteAdapter->CloseModalUIExtension();
10158     };
10159     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
10160     CHECK_NULL_VOID(pipeline);
10161     aiWriteAdapter->SetPipelineContext(pipeline);
10162     aiWriteAdapter->ShowModalUIExtension(info, callback);
10163 }
10164 
10165 void TextFieldPattern::HandleAIWriteResult(int32_t start, int32_t end, std::vector<uint8_t>& buffer)
10166 {
10167     RefPtr<SpanString> spanString = SpanString::DecodeTlv(buffer);
10168     auto resultText = spanString->GetU16string();
10169     TAG_LOGD(AceLogTag::ACE_RICH_TEXT, "Backfilling results range=[%{public}d--%{public}d], content size=%{public}zu",
10170         start, end, spanString->GetString().size());
10171     if (spanString->GetSpanItems().empty()) {
10172         return;
10173     }
10174 
10175     auto host = GetHost();
10176     CHECK_NULL_VOID(host);
10177     auto value = contentController_->GetSelectedValue(start, end);
10178     InputCommandInfo inputCommandInfo;
10179     inputCommandInfo.deleteRange = { start, end };
10180     inputCommandInfo.insertOffset = start;
10181     inputCommandInfo.insertValue = resultText;
10182     inputCommandInfo.reason = InputReason::AI_WRITE;
10183     AddInputCommand(inputCommandInfo);
10184 }
10185 
10186 bool TextFieldPattern::IsTextEditableForStylus() const
10187 {
10188     CHECK_NULL_RETURN(!HasCustomKeyboard(), false);
10189     auto host = GetHost();
10190     CHECK_NULL_RETURN(host, false);
10191     auto focusHub = host->GetFocusHub();
10192     CHECK_NULL_RETURN(focusHub, false);
10193     if (!focusHub->IsFocusable() || !host->IsVisible()) {
10194         return false;
10195     }
10196     auto renderContext = host->GetRenderContext();
10197     CHECK_NULL_RETURN(renderContext, false);
10198     auto opacity = renderContext->GetOpacity();
10199     // if opacity is 0.0f, no need to hit frameNode.
10200     if (NearZero(opacity.value_or(1.0f))) {
10201         return false;
10202     }
10203     return !IsInPasswordMode();
10204 }
10205 
10206 void TextFieldPattern::UpdateContentScroller(const Offset& offset, float delay, bool enableScrollOutside)
10207 {
10208     auto localOffset = enableScrollOutside ? AdjustAutoScrollOffset(offset) : offset;
10209     auto scrollStep = CalcAutoScrollStepOffset(localOffset);
10210     // 在热区外移动
10211     if (!scrollStep || (!GetScrollEnabled() && !moveCaretState_.isMoveCaret)) {
10212         contentScroller_.OnBeforeScrollingCallback(localOffset);
10213         PauseContentScroll();
10214         contentScroller_.hotAreaOffset.reset();
10215         return;
10216     }
10217     contentScroller_.stepOffset = scrollStep.value();
10218     contentScroller_.localOffset = localOffset;
10219     if (contentScroller_.isScrolling) {
10220         return;
10221     }
10222     contentScroller_.OnBeforeScrollingCallback(localOffset);
10223     if (!contentScroller_.hotAreaOffset) {
10224         contentScroller_.hotAreaOffset = localOffset;
10225         ScheduleContentScroll(delay);
10226     } else {
10227         auto hotAreaMoveDistance = (localOffset - contentScroller_.hotAreaOffset.value()).GetDistance();
10228         if (GreatOrEqual(hotAreaMoveDistance, AUTO_SCROLL_HOT_AREA_LONGPRESS_DISTANCE.ConvertToPx())) {
10229             contentScroller_.hotAreaOffset = localOffset;
10230             contentScroller_.autoScrollTask.Cancel();
10231             ScheduleContentScroll(delay);
10232         }
10233     }
10234 }
10235 
10236 Offset TextFieldPattern::AdjustAutoScrollOffset(const Offset& offset)
10237 {
10238     auto contentRect = GetContentRect();
10239     // ensure the point is in the content area.
10240     double margin = 1.0f;
10241     auto offsetX = std::clamp(offset.GetX(), static_cast<double>(contentRect.Left()) + margin,
10242         static_cast<double>(contentRect.Right()) - margin);
10243     auto offsetY = std::clamp(offset.GetY(), static_cast<double>(contentRect.Top()) + margin,
10244         static_cast<double>(contentRect.Bottom()) - margin);
10245     return Offset(offsetX, offsetY);
10246 }
10247 
10248 std::optional<float> TextFieldPattern::CalcAutoScrollStepOffset(const Offset& localOffset)
10249 {
10250     auto contentRect = GetContentRect();
10251     auto axis = GetAxis();
10252     auto isVertical = (axis == Axis::VERTICAL);
10253     auto hotArea = isVertical ? AUTO_SCROLL_HOT_ZONE_HEIGHT.ConvertToPx() : AUTO_SCROLL_HOT_ZONE_WIDTH.ConvertToPx();
10254     if (isVertical) {
10255         if (LessOrEqual(contentRect.Height(), hotArea)) {
10256             hotArea = contentRect.Height() / 3.0f;
10257         }
10258     } else {
10259         if (LessOrEqual(contentRect.Width(), hotArea)) {
10260             hotArea = contentRect.Width() / 3.0f;
10261         }
10262     }
10263     struct HotEdge {
10264         float start = 0.0f;
10265         float end = 0.0f;
10266         float scrollDirection = 1.0f;
10267     };
10268     std::vector<HotEdge> hotEdges = { { contentRect.Top() + hotArea, contentRect.Top(), 1.0f },
10269         { contentRect.Bottom() - hotArea, contentRect.Bottom(), -1.0f },
10270         { contentRect.Left() + hotArea, contentRect.Left(), 1.0f },
10271         { contentRect.Right() - hotArea, contentRect.Right(), -1.0f } };
10272     auto itStart = isVertical ? hotEdges.begin() : hotEdges.begin() + 2;
10273     auto point = isVertical ? localOffset.GetY() : localOffset.GetX();
10274     std::optional<float> scrollStep;
10275     for (auto it = itStart; it != (itStart + 2); ++it) {
10276         auto speed = CalcScrollSpeed(it->start, it->end, point);
10277         if (!NearZero(speed)) {
10278             scrollStep = speed * it->scrollDirection;
10279             break;
10280         }
10281     }
10282     return scrollStep;
10283 }
10284 
10285 float TextFieldPattern::CalcScrollSpeed(float hotAreaStart, float hotAreaEnd, float point)
10286 {
10287     auto minHotArea = std::min(hotAreaStart, hotAreaEnd);
10288     auto maxHotArea = std::max(hotAreaStart, hotAreaEnd);
10289     if (GreatNotEqual(point, minHotArea) && LessNotEqual(point, maxHotArea)) {
10290         auto distanceRatio = (point - hotAreaStart) / (hotAreaEnd - hotAreaStart);
10291         auto speedFactor = Curves::SHARP->MoveInternal(distanceRatio);
10292         return ((MAX_DRAG_SCROLL_SPEED * speedFactor) / TIME_UNIT) * contentScroller_.scrollInterval;
10293     }
10294     return 0.0f;
10295 }
10296 
10297 void TextFieldPattern::StopContentScroll()
10298 {
10299     PauseContentScroll();
10300     contentScroller_.scrollingCallback = nullptr;
10301     contentScroller_.beforeScrollingCallback = nullptr;
10302 }
10303 
10304 void TextFieldPattern::PauseContentScroll()
10305 {
10306     contentScroller_.autoScrollTask.Cancel();
10307     contentScroller_.isScrolling = false;
10308     ScheduleDisappearDelayTask();
10309 }
10310 
10311 void TextFieldPattern::ScheduleContentScroll(float delay)
10312 {
10313     auto host = GetHost();
10314     CHECK_NULL_VOID(host);
10315     auto context = host->GetContext();
10316     CHECK_NULL_VOID(context);
10317     auto taskExecutor = context->GetTaskExecutor();
10318     CHECK_NULL_VOID(taskExecutor);
10319     contentScroller_.autoScrollTask.Reset([weak = WeakClaim(this)]() {
10320         auto pattern = weak.Upgrade();
10321         CHECK_NULL_VOID(pattern);
10322         pattern->contentScroller_.isScrolling = true;
10323         pattern->contentScroller_.hotAreaOffset = std::nullopt;
10324         pattern->OnScrollCallback(pattern->contentScroller_.stepOffset, SCROLL_FROM_UPDATE);
10325         if (pattern->contentScroller_.scrollingCallback) {
10326             pattern->contentScroller_.scrollingCallback(pattern->contentScroller_.localOffset);
10327         }
10328         pattern->ScheduleContentScroll(pattern->contentScroller_.scrollInterval);
10329     });
10330     taskExecutor->PostDelayedTask(contentScroller_.autoScrollTask, TaskExecutor::TaskType::UI, delay,
10331         "ArkUIAutoScrollControllerScheduleAutoScroll");
10332 }
10333 
10334 void TextFieldPattern::SetDragMovingScrollback()
10335 {
10336     StopContentScroll();
10337     contentScroller_.scrollingCallback = [weak = WeakClaim(this)](const Offset& localOffset) {
10338         auto pattern = weak.Upgrade();
10339         CHECK_NULL_VOID(pattern);
10340         auto host = pattern->GetHost();
10341         CHECK_NULL_VOID(host);
10342         auto pipeline = host->GetContext();
10343         CHECK_NULL_VOID(pipeline);
10344         auto theme = pipeline->GetTheme<TextFieldTheme>();
10345         CHECK_NULL_VOID(theme);
10346         Offset offset = localOffset - Offset(pattern->textRect_.GetX(), pattern->textRect_.GetY()) -
10347                         Offset(0, theme->GetInsertCursorOffset().ConvertToPx());
10348         auto position = pattern->ConvertTouchOffsetToCaretPosition(offset);
10349         pattern->SetCaretPosition(position, false);
10350         pattern->ShowCaretAndStopTwinkling();
10351     };
10352     contentScroller_.beforeScrollingCallback = contentScroller_.scrollingCallback;
10353 }
10354 
10355 void TextFieldPattern::OnAttachToMainTree()
10356 {
10357     auto host = GetHost();
10358     THREAD_SAFE_NODE_CHECK(host, OnAttachToMainTree);  // call OnAttachToMainTreeMultiThread() by multi thread
10359     isDetachFromMainTree_ = false;
10360     CHECK_NULL_VOID(host);
10361     auto autoFillContainerNode = host->GetFirstAutoFillContainerNode();
10362     CHECK_NULL_VOID(autoFillContainerNode);
10363     firstAutoFillContainerNode_ = WeakClaim(RawPtr(autoFillContainerNode));
10364     AddTextFieldInfo();
10365 }
10366 
10367 void TextFieldPattern::OnDetachFromMainTree()
10368 {
10369     auto host = GetHost();
10370     THREAD_SAFE_NODE_CHECK(host, OnDetachFromMainTree);  // call OnDetachFromMainTreeMultiThread() by multi thread
10371     isDetachFromMainTree_ = true;
10372     RemoveTextFieldInfo();
10373     RemoveFillContentMap();
10374 }
10375 
10376 TextFieldInfo TextFieldPattern::GenerateTextFieldInfo()
10377 {
10378     TextFieldInfo textFieldInfo;
10379     auto host = GetHost();
10380     CHECK_NULL_RETURN(host, textFieldInfo);
10381     textFieldInfo.nodeId = host->GetId();
10382     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
10383     CHECK_NULL_RETURN(autoFillContainerNode, textFieldInfo);
10384     textFieldInfo.autoFillContainerNodeId = autoFillContainerNode->GetId();
10385     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10386     CHECK_NULL_RETURN(layoutProperty, textFieldInfo);
10387     textFieldInfo.enableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
10388     textFieldInfo.inputType = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED);
10389     textFieldInfo.contentType = layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED);
10390     return textFieldInfo;
10391 }
10392 
10393 void TextFieldPattern::AddTextFieldInfo()
10394 {
10395     CHECK_NULL_VOID(IsNeedProcessAutoFill());
10396     auto host = GetHost();
10397     CHECK_NULL_VOID(host);
10398     auto pipeline = host->GetContext();
10399     CHECK_NULL_VOID(pipeline);
10400     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10401     CHECK_NULL_VOID(textFieldManager);
10402     auto textFieldInfo = GenerateTextFieldInfo();
10403     textFieldManager->AddTextFieldInfo(textFieldInfo);
10404 }
10405 
10406 void TextFieldPattern::RemoveTextFieldInfo()
10407 {
10408     CHECK_NULL_VOID(IsNeedProcessAutoFill());
10409     auto host = GetHost();
10410     CHECK_NULL_VOID(host);
10411     auto pipeline = host->GetContext();
10412     CHECK_NULL_VOID(pipeline);
10413     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10414     CHECK_NULL_VOID(textFieldManager);
10415     auto nodeId = host->GetId();
10416     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
10417     CHECK_NULL_VOID(autoFillContainerNode);
10418     auto autoFillContainerNodeId = autoFillContainerNode->GetId();
10419     textFieldManager->RemoveTextFieldInfo(autoFillContainerNodeId, nodeId);
10420 }
10421 
10422 void TextFieldPattern::UpdateTextFieldInfo()
10423 {
10424     CHECK_NULL_VOID(IsNeedProcessAutoFill());
10425     auto host = GetHost();
10426     CHECK_NULL_VOID(host);
10427     auto pipeline = host->GetContext();
10428     CHECK_NULL_VOID(pipeline);
10429     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10430     CHECK_NULL_VOID(textFieldManager);
10431     auto textFieldInfo = GenerateTextFieldInfo();
10432     textFieldManager->UpdateTextFieldInfo(textFieldInfo);
10433 }
10434 
10435 bool TextFieldPattern::IsAutoFillUserName(const AceAutoFillType& autoFillType)
10436 {
10437     auto isUserName =
10438         autoFillType == AceAutoFillType::ACE_USER_NAME || autoFillType == AceAutoFillType::ACE_UNSPECIFIED;
10439     return isUserName && HasAutoFillPasswordNode();
10440 }
10441 
10442 bool TextFieldPattern::HasAutoFillPasswordNode()
10443 {
10444     auto host = GetHost();
10445     CHECK_NULL_RETURN(host, false);
10446     auto pipeline = host->GetContext();
10447     CHECK_NULL_RETURN(pipeline, false);
10448     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
10449     CHECK_NULL_RETURN(textFieldManager, false);
10450     auto nodeId = host->GetId();
10451     auto autoFillContainerNode = firstAutoFillContainerNode_.Upgrade();
10452     CHECK_NULL_RETURN(autoFillContainerNode, false);
10453     auto autoFillContainerNodeId = autoFillContainerNode->GetId();
10454     return textFieldManager->HasAutoFillPasswordNodeInContainer(autoFillContainerNodeId, nodeId);
10455 }
10456 
10457 bool TextFieldPattern::IsTriggerAutoFillPassword()
10458 {
10459     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10460     CHECK_NULL_RETURN(layoutProperty, false);
10461     auto aceContentType =
10462         TextContentTypeToAceAutoFillType(layoutProperty->GetTextContentTypeValue(TextContentType::UNSPECIFIED));
10463     if (aceContentType != AceAutoFillType::ACE_UNSPECIFIED) {
10464         if (!IsAutoFillPasswordType(aceContentType)) {
10465             return false;
10466         } else {
10467             if (aceContentType == AceAutoFillType::ACE_PASSWORD ||
10468                 aceContentType == AceAutoFillType::ACE_NEW_PASSWORD) {
10469                 return true;
10470             }
10471             return HasAutoFillPasswordNode();
10472         }
10473     }
10474 
10475     auto aceInputType = ConvertToAceAutoFillType(layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED));
10476     if (aceInputType != AceAutoFillType::ACE_UNSPECIFIED) {
10477         if (aceInputType == AceAutoFillType::ACE_PASSWORD || aceInputType == AceAutoFillType::ACE_NEW_PASSWORD) {
10478             return true;
10479         }
10480     }
10481     return HasAutoFillPasswordNode();
10482 }
10483 
10484 bool TextFieldPattern::IsNeedProcessAutoFill()
10485 {
10486     return true;
10487 }
10488 
10489 std::vector<RectF> TextFieldPattern::GetTextBoxesForSelect()
10490 {
10491     auto selectedRects = GetTextBoxes();
10492     CHECK_NULL_RETURN(paragraph_, selectedRects);
10493     auto paragraphStyle = paragraph_->GetParagraphStyle();
10494     auto textAlign = TextBase::CheckTextAlignByDirection(paragraphStyle.align, paragraphStyle.direction);
10495     const float blankWidth = TextBase::GetSelectedBlankLineWidth();
10496     auto contentWidth = GetTextContentRect().Width();
10497     TextBase::CalculateSelectedRectEx(selectedRects, -1.0f);
10498     for (auto& rect : selectedRects) {
10499         TextBase::UpdateSelectedBlankLineRect(rect, blankWidth, textAlign, contentWidth);
10500     }
10501     return selectedRects;
10502 }
10503 
10504 void TextFieldPattern::AdjustSelectedBlankLineWidth(RectF& rect)
10505 {
10506     CHECK_NULL_VOID(paragraph_);
10507     auto paragraphStyle = paragraph_->GetParagraphStyle();
10508     auto textAlign = TextBase::CheckTextAlignByDirection(paragraphStyle.align, paragraphStyle.direction);
10509     const float blankWidth = TextBase::GetSelectedBlankLineWidth();
10510     auto contentWidth = GetTextContentRect().Width();
10511     TextBase::UpdateSelectedBlankLineRect(rect, blankWidth, textAlign, contentWidth + GetTextContentRect().Left());
10512 }
10513 
10514 std::optional<TouchLocationInfo> TextFieldPattern::GetAcceptedTouchLocationInfo(const TouchEventInfo& info)
10515 {
10516     auto touchInfos = info.GetChangedTouches();
10517     if (touchInfos.empty()) {
10518         return std::nullopt;
10519     }
10520     if (!moveCaretState_.isMoveCaret && !IsGestureSelectingText()) {
10521         return touchInfos.front();
10522     }
10523     auto fingerId = moveCaretState_.isMoveCaret ? moveCaretState_.touchFingerId : GetSelectingFingerId();
10524     for (auto touchInfo : touchInfos) {
10525         if (touchInfo.GetFingerId() == fingerId) {
10526             return touchInfo;
10527         }
10528     }
10529     return std::nullopt;
10530 }
10531 
10532 void TextFieldPattern::DoTextSelectionTouchCancel()
10533 {
10534     CHECK_NULL_VOID(magnifierController_);
10535     magnifierController_->RemoveMagnifierFrameNode();
10536     selectController_->UpdateCaretIndex(selectController_->GetCaretIndex());
10537     StopContentScroll();
10538     StartTwinkling();
10539 }
10540 
10541 float TextFieldPattern::GetVerticalPaddingAndBorderSum() const
10542 {
10543     auto border = GetBorderWidthProperty();
10544     if (utilPadding_.has_value()) {
10545         return utilPadding_.value().top.value_or(0.0f) + utilPadding_.value().bottom.value_or(0.0f) +
10546                GetBorderTop(border) + GetBorderBottom(border);
10547     }
10548     auto textFieldTheme = GetTheme();
10549     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10550     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10551     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10552     CHECK_NULL_RETURN(layoutProperty, themePadding.Top().ConvertToPx() + themePadding.Bottom().ConvertToPx());
10553     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10554     CHECK_NULL_RETURN(paddingProperty, themePadding.Top().ConvertToPx() + themePadding.Bottom().ConvertToPx());
10555 
10556     auto result = static_cast<float>(
10557         paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension().ConvertToPx() +
10558         paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension().ConvertToPx());
10559     return result + GetBorderTop(border) + GetBorderBottom(border);
10560 }
10561 
10562 float TextFieldPattern::GetHorizontalPaddingAndBorderSum() const
10563 {
10564     auto border = GetBorderWidthProperty();
10565     if (utilPadding_.has_value()) {
10566         return utilPadding_.value().left.value_or(0.0f) + utilPadding_.value().right.value_or(0.0f) +
10567                GetBorderLeft(border) + GetBorderRight(border);
10568     }
10569     auto textFieldTheme = GetTheme();
10570     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10571     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10572     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10573     CHECK_NULL_RETURN(layoutProperty, themePadding.Left().ConvertToPx() + themePadding.Right().ConvertToPx());
10574     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10575     CHECK_NULL_RETURN(paddingProperty, themePadding.Left().ConvertToPx() + themePadding.Right().ConvertToPx());
10576     auto padding = static_cast<float>(
10577         paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension().ConvertToPx() +
10578         paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension().ConvertToPx());
10579     return padding + GetBorderLeft(border) + GetBorderRight(border);
10580 }
10581 
10582 float TextFieldPattern::GetPaddingTop() const
10583 {
10584     if (utilPadding_.has_value()) {
10585         return utilPadding_.value().top.value_or(0.0f);
10586     }
10587     auto textFieldTheme = GetTheme();
10588     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10589     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10590     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10591     CHECK_NULL_RETURN(layoutProperty, themePadding.Top().ConvertToPx());
10592     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10593     CHECK_NULL_RETURN(paddingProperty, themePadding.Top().ConvertToPx());
10594     return static_cast<float>(
10595         paddingProperty->top.value_or(CalcLength(themePadding.Top())).GetDimension().ConvertToPx());
10596 }
10597 
10598 float TextFieldPattern::GetPaddingBottom() const
10599 {
10600     if (utilPadding_.has_value()) {
10601         return utilPadding_.value().bottom.value_or(0.0f);
10602     }
10603     auto textFieldTheme = GetTheme();
10604     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10605     auto themePadding = IsUnderlineMode() ? textFieldTheme->GetUnderlinePadding() : textFieldTheme->GetPadding();
10606     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10607     CHECK_NULL_RETURN(layoutProperty, themePadding.Bottom().ConvertToPx());
10608     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10609     CHECK_NULL_RETURN(paddingProperty, themePadding.Bottom().ConvertToPx());
10610     return static_cast<float>(
10611         paddingProperty->bottom.value_or(CalcLength(themePadding.Bottom())).GetDimension().ConvertToPx());
10612 }
10613 
10614 float TextFieldPattern::GetPaddingLeft() const
10615 {
10616     if (utilPadding_.has_value()) {
10617         return utilPadding_.value().left.value_or(0.0f);
10618     }
10619     auto textFieldTheme = GetTheme();
10620     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10621     auto themePadding = IsUnderlineMode() ? GetUnderlinePadding(textFieldTheme, true, false) :
10622         textFieldTheme->GetPadding();
10623     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10624     CHECK_NULL_RETURN(layoutProperty, themePadding.Left().ConvertToPx());
10625     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10626     CHECK_NULL_RETURN(paddingProperty, themePadding.Left().ConvertToPx());
10627     return static_cast<float>(
10628         paddingProperty->left.value_or(CalcLength(themePadding.Left())).GetDimension().ConvertToPx());
10629 }
10630 
10631 float TextFieldPattern::GetPaddingRight() const
10632 {
10633     if (utilPadding_.has_value()) {
10634         return utilPadding_.value().right.value_or(0.0f);
10635     }
10636     auto textFieldTheme = GetTheme();
10637     CHECK_NULL_RETURN(textFieldTheme, 0.0f);
10638     auto themePadding = IsUnderlineMode() ? GetUnderlinePadding(textFieldTheme, false, true) :
10639         textFieldTheme->GetPadding();
10640     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10641     CHECK_NULL_RETURN(layoutProperty, themePadding.Right().ConvertToPx());
10642     const auto& paddingProperty = layoutProperty->GetPaddingProperty();
10643     CHECK_NULL_RETURN(paddingProperty, themePadding.Right().ConvertToPx());
10644     return static_cast<float>(
10645         paddingProperty->right.value_or(CalcLength(themePadding.Right())).GetDimension().ConvertToPx());
10646 }
10647 
10648 BorderWidthProperty TextFieldPattern::GetBorderWidthProperty() const
10649 {
10650     BorderWidthProperty currentBorderWidth;
10651     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10652     CHECK_NULL_RETURN(layoutProperty, currentBorderWidth);
10653     if (layoutProperty->GetBorderWidthProperty() != nullptr) {
10654         currentBorderWidth = *(layoutProperty->GetBorderWidthProperty());
10655     } else {
10656         currentBorderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
10657     }
10658     return currentBorderWidth;
10659 }
10660 
10661 float TextFieldPattern::GetBorderLeft(BorderWidthProperty border) const
10662 {
10663     auto leftBorderWidth = border.leftDimen.value_or(Dimension(0.0f));
10664     auto percentReferenceWidth = GetPercentReferenceWidth();
10665     if (leftBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10666         return leftBorderWidth.Value() * percentReferenceWidth;
10667     }
10668     return leftBorderWidth.ConvertToPx();
10669 }
10670 
10671 float TextFieldPattern::GetBorderTop(BorderWidthProperty border) const
10672 {
10673     auto topBorderWidth = border.topDimen.value_or(Dimension(0.0f));
10674     auto percentReferenceWidth = GetPercentReferenceWidth();
10675     if (topBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10676         return topBorderWidth.Value() * percentReferenceWidth;
10677     }
10678     return topBorderWidth.ConvertToPx();
10679 }
10680 
10681 float TextFieldPattern::GetBorderBottom(BorderWidthProperty border) const
10682 {
10683     auto bottomBorderWidth = border.bottomDimen.value_or(Dimension(0.0f));
10684     auto percentReferenceWidth = GetPercentReferenceWidth();
10685     if (bottomBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10686         return bottomBorderWidth.Value() * percentReferenceWidth;
10687     }
10688     return bottomBorderWidth.ConvertToPx();
10689 }
10690 
10691 float TextFieldPattern::GetBorderRight(BorderWidthProperty border) const
10692 {
10693     auto rightBorderWidth = border.rightDimen.value_or(Dimension(0.0f));
10694     auto percentReferenceWidth = GetPercentReferenceWidth();
10695     if (rightBorderWidth.Unit() == DimensionUnit::PERCENT && percentReferenceWidth > 0) {
10696         return rightBorderWidth.Value() * percentReferenceWidth;
10697     }
10698     return rightBorderWidth.ConvertToPx();
10699 }
10700 
10701 void TextFieldPattern::ResetFirstClickAfterGetFocus()
10702 {
10703     if (!firstClickAfterLosingFocus_) {
10704         return;
10705     }
10706     auto host = GetHost();
10707     CHECK_NULL_VOID(host);
10708     auto pipeline = host->GetContext();
10709     CHECK_NULL_VOID(pipeline);
10710     auto taskExecutor = pipeline->GetTaskExecutor();
10711     CHECK_NULL_VOID(taskExecutor);
10712     firstClickResetTask_.Cancel();
10713     firstClickResetTask_.Reset([weak = WeakClaim(this)]() {
10714         auto pattern = weak.Upgrade();
10715         CHECK_NULL_VOID(pattern);
10716         pattern->firstClickAfterLosingFocus_ = false;
10717     });
10718     taskExecutor->PostDelayedTask(
10719         firstClickResetTask_, TaskExecutor::TaskType::UI, TWINKLING_INTERVAL_MS, "ResetFirstClickAfterGetFocusTask");
10720 }
10721 
10722 SelectionInfo TextFieldPattern::GetSelection()
10723 {
10724     SelectionInfo selection;
10725     selection.SetSelectionStart(selectController_->GetStartIndex());
10726     selection.SetSelectionEnd(selectController_->GetEndIndex());
10727     return selection;
10728 }
10729 
10730 FocusPattern TextFieldPattern::GetFocusPattern() const
10731 {
10732     FocusPattern focusPattern = { FocusType::NODE, true, FocusStyleType::FORCE_NONE };
10733     focusPattern.SetIsFocusActiveWhenFocused(true);
10734     auto host = GetHost();
10735     CHECK_NULL_RETURN(host, focusPattern);
10736     auto pipelineContext = host->GetContext();
10737     CHECK_NULL_RETURN(pipelineContext, focusPattern);
10738     auto theme = pipelineContext->GetTheme<TextFieldTheme>();
10739     CHECK_NULL_RETURN(theme, focusPattern);
10740     if (theme->NeedFocusBox()) {
10741         focusPattern.SetStyleType(FocusStyleType::OUTER_BORDER);
10742     }
10743     return focusPattern;
10744 }
10745 
10746 bool TextFieldPattern::FireOnWillChange(const ChangeValueInfo& changeValueInfo)
10747 {
10748     auto host = GetHost();
10749     CHECK_NULL_RETURN(host, true);
10750     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
10751     CHECK_NULL_RETURN(eventHub, true);
10752     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10753     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10754     callbackOldContent_ = changeValueInfo.oldContent;
10755     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10756     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10757 }
10758 
10759 bool TextFieldPattern::OnWillChangePreInsert(const std::u16string& insertValue, const std::u16string& oldContent,
10760     uint32_t start, uint32_t end)
10761 {
10762     auto host = GetHost();
10763     CHECK_NULL_RETURN(host, true);
10764     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
10765     CHECK_NULL_RETURN(eventHub, true);
10766     ChangeValueInfo changeValueInfo;
10767     PreviewText previewText {.offset = -1, .value = u""};
10768     if (hasPreviewText_) {
10769         previewText.offset = GetPreviewTextStart();
10770         previewText.value = GetPreviewTextValue();
10771     }
10772     changeValueInfo.oldPreviewText = previewText;
10773     changeValueInfo.previewText = previewText;
10774 
10775     auto insertLength = insertValue.length();
10776     changeValueInfo.rangeBefore = TextRange { start, end };
10777     changeValueInfo.rangeAfter = TextRange { start, start + insertLength };
10778 
10779     changeValueInfo.oldContent = oldContent;
10780     changeValueInfo.value = contentController_->GetTextUtf16Value();
10781     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10782     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10783     callbackOldContent_ = changeValueInfo.oldContent;
10784     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10785     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10786 }
10787 
10788 bool TextFieldPattern::OnWillChangePreDelete(const std::u16string& oldContent, uint32_t start, uint32_t end)
10789 {
10790     auto host = GetHost();
10791     CHECK_NULL_RETURN(host, true);
10792     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
10793     CHECK_NULL_RETURN(eventHub, true);
10794     ChangeValueInfo changeValueInfo;
10795     PreviewText previewText {.offset = -1, .value = u""};
10796     if (hasPreviewText_) {
10797         previewText.offset = GetPreviewTextStart();
10798         previewText.value = GetPreviewTextValue();
10799     }
10800     changeValueInfo.oldPreviewText = previewText;
10801     changeValueInfo.previewText = previewText;
10802 
10803     changeValueInfo.rangeBefore = TextRange { start, end };
10804     changeValueInfo.rangeAfter = TextRange { start, start };
10805 
10806     changeValueInfo.oldContent = oldContent;
10807     changeValueInfo.value = contentController_->GetTextUtf16Value();
10808     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10809     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10810     callbackOldContent_ = changeValueInfo.oldContent;
10811     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10812     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10813 }
10814 
10815 bool TextFieldPattern::OnWillChangePreSetValue(const std::u16string& newValue)
10816 {
10817     auto host = GetHost();
10818     CHECK_NULL_RETURN(host, true);
10819     auto eventHub = host->GetOrCreateEventHub<TextFieldEventHub>();
10820     CHECK_NULL_RETURN(eventHub, true);
10821     ChangeValueInfo changeValueInfo;
10822     changeValueInfo.oldContent = contentController_->GetTextUtf16Value();
10823     changeValueInfo.value = newValue;
10824     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10825     changeValueInfo.previewText.value = GetPreviewTextValue();
10826     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10827     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
10828     changeValueInfo.rangeBefore = TextRange { 0, contentController_->GetTextUtf16Value().length() };
10829     changeValueInfo.rangeAfter = TextRange { 0, newValue.length() };
10830     callbackRangeBefore_ = changeValueInfo.rangeBefore;
10831     callbackRangeAfter_ = changeValueInfo.rangeAfter;
10832     callbackOldContent_ = changeValueInfo.oldContent;
10833     callbackOldPreviewText_ = changeValueInfo.oldPreviewText;
10834     return eventHub->FireOnWillChangeEvent(changeValueInfo);
10835 }
10836 
10837 void TextFieldPattern::RecoverTextValueAndCaret(const std::u16string& oldValue, TextRange caretIndex)
10838 {
10839     contentController_->SetTextValueOnly(oldValue);
10840     selectController_->UpdateHandleIndex(caretIndex.start, caretIndex.end);
10841     if (IsSelected()) {
10842         ProcessOverlay({ .menuIsShow = false });
10843     }
10844 }
10845 
10846 void TextFieldPattern::AddInsertCommand(const std::u16string& insertValue, InputReason reason)
10847 {
10848     auto host = GetHost();
10849     CHECK_NULL_VOID(host);
10850     ACE_SCOPED_TRACE("TextInput[%d]AddInsertCommand freeze:[%d] previewText:[%d]", host->GetId(),
10851         host->IsFreeze(), GetIsPreviewText());
10852     if (reason != InputReason::PASTE) {
10853         if (!HasFocus()) {
10854             int32_t frameId = host->GetId();
10855             TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "textfield %{public}d on blur, can't insert value", frameId);
10856             int32_t depth = host->GetDepth();
10857             std::string errorType = "textfield on blur, can't insert value";
10858             EventReport::ReportTextFieldErrorEvent(frameId, depth, errorType);
10859             auto currentFocusNode = InputMethodManager::GetInstance()->GetCurFocusNode();
10860             auto curFocusNode = currentFocusNode.Upgrade();
10861             CHECK_NULL_VOID(curFocusNode);
10862             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "curFocusNode:%{public}s, ", curFocusNode->GetTag().c_str());
10863             return;
10864         }
10865         if (!isEdit_ || (reason == InputReason::IME && IsDragging())) {
10866             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD,
10867                 "textfield %{public}d NOT allow input, isEdit_ = %{public}d, IsDragging = %{public}d", host->GetId(),
10868                 isEdit_, IsDragging());
10869             return;
10870         }
10871     }
10872     if (focusIndex_ != FocuseIndex::TEXT) {
10873         if (insertValue == u" ") {
10874             HandleSpaceEvent();
10875         }
10876         return;
10877     }
10878     if (FinishTextPreviewByPreview(insertValue)) {
10879         return;
10880     }
10881     inputOperations_.emplace(InputOperation::INSERT);
10882     InsertCommandInfo info;
10883     info.insertValue = insertValue;
10884     info.reason = reason;
10885     insertCommands_.emplace(info);
10886     CloseSelectOverlay(true);
10887     ScrollToSafeArea();
10888     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
10889 }
10890 
10891 void TextFieldPattern::AddInputCommand(const InputCommandInfo& inputCommandInfo)
10892 {
10893     auto host = GetHost();
10894     CHECK_NULL_VOID(host);
10895     inputOperations_.emplace(InputOperation::INPUT);
10896     inputCommands_.emplace(inputCommandInfo);
10897     CloseSelectOverlay(true);
10898     ScrollToSafeArea();
10899     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
10900 }
10901 
10902 void TextFieldPattern::ExecuteInputCommand(const InputCommandInfo& info)
10903 {
10904     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
10905     CHECK_NULL_VOID(layoutProperty);
10906     auto start = info.deleteRange.start;
10907     auto end = info.deleteRange.end;
10908     auto insertValue = info.insertValue;
10909     auto caretIndex = info.insertOffset;
10910     auto originCaretIndex =
10911             TextRange { selectController_->GetFirstHandleIndex(), selectController_->GetSecondHandleIndex() };
10912     if ((info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) && !insertValue.empty()) {
10913         auto isInsert = BeforeIMEInsertValue(insertValue, caretIndex - (end - start));
10914         CHECK_NULL_VOID(isInsert);
10915     }
10916 
10917     ChangeValueInfo changeValueInfo;
10918     changeValueInfo.oldContent = contentController_->GetTextUtf16Value();
10919     changeValueInfo.oldPreviewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10920     changeValueInfo.oldPreviewText.value = GetPreviewTextValue();
10921     changeValueInfo.rangeBefore = TextRange { start, end };
10922 
10923     auto isDelete = true;
10924     if (start != end) {
10925         auto deleteValue = contentController_->GetSelectedValue(start, end);
10926         if (info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) {
10927             isDelete = BeforeIMEDeleteValue(deleteValue, TextDeleteDirection::BACKWARD, end);
10928         }
10929         contentController_->erase(start, end - start);
10930         selectController_->UpdateCaretIndex(start);
10931         if ((info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) && isDelete) {
10932             AfterIMEDeleteValue(deleteValue, TextDeleteDirection::BACKWARD);
10933         }
10934     }
10935 
10936     int32_t insertLength = 0;
10937     if (!insertValue.empty()) {
10938         if (info.insertOffset >= end && isDelete) {
10939             caretIndex = caretIndex - (end - start);
10940         }
10941         auto originLength = contentController_->GetTextUtf16Value().length();
10942         auto hasInsertValue = contentController_->InsertValue(caretIndex, info.insertValue);
10943         insertLength = static_cast<int32_t>(contentController_->GetTextUtf16Value().length() - originLength);
10944         caretIndex += insertLength;
10945 
10946         if (layoutProperty->HasMaxLength()) {
10947             CalcCounterAfterFilterInsertValue(originLength, insertValue,
10948                 static_cast<int32_t>(layoutProperty->GetMaxLengthValue(Infinity<uint32_t>())));
10949         }
10950         selectController_->UpdateCaretIndex(caretIndex);
10951         UpdateObscure(insertValue, hasInsertValue);
10952         if (info.reason == InputReason::IME || info.reason == InputReason::AI_WRITE) {
10953             AfterIMEInsertValue(contentController_->GetInsertValue());
10954         }
10955     }
10956 
10957     changeValueInfo.value = contentController_->GetTextUtf16Value();
10958     changeValueInfo.previewText.offset = hasPreviewText_ ? GetPreviewTextStart() : -1;
10959     changeValueInfo.previewText.value = GetPreviewTextValue();
10960     changeValueInfo.rangeAfter = TextRange { caretIndex - insertLength, caretIndex };
10961 
10962     bool isWillChange = FireOnWillChange(changeValueInfo);
10963     if (!isWillChange) {
10964         RecoverTextValueAndCaret(changeValueInfo.oldContent, originCaretIndex);
10965         return;
10966     }
10967     UpdateEditingValueToRecord();
10968     TwinklingByFocus();
10969 }
10970 
10971 void TextFieldPattern::ClearTextContent()
10972 {
10973     if (GetIsPreviewText()) {
10974         PreviewTextInfo info = {
10975             .text = u"",
10976             .range = {-1, -1}
10977         };
10978         SetPreviewTextOperation(info);
10979         hasPreviewText_ = false;
10980     }
10981     if (contentController_->IsEmpty()) {
10982         return;
10983     }
10984     showCountBorderStyle_ = false;
10985     HandleCountStyle();
10986     InputCommandInfo inputCommandInfo;
10987     inputCommandInfo.deleteRange = { 0, contentController_->GetTextUtf16Value().length() };
10988     inputCommandInfo.insertOffset = 0;
10989     inputCommandInfo.insertValue = u"";
10990     inputCommandInfo.reason = InputReason::CANCEL_BUTTON;
10991     AddInputCommand(inputCommandInfo);
10992 }
10993 
10994 // return: whether the offset is valid, return false if invalid
10995 bool TextFieldPattern::GetOriginCaretPosition(OffsetF& offset) const
10996 {
10997     if (!originCaretPosition_.NonNegative()) {
10998         return false;
10999     }
11000     offset = originCaretPosition_;
11001     return true;
11002 }
11003 
11004 void TextFieldPattern::ResetOriginCaretPosition()
11005 {
11006     originCaretPosition_ = DEFAULT_NEGATIVE_CARET_OFFSET;
11007 }
11008 
11009 // Record current caret position if originCaretPosition_ is invalid
11010 // return: whether the current offset is recorded and valid
11011 bool TextFieldPattern::RecordOriginCaretPosition()
11012 {
11013     if (originCaretPosition_.NonNegative()) {
11014         return false;
11015     }
11016     originCaretPosition_ = selectController_->GetCaretRect().GetOffset();
11017     return originCaretPosition_.NonNegative();
11018 }
11019 
11020 void TextFieldPattern::SetIsEnableSubWindowMenu()
11021 {
11022     if (selectOverlay_) {
11023         auto enable = !IsNeedProcessAutoFill() || !CheckAutoFill();
11024         selectOverlay_->SetIsHostNodeEnableSubWindowMenu(enable);
11025         if (!enable) {
11026             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetIsEnableSubWindowMenu not enable");
11027         }
11028     }
11029 }
11030 
11031 void TextFieldPattern::InitCancelButtonMouseEvent()
11032 {
11033     CHECK_NULL_VOID(cleanNodeResponseArea_);
11034     auto cleanNodeResponseArea = AceType::DynamicCast<CleanNodeResponseArea>(cleanNodeResponseArea_);
11035     CHECK_NULL_VOID(cleanNodeResponseArea);
11036     auto stackNode = cleanNodeResponseArea->GetFrameNode();
11037     CHECK_NULL_VOID(stackNode);
11038     auto imageTouchHub = stackNode->GetOrCreateGestureEventHub();
11039     CHECK_NULL_VOID(imageTouchHub);
11040     auto imageInputHub = stackNode->GetOrCreateInputEventHub();
11041     CHECK_NULL_VOID(imageInputHub);
11042     auto imageHoverTask = [weak = WeakClaim(this), cleanNodeResponseAreaWeak =
11043         WeakPtr<TextInputResponseArea>(cleanNodeResponseArea_)](bool isHover, const HoverInfo& info) {
11044             auto cleanNodeResponseArea = cleanNodeResponseAreaWeak.Upgrade();
11045             CHECK_NULL_VOID(cleanNodeResponseArea);
11046             auto pattern = weak.Upgrade();
11047             if (pattern) {
11048                 pattern->OnHover(isHover, info);
11049                 pattern->HandleButtonMouseEvent(cleanNodeResponseArea, isHover);
11050             }
11051     };
11052     imageHoverEvent_ = MakeRefPtr<InputEvent>(std::move(imageHoverTask));
11053     imageInputHub->AddOnHoverEvent(imageHoverEvent_);
11054 
11055     auto imageTouchTask = [weak = WeakClaim(this), cleanNodeResponseAreaWeak =
11056         WeakPtr<TextInputResponseArea>(cleanNodeResponseArea_)](const TouchEventInfo& info) {
11057             auto cleanNodeResponseArea = cleanNodeResponseAreaWeak.Upgrade();
11058             CHECK_NULL_VOID(cleanNodeResponseArea);
11059             auto pattern = weak.Upgrade();
11060             CHECK_NULL_VOID(pattern);
11061             auto touchType = info.GetTouches().front().GetTouchType();
11062             if (touchType == TouchType::DOWN) {
11063                 pattern->HandleCancelButtonTouchDown(cleanNodeResponseArea);
11064             }
11065             if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
11066                 pattern->HandleCancelButtonTouchUp();
11067             }
11068     };
11069 
11070     imageTouchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(imageTouchTask));
11071     imageTouchHub->AddTouchEvent(imageTouchEvent_);
11072 }
11073 
11074 void TextFieldPattern::InitPasswordButtonMouseEvent()
11075 {
11076     CHECK_NULL_VOID(responseArea_);
11077     auto passwordResponseArea = AceType::DynamicCast<PasswordResponseArea>(responseArea_);
11078     CHECK_NULL_VOID(passwordResponseArea);
11079     auto stackNode = passwordResponseArea->GetFrameNode();
11080     CHECK_NULL_VOID(stackNode);
11081     auto imageTouchHub = stackNode->GetOrCreateGestureEventHub();
11082     CHECK_NULL_VOID(imageTouchHub);
11083     auto imageInputHub = stackNode->GetOrCreateInputEventHub();
11084     CHECK_NULL_VOID(imageInputHub);
11085     auto imageHoverTask = [weak = WeakClaim(this), responseAreaWeak =
11086         WeakPtr<TextInputResponseArea>(responseArea_)](bool isHover, const HoverInfo& info) {
11087             auto responseArea = responseAreaWeak.Upgrade();
11088             CHECK_NULL_VOID(responseArea);
11089             auto pattern = weak.Upgrade();
11090             if (pattern) {
11091                 pattern->OnHover(isHover, info);
11092                 pattern->HandleButtonMouseEvent(responseArea, isHover);
11093             }
11094     };
11095     imageHoverEvent_ = MakeRefPtr<InputEvent>(std::move(imageHoverTask));
11096     imageInputHub->AddOnHoverEvent(imageHoverEvent_);
11097 
11098     auto imageTouchTask = [weak = WeakClaim(this), responseAreaWeak = WeakPtr<TextInputResponseArea>(responseArea_)]
11099         (const TouchEventInfo& info) {
11100             auto responseArea = responseAreaWeak.Upgrade();
11101             CHECK_NULL_VOID(responseArea);
11102             auto pattern = weak.Upgrade();
11103             CHECK_NULL_VOID(pattern);
11104             auto touchType = info.GetTouches().front().GetTouchType();
11105             if (touchType == TouchType::DOWN) {
11106                 pattern->HandleCancelButtonTouchDown(responseArea);
11107             }
11108             if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
11109                 pattern->HandleCancelButtonTouchUp();
11110             }
11111     };
11112     imageTouchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(imageTouchTask));
11113     imageTouchHub->AddTouchEvent(imageTouchEvent_);
11114 }
11115 
11116 void TextFieldPattern::HandleCancelButtonTouchDown(const RefPtr<TextInputResponseArea>& responseArea)
11117 {
11118     auto host = GetHost();
11119     CHECK_NULL_VOID(host);
11120     RoundRect mouseRect;
11121     CHECK_NULL_VOID(responseArea);
11122     responseArea->CreateIconRect(mouseRect, false);
11123     float cornerRadius = mouseRect.GetRect().Width() / 2;
11124     mouseRect.SetCornerRadius(cornerRadius);
11125     auto textFieldTheme = GetTheme();
11126     CHECK_NULL_VOID(textFieldTheme);
11127     auto touchColor = textFieldTheme->GetPressColor();
11128     std::vector<RoundRect> roundRectVector;
11129     roundRectVector.push_back(mouseRect);
11130     CHECK_NULL_VOID(textFieldOverlayModifier_);
11131     textFieldOverlayModifier_->SetHoverColorAndRects(roundRectVector, touchColor.GetValue());
11132     cancelButtonTouched_ = true;
11133     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
11134 }
11135 
11136 void TextFieldPattern::HandleCancelButtonTouchUp()
11137 {
11138     auto host = GetHost();
11139     CHECK_NULL_VOID(host);
11140     CHECK_NULL_VOID(textFieldOverlayModifier_);
11141     textFieldOverlayModifier_->ClearHoverColorAndRects();
11142     cancelButtonTouched_ = false;
11143     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
11144 }
11145 
11146 void TextFieldPattern::HandleButtonMouseEvent(const RefPtr<TextInputResponseArea>& responseArea, bool isHover)
11147 {
11148     auto host = GetHost();
11149     CHECK_NULL_VOID(host);
11150     CHECK_NULL_VOID(textFieldOverlayModifier_);
11151     if (isHover) {
11152         RoundRect mouseRect;
11153         CHECK_NULL_VOID(responseArea);
11154         responseArea->CreateIconRect(mouseRect, false);
11155         float cornerRadius = mouseRect.GetRect().Width() / 2;
11156         mouseRect.SetCornerRadius(cornerRadius);
11157         auto textFieldTheme = GetTheme();
11158         CHECK_NULL_VOID(textFieldTheme);
11159         auto touchColor = textFieldTheme->GetHoverColor();
11160         std::vector<RoundRect> roundRectVector;
11161         roundRectVector.push_back(mouseRect);
11162         textFieldOverlayModifier_->SetHoverColorAndRects(roundRectVector, touchColor.GetValue());
11163         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
11164     } else {
11165         textFieldOverlayModifier_->ClearHoverColorAndRects();
11166         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
11167     }
11168 }
11169 
11170 double TextFieldPattern::GetPercentReferenceWidth() const
11171 {
11172     auto host = GetHost();
11173     if (host && host->GetGeometryNode() && host->GetGeometryNode()->GetParentLayoutConstraint().has_value()) {
11174         return host->GetGeometryNode()->GetParentLayoutConstraint()->percentReference.Width();
11175     }
11176     return 0.0f;
11177 }
11178 
11179 void TextFieldPattern::NotifyKeyboardClosedByUser()
11180 {
11181     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "NotifyKeyboardClosedByUser");
11182     CHECK_NULL_VOID(HasFocus());
11183     isKeyboardClosedByUser_ = true;
11184     FocusHub::LostFocusToViewRoot();
11185     isKeyboardClosedByUser_ = false;
11186 }
11187 
11188 void TextFieldPattern::NotifyKeyboardClosed()
11189 {
11190     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "NotifyKeyboardClosed");
11191     CHECK_NULL_VOID(IsStopEditWhenCloseKeyboard()); // false when specified product
11192     if (HasFocus() && !(customKeyboard_ || customKeyboardBuilder_)) {
11193         FocusHub::LostFocusToViewRoot();
11194     }
11195 }
11196 
11197 bool TextFieldPattern::BetweenSelectedPosition(const Offset& globalOffset)
11198 {
11199     if (!IsSelected()) {
11200         return false;
11201     }
11202     auto localOffset = ConvertGlobalToLocalOffset(globalOffset);
11203     auto offsetX = IsTextArea() ? contentRect_.GetX() : textRect_.GetX();
11204     auto offsetY = IsTextArea() ? textRect_.GetY() : contentRect_.GetY();
11205     Offset offset = localOffset - Offset(offsetX, offsetY);
11206     for (const auto& rect : selectController_->GetSelectedRects()) {
11207         bool isInRange = rect.IsInRegion({ offset.GetX(), offset.GetY() });
11208         if (isInRange) {
11209             return true;
11210         }
11211     }
11212     return false;
11213 }
11214 
11215 void TextFieldPattern::SetUnitNode(const RefPtr<NG::UINode>& unitNode)
11216 {
11217     if (unitNode_ && responseArea_) {
11218         // clear old node
11219         auto unitResponseArea = AceType::DynamicCast<UnitResponseArea>(responseArea_);
11220         CHECK_NULL_VOID(unitResponseArea);
11221         unitResponseArea->ClearArea();
11222         responseArea_ = nullptr;
11223     }
11224     unitNode_ = unitNode;
11225 }
11226 
11227 void TextFieldPattern::SetCustomKeyboard(const std::function<void()>&& keyboardBuilder)
11228 {
11229     if (customKeyboardBuilder_ && isCustomKeyboardAttached_ && !keyboardBuilder) {
11230         // close customKeyboard and request system keyboard
11231         CloseCustomKeyboard();
11232         customKeyboardBuilder_ = keyboardBuilder; // refresh current keyboard
11233         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
11234         StartTwinkling();
11235         return;
11236     }
11237     if (!customKeyboardBuilder_ && keyboardBuilder) {
11238         // close system keyboard and request custom keyboard
11239 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
11240         if (imeShown_) {
11241             CloseKeyboard(true);
11242             customKeyboardBuilder_ = keyboardBuilder; // refresh current keyboard
11243             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
11244             StartTwinkling();
11245             return;
11246         }
11247 #endif
11248     }
11249     customKeyboardBuilder_ = keyboardBuilder;
11250 }
11251 
11252 void TextFieldPattern::SetCustomKeyboardWithNode(const RefPtr<UINode>& keyboardBuilder)
11253 {
11254     auto host = GetHost();
11255     FREE_NODE_CHECK(host, SetCustomKeyboardWithNode,
11256         keyboardBuilder);  // call SetCustomKeyboardWithNodeMultiThread() by multi thread
11257     if (customKeyboard_ && isCustomKeyboardAttached_ && !keyboardBuilder) {
11258         // close customKeyboard and request system keyboard
11259         CloseCustomKeyboard();
11260         customKeyboard_ = keyboardBuilder; // refresh current keyboard
11261         RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
11262         StartTwinkling();
11263         return;
11264     }
11265     if (!customKeyboard_ && keyboardBuilder) {
11266         // close system keyboard and request custom keyboard
11267 #if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
11268         if (imeShown_) {
11269             CloseKeyboard(true);
11270             customKeyboard_ = keyboardBuilder; // refresh current keyboard
11271             RequestKeyboardNotByFocusSwitch(RequestKeyboardReason::CUSTOM_KEYBOARD);
11272             StartTwinkling();
11273             return;
11274         }
11275 #endif
11276     }
11277     customKeyboard_ = keyboardBuilder;
11278 }
11279 
11280 bool TextFieldPattern::IsStopEditWhenCloseKeyboard()
11281 {
11282     auto host = GetHost();
11283     CHECK_NULL_RETURN(host, true);
11284     auto context = host->GetContext();
11285     CHECK_NULL_RETURN(context, true);
11286     return !(context->GetIsFocusActive() && independentControlKeyboard_);
11287 }
11288 
11289 void TextFieldPattern::OnReportPasteEvent(const RefPtr<FrameNode>& frameNode)
11290 {
11291     CHECK_NULL_VOID(frameNode);
11292     if (frameNode->GetTag() == V2::TEXTINPUT_ETS_TAG) {
11293         UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "TextInput.onPasteComplete");
11294         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "nodeId:[%{public}d] TextInput reportComponentChangeEvent onPasteComplete",
11295             frameNode->GetId());
11296     } else if (frameNode->GetTag() == V2::SEARCH_Field_ETS_TAG) {
11297         UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "Search.onPasteComplete");
11298         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "nodeId:[%{public}d] Search reportComponentChangeEvent onPasteComplete",
11299             frameNode->GetId());
11300     }
11301 }
11302 
11303 void TextFieldPattern::OnReportSubmitEvent(const RefPtr<FrameNode>& frameNode)
11304 {
11305     CHECK_NULL_VOID(frameNode);
11306     if (frameNode->GetTag() == V2::TEXTINPUT_ETS_TAG) {
11307         UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "TextInput.onSubmitComplete");
11308         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "nodeId:[%{public}d] TextInput reportComponentChangeEvent onSubmitComplete",
11309             frameNode->GetId());
11310     }
11311 }
11312 
11313 void TextFieldPattern::BeforeAutoFillAnimation(const std::u16string& content, const AceAutoFillType& type)
11314 {
11315     auto host = GetHost();
11316     CHECK_NULL_VOID(host);
11317     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
11318     CHECK_NULL_VOID(layoutProperty);
11319     auto enableAutoFillAnimation = layoutProperty->GetEnableAutoFillAnimationValue(true);
11320     auto textValue = content;
11321     contentController_->FilterValue(textValue);
11322     CHECK_NULL_VOID(GetOrCreateAutoFillController());
11323     autoFillController_->SetAutoFillTextUtf16Value(textValue);
11324     auto onFinishCallback = [weak = AceType::WeakClaim(this), textValue, unFilteredValue = content]() {
11325         auto textFieldPattern = weak.Upgrade();
11326         CHECK_NULL_VOID(textFieldPattern);
11327         auto autoFillController = textFieldPattern->GetOrCreateAutoFillController();
11328         CHECK_NULL_VOID(autoFillController);
11329         autoFillController->ResetAutoFillAnimationStatus();
11330         auto hostNode = textFieldPattern->GetHost();
11331         CHECK_NULL_VOID(hostNode);
11332         if (!textFieldPattern->OnWillChangePreSetValue(unFilteredValue)) {
11333             hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
11334             return;
11335         }
11336         auto contentController = textFieldPattern->GetTextContentController();
11337         CHECK_NULL_VOID(contentController);
11338         contentController->SetTextValue(unFilteredValue);
11339         auto textLength = static_cast<int32_t>(contentController->GetTextUtf16Value().length());
11340         auto selectController = textFieldPattern->GetTextSelectController();
11341         CHECK_NULL_VOID(selectController);
11342         selectController->UpdateCaretIndex(textLength);
11343         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
11344     };
11345     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
11346     auto needsAnimation = pipeline && enableAutoFillAnimation &&
11347                           (type == AceAutoFillType::ACE_NEW_PASSWORD || type == AceAutoFillType::ACE_PASSWORD) &&
11348                           textValue.length() > 0;
11349     if (needsAnimation) {
11350         autoFillController_->SetAutoFillAnimationStatus(AutoFillAnimationStatus::SHOW_ICON);
11351         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
11352         pipeline->AddAfterLayoutTask(
11353             [weak = AceType::WeakClaim(this), onFinish = std::move(onFinishCallback), textValue]() {
11354                 auto textFieldPattern = weak.Upgrade();
11355                 CHECK_NULL_VOID(textFieldPattern);
11356                 auto autoFillController = textFieldPattern->GetOrCreateAutoFillController();
11357                 CHECK_NULL_VOID(autoFillController);
11358                 autoFillController->StartAutoFillAnimation(onFinish, textValue);
11359             });
11360     } else {
11361         onFinishCallback();
11362     }
11363 }
11364 
11365 void TextFieldPattern::RemoveFillContentMap()
11366 {
11367     auto host = GetHost();
11368     CHECK_NULL_VOID(host);
11369     auto pipeline = host->GetContext();
11370     CHECK_NULL_VOID(pipeline);
11371     auto textFieldManager = DynamicCast<TextFieldManagerNG>(pipeline->GetTextFieldManager());
11372     CHECK_NULL_VOID(textFieldManager);
11373     auto nodeId = host->GetId();
11374     textFieldManager->RemoveFillContentMap(nodeId);
11375 }
11376 
11377 bool TextFieldPattern::NeedsSendFillContent()
11378 {
11379     CHECK_NULL_RETURN(IsNeedProcessAutoFill(), false);
11380     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
11381     CHECK_NULL_RETURN(layoutProperty, false);
11382     bool isEnableAutoFill = layoutProperty->GetEnableAutoFillValue(true);
11383     if (!isEnableAutoFill) {
11384         return false;
11385     }
11386     return IsTriggerAutoFillPassword();
11387 }
11388 
11389 void TextFieldPattern::OnAccessibilityEventTextChange(const std::string& changeType, const std::string& changeString)
11390 {
11391     auto pipeline = GetContext();
11392     CHECK_NULL_VOID(pipeline);
11393     auto host = GetHost();
11394     CHECK_NULL_VOID(host);
11395     AccessibilityEvent event;
11396     event.type = AccessibilityEventType::TEXT_CHANGE;
11397     event.nodeId = host->GetAccessibilityId();
11398     std::string finalText;
11399     if (IsInPasswordMode()) {
11400         char16_t obscuring =
11401         Localization::GetInstance()->GetLanguage() == "ar" ? OBSCURING_CHARACTER_FOR_AR : OBSCURING_CHARACTER;
11402         finalText = UtfUtils::Str16DebugToStr8(std::u16string(changeString.length(), obscuring));
11403     } else {
11404         finalText = changeString;
11405     }
11406     event.extraEventInfo.insert({ changeType, finalText });
11407     pipeline->SendEventToAccessibilityWithNode(event, GetHost());
11408 }
11409 
11410 IMEClient TextFieldPattern::GetIMEClientInfo()
11411 {
11412     IMEClient clientInfo;
11413     auto host = GetHost();
11414     CHECK_NULL_RETURN(host, clientInfo);
11415     clientInfo.nodeId = host->GetId();
11416     return clientInfo;
11417 }
11418 
11419 void TextFieldPattern::FireOnWillAttachIME()
11420 {
11421     auto host = GetHost();
11422     CHECK_NULL_VOID(host);
11423     auto eventHub = host->GetEventHub<TextFieldEventHub>();
11424     CHECK_NULL_VOID(eventHub);
11425     eventHub->FireOnWillAttachIME(GetIMEClientInfo());
11426 }
11427 
11428 void TextFieldPattern::OnColorModeChange(uint32_t colorMode)
11429 {
11430     Pattern::OnColorModeChange(colorMode);
11431     auto host = GetHost();
11432     CHECK_NULL_VOID(host);
11433     host->MarkModifyDone();
11434 }
11435 
11436 #define DEFINE_PROP_HANDLER(KEY_TYPE, VALUE_TYPE, UPDATE_METHOD)                            \
11437     {                                                                                       \
11438         #KEY_TYPE, [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {     \
11439             if (auto realValue = std::get_if<VALUE_TYPE>(&(value->GetValue()))) {           \
11440                 prop->UPDATE_METHOD(*realValue);                                            \
11441             }                                                                               \
11442         }                                                                                   \
11443     }
11444 
11445 void TextFieldPattern::UpdatePropertyImpl(const std::string& key, RefPtr<PropertyValueBase> value)
11446 {
11447     auto frameNode = GetHost();
11448     CHECK_NULL_VOID(frameNode);
11449     auto layoutProperty = frameNode->GetLayoutPropertyPtr<TextFieldLayoutProperty>();
11450     CHECK_NULL_VOID(layoutProperty);
11451     CHECK_NULL_VOID(value);
11452 
11453     using Handler = std::function<void(TextFieldLayoutProperty*, RefPtr<PropertyValueBase>)>;
11454     const std::unordered_map<std::string, Handler> handlers = {
11455         DEFINE_PROP_HANDLER(fontSize, CalcDimension, UpdateFontSize),
11456         DEFINE_PROP_HANDLER(decorationColor, Color, UpdateTextDecorationColor),
11457         DEFINE_PROP_HANDLER(minFontSize, CalcDimension, UpdateAdaptMinFontSize),
11458         DEFINE_PROP_HANDLER(maxFontSize, CalcDimension, UpdateAdaptMaxFontSize),
11459         DEFINE_PROP_HANDLER(lineHeight, CalcDimension, UpdateLineHeight),
11460         DEFINE_PROP_HANDLER(lineHeight, CalcDimension, UpdateLineHeight),
11461         DEFINE_PROP_HANDLER(cancelButtonIconSrc, std::string, UpdateIconSrc),
11462 
11463         {"placeholder", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11464                 if (auto realValue = std::get_if<std::u16string>(&(value->GetValue()))) {
11465                     prop->UpdatePlaceholder(*realValue);
11466                 }
11467             }
11468         },
11469 
11470         {"text", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11471                 if (auto realValue = std::get_if<std::u16string>(&(value->GetValue()))) {
11472                     auto pattern = wp.Upgrade();
11473                     CHECK_NULL_VOID(pattern);
11474                     auto oldValue = pattern->GetTextUtf16Value();
11475                     if (*realValue != oldValue) {
11476                         pattern->InitEditingValueText(*realValue);
11477                         pattern->SetTextChangedAtCreation(true);
11478                     }
11479                 }
11480             }
11481         },
11482 
11483         {"cancelButtonIconSize", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11484                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11485                     auto pattern = wp.Upgrade();
11486                     CHECK_NULL_VOID(pattern);
11487                     realValue->SetUnit(DimensionUnit::VP);
11488                     prop->UpdateIconSize(*realValue);
11489                     pattern->ProcessResponseArea();
11490                 }
11491             }
11492         },
11493 
11494         {"cancelButtonIconColor", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11495                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11496                     auto pattern = wp.Upgrade();
11497                     CHECK_NULL_VOID(pattern);
11498                     prop->UpdateIconColor(*realValue);
11499                     pattern->ProcessResponseArea();
11500                 }
11501             }
11502         },
11503 
11504         {"placeholderColor", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11505                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11506                     prop->UpdatePlaceholderTextColor(*realValue);
11507                     auto frameNode = wp.Upgrade();
11508                     CHECK_NULL_VOID(frameNode);
11509                     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, PlaceholderColorFlagByUser, true, frameNode);
11510                 }
11511             }
11512         },
11513 
11514         {"placeholderFontSize", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11515                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11516                     prop->UpdatePlaceholderFontSize(*realValue);
11517                     prop->UpdatePreferredPlaceholderLineHeightNeedToUpdate(true);
11518                 }
11519             }
11520         },
11521 
11522         {"placeholderFontFamily", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11523                 if (auto realValue = std::get_if<std::vector<std::string>>(&(value->GetValue()))) {
11524                     prop->UpdatePlaceholderFontFamily(*realValue);
11525                     prop->UpdatePreferredPlaceholderLineHeightNeedToUpdate(true);
11526                 }
11527             }
11528         },
11529 
11530         {"backgroundColor", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11531                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11532                     auto frameNode = wp.Upgrade();
11533                     CHECK_NULL_VOID(frameNode);
11534                     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, BackgroundColor, *realValue, frameNode);
11535                     ACE_UPDATE_NODE_RENDER_CONTEXT(BackgroundColor, *realValue, frameNode);
11536                 }
11537             }
11538         },
11539 
11540         {"foregroundColor", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11541                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11542                     prop->UpdateTextColor(*realValue);
11543                     auto frameNode = wp.Upgrade();
11544                     CHECK_NULL_VOID(frameNode);
11545                     auto renderContext = frameNode->GetRenderContext();
11546                     CHECK_NULL_VOID(renderContext);
11547                     if (renderContext->GetForegroundColorStrategy().has_value()) {
11548                         renderContext->UpdateForegroundColorStrategy(ForegroundColorStrategy::NONE);
11549                         renderContext->ResetForegroundColorStrategy();
11550                     }
11551                     renderContext->UpdateForegroundColor(*realValue);
11552                     renderContext->UpdateForegroundColorFlag(true);
11553                 }
11554             }
11555         },
11556 
11557         {"caretColor", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11558                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11559                     auto frameNode = wp.Upgrade();
11560                     CHECK_NULL_VOID(frameNode);
11561                     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, CursorColor, *realValue, frameNode);
11562                     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, CaretColorFlagByUser, true, frameNode);
11563                 }
11564             }
11565         },
11566 
11567         {"selectedBackgroundColor", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11568                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11569                     if (realValue->GetAlpha() == 255) {
11570                         *realValue = realValue->ChangeOpacity(0.2);
11571                     }
11572                     auto frameNode = wp.Upgrade();
11573                     CHECK_NULL_VOID(frameNode);
11574                     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, SelectedBackgroundColor, *realValue, frameNode);
11575                 }
11576             }
11577         },
11578 
11579         {"caretWidth", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11580                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11581                     auto pattern = wp.Upgrade();
11582                     CHECK_NULL_VOID(pattern);
11583                     auto frameNode = pattern->GetHost();
11584                     CHECK_NULL_VOID(frameNode);
11585                     realValue->SetUnit(DimensionUnit::VP);
11586                     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, CursorWidth, *realValue, frameNode);
11587                     pattern->CalculateDefaultCursor();
11588                 }
11589             }
11590         },
11591 
11592         {"letterSpacing", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11593                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11594                     auto frameNode = wp.Upgrade();
11595                     CHECK_NULL_VOID(frameNode);
11596                     realValue->SetUnit(DimensionUnit::VP);
11597                     prop->UpdateLetterSpacing(*realValue);
11598                 }
11599             }
11600         },
11601 
11602         {"width", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11603                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11604                     realValue->SetUnit(DimensionUnit::VP);
11605                     if (LessNotEqual(realValue->Value(), 0.0)) {
11606                         return;
11607                     }
11608                     CalcLength width(*realValue);
11609                     std::optional<CalcLength> height = std::nullopt;
11610                     auto&& layoutConstraint = prop->GetCalcLayoutConstraint();
11611                     if (layoutConstraint && layoutConstraint->selfIdealSize) {
11612                         height = layoutConstraint->selfIdealSize->Height();
11613                     }
11614                     prop->UpdateUserDefinedIdealSize(CalcSize(width, height));
11615                 }
11616             }
11617         },
11618 
11619         {"paddingTop", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11620                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11621                     auto frameNode = wp.Upgrade();
11622                     CHECK_NULL_VOID(frameNode);
11623                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11624                     CHECK_NULL_VOID(paintProperty);
11625                     PaddingProperty padding;
11626                     padding = paintProperty->GetPaddingByUserValue(padding);
11627                     realValue->SetUnit(DimensionUnit::VP);
11628                     padding.top = CalcLength(*realValue);
11629                     paintProperty->UpdatePaddingByUser(padding);
11630                 }
11631             }
11632         },
11633 
11634         {"paddingBottom", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11635                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11636                     auto frameNode = wp.Upgrade();
11637                     CHECK_NULL_VOID(frameNode);
11638                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11639                     CHECK_NULL_VOID(paintProperty);
11640                     PaddingProperty padding;
11641                     padding = paintProperty->GetPaddingByUserValue(padding);
11642                     realValue->SetUnit(DimensionUnit::VP);
11643                     padding.bottom = CalcLength(*realValue);
11644                     paintProperty->UpdatePaddingByUser(padding);
11645                 }
11646             }
11647         },
11648 
11649         {"paddingLeft", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11650                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11651                     auto frameNode = wp.Upgrade();
11652                     CHECK_NULL_VOID(frameNode);
11653                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11654                     CHECK_NULL_VOID(paintProperty);
11655                     PaddingProperty padding;
11656                     padding = paintProperty->GetPaddingByUserValue(padding);
11657                     realValue->SetUnit(DimensionUnit::VP);
11658                     padding.left = CalcLength(*realValue);
11659                     paintProperty->UpdatePaddingByUser(padding);
11660                 }
11661             }
11662         },
11663 
11664         {"paddingRight", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11665                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11666                     auto frameNode = wp.Upgrade();
11667                     CHECK_NULL_VOID(frameNode);
11668                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11669                     CHECK_NULL_VOID(paintProperty);
11670                     PaddingProperty padding;
11671                     padding = paintProperty->GetPaddingByUserValue(padding);
11672                     realValue->SetUnit(DimensionUnit::VP);
11673                     padding.right = CalcLength(*realValue);
11674                     paintProperty->UpdatePaddingByUser(padding);
11675                 }
11676             }
11677         },
11678 
11679         {"marginTop", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11680                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11681                     auto frameNode = wp.Upgrade();
11682                     CHECK_NULL_VOID(frameNode);
11683                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11684                     CHECK_NULL_VOID(paintProperty);
11685                     PaddingProperty margin;
11686                     margin = paintProperty->GetMarginByUserValue(margin);
11687                     realValue->SetUnit(DimensionUnit::VP);
11688                     margin.top = CalcLength(*realValue);
11689                     paintProperty->UpdatePaddingByUser(margin);
11690                 }
11691             }
11692         },
11693 
11694         {"marginBottom", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11695                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11696                     auto frameNode = wp.Upgrade();
11697                     CHECK_NULL_VOID(frameNode);
11698                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11699                     CHECK_NULL_VOID(paintProperty);
11700                     PaddingProperty margin;
11701                     margin = paintProperty->GetMarginByUserValue(margin);
11702                     realValue->SetUnit(DimensionUnit::VP);
11703                     margin.bottom = CalcLength(*realValue);
11704                     paintProperty->UpdatePaddingByUser(margin);
11705                 }
11706             }
11707         },
11708 
11709         {"marginLeft", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11710                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11711                     auto frameNode = wp.Upgrade();
11712                     CHECK_NULL_VOID(frameNode);
11713                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11714                     CHECK_NULL_VOID(paintProperty);
11715                     PaddingProperty margin;
11716                     margin = paintProperty->GetMarginByUserValue(margin);
11717                     realValue->SetUnit(DimensionUnit::VP);
11718                     margin.left = CalcLength(*realValue);
11719                     paintProperty->UpdatePaddingByUser(margin);
11720                 }
11721             }
11722         },
11723 
11724         {"marginRight", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11725                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11726                     auto frameNode = wp.Upgrade();
11727                     CHECK_NULL_VOID(frameNode);
11728                     auto paintProperty = frameNode->GetPaintProperty<TextFieldPaintProperty>();
11729                     CHECK_NULL_VOID(paintProperty);
11730                     PaddingProperty margin;
11731                     margin = paintProperty->GetMarginByUserValue(margin);
11732                     realValue->SetUnit(DimensionUnit::VP);
11733                     margin.right = CalcLength(*realValue);
11734                     paintProperty->UpdatePaddingByUser(margin);
11735                 }
11736             }
11737         },
11738 
11739         {"fontWeight", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11740                 if (auto realValue = std::get_if<std::string>(&(value->GetValue()))) {
11741                     FontWeight fontWeight = ConvertStrToFontWeight(*realValue);
11742                     prop->UpdateFontWeight(fontWeight);
11743                     prop->UpdatePreferredTextLineHeightNeedToUpdate(true);
11744                 }
11745             }
11746         },
11747 
11748         {"fontColor", [wp = WeakClaim(RawPtr(frameNode))](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11749                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11750                     prop->UpdateTextColor(*realValue);
11751                     auto frameNode = wp.Upgrade();
11752                     CHECK_NULL_VOID(frameNode);
11753                     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, *realValue, frameNode);
11754                     ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, ForegroundColorStrategy, frameNode);
11755                     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, frameNode);
11756                     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, TextColorFlagByUser, *realValue, frameNode);
11757                 }
11758             }
11759         },
11760 
11761         {"fontFamily", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11762                 if (auto realValue = std::get_if<std::vector<std::string>>(&(value->GetValue()))) {
11763                     prop->UpdateFontFamily(*realValue);
11764                     prop->UpdatePreferredTextLineHeightNeedToUpdate(true);
11765                 }
11766             }
11767         },
11768 
11769         {"errorString", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11770                 if (auto realValue = std::get_if<std::u16string>(&(value->GetValue()))) {
11771                     prop->UpdateErrorText(*realValue);
11772                     prop->UpdateShowErrorText(true);
11773                 }
11774             }
11775         },
11776 
11777         {"onIconSrc", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11778                 if (auto realValue = std::get_if<std::string>(&(value->GetValue()))) {
11779                     auto pattern = wp.Upgrade();
11780                     CHECK_NULL_VOID(pattern);
11781                     auto frameNode = pattern->GetHost();
11782                     CHECK_NULL_VOID(frameNode);
11783                     pattern->SetIsPasswordSymbol(false);
11784                     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TextFieldLayoutProperty, ShowPasswordSourceInfo,
11785                         ImageSourceInfo(*realValue, "", ""), frameNode);
11786                 }
11787             }
11788         },
11789 
11790         {"offIconSrc", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11791                 if (auto realValue = std::get_if<std::string>(&(value->GetValue()))) {
11792                     auto pattern = wp.Upgrade();
11793                     CHECK_NULL_VOID(pattern);
11794                     auto frameNode = pattern->GetHost();
11795                     CHECK_NULL_VOID(frameNode);
11796                     pattern->SetIsPasswordSymbol(false);
11797                     ACE_UPDATE_NODE_LAYOUT_PROPERTY(TextFieldLayoutProperty, HidePasswordSourceInfo,
11798                         ImageSourceInfo(*realValue, "", ""), frameNode);
11799                 }
11800             }
11801         },
11802 
11803         {"inputFilter", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11804                 if (auto realValue = std::get_if<std::string>(&(value->GetValue()))) {
11805                     prop->UpdateInputFilter(*realValue);
11806                     auto pattern = wp.Upgrade();
11807                     CHECK_NULL_VOID(pattern);
11808                     pattern->FilterInitializeText();
11809                 }
11810             }
11811         },
11812 
11813         {"underlineColorTyping", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11814                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11815                     auto pattern = wp.Upgrade();
11816                     CHECK_NULL_VOID(pattern);
11817                     pattern->SetTypingUnderlineColor(*realValue);
11818                 }
11819             }
11820         },
11821 
11822         {"underlineColorNormal", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11823                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11824                     auto pattern = wp.Upgrade();
11825                     CHECK_NULL_VOID(pattern);
11826                     pattern->SetNormalUnderlineColor(*realValue);
11827                 }
11828             }
11829         },
11830 
11831         {"underlineColorError", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11832                 if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11833                     auto pattern = wp.Upgrade();
11834                     CHECK_NULL_VOID(pattern);
11835                     pattern->SetErrorUnderlineColor(*realValue);
11836                 }
11837             }
11838         },
11839 
11840         {"underlineColorDisable", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11841             if (auto realValue = std::get_if<Color>(&(value->GetValue()))) {
11842                     auto pattern = wp.Upgrade();
11843                     CHECK_NULL_VOID(pattern);
11844                     pattern->SetDisableUnderlineColor(*realValue);
11845                 }
11846             }
11847         },
11848 
11849         {"textIndent", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11850                 if (auto realValue = std::get_if<CalcDimension>(&(value->GetValue()))) {
11851                     realValue->SetUnit(DimensionUnit::VP);
11852                     prop->UpdateTextIndent(*realValue);
11853                 }
11854             }
11855         },
11856 
11857         {"cancelButtonIconColorDefault", [wp = WeakClaim(this)](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11858                 auto pattern = wp.Upgrade();
11859                 CHECK_NULL_VOID(pattern);
11860                 auto host = pattern->GetHost();
11861                 CHECK_NULL_VOID(host);
11862                 Color iconColor;
11863                 auto context = host->GetContext();
11864                 CHECK_NULL_VOID(context);
11865                 auto colorMode = context->GetColorMode();
11866                 if (colorMode == ColorMode::DARK) {
11867                     auto theme = pattern->GetTheme();
11868                     iconColor = theme->GetCancelButtonIconColor();
11869                 }
11870                 prop->UpdateIconColor(iconColor);
11871             }
11872         },
11873 
11874         {"minFontScale", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11875                 if (auto realValue = std::get_if<float>(&(value->GetValue()))) {
11876                     float minFontScale = *realValue;
11877                     minFontScale = LessOrEqual(minFontScale, 0.0f) ? 0.0f : minFontScale;
11878                     minFontScale = GreatOrEqual(minFontScale, 1.0f) ? 1.0f : minFontScale;
11879                     prop->UpdateMinFontScale(minFontScale);
11880                 }
11881             }
11882         },
11883 
11884         {"maxFontScale", [](TextFieldLayoutProperty* prop, RefPtr<PropertyValueBase> value) {
11885                 if (auto realValue = std::get_if<float>(&(value->GetValue()))) {
11886                     float maxFontScale = *realValue;
11887                     maxFontScale = LessOrEqual(maxFontScale, 1.0f) ? 1.0f : maxFontScale;
11888                     prop->UpdateMaxFontScale(maxFontScale);
11889                 }
11890             }
11891         },
11892     };
11893 
11894     auto it = handlers.find(key);
11895     if (it != handlers.end()) {
11896         it->second(layoutProperty, value);
11897     }
11898 
11899     if (frameNode->GetRerenderable()) {
11900         frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
11901     }
11902 }
11903 
11904 void TextFieldPattern::SetBackBorderRadius()
11905 {
11906     auto frameNode = GetHost();
11907     CHECK_NULL_VOID(frameNode);
11908     auto renderContext = frameNode->GetRenderContext();
11909     CHECK_NULL_VOID(renderContext);
11910     auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
11911     CHECK_NULL_VOID(layoutProperty);
11912 
11913     bool isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
11914     auto borderRadiusProperty = renderContext->GetBorderRadius();
11915     CHECK_NULL_VOID(borderRadiusProperty);
11916     auto radius = borderRadiusProperty.value();
11917 
11918     radius.radiusTopLeft = radius.radiusTopLeft.has_value() ? radius.radiusTopLeft :
11919         (isRTL ? radius.radiusTopEnd : radius.radiusTopStart);
11920     radius.radiusTopRight = radius.radiusTopRight.has_value() ? radius.radiusTopRight :
11921         (isRTL ? radius.radiusTopStart : radius.radiusTopEnd);
11922     radius.radiusBottomLeft = radius.radiusBottomLeft.has_value() ? radius.radiusBottomLeft :
11923         (isRTL ? radius.radiusBottomEnd : radius.radiusBottomStart);
11924     radius.radiusBottomRight = radius.radiusBottomRight.has_value() ? radius.radiusBottomRight :
11925         (isRTL ? radius.radiusBottomStart : radius.radiusBottomEnd);
11926 
11927     ACE_UPDATE_NODE_PAINT_PROPERTY(TextFieldPaintProperty, BorderRadiusFlagByUser, radius, frameNode);
11928 }
11929 
11930 void TextFieldPattern::UpdateBorderResource()
11931 {
11932     auto frameNode = GetHost();
11933     auto renderContext = frameNode->GetRenderContext();
11934     CHECK_NULL_VOID(renderContext);
11935     if (renderContext->HasBorderRadius()) {
11936         SetBackBorderRadius();
11937     }
11938     if (renderContext->HasBorderColor()) {
11939         ACE_UPDATE_NODE_PAINT_PROPERTY(
11940             TextFieldPaintProperty, BorderColorFlagByUser, renderContext->GetBorderColor().value(), frameNode);
11941     }
11942     if (renderContext->HasBorderWidth()) {
11943         ACE_UPDATE_NODE_PAINT_PROPERTY(
11944             TextFieldPaintProperty, BorderWidthFlagByUser, renderContext->GetBorderWidth().value(), frameNode);
11945     }
11946     if (renderContext->HasBorderStyle()) {
11947         ACE_UPDATE_NODE_PAINT_PROPERTY(
11948             TextFieldPaintProperty, BorderStyleFlagByUser, renderContext->GetBorderStyle().value(), frameNode);
11949     }
11950 }
11951 
11952 void TextFieldPattern::UpdateMarginResource()
11953 {
11954     auto frameNode = GetHost();
11955     CHECK_NULL_VOID(frameNode);
11956     auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
11957     CHECK_NULL_VOID(layoutProperty);
11958     const auto& margin = layoutProperty->GetMarginProperty();
11959     CHECK_NULL_VOID(margin);
11960     bool isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
11961 
11962     MarginProperty userMargin;
11963     userMargin.top = margin->top;
11964     userMargin.bottom = margin->bottom;
11965     userMargin.left = margin->left.has_value() ? margin->left :
11966         (isRTL ? margin->end : margin->start);
11967     userMargin.right = margin->right.has_value() ? margin->right :
11968         (isRTL ? margin->start : margin->end);
11969     ACE_UPDATE_PAINT_PROPERTY(TextFieldPaintProperty, MarginByUser, userMargin);
11970 }
11971 
11972 Offset TextFieldPattern::GetCaretClickLocalOffset(const Offset& offset)
11973 {
11974     if (!IsTextArea()) {
11975         return offset;
11976     }
11977     auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
11978     CHECK_NULL_RETURN(layoutProperty, offset);
11979     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
11980     auto localOffset = offset;
11981     if (GreatNotEqual(localOffset.GetY(), textRect_.Bottom())) {
11982         localOffset.SetX(isRTL ? contentRect_.Left() : contentRect_.Right());
11983         localOffset.SetY(textRect_.Bottom() - PreferredLineHeight() / 2.0f);
11984     } else if (GreatNotEqual(localOffset.GetY(), contentRect_.Bottom())) {
11985         localOffset.SetX(isRTL ? contentRect_.Left() : contentRect_.Right());
11986         localOffset.SetY(contentRect_.Bottom() - PreferredLineHeight() / 2.0f);
11987     }
11988     return localOffset;
11989 }
11990 
11991 bool TextFieldPattern::ShouldSkipUpdateParagraph()
11992 {
11993     if (IsDragging() || !dragNode_ || !IsNormalInlineState()) {
11994         return false;
11995     }
11996     auto dragNodePattern = AceType::DynamicCast<TextDragPattern>(dragNode_->GetPattern());
11997     CHECK_NULL_RETURN(dragNodePattern, false);
11998     if (!dragNodePattern->IsAnimating()) {
11999         return false;
12000     }
12001     TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "Destroy the paragraph after the drag floating animation ends.");
12002     dragNodePattern->UpdateAnimatingParagraph();
12003     return true;
12004 }
12005 
12006 void TextFieldPattern::UpdateParagraphForDragNode(bool skipUpdate)
12007 {
12008     if (IsDragging() || !dragNode_ || skipUpdate) {
12009         return;
12010     }
12011     auto dragNodePattern = AceType::DynamicCast<TextDragPattern>(dragNode_->GetPattern());
12012     CHECK_NULL_VOID(dragNodePattern);
12013     dragNodePattern->UpdateParagraph(paragraph_);
12014 }
12015 } // namespace OHOS::Ace::NG
12016