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