diff --git a/wm/test/systemtest/BUILD.gn b/wm/test/systemtest/BUILD.gn index 5b1f16a7de2c93be2c54af0b4147e76f199c036c..e60a6e5c530ec69cadae192c80cd95abdc27bb16 100644 --- a/wm/test/systemtest/BUILD.gn +++ b/wm/test/systemtest/BUILD.gn @@ -22,6 +22,7 @@ group("systemtest") { ":wm_window_immersive_test", ":wm_window_layout_test", ":wm_window_multi_ability_test", + ":wm_window_split_test", ":wm_window_subwindow_test", ] } @@ -70,6 +71,17 @@ ohos_systemtest("wm_window_immersive_test") { ## SystemTest wm_window_immersive_test }}} +## SystemTest wm_window_split_test {{{ +ohos_systemtest("wm_window_split_test") { + module_out_path = module_out_path + + sources = [ "window_split_test.cpp" ] + + deps = [ ":wm_systemtest_common" ] +} + +## SystemTest wm_window_split_test }}} + ## Build wm_systemtest_common.a {{{ config("wm_systemtest_common_public_config") { include_dirs = [ diff --git a/wm/test/systemtest/window_split_test.cpp b/wm/test/systemtest/window_split_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5925d702caa446b98f5edd5b61c31ec458c4cef7 --- /dev/null +++ b/wm/test/systemtest/window_split_test.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2021 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. + */ + +// gtest +#include +#include "window_test_utils.h" +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +using utils = WindowTestUtils; +class WindowSplitTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + virtual void SetUp() override; + virtual void TearDown() override; + std::vector> activeWindows_; +}; + +void WindowSplitTest::SetUpTestCase() +{ +} + +void WindowSplitTest::TearDownTestCase() +{ +} + +void WindowSplitTest::SetUp() +{ + activeWindows_.clear(); +} + +void WindowSplitTest::TearDown() +{ + while (!activeWindows_.empty()) { + ASSERT_EQ(WMError::WM_OK, activeWindows_.back()->Destroy()); + activeWindows_.pop_back(); + } +} + +namespace { +/** + * @tc.name: SplitWindow01 + * @tc.desc: one primary window and one fullscreen window + * @tc.type: FUNC + * @tc.require: AR000GGTV7 + */ +HWTEST_F(WindowSplitTest, SplitWindow01, Function | MediumTest | Level3) +{ + utils::TestWindowInfo infoFullScreen = { + .name = "fullscreen.1", + .rect = utils::defaultAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = true, + .parentLimit = false, + .parentName = "", + }; + utils::TestWindowInfo infoPrimary = { + .name = "primary.1", + .rect = utils::defaultAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_SPLIT_PRIMARY, + .needAvoid = true, + .parentLimit = false, + .parentName = "", + }; + const sptr& windowFullScreen = utils::CreateTestWindow(infoFullScreen); + ASSERT_EQ(WMError::WM_OK, windowFullScreen->Show()); + + activeWindows_.push_back(windowFullScreen); + const sptr& windowPrimary = utils::CreateTestWindow(infoPrimary); + ASSERT_EQ(WMError::WM_OK, windowPrimary->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, windowPrimary->GetMode()); + activeWindows_.push_back(windowPrimary); + // show one split primary window + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, windowFullScreen->GetMode()); + ASSERT_EQ(WMError::WM_OK, windowPrimary->Hide()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, windowFullScreen->GetMode()); + ASSERT_EQ(WMError::WM_OK, windowFullScreen->Hide()); +} + +/** + * @tc.name: SplitWindow02 + * @tc.desc: one secondary window and one fullscreen window + * @tc.type: FUNC + * @tc.require: AR000GGTV7 + */ +HWTEST_F(WindowSplitTest, SplitWindow02, Function | MediumTest | Level3) +{ + utils::TestWindowInfo infoFullScreen = { + .name = "fullscreen.2", + .rect = utils::defaultAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = true, + .parentLimit = false, + .parentName = "", + }; + utils::TestWindowInfo infoPrimary = { + .name = "secondary.2", + .rect = utils::defaultAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_SPLIT_SECONDARY, + .needAvoid = true, + .parentLimit = false, + .parentName = "", + }; + const sptr& windowFullScreen = utils::CreateTestWindow(infoFullScreen); + ASSERT_EQ(WMError::WM_OK, windowFullScreen->Show()); + activeWindows_.push_back(windowFullScreen); + const sptr& windowSecondary = utils::CreateTestWindow(infoPrimary); + ASSERT_EQ(WMError::WM_OK, windowSecondary->Show()); + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_SECONDARY, windowSecondary->GetMode()); + activeWindows_.push_back(windowSecondary); + // show one split primary window + ASSERT_EQ(WindowMode::WINDOW_MODE_SPLIT_PRIMARY, windowFullScreen->GetMode()); + ASSERT_EQ(WMError::WM_OK, windowFullScreen->Hide()); + ASSERT_EQ(WindowMode::WINDOW_MODE_FULLSCREEN, windowSecondary->GetMode()); + ASSERT_EQ(WMError::WM_OK, windowSecondary->Hide()); +} +} +} // namespace Rosen +} // namespace OHOS diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 858b980ba36883708c226173bc0aa57486e5f107..6e22a2256c5e6ba828c116bf70f86c85ef9f37b5 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -54,7 +54,8 @@ public: Rect GetDisplayRect() const; sptr GetTopImmersiveNode() const; void NotifySystemBarIfChanged(); - void HandleSplitWindowModeChange(sptr& triggerNode, bool isChangeToSplit); + WMError HandleSplitWindowModeChange(sptr& triggerNode, bool isChangeToSplit); + void OnAvoidAreaChange(const std::vector& avoidAreas); std::shared_ptr GetDisplayNode() const; void LayoutDividerWindow(sptr& node); @@ -90,9 +91,9 @@ private: void SendSplitScreenEvent(WindowMode mode); sptr FindSplitPairNode(sptr& node) const; - void HandleModeChangeToSplit(sptr& triggerNode); - void HandleModeChangeFromSplit(sptr& triggerNode); - void UpdateWindowPairInfo(sptr& triggerNode, sptr& pairNode); + WMError HandleModeChangeToSplit(sptr& triggerNode); + WMError HandleModeChangeFromSplit(sptr& triggerNode); + WMError UpdateWindowPairInfo(sptr& triggerNode, sptr& pairNode); sptr avoidController_; sptr zorderPolicy_ = new WindowZorderPolicy(); diff --git a/wmserver/src/window_inner_manager.cpp b/wmserver/src/window_inner_manager.cpp index 4f13b95c0c4bfb5c2ad4a1e10d60584a725da29a..29b71e74761ccc7c6eb979ba6cb333a087a302c0 100644 --- a/wmserver/src/window_inner_manager.cpp +++ b/wmserver/src/window_inner_manager.cpp @@ -187,7 +187,6 @@ void WindowInnerManager::HandleMessage() void WindowInnerManager::SendMessage(InnerWMCmd cmdType, uint32_t displayId) { - std::unique_lock lk(mutex_); if (!hasInitThread_) { WLOGFI("Inner window manager thread has not been created"); return; @@ -204,7 +203,6 @@ void WindowInnerManager::SendMessage(InnerWMCmd cmdType, uint32_t displayId) void WindowInnerManager::SendMessage(InnerWMCmd cmdType, uint32_t displayId, const Rect& dividerRect) { - std::unique_lock lk(mutex_); if (!hasInitThread_) { WLOGFI("Inner window manager thread has not been created"); return; diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index e4bcffd62bb812047b3b7cdccf52f509a0c86597..f367683fd5ea2712da3f4784744480ecfcedc22a 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -117,9 +117,12 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptrparent_ = parentNode; if (node->IsSplitMode()) { - HandleSplitWindowModeChange(node, true); + WMError ret = HandleSplitWindowModeChange(node, true); + if (ret != WMError::WM_OK) { + WLOGFE("Add split window failed!"); + return ret; + } } - UpdateWindowTree(node); UpdateRSTree(node, true); AssignZOrder(); @@ -234,9 +237,12 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr& node) } if (node->IsSplitMode()) { - HandleSplitWindowModeChange(node, false); + WMError ret = HandleSplitWindowModeChange(node, false); + if (ret != WMError::WM_OK) { + WLOGFE("Remove split window failed!"); + return ret; + } } - UpdateRSTree(node, false); UpdateFocusWindow(); layoutPolicy_->RemoveWindowNode(node); @@ -615,23 +621,27 @@ sptr WindowNodeContainer::FindSplitPairNode(sptr& trigge return nullptr; } -void WindowNodeContainer::HandleModeChangeToSplit(sptr& triggerNode) +WMError WindowNodeContainer::HandleModeChangeToSplit(sptr& triggerNode) { WM_FUNCTION_TRACE(); WLOGFI("HandleModeChangeToSplit %{public}d", triggerNode->GetWindowId()); auto pairNode = FindSplitPairNode(triggerNode); if (pairNode != nullptr) { WLOGFI("Window %{public}d find pair %{public}d", triggerNode->GetWindowId(), pairNode->GetWindowId()); - UpdateWindowPairInfo(triggerNode, pairNode); + WMError ret = UpdateWindowPairInfo(triggerNode, pairNode); + if (ret != WMError::WM_OK) { + return ret; + } } else { // sent split event displayRects_->SetSplitRect(DEFAULT_SPLIT_RATIO); SendSplitScreenEvent(triggerNode->GetWindowMode()); } UpdateDisplayInfo(); + return WMError::WM_OK; } -void WindowNodeContainer::HandleModeChangeFromSplit(sptr& triggerNode) +WMError WindowNodeContainer::HandleModeChangeFromSplit(sptr& triggerNode) { WLOGFI("HandleModeChangeFromSplit %{public}d", triggerNode->GetWindowId()); if (pairedWindowMap_.find(triggerNode->GetWindowId()) != pairedWindowMap_.end()) { @@ -640,7 +650,7 @@ void WindowNodeContainer::HandleModeChangeFromSplit(sptr& triggerNod pairNode->GetWindowProperty()->ResumeLastWindowMode(); pairNode->GetWindowToken()->UpdateWindowMode(pairNode->GetWindowMode()); triggerNode->GetWindowProperty()->ResumeLastWindowMode(); - triggerNode->GetWindowToken()->UpdateWindowMode(pairNode->GetWindowMode()); + triggerNode->GetWindowToken()->UpdateWindowMode(triggerNode->GetWindowMode()); pairedWindowMap_.erase(pairNode->GetWindowId()); pairedWindowMap_.erase(triggerNode->GetWindowId()); WLOGFI("Split out, Id[%{public}d, %{public}d], Mode[%{public}d, %{public}d]", @@ -648,22 +658,21 @@ void WindowNodeContainer::HandleModeChangeFromSplit(sptr& triggerNod triggerNode->GetWindowMode(), pairNode->GetWindowMode()); } else { WLOGFE("Split out, but can not find pair in map %{public}d", triggerNode->GetWindowId()); + return WMError::WM_ERROR_INVALID_WINDOW; } if (pairedWindowMap_.empty()) { + WLOGFI("Notify devider to destroy"); SingletonContainer::Get().SendMessage(INNER_WM_DESTROY_DIVIDER, screenId_); } + return WMError::WM_OK; } -void WindowNodeContainer::HandleSplitWindowModeChange(sptr& triggerNode, bool isChangeToSplit) +WMError WindowNodeContainer::HandleSplitWindowModeChange(sptr& triggerNode, bool isChangeToSplit) { - if (isChangeToSplit) { - HandleModeChangeToSplit(triggerNode); - } else { - HandleModeChangeFromSplit(triggerNode); - } + return isChangeToSplit ? HandleModeChangeToSplit(triggerNode) : HandleModeChangeFromSplit(triggerNode); } -void WindowNodeContainer::UpdateWindowPairInfo(sptr& triggerNode, sptr& pairNode) +WMError WindowNodeContainer::UpdateWindowPairInfo(sptr& triggerNode, sptr& pairNode) { float splitRatio = DEFAULT_SPLIT_RATIO; WindowMode triggerMode = triggerNode->GetWindowMode(); @@ -673,7 +682,11 @@ void WindowNodeContainer::UpdateWindowPairInfo(sptr& triggerNode, sp WindowMode::WINDOW_MODE_SPLIT_SECONDARY : WindowMode::WINDOW_MODE_SPLIT_PRIMARY; pairNode->SetWindowMode(pairDstMode); pairNode->GetWindowToken()->UpdateWindowMode(pairDstMode); - layoutPolicy_->AddWindowNode(pairNode); + WMError ret = UpdateWindowNode(pairNode); + if (ret != WMError::WM_OK) { + WLOGFE("Update window pair info failed"); + return ret; + } WLOGFI("Pair FullScreen [%{public}d, %{public}d], Mode[%{public}d, %{public}d], splitRatio = %{public}f", triggerNode->GetWindowId(), pairNode->GetWindowId(), triggerMode, pairDstMode, splitRatio); } else { @@ -697,8 +710,10 @@ void WindowNodeContainer::UpdateWindowPairInfo(sptr& triggerNode, sp pairedWindowMap_.insert(std::pair(pairNode->GetWindowId(), {triggerNode, 1 - splitRatio})); displayRects_->SetSplitRect(splitRatio); + WLOGFI("Notify devider to create"); Rect dividerRect = displayRects_->GetDividerRect(); SingletonContainer::Get().SendMessage(INNER_WM_CREATE_DIVIDER, screenId_, dividerRect); + return WMError::WM_OK; } } } diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index cbbd449785e8c2b3eb2800a17eb6fef1302c4f38..a3abc4f1049403625e2cc23845d9f907ec4d309c 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -209,8 +209,7 @@ WMError WindowRoot::HandleSplitWindowModeChange(sptr& node, bool isS WLOGFE("HandleSplitWindowModeChange failed, window container could not be found"); return WMError::WM_ERROR_NULLPTR; } - container->HandleSplitWindowModeChange(node, isSplitIn); - return WMError::WM_OK; + return container->HandleSplitWindowModeChange(node, isSplitIn); } WMError WindowRoot::DestroyWindow(uint32_t windowId)