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