1/*
2 * Copyright (c) 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 <ability_manager_client.h>
17#include <transaction/rs_transaction.h>
18#include <unordered_set>
19
20#include "display_manager_service_inner.h"
21#include "dm_common.h"
22#include "singleton_container.h"
23#include "window_adapter.h"
24#include "window_group_mgr.h"
25#include "window_manager_hilog.h"
26#include "window_manager_service.h"
27#include "minimize_app.h"
28#include "wm_common.h"
29
30namespace OHOS {
31namespace Rosen {
32
33namespace {
34constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowGroupMgr"};
35}
36
37WMError WindowGroupMgr::MoveMissionsToForeground(const std::vector<int32_t>& missionIds, int32_t topMissionId)
38{
39    WLOGFD("%{public}s, topMissionId: %{public}d ", DumpVector(missionIds).c_str(), topMissionId);
40    if (missionIds.empty()) {
41        return WMError::WM_DO_NOTHING;
42    }
43
44    WMError res = WMError::WM_OK;
45    for (auto it = missionIds.rbegin(); it != missionIds.rend(); it++) {
46        if (*it == topMissionId) {
47            continue;
48        }
49        WMError tempRes = MoveMissionToForeground(*it);
50        res = tempRes != WMError::WM_OK ? tempRes : res;
51    }
52
53    if (topMissionId != DEFAULT_MISSION_ID) {
54        WMError tempRes = MoveMissionToForeground(topMissionId);
55        res = tempRes == WMError::WM_OK ? tempRes : res;
56        WLOGFD("raise zOrder, missindId: %{public}d ", topMissionId);
57        auto windowNode = windowRoot_->GetWindowNodeByMissionId(topMissionId);
58        windowRoot_->RaiseZOrderForAppWindow(windowNode);
59        OHOS::Rosen::RSTransaction::FlushImplicitTransaction();
60    }
61    return res;
62}
63
64WMError WindowGroupMgr::MoveMissionsToBackground(const std::vector<int32_t>& missionIds, std::vector<int32_t>& result)
65{
66    WLOGFD("%{public}s ", DumpVector(missionIds).c_str());
67    if (missionIds.empty()) {
68        return WMError::WM_DO_NOTHING;
69    }
70
71    std::vector<sptr<WindowNode>> windowNodes;
72    std::vector<uint32_t> hideWindowIds;
73    for (auto missionId : missionIds) {
74        sptr<WindowNode> windowNode = windowRoot_->GetWindowNodeByMissionId(missionId);
75        if (!windowNode) {
76            continue;
77        }
78        windowNodes.emplace_back(windowNode);
79    }
80    std::sort(windowNodes.begin(), windowNodes.end(), [](const sptr<WindowNode>& w1, const sptr<WindowNode>& w2) {
81        return w1->zOrder_ > w2->zOrder_;
82    });
83
84    std::unordered_set<DisplayId> displayIds;
85    for (auto windowNode : windowNodes) {
86        result.emplace_back(windowNode->abilityInfo_.missionId_);
87        hideWindowIds.emplace_back(windowNode->GetWindowId());
88        backupWindowModes_[windowNode->GetWindowId()] = windowNode->GetWindowMode();
89        WLOGFD("windowId: %{public}d, missionId: %{public}d, node: %{public}s, zOrder: %{public}d, "
90            "mode: %{public}d ", windowNode->GetWindowId(), windowNode->abilityInfo_.missionId_,
91            (windowNode == nullptr ? "NUll" : windowNode->GetWindowName().c_str()),
92            windowNode->zOrder_, windowNode->GetWindowMode());
93        displayIds.insert(windowNode->GetDisplayId());
94    }
95
96    for (auto displayId : displayIds) {
97        auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
98        if (container != nullptr) {
99            auto windowPair = container->GetDisplayGroupController()->GetWindowPairByDisplayId(displayId);
100            if (windowPair && windowPair->GetDividerWindow()) {
101                backupDividerWindowRect_[displayId] = windowPair->GetDividerWindow()->GetWindowRect();
102            }
103        }
104    }
105
106    WLOGFD("WindowGroupMgr::HideWindowGroup, hide WindowIds: %{public}s", DumpVector(hideWindowIds).c_str());
107    windowRoot_->MinimizeTargetWindows(hideWindowIds);
108    MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::GESTURE_ANIMATION);
109    return WMError::WM_OK;
110}
111
112WMError WindowGroupMgr::MoveMissionToForeground(int32_t missionId)
113{
114    auto windowNode = windowRoot_->GetWindowNodeByMissionId(missionId);
115    if (windowNode == nullptr || windowNode->GetWindowToken() == nullptr) {
116        WLOGFE("GetWindowToken failed, missionId: %{public}d", missionId);
117        return WMError::WM_ERROR_NULLPTR;
118    }
119    auto property = windowNode->GetWindowToken()->GetWindowProperty();
120    if (property == nullptr) {
121        WLOGFE("Get property failed , skip, missionId: %{public}d ", missionId);
122        return WMError::WM_ERROR_NULLPTR;
123    }
124    std::set<DisplayId> displayIds;
125    if (backupWindowModes_.count(windowNode->GetWindowId()) > 0) {
126        auto mode = backupWindowModes_.at(windowNode->GetWindowId());
127        if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
128            property->SetWindowMode(mode);
129            windowNode->SetWindowMode(mode);
130            // when change mode, need to reset shadow and radius
131            WindowSystemEffect::SetWindowEffect(windowNode);
132            displayIds.insert(windowNode->GetDisplayId());
133            windowNode->GetWindowToken()->RestoreSplitWindowMode(static_cast<uint32_t>(mode));
134            WLOGFD("Restore windowId: %{public}d, missionId: %{public}d, node: %{public}s, \
135                zOrder: %{public}d, mode: %{public}d ",
136                windowNode->GetWindowId(), windowNode->abilityInfo_.missionId_,
137                (windowNode == nullptr ? "NUll" : windowNode->GetWindowName().c_str()),
138                windowNode->zOrder_, windowNode->GetWindowMode());
139        }
140    }
141    for (auto displayId : displayIds) {
142        auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
143        if (container != nullptr) {
144            auto windowPair = container->GetDisplayGroupController()->GetWindowPairByDisplayId(displayId);
145            if (windowPair != nullptr) {
146                windowPair->SetAllSplitAppWindowsRestoring(true);
147            }
148        }
149    }
150    windowNode->GetWindowToken()->UpdateWindowState(WindowState::STATE_SHOWN);
151    WindowManagerService::GetInstance().AddWindow(property);
152    for (auto displayId : displayIds) {
153        auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
154        if (container != nullptr) {
155            auto windowPair = container->GetDisplayGroupController()->GetWindowPairByDisplayId(displayId);
156            if (windowPair != nullptr) {
157                windowPair->SetAllSplitAppWindowsRestoring(false);
158                container->GetLayoutPolicy()->SetSplitDividerWindowRects(backupDividerWindowRect_);
159            }
160        }
161    }
162    return WMError::WM_OK;
163}
164
165void WindowGroupMgr::OnWindowDestroyed(uint32_t windowId)
166{
167    WLOGFD("OnWindowDestroyed WindowIds: %{public}d", windowId);
168    backupWindowModes_.erase(windowId);
169}
170
171void WindowGroupMgr::OnDisplayStateChange(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
172    const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap, DisplayStateChangeType type)
173{
174    WLOGFD("OnDisplayStateChange displayId: %{public}" PRIu64", type: %{public}d", defaultDisplayId, type);
175    if (type == DisplayStateChangeType::DESTROY) {
176        backupDividerWindowRect_.erase(defaultDisplayId);
177    }
178}
179
180}
181}
182