diff --git a/wm/include/picture_in_picture_controller.h b/wm/include/picture_in_picture_controller.h index 1228ef86aee818f0ce6df4b7df323a459fe87355..94cf0f9dc0626270022d749142eea770d940c14d 100644 --- a/wm/include/picture_in_picture_controller.h +++ b/wm/include/picture_in_picture_controller.h @@ -73,17 +73,45 @@ public: PiPWindowState GetControllerState(); std::string GetPiPNavigationId(); + class PiPMainWindowListenerImpl : public Rosen::IWindowChangeListener { + public: + PiPMainWindowListenerImpl(const sptr window); + void OnSizeChange(Rect rect, WindowSizeChangeReason reason, + const std::shared_ptr& rsTransaction = nullptr) override {}; + void OnModeChange(WindowMode mode, bool hasDeco = true) override; + WindowMode GetMode(); + bool IsValid(); + private: + void DelayReset(); + + WindowMode mode_; + bool isValid_ = true; + std::shared_ptr handler_ = nullptr; + }; + class PipMainWindowLifeCycleImpl : public Rosen::IWindowLifeCycle { public: - PipMainWindowLifeCycleImpl(const std::string& navigationId) + PipMainWindowLifeCycleImpl(const std::string& navigationId, const sptr window) { navigationId_ = navigationId; + if (window != nullptr) { + window_ = window; + windowListener_ = new PiPMainWindowListenerImpl(window_); + window_->RegisterWindowChangeListener(windowListener_); + } + }; + ~PipMainWindowLifeCycleImpl() + { + if (window_ != nullptr && windowListener_ != nullptr) { + window_->UnregisterWindowChangeListener(windowListener_); + } }; - ~PipMainWindowLifeCycleImpl() {}; void AfterBackground() override; void BackgroundFailed(int32_t type) override; private: std::string navigationId_ = ""; + sptr window_; + sptr windowListener_; }; private: @@ -94,6 +122,7 @@ private: WMError StartPictureInPictureInner(StartPipType startType); WMError StopPictureInPictureInner(StopPipType stopType); void UpdateXComponentPositionAndSize(); + void UpdatePiPSourceRect() const; void ResetExtController(); bool IsPullPiPAndHandleNavigation(); wptr weakRef_ = nullptr; diff --git a/wm/src/picture_in_picture_controller.cpp b/wm/src/picture_in_picture_controller.cpp index 8081db73677c00ef17689f42aa4d6c5adb5b72d1..4d51922478bc3ef84e41357d9ba44fbc0349e23a 100644 --- a/wm/src/picture_in_picture_controller.cpp +++ b/wm/src/picture_in_picture_controller.cpp @@ -38,7 +38,8 @@ namespace Rosen { sptr PictureInPictureController::remoteObj_; namespace { constexpr int32_t DELAY_ANIM = 500; - constexpr int32_t SUCCESS = 1; + constexpr int32_t DELAY_RESET = 100; + constexpr int32_t PIP_SUCCESS = 1; constexpr int32_t FAILED = 0; constexpr uint32_t PIP_LOW_PRIORITY = 0; constexpr uint32_t PIP_HIGH_PRIORITY = 1; @@ -173,7 +174,7 @@ WMError PictureInPictureController::ShowPictureInPictureWindow(StartPipType star } PictureInPictureManager::SetActiveController(this); SingletonContainer::Get().ReportPiPStartWindow(static_cast(startType), - pipOption_->GetPipTemplate(), SUCCESS, "show pip success"); + pipOption_->GetPipTemplate(), PIP_SUCCESS, "show pip success"); return WMError::WM_OK; } @@ -251,7 +252,7 @@ WMError PictureInPictureController::StartPictureInPictureInner(StartPipType star } curState_ = PiPWindowState::STATE_STARTED; SingletonContainer::Get().ReportPiPStartWindow(static_cast(startType), - pipOption_->GetPipTemplate(), SUCCESS, "start pip success"); + pipOption_->GetPipTemplate(), PIP_SUCCESS, "start pip success"); return WMError::WM_OK; } @@ -351,7 +352,7 @@ WMError PictureInPictureController::StopPictureInPictureInner(StopPipType stopTy } } SingletonContainer::Get().ReportPiPStopWindow(static_cast(currentStopType), - currentPipOption->GetPipTemplate(), SUCCESS, "pip window stop success"); + currentPipOption->GetPipTemplate(), PIP_SUCCESS, "pip window stop success"); return WMError::WM_OK; }; if (handler_) { @@ -468,8 +469,19 @@ void PictureInPictureController::PipMainWindowLifeCycleImpl::AfterBackground() if (value == "false") { return; } - TLOGI(WmsLogTag::WMS_PIP, "PipMainWindowLifeCycleImpl AfterBackground is called success"); + if (windowListener_ != nullptr) { + auto curMode = windowListener_->GetMode(); + if (curMode == WindowMode::WINDOW_MODE_FLOATING) { + TLOGI(WmsLogTag::WMS_PIP, "floating not process"); + return; + } + if (!windowListener_->IsValid()) { + TLOGI(WmsLogTag::WMS_PIP, "split close not process"); + return; + } + } PictureInPictureManager::AutoStartPipWindow(navigationId_); + TLOGI(WmsLogTag::WMS_PIP, "called success"); } void PictureInPictureController::PipMainWindowLifeCycleImpl::BackgroundFailed(int32_t type) @@ -497,6 +509,7 @@ void PictureInPictureController::RestorePictureInPictureWindow() TLOGI(WmsLogTag::WMS_PIP, "main window is nullptr"); return; } + UpdatePiPSourceRect(); std::string navId = pipOption_->GetNavigationId(); if (navId != "") { auto navController = NavigationController::GetNavigationController(mainWindow_->GetUIContent(), navId); @@ -545,6 +558,25 @@ void PictureInPictureController::UpdateXComponentPositionAndSize() windowRect_.width_, windowRect_.height_, windowRect_.posX_, windowRect_.posY_); } +void PictureInPictureController::UpdatePiPSourceRect() const +{ + TLOGD(WmsLogTag::WMS_PIP, "UpdatePiPSourceRect is called"); + if (mainWindowXComponentController_ == nullptr || window_ == nullptr) { + TLOGE(WmsLogTag::WMS_PIP, "xcomponent controller not valid"); + return; + } + float posX = 0; + float posY = 0; + float width = 0; + float height = 0; + mainWindowXComponentController_->GetGlobalPosition(posX, posY); + mainWindowXComponentController_->GetSize(width, height); + Rect rect = { posX, posY, width, height }; + TLOGI(WmsLogTag::WMS_PIP, "result rect: [%{public}d, %{public}d, %{public}u, %{public}u]", + rect.posX_, rect.posY_, rect.width_, rect.height_); + window_->UpdatePiPRect(rect, WindowSizeChangeReason::RECOVER); +} + void PictureInPictureController::ResetExtController() { TLOGI(WmsLogTag::WMS_PIP, "ResetExtController is called"); @@ -675,5 +707,54 @@ std::string PictureInPictureController::GetPiPNavigationId() { return pipOption_? pipOption_->GetNavigationId() : ""; } + +PictureInPictureController::PiPMainWindowListenerImpl::PiPMainWindowListenerImpl(const sptr window) +{ + mode_ = window ? window->GetMode() : WindowMode::WINDOW_MODE_UNDEFINED; + handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); +} + +void PictureInPictureController::PiPMainWindowListenerImpl::OnModeChange(WindowMode mode, bool hasDeco) +{ + TLOGD(WmsLogTag::WMS_PIP, "OnModeChange is called"); + if (mode == WindowMode::WINDOW_MODE_FULLSCREEN && + (mode_ == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode_ == WindowMode::WINDOW_MODE_SPLIT_SECONDARY)) { + isValid_ = false; + DelayReset(); + } else { + isValid_ = true; + } + mode_ = mode; +} + +void PictureInPictureController::PiPMainWindowListenerImpl::DelayReset() +{ + TLOGD(WmsLogTag::WMS_PIP, "DelayReset is called"); + if (handler_ == nullptr) { + TLOGW(WmsLogTag::WMS_PIP, "task is not append to queue"); + isValid_ = true; + return; + } + auto delayTask = [weakThis = wptr(this)]() { + auto listener = weakThis.promote(); + if (!listener) { + TLOGE(WmsLogTag::WMS_PIP, "listener is nullptr"); + return; + } + listener->isValid_ = true; + TLOGI(WmsLogTag::WMS_PIP, "reset to valid"); + }; + handler_->PostTask(delayTask, "wms:PiPMainWindowListenerImpl_DelayReset", DELAY_RESET); +} + +WindowMode PictureInPictureController::PiPMainWindowListenerImpl::GetMode() +{ + return mode_; +} + +bool PictureInPictureController::PiPMainWindowListenerImpl::IsValid() +{ + return isValid_; +} } // namespace Rosen } // namespace OHOS \ No newline at end of file diff --git a/wm/src/picture_in_picture_manager.cpp b/wm/src/picture_in_picture_manager.cpp index 03f464b8a089a38386fb9a115d2007f2f20684f1..c2c3f94fa3ea0efa02443b59af484188c6dc3ebb 100644 --- a/wm/src/picture_in_picture_manager.cpp +++ b/wm/src/picture_in_picture_manager.cpp @@ -134,7 +134,7 @@ void PictureInPictureManager::AttachAutoStartController(int32_t handleId, autoStartController_->GetMainWindowId()); if (mainWindow != nullptr) { mainWindowLifeCycleImpl_ = new PictureInPictureController::PipMainWindowLifeCycleImpl( - pipController->GetPiPNavigationId()); + pipController->GetPiPNavigationId(), mainWindow); mainWindow->RegisterLifeCycleListener(mainWindowLifeCycleImpl_); } autoStartControllerMap_[handleId] = pipController; diff --git a/wm/test/unittest/picture_in_picture_controller_test.cpp b/wm/test/unittest/picture_in_picture_controller_test.cpp index b58b8195e7556ac4f860d3d19e34129219627983..c87c8ede36da46fb8564145f2602e92493ca5786 100644 --- a/wm/test/unittest/picture_in_picture_controller_test.cpp +++ b/wm/test/unittest/picture_in_picture_controller_test.cpp @@ -322,7 +322,7 @@ HWTEST_F(PictureInPictureControllerTest, StartMove, Function | SmallTest | Level GTEST_LOG_(INFO) << "TearDownCasecccccc"; sptr pipMainWindowLifeCycleImpl = - new PictureInPictureController::PipMainWindowLifeCycleImpl(navigationId); + new PictureInPictureController::PipMainWindowLifeCycleImpl(navigationId, mw); GTEST_LOG_(INFO) << "TearDownCasecccccc3"; pipMainWindowLifeCycleImpl->AfterBackground(); @@ -375,6 +375,24 @@ HWTEST_F(PictureInPictureControllerTest, SetXComponentController, Function | Sma auto ret1 = pipControl->IsPullPiPAndHandleNavigation(); ASSERT_EQ(true, ret1); } + +/** + * @tc.name: UpdatePiPSourceRect + * @tc.desc: UpdatePiPSourceRect + * @tc.type: FUNC + */ +HWTEST_F(PictureInPictureControllerTest, UpdatePiPSourceRect, Function | SmallTest | Level2) +{ + sptr listener = nullptr; + sptr listener1 = nullptr; + std::shared_ptr xComponentController = nullptr; + sptr mw = new MockWindow(); + sptr option = new PipOption(); + sptr pipControl = new PictureInPictureController(option, mw, 100, nullptr); + pipControl->SetXComponentController(xComponentController); + pipControl->UpdatePiPSourceRect(); + ASSERT_NE(WMError::WM_OK, pipControl->CreatePictureInPictureWindow()); +} } } } \ No newline at end of file