/* * 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 "window_node_container.h" #include #include #include #include #include #include #include "common_event_manager.h" #include "display_manager_service_inner.h" #include "dm_common.h" #include "window_helper.h" #include "window_inner_manager.h" #include "window_layout_policy_cascade.h" #include "window_layout_policy_tile.h" #include "window_manager_agent_controller.h" #include "window_manager_hilog.h" #include "wm_common.h" #include "wm_common_inner.h" #include "wm_trace.h" namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowNodeContainer"}; constexpr int WINDOW_NAME_MAX_LENGTH = 10; const std::string SPLIT_SCREEN_EVENT_NAME = "common.event.SPLIT_SCREEN"; const char DISABLE_WINDOW_ANIMATION_PATH[] = "/etc/disable_window_animation"; constexpr uint32_t MAX_BRIGHTNESS = 255; } WindowNodeContainer::WindowNodeContainer(DisplayId displayId, uint32_t width, uint32_t height) { Rect displayRect = { .posX_ = 0, .posY_ = 0, .width_ = width, .height_ = height }; displayRectMap_.insert(std::make_pair(displayId, displayRect)); windowPair_ = new WindowPair(displayId, appWindowNode_); // init window node maps InitWindowNodeMapForDisplay(displayId); // init layout policy layoutPolicys_[WindowLayoutMode::CASCADE] = new WindowLayoutPolicyCascade(displayRectMap_, windowNodeMaps_); layoutPolicys_[WindowLayoutMode::TILE] = new WindowLayoutPolicyTile(displayRectMap_, windowNodeMaps_); layoutPolicy_ = layoutPolicys_[WindowLayoutMode::CASCADE]; layoutPolicy_->Launch(); // init avoidAreaController UpdateAvoidAreaFunc func = std::bind(&WindowNodeContainer::OnAvoidAreaChange, this, std::placeholders::_1, std::placeholders::_2); avoidController_ = new AvoidAreaController(displayId, func); // init systembar map InitSysBarMapForDisplay(displayId); } WindowNodeContainer::~WindowNodeContainer() { Destroy(); } void WindowNodeContainer::InitSysBarMapForDisplay(DisplayId displayId) { SysBarNodeMap sysBarNodeMap { { WindowType::WINDOW_TYPE_STATUS_BAR, nullptr }, { WindowType::WINDOW_TYPE_NAVIGATION_BAR, nullptr }, }; sysBarNodeMaps_.insert(std::make_pair(displayId, sysBarNodeMap)); SysBarTintMap sysBarTintMap { { WindowType::WINDOW_TYPE_STATUS_BAR, SystemBarRegionTint() }, { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarRegionTint() }, }; sysBarTintMaps_.insert(std::make_pair(displayId, sysBarTintMap)); } void WindowNodeContainer::InitWindowNodeMapForDisplay(DisplayId displayId) { std::map>>> windowRootNodeMap; windowRootNodeMap.insert(std::make_pair(WindowRootNodeType::APP_WINDOW_NODE, std::make_unique>>())); windowRootNodeMap.insert(std::make_pair(WindowRootNodeType::ABOVE_WINDOW_NODE, std::make_unique>>())); windowRootNodeMap.insert(std::make_pair(WindowRootNodeType::BELOW_WINDOW_NODE, std::make_unique>>())); windowNodeMaps_.insert(std::make_pair(displayId, std::move(windowRootNodeMap))); } int WindowNodeContainer::GetWindowCountByType(WindowType windowType) { int windowNumber = 0; auto counter = [&windowNumber, &windowType](sptr& windowNode) { if (windowNode->GetWindowType() == windowType) ++windowNumber; }; std::for_each(belowAppWindowNode_->children_.begin(), belowAppWindowNode_->children_.end(), counter); std::for_each(appWindowNode_->children_.begin(), appWindowNode_->children_.end(), counter); std::for_each(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), counter); return windowNumber; } WMError WindowNodeContainer::MinimizeStructuredAppWindowsExceptSelf(const sptr& node) { std::vector exceptionalIds = { node->GetWindowId() }; std::vector exceptionalModes = { WindowMode::WINDOW_MODE_FLOATING, WindowMode::WINDOW_MODE_PIP }; return MinimizeAppNodeExceptOptions(false, exceptionalIds, exceptionalModes); } std::vector>* WindowNodeContainer::FindNodeVectorOfRoot(DisplayId displayId, WindowRootNodeType type) { if (windowNodeMaps_.find(displayId) != windowNodeMaps_.end()) { auto& rootNodemap = windowNodeMaps_[displayId]; if (rootNodemap.find(type) != rootNodemap.end()) { return rootNodemap[type].get(); } } return nullptr; } void WindowNodeContainer::AddWindowNodeInRootNodeVector(sptr& node, WindowRootNodeType rootType) { std::vector>* rootNodeVectorPtr = FindNodeVectorOfRoot(node->GetDisplayId(), rootType); if (rootNodeVectorPtr != nullptr) { rootNodeVectorPtr->push_back(node); WLOGFI("add node in node vector of root, windowId: %{public}d, rootType: %{public}d", node->GetWindowId(), rootType); } else { WLOGFE("add node failed, rootNode vector is empty, windowId: %{public}d, rootType: %{public}d", node->GetWindowId(), rootType); } } void WindowNodeContainer::RemoveWindowNodeFromRootNodeVector(sptr& node, WindowRootNodeType rootType) { std::vector>* rootNodeVectorPtr = FindNodeVectorOfRoot(node->GetDisplayId(), rootType); if (rootNodeVectorPtr != nullptr) { auto iter = std::remove(rootNodeVectorPtr->begin(), rootNodeVectorPtr->end(), node); rootNodeVectorPtr->erase(iter, rootNodeVectorPtr->end()); WLOGFI("remove node from node vector of root, windowId: %{public}d, rootType: %{public}d", node->GetWindowId(), rootType); } else { WLOGFE("remove node failed, rootNode vector is empty, windowId: %{public}d, rootType: %{public}d", node->GetWindowId(), rootType); } } void WindowNodeContainer::UpdateWindowNodeMaps() { for (auto& elem : windowNodeMaps_) { for (auto& nodeVec : elem.second) { auto emptyVector = std::vector>(); nodeVec.second->swap(emptyVector); } } std::vector> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ }; std::vector rootNodeType = { WindowRootNodeType::ABOVE_WINDOW_NODE, WindowRootNodeType::APP_WINDOW_NODE, WindowRootNodeType::BELOW_WINDOW_NODE }; for (size_t index = 0; index < rootNodes.size(); ++index) { auto rootType = rootNodeType[index]; for (auto& node : rootNodes[index]->children_) { AddWindowNodeInRootNodeVector(node, rootType); } } } WMError WindowNodeContainer::AddWindowNodeOnWindowTree(sptr& node, sptr& parentNode) { sptr root = FindRoot(node->GetWindowType()); if (root == nullptr) { WLOGFE("root is nullptr!"); return WMError::WM_ERROR_NULLPTR; } node->requestedVisibility_ = true; if (parentNode != nullptr) { // subwindow if (parentNode->parent_ != root && !((parentNode->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) && (parentNode->parent_ == aboveAppWindowNode_))) { WLOGFE("window type and parent window not match or try to add subwindow to subwindow, which is forbidden"); return WMError::WM_ERROR_INVALID_PARAM; } node->currentVisibility_ = parentNode->currentVisibility_; node->parent_ = parentNode; } else { // mainwindow node->parent_ = root; node->currentVisibility_ = true; for (auto& child : node->children_) { child->currentVisibility_ = child->requestedVisibility_; } if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) { sysBarNodeMaps_[node->GetDisplayId()][node->GetWindowType()] = node; } } return WMError::WM_OK; } WMError WindowNodeContainer::ShowInTransition(sptr& node) { return WMError::WM_OK; } WMError WindowNodeContainer::AddWindowNode(sptr& node, sptr& parentNode) { if (!node->surfaceNode_) { WLOGFE("surface node is nullptr!"); return WMError::WM_ERROR_NULLPTR; } WMError ret = AddWindowNodeOnWindowTree(node, parentNode); if (ret != WMError::WM_OK) { WLOGFE("Add window failed!"); return ret; } windowPair_->UpdateIfSplitRelated(node); UpdateWindowTree(node); if (node->IsSplitMode() || node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { RaiseSplitRelatedWindowToTop(node); } UpdateRSTree(node, true, node->isPlayAnimationShow_); AssignZOrder(); layoutPolicy_->AddWindowNode(node); if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) { avoidController_->AvoidControl(node, AvoidControlType::AVOID_NODE_ADD); NotifyIfSystemBarRegionChanged(node->GetDisplayId()); } else { NotifyIfSystemBarTintChanged(node->GetDisplayId()); } std::vector> infos; UpdateWindowVisibilityInfos(infos); DumpScreenWindowTree(); NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_ADDED); WLOGFI("AddWindowNode windowId: %{public}u end", node->GetWindowId()); return WMError::WM_OK; } WMError WindowNodeContainer::UpdateWindowNode(sptr& node, WindowUpdateReason reason) { if (WindowHelper::IsMainWindow(node->GetWindowType()) && WindowHelper::IsSwitchCascadeReason(reason)) { SwitchLayoutPolicy(WindowLayoutMode::CASCADE, node->GetDisplayId()); } layoutPolicy_->UpdateWindowNode(node); if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) { avoidController_->AvoidControl(node, AvoidControlType::AVOID_NODE_UPDATE); NotifyIfSystemBarRegionChanged(node->GetDisplayId()); } else { NotifyIfSystemBarTintChanged(node->GetDisplayId()); } DumpScreenWindowTree(); WLOGFI("UpdateWindowNode windowId: %{public}u end", node->GetWindowId()); return WMError::WM_OK; } void WindowNodeContainer::UpdateSizeChangeReason(sptr& node, WindowSizeChangeReason reason) { if (!node->GetWindowToken()) { WLOGFE("windowToken is null"); return; } if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { for (auto& childNode : appWindowNode_->children_) { if (childNode->IsSplitMode()) { childNode->GetWindowToken()->UpdateWindowRect(childNode->GetWindowRect(), childNode->GetDecoStatus(), reason); childNode->ResetWindowSizeChangeReason(); WLOGFI("Notify split window that the drag action is start or end, windowId: %{public}d, " "reason: %{public}u", childNode->GetWindowId(), reason); } } } else { node->GetWindowToken()->UpdateWindowRect(node->GetWindowRect(), node->GetDecoStatus(), reason); node->ResetWindowSizeChangeReason(); WLOGFI("Notify window that the drag action is start or end, windowId: %{public}d, " "reason: %{public}u", node->GetWindowId(), reason); } } void WindowNodeContainer::UpdateWindowTree(sptr& node) { WM_FUNCTION_TRACE(); node->priority_ = zorderPolicy_->GetWindowPriority(node->GetWindowType()); RaiseInputMethodWindowPriorityIfNeeded(node); RaiseShowWhenLockedWindowIfNeeded(node); auto parentNode = node->parent_; auto position = parentNode->children_.end(); for (auto iter = parentNode->children_.begin(); iter < parentNode->children_.end(); ++iter) { if ((*iter)->priority_ > node->priority_) { position = iter; break; } } parentNode->children_.insert(position, node); } bool WindowNodeContainer::UpdateRSTree(sptr& node, bool isAdd, bool animationPlayed) { WM_FUNCTION_TRACE(); static const bool IsWindowAnimationEnabled = ReadIsWindowAnimationEnabledProperty(); DisplayId displayId = node->GetDisplayId(); auto updateRSTreeFunc = [&]() { auto& dms = DisplayManagerServiceInner::GetInstance(); if (isAdd) { dms.UpdateRSTree(displayId, node->surfaceNode_, true); for (auto& child : node->children_) { if (child->currentVisibility_) { dms.UpdateRSTree(displayId, child->surfaceNode_, true); } } } else { if (node->leashWinSurfaceNode_) { dms.UpdateRSTree(displayId, node->leashWinSurfaceNode_, false); } else { dms.UpdateRSTree(displayId, node->surfaceNode_, false); } for (auto& child : node->children_) { dms.UpdateRSTree(displayId, child->surfaceNode_, false); } } }; if (IsWindowAnimationEnabled && !animationPlayed) { // default transition duration: 350ms static const RSAnimationTimingProtocol timingProtocol(350); // default transition curve: EASE OUT static const Rosen::RSAnimationTimingCurve curve = Rosen::RSAnimationTimingCurve::EASE_OUT; // add or remove window with transition animation RSNode::Animate(timingProtocol, curve, updateRSTreeFunc); } else { // add or remove window without animation updateRSTreeFunc(); } return true; } WMError WindowNodeContainer::DestroyWindowNode(sptr& node, std::vector& windowIds) { WMError ret = RemoveWindowNode(node); if (ret != WMError::WM_OK) { WLOGFE("RemoveWindowNode failed"); return ret; } node->leashWinSurfaceNode_ = nullptr; node->startingWinSurfaceNode_ = nullptr; node->surfaceNode_ = nullptr; windowIds.push_back(node->GetWindowId()); for (auto& child : node->children_) { // destroy sub window if exists windowIds.push_back(child->GetWindowId()); child->parent_ = nullptr; if (child->surfaceNode_ != nullptr) { WLOGFI("child surfaceNode set nullptr"); child->surfaceNode_ = nullptr; } } auto emptyVector = std::vector>(); node->children_.swap(emptyVector); return WMError::WM_OK; } void WindowNodeContainer::RemoveWindowNodeFromWindowTree(sptr& node) { // remove this node from node vector of display sptr root = FindRoot(node->GetWindowType()); // remove this node from parent auto iter = std::find(node->parent_->children_.begin(), node->parent_->children_.end(), node); if (iter != node->parent_->children_.end()) { node->parent_->children_.erase(iter); } else { WLOGFE("can't find this node in parent"); } node->parent_ = nullptr; } WMError WindowNodeContainer::RemoveWindowNode(sptr& node) { if (node == nullptr) { WLOGFE("window node or surface node is nullptr, invalid"); return WMError::WM_ERROR_DESTROYED_OBJECT; } if (node->parent_ == nullptr) { WLOGFW("can't find parent of this node"); } else { RemoveWindowNodeFromWindowTree(node); } node->requestedVisibility_ = false; node->currentVisibility_ = false; node->isCovered_ = true; std::vector> infos = {new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(), node->GetCallingUid(), false)}; for (auto& child : node->children_) { if (child->currentVisibility_) { child->currentVisibility_ = false; child->isCovered_ = true; infos.emplace_back(new WindowVisibilityInfo(child->GetWindowId(), child->GetCallingPid(), child->GetCallingUid(), false)); } } UpdateRSTree(node, false, node->isPlayAnimationHide_); UpdateWindowNodeMaps(); layoutPolicy_->RemoveWindowNode(node); windowPair_->HandleRemoveWindow(node); if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) { avoidController_->AvoidControl(node, AvoidControlType::AVOID_NODE_REMOVE); NotifyIfSystemBarRegionChanged(node->GetDisplayId()); } else { NotifyIfSystemBarTintChanged(node->GetDisplayId()); } UpdateWindowVisibilityInfos(infos); DumpScreenWindowTree(); NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_REMOVED); RcoveryScreenDefaultOrientationIfNeed(node->GetDisplayId()); WLOGFI("RemoveWindowNode windowId: %{public}u end", node->GetWindowId()); return WMError::WM_OK; } void WindowNodeContainer::RcoveryScreenDefaultOrientationIfNeed(DisplayId displayId) { if (windowNodeMaps_[displayId][WindowRootNodeType::APP_WINDOW_NODE]->empty()) { WLOGFI("appWindowNode_ child is empty in display %{public}" PRIu64"", displayId); DisplayManagerServiceInner::GetInstance(). SetOrientationFromWindow(displayId, Orientation::UNSPECIFIED); } } const std::vector& WindowNodeContainer::Destroy() { auto emptyVector = std::vector(); removedIds_.swap(emptyVector); for (auto& node : belowAppWindowNode_->children_) { DestroyWindowNode(node, removedIds_); } for (auto& node : appWindowNode_->children_) { DestroyWindowNode(node, removedIds_); } for (auto& node : aboveAppWindowNode_->children_) { DestroyWindowNode(node, removedIds_); } return removedIds_; } sptr WindowNodeContainer::FindRoot(WindowType type) const { if (WindowHelper::IsAppWindow(type) || type == WindowType::WINDOW_TYPE_DOCK_SLICE) { return appWindowNode_; } if (WindowHelper::IsBelowSystemWindow(type)) { return belowAppWindowNode_; } if (WindowHelper::IsAboveSystemWindow(type)) { return aboveAppWindowNode_; } return nullptr; } sptr WindowNodeContainer::FindWindowNodeById(uint32_t id) const { std::vector> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ }; for (auto& rootNode : rootNodes) { for (auto& node : rootNode->children_) { if (node->GetWindowId() == id) { return node; } for (auto& subNode : node->children_) { if (subNode->GetWindowId() == id) { return subNode; } } } } return nullptr; } void WindowNodeContainer::UpdateFocusStatus(uint32_t id, bool focused) const { auto node = FindWindowNodeById(id); if (node == nullptr) { WLOGFW("cannot find focused window id:%{public}d", id); } else { if (node->GetWindowToken()) { node->GetWindowToken()->UpdateFocusStatus(focused); } if (node->abilityToken_ == nullptr) { WLOGFI("abilityToken is null, window : %{public}d", id); } if (focused) { WLOGFW("current focus window: windowId: %{public}d, windowName: %{public}s", id, node->GetWindowProperty()->GetWindowName().c_str()); } sptr focusChangeInfo = new FocusChangeInfo(node->GetWindowId(), node->GetDisplayId(), node->GetCallingPid(), node->GetCallingUid(), node->GetWindowType(), node->abilityToken_); WindowManagerAgentController::GetInstance().UpdateFocusChangeInfo( focusChangeInfo, focused); } } void WindowNodeContainer::UpdateActiveStatus(uint32_t id, bool isActive) const { auto node = FindWindowNodeById(id); if (node == nullptr) { WLOGFE("cannot find active window id: %{public}d", id); return; } if (node->GetWindowToken()) { node->GetWindowToken()->UpdateActiveStatus(isActive); } } void WindowNodeContainer::UpdateBrightness(uint32_t id, bool byRemoved) { auto node = FindWindowNodeById(id); if (node == nullptr) { WLOGFE("cannot find active window id: %{public}d", id); return; } if (!byRemoved) { if (!WindowHelper::IsAppWindow(node->GetWindowType())) { return; } } WLOGFI("brightness: [%{public}f, %{public}f]", GetDisplayBrightness(), node->GetBrightness()); if (node->GetBrightness() == UNDEFINED_BRIGHTNESS) { if (GetDisplayBrightness() != node->GetBrightness()) { WLOGFI("adjust brightness with default value"); DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().RestoreBrightness(); SetDisplayBrightness(UNDEFINED_BRIGHTNESS); // UNDEFINED_BRIGHTNESS means system default brightness } SetBrightnessWindow(INVALID_WINDOW_ID); } else { if (GetDisplayBrightness() != node->GetBrightness()) { WLOGFI("adjust brightness with value: %{public}u", ToOverrideBrightness(node->GetBrightness())); DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().OverrideBrightness( ToOverrideBrightness(node->GetBrightness())); SetDisplayBrightness(node->GetBrightness()); } SetBrightnessWindow(node->GetWindowId()); } } void WindowNodeContainer::AssignZOrder() { zOrder_ = 0; WindowNodeOperationFunc func = [this](sptr node) { if (node->surfaceNode_ == nullptr) { WLOGE("AssignZOrder: surfaceNode is nullptr, window Id:%{public}u", node->GetWindowId()); return false; } node->surfaceNode_->SetPositionZ(zOrder_); ++zOrder_; return false; }; TraverseWindowTree(func, false); UpdateWindowNodeMaps(); } WMError WindowNodeContainer::SetFocusWindow(uint32_t windowId) { if (focusedWindow_ == windowId) { WLOGFI("focused window do not change, id: %{public}u", windowId); return WMError::WM_DO_NOTHING; } UpdateFocusStatus(focusedWindow_, false); focusedWindow_ = windowId; sptr node = FindWindowNodeById(windowId); NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_FOCUSED); UpdateFocusStatus(focusedWindow_, true); return WMError::WM_OK; } uint32_t WindowNodeContainer::GetFocusWindow() const { return focusedWindow_; } WMError WindowNodeContainer::SetActiveWindow(uint32_t windowId, bool byRemoved) { if (activeWindow_ == windowId) { WLOGFI("active window do not change, id: %{public}u", windowId); return WMError::WM_DO_NOTHING; } UpdateActiveStatus(activeWindow_, false); activeWindow_ = windowId; UpdateActiveStatus(activeWindow_, true); UpdateBrightness(activeWindow_, byRemoved); return WMError::WM_OK; } void WindowNodeContainer::SetDisplayBrightness(float brightness) { displayBrightness_ = brightness; } float WindowNodeContainer::GetDisplayBrightness() const { return displayBrightness_; } void WindowNodeContainer::SetBrightnessWindow(uint32_t windowId) { brightnessWindow_ = windowId; } uint32_t WindowNodeContainer::GetBrightnessWindow() const { return brightnessWindow_; } uint32_t WindowNodeContainer::ToOverrideBrightness(float brightness) { return static_cast(brightness * MAX_BRIGHTNESS); } uint32_t WindowNodeContainer::GetActiveWindow() const { return activeWindow_; } void WindowNodeContainer::HandleKeepScreenOn(const sptr& node, bool requireLock) { if (requireLock && node->keepScreenLock_ == nullptr) { // reset ipc identity std::string identity = IPCSkeleton::ResetCallingIdentity(); node->keepScreenLock_ = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock(node->GetWindowName(), PowerMgr::RunningLockType::RUNNINGLOCK_SCREEN); // set ipc identity to raw IPCSkeleton::SetCallingIdentity(identity); } if (node->keepScreenLock_ == nullptr) { return; } WLOGFI("handle keep screen on: [%{public}s, %{public}d]", node->GetWindowName().c_str(), requireLock); ErrCode res; // reset ipc identity std::string identity = IPCSkeleton::ResetCallingIdentity(); if (requireLock) { res = node->keepScreenLock_->Lock(); } else { res = node->keepScreenLock_->UnLock(); } // set ipc identity to raw IPCSkeleton::SetCallingIdentity(identity); if (res != ERR_OK) { WLOGFE("handle keep screen running lock failed: [operation: %{public}d, err: %{public}d]", requireLock, res); } } bool WindowNodeContainer::IsAboveSystemBarNode(sptr node) const { int32_t curPriority = zorderPolicy_->GetWindowPriority(node->GetWindowType()); if ((curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_STATUS_BAR)) && (curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_NAVIGATION_BAR))) { return true; } return false; } bool WindowNodeContainer::IsFullImmersiveNode(sptr node) const { auto mode = node->GetWindowMode(); auto flags = node->GetWindowFlags(); return mode == WindowMode::WINDOW_MODE_FULLSCREEN && !(flags & static_cast(WindowFlag::WINDOW_FLAG_NEED_AVOID)); } bool WindowNodeContainer::IsSplitImmersiveNode(sptr node) const { auto type = node->GetWindowType(); return node->IsSplitMode() || type == WindowType::WINDOW_TYPE_DOCK_SLICE; } std::unordered_map WindowNodeContainer::GetExpectImmersiveProperty() const { std::unordered_map sysBarPropMap { { WindowType::WINDOW_TYPE_STATUS_BAR, SystemBarProperty() }, { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarProperty() }, }; std::vector> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ }; for (auto& node : rootNodes) { for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); ++iter) { auto& sysBarPropMapNode = (*iter)->GetSystemBarProperty(); if (IsAboveSystemBarNode(*iter)) { continue; } if (IsFullImmersiveNode(*iter)) { WLOGFI("Top immersive window id: %{public}d. Use full immersive prop", (*iter)->GetWindowId()); for (auto it : sysBarPropMap) { sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second; } return sysBarPropMap; } else if (IsSplitImmersiveNode(*iter)) { WLOGFI("Top split window id: %{public}d. Use split immersive prop", (*iter)->GetWindowId()); for (auto it : sysBarPropMap) { sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second; sysBarPropMap[it.first].enable_ = false; } return sysBarPropMap; } } } WLOGFI("No immersive window on top. Use default systembar Property"); return sysBarPropMap; } void WindowNodeContainer::NotifyIfSystemBarTintChanged(DisplayId displayId) { WM_FUNCTION_TRACE(); auto expectSystemBarProp = GetExpectImmersiveProperty(); SystemBarRegionTints tints; SysBarTintMap& sysBarTintMap = sysBarTintMaps_[displayId]; for (auto it : sysBarTintMap) { auto expectProp = expectSystemBarProp.find(it.first)->second; if (it.second.prop_ == expectProp) { continue; } WLOGFI("System bar prop update, Type: %{public}d, Visible: %{public}d, Color: %{public}x | %{public}x", static_cast(it.first), expectProp.enable_, expectProp.backgroundColor_, expectProp.contentColor_); sysBarTintMap[it.first].prop_ = expectProp; sysBarTintMap[it.first].type_ = it.first; tints.emplace_back(sysBarTintMap[it.first]); } WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); } void WindowNodeContainer::NotifyIfSystemBarRegionChanged(DisplayId displayId) { WM_FUNCTION_TRACE(); SystemBarRegionTints tints; SysBarTintMap& sysBarTintMap = sysBarTintMaps_[displayId]; SysBarNodeMap& sysBarNodeMap = sysBarNodeMaps_[displayId]; for (auto it : sysBarTintMap) { // split screen mode not support yet auto sysNode = sysBarNodeMap[it.first]; if (sysNode == nullptr || it.second.region_ == sysNode->GetWindowRect()) { continue; } const Rect& newRegion = sysNode->GetWindowRect(); sysBarTintMap[it.first].region_ = newRegion; sysBarTintMap[it.first].type_ = it.first; tints.emplace_back(sysBarTintMap[it.first]); WLOGFI("system bar region update, type: %{public}d" \ "region: [%{public}d, %{public}d, %{public}d, %{public}d]", static_cast(it.first), newRegion.posX_, newRegion.posY_, newRegion.width_, newRegion.height_); } WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); } void WindowNodeContainer::NotifySystemBarDismiss(sptr& node) { WM_FUNCTION_TRACE(); if (node == nullptr) { WLOGE("could not find window"); return; } SystemBarRegionTints tints; auto& sysBarPropMapNode = node->GetSystemBarProperty(); SysBarTintMap& sysBarTintMap = sysBarTintMaps_[node->GetDisplayId()]; for (auto it : sysBarPropMapNode) { it.second.enable_ = false; node->SetSystemBarProperty(it.first, it.second); WLOGFI("set system bar enable to false, id: %{public}u, type: %{public}d", node->GetWindowId(), static_cast(it.first)); if (sysBarTintMap[it.first].prop_.enable_) { sysBarTintMap[it.first].prop_.enable_ = false; tints.emplace_back(sysBarTintMap[it.first]); WLOGFI("notify system bar dismiss, type: %{public}d", static_cast(it.first)); } } WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(node->GetDisplayId(), tints); } void WindowNodeContainer::NotifySystemBarTints(std::vector displayIdVec) { WM_FUNCTION_TRACE(); if (displayIdVec.size() != sysBarTintMaps_.size()) { WLOGE("the number of display is error"); } for (auto displayId : displayIdVec) { SystemBarRegionTints tints; SysBarTintMap& sysBarTintMap = sysBarTintMaps_[displayId]; for (auto it : sysBarTintMap) { WLOGFI("system bar cur notify, type: %{public}d, " \ "visible: %{public}d, color: %{public}x | %{public}x, " \ "region: [%{public}d, %{public}d, %{public}d, %{public}d]", static_cast(it.first), sysBarTintMap[it.first].prop_.enable_, sysBarTintMap[it.first].prop_.backgroundColor_, sysBarTintMap[it.first].prop_.contentColor_, sysBarTintMap[it.first].region_.posX_, sysBarTintMap[it.first].region_.posY_, sysBarTintMap[it.first].region_.width_, sysBarTintMap[it.first].region_.height_); tints.push_back(sysBarTintMap[it.first]); } WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints); } } bool WindowNodeContainer::IsTopWindow(uint32_t windowId, sptr& rootNode) const { if (rootNode->children_.empty()) { WLOGFE("root does not have any node"); return false; } auto node = *(rootNode->children_.rbegin()); if (node == nullptr) { WLOGFE("window tree does not have any node"); return false; } for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); iter++) { if ((*iter)->priority_ > 0) { return (*iter)->GetWindowId() == windowId; } else { break; } } return node->GetWindowId() == windowId; } void WindowNodeContainer::RaiseOrderedWindowToTop(std::vector>& orderedNodes, std::vector>& windowNodes) { for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end();) { uint32_t wid = (*iter)->GetWindowId(); auto orderedIter = std::find_if(orderedNodes.begin(), orderedNodes.end(), [wid] (sptr orderedNode) { return orderedNode->GetWindowId() == wid; }); if (orderedIter != orderedNodes.end()) { iter = windowNodes.erase(iter); } else { iter++; } } for (auto iter = orderedNodes.begin(); iter != orderedNodes.end(); iter++) { UpdateWindowTree(*iter); } return; } void WindowNodeContainer::RaiseWindowToTop(uint32_t windowId, std::vector>& windowNodes) { auto iter = std::find_if(windowNodes.begin(), windowNodes.end(), [windowId](sptr node) { return node->GetWindowId() == windowId; }); // raise app node window to top if (iter != windowNodes.end()) { sptr node = *iter; windowNodes.erase(iter); UpdateWindowTree(node); WLOGFI("raise window to top %{public}u", node->GetWindowId()); } } void WindowNodeContainer::NotifyAccessibilityWindowInfo(const sptr& node, WindowUpdateType type) const { if (node == nullptr) { WLOGFE("window node is null"); return; } bool isNeedNotify = false; switch (type) { case WindowUpdateType::WINDOW_UPDATE_ADDED: if (node->currentVisibility_) { isNeedNotify = true; } break; case WindowUpdateType::WINDOW_UPDATE_FOCUSED: if (node->GetWindowId() == focusedWindow_) { isNeedNotify = true; } break; case WindowUpdateType::WINDOW_UPDATE_REMOVED: isNeedNotify = true; break; default: break; } if (isNeedNotify) { std::vector> windowList; GetWindowList(windowList); sptr windowInfo = new (std::nothrow) WindowInfo(); sptr accessibilityWindowInfo = new (std::nothrow) AccessibilityWindowInfo(); if (windowInfo != nullptr && accessibilityWindowInfo != nullptr) { windowInfo->wid_ = static_cast(node->GetWindowId()); windowInfo->windowRect_ = node->GetWindowRect(); windowInfo->focused_ = node->GetWindowId() == focusedWindow_; windowInfo->displayId_ = node->GetDisplayId(); windowInfo->mode_ = node->GetWindowMode(); windowInfo->type_ = node->GetWindowType(); accessibilityWindowInfo->currentWindowInfo_ = windowInfo; accessibilityWindowInfo->windowList_ = windowList; WindowManagerAgentController::GetInstance().NotifyAccessibilityWindowInfo(accessibilityWindowInfo, type); } } } void WindowNodeContainer::GetWindowList(std::vector>& windowList) const { std::vector> windowNodes; TraverseContainer(windowNodes); for (auto node : windowNodes) { sptr windowInfo = new WindowInfo(); windowInfo->wid_ = static_cast(node->GetWindowId()); windowInfo->windowRect_ = node->GetWindowRect(); windowInfo->focused_ = node->GetWindowId() == focusedWindow_; windowInfo->displayId_ = node->GetDisplayId(); windowInfo->mode_ = node->GetWindowMode(); windowInfo->type_ = node->GetWindowType(); windowList.emplace_back(windowInfo); } } void WindowNodeContainer::TraverseContainer(std::vector>& windowNodes) const { for (auto& node : belowAppWindowNode_->children_) { TraverseWindowNode(node, windowNodes); } for (auto& node : appWindowNode_->children_) { TraverseWindowNode(node, windowNodes); } for (auto& node : aboveAppWindowNode_->children_) { TraverseWindowNode(node, windowNodes); } std::reverse(windowNodes.begin(), windowNodes.end()); } void WindowNodeContainer::TraverseWindowNode(sptr& node, std::vector>& windowNodes) const { if (node == nullptr) { return; } auto iter = node->children_.begin(); for (; iter < node->children_.end(); ++iter) { if ((*iter)->priority_ < 0) { windowNodes.emplace_back(*iter); } else { break; } } windowNodes.emplace_back(node); for (; iter < node->children_.end(); ++iter) { windowNodes.emplace_back(*iter); } } std::vector WindowNodeContainer::GetAvoidAreaByType(AvoidAreaType avoidAreaType, DisplayId displayId) { return avoidController_->GetAvoidAreaByType(avoidAreaType, displayId); } void WindowNodeContainer::OnAvoidAreaChange(const std::vector& avoidArea, DisplayId displayId) { for (auto& node : appWindowNode_->children_) { if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && node->GetWindowToken() != nullptr) { // notify client node->GetWindowToken()->UpdateAvoidArea(avoidArea); } } } void WindowNodeContainer::DumpScreenWindowTree() { WLOGFI("-------- dump window info begin---------"); WLOGFI("WindowName DisplayId WinId Type Mode Flag ZOrd Orientation [ x y w h]"); uint32_t zOrder = zOrder_; WindowNodeOperationFunc func = [&zOrder](sptr node) { Rect rect = node->GetWindowRect(); const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ? node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH); WLOGI("DumpScreenWindowTree: %{public}10s %{public}9" PRIu64" %{public}5u %{public}4u %{public}4u %{public}4u " "%{public}4u %{public}11u [%{public}4d %{public}4d %{public}4u %{public}4u]", windowName.c_str(), node->GetDisplayId(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(), node->GetWindowFlags(), --zOrder, static_cast(node->GetRequestedOrientation()), rect.posX_, rect.posY_, rect.width_, rect.height_); return false; }; TraverseWindowTree(func, true); WLOGFI("-------- dump window info end ---------"); } uint64_t WindowNodeContainer::GetScreenId(DisplayId displayId) const { return DisplayManagerServiceInner::GetInstance().GetRSScreenId(displayId); } Rect WindowNodeContainer::GetDisplayRect(DisplayId displayId) const { return const_cast(this)->displayRectMap_[displayId]; } bool WindowNodeContainer::isVerticalDisplay(DisplayId displayId) const { return const_cast(this)->displayRectMap_[displayId].width_ < const_cast(this)->displayRectMap_[displayId].height_; } void WindowNodeContainer::ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason) { switch (reason) { case WindowStateChangeReason::KEYGUARD: { int32_t topPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD); TraverseAndUpdateWindowState(state, topPriority); break; } default: return; } } void WindowNodeContainer::TraverseAndUpdateWindowState(WindowState state, int32_t topPriority) { std::vector> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ }; for (auto& node : rootNodes) { UpdateWindowState(node, topPriority, state); } } void WindowNodeContainer::UpdateWindowState(sptr node, int32_t topPriority, WindowState state) { if (node == nullptr) { return; } if (node->parent_ != nullptr && node->currentVisibility_) { if (node->priority_ < topPriority && !(node->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) { if (node->GetWindowToken()) { node->GetWindowToken()->UpdateWindowState(state); } HandleKeepScreenOn(node, state); } } for (auto& childNode : node->children_) { UpdateWindowState(childNode, topPriority, state); } } void WindowNodeContainer::HandleKeepScreenOn(const sptr& node, WindowState state) { if (node == nullptr) { WLOGFE("window is invalid"); return; } if (state == WindowState::STATE_FROZEN) { HandleKeepScreenOn(node, false); } else if (state == WindowState::STATE_UNFROZEN) { HandleKeepScreenOn(node, node->IsKeepScreenOn()); } else { // do nothing } } sptr WindowNodeContainer::FindDividerNode() const { for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end(); iter++) { if ((*iter)->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { return *iter; } } return nullptr; } void WindowNodeContainer::RaiseSplitRelatedWindowToTop(sptr& node) { if (node == nullptr) { return; } std::vector> orderedPair = windowPair_->GetOrderedPair(node); RaiseOrderedWindowToTop(orderedPair, appWindowNode_->children_); AssignZOrder(); return; } WMError WindowNodeContainer::RaiseZOrderForAppWindow(sptr& node, sptr& parentNode) { if (node == nullptr) { return WMError::WM_ERROR_NULLPTR; } if (IsTopWindow(node->GetWindowId(), appWindowNode_) || IsTopWindow(node->GetWindowId(), aboveAppWindowNode_)) { WLOGFI("it is already top app window, id: %{public}u", node->GetWindowId()); return WMError::WM_ERROR_INVALID_TYPE; } if (WindowHelper::IsSubWindow(node->GetWindowType())) { if (parentNode == nullptr) { WLOGFE("window type is invalid"); return WMError::WM_ERROR_NULLPTR; } RaiseWindowToTop(node->GetWindowId(), parentNode->children_); // raise itself if (parentNode->IsSplitMode()) { RaiseSplitRelatedWindowToTop(parentNode); } else { RaiseWindowToTop(node->GetParentId(), parentNode->parent_->children_); // raise parent window } } else if (WindowHelper::IsMainWindow(node->GetWindowType())) { if (node->IsSplitMode()) { RaiseSplitRelatedWindowToTop(node); } else { RaiseWindowToTop(node->GetWindowId(), node->parent_->children_); } } else { // do nothing } AssignZOrder(); WLOGFI("RaiseZOrderForAppWindow finished"); DumpScreenWindowTree(); return WMError::WM_OK; } sptr WindowNodeContainer::GetNextFocusableWindow(uint32_t windowId) const { sptr nextFocusableWindow; bool previousFocusedWindowFound = false; WindowNodeOperationFunc func = [windowId, &nextFocusableWindow, &previousFocusedWindowFound]( sptr node) { if (previousFocusedWindowFound && node->GetWindowProperty()->GetFocusable()) { nextFocusableWindow = node; return true; } if (node->GetWindowId() == windowId) { previousFocusedWindowFound = true; } return false; }; TraverseWindowTree(func, true); return nextFocusableWindow; } sptr WindowNodeContainer::GetNextActiveWindow(uint32_t windowId) const { auto currentNode = FindWindowNodeById(windowId); if (currentNode == nullptr) { WLOGFE("cannot find window id: %{public}u by tree", windowId); return nullptr; } WLOGFI("current window: [%{public}u, %{public}u]", windowId, static_cast(currentNode->GetWindowType())); if (WindowHelper::IsSystemWindow(currentNode->GetWindowType())) { for (auto& node : appWindowNode_->children_) { if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { continue; } return node; } for (auto& node : belowAppWindowNode_->children_) { if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) { return node; } } } else if (WindowHelper::IsAppWindow(currentNode->GetWindowType())) { std::vector> windowNodes; TraverseContainer(windowNodes); auto iter = std::find_if(windowNodes.begin(), windowNodes.end(), [windowId](sptr& node) { return node->GetWindowId() == windowId; }); if (iter == windowNodes.end()) { WLOGFE("could not find this window"); return nullptr; } int index = std::distance(windowNodes.begin(), iter); for (size_t i = static_cast(index) + 1; i < windowNodes.size(); i++) { if (windowNodes[i]->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { continue; } return windowNodes[i]; } } else { // do nothing } WLOGFE("could not get next active window"); return nullptr; } void WindowNodeContainer::MinimizeAllAppWindows(DisplayId displayId) { WMError ret = MinimizeAppNodeExceptOptions(true); SwitchLayoutPolicy(WindowLayoutMode::CASCADE, displayId); if (ret != WMError::WM_OK) { WLOGFE("Minimize all app window failed"); } return; } void WindowNodeContainer::MinimizeOldestAppWindow() { for (auto& appNode : appWindowNode_->children_) { if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { WLOGFI("minimize window, windowId:%{public}u", appNode->GetWindowId()); MinimizeWindowFromAbility(appNode, true); return; } } for (auto& appNode : aboveAppWindowNode_->children_) { if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { WLOGFI("minimize window, windowId:%{public}u", appNode->GetWindowId()); MinimizeWindowFromAbility(appNode, true); return; } } WLOGFI("no window needs to minimize"); } void WindowNodeContainer::MinimizeWindowFromAbility(const sptr& node, bool fromUser) { if (node->abilityToken_ == nullptr) { WLOGFW("Target abilityToken is nullptr, windowId:%{public}u", node->GetWindowId()); return; } WLOGFI("minimize window fromUser:%{public}d, isMinimizedByOther:%{public}d", fromUser, isMinimizedByOther_); if (!fromUser && !isMinimizedByOther_) { return; } AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(node->abilityToken_, fromUser); } WMError WindowNodeContainer::MinimizeAppNodeExceptOptions(bool fromUser, const std::vector &exceptionalIds, const std::vector &exceptionalModes) { if (appWindowNode_->children_.empty()) { return WMError::WM_OK; } for (auto& appNode : appWindowNode_->children_) { // exclude exceptional window if (std::find(exceptionalIds.begin(), exceptionalIds.end(), appNode->GetWindowId()) != exceptionalIds.end() || std::find(exceptionalModes.begin(), exceptionalModes.end(), appNode->GetWindowMode()) != exceptionalModes.end() || appNode->GetWindowType() != WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) { continue; } // minimize window WLOGFI("minimize window, windowId:%{public}u", appNode->GetWindowId()); MinimizeWindowFromAbility(appNode, fromUser); } return WMError::WM_OK; } void WindowNodeContainer::ResetLayoutPolicy() { layoutPolicy_->Reset(); } WMError WindowNodeContainer::SwitchLayoutPolicy(WindowLayoutMode dstMode, DisplayId displayId, bool reorder) { WLOGFI("SwitchLayoutPolicy src: %{public}d dst: %{public}d, reorder: %{public}d, displayId: %{public}" PRIu64"", static_cast(layoutMode_), static_cast(dstMode), static_cast(reorder), displayId); if (dstMode < WindowLayoutMode::BASE || dstMode >= WindowLayoutMode::END) { WLOGFE("invalid layout mode"); return WMError::WM_ERROR_INVALID_PARAM; } if (layoutMode_ != dstMode) { if (layoutMode_ == WindowLayoutMode::CASCADE) { layoutPolicy_->Reset(); windowPair_->Clear(); } layoutMode_ = dstMode; layoutPolicy_->Clean(); layoutPolicy_ = layoutPolicys_[dstMode]; layoutPolicy_->Launch(); DumpScreenWindowTree(); } else { WLOGFI("Current layout mode is already: %{public}d", static_cast(dstMode)); } if (reorder) { windowPair_->Clear(); layoutPolicy_->Reorder(); DumpScreenWindowTree(); } NotifyIfSystemBarTintChanged(displayId); return WMError::WM_OK; } void WindowNodeContainer::RaiseInputMethodWindowPriorityIfNeeded(const sptr& node) const { if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) { return; } auto iter = std::find_if(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), [](sptr node) { return node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD; }); if (iter != aboveAppWindowNode_->children_.end()) { WLOGFI("raise input method float window priority."); node->priority_ = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1; } } void WindowNodeContainer::ReZOrderShowWhenLockedWindows(const sptr& node, bool up) { WLOGFI("Keyguard change %{public}u, re-zorder showWhenLocked window", up); std::vector> needReZOrderNodes; auto& srcRoot = up ? appWindowNode_ : aboveAppWindowNode_; auto& dstRoot = up ? aboveAppWindowNode_ : appWindowNode_; auto dstPriority = up ? zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1 : zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW); for (auto iter = srcRoot->children_.begin(); iter != srcRoot->children_.end();) { if ((*iter)->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) { needReZOrderNodes.emplace_back(*iter); iter = srcRoot->children_.erase(iter); } else { iter++; } } for (auto& needReZOrderNode : needReZOrderNodes) { needReZOrderNode->priority_ = dstPriority; needReZOrderNode->parent_ = dstRoot; auto parentNode = needReZOrderNode->parent_; auto position = parentNode->children_.end(); for (auto iter = parentNode->children_.begin(); iter < parentNode->children_.end(); ++iter) { if ((*iter)->priority_ > needReZOrderNode->priority_) { position = iter; break; } } parentNode->children_.insert(position, needReZOrderNode); WLOGFI("ShowWhenLocked window %{public}u re-zorder when keyguard change %{public}u", needReZOrderNode->GetWindowId(), up); } } void WindowNodeContainer::RaiseShowWhenLockedWindowIfNeeded(const sptr& node) { // if keyguard window show, raise show when locked windows if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { ReZOrderShowWhenLockedWindows(node, true); return; } // if show when locked window show, raise itself when exist keyguard if (!(node->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) { return; } auto iter = std::find_if(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), [](sptr node) { return node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD; }); if (iter != aboveAppWindowNode_->children_.end()) { WLOGFI("ShowWhenLocked window %{public}u raise itself", node->GetWindowId()); node->priority_ = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1; node->parent_ = aboveAppWindowNode_; } } void WindowNodeContainer::DropShowWhenLockedWindowIfNeeded(const sptr& node) { // if keyguard window hide, drop show when locked windows if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) { ReZOrderShowWhenLockedWindows(node, false); AssignZOrder(); } } void WindowNodeContainer::MoveWindowNodes(DisplayId displayId, std::vector& windowIds) { WLOGFI("Move window nodes when destroy display"); } void WindowNodeContainer::ProcessDisplayCreate(DisplayId displayId, const Rect& displayRect) { avoidController_->UpdateAvoidNodesMap(displayId, true); InitSysBarMapForDisplay(displayId); InitWindowNodeMapForDisplay(displayId); displayRectMap_.insert(std::make_pair(displayId, displayRect)); layoutPolicy_->UpdateDisplayInfo(displayRectMap_); } void WindowNodeContainer::ProcessDisplayDestroy(DisplayId displayId, std::vector& windowIds) { WLOGFI("Process display destroy"); } void WindowNodeContainer::ProcessDisplayChange(DisplayId displayId, const Rect& displayRect) { displayRectMap_[displayId] = displayRect; layoutPolicy_->UpdateDisplayInfo(displayRectMap_); } void WindowNodeContainer::TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom) const { std::vector> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ }; if (isFromTopToBottom) { std::reverse(rootNodes.begin(), rootNodes.end()); } for (auto& node : rootNodes) { if (isFromTopToBottom) { for (auto iter = node->children_.rbegin(); iter != node->children_.rend(); ++iter) { if (TraverseFromTopToBottom(*iter, func)) { return; } } } else { for (auto iter = node->children_.begin(); iter != node->children_.end(); ++iter) { if (TraverseFromBottomToTop(*iter, func)) { return; } } } } } bool WindowNodeContainer::TraverseFromTopToBottom(sptr node, const WindowNodeOperationFunc& func) const { if (node == nullptr) { return false; } auto iterBegin = node->children_.rbegin(); for (; iterBegin != node->children_.rend(); ++iterBegin) { if ((*iterBegin)->priority_ <= 0) { break; } if (func(*iterBegin)) { return true; } } if (func(node)) { return true; } for (; iterBegin != node->children_.rend(); ++iterBegin) { if (func(*iterBegin)) { return true; } } return false; } bool WindowNodeContainer::TraverseFromBottomToTop(sptr node, const WindowNodeOperationFunc& func) const { if (node == nullptr) { return false; } auto iterBegin = node->children_.begin(); for (; iterBegin != node->children_.end(); ++iterBegin) { if ((*iterBegin)->priority_ >= 0) { break; } if (func(*iterBegin)) { return true; } } if (func(node)) { return true; } for (; iterBegin != node->children_.end(); ++iterBegin) { if (func(*iterBegin)) { return true; } } return false; } void WindowNodeContainer::UpdateWindowVisibilityInfos(std::vector>& infos) { auto emptyVector = std::vector(); currentCoveredArea_.swap(emptyVector); WindowNodeOperationFunc func = [this, &infos](sptr node) { if (node == nullptr) { return false; } Rect layoutRect = node->GetWindowRect(); const Rect& displayRect = displayRectMap_[node->GetDisplayId()]; int32_t nodeX = std::max(0, layoutRect.posX_); int32_t nodeY = std::max(0, layoutRect.posY_); int32_t nodeXEnd = std::min(displayRect.posX_ + static_cast(displayRect.width_), layoutRect.posX_ + static_cast(layoutRect.width_)); int32_t nodeYEnd = std::min(displayRect.posY_ + static_cast(displayRect.height_), layoutRect.posY_ + static_cast(layoutRect.height_)); Rect rectInDisplay = {nodeX, nodeY, static_cast(nodeXEnd - nodeX), static_cast(nodeYEnd - nodeY)}; bool isCovered = false; for (auto& rect : currentCoveredArea_) { if (rectInDisplay.IsInsideOf(rect)) { isCovered = true; WLOGD("UpdateWindowVisibilityInfos: find covered window:%{public}u", node->GetWindowId()); break; } } if (!isCovered) { currentCoveredArea_.emplace_back(rectInDisplay); } if (isCovered != node->isCovered_) { node->isCovered_ = isCovered; infos.emplace_back(new WindowVisibilityInfo(node->GetWindowId(), node->GetCallingPid(), node->GetCallingUid(), !isCovered)); WLOGD("UpdateWindowVisibilityInfos: covered status changed window:%{public}u, covered:%{public}d", node->GetWindowId(), isCovered); } return false; }; TraverseWindowTree(func, true); WindowManagerAgentController::GetInstance().UpdateWindowVisibilityInfo(infos); } float WindowNodeContainer::GetVirtualPixelRatio(DisplayId displayId) const { return layoutPolicy_->GetVirtualPixelRatio(displayId); } bool WindowNodeContainer::ReadIsWindowAnimationEnabledProperty() { if (access(DISABLE_WINDOW_ANIMATION_PATH, F_OK) == 0) { return false; } return true; } WMError WindowNodeContainer::SetWindowMode(sptr& node, WindowMode dstMode) { if (node == nullptr) { WLOGFE("could not find window"); return WMError::WM_ERROR_NULLPTR; } WindowMode srcMode = node->GetWindowMode(); if (srcMode == dstMode) { return WMError::WM_OK; } WMError res = WMError::WM_OK; if ((srcMode == WindowMode::WINDOW_MODE_FULLSCREEN) && (dstMode == WindowMode::WINDOW_MODE_FLOATING)) { node->SetWindowSizeChangeReason(WindowSizeChangeReason::RECOVER); } else if (dstMode == WindowMode::WINDOW_MODE_FULLSCREEN) { node->SetWindowSizeChangeReason(WindowSizeChangeReason::MAXIMIZE); } else { node->SetWindowSizeChangeReason(WindowSizeChangeReason::RESIZE); } node->SetWindowMode(dstMode); windowPair_->UpdateIfSplitRelated(node); if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && WindowHelper::IsAppWindow(node->GetWindowType())) { // minimize other app window res = MinimizeStructuredAppWindowsExceptSelf(node); if (res != WMError::WM_OK) { return res; } } if (node->GetWindowToken() != nullptr) { node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode()); } res = UpdateWindowNode(node, WindowUpdateReason::UPDATE_MODE); if (res != WMError::WM_OK) { WLOGFE("Set window mode failed, update node failed"); return res; } return WMError::WM_OK; } void WindowNodeContainer::SetMinimizedByOther(bool isMinimizedByOther) { isMinimizedByOther_ = isMinimizedByOther; } void WindowNodeContainer::GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config) { auto displayRect = displayRectMap_[displayId]; hotZones.fullscreen_.width_ = displayRect.width_; hotZones.fullscreen_.height_ = config.fullscreenRange_; hotZones.primary_.width_ = config.primaryRange_; hotZones.primary_.height_ = displayRect.height_; hotZones.secondary_.posX_ = static_cast(displayRect.width_) - config.secondaryRange_; hotZones.secondary_.width_ = config.secondaryRange_; hotZones.secondary_.height_ = displayRect.height_; } void WindowNodeContainer::UpdateVirtualPixelRatio(DisplayId displayId, float virtualPixelRatio) { layoutPolicy_->SetVirtualPixelRatioChangedFlag(true); layoutPolicy_->LayoutWindowTree(displayId); layoutPolicy_->SetVirtualPixelRatioChangedFlag(false); } } // namespace Rosen } // namespace OHOS