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