1 /*
2  * Copyright (c) 2022-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 #include "display_group_controller.h"
16 
17 #include "window_helper.h"
18 #include "window_inner_manager.h"
19 #include "window_manager_hilog.h"
20 #include "window_node_container.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 namespace {
25 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayGroupController"};
26 }
27 
InitNewDisplay(DisplayId displayId)28 void DisplayGroupController::InitNewDisplay(DisplayId displayId)
29 {
30     // system bar map for display
31     SysBarNodeMap sysBarNodeMap {
32         { WindowType::WINDOW_TYPE_STATUS_BAR,     nullptr },
33         { WindowType::WINDOW_TYPE_NAVIGATION_BAR, nullptr },
34     };
35     sysBarNodeMaps_.insert(std::make_pair(displayId, sysBarNodeMap));
36 
37     SysBarTintMap sysBarTintMap {
38         { WindowType::WINDOW_TYPE_STATUS_BAR,     SystemBarRegionTint() },
39         { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarRegionTint() },
40     };
41     sysBarTintMaps_.insert(std::make_pair(displayId, sysBarTintMap));
42 
43     // window node maps for display
44     std::map<WindowRootNodeType, std::unique_ptr<std::vector<sptr<WindowNode>>>> displayWindowTree;
45     displayWindowTree.insert(std::make_pair(WindowRootNodeType::APP_WINDOW_NODE,
46         std::make_unique<std::vector<sptr<WindowNode>>>()));
47     displayWindowTree.insert(std::make_pair(WindowRootNodeType::ABOVE_WINDOW_NODE,
48         std::make_unique<std::vector<sptr<WindowNode>>>()));
49     displayWindowTree.insert(std::make_pair(WindowRootNodeType::BELOW_WINDOW_NODE,
50         std::make_unique<std::vector<sptr<WindowNode>>>()));
51     displayGroupWindowTree_.insert(std::make_pair(displayId, std::move(displayWindowTree)));
52 
53     // window pair for display
54     auto windowPair = new WindowPair(displayId);
55     windowPairMap_.insert(std::make_pair(displayId, windowPair));
56 }
57 
GetWindowNodesByDisplayIdAndRootType(DisplayId displayId,WindowRootNodeType type)58 std::vector<sptr<WindowNode>>* DisplayGroupController::GetWindowNodesByDisplayIdAndRootType(DisplayId displayId,
59                                                                                             WindowRootNodeType type)
60 {
61     if (displayGroupWindowTree_.find(displayId) != displayGroupWindowTree_.end()) {
62         auto& displayWindowTree = displayGroupWindowTree_[displayId];
63         if (displayWindowTree.find(type) != displayWindowTree.end()) {
64             return displayWindowTree[type].get();
65         }
66     }
67     return nullptr;
68 }
69 
AddWindowNodeOnWindowTree(sptr<WindowNode> & node,WindowRootNodeType rootType)70 void DisplayGroupController::AddWindowNodeOnWindowTree(sptr<WindowNode>& node, WindowRootNodeType rootType)
71 {
72     std::vector<sptr<WindowNode>>* rootNodeVectorPtr = GetWindowNodesByDisplayIdAndRootType(node->GetDisplayId(),
73         rootType);
74     if (rootNodeVectorPtr != nullptr) {
75         rootNodeVectorPtr->push_back(node);
76         WLOGFD("add node in node vector of root, displayId: %{public}" PRIu64" windowId: %{public}d, "
77             "rootType: %{public}d", node->GetDisplayId(), node->GetWindowId(), rootType);
78     } else {
79         WLOGFE("add node failed, rootNode vector is empty, windowId: %{public}d, rootType: %{public}d",
80             node->GetWindowId(), rootType);
81     }
82 }
83 
UpdateDisplayGroupWindowTree()84 void DisplayGroupController::UpdateDisplayGroupWindowTree()
85 {
86     // clear ori window tree of displayGroup
87     for (auto& elem : displayGroupWindowTree_) {
88         for (auto& nodeVec : elem.second) {
89             auto emptyVector = std::vector<sptr<WindowNode>>();
90             nodeVec.second->swap(emptyVector);
91         }
92     }
93     std::vector<WindowRootNodeType> rootNodeType = {
94         WindowRootNodeType::ABOVE_WINDOW_NODE,
95         WindowRootNodeType::APP_WINDOW_NODE,
96         WindowRootNodeType::BELOW_WINDOW_NODE
97     };
98     for (auto& rootType : rootNodeType) {
99         auto rootNode = windowNodeContainer_->GetRootNode(rootType);
100         if (rootNode == nullptr) {
101             WLOGFE("rootNode is nullptr, %{public}d", rootType);
102             continue;
103         }
104         for (auto& node : rootNode->children_) {
105             AddWindowNodeOnWindowTree(node, rootType);
106         }
107     }
108 }
109 
ProcessCrossNodes(DisplayId defaultDisplayId,DisplayStateChangeType type)110 void DisplayGroupController::ProcessCrossNodes(DisplayId defaultDisplayId, DisplayStateChangeType type)
111 {
112     defaultDisplayId_ = defaultDisplayId;
113     for (auto& iter : displayGroupWindowTree_) {
114         auto nodeVec = *(iter.second[WindowRootNodeType::APP_WINDOW_NODE]);
115         for (auto node : nodeVec) {
116             if (node->isShowingOnMultiDisplays_) {
117                 WLOGFD("process cross node, windowId: %{public}u, displayId: %{public}" PRIu64"",
118                     node->GetWindowId(), node->GetDisplayId());
119                 auto showingDisplays = node->GetShowingDisplays();
120 
121                 DisplayId newDisplayId;
122                 if (type == DisplayStateChangeType::SIZE_CHANGE ||
123                     type == DisplayStateChangeType::UPDATE_ROTATION ||
124                     type == DisplayStateChangeType::DISPLAY_COMPRESS ||
125                     type == DisplayStateChangeType::UPDATE_ROTATION_FROM_WINDOW) {
126                     newDisplayId = node->GetDisplayId();
127                 } else {
128                     newDisplayId = defaultDisplayId;
129                 }
130 
131                 for (auto& displayId : showingDisplays) {
132                     if (displayId == newDisplayId) {
133                         continue;
134                     }
135                     windowNodeContainer_->RemoveNodeFromRSTree(node, displayId, newDisplayId,
136                         WindowUpdateType::WINDOW_UPDATE_ACTIVE);
137                 }
138                 // update shown displays and displayId
139                 MoveCrossNodeToTargetDisplay(node, newDisplayId);
140             }
141         }
142     }
143 }
144 
UpdateWindowShowingDisplays(const sptr<WindowNode> & node)145 void DisplayGroupController::UpdateWindowShowingDisplays(const sptr<WindowNode>& node)
146 {
147     auto& displayGroupInfo = DisplayGroupInfo::GetInstance();
148     auto leftDisplayId = displayGroupInfo.GetLeftDisplayId();
149     auto rightDisplayId = displayGroupInfo.GetRightDisplayId();
150     auto displayRectMap = displayGroupInfo.GetAllDisplayRects();
151     auto showingDisplays = std::vector<DisplayId>();
152     const auto& winRect = node->GetWindowRect();
153     for (auto& elem : displayRectMap) {
154         auto& curDisplayRect = elem.second;
155 
156         // if window is showing in display region
157         if (((winRect.posX_ + static_cast<int32_t>(winRect.width_)) > curDisplayRect.posX_) &&
158             (winRect.posX_ < (curDisplayRect.posX_ + static_cast<int32_t>(curDisplayRect.width_)))) {
159             showingDisplays.push_back(elem.first);
160         }
161     }
162 
163     // if window is not showing on any display, maybe in the left of minPosX display, or the right of maxPosX display
164     if (showingDisplays.empty()) {
165         if (((winRect.posX_ + static_cast<int32_t>(winRect.width_)) <=
166             displayRectMap[leftDisplayId].posX_)) {
167             showingDisplays.push_back(leftDisplayId);
168         }
169         if (winRect.posX_ >=
170             (displayRectMap[rightDisplayId].posX_ + static_cast<int32_t>(displayRectMap[rightDisplayId].width_))) {
171             showingDisplays.push_back(rightDisplayId);
172         }
173     }
174 
175     // mean that this is cross-display window
176     if (showingDisplays.size() > 1) {
177         node->isShowingOnMultiDisplays_ = true;
178     } else {
179         node->isShowingOnMultiDisplays_ = false;
180     }
181     node->SetShowingDisplays(showingDisplays);
182 }
183 
UpdateWindowDisplayIdIfNeeded(const sptr<WindowNode> & node)184 void DisplayGroupController::UpdateWindowDisplayIdIfNeeded(const sptr<WindowNode>& node)
185 {
186     // current multi-display is only support left-right combination, maxNum is two
187     DisplayId newDisplayId = node->GetDisplayId();
188     const auto& curShowingDisplays = node->GetShowingDisplays();
189     if (curShowingDisplays.empty()) {
190         WLOGFE("id:%{public}u not show on any display!", node->GetWindowId());
191         return;
192     }
193     const auto& winRect = node->GetWindowRect();
194     if (curShowingDisplays.size() == 1) {
195         newDisplayId = *(curShowingDisplays.begin());
196     } else {
197         // if more than half width of the window is showing on the display, means the window belongs to this display
198         int32_t halfWidth = static_cast<int32_t>(winRect.width_ * 0.5);
199         const auto& displayRectMap = DisplayGroupInfo::GetInstance().GetAllDisplayRects();
200         for (auto& elem : displayRectMap) {
201             auto& displayRect = elem.second;
202             if ((winRect.posX_ < displayRect.posX_) &&
203                 (winRect.posX_ + static_cast<int32_t>(winRect.width_) >
204                 displayRect.posX_ + static_cast<int32_t>(displayRect.width_))) { // window covers whole display region
205                 newDisplayId = elem.first;
206                 break;
207             }
208             if (winRect.posX_ >= displayRect.posX_) { // current display is default display
209                 if ((displayRect.posX_ + static_cast<int32_t>(displayRect.width_) - winRect.posX_) >= halfWidth) {
210                     newDisplayId = elem.first;
211                     break;
212                 }
213             } else { // current display is expand display
214                 if ((winRect.posX_ + static_cast<int32_t>(winRect.width_) - displayRect.posX_) >= halfWidth) {
215                     newDisplayId = elem.first;
216                     break;
217                 }
218             }
219         }
220     }
221 
222     // update displayId if needed
223     if (node->GetDisplayId() != newDisplayId) {
224         UpdateWindowDisplayId(node, newDisplayId);
225         UpdateDisplayGroupWindowTree();
226     }
227 }
228 
ChangeToRectInDisplayGroup(const sptr<WindowNode> & node,DisplayId displayId)229 void DisplayGroupController::ChangeToRectInDisplayGroup(const sptr<WindowNode>& node, DisplayId displayId)
230 {
231     auto displays = node->GetShowingDisplays();
232     if (std::find(displays.begin(), displays.end(), displayId) != displays.end()) {
233         WLOGFD("Alreedy show in display %{public}" PRIu64 "", displayId);
234         return;
235     }
236 
237     Rect requestRect = node->GetRequestRect();
238     const Rect& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId);
239     requestRect.posX_ += displayRect.posX_;
240     requestRect.posY_ += displayRect.posY_;
241     node->SetRequestRect(requestRect);
242 
243     std::vector<DisplayId> curShowingDisplays = { node->GetDisplayId() };
244     node->SetShowingDisplays(curShowingDisplays);
245 }
246 
PreProcessWindowNode(const sptr<WindowNode> & node,WindowUpdateType type)247 void DisplayGroupController::PreProcessWindowNode(const sptr<WindowNode>& node, WindowUpdateType type)
248 {
249     if (!windowNodeContainer_->GetLayoutPolicy()->IsMultiDisplay()) {
250         if (type == WindowUpdateType::WINDOW_UPDATE_ADDED) {
251             std::vector<DisplayId> curShowingDisplays = { node->GetDisplayId() };
252             node->SetShowingDisplays(curShowingDisplays);
253             for (auto& childNode : node->children_) {
254                 PreProcessWindowNode(childNode, type);
255             }
256         }
257         WLOGFD("Current mode is not multi-display");
258         return;
259     }
260 
261     switch (type) {
262         case WindowUpdateType::WINDOW_UPDATE_ADDED: {
263             if (!node->isShowingOnMultiDisplays_) {
264                 // change rect to rect in display group
265                 ChangeToRectInDisplayGroup(node, node->GetDisplayId());
266             }
267             WLOGFD("preprocess node when add window");
268             break;
269         }
270         case WindowUpdateType::WINDOW_UPDATE_ACTIVE: {
271             // MoveTo can be called by user, calculate rect in display group if the reason is move
272             if (IsMoveToOrDragMove(node->GetWindowSizeChangeReason())) {
273                 ChangeToRectInDisplayGroup(node, defaultDisplayId_);
274             }
275             WLOGFD("preprocess node when update window");
276             break;
277         }
278         default:
279             break;
280     }
281 
282     for (auto& childNode : node->children_) {
283         PreProcessWindowNode(childNode, type);
284     }
285 }
286 
PostProcessWindowNode(const sptr<WindowNode> & node)287 void DisplayGroupController::PostProcessWindowNode(const sptr<WindowNode>& node)
288 {
289     if (!windowNodeContainer_->GetLayoutPolicy()->IsMultiDisplay()) {
290         WLOGFD("Current mode is not multi-display");
291         return;
292     }
293 
294     UpdateWindowShowingDisplays(node);
295     UpdateWindowDisplayIdIfNeeded(node);
296 }
297 
UpdateWindowDisplayId(const sptr<WindowNode> & node,DisplayId newDisplayId)298 void DisplayGroupController::UpdateWindowDisplayId(const sptr<WindowNode>& node, DisplayId newDisplayId)
299 {
300     WLOGFD("update node displayId, srcDisplayId: %{public}" PRIu64", newDisplayId: %{public}" PRIu64"",
301         node->GetDisplayId(), newDisplayId);
302     if (node->GetWindowToken()) {
303         node->GetWindowToken()->UpdateDisplayId(node->GetDisplayId(), newDisplayId);
304     }
305     node->SetDisplayId(newDisplayId);
306 }
307 
MoveCrossNodeToTargetDisplay(const sptr<WindowNode> & node,DisplayId targetDisplayId)308 void DisplayGroupController::MoveCrossNodeToTargetDisplay(const sptr<WindowNode>& node, DisplayId targetDisplayId)
309 {
310     node->isShowingOnMultiDisplays_ = false;
311     // update showing display
312     std::vector<DisplayId> newShowingDisplays = { targetDisplayId };
313     node->SetShowingDisplays(newShowingDisplays);
314     // update new displayId
315     if (node->GetDisplayId() != targetDisplayId) {
316         UpdateWindowDisplayId(node, targetDisplayId);
317     }
318 
319     for (auto& childNode : node->children_) {
320         MoveCrossNodeToTargetDisplay(childNode, targetDisplayId);
321     }
322 }
323 
MoveNotCrossNodeToDefaultDisplay(const sptr<WindowNode> & node,DisplayId displayId)324 void DisplayGroupController::MoveNotCrossNodeToDefaultDisplay(const sptr<WindowNode>& node, DisplayId displayId)
325 {
326     WLOGFD("windowId: %{public}d, displayId: %{public}" PRIu64"", node->GetWindowId(), displayId);
327     // update new rect in display group
328     const Rect& srcDisplayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId);
329     const Rect& dstDisplayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(defaultDisplayId_);
330     Rect newRect = node->GetRequestRect();
331     if (node->GetWindowType() == WindowType::WINDOW_TYPE_POINTER) {
332         newRect.posX_ = static_cast<int32_t>(dstDisplayRect.width_ / 2); // default pointerX : displayRect.width / 2
333         newRect.posY_ = static_cast<int32_t>(dstDisplayRect.height_ / 2); // default pointerY : displayRect.height / 2
334     } else {
335         newRect.posX_ = newRect.posX_ - srcDisplayRect.posX_ + dstDisplayRect.posX_;
336         newRect.posY_ = newRect.posY_ - srcDisplayRect.posY_ + dstDisplayRect.posY_;
337     }
338 
339     node->SetRequestRect(newRect);
340     // update showing display
341     std::vector<DisplayId> newShowingDisplays = { defaultDisplayId_ };
342     node->SetShowingDisplays(newShowingDisplays);
343     // update new displayId
344     UpdateWindowDisplayId(node, defaultDisplayId_);
345 
346     for (auto& childNode : node->children_) {
347         MoveNotCrossNodeToDefaultDisplay(childNode, displayId);
348     }
349 }
350 
ProcessNotCrossNodesOnDestroyedDisplay(DisplayId displayId,std::vector<uint32_t> & windowIds)351 void DisplayGroupController::ProcessNotCrossNodesOnDestroyedDisplay(DisplayId displayId,
352                                                                     std::vector<uint32_t>& windowIds)
353 {
354     if (displayId == defaultDisplayId_) {
355         WLOGFE("Move window nodes failed, displayId is the same as defaultDisplayId");
356         return;
357     }
358     if (displayGroupWindowTree_.find(displayId) == displayGroupWindowTree_.end()) {
359         WLOGFE("displayId: %{public}" PRIu64" not in display group window tree", displayId);
360         return;
361     }
362     WLOGI("move window nodes for display destroy, displayId: %{public}" PRIu64"", displayId);
363 
364     std::vector<WindowRootNodeType> rootNodeType = {
365         WindowRootNodeType::ABOVE_WINDOW_NODE,
366         WindowRootNodeType::APP_WINDOW_NODE,
367         WindowRootNodeType::BELOW_WINDOW_NODE
368     };
369     for (const auto& type : rootNodeType) {
370         if (displayGroupWindowTree_[displayId].find(type) == displayGroupWindowTree_[displayId].end()) {
371             continue;
372         }
373         auto nodesVec = *(displayGroupWindowTree_[displayId][type]);
374         for (auto node : nodesVec) {
375             WLOGFD("node on destroied display, windowId: %{public}d, isShowingOnMulti: %{public}d",
376                 node->GetWindowId(), node->isShowingOnMultiDisplays_);
377             if (node->GetDisplayId() != displayId || node->isShowingOnMultiDisplays_) {
378                 continue;
379             }
380             // destroy status and navigation bar
381             if (node->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR ||
382                 node->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR) {
383                 windowNodeContainer_->DestroyWindowNode(node, windowIds);
384                 WLOGFW("destroy status or navigation bar on destroyed display, windowId: %{public}d",
385                     node->GetWindowId());
386                 continue;
387             }
388             // move not cross-display nodes to default display
389             MoveNotCrossNodeToDefaultDisplay(node, displayId);
390 
391             // update RS tree
392             windowNodeContainer_->RemoveNodeFromRSTree(node, displayId, defaultDisplayId_,
393                 WindowUpdateType::WINDOW_UPDATE_ACTIVE);
394             windowNodeContainer_->AddNodeOnRSTree(node, defaultDisplayId_, defaultDisplayId_,
395                 WindowUpdateType::WINDOW_UPDATE_ACTIVE);
396         }
397     }
398 }
399 
ProcessDisplayCreate(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,Rect> & displayRectMap)400 void DisplayGroupController::ProcessDisplayCreate(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
401                                                   const std::map<DisplayId, Rect>& displayRectMap)
402 {
403     defaultDisplayId_ = defaultDisplayId;
404     WLOGI("defaultDisplay, displayId: %{public}" PRIu64"", defaultDisplayId);
405 
406     DisplayId displayId = displayInfo->GetDisplayId();
407 
408     InitNewDisplay(displayId);
409 
410     // add displayInfo in displayGroupInfo
411     DisplayGroupInfo::GetInstance().AddDisplayInfo(displayInfo);
412 
413     // modify RSTree and window tree of displayGroup for cross-display nodes
414     ProcessCrossNodes(defaultDisplayId, DisplayStateChangeType::CREATE);
415     UpdateDisplayGroupWindowTree();
416     const auto& layoutPolicy = windowNodeContainer_->GetLayoutPolicy();
417     if (layoutPolicy == nullptr) {
418         return;
419     }
420     layoutPolicy->ProcessDisplayCreate(displayId, displayRectMap);
421     ProcessWindowPairWhenDisplayChange();
422 }
423 
ProcessDisplayDestroy(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,Rect> & displayRectMap,std::vector<uint32_t> & windowIds)424 void DisplayGroupController::ProcessDisplayDestroy(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
425                                                    const std::map<DisplayId, Rect>& displayRectMap,
426                                                    std::vector<uint32_t>& windowIds)
427 {
428     defaultDisplayId_ = defaultDisplayId;
429     DisplayGroupInfo::GetInstance().SetDefaultDisplayId(defaultDisplayId);
430     DisplayId displayId = displayInfo->GetDisplayId();
431     // delete nodes and map element of deleted display
432     ProcessNotCrossNodesOnDestroyedDisplay(displayId, windowIds);
433     // modify RSTree and window tree of displayGroup for cross-display nodes
434     ProcessCrossNodes(defaultDisplayId, DisplayStateChangeType::DESTROY);
435     UpdateDisplayGroupWindowTree();
436     ClearMapOfDestroyedDisplay(displayId);
437     windowNodeContainer_->GetLayoutPolicy()->ProcessDisplayDestroy(displayId, displayRectMap);
438     ProcessWindowPairWhenDisplayChange();
439 }
440 
ProcessSystemBarRotation(const sptr<WindowNode> & node,const std::map<DisplayId,Rect> & displayRectMap)441 void DisplayGroupController::ProcessSystemBarRotation(const sptr<WindowNode>& node,
442     const std::map<DisplayId, Rect>& displayRectMap)
443 {
444     auto rect = node->GetWindowRect();
445     auto displayId = node->GetDisplayId();
446     auto iter = displayRectMap.find(displayId);
447     if (iter == displayRectMap.end()) {
448         return;
449     }
450     auto displayRect = iter->second;
451     if (node->GetWindowType() == WindowType::WINDOW_TYPE_STATUS_BAR) {
452         rect.width_ = displayRect.width_;
453     } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR) {
454         rect.posY_ = static_cast<int32_t>(displayRect.height_ - rect.height_) + displayRect.posY_;
455         rect.width_ = displayRect.width_;
456     }
457 
458     node->SetRequestRect(rect);
459 }
460 
UpdateNodeSizeChangeReasonWithRotation(DisplayId displayId,const std::map<DisplayId,Rect> & displayRectMap)461 void DisplayGroupController::UpdateNodeSizeChangeReasonWithRotation(DisplayId displayId,
462     const std::map<DisplayId, Rect>& displayRectMap)
463 {
464     std::vector<WindowRootNodeType> rootNodeType = {
465         WindowRootNodeType::ABOVE_WINDOW_NODE,
466         WindowRootNodeType::APP_WINDOW_NODE,
467         WindowRootNodeType::BELOW_WINDOW_NODE
468     };
469     for (auto& rootType : rootNodeType) {
470         std::vector<sptr<WindowNode>>* rootNodeVectorPtr = GetWindowNodesByDisplayIdAndRootType(displayId, rootType);
471         if (rootNodeVectorPtr == nullptr) {
472             WLOGFE("rootNodeVectorPtr is nullptr, %{public}d, displayId: %{public}" PRIu64, rootType, displayId);
473             return;
474         }
475         for (auto& node : (*rootNodeVectorPtr)) {
476             // DOCK_SLICE not need do rotation animation
477             if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
478                 continue;
479             }
480             if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
481                 ProcessSystemBarRotation(node, displayRectMap);
482             }
483             node->SetWindowSizeChangeReason(WindowSizeChangeReason::ROTATION);
484         }
485     }
486 }
487 
ProcessDisplayChange(DisplayId defaultDisplayId,sptr<DisplayInfo> displayInfo,const std::map<DisplayId,Rect> & displayRectMap,DisplayStateChangeType type)488 void DisplayGroupController::ProcessDisplayChange(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
489                                                   const std::map<DisplayId, Rect>& displayRectMap,
490                                                   DisplayStateChangeType type)
491 {
492     defaultDisplayId_ = defaultDisplayId;
493     auto& displayGroupInfo = DisplayGroupInfo::GetInstance();
494     displayGroupInfo.SetDefaultDisplayId(defaultDisplayId);
495     DisplayId displayId = displayInfo->GetDisplayId();
496     WLOGI("display change, displayId: %{public}" PRIu64", type: %{public}d", displayId, type);
497     switch (type) {
498         case DisplayStateChangeType::UPDATE_ROTATION:
499         case DisplayStateChangeType::UPDATE_ROTATION_FROM_WINDOW: {
500             displayGroupInfo.SetDisplayRotation(displayId, displayInfo->GetRotation());
501             displayGroupInfo.SetDisplayOrientation(displayId, displayInfo->GetDisplayOrientation());
502             displayGroupInfo.SetDisplayStateChangeType(displayId, type);
503             [[fallthrough]];
504         }
505         case DisplayStateChangeType::DISPLAY_COMPRESS:
506         case DisplayStateChangeType::SIZE_CHANGE: {
507             ProcessDisplaySizeChangeOrRotation(defaultDisplayId, displayId, displayRectMap, type);
508             break;
509         }
510         case DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE: {
511             displayGroupInfo.SetDisplayVirtualPixelRatio(displayId, displayInfo->GetVirtualPixelRatio());
512             windowNodeContainer_->GetLayoutPolicy()->ProcessDisplayVprChange(displayId);
513             break;
514         }
515         default: {
516             break;
517         }
518     }
519 }
520 
ProcessDisplaySizeChangeOrRotation(DisplayId defaultDisplayId,DisplayId displayId,const std::map<DisplayId,Rect> & displayRectMap,DisplayStateChangeType type)521 void DisplayGroupController::ProcessDisplaySizeChangeOrRotation(DisplayId defaultDisplayId, DisplayId displayId,
522     const std::map<DisplayId, Rect>& displayRectMap, DisplayStateChangeType type)
523 {
524     // modify RSTree and window tree of displayGroup for cross-display nodes
525     ProcessCrossNodes(defaultDisplayId, type);
526     UpdateDisplayGroupWindowTree();
527     // update reason after process cross Nodes to get correct display attribution
528     UpdateNodeSizeChangeReasonWithRotation(displayId, displayRectMap);
529     const auto& layoutPolicy = windowNodeContainer_->GetLayoutPolicy();
530     if (layoutPolicy == nullptr) {
531         return;
532     }
533     layoutPolicy->ProcessDisplaySizeChangeOrRotation(displayId, displayRectMap);
534     ProcessWindowPairWhenDisplayChange(true);
535 }
536 
ClearMapOfDestroyedDisplay(DisplayId displayId)537 void DisplayGroupController::ClearMapOfDestroyedDisplay(DisplayId displayId)
538 {
539     sysBarTintMaps_.erase(displayId);
540     sysBarNodeMaps_.erase(displayId);
541     displayGroupWindowTree_.erase(displayId);
542     DisplayGroupInfo::GetInstance().RemoveDisplayInfo(displayId);
543     windowPairMap_.erase(displayId);
544 }
545 
GetWindowPairByDisplayId(DisplayId displayId)546 sptr<WindowPair> DisplayGroupController::GetWindowPairByDisplayId(DisplayId displayId)
547 {
548     if (windowPairMap_.find(displayId) != windowPairMap_.end()) {
549         return windowPairMap_[displayId];
550     }
551     return nullptr;
552 }
553 
ProcessWindowPairWhenDisplayChange(bool rotateDisplay)554 void DisplayGroupController::ProcessWindowPairWhenDisplayChange(bool rotateDisplay)
555 {
556     for (auto& elem : DisplayGroupInfo::GetInstance().GetAllDisplayRects()) {
557         const auto& displayId = elem.first;
558         const auto& windowPair = GetWindowPairByDisplayId(displayId);
559         if (windowPair == nullptr) {
560             WLOGFE("WindowPair is nullptr, displayId: %{public}" PRIu64"", displayId);
561             return;
562         }
563         const auto& layoutPolicy = windowNodeContainer_->GetLayoutPolicy();
564         if (layoutPolicy == nullptr) {
565             WLOGFE("LayoutPolicy is nullptr, displayId: %{public}" PRIu64"", displayId);
566             return;
567         }
568         Rect divRect = layoutPolicy->GetDividerRect(displayId);
569         if (rotateDisplay) {
570             windowPair->RotateDividerWindow(divRect);
571         } else {
572             windowPair->SetDividerRect(divRect);
573         }
574         UpdateSplitRatioPoints(displayId);
575     }
576 }
577 
SetSplitRatioConfig(const SplitRatioConfig & splitRatioConfig)578 void DisplayGroupController::SetSplitRatioConfig(const SplitRatioConfig& splitRatioConfig)
579 {
580     for (auto& elem : DisplayGroupInfo::GetInstance().GetAllDisplayRects()) {
581         const auto& displayId = elem.first;
582         const auto& windowPair = GetWindowPairByDisplayId(displayId);
583         if (windowPair == nullptr) {
584             WLOGFE("WindowPair is nullptr, displayId: %{public}" PRIu64"", displayId);
585             continue;
586         }
587         windowPair->SetSplitRatioConfig(splitRatioConfig);
588         UpdateSplitRatioPoints(displayId);
589     }
590 }
591 
UpdateSplitRatioPoints(DisplayId displayId)592 void DisplayGroupController::UpdateSplitRatioPoints(DisplayId displayId)
593 {
594     const auto& windowPair = GetWindowPairByDisplayId(displayId);
595     if (windowPair == nullptr) {
596         WLOGFE("WindowPair is nullptr, displayId: %{public}" PRIu64"", displayId);
597         return;
598     }
599     auto displayRects = DisplayGroupInfo::GetInstance().GetAllDisplayRects();
600     if (displayRects.find(displayId) == displayRects.end()) {
601         return;
602     }
603     windowPair->CalculateSplitRatioPoints(displayRects[displayId]);
604     const auto& layoutPolicy = windowNodeContainer_->GetLayoutPolicy();
605     if (layoutPolicy == nullptr) {
606         WLOGFE("LayoutPolicy is nullptr, displayId: %{public}" PRIu64"", displayId);
607         return;
608     }
609     layoutPolicy->SetSplitRatioPoints(displayId, windowPair->GetSplitRatioPoints());
610 }
611 } // namespace Rosen
612 } // namespace OHOS
613