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