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 return keyboardInset_; 135 } 136 UpdateKeyboardOffset(float offset)137 void UpdateKeyboardOffset(float offset) 138 { 139 keyboardOffset_ = offset; 140 } 141 float GetKeyboardOffset() const; 142 GetRawKeyboardHeight()143 float GetRawKeyboardHeight() const 144 { 145 return rawKeyboardHeight_; 146 } 147 SetRawKeyboardHeight(float height)148 void SetRawKeyboardHeight(float height) 149 { 150 rawKeyboardHeight_ = height; 151 } 152 KeyboardSafeAreaEnabled()153 bool KeyboardSafeAreaEnabled() const 154 { 155 return keyboardSafeAreaEnabled_; 156 } 157 158 SafeAreaInsets GetCombinedSafeArea(const SafeAreaExpandOpts& opts) const; 159 GetGeoRestoreNodes()160 const std::set<WeakPtr<FrameNode>>& GetGeoRestoreNodes() const 161 { 162 return geoRestoreNodes_; 163 } 164 AddGeoRestoreNode(const WeakPtr<FrameNode> & node)165 void AddGeoRestoreNode(const WeakPtr<FrameNode>& node) 166 { 167 geoRestoreNodes_.insert(node); 168 } 169 AddNeedExpandNode(const WeakPtr<FrameNode> & node)170 void AddNeedExpandNode(const WeakPtr<FrameNode>& node) 171 { 172 needExpandNodes_.insert(node); 173 } 174 175 bool AddNodeToExpandListIfNeeded(const WeakPtr<FrameNode>& node); 176 ClearNeedExpandNode()177 void ClearNeedExpandNode() 178 { 179 needExpandNodes_.clear(); 180 } 181 RemoveRestoreNode(const WeakPtr<FrameNode> & node)182 void RemoveRestoreNode(const WeakPtr<FrameNode>& node) 183 { 184 geoRestoreNodes_.erase(node); 185 } 186 GetSafeAreaCurve()187 RefPtr<InterpolatingSpring> GetSafeAreaCurve() const 188 { 189 return safeAreaCurve_; 190 } 191 void ExpandSafeArea(); 192 193 OffsetF GetWindowWrapperOffset(); 194 195 SafeAreaInsets GetSafeAreaWithoutProcess() const; 196 197 bool SetIsFullScreen(bool value); 198 bool SetIsNeedAvoidWindow(bool value); 199 bool SetIgnoreSafeArea(bool value); 200 bool SetKeyBoardAvoidMode(bool value); IsIgnoreAsfeArea()201 bool IsIgnoreAsfeArea() 202 { 203 return ignoreSafeArea_; 204 } IsNeedAvoidWindow()205 bool IsNeedAvoidWindow() 206 { 207 return isNeedAvoidWindow_; 208 } IsFullScreen()209 bool IsFullScreen() 210 { 211 return isFullScreen_; 212 } 213 bool SetIsAtomicService(bool value); 214 bool IsAtomicService() const; 215 GetSafeHeight()216 float GetSafeHeight() const 217 { 218 Dimension safeDistance = 16.0_vp; 219 return safeDistance.ConvertToPx(); 220 } 221 SetLastKeyboardPoistion(float position)222 void SetLastKeyboardPoistion(float position) 223 { 224 lastKeyboardY_ = position; 225 } 226 GetLastKeyboardPoistion()227 float GetLastKeyboardPoistion() const 228 { 229 return lastKeyboardY_; 230 } 231 232 bool IsSafeAreaValid() const; 233 // check if the page node needs to be avoid keyboard 234 bool CheckPageNeedAvoidKeyboard(const RefPtr<FrameNode>& frameNode); 235 GetkeyboardHeightConsideringUIExtension()236 uint32_t GetkeyboardHeightConsideringUIExtension() 237 { 238 return keyboardHeightConsideringUIExtension_; 239 } SetkeyboardHeightConsideringUIExtension(uint32_t height)240 void SetkeyboardHeightConsideringUIExtension(uint32_t height) 241 { 242 if (keyboardHeightConsideringUIExtension_ != height) { 243 for (const auto& [nodeId, callback] : keyboardChangeCbsConsideringUIExt_) { 244 if (callback) { 245 callback(); 246 } 247 } 248 keyboardHeightConsideringUIExtension_ = height; 249 } 250 } AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId,const std::function<void ()> & callback)251 void AddKeyboardChangeCallbackConsideringUIExt(int32_t nodeId, const std::function<void()>& callback) 252 { 253 keyboardChangeCbsConsideringUIExt_[nodeId] = callback; 254 } RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId)255 void RemoveKeyboardChangeCallbackConsideringUIExt(int32_t nodeId) 256 { 257 keyboardChangeCbsConsideringUIExt_.erase(nodeId); 258 } 259 260 private: 261 bool isAtomicService_ = false; 262 263 // app window is full screen 264 // todo: remove and only use isNeedAvoidWindow_ 265 bool isFullScreen_ = false; 266 267 /** 268 * @brief Indicates whether the UI within the current window type needs to avoid SafeAreaInsets. 269 */ 270 bool isNeedAvoidWindow_ = false; 271 272 /** 273 * @brief Indicates whether to ignore the SafeAreaInsets, specified by the developer from frontend. 274 */ 275 bool ignoreSafeArea_ = false; 276 277 /** 278 * @brief Indicates whether the keyboard safe area is enabled. When enabled, UI avoids the keyboard inset and the 279 * Page is compressed when the keyboard is up. When disabled, the size of Page doesn't change, but Page would 280 * offset vertically according to [keyboardOffset_]. 281 */ 282 bool keyboardSafeAreaEnabled_ = false; 283 284 SafeAreaInsets systemSafeArea_; 285 SafeAreaInsets cutoutSafeArea_; 286 SafeAreaInsets navSafeArea_; 287 // keyboard is bottom direction only 288 SafeAreaInsets::Inset keyboardInset_; 289 290 /** 291 * @brief A set of weak pointers to FrameNode objects whose geometry info are saved before their SafeArea 292 * expansion. The geometry info of these nodes need to be restored when their next Layout task begins. 293 */ 294 std::set<WeakPtr<FrameNode>> geoRestoreNodes_; 295 296 struct DepthCompare { operatorDepthCompare297 bool operator()(const WeakPtr<FrameNode>& a, const WeakPtr<FrameNode>& b) const 298 { 299 auto ptrA = a.Upgrade(); 300 auto ptrB = b.Upgrade(); 301 if (!ptrA || !ptrB) { 302 return false; 303 } 304 if (ptrA->GetDepth() < ptrB->GetDepth()) { 305 return true; 306 } 307 if (ptrA->GetDepth() == ptrB->GetDepth()) { 308 return ptrA < ptrB; 309 } 310 return false; 311 } 312 }; 313 std::set<WeakPtr<FrameNode>, DepthCompare> needExpandNodes_; 314 // amount of offset to apply to Page when keyboard is up 315 float keyboardOffset_ = 0.0f; 316 float lastKeyboardY_ = 0.0f; 317 float rawKeyboardHeight_ = 0.0f; 318 319 static constexpr float SAFE_AREA_VELOCITY = 0.0f; 320 static constexpr float SAFE_AREA_MASS = 1.0f; 321 static constexpr float SAFE_AREA_STIFFNESS = 228.0f; 322 static constexpr float SAFE_AREA_DAMPING = 30.0f; 323 RefPtr<InterpolatingSpring> safeAreaCurve_ = AceType::MakeRefPtr<InterpolatingSpring>( 324 SAFE_AREA_VELOCITY, SAFE_AREA_MASS, SAFE_AREA_STIFFNESS, SAFE_AREA_DAMPING); 325 326 uint32_t keyboardHeightConsideringUIExtension_ = 0; 327 std::unordered_map<int32_t, std::function<void()>> keyboardChangeCbsConsideringUIExt_; 328 329 ACE_DISALLOW_COPY_AND_MOVE(SafeAreaManager); 330 }; 331 } // namespace OHOS::Ace::NG 332 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_SAFE_AREA_SAFE_AREA_MANAGER_H 333