1e0dac50fSopenharmony_ci/* 2e0dac50fSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License. 5e0dac50fSopenharmony_ci * You may obtain a copy of the License at 6e0dac50fSopenharmony_ci * 7e0dac50fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8e0dac50fSopenharmony_ci * 9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and 13e0dac50fSopenharmony_ci * limitations under the License. 14e0dac50fSopenharmony_ci */ 15e0dac50fSopenharmony_ci 16e0dac50fSopenharmony_ci#include "window_layout_policy.h" 17e0dac50fSopenharmony_ci#include "display_manager_service_inner.h" 18e0dac50fSopenharmony_ci#include "persistent_storage.h" 19e0dac50fSopenharmony_ci#include "remote_animation.h" 20e0dac50fSopenharmony_ci#include "window_helper.h" 21e0dac50fSopenharmony_ci#include "window_inner_manager.h" 22e0dac50fSopenharmony_ci#include "window_manager_hilog.h" 23e0dac50fSopenharmony_ci#include "window_manager_service_utils.h" 24e0dac50fSopenharmony_ci#include "wm_common_inner.h" 25e0dac50fSopenharmony_ci#include "wm_math.h" 26e0dac50fSopenharmony_ci#include <transaction/rs_sync_transaction_controller.h> 27e0dac50fSopenharmony_ci 28e0dac50fSopenharmony_cinamespace OHOS { 29e0dac50fSopenharmony_cinamespace Rosen { 30e0dac50fSopenharmony_cinamespace { 31e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Layout"}; 32e0dac50fSopenharmony_ci} 33e0dac50fSopenharmony_ci 34e0dac50fSopenharmony_ciuint32_t WindowLayoutPolicy::floatingBottomPosY_ = 0; 35e0dac50fSopenharmony_ciuint32_t WindowLayoutPolicy::maxFloatingWindowSize_ = 1920; // 1920: default max size of floating window 36e0dac50fSopenharmony_ci 37e0dac50fSopenharmony_ciWindowLayoutPolicy::WindowLayoutPolicy(DisplayGroupWindowTree& displayGroupWindowTree) 38e0dac50fSopenharmony_ci : displayGroupWindowTree_(displayGroupWindowTree) 39e0dac50fSopenharmony_ci{ 40e0dac50fSopenharmony_ci limitRectMap_ = DisplayGroupInfo::GetInstance().GetAllDisplayRects(); 41e0dac50fSopenharmony_ci} 42e0dac50fSopenharmony_ci 43e0dac50fSopenharmony_civoid WindowLayoutPolicy::Launch() 44e0dac50fSopenharmony_ci{ 45e0dac50fSopenharmony_ci WLOGI("WindowLayoutPolicy::Launch"); 46e0dac50fSopenharmony_ci} 47e0dac50fSopenharmony_ci 48e0dac50fSopenharmony_civoid WindowLayoutPolicy::Reorder() 49e0dac50fSopenharmony_ci{ 50e0dac50fSopenharmony_ci WLOGI("WindowLayoutPolicy::Reorder"); 51e0dac50fSopenharmony_ci} 52e0dac50fSopenharmony_ci 53e0dac50fSopenharmony_civoid WindowLayoutPolicy::LimitWindowToBottomRightCorner(const sptr<WindowNode>& node) 54e0dac50fSopenharmony_ci{ 55e0dac50fSopenharmony_ci Rect windowRect = node->GetRequestRect(); 56e0dac50fSopenharmony_ci Rect displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(node->GetDisplayId()); 57e0dac50fSopenharmony_ci windowRect.posX_ = std::max(windowRect.posX_, displayRect.posX_); 58e0dac50fSopenharmony_ci windowRect.posY_ = std::max(windowRect.posY_, displayRect.posY_); 59e0dac50fSopenharmony_ci windowRect.width_ = std::min(windowRect.width_, displayRect.width_); 60e0dac50fSopenharmony_ci windowRect.height_ = std::min(windowRect.height_, displayRect.height_); 61e0dac50fSopenharmony_ci 62e0dac50fSopenharmony_ci if (windowRect.posX_ + static_cast<int32_t>(windowRect.width_) > 63e0dac50fSopenharmony_ci displayRect.posX_ + static_cast<int32_t>(displayRect.width_)) { 64e0dac50fSopenharmony_ci windowRect.posX_ = displayRect.posX_ + static_cast<int32_t>(displayRect.width_) - 65e0dac50fSopenharmony_ci static_cast<int32_t>(windowRect.width_); 66e0dac50fSopenharmony_ci } 67e0dac50fSopenharmony_ci 68e0dac50fSopenharmony_ci if (windowRect.posY_ + static_cast<int32_t>(windowRect.height_) > 69e0dac50fSopenharmony_ci displayRect.posY_ + static_cast<int32_t>(displayRect.height_)) { 70e0dac50fSopenharmony_ci windowRect.posY_ = displayRect.posY_ + static_cast<int32_t>(displayRect.height_) - 71e0dac50fSopenharmony_ci static_cast<int32_t>(windowRect.height_); 72e0dac50fSopenharmony_ci } 73e0dac50fSopenharmony_ci node->SetRequestRect(windowRect); 74e0dac50fSopenharmony_ci 75e0dac50fSopenharmony_ci WLOGD("WindowId: %{public}d, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]", 76e0dac50fSopenharmony_ci node->GetWindowId(), windowRect.posX_, windowRect.posY_, windowRect.width_, windowRect.height_); 77e0dac50fSopenharmony_ci 78e0dac50fSopenharmony_ci for (auto& childNode : node->children_) { 79e0dac50fSopenharmony_ci LimitWindowToBottomRightCorner(childNode); 80e0dac50fSopenharmony_ci } 81e0dac50fSopenharmony_ci} 82e0dac50fSopenharmony_ci 83e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateDisplayGroupRect() 84e0dac50fSopenharmony_ci{ 85e0dac50fSopenharmony_ci Rect newDisplayGroupRect = { 0, 0, 0, 0 }; 86e0dac50fSopenharmony_ci // current multi-display is only support left-right combination, maxNum is two 87e0dac50fSopenharmony_ci for (auto& elem : DisplayGroupInfo::GetInstance().GetAllDisplayRects()) { 88e0dac50fSopenharmony_ci newDisplayGroupRect.posX_ = std::min(displayGroupRect_.posX_, elem.second.posX_); 89e0dac50fSopenharmony_ci newDisplayGroupRect.posY_ = std::min(displayGroupRect_.posY_, elem.second.posY_); 90e0dac50fSopenharmony_ci int32_t right = std::max(newDisplayGroupRect.posX_ + static_cast<int32_t>(newDisplayGroupRect.width_), 91e0dac50fSopenharmony_ci elem.second.posX_+ static_cast<int32_t>(elem.second.width_)); 92e0dac50fSopenharmony_ci newDisplayGroupRect.width_ = right - newDisplayGroupRect.posX_; 93e0dac50fSopenharmony_ci int32_t maxHeight = std::max(newDisplayGroupRect.posY_ + static_cast<int32_t>(newDisplayGroupRect.height_), 94e0dac50fSopenharmony_ci elem.second.posY_+ static_cast<int32_t>(elem.second.height_)); 95e0dac50fSopenharmony_ci newDisplayGroupRect.height_ = maxHeight - newDisplayGroupRect.posY_; 96e0dac50fSopenharmony_ci } 97e0dac50fSopenharmony_ci displayGroupRect_ = newDisplayGroupRect; 98e0dac50fSopenharmony_ci WLOGD("Update displayGroupRect: [%{public}d, %{public}d, %{public}d, %{public}d]", 99e0dac50fSopenharmony_ci displayGroupRect_.posX_, displayGroupRect_.posY_, displayGroupRect_.width_, displayGroupRect_.height_); 100e0dac50fSopenharmony_ci} 101e0dac50fSopenharmony_ci 102e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateDisplayGroupLimitRect() 103e0dac50fSopenharmony_ci{ 104e0dac50fSopenharmony_ci auto firstDisplayLimitRect = limitRectMap_.begin()->second; 105e0dac50fSopenharmony_ci Rect newDisplayGroupLimitRect = { firstDisplayLimitRect.posX_, firstDisplayLimitRect.posY_, 0, 0 }; 106e0dac50fSopenharmony_ci for (auto& elem : limitRectMap_) { 107e0dac50fSopenharmony_ci newDisplayGroupLimitRect.posX_ = std::min(newDisplayGroupLimitRect.posX_, elem.second.posX_); 108e0dac50fSopenharmony_ci newDisplayGroupLimitRect.posY_ = std::min(newDisplayGroupLimitRect.posY_, elem.second.posY_); 109e0dac50fSopenharmony_ci 110e0dac50fSopenharmony_ci int32_t maxWidth = std::max(newDisplayGroupLimitRect.posX_ + 111e0dac50fSopenharmony_ci static_cast<int32_t>(newDisplayGroupLimitRect.width_), 112e0dac50fSopenharmony_ci elem.second.posX_+ static_cast<int32_t>(elem.second.width_)); 113e0dac50fSopenharmony_ci 114e0dac50fSopenharmony_ci int32_t maxHeight = std::max(newDisplayGroupLimitRect.posY_ + 115e0dac50fSopenharmony_ci static_cast<int32_t>(newDisplayGroupLimitRect.height_), 116e0dac50fSopenharmony_ci elem.second.posY_+ static_cast<int32_t>(elem.second.height_)); 117e0dac50fSopenharmony_ci newDisplayGroupLimitRect.width_ = static_cast<uint32_t>(maxWidth - newDisplayGroupLimitRect.posX_); 118e0dac50fSopenharmony_ci newDisplayGroupLimitRect.height_ = static_cast<uint32_t>(maxHeight - newDisplayGroupLimitRect.posY_); 119e0dac50fSopenharmony_ci } 120e0dac50fSopenharmony_ci displayGroupLimitRect_ = newDisplayGroupLimitRect; 121e0dac50fSopenharmony_ci WLOGFD("Update displayGroupLimitRect: [%{public}d, %{public}d, %{public}d, %{public}d]", 122e0dac50fSopenharmony_ci displayGroupLimitRect_.posX_, displayGroupLimitRect_.posY_, 123e0dac50fSopenharmony_ci displayGroupLimitRect_.width_, displayGroupLimitRect_.height_); 124e0dac50fSopenharmony_ci} 125e0dac50fSopenharmony_ci 126e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateRectInDisplayGroup(const sptr<WindowNode>& node, 127e0dac50fSopenharmony_ci const Rect& oriDisplayRect, 128e0dac50fSopenharmony_ci const Rect& newDisplayRect) 129e0dac50fSopenharmony_ci{ 130e0dac50fSopenharmony_ci Rect newRect = node->GetRequestRect(); 131e0dac50fSopenharmony_ci WLOGD("Before update rect in display group, windowId: %{public}d, rect: [%{public}d, %{public}d, " 132e0dac50fSopenharmony_ci "%{public}d, %{public}d]", node->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); 133e0dac50fSopenharmony_ci 134e0dac50fSopenharmony_ci newRect.posX_ = newRect.posX_ - oriDisplayRect.posX_ + newDisplayRect.posX_; 135e0dac50fSopenharmony_ci newRect.posY_ = newRect.posY_ - oriDisplayRect.posY_ + newDisplayRect.posY_; 136e0dac50fSopenharmony_ci node->SetRequestRect(newRect); 137e0dac50fSopenharmony_ci WLOGD("After update rect in display group, windowId: %{public}d, newRect: [%{public}d, %{public}d, " 138e0dac50fSopenharmony_ci "%{public}d, %{public}d]", node->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); 139e0dac50fSopenharmony_ci 140e0dac50fSopenharmony_ci for (auto& childNode : node->children_) { 141e0dac50fSopenharmony_ci UpdateRectInDisplayGroup(childNode, oriDisplayRect, newDisplayRect); 142e0dac50fSopenharmony_ci } 143e0dac50fSopenharmony_ci} 144e0dac50fSopenharmony_ci 145e0dac50fSopenharmony_cibool WindowLayoutPolicy::IsMultiDisplay() 146e0dac50fSopenharmony_ci{ 147e0dac50fSopenharmony_ci return isMultiDisplay_; 148e0dac50fSopenharmony_ci} 149e0dac50fSopenharmony_ci 150e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateMultiDisplayFlag() 151e0dac50fSopenharmony_ci{ 152e0dac50fSopenharmony_ci if (DisplayGroupInfo::GetInstance().GetAllDisplayIds().size() > 1) { 153e0dac50fSopenharmony_ci isMultiDisplay_ = true; 154e0dac50fSopenharmony_ci WLOGFD("Current mode is multi-display"); 155e0dac50fSopenharmony_ci } else { 156e0dac50fSopenharmony_ci isMultiDisplay_ = false; 157e0dac50fSopenharmony_ci WLOGFD("Current mode is not multi-display"); 158e0dac50fSopenharmony_ci } 159e0dac50fSopenharmony_ci} 160e0dac50fSopenharmony_ci 161e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateRectInDisplayGroupForAllNodes(DisplayId displayId, 162e0dac50fSopenharmony_ci const Rect& oriDisplayRect, 163e0dac50fSopenharmony_ci const Rect& newDisplayRect) 164e0dac50fSopenharmony_ci{ 165e0dac50fSopenharmony_ci WLOGFD("DisplayId: %{public}" PRIu64", oriDisplayRect: [ %{public}d, %{public}d, %{public}d, %{public}d] " 166e0dac50fSopenharmony_ci "newDisplayRect: [ %{public}d, %{public}d, %{public}d, %{public}d]", 167e0dac50fSopenharmony_ci displayId, oriDisplayRect.posX_, oriDisplayRect.posY_, oriDisplayRect.width_, oriDisplayRect.height_, 168e0dac50fSopenharmony_ci newDisplayRect.posX_, newDisplayRect.posY_, newDisplayRect.width_, newDisplayRect.height_); 169e0dac50fSopenharmony_ci 170e0dac50fSopenharmony_ci auto& displayWindowTree = displayGroupWindowTree_[displayId]; 171e0dac50fSopenharmony_ci for (auto& iter : displayWindowTree) { 172e0dac50fSopenharmony_ci auto& nodeVector = *(iter.second); 173e0dac50fSopenharmony_ci for (auto& node : nodeVector) { 174e0dac50fSopenharmony_ci if (!node->isShowingOnMultiDisplays_) { 175e0dac50fSopenharmony_ci UpdateRectInDisplayGroup(node, oriDisplayRect, newDisplayRect); 176e0dac50fSopenharmony_ci } 177e0dac50fSopenharmony_ci if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { 178e0dac50fSopenharmony_ci LimitWindowToBottomRightCorner(node); 179e0dac50fSopenharmony_ci } 180e0dac50fSopenharmony_ci } 181e0dac50fSopenharmony_ci WLOGFD("Recalculate window rect in display group, displayId: %{public}" PRIu64", rootType: %{public}d", 182e0dac50fSopenharmony_ci displayId, iter.first); 183e0dac50fSopenharmony_ci } 184e0dac50fSopenharmony_ci} 185e0dac50fSopenharmony_ci 186e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateDisplayRectAndDisplayGroupInfo(const std::map<DisplayId, Rect>& displayRectMap) 187e0dac50fSopenharmony_ci{ 188e0dac50fSopenharmony_ci for (auto& elem : displayRectMap) { 189e0dac50fSopenharmony_ci auto& displayId = elem.first; 190e0dac50fSopenharmony_ci auto& displayRect = elem.second; 191e0dac50fSopenharmony_ci DisplayGroupInfo::GetInstance().SetDisplayRect(displayId, displayRect); 192e0dac50fSopenharmony_ci } 193e0dac50fSopenharmony_ci} 194e0dac50fSopenharmony_ci 195e0dac50fSopenharmony_civoid WindowLayoutPolicy::PostProcessWhenDisplayChange() 196e0dac50fSopenharmony_ci{ 197e0dac50fSopenharmony_ci DisplayGroupInfo::GetInstance().UpdateLeftAndRightDisplayId(); 198e0dac50fSopenharmony_ci UpdateMultiDisplayFlag(); 199e0dac50fSopenharmony_ci Launch(); 200e0dac50fSopenharmony_ci} 201e0dac50fSopenharmony_ci 202e0dac50fSopenharmony_civoid WindowLayoutPolicy::ProcessDisplayCreate(DisplayId displayId, const std::map<DisplayId, Rect>& displayRectMap) 203e0dac50fSopenharmony_ci{ 204e0dac50fSopenharmony_ci const auto& oriDisplayRectMap = DisplayGroupInfo::GetInstance().GetAllDisplayRects(); 205e0dac50fSopenharmony_ci // check displayId and displayRectMap size 206e0dac50fSopenharmony_ci if (oriDisplayRectMap.find(displayId) == oriDisplayRectMap.end() || 207e0dac50fSopenharmony_ci displayRectMap.size() != oriDisplayRectMap.size()) { 208e0dac50fSopenharmony_ci WLOGFE("current display is exited or displayInfo map size is error, displayId: %{public}" PRIu64"", displayId); 209e0dac50fSopenharmony_ci return; 210e0dac50fSopenharmony_ci } 211e0dac50fSopenharmony_ci for (auto& elem : displayRectMap) { 212e0dac50fSopenharmony_ci auto iter = oriDisplayRectMap.find(elem.first); 213e0dac50fSopenharmony_ci if (iter != oriDisplayRectMap.end()) { 214e0dac50fSopenharmony_ci const auto& oriDisplayRect = iter->second; 215e0dac50fSopenharmony_ci const auto& newDisplayRect = elem.second; 216e0dac50fSopenharmony_ci UpdateRectInDisplayGroupForAllNodes(elem.first, oriDisplayRect, newDisplayRect); 217e0dac50fSopenharmony_ci } else { 218e0dac50fSopenharmony_ci if (elem.first != displayId) { 219e0dac50fSopenharmony_ci WLOGFE("Wrong display, displayId: %{public}" PRIu64"", displayId); 220e0dac50fSopenharmony_ci return; 221e0dac50fSopenharmony_ci } 222e0dac50fSopenharmony_ci } 223e0dac50fSopenharmony_ci } 224e0dac50fSopenharmony_ci UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); 225e0dac50fSopenharmony_ci PostProcessWhenDisplayChange(); 226e0dac50fSopenharmony_ci WLOGI("Process display create, displayId: %{public}" PRIu64"", displayId); 227e0dac50fSopenharmony_ci} 228e0dac50fSopenharmony_ci 229e0dac50fSopenharmony_civoid WindowLayoutPolicy::ProcessDisplayDestroy(DisplayId displayId, const std::map<DisplayId, Rect>& displayRectMap) 230e0dac50fSopenharmony_ci{ 231e0dac50fSopenharmony_ci const auto& oriDisplayRectMap = DisplayGroupInfo::GetInstance().GetAllDisplayRects(); 232e0dac50fSopenharmony_ci // check displayId and displayRectMap size 233e0dac50fSopenharmony_ci if (oriDisplayRectMap.find(displayId) != oriDisplayRectMap.end() || 234e0dac50fSopenharmony_ci displayRectMap.size() != oriDisplayRectMap.size()) { 235e0dac50fSopenharmony_ci WLOGFE("can not find current display or displayInfo map size is error, displayId: %{public}" PRIu64"", 236e0dac50fSopenharmony_ci displayId); 237e0dac50fSopenharmony_ci return; 238e0dac50fSopenharmony_ci } 239e0dac50fSopenharmony_ci for (auto oriIter = oriDisplayRectMap.begin(); oriIter != oriDisplayRectMap.end();) { 240e0dac50fSopenharmony_ci auto newIter = displayRectMap.find(oriIter->first); 241e0dac50fSopenharmony_ci if (newIter != displayRectMap.end()) { 242e0dac50fSopenharmony_ci const auto& oriDisplayRect = oriIter->second; 243e0dac50fSopenharmony_ci const auto& newDisplayRect = newIter->second; 244e0dac50fSopenharmony_ci UpdateRectInDisplayGroupForAllNodes(oriIter->first, oriDisplayRect, newDisplayRect); 245e0dac50fSopenharmony_ci } else { 246e0dac50fSopenharmony_ci if (oriIter->first != displayId) { 247e0dac50fSopenharmony_ci WLOGFE("Wrong display, displayId: %{public}" PRIu64"", displayId); 248e0dac50fSopenharmony_ci return; 249e0dac50fSopenharmony_ci } 250e0dac50fSopenharmony_ci } 251e0dac50fSopenharmony_ci ++oriIter; 252e0dac50fSopenharmony_ci } 253e0dac50fSopenharmony_ci 254e0dac50fSopenharmony_ci UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); 255e0dac50fSopenharmony_ci PostProcessWhenDisplayChange(); 256e0dac50fSopenharmony_ci WLOGI("Process display destroy, displayId: %{public}" PRIu64"", displayId); 257e0dac50fSopenharmony_ci} 258e0dac50fSopenharmony_ci 259e0dac50fSopenharmony_civoid WindowLayoutPolicy::ProcessDisplaySizeChangeOrRotation(DisplayId displayId, 260e0dac50fSopenharmony_ci const std::map<DisplayId, Rect>& displayRectMap) 261e0dac50fSopenharmony_ci{ 262e0dac50fSopenharmony_ci const auto& oriDisplayRectMap = DisplayGroupInfo::GetInstance().GetAllDisplayRects(); 263e0dac50fSopenharmony_ci // check displayId and displayRectMap size 264e0dac50fSopenharmony_ci if (oriDisplayRectMap.find(displayId) == oriDisplayRectMap.end() || 265e0dac50fSopenharmony_ci displayRectMap.size() != oriDisplayRectMap.size()) { 266e0dac50fSopenharmony_ci WLOGFE("can not find current display or displayInfo map size is error, displayId: %{public}" PRIu64"", 267e0dac50fSopenharmony_ci displayId); 268e0dac50fSopenharmony_ci return; 269e0dac50fSopenharmony_ci } 270e0dac50fSopenharmony_ci 271e0dac50fSopenharmony_ci for (auto& elem : displayRectMap) { 272e0dac50fSopenharmony_ci auto iter = oriDisplayRectMap.find(elem.first); 273e0dac50fSopenharmony_ci if (iter != oriDisplayRectMap.end()) { 274e0dac50fSopenharmony_ci UpdateRectInDisplayGroupForAllNodes(elem.first, iter->second, elem.second); 275e0dac50fSopenharmony_ci } 276e0dac50fSopenharmony_ci } 277e0dac50fSopenharmony_ci 278e0dac50fSopenharmony_ci UpdateDisplayRectAndDisplayGroupInfo(displayRectMap); 279e0dac50fSopenharmony_ci PostProcessWhenDisplayChange(); 280e0dac50fSopenharmony_ci WLOGI("Process display change, displayId: %{public}" PRIu64"", displayId); 281e0dac50fSopenharmony_ci} 282e0dac50fSopenharmony_ci 283e0dac50fSopenharmony_civoid WindowLayoutPolicy::ProcessDisplayVprChange(DisplayId displayId) 284e0dac50fSopenharmony_ci{ 285e0dac50fSopenharmony_ci Launch(); 286e0dac50fSopenharmony_ci} 287e0dac50fSopenharmony_ci 288e0dac50fSopenharmony_civoid WindowLayoutPolicy::LayoutWindowNodesByRootType(const std::vector<sptr<WindowNode>>& nodeVec) 289e0dac50fSopenharmony_ci{ 290e0dac50fSopenharmony_ci if (nodeVec.empty()) { 291e0dac50fSopenharmony_ci WLOGW("The node vector is empty!"); 292e0dac50fSopenharmony_ci return; 293e0dac50fSopenharmony_ci } 294e0dac50fSopenharmony_ci for (auto& node : nodeVec) { 295e0dac50fSopenharmony_ci LayoutWindowNode(node); 296e0dac50fSopenharmony_ci } 297e0dac50fSopenharmony_ci} 298e0dac50fSopenharmony_ci 299e0dac50fSopenharmony_civoid WindowLayoutPolicy::NotifyAnimationSizeChangeIfNeeded() 300e0dac50fSopenharmony_ci{ 301e0dac50fSopenharmony_ci if (!RemoteAnimation::CheckAnimationController()) { 302e0dac50fSopenharmony_ci WLOGFD("no animation controller!"); 303e0dac50fSopenharmony_ci return; 304e0dac50fSopenharmony_ci } 305e0dac50fSopenharmony_ci std::vector<uint32_t> fullScreenWinIds; 306e0dac50fSopenharmony_ci std::vector<uint32_t> floatMainIds; 307e0dac50fSopenharmony_ci for (auto& iter : displayGroupWindowTree_) { 308e0dac50fSopenharmony_ci auto& displayWindowTree = iter.second; 309e0dac50fSopenharmony_ci auto& nodeVec = *(displayWindowTree[WindowRootNodeType::APP_WINDOW_NODE]); 310e0dac50fSopenharmony_ci if (nodeVec.empty()) { 311e0dac50fSopenharmony_ci WLOGE("The node vector is empty!"); 312e0dac50fSopenharmony_ci return; 313e0dac50fSopenharmony_ci } 314e0dac50fSopenharmony_ci for (auto& node : nodeVec) { 315e0dac50fSopenharmony_ci // just has one fullscreen app node on foreground 316e0dac50fSopenharmony_ci if (WindowHelper::IsMainFullScreenWindow(node->GetWindowType(), node->GetWindowMode())) { 317e0dac50fSopenharmony_ci fullScreenWinIds.emplace_back(node->GetWindowId()); 318e0dac50fSopenharmony_ci } 319e0dac50fSopenharmony_ci if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { 320e0dac50fSopenharmony_ci floatMainIds.emplace_back(node->GetWindowId()); 321e0dac50fSopenharmony_ci } 322e0dac50fSopenharmony_ci } 323e0dac50fSopenharmony_ci } 324e0dac50fSopenharmony_ci RemoteAnimation::NotifyAnimationTargetsUpdate(fullScreenWinIds, floatMainIds); 325e0dac50fSopenharmony_ci} 326e0dac50fSopenharmony_ci 327e0dac50fSopenharmony_civoid WindowLayoutPolicy::LayoutWindowTree(DisplayId displayId) 328e0dac50fSopenharmony_ci{ 329e0dac50fSopenharmony_ci // reset limit rect 330e0dac50fSopenharmony_ci limitRectMap_[displayId] = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId); 331e0dac50fSopenharmony_ci displayGroupLimitRect_ = displayGroupRect_; 332e0dac50fSopenharmony_ci 333e0dac50fSopenharmony_ci // ensure that the avoid area windows are traversed first 334e0dac50fSopenharmony_ci auto& displayWindowTree = displayGroupWindowTree_[displayId]; 335e0dac50fSopenharmony_ci LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::ABOVE_WINDOW_NODE])); 336e0dac50fSopenharmony_ci LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::APP_WINDOW_NODE])); 337e0dac50fSopenharmony_ci LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::BELOW_WINDOW_NODE])); 338e0dac50fSopenharmony_ci} 339e0dac50fSopenharmony_ci 340e0dac50fSopenharmony_civoid WindowLayoutPolicy::LayoutWindowNode(const sptr<WindowNode>& node) 341e0dac50fSopenharmony_ci{ 342e0dac50fSopenharmony_ci if (node == nullptr || node->parent_ == nullptr) { 343e0dac50fSopenharmony_ci WLOGFE("Node or it's parent is nullptr"); 344e0dac50fSopenharmony_ci return; 345e0dac50fSopenharmony_ci } 346e0dac50fSopenharmony_ci if (!node->currentVisibility_) { 347e0dac50fSopenharmony_ci WLOGFD("window[%{public}u] currently not visible, no need to layout", node->GetWindowId()); 348e0dac50fSopenharmony_ci return; 349e0dac50fSopenharmony_ci } 350e0dac50fSopenharmony_ci 351e0dac50fSopenharmony_ci /* 352e0dac50fSopenharmony_ci * 1. update window rect 353e0dac50fSopenharmony_ci * 2. update diplayLimitRect and displayGroupRect if this is avoidNode 354e0dac50fSopenharmony_ci */ 355e0dac50fSopenharmony_ci UpdateLayoutRect(node); 356e0dac50fSopenharmony_ci if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) { 357e0dac50fSopenharmony_ci UpdateDisplayLimitRect(node, limitRectMap_[node->GetDisplayId()]); 358e0dac50fSopenharmony_ci UpdateDisplayGroupLimitRect(); 359e0dac50fSopenharmony_ci WindowInnerManager::GetInstance().NotifyDisplayLimitRectChange(limitRectMap_); 360e0dac50fSopenharmony_ci } 361e0dac50fSopenharmony_ci for (auto& childNode : node->children_) { 362e0dac50fSopenharmony_ci LayoutWindowNode(childNode); 363e0dac50fSopenharmony_ci } 364e0dac50fSopenharmony_ci} 365e0dac50fSopenharmony_ci 366e0dac50fSopenharmony_cibool WindowLayoutPolicy::IsVerticalDisplay(DisplayId displayId) const 367e0dac50fSopenharmony_ci{ 368e0dac50fSopenharmony_ci return DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).width_ < 369e0dac50fSopenharmony_ci DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).height_; 370e0dac50fSopenharmony_ci} 371e0dac50fSopenharmony_ci 372e0dac50fSopenharmony_civoid WindowLayoutPolicy::NotifyClientAndAnimation(const sptr<WindowNode>& node, 373e0dac50fSopenharmony_ci const Rect& winRect, WindowSizeChangeReason reason) 374e0dac50fSopenharmony_ci{ 375e0dac50fSopenharmony_ci if (node->GetWindowToken()) { 376e0dac50fSopenharmony_ci auto type = node->GetWindowType(); 377e0dac50fSopenharmony_ci auto syncTransactionController = RSSyncTransactionController::GetInstance(); 378e0dac50fSopenharmony_ci if (reason == WindowSizeChangeReason::ROTATION && syncTransactionController && IsNeedAnimationSync(type)) { 379e0dac50fSopenharmony_ci node->GetWindowToken()->UpdateWindowRect(winRect, node->GetDecoStatus(), reason, 380e0dac50fSopenharmony_ci syncTransactionController->GetRSTransaction()); 381e0dac50fSopenharmony_ci } else { 382e0dac50fSopenharmony_ci node->GetWindowToken()->UpdateWindowRect(winRect, node->GetDecoStatus(), reason); 383e0dac50fSopenharmony_ci } 384e0dac50fSopenharmony_ci WLOGFD("Id: %{public}d, winRect:[%{public}d, %{public}d, %{public}u, %{public}u], reason: " 385e0dac50fSopenharmony_ci "%{public}u", node->GetWindowId(), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_, reason); 386e0dac50fSopenharmony_ci } 387e0dac50fSopenharmony_ci if ((reason != WindowSizeChangeReason::MOVE) && (node->GetWindowType() != WindowType::WINDOW_TYPE_DOCK_SLICE)) { 388e0dac50fSopenharmony_ci node->ResetWindowSizeChangeReason(); 389e0dac50fSopenharmony_ci } 390e0dac50fSopenharmony_ci NotifyAnimationSizeChangeIfNeeded(); 391e0dac50fSopenharmony_ci} 392e0dac50fSopenharmony_ci 393e0dac50fSopenharmony_cibool WindowLayoutPolicy::IsNeedAnimationSync(WindowType type) 394e0dac50fSopenharmony_ci{ 395e0dac50fSopenharmony_ci if (type == WindowType::WINDOW_TYPE_POINTER || 396e0dac50fSopenharmony_ci type == WindowType::WINDOW_TYPE_BOOT_ANIMATION) { 397e0dac50fSopenharmony_ci return false; 398e0dac50fSopenharmony_ci } 399e0dac50fSopenharmony_ci return true; 400e0dac50fSopenharmony_ci} 401e0dac50fSopenharmony_ci 402e0dac50fSopenharmony_ciRect WindowLayoutPolicy::CalcEntireWindowHotZone(const sptr<WindowNode>& node, const Rect& winRect, uint32_t hotZone, 403e0dac50fSopenharmony_ci float vpr, TransformHelper::Vector2 hotZoneScale) 404e0dac50fSopenharmony_ci{ 405e0dac50fSopenharmony_ci Rect rect = winRect; 406e0dac50fSopenharmony_ci uint32_t hotZoneX = static_cast<uint32_t>(hotZone * vpr / hotZoneScale.x_); 407e0dac50fSopenharmony_ci uint32_t hotZoneY = static_cast<uint32_t>(hotZone * vpr / hotZoneScale.y_); 408e0dac50fSopenharmony_ci 409e0dac50fSopenharmony_ci if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { 410e0dac50fSopenharmony_ci if (rect.width_ < rect.height_) { 411e0dac50fSopenharmony_ci rect.posX_ -= static_cast<int32_t>(hotZoneX); 412e0dac50fSopenharmony_ci rect.width_ += (hotZoneX + hotZoneX); 413e0dac50fSopenharmony_ci } else { 414e0dac50fSopenharmony_ci rect.posY_ -= static_cast<int32_t>(hotZoneY); 415e0dac50fSopenharmony_ci rect.height_ += (hotZoneY + hotZoneY); 416e0dac50fSopenharmony_ci } 417e0dac50fSopenharmony_ci } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT) { 418e0dac50fSopenharmony_ci rect = DisplayGroupInfo::GetInstance().GetDisplayRect(node->GetDisplayId()); 419e0dac50fSopenharmony_ci } else if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { 420e0dac50fSopenharmony_ci rect.posX_ -= static_cast<int32_t>(hotZoneX); 421e0dac50fSopenharmony_ci rect.posY_ -= static_cast<int32_t>(hotZoneY); 422e0dac50fSopenharmony_ci rect.width_ += (hotZoneX + hotZoneX); 423e0dac50fSopenharmony_ci rect.height_ += (hotZoneY + hotZoneY); 424e0dac50fSopenharmony_ci } 425e0dac50fSopenharmony_ci return rect; 426e0dac50fSopenharmony_ci} 427e0dac50fSopenharmony_ci 428e0dac50fSopenharmony_civoid WindowLayoutPolicy::CalcAndSetNodeHotZone(const Rect& winRect, const sptr<WindowNode>& node) 429e0dac50fSopenharmony_ci{ 430e0dac50fSopenharmony_ci float virtualPixelRatio = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(node->GetDisplayId()); 431e0dac50fSopenharmony_ci TransformHelper::Vector2 hotZoneScale(1, 1); 432e0dac50fSopenharmony_ci if (node->GetWindowProperty()->isNeedComputerTransform()) { 433e0dac50fSopenharmony_ci node->ComputeTransform(); 434e0dac50fSopenharmony_ci hotZoneScale = WindowHelper::CalculateHotZoneScale(node->GetWindowProperty()->GetTransformMat()); 435e0dac50fSopenharmony_ci } 436e0dac50fSopenharmony_ci 437e0dac50fSopenharmony_ci auto hotZoneRectTouch = CalcEntireWindowHotZone(node, winRect, HOTZONE_TOUCH, virtualPixelRatio, hotZoneScale); 438e0dac50fSopenharmony_ci auto hotZoneRectPointer = CalcEntireWindowHotZone(node, winRect, HOTZONE_POINTER, virtualPixelRatio, hotZoneScale); 439e0dac50fSopenharmony_ci 440e0dac50fSopenharmony_ci node->SetEntireWindowTouchHotArea(hotZoneRectTouch); 441e0dac50fSopenharmony_ci node->SetEntireWindowPointerHotArea(hotZoneRectPointer); 442e0dac50fSopenharmony_ci 443e0dac50fSopenharmony_ci std::vector<Rect> requestedHotAreas; 444e0dac50fSopenharmony_ci node->GetWindowProperty()->GetTouchHotAreas(requestedHotAreas); 445e0dac50fSopenharmony_ci std::vector<Rect> touchHotAreas; 446e0dac50fSopenharmony_ci std::vector<Rect> pointerHotAreas; 447e0dac50fSopenharmony_ci if (requestedHotAreas.empty()) { 448e0dac50fSopenharmony_ci touchHotAreas.emplace_back(hotZoneRectTouch); 449e0dac50fSopenharmony_ci pointerHotAreas.emplace_back(hotZoneRectPointer); 450e0dac50fSopenharmony_ci } else { 451e0dac50fSopenharmony_ci if (!WindowHelper::CalculateTouchHotAreas(winRect, requestedHotAreas, touchHotAreas)) { 452e0dac50fSopenharmony_ci WLOGFW("some parameters in requestedHotAreas are abnormal"); 453e0dac50fSopenharmony_ci } 454e0dac50fSopenharmony_ci pointerHotAreas = touchHotAreas; 455e0dac50fSopenharmony_ci } 456e0dac50fSopenharmony_ci node->SetTouchHotAreas(touchHotAreas); 457e0dac50fSopenharmony_ci node->SetPointerHotAreas(pointerHotAreas); 458e0dac50fSopenharmony_ci} 459e0dac50fSopenharmony_ci 460e0dac50fSopenharmony_ciWindowLimits WindowLayoutPolicy::GetSystemSizeLimits(const sptr<WindowNode>& node, 461e0dac50fSopenharmony_ci const Rect& displayRect, float vpr) 462e0dac50fSopenharmony_ci{ 463e0dac50fSopenharmony_ci WindowLimits systemLimits; 464e0dac50fSopenharmony_ci systemLimits.maxWidth_ = static_cast<uint32_t>(maxFloatingWindowSize_ * vpr); 465e0dac50fSopenharmony_ci systemLimits.maxHeight_ = static_cast<uint32_t>(maxFloatingWindowSize_ * vpr); 466e0dac50fSopenharmony_ci 467e0dac50fSopenharmony_ci // Float camera window has a special limit: 468e0dac50fSopenharmony_ci // if display sw <= 600dp, portrait: min width = display sw * 30%, landscape: min width = sw * 50% 469e0dac50fSopenharmony_ci // if display sw > 600dp, portrait: min width = display sw * 12%, landscape: min width = sw * 30% 470e0dac50fSopenharmony_ci if (node->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { 471e0dac50fSopenharmony_ci uint32_t smallWidth = displayRect.height_ <= displayRect.width_ ? displayRect.height_ : displayRect.width_; 472e0dac50fSopenharmony_ci float hwRatio = static_cast<float>(displayRect.height_) / static_cast<float>(displayRect.width_); 473e0dac50fSopenharmony_ci if (smallWidth <= static_cast<uint32_t>(600 * vpr)) { // sw <= 600dp 474e0dac50fSopenharmony_ci if (displayRect.width_ <= displayRect.height_) { 475e0dac50fSopenharmony_ci systemLimits.minWidth_ = static_cast<uint32_t>(smallWidth * 0.3); // min width = display sw * 0.3 476e0dac50fSopenharmony_ci } else { 477e0dac50fSopenharmony_ci systemLimits.minWidth_ = static_cast<uint32_t>(smallWidth * 0.5); // min width = display sw * 0.5 478e0dac50fSopenharmony_ci } 479e0dac50fSopenharmony_ci } else { 480e0dac50fSopenharmony_ci if (displayRect.width_ <= displayRect.height_) { 481e0dac50fSopenharmony_ci systemLimits.minWidth_ = static_cast<uint32_t>(smallWidth * 0.12); // min width = display sw * 0.12 482e0dac50fSopenharmony_ci } else { 483e0dac50fSopenharmony_ci systemLimits.minWidth_ = static_cast<uint32_t>(smallWidth * 0.3); // min width = display sw * 0.3 484e0dac50fSopenharmony_ci } 485e0dac50fSopenharmony_ci } 486e0dac50fSopenharmony_ci systemLimits.minHeight_ = static_cast<uint32_t>(systemLimits.minWidth_ * hwRatio); 487e0dac50fSopenharmony_ci } else { 488e0dac50fSopenharmony_ci systemLimits.minWidth_ = static_cast<uint32_t>(MIN_FLOATING_WIDTH * vpr); 489e0dac50fSopenharmony_ci systemLimits.minHeight_ = static_cast<uint32_t>(MIN_FLOATING_HEIGHT * vpr); 490e0dac50fSopenharmony_ci } 491e0dac50fSopenharmony_ci WLOGFD("[System SizeLimits] [maxWidth: %{public}u, minWidth: %{public}u, maxHeight: %{public}u, " 492e0dac50fSopenharmony_ci "minHeight: %{public}u]", systemLimits.maxWidth_, systemLimits.minWidth_, 493e0dac50fSopenharmony_ci systemLimits.maxHeight_, systemLimits.minHeight_); 494e0dac50fSopenharmony_ci return systemLimits; 495e0dac50fSopenharmony_ci} 496e0dac50fSopenharmony_ci 497e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateWindowSizeLimits(const sptr<WindowNode>& node) 498e0dac50fSopenharmony_ci{ 499e0dac50fSopenharmony_ci const auto& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(node->GetDisplayId()); 500e0dac50fSopenharmony_ci const auto& virtualPixelRatio = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(node->GetDisplayId()); 501e0dac50fSopenharmony_ci const auto& systemLimits = GetSystemSizeLimits(node, displayRect, virtualPixelRatio); 502e0dac50fSopenharmony_ci const auto& customizedLimits = node->GetWindowSizeLimits(); 503e0dac50fSopenharmony_ci 504e0dac50fSopenharmony_ci WindowLimits newLimits = systemLimits; 505e0dac50fSopenharmony_ci 506e0dac50fSopenharmony_ci // configured limits of floating window 507e0dac50fSopenharmony_ci uint32_t configuredMaxWidth = static_cast<uint32_t>(customizedLimits.maxWidth_ * virtualPixelRatio); 508e0dac50fSopenharmony_ci uint32_t configuredMaxHeight = static_cast<uint32_t>(customizedLimits.maxHeight_ * virtualPixelRatio); 509e0dac50fSopenharmony_ci uint32_t configuredMinWidth = static_cast<uint32_t>(customizedLimits.minWidth_ * virtualPixelRatio); 510e0dac50fSopenharmony_ci uint32_t configuredMinHeight = static_cast<uint32_t>(customizedLimits.minHeight_ * virtualPixelRatio); 511e0dac50fSopenharmony_ci 512e0dac50fSopenharmony_ci // calculate new limit size 513e0dac50fSopenharmony_ci if (systemLimits.minWidth_ <= configuredMaxWidth && configuredMaxWidth <= systemLimits.maxWidth_) { 514e0dac50fSopenharmony_ci newLimits.maxWidth_ = configuredMaxWidth; 515e0dac50fSopenharmony_ci } 516e0dac50fSopenharmony_ci if (systemLimits.minHeight_ <= configuredMaxHeight && configuredMaxHeight <= systemLimits.maxHeight_) { 517e0dac50fSopenharmony_ci newLimits.maxHeight_ = configuredMaxHeight; 518e0dac50fSopenharmony_ci } 519e0dac50fSopenharmony_ci if (systemLimits.minWidth_ <= configuredMinWidth && configuredMinWidth <= newLimits.maxWidth_) { 520e0dac50fSopenharmony_ci newLimits.minWidth_ = configuredMinWidth; 521e0dac50fSopenharmony_ci } 522e0dac50fSopenharmony_ci if (systemLimits.minHeight_ <= configuredMinHeight && configuredMinHeight <= newLimits.maxHeight_) { 523e0dac50fSopenharmony_ci newLimits.minHeight_ = configuredMinHeight; 524e0dac50fSopenharmony_ci } 525e0dac50fSopenharmony_ci 526e0dac50fSopenharmony_ci // calculate new limit ratio 527e0dac50fSopenharmony_ci newLimits.maxRatio_ = static_cast<float>(newLimits.maxWidth_) / static_cast<float>(newLimits.minHeight_); 528e0dac50fSopenharmony_ci newLimits.minRatio_ = static_cast<float>(newLimits.minWidth_) / static_cast<float>(newLimits.maxHeight_); 529e0dac50fSopenharmony_ci if (newLimits.minRatio_ <= customizedLimits.maxRatio_ && customizedLimits.maxRatio_ <= newLimits.maxRatio_) { 530e0dac50fSopenharmony_ci newLimits.maxRatio_ = customizedLimits.maxRatio_; 531e0dac50fSopenharmony_ci } 532e0dac50fSopenharmony_ci if (newLimits.minRatio_ <= customizedLimits.minRatio_ && customizedLimits.minRatio_ <= newLimits.maxRatio_) { 533e0dac50fSopenharmony_ci newLimits.minRatio_ = customizedLimits.minRatio_; 534e0dac50fSopenharmony_ci } 535e0dac50fSopenharmony_ci 536e0dac50fSopenharmony_ci // recalculate limit size by new ratio 537e0dac50fSopenharmony_ci uint32_t newMaxWidth = static_cast<uint32_t>(static_cast<float>(newLimits.maxHeight_) * newLimits.maxRatio_); 538e0dac50fSopenharmony_ci newLimits.maxWidth_ = std::min(newMaxWidth, newLimits.maxWidth_); 539e0dac50fSopenharmony_ci uint32_t newMinWidth = static_cast<uint32_t>(static_cast<float>(newLimits.minHeight_) * newLimits.minRatio_); 540e0dac50fSopenharmony_ci newLimits.minWidth_ = std::max(newMinWidth, newLimits.minWidth_); 541e0dac50fSopenharmony_ci uint32_t newMaxHeight = static_cast<uint32_t>(static_cast<float>(newLimits.maxWidth_) / newLimits.minRatio_); 542e0dac50fSopenharmony_ci newLimits.maxHeight_ = std::min(newMaxHeight, newLimits.maxHeight_); 543e0dac50fSopenharmony_ci uint32_t newMinHeight = static_cast<uint32_t>(static_cast<float>(newLimits.minWidth_) / newLimits.maxRatio_); 544e0dac50fSopenharmony_ci newLimits.minHeight_ = std::max(newMinHeight, newLimits.minHeight_); 545e0dac50fSopenharmony_ci 546e0dac50fSopenharmony_ci WLOGFD("[Update SizeLimits] winId: %{public}u, Width: [max:%{public}u, min:%{public}u], Height: [max:%{public}u, " 547e0dac50fSopenharmony_ci "min:%{public}u], Ratio: [max:%{public}f, min:%{public}f]", node->GetWindowId(), newLimits.maxWidth_, 548e0dac50fSopenharmony_ci newLimits.minWidth_, newLimits.maxHeight_, newLimits.minHeight_, newLimits.maxRatio_, newLimits.minRatio_); 549e0dac50fSopenharmony_ci node->SetWindowUpdatedSizeLimits(newLimits); 550e0dac50fSopenharmony_ci} 551e0dac50fSopenharmony_ci 552e0dac50fSopenharmony_ciAvoidPosType WindowLayoutPolicy::GetAvoidPosType(const Rect& rect, DisplayId displayId) const 553e0dac50fSopenharmony_ci{ 554e0dac50fSopenharmony_ci const auto& displayRectMap = DisplayGroupInfo::GetInstance().GetAllDisplayRects(); 555e0dac50fSopenharmony_ci if (displayRectMap.find(displayId) == std::end(displayRectMap)) { 556e0dac50fSopenharmony_ci WLOGFE("GetAvoidPosType fail. Get display fail. displayId: %{public}" PRIu64"", displayId); 557e0dac50fSopenharmony_ci return AvoidPosType::AVOID_POS_UNKNOWN; 558e0dac50fSopenharmony_ci } 559e0dac50fSopenharmony_ci const auto& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId); 560e0dac50fSopenharmony_ci return WindowHelper::GetAvoidPosType(rect, displayRect); 561e0dac50fSopenharmony_ci} 562e0dac50fSopenharmony_ci 563e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateDisplayLimitRect(const sptr<WindowNode>& node, Rect& limitRect) 564e0dac50fSopenharmony_ci{ 565e0dac50fSopenharmony_ci const auto& layoutRect = node->GetWindowRect(); 566e0dac50fSopenharmony_ci int32_t limitH = static_cast<int32_t>(limitRect.height_); 567e0dac50fSopenharmony_ci int32_t limitW = static_cast<int32_t>(limitRect.width_); 568e0dac50fSopenharmony_ci int32_t layoutH = static_cast<int32_t>(layoutRect.height_); 569e0dac50fSopenharmony_ci int32_t layoutW = static_cast<int32_t>(layoutRect.width_); 570e0dac50fSopenharmony_ci if (node->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR || 571e0dac50fSopenharmony_ci node->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR) { 572e0dac50fSopenharmony_ci auto avoidPosType = GetAvoidPosType(layoutRect, node->GetDisplayId()); 573e0dac50fSopenharmony_ci int32_t offsetH = 0; 574e0dac50fSopenharmony_ci int32_t offsetW = 0; 575e0dac50fSopenharmony_ci switch (avoidPosType) { 576e0dac50fSopenharmony_ci case AvoidPosType::AVOID_POS_TOP: 577e0dac50fSopenharmony_ci offsetH = layoutRect.posY_ + layoutH - limitRect.posY_; 578e0dac50fSopenharmony_ci limitRect.posY_ += offsetH; 579e0dac50fSopenharmony_ci limitH -= offsetH; 580e0dac50fSopenharmony_ci break; 581e0dac50fSopenharmony_ci case AvoidPosType::AVOID_POS_BOTTOM: 582e0dac50fSopenharmony_ci offsetH = limitRect.posY_ + limitH - layoutRect.posY_; 583e0dac50fSopenharmony_ci limitH -= offsetH; 584e0dac50fSopenharmony_ci break; 585e0dac50fSopenharmony_ci case AvoidPosType::AVOID_POS_LEFT: 586e0dac50fSopenharmony_ci offsetW = layoutRect.posX_ + layoutW - limitRect.posX_; 587e0dac50fSopenharmony_ci limitRect.posX_ += offsetW; 588e0dac50fSopenharmony_ci limitW -= offsetW; 589e0dac50fSopenharmony_ci break; 590e0dac50fSopenharmony_ci case AvoidPosType::AVOID_POS_RIGHT: 591e0dac50fSopenharmony_ci offsetW = limitRect.posX_ + limitW - layoutRect.posX_; 592e0dac50fSopenharmony_ci limitW -= offsetW; 593e0dac50fSopenharmony_ci break; 594e0dac50fSopenharmony_ci default: 595e0dac50fSopenharmony_ci WLOGFE("invalid avoidPosType: %{public}d", avoidPosType); 596e0dac50fSopenharmony_ci } 597e0dac50fSopenharmony_ci } 598e0dac50fSopenharmony_ci limitRect.height_ = static_cast<uint32_t>(limitH < 0 ? 0 : limitH); 599e0dac50fSopenharmony_ci limitRect.width_ = static_cast<uint32_t>(limitW < 0 ? 0 : limitW); 600e0dac50fSopenharmony_ci WLOGFD("AvoidNodeId: %{public}d, avoidNodeRect: [%{public}d %{public}d " 601e0dac50fSopenharmony_ci "%{public}u %{public}u], limitDisplayRect: [%{public}d %{public}d, %{public}u %{public}u]", 602e0dac50fSopenharmony_ci node->GetWindowId(), layoutRect.posX_, layoutRect.posY_, layoutRect.width_, layoutRect.height_, 603e0dac50fSopenharmony_ci limitRect.posX_, limitRect.posY_, limitRect.width_, limitRect.height_); 604e0dac50fSopenharmony_ci} 605e0dac50fSopenharmony_ci 606e0dac50fSopenharmony_cibool WindowLayoutPolicy::IsFullScreenRecentWindowExist(const std::vector<sptr<WindowNode>>& nodeVec) const 607e0dac50fSopenharmony_ci{ 608e0dac50fSopenharmony_ci for (auto& node : nodeVec) { 609e0dac50fSopenharmony_ci if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT && 610e0dac50fSopenharmony_ci node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) { 611e0dac50fSopenharmony_ci return true; 612e0dac50fSopenharmony_ci } 613e0dac50fSopenharmony_ci } 614e0dac50fSopenharmony_ci return false; 615e0dac50fSopenharmony_ci} 616e0dac50fSopenharmony_ci 617e0dac50fSopenharmony_cistatic void AdjustFixedOrientationRSSurfaceNode(const sptr<WindowNode>& node, const Rect& winRect, 618e0dac50fSopenharmony_ci std::shared_ptr<RSSurfaceNode> surfaceNode, sptr<DisplayInfo> displayInfo) 619e0dac50fSopenharmony_ci{ 620e0dac50fSopenharmony_ci if (!displayInfo) { 621e0dac50fSopenharmony_ci WLOGFE("display invaild"); 622e0dac50fSopenharmony_ci return; 623e0dac50fSopenharmony_ci } 624e0dac50fSopenharmony_ci auto requestOrientation = node->GetRequestedOrientation(); 625e0dac50fSopenharmony_ci if (!WmsUtils::IsFixedOrientation(requestOrientation, node->GetWindowMode(), node->GetWindowFlags())) { 626e0dac50fSopenharmony_ci return; 627e0dac50fSopenharmony_ci } 628e0dac50fSopenharmony_ci 629e0dac50fSopenharmony_ci auto displayOri = displayInfo->GetDisplayOrientation(); 630e0dac50fSopenharmony_ci auto displayW = displayInfo->GetWidth(); 631e0dac50fSopenharmony_ci auto displayH = displayInfo->GetHeight(); 632e0dac50fSopenharmony_ci if (WINDOW_TO_DISPLAY_ORIENTATION_MAP.count(requestOrientation) == 0) { 633e0dac50fSopenharmony_ci return; 634e0dac50fSopenharmony_ci } 635e0dac50fSopenharmony_ci int32_t diffOrientation = static_cast<int32_t>(WINDOW_TO_DISPLAY_ORIENTATION_MAP.at(requestOrientation)) - 636e0dac50fSopenharmony_ci static_cast<int32_t>(displayOri); 637e0dac50fSopenharmony_ci float rotation = (displayInfo->GetIsDefaultVertical() ? -90.f : 90.f) * (diffOrientation); // 90.f is base degree 638e0dac50fSopenharmony_ci WLOGFD("[FixOrientation] %{public}d adjust display [%{public}d, %{public}d], rotation: %{public}f", 639e0dac50fSopenharmony_ci node->GetWindowId(), displayW, displayH, rotation); 640e0dac50fSopenharmony_ci surfaceNode->SetTranslateX((displayW - static_cast<int32_t>(winRect.width_)) / 2); // 2 is half 641e0dac50fSopenharmony_ci surfaceNode->SetTranslateY((displayH - static_cast<int32_t>(winRect.height_)) / 2); // 2 is half 642e0dac50fSopenharmony_ci surfaceNode->SetPivotX(0.5); // 0.5 means center 643e0dac50fSopenharmony_ci surfaceNode->SetPivotY(0.5); // 0.5 means center 644e0dac50fSopenharmony_ci surfaceNode->SetRotation(rotation); 645e0dac50fSopenharmony_ci} 646e0dac50fSopenharmony_ci 647e0dac50fSopenharmony_cistatic void SetBounds(const sptr<WindowNode>& node, const Rect& winRect, const Rect& preRect) 648e0dac50fSopenharmony_ci{ 649e0dac50fSopenharmony_ci if (node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT || 650e0dac50fSopenharmony_ci node->GetWindowSizeChangeReason() == WindowSizeChangeReason::TRANSFORM) { 651e0dac50fSopenharmony_ci WLOGI("not need to update bounds"); 652e0dac50fSopenharmony_ci return; 653e0dac50fSopenharmony_ci } 654e0dac50fSopenharmony_ci 655e0dac50fSopenharmony_ci WLOGFD("Name:%{public}s id:%{public}u preRect: [%{public}d, %{public}d, %{public}d, %{public}d], " 656e0dac50fSopenharmony_ci "winRect: [%{public}d, %{public}d, %{public}d, %{public}d], %{public}u", node->GetWindowName().c_str(), 657e0dac50fSopenharmony_ci node->GetWindowId(), preRect.posX_, preRect.posY_, preRect.width_, preRect.height_, 658e0dac50fSopenharmony_ci winRect.posX_, winRect.posY_, winRect.width_, winRect.height_, node->GetWindowSizeChangeReason()); 659e0dac50fSopenharmony_ci auto& displayGroupInfo = DisplayGroupInfo::GetInstance(); 660e0dac50fSopenharmony_ci if (node->leashWinSurfaceNode_) { 661e0dac50fSopenharmony_ci if (winRect != preRect) { 662e0dac50fSopenharmony_ci // avoid animation interpreted when client coming 663e0dac50fSopenharmony_ci node->leashWinSurfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); 664e0dac50fSopenharmony_ci } 665e0dac50fSopenharmony_ci if (node->startingWinSurfaceNode_) { 666e0dac50fSopenharmony_ci node->startingWinSurfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_); 667e0dac50fSopenharmony_ci } 668e0dac50fSopenharmony_ci if (node->surfaceNode_) { 669e0dac50fSopenharmony_ci node->surfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_); 670e0dac50fSopenharmony_ci } 671e0dac50fSopenharmony_ci AdjustFixedOrientationRSSurfaceNode(node, winRect, node->leashWinSurfaceNode_, 672e0dac50fSopenharmony_ci displayGroupInfo.GetDisplayInfo(node->GetDisplayId())); 673e0dac50fSopenharmony_ci } else if (node->surfaceNode_) { 674e0dac50fSopenharmony_ci node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); 675e0dac50fSopenharmony_ci AdjustFixedOrientationRSSurfaceNode(node, winRect, node->surfaceNode_, 676e0dac50fSopenharmony_ci displayGroupInfo.GetDisplayInfo(node->GetDisplayId())); 677e0dac50fSopenharmony_ci } 678e0dac50fSopenharmony_ci} 679e0dac50fSopenharmony_ci 680e0dac50fSopenharmony_civoid WindowLayoutPolicy::UpdateSurfaceBounds(const sptr<WindowNode>& node, const Rect& winRect, const Rect& preRect) 681e0dac50fSopenharmony_ci{ 682e0dac50fSopenharmony_ci wptr<WindowNode> weakNode = node; 683e0dac50fSopenharmony_ci auto SetBoundsFunc = [weakNode, winRect, preRect]() { 684e0dac50fSopenharmony_ci auto winNode = weakNode.promote(); 685e0dac50fSopenharmony_ci if (winNode == nullptr) { 686e0dac50fSopenharmony_ci WLOGI("winNode is nullptr"); 687e0dac50fSopenharmony_ci return; 688e0dac50fSopenharmony_ci } 689e0dac50fSopenharmony_ci SetBounds(winNode, winRect, preRect); 690e0dac50fSopenharmony_ci }; 691e0dac50fSopenharmony_ci 692e0dac50fSopenharmony_ci switch (node->GetWindowSizeChangeReason()) { 693e0dac50fSopenharmony_ci case WindowSizeChangeReason::MAXIMIZE: 694e0dac50fSopenharmony_ci [[fallthrough]]; 695e0dac50fSopenharmony_ci case WindowSizeChangeReason::RECOVER: { 696e0dac50fSopenharmony_ci const RSAnimationTimingProtocol timingProtocol(400); // animation time 697e0dac50fSopenharmony_ci RSNode::Animate(timingProtocol, RSAnimationTimingCurve::EASE_OUT, SetBoundsFunc); 698e0dac50fSopenharmony_ci break; 699e0dac50fSopenharmony_ci } 700e0dac50fSopenharmony_ci case WindowSizeChangeReason::ROTATION: { 701e0dac50fSopenharmony_ci if (WmsUtils::IsFixedOrientation(node->GetRequestedOrientation(), 702e0dac50fSopenharmony_ci node->GetWindowMode(), node->GetWindowFlags())) { 703e0dac50fSopenharmony_ci auto disInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(node->GetDisplayId()); 704e0dac50fSopenharmony_ci if (disInfo && disInfo->GetDisplayStateChangeType() != DisplayStateChangeType::UPDATE_ROTATION) { 705e0dac50fSopenharmony_ci WLOGI("[FixOrientation] winNode %{public}u orientation, skip animation", node->GetWindowId()); 706e0dac50fSopenharmony_ci SetBoundsFunc(); 707e0dac50fSopenharmony_ci return; 708e0dac50fSopenharmony_ci } 709e0dac50fSopenharmony_ci } 710e0dac50fSopenharmony_ci const RSAnimationTimingProtocol timingProtocol(600); // animation time 711e0dac50fSopenharmony_ci const RSAnimationTimingCurve curve_ = RSAnimationTimingCurve::CreateCubicCurve( 712e0dac50fSopenharmony_ci 0.2, 0.0, 0.2, 1.0); // animation curve: cubic [0.2, 0.0, 0.2, 1.0] 713e0dac50fSopenharmony_ci RSNode::Animate(timingProtocol, curve_, SetBoundsFunc); 714e0dac50fSopenharmony_ci break; 715e0dac50fSopenharmony_ci } 716e0dac50fSopenharmony_ci case WindowSizeChangeReason::FULL_TO_SPLIT: 717e0dac50fSopenharmony_ci case WindowSizeChangeReason::SPLIT_TO_FULL: { 718e0dac50fSopenharmony_ci const RSAnimationTimingProtocol timingProtocol(350); // animation time 719e0dac50fSopenharmony_ci RSNode::Animate(timingProtocol, RSAnimationTimingCurve::EASE_OUT, SetBoundsFunc); 720e0dac50fSopenharmony_ci break; 721e0dac50fSopenharmony_ci } 722e0dac50fSopenharmony_ci case WindowSizeChangeReason::UNDEFINED: 723e0dac50fSopenharmony_ci [[fallthrough]]; 724e0dac50fSopenharmony_ci default: 725e0dac50fSopenharmony_ci SetBoundsFunc(); 726e0dac50fSopenharmony_ci } 727e0dac50fSopenharmony_ci} 728e0dac50fSopenharmony_ci 729e0dac50fSopenharmony_ciRect WindowLayoutPolicy::GetDisplayGroupRect() const 730e0dac50fSopenharmony_ci{ 731e0dac50fSopenharmony_ci return displayGroupRect_; 732e0dac50fSopenharmony_ci} 733e0dac50fSopenharmony_ci 734e0dac50fSopenharmony_civoid WindowLayoutPolicy::SetSplitRatioPoints(DisplayId displayId, const std::vector<int32_t>& splitRatioPoints) 735e0dac50fSopenharmony_ci{ 736e0dac50fSopenharmony_ci splitRatioPointsMap_[displayId] = splitRatioPoints; 737e0dac50fSopenharmony_ci} 738e0dac50fSopenharmony_ci 739e0dac50fSopenharmony_ciRect WindowLayoutPolicy::GetDividerRect(DisplayId displayId) const 740e0dac50fSopenharmony_ci{ 741e0dac50fSopenharmony_ci return INVALID_EMPTY_RECT; 742e0dac50fSopenharmony_ci} 743e0dac50fSopenharmony_ci 744e0dac50fSopenharmony_cibool WindowLayoutPolicy::IsTileRectSatisfiedWithSizeLimits(const sptr<WindowNode>& node) 745e0dac50fSopenharmony_ci{ 746e0dac50fSopenharmony_ci return true; 747e0dac50fSopenharmony_ci} 748e0dac50fSopenharmony_ci 749e0dac50fSopenharmony_civoid WindowLayoutPolicy::SetCascadeRectBottomPosYLimit(uint32_t floatingBottomPosY) 750e0dac50fSopenharmony_ci{ 751e0dac50fSopenharmony_ci floatingBottomPosY_ = floatingBottomPosY; 752e0dac50fSopenharmony_ci} 753e0dac50fSopenharmony_ci 754e0dac50fSopenharmony_civoid WindowLayoutPolicy::SetMaxFloatingWindowSize(uint32_t maxSize) 755e0dac50fSopenharmony_ci{ 756e0dac50fSopenharmony_ci maxFloatingWindowSize_ = maxSize; 757e0dac50fSopenharmony_ci} 758e0dac50fSopenharmony_ci 759e0dac50fSopenharmony_civoid WindowLayoutPolicy::GetStoragedAspectRatio(const sptr<WindowNode>& node) 760e0dac50fSopenharmony_ci{ 761e0dac50fSopenharmony_ci if (!WindowHelper::IsMainWindow(node->GetWindowType())) { 762e0dac50fSopenharmony_ci return; 763e0dac50fSopenharmony_ci } 764e0dac50fSopenharmony_ci 765e0dac50fSopenharmony_ci std::string abilityName = node->abilityInfo_.abilityName_; 766e0dac50fSopenharmony_ci std::vector<std::string> nameVector; 767e0dac50fSopenharmony_ci if (abilityName.size() > 0) { 768e0dac50fSopenharmony_ci nameVector = WindowHelper::Split(abilityName, "."); 769e0dac50fSopenharmony_ci } 770e0dac50fSopenharmony_ci std::string keyName = nameVector.empty() ? node->abilityInfo_.bundleName_ : 771e0dac50fSopenharmony_ci node->abilityInfo_.bundleName_ + "." + nameVector.back(); 772e0dac50fSopenharmony_ci if (PersistentStorage::HasKey(keyName, PersistentStorageType::ASPECT_RATIO)) { 773e0dac50fSopenharmony_ci float ratio = 0.0; 774e0dac50fSopenharmony_ci PersistentStorage::Get(keyName, ratio, PersistentStorageType::ASPECT_RATIO); 775e0dac50fSopenharmony_ci node->SetAspectRatio(ratio); 776e0dac50fSopenharmony_ci } 777e0dac50fSopenharmony_ci} 778e0dac50fSopenharmony_ci 779e0dac50fSopenharmony_civoid WindowLayoutPolicy::FixWindowRectWithinDisplay(const sptr<WindowNode>& node) const 780e0dac50fSopenharmony_ci{ 781e0dac50fSopenharmony_ci auto displayId = node->GetDisplayId(); 782e0dac50fSopenharmony_ci const Rect& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId); 783e0dac50fSopenharmony_ci auto type = node->GetWindowType(); 784e0dac50fSopenharmony_ci Rect rect = node->GetRequestRect(); 785e0dac50fSopenharmony_ci switch (type) { 786e0dac50fSopenharmony_ci case WindowType::WINDOW_TYPE_STATUS_BAR: 787e0dac50fSopenharmony_ci rect.posY_ = displayRect.posY_; 788e0dac50fSopenharmony_ci break; 789e0dac50fSopenharmony_ci case WindowType::WINDOW_TYPE_NAVIGATION_BAR: 790e0dac50fSopenharmony_ci rect.posY_ = static_cast<int32_t>(displayRect.height_) + displayRect.posY_ - 791e0dac50fSopenharmony_ci static_cast<int32_t>(rect.height_); 792e0dac50fSopenharmony_ci break; 793e0dac50fSopenharmony_ci default: 794e0dac50fSopenharmony_ci auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(displayId); 795e0dac50fSopenharmony_ci if (displayInfo == nullptr) { 796e0dac50fSopenharmony_ci WLOGE("displayInfo is nullptr"); 797e0dac50fSopenharmony_ci return; 798e0dac50fSopenharmony_ci } 799e0dac50fSopenharmony_ci if (!displayInfo->GetWaterfallDisplayCompressionStatus()) { 800e0dac50fSopenharmony_ci return; 801e0dac50fSopenharmony_ci } 802e0dac50fSopenharmony_ci rect.posY_ = std::max(rect.posY_, displayRect.posY_); 803e0dac50fSopenharmony_ci rect.posY_ = std::min(rect.posY_, displayRect.posY_ + static_cast<int32_t>(displayRect.height_)); 804e0dac50fSopenharmony_ci } 805e0dac50fSopenharmony_ci node->SetRequestRect(rect); 806e0dac50fSopenharmony_ci WLOGFD("WinId: %{public}d, requestRect: [%{public}d, %{public}d, %{public}u, %{public}u]", 807e0dac50fSopenharmony_ci node->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_); 808e0dac50fSopenharmony_ci} 809e0dac50fSopenharmony_ci 810e0dac50fSopenharmony_civoid WindowLayoutPolicy::GetMaximizeRect(const sptr<WindowNode>& node, Rect& maxRect) 811e0dac50fSopenharmony_ci{ 812e0dac50fSopenharmony_ci WLOGFI("WindowLayoutPolicy GetMaximizeRect maxRect = %{public}d, %{public}d, %{public}u, %{public}u ", 813e0dac50fSopenharmony_ci maxRect.posX_, maxRect.posY_, maxRect.width_, maxRect.height_); 814e0dac50fSopenharmony_ci} 815e0dac50fSopenharmony_ci} 816e0dac50fSopenharmony_ci}