• 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 
87     /**
88      * @brief Cut the incoming area with root size, then check if the result is identical to the cutout safe area.
89      *
90      * @param safeArea The SafeAreaInsets representing the new cutout safe area, which would be modified.
91      * @return True if the incoming safe area is identical to the current one, false otherwise.
92      */
93     bool CheckCutoutSafeArea(
94         const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>());
95 
96     /**
97      * @brief Updates the cutout safe area.
98      *
99      * This function is responsible for updating the cutout safe area based on the provided SafeAreaInsets.
100      *
101      * @param safeArea The SafeAreaInsets representing the new cutout safe area.
102      * @return true if the cutout safe area was successfully updated, false otherwise.
103      */
104     bool UpdateCutoutSafeArea(
105         const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>());
106 
107     /**
108      * @brief Retrieves the safe area insets that account for any cutout areas on the screen.
109      *
110      * @return The safe area insets that account for any cutout areas on the screen.
111      */
112     SafeAreaInsets GetCutoutSafeArea() const;
113 
114     /**
115      * @brief Retrieves the safe area insets that account for any cutout areas on the screen.
116      *
117      * @return The safe area insets that account for cutout areas on the screen without any judgement.
118      */
119     SafeAreaInsets GetCutoutSafeAreaWithoutProcess() const;
120 
121     bool UpdateScbSystemSafeArea(const SafeAreaInsets& safeArea);
122 
123     bool UpdateScbCutoutSafeArea(
124         const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>());
125 
126     bool UpdateScbNavSafeArea(const SafeAreaInsets& safeArea);
127 
128     /**
129      * @brief Retrieves the safe area insets combining System and Cutout.
130      *
131      * @return The System & Cutout safe area insets.
132      */
133     SafeAreaInsets GetSafeArea() const;
134 
135     /**
136      * @brief Retrieves the safe area insets only System.
137      *
138      * @return The System safe area insets.
139      */
140     SafeAreaInsets GetSafeAreaWithoutCutout() const;
141 
142     /**
143      * @brief Updates the safe area to accommodate the keyboard.
144      *
145      * This function is called to update the safe area when the keyboard is shown or hidden.
146      *
147      * @param keyboardHeight The height of the keyboard in pixels.
148      * @return true if the safe area was modified, false otherwise.
149      */
150     bool UpdateKeyboardSafeArea(float keyboardHeight, std::optional<uint32_t> rootHeight = std::nullopt);
151 
152     /**
153      * @brief Retrieves the inset of the safe area caused by the keyboard.
154      *
155      * @return The inset of the safe area caused by the keyboard.
156      */
GetKeyboardInset()157     SafeAreaInsets::Inset GetKeyboardInset() const
158     {
159         if (keyboardAvoidMode_ == KeyBoardAvoidMode::NONE) {
160             SafeAreaInsets::Inset inset;
161             return inset;
162         }
163         return keyboardInset_;
164     }
165 
UpdateKeyboardOffset(float offset)166     void UpdateKeyboardOffset(float offset)
167     {
168         keyboardOffset_ = offset;
169     }
170 
171     float GetKeyboardOffset(bool withoutProcess = false) const;
172 
GetKeyboardOffsetDirectly()173     float GetKeyboardOffsetDirectly() const
174     {
175         return keyboardOffset_;
176     }
177 
178     void SetKeyboardInfo(float height);
179 
GetKeyboardOrientation()180     int32_t GetKeyboardOrientation() const
181     {
182         return keyboardOrientation_;
183     }
184 
GetRawKeyboardHeight()185     float GetRawKeyboardHeight() const
186     {
187         return rawKeyboardHeight_;
188     }
189 
SetRawKeyboardHeight(float height)190     void SetRawKeyboardHeight(float height)
191     {
192         rawKeyboardHeight_ = height;
193     }
194 
KeyboardSafeAreaEnabled()195     bool KeyboardSafeAreaEnabled() const
196     {
197         return keyboardSafeAreaEnabled_;
198     }
199 
200     SafeAreaInsets GetCombinedSafeArea(const SafeAreaExpandOpts& opts) const;
201 
GetGeoRestoreNodes()202     const std::set<WeakPtr<FrameNode>>& GetGeoRestoreNodes() const
203     {
204         return geoRestoreNodes_;
205     }
206 
AddGeoRestoreNode(const WeakPtr<FrameNode> & node)207     void AddGeoRestoreNode(const WeakPtr<FrameNode>& node)
208     {
209         geoRestoreNodes_.insert(node);
210     }
211 
AddNeedExpandNode(const WeakPtr<FrameNode> & node)212     void AddNeedExpandNode(const WeakPtr<FrameNode>& node)
213     {
214         needExpandNodes_.insert(node);
215     }
216 
217     std::vector<WeakPtr<FrameNode>> GetExpandNodeSet();
218 
219     bool AddNodeToExpandListIfNeeded(const WeakPtr<FrameNode>& node);
220 
ClearNeedExpandNode()221     void ClearNeedExpandNode()
222     {
223         needExpandNodes_.clear();
224     }
225 
RemoveRestoreNode(const WeakPtr<FrameNode> & node)226     void RemoveRestoreNode(const WeakPtr<FrameNode>& node)
227     {
228         geoRestoreNodes_.erase(node);
229     }
230 
GetSafeAreaCurve()231     RefPtr<InterpolatingSpring> GetSafeAreaCurve() const
232     {
233         return safeAreaCurve_;
234     }
235     void ExpandSafeArea();
236 
237     OffsetF GetWindowWrapperOffset();
238 
239     SafeAreaInsets GetSafeAreaWithoutProcess() const;
240 
241     bool SetIsFullScreen(bool value);
242     bool SetIsNeedAvoidWindow(bool value);
243     bool SetIgnoreSafeArea(bool value);
244     bool SetKeyBoardAvoidMode(KeyBoardAvoidMode value);
245 
246     KeyBoardAvoidMode GetKeyBoardAvoidMode();
247 
IsIgnoreSafeArea()248     bool IsIgnoreSafeArea()
249     {
250         return ignoreSafeArea_;
251     }
252 
IsNeedAvoidWindow()253     bool IsNeedAvoidWindow()
254     {
255         return isNeedAvoidWindow_;
256     }
257 
IsFullScreen()258     bool IsFullScreen()
259     {
260         return isFullScreen_;
261     }
262 
263     bool SetIsAtomicService(bool value);
264     bool IsAtomicService() const;
265 
GetSafeHeight()266     float GetSafeHeight() const
267     {
268         Dimension safeDistance = 16.0_vp;
269         return safeDistance.ConvertToPx();
270     }
271 
SetLastKeyboardPoistion(float position)272     void SetLastKeyboardPoistion(float position)
273     {
274         lastKeyboardY_ = position;
275     }
276 
GetLastKeyboardPoistion()277     float GetLastKeyboardPoistion() const
278     {
279         return lastKeyboardY_;
280     }
281 
282     bool IsSafeAreaValid() const;
283 
284     // check if the page node needs to be avoid keyboard
285     bool CheckPageNeedAvoidKeyboard(const RefPtr<FrameNode>& frameNode);
286 
287     PaddingPropertyF SafeAreaToPadding(bool withoutProcess = false);
288 
SetWindowTypeConfig(bool isAppWindow,bool isSystemWindow,bool isSceneBoardWindow)289     void SetWindowTypeConfig(bool isAppWindow, bool isSystemWindow, bool isSceneBoardWindow)
290     {
291         windowTypeConfig_ = WindowTypeConfig(isAppWindow, isSystemWindow, isSceneBoardWindow);
292     }
293 
GetWindowTypeConfig()294     WindowTypeConfig GetWindowTypeConfig()
295     {
296         return windowTypeConfig_;
297     }
298 
GetkeyboardHeightConsideringUIExtension()299     uint32_t GetkeyboardHeightConsideringUIExtension()
300     {
301         return keyboardHeightConsideringUIExtension_;
302     }
303 
SetkeyboardHeightConsideringUIExtension(uint32_t height)304     void SetkeyboardHeightConsideringUIExtension(uint32_t height)
305     {
306         if (keyboardHeightConsideringUIExtension_ != height) {
307             for (const auto& [nodeId, callback] : keyboardChangeCbsConsideringUIExt_) {
308                 if (callback) {
309                     callback();
310                 }
311             }
312             keyboardHeightConsideringUIExtension_ = height;
313         }
314     }
315 
AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId,const std::function<void ()> & callback)316     void AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId, const std::function<void()>& callback)
317     {
318         keyboardChangeCbsConsideringUIExt_[nodeId] = callback;
319     }
320 
RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId)321     void RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId)
322     {
323         keyboardChangeCbsConsideringUIExt_.erase(nodeId);
324     }
325 
SetUseCutout(bool useCutout)326     void SetUseCutout(bool useCutout)
327     {
328         useCutout_ = useCutout;
329     }
330 
GetUseCutout()331     bool GetUseCutout()
332     {
333         return useCutout_;
334     }
335 
336 private:
337     bool isAtomicService_ = false;
338 
339     // app window is full screen
340     // todo: remove and only use isNeedAvoidWindow_
341     bool isFullScreen_ = false;
342 
343     /**
344      * @brief Indicates whether the UI within the current window type needs to avoid SafeAreaInsets.
345      */
346     bool isNeedAvoidWindow_ = false;
347 
348     /**
349      * @brief Indicates whether to ignore the SafeAreaInsets, specified by the developer from frontend.
350      */
351     bool ignoreSafeArea_ = false;
352 
353     /**
354      * @brief Indicates whether the keyboard safe area is enabled. When enabled, UI avoids the keyboard inset and the
355      * Page is compressed when the keyboard is up. When disabled, the size of Page doesn't change, but Page would
356      * offset vertically according to [keyboardOffset_] when [keyboardAvoidMode_] is OFFSET or stay still when
357      * [keyboardAvoidMode_] is NONE.
358      */
359     bool keyboardSafeAreaEnabled_ = false;
360 
361     bool useCutout_ = false;
362 
363     KeyBoardAvoidMode keyboardAvoidMode_ = KeyBoardAvoidMode::OFFSET;
364 
365     SafeAreaInsets systemSafeArea_;
366     SafeAreaInsets cutoutSafeArea_;
367     SafeAreaInsets navSafeArea_;
368     // keyboard is bottom direction only
369     SafeAreaInsets::Inset keyboardInset_;
370 
371     std::optional<SafeAreaInsets> scbSystemSafeArea_;
372     std::optional<SafeAreaInsets> scbCutoutSafeArea_;
373     std::optional<SafeAreaInsets> scbNavSafeArea_;
374 
375     WindowTypeConfig windowTypeConfig_;
376 
377     /**
378      * @brief A set of weak pointers to FrameNode objects whose geometry info are saved before their SafeArea
379      * expansion. The geometry info of these nodes need to be restored when their next Layout task begins.
380      */
381     std::set<WeakPtr<FrameNode>> geoRestoreNodes_;
382 
383     struct DepthCompare {
operatorDepthCompare384         bool operator()(const WeakPtr<FrameNode>& a, const WeakPtr<FrameNode>& b) const
385         {
386             auto ptrA = a.Upgrade();
387             auto ptrB = b.Upgrade();
388             if (!ptrA || !ptrB) {
389                 return false;
390             }
391             if (ptrA->GetDepth() < ptrB->GetDepth()) {
392                 return true;
393             }
394             if (ptrA->GetDepth() == ptrB->GetDepth()) {
395                 return ptrA < ptrB;
396             }
397             return false;
398         }
399     };
400     std::set<WeakPtr<FrameNode>, DepthCompare> needExpandNodes_;
401     // amount of offset to apply to Page when keyboard is up
402     float keyboardOffset_ = 0.0f;
403     float lastKeyboardY_ = 0.0f;
404     float rawKeyboardHeight_ = 0.0f;
405     int32_t keyboardOrientation_ = -1;
406 
407     static constexpr float SAFE_AREA_VELOCITY = 0.0f;
408     static constexpr float SAFE_AREA_MASS = 1.0f;
409     static constexpr float SAFE_AREA_STIFFNESS = 228.0f;
410     static constexpr float SAFE_AREA_DAMPING = 30.0f;
411     RefPtr<InterpolatingSpring> safeAreaCurve_ = AceType::MakeRefPtr<InterpolatingSpring>(
412         SAFE_AREA_VELOCITY, SAFE_AREA_MASS, SAFE_AREA_STIFFNESS, SAFE_AREA_DAMPING);
413 
414     uint32_t keyboardHeightConsideringUIExtension_ = 0;
415     std::unordered_map<int32_t, std::function<void()>> keyboardChangeCbsConsideringUIExt_;
416 
417     ACE_DISALLOW_COPY_AND_MOVE(SafeAreaManager);
418 };
419 } // namespace OHOS::Ace::NG
420 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_SAFE_AREA_SAFE_AREA_MANAGER_H
421