From 1a749e2466b227e525950744e6e4aa95e7264caf Mon Sep 17 00:00:00 2001 From: chenqinxin Date: Thu, 17 Feb 2022 17:02:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=AA=97=E5=8F=A3=E5=8F=AF?= =?UTF-8?q?=E8=A7=81=E6=80=A7=E6=B3=A8=E5=86=8C=E7=9B=91=E5=90=AC=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chenqinxin Change-Id: I86cd8f99a77e3ea157868fc366f48469c5ccc977 --- dm/src/display_manager.cpp | 2 +- interfaces/innerkits/wm/window_manager.h | 25 ++ interfaces/innerkits/wm/wm_common.h | 9 +- wm/include/window_manager_agent.h | 1 + .../zidl/window_manager_agent_interface.h | 3 + wm/include/zidl/window_manager_agent_proxy.h | 1 + wm/src/window_manager.cpp | 74 +++++- wm/src/window_manager_agent.cpp | 5 + wm/src/zidl/window_manager_agent_proxy.cpp | 26 ++ wm/src/zidl/window_manager_agent_stub.cpp | 10 + wm/test/systemtest/BUILD.gn | 12 + .../window_visibility_info_test.cpp | 245 ++++++++++++++++++ .../include/window_manager_agent_controller.h | 1 + wmserver/include/window_node.h | 3 +- wmserver/include/window_node_container.h | 13 +- wmserver/include/window_root.h | 2 +- wmserver/src/window_controller.cpp | 2 +- .../src/window_manager_agent_controller.cpp | 10 + wmserver/src/window_node_container.cpp | 224 +++++++++++----- wmserver/src/window_root.cpp | 15 +- 20 files changed, 592 insertions(+), 91 deletions(-) create mode 100644 wm/test/systemtest/window_visibility_info_test.cpp diff --git a/dm/src/display_manager.cpp b/dm/src/display_manager.cpp index 3bf4520329..bc113aa90e 100644 --- a/dm/src/display_manager.cpp +++ b/dm/src/display_manager.cpp @@ -484,7 +484,7 @@ bool DisplayManager::SetScreenBrightness(uint64_t screenId, uint32_t level) uint32_t DisplayManager::GetScreenBrightness(uint64_t screenId) const { uint32_t level = static_cast(RSInterfaces::GetInstance().GetScreenBacklight(screenId)); - WLOGFI("screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); + WLOGFD("screenId:%{public}" PRIu64", level:%{public}u,", screenId, level); return level; } diff --git a/interfaces/innerkits/wm/window_manager.h b/interfaces/innerkits/wm/window_manager.h index 931d6ef0a7..989fdae00c 100644 --- a/interfaces/innerkits/wm/window_manager.h +++ b/interfaces/innerkits/wm/window_manager.h @@ -49,6 +49,27 @@ public: virtual void OnSystemBarPropertyChange(DisplayId displayId, const SystemBarRegionTints& tints) = 0; }; +class WindowVisibilityInfo : public Parcelable { +public: + WindowVisibilityInfo() = default; + WindowVisibilityInfo(uint32_t winId, int32_t pid, int32_t uid, bool visibility) + : windowId_(winId), pid_(pid), uid_(uid), isVisible_(visibility) {}; + ~WindowVisibilityInfo() = default; + + virtual bool Marshalling(Parcel& parcel) const override; + static WindowVisibilityInfo* Unmarshalling(Parcel& parcel); + + uint32_t windowId_ { INVALID_WINDOW_ID }; + int32_t pid_ { 0 }; + int32_t uid_ { 0 }; + bool isVisible_ { false }; +}; + +class IVisibilityChangedListener : public RefBase { +public: + virtual void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) = 0; +}; + class WindowInfo : public Parcelable { public: WindowInfo() = default; @@ -78,6 +99,8 @@ public: void UnregisterSystemBarChangedListener(const sptr& listener); void RegisterWindowUpdateListener(const sptr& listener); void UnregisterWindowUpdateListener(const sptr& listener); + void RegisterVisibilityChangedListener(const sptr& listener); + void UnregisterVisibilityChangedListener(const sptr& listener); void MinimizeAllAppWindows(DisplayId displayId); void SetWindowLayoutMode(WindowLayoutMode mode, DisplayId displayId); @@ -91,6 +114,8 @@ private: DisplayId displayId, bool focused) const; void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) const; void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type); + void UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) const; }; } // namespace Rosen } // namespace OHOS diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 70058ca953..9256feac19 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -124,10 +124,17 @@ struct Rect { int32_t posY_; uint32_t width_; uint32_t height_; - bool operator == (const Rect& a) const + + bool operator==(const Rect& a) const { return (posX_ == a.posX_ && posY_ == a.posY_ && width_ == a.width_ && height_ == a.height_); } + + bool IsInsideOf(const Rect& a) const + { + return (posX_ >= a.posX_ && posY_ >= a.posY_ && + posX_ + width_ <= a.posX_ + a.width_ && posY_ + height_ <= a.posY_ + a.height_); + } }; struct PointInfo { diff --git a/wm/include/window_manager_agent.h b/wm/include/window_manager_agent.h index b432574212..d3d1de4264 100644 --- a/wm/include/window_manager_agent.h +++ b/wm/include/window_manager_agent.h @@ -30,6 +30,7 @@ public: DisplayId displayId, bool focused) override; void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& props) override; void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type) override; + void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) override; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/zidl/window_manager_agent_interface.h b/wm/include/zidl/window_manager_agent_interface.h index 57746aea95..2c1daff846 100644 --- a/wm/include/zidl/window_manager_agent_interface.h +++ b/wm/include/zidl/window_manager_agent_interface.h @@ -26,6 +26,7 @@ enum class WindowManagerAgentType : uint32_t { WINDOW_MANAGER_AGENT_TYPE_FOCUS, WINDOW_MANAGER_AGENT_TYPE_SYSTEM_BAR, WINDOW_MANAGER_AGENT_TYPE_WINDOW_UPDATE, + WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, }; class IWindowManagerAgent : public IRemoteBroker { @@ -36,12 +37,14 @@ public: TRANS_ID_UPDATE_FOCUS_STATUS = 1, TRANS_ID_UPDATE_SYSTEM_BAR_PROPS, TRANS_ID_UPDATE_WINDOW_STATUS, + TRANS_ID_UPDATE_WINDOW_VISIBILITY, }; virtual void UpdateFocusStatus(uint32_t windowId, const sptr& abilityToken, WindowType windowType, DisplayId displayId, bool focused) = 0; virtual void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) = 0; virtual void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type) = 0; + virtual void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) = 0; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/include/zidl/window_manager_agent_proxy.h b/wm/include/zidl/window_manager_agent_proxy.h index 7531213dc3..fd1b114df0 100644 --- a/wm/include/zidl/window_manager_agent_proxy.h +++ b/wm/include/zidl/window_manager_agent_proxy.h @@ -31,6 +31,7 @@ public: DisplayId displayId, bool focused) override; void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints) override; void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type) override; + void UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) override; private: static inline BrokerDelegator delegator_; diff --git a/wm/src/window_manager.cpp b/wm/src/window_manager.cpp index 73e2610d9e..6774bcaf19 100644 --- a/wm/src/window_manager.cpp +++ b/wm/src/window_manager.cpp @@ -29,6 +29,24 @@ namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowManager"}; } +bool WindowVisibilityInfo::Marshalling(Parcel &parcel) const +{ + return parcel.WriteUint32(windowId_) && parcel.WriteInt32(pid_) && + parcel.WriteInt32(uid_) && parcel.WriteBool(isVisible_); +} + +WindowVisibilityInfo* WindowVisibilityInfo::Unmarshalling(Parcel &parcel) +{ + WindowVisibilityInfo* windowVisibilityInfo = new WindowVisibilityInfo(); + bool res = parcel.ReadUint32(windowVisibilityInfo->windowId_) && parcel.ReadInt32(windowVisibilityInfo->pid_) && + parcel.ReadInt32(windowVisibilityInfo->uid_) && parcel.ReadBool(windowVisibilityInfo->isVisible_); + if (!res) { + delete windowVisibilityInfo; + return nullptr; + } + return windowVisibilityInfo; +} + bool WindowInfo::Marshalling(Parcel &parcel) const { return parcel.WriteInt32(wid_) && parcel.WriteUint32(windowRect_.width_) && @@ -40,13 +58,11 @@ bool WindowInfo::Marshalling(Parcel &parcel) const WindowInfo* WindowInfo::Unmarshalling(Parcel &parcel) { WindowInfo* windowInfo = new WindowInfo(); - if (windowInfo == nullptr) { - return nullptr; - } bool res = parcel.ReadInt32(windowInfo->wid_) && parcel.ReadUint32(windowInfo->windowRect_.width_) && parcel.ReadUint32(windowInfo->windowRect_.height_) && parcel.ReadInt32(windowInfo->windowRect_.posX_) && parcel.ReadInt32(windowInfo->windowRect_.posY_) && parcel.ReadBool(windowInfo->focused_); if (!res) { + delete windowInfo; return nullptr; } windowInfo->mode_ = static_cast(parcel.ReadUint32()); @@ -64,6 +80,7 @@ public: WindowType windowType, DisplayId displayId) const; void NotifySystemBarChanged(DisplayId displayId, const SystemBarRegionTints& tints) const; void NotifyWindowUpdate(const sptr& windowInfo, WindowUpdateType type) const; + void NotifyWindowVisibilityInfoChanged(const std::vector>& windowVisibilityInfos) const; static inline SingletonDelegator delegator_; std::recursive_mutex mutex_; @@ -73,6 +90,8 @@ public: sptr systemBarChangedListenerAgent_; std::vector> windowUpdateListeners_; sptr windowUpdateListenerAgent_; + std::vector> windowVisibilityListeners_; + sptr windowVisibilityListenerAgent_; }; void WindowManager::Impl::NotifyFocused(uint32_t windowId, const sptr& abilityToken, @@ -122,6 +141,14 @@ void WindowManager::Impl::NotifyWindowUpdate(const sptr& windowInfo, } } +void WindowManager::Impl::NotifyWindowVisibilityInfoChanged( + const std::vector>& windowVisibilityInfos) const +{ + for (auto& listener : windowVisibilityListeners_) { + listener->OnWindowVisibilityChanged(windowVisibilityInfos); + } +} + WindowManager::WindowManager() : pImpl_(std::make_unique()) { } @@ -257,6 +284,41 @@ void WindowManager::UnregisterWindowUpdateListener(const sptr& listener) +{ + if (listener == nullptr) { + WLOGFE("listener could not be null"); + return; + } + std::lock_guard lock(pImpl_->mutex_); + pImpl_->windowVisibilityListeners_.emplace_back(listener); + if (pImpl_->windowVisibilityListenerAgent_ == nullptr) { + pImpl_->windowVisibilityListenerAgent_ = new WindowManagerAgent(); + SingletonContainer::Get().RegisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, + pImpl_->windowVisibilityListenerAgent_); + } +} + +void WindowManager::UnregisterVisibilityChangedListener(const sptr& listener) +{ + if (listener == nullptr) { + return; + } + std::lock_guard lock(pImpl_->mutex_); + pImpl_->windowVisibilityListeners_.erase(std::remove_if(pImpl_->windowVisibilityListeners_.begin(), + pImpl_->windowVisibilityListeners_.end(), [listener](sptr registeredListener) { + return registeredListener == listener; + }), pImpl_->windowVisibilityListeners_.end()); + + if (pImpl_->windowVisibilityListeners_.empty() && pImpl_->windowVisibilityListenerAgent_ != nullptr) { + SingletonContainer::Get().UnregisterWindowManagerAgent( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY, + pImpl_->windowVisibilityListenerAgent_); + pImpl_->windowVisibilityListenerAgent_ = nullptr; + } +} + void WindowManager::UpdateFocusStatus(uint32_t windowId, const sptr& abilityToken, WindowType windowType, DisplayId displayId, bool focused) const { @@ -278,5 +340,11 @@ void WindowManager::UpdateWindowStatus(const sptr& windowInfo, Windo { pImpl_->NotifyWindowUpdate(windowInfo, type); } + +void WindowManager::UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) const +{ + pImpl_->NotifyWindowVisibilityInfoChanged(windowVisibilityInfos); +} } // namespace Rosen } // namespace OHOS diff --git a/wm/src/window_manager_agent.cpp b/wm/src/window_manager_agent.cpp index b501c1812e..d3e7e7c6eb 100644 --- a/wm/src/window_manager_agent.cpp +++ b/wm/src/window_manager_agent.cpp @@ -35,5 +35,10 @@ void WindowManagerAgent::UpdateWindowStatus(const sptr& windowInfo, { SingletonContainer::Get().UpdateWindowStatus(windowInfo, type); } + +void WindowManagerAgent::UpdateWindowVisibilityInfo(const std::vector>& visibilityInfos) +{ + SingletonContainer::Get().UpdateWindowVisibilityInfo(visibilityInfos); +} } // namespace Rosen } // namespace OHOS diff --git a/wm/src/zidl/window_manager_agent_proxy.cpp b/wm/src/zidl/window_manager_agent_proxy.cpp index 80da77d885..b3ebe95672 100644 --- a/wm/src/zidl/window_manager_agent_proxy.cpp +++ b/wm/src/zidl/window_manager_agent_proxy.cpp @@ -131,6 +131,32 @@ void WindowManagerAgentProxy::UpdateWindowStatus(const sptr& windowI WLOGFE("SendRequest failed"); } } + +void WindowManagerAgentProxy::UpdateWindowVisibilityInfo( + const std::vector>& visibilityInfos) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + WLOGFE("WriteInterfaceToken failed"); + return; + } + if (!data.WriteUint32(static_cast(visibilityInfos.size()))) { + WLOGFE("write windowVisibilityInfos size failed"); + return; + } + for (auto& info : visibilityInfos) { + if (!data.WriteParcelable(info)) { + WLOGFE("Write windowVisibilityInfo failed"); + return; + } + } + + if (Remote()->SendRequest(TRANS_ID_UPDATE_WINDOW_VISIBILITY, data, reply, option) != ERR_NONE) { + WLOGFE("SendRequest failed"); + } +} } // namespace Rosen } // namespace OHOS diff --git a/wm/src/zidl/window_manager_agent_stub.cpp b/wm/src/zidl/window_manager_agent_stub.cpp index 0a1fd55bf0..83e104860d 100644 --- a/wm/src/zidl/window_manager_agent_stub.cpp +++ b/wm/src/zidl/window_manager_agent_stub.cpp @@ -62,6 +62,16 @@ int WindowManagerAgentStub::OnRemoteRequest(uint32_t code, MessageParcel& data, UpdateWindowStatus(windowInfo, type); break; } + case TRANS_ID_UPDATE_WINDOW_VISIBILITY: { + uint32_t size = data.ReadUint32(); + std::vector> windowVisibilityInfos; + for (uint32_t i = 0; i < size; ++i) { + sptr info = data.ReadParcelable(); + windowVisibilityInfos.emplace_back(info); + } + UpdateWindowVisibilityInfo(windowVisibilityInfos); + break; + } default: break; } diff --git a/wm/test/systemtest/BUILD.gn b/wm/test/systemtest/BUILD.gn index b5b193f796..4aa3d3a2d1 100644 --- a/wm/test/systemtest/BUILD.gn +++ b/wm/test/systemtest/BUILD.gn @@ -30,6 +30,7 @@ group("systemtest") { ":wm_window_split_immersive_test", ":wm_window_split_test", ":wm_window_subwindow_test", + ":wm_window_visibility_info_test", ] } @@ -154,6 +155,17 @@ ohos_systemtest("wm_window_gamut_test") { ## SystemTest window_gamut_test }}} +## SystemTest wm_window_visibility_info_test {{{ +ohos_systemtest("wm_window_visibility_info_test") { + module_out_path = module_out_path + + sources = [ "window_visibility_info_test.cpp" ] + + deps = [ ":wm_systemtest_common" ] +} + +## SystemTest wm_window_visibility_info_test }}} + ## Build wm_systemtest_common.a {{{ config("wm_systemtest_common_public_config") { include_dirs = [ diff --git a/wm/test/systemtest/window_visibility_info_test.cpp b/wm/test/systemtest/window_visibility_info_test.cpp new file mode 100644 index 0000000000..668deab2fb --- /dev/null +++ b/wm/test/systemtest/window_visibility_info_test.cpp @@ -0,0 +1,245 @@ +/* + * 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. + */ + +// gtest +#include +#include "wm_common.h" +#include "window_manager.h" +#include "window_test_utils.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowVisibilityInfoTest"}; +} + +using utils = WindowTestUtils; +constexpr int WAIT_ASYNC_US = 200000; // 200ms + +class VisibilityChangedListenerImpl : public IVisibilityChangedListener { +public: + void OnWindowVisibilityChanged(const std::vector>& windowVisibilityInfo) override; + std::vector> windowVisibilityInfos_; +}; + +void VisibilityChangedListenerImpl::OnWindowVisibilityChanged( + const std::vector>& windowVisibilityInfo) +{ + WLOGFI("size:%{public}zu", windowVisibilityInfo.size()); + windowVisibilityInfos_ = std::move(windowVisibilityInfo); + for (auto& info : windowVisibilityInfos_) { + WLOGFI("windowId:%{public}u, covered:%{public}d, pid:%{public}d, uid:%{public}d", info->windowId_, + info->isVisible_, info->pid_, info->uid_); + } +} + +class WindowVisibilityInfoTest : public testing::Test { +public: + static void SetUpTestCase(); + + static void TearDownTestCase(); + + virtual void SetUp() override; + + virtual void TearDown() override; + + static inline sptr visibilityChangedListener_ = new VisibilityChangedListenerImpl(); + utils::TestWindowInfo fullScreenAppInfo_; + utils::TestWindowInfo floatAppInfo_; + utils::TestWindowInfo subAppInfo_; +}; + +void WindowVisibilityInfoTest::SetUpTestCase() +{ + auto display = DisplayManager::GetInstance().GetDisplayById(0); + if (display == nullptr) { + WLOGFE("GetDefaultDisplay: failed!"); + } else { + WLOGFI("GetDefaultDisplay: id %{public}" PRIu64", w %{public}d, h %{public}d, fps %{public}u", + display->GetId(), display->GetWidth(), display->GetHeight(), display->GetFreshRate()); + } + Rect displayRect = {0, 0, + static_cast(display->GetWidth()), static_cast(display->GetHeight())}; + utils::InitByDisplayRect(displayRect); + WindowManager::GetInstance().RegisterVisibilityChangedListener(visibilityChangedListener_); +} + +void WindowVisibilityInfoTest::TearDownTestCase() +{ + WindowManager::GetInstance().UnregisterVisibilityChangedListener(visibilityChangedListener_); +} + +void WindowVisibilityInfoTest::SetUp() +{ + fullScreenAppInfo_ = { + .name = "FullWindow", + .rect = utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FULLSCREEN, + .needAvoid = false, + .parentLimit = false, + .parentName = "", + }; + floatAppInfo_ = { + .name = "ParentWindow", + .rect = utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_MAIN_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentName = "", + }; + subAppInfo_ = { + .name = "SubWindow", + .rect = utils::customAppRect_, + .type = WindowType::WINDOW_TYPE_APP_SUB_WINDOW, + .mode = WindowMode::WINDOW_MODE_FLOATING, + .needAvoid = false, + .parentLimit = false, + .parentName = "", + }; +} + +void WindowVisibilityInfoTest::TearDown() +{ +} + +namespace { +/** +* @tc.name: WindowVisibilityInfoTest01 +* @tc.desc: add main window and sub window, show and hide and test callback +* @tc.type: FUNC +*/ +HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest01, Function | MediumTest | Level1) +{ + floatAppInfo_.name = "window1"; + floatAppInfo_.rect = {250, 150, 300, 500}; + sptr window1 = utils::CreateTestWindow(floatAppInfo_); + + subAppInfo_.name = "subWindow1"; + subAppInfo_.rect = {400, 200, 100, 100}; + subAppInfo_.parentName = window1->GetWindowName(); + sptr subWindow1 = utils::CreateTestWindow(subAppInfo_); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Hide()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Hide()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Hide()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + window1->Destroy(); + subWindow1->Destroy(); +} + +/** +* @tc.name: WindowVisibilityInfoTest02 +* @tc.desc: add two fullscreen main window, test callback +* @tc.type: FUNC +*/ +HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest02, Function | MediumTest | Level1) +{ + fullScreenAppInfo_.name = "window1"; + sptr window1 = utils::CreateTestWindow(fullScreenAppInfo_); + + fullScreenAppInfo_.name = "window2"; + sptr window2 = utils::CreateTestWindow(fullScreenAppInfo_); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + window1->Destroy(); + window2->Destroy(); +} + +/** +* @tc.name: WindowVisibilityInfoTest03 +* @tc.desc: add two main window and sub windows and test callback +* @tc.type: FUNC +*/ +HWTEST_F(WindowVisibilityInfoTest, WindowVisibilityInfoTest03, Function | MediumTest | Level1) +{ + floatAppInfo_.name = "window1"; + floatAppInfo_.rect = {0, 0, 300, 600}; + sptr window1 = utils::CreateTestWindow(floatAppInfo_); + + subAppInfo_.name = "subWindow1"; + subAppInfo_.rect = {400, 200, 100, 100}; + subAppInfo_.parentName = window1->GetWindowName(); + sptr subWindow1 = utils::CreateTestWindow(subAppInfo_); + + floatAppInfo_.name = "window2"; + floatAppInfo_.rect = {50, 150, 240, 426}; + sptr window2 = utils::CreateTestWindow(floatAppInfo_); + + subAppInfo_.name = "subWindow2"; + subAppInfo_.type = WindowType::WINDOW_TYPE_MEDIA; + subAppInfo_.parentName = window2->GetWindowName(); + sptr subWindow2 = utils::CreateTestWindow(subAppInfo_); + + ASSERT_EQ(WMError::WM_OK, window2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow2->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(1, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, window1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + ASSERT_EQ(WMError::WM_OK, subWindow1->Show()); + usleep(WAIT_ASYNC_US); + ASSERT_EQ(2, visibilityChangedListener_->windowVisibilityInfos_.size()); + + window1->Destroy(); + subWindow1->Destroy(); + window2->Destroy(); + subWindow2->Destroy(); +} +} +} // namespace Rosen +} // namespace OHOS + diff --git a/wmserver/include/window_manager_agent_controller.h b/wmserver/include/window_manager_agent_controller.h index 9f99bf313b..1f6204acd4 100644 --- a/wmserver/include/window_manager_agent_controller.h +++ b/wmserver/include/window_manager_agent_controller.h @@ -35,6 +35,7 @@ public: DisplayId displayId, bool focused); void UpdateSystemBarRegionTints(DisplayId displayId, const SystemBarRegionTints& tints); void UpdateWindowStatus(const sptr& windowInfo, WindowUpdateType type); + void UpdateWindowVisibilityInfo(const std::vector>& windowVisibilityInfos); private: WindowManagerAgentController() {} diff --git a/wmserver/include/window_node.h b/wmserver/include/window_node.h index 6ba52af316..2234a7e749 100644 --- a/wmserver/include/window_node.h +++ b/wmserver/include/window_node.h @@ -81,7 +81,8 @@ public: int32_t priority_ { 0 }; bool requestedVisibility_ { false }; bool currentVisibility_ { false }; - bool hasDecorated_ = false; + bool hasDecorated_ { false }; + bool isCovered_ { true }; // initial value true to ensure notification when this window is shown private: // colorspace, gamut diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 6dc7ef721c..8acd73b5fe 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -27,6 +27,7 @@ namespace OHOS { namespace Rosen { +using WindowNodeOperationFunc = std::function)>; // return true indicates to stop traverse class WindowNodeContainer : public RefBase { public: WindowNodeContainer(DisplayId displayId, uint32_t width, uint32_t height); @@ -50,7 +51,6 @@ public: void UpdateDisplayRect(uint32_t width, uint32_t height); void OnAvoidAreaChange(const std::vector& avoidAreas); - void LayoutDividerWindow(sptr& node); bool isVerticalDisplay() const; WMError RaiseZOrderForAppWindow(sptr& node, sptr& parentNode); sptr GetNextFocusableWindow(uint32_t windowId) const; @@ -63,13 +63,10 @@ public: WMError ExitSplitWindowMode(sptr& node); WMError SwitchLayoutPolicy(WindowLayoutMode mode, bool reorder = false); void MoveWindowNode(sptr& container); - sptr GetBelowAppWindowNode() const; - sptr GetAppWindowNode() const; - sptr GetAboveAppWindowNode() const; float GetVirtualPixelRatio() const; + void TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom = true) const; private: - void AssignZOrder(sptr& node); void TraverseWindowNode(sptr& root, std::vector>& windowNodes) const; sptr FindRoot(WindowType type) const; sptr FindWindowNodeById(uint32_t id) const; @@ -92,6 +89,11 @@ private: void ResetLayoutPolicy(); bool IsFullImmersiveNode(sptr node) const; bool IsSplitImmersiveNode(sptr node) const; + bool TraverseFromTopToBottom(sptr node, const WindowNodeOperationFunc& func) const; + bool TraverseFromBottomToTop(sptr node, const WindowNodeOperationFunc& func) const; + + // cannot determine in case of a window covered by union of several windows or with transparent value + void UpdateWindowVisibilityInfos(std::vector>& infos); sptr avoidController_; sptr zorderPolicy_ = new WindowZorderPolicy(); @@ -101,6 +103,7 @@ private: std::vector removedIds_; DisplayId displayId_ = 0; Rect displayRect_; + std::vector currentCoveredArea_; std::unordered_map> sysBarNodeMap_ { { WindowType::WINDOW_TYPE_STATUS_BAR, nullptr }, { WindowType::WINDOW_TYPE_NAVIGATION_BAR, nullptr }, diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index b15250145f..9cd558f114 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -59,7 +59,7 @@ public: void NotifyWindowStateChange(WindowState state, WindowStateChangeReason reason); void NotifyDisplayChange(sptr abstractDisplay); - void NotifyDisplayDestory(DisplayId displayId); + void NotifyDisplayDestroy(DisplayId displayId); void NotifySystemBarTints(); WMError RaiseZOrderForAppWindow(sptr& node); float GetVirtualPixelRatio(DisplayId displayId) const; diff --git a/wmserver/src/window_controller.cpp b/wmserver/src/window_controller.cpp index dcbc9d18b0..efaf27a0f2 100644 --- a/wmserver/src/window_controller.cpp +++ b/wmserver/src/window_controller.cpp @@ -259,7 +259,7 @@ void WindowController::NotifyDisplayStateChange(DisplayId displayId, DisplayStat break; } case DisplayStateChangeType::DESTROY: { - windowRoot_->NotifyDisplayDestory(displayId); + windowRoot_->NotifyDisplayDestroy(displayId); break; } default: { diff --git a/wmserver/src/window_manager_agent_controller.cpp b/wmserver/src/window_manager_agent_controller.cpp index d0ffad1c49..d976b03cb1 100644 --- a/wmserver/src/window_manager_agent_controller.cpp +++ b/wmserver/src/window_manager_agent_controller.cpp @@ -65,5 +65,15 @@ void WindowManagerAgentController::UpdateWindowStatus(const sptr& wi agent->UpdateWindowStatus(windowInfo, type); } } + +void WindowManagerAgentController::UpdateWindowVisibilityInfo( + const std::vector>& windowVisibilityInfos) +{ + WLOGFD("UpdateWindowVisibilityInfo size:%{public}zu", windowVisibilityInfos.size()); + for (auto& agent : wmAgentContainer_.GetAgentsByType( + WindowManagerAgentType::WINDOW_MANAGER_AGENT_TYPE_WINDOW_VISIBILITY)) { + agent->UpdateWindowVisibilityInfo(windowVisibilityInfos); + } +} } } \ No newline at end of file diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 776e34f83f..feeb28b56e 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "common_event_manager.h" #include "display_manager_service_inner.h" @@ -122,7 +123,6 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptrAddWindowNode(node); @@ -132,6 +132,8 @@ WMError WindowNodeContainer::AddWindowNode(sptr& node, sptr> infos; + UpdateWindowVisibilityInfos(infos); DumpScreenWindowTree(); UpdateWindowStatus(node, WindowUpdateType::WINDOW_UPDATE_ADDED); WLOGFI("AddWindowNode windowId: %{public}d end", node->GetWindowId()); @@ -256,8 +258,16 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr& node) node->requestedVisibility_ = false; node->currentVisibility_ = false; node->hasDecorated_ = false; + node->isCovered_ = true; + std::vector> infos = {new WindowVisibilityInfo(node->GetWindowId(), + node->GetCallingPid(), node->GetCallingUid(), false)}; for (auto& child : node->children_) { - child->currentVisibility_ = false; + if (child->currentVisibility_) { + child->currentVisibility_ = false; + child->isCovered_ = true; + infos.emplace_back(new WindowVisibilityInfo(child->GetWindowId(), child->GetCallingPid(), + child->GetCallingUid(), false)); + } } if (node->IsSplitMode()) { @@ -276,6 +286,7 @@ WMError WindowNodeContainer::RemoveWindowNode(sptr& node) } else { NotifyIfSystemBarTintChanged(); } + UpdateWindowVisibilityInfos(infos); DumpScreenWindowTree(); UpdateWindowStatus(node, WindowUpdateType::WINDOW_UPDATE_REMOVED); WLOGFI("RemoveWindowNode windowId: %{public}d end", node->GetWindowId()); @@ -347,43 +358,16 @@ void WindowNodeContainer::UpdateFocusStatus(uint32_t id, bool focused) const void WindowNodeContainer::AssignZOrder() { zOrder_ = 0; - for (auto& node : belowAppWindowNode_->children_) { - AssignZOrder(node); - } - for (auto& node : appWindowNode_->children_) { - AssignZOrder(node); - } - for (auto& node : aboveAppWindowNode_->children_) { - AssignZOrder(node); - } -} - -void WindowNodeContainer::AssignZOrder(sptr& node) -{ - if (node == nullptr) { - return; - } - auto iter = node->children_.begin(); - for (; iter < node->children_.end(); ++iter) { - if ((*iter)->priority_ < 0) { - if ((*iter)->surfaceNode_) { - (*iter)->surfaceNode_->SetPositionZ(zOrder_); - ++zOrder_; - } - } else { - break; + WindowNodeOperationFunc func = [this](sptr node) { + if (node->surfaceNode_ == nullptr) { + WLOGE("AssignZOrder: surfaceNode is nullptr, window Id:%{public}u", node->GetWindowId()); + return false; } - } - if (node->surfaceNode_) { node->surfaceNode_->SetPositionZ(zOrder_); ++zOrder_; - } - for (; iter < node->children_.end(); ++iter) { - if ((*iter)->surfaceNode_) { - (*iter)->surfaceNode_->SetPositionZ(zOrder_); - ++zOrder_; - } - } + return false; + }; + TraverseWindowTree(func, false); } WMError WindowNodeContainer::SetFocusWindow(uint32_t windowId) @@ -636,18 +620,18 @@ void WindowNodeContainer::DumpScreenWindowTree() { WLOGFI("-------- display %{public}" PRIu64" dump window info begin---------", displayId_); WLOGFI("WindowName WinId Type Mode Flag ZOrd [ x y w h]"); - std::vector> windowNodes; - TraverseContainer(windowNodes); - int32_t zOrder = static_cast(windowNodes.size()); - for (auto node : windowNodes) { + uint32_t zOrder = zOrder_; + WindowNodeOperationFunc func = [&zOrder](sptr node) { Rect rect = node->GetLayoutRect(); const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ? node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH); - WLOGFI("%{public}10s %{public}5d %{public}4d %{public}4d %{public}4d %{public}4d [%{public}4d %{public}4d " \ - "%{public}4d %{public}4d]", windowName.c_str(), node->GetWindowId(), node->GetWindowType(), - node->GetWindowMode(), node->GetWindowFlags(), - --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_); - } + WLOGI("DumpScreenWindowTree: %{public}10s %{public}5d %{public}4d %{public}4d %{public}4d %{public}4d " \ + "[%{public}4d %{public}4d %{public}4d %{public}4d]", + windowName.c_str(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(), + node->GetWindowFlags(), --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_); + return false; + }; + TraverseWindowTree(func, true); WLOGFI("-------- display %{public}" PRIu64" dump window info end ---------", displayId_); } @@ -780,22 +764,21 @@ WMError WindowNodeContainer::RaiseZOrderForAppWindow(sptr& node, spt sptr WindowNodeContainer::GetNextFocusableWindow(uint32_t windowId) const { - 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()) { - int index = std::distance(windowNodes.begin(), iter); - for (int i = index + 1; i < windowNodes.size(); i++) { - if (windowNodes[i]->GetWindowProperty()->GetFocusable()) { - return windowNodes[i]; - } + sptr nextFocusableWindow; + bool previousFocusedWindowFound = false; + WindowNodeOperationFunc func = [windowId, &nextFocusableWindow, &previousFocusedWindowFound]( + sptr node) { + if (previousFocusedWindowFound && node->GetWindowProperty()->GetFocusable()) { + nextFocusableWindow = node; + return true; } - } - WLOGFI("could not get next focusable window"); - return nullptr; + if (node->GetWindowId() == windowId) { + previousFocusedWindowFound = true; + } + return false; + }; + TraverseWindowTree(func, true); + return nextFocusableWindow; } void WindowNodeContainer::MinimizeAllAppWindows() @@ -1027,39 +1010,136 @@ void WindowNodeContainer::MoveWindowNode(sptr& container) { WLOGFI("MoveWindowNode: disconnect expand display: %{public}" PRId64 ", move window node to display: " "%{public}" PRId64 "", container->GetDisplayId(), displayId_); - sptr belowAppNode = container->GetBelowAppWindowNode(); - sptr appNode = container->GetAppWindowNode(); - sptr aboveAppNode = container->GetAboveAppWindowNode(); - for (auto& node : belowAppNode->children_) { + for (auto& node : container->belowAppWindowNode_->children_) { WLOGFI("belowAppWindowNode_: move windowNode: {public}%d", node->GetWindowId()); node->SetDisplayId(displayId_); belowAppWindowNode_->children_.push_back(node); } - for (auto& node : appNode->children_) { + for (auto& node : container->appWindowNode_->children_) { WLOGFI("appWindowNode_: move windowNode: {public}%d", node->GetWindowId()); node->SetDisplayId(displayId_); appWindowNode_->children_.push_back(node); } - for (auto& node : aboveAppNode->children_) { + for (auto& node : container->aboveAppWindowNode_->children_) { WLOGFI("aboveAppWindowNode_: move windowNode: {public}%d", node->GetWindowId()); node->SetDisplayId(displayId_); aboveAppWindowNode_->children_.push_back(node); } } -sptr WindowNodeContainer::GetBelowAppWindowNode() const +void WindowNodeContainer::TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom) const { - return belowAppWindowNode_; + 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; + } + } + } + } } -sptr WindowNodeContainer::GetAppWindowNode() const +bool WindowNodeContainer::TraverseFromTopToBottom(sptr node, const WindowNodeOperationFunc& func) const { - return appWindowNode_; + 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; } -sptr WindowNodeContainer::GetAboveAppWindowNode() const +bool WindowNodeContainer::TraverseFromBottomToTop(sptr node, const WindowNodeOperationFunc& func) const { - return aboveAppWindowNode_; + 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) +{ + currentCoveredArea_.clear(); + WindowNodeOperationFunc func = [this, &infos](sptr node) { + if (node == nullptr) { + return false; + } + Rect layoutRect = node->GetLayoutRect(); + 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() const diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index 5a18a64626..6a67ba3bd0 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -467,14 +467,17 @@ WMError WindowRoot::SetWindowLayoutMode(DisplayId displayId, WindowLayoutMode mo return ret; } -void WindowRoot::NotifyDisplayDestory(DisplayId expandDisplayId) +void WindowRoot::NotifyDisplayDestroy(DisplayId expandDisplayId) { - WLOGFW("disconnect expand display, get default and expand display container"); + WLOGFD("disconnect expand display, get default and expand display container"); DisplayId defaultDisplayId = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId(); - auto expandDisplaycontainer = GetOrCreateWindowNodeContainer(expandDisplayId); - auto defaultDisplaycontainer = GetOrCreateWindowNodeContainer(defaultDisplayId); - - defaultDisplaycontainer->MoveWindowNode(expandDisplaycontainer); + auto expandDisplayContainer = GetOrCreateWindowNodeContainer(expandDisplayId); + auto defaultDisplayContainer = GetOrCreateWindowNodeContainer(defaultDisplayId); + if (expandDisplayContainer == nullptr || defaultDisplayContainer == nullptr) { + WLOGFE("window node container is nullptr!"); + return; + } + defaultDisplayContainer->MoveWindowNode(expandDisplayContainer); NotifyDisplayRemoved(expandDisplayId); }