• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "safe_area_manager.h"
16 
17 #include "base/utils/utils.h"
18 #include "core/components/container_modal/container_modal_constants.h"
19 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
20 #include "core/components_ng/pattern/stage/page_pattern.h"
21 #include "core/components_ng/property/safe_area_insets.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 
24 namespace OHOS::Ace::NG {
GenerateCutOutAreaWithRoot(const SafeAreaInsets & safeArea,NG::OptionalSize<uint32_t> rootSize)25 SafeAreaInsets GenerateCutOutAreaWithRoot(const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize)
26 {
27     auto pipeline = PipelineContext::GetCurrentContext();
28     CHECK_NULL_RETURN(pipeline, {});
29     CHECK_NULL_RETURN(pipeline->GetUseCutout(), {});
30     // cutout regions adjacent to edges.
31     auto cutoutArea = safeArea;
32 
33     if (cutoutArea.top_.IsValid()) {
34         cutoutArea.top_.start = 0;
35     }
36     if (safeArea.bottom_.IsValid()) {
37         cutoutArea.bottom_.end = rootSize.Height().has_value() ? rootSize.Height().value()
38                                                                : PipelineContext::GetCurrentRootHeight();
39     }
40     if (cutoutArea.left_.IsValid()) {
41         cutoutArea.left_.start = 0;
42     }
43     if (cutoutArea.right_.IsValid()) {
44         cutoutArea.right_.end = rootSize.Width().has_value() ? rootSize.Width().value()
45                                                              : PipelineContext::GetCurrentRootWidth();
46     }
47     return cutoutArea;
48 }
49 
CheckCutoutSafeArea(const SafeAreaInsets & safeArea,NG::OptionalSize<uint32_t> rootSize)50 bool SafeAreaManager::CheckCutoutSafeArea(const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize)
51 {
52     return cutoutSafeArea_ != GenerateCutOutAreaWithRoot(safeArea, rootSize);
53 }
54 
UpdateCutoutSafeArea(const SafeAreaInsets & safeArea,NG::OptionalSize<uint32_t> rootSize)55 bool SafeAreaManager::UpdateCutoutSafeArea(const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize)
56 {
57     auto safeAreaWithRoot = GenerateCutOutAreaWithRoot(safeArea, rootSize);
58     if (cutoutSafeArea_ == safeAreaWithRoot) {
59         return false;
60     }
61     ACE_SCOPED_TRACE("SafeAreaManager::UpdateCutoutSafeArea %s", safeAreaWithRoot.ToString().c_str());
62     cutoutSafeArea_ = safeAreaWithRoot;
63     return true;
64 }
65 
CheckSystemSafeArea(const SafeAreaInsets & safeArea)66 bool SafeAreaManager::CheckSystemSafeArea(const SafeAreaInsets& safeArea)
67 {
68     return systemSafeArea_ != safeArea;
69 }
70 
UpdateSystemSafeArea(const SafeAreaInsets & safeArea)71 bool SafeAreaManager::UpdateSystemSafeArea(const SafeAreaInsets& safeArea)
72 {
73     if (systemSafeArea_ == safeArea) {
74         return false;
75     }
76     ACE_SCOPED_TRACE("SafeAreaManager::UpdateSystemSafeArea %s", safeArea.ToString().c_str());
77     systemSafeArea_ = safeArea;
78     return true;
79 }
80 
CheckNavArea(const SafeAreaInsets & safeArea)81 bool SafeAreaManager::CheckNavArea(const SafeAreaInsets& safeArea)
82 {
83     return navSafeArea_ != safeArea;
84 }
85 
UpdateNavArea(const SafeAreaInsets & safeArea)86 bool SafeAreaManager::UpdateNavArea(const SafeAreaInsets& safeArea)
87 {
88     if (navSafeArea_ == safeArea) {
89         return false;
90     }
91     ACE_SCOPED_TRACE("SafeAreaManager::UpdateNavArea %s", safeArea.ToString().c_str());
92     navSafeArea_ = safeArea;
93     return true;
94 }
95 
UpdateKeyboardSafeArea(float keyboardHeight,std::optional<uint32_t> rootHeight)96 bool SafeAreaManager::UpdateKeyboardSafeArea(float keyboardHeight, std::optional<uint32_t> rootHeight)
97 {
98     uint32_t bottom;
99     if (systemSafeArea_.bottom_.IsValid()) {
100         bottom = systemSafeArea_.bottom_.start;
101     } else {
102         bottom = rootHeight.has_value() ? rootHeight.value() : PipelineContext::GetCurrentRootHeight();
103     }
104     SafeAreaInsets::Inset inset = { .start = bottom - keyboardHeight, .end = bottom };
105     if (inset == keyboardInset_) {
106         return false;
107     }
108     keyboardInset_ = inset;
109     return true;
110 }
111 
GetCombinedSafeArea(const SafeAreaExpandOpts & opts) const112 SafeAreaInsets SafeAreaManager::GetCombinedSafeArea(const SafeAreaExpandOpts& opts) const
113 {
114     SafeAreaInsets res;
115     if (!IsSafeAreaValid()) {
116         return {};
117     }
118     if (opts.type & SAFE_AREA_TYPE_CUTOUT) {
119         res = res.Combine(cutoutSafeArea_);
120     }
121     if (opts.type & SAFE_AREA_TYPE_SYSTEM) {
122         res = res.Combine(systemSafeArea_).Combine(navSafeArea_);
123     }
124     if (keyboardSafeAreaEnabled_ && (opts.type & SAFE_AREA_TYPE_KEYBOARD)) {
125         res.bottom_ = res.bottom_.Combine(keyboardInset_);
126     }
127     return res;
128 }
129 
IsSafeAreaValid() const130 bool SafeAreaManager::IsSafeAreaValid() const
131 {
132 #ifdef PREVIEW
133     return !ignoreSafeArea_;
134 #else
135     return !(ignoreSafeArea_ || (!isFullScreen_ && !isNeedAvoidWindow_));
136 #endif
137 }
138 
SetIsFullScreen(bool value)139 bool SafeAreaManager::SetIsFullScreen(bool value)
140 {
141     if (isFullScreen_ == value) {
142         return false;
143     }
144     isFullScreen_ = value;
145     LOGI("SafeAreaManager::SetIsFullScreen %{public}d", isFullScreen_);
146     return true;
147 }
148 
SetIsNeedAvoidWindow(bool value)149 bool SafeAreaManager::SetIsNeedAvoidWindow(bool value)
150 {
151     if (isNeedAvoidWindow_ == value) {
152         return false;
153     }
154     isNeedAvoidWindow_ = value;
155     LOGI("SafeAreaManager::SetIsNeedAvoidWindow %{public}d", isNeedAvoidWindow_);
156     return true;
157 }
158 
SetIgnoreSafeArea(bool value)159 bool SafeAreaManager::SetIgnoreSafeArea(bool value)
160 {
161     if (ignoreSafeArea_ == value) {
162         return false;
163     }
164     ignoreSafeArea_ = value;
165     LOGI("SafeAreaManager::SetIgnoreSafeArea %{public}d", ignoreSafeArea_);
166     return true;
167 }
168 
SetKeyBoardAvoidMode(bool value)169 bool SafeAreaManager::SetKeyBoardAvoidMode(bool value)
170 {
171     if (keyboardSafeAreaEnabled_ == value) {
172         return false;
173     }
174     keyboardSafeAreaEnabled_ = value;
175     LOGI("SafeAreaManager::SetKeyBoardAvoidMode %{public}d", keyboardSafeAreaEnabled_);
176     return true;
177 }
178 
SetIsAtomicService(bool value)179 bool SafeAreaManager::SetIsAtomicService(bool value)
180 {
181     if (isAtomicService_ == value) {
182         return false;
183     }
184     isAtomicService_ = value;
185     LOGI("SafeAreaManager::SetIsAtomicService %{public}d", isAtomicService_);
186     return true;
187 }
188 
IsAtomicService() const189 bool SafeAreaManager::IsAtomicService() const
190 {
191     return isAtomicService_;
192 }
193 
GetSystemSafeArea() const194 SafeAreaInsets SafeAreaManager::GetSystemSafeArea() const
195 {
196     return systemSafeArea_;
197 }
198 
GetCutoutSafeArea() const199 SafeAreaInsets SafeAreaManager::GetCutoutSafeArea() const
200 {
201     if (!IsSafeAreaValid()) {
202         return {};
203     }
204     return cutoutSafeArea_;
205 }
206 
GetSafeArea() const207 SafeAreaInsets SafeAreaManager::GetSafeArea() const
208 {
209     if (!IsSafeAreaValid()) {
210         return {};
211     }
212     return systemSafeArea_.Combine(cutoutSafeArea_).Combine(navSafeArea_);
213 }
214 
GetSafeAreaWithoutCutout() const215 SafeAreaInsets SafeAreaManager::GetSafeAreaWithoutCutout() const
216 {
217     if (!IsSafeAreaValid()) {
218         return {};
219     }
220     return systemSafeArea_.Combine(navSafeArea_);
221 }
222 
GetSafeAreaWithoutProcess() const223 SafeAreaInsets SafeAreaManager::GetSafeAreaWithoutProcess() const
224 {
225     return systemSafeArea_.Combine(cutoutSafeArea_).Combine(navSafeArea_);
226 }
227 
GetKeyboardOffset() const228 float SafeAreaManager::GetKeyboardOffset() const
229 {
230     if (keyboardSafeAreaEnabled_) {
231         return 0.0f;
232     }
233     return keyboardOffset_;
234 }
235 
GetWindowWrapperOffset()236 OffsetF SafeAreaManager::GetWindowWrapperOffset()
237 {
238     auto pipelineContext = PipelineContext::GetCurrentContext();
239     CHECK_NULL_RETURN(pipelineContext, OffsetF());
240     auto windowManager = pipelineContext->GetWindowManager();
241     auto isContainerModal = pipelineContext->GetWindowModal() == WindowModal::CONTAINER_MODAL && windowManager &&
242                             windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
243     if (isContainerModal) {
244         auto wrapperOffset = OffsetF(static_cast<float>((CONTAINER_BORDER_WIDTH + CONTENT_PADDING).ConvertToPx()),
245             static_cast<float>((pipelineContext->GetCustomTitleHeight() + CONTAINER_BORDER_WIDTH).ConvertToPx()));
246         return wrapperOffset;
247     }
248     return OffsetF();
249 }
250 
ExpandSafeArea()251 void SafeAreaManager::ExpandSafeArea()
252 {
253     ACE_SCOPED_TRACE("ExpandSafeArea node count %zu, IsSafeAreaValid: %d, ignoreSafeArea: %d, isFullScreen: %d, "
254                      "isNeedAvoidWindow %d",
255         needExpandNodes_.size(), IsSafeAreaValid(), ignoreSafeArea_, isFullScreen_, isNeedAvoidWindow_);
256     auto pipeline = PipelineContext::GetCurrentContext();
257     CHECK_NULL_VOID(pipeline);
258     auto manager = pipeline->GetSafeAreaManager();
259     auto iter = needExpandNodes_.begin();
260     while (iter != needExpandNodes_.end()) {
261         auto frameNode = (*iter).Upgrade();
262         if (frameNode) {
263             manager->AddGeoRestoreNode(frameNode);
264             frameNode->ExpandSafeArea();
265         }
266         ++iter;
267     }
268     ClearNeedExpandNode();
269 }
270 
AddNodeToExpandListIfNeeded(const WeakPtr<FrameNode> & node)271 bool SafeAreaManager::AddNodeToExpandListIfNeeded(const WeakPtr<FrameNode>& node)
272 {
273     if (needExpandNodes_.find(node) == needExpandNodes_.end()) {
274         AddNeedExpandNode(node);
275         return true;
276     }
277     return false;
278 }
279 
CheckPageNeedAvoidKeyboard(const RefPtr<FrameNode> & frameNode)280 bool SafeAreaManager::CheckPageNeedAvoidKeyboard(const RefPtr<FrameNode>& frameNode)
281 {
282     if (frameNode->GetTag() != V2::PAGE_ETS_TAG) {
283         return false;
284     }
285     // page will not avoid keyboard when lastChild is sheet
286     RefPtr<OverlayManager> overlay;
287     if (frameNode->RootNodeIsPage()) {
288         auto pattern = frameNode->GetPattern<PagePattern>();
289         CHECK_NULL_RETURN(pattern, true);
290         overlay = pattern->GetOverlayManager();
291     } else {
292         auto navNode = FrameNode::GetFrameNode(V2::NAVDESTINATION_VIEW_ETS_TAG, frameNode->GetRootNodeId());
293         CHECK_NULL_RETURN(navNode, true);
294         auto pattern = navNode->GetPattern<NavDestinationPattern>();
295         CHECK_NULL_RETURN(pattern, true);
296         overlay = pattern->GetOverlayManager();
297     }
298     CHECK_NULL_RETURN(overlay, true);
299     return overlay->CheckPageNeedAvoidKeyboard();
300 }
301 } // namespace OHOS::Ace::NG
302