1/*
2 * Copyright (c) 2022 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 "accessibility_connection.h"
17
18#include "display_manager_service_inner.h"
19#include "window_manager.h"
20#include "window_manager_agent_controller.h"
21#include "window_manager_hilog.h"
22
23namespace OHOS::Rosen {
24namespace {
25constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "AccessibilityConnection"};
26}
27
28void AccessibilityConnection::NotifyAccessibilityWindowInfo(const sptr<WindowNode>& node, WindowUpdateType type)
29{
30    if (node == nullptr) {
31        WLOGFE("window node is null");
32        return;
33    }
34    auto container = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId());
35    if (container == nullptr) {
36        WLOGFE("container is null");
37        return;
38    }
39    std::vector<sptr<WindowNode>> nodes;
40    nodes.emplace_back(node);
41    UpdateFocusChangeEvent(container);
42    NotifyAccessibilityWindowInfo(nodes, container->GetFocusWindow(), type);
43}
44
45void AccessibilityConnection::NotifyAccessibilityWindowInfo(DisplayId displayId,
46    const std::vector<sptr<WindowNode>>& nodes, WindowUpdateType type)
47{
48    if (nodes.empty()) {
49        WLOGFE("nodes is empty");
50        return;
51    }
52    auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
53    if (container == nullptr) {
54        WLOGFE("container is null");
55        return;
56    }
57    UpdateFocusChangeEvent(container);
58    NotifyAccessibilityWindowInfo(nodes, container->GetFocusWindow(), type);
59}
60
61void AccessibilityConnection::NotifyAccessibilityWindowInfo(DisplayId displayId, WindowUpdateType type)
62{
63    auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
64    if (container == nullptr) {
65        WLOGFE("container is null");
66        return;
67    }
68    std::vector<sptr<WindowNode>> nodes;
69    container->TraverseContainer(nodes);
70    UpdateFocusChangeEvent(container);
71    NotifyAccessibilityWindowInfo(nodes, container->GetFocusWindow(), type);
72}
73
74void AccessibilityConnection::NotifyAccessibilityWindowInfo(const std::vector<sptr<WindowNode>>& nodes,
75    uint32_t focusedWindow, WindowUpdateType type) const
76{
77    std::vector<sptr<AccessibilityWindowInfo>> infos;
78    FillAccessibilityWindowInfo(nodes, focusedWindow, infos);
79    if (infos.empty()) {
80        WLOGFE("infos is empty");
81        return;
82    }
83    WindowManagerAgentController::GetInstance().NotifyAccessibilityWindowInfo(infos, type);
84}
85
86void AccessibilityConnection::FillAccessibilityWindowInfo(const std::vector<sptr<WindowNode>>& nodes,
87    uint32_t focusedWindow, std::vector<sptr<AccessibilityWindowInfo>>& infos) const
88{
89    for (auto& node : nodes) {
90        sptr<AccessibilityWindowInfo> info = new (std::nothrow) AccessibilityWindowInfo();
91        if (info == nullptr) {
92            WLOGFE("new accessibilityWindowInfo is null");
93            return;
94        }
95        if (node == nullptr) {
96            WLOGFW("node is null");
97            break;
98        }
99        info->wid_ = static_cast<int32_t>(node->GetWindowId());
100        info->windowRect_ = node->GetWindowRect();
101        info->focused_ = node->GetWindowId() == focusedWindow;
102        info->displayId_ = node->GetDisplayId();
103        info->layer_ = node->zOrder_;
104        info->mode_ = node->GetWindowMode();
105        info->type_ = node->GetWindowType();
106        auto property = node->GetWindowProperty();
107        if (property != nullptr) {
108            info->isDecorEnable_ = property->GetDecorEnable();
109        }
110        infos.emplace_back(info);
111    }
112}
113
114void AccessibilityConnection::GetAccessibilityWindowInfo(std::vector<sptr<AccessibilityWindowInfo>>& infos) const
115{
116    std::map<ScreenId, sptr<WindowNodeContainer>> windowNodeContainers;
117    std::vector<DisplayId> displayIds = DisplayManagerServiceInner::GetInstance().GetAllDisplayIds();
118    for (DisplayId displayId : displayIds) {
119        ScreenId screenGroupId = DisplayManagerServiceInner::GetInstance().GetScreenGroupIdByDisplayId(displayId);
120        auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
121        if (windowNodeContainers.count(screenGroupId) == 0 && container != nullptr) {
122            windowNodeContainers.insert(std::make_pair(screenGroupId, container));
123            std::vector<sptr<WindowNode>> nodes;
124            container->TraverseContainer(nodes);
125            FillAccessibilityWindowInfo(nodes, container->GetFocusWindow(), infos);
126        }
127    }
128}
129
130void AccessibilityConnection::UpdateFocusChangeEvent(const sptr<WindowNodeContainer>& container)
131{
132    if (container == nullptr) {
133        WLOGFE("container is null");
134        return;
135    }
136    bool focusChange = false;
137    uint32_t focusWindowId = container->GetFocusWindow();
138    auto iter = focusedWindowMap_.find(container);
139    if (iter == focusedWindowMap_.end()) {
140        focusedWindowMap_.insert(std::make_pair(container, focusWindowId));
141        if (focusWindowId != INVALID_WINDOW_ID) {
142            focusChange = true;
143        }
144    } else {
145        if (focusWindowId != iter->second) {
146            focusChange = true;
147            iter->second = focusWindowId;
148        }
149    }
150    if (focusChange) {
151        auto focusWindowNode = windowRoot_->GetWindowNode(focusWindowId);
152        if (focusWindowNode == nullptr) {
153            WLOGFE("could not find window");
154            return;
155        }
156        std::vector<sptr<WindowNode>> focusNodes;
157        focusNodes.emplace_back(focusWindowNode);
158        WLOGFD("notify accessibility window info: focus change, focusWindowId: %{public}u", focusWindowId);
159        NotifyAccessibilityWindowInfo(focusNodes, focusWindowId, WindowUpdateType::WINDOW_UPDATE_FOCUSED);
160    }
161}
162}
163