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