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