From babff29507e49daf8d1d296df1b95ba31ef94fc5 Mon Sep 17 00:00:00 2001 From: quchongchong Date: Wed, 16 Apr 2025 00:00:47 +0800 Subject: [PATCH] =?UTF-8?q?UEC=E8=92=99=E5=B1=82=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: quchongchong Change-Id: I4963f8dbb7990424133c858018d3375031c149e6 Signed-off-by: quchongchong --- adapter/ohos/entrance/ui_content_impl.cpp | 2 + adapter/ohos/osal/modal_ui_extension_impl.cpp | 68 ++++ .../preview/osal/modal_ui_extension_impl.cpp | 25 ++ frameworks/core/common/modal_ui_extension.h | 21 ++ .../components/dialog/dialog_properties.h | 44 +++ .../core/components_ng/pattern/BUILD.gn | 1 + .../dialog/dialog_layout_algorithm.cpp | 82 +---- .../pattern/dialog/dialog_layout_algorithm.h | 2 - .../pattern/dialog/dialog_pattern.cpp | 76 +++-- .../pattern/dialog/dialog_pattern.h | 12 + .../pattern/overlay/overlay_manager.cpp | 33 +- .../pattern/overlay/overlay_mask_manager.cpp | 297 ++++++++++++++++++ .../pattern/overlay/overlay_mask_manager.h | 59 ++++ .../ui_extension_pattern.cpp | 2 + .../ui_extension/ui_extension_config.h | 2 + test/mock/adapter/mock_modal_ui_extension.cpp | 25 ++ test/unittest/BUILD.gn | 1 + .../pattern/dialog/dialog_model_test_ng.cpp | 79 ----- .../pattern/dialog/dialog_pattern_test_ng.cpp | 5 - test/unittest/core/pattern/web/BUILD.gn | 1 + 20 files changed, 630 insertions(+), 207 deletions(-) create mode 100644 frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.cpp create mode 100644 frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.h diff --git a/adapter/ohos/entrance/ui_content_impl.cpp b/adapter/ohos/entrance/ui_content_impl.cpp index fa06cfc8574..f231bd8eccf 100644 --- a/adapter/ohos/entrance/ui_content_impl.cpp +++ b/adapter/ohos/entrance/ui_content_impl.cpp @@ -112,6 +112,7 @@ #include "core/components_ng/base/view_abstract.h" #include "core/components_ng/pattern/container_modal/container_modal_view.h" #include "core/components_ng/pattern/container_modal/enhance/container_modal_view_enhance.h" +#include "core/components_ng/pattern/overlay/overlay_mask_manager.h" #include "core/components_ng/pattern/text_field/text_field_manager.h" #include "core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_pattern.h" #include "core/components_ng/pattern/ui_extension/ui_extension_config.h" @@ -2355,6 +2356,7 @@ UIContentErrorCode UIContentImpl::CommonInitialize( InitializeDisplayAvailableRect(container); InitDragSummaryMap(container); + NG::OverlayMaskManager::GetInstance().RegisterOverlayHostMaskEventCallback(); // set container temp dir if (abilityContext) { diff --git a/adapter/ohos/osal/modal_ui_extension_impl.cpp b/adapter/ohos/osal/modal_ui_extension_impl.cpp index 982fce67c07..c381d80049b 100644 --- a/adapter/ohos/osal/modal_ui_extension_impl.cpp +++ b/adapter/ohos/osal/modal_ui_extension_impl.cpp @@ -13,7 +13,9 @@ * limitations under the License. */ +#include "want.h" #include "core/common/modal_ui_extension.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_manager.h" #include "core/components_ng/pattern/ui_extension/ui_extension_model_ng.h" #include "core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_pattern.h" @@ -39,4 +41,70 @@ void ModalUIExtension::SetBindModalCallback(const RefPtr& uiExtNo CHECK_NULL_VOID(pattern); pattern->SetBindModalCallback(std::move(bindModalCallback)); } + +OHOS::AAFwk::Want GetWantFromUECHostMaskInfo(const UECHostMaskInfo& maskInfo) +{ + OHOS::AAFwk::Want want; + want.SetParam("uuid", maskInfo.uuid); + want.SetParam("instanceId", maskInfo.instanceId); + want.SetParam("overlayTag", maskInfo.overlayTag); + want.SetParam("overlayId", maskInfo.overlayId); + want.SetParam("maskAction", static_cast(maskInfo.maskAction)); + want.SetParam("maskType", static_cast(maskInfo.maskType)); + if (maskInfo.maskColor.has_value()) { + want.SetParam("maskColor", maskInfo.maskColor.value().ToString()); + } + return want; +} + +UECHostMaskInfo ModalUIExtension::GetUECHostMaskInfoFromWant(const OHOS::AAFwk::Want& want) +{ + UECHostMaskInfo maskInfo; + maskInfo.uuid = want.GetStringParam("uuid"); + maskInfo.instanceId = want.GetIntParam("instanceId", -1); + maskInfo.overlayTag = want.GetStringParam("overlayTag"); + maskInfo.overlayId = want.GetIntParam("overlayId", -1); + maskInfo.maskAction = static_cast(want.GetIntParam("maskAction", 0)); + maskInfo.maskType = static_cast(want.GetIntParam("maskType", 0)); + if (want.HasParameter("maskColor")) { + maskInfo.maskColor = Color::FromString(want.GetStringParam("maskColor")); + } + return maskInfo; +} + +void ModalUIExtension::RegisterBusinessConsumeCallbackOnUEA(const RefPtr& uiExtMgr, + NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback) +{ + CHECK_NULL_VOID(uiExtMgr); + uiExtMgr->RegisterBusinessDataConsumeCallback(code, std::move(callback)); +} + +void ModalUIExtension::RegisterBusinessConsumeCallbackOnHost( + const RefPtr& uiExtNode, NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback) +{ + CHECK_NULL_VOID(uiExtNode); + auto pattern = uiExtNode->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->RegisterUIExtBusinessConsumeCallback(code, std::move(callback)); +} + +bool ModalUIExtension::SendOverlayMaskInfoToUEA(const RefPtr& uiExtNode, const UECHostMaskInfo& info, + NG::UIContentBusinessCode code, NG::BusinessDataSendType type) +{ + CHECK_NULL_RETURN(uiExtNode, false); + auto pattern = uiExtNode->GetPattern(); + CHECK_NULL_RETURN(pattern, false); + + OHOS::AAFwk::Want data = GetWantFromUECHostMaskInfo(info); + return pattern->SendBusinessData(code, std::move(data), type); +} + +bool ModalUIExtension::SendOverlayMaskInfoToHost(const RefPtr& uiExtMgr, + const UECHostMaskInfo& info, NG::UIContentBusinessCode code, NG::BusinessDataSendType type) +{ + CHECK_NULL_RETURN(uiExtMgr, false); + + OHOS::AAFwk::Want data = GetWantFromUECHostMaskInfo(info); + return uiExtMgr->SendBusinessToHost(code, std::move(data), type); +} } // namespace OHOS::Ace diff --git a/adapter/preview/osal/modal_ui_extension_impl.cpp b/adapter/preview/osal/modal_ui_extension_impl.cpp index 9e5ab7015a5..868aaee6e93 100644 --- a/adapter/preview/osal/modal_ui_extension_impl.cpp +++ b/adapter/preview/osal/modal_ui_extension_impl.cpp @@ -32,4 +32,29 @@ void ModalUIExtension::SetBindModalCallback(const RefPtr& uiExtNo std::function&& bindModalCallback) { } + +UECHostMaskInfo ModalUIExtension::GetUECHostMaskInfoFromWant(const AAFwk::Want& data) +{ + return {}; +} + +void ModalUIExtension::RegisterBusinessConsumeCallbackOnUEA(const RefPtr& uiExtMgr, + NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback) +{} + +void ModalUIExtension::RegisterBusinessConsumeCallbackOnHost( + const RefPtr& uiExtNode, NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback) +{} + +bool ModalUIExtension::SendOverlayMaskInfoToUEA(const RefPtr& uiExtNode, const UECHostMaskInfo& info, + NG::UIContentBusinessCode code, NG::BusinessDataSendType type) +{ + return false; +} + +bool ModalUIExtension::SendOverlayMaskInfoToHost(const RefPtr& uiExtMgr, + const UECHostMaskInfo& info, NG::UIContentBusinessCode code, NG::BusinessDataSendType type) +{ + return false; +} } // namespace OHOS::Ace diff --git a/frameworks/core/common/modal_ui_extension.h b/frameworks/core/common/modal_ui_extension.h index 203507f2674..6c81e28c70e 100644 --- a/frameworks/core/common/modal_ui_extension.h +++ b/frameworks/core/common/modal_ui_extension.h @@ -18,7 +18,9 @@ #include +#include "core/components/dialog/dialog_properties.h" #include "core/components_ng/base/frame_node.h" +#include "core/components_ng/pattern/ui_extension/ui_extension_config.h" #include "core/components_ng/pattern/ui_extension/ui_extension_model.h" namespace OHOS::AAFwk { @@ -27,8 +29,13 @@ class Want; namespace OHOS::Ace { struct ModalUIExtensionCallbacks; +using BusinessDataUECConsumeCallback = std::function; } // namespace OHOS::Ace +namespace OHOS::Ace::NG { +class UIExtensionManager; +} // namespace OHOS::Ace::NG + namespace OHOS::Ace { class ModalUIExtension final { public: @@ -39,6 +46,20 @@ public: static void SetBindModalCallback(const RefPtr& uiExtNode, std::function&& bindModalCallback); + + static UECHostMaskInfo GetUECHostMaskInfoFromWant(const AAFwk::Want& data); + + static void RegisterBusinessConsumeCallbackOnUEA(const RefPtr& uiExtMgr, + NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback); + + static void RegisterBusinessConsumeCallbackOnHost(const RefPtr& uiExtNode, + NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback); + + static bool SendOverlayMaskInfoToUEA(const RefPtr& uiExtNode, const UECHostMaskInfo& info, + NG::UIContentBusinessCode code, NG::BusinessDataSendType type = NG::BusinessDataSendType::ASYNC); + + static bool SendOverlayMaskInfoToHost(const RefPtr& uiExtMgr, const UECHostMaskInfo& info, + NG::UIContentBusinessCode code, NG::BusinessDataSendType type = NG::BusinessDataSendType::ASYNC); }; } // namespace OHOS::Ace diff --git a/frameworks/core/components/dialog/dialog_properties.h b/frameworks/core/components/dialog/dialog_properties.h index 6814017dfe6..51e5860b201 100644 --- a/frameworks/core/components/dialog/dialog_properties.h +++ b/frameworks/core/components/dialog/dialog_properties.h @@ -246,6 +246,7 @@ struct DialogProperties { bool isShowInSubWindow = false; DialogButtonDirection buttonDirection = DialogButtonDirection::AUTO; bool isMask = false; + bool isUECHostMask = false; bool isModal = true; std::optional enableHoverMode; bool isSceneBoardDialog = false; @@ -355,6 +356,49 @@ struct PromptDialogAttr { WeakPtr customCNode; }; +enum class UECHostMaskAction { + NONE = 0, + MOUNT, + UNMOUNT, + UPDATE, + CLICK, +}; + +enum class UECHostMaskType { + NONE = 0, + DIALOG, + BIND_SHEET, +}; + +struct UECHostMaskInfo { + std::string uuid; + int32_t instanceId = -1; + + std::string overlayTag; // the tag of overlay node on UEA + int32_t overlayId = -1; // the id of overlay node on UEA + + std::optional maskColor; + UECHostMaskAction maskAction = UECHostMaskAction::NONE; + UECHostMaskType maskType = UECHostMaskType::NONE; + + std::string ToString() const + { + std::stringstream ss; + ss << "uuid: " << uuid << ", "; + ss << "instanceId: " << instanceId << ", "; + ss << "overlayTag: " << overlayTag << ", "; + ss << "overlayId: " << overlayId << ", "; + if (maskColor.has_value()) { + ss << "maskColor: " << maskColor.value().ToString() << ", "; + } + ss << "maskAction: " << static_cast(maskAction) << ", "; + ss << "maskType: " << static_cast(maskType); + + std::string output = ss.str(); + return output; + }; +}; + } // namespace OHOS::Ace #endif // FOUNDATION_ACE_ACE_ENGINE_FRAMEWORKS_CORE_COMPONENTS_COMMON_PROPERTIES_DIALOG_PROPERTIES_H diff --git a/frameworks/core/components_ng/pattern/BUILD.gn b/frameworks/core/components_ng/pattern/BUILD.gn index ed565bf9ae6..6ce2f9aad10 100644 --- a/frameworks/core/components_ng/pattern/BUILD.gn +++ b/frameworks/core/components_ng/pattern/BUILD.gn @@ -315,6 +315,7 @@ build_component_ng("pattern_ng") { "overlay/modal_presentation_pattern.cpp", "overlay/overlay_container_pattern.cpp", "overlay/overlay_manager.cpp", + "overlay/overlay_mask_manager.cpp", "overlay/popup_base_pattern.cpp", "overlay/sheet_drag_bar_paint_method.cpp", "overlay/sheet_drag_bar_pattern.cpp", diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.cpp index 07bf3d25d17..2bfe69feb80 100644 --- a/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.cpp @@ -42,7 +42,6 @@ constexpr double HALF = 2.0; constexpr double LANDSCAPE_DIALOG_WIDTH_RATIO = 0.75; constexpr Dimension SCROLL_MIN_HEIGHT_SUITOLD = 100.0_vp; constexpr int32_t TEXT_ALIGN_CONTENT_CENTER = 1; -constexpr int32_t EXTRA_MASK_NODE_INDEX = 1; } // namespace void DialogLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) @@ -572,9 +571,6 @@ void DialogLayoutAlgorithm::ProcessMaskRect( dialogContext->UpdateClipEdge(true); } } - if (isUIExtensionSubWindow_ && isModal_) { - ClipUIExtensionSubWindowContent(dialog); - } auto gestureHub = hub->GetOrCreateGestureEventHub(); std::vector mouseResponseRegion; mouseResponseRegion.emplace_back(width, height, offset); @@ -582,26 +578,6 @@ void DialogLayoutAlgorithm::ProcessMaskRect( gestureHub->SetResponseRegion(mouseResponseRegion); } -std::optional DialogLayoutAlgorithm::GetMaskRect(const RefPtr& dialog) -{ - std::optional maskRect; - auto dialogPattern = dialog->GetPattern(); - CHECK_NULL_RETURN(dialogPattern, maskRect); - maskRect = dialogPattern->GetDialogProperties().maskRect; - if (!isUIExtensionSubWindow_) { - return maskRect; - } - - if (expandDisplay_ && hostWindowRect_.GetSize().IsPositive()) { - auto offset = DimensionOffset(Dimension(hostWindowRect_.GetX()), Dimension(hostWindowRect_.GetY())); - maskRect = DimensionRect(Dimension(hostWindowRect_.Width()), Dimension(hostWindowRect_.Height()), offset); - } else { - maskRect = DimensionRect(CalcDimension(1, DimensionUnit::PERCENT), CalcDimension(1, DimensionUnit::PERCENT), - DimensionOffset(CalcDimension(0, DimensionUnit::VP), CalcDimension(0, DimensionUnit::VP))); - } - return maskRect; -} - void DialogLayoutAlgorithm::UpdateCustomMaskNodeLayout(const RefPtr& dialog) { auto maskNodePtr = dialog->GetChildByIndex(1); @@ -639,8 +615,7 @@ void DialogLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) auto dialogPattern = frameNode->GetPattern(); CHECK_NULL_VOID(dialogPattern); if (isModal_ && dialogPattern->GetDialogProperties().maskRect.has_value()) { - std::optional maskRect = GetMaskRect(frameNode); - ProcessMaskRect(maskRect, frameNode, true); + ProcessMaskRect(dialogPattern->GetDialogProperties().maskRect, frameNode, true); } if (hasAddMaskNode_) { UpdateCustomMaskNodeLayout(frameNode); @@ -662,8 +637,7 @@ void DialogLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) dialogOffset_ = dialogProp->GetDialogOffset().value_or(DimensionOffset()); alignment_ = dialogProp->GetDialogAlignment().value_or(DialogAlignment::DEFAULT); topLeftPoint_ = ComputeChildPosition(childSize, dialogProp, selfSize); - auto isNonUIExtensionSubwindow = isShowInSubWindow_ && !isUIExtensionSubWindow_; - if ((!isModal_ || isNonUIExtensionSubwindow) && !dialogProp->GetIsSceneBoardDialog().value_or(false)) { + if ((!isModal_ || isShowInSubWindow_) && !dialogProp->GetIsSceneBoardDialog().value_or(false)) { ProcessMaskRect( DimensionRect(Dimension(childSize.Width()), Dimension(childSize.Height()), DimensionOffset(topLeftPoint_)), frameNode); @@ -681,8 +655,7 @@ void DialogLayoutAlgorithm::AvoidScreen( auto availableRect = OverlayManager::GetDisplayAvailableRect(dialogProp->GetHost()); auto overScreen = LessNotEqual(availableRect.Width(), childSize.Width()) || LessNotEqual(availableRect.Height(), childSize.Height()); - auto needAvoidScreen = - SystemProperties::IsSuperFoldDisplayDevice() && !isModal_ && isUIExtensionSubWindow_ && !overScreen; + auto needAvoidScreen = SystemProperties::IsSuperFoldDisplayDevice() && isUIExtensionSubWindow_ && !overScreen; if (!needAvoidScreen) { return; } @@ -751,18 +724,6 @@ void DialogLayoutAlgorithm::SetSubWindowHotarea( } else { rect = Rect(0.0f, 0.0f, selfSize.Width(), selfSize.Height()); } - if (isUIExtensionSubWindow_ && isModal_) { - if (expandDisplay_) { - auto isValid = hostWindowRect_.GetSize().IsPositive(); - auto hostOffset = Offset(hostWindowRect_.GetX(), hostWindowRect_.GetY()); - auto hostSize = Size(hostWindowRect_.Width(), hostWindowRect_.Height()); - rect = isValid ? Rect(hostOffset, hostSize) : Rect(0.0f, 0.0f, selfSize.Width(), selfSize.Height()); - auto contentRect = Rect(topLeftPoint_.GetX(), topLeftPoint_.GetY(), childSize.Width(), childSize.Height()); - rects.emplace_back(contentRect); - } else { - rect = Rect(0.0f, 0.0f, selfSize.Width(), selfSize.Height()); - } - } rects.emplace_back(rect); SubwindowManager::GetInstance()->SetHotAreas(rects, SubwindowType::TYPE_DIALOG, frameNodeId, subWindowId_); } @@ -1049,43 +1010,6 @@ void DialogLayoutAlgorithm::UpdateSafeArea(const RefPtr& frameNode) TAG_LOGI(AceLogTag::ACE_DIALOG, "safeAreaInsets: %{public}s", safeAreaInsets_.ToString().c_str()); } -void DialogLayoutAlgorithm::ClipUIExtensionSubWindowContent(const RefPtr& dialog) -{ - CHECK_NULL_VOID(dialog); - auto isFullScreen = - IsGetExpandDisplayValidHeight() && NearEqual(expandDisplayValidHeight_, hostWindowRect_.Height()); - auto maskNodePtr = dialog->GetChildByIndex(EXTRA_MASK_NODE_INDEX); - CHECK_NULL_VOID(maskNodePtr); - auto maskNode = AceType::DynamicCast(maskNodePtr); - CHECK_NULL_VOID(maskNode); - auto maskNodeLayoutProp = maskNode->GetLayoutProperty(); - CHECK_NULL_VOID(maskNodeLayoutProp); - auto maskGeometryNode = maskNode->GetGeometryNode(); - CHECK_NULL_VOID(maskGeometryNode); - if (expandDisplay_) { - maskNodeLayoutProp->ClearUserDefinedIdealSize(true, true); - SizeF realSize; - realSize.SetWidth(hostWindowRect_.Width()); - realSize.SetHeight(hostWindowRect_.Height()); - maskGeometryNode->SetFrameSize(realSize); - OffsetF offset; - offset.SetX(hostWindowRect_.GetX()); - offset.SetY(hostWindowRect_.GetY()); - maskGeometryNode->SetFrameOffset(offset); - if (!isFullScreen) { - auto maskNodeContext = maskNode->GetRenderContext(); - CHECK_NULL_VOID(maskNodeContext); - maskNodeContext->UpdateBorderRadius(NG::BorderRadiusPropertyT(CONTAINER_OUTER_RADIUS)); - } - } else { - maskNodeLayoutProp->UpdateUserDefinedIdealSize( - CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(1.0, DimensionUnit::PERCENT))); - maskGeometryNode->SetFrameOffset(OffsetF(0, 0)); - maskNode->Measure(dialog->GetLayoutConstraint()); - } - maskNode->Layout(); -} - void DialogLayoutAlgorithm::UpdateIsScrollHeightNegative(LayoutWrapper* layoutWrapper, float height) { if (height < SCROLL_MIN_HEIGHT_SUITOLD.ConvertToPx()) { diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.h b/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.h index 2fc34b0660b..e08e8126b6b 100644 --- a/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/dialog/dialog_layout_algorithm.h @@ -81,7 +81,6 @@ private: void ProcessMaskRect(std::optional maskRect, const RefPtr& dialog, bool isMask = false); void SetSubWindowHotarea( const RefPtr& dialogProp, SizeF childSize, SizeF selfSize, int32_t frameNodeId); - std::optional GetMaskRect(const RefPtr& dialog); void UpdateTouchRegion(); @@ -95,7 +94,6 @@ private: void UpdateSafeArea(const RefPtr& frameNode); void UpdateChildLayoutConstraint(const RefPtr& dialogProp, LayoutConstraintF& childLayoutConstraint, RefPtr& childLayoutWrapper); - void ClipUIExtensionSubWindowContent(const RefPtr& dialog); void AdjustHeightForKeyboard(LayoutWrapper* layoutWrapper, const RefPtr& child); void UpdateIsScrollHeightNegative(LayoutWrapper* layoutWrapper, float height); void UpdateChildMaxSizeHeight(SizeT& maxSize); diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp index 7720f261886..b1b6f191192 100644 --- a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp +++ b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.cpp @@ -52,6 +52,7 @@ #include "core/components_ng/pattern/navrouter/navdestination_pattern.h" #include "core/components_ng/pattern/overlay/dialog_manager.h" #include "core/components_ng/pattern/overlay/overlay_manager.h" +#include "core/components_ng/pattern/overlay/overlay_mask_manager.h" #include "core/components_ng/pattern/relative_container/relative_container_model_ng.h" #include "core/components_ng/pattern/relative_container/relative_container_pattern.h" #include "core/components_ng/pattern/scroll/scroll_pattern.h" @@ -249,26 +250,42 @@ void DialogPattern::HandleClick(const GestureEvent& info) auto&& clickPosition = info.GetGlobalLocation(); if (!contentRect.IsInRegion( PointF(clickPosition.GetX() - globalOffset.GetX(), clickPosition.GetY() - globalOffset.GetY()))) { - auto overlayManager = GetOverlayManager(nullptr); - CHECK_NULL_VOID(overlayManager); - if (this->CallDismissInNDK(static_cast(DialogDismissReason::DIALOG_TOUCH_OUTSIDE))) { + if (dialogProperties_.isUECHostMask) { + NG::OverlayMaskManager::GetInstance().SendDialogMaskEventToUEA(host, UECHostMaskAction::CLICK); return; - } else if (this->ShouldDismiss()) { - overlayManager->SetDismissDialogId(host->GetId()); - DialogManager::GetInstance().SetDismissDialogInfo(host->GetId(), host->GetTag()); - auto currentId = Container::CurrentId(); - this->CallOnWillDismiss(static_cast(DialogDismissReason::DIALOG_TOUCH_OUTSIDE), currentId); - TAG_LOGI(AceLogTag::ACE_DIALOG, "Dialog Should Dismiss, currentId: %{public}d", currentId); - return; - } - PopDialog(-1); - if (overlayManager->isMaskNode(GetHost()->GetId())) { - overlayManager->PopModalDialog(GetHost()->GetId()); } + + CloseDialogByClick(); } } } +void DialogPattern::CloseDialogByClick() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto overlayManager = GetOverlayManager(nullptr); + CHECK_NULL_VOID(overlayManager); + + if (CallDismissInNDK(static_cast(DialogDismissReason::DIALOG_TOUCH_OUTSIDE))) { + return; + } + + if (ShouldDismiss()) { + overlayManager->SetDismissDialogId(host->GetId()); + DialogManager::GetInstance().SetDismissDialogInfo(host->GetId(), host->GetTag()); + auto currentId = Container::CurrentId(); + CallOnWillDismiss(static_cast(DialogDismissReason::DIALOG_TOUCH_OUTSIDE), currentId); + TAG_LOGI(AceLogTag::ACE_DIALOG, "Dialog Should Dismiss, currentId: %{public}d", currentId); + return; + } + + PopDialog(-1); + if (overlayManager->isMaskNode(host->GetId()) && !dialogProperties_.isUECHostMask) { + overlayManager->PopModalDialog(host->GetId()); + } +} + void DialogPattern::PopDialog(int32_t buttonIdx = -1) { auto host = GetHost(); @@ -563,8 +580,7 @@ void DialogPattern::AddExtraMaskNode(const DialogProperties& props) auto dialogTheme = pipeline->GetTheme(); CHECK_NULL_VOID(dialogTheme); auto needAddMaskNode = props.maskTransitionEffect != nullptr || props.dialogTransitionEffect != nullptr; - if ((IsUIExtensionSubWindow() && props.isModal) || - (needAddMaskNode && props.isModal && !props.isShowInSubWindow)) { + if (needAddMaskNode && props.isModal && !props.isShowInSubWindow) { auto extraMaskNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr(true)); CHECK_NULL_VOID(extraMaskNode); @@ -1887,15 +1903,7 @@ void DialogPattern::UpdateHostWindowRect() return; } - auto needUpdate = true; - if (SystemProperties::IsSuperFoldDisplayDevice()) { - auto container = AceEngine::Get().GetContainer(currentId); - auto isHalfFold = container && container->GetCurrentFoldStatus() == FoldStatus::HALF_FOLD; - auto subwindow = SubwindowManager::GetInstance()->GetSubwindowById(currentId); - needUpdate = isHalfFold && subwindow && subwindow->IsSameDisplayWithParentWindow() && dialogProperties_.isModal; - } - - if (needUpdate) { + if (!SystemProperties::IsSuperFoldDisplayDevice()) { InitHostWindowRect(); host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); } @@ -2243,6 +2251,7 @@ void DialogPattern::OnAttachToMainTree() { auto host = GetHost(); CHECK_NULL_VOID(host); + MountMaskToUECHost(); auto parentNode = AceType::DynamicCast(host->GetParent()); CHECK_NULL_VOID(parentNode); if (parentNode->GetTag() != V2::NAVDESTINATION_VIEW_ETS_TAG) { @@ -2256,6 +2265,23 @@ void DialogPattern::OnAttachToMainTree() dialogRenderContext->UpdateZIndex(zIndex + 1); } +void DialogPattern::MountMaskToUECHost() +{ + auto hasHostMask = !hostMaskInfo_.uuid.empty(); + if (dialogProperties_.isMask || hasHostMask) { + return; + } + + auto host = GetHost(); + CHECK_NULL_VOID(host); + + if (isUIExtensionSubWindow_ && dialogProperties_.isModal) { + auto pipeline = host->GetContextRefPtr(); + auto instanceId = pipeline ? pipeline->GetInstanceId() : -1; + NG::OverlayMaskManager::GetInstance().SendDialogMaskInfoToHost(host, UECHostMaskAction::MOUNT, instanceId); + } +} + RefPtr DialogPattern::GetOverlayManager(const RefPtr& host) { RefPtr pipeline; diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h index 0908ac94ed9..ea1d00462e5 100644 --- a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h +++ b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h @@ -318,6 +318,17 @@ public: void OverlayDismissDialog(const RefPtr& dialogNode); RefPtr GetEmbeddedOverlay(const RefPtr& context); + void MountMaskToUECHost(); + void CloseDialogByClick(); + void SetUECHostMaskInfo(UECHostMaskInfo maskInfo) + { + hostMaskInfo_ = maskInfo; + } + + UECHostMaskInfo GetUECHostMaskInfo() + { + return hostMaskInfo_; + } private: bool AvoidKeyboard() const override @@ -440,6 +451,7 @@ private: std::unordered_map> contentNodeMap_; bool isUIExtensionSubWindow_ = false; RectF hostWindowRect_; + UECHostMaskInfo hostMaskInfo_; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp index 0b161b76b43..be60695d131 100644 --- a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp +++ b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp @@ -73,6 +73,7 @@ #include "core/components_ng/pattern/overlay/keyboard_view.h" #include "core/components_ng/pattern/overlay/level_order.h" #include "core/components_ng/pattern/overlay/overlay_container_pattern.h" +#include "core/components_ng/pattern/overlay/overlay_mask_manager.h" #include "core/components_ng/pattern/overlay/sheet_manager.h" #include "core/components_ng/pattern/overlay/sheet_view.h" #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h" @@ -2897,6 +2898,7 @@ RefPtr OverlayManager::SetDialogMask(const DialogProperties& dialogPr { DialogProperties Maskarg; Maskarg.isMask = true; + Maskarg.isUECHostMask = dialogProps.isUECHostMask; Maskarg.autoCancel = dialogProps.autoCancel; Maskarg.onWillDismiss = dialogProps.onWillDismiss; Maskarg.maskColor = dialogProps.maskColor; @@ -2908,7 +2910,7 @@ RefPtr OverlayManager::SetDialogMask(const DialogProperties& dialogPr RefPtr OverlayManager::ShowDialog( const DialogProperties& dialogProps, std::function&& buildFunc, bool isRightToLeft) { - TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter"); + TAG_LOGI(AceLogTag::ACE_OVERLAY, "show dialog enter"); RefPtr customNode; // create custom builder content if (buildFunc) { @@ -3635,7 +3637,7 @@ RefPtr OverlayManager::GetDialog(int32_t dialogId) void OverlayManager::CloseDialog(const RefPtr& dialogNode) { - TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog enter"); + TAG_LOGI(AceLogTag::ACE_OVERLAY, "close dialog enter"); DeleteDialogHotAreas(dialogNode); auto dialogLayoutProp = AceType::DynamicCast(dialogNode->GetLayoutProperty()); CHECK_NULL_VOID(dialogLayoutProp); @@ -3689,6 +3691,7 @@ void OverlayManager::DeleteDialogHotAreas(const RefPtr& dialogNode) void OverlayManager::CloseDialogInner(const RefPtr& dialogNode) { + CHECK_NULL_VOID(dialogNode); RemoveDialogFromMap(dialogNode); auto topNodeId = GetTopFocusableNodeId(); PopLevelOrder(dialogNode->GetId()); @@ -3698,20 +3701,12 @@ void OverlayManager::CloseDialogInner(const RefPtr& dialogNode) return; } - auto container = Container::Current(); - auto currentId = Container::CurrentId(); - CHECK_NULL_VOID(container); - if (container->IsSubContainer()) { - currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId()); - container = AceEngine::Get().GetContainer(currentId); - CHECK_NULL_VOID(container); - } - ContainerScope scope(currentId); - auto pipelineContext = container->GetPipelineContext(); - CHECK_NULL_VOID(pipelineContext); - auto context = AceType::DynamicCast(pipelineContext); - CHECK_NULL_VOID(context); - auto overlayManager = context->GetOverlayManager(); + auto pipeline = PipelineContext::GetMainPipelineContext(); + CHECK_NULL_VOID(pipeline); + ContainerScope scope(pipeline->GetInstanceId()); + auto mainPipeline = AceType::DynamicCast(pipeline); + CHECK_NULL_VOID(mainPipeline); + auto overlayManager = mainPipeline->GetOverlayManager(); CHECK_NULL_VOID(overlayManager); overlayManager->ResetLowerNodeFocusable(dialogNode); auto dialogPattern = dialogNode->GetPattern(); @@ -3728,7 +3723,11 @@ void OverlayManager::CloseDialogInner(const RefPtr& dialogNode) CloseDialogAnimation(dialogNode); } dialogCount_--; - overlayManager->RemoveMaskFromMap(dialogNode); + if (dialogPattern->IsUIExtensionSubWindow() && !dialogPattern->GetUECHostMaskInfo().uuid.empty()) { + OverlayMaskManager::GetInstance().SendDialogMaskInfoToHost(dialogNode, UECHostMaskAction::UNMOUNT); + } else { + overlayManager->RemoveMaskFromMap(dialogNode); + } // set close button enable if (dialogCount_ == 0) { SetContainerButtonEnable(true); diff --git a/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.cpp b/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.cpp new file mode 100644 index 00000000000..07bc532b6a3 --- /dev/null +++ b/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.cpp @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2025 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. + */ + +#include "core/components_ng/pattern/overlay/overlay_mask_manager.h" + +#include "core/components_ng/pattern/dialog/dialog_pattern.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { +OverlayMaskManager::OverlayMaskManager() = default; + +OverlayMaskManager::~OverlayMaskManager() = default; + +void OverlayMaskManager::AddUECHostNodeMap(const std::string& uuid, const RefPtr& node) +{ + std::lock_guard lock(uecHostNodeMutex_); + uecHostNodeMap_.try_emplace(uuid, AceType::WeakClaim(AceType::RawPtr(node))); +} + +void OverlayMaskManager::RemoveUECHostNodeMap(const std::string& uuid) +{ + std::lock_guard lock(uecHostNodeMutex_); + uecHostNodeMap_.erase(uuid); +} + +RefPtr OverlayMaskManager::GetUECHostNode(const std::string& uuid) +{ + std::lock_guard lock(uecHostNodeMutex_); + auto result = uecHostNodeMap_.find(uuid); + if (result != uecHostNodeMap_.end()) { + return result->second.Upgrade(); + } + + return nullptr; +} + +void OverlayMaskManager::AddUECHostMaskMap(const std::string& uuid, const RefPtr& node) +{ + std::lock_guard lock(uecHostMaskMutex_); + uecHostMaskMap_.try_emplace(uuid, AceType::WeakClaim(AceType::RawPtr(node))); +} + +void OverlayMaskManager::RemoveUECHostMaskMap(const std::string& uuid) +{ + std::lock_guard lock(uecHostMaskMutex_); + uecHostMaskMap_.erase(uuid); +} + +RefPtr OverlayMaskManager::GetUECHostMaskNode(const std::string& uuid) +{ + std::lock_guard lock(uecHostMaskMutex_); + auto result = uecHostMaskMap_.find(uuid); + if (result != uecHostMaskMap_.end()) { + return result->second.Upgrade(); + } + + return nullptr; +} + +void OverlayMaskManager::RegisterOverlayHostMaskEventCallback() +{ + auto pipeline = PipelineContext::GetMainPipelineContext(); + CHECK_NULL_VOID(pipeline); + auto container = Container::GetContainer(pipeline->GetInstanceId()); + CHECK_NULL_VOID(container); + if (!container->IsUIExtensionWindow()) { + return; + } + +#ifdef WINDOW_SCENE_SUPPORTED + auto uiExtMgr = pipeline->GetUIExtensionManager(); + CHECK_NULL_VOID(uiExtMgr); + + ModalUIExtension::RegisterBusinessConsumeCallbackOnUEA( + uiExtMgr, UIContentBusinessCode::OVERLAY_MASK_EVENT, [](const AAFwk::Want& data) -> int32_t { + UECHostMaskInfo maskInfo = ModalUIExtension::GetUECHostMaskInfoFromWant(data); + TAG_LOGI(AceLogTag::ACE_OVERLAY, "UEA recv mask event from host, %{public}s", maskInfo.ToString().c_str()); + OverlayMaskManager::GetInstance().OnOverlayHostMaskEventCallback(data, maskInfo); + return 0; + }); +#endif +} + +void OverlayMaskManager::OnOverlayHostMaskEventCallback(const AAFwk::Want& data, const UECHostMaskInfo& maskInfo) +{ + auto uecNode = GetUECHostNode(maskInfo.uuid); + if (uecNode) { + TAG_LOGI(AceLogTag::ACE_OVERLAY, "current window is UEC, send host mask event to next UEC"); + auto ret = ModalUIExtension::SendOverlayMaskInfoToUEA( + uecNode, maskInfo, UIContentBusinessCode::OVERLAY_MASK_EVENT, BusinessDataSendType::ASYNC); + if (!ret) { + TAG_LOGW(AceLogTag::ACE_OVERLAY, "failed to send host mask event to UEA"); + } + return; + } + + if (maskInfo.maskType == UECHostMaskType::DIALOG) { + HandleDialogHostMaskEvent(maskInfo); + } +} + +void OverlayMaskManager::HandleDialogHostMaskEvent(const UECHostMaskInfo& maskInfo) +{ + TAG_LOGI(AceLogTag::ACE_OVERLAY, "UEA handle dialog host mask event enter"); + + auto dialog = FrameNode::GetFrameNodeOnly(maskInfo.overlayTag, maskInfo.overlayId); + CHECK_NULL_VOID(dialog); + + if (maskInfo.maskAction == UECHostMaskAction::CLICK) { + auto dialogPattern = dialog->GetPattern(); + CHECK_NULL_VOID(dialogPattern); + auto dialogProperties = dialogPattern->GetDialogProperties(); + if (dialogProperties.autoCancel) { + dialogPattern->CloseDialogByClick(); + } + } +} + +void OverlayMaskManager::RegisterOverlayHostMaskMountCallback(const RefPtr& uiextNode) +{ + CHECK_NULL_VOID(uiextNode); + ModalUIExtension::RegisterBusinessConsumeCallbackOnHost(uiextNode, UIContentBusinessCode::OVERLAY_MASK_MOUNT, + [uiextWeak = AceType::WeakClaim(AceType::RawPtr(uiextNode))](const AAFwk::Want& data) -> int32_t { + UECHostMaskInfo maskInfo = ModalUIExtension::GetUECHostMaskInfoFromWant(data); + TAG_LOGI(AceLogTag::ACE_OVERLAY, "host recv maskInfo from UEC, %{public}s", maskInfo.ToString().c_str()); + + auto uiextNode = uiextWeak.Upgrade(); + CHECK_NULL_RETURN(uiextNode, -1); + OverlayMaskManager::GetInstance().OnOverlayHostMaskMountCallback(uiextNode, data, maskInfo); + return 0; + }); +} + +void OverlayMaskManager::OnOverlayHostMaskMountCallback( + const RefPtr& uiextNode, const AAFwk::Want& data, const UECHostMaskInfo& maskInfo) +{ + CHECK_NULL_VOID(uiextNode); + auto pipeline = uiextNode->GetContextRefPtr(); + CHECK_NULL_VOID(pipeline); + auto container = Container::GetContainer(pipeline->GetInstanceId()); + CHECK_NULL_VOID(container); + + if (maskInfo.maskAction == UECHostMaskAction::UNMOUNT) { + RemoveUECHostNodeMap(maskInfo.uuid); + } else { + AddUECHostNodeMap(maskInfo.uuid, uiextNode); + } + + if (container->IsUIExtensionWindow()) { + TAG_LOGI(AceLogTag::ACE_OVERLAY, "current window is UEC, send to parnet host again"); +#ifdef WINDOW_SCENE_SUPPORTED + auto uiExtMgr = pipeline->GetUIExtensionManager(); + CHECK_NULL_VOID(uiExtMgr); + auto ret = ModalUIExtension::SendOverlayMaskInfoToHost( + uiExtMgr, maskInfo, UIContentBusinessCode::OVERLAY_MASK_MOUNT, BusinessDataSendType::ASYNC); + if (!ret) { + TAG_LOGW(AceLogTag::ACE_OVERLAY, "failed to send overlay mask info to host"); + } +#endif + return; + } + + if (maskInfo.maskType == UECHostMaskType::DIALOG) { + HostMountDialogMask(maskInfo); + } +} + +void OverlayMaskManager::HostMountDialogMask(const UECHostMaskInfo& maskInfo) +{ + TAG_LOGI(AceLogTag::ACE_OVERLAY, "host process dialog mask info enter"); + + if (maskInfo.maskAction == UECHostMaskAction::MOUNT) { + auto pipeline = PipelineContext::GetMainPipelineContext(); + CHECK_NULL_VOID(pipeline); + auto overlayManager = pipeline->GetOverlayManager(); + CHECK_NULL_VOID(overlayManager); + + DialogProperties maskarg; + maskarg.isUECHostMask = true; + maskarg.maskColor = maskInfo.maskColor; + auto mask = overlayManager->SetDialogMask(maskarg); + CHECK_NULL_VOID(mask); + auto dialogPattern = mask->GetPattern(); + CHECK_NULL_VOID(dialogPattern); + dialogPattern->SetUECHostMaskInfo(maskInfo); + AddUECHostMaskMap(maskInfo.uuid, mask); + } else if (maskInfo.maskAction == UECHostMaskAction::UNMOUNT) { + auto mask = GetUECHostMaskNode(maskInfo.uuid); + CHECK_NULL_VOID(mask); + auto dialogPattern = mask->GetPattern(); + CHECK_NULL_VOID(dialogPattern); + dialogPattern->CloseDialogByClick(); + RemoveUECHostMaskMap(maskInfo.uuid); + } +} + +void OverlayMaskManager::SendMaskInfoToHost(const UECHostMaskInfo& maskInfo) +{ + if (maskInfo.uuid.empty()) { + TAG_LOGW(AceLogTag::ACE_OVERLAY, "uuid of maskInfo is invalid"); + return; + } + +#ifdef WINDOW_SCENE_SUPPORTED + auto pipeline = PipelineContext::GetMainPipelineContext(); + CHECK_NULL_VOID(pipeline); + auto uiExtMgr = pipeline->GetUIExtensionManager(); + CHECK_NULL_VOID(uiExtMgr); + + TAG_LOGI(AceLogTag::ACE_OVERLAY, "send mask info to host, %{public}s", maskInfo.ToString().c_str()); + + auto ret = ModalUIExtension::SendOverlayMaskInfoToHost( + uiExtMgr, maskInfo, UIContentBusinessCode::OVERLAY_MASK_MOUNT, BusinessDataSendType::ASYNC); + if (!ret) { + TAG_LOGW(AceLogTag::ACE_OVERLAY, "failed to send overlay mask info to host"); + } +#endif +} + +void OverlayMaskManager::SendMaskEventToUEA(const UECHostMaskInfo& maskInfo) +{ + auto hostUECNode = GetUECHostNode(maskInfo.uuid); + CHECK_NULL_VOID(hostUECNode); + + TAG_LOGI(AceLogTag::ACE_OVERLAY, "host send mask event to UEA, %{public}s", maskInfo.ToString().c_str()); + + auto ret = ModalUIExtension::SendOverlayMaskInfoToUEA( + hostUECNode, maskInfo, UIContentBusinessCode::OVERLAY_MASK_EVENT, BusinessDataSendType::ASYNC); + if (!ret) { + TAG_LOGW(AceLogTag::ACE_OVERLAY, "failed to send host mask event to UEA"); + } +} + +void OverlayMaskManager::SendDialogMaskInfoToHost( + const RefPtr& dialogNode, UECHostMaskAction maskAction, int32_t instanceId) +{ + TAG_LOGI(AceLogTag::ACE_OVERLAY, "UEA send dialog mask info to host"); + + CHECK_NULL_VOID(dialogNode); + auto pipeline = dialogNode->GetContextRefPtr(); + auto currentId = pipeline ? pipeline->GetInstanceId() : instanceId; + if (currentId < MIN_SUBCONTAINER_ID) { + return; + } + + CHECK_NULL_VOID(dialogNode); + auto dialogPattern = dialogNode->GetPattern(); + CHECK_NULL_VOID(dialogPattern); + auto dialogprop = dialogPattern->GetDialogProperties(); + + UECHostMaskInfo maskInfo; + if (maskAction == UECHostMaskAction::MOUNT) { + auto nowTime = std::chrono::system_clock::now().time_since_epoch(); + uint64_t stamp = static_cast(std::chrono::duration_cast(nowTime).count()); + maskInfo = { + .uuid = std::to_string(stamp), + .instanceId = currentId, + .overlayTag = dialogNode->GetTag(), + .overlayId = dialogNode->GetId(), + .maskColor = dialogprop.maskColor, + .maskAction = UECHostMaskAction::MOUNT, + .maskType = UECHostMaskType::DIALOG, + }; + dialogPattern->SetUECHostMaskInfo(maskInfo); + } else if (maskAction == UECHostMaskAction::UNMOUNT) { + maskInfo = dialogPattern->GetUECHostMaskInfo(); + maskInfo.maskAction = UECHostMaskAction::UNMOUNT; + } + + SendMaskInfoToHost(maskInfo); +} + +void OverlayMaskManager::SendDialogMaskEventToUEA(const RefPtr& maskNode, UECHostMaskAction maskAction) +{ + TAG_LOGI(AceLogTag::ACE_OVERLAY, "host send dialog mask event to UEA enter"); + + CHECK_NULL_VOID(maskNode); + auto dialogPattern = maskNode->GetPattern(); + CHECK_NULL_VOID(dialogPattern); + + UECHostMaskInfo maskInfo = dialogPattern->GetUECHostMaskInfo(); + maskInfo.maskAction = maskAction; + SendMaskEventToUEA(maskInfo); +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.h b/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.h new file mode 100644 index 00000000000..73aa979a7cc --- /dev/null +++ b/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 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. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_OVERLAY_OVERLAY_MASK_MANAGER_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_OVERLAY_OVERLAY_MASK_MANAGER_H + +#include "base/utils/singleton.h" +#include "core/common/modal_ui_extension.h" +#include "core/components_ng/pattern/overlay/overlay_manager.h" + +namespace OHOS::Ace::NG { +class ACE_FORCE_EXPORT OverlayMaskManager : public Singleton { + DECLARE_SINGLETON(OverlayMaskManager); +public: + void RegisterOverlayHostMaskEventCallback(); + void RegisterOverlayHostMaskMountCallback(const RefPtr& uiextNode); + + void AddUECHostNodeMap(const std::string& uuid, const RefPtr& node); + void AddUECHostMaskMap(const std::string& uuid, const RefPtr& node); + void RemoveUECHostNodeMap(const std::string& uuid); + void RemoveUECHostMaskMap(const std::string& uuid); + RefPtr GetUECHostNode(const std::string& uuid); + RefPtr GetUECHostMaskNode(const std::string& uuid); + + void SendDialogMaskInfoToHost( + const RefPtr& dialogNode, UECHostMaskAction maskAction, int32_t instanceId = -1); + void SendDialogMaskEventToUEA(const RefPtr& maskNode, UECHostMaskAction maskAction); + +private: + void OnOverlayHostMaskMountCallback( + const RefPtr& uiextNode, const AAFwk::Want& data, const UECHostMaskInfo& maskInfo); + void OnOverlayHostMaskEventCallback(const AAFwk::Want& data, const UECHostMaskInfo& maskInfo); + + void SendMaskInfoToHost(const UECHostMaskInfo& maskInfo); + void SendMaskEventToUEA(const UECHostMaskInfo& maskInfo); + + void HostMountDialogMask(const UECHostMaskInfo& maskInfo); + void HandleDialogHostMaskEvent(const UECHostMaskInfo& maskInfo); + + std::mutex uecHostNodeMutex_; + std::unordered_map> uecHostNodeMap_; + + std::mutex uecHostMaskMutex_; + std::unordered_map> uecHostMaskMap_; +}; +} // namespace OHOS::Ace::NG +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_OVERLAY_OVERLAY_MASK_MANAGER_H diff --git a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_pattern.cpp b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_pattern.cpp index b5417f288e5..66ae8b1809c 100644 --- a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_pattern.cpp +++ b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_component/ui_extension_pattern.cpp @@ -27,6 +27,7 @@ #include "base/utils/utils.h" #include "core/common/container.h" #include "core/components_ng/event/event_hub.h" +#include "core/components_ng/pattern/overlay/overlay_mask_manager.h" #include "core/components_ng/pattern/pattern.h" #include "core/components_ng/pattern/text_field/text_field_manager.h" #include "core/components_ng/pattern/ui_extension/session_wrapper.h" @@ -611,6 +612,7 @@ void UIExtensionPattern::InitBusinessDataHandleCallback() RegisterEventProxyFlagCallback(); RegisterGetAvoidInfoCallback(); RegisterReplyPageModeCallback(); + OverlayMaskManager::GetInstance().RegisterOverlayHostMaskMountCallback(GetHost()); } void UIExtensionPattern::ReplacePlaceholderByContent() diff --git a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_config.h b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_config.h index 56239c798ef..71f0c1fa93b 100644 --- a/frameworks/core/components_ng/pattern/ui_extension/ui_extension_config.h +++ b/frameworks/core/components_ng/pattern/ui_extension/ui_extension_config.h @@ -61,6 +61,8 @@ enum class UIContentBusinessCode : uint32_t { // avoid info business begin NOTIFY_AVOID_INFO_CHANGE = 3001, GET_AVOID_INFO = 3002, + OVERLAY_MASK_MOUNT = 4001, + OVERLAY_MASK_EVENT = 4002, }; } // namespace OHOS::Ace::NG #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_UIEXTENSION_CONFIG_H diff --git a/test/mock/adapter/mock_modal_ui_extension.cpp b/test/mock/adapter/mock_modal_ui_extension.cpp index 73cf7d65990..60ea43b2d91 100644 --- a/test/mock/adapter/mock_modal_ui_extension.cpp +++ b/test/mock/adapter/mock_modal_ui_extension.cpp @@ -31,4 +31,29 @@ int32_t ModalUIExtension::GetSessionId(const RefPtr& /* uiExtNode void ModalUIExtension::SetBindModalCallback( const RefPtr& uiExtNode, std::function&& bindModalCallback) {} + +UECHostMaskInfo ModalUIExtension::GetUECHostMaskInfoFromWant(const AAFwk::Want& data) +{ + return {}; +} + +void ModalUIExtension::RegisterBusinessConsumeCallbackOnUEA(const RefPtr& uiExtMgr, + NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback) +{} + +void ModalUIExtension::RegisterBusinessConsumeCallbackOnHost( + const RefPtr& uiExtNode, NG::UIContentBusinessCode code, BusinessDataUECConsumeCallback callback) +{} + +bool ModalUIExtension::SendOverlayMaskInfoToUEA(const RefPtr& uiExtNode, const UECHostMaskInfo& info, + NG::UIContentBusinessCode code, NG::BusinessDataSendType type) +{ + return false; +} + +bool ModalUIExtension::SendOverlayMaskInfoToHost(const RefPtr& uiExtMgr, + const UECHostMaskInfo& info, NG::UIContentBusinessCode code, NG::BusinessDataSendType type) +{ + return false; +} } // namespace OHOS::Ace diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index b1462f03d18..2490d0e8786 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -1028,6 +1028,7 @@ ohos_source_set("ace_components_pattern") { "$ace_root/frameworks/core/components_ng/pattern/overlay/modal_presentation_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/overlay_container_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp", + "$ace_root/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/popup_base_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/sheet_drag_bar_paint_method.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/sheet_drag_bar_pattern.cpp", diff --git a/test/unittest/core/pattern/dialog/dialog_model_test_ng.cpp b/test/unittest/core/pattern/dialog/dialog_model_test_ng.cpp index 1ac6874d171..9c12f1e3890 100644 --- a/test/unittest/core/pattern/dialog/dialog_model_test_ng.cpp +++ b/test/unittest/core/pattern/dialog/dialog_model_test_ng.cpp @@ -1218,42 +1218,6 @@ HWTEST_F(DialogModelTestNg, DialogModelTestNg029, TestSize.Level1) AceApplicationInfo::GetInstance().isRightToLeft_ = false; } -/** - * @tc.name: DialogModelTestNg030 - * @tc.desc: Test DialogLayoutAlgorithm.ClipUIExtensionSubWindowContent function - * @tc.type: FUNC - */ -HWTEST_F(DialogModelTestNg, DialogModelTestNg030, TestSize.Level1) -{ - DialogProperties props; - auto dialog = DialogView::CreateDialogNode(props, nullptr); - ASSERT_NE(dialog, nullptr); - auto extraMaskNode = FrameNode::CreateFrameNode(V2::BLANK_ETS_TAG, 100, AceType::MakeRefPtr()); - extraMaskNode->MountToParent(dialog); - auto dialogPattern = dialog->GetPattern(); - ASSERT_NE(dialogPattern, nullptr); - auto dialogContext = dialog->GetRenderContext(); - ASSERT_NE(dialogContext, nullptr); - - auto dialogLayoutAlgorithm = dialogPattern->CreateLayoutAlgorithm(); - ASSERT_NE(dialogLayoutAlgorithm, nullptr); - RefPtr layoutAlgorithm = AceType::MakeRefPtr(); - ASSERT_NE(layoutAlgorithm, nullptr); - layoutAlgorithm->hostWindowRect_ = RectF(OffsetF(), SizeF(FULL_SCREEN_WIDTH / 2, FULL_SCREEN_HEIGHT / 2)); - layoutAlgorithm->expandDisplay_ = true; - layoutAlgorithm->ClipUIExtensionSubWindowContent(dialog); - NG::BorderRadiusPropertyT borderRadius; - borderRadius.SetRadius(Dimension(16.0, OHOS::Ace::DimensionUnit::VP)); - auto maskNode = AceType::DynamicCast(dialog->GetChildAtIndex(1)); - EXPECT_EQ(maskNode->GetRenderContext()->GetBorderRadius().value(), borderRadius); - - layoutAlgorithm->expandDisplay_ = false; - layoutAlgorithm->ClipUIExtensionSubWindowContent(dialog); - auto maskNodeProp = maskNode->GetLayoutProperty(); - EXPECT_EQ(maskNodeProp->GetCalcLayoutConstraint()->selfIdealSize.value(), - CalcSize(CalcLength(1.0, DimensionUnit::PERCENT), CalcLength(1.0, DimensionUnit::PERCENT))); -} - /** * @tc.name: DialogModelTestNg031 * @tc.desc: Test DialogLayoutAlgorithm.AdjustChildPosition function @@ -1295,49 +1259,6 @@ HWTEST_F(DialogModelTestNg, DialogModelTestNg031, TestSize.Level1) MockContainer::Current()->SetApiTargetVersion(backupApiVersion); } -/** - * @tc.name: DialogModelTestNg032 - * @tc.desc: Test DialogLayoutAlgorithm.SetSubWindowHotarea/GetMaskRect function - * @tc.type: FUNC - */ -HWTEST_F(DialogModelTestNg, DialogModelTestNg032, TestSize.Level1) -{ - auto layoutAlgorithm = AceType::MakeRefPtr(); - ASSERT_NE(layoutAlgorithm, nullptr); - DialogProperties props; - props.isShowInSubWindow = true; - auto dialog = DialogView::CreateDialogNode(props, nullptr); - ASSERT_NE(dialog, nullptr); - auto layoutWrapper = - AceType::MakeRefPtr(dialog, dialog->GetGeometryNode(), dialog->GetLayoutProperty()); - auto dialogProp = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); - CHECK_NULL_VOID(dialogProp); - - auto childSize = SizeF(CHILD_SIZE, CHILD_SIZE); - auto selfSize = SizeF(CHILD_SIZE_2, CHILD_SIZE_2); - - layoutAlgorithm->SetSubWindowHotarea(dialogProp, childSize, selfSize, dialog->GetId()); - auto maskRect = layoutAlgorithm->GetMaskRect(dialog); - EXPECT_FALSE(maskRect.has_value()); - - auto offset = DimensionOffset(CalcDimension(0, DimensionUnit::VP), CalcDimension(0, DimensionUnit::VP)); - layoutAlgorithm->isUIExtensionSubWindow_ = true; - layoutAlgorithm->SetSubWindowHotarea(dialogProp, childSize, selfSize, dialog->GetId()); - maskRect = layoutAlgorithm->GetMaskRect(dialog); - EXPECT_EQ(maskRect.value().GetOffset(), offset); - EXPECT_EQ(maskRect.value().GetWidth(), CalcDimension(1, DimensionUnit::PERCENT)); - EXPECT_EQ(maskRect.value().GetHeight(), CalcDimension(1, DimensionUnit::PERCENT)); - - layoutAlgorithm->expandDisplay_ = true; - layoutAlgorithm->hostWindowRect_ = RectF(OffsetF(), SizeF(CHILD_SIZE, CHILD_SIZE)); - layoutAlgorithm->SetSubWindowHotarea(dialogProp, childSize, selfSize, dialog->GetId()); - maskRect = layoutAlgorithm->GetMaskRect(dialog); - offset = DimensionOffset(CalcDimension(0, DimensionUnit::PX), CalcDimension(0, DimensionUnit::PX)); - EXPECT_EQ(maskRect.value().GetOffset(), offset); - EXPECT_EQ(maskRect.value().GetWidth(), Dimension(CHILD_SIZE, DimensionUnit::PX)); - EXPECT_EQ(maskRect.value().GetHeight(), Dimension(CHILD_SIZE, DimensionUnit::PX)); -} - /** * @tc.name: DialogModelTestNg033 * @tc.desc: Test DialogLayoutAlgorithm::UpdateChildMaxSizeHeight function diff --git a/test/unittest/core/pattern/dialog/dialog_pattern_test_ng.cpp b/test/unittest/core/pattern/dialog/dialog_pattern_test_ng.cpp index 1477337c404..14fa204adc0 100644 --- a/test/unittest/core/pattern/dialog/dialog_pattern_test_ng.cpp +++ b/test/unittest/core/pattern/dialog/dialog_pattern_test_ng.cpp @@ -898,11 +898,6 @@ HWTEST_F(DialogPatternAdditionalTestNg, DialogPatternAdditionalTestNgAddExtraMas props.isModal = false; pattern->AddExtraMaskNode(props); EXPECT_EQ(totalChildCount, frameNode->GetTotalChildCount()); - - pattern->isUIExtensionSubWindow_ = true; - props.isModal = true; - pattern->AddExtraMaskNode(props); - EXPECT_EQ(totalChildCount + 1, frameNode->GetTotalChildCount()); } /** diff --git a/test/unittest/core/pattern/web/BUILD.gn b/test/unittest/core/pattern/web/BUILD.gn index ef388569d87..d0c49afb8fd 100755 --- a/test/unittest/core/pattern/web/BUILD.gn +++ b/test/unittest/core/pattern/web/BUILD.gn @@ -310,6 +310,7 @@ ohos_unittest("web_pattern_unit_test_ohos") { "$ace_root/frameworks/core/components_ng/pattern/overlay/modal_presentation_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/overlay_container_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp", + "$ace_root/frameworks/core/components_ng/pattern/overlay/overlay_mask_manager.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/popup_base_pattern.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/sheet_drag_bar_paint_method.cpp", "$ace_root/frameworks/core/components_ng/pattern/overlay/sheet_drag_bar_pattern.cpp", -- Gitee