• 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/memory/ace_type.h"
19 #include "base/utils/utils.h"
20 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
21 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
22 
23 namespace OHOS::Ace::NG {
GetKeyEventHandler()24 const RefPtr<KeyEventHandler>& TextFieldManagerNG::GetKeyEventHandler()
25 {
26     if (!keyEventHandler_) {
27         keyEventHandler_ = AceType::MakeRefPtr<KeyEventHandler>();
28     }
29     return keyEventHandler_;
30 }
31 
ClearOnFocusTextField()32 void TextFieldManagerNG::ClearOnFocusTextField()
33 {
34     onFocusTextField_ = nullptr;
35     CHECK_NULL_VOID(keyEventHandler_);
36     keyEventHandler_->ClearClient();
37 }
38 
OnBackPressed()39 bool TextFieldManagerNG::OnBackPressed()
40 {
41     auto pattern = onFocusTextField_.Upgrade();
42     CHECK_NULL_RETURN(pattern, false);
43     auto textfieldPattern = AceType::DynamicCast<TextFieldPattern>(pattern);
44     CHECK_NULL_RETURN(textfieldPattern, false);
45     return textfieldPattern->OnBackPressed();
46 }
47 
FindScrollableOfFocusedTextField(const RefPtr<FrameNode> & textField)48 RefPtr<FrameNode> TextFieldManagerNG::FindScrollableOfFocusedTextField(const RefPtr<FrameNode>& textField)
49 {
50     CHECK_NULL_RETURN(textField, {});
51     auto parent = textField->GetAncestorNodeOfFrame();
52     while (parent) {
53         auto pattern = parent->GetPattern<ScrollablePattern>();
54         if (pattern) {
55             return parent;
56         }
57         parent = parent->GetAncestorNodeOfFrame();
58     }
59     return {};
60 }
61 
ScrollToSafeAreaHelper(const SafeAreaInsets::Inset & bottomInset)62 void TextFieldManagerNG::ScrollToSafeAreaHelper(const SafeAreaInsets::Inset& bottomInset)
63 {
64     auto textField = DynamicCast<TextFieldPattern>(onFocusTextField_.Upgrade());
65     CHECK_NULL_VOID(textField);
66     auto textFieldNode = textField->GetHost();
67     CHECK_NULL_VOID(textFieldNode);
68 
69     auto scrollableNode = FindScrollableOfFocusedTextField(textFieldNode);
70     CHECK_NULL_VOID_NOLOG(scrollableNode);
71     auto scrollPattern = scrollableNode->GetPattern<ScrollablePattern>();
72     CHECK_NULL_VOID(scrollPattern);
73 
74     auto scrollableRect = scrollableNode->GetTransformRectRelativeToWindow();
75     CHECK_NULL_VOID_NOLOG(scrollableRect.Top() < bottomInset.start);
76 
77     auto caretRect = textField->GetCaretRect() + textFieldNode->GetOffsetRelativeToWindow();
78     // caret above scroll's content region
79     auto diffTop = (caretRect.Top() - caretRect.Height() * 2) - scrollableRect.Top();
80     if (diffTop < 0) {
81         scrollPattern->ScrollTo(scrollPattern->GetTotalOffset() + diffTop);
82         return;
83     }
84 
85     // caret below safeArea
86     auto diffBot = bottomInset.start - (caretRect.Bottom() + caretRect.Height() * 2);
87     CHECK_NULL_VOID_NOLOG(diffBot < 0);
88     scrollPattern->ScrollTo(scrollPattern->GetTotalOffset() - diffBot);
89 }
90 
ScrollTextFieldToSafeArea()91 void TextFieldManagerNG::ScrollTextFieldToSafeArea()
92 {
93     auto pipeline = PipelineContext::GetCurrentContext();
94     CHECK_NULL_VOID(pipeline);
95     auto keyboardInset = pipeline->GetSafeAreaManager()->GetKeyboardInset();
96     // only scroll when keyboard shows
97     CHECK_NULL_VOID_NOLOG(keyboardInset.IsValid());
98     auto bottomInset = pipeline->GetSafeArea().bottom_.Combine(keyboardInset);
99     CHECK_NULL_VOID_NOLOG(bottomInset.IsValid());
100     ScrollToSafeAreaHelper(bottomInset);
101 }
102 } // namespace OHOS::Ace::NG
103