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 std::vector<MMI::ScreenInfo> screenInfos;
75 UpdateDisplayGroupInfo(container, displayGroupInfo_, displayId);
76 UpdateDisplayInfo(displayInfos, displayGroupInfo_.displaysInfo);
77 ConstructScreenInfos(displayGroupInfo_.displaysInfo, screenInfos);
78 std::vector<sptr<WindowNode>> windowNodes;
79 container->TraverseContainer(windowNodes);
80 TraverseWindowNodes(windowNodes, displayGroupInfo_.windowsInfo);
81 WLOGFD("update display info to IMS, displayId: %{public}" PRIu64"", displayId);
82 std::vector<MMI::DisplayGroupInfo> displayGroups;
83 displayGroups.emplace_back(displayGroupInfo_);
84 MMI::UserScreenInfo userScreenInfo = {
85 .userId = 0,
86 .screens = screenInfos,
87 .displayGroups = displayGroups
88 };
89 auto task = [userScreenInfo]() {
90 MMI::InputManager::GetInstance()->UpdateDisplayInfo(userScreenInfo);
91 };
92 WindowInnerManager::GetInstance().PostTask(std::move(task), "wms:UpdateDisplayInfoBydisplayId");
93 }
94
UpdateDisplayGroupInfo(const sptr<WindowNodeContainer> & windowNodeContainer,MMI::DisplayGroupInfo & displayGroupInfo,DisplayId displayId)95 void InputWindowMonitor::UpdateDisplayGroupInfo(const sptr<WindowNodeContainer>& windowNodeContainer,
96 MMI::DisplayGroupInfo& displayGroupInfo, DisplayId displayId)
97 {
98 displayGroupInfo.id = 0;
99 displayGroupInfo.name = "displayGroup0";
100 displayGroupInfo.type = MMI::GROUP_DEFAULT;
101 displayGroupInfo.mainDisplayId = displayId;
102 displayGroupInfo.focusWindowId = static_cast<int32_t>(windowNodeContainer->GetFocusWindow());
103 displayGroupInfo.windowsInfo.clear();
104 displayGroupInfo.displaysInfo.clear();
105 }
106
UpdateDisplayInfo(const std::vector<sptr<DisplayInfo>> & displayInfos,std::vector<MMI::DisplayInfo> & displayInfoVector)107 void InputWindowMonitor::UpdateDisplayInfo(const std::vector<sptr<DisplayInfo>>& displayInfos,
108 std::vector<MMI::DisplayInfo>& displayInfoVector)
109 {
110 for (auto& displayInfo : displayInfos) {
111 if (displayInfo == nullptr) {
112 continue;
113 }
114 uint32_t displayWidth = static_cast<uint32_t>(displayInfo->GetWidth());
115 uint32_t displayHeight = static_cast<uint32_t>(displayInfo->GetHeight());
116 int32_t offsetX = displayInfo->GetOffsetX();
117 int32_t offsetY = displayInfo->GetOffsetY();
118 if (displayInfo->GetWaterfallDisplayCompressionStatus()) {
119 displayWidth = static_cast<uint32_t>(
120 static_cast<int32_t>(displayWidth) + offsetX * 2); // 2: Get full width;
121 displayHeight = static_cast<uint32_t>(
122 static_cast<int32_t>(displayHeight) + offsetY * 2); // 2: Get full height;
123 offsetX = 0;
124 offsetY = 0;
125 }
126 if (displayInfo->GetRotation() == Rotation::ROTATION_90 ||
127 displayInfo->GetRotation() == Rotation::ROTATION_270) {
128 std::swap(displayWidth, displayHeight);
129 }
130 MMI::DisplayInfo display = {
131 .id = static_cast<int32_t>(displayInfo->GetDisplayId()),
132 .x = offsetX,
133 .y = offsetY,
134 .width = static_cast<int32_t>(displayWidth),
135 .height = static_cast<int32_t>(displayHeight),
136 .dpi = displayInfo->GetDpi(),
137 .name = "display " + std::to_string(displayInfo->GetDisplayId()),
138 .direction = GetDisplayDirectionForMmi(displayInfo->GetRotation()),
139 .displayDirection = GetDisplayDirectionForMmi(displayInfo->GetRotation()),
140 .screenArea = {
141 .id = static_cast<int32_t>(displayInfo->GetDisplayId()),
142 .area = { offsetX, offsetY, static_cast<int32_t>(displayWidth), static_cast<int32_t>(displayHeight) }
143 }
144 };
145 auto displayIter = std::find_if(displayInfoVector.begin(), displayInfoVector.end(),
146 [&display](MMI::DisplayInfo& displayInfoTmp) {
147 return displayInfoTmp.id == display.id;
148 });
149 if (displayIter != displayInfoVector.end()) {
150 *displayIter = display;
151 } else {
152 displayInfoVector.emplace_back(display);
153 }
154 WLOGFD("UpdateDisplayInfo, displayId: %{public}d, displayRect: "
155 "[%{public}d, %{public}d, %{public}u, %{public}u]",
156 display.id, display.x, display.y, display.width, display.height);
157 }
158 }
159
ConstructScreenInfos(std::vector<MMI::DisplayInfo> & displayInfoVector,std::vector<MMI::ScreenInfo> & screenInfos)160 void InputWindowMonitor::ConstructScreenInfos(std::vector<MMI::DisplayInfo>& displayInfoVector,
161 std::vector<MMI::ScreenInfo>& screenInfos)
162 {
163 for (auto& displayInfo : displayInfoVector) {
164 MMI::ScreenInfo screenInfo;
165 screenInfo.id = displayInfo.id;
166 screenInfo.uniqueId = "default" + std::to_string(displayInfo.id);
167 screenInfo.screenType = MMI::ScreenType::REAL;
168 screenInfo.width = displayInfo.width;
169 screenInfo.height = displayInfo.height;
170 screenInfo.tpDirection = displayInfo.direction;
171 screenInfo.dpi = displayInfo.dpi;
172 screenInfo.rotation = static_cast<MMI::Rotation>(displayInfo.direction);
173 screenInfos.emplace_back(screenInfo);
174 }
175 }
176
TransformWindowRects(const sptr<WindowNode> & windowNode,Rect & areaRect,std::vector<Rect> & touchHotAreas,std::vector<Rect> & pointerHotAreas)177 void InputWindowMonitor::TransformWindowRects(const sptr<WindowNode>& windowNode, Rect& areaRect,
178 std::vector<Rect>& touchHotAreas, std::vector<Rect>& pointerHotAreas)
179 {
180 if (windowNode->GetWindowProperty()->isNeedComputerTransform()) {
181 windowNode->ComputeTransform();
182 for (Rect& rect : touchHotAreas) {
183 rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect);
184 }
185 for (Rect& rect : pointerHotAreas) {
186 rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect);
187 }
188 WLOGD("Area rect before tranform: [%{public}d, %{public}d, %{public}u, %{public}u]",
189 areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_);
190 areaRect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), areaRect);
191 WLOGD("Area rect after tranform: [%{public}d, %{public}d, %{public}u, %{public}u]",
192 areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_);
193 }
194 }
195
TraverseWindowNodes(const std::vector<sptr<WindowNode>> & windowNodes,std::vector<MMI::WindowInfo> & windowsInfo)196 void InputWindowMonitor::TraverseWindowNodes(const std::vector<sptr<WindowNode>>& windowNodes,
197 std::vector<MMI::WindowInfo>& windowsInfo)
198 {
199 std::map<uint32_t, sptr<WindowNode>> dialogWindowMap;
200 for (const auto& windowNode: windowNodes) {
201 if (windowNode->GetWindowType() != WindowType::WINDOW_TYPE_DIALOG) {
202 continue;
203 }
204 sptr<WindowNode> callerNode =
205 windowRoot_->FindMainWindowWithToken(windowNode->dialogTargetToken_);
206 if (callerNode != nullptr) {
207 dialogWindowMap.insert(std::make_pair(callerNode->GetWindowId(), windowNode));
208 }
209 }
210 for (const auto& windowNode: windowNodes) {
211 if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowType()) != INPUT_WINDOW_TYPE_SKIPPED.end()) {
212 WLOGI("skip node[id:%{public}u, type:%{public}d]", windowNode->GetWindowId(), windowNode->GetWindowType());
213 continue;
214 }
215
216 std::vector<Rect> touchHotAreas;
217 std::vector<Rect> pointerHotAreas;
218 windowNode->GetTouchHotAreas(touchHotAreas);
219 windowNode->GetPointerHotAreas(pointerHotAreas);
220 Rect areaRect = windowNode->GetWindowRect();
221
222 TransformWindowRects(windowNode, areaRect, touchHotAreas, pointerHotAreas);
223
224 MMI::WindowInfo windowInfo = {
225 .id = static_cast<int32_t>(windowNode->GetWindowId()),
226 .pid = windowNode->GetInputEventCallingPid(),
227 .uid = windowNode->GetCallingUid(),
228 .area = MMI::Rect { areaRect.posX_, areaRect.posY_,
229 static_cast<int32_t>(areaRect.width_), static_cast<int32_t>(areaRect.height_) },
230 .agentWindowId = static_cast<int32_t>(windowNode->GetWindowId()),
231 };
232
233 auto iter = (windowNode->GetParentId() == INVALID_WINDOW_ID) ?
234 dialogWindowMap.find(windowNode->GetWindowId()) : dialogWindowMap.find(windowNode->GetParentId());
235 if (iter != dialogWindowMap.end()) {
236 windowInfo.agentWindowId = static_cast<int32_t>(iter->second->GetWindowId());
237 }
238 convertRectsToMmiRects(touchHotAreas, windowInfo.defaultHotAreas);
239 convertRectsToMmiRects(pointerHotAreas, windowInfo.pointerHotAreas);
240 if (!windowNode->GetWindowProperty()->GetTouchable()) {
241 WLOGFD("window is not touchable: %{public}u", windowNode->GetWindowId());
242 windowInfo.flags |= MMI::WindowInfo::FLAG_BIT_UNTOUCHABLE;
243 }
244 windowsInfo.emplace_back(windowInfo);
245 }
246 }
247
GetDisplayDirectionForMmi(Rotation rotation)248 MMI::Direction InputWindowMonitor::GetDisplayDirectionForMmi(Rotation rotation)
249 {
250 MMI::Direction direction = MMI::DIRECTION0;
251 switch (rotation) {
252 case Rotation::ROTATION_0:
253 direction = MMI::DIRECTION0;
254 break;
255 case Rotation::ROTATION_90:
256 direction = MMI::DIRECTION90;
257 break;
258 case Rotation::ROTATION_180:
259 direction = MMI::DIRECTION180;
260 break;
261 case Rotation::ROTATION_270:
262 direction = MMI::DIRECTION270;
263 break;
264 default:
265 break;
266 }
267 return direction;
268 }
269 }
270 }
271