diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp index d41746f0c7d4def79c4aa2f67151cfa3fa346933..61243fbc9b0fa75ddaab23dd2732ed92263afa78 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.cpp @@ -95,6 +95,7 @@ napi_value JsSceneSession::Create(napi_env env, const sptr& sessio WLOGFE("do not get ref "); } jsSceneSessionMap_[session->GetPersistentId()] = jsRef; + BindNativeFunction(env, objValue, "updateSizeChangeReason", moduleName, JsSceneSession::UpdateSizeChangeReason); return objValue; } @@ -724,6 +725,13 @@ napi_value JsSceneSession::SetFocusable(napi_env env, napi_callback_info info) return (me != nullptr) ? me->OnSetFocusable(env, info) : nullptr; } +napi_value JsSceneSession::UpdateSizeChangeReason(napi_env env, napi_callback_info info) +{ + WLOGD("[NAPI]UpdateSizeChangeReason"); + JsSceneSession* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnUpdateSizeChangeReason(env, info) : nullptr; +} + napi_value JsSceneSession::SetShowRecent(napi_env env, napi_callback_info info) { WLOGI("[NAPI]SetShowRecent"); @@ -944,6 +952,36 @@ napi_value JsSceneSession::OnSetFocusable(napi_env env, napi_callback_info info) return NapiGetUndefined(env); } +napi_value JsSceneSession::OnUpdateSizeChangeReason(napi_env env, napi_callback_info info) +{ + size_t argc = 4; + napi_value argv[4] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < 1) { // 1: params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", argc); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + SizeChangeReason reason = SizeChangeReason::UNDEFINED; + if (!ConvertFromJsValue(env, argv[0], reason)) { + WLOGFE("[NAPI]Failed to convert parameter to bool"); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + auto session = weakSession_.promote(); + if (session == nullptr) { + WLOGFE("[NAPI]session is nullptr"); + napi_throw(env, CreateJsError(env, static_cast(WSErrorCode::WS_ERROR_INVALID_PARAM), + "Input parameter is missing or invalid")); + return NapiGetUndefined(env); + } + session->UpdateSizeChangeReason(reason); + WLOGI("[NAPI]UpdateSizeChangeReason reason: %{public}u end", reason); + return NapiGetUndefined(env); +} + void JsSceneSession::OnCreateSpecificSession(const sptr& sceneSession) { WLOGFD("OnCreateSpecificSession"); diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h index 367a07464d1690ad3dad31c670f8481132e1a9c1..1c7c9eeb1ed38e9feadf65a8e040eb8a6d5930a3 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session.h @@ -50,6 +50,7 @@ private: static napi_value SetFloatingScale(napi_env env, napi_callback_info info); static napi_value SetSystemSceneOcclusionAlpha(napi_env env, napi_callback_info info); static napi_value SetFocusable(napi_env env, napi_callback_info info); + static napi_value UpdateSizeChangeReason(napi_env env, napi_callback_info info); napi_value OnRegisterCallback(napi_env env, napi_callback_info info); napi_value OnUpdateNativeVisibility(napi_env env, napi_callback_info info); @@ -59,6 +60,7 @@ private: napi_value OnSetFloatingScale(napi_env env, napi_callback_info info); napi_value OnSetSystemSceneOcclusionAlpha(napi_env env, napi_callback_info info); napi_value OnSetFocusable(napi_env env, napi_callback_info info); + napi_value OnUpdateSizeChangeReason(napi_env env, napi_callback_info info); bool IsCallbackRegistered(napi_env env, const std::string& type, napi_value jsListenerObject); bool IsCallbackTypeSupported(const std::string& type); diff --git a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp index f5596581e41a64fe8b848a90eb137a4fa6c0bc2e..ab429c5fe7b35e6e426116e0773fcaad9acb5016 100644 --- a/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp +++ b/window_scene/interfaces/kits/napi/scene_session_manager/js_scene_session_manager.cpp @@ -819,7 +819,9 @@ napi_value JsSceneSessionManager::OnGetRootSceneSession(napi_env env, napi_callb ScenePersistentStorage::InitDir(context->GetPreferencesDir()); SceneSessionManager::GetInstance().InitPersistentStorage(); }); - + rootScene_->SetFrameLayoutFinishCallback([]() { + SceneSessionManager::GetInstance().NotifyUpdateRectAfterLayout(); + }); napi_value jsRootSceneSessionObj = JsRootSceneSession::Create(env, rootSceneSession); if (jsRootSceneSessionObj == nullptr) { WLOGFE("[NAPI]jsRootSceneSessionObj is nullptr"); diff --git a/window_scene/session/host/include/scene_session.h b/window_scene/session/host/include/scene_session.h index 8f69cef1790b77dd4b1b4ae3446207a68db35367..0c1166ebb7097e5c376e8bd251512df43790560d 100644 --- a/window_scene/session/host/include/scene_session.h +++ b/window_scene/session/host/include/scene_session.h @@ -130,6 +130,7 @@ public: WSError PendingSessionActivation(const sptr info) override; WSError TerminateSession(const sptr info) override; WSError NotifySessionException(const sptr info) override; + WSError NotifyClientToUpdateRect() override; WSError SetSystemBarProperty(WindowType type, SystemBarProperty systemBarProperty); WSError OnNeedAvoid(bool status) override; @@ -218,6 +219,8 @@ public: void NotifyPiPWindowPrepareClose() override; WSError UpdatePiPRect(uint32_t width, uint32_t height, PiPRectUpdateReason reason) override; WSError RecoveryPullPiPMainWindow(int32_t persistentId) override; + WSError UpdateSizeChangeReason(SizeChangeReason reason); + bool IsDirtyWindow(); private: void HandleStyleEvent(MMI::WindowArea area) override; @@ -259,6 +262,10 @@ private: void SavePiPRectInfo(); void GetNewPiPRect(const uint32_t displayWidth, const uint32_t displayHeight, Rect& rect); void ProcessUpdatePiPRect(SizeChangeReason reason); + SizeChangeReason reason_ = SizeChangeReason::UNDEFINED; + std::recursive_mutex sizeChangeMutex_; + bool isDirty_ = false; + public: double textFieldPositionY_ = 0.0; double textFieldHeight_ = 0.0; diff --git a/window_scene/session/host/include/session.h b/window_scene/session/host/include/session.h index 7c8b1498585a1ae80176f69c8fabcf82a6c9e484..8910108ff9c13962ea21d9535822f940f9528e1c 100644 --- a/window_scene/session/host/include/session.h +++ b/window_scene/session/host/include/session.h @@ -118,6 +118,7 @@ public: Accessibility::AccessibilityElementInfo& info); virtual WSError TransferFocusMoveSearch(int32_t elementId, int32_t direction, int32_t baseParent, Accessibility::AccessibilityElementInfo& info); + virtual WSError NotifyClientToUpdateRect() { return WSError::WS_OK; }; WSError TransferBackPressedEventForConsumed(bool& isConsumed); WSError TransferKeyEventForConsumed(const std::shared_ptr& keyEvent, bool& isConsumed); WSError TransferFocusActiveEvent(bool isFocusActive); diff --git a/window_scene/session/host/src/scene_session.cpp b/window_scene/session/host/src/scene_session.cpp index 7d6cf7740644b042c5811e0d5f000735efa57e37..9683775d629a9a3add406f6c009033ddb3880a32 100644 --- a/window_scene/session/host/src/scene_session.cpp +++ b/window_scene/session/host/src/scene_session.cpp @@ -20,6 +20,7 @@ #include #include #include +#include "transaction/rs_sync_transaction_controller.h" #include #include @@ -383,29 +384,64 @@ WSError SceneSession::SetAspectRatio(float ratio) WSError SceneSession::UpdateRect(const WSRect& rect, SizeChangeReason reason, const std::shared_ptr& rsTransaction) { - PostTask([weakThis = wptr(this), rect, reason, rsTransaction]() { + std::lock_guard lock(sizeChangeMutex_); + if (winRect_ == rect) { + WLOGFW("[WMSWinLayout] skip same rect update id:%{public}d!", GetPersistentId()); + return WSError::WS_OK; + } + winRect_ = rect; + isDirty_ = true; + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, + "SceneSession::UpdateRect%d [%d, %d, %u, %u]", + GetPersistentId(), rect.posX_, rect.posY_, rect.width_, rect.height_); + WLOGFD("[WMSWinLayout] Id: %{public}d, reason: %{public}d, rect: [%{public}d, %{public}d, %{public}u, %{public}u]", + GetPersistentId(), reason_, rect.posX_, rect.posY_, rect.width_, rect.height_); + return WSError::WS_OK; +} + +WSError SceneSession::NotifyClientToUpdateRect() +{ + PostTask([weakThis = wptr(this)]() { auto session = weakThis.promote(); if (!session) { WLOGFE("session is null"); return WSError::WS_ERROR_DESTROYED_OBJECT; } - WLOGFD("Id: %{public}d, reason: %{public}d, rect: [%{public}d, %{public}d, %{public}u, %{public}u]", - session->GetPersistentId(), reason, rect.posX_, rect.posY_, rect.width_, rect.height_); + std::lock_guard lock(session->sizeChangeMutex_); + WLOGFD("[WMSWinLayout] id:%{public}d, reason:%{public}d, rect:[%{public}d, %{public}d, %{public}u, %{public}u]", + session->GetPersistentId(), session->reason_, session->winRect_.posX_, + session->winRect_.posY_, session->winRect_.width_, session->winRect_.height_); bool isMoveOrDrag = session->moveDragController_ && (session->moveDragController_->GetStartDragFlag() || session->moveDragController_->GetStartMoveFlag()); - if (isMoveOrDrag && reason == SizeChangeReason::UNDEFINED) { - WLOGFD("skip redundant rect update!"); + if (isMoveOrDrag && session->reason_ == SizeChangeReason::UNDEFINED) { + WLOGFD("[WMSWinLayout] skip redundant rect update!"); return WSError::WS_ERROR_REPEAT_OPERATION; } - WSError ret = session->Session::UpdateRect(rect, reason, rsTransaction); - if (WindowHelper::IsPipWindow(session->GetWindowType()) && reason == SizeChangeReason::DRAG_END) { + auto transactionController = Rosen::RSSyncTransactionController::GetInstance(); + std::shared_ptr rsTransaction = nullptr; + if (transactionController) { + rsTransaction = transactionController->GetRSTransaction(); + } + WSError ret = session->Session::UpdateRect(session->winRect_, session->reason_, rsTransaction); + if (WindowHelper::IsPipWindow(session->GetWindowType()) && session->reason_ == SizeChangeReason::DRAG_END) { session->ClearPiPRectPivotInfo(); - ScenePersistentStorage::Insert("pip_window_pos_x", rect.posX_, ScenePersistentStorageType::PIP_INFO); - ScenePersistentStorage::Insert("pip_window_pos_y", rect.posY_, ScenePersistentStorageType::PIP_INFO); + ScenePersistentStorage::Insert("pip_window_pos_x", session->winRect_.posX_, + ScenePersistentStorageType::PIP_INFO); + ScenePersistentStorage::Insert("pip_window_pos_y", session->winRect_.posY_, + ScenePersistentStorageType::PIP_INFO); } if ((ret == WSError::WS_OK || session->sessionInfo_.isSystem_) && session->specificCallback_ != nullptr) { session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId()); } + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, + "SceneSession::NotifyClientToUpdateRect%d [%d, %d, %u, %u] reason:%u", + session->GetPersistentId(), session->winRect_.posX_, + session->winRect_.posY_, session->winRect_.width_, session->winRect_.height_, session->reason_); + // clear after use + if (ret == WSError::WS_OK) { + session->reason_ = SizeChangeReason::UNDEFINED; + session->isDirty_ = false; + } return ret; }); return WSError::WS_OK; @@ -1025,7 +1061,7 @@ WSError SceneSession::TransferPointerEvent(const std::shared_ptrGetWindowMode() == WindowMode::WINDOW_MODE_PIP && WindowHelper::IsPipWindow(property->GetWindowType())) { WLOGFD("WINDOW_MODE_PIP"); @@ -2077,4 +2113,36 @@ WSError SceneSession::UpdatePiPRect(uint32_t width, uint32_t height, PiPRectUpda }); return WSError::WS_OK; } + +WSError SceneSession::UpdateSizeChangeReason(SizeChangeReason reason) +{ + PostTask([weakThis = wptr(this), reason]() { + auto session = weakThis.promote(); + if (!session) { + WLOGFE("session is null"); + return WSError::WS_ERROR_DESTROYED_OBJECT; + } + if (session->sessionInfo_.isSystem_) { + // system scene no need to update reason + return WSError::WS_DO_NOTHING; + } + std::lock_guard lock(session->sizeChangeMutex_); + session->reason_ = reason; + if (reason != SizeChangeReason::UNDEFINED) { + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, + "SceneSession::UpdateSizeChangeReason%d reason:%d", + session->GetPersistentId(), static_cast(reason)); + WLOGFD("[WMSWinLayout]UpdateSizeChangeReason Id: %{public}d, reason: %{public}d", + session->GetPersistentId(), reason); + } + return WSError::WS_OK; + }); + return WSError::WS_OK; +} + +bool SceneSession::IsDirtyWindow() +{ + std::lock_guard lock(sizeChangeMutex_); + return isDirty_; +} } // namespace OHOS::Rosen diff --git a/window_scene/session/host/src/session.cpp b/window_scene/session/host/src/session.cpp index 8bf11a3f603d7a52ba02e42f3e92f8db00e64613..d4f1141207309488f716e1fa8f479a60f4d1fac0 100644 --- a/window_scene/session/host/src/session.cpp +++ b/window_scene/session/host/src/session.cpp @@ -663,7 +663,11 @@ WSError Session::Connect(const sptr& sessionStage, const sptr::GetInstance()->GetBundleName(callingPid_, callingUid_); DelayedSingleton::GetInstance()->SetApplicationInfo(persistentId_, callingPid_, callingBundleName_); diff --git a/window_scene/session_manager/include/scene_session_manager.h b/window_scene/session_manager/include/scene_session_manager.h index c1d5b7ca5c84e125c7ad5041867a74463684e1a9..03c3b919bb4065cc696ec3c3b9246ddd7ec6ed50 100644 --- a/window_scene/session_manager/include/scene_session_manager.h +++ b/window_scene/session_manager/include/scene_session_manager.h @@ -223,6 +223,7 @@ public: bool UpdateImmersiveState(); WSError UpdateTitleInTargetPos(int32_t persistentId, bool isShow, int32_t height); + void NotifyUpdateRectAfterLayout(); public: std::shared_ptr GetTaskScheduler() {return taskScheduler_;}; protected: diff --git a/window_scene/session_manager/src/scene_session_manager.cpp b/window_scene/session_manager/src/scene_session_manager.cpp index 6c1ec9a479c2bb5c67be69e6f47002c5187b311e..b54a492d6f70b3465190c1821870927f18028340 100644 --- a/window_scene/session_manager/src/scene_session_manager.cpp +++ b/window_scene/session_manager/src/scene_session_manager.cpp @@ -5379,7 +5379,7 @@ void SceneSessionManager::PreHandleCollaborator(sptr& sceneSession if (notifyReturn != BrokerStates::BROKER_STARTED) { WLOGFI("PreHandleCollaborator cant notify"); return; - } + } } if (sceneSession->GetSessionInfo().want != nullptr) { @@ -5493,4 +5493,19 @@ WSError SceneSessionManager::UpdateTitleInTargetPos(int32_t persistentId, bool i } return sceneSession->UpdateTitleInTargetPos(isShow, height); } + +void SceneSessionManager::NotifyUpdateRectAfterLayout() +{ + auto task = [this]() { + std::shared_lock lock(sceneSessionMapMutex_); + for (auto& iter: sceneSessionMap_) { + auto sceneSession = iter.second; + if (sceneSession && !sceneSession->GetSessionInfo().isSystem_ && sceneSession->IsDirtyWindow()) { + sceneSession->NotifyClientToUpdateRect(); + } + } + }; + // need sync task since animation transcation need + return taskScheduler_->PostVoidSyncTask(task); +} } // namespace OHOS::Rosen diff --git a/wm/include/root_scene.h b/wm/include/root_scene.h index 8117a0037c54714045981330064d1f33e1d94704..874fce3b9d81728cc2456ffa3c1f171e297d848c 100644 --- a/wm/include/root_scene.h +++ b/wm/include/root_scene.h @@ -47,6 +47,7 @@ public: int64_t GetVSyncPeriod() override; void OnBundleUpdated(const std::string& bundleName); + void SetFrameLayoutFinishCallback(std::function&& callback); void SetDisplayDensity(float density) { @@ -79,7 +80,6 @@ public: } static sptr staticRootScene_; - private: void RegisterInputEventListener(); @@ -90,6 +90,7 @@ private: float density_ = 1.0f; WindowType type_ = WindowType::WINDOW_TYPE_SCENE_BOARD; std::string name_ = "EntryView"; + std::function frameLayoutFinishCb_ = nullptr; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/src/root_scene.cpp b/wm/src/root_scene.cpp index 1c5c6213b7b677124699f9fe5995e77565ad293d..43027660a44c4b85799f4f85ba11bb6e8b109a81 100644 --- a/wm/src/root_scene.cpp +++ b/wm/src/root_scene.cpp @@ -74,6 +74,7 @@ RootScene::RootScene() RootScene::~RootScene() { + uiContent_ = nullptr; } void RootScene::LoadContent(const std::string& contentUrl, napi_env env, napi_value storage, @@ -91,7 +92,7 @@ void RootScene::LoadContent(const std::string& contentUrl, napi_env env, napi_va uiContent_->Initialize(this, contentUrl, storage); uiContent_->Foreground(); - + uiContent_->SetFrameLayoutFinishCallback(std::move(frameLayoutFinishCb_)); RegisterInputEventListener(); DelayedSingleton::GetInstance()->Init(); DelayedSingleton::GetInstance()->SetAnrObserver(([](int32_t pid) { @@ -188,5 +189,14 @@ void RootScene::OnBundleUpdated(const std::string& bundleName) uiContent_->UpdateResource(); } } + +void RootScene::SetFrameLayoutFinishCallback(std::function&& callback) +{ + frameLayoutFinishCb_ = callback; + if (uiContent_) { + uiContent_->SetFrameLayoutFinishCallback(std::move(frameLayoutFinishCb_)); + } + WLOGFI("[WMSWinLayout] SetFrameLayoutFinishCallback end"); +} } // namespace Rosen } // namespace OHOS diff --git a/wm/src/window_session_impl.cpp b/wm/src/window_session_impl.cpp index 7fb18dd20c13187cd38c17fe33c47b9647edb964..515681d7ae54f37aba224b1910921b11045a6a52 100644 --- a/wm/src/window_session_impl.cpp +++ b/wm/src/window_session_impl.cpp @@ -32,6 +32,7 @@ #include "color_parser.h" #include "display_info.h" #include "display_manager.h" +#include "hitrace_meter.h" #include "interfaces/include/ws_common.h" #include "session_permission.h" #include "key_event.h" @@ -386,21 +387,7 @@ WSError WindowSessionImpl::UpdateRect(const WSRect& rect, SizeChangeReason reaso // delete after replace ws_common.h with wm_common.h auto wmReason = static_cast(reason); Rect wmRect = { rect.posX_, rect.posY_, rect.width_, rect.height_ }; - if (GetRect().width_ != 0 && GetRect().height_ != 0 && WindowHelper::IsMainWindow(GetType())) { - // 50 session动画阈值 - int widthRange = 50; - int heightRange = 50; - if (std::abs((int)(GetRect().width_) - (int)(wmRect.width_)) > widthRange || - std::abs((int)(GetRect().height_) - (int)(wmRect.height_)) > heightRange) { - wmReason = wmReason == WindowSizeChangeReason::UNDEFINED ? - WindowSizeChangeReason::MAXIMIZE : wmReason; - } - } auto preRect = GetRect(); - if (preRect.width_ == wmRect.height_ && preRect.height_ == wmRect.width_ && - (preRect.width_ != wmRect.width_ || preRect.height_ != wmRect.height_)) { - wmReason = WindowSizeChangeReason::ROTATION; - } property_->SetWindowRect(wmRect); if (handler_ != nullptr && wmReason == WindowSizeChangeReason::ROTATION) { postTaskDone_ = false; @@ -413,7 +400,10 @@ WSError WindowSessionImpl::UpdateRect(const WSRect& rect, SizeChangeReason reaso } UpdateViewportConfig(wmRect, wmReason, rsTransaction); } - WLOGFI("update rect [%{public}d, %{public}d, %{public}u, %{public}u], reason:%{public}u" + HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, + "WindowSessionImpl::UpdateRect%d [%d, %d, %u, %u] reason:%u", + GetPersistentId(), wmRect.posX_, wmRect.posY_, wmRect.width_, wmRect.height_, wmReason); + WLOGFI("[WMSWinLayout] updateRect [%{public}d, %{public}d, %{public}u, %{public}u], reason:%{public}u" "WindowInfo:[name: %{public}s, persistentId:%{public}d]", rect.posX_, rect.posY_, rect.width_, rect.height_, wmReason, GetWindowName().c_str(), GetPersistentId()); return WSError::WS_OK;