• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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