From 1c3a6c01dd6be18702d45b10f211a2a1c7735e16 Mon Sep 17 00:00:00 2001 From: liuanguang Date: Mon, 1 Sep 2025 16:21:19 +0800 Subject: [PATCH] feat(wms-layout): add setContentAspectRatio API Signed-off-by: liuanguang --- interfaces/innerkits/wm/window.h | 11 +++ interfaces/innerkits/wm/wm_common.h | 2 +- .../window_runtime/window_napi/js_window.cpp | 80 +++++++++++++++++++ .../window_runtime/window_napi/js_window.h | 1 + previewer/include/window.h | 12 +++ previewer/include/wm_common.h | 50 ++++++++++++ utils/src/wm_common.cpp | 8 +- .../session/host/include/layout_controller.h | 2 + .../session/host/include/scene_session.h | 2 + .../host/include/zidl/session_interface.h | 16 ++++ .../include/zidl/session_ipc_interface_code.h | 1 + .../session/host/include/zidl/session_proxy.h | 2 + .../session/host/include/zidl/session_stub.h | 1 + .../session/host/src/layout_controller.cpp | 53 ++++++++++++ .../session/host/src/scene_session.cpp | 67 ++++++++++++++++ .../session/host/src/zidl/session_proxy.cpp | 44 ++++++++++ .../session/host/src/zidl/session_stub.cpp | 33 ++++++++ wm/include/window_session_impl.h | 1 + wm/src/window_scene_session_impl.cpp | 31 +++++++ wm/src/window_session_impl.cpp | 12 +++ 20 files changed, 425 insertions(+), 4 deletions(-) diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index 478e0d23d6..8b391343b8 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -2742,6 +2742,17 @@ public: */ virtual WMError ResetAspectRatio() { return WMError::WM_OK; } + /** + * @brief Set content aspect ratio of this window + * + * @param ratio the aspect ratio of window content + * @param isPersistent whether to persist the aspect ratio setting + * @param needUpdateRect whether to update the window rect after setting aspect ratio + * @return WMError + */ + virtual WMError SetContentAspectRatio( + float ratio, bool isPersistent, bool needUpdateRect) { return WMError::WM_OK; } + /** * @brief Get keyboard animation config * @return KeyboardAnimationConfig diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 0e344de181..4360a39540 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -458,7 +458,7 @@ enum class WindowUIType : uint8_t { * @brief Used to map from WMError to WmErrorCode. */ extern const std::map WM_JS_TO_ERROR_CODE_MAP; -WmErrorCode ConvertErrorToCode(WMError error); +WmErrorCode ConvertErrorToCode(WMError error, WmErrorCode defaultCode = WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY); /** * @brief Enumerates flag of window. diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp index bf783a9d9b..dedf663371 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp @@ -887,6 +887,13 @@ napi_value JsWindow::ResetAspectRatio(napi_env env, napi_callback_info info) return (me != nullptr) ? me->OnResetAspectRatio(env, info) : nullptr; } +napi_value JsWindow::SetContentAspectRatio(napi_env env, napi_callback_info info) +{ + TLOGD(WmsLogTag::DEFAULT, "[NAPI]"); + JsWindow* me = CheckParamsAndGetThis(env, info); + return (me != nullptr) ? me->OnSetContentAspectRatio(env, info) : nullptr; +} + napi_value JsWindow::Minimize(napi_env env, napi_callback_info info) { TLOGD(WmsLogTag::WMS_LAYOUT, "[NAPI]"); @@ -6907,6 +6914,78 @@ napi_value JsWindow::OnResetAspectRatio(napi_env env, napi_callback_info info) return result; } +napi_value JsWindow::OnSetContentAspectRatio(napi_env env, napi_callback_info info) +{ + size_t argc = THREE_PARAMS_SIZE; + napi_value argv[THREE_PARAMS_SIZE] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc < ONE_PARAMS_SIZE || argc > THREE_PARAMS_SIZE) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid argc: %{public}zu", argc); + return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM, + "[window][setContentAspectRatio]msg: Number of parameters is invalid"); + } + + if (!windowToken_) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Window is nullptr"); + return NapiThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY, + "[window][setContentAspectRatio]msg: Window is nullptr"); + } + + if (!WindowHelper::IsMainWindow(windowToken_->GetType())) { + TLOGE(WmsLogTag::WMS_LAYOUT, "SetContentAspectRatio is only allowed for the main window"); + return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_CALLING, + "[window][setContentAspectRatio]msg: SetContentAspectRatio is only allowed for the main window"); + } + + double aspectRatio = 0.0; + if (!ConvertFromJsValue(env, argv[INDEX_ZERO], aspectRatio) || aspectRatio <= 0.0) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to convert parameter to aspectRatio"); + return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM, + "[window][moveWindowToGlobalDisplay]msg: Failed to convert parameter to aspectRatio"); + } + + bool isPersistent = false; + if (argc >= TWO_PARAMS_SIZE && !ConvertFromJsValue(env, argv[INDEX_ONE], isPersistent)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to convert parameter to isPersistent"); + return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM, + "[window][setContentAspectRatio]msg: Failed to convert parameter to isPersistent"); + } + + bool needUpdateRect = false; + if (argc == THREE_PARAMS_SIZE && !ConvertFromJsValue(env, argv[INDEX_TWO], needUpdateRect)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to convert parameter to needUpdateRect"); + return NapiThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM, + "[window][setContentAspectRatio]msg: Failed to convert parameter to needUpdateRect"); + } + + napi_value result = nullptr; + std::shared_ptr napiAsyncTask = CreateEmptyAsyncTask(env, nullptr, &result); + auto asyncTask = [windowToken = wptr(windowToken_), aspectRatio, isPersistent, needUpdateRect, + env, napiAsyncTask, where = __func__] { + auto window = windowToken.promote(); + if (!window) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "%{public}s: Window is nullptr", where); + napiAsyncTask->Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY, + "[window][setContentAspectRatio]msg: Window is nullptr")); + return; + } + WMError ret = window->SetContentAspectRatio(aspectRatio, isPersistent, needUpdateRect); + WmErrorCode code = ConvertErrorToCode(ret); + if (code == WmErrorCode::WM_OK) { + napiAsyncTask->Resolve(env, NapiGetUndefined(env)); + } else { + napiAsyncTask->Reject(env, + JsErrUtils::CreateJsError(env, code, "[window][setContentAspectRatio]msg: Falied")); + } + }; + if (napi_send_event(env, asyncTask, napi_eprio_high, __func__) != napi_status::napi_ok) { + napiAsyncTask->Reject(env, + JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY, + "[window][setContentAspectRatio]msg: Falied to send event")); + } + return result; +} + napi_value JsWindow::OnMinimize(napi_env env, napi_callback_info info) { size_t argc = FOUR_PARAMS_SIZE; @@ -9234,6 +9313,7 @@ void BindFunctions(napi_env env, napi_value object, const char* moduleName) BindNativeFunction(env, object, "setBackdropBlurStyle", moduleName, JsWindow::SetBackdropBlurStyle); BindNativeFunction(env, object, "setAspectRatio", moduleName, JsWindow::SetAspectRatio); BindNativeFunction(env, object, "resetAspectRatio", moduleName, JsWindow::ResetAspectRatio); + BindNativeFunction(env, object, "setContentAspectRatio", moduleName, JsWindow::SetContentAspectRatio); BindNativeFunction(env, object, "setWaterMarkFlag", moduleName, JsWindow::SetWaterMarkFlag); BindNativeFunction(env, object, "setHandwritingFlag", moduleName, JsWindow::SetHandwritingFlag); BindNativeFunction(env, object, "minimize", moduleName, JsWindow::Minimize); diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.h b/interfaces/kits/napi/window_runtime/window_napi/js_window.h index ca07a5636d..5f2672c1df 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.h @@ -115,6 +115,7 @@ public: static napi_value RaiseToAppTop(napi_env env, napi_callback_info info); static napi_value SetAspectRatio(napi_env env, napi_callback_info info); static napi_value ResetAspectRatio(napi_env env, napi_callback_info info); + static napi_value SetContentAspectRatio(napi_env env, napi_callback_info info); static napi_value Minimize(napi_env env, napi_callback_info info); static napi_value RaiseAboveTarget(napi_env env, napi_callback_info info); static napi_value RaiseMainWindowAboveTarget(napi_env env, napi_callback_info info); diff --git a/previewer/include/window.h b/previewer/include/window.h index 8d23c8ea8b..9a504026f3 100644 --- a/previewer/include/window.h +++ b/previewer/include/window.h @@ -420,6 +420,18 @@ public: virtual bool IsAllowHaveSystemSubWindow() = 0; virtual WMError SetAspectRatio(float ratio) = 0; virtual WMError ResetAspectRatio() = 0; + + /** + * @brief Set content aspect ratio of this window + * + * @param ratio the aspect ratio of window content + * @param isPersistent whether to persist the aspect ratio setting + * @param needUpdateRect whether to update the window rect after setting aspect ratio + * @return WMError + */ + virtual WMError SetContentAspectRatio( + float ratio, bool isPersistent, bool needUpdateRect) { return WMError::WM_OK; } + virtual KeyboardAnimationConfig GetKeyboardAnimationConfig() = 0; virtual void SetNeedDefaultAnimation(bool needDefaultAnimation) = 0; diff --git a/previewer/include/wm_common.h b/previewer/include/wm_common.h index 24a96d4f74..f96b435da8 100644 --- a/previewer/include/wm_common.h +++ b/previewer/include/wm_common.h @@ -815,6 +815,56 @@ struct Rect { inline constexpr Rect Rect::EMPTY_RECT { 0, 0, 0, 0 }; +/** + * @struct WindowDecoration + * + * @brief Represents the window decoration thickness (non-drawable area). + * In general, the top decoration includes the title bar. + */ +struct WindowDecoration +{ + uint32_t left = 0; + uint32_t top = 0; + uint32_t right = 0; + uint32_t bottom = 0; + + /** + * @brief Calculate the total horizontal decoration. + */ + uint32_t Horizontal() const { return left + right; } + + /** + * @brief Calculate the total vertical decoration. + */ + uint32_t Vertical() const { return top + bottom; } + + std::string ToString() const + { + std::ostringstream oss; + oss << "[" << left << " " << top << " " << right << " " << bottom << "]"; + return oss.str(); + } +}; + +/** + * @brief Compute window decoration sizes from window rect and drawble rect. + * @param winRect The full window rectangle (including borders). + * @param drawbleRect The drawble rectangle (inside borders). + * @return WindowDecoration + */ +inline WindowDecoration ComputeWindowDecoration( + const Rect& winRect, const Rect& drawbleRect) +{ + int left = std::max(0, drawbleRect.posX_ - winRect.posX_); + int top = std::max(0, drawbleRect.posY_ - winRect.posY_); + int right = std::max(0, (winRect.posX_ + winRect.width_) - + (drawbleRect.posX_ + drawbleRect.width_)); + int bottom = std::max(0, (winRect.posY_ + winRect.height_) - + (drawbleRect.posY_ + drawbleRect.height_)); + + return {left, top, right, bottom}; +} + /** * @struct SystemBarProperty * diff --git a/utils/src/wm_common.cpp b/utils/src/wm_common.cpp index 0d469bd183..4e46252b4c 100644 --- a/utils/src/wm_common.cpp +++ b/utils/src/wm_common.cpp @@ -62,13 +62,15 @@ const std::map WM_JS_TO_ERROR_CODE_MAP { {WMError::WM_ERROR_UI_EFFECT_ERROR, WmErrorCode::WM_ERROR_UI_EFFECT_ERROR }, }; -WmErrorCode ConvertErrorToCode(WMError error) +WmErrorCode ConvertErrorToCode(WMError error, WmErrorCode defaultCode) { auto iter = WM_JS_TO_ERROR_CODE_MAP.find(error); if (iter != WM_JS_TO_ERROR_CODE_MAP.end()) { return iter->second; } - TLOGE(WmsLogTag::DEFAULT, "not find error::%{public}d", static_cast(error)); - return WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY; + TLOGE(WmsLogTag::DEFAULT, + "No mapping found for WMError: %{public}d, fallback to default WmErrorCode: %{public}d", + static_cast(error), static_cast(defaultCode)); + return defaultCode; } } \ No newline at end of file diff --git a/window_scene/session/host/include/layout_controller.h b/window_scene/session/host/include/layout_controller.h index 04f3ea5a1b..639bc787cf 100644 --- a/window_scene/session/host/include/layout_controller.h +++ b/window_scene/session/host/include/layout_controller.h @@ -43,6 +43,7 @@ public: WSRect ConvertGlobalRectToRelative(const WSRect& globalRect, DisplayId targetDisplayId) const; int32_t GetSessionPersistentId() const; bool AdjustRectByAspectRatio(WSRect& rect, bool isDecorEnable); + bool AdjustRectByAspectRatio(WSRect& rect, bool isDecorEnable, const WindowDecoration& decoration); float GetAspectRatio() const { return aspectRatio_; } void SetAspectRatio(float ratio) { aspectRatio_ = ratio; } float GetScaleX() const { return scaleX_; } @@ -75,6 +76,7 @@ private: GetSystemConfigFunc getSystemConfigFunc_; void AdjustRectByLimits(WindowLimits limits, float ratio, bool isDecor, float vpr, WSRect& rect); + void AdjustRectByLimits(WindowLimits limits, float ratio, bool isDecor, float vpr, Rect& rect); }; } // namespace OHOS::Rosen #endif // OHOS_ROSEN_LAYOUT_CONTROLLER_H diff --git a/window_scene/session/host/include/scene_session.h b/window_scene/session/host/include/scene_session.h index f0f5d2c7e8..0b606f01f7 100644 --- a/window_scene/session/host/include/scene_session.h +++ b/window_scene/session/host/include/scene_session.h @@ -294,6 +294,8 @@ public: bool needNotifyClient = true, bool isExecuteDelayRaise = false); WSError RequestSessionBack(bool needMoveToBackground) override; WSError SetAspectRatio(float ratio) override; + WSError SetContentAspectRatio( + float ratio, bool isPersistent, bool needUpdateRect, const WindowDecoration& decoration) override; WSError SetGlobalMaximizeMode(MaximizeMode mode) override; WSError GetGlobalMaximizeMode(MaximizeMode& mode) override; WSError UpdateWindowSceneAfterCustomAnimation(bool isAdd) override; diff --git a/window_scene/session/host/include/zidl/session_interface.h b/window_scene/session/host/include/zidl/session_interface.h index f21a265797..375bd68b62 100644 --- a/window_scene/session/host/include/zidl/session_interface.h +++ b/window_scene/session/host/include/zidl/session_interface.h @@ -193,6 +193,22 @@ public: * @return Returns WSError::WS_OK if called success, otherwise failed. */ virtual WSError SetAspectRatio(float ratio) { return WSError::WS_OK; } + + /** + * @brief Sets the content aspect ratio of window. + * + * @param ratio Indicates the value of the aspect ratio (width divided by height). + * @param isPersistent Indicates whether to persist the aspect ratio across sessions. + * @param needUpdateRect Indicates whether to update the window rectangle after setting the aspect ratio. + * @param decoration Indicates the window decoration thickness. + * @return Returns WSError::WS_OK if called success, otherwise failed. + */ + virtual WSError SetContentAspectRatio( + float ratio, bool isPersistent, bool needUpdateRect, const WindowDecoration& decoration) + { + return WSError::WS_OK; + } + virtual WSError UpdateWindowAnimationFlag(bool needDefaultAnimationFlag) { return WSError::WS_OK; } virtual WSError UpdateWindowSceneAfterCustomAnimation(bool isAdd) { return WSError::WS_OK; } diff --git a/window_scene/session/host/include/zidl/session_ipc_interface_code.h b/window_scene/session/host/include/zidl/session_ipc_interface_code.h index 78c45862df..3fd532b83f 100644 --- a/window_scene/session/host/include/zidl/session_ipc_interface_code.h +++ b/window_scene/session/host/include/zidl/session_ipc_interface_code.h @@ -45,6 +45,7 @@ enum class SessionInterfaceCode { TRANS_ID_NEED_AVOID, TRANS_ID_GET_AVOID_AREA, TRANS_ID_SET_ASPECT_RATIO, + TRANS_ID_SET_CONTENT_ASPECT_RATIO, TRANS_ID_UPDATE_WINDOW_ANIMATION_FLAG, TRANS_ID_UPDATE_CUSTOM_ANIMATION, TRANS_ID_RAISE_ABOVE_TARGET, diff --git a/window_scene/session/host/include/zidl/session_proxy.h b/window_scene/session/host/include/zidl/session_proxy.h index 943b3fb921..a65d94539e 100644 --- a/window_scene/session/host/include/zidl/session_proxy.h +++ b/window_scene/session/host/include/zidl/session_proxy.h @@ -74,6 +74,8 @@ public: WSError SetGlobalMaximizeMode(MaximizeMode mode) override; WSError GetGlobalMaximizeMode(MaximizeMode& mode) override; WSError SetAspectRatio(float ratio) override; + WSError SetContentAspectRatio( + float ratio, bool isPersistent, bool needUpdateRect, const WindowDecoration& decoration) override; WSError UpdateWindowAnimationFlag(bool needDefaultAnimationFlag) override; WSError SetLandscapeMultiWindow(bool isLandscapeMultiWindow) override; WSError GetIsMidScene(bool& isMidScene) override; diff --git a/window_scene/session/host/include/zidl/session_stub.h b/window_scene/session/host/include/zidl/session_stub.h index 020dfcebba..8ae4116278 100644 --- a/window_scene/session/host/include/zidl/session_stub.h +++ b/window_scene/session/host/include/zidl/session_stub.h @@ -57,6 +57,7 @@ private: int HandleGetAllAvoidAreas(MessageParcel& data, MessageParcel& reply); int HandleGetTargetOrientationConfigInfo(MessageParcel& data, MessageParcel& reply); int HandleSetAspectRatio(MessageParcel& data, MessageParcel& reply); + int HandleSetContentAspectRatio(MessageParcel& data, MessageParcel& reply); int HandleSetWindowAnimationFlag(MessageParcel& data, MessageParcel& reply); int HandleUpdateWindowSceneAfterCustomAnimation(MessageParcel& data, MessageParcel& reply); int HandleRaiseAboveTarget(MessageParcel& data, MessageParcel& reply); diff --git a/window_scene/session/host/src/layout_controller.cpp b/window_scene/session/host/src/layout_controller.cpp index e6b44555c0..b77faf74ad 100644 --- a/window_scene/session/host/src/layout_controller.cpp +++ b/window_scene/session/host/src/layout_controller.cpp @@ -167,6 +167,7 @@ void LayoutController::AdjustRectByLimits(WindowLimits limits, float ratio, bool } } +// TODO:根据 decoration 调整 bool LayoutController::AdjustRectByAspectRatio(WSRect& rect, bool isDecorEnable) { const int tolerancePx = 2; // 2: tolerance delta pixel value, unit: px @@ -217,6 +218,58 @@ bool LayoutController::AdjustRectByAspectRatio(WSRect& rect, bool isDecorEnable) return true; } +bool LayoutController::AdjustRectByAspectRatio(WSRect& rect, bool isDecorEnable, const WindowDecoration& decoration) +{ + const int tolerancePx = 2; // 2: tolerance delta pixel value, unit: px + WSRect originalRect = rect; + if (sessionProperty_->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING || + !WindowHelper::IsMainWindow(sessionProperty_->GetWindowType())) { + return false; + } + + if (MathHelper::NearZero(aspectRatio_)) { + return false; + } + float vpr = 1.5f; // 1.5f: default virtual pixel ratio + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + if (display) { + vpr = display->GetVirtualPixelRatio(); + } + int32_t minW; + int32_t maxW; + int32_t minH; + int32_t maxH; + SessionUtils::CalcFloatWindowRectLimits(sessionProperty_->GetWindowLimits(), + getSystemConfigFunc_().maxFloatingWindowSize_, vpr, minW, maxW, minH, maxH); + rect.width_ = std::max(minW, static_cast(rect.width_)); + rect.width_ = std::min(maxW, static_cast(rect.width_)); + rect.height_ = std::max(minH, static_cast(rect.height_)); + rect.height_ = std::min(maxH, static_cast(rect.height_)); + if (isDecorEnable) { + uint32_t width = rect.width_ - decoration.Horizontal(); + uint32_t height = rect.height_ - decoration.Vertical(); + if (width > height * aspectRatio_) { + rect.width_ = height * aspectRatio_ + decoration.Horizontal(); + } else { + rect.height_ = + width / aspectRatio_ + decoration.Vertical(); + } + } else { + if (rect.width_ > rect.height_ * aspectRatio_) { + rect.width_ = rect.height_ * aspectRatio_; + } else { + rect.height_ = rect.width_ / aspectRatio_; + } + } + AdjustRectByLimits(sessionProperty_->GetWindowLimits(), aspectRatio_, isDecorEnable, vpr, rect); + if (std::abs(static_cast(originalRect.width_) - static_cast(rect.width_)) <= tolerancePx && + std::abs(static_cast(originalRect.height_) - static_cast(rect.height_)) <= tolerancePx) { + rect = originalRect; + return false; + } + return true; +} + void LayoutController::SetScale(float scaleX, float scaleY, float pivotX, float pivotY) { scaleX_ = scaleX; diff --git a/window_scene/session/host/src/scene_session.cpp b/window_scene/session/host/src/scene_session.cpp index 2a037c2232..1fd85755b8 100644 --- a/window_scene/session/host/src/scene_session.cpp +++ b/window_scene/session/host/src/scene_session.cpp @@ -1407,6 +1407,7 @@ static WSError CheckAspectRatioValid(const sptr& session, float ra return WSError::WS_ERROR_INVALID_PARAM; } auto limits = sessionProperty->GetWindowLimits(); + // FIXME:需要改为 if (session->IsDecorEnable()) { if (limits.minWidth_ && limits.maxHeight_ && MathHelper::LessNotEqual(ratio, SessionUtils::ToLayoutWidth(limits.minWidth_, vpr) / @@ -1433,6 +1434,37 @@ static WSError CheckAspectRatioValid(const sptr& session, float ra return WSError::WS_OK; } +static WSError CheckAspectRatioValid( + const sptr& session, float ratio, const WindowDecoration& decoration) +{ + if (MathHelper::NearZero(ratio)) { + return WSError::WS_OK; + } + if (!session) { + return WSError::WS_ERROR_INVALID_PARAM; + } + auto sessionProperty = session->GetSessionProperty(); + if (!sessionProperty) { + return WSError::WS_ERROR_INVALID_PARAM; + } + auto limits = sessionProperty->GetWindowLimits(); + uint32_t horizontal = session->IsDecorEnable() ? decoration.Horizontal() : 0; + uint32_t vertical = session->IsDecorEnable() ? decoration.Vertical() : 0; + float minValidRatio = (limits.minWidth_ - horizontal) / (limits.maxHeight_ - vertical); + if (MathHelper::LessNotEqual(ratio, minValidRatio)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "aspectRatio(%{public}f) is smaller than minValidRatio(%{public}f)", + ratio, minValidRatio); + return WSError::WS_ERROR_INVALID_PARAM; + } + float maxValidRatio = (limits.maxWidth_ - horizontal) / (limits.minHeight_ - vertical); + if (MathHelper::GreatNotEqual(ratio, maxValidRatio)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "aspectRatio(%{public}f) is bigger than maxValidRatio(%{public}f)", + ratio, maxValidRatio); + return WSError::WS_ERROR_INVALID_PARAM; + } + return WSError::WS_OK; +} + /** @note @window.layout */ WSError SceneSession::SetAspectRatio(float ratio) { @@ -1469,6 +1501,41 @@ WSError SceneSession::SetAspectRatio(float ratio) }, __func__); } +WSError SceneSession::SetContentAspectRatio( + float ratio, bool isPersistent, bool needUpdateRect, const WindowDecoration& decoration) +{ + return PostTask([weakThis = wptr(this), ratio, isPersistent, needUpdateRect, decoration, where = __func__] { + auto session = weakThis.promote(); + if (!session) { + TLOGNE(WmsLogTag::WMS_LAYOUT, "%{public}s: session is null", where); + return WSError::WS_ERROR_DESTROYED_OBJECT; + } + WSError ret = CheckAspectRatioValid(session, ratio, decoration); + if (ret != WSError::WS_OK) { + return ret; + } + session->Session::SetAspectRatio(ratio); + if (session->moveDragController_) { + session->moveDragController_->SetAspectRatio(ratio); + } + if (isPersistent) { + session->SaveAspectRatio(ratio); + } + if (needUpdateRect) { + WSRect adjustedRect = session->GetSessionRect(); + TLOGNI(WmsLogTag::WMS_LAYOUT, "%{public}s Before adjusting, the id:%{public}d, the current rect:%{public}s, " + "content ratio:%{public}f", where, session->GetPersistentId(), adjustedRect.ToString().c_str(), ratio); + if (session->layoutController_->AdjustRectByAspectRatio(adjustedRect, session->IsDecorEnable())) { + TLOGNI(WmsLogTag::WMS_LAYOUT, + "%{public}s After adjusting, the id:%{public}d, the adjusted rect:%{public}s", + where, session->GetPersistentId(), adjustedRect.ToString().c_str()); + session->NotifySessionRectChange(adjustedRect, SizeChangeReason::RESIZE); + } + } + return WSError::WS_OK; + }, __func__); +} + /** @note @window.layout */ WSError SceneSession::UpdateRect(const WSRect& rect, SizeChangeReason reason, const std::string& updateReason, const std::shared_ptr& rsTransaction) diff --git a/window_scene/session/host/src/zidl/session_proxy.cpp b/window_scene/session/host/src/zidl/session_proxy.cpp index 00d3dd6a18..124cbb0048 100644 --- a/window_scene/session/host/src/zidl/session_proxy.cpp +++ b/window_scene/session/host/src/zidl/session_proxy.cpp @@ -1644,6 +1644,50 @@ WSError SessionProxy::SetAspectRatio(float ratio) return static_cast(ret); } +/** @note @window.layout */ +WSError SessionProxy::SetContentAspectRatio( + float ratio, bool isPersistent, bool needUpdateRect, const WindowDecoration& decoration) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to write interface token"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteFloat(ratio)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to write ratio"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteBool(isPersistent)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to write isPersistent"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteBool(needUpdateRect)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to write needUpdateRect"); + return WSError::WS_ERROR_IPC_FAILED; + } + if (!data.WriteUint32(static_cast(decoration.left)) || + !data.WriteUint32(static_cast(decoration.top)) || + !data.WriteUint32(static_cast(decoration.right)) || + !data.WriteUint32(static_cast(decoration.bottom))) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to write decoration"); + return WSError::WS_ERROR_IPC_FAILED; + } + sptr remote = Remote(); + if (remote == nullptr) { + WLOGFE("remote is null"); + return WSError::WS_ERROR_IPC_FAILED; + } + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + int sendRet = remote->SendRequest( + static_cast(SessionInterfaceCode::TRANS_ID_SET_CONTENT_ASPECT_RATIO), data, reply, option); + if (sendRet != ERR_NONE) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to send request, error = %{public}d", sendRet); + return WSError::WS_ERROR_IPC_FAILED; + } + return WSError::WS_OK; +} + WSError SessionProxy::UpdateWindowSceneAfterCustomAnimation(bool isAdd) { MessageParcel data; diff --git a/window_scene/session/host/src/zidl/session_stub.cpp b/window_scene/session/host/src/zidl/session_stub.cpp index 455a2f243f..902fa4b3e1 100644 --- a/window_scene/session/host/src/zidl/session_stub.cpp +++ b/window_scene/session/host/src/zidl/session_stub.cpp @@ -143,6 +143,8 @@ int SessionStub::ProcessRemoteRequest(uint32_t code, MessageParcel& data, Messag return HandleGetTargetOrientationConfigInfo(data, reply); case static_cast(SessionInterfaceCode::TRANS_ID_SET_ASPECT_RATIO): return HandleSetAspectRatio(data, reply); + case static_cast(SessionInterfaceCode::TRANS_ID_SET_CONTENT_ASPECT_RATIO): + return HandleSetContentAspectRatio(data, reply); case static_cast(SessionInterfaceCode::TRANS_ID_UPDATE_WINDOW_ANIMATION_FLAG): return HandleSetWindowAnimationFlag(data, reply); case static_cast(SessionInterfaceCode::TRANS_ID_UPDATE_CUSTOM_ANIMATION): @@ -1244,6 +1246,37 @@ int SessionStub::HandleSetAspectRatio(MessageParcel& data, MessageParcel& reply) return ERR_NONE; } +/** @note @window.layout */ +int SessionStub::HandleSetContentAspectRatio(MessageParcel& data, MessageParcel& reply) +{ + float ratio = 0.0f; + if (!data.ReadFloat(ratio)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to read ratio"); + return ERR_INVALID_DATA; + } + bool isPersistent = false; + if (!data.ReadBool(isPersistent)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to read isPersistent"); + return ERR_INVALID_DATA; + } + bool needUpdateRect = false; + if (!data.ReadBool(needUpdateRect)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to read needUpdateRect"); + return ERR_INVALID_DATA; + } + uint32_t left = 0; + uint32_t top = 0; + uint32_t right = 0; + uint32_t bottom = 0; + if (!data.ReadUint32(left) || !data.ReadUint32(top) || !data.ReadUint32(right) || !data.ReadUint32(bottom)) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Failed to read decoration"); + return ERR_INVALID_DATA; + } + WindowDecoration decoration{left, top, right, bottom}; + SetContentAspectRatio(ratio, isPersistent, needUpdateRect, decoration); + return ERR_NONE; +} + int SessionStub::HandleUpdateWindowSceneAfterCustomAnimation(MessageParcel& data, MessageParcel& reply) { WLOGD("HandleUpdateWindowSceneAfterCustomAnimation!"); diff --git a/wm/include/window_session_impl.h b/wm/include/window_session_impl.h index ec8fad751c..d668b51fa1 100644 --- a/wm/include/window_session_impl.h +++ b/wm/include/window_session_impl.h @@ -193,6 +193,7 @@ public: uint32_t GetWindowId() const override; uint64_t GetDisplayId() const override; Rect GetRect() const override; + std::optional GetDrawableRect() const override; bool GetFocusable() const override; std::string GetContentInfo(BackupAndRestoreType type = BackupAndRestoreType::CONTINUATION) override; WMError SetRestoredRouterStack(const std::string& routerStack) override; diff --git a/wm/src/window_scene_session_impl.cpp b/wm/src/window_scene_session_impl.cpp index cf31a7e89a..e89d68b605 100644 --- a/wm/src/window_scene_session_impl.cpp +++ b/wm/src/window_scene_session_impl.cpp @@ -2607,6 +2607,37 @@ WMError WindowSceneSessionImpl::ResetAspectRatio() return static_cast(hostSession->SetAspectRatio(0.0f)); } +WMError WindowSceneSessionImpl::SetContentAspectRatio(float ratio, bool isPersistent, bool needUpdateRect) +{ + if (IsWindowSessionInvalid()) { + TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid session"); + return WMError::WM_ERROR_INVALID_WINDOW; + } + auto hostSession = GetHostSession(); + CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR); + if (ratio == MathHelper::INF || ratio == MathHelper::NAG_INF || std::isnan(ratio) || MathHelper::NearZero(ratio)) { + TLOGE(WmsLogTag::WM_LAYOUT, "failed, because of wrong value: %{public}f", ratio); + return WMError::WM_ERROR_INVALID_PARAM; + } + WindowDecoration decoration; + auto rect = GetRect(); + auto drawableRect = GetDrawableRect(); + if (drawableRect) { + decoration = ComputeWindowDecoration(rect, *drawableRect); + } else { + TLOGW(WmsLogTag::WM_LAYOUT, "Failed to get drawableRect, use default decoration"); + // FIXME: 这里是以 VP 为单位的,不是 PX + decoration = {WINDOW_FRAME_WIDTH, WINDOW_TITLE_BAR_HEIGHT, WINDOW_FRAME_WIDTH, WINDOW_FRAME_WIDTH}; + } + TLOGD(WmsLogTag::WM_LAYOUT, + "ratio: %{public}f, isPersistent: %{public}d, needUpdateRect: %{public}d, decoration: %{public}s", + ratio, isPersistent, needUpdateRect, decoration.ToString().c_str()); + if (hostSession->SetContentAspectRatio(ratio, isPersistent, needUpdateRect, decoration) != WSError::WS_OK) { + return WMError::WM_ERROR_INVALID_PARAM; + } + return WMError::WM_OK; +} + /** @note @window.hierarchy */ WMError WindowSceneSessionImpl::RaiseToAppTop() { diff --git a/wm/src/window_session_impl.cpp b/wm/src/window_session_impl.cpp index 10068cf229..a9d7362ca6 100644 --- a/wm/src/window_session_impl.cpp +++ b/wm/src/window_session_impl.cpp @@ -1830,6 +1830,18 @@ Rect WindowSessionImpl::GetRect() const return property_->GetWindowRect(); } +std::optional WindowSessionImpl::GetDrawableRect() const +{ + Rect drawableRect = Rect::EMPTY_RECT; + auto uiContent = GetUIContentSharedPtr(); + if (uiContent == nullptr) { + TLOGW(WmsLogTag::WMS_LAYOUT, "Failed to get drawableRect, uiContent is nullptr"); + return std::nullopt; + } + uiContent->GetWindowPaintSize(drawableRect); + return drawableRect; +} + void WindowSessionImpl::UpdateTitleButtonVisibility() { std::shared_ptr uiContent = GetUIContentSharedPtr(); -- Gitee