1e0dac50fSopenharmony_ci/* 2e0dac50fSopenharmony_ci * Copyright (c) 2022-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_tile.h" 17e0dac50fSopenharmony_ci#include <ability_manager_client.h> 18e0dac50fSopenharmony_ci#include <hitrace_meter.h> 19e0dac50fSopenharmony_ci 20e0dac50fSopenharmony_ci#include "minimize_app.h" 21e0dac50fSopenharmony_ci#include "window_helper.h" 22e0dac50fSopenharmony_ci#include "window_inner_manager.h" 23e0dac50fSopenharmony_ci#include "window_manager_hilog.h" 24e0dac50fSopenharmony_ci#include "window_system_effect.h" 25e0dac50fSopenharmony_ci 26e0dac50fSopenharmony_cinamespace OHOS { 27e0dac50fSopenharmony_cinamespace Rosen { 28e0dac50fSopenharmony_cinamespace { 29e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Tile"}; 30e0dac50fSopenharmony_ciconstexpr uint32_t EDGE_INTERVAL = 48; 31e0dac50fSopenharmony_ciconstexpr uint32_t MID_INTERVAL = 24; 32e0dac50fSopenharmony_ci} 33e0dac50fSopenharmony_ci 34e0dac50fSopenharmony_ciWindowLayoutPolicyTile::WindowLayoutPolicyTile(DisplayGroupWindowTree& displayGroupWindowTree) 35e0dac50fSopenharmony_ci : WindowLayoutPolicy(displayGroupWindowTree) 36e0dac50fSopenharmony_ci{ 37e0dac50fSopenharmony_ci} 38e0dac50fSopenharmony_ci 39e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::Launch() 40e0dac50fSopenharmony_ci{ 41e0dac50fSopenharmony_ci for (auto& iter : DisplayGroupInfo::GetInstance().GetAllDisplayRects()) { 42e0dac50fSopenharmony_ci const auto& displayId = iter.first; 43e0dac50fSopenharmony_ci /* 44e0dac50fSopenharmony_ci * Init tile rects and layout tile queue 45e0dac50fSopenharmony_ci */ 46e0dac50fSopenharmony_ci InitTileRects(displayId); 47e0dac50fSopenharmony_ci InitTileQueue(displayId); 48e0dac50fSopenharmony_ci LayoutTileQueue(displayId); 49e0dac50fSopenharmony_ci 50e0dac50fSopenharmony_ci /* 51e0dac50fSopenharmony_ci * Layout above and below nodes, it is necessary when display rotatation or size change 52e0dac50fSopenharmony_ci */ 53e0dac50fSopenharmony_ci auto& displayWindowTree = displayGroupWindowTree_[displayId]; 54e0dac50fSopenharmony_ci LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::ABOVE_WINDOW_NODE])); 55e0dac50fSopenharmony_ci LayoutWindowNodesByRootType(*(displayWindowTree[WindowRootNodeType::BELOW_WINDOW_NODE])); 56e0dac50fSopenharmony_ci WLOGFD("[Launch TileLayout], displayId: %{public}" PRIu64"", displayId); 57e0dac50fSopenharmony_ci } 58e0dac50fSopenharmony_ci WLOGI("[Launch TileLayout Finished]"); 59e0dac50fSopenharmony_ci} 60e0dac50fSopenharmony_ci 61e0dac50fSopenharmony_ciuint32_t WindowLayoutPolicyTile::GetMaxTileWinNum(DisplayId displayId) const 62e0dac50fSopenharmony_ci{ 63e0dac50fSopenharmony_ci float virtualPixelRatio = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(displayId); 64e0dac50fSopenharmony_ci constexpr uint32_t half = 2; 65e0dac50fSopenharmony_ci uint32_t edgeIntervalVp = static_cast<uint32_t>(EDGE_INTERVAL * half * virtualPixelRatio); 66e0dac50fSopenharmony_ci uint32_t midIntervalVp = static_cast<uint32_t>(MID_INTERVAL * virtualPixelRatio); 67e0dac50fSopenharmony_ci uint32_t minFloatingW = static_cast<uint32_t>(MIN_FLOATING_WIDTH * virtualPixelRatio); 68e0dac50fSopenharmony_ci uint32_t drawableW = limitRectMap_[displayId].width_ - edgeIntervalVp + midIntervalVp; 69e0dac50fSopenharmony_ci return static_cast<uint32_t>(drawableW / (minFloatingW + midIntervalVp)); 70e0dac50fSopenharmony_ci} 71e0dac50fSopenharmony_ci 72e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::InitTileRects(DisplayId displayId) 73e0dac50fSopenharmony_ci{ 74e0dac50fSopenharmony_ci // TileLayout don't consider limitRect yet, limitDisplay equals to displayRect 75e0dac50fSopenharmony_ci const auto& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId); 76e0dac50fSopenharmony_ci if (WindowHelper::IsEmptyRect(displayRect)) { 77e0dac50fSopenharmony_ci WLOGFE("DisplayRect is empty, displayRect: %{public}" PRIu64"", displayId); 78e0dac50fSopenharmony_ci return; 79e0dac50fSopenharmony_ci } 80e0dac50fSopenharmony_ci 81e0dac50fSopenharmony_ci limitRectMap_[displayId] = displayRect; 82e0dac50fSopenharmony_ci float virtualPixelRatio = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(displayId); 83e0dac50fSopenharmony_ci uint32_t edgeIntervalVp = static_cast<uint32_t>(EDGE_INTERVAL * virtualPixelRatio); 84e0dac50fSopenharmony_ci uint32_t midIntervalVp = static_cast<uint32_t>(MID_INTERVAL * virtualPixelRatio); 85e0dac50fSopenharmony_ci 86e0dac50fSopenharmony_ci constexpr float ratio = DEFAULT_ASPECT_RATIO; 87e0dac50fSopenharmony_ci const Rect& limitRect = limitRectMap_[displayId]; 88e0dac50fSopenharmony_ci constexpr int half = 2; 89e0dac50fSopenharmony_ci maxTileWinNumMap_[displayId] = GetMaxTileWinNum(displayId); 90e0dac50fSopenharmony_ci WLOGFD("set max tile window num %{public}u", maxTileWinNumMap_[displayId]); 91e0dac50fSopenharmony_ci auto& presetRectsForAllLevel = presetRectsMap_[displayId]; 92e0dac50fSopenharmony_ci presetRectsForAllLevel.clear(); 93e0dac50fSopenharmony_ci uint32_t w = displayRect.width_ * ratio; 94e0dac50fSopenharmony_ci uint32_t h = displayRect.height_ * ratio; 95e0dac50fSopenharmony_ci w = w > limitRect.width_ ? limitRect.width_ : w; 96e0dac50fSopenharmony_ci h = h > limitRect.height_ ? limitRect.height_ : h; 97e0dac50fSopenharmony_ci int32_t x = limitRect.posX_ + (static_cast<int32_t>(limitRect.width_ - w) / half); 98e0dac50fSopenharmony_ci int32_t y = limitRect.posY_ + (static_cast<int32_t>(limitRect.height_ - h) / half); 99e0dac50fSopenharmony_ci 100e0dac50fSopenharmony_ci std::vector<Rect> single = {{ x, y, w, h }}; 101e0dac50fSopenharmony_ci presetRectsForAllLevel.emplace_back(single); 102e0dac50fSopenharmony_ci for (uint32_t num = 2; num <= maxTileWinNumMap_[displayId]; num++) { // start calc preset with 2 windows 103e0dac50fSopenharmony_ci w = (limitRect.width_ - edgeIntervalVp * half - midIntervalVp * (num - 1)) / num; 104e0dac50fSopenharmony_ci std::vector<Rect> curLevel; 105e0dac50fSopenharmony_ci for (uint32_t i = 0; i < num; i++) { 106e0dac50fSopenharmony_ci int32_t curX = static_cast<int32_t>(limitRect.posX_ + edgeIntervalVp + i * (w + midIntervalVp)); 107e0dac50fSopenharmony_ci Rect curRect = { curX, y, w, h }; 108e0dac50fSopenharmony_ci WLOGFD("presetRectsForAllLevel: level %{public}u, id %{public}u, tileRect: [%{public}d %{public}d " 109e0dac50fSopenharmony_ci "%{public}u %{public}u]", num, i, curX, y, w, h); 110e0dac50fSopenharmony_ci curLevel.emplace_back(curRect); 111e0dac50fSopenharmony_ci } 112e0dac50fSopenharmony_ci presetRectsForAllLevel.emplace_back(curLevel); 113e0dac50fSopenharmony_ci } 114e0dac50fSopenharmony_ci} 115e0dac50fSopenharmony_ci 116e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::InitTileQueue(DisplayId displayId) 117e0dac50fSopenharmony_ci{ 118e0dac50fSopenharmony_ci foregroundNodesMap_[displayId].clear(); 119e0dac50fSopenharmony_ci const auto& appWindowNodes = *(displayGroupWindowTree_[displayId][WindowRootNodeType::APP_WINDOW_NODE]); 120e0dac50fSopenharmony_ci for (auto& node : appWindowNodes) { 121e0dac50fSopenharmony_ci if (WindowHelper::IsMainWindow(node->GetWindowType())) { 122e0dac50fSopenharmony_ci PushBackNodeInTileQueue(node, displayId); 123e0dac50fSopenharmony_ci } 124e0dac50fSopenharmony_ci } 125e0dac50fSopenharmony_ci} 126e0dac50fSopenharmony_ci 127e0dac50fSopenharmony_cibool WindowLayoutPolicyTile::IsTileRectSatisfiedWithSizeLimits(const sptr<WindowNode>& node) 128e0dac50fSopenharmony_ci{ 129e0dac50fSopenharmony_ci if (!WindowHelper::IsMainWindow(node->GetWindowType())) { 130e0dac50fSopenharmony_ci return true; 131e0dac50fSopenharmony_ci } 132e0dac50fSopenharmony_ci const auto& displayId = node->GetDisplayId(); 133e0dac50fSopenharmony_ci auto& foregroundNodes = foregroundNodesMap_[displayId]; 134e0dac50fSopenharmony_ci auto num = foregroundNodes.size(); 135e0dac50fSopenharmony_ci if (num > maxTileWinNumMap_[displayId] || maxTileWinNumMap_[displayId] == 0) { 136e0dac50fSopenharmony_ci return false; 137e0dac50fSopenharmony_ci } 138e0dac50fSopenharmony_ci 139e0dac50fSopenharmony_ci // find if node already exits in foreground nodes map 140e0dac50fSopenharmony_ci if (IsWindowAlreadyInTileQueue(node)) { 141e0dac50fSopenharmony_ci return true; 142e0dac50fSopenharmony_ci } 143e0dac50fSopenharmony_ci 144e0dac50fSopenharmony_ci UpdateWindowSizeLimits(node); 145e0dac50fSopenharmony_ci const auto& presetRectsForAllLevel = presetRectsMap_[displayId]; 146e0dac50fSopenharmony_ci Rect tileRect; 147e0dac50fSopenharmony_ci // if size of foreground nodes is equal to or more than max tile window number 148e0dac50fSopenharmony_ci if (num == maxTileWinNumMap_[displayId]) { 149e0dac50fSopenharmony_ci tileRect = *(presetRectsForAllLevel[num - 1].begin()); 150e0dac50fSopenharmony_ci } else { // if size of foreground nodes is less than max tile window number 151e0dac50fSopenharmony_ci tileRect = *(presetRectsForAllLevel[num].begin()); 152e0dac50fSopenharmony_ci } 153e0dac50fSopenharmony_ci WLOGFD("id %{public}u, tileRect: [%{public}d %{public}d %{public}u %{public}u]", 154e0dac50fSopenharmony_ci node->GetWindowId(), tileRect.posX_, tileRect.posY_, tileRect.width_, tileRect.height_); 155e0dac50fSopenharmony_ci return WindowHelper::IsRectSatisfiedWithSizeLimits(tileRect, node->GetWindowUpdatedSizeLimits()); 156e0dac50fSopenharmony_ci} 157e0dac50fSopenharmony_ci 158e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::PerformWindowLayout(const sptr<WindowNode>& node, WindowUpdateType updateType) 159e0dac50fSopenharmony_ci{ 160e0dac50fSopenharmony_ci HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); 161e0dac50fSopenharmony_ci const auto& windowType = node->GetWindowType(); 162e0dac50fSopenharmony_ci const auto& requestRect = node->GetRequestRect(); 163e0dac50fSopenharmony_ci WLOGI("[PerformWindowLayout] windowId: %{public}u, windowType: %{public}u, updateType: %{public}u, requestRect: " 164e0dac50fSopenharmony_ci "requestRect: [%{public}d, %{public}d, %{public}u, %{public}u]", node->GetWindowId(), windowType, updateType, 165e0dac50fSopenharmony_ci requestRect.posX_, requestRect.posY_, requestRect.width_, requestRect.height_); 166e0dac50fSopenharmony_ci FixWindowRectWithinDisplay(node); 167e0dac50fSopenharmony_ci switch (updateType) { 168e0dac50fSopenharmony_ci case WindowUpdateType::WINDOW_UPDATE_ADDED: { 169e0dac50fSopenharmony_ci if (WindowHelper::IsMainWindow(windowType)) { 170e0dac50fSopenharmony_ci PushBackNodeInTileQueue(node, node->GetDisplayId()); 171e0dac50fSopenharmony_ci LayoutTileQueue(node->GetDisplayId()); 172e0dac50fSopenharmony_ci return; 173e0dac50fSopenharmony_ci } 174e0dac50fSopenharmony_ci break; 175e0dac50fSopenharmony_ci } 176e0dac50fSopenharmony_ci case WindowUpdateType::WINDOW_UPDATE_REMOVED: { 177e0dac50fSopenharmony_ci if (WindowHelper::IsMainWindow(windowType)) { 178e0dac50fSopenharmony_ci RemoveNodeFromTileQueue(node); 179e0dac50fSopenharmony_ci LayoutTileQueue(node->GetDisplayId()); 180e0dac50fSopenharmony_ci } 181e0dac50fSopenharmony_ci NotifyClientAndAnimation(node, node->GetRequestRect(), WindowSizeChangeReason::HIDE); 182e0dac50fSopenharmony_ci return; 183e0dac50fSopenharmony_ci } 184e0dac50fSopenharmony_ci default: 185e0dac50fSopenharmony_ci WLOGFD("Update type is not add or remove"); 186e0dac50fSopenharmony_ci } 187e0dac50fSopenharmony_ci LayoutWindowNode(node); 188e0dac50fSopenharmony_ci} 189e0dac50fSopenharmony_ci 190e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::LayoutTileQueue(DisplayId displayId) 191e0dac50fSopenharmony_ci{ 192e0dac50fSopenharmony_ci ApplyPresetRectForTileWindows(displayId); 193e0dac50fSopenharmony_ci for (auto& node : foregroundNodesMap_[displayId]) { 194e0dac50fSopenharmony_ci LayoutWindowNode(node); 195e0dac50fSopenharmony_ci } 196e0dac50fSopenharmony_ci} 197e0dac50fSopenharmony_ci 198e0dac50fSopenharmony_cibool WindowLayoutPolicyTile::IsWindowAlreadyInTileQueue(const sptr<WindowNode>& node) 199e0dac50fSopenharmony_ci{ 200e0dac50fSopenharmony_ci auto& foregroundNodes = foregroundNodesMap_[node->GetDisplayId()]; 201e0dac50fSopenharmony_ci auto iter = std::find_if(foregroundNodes.begin(), foregroundNodes.end(), 202e0dac50fSopenharmony_ci [node](sptr<WindowNode> foregroundNode) { 203e0dac50fSopenharmony_ci return foregroundNode->GetWindowId() == node->GetWindowId(); 204e0dac50fSopenharmony_ci }); 205e0dac50fSopenharmony_ci if (iter != foregroundNodes.end()) { 206e0dac50fSopenharmony_ci WLOGFD("Window is already in tile queue, windowId: %{public}d", node->GetWindowId()); 207e0dac50fSopenharmony_ci return true; 208e0dac50fSopenharmony_ci } 209e0dac50fSopenharmony_ci return false; 210e0dac50fSopenharmony_ci} 211e0dac50fSopenharmony_ci 212e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::PushBackNodeInTileQueue(const sptr<WindowNode>& node, DisplayId displayId) 213e0dac50fSopenharmony_ci{ 214e0dac50fSopenharmony_ci if (node == nullptr) { 215e0dac50fSopenharmony_ci return; 216e0dac50fSopenharmony_ci } 217e0dac50fSopenharmony_ci if (IsWindowAlreadyInTileQueue(node)) { 218e0dac50fSopenharmony_ci return; 219e0dac50fSopenharmony_ci } 220e0dac50fSopenharmony_ci 221e0dac50fSopenharmony_ci if (!WindowHelper::IsWindowModeSupported(node->GetModeSupportInfo(), WindowMode::WINDOW_MODE_FLOATING)) { 222e0dac50fSopenharmony_ci WLOGFD("Window don't support floating mode that should be minimized, winId: %{public}u, " 223e0dac50fSopenharmony_ci "modeSupportInfo: %{public}u", node->GetWindowId(), node->GetModeSupportInfo()); 224e0dac50fSopenharmony_ci MinimizeApp::AddNeedMinimizeApp(node, MinimizeReason::INVALID_MODE_OR_SIZE_IN_TILE); 225e0dac50fSopenharmony_ci return; 226e0dac50fSopenharmony_ci } 227e0dac50fSopenharmony_ci auto& foregroundNodes = foregroundNodesMap_[displayId]; 228e0dac50fSopenharmony_ci while (!foregroundNodes.empty() && foregroundNodes.size() >= maxTileWinNumMap_[displayId]) { 229e0dac50fSopenharmony_ci auto removeNode = foregroundNodes.front(); 230e0dac50fSopenharmony_ci foregroundNodes.pop_front(); 231e0dac50fSopenharmony_ci WLOGFD("Minimize win in queue head for add new win, windowId: %{public}d", removeNode->GetWindowId()); 232e0dac50fSopenharmony_ci MinimizeApp::AddNeedMinimizeApp(removeNode, MinimizeReason::LAYOUT_TILE); 233e0dac50fSopenharmony_ci } 234e0dac50fSopenharmony_ci foregroundNodes.push_back(node); 235e0dac50fSopenharmony_ci WLOGFD("Pusk back win in tile queue, displayId: %{public}" PRIu64", winId: %{public}d", 236e0dac50fSopenharmony_ci displayId, node->GetWindowId()); 237e0dac50fSopenharmony_ci} 238e0dac50fSopenharmony_ci 239e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::RemoveNodeFromTileQueue(const sptr<WindowNode>& node) 240e0dac50fSopenharmony_ci{ 241e0dac50fSopenharmony_ci if (node == nullptr) { 242e0dac50fSopenharmony_ci return; 243e0dac50fSopenharmony_ci } 244e0dac50fSopenharmony_ci DisplayId displayId = node->GetDisplayId(); 245e0dac50fSopenharmony_ci auto& foregroundNodes = foregroundNodesMap_[displayId]; 246e0dac50fSopenharmony_ci auto iter = std::find(foregroundNodes.begin(), foregroundNodes.end(), node); 247e0dac50fSopenharmony_ci if (iter != foregroundNodes.end()) { 248e0dac50fSopenharmony_ci WLOGFD("Remove win in tile for win id: %{public}d", node->GetWindowId()); 249e0dac50fSopenharmony_ci foregroundNodes.erase(iter); 250e0dac50fSopenharmony_ci } 251e0dac50fSopenharmony_ci} 252e0dac50fSopenharmony_ci 253e0dac50fSopenharmony_cibool WindowLayoutPolicyTile::IsValidTileQueueAndPresetRects(DisplayId displayId) 254e0dac50fSopenharmony_ci{ 255e0dac50fSopenharmony_ci auto& foregroundNodes = foregroundNodesMap_[displayId]; 256e0dac50fSopenharmony_ci uint32_t num = foregroundNodes.size(); 257e0dac50fSopenharmony_ci auto& presetRectsForAllLevel = presetRectsMap_[displayId]; 258e0dac50fSopenharmony_ci if (num > maxTileWinNumMap_[displayId] || num > presetRectsForAllLevel.size() || num == 0) { 259e0dac50fSopenharmony_ci WLOGE("Invalid tile queue, foreground tileNum: %{public}u, maxTileNum: %{public}u, presetRectsForAllLevel: " 260e0dac50fSopenharmony_ci "%{public}u", num, maxTileWinNumMap_[displayId], static_cast<uint32_t>(presetRectsForAllLevel.size())); 261e0dac50fSopenharmony_ci return false; 262e0dac50fSopenharmony_ci } 263e0dac50fSopenharmony_ci auto& presetRect = presetRectsForAllLevel[num - 1]; 264e0dac50fSopenharmony_ci if (presetRect.size() != num) { 265e0dac50fSopenharmony_ci WLOGE("Invalid preset rects, foreground tileNum: %{public}u, presetRect.size(): %{public}u", 266e0dac50fSopenharmony_ci num, static_cast<uint32_t>(presetRect.size())); 267e0dac50fSopenharmony_ci return false; 268e0dac50fSopenharmony_ci } 269e0dac50fSopenharmony_ci return true; 270e0dac50fSopenharmony_ci} 271e0dac50fSopenharmony_ci 272e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::RefreshTileQueue(DisplayId displayId, 273e0dac50fSopenharmony_ci std::vector<sptr<WindowNode>>& needMinimizeNodes, std::vector<sptr<WindowNode>>& needRecoverNodes) 274e0dac50fSopenharmony_ci{ 275e0dac50fSopenharmony_ci /* 276e0dac50fSopenharmony_ci * Usually, needMinimizeNodes and needRecoverNodes will be empty, there is no need to refresh tile queue 277e0dac50fSopenharmony_ci */ 278e0dac50fSopenharmony_ci auto& foregroundNodes = foregroundNodesMap_[displayId]; 279e0dac50fSopenharmony_ci if (needMinimizeNodes.empty() && needRecoverNodes.empty()) { 280e0dac50fSopenharmony_ci WLOGD("No need to refresh tileQueue"); 281e0dac50fSopenharmony_ci return; 282e0dac50fSopenharmony_ci } 283e0dac50fSopenharmony_ci 284e0dac50fSopenharmony_ci WLOGD("Update tile queue for the nodes which should be minimized or recovered"); 285e0dac50fSopenharmony_ci for (auto& miniNode : needMinimizeNodes) { 286e0dac50fSopenharmony_ci auto iter = std::find(foregroundNodes.begin(), foregroundNodes.end(), miniNode); 287e0dac50fSopenharmony_ci if (iter != foregroundNodes.end()) { 288e0dac50fSopenharmony_ci foregroundNodes.erase(iter); 289e0dac50fSopenharmony_ci } 290e0dac50fSopenharmony_ci } 291e0dac50fSopenharmony_ci for (auto& recNode : needRecoverNodes) { 292e0dac50fSopenharmony_ci auto iter = std::find(foregroundNodes.begin(), foregroundNodes.end(), recNode); 293e0dac50fSopenharmony_ci if (iter == foregroundNodes.end()) { 294e0dac50fSopenharmony_ci foregroundNodes.push_back(recNode); 295e0dac50fSopenharmony_ci } 296e0dac50fSopenharmony_ci } 297e0dac50fSopenharmony_ci ApplyPresetRectForTileWindows(displayId); 298e0dac50fSopenharmony_ci needMinimizeNodes.clear(); 299e0dac50fSopenharmony_ci needRecoverNodes.clear(); 300e0dac50fSopenharmony_ci} 301e0dac50fSopenharmony_ci 302e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::ApplyPresetRectForTileWindows(DisplayId displayId) 303e0dac50fSopenharmony_ci{ 304e0dac50fSopenharmony_ci if (!(IsValidTileQueueAndPresetRects(displayId))) { 305e0dac50fSopenharmony_ci return; 306e0dac50fSopenharmony_ci } 307e0dac50fSopenharmony_ci 308e0dac50fSopenharmony_ci auto& foregroundNodes = foregroundNodesMap_[displayId]; 309e0dac50fSopenharmony_ci uint32_t num = foregroundNodes.size(); 310e0dac50fSopenharmony_ci auto rectIt = presetRectsMap_[displayId][num - 1].begin(); 311e0dac50fSopenharmony_ci std::vector<sptr<WindowNode>> needMinimizeNodes; 312e0dac50fSopenharmony_ci std::vector<sptr<WindowNode>> needRecoverNodes; 313e0dac50fSopenharmony_ci for (auto node : foregroundNodes) { 314e0dac50fSopenharmony_ci auto& rect = (*rectIt); 315e0dac50fSopenharmony_ci if (WindowHelper::IsRectSatisfiedWithSizeLimits(rect, node->GetWindowUpdatedSizeLimits())) { 316e0dac50fSopenharmony_ci node->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); 317e0dac50fSopenharmony_ci // when change mode, need to reset shadow and radius 318e0dac50fSopenharmony_ci WindowSystemEffect::SetWindowEffect(node); 319e0dac50fSopenharmony_ci if (node->GetWindowToken()) { 320e0dac50fSopenharmony_ci node->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING); 321e0dac50fSopenharmony_ci } 322e0dac50fSopenharmony_ci node->SetRequestRect(rect); 323e0dac50fSopenharmony_ci node->SetDecoStatus(true); 324e0dac50fSopenharmony_ci rectIt++; 325e0dac50fSopenharmony_ci WLOGFD("Set preset rect for tileWin, id: %{public}d [%{public}d %{public}d %{public}d %{public}d]", 326e0dac50fSopenharmony_ci node->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_); 327e0dac50fSopenharmony_ci } else { 328e0dac50fSopenharmony_ci WLOGFD("Minimize node which can't be applied to tileRect, winId: %{public}u", node->GetWindowId()); 329e0dac50fSopenharmony_ci if (num == maxTileWinNumMap_[displayId]) { 330e0dac50fSopenharmony_ci // if foreground nodes equal to max tileWinNum, means need to recover one node before minimize curNode 331e0dac50fSopenharmony_ci auto recoverNode = MinimizeApp::GetRecoverdNodeFromMinimizeList(); 332e0dac50fSopenharmony_ci if (recoverNode != nullptr) { 333e0dac50fSopenharmony_ci needRecoverNodes.push_back(recoverNode); 334e0dac50fSopenharmony_ci WLOGFD("Cancel minimize node from minimizeList, winId: %{public}u", node->GetWindowId()); 335e0dac50fSopenharmony_ci } 336e0dac50fSopenharmony_ci } 337e0dac50fSopenharmony_ci needMinimizeNodes.push_back(node); 338e0dac50fSopenharmony_ci MinimizeApp::AddNeedMinimizeApp(node, MinimizeReason::INVALID_MODE_OR_SIZE_IN_TILE); 339e0dac50fSopenharmony_ci break; 340e0dac50fSopenharmony_ci } 341e0dac50fSopenharmony_ci } 342e0dac50fSopenharmony_ci 343e0dac50fSopenharmony_ci RefreshTileQueue(displayId, needMinimizeNodes, needRecoverNodes); 344e0dac50fSopenharmony_ci} 345e0dac50fSopenharmony_ci 346e0dac50fSopenharmony_civoid WindowLayoutPolicyTile::UpdateLayoutRect(const sptr<WindowNode>& node) 347e0dac50fSopenharmony_ci{ 348e0dac50fSopenharmony_ci UpdateWindowSizeLimits(node); 349e0dac50fSopenharmony_ci bool floatingWindow = (node->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING); 350e0dac50fSopenharmony_ci bool needAvoid = (node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_NEED_AVOID)); 351e0dac50fSopenharmony_ci Rect lastRect = node->GetWindowRect(); 352e0dac50fSopenharmony_ci Rect winRect = node->GetRequestRect(); 353e0dac50fSopenharmony_ci WLOGI("[Before TileLayout] windowId: %{public}u, mode: %{public}u, type: %{public}u requestRect: [%{public}d, " 354e0dac50fSopenharmony_ci "%{public}d, %{public}u, %{public}u]", node->GetWindowId(), node->GetWindowMode(), node->GetWindowType(), 355e0dac50fSopenharmony_ci winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); 356e0dac50fSopenharmony_ci 357e0dac50fSopenharmony_ci if (!floatingWindow) { // fullscreen window 358e0dac50fSopenharmony_ci const auto& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(node->GetDisplayId()); 359e0dac50fSopenharmony_ci const auto& limitDisplayRect = limitRectMap_[node->GetDisplayId()]; 360e0dac50fSopenharmony_ci winRect = needAvoid ? limitDisplayRect : displayRect; 361e0dac50fSopenharmony_ci } 362e0dac50fSopenharmony_ci 363e0dac50fSopenharmony_ci WLOGI("[After TileLayout] windowId: %{public}u, isDecor: %{public}u, winRect: [%{public}d, %{public}d, " 364e0dac50fSopenharmony_ci "%{public}u, %{public}u]", node->GetWindowId(), node->GetDecoStatus(), winRect.posX_, winRect.posY_, 365e0dac50fSopenharmony_ci winRect.width_, winRect.height_); 366e0dac50fSopenharmony_ci node->SetWindowRect(winRect); 367e0dac50fSopenharmony_ci 368e0dac50fSopenharmony_ci // postProcess after update winRect 369e0dac50fSopenharmony_ci CalcAndSetNodeHotZone(winRect, node); 370e0dac50fSopenharmony_ci UpdateSurfaceBounds(node, winRect, lastRect); 371e0dac50fSopenharmony_ci NotifyClientAndAnimation(node, winRect, node->GetWindowSizeChangeReason()); 372e0dac50fSopenharmony_ci} 373e0dac50fSopenharmony_ci} // Rosen 374e0dac50fSopenharmony_ci} // OHOS 375