/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "input_window_monitor.h" #include #include #include "display_group_info.h" #include "display_manager_service_inner.h" #include "dm_common.h" #include "window_helper.h" #include "window_manager_hilog.h" #include "window_inner_manager.h" namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "InputMonitor"}; } static inline void convertRectsToMmiRects(const std::vector& rects, std::vector& mmiRects) { for (const auto& rect : rects) { mmiRects.emplace_back( MMI::Rect{ rect.posX_, rect.posY_, static_cast(rect.width_), static_cast(rect.height_) }); } } void InputWindowMonitor::UpdateInputWindow(uint32_t windowId) { if (windowRoot_ == nullptr) { WLOGFE("windowRoot is null."); return; } sptr windowNode = windowRoot_->GetWindowNode(windowId); if (windowNode == nullptr) { WLOGFE("window node could not be found."); return; } if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowProperty()->GetWindowType()) != INPUT_WINDOW_TYPE_SKIPPED.end()) { return; } DisplayId displayId = windowNode->GetDisplayId(); UpdateInputWindowByDisplayId(displayId); } void InputWindowMonitor::UpdateInputWindowByDisplayId(DisplayId displayId) { if (displayId == DISPLAY_ID_INVALID) { return; } auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId); if (container == nullptr) { WLOGFE("can not get window node container."); return; } auto displayInfos = DisplayGroupInfo::GetInstance().GetAllDisplayInfo(); if (displayInfos.empty()) { return; } UpdateDisplayGroupInfo(container, displayGroupInfo_); UpdateDisplayInfo(displayInfos, displayGroupInfo_.displaysInfo); std::vector> windowNodes; container->TraverseContainer(windowNodes); TraverseWindowNodes(windowNodes, displayGroupInfo_.windowsInfo); WLOGFD("update display info to IMS, displayId: %{public}" PRIu64"", displayId); auto task = [displayGroupInfo = displayGroupInfo_]() { MMI::InputManager::GetInstance()->UpdateDisplayInfo(displayGroupInfo); }; WindowInnerManager::GetInstance().PostTask(std::move(task), "wms:UpdateDisplayInfoBydisplayId"); } void InputWindowMonitor::UpdateDisplayGroupInfo(const sptr& windowNodeContainer, MMI::DisplayGroupInfo& displayGroupInfo) { const Rect&& rect = windowNodeContainer->GetDisplayGroupRect(); displayGroupInfo.width = static_cast(rect.width_); displayGroupInfo.height = static_cast(rect.height_); displayGroupInfo.focusWindowId = static_cast(windowNodeContainer->GetFocusWindow()); displayGroupInfo.windowsInfo.clear(); displayGroupInfo.displaysInfo.clear(); } void InputWindowMonitor::UpdateDisplayInfo(const std::vector>& displayInfos, std::vector& displayInfoVector) { for (auto& displayInfo : displayInfos) { if (displayInfo == nullptr) { continue; } uint32_t displayWidth = static_cast(displayInfo->GetWidth()); uint32_t displayHeight = static_cast(displayInfo->GetHeight()); int32_t offsetX = displayInfo->GetOffsetX(); int32_t offsetY = displayInfo->GetOffsetY(); if (displayInfo->GetWaterfallDisplayCompressionStatus()) { displayWidth = static_cast( static_cast(displayWidth) + offsetX * 2); // 2: Get full width; displayHeight = static_cast( static_cast(displayHeight) + offsetY * 2); // 2: Get full height; offsetX = 0; offsetY = 0; } if (displayInfo->GetRotation() == Rotation::ROTATION_90 || displayInfo->GetRotation() == Rotation::ROTATION_270) { std::swap(displayWidth, displayHeight); } MMI::DisplayInfo display = { .id = static_cast(displayInfo->GetDisplayId()), .x = offsetX, .y = offsetY, .width = static_cast(displayWidth), .height = static_cast(displayHeight), .dpi = displayInfo->GetDpi(), .name = "display " + std::to_string(displayInfo->GetDisplayId()), .uniq = "default" + std::to_string(displayInfo->GetDisplayId()), .direction = GetDisplayDirectionForMmi(displayInfo->GetRotation()), .displayDirection = GetDisplayDirectionForMmi(displayInfo->GetRotation()), }; auto displayIter = std::find_if(displayInfoVector.begin(), displayInfoVector.end(), [&display](MMI::DisplayInfo& displayInfoTmp) { return displayInfoTmp.id == display.id; }); if (displayIter != displayInfoVector.end()) { *displayIter = display; } else { displayInfoVector.emplace_back(display); } WLOGFD("UpdateDisplayInfo, displayId: %{public}d, displayRect: " "[%{public}d, %{public}d, %{public}u, %{public}u]", display.id, display.x, display.y, display.width, display.height); } } void InputWindowMonitor::TransformWindowRects(const sptr& windowNode, Rect& areaRect, std::vector& touchHotAreas, std::vector& pointerHotAreas) { if (windowNode->GetWindowProperty()->isNeedComputerTransform()) { windowNode->ComputeTransform(); for (Rect& rect : touchHotAreas) { rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect); } for (Rect& rect : pointerHotAreas) { rect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), rect); } WLOGD("Area rect before tranform: [%{public}d, %{public}d, %{public}u, %{public}u]", areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_); areaRect = WindowHelper::TransformRect(windowNode->GetWindowProperty()->GetTransformMat(), areaRect); WLOGD("Area rect after tranform: [%{public}d, %{public}d, %{public}u, %{public}u]", areaRect.posX_, areaRect.posY_, areaRect.width_, areaRect.height_); } } void InputWindowMonitor::TraverseWindowNodes(const std::vector> &windowNodes, std::vector& windowsInfo) { std::map> dialogWindowMap; for (const auto& windowNode: windowNodes) { if (windowNode->GetWindowType() != WindowType::WINDOW_TYPE_DIALOG) { continue; } sptr callerNode = windowRoot_->FindMainWindowWithToken(windowNode->dialogTargetToken_); if (callerNode != nullptr) { dialogWindowMap.insert(std::make_pair(callerNode->GetWindowId(), windowNode)); } } for (const auto& windowNode: windowNodes) { if (INPUT_WINDOW_TYPE_SKIPPED.find(windowNode->GetWindowType()) != INPUT_WINDOW_TYPE_SKIPPED.end()) { WLOGI("skip node[id:%{public}u, type:%{public}d]", windowNode->GetWindowId(), windowNode->GetWindowType()); continue; } std::vector touchHotAreas; std::vector pointerHotAreas; windowNode->GetTouchHotAreas(touchHotAreas); windowNode->GetPointerHotAreas(pointerHotAreas); Rect areaRect = windowNode->GetWindowRect(); TransformWindowRects(windowNode, areaRect, touchHotAreas, pointerHotAreas); MMI::WindowInfo windowInfo = { .id = static_cast(windowNode->GetWindowId()), .pid = windowNode->GetInputEventCallingPid(), .uid = windowNode->GetCallingUid(), .area = MMI::Rect { areaRect.posX_, areaRect.posY_, static_cast(areaRect.width_), static_cast(areaRect.height_) }, .agentWindowId = static_cast(windowNode->GetWindowId()), }; auto iter = (windowNode->GetParentId() == INVALID_WINDOW_ID) ? dialogWindowMap.find(windowNode->GetWindowId()) : dialogWindowMap.find(windowNode->GetParentId()); if (iter != dialogWindowMap.end()) { windowInfo.agentWindowId = static_cast(iter->second->GetWindowId()); } convertRectsToMmiRects(touchHotAreas, windowInfo.defaultHotAreas); convertRectsToMmiRects(pointerHotAreas, windowInfo.pointerHotAreas); if (!windowNode->GetWindowProperty()->GetTouchable()) { WLOGFD("window is not touchable: %{public}u", windowNode->GetWindowId()); windowInfo.flags |= MMI::WindowInfo::FLAG_BIT_UNTOUCHABLE; } windowsInfo.emplace_back(windowInfo); } } MMI::Direction InputWindowMonitor::GetDisplayDirectionForMmi(Rotation rotation) { MMI::Direction direction = MMI::DIRECTION0; switch (rotation) { case Rotation::ROTATION_0: direction = MMI::DIRECTION0; break; case Rotation::ROTATION_90: direction = MMI::DIRECTION90; break; case Rotation::ROTATION_180: direction = MMI::DIRECTION180; break; case Rotation::ROTATION_270: direction = MMI::DIRECTION270; break; default: break; } return direction; } } }