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 class SafeAreaManager : public virtual AceType { 28 DECLARE_ACE_TYPE(SafeAreaManager, AceType); 29 30 public: 31 SafeAreaManager() = default; 32 ~SafeAreaManager() override = default; 33 34 /** 35 * @brief Check if the incoming safe area is identical to the system safe area 36 * 37 * @param safeArea The new system safe area. 38 * @return True if the incoming safe area is identical to the current one, false otherwise. 39 */ 40 bool CheckSystemSafeArea(const SafeAreaInsets& safeArea); 41 42 /** 43 * @brief Updates the system safe area. 44 * 45 * @param safeArea The new system safe area. 46 * @return True if the system safe area was modified, false otherwise. 47 */ 48 bool UpdateSystemSafeArea(const SafeAreaInsets& safeArea); 49 50 /** 51 * @brief Check if the incoming safe area is identical to the navigation indictor safe area. 52 * 53 * @param safeArea The new navigation indictor safe area. 54 * @return True if the incoming safe area is identical to the current one, false otherwise. 55 */ 56 bool CheckNavArea(const SafeAreaInsets& safeArea); 57 58 /** 59 * @brief Updates the navigation indictor safe area. 60 * 61 * @param safeArea The new navigation indictor safe area. 62 * @return True if the system safe area was modified, false otherwise. 63 */ 64 bool UpdateNavArea(const SafeAreaInsets& safeArea); 65 66 /** 67 * @brief Retrieves the system safe area insets. 68 * 69 * This function returns the safe area insets of the system, which represents the portion of the screen that is 70 * covered by system UI elements such as the status bar or navigation bar. 71 * 72 * @return The system safe area insets. 73 */ 74 SafeAreaInsets GetSystemSafeArea() const; 75 76 /** 77 * @brief Cut the incoming area with root size, then check if the result is identical to the cutout safe area. 78 * 79 * @param safeArea The SafeAreaInsets representing the new cutout safe area, which would be modified. 80 * @return True if the incoming safe area is identical to the current one, false otherwise. 81 */ 82 bool CheckCutoutSafeArea( 83 const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>()); 84 85 /** 86 * @brief Updates the cutout safe area. 87 * 88 * This function is responsible for updating the cutout safe area based on the provided SafeAreaInsets. 89 * 90 * @param safeArea The SafeAreaInsets representing the new cutout safe area. 91 * @return true if the cutout safe area was successfully updated, false otherwise. 92 */ 93 bool UpdateCutoutSafeArea( 94 const SafeAreaInsets& safeArea, NG::OptionalSize<uint32_t> rootSize = NG::OptionalSize<uint32_t>()); 95 96 /** 97 * @brief Retrieves the safe area insets that account for any cutout areas on the screen. 98 * 99 * @return The safe area insets that account for any cutout areas on the screen. 100 */ 101 SafeAreaInsets GetCutoutSafeArea() const; 102 103 /** 104 * @brief Retrieves the safe area insets combining System and Cutout. 105 * 106 * @return The System & Cutout safe area insets. 107 */ 108 SafeAreaInsets GetSafeArea() const; 109 110 /** 111 * @brief Retrieves the safe area insets only System. 112 * 113 * @return The System safe area insets. 114 */ 115 SafeAreaInsets GetSafeAreaWithoutCutout() const; 116 117 /** 118 * @brief Updates the safe area to accommodate the keyboard. 119 * 120 * This function is called to update the safe area when the keyboard is shown or hidden. 121 * 122 * @param keyboardHeight The height of the keyboard in pixels. 123 * @return true if the safe area was modified, false otherwise. 124 */ 125 bool UpdateKeyboardSafeArea(float keyboardHeight, std::optional<uint32_t> rootHeight = std::nullopt); 126 127 /** 128 * @brief Retrieves the inset of the safe area caused by the keyboard. 129 * 130 * @return The inset of the safe area caused by the keyboard. 131 */ GetKeyboardInset()132 SafeAreaInsets::Inset GetKeyboardInset() const 133 { 134 if (keyboardAvoidMode_ == KeyBoardAvoidMode::NONE) { 135 SafeAreaInsets::Inset inset; 136 return inset; 137 } 138 return keyboardInset_; 139 } 140 UpdateKeyboardOffset(float offset)141 void UpdateKeyboardOffset(float offset) 142 { 143 keyboardOffset_ = offset; 144 } 145 146 float GetKeyboardOffset(bool withoutProcess = false) const; 147 GetKeyboardOffsetDirectly()148 float GetKeyboardOffsetDirectly() const 149 { 150 return keyboardOffset_; 151 } 152 GetRawKeyboardHeight()153 float GetRawKeyboardHeight() const 154 { 155 return rawKeyboardHeight_; 156 } 157 SetRawKeyboardHeight(float height)158 void SetRawKeyboardHeight(float height) 159 { 160 rawKeyboardHeight_ = height; 161 } 162 KeyboardSafeAreaEnabled()163 bool KeyboardSafeAreaEnabled() const 164 { 165 return keyboardSafeAreaEnabled_; 166 } 167 168 SafeAreaInsets GetCombinedSafeArea(const SafeAreaExpandOpts& opts) const; 169 GetGeoRestoreNodes()170 const std::set<WeakPtr<FrameNode>>& GetGeoRestoreNodes() const 171 { 172 return geoRestoreNodes_; 173 } 174 AddGeoRestoreNode(const WeakPtr<FrameNode> & node)175 void AddGeoRestoreNode(const WeakPtr<FrameNode>& node) 176 { 177 geoRestoreNodes_.insert(node); 178 } 179 AddNeedExpandNode(const WeakPtr<FrameNode> & node)180 void AddNeedExpandNode(const WeakPtr<FrameNode>& node) 181 { 182 needExpandNodes_.insert(node); 183 } 184 185 bool AddNodeToExpandListIfNeeded(const WeakPtr<FrameNode>& node); 186 ClearNeedExpandNode()187 void ClearNeedExpandNode() 188 { 189 needExpandNodes_.clear(); 190 } 191 RemoveRestoreNode(const WeakPtr<FrameNode> & node)192 void RemoveRestoreNode(const WeakPtr<FrameNode>& node) 193 { 194 geoRestoreNodes_.erase(node); 195 } 196 GetSafeAreaCurve()197 RefPtr<InterpolatingSpring> GetSafeAreaCurve() const 198 { 199 return safeAreaCurve_; 200 } 201 void ExpandSafeArea(); 202 203 OffsetF GetWindowWrapperOffset(); 204 205 SafeAreaInsets GetSafeAreaWithoutProcess() const; 206 207 bool SetIsFullScreen(bool value); 208 bool SetIsNeedAvoidWindow(bool value); 209 bool SetIgnoreSafeArea(bool value); 210 bool SetKeyBoardAvoidMode(KeyBoardAvoidMode value); 211 KeyBoardAvoidMode GetKeyBoardAvoidMode(); IsIgnoreAsfeArea()212 bool IsIgnoreAsfeArea() 213 { 214 return ignoreSafeArea_; 215 } IsNeedAvoidWindow()216 bool IsNeedAvoidWindow() 217 { 218 return isNeedAvoidWindow_; 219 } IsFullScreen()220 bool IsFullScreen() 221 { 222 return isFullScreen_; 223 } 224 bool SetIsAtomicService(bool value); 225 bool IsAtomicService() const; 226 GetSafeHeight()227 float GetSafeHeight() const 228 { 229 Dimension safeDistance = 16.0_vp; 230 return safeDistance.ConvertToPx(); 231 } 232 SetLastKeyboardPoistion(float position)233 void SetLastKeyboardPoistion(float position) 234 { 235 lastKeyboardY_ = position; 236 } 237 GetLastKeyboardPoistion()238 float GetLastKeyboardPoistion() const 239 { 240 return lastKeyboardY_; 241 } 242 243 bool IsSafeAreaValid() const; 244 // check if the page node needs to be avoid keyboard 245 bool CheckPageNeedAvoidKeyboard(const RefPtr<FrameNode>& frameNode); 246 GetkeyboardHeightConsideringUIExtension()247 uint32_t GetkeyboardHeightConsideringUIExtension() 248 { 249 return keyboardHeightConsideringUIExtension_; 250 } SetkeyboardHeightConsideringUIExtension(uint32_t height)251 void SetkeyboardHeightConsideringUIExtension(uint32_t height) 252 { 253 if (keyboardHeightConsideringUIExtension_ != height) { 254 for (const auto& [nodeId, callback] : keyboardChangeCbsConsideringUIExt_) { 255 if (callback) { 256 callback(); 257 } 258 } 259 keyboardHeightConsideringUIExtension_ = height; 260 } 261 } AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId,const std::function<void ()> & callback)262 void AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId, const std::function<void()>& callback) 263 { 264 keyboardChangeCbsConsideringUIExt_[nodeId] = callback; 265 } RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId)266 void RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId) 267 { 268 keyboardChangeCbsConsideringUIExt_.erase(nodeId); 269 } 270 271 PaddingPropertyF SafeAreaToPadding(bool withoutProcess = false); 272 273 private: 274 bool isAtomicService_ = false; 275 276 // app window is full screen 277 // todo: remove and only use isNeedAvoidWindow_ 278 bool isFullScreen_ = false; 279 280 /** 281 * @brief Indicates whether the UI within the current window type needs to avoid SafeAreaInsets. 282 */ 283 bool isNeedAvoidWindow_ = false; 284 285 /** 286 * @brief Indicates whether to ignore the SafeAreaInsets, specified by the developer from frontend. 287 */ 288 bool ignoreSafeArea_ = false; 289 290 /** 291 * @brief Indicates whether the keyboard safe area is enabled. When enabled, UI avoids the keyboard inset and the 292 * Page is compressed when the keyboard is up. When disabled, the size of Page doesn't change, but Page would 293 * offset vertically according to [keyboardOffset_]. 294 */ 295 bool keyboardSafeAreaEnabled_ = false; 296 297 KeyBoardAvoidMode keyboardAvoidMode_ = KeyBoardAvoidMode::OFFSET; 298 299 SafeAreaInsets systemSafeArea_; 300 SafeAreaInsets cutoutSafeArea_; 301 SafeAreaInsets navSafeArea_; 302 // keyboard is bottom direction only 303 SafeAreaInsets::Inset keyboardInset_; 304 305 /** 306 * @brief A set of weak pointers to FrameNode objects whose geometry info are saved before their SafeArea 307 * expansion. The geometry info of these nodes need to be restored when their next Layout task begins. 308 */ 309 std::set<WeakPtr<FrameNode>> geoRestoreNodes_; 310 311 struct DepthCompare { operatorDepthCompare312 bool operator()(const WeakPtr<FrameNode>& a, const WeakPtr<FrameNode>& b) const 313 { 314 auto ptrA = a.Upgrade(); 315 auto ptrB = b.Upgrade(); 316 if (!ptrA || !ptrB) { 317 return false; 318 } 319 if (ptrA->GetDepth() < ptrB->GetDepth()) { 320 return true; 321 } 322 if (ptrA->GetDepth() == ptrB->GetDepth()) { 323 return ptrA < ptrB; 324 } 325 return false; 326 } 327 }; 328 std::set<WeakPtr<FrameNode>, DepthCompare> needExpandNodes_; 329 // amount of offset to apply to Page when keyboard is up 330 float keyboardOffset_ = 0.0f; 331 float lastKeyboardY_ = 0.0f; 332 float rawKeyboardHeight_ = 0.0f; 333 334 static constexpr float SAFE_AREA_VELOCITY = 0.0f; 335 static constexpr float SAFE_AREA_MASS = 1.0f; 336 static constexpr float SAFE_AREA_STIFFNESS = 228.0f; 337 static constexpr float SAFE_AREA_DAMPING = 30.0f; 338 RefPtr<InterpolatingSpring> safeAreaCurve_ = AceType::MakeRefPtr<InterpolatingSpring>( 339 SAFE_AREA_VELOCITY, SAFE_AREA_MASS, SAFE_AREA_STIFFNESS, SAFE_AREA_DAMPING); 340 341 uint32_t keyboardHeightConsideringUIExtension_ = 0; 342 std::unordered_map<int32_t, std::function<void()>> keyboardChangeCbsConsideringUIExt_; 343 344 ACE_DISALLOW_COPY_AND_MOVE(SafeAreaManager); 345 }; 346 } // namespace OHOS::Ace::NG 347 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_SAFE_AREA_SAFE_AREA_MANAGER_H 348