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 28namespace OHOS { 29namespace Rosen { 30namespace { 31constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InputMonitor"}; 32} 33static 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 41void 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 60void 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 86void 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 97void 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 147void 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 166void 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 218MMI::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