• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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