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