1 /*
2 * Copyright (c) 2021-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 "input_window_monitor.h"
17
18 #include <ipc_skeleton.h>
19 #include <ability_manager_client.h>
20
21 #include "display_group_info.h"
22 #include "display_manager_service_inner.h"
23 #include "dm_common.h"
24 #include "window_helper.h"
25 #include "window_manager_hilog.h"
26 #include "window_inner_manager.h"
27
28 namespace OHOS {
29 namespace Rosen {
30 namespace {
31 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InputMonitor"};
32 }
convertRectsToMmiRects(const std::vector<Rect> & rects,std::vector<MMI::Rect> & mmiRects)33 static inline void convertRectsToMmiRects(const std::vector<Rect>& rects, std::vector<MMI::Rect>& mmiRects)
34 {
35 for (const auto& rect : rects) {
36 mmiRects.emplace_back(
37 MMI::Rect{ rect.posX_, rect.posY_, static_cast<int32_t>(rect.width_), static_cast<int32_t>(rect.height_) });
38 }
39 }
40
UpdateInputWindow(uint32_t windowId)41 void InputWindowMonitor::UpdateInputWindow(uint32_t windowId)
42 {
43 if (windowRoot_ == nullptr) {
44 WLOGFE("windowRoot is null.");
45 return;
46 }
47 sptr<WindowNode> windowNode = windowRoot_->GetWindowNode(windowId);
48 if (windowNode == nullptr) {
49 WLOGFE("window node could not be found.");
50 return;
51 }
52 if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowProperty()->GetWindowType()) !=
53 INPUT_WINDOW_TYPE_SKIPPED.end()) {
54 return;
55 }
56 DisplayId displayId = windowNode->GetDisplayId();
57 UpdateInputWindowByDisplayId(displayId);
58 }
59
UpdateInputWindowByDisplayId(DisplayId displayId)60 void InputWindowMonitor::UpdateInputWindowByDisplayId(DisplayId displayId)
61 {
62 if (displayId == DISPLAY_ID_INVALID) {
63 return;
64 }
65 auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
66 if (container == nullptr) {
67 WLOGFE("can not get window node container.");
68 return;
69 }
70 auto displayInfos = DisplayGroupInfo::GetInstance().GetAllDisplayInfo();
71 if (displayInfos.empty()) {
72 return;
73 }
74 UpdateDisplayGroupInfo(container, displayGroupInfo_);
75 UpdateDisplayInfo(displayInfos, displayGroupInfo_.displaysInfo);
76 std::vector<sptr<WindowNode>> windowNodes;
77 container->TraverseContainer(windowNodes);
78 TraverseWindowNodes(windowNodes, displayGroupInfo_.windowsInfo);
79 WLOGFD("update display info to IMS, displayId: %{public}" PRIu64"", displayId);
80 auto task = [displayGroupInfo = displayGroupInfo_]() {
81 MMI::InputManager::GetInstance()->UpdateDisplayInfo(displayGroupInfo);
82 };
83 WindowInnerManager::GetInstance().PostTask(std::move(task), "wms:UpdateDisplayInfoBydisplayId");
84 }
85
UpdateDisplayGroupInfo(const sptr<WindowNodeContainer> & windowNodeContainer,MMI::DisplayGroupInfo & displayGroupInfo)86 void InputWindowMonitor::UpdateDisplayGroupInfo(const sptr<WindowNodeContainer>& windowNodeContainer,
87 MMI::DisplayGroupInfo& displayGroupInfo)
88 {
89 const Rect&& rect = windowNodeContainer->GetDisplayGroupRect();
90 displayGroupInfo.width = static_cast<int32_t>(rect.width_);
91 displayGroupInfo.height = static_cast<int32_t>(rect.height_);
92 displayGroupInfo.focusWindowId = static_cast<int32_t>(windowNodeContainer->GetFocusWindow());
93 displayGroupInfo.windowsInfo.clear();
94 displayGroupInfo.displaysInfo.clear();
95 }
96
UpdateDisplayInfo(const std::vector<sptr<DisplayInfo>> & displayInfos,std::vector<MMI::DisplayInfo> & displayInfoVector)97 void InputWindowMonitor::UpdateDisplayInfo(const std::vector<sptr<DisplayInfo>>& displayInfos,
98 std::vector<MMI::DisplayInfo>& displayInfoVector)
99 {
100 for (auto& displayInfo : displayInfos) {
101 if (displayInfo == nullptr) {
102 continue;
103 }
104 uint32_t displayWidth = static_cast<uint32_t>(displayInfo->GetWidth());
105 uint32_t displayHeight = static_cast<uint32_t>(displayInfo->GetHeight());
106 int32_t offsetX = displayInfo->GetOffsetX();
107 int32_t offsetY = displayInfo->GetOffsetY();
108 if (displayInfo->GetWaterfallDisplayCompressionStatus()) {
109 displayWidth = static_cast<uint32_t>(
110 static_cast<int32_t>(displayWidth) + offsetX * 2); // 2: Get full width;
111 displayHeight = static_cast<uint32_t>(
112 static_cast<int32_t>(displayHeight) + offsetY * 2); // 2: Get full height;
113 offsetX = 0;
114 offsetY = 0;
115 }
116 if (displayInfo->GetRotation() == Rotation::ROTATION_90 ||
117 displayInfo->GetRotation() == Rotation::ROTATION_270) {
118 std::swap(displayWidth, displayHeight);
119 }
120 MMI::DisplayInfo display = {
121 .id = static_cast<int32_t>(displayInfo->GetDisplayId()),
122 .x = offsetX,
123 .y = offsetY,
124 .width = static_cast<int32_t>(displayWidth),
125 .height = static_cast<int32_t>(displayHeight),
126 .dpi = displayInfo->GetDpi(),
127 .name = "display " + std::to_string(displayInfo->GetDisplayId()),
128 .uniq = "default" + std::to_string(displayInfo->GetDisplayId()),
129 .direction = GetDisplayDirectionForMmi(displayInfo->GetRotation()),
130 .displayDirection = GetDisplayDirectionForMmi(displayInfo->GetRotation()),
131 };
132 auto displayIter = std::find_if(displayInfoVector.begin(), displayInfoVector.end(),
133 [&display](MMI::DisplayInfo& displayInfoTmp) {
134 return displayInfoTmp.id == display.id;
135 });
136 if (displayIter != displayInfoVector.end()) {
137 *displayIter = display;
138 } else {
139 displayInfoVector.emplace_back(display);
140 }
141 WLOGFD("UpdateDisplayInfo, displayId: %{public}d, displayRect: "
142 "[%{public}d, %{public}d, %{public}u, %{public}u]",
143 display.id, display.x, display.y, display.width, display.height);
144 }
145 }
146
TransformWindowRects(const sptr<WindowNode> & windowNode,Rect & areaRect,std::vector<Rect> & touchHotAreas,std::vector<Rect> & pointerHotAreas)147 void InputWindowMonitor::TransformWindowRects(const sptr<WindowNode>& windowNode, Rect& areaRect,
148 std::vector<Rect>& touchHotAreas, std::vector<Rect>& pointerHotAreas)
149 {
150 if (windowNode->GetWindowProperty()->isNeedComputerTransform()) {
151 windowNode->ComputeTransform();
152 for (Rect& rect : touchHotAreas) {
153 rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect);
154 }
155 for (Rect& rect : pointerHotAreas) {
156 rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect);
157 }
158 WLOGD("Area rect before tranform: [%{public}d, %{public}d, %{public}u, %{public}u]",
159 areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_);
160 areaRect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), areaRect);
161 WLOGD("Area rect after tranform: [%{public}d, %{public}d, %{public}u, %{public}u]",
162 areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_);
163 }
164 }
165
TraverseWindowNodes(const std::vector<sptr<WindowNode>> & windowNodes,std::vector<MMI::WindowInfo> & windowsInfo)166 void InputWindowMonitor::TraverseWindowNodes(const std::vector<sptr<WindowNode>> &windowNodes,
167 std::vector<MMI::WindowInfo>& windowsInfo)
168 {
169 std::map<uint32_t, sptr<WindowNode>> dialogWindowMap;
170 for (const auto& windowNode: windowNodes) {
171 if (windowNode->GetWindowType() != WindowType::WINDOW_TYPE_DIALOG) {
172 continue;
173 }
174 sptr<WindowNode> callerNode =
175 windowRoot_->FindMainWindowWithToken(windowNode->dialogTargetToken_);
176 if (callerNode != nullptr) {
177 dialogWindowMap.insert(std::make_pair(callerNode->GetWindowId(), windowNode));
178 }
179 }
180 for (const auto& windowNode: windowNodes) {
181 if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowType()) != INPUT_WINDOW_TYPE_SKIPPED.end()) {
182 WLOGI("skip node[id:%{public}u, type:%{public}d]", windowNode->GetWindowId(), windowNode->GetWindowType());
183 continue;
184 }
185
186 std::vector<Rect> touchHotAreas;
187 std::vector<Rect> pointerHotAreas;
188 windowNode->GetTouchHotAreas(touchHotAreas);
189 windowNode->GetPointerHotAreas(pointerHotAreas);
190 Rect areaRect = windowNode->GetWindowRect();
191
192 TransformWindowRects(windowNode, areaRect, touchHotAreas, pointerHotAreas);
193
194 MMI::WindowInfo windowInfo = {
195 .id = static_cast<int32_t>(windowNode->GetWindowId()),
196 .pid = windowNode->GetInputEventCallingPid(),
197 .uid = windowNode->GetCallingUid(),
198 .area = MMI::Rect { areaRect.posX_, areaRect.posY_,
199 static_cast<int32_t>(areaRect.width_), static_cast<int32_t>(areaRect.height_) },
200 .agentWindowId = static_cast<int32_t>(windowNode->GetWindowId()),
201 };
202
203 auto iter = (windowNode->GetParentId() == INVALID_WINDOW_ID) ?
204 dialogWindowMap.find(windowNode->GetWindowId()) : dialogWindowMap.find(windowNode->GetParentId());
205 if (iter != dialogWindowMap.end()) {
206 windowInfo.agentWindowId = static_cast<int32_t>(iter->second->GetWindowId());
207 }
208 convertRectsToMmiRects(touchHotAreas, windowInfo.defaultHotAreas);
209 convertRectsToMmiRects(pointerHotAreas, windowInfo.pointerHotAreas);
210 if (!windowNode->GetWindowProperty()->GetTouchable()) {
211 WLOGFD("window is not touchable: %{public}u", windowNode->GetWindowId());
212 windowInfo.flags |= MMI::WindowInfo::FLAG_BIT_UNTOUCHABLE;
213 }
214 windowsInfo.emplace_back(windowInfo);
215 }
216 }
217
GetDisplayDirectionForMmi(Rotation rotation)218 MMI::Direction InputWindowMonitor::GetDisplayDirectionForMmi(Rotation rotation)
219 {
220 MMI::Direction direction = MMI::DIRECTION0;
221 switch (rotation) {
222 case Rotation::ROTATION_0:
223 direction = MMI::DIRECTION0;
224 break;
225 case Rotation::ROTATION_90:
226 direction = MMI::DIRECTION90;
227 break;
228 case Rotation::ROTATION_180:
229 direction = MMI::DIRECTION180;
230 break;
231 case Rotation::ROTATION_270:
232 direction = MMI::DIRECTION270;
233 break;
234 default:
235 break;
236 }
237 return direction;
238 }
239 }
240 }
241