1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/text_field/text_field_manager.h"
17
18 #include "base/geometry/dimension.h"
19 #include "base/memory/ace_type.h"
20 #include "base/utils/utils.h"
21 #include "core/common/ime/text_input_type.h"
22 #include "core/components_ng/event/focus_hub.h"
23 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
24 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
25 #include "core/components_ng/pattern/text/text_base.h"
26 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
27
28 namespace OHOS::Ace::NG {
29 namespace {
30 constexpr Dimension RESERVE_BOTTOM_HEIGHT = 24.0_vp;
31 } // namespace
32
ClearOnFocusTextField()33 void TextFieldManagerNG::ClearOnFocusTextField()
34 {
35 onFocusTextField_ = nullptr;
36 }
37
ClearOnFocusTextField(int32_t id)38 void TextFieldManagerNG::ClearOnFocusTextField(int32_t id)
39 {
40 if (onFocusTextFieldId_ == id) {
41 onFocusTextField_ = nullptr;
42 focusFieldIsInline_ = false;
43 optionalPosition_ = std::nullopt;
44 usingCustomKeyboardAvoid_ = false;
45 isScrollableChild_ = false;
46 }
47 }
48
OnBackPressed()49 bool TextFieldManagerNG::OnBackPressed()
50 {
51 auto pattern = onFocusTextField_.Upgrade();
52 CHECK_NULL_RETURN(pattern, false);
53 auto textBasePattern = AceType::DynamicCast<TextBase>(pattern);
54 CHECK_NULL_RETURN(textBasePattern, false);
55 return textBasePattern->OnBackPressed();
56 }
57
SetClickPosition(const Offset & position)58 void TextFieldManagerNG::SetClickPosition(const Offset& position)
59 {
60 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
61 CHECK_NULL_VOID(pipeline);
62 auto rootHeight = pipeline->GetRootHeight();
63 if (GreatOrEqual(position.GetY(), rootHeight) || LessOrEqual(position.GetY(), 0.0f)) {
64 auto pattern = onFocusTextField_.Upgrade();
65 CHECK_NULL_VOID(pattern);
66 auto host = pattern->GetHost();
67 CHECK_NULL_VOID(host);
68 auto parent = host->GetAncestorNodeOfFrame(true);
69 while (parent) {
70 // when Panel and SheetPage is out of screen, no need to update position_ for keyboard avoidance
71 if (parent->GetTag() == V2::PANEL_ETS_TAG || parent->GetTag() == V2::SHEET_PAGE_TAG) {
72 return;
73 }
74 parent = parent->GetAncestorNodeOfFrame(true);
75 }
76 }
77 auto rootWidth = pipeline->GetRootWidth();
78 if (GreatOrEqual(position.GetX(), rootWidth) || LessNotEqual(position.GetX(), 0.0f)) {
79 return;
80 }
81 auto y = std::max(0.0, position.GetY());
82 position_ = {position.GetX(), y};
83 optionalPosition_ = position_;
84 }
85
FindScrollableOfFocusedTextField(const RefPtr<FrameNode> & textField)86 RefPtr<FrameNode> TextFieldManagerNG::FindScrollableOfFocusedTextField(const RefPtr<FrameNode>& textField)
87 {
88 CHECK_NULL_RETURN(textField, {});
89 auto parent = textField->GetAncestorNodeOfFrame(true);
90 while (parent) {
91 auto pattern = parent->GetPattern<ScrollablePattern>();
92 if (pattern) {
93 return parent;
94 }
95 parent = parent->GetAncestorNodeOfFrame(true);
96 }
97 return {};
98 }
99
GetFocusedNodeCaretRect()100 RectF TextFieldManagerNG::GetFocusedNodeCaretRect()
101 {
102 auto node = onFocusTextField_.Upgrade();
103 CHECK_NULL_RETURN(node, RectF());
104 auto frameNode = node->GetHost();
105 CHECK_NULL_RETURN(frameNode, RectF());
106 auto textBase = DynamicCast<TextBase>(node);
107 CHECK_NULL_RETURN(textBase, RectF());
108 auto caretRect = textBase->GetCaretRect() + frameNode->GetTransformRectRelativeToWindow();
109 return caretRect;
110 }
111
TriggerCustomKeyboardAvoid()112 void TextFieldManagerNG::TriggerCustomKeyboardAvoid()
113 {
114 CHECK_NULL_VOID(UsingCustomKeyboardAvoid());
115 auto pattern = onFocusTextField_.Upgrade();
116 CHECK_NULL_VOID(pattern);
117 auto curPattern = DynamicCast<TextFieldPattern>(pattern);
118 CHECK_NULL_VOID(curPattern);
119 if (!curPattern->GetIsCustomKeyboardAttached()) {
120 return;
121 }
122 auto caretHeight = curPattern->GetCaretRect().Height();
123 auto safeHeight = caretHeight + curPattern->GetCaretRect().GetY();
124 if (curPattern->GetCaretRect().GetY() > caretHeight) {
125 safeHeight = caretHeight;
126 }
127 auto keyboardOverLay = curPattern->GetKeyboardOverLay();
128 CHECK_NULL_VOID(keyboardOverLay);
129 auto host = curPattern->GetHost();
130 CHECK_NULL_VOID(host);
131 auto nodeId = host->GetId();
132 keyboardOverLay->AvoidCustomKeyboard(nodeId, safeHeight);
133 }
134
TriggerAvoidOnCaretChange()135 void TextFieldManagerNG::TriggerAvoidOnCaretChange()
136 {
137 auto pattern = onFocusTextField_.Upgrade();
138 CHECK_NULL_VOID(pattern);
139 auto host = pattern->GetHost();
140 CHECK_NULL_VOID(host);
141 auto pipeline = host->GetContext();
142 CHECK_NULL_VOID(pipeline);
143 auto safeAreaManager = pipeline->GetSafeAreaManager();
144 CHECK_NULL_VOID(safeAreaManager);
145 if (!pipeline->UsingCaretAvoidMode() || NearEqual(safeAreaManager->GetKeyboardInset().Length(), 0)) {
146 return;
147 }
148 if (UsingCustomKeyboardAvoid()) {
149 ScrollTextFieldToSafeArea();
150 TriggerCustomKeyboardAvoid();
151 } else {
152 ScrollTextFieldToSafeArea();
153 auto keyboardInset = safeAreaManager->GetKeyboardInset();
154 lastKeyboardOffset_ = safeAreaManager->GetKeyboardOffsetDirectly();
155 Rect keyboardRect;
156 keyboardRect.SetRect(0, 0, 0, keyboardInset.Length());
157 pipeline->OnVirtualKeyboardAreaChange(keyboardRect,
158 GetFocusedNodeCaretRect().Top(), GetHeight());
159 }
160 auto currentKeyboardOffset = safeAreaManager->GetKeyboardOffsetDirectly();
161 if (currentKeyboardOffset != lastKeyboardOffset_) {
162 AvoidKeyboardInSheet(host);
163 }
164 }
165
GetOnFocusTextFieldInfo(const WeakPtr<Pattern> & onFocusTextField)166 void TextFieldManagerNG::GetOnFocusTextFieldInfo(const WeakPtr<Pattern>& onFocusTextField)
167 {
168 auto node = onFocusTextField.Upgrade();
169 CHECK_NULL_VOID(node);
170 auto frameNode = node->GetHost();
171 CHECK_NULL_VOID(frameNode);
172 auto scrollableNode = FindScrollableOfFocusedTextField(frameNode);
173 CHECK_NULL_VOID(scrollableNode);
174 auto scrollPattern = scrollableNode->GetPattern<ScrollablePattern>();
175 CHECK_NULL_VOID(scrollPattern);
176 isScrollableChild_ = scrollPattern->IsScrollToSafeAreaHelper();
177 TAG_LOGI(ACE_KEYBOARD, "isScrollableChild_: %{public}d", isScrollableChild_);
178 }
179
ScrollToSafeAreaHelper(const SafeAreaInsets::Inset & bottomInset,bool isShowKeyboard)180 bool TextFieldManagerNG::ScrollToSafeAreaHelper(
181 const SafeAreaInsets::Inset& bottomInset, bool isShowKeyboard)
182 {
183 auto node = onFocusTextField_.Upgrade();
184 CHECK_NULL_RETURN(node, false);
185 auto frameNode = node->GetHost();
186 CHECK_NULL_RETURN(frameNode, false);
187 auto textBase = DynamicCast<TextBase>(node);
188 CHECK_NULL_RETURN(textBase, false);
189 textBase->OnVirtualKeyboardAreaChanged();
190
191 auto scrollableNode = FindScrollableOfFocusedTextField(frameNode);
192 CHECK_NULL_RETURN(scrollableNode, false);
193 auto scrollPattern = scrollableNode->GetPattern<ScrollablePattern>();
194 CHECK_NULL_RETURN(scrollPattern && scrollPattern->IsScrollToSafeAreaHelper(), false);
195 CHECK_NULL_RETURN(scrollPattern->GetAxis() != Axis::HORIZONTAL, false);
196
197 auto scrollableRect = scrollableNode->GetTransformRectRelativeToWindow();
198 if (isShowKeyboard) {
199 CHECK_NULL_RETURN(LessNotEqual(scrollableRect.Top(), bottomInset.start), false);
200 }
201
202 auto pipeline = frameNode->GetContext();
203 CHECK_NULL_RETURN(pipeline, false);
204 auto safeAreaManager = pipeline->GetSafeAreaManager();
205 CHECK_NULL_RETURN(safeAreaManager, false);
206 if (pipeline->UsingCaretAvoidMode()) {
207 scrollableRect.SetTop(scrollableRect.Top() - safeAreaManager->GetKeyboardOffset());
208 }
209
210 auto caretRect = textBase->GetCaretRect() + frameNode->GetPositionToWindowWithTransform();
211 auto diffTop = caretRect.Top() - scrollableRect.Top();
212 // caret height larger scroll's content region
213 if (isShowKeyboard && LessOrEqual(diffTop, 0) && LessNotEqual(bottomInset.start,
214 (caretRect.Bottom() + RESERVE_BOTTOM_HEIGHT.ConvertToPx()))) {
215 return false;
216 }
217
218 // caret above scroll's content region
219 if (LessNotEqual(diffTop, 0)) {
220 TAG_LOGI(ACE_KEYBOARD, "scrollRect:%{public}s caretRect:%{public}s totalOffset()=%{public}f diffTop=%{public}f",
221 scrollableRect.ToString().c_str(), caretRect.ToString().c_str(), scrollPattern->GetTotalOffset(), diffTop);
222 scrollPattern->ScrollTo(scrollPattern->GetTotalOffset() + diffTop);
223 return true;
224 }
225
226 // caret inner scroll's content region
227 if (isShowKeyboard && LessNotEqual((caretRect.Bottom() + RESERVE_BOTTOM_HEIGHT.ConvertToPx()), bottomInset.start)) {
228 return false;
229 }
230
231 // caret below safeArea
232 float diffBot = 0.0f;
233
234 auto scrollBottom = isShowKeyboard && GreatOrEqual(scrollableRect.Bottom(), bottomInset.start) ?
235 bottomInset.start : scrollableRect.Bottom();
236 diffBot = scrollBottom - caretRect.Bottom() - RESERVE_BOTTOM_HEIGHT.ConvertToPx();
237 CHECK_NULL_RETURN(diffBot < 0, false);
238 TAG_LOGI(ACE_KEYBOARD, "scrollRect:%{public}s caretRect:%{public}s totalOffset()=%{public}f diffBot=%{public}f",
239 scrollableRect.ToString().c_str(), caretRect.ToString().c_str(), scrollPattern->GetTotalOffset(), diffBot);
240 scrollPattern->ScrollTo(scrollPattern->GetTotalOffset() - diffBot);
241 return true;
242 }
243
ScrollTextFieldToSafeArea()244 bool TextFieldManagerNG::ScrollTextFieldToSafeArea()
245 {
246 auto pipeline = PipelineContext::GetCurrentContext();
247 CHECK_NULL_RETURN(pipeline, false);
248 auto manager = pipeline->GetSafeAreaManager();
249 CHECK_NULL_RETURN(manager, false);
250 auto systemSafeArea = manager->GetSystemSafeArea();
251 uint32_t bottom = systemSafeArea.bottom_.IsValid()? systemSafeArea.bottom_.start : pipeline->GetCurrentRootHeight();
252 auto keyboardHeight = manager->GetRawKeyboardHeight();
253 SafeAreaInsets::Inset keyboardInset = { .start = bottom - keyboardHeight, .end = bottom };
254 bool isShowKeyboard = manager->GetKeyboardInset().IsValid();
255 int32_t keyboardOrientation = manager->GetKeyboardOrientation();
256 auto container = Container::Current();
257 if (keyboardOrientation != -1 && container && container->GetDisplayInfo()) {
258 auto nowOrientation = static_cast<int32_t>(container->GetDisplayInfo()->GetRotation());
259 if (nowOrientation != keyboardOrientation) {
260 // When rotating the screen, sometimes we might get a keyboard height that in wrong
261 // orientation due to timeing issue. In this case, we ignore the illegal keyboard height.
262 TAG_LOGI(ACE_KEYBOARD, "Current Orientation not match keyboard orientation, ignore it");
263 isShowKeyboard = false;
264 }
265 }
266 if (isShowKeyboard) {
267 auto bottomInset = pipeline->GetSafeArea().bottom_.Combine(keyboardInset);
268 CHECK_NULL_RETURN(bottomInset.IsValid(), false);
269 return ScrollToSafeAreaHelper(bottomInset, isShowKeyboard);
270 } else if (manager->KeyboardSafeAreaEnabled()) {
271 // hide keyboard only scroll when keyboard avoid mode is resize
272 return ScrollToSafeAreaHelper({0, 0}, isShowKeyboard);
273 }
274 return false;
275 }
276
SetHeight(float height)277 void TextFieldManagerNG::SetHeight(float height)
278 {
279 height_ = height + RESERVE_BOTTOM_HEIGHT.ConvertToPx();
280 }
281
UpdateScrollableParentViewPort(const RefPtr<FrameNode> & node)282 void TextFieldManagerNG::UpdateScrollableParentViewPort(const RefPtr<FrameNode>& node)
283 {
284 CHECK_NULL_VOID(node);
285 auto scrollableNode = FindScrollableOfFocusedTextField(node);
286 CHECK_NULL_VOID(scrollableNode);
287 auto scrollPattern = scrollableNode->GetPattern<ScrollablePattern>();
288 CHECK_NULL_VOID(scrollPattern);
289 if (scrollPattern->GetAxis() == Axis::HORIZONTAL) {
290 return;
291 }
292 auto scrollableRect = scrollableNode->GetTransformRectRelativeToWindow();
293 scrollableNode->SetViewPort(scrollableRect);
294 }
295
AvoidKeyBoardInNavigation()296 void TextFieldManagerNG::AvoidKeyBoardInNavigation()
297 {
298 auto node = onFocusTextField_.Upgrade();
299 auto pipeline = PipelineContext::GetCurrentContext();
300 CHECK_NULL_VOID(pipeline);
301 auto manager = pipeline->GetSafeAreaManager();
302 auto avoidKeyboardOffset = manager ? manager->GetKeyboardOffset() : 0.0f;
303 if (!node) {
304 auto navNode = weakNavNode_.Upgrade();
305 CHECK_NULL_VOID(navNode);
306 SetNavContentAvoidKeyboardOffset(navNode, avoidKeyboardOffset);
307 return;
308 }
309 auto frameNode = node->GetHost();
310 CHECK_NULL_VOID(frameNode);
311 auto preNavNode = weakNavNode_.Upgrade();
312 if (preNavNode) {
313 SetNavContentAvoidKeyboardOffset(preNavNode, 0.0f);
314 }
315 auto navNode = FindNavNode(frameNode);
316 CHECK_NULL_VOID(navNode);
317 weakNavNode_ = navNode;
318 SetNavContentAvoidKeyboardOffset(navNode, avoidKeyboardOffset);
319 }
320
AvoidKeyboardInSheet(const RefPtr<FrameNode> & textField)321 void TextFieldManagerNG::AvoidKeyboardInSheet(const RefPtr<FrameNode>& textField)
322 {
323 CHECK_NULL_VOID(textField);
324 auto parent = textField->GetAncestorNodeOfFrame(true);
325 while (parent) {
326 if (parent->GetHostTag() == V2::SHEET_PAGE_TAG) {
327 break;
328 }
329 parent = parent->GetAncestorNodeOfFrame(true);
330 }
331 CHECK_NULL_VOID(parent);
332 auto sheetNodePattern = parent->GetPattern<SheetPresentationPattern>();
333 CHECK_NULL_VOID(sheetNodePattern);
334 TAG_LOGI(ACE_KEYBOARD, "Force AvoidKeyboard in sheet");
335 sheetNodePattern->AvoidSafeArea(true);
336 }
337
FindNavNode(const RefPtr<FrameNode> & textField)338 RefPtr<FrameNode> TextFieldManagerNG::FindNavNode(const RefPtr<FrameNode>& textField)
339 {
340 CHECK_NULL_RETURN(textField, nullptr);
341 auto parent = textField->GetAncestorNodeOfFrame(true);
342 RefPtr<FrameNode> ret = nullptr;
343 while (parent) {
344 // when the sheet showed in navdestination, sheet replaced navdestination to do avoid keyboard.
345 if (parent->GetHostTag() == V2::SHEET_WRAPPER_TAG) {
346 auto sheetNode = parent->GetChildAtIndex(0);
347 CHECK_NULL_RETURN(sheetNode, nullptr);
348 return AceType::DynamicCast<FrameNode>(sheetNode);
349 }
350 if (parent->GetHostTag() == V2::DIALOG_ETS_TAG) {
351 return AceType::DynamicCast<FrameNode>(parent);
352 }
353 if (parent->GetHostTag() == V2::NAVDESTINATION_VIEW_ETS_TAG ||
354 parent->GetHostTag() == V2::NAVBAR_ETS_TAG) {
355 ret = parent;
356 break;
357 }
358 parent = parent->GetAncestorNodeOfFrame(true);
359 }
360 CHECK_NULL_RETURN(ret, nullptr);
361
362 // return navdestination or navBar if the closest ancestor navigation can expandKeyboard
363 // if can't, recursively find the ancestor navigation can expandKeyboard.
364 auto navigationNode = ret->GetAncestorNodeOfFrame(true);
365 while (navigationNode) {
366 if (navigationNode->GetHostTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
367 break;
368 }
369 navigationNode = navigationNode->GetAncestorNodeOfFrame(true);
370 }
371 CHECK_NULL_RETURN(navigationNode, nullptr);
372 auto layoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
373 CHECK_NULL_RETURN(layoutProperty, nullptr);
374 auto& opts = layoutProperty->GetSafeAreaExpandOpts();
375
376 // if the extended keyboard area is set for the navigation, top navdestination or navbar need to avoid keyboard,
377 // otherwise don't aovid, following parent navigation.
378 bool isExpandKeyboard = opts && (opts->type & SAFE_AREA_TYPE_KEYBOARD) && (opts->edges & SAFE_AREA_EDGE_BOTTOM);
379 if (isExpandKeyboard) {
380 return ret;
381 }
382 auto mayAvoidNavContentNode = FindNavNode(navigationNode);
383 if (mayAvoidNavContentNode) {
384 return mayAvoidNavContentNode;
385 }
386 SetNavContentAvoidKeyboardOffset(ret, 0.0f);
387 return nullptr;
388 }
389
SetNavContentAvoidKeyboardOffset(const RefPtr<FrameNode> & navNode,float avoidKeyboardOffset)390 void TextFieldManagerNG::SetNavContentAvoidKeyboardOffset(const RefPtr<FrameNode>& navNode, float avoidKeyboardOffset)
391 {
392 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(navNode);
393 if (navDestinationNode) {
394 TAG_LOGI(ACE_KEYBOARD, "navNode id:%{public}d, avoidKeyboardOffset:%{public}f", navNode->GetId(),
395 avoidKeyboardOffset);
396 auto pattern = navDestinationNode->GetPattern<NavDestinationPattern>();
397 if (pattern) {
398 avoidKeyboardOffset = pattern->NeedIgnoreKeyboard() ? 0.0f : avoidKeyboardOffset;
399 pattern->SetAvoidKeyboardOffset(avoidKeyboardOffset);
400 }
401 }
402 auto navBarNode = AceType::DynamicCast<NavBarNode>(navNode);
403 if (navBarNode) {
404 auto pattern = navBarNode->GetPattern<NavBarPattern>();
405 if (pattern) {
406 pattern->SetAvoidKeyboardOffset(avoidKeyboardOffset);
407 }
408 }
409 navNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
410 }
411
AddTextFieldInfo(const TextFieldInfo & textFieldInfo)412 void TextFieldManagerNG::AddTextFieldInfo(const TextFieldInfo& textFieldInfo)
413 {
414 if (textFieldInfo.nodeId == -1 || textFieldInfo.autoFillContainerNodeId == -1) {
415 return;
416 }
417
418 auto containerNodeIter = textFieldInfoMap_.find(textFieldInfo.autoFillContainerNodeId);
419 if (containerNodeIter != textFieldInfoMap_.end()) {
420 auto& innerTextFieldMap = containerNodeIter->second;
421 innerTextFieldMap[textFieldInfo.nodeId] = textFieldInfo;
422 } else {
423 std::unordered_map<int32_t, TextFieldInfo> innerTextFieldInfoMap;
424 innerTextFieldInfoMap[textFieldInfo.nodeId] = textFieldInfo;
425 textFieldInfoMap_[textFieldInfo.autoFillContainerNodeId] = innerTextFieldInfoMap;
426 }
427 }
428
RemoveTextFieldInfo(const int32_t & autoFillContainerNodeId,const int32_t & nodeId)429 void TextFieldManagerNG::RemoveTextFieldInfo(const int32_t& autoFillContainerNodeId, const int32_t& nodeId)
430 {
431 auto containerNodeIter = textFieldInfoMap_.find(autoFillContainerNodeId);
432 if (containerNodeIter != textFieldInfoMap_.end()) {
433 auto& innerTextFieldInfoMap = containerNodeIter->second;
434 auto textFieldNodeIter = innerTextFieldInfoMap.find(nodeId);
435 if (textFieldNodeIter != innerTextFieldInfoMap.end()) {
436 innerTextFieldInfoMap.erase(textFieldNodeIter);
437 }
438 }
439 }
440
UpdateTextFieldInfo(const TextFieldInfo & textFieldInfo)441 void TextFieldManagerNG::UpdateTextFieldInfo(const TextFieldInfo& textFieldInfo)
442 {
443 if (textFieldInfo.nodeId == -1 || textFieldInfo.autoFillContainerNodeId == -1) {
444 return;
445 }
446 auto containerNodeIter = textFieldInfoMap_.find(textFieldInfo.autoFillContainerNodeId);
447 if (containerNodeIter != textFieldInfoMap_.end()) {
448 auto& innerTextFieldInfoMap = containerNodeIter->second;
449 auto textFieldNodeIter = innerTextFieldInfoMap.find(textFieldInfo.nodeId);
450 if (textFieldNodeIter != innerTextFieldInfoMap.end()) {
451 innerTextFieldInfoMap.erase(textFieldNodeIter);
452 }
453 innerTextFieldInfoMap[textFieldInfo.nodeId] = textFieldInfo;
454 } else {
455 AddTextFieldInfo(textFieldInfo);
456 }
457 }
458
HasAutoFillPasswordNodeInContainer(const int32_t & autoFillContainerNodeId,const int32_t & nodeId)459 bool TextFieldManagerNG::HasAutoFillPasswordNodeInContainer(
460 const int32_t& autoFillContainerNodeId, const int32_t& nodeId)
461 {
462 auto containerNodeIter = textFieldInfoMap_.find(autoFillContainerNodeId);
463 if (containerNodeIter == textFieldInfoMap_.end()) {
464 return false;
465 }
466
467 auto& innerTextFieldInfoMap = containerNodeIter->second;
468 auto textFieldNodeIter = innerTextFieldInfoMap.find(nodeId);
469 if (textFieldNodeIter == innerTextFieldInfoMap.end()) {
470 return false;
471 }
472
473 for (const auto& textField : innerTextFieldInfoMap) {
474 auto textFieldId = textField.first;
475 auto textFieldInfo = textField.second;
476 if (textFieldId == nodeId) {
477 continue;
478 }
479
480 auto isPasswordType = IsAutoFillPasswordType(textFieldInfo);
481 if (isPasswordType && textFieldInfo.enableAutoFill) {
482 return true;
483 }
484 }
485
486 return false;
487 }
488
IsAutoFillPasswordType(const TextFieldInfo & textFieldInfo)489 bool TextFieldManagerNG::IsAutoFillPasswordType(const TextFieldInfo& textFieldInfo)
490 {
491 return textFieldInfo.inputType == TextInputType::VISIBLE_PASSWORD ||
492 textFieldInfo.inputType == TextInputType::NEW_PASSWORD ||
493 textFieldInfo.inputType == TextInputType::NUMBER_PASSWORD ||
494 textFieldInfo.contentType == TextContentType::VISIBLE_PASSWORD ||
495 textFieldInfo.contentType == TextContentType::NEW_PASSWORD;
496 }
497
SetOnFocusTextField(const WeakPtr<Pattern> & onFocusTextField)498 void TextFieldManagerNG::SetOnFocusTextField(const WeakPtr<Pattern>& onFocusTextField)
499 {
500 const auto& pattern = onFocusTextField.Upgrade();
501 if (pattern && pattern->GetHost()) {
502 onFocusTextFieldId_ = pattern->GetHost()->GetId();
503 }
504 if (onFocusTextField_ != onFocusTextField) {
505 SetImeAttached(false);
506 GetOnFocusTextFieldInfo(onFocusTextField);
507 }
508 onFocusTextField_ = onFocusTextField;
509 }
510
GetImeShow() const511 bool TextFieldManagerNG::GetImeShow() const
512 {
513 if (!imeShow_ && imeAttachCalled_) {
514 TAG_LOGI(ACE_KEYBOARD, "imeNotShown but attach called, still consider that as shown");
515 }
516 return imeShow_ || imeAttachCalled_;
517 }
518
AddAvoidKeyboardCallback(int32_t id,bool isCustomKeyboard,const std::function<void ()> && callback)519 void TextFieldManagerNG::AddAvoidKeyboardCallback(
520 int32_t id, bool isCustomKeyboard, const std::function<void()>&& callback)
521 {
522 if (isCustomKeyboard) {
523 avoidCustomKeyboardCallbacks_.insert({ id, std::move(callback) });
524 } else {
525 avoidSystemKeyboardCallbacks_.insert({ id, std::move(callback) });
526 }
527 }
528
OnAfterAvoidKeyboard(bool isCustomKeyboard)529 void TextFieldManagerNG::OnAfterAvoidKeyboard(bool isCustomKeyboard)
530 {
531 auto callbacks =
532 isCustomKeyboard ? std::move(avoidCustomKeyboardCallbacks_) : std::move(avoidSystemKeyboardCallbacks_);
533 for (const auto& pair : callbacks) {
534 if (pair.second) {
535 pair.second();
536 }
537 }
538 }
539
~TextFieldManagerNG()540 TextFieldManagerNG::~TextFieldManagerNG()
541 {
542 textFieldInfoMap_.clear();
543 }
544 } // namespace OHOS::Ace::NG
545