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