• 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 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_SAFE_AREA_SAFE_AREA_MANAGER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_SAFE_AREA_SAFE_AREA_MANAGER_H
18 
19 #include "base/memory/ace_type.h"
20 #include "base/utils/noncopyable.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/property/safe_area_insets.h"
23 #include "core/components_ng/property/transition_property.h"
24 
25 namespace OHOS::Ace::NG {
26 // SafeAreaManager stores layout information to apply SafeArea correctly.
27 
28 struct WindowTypeConfig {
29     WindowTypeConfig() = default;
WindowTypeConfigWindowTypeConfig30     WindowTypeConfig(bool isAppWindow, bool isSystemWindow, bool isSceneBoardWindow)
31         : isAppWindow(isAppWindow), isSystemWindow(isSystemWindow), isSceneBoardWindow(isSceneBoardWindow)
32     {}
33     bool isAppWindow = true;
34     bool isSystemWindow = false;
35     bool isSceneBoardWindow = false;
36 };
37 
38 class SafeAreaManager : public virtual AceType {
39     DECLARE_ACE_TYPE(SafeAreaManager, AceType);
40 
41 public:
42     SafeAreaManager() = default;
43     ~SafeAreaManager() override = default;
44 
45     /**
46      * @brief Check if the incoming safe area is identical to the system safe area
47      *
48      * @param safeArea The new system safe area.
49      * @return True if the incoming safe area is identical to the current one, false otherwise.
50      */
51     bool CheckSystemSafeArea(const SafeAreaInsets& safeArea);
52 
53     /**
54      * @brief Updates the system safe area.
55      *
56      * @param safeArea The new system safe area.
57      * @return True if the system safe area was modified, false otherwise.
58      */
59     bool UpdateSystemSafeArea(const SafeAreaInsets& safeArea);
60 
61     /**
62      * @brief Check if the incoming safe area is identical to the navigation indictor safe area.
63      *
64      * @param safeArea The new navigation indictor safe area.
65      * @return True if the incoming safe area is identical to the current one, false otherwise.
66      */
67     bool CheckNavSafeArea(const SafeAreaInsets& safeArea);
68 
69     /**
70      * @brief Updates the navigation indictor safe area.
71      *
72      * @param safeArea The new navigation indictor safe area.
73      * @return True if the system safe area was modified, false otherwise.
74      */
75     bool UpdateNavSafeArea(const SafeAreaInsets& safeArea);
76 
77     /**
78      * @brief Retrieves the system safe area insets.
79      *
80      * This function returns the safe area insets of the system, which represents the portion of the screen that is
81      * covered by system UI elements such as the status bar or navigation bar.
82      *
83      * @return The system safe area insets.
84      */
85     SafeAreaInsets GetSystemSafeArea() const;
86 
GetNavSafeArea()87     SafeAreaInsets GetNavSafeArea() const
88     {
89         return navSafeArea_;
90     }
91 
92     /**
93      * @brief Cut the incoming area with root size, then check if the result is identical to the cutout safe area.
94      *
95      * @param safeArea The SafeAreaInsets representing the new cutout safe area, which would be modified.
96      * @return True if the incoming safe area is identical to the current one, false otherwise.
97      */
98     bool CheckCutoutSafeArea(
99         const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>());
100 
101     /**
102      * @brief Updates the cutout safe area.
103      *
104      * This function is responsible for updating the cutout safe area based on the provided SafeAreaInsets.
105      *
106      * @param safeArea The SafeAreaInsets representing the new cutout safe area.
107      * @return true if the cutout safe area was successfully updated, false otherwise.
108      */
109     bool UpdateCutoutSafeArea(
110         const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>());
111 
112     /**
113      * @brief Retrieves the safe area insets that account for any cutout areas on the screen.
114      *
115      * @return The safe area insets that account for any cutout areas on the screen.
116      */
117     SafeAreaInsets GetCutoutSafeArea() const;
118 
119     /**
120      * @brief Retrieves the safe area insets that account for any cutout areas on the screen.
121      *
122      * @return The safe area insets that account for cutout areas on the screen without any judgement.
123      */
124     SafeAreaInsets GetCutoutSafeAreaWithoutProcess() const;
125 
126     bool UpdateScbSystemSafeArea(const SafeAreaInsets& safeArea);
127 
128     bool UpdateScbCutoutSafeArea(
129         const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>());
130 
131     bool UpdateScbNavSafeArea(const SafeAreaInsets& safeArea);
132 
133     /**
134      * @brief Retrieves the safe area insets combining System and Cutout.
135      *
136      * @return The System & Cutout safe area insets.
137      */
138     SafeAreaInsets GetSafeArea() const;
139 
140     /**
141      * @brief Retrieves the safe area insets only System.
142      *
143      * @return The System safe area insets.
144      */
145     SafeAreaInsets GetSafeAreaWithoutCutout() const;
146 
147     /**
148      * @brief Updates the safe area to accommodate the keyboard.
149      *
150      * This function is called to update the safe area when the keyboard is shown or hidden.
151      *
152      * @param keyboardHeight The height of the keyboard in pixels.
153      * @return true if the safe area was modified, false otherwise.
154      */
155     bool UpdateKeyboardSafeArea(float keyboardHeight, std::optional<uint32_t> rootHeight = std::nullopt);
156 
157     /**
158      * @brief Updates a mirror of safe area to accommodate the keyboard from web
159      *
160      * Third-party platform may use SafeArea, so web_pattern using safearea to keep menu away
161      * from keyboard might lead to several problem.This function is called to update a mirror of
162      * keyboardInset when the keyboard is shown or hidden by web. SelectOverlaylayoutAlgorithm will
163      * use it to calculate the position of menu, but not participate in other safearea calculation.
164      *
165      * @param keyboardHeight The height of the keyboard in pixels.
166      * @return true if the safe area was modified, false otherwise.
167      */
168     bool UpdateKeyboardWebSafeArea(float keyboardHeight, std::optional<uint32_t> rootHeight = std::nullopt);
169 
170     /**
171      * @brief Retrieves the inset of the safe area caused by the keyboard.
172      *
173      * @return The inset of the safe area caused by the keyboard.
174      */
GetKeyboardInset()175     SafeAreaInsets::Inset GetKeyboardInset() const
176     {
177         if (keyboardAvoidMode_ == KeyBoardAvoidMode::NONE) {
178             SafeAreaInsets::Inset inset;
179             return inset;
180         }
181         return keyboardInset_;
182     }
183 
GetKeyboardWebInset()184     SafeAreaInsets::Inset GetKeyboardWebInset() const
185     {
186         if (keyboardAvoidMode_ == KeyBoardAvoidMode::NONE) {
187             SafeAreaInsets::Inset inset;
188             return inset;
189         }
190         return keyboardWebInset_;
191     }
192 
UpdateKeyboardOffset(float offset)193     void UpdateKeyboardOffset(float offset)
194     {
195         keyboardOffset_ = offset;
196     }
197 
198     float GetKeyboardOffset(bool withoutProcess = false) const;
199 
200     void SetKeyboardInfo(float height);
201 
GetKeyboardOrientation()202     int32_t GetKeyboardOrientation() const
203     {
204         return keyboardOrientation_;
205     }
206 
GetRawKeyboardHeight()207     float GetRawKeyboardHeight() const
208     {
209         return rawKeyboardHeight_;
210     }
211 
SetRawKeyboardHeight(float height)212     void SetRawKeyboardHeight(float height)
213     {
214         rawKeyboardHeight_ = height;
215     }
216 
KeyboardSafeAreaEnabled()217     bool KeyboardSafeAreaEnabled() const
218     {
219         return keyboardSafeAreaEnabled_;
220     }
221 
222     SafeAreaInsets GetCombinedSafeArea(const SafeAreaExpandOpts& opts) const;
223 
GetGeoRestoreNodes()224     const std::set<WeakPtr<FrameNode>>& GetGeoRestoreNodes() const
225     {
226         return geoRestoreNodes_;
227     }
228 
AddGeoRestoreNode(const WeakPtr<FrameNode> & node)229     void AddGeoRestoreNode(const WeakPtr<FrameNode>& node)
230     {
231         geoRestoreNodes_.insert(node);
232     }
233 
AddNeedExpandNode(const WeakPtr<FrameNode> & node)234     void AddNeedExpandNode(const WeakPtr<FrameNode>& node)
235     {
236         needExpandNodes_.insert(node);
237     }
238 
239     std::vector<WeakPtr<FrameNode>> GetExpandNodeSet();
240 
241     bool AddNodeToExpandListIfNeeded(const WeakPtr<FrameNode>& node);
242 
ClearNeedExpandNode()243     void ClearNeedExpandNode()
244     {
245         needExpandNodes_.clear();
246     }
247 
RemoveRestoreNode(const WeakPtr<FrameNode> & node)248     void RemoveRestoreNode(const WeakPtr<FrameNode>& node)
249     {
250         geoRestoreNodes_.erase(node);
251     }
252 
GetSafeAreaCurve()253     RefPtr<InterpolatingSpring> GetSafeAreaCurve() const
254     {
255         return safeAreaCurve_;
256     }
257     void ExpandSafeArea();
258 
259     OffsetF GetWindowWrapperOffset();
260 
261     SafeAreaInsets GetSafeAreaWithoutProcess() const;
262 
263     bool SetIsFullScreen(bool value);
264     bool SetIsNeedAvoidWindow(bool value);
265     bool SetIgnoreSafeArea(bool value);
266     bool SetKeyBoardAvoidMode(KeyBoardAvoidMode value);
267 
268     KeyBoardAvoidMode GetKeyBoardAvoidMode();
269 
IsIgnoreSafeArea()270     bool IsIgnoreSafeArea()
271     {
272         return ignoreSafeArea_;
273     }
274 
IsNeedAvoidWindow()275     bool IsNeedAvoidWindow()
276     {
277         return isNeedAvoidWindow_;
278     }
279 
IsFullScreen()280     bool IsFullScreen()
281     {
282         return isFullScreen_;
283     }
284 
285     bool SetIsAtomicService(bool value);
286     bool IsAtomicService() const;
287 
GetSafeHeight()288     float GetSafeHeight() const
289     {
290         Dimension safeDistance = 16.0_vp;
291         return safeDistance.ConvertToPx();
292     }
293 
SetLastKeyboardPoistion(float position)294     void SetLastKeyboardPoistion(float position)
295     {
296         lastKeyboardY_ = position;
297     }
298 
GetLastKeyboardPoistion()299     float GetLastKeyboardPoistion() const
300     {
301         return lastKeyboardY_;
302     }
303 
304     bool IsSafeAreaValid() const;
305 
306     // check if the page node needs to be avoid keyboard
307     bool CheckPageNeedAvoidKeyboard(const RefPtr<FrameNode>& frameNode);
308 
309     PaddingPropertyF SafeAreaToPadding(
310         bool withoutProcess = false, LayoutSafeAreaType ignoreType = LAYOUT_SAFE_AREA_TYPE_SYSTEM);
311 
SetWindowTypeConfig(bool isAppWindow,bool isSystemWindow,bool isSceneBoardWindow)312     void SetWindowTypeConfig(bool isAppWindow, bool isSystemWindow, bool isSceneBoardWindow)
313     {
314         windowTypeConfig_ = WindowTypeConfig(isAppWindow, isSystemWindow, isSceneBoardWindow);
315     }
316 
GetWindowTypeConfig()317     WindowTypeConfig GetWindowTypeConfig()
318     {
319         return windowTypeConfig_;
320     }
321 
GetkeyboardHeightConsideringUIExtension()322     uint32_t GetkeyboardHeightConsideringUIExtension()
323     {
324         return keyboardHeightConsideringUIExtension_;
325     }
326 
SetkeyboardHeightConsideringUIExtension(uint32_t height)327     void SetkeyboardHeightConsideringUIExtension(uint32_t height)
328     {
329         if (keyboardHeightConsideringUIExtension_ != height) {
330             for (const auto& [nodeId, callback] : keyboardChangeCbsConsideringUIExt_) {
331                 if (callback) {
332                     callback();
333                 }
334             }
335             keyboardHeightConsideringUIExtension_ = height;
336         }
337     }
338 
AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId,const std::function<void ()> & callback)339     void AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId, const std::function<void()>& callback)
340     {
341         keyboardChangeCbsConsideringUIExt_[nodeId] = callback;
342     }
343 
RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId)344     void RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId)
345     {
346         keyboardChangeCbsConsideringUIExt_.erase(nodeId);
347     }
348 
SetUseCutout(bool useCutout)349     void SetUseCutout(bool useCutout)
350     {
351         useCutout_ = useCutout;
352     }
353 
GetUseCutout()354     bool GetUseCutout()
355     {
356         return useCutout_;
357     }
358 
GetKeyboardInsetImpl()359     SafeAreaInsets::Inset GetKeyboardInsetImpl()
360     {
361         return getKeyboardInset ? getKeyboardInset(this) : GetKeyboardInset();
362     }
363 
SetKeyboardInsetImpl(std::function<SafeAreaInsets::Inset (SafeAreaManager *)> method)364     void SetKeyboardInsetImpl(std::function<SafeAreaInsets::Inset(SafeAreaManager*)> method)
365     {
366         getKeyboardInset = method;
367     }
368 
369 private:
370     bool isAtomicService_ = false;
371 
372     // app window is full screen
373     // todo: remove and only use isNeedAvoidWindow_
374     bool isFullScreen_ = false;
375 
376     /**
377      * @brief Indicates whether the UI within the current window type needs to avoid SafeAreaInsets.
378      */
379     bool isNeedAvoidWindow_ = false;
380 
381     /**
382      * @brief Indicates whether to ignore the SafeAreaInsets, specified by the developer from frontend.
383      */
384     bool ignoreSafeArea_ = false;
385 
386     /**
387      * @brief Indicates whether the keyboard safe area is enabled. When enabled, UI avoids the keyboard inset and the
388      * Page is compressed when the keyboard is up. When disabled, the size of Page doesn't change, but Page would
389      * offset vertically according to [keyboardOffset_] when [keyboardAvoidMode_] is OFFSET or stay still when
390      * [keyboardAvoidMode_] is NONE.
391      */
392     bool keyboardSafeAreaEnabled_ = false;
393 
394     bool useCutout_ = false;
395 
396     KeyBoardAvoidMode keyboardAvoidMode_ = KeyBoardAvoidMode::OFFSET;
397     bool IsModeResize();
398     bool IsModeOffset();
399 
400     SafeAreaInsets systemSafeArea_;
401     SafeAreaInsets cutoutSafeArea_;
402     SafeAreaInsets navSafeArea_;
403     // keyboard is bottom direction only
404     SafeAreaInsets::Inset keyboardInset_;
405     SafeAreaInsets::Inset keyboardWebInset_;
406 
407     std::optional<SafeAreaInsets> scbSystemSafeArea_;
408     std::optional<SafeAreaInsets> scbCutoutSafeArea_;
409     std::optional<SafeAreaInsets> scbNavSafeArea_;
410 
411     WindowTypeConfig windowTypeConfig_;
412 
413     /**
414      * @brief A set of weak pointers to FrameNode objects whose geometry info are saved before their SafeArea
415      * expansion. The geometry info of these nodes need to be restored when their next Layout task begins.
416      */
417     std::set<WeakPtr<FrameNode>> geoRestoreNodes_;
418 
419     struct DepthCompare {
operatorDepthCompare420         bool operator()(const WeakPtr<FrameNode>& a, const WeakPtr<FrameNode>& b) const
421         {
422             auto ptrA = a.Upgrade();
423             auto ptrB = b.Upgrade();
424             if (!ptrA || !ptrB) {
425                 return false;
426             }
427             if (ptrA->GetDepth() < ptrB->GetDepth()) {
428                 return true;
429             }
430             if (ptrA->GetDepth() == ptrB->GetDepth()) {
431                 return ptrA < ptrB;
432             }
433             return false;
434         }
435     };
436     std::set<WeakPtr<FrameNode>, DepthCompare> needExpandNodes_;
437     // amount of offset to apply to Page when keyboard is up
438     float keyboardOffset_ = 0.0f;
439     float lastKeyboardY_ = 0.0f;
440     float rawKeyboardHeight_ = 0.0f;
441     int32_t keyboardOrientation_ = -1;
442 
443     static constexpr float SAFE_AREA_VELOCITY = 0.0f;
444     static constexpr float SAFE_AREA_MASS = 1.0f;
445     static constexpr float SAFE_AREA_STIFFNESS = 228.0f;
446     static constexpr float SAFE_AREA_DAMPING = 30.0f;
447     RefPtr<InterpolatingSpring> safeAreaCurve_ = AceType::MakeRefPtr<InterpolatingSpring>(
448         SAFE_AREA_VELOCITY, SAFE_AREA_MASS, SAFE_AREA_STIFFNESS, SAFE_AREA_DAMPING);
449 
450     uint32_t keyboardHeightConsideringUIExtension_ = 0;
451     std::unordered_map<int32_t, std::function<void()>> keyboardChangeCbsConsideringUIExt_;
452 
453     std::function<SafeAreaInsets::Inset(SafeAreaManager*)> getKeyboardInset = nullptr;
454 
455     ACE_DISALLOW_COPY_AND_MOVE(SafeAreaManager);
456 };
457 } // namespace OHOS::Ace::NG
458 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_SAFE_AREA_SAFE_AREA_MANAGER_H
459