分屏重构

Signed-off-by: xingyanan <xingyanan2@huawei.com>
Change-Id: Ia5446fb6134c98c8dcab9a7b29108b9bd062554d
Signed-off-by: xingyanan <xingyanan2@huawei.com>
This commit is contained in:
xingyanan
2022-04-20 16:25:01 +08:00
parent ae5a30c6ba
commit f743756bb6
11 changed files with 756 additions and 266 deletions
+1
View File
@@ -67,6 +67,7 @@ ohos_shared_library("libwms") {
"src/window_manager_stub.cpp",
"src/window_node.cpp",
"src/window_node_container.cpp",
"src/window_pair.cpp",
"src/window_root.cpp",
"src/window_snapshot/snapshot_controller.cpp",
"src/window_snapshot/snapshot_proxy.cpp",
@@ -40,6 +40,7 @@ public:
void AddWindowNode(sptr<WindowNode>& node) override;
void UpdateWindowNode(sptr<WindowNode>& node, bool isAddWindow = false) override;
void UpdateLayoutRect(sptr<WindowNode>& node) override;
void RemoveWindowNode(sptr<WindowNode>& node) override;
private:
// Rects for split screen
+5 -12
View File
@@ -24,6 +24,7 @@
#include "window_zorder_policy.h"
#include "wm_common.h"
#include "wm_common_inner.h"
#include "window_pair.h"
namespace OHOS {
namespace Rosen {
@@ -70,9 +71,8 @@ public:
void NotifySystemBarDismiss(sptr<WindowNode>& node);
WMError MinimizeAppNodeExceptOptions(bool fromUser, const std::vector<uint32_t> &exceptionalIds = {},
const std::vector<WindowMode> &exceptionalModes = {});
WMError EnterSplitWindowMode(sptr<WindowNode>& node);
WMError ExitSplitWindowMode(sptr<WindowNode>& node);
WMError SwitchLayoutPolicy(WindowLayoutMode mode, bool reorder = false);
WMError SetWindowMode(sptr<WindowNode>& node, WindowMode dstMode);
void RaiseSplitRelatedWindowToTop(sptr<WindowNode>& node);
void MoveWindowNode(sptr<WindowNodeContainer>& container);
float GetVirtualPixelRatio() const;
@@ -90,9 +90,6 @@ private:
void UpdateWindowTree(sptr<WindowNode>& node);
bool UpdateRSTree(sptr<WindowNode>& node, bool isAdd);
void SendSplitScreenEvent(sptr<WindowNode>& node);
sptr<WindowNode> FindSplitPairNode(sptr<WindowNode>& node) const;
WMError UpdateWindowPairInfo(sptr<WindowNode>& triggerNode, sptr<WindowNode>& pairNode);
void NotifyIfSystemBarTintChanged();
void NotifyIfSystemBarRegionChanged();
void TraverseAndUpdateWindowState(WindowState state, int32_t topPriority);
@@ -111,7 +108,8 @@ private:
void RcoveryScreenDefaultOrientationIfNeed();
// cannot determine in case of a window covered by union of several windows or with transparent value
void UpdateWindowVisibilityInfos(std::vector<sptr<WindowVisibilityInfo>>& infos);
void RaiseOrderedWindowToTop(std::vector<uint32_t> orderedIds, std::vector<sptr<WindowNode>>& windowNodes);
void RaiseOrderedWindowToTop(std::vector<sptr<WindowNode>>& orderedNodes,
std::vector<sptr<WindowNode>>& windowNodes);
static bool ReadIsWindowAnimationEnabledProperty();
sptr<AvoidAreaController> avoidController_;
@@ -140,12 +138,7 @@ private:
float displayBrightness_ = UNDEFINED_BRIGHTNESS; // UNDEFINED_BRIGHTNESS means system default brightness
uint32_t brightnessWindow_ = INVALID_WINDOW_ID;
void DumpScreenWindowTree();
struct WindowPairInfo {
sptr<WindowNode> pairNode_;
float splitRatio_;
};
std::unordered_map<uint32_t, WindowPairInfo> pairedWindowMap_;
sptr<WindowPair> windowPair_;
void RaiseInputMethodWindowPriorityIfNeeded(const sptr<WindowNode>& node) const;
void RaiseShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node);
void ReZOrderShowWhenLockedWindows(const sptr<WindowNode>& node, bool up);
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright (c) 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.
*/
#ifndef OHOS_ROSEN_WINDOW_PAIR_H
#define OHOS_ROSEN_WINDOW_PAIR_H
#include <refbase.h>
#include "window_inner_manager.h"
#include "window_node.h"
#include "wm_common_inner.h"
#include "wm_common.h"
namespace OHOS {
namespace Rosen {
/**
* Enumerates the status of window pair.
*/
enum class WindowPairStatus : uint32_t {
STATUS_EMPTY,
STATUS_SINGLE_PRIMARY,
STATUS_SINGLE_SECONDARY,
STATUS_PAIRING,
STATUS_PAIRED_DONE
};
/**
* Enumerates the message of split event.
*/
enum class SplitBroadcastMsg : uint32_t {
MSG_NONE,
MSG_START_PRIMARY,
MSG_START_SECONDARY,
MSG_START_DIVIDER
};
class WindowPair : public RefBase {
public:
/**
* Constructor used to create an empty WindowPair instance.
*
* @param displayId the disply of window pair
* @param appNode the window root of app window
*/
WindowPair(const DisplayId& displayId, sptr<WindowNode>& appNode);
/**
* Deconstructor used to deconstruct.
*
*/
~WindowPair();
/**
* Clear window pair.
*
*/
void Clear();
/**
* Set split ratio.
*
* @param ratio split ratio
*/
void SetSplitRatio(float ratio);
/**
* Get split ratio.
*
* @return split ratio
*/
float GetSplitRatio() const;
/**
* Get whether the window pair is paired..
*
* @return the pair state of window pair
*/
bool IsPaired() const;
/**
* Handle changes in the state of the window pair
*
* @param node trigger window node
*/
void UpdateIfSplitRelated(sptr<WindowNode>& node);
/**
* Handle remove window from pair.
*
* @param node target node
*/
void HandleRemoveWindow(sptr<WindowNode>& node);
/**
* Find window node from window pair.
*
* @param node target window node
* @return window node
*/
sptr<WindowNode> Find(sptr<WindowNode>& node);
/**
* Get primary window node.
*
* @return primary window node
*/
sptr<WindowNode> GetPrimaryWindow() const;
/**
* Get secondary window node.
*
* @return secondary window node
*/
sptr<WindowNode> GetSecondaryWindow() const;
/**
* Get divider window node.
*
* @return divider window node
*/
sptr<WindowNode> GetDividerWindow() const;
/**
* Get pair status.
*
* @return the pair status of window pair
*/
WindowPairStatus GetPairStatus() const;
/**
* Get all window node form pair in Z order.
*
* @return the list window form pair
*/
std::vector<sptr<WindowNode>> GetOrderedPair(sptr<WindowNode>& node);
/**
* Get all window node form pair.
*
* @return the list window form pair
*/
std::vector<sptr<WindowNode>> GetPairedWindows();
private:
/**
* Gets whether the window is related to split window.
*
* @param node target node
* @return Whether target node is related to the split window
*/
bool IsSplitRelated(sptr<WindowNode>& node) const;
/**
* Replace paired window.
*
* @param node current node
*/
void Insert(sptr<WindowNode>& node);
/**
* Update paired window node
*
*/
void HandlePairedNodesChange();
/**
* Update pair status
*
*/
void UpdateWindowPairStatus();
/**
* Switch the position of two paired window.
*
*/
void SwitchPosition();
/**
* Dump the info of pair.
*
*/
void DumpPairInfo();
/**
* Send inner window message.
*
* @param cmd the message of inner window manager
* @param displayId the id of target display
*/
void SendInnerMessage(InnerWMCmd cmd, DisplayId displayId);
/**
* Find pairable window frome window trees.
*
* @param node the node waiting to be paired
* @return window node
*/
sptr<WindowNode> FindPairableWindow(sptr<WindowNode>& node);
/**
* Get pairable node from trees or send split broadcast.
*
* @param node the node waiting to be paired
* @return pairable node
*/
sptr<WindowNode> GetPairableWindow(sptr<WindowNode>& node);
/**
* Send brodcast message of split event.
*
* @param node trigger node
*/
void SendBroadcastMsg(sptr<WindowNode>& node);
private:
float ratio_ = DEFAULT_SPLIT_RATIO;
DisplayId displayId_;
sptr<WindowNode> appWindowNode_;
sptr<WindowNode> primary_;
sptr<WindowNode> secondary_;
sptr<WindowNode> divider_;
WindowPairStatus status_ = {WindowPairStatus::STATUS_EMPTY};
};
} // namespace Rosen
} // namespace OHOS
#endif // OHOS_ROSEN_WINDOW_PAIR_H
+1 -2
View File
@@ -51,8 +51,7 @@ public:
WMError RequestActiveWindow(uint32_t windowId);
WMError MinimizeStructuredAppWindowsExceptSelf(sptr<WindowNode>& node);
std::vector<Rect> GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType);
WMError EnterSplitWindowMode(sptr<WindowNode>& node);
WMError ExitSplitWindowMode(sptr<WindowNode>& node);
WMError SetWindowMode(sptr<WindowNode>& node, WindowMode dstMode);
std::shared_ptr<RSSurfaceNode> GetSurfaceNodeByAbilityToken(const sptr<IRemoteObject>& abilityToken) const;
WMError GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId);
void MinimizeAllAppWindows(DisplayId displayId);
+3 -40
View File
@@ -219,47 +219,10 @@ WMError WindowController::SetWindowMode(uint32_t windowId, WindowMode dstMode)
WLOGFE("could not find window");
return WMError::WM_ERROR_NULLPTR;
}
WindowMode srcMode = node->GetWindowMode();
if (srcMode == dstMode) {
return WMError::WM_OK;
WMError ret = windowRoot_->SetWindowMode(node, dstMode);
if (ret != WMError::WM_OK) {
return ret;
}
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);
}
if (WindowHelper::IsSplitWindowMode(srcMode)) {
// change split mode to other
res = windowRoot_->ExitSplitWindowMode(node);
node->SetWindowMode(dstMode);
} else if (!WindowHelper::IsSplitWindowMode(srcMode) && WindowHelper::IsSplitWindowMode(dstMode)) {
// change other mode to split
node->SetWindowMode(dstMode);
res = windowRoot_->EnterSplitWindowMode(node);
} else {
node->SetWindowMode(dstMode);
}
if (res != WMError::WM_OK) {
node->GetWindowProperty()->ResumeLastWindowMode();
return res;
}
if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN &&
WindowHelper::IsAppWindow(node->GetWindowType())) {
// minimize other app window
res = windowRoot_->MinimizeStructuredAppWindowsExceptSelf(node);
if (res != WMError::WM_OK) {
return res;
}
}
res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_MODE);
if (res != WMError::WM_OK) {
WLOGFE("Set window mode failed, update node failed");
return res;
}
node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
FlushWindowInfo(windowId);
return WMError::WM_OK;
}
+18 -1
View File
@@ -87,6 +87,21 @@ void WindowLayoutPolicyCascade::LayoutWindowTree()
WindowLayoutPolicy::LayoutWindowTree();
}
void WindowLayoutPolicyCascade::RemoveWindowNode(sptr<WindowNode>& node)
{
WM_FUNCTION_TRACE();
auto type = node->GetWindowType();
// affect other windows, trigger off global layout
if (avoidTypes_.find(type) != avoidTypes_.end()) {
LayoutWindowTree();
} else if (type == WindowType::WINDOW_TYPE_DOCK_SLICE) { // split screen mode
InitSplitRects();
LayoutWindowTree();
}
Rect reqRect = node->GetRequestRect();
node->GetWindowToken()->UpdateWindowRect(reqRect, node->GetDecoStatus(), WindowSizeChangeReason::HIDE);
}
void WindowLayoutPolicyCascade::UpdateWindowNode(sptr<WindowNode>& node, bool isAddWindow)
{
WM_FUNCTION_TRACE();
@@ -109,6 +124,8 @@ void WindowLayoutPolicyCascade::UpdateWindowNode(sptr<WindowNode>& node, bool is
}
}
LayoutWindowTree();
} else if (node->IsSplitMode()) {
LayoutWindowTree();
} else { // layout single window
LayoutWindowNode(node);
}
@@ -159,7 +176,7 @@ void WindowLayoutPolicyCascade::LimitMoveBounds(Rect& rect) const
void WindowLayoutPolicyCascade::InitCascadeRect()
{
constexpr uint32_t half = 2;
constexpr float ratio = 0.75; // 0.75: default height/width ratio
constexpr float ratio = 0.66; // 0.66: default height/width ratio
// calculate default H and w
uint32_t defaultW = static_cast<uint32_t>(displayRect_.width_ * ratio);
+1 -1
View File
@@ -272,4 +272,4 @@ void WindowLayoutPolicyTile::UpdateLayoutRect(sptr<WindowNode>& node)
}
}
} // Rosen
} // OHOS
} // OHOS
+55 -197
View File
@@ -53,6 +53,7 @@ WindowNodeContainer::WindowNodeContainer(DisplayId displayId, uint32_t width, ui
.width_ = width,
.height_ = height
};
windowPair_ = new WindowPair(displayId_, appWindowNode_);
layoutPolicys_[WindowLayoutMode::CASCADE] =
new WindowLayoutPolicyCascade(displayRect_, displayId_,
belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_);
@@ -118,14 +119,7 @@ WMError WindowNodeContainer::AddWindowNode(sptr<WindowNode>& node, sptr<WindowNo
}
}
node->parent_ = parentNode;
if (node->IsSplitMode()) {
WMError ret = EnterSplitWindowMode(node);
if (ret != WMError::WM_OK) {
WLOGFE("Add split window failed!");
return ret;
}
}
windowPair_->UpdateIfSplitRelated(node);
UpdateWindowTree(node);
if (node->IsSplitMode() || node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
RaiseSplitRelatedWindowToTop(node);
@@ -295,17 +289,9 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr<WindowNode>& node)
child->GetCallingUid(), false));
}
}
if (node->IsSplitMode()) {
WMError ret = ExitSplitWindowMode(node);
if (ret != WMError::WM_OK) {
WLOGFE("Remove split window failed!");
return ret;
}
}
UpdateRSTree(node, false);
layoutPolicy_->RemoveWindowNode(node);
windowPair_->HandleRemoveWindow(node);
if (WindowHelper::IsAvoidAreaWindow(node->GetWindowType())) {
avoidController_->AvoidControl(node, AvoidControlType::AVOID_NODE_REMOVE);
NotifyIfSystemBarRegionChanged();
@@ -706,23 +692,22 @@ bool WindowNodeContainer::IsTopWindow(uint32_t windowId, sptr<WindowNode>& rootN
return node->GetWindowId() == windowId;
}
void WindowNodeContainer::RaiseOrderedWindowToTop(std::vector<uint32_t> orderedIds,
void WindowNodeContainer::RaiseOrderedWindowToTop(std::vector<sptr<WindowNode>>& orderedNodes,
std::vector<sptr<WindowNode>>& windowNodes)
{
for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end();) {
uint32_t wid = (*iter)->GetWindowId();
auto idIter = std::find_if(orderedIds.begin(), orderedIds.end(),
[wid] (uint32_t id) { return id == wid; });
if (idIter != orderedIds.end()) {
orderedIds.erase(idIter);
sptr<WindowNode> node = *iter;
auto orderedIter = std::find_if(orderedNodes.begin(), orderedNodes.end(),
[wid] (sptr<WindowNode> orderedNode) { return orderedNode->GetWindowId() == wid; });
if (orderedIter != orderedNodes.end()) {
iter = windowNodes.erase(iter);
UpdateWindowTree(node);
WLOGFI("raise group window to top %{public}u", node->GetWindowId());
} else {
iter++;
}
}
for (auto iter = orderedNodes.begin(); iter != orderedNodes.end(); iter++) {
UpdateWindowTree(*iter);
}
return;
}
@@ -956,36 +941,8 @@ void WindowNodeContainer::RaiseSplitRelatedWindowToTop(sptr<WindowNode>& node)
if (node == nullptr) {
return;
}
if (!node->IsSplitMode() && node->GetWindowType() != WindowType::WINDOW_TYPE_DOCK_SLICE) {
return;
}
if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE && !pairedWindowMap_.empty()) {
std::vector<uint32_t> raiseNodeIds;
for (auto& splitInfo : pairedWindowMap_) {
auto pairNode = splitInfo.second.pairNode_;
if (pairNode != nullptr) {
raiseNodeIds.push_back(pairNode->GetWindowId());
}
}
// raise primary and secondary window to top, keep raw zorder
RaiseOrderedWindowToTop(raiseNodeIds, appWindowNode_->children_);
// raise divider final, keep divider on top
RaiseWindowToTop(node->GetWindowId(), appWindowNode_->children_);
} else if (!pairedWindowMap_.empty()) {
if (pairedWindowMap_.count(node->GetWindowId())) {
auto pairNode = pairedWindowMap_.at(node->GetWindowId()).pairNode_;
RaiseWindowToTop(pairNode->GetWindowId(), appWindowNode_->children_);
}
RaiseWindowToTop(node->GetWindowId(), appWindowNode_->children_);
sptr<WindowNode> deviderNode = FindDividerNode();
if (deviderNode != nullptr) {
// raise divider final, keep divider on top
RaiseWindowToTop(deviderNode->GetWindowId(), appWindowNode_->children_);
}
} else {
// raise self if not paired
RaiseWindowToTop(node->GetWindowId(), appWindowNode_->children_);
}
std::vector<sptr<WindowNode>> orderedPair = windowPair_->GetOrderedPair(node);
RaiseOrderedWindowToTop(orderedPair, appWindowNode_->children_);
AssignZOrder();
return;
}
@@ -1100,46 +1057,6 @@ void WindowNodeContainer::MinimizeAllAppWindows()
return;
}
void WindowNodeContainer::SendSplitScreenEvent(sptr<WindowNode>& node)
{
// reset ipc identity
std::string identity = IPCSkeleton::ResetCallingIdentity();
AAFwk::Want want;
want.SetAction(SPLIT_SCREEN_EVENT_NAME);
std::string modeData = (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) ? "Secondary" : "Primary";
int32_t missionId = -1;
AAFwk::AbilityManagerClient::GetInstance()->GetMissionIdByToken(node->abilityToken_, missionId);
WLOGFI("split window missionId is: %{public}d", missionId);
want.SetParam("windowMode", modeData);
want.SetParam("missionId", missionId);
EventFwk::CommonEventData commonEventData;
commonEventData.SetWant(want);
EventFwk::CommonEventManager::PublishCommonEvent(commonEventData);
// set ipc identity to raw
IPCSkeleton::SetCallingIdentity(identity);
WLOGFI("send split sceen event finish.");
}
sptr<WindowNode> WindowNodeContainer::FindSplitPairNode(sptr<WindowNode>& triggerNode) const
{
auto triggerMode = triggerNode->GetWindowMode();
for (auto iter = appWindowNode_->children_.rbegin(); iter != appWindowNode_->children_.rend(); iter++) {
if ((*iter)->GetWindowId() == triggerNode->GetWindowId()) {
continue;
}
// Find Top FullScreen main winodow or top paired split mode app main window
if ((*iter)->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN ||
(triggerMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY &&
(*iter)->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) ||
(triggerMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY &&
(*iter)->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY)) {
WLOGFI("Find pair node mode is: %{public}d", static_cast<uint32_t>((*iter)->GetWindowMode()));
return *iter;
}
}
return nullptr;
}
void WindowNodeContainer::MinimizeWindowFromAbility(const sptr<WindowNode>& node, bool fromUser)
{
if (node->abilityToken_ == nullptr) {
@@ -1170,105 +1087,11 @@ WMError WindowNodeContainer::MinimizeAppNodeExceptOptions(bool fromUser, const s
return WMError::WM_OK;
}
WMError WindowNodeContainer::EnterSplitWindowMode(sptr<WindowNode>& node)
{
WM_FUNCTION_TRACE();
WLOGFI("Enter split window mode: %{public}u", node->GetWindowId());
SwitchLayoutPolicy(WindowLayoutMode::CASCADE); // window split mode is belong to cascade
auto pairNode = FindSplitPairNode(node);
if (pairNode != nullptr) {
WLOGFI("Window %{public}d find pair %{public}u", node->GetWindowId(), pairNode->GetWindowId());
WMError ret = UpdateWindowPairInfo(node, pairNode);
if (ret != WMError::WM_OK) {
return ret;
}
SingletonContainer::Get<WindowInnerManager>().SendMessage(InnerWMCmd::INNER_WM_CREATE_DIVIDER, displayId_);
std::vector<uint32_t> exceptionalIds;
for (auto iter = pairedWindowMap_.begin(); iter != pairedWindowMap_.end(); iter++) {
exceptionalIds.emplace_back(iter->first);
}
std::vector<WindowMode> exceptionalModes = { WindowMode::WINDOW_MODE_FLOATING, WindowMode::WINDOW_MODE_PIP };
ret = MinimizeAppNodeExceptOptions(false, exceptionalIds, exceptionalModes);
if (ret != WMError::WM_OK) {
return ret;
}
} else {
SendSplitScreenEvent(node);
}
return WMError::WM_OK;
}
void WindowNodeContainer::ResetLayoutPolicy()
{
layoutPolicy_->Reset();
}
WMError WindowNodeContainer::ExitSplitWindowMode(sptr<WindowNode>& node)
{
WM_FUNCTION_TRACE();
WLOGFI("exit split window mode %{public}u", node->GetWindowId());
node->GetWindowProperty()->ResumeLastWindowMode();
node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
if (pairedWindowMap_.count(node->GetWindowId()) != 0) {
auto pairNode = pairedWindowMap_.at(node->GetWindowId()).pairNode_;
pairNode->GetWindowProperty()->ResumeLastWindowMode();
pairNode->GetWindowToken()->UpdateWindowMode(pairNode->GetWindowMode());
pairedWindowMap_.erase(pairNode->GetWindowId());
pairedWindowMap_.erase(node->GetWindowId());
WLOGFI("resume pair node mode, Id[%{public}u, %{public}u], Mode[%{public}d, %{public}d]", node->GetWindowId(),
pairNode->GetWindowId(), node->GetWindowMode(), pairNode->GetWindowMode());
}
if (pairedWindowMap_.empty()) {
WLOGFI("send destroy msg to divider, Id: %{public}u", node->GetWindowId());
SingletonContainer::Get<WindowInnerManager>().SendMessage(InnerWMCmd::INNER_WM_DESTROY_DIVIDER, displayId_);
}
ResetLayoutPolicy();
return WMError::WM_OK;
}
WMError WindowNodeContainer::UpdateWindowPairInfo(sptr<WindowNode>& triggerNode, sptr<WindowNode>& pairNode)
{
float splitRatio = DEFAULT_SPLIT_RATIO;
WindowMode triggerMode = triggerNode->GetWindowMode();
WindowMode pairSrcMode = pairNode->GetWindowMode();
if (pairSrcMode == WindowMode::WINDOW_MODE_FULLSCREEN) {
WindowMode pairDstMode = (triggerMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) ?
WindowMode::WINDOW_MODE_SPLIT_SECONDARY : WindowMode::WINDOW_MODE_SPLIT_PRIMARY;
pairNode->SetWindowMode(pairDstMode);
pairNode->GetWindowToken()->UpdateWindowMode(pairDstMode);
WMError ret = UpdateWindowNode(pairNode, WindowUpdateReason::UPDATE_MODE);
if (ret != WMError::WM_OK) {
WLOGFE("Update window pair info failed");
return ret;
}
WLOGFI("Pair FullScreen [%{public}u, %{public}u], Mode[%{public}d, %{public}d], splitRatio = %{public}f",
triggerNode->GetWindowId(), pairNode->GetWindowId(), triggerMode, pairDstMode, splitRatio);
} else {
if (pairedWindowMap_.count(pairNode->GetWindowId()) != 0) {
WindowPairInfo info = pairedWindowMap_.at(pairNode->GetWindowId());
auto prevPairNode = info.pairNode_;
WLOGFI("%{public}d node is paird , pre paired id is %{public}d,",
pairNode->GetWindowId(), prevPairNode->GetWindowId());
prevPairNode->GetWindowProperty()->ResumeLastWindowMode();
prevPairNode->GetWindowToken()->UpdateWindowMode(prevPairNode->GetWindowMode());
pairedWindowMap_.erase(prevPairNode->GetWindowId());
pairedWindowMap_.erase(pairNode->GetWindowId());
splitRatio = info.splitRatio_;
WLOGFI("Pair Split [%{public}d, %{public}d], Mode[%{public}d, %{public}d], splitRatio = %{public}f",
triggerNode->GetWindowId(), pairNode->GetWindowId(), triggerMode, pairSrcMode, splitRatio);
} else {
WLOGFI("%{public}d node is not paird", pairNode->GetWindowId());
}
}
pairedWindowMap_.insert(std::pair<uint32_t, WindowPairInfo>(triggerNode->GetWindowId(),
{pairNode, splitRatio}));
pairedWindowMap_.insert(std::pair<uint32_t, WindowPairInfo>(pairNode->GetWindowId(),
{triggerNode, 1 - splitRatio}));
return WMError::WM_OK;
}
WMError WindowNodeContainer::SwitchLayoutPolicy(WindowLayoutMode dstMode, bool reorder)
{
WLOGFI("SwitchLayoutPolicy src: %{public}d dst: %{public}d reorder: %{public}d",
@@ -1278,9 +1101,9 @@ WMError WindowNodeContainer::SwitchLayoutPolicy(WindowLayoutMode dstMode, bool r
return WMError::WM_ERROR_INVALID_PARAM;
}
if (layoutMode_ != dstMode) {
if (layoutMode_ == WindowLayoutMode::CASCADE && !pairedWindowMap_.empty()) {
pairedWindowMap_.clear();
SingletonContainer::Get<WindowInnerManager>().SendMessage(InnerWMCmd::INNER_WM_DESTROY_DIVIDER, displayId_);
if (layoutMode_ == WindowLayoutMode::CASCADE) {
layoutPolicy_->Reset();
windowPair_->Clear();
}
layoutMode_ = dstMode;
layoutPolicy_->Clean();
@@ -1291,11 +1114,7 @@ WMError WindowNodeContainer::SwitchLayoutPolicy(WindowLayoutMode dstMode, bool r
WLOGFI("Current layout mode is already: %{public}d", static_cast<uint32_t>(dstMode));
}
if (reorder) {
if (!pairedWindowMap_.empty()) {
// exit divider window when reorder
pairedWindowMap_.clear();
SingletonContainer::Get<WindowInnerManager>().SendMessage(InnerWMCmd::INNER_WM_DESTROY_DIVIDER, displayId_);
}
windowPair_->Clear();
layoutPolicy_->Reorder();
DumpScreenWindowTree();
}
@@ -1535,5 +1354,44 @@ bool WindowNodeContainer::ReadIsWindowAnimationEnabledProperty()
}
return true;
}
WMError WindowNodeContainer::SetWindowMode(sptr<WindowNode>& 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;
}
} // namespace Rosen
} // namespace OHOS
+431
View File
@@ -0,0 +1,431 @@
/*
* Copyright (c) 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_pair.h"
#include <ability_manager_client.h>
#include "common_event_manager.h"
#include "window_manager_hilog.h"
#include "window_helper.h"
#include "wm_trace.h"
namespace OHOS {
namespace Rosen {
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowPair"};
const std::string SPLIT_SCREEN_EVENT_NAME = "common.event.SPLIT_SCREEN";
}
WindowPair::WindowPair(const DisplayId& displayId, sptr<WindowNode>& appNode)
: displayId_(displayId), appWindowNode_(appNode) {
}
WindowPair::~WindowPair()
{
WLOGI("~WindowPair");
Clear();
}
void WindowPair::SendInnerMessage(InnerWMCmd cmd, DisplayId displayId)
{
WLOGI("Send inner message cmd id: %{public}u display id: %{public}u.", static_cast<uint32_t>(cmd),
static_cast<uint32_t>(displayId));
SingletonContainer::Get<WindowInnerManager>().SendMessage(cmd, displayId);
}
void WindowPair::SendBroadcastMsg(sptr<WindowNode>& node)
{
if (node == nullptr) {
return;
}
// reset ipc identity
std::string identity = IPCSkeleton::ResetCallingIdentity();
AAFwk::Want want;
want.SetAction(SPLIT_SCREEN_EVENT_NAME);
int32_t missionId = -1;
AAFwk::AbilityManagerClient::GetInstance()->GetMissionIdByToken(node->abilityToken_, missionId);
std::string modeData = "";
auto msg = (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) ?
SplitBroadcastMsg::MSG_START_PRIMARY : SplitBroadcastMsg::MSG_START_SECONDARY;
switch (msg) {
case SplitBroadcastMsg::MSG_START_PRIMARY :
modeData = "Primary";
break;
case SplitBroadcastMsg::MSG_START_SECONDARY :
modeData = "Secondary";
break;
case SplitBroadcastMsg::MSG_START_DIVIDER :
modeData = "Divider";
break;
default:
break;
}
want.SetParam("windowMode", modeData);
want.SetParam("missionId", missionId);
EventFwk::CommonEventData commonEventData;
commonEventData.SetWant(want);
EventFwk::CommonEventManager::PublishCommonEvent(commonEventData);
// set ipc identity to raw
IPCSkeleton::SetCallingIdentity(identity);
WLOGI("Send broadcast msg: %{public}s", modeData.c_str());
}
sptr<WindowNode> WindowPair::Find(sptr<WindowNode>& node)
{
if (node == nullptr) {
return nullptr;
}
if (primary_ != nullptr && primary_->GetWindowId() == node->GetWindowId()) {
return primary_;
} else if (secondary_ != nullptr && secondary_->GetWindowId() == node->GetWindowId()) {
return secondary_;
} else if (divider_ != nullptr && divider_->GetWindowId() == node->GetWindowId()) {
return divider_;
}
return nullptr;
}
bool WindowPair::IsPaired() const
{
if (primary_ == nullptr || secondary_ == nullptr) {
return false;
}
if (primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY &&
secondary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY &&
divider_ != nullptr) {
return true;
}
return false;
}
void WindowPair::SetSplitRatio(float ratio)
{
ratio_ = ratio;
}
float WindowPair::GetSplitRatio() const
{
return ratio_;
}
WindowPairStatus WindowPair::GetPairStatus() const
{
return status_;
}
sptr<WindowNode> WindowPair::GetDividerWindow() const
{
return divider_;
}
sptr<WindowNode> WindowPair::GetPrimaryWindow() const
{
return primary_;
}
sptr<WindowNode> WindowPair::GetSecondaryWindow() const
{
return secondary_;
}
void WindowPair::Clear()
{
WLOGI("Clear window pair.");
DumpPairInfo();
if (primary_ != nullptr && primary_->GetWindowProperty() != nullptr &&
primary_->GetWindowToken() != nullptr) {
primary_->GetWindowProperty()->ResumeLastWindowMode();
primary_->GetWindowToken()->UpdateWindowMode(primary_->GetWindowMode());
}
if (secondary_ != nullptr && secondary_->GetWindowProperty() != nullptr &&
secondary_->GetWindowToken() != nullptr) {
secondary_->GetWindowProperty()->ResumeLastWindowMode();
secondary_->GetWindowToken()->UpdateWindowMode(secondary_->GetWindowMode());
}
primary_ = nullptr;
secondary_ = nullptr;
if (divider_ != nullptr) {
SendInnerMessage(InnerWMCmd::INNER_WM_DESTROY_DIVIDER, displayId_);
divider_ = nullptr;
}
status_ = WindowPairStatus::STATUS_EMPTY;
}
bool WindowPair::IsSplitRelated(sptr<WindowNode>& node) const
{
if (node == nullptr) {
return false;
}
return WindowHelper::IsSplitWindowMode((node->GetWindowMode())) ||
(node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE);
}
std::vector<sptr<WindowNode>> WindowPair::GetOrderedPair(sptr<WindowNode>& node)
{
WLOGI("Get piared node in Z order");
std::vector<sptr<WindowNode>> orderedPair;
if (node == nullptr || Find(node) == nullptr) {
return orderedPair;
}
if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY ||
node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
// primary secondary
if (primary_ != nullptr && WindowHelper::IsAppWindow(primary_->GetWindowType())) {
orderedPair.push_back(primary_);
}
if (secondary_ != nullptr && WindowHelper::IsAppWindow(secondary_->GetWindowType())) {
orderedPair.push_back(secondary_);
}
} else if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
// secondary primary divider
if (secondary_ != nullptr && WindowHelper::IsAppWindow(secondary_->GetWindowType())) {
orderedPair.push_back(secondary_);
}
if (primary_ != nullptr && WindowHelper::IsAppWindow(primary_->GetWindowType())) {
orderedPair.push_back(primary_);
}
}
if (divider_ != nullptr) {
orderedPair.push_back(divider_);
}
return orderedPair;
}
std::vector<sptr<WindowNode>> WindowPair::GetPairedWindows()
{
WLOGI("Get all node of window pair");
std::vector<sptr<WindowNode>> orderedPair;
if (primary_ != nullptr) {
orderedPair.push_back(primary_);
}
if (secondary_ != nullptr) {
orderedPair.push_back(secondary_);
}
if (divider_ != nullptr) {
orderedPair.push_back(divider_);
}
return orderedPair;
}
sptr<WindowNode> WindowPair::FindPairableWindow(sptr<WindowNode>& node)
{
if (node == nullptr) {
return nullptr;
}
if (!node->IsSplitMode()) {
return nullptr;
}
for (auto iter = appWindowNode_->children_.rbegin(); iter != appWindowNode_->children_.rend(); iter++) {
auto pairNode = *iter;
if (pairNode == nullptr) {
continue;
}
if (pairNode->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) {
WindowMode dstMode = (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ?
WindowMode::WINDOW_MODE_SPLIT_SECONDARY : WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
pairNode->SetWindowMode(dstMode);
if (pairNode->GetWindowToken() != nullptr) {
pairNode->GetWindowToken()->UpdateWindowMode(pairNode->GetWindowMode());
}
WLOGFI("Find full screen pair window: %{public}u", static_cast<uint32_t>(pairNode->GetWindowId()));
return pairNode;
}
}
return nullptr;
}
sptr<WindowNode> WindowPair::GetPairableWindow(sptr<WindowNode>& node)
{
if (node == nullptr) {
return nullptr;
}
// get pairable window from window tree or send broadcast msg to start pair window
sptr<WindowNode> pairableNode = FindPairableWindow(node);
if (pairableNode == nullptr) {
WLOGFI("Can not find pairable window from current tree.");
SendBroadcastMsg(node);
return nullptr;
}
WLOGFI("Find pairable window id: %{public}u", pairableNode->GetWindowId());
return pairableNode;
}
void WindowPair::UpdateIfSplitRelated(sptr<WindowNode>& node)
{
if (node == nullptr) {
WLOGI("Window is nullptr.");
return;
}
if (Find(node) == nullptr && !IsSplitRelated(node)) {
WLOGI("Window id: %{public}u is not split related and paired.", node->GetWindowId());
return;
}
WLOGI("Current status: %{public}u, window id: %{public}u mode: %{public}u",
status_, node->GetWindowId(), node->GetWindowMode());
if (status_ == WindowPairStatus::STATUS_EMPTY) {
Insert(node);
// find pairable window from trees or send broadcast
sptr<WindowNode> pairableNode = GetPairableWindow(node);
// insert pairable node
Insert(pairableNode);
} else {
if (Find(node) == nullptr) {
// add new split related node to pair
Insert(node);
} else {
// handle paired nodes change
HandlePairedNodesChange();
}
}
}
void WindowPair::UpdateWindowPairStatus()
{
WLOGI("Update window pair status.");
WindowPairStatus prevStatus = status_;
if (primary_ != nullptr && secondary_ != nullptr && divider_ != nullptr) {
status_ = WindowPairStatus::STATUS_PAIRED_DONE;
} else if (primary_ != nullptr && secondary_ != nullptr && divider_ == nullptr) {
status_ = WindowPairStatus::STATUS_PAIRING;
} else if (primary_ != nullptr && secondary_ == nullptr) {
status_ = WindowPairStatus::STATUS_SINGLE_PRIMARY;
} else if (primary_ == nullptr && secondary_ != nullptr) {
status_ = WindowPairStatus::STATUS_SINGLE_SECONDARY;
} else {
status_ = WindowPairStatus::STATUS_EMPTY;
}
if ((prevStatus == WindowPairStatus::STATUS_SINGLE_PRIMARY ||
prevStatus == WindowPairStatus::STATUS_SINGLE_SECONDARY || prevStatus == WindowPairStatus::STATUS_EMPTY) &&
status_ == WindowPairStatus::STATUS_PAIRING) {
// create divider
SendInnerMessage(InnerWMCmd::INNER_WM_CREATE_DIVIDER, displayId_);
} else if ((prevStatus == WindowPairStatus::STATUS_PAIRED_DONE || prevStatus == WindowPairStatus::STATUS_PAIRING) &&
(status_ != WindowPairStatus::STATUS_PAIRED_DONE && status_ != WindowPairStatus::STATUS_PAIRING)) {
// clear pair
Clear();
}
DumpPairInfo();
}
void WindowPair::SwitchPosition()
{
if (primary_ == nullptr || secondary_ == nullptr) {
return;
}
WLOGFI("Switch the pair pos, pri: %{public}u pri-mode: %{public}u, sec: %{public}u sec-mode: %{public}u,",
primary_->GetWindowId(), primary_->GetWindowMode(), secondary_->GetWindowId(), secondary_->GetWindowMode());
if (primary_->GetWindowMode() == secondary_->GetWindowMode() &&
primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
primary_->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
if (primary_->GetWindowToken() != nullptr) {
primary_->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
}
std::swap(primary_, secondary_);
} else if (primary_->GetWindowMode() == secondary_->GetWindowMode() &&
primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
secondary_->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
if (secondary_->GetWindowToken() != nullptr) {
secondary_->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
}
std::swap(primary_, secondary_);
}
}
void WindowPair::HandlePairedNodesChange()
{
WLOGI("Update pair node.");
if (primary_ != nullptr && !primary_->IsSplitMode()) {
primary_ = nullptr;
}
if (secondary_ != nullptr && !secondary_->IsSplitMode()) {
secondary_ = nullptr;
}
// paired node mode change
if (primary_ != nullptr && secondary_ == nullptr &&
primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
std::swap(primary_, secondary_);
} else if (primary_ == nullptr && secondary_ != nullptr &&
secondary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
std::swap(primary_, secondary_);
} else if (primary_ != nullptr && secondary_ != nullptr &&
primary_->GetWindowMode() == secondary_->GetWindowMode()) {
// switch position
SwitchPosition();
}
UpdateWindowPairStatus();
}
void WindowPair::Insert(sptr<WindowNode>& node)
{
if (node == nullptr) {
return;
}
WLOGI("Insert a window to pair id: %{public}u", node->GetWindowId());
sptr<WindowNode> pairedNode;
if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
pairedNode = primary_;
primary_ = node;
} else if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
pairedNode = secondary_;
secondary_ = node;
} else if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
pairedNode = divider_;
divider_ = node;
}
// minimize invalid paired window
if (pairedNode != nullptr && pairedNode->abilityToken_ != nullptr) {
AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(pairedNode->abilityToken_, false);
}
UpdateWindowPairStatus();
}
void WindowPair::DumpPairInfo()
{
if (primary_ != nullptr) {
WLOGI("[DumpPairInfo] primary id: %{public}u mode: %{public}u", primary_->GetWindowId(),
primary_->GetWindowMode());
}
if (secondary_ != nullptr) {
WLOGI("[DumpPairInfo] secondary id: %{public}u mode: %{public}u", secondary_->GetWindowId(),
secondary_->GetWindowMode());
}
if (divider_ != nullptr) {
WLOGI("[DumpPairInfo] divider id: %{public}u mode: %{public}u", divider_->GetWindowId(),
divider_->GetWindowMode());
}
WLOGI("[DumpPairInfo] pair status %{public}u", status_);
}
void WindowPair::HandleRemoveWindow(sptr<WindowNode>& node)
{
if (node == nullptr) {
return;
}
if (Find(node) == nullptr && node->IsSplitMode()) {
WLOGI("Resume unpaired split related window id: %{public}u", node->GetWindowId());
if (node->GetWindowProperty() != nullptr && node->GetWindowToken() != nullptr) {
node->GetWindowProperty()->ResumeLastWindowMode();
node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
}
// target node is not in window pair, need resume mode when remove
return;
} else if (Find(node) != nullptr) {
WLOGI("Pairing window id: %{public}u is remove, clear window pair", node->GetWindowId());
Clear();
}
}
} // namespace Rosen
} // namespace OHOS
+3 -13
View File
@@ -361,24 +361,14 @@ void WindowRoot::UpdateFocusableProperty(uint32_t windowId)
}
}
WMError WindowRoot::EnterSplitWindowMode(sptr<WindowNode>& node)
WMError WindowRoot::SetWindowMode(sptr<WindowNode>& node, WindowMode dstMode)
{
auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
if (container == nullptr) {
WLOGFE("Enter split window mode failed, window container could not be found");
WLOGFE("set window mode failed, window container could not be found");
return WMError::WM_ERROR_NULLPTR;
}
return container->EnterSplitWindowMode(node);
}
WMError WindowRoot::ExitSplitWindowMode(sptr<WindowNode>& node)
{
auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
if (container == nullptr) {
WLOGFE("Exit split window mode failed, window container could not be found");
return WMError::WM_ERROR_NULLPTR;
}
return container->ExitSplitWindowMode(node);
return container->SetWindowMode(node, dstMode);
}
WMError WindowRoot::DestroyWindow(uint32_t windowId, bool onlySelf)