1 /*
2  * Copyright (c) 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/overlay/keyboard_base_pattern.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/utils/utils.h"
20 #include "core/pipeline_ng/pipeline_context.h"
21 #include "core/pipeline_ng/ui_task_scheduler.h"
22 
23 namespace OHOS::Ace::NG {
BeforeCreateLayoutWrapper()24 void KeyboardPattern::BeforeCreateLayoutWrapper()
25 {
26     auto host = GetHost();
27     CHECK_NULL_VOID(host);
28     auto child = host->GetChildAtIndex(0);
29     while (child) {
30         // find first framenode, filter SyntaxItem
31         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
32         if (childFrameNode) {
33             auto layoutProperty = childFrameNode->GetLayoutProperty();
34             if (!layoutProperty) {
35                 break;
36             }
37             // set custom keyboard view width match parent
38             std::optional<CalcLength> height = std::nullopt;
39             auto&& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
40             if (layoutConstraint != nullptr && layoutConstraint->selfIdealSize) {
41                 height = layoutConstraint->selfIdealSize->Height();
42             }
43             auto dimension = Dimension(1.0f, DimensionUnit::PERCENT);
44             layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(dimension), height));
45             if (CheckChildPosition(childFrameNode)) {
46                 host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
47             }
48             break;
49         }
50         child = child->GetChildAtIndex(0);
51     }
52 }
53 
CheckChildPosition(const RefPtr<FrameNode> & frameNode)54 bool KeyboardPattern::CheckChildPosition(const RefPtr<FrameNode>& frameNode)
55 {
56     CHECK_NULL_RETURN(frameNode, false);
57     auto childRender = frameNode->GetRenderContext();
58     CHECK_NULL_RETURN(childRender, false);
59     return childRender->HasPosition();
60 }
61 
DumpInfo()62 void KeyboardPattern::DumpInfo()
63 {
64     DumpLog::GetInstance().AddDesc(std::string("TargetId: ")
65                                         .append(std::to_string(targetId_)));
66 }
67 
OnModifyDone()68 void KeyboardPattern::OnModifyDone()
69 {
70     auto context = OHOS::Ace::NG::PipelineContext::GetCurrentContext();
71     CHECK_NULL_VOID(context);
72     context->AddOnAreaChangeNode(GetHost()->GetId());
73 }
74 
OnAreaChangedInner()75 void KeyboardPattern::OnAreaChangedInner()
76 {
77     if (!supportAvoidance_) {
78         return;
79     }
80     auto host = GetHost();
81     CHECK_NULL_VOID(host);
82     auto customHeight = GetKeyboardHeight();
83     if (NearEqual(customHeight, keyboardHeight_)) {
84         return;
85     }
86     auto boundaryHeight = 0.0f;
87     // Check that the effective height of the keyboard is captured
88     if (std::abs(customHeight) > boundaryHeight) {
89         auto pipeline = OHOS::Ace::NG::PipelineContext::GetCurrentContext();
90         CHECK_NULL_VOID(pipeline);
91         Rect keyboardRect = Rect(0.0f, 0.0f, 0.0f, customHeight);
92         TAG_LOGI(ACE_KEYBOARD, "customKeyboardHeight Change to %{public}f, safeHeight: %{public}f",
93             customHeight, safeHeight_);
94         pipeline->OnVirtualKeyboardAreaChange(keyboardRect, nullptr, safeHeight_, supportAvoidance_, true);
95     }
96     keyboardHeight_ = customHeight;
97 }
98 
SetKeyboardAreaChange(bool keyboardAvoidance)99 void KeyboardPattern::SetKeyboardAreaChange(bool keyboardAvoidance)
100 {
101     if (keyboardAvoidance) {
102         auto host = GetHost();
103         CHECK_NULL_VOID(host);
104         auto keyboardHeight = GetKeyboardHeight();
105         auto pipeline = OHOS::Ace::NG::PipelineContext::GetCurrentContext();
106         CHECK_NULL_VOID(pipeline);
107         Rect keyboardRect = Rect(0.0f, 0.0f, 0.0f, keyboardHeight);
108         TAG_LOGI(ACE_KEYBOARD, "customKeyboardHeight Change to %{public}f, safeHeight: %{public}f",
109             keyboardHeight, safeHeight_);
110         pipeline->OnVirtualKeyboardAreaChange(keyboardRect, nullptr, safeHeight_, supportAvoidance_, true);
111     }
112 }
113 
GetKeyboardHeight()114 float KeyboardPattern::GetKeyboardHeight()
115 {
116     auto host = GetHost();
117     CHECK_NULL_RETURN(host, 0.0f);
118     auto child = host->GetChildAtIndex(0);
119     while (child) {
120         auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
121         if (!childFrameNode) {
122             child = child->GetChildAtIndex(0);
123             continue;
124         }
125         auto hostRect = host->GetTransformRectRelativeToWindow();
126         if (!CheckChildPosition(childFrameNode)) {
127             return hostRect.Height();
128         }
129         auto childRender = childFrameNode->GetRenderContext();
130         CHECK_NULL_RETURN(childRender, false);
131         auto positionY = childRender->GetPositionValue({}).GetY().ConvertToPx();
132         return hostRect.Height() - positionY > 0.0f ? hostRect.Height() - positionY : 0.0f;
133     }
134     return 0.0f;
135 }
136 
OnDetachFromFrameNode(FrameNode * node)137 void KeyboardPattern::OnDetachFromFrameNode(FrameNode* node)
138 {
139     auto pipeline = PipelineContext::GetCurrentContext();
140     CHECK_NULL_VOID(pipeline);
141     pipeline->RemoveOnAreaChangeNode(node->GetId());
142 }
143 
144 } // namespace OHOS::Ace::NG