1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16
17 #include "base/error/error_code.h"
18 #include "core/common/container.h"
19 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
20 #include "core/components_ng/pattern/overlay/dialog_manager.h"
21 #include "core/components_ng/pattern/overlay/sheet_manager.h"
22 #include "core/components_ng/pattern/stage/page_pattern.h"
23 #include "core/common/ace_engine.h"
24 #include "base/memory/ace_type.h"
25 #include "base/subwindow/subwindow_manager.h"
26
27 namespace OHOS::Ace::NG {
28 namespace {
29 } // namespace
30
31 DialogManager::DialogManager() = default;
32
33 DialogManager::~DialogManager() = default;
34
ShowInEmbeddedOverlay(std::function<void (RefPtr<NG::OverlayManager>)> && task,const std::string & name,int32_t uniqueId)35 void DialogManager::ShowInEmbeddedOverlay(std::function<void(RefPtr<NG::OverlayManager>)>&& task,
36 const std::string& name, int32_t uniqueId)
37 {
38 auto currentId = Container::CurrentId();
39 ContainerScope scope(currentId);
40 auto context = NG::PipelineContext::GetCurrentContext();
41 CHECK_NULL_VOID(context);
42 auto overlayManager = context->GetOverlayManager();
43 auto embeddedOverlay = GetEmbeddedOverlay(uniqueId, context);
44 if (embeddedOverlay) {
45 overlayManager = embeddedOverlay;
46 }
47 context->GetTaskExecutor()->PostTask(
48 [task = std::move(task), weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
49 auto overlayManager = weak.Upgrade();
50 task(overlayManager);
51 },
52 TaskExecutor::TaskType::UI, name);
53 }
54
FindPageNodeOverlay(const RefPtr<FrameNode> & currentNode)55 RefPtr<OverlayManager> DialogManager::FindPageNodeOverlay(const RefPtr<FrameNode>& currentNode)
56 {
57 if (currentNode == nullptr || !currentNode->IsOnMainTree()) {
58 TAG_LOGE(AceLogTag::ACE_DIALOG, "dialog node does not exist or not on main tree.");
59 } else {
60 return SheetManager::FindPageNodeOverlay(currentNode, true, true);
61 }
62 return nullptr;
63 }
64
GetEmbeddedOverlay(int32_t uniqueId,const RefPtr<PipelineContext> & context)65 RefPtr<OverlayManager> DialogManager::GetEmbeddedOverlay(int32_t uniqueId, const RefPtr<PipelineContext>& context)
66 {
67 CHECK_NULL_RETURN(context, nullptr);
68 if (uniqueId >= 0) {
69 auto currentNode = ElementRegister::GetInstance()->GetSpecificItemById<NG::FrameNode>(uniqueId);
70 if (currentNode == nullptr || !currentNode->IsOnMainTree()) {
71 TAG_LOGE(AceLogTag::ACE_DIALOG, "Level uniqueId/%{public}d does not exist or not on main tree.", uniqueId);
72 } else {
73 auto getOverlayManager = FindPageNodeOverlay(currentNode);
74 if (getOverlayManager) {
75 return getOverlayManager;
76 } else {
77 TAG_LOGE(AceLogTag::ACE_DIALOG, "Level uniqueId/%{public}d can not get overlay manager.", uniqueId);
78 }
79 }
80 } else {
81 auto stateMgr = context->GetStageManager();
82 if (stateMgr && stateMgr->GetLastPage()) {
83 auto pagePattern = stateMgr->GetLastPage()->GetPattern<NG::PagePattern>();
84 if (pagePattern) {
85 pagePattern->CreateOverlayManager(true);
86 return pagePattern->GetOverlayManager();
87 }
88 } else {
89 TAG_LOGE(AceLogTag::ACE_DIALOG, "Can not get current page");
90 }
91 }
92 return nullptr;
93 }
94
GetEmbeddedOverlayWithNode(const RefPtr<UINode> & dialogNode)95 RefPtr<OverlayManager> DialogManager::GetEmbeddedOverlayWithNode(const RefPtr<UINode>& dialogNode)
96 {
97 CHECK_NULL_RETURN(dialogNode, nullptr);
98 auto parent = dialogNode->GetParent();
99 CHECK_NULL_RETURN(parent, nullptr);
100 auto parentNode = AceType::DynamicCast<FrameNode>(parent);
101 CHECK_NULL_RETURN(parentNode, nullptr);
102 if (parentNode->GetTag() == V2::PAGE_ETS_TAG) {
103 auto pattern = parentNode->GetPattern<PagePattern>();
104 CHECK_NULL_RETURN(pattern, nullptr);
105 return pattern->GetOverlayManager();
106 } else if (parentNode->GetTag() == V2::NAVDESTINATION_VIEW_ETS_TAG) {
107 auto pattern = parentNode->GetPattern<NavDestinationPattern>();
108 CHECK_NULL_RETURN(pattern, nullptr);
109 return pattern->GetOverlayManager();
110 }
111 return nullptr;
112 }
113
GetDialogNodeByContentNode(const RefPtr<UINode> & currentNode)114 RefPtr<UINode> DialogManager::GetDialogNodeByContentNode(const RefPtr<UINode>& currentNode)
115 {
116 RefPtr<UINode> parent = currentNode;
117 while (parent) {
118 if (parent->GetTag() == V2::DIALOG_ETS_TAG) {
119 break;
120 }
121 parent = parent->GetParent();
122 }
123 return parent;
124 }
125
IsPcOrFreeMultiWindow(const RefPtr<FrameNode> & currentNode) const126 bool DialogManager::IsPcOrFreeMultiWindow(const RefPtr<FrameNode>& currentNode) const
127 {
128 auto pipelineContext = currentNode->GetContextRefPtr();
129 CHECK_NULL_RETURN(pipelineContext, false);
130 auto dialogTheme = pipelineContext->GetTheme<DialogTheme>();
131 CHECK_NULL_RETURN(dialogTheme, false);
132 auto expandDisplay = dialogTheme->GetExpandDisplay();
133 auto containerId = pipelineContext->GetInstanceId();
134 auto container = AceEngine::Get().GetContainer(containerId);
135 CHECK_NULL_RETURN(container, false);
136 auto isFreeMultiWindow = container->IsFreeMultiWindow();
137 return expandDisplay || isFreeMultiWindow;
138 }
139
GetMainPipelineContext(const RefPtr<FrameNode> & frameNode,bool isTargetNodeInSubwindow)140 RefPtr<PipelineContext> DialogManager::GetMainPipelineContext(
141 const RefPtr<FrameNode>& frameNode, bool isTargetNodeInSubwindow)
142 {
143 // Get pipelineContext of main window or host window for UIExtension
144 if (!frameNode) {
145 TAG_LOGE(AceLogTag::ACE_OVERLAY, "get frameNode failed");
146 return nullptr;
147 }
148 auto pipeline = frameNode->GetContext();
149 if (!pipeline) {
150 TAG_LOGE(AceLogTag::ACE_OVERLAY, "get pipeline failed, nodeId: %{public}d", frameNode->GetId());
151 return nullptr;
152 }
153 auto containerId = pipeline->GetInstanceId();
154 auto container = AceEngine::Get().GetContainer(containerId);
155 if (!container) {
156 TAG_LOGE(AceLogTag::ACE_OVERLAY, "get container failed, nodeId: %{public}d", frameNode->GetId());
157 return nullptr;
158 }
159 RefPtr<PipelineContext> context;
160 if (container->IsSubContainer() && !isTargetNodeInSubwindow) {
161 auto parentContainerId = SubwindowManager::GetInstance()->GetParentContainerId(containerId);
162 auto parentContainer = AceEngine::Get().GetContainer(parentContainerId);
163 if (!parentContainer) {
164 TAG_LOGE(AceLogTag::ACE_OVERLAY, "get parentContainer failed, nodeId: %{public}d", frameNode->GetId());
165 return nullptr;
166 }
167 context = AceType::DynamicCast<PipelineContext>(parentContainer->GetPipelineContext());
168 if (!context) {
169 TAG_LOGE(AceLogTag::ACE_OVERLAY, "get context failed, nodeId: %{public}d", frameNode->GetId());
170 return nullptr;
171 }
172 } else {
173 context = AceType::Claim(pipeline);
174 }
175 return context;
176 }
177 } // namespace OHOS::Ace::NG
178