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
22namespace OHOS {
23namespace Rosen {
24namespace {
25constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayGroupController"};
26}
27
28void 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
58std::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
70void 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
84void 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
110void 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
145void 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
184void 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
229void 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
247void 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 (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE) {
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
287void 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
298void 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
308void 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
324void 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
351void 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
400void 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
424void 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
441void 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
461void 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
488void 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
521void 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
537void 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
546sptr<WindowPair> DisplayGroupController::GetWindowPairByDisplayId(DisplayId displayId)
547{
548    if (windowPairMap_.find(displayId) != windowPairMap_.end()) {
549        return windowPairMap_[displayId];
550    }
551    return nullptr;
552}
553
554void 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
578void 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
592void 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