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