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}