1 /*
2 * Copyright (c) 2023 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 #include "core/components_ng/pattern/dialog/custom_dialog_controller_model_ng.h"
16
17 #include "base/subwindow/subwindow_manager.h"
18 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
19 #include "core/components_ng/pattern/overlay/dialog_manager.h"
20
21 namespace OHOS::Ace::NG {
SetOpenDialog(DialogProperties & dialogProperties,const WeakPtr<AceType> & controller,std::vector<WeakPtr<AceType>> & dialogs,bool & pending,bool & isShown,std::function<void ()> && cancelTask,std::function<void ()> && buildFunc,RefPtr<AceType> & dialogComponent,RefPtr<AceType> & customDialog,std::list<DialogOperation> & dialogOperation,bool & hasBind)22 void CustomDialogControllerModelNG::SetOpenDialog(DialogProperties& dialogProperties,
23 const WeakPtr<AceType>& controller, std::vector<WeakPtr<AceType>>& dialogs,
24 bool& pending, bool& isShown, std::function<void()>&& cancelTask, std::function<void()>&& buildFunc,
25 RefPtr<AceType>& dialogComponent, RefPtr<AceType>& customDialog, std::list<DialogOperation>& dialogOperation,
26 bool& hasBind)
27 {
28 auto container = Container::Current();
29 auto currentId = Container::CurrentId();
30 if (!container) {
31 TAG_LOGE(AceLogTag::ACE_DIALOG, "Container is null.");
32 return;
33 }
34
35 auto pipelineContext = container->GetPipelineContext();
36 CHECK_NULL_VOID(pipelineContext);
37 auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
38 CHECK_NULL_VOID(context);
39 auto executor = context->GetTaskExecutor();
40 if (!executor) {
41 TAG_LOGE(AceLogTag::ACE_DIALOG, "Task executor is null.");
42 return;
43 }
44 auto task = ParseOpenDialogTask(
45 currentId, controller, dialogProperties, dialogs, std::move(buildFunc), hasBind, isShown);
46 executor->PostTask(task, TaskExecutor::TaskType::UI, "ArkUIDialogShowCustomDialog");
47 }
48
SetOpenDialogInTask(const RefPtr<OverlayManager> & overlayManager,const RefPtr<Container> & container,const WeakPtr<AceType> & controller,RefPtr<NG::FrameNode> & dialog,DialogProperties & dialogProperties,std::function<void ()> && func,bool & isShown)49 void CustomDialogControllerModelNG::SetOpenDialogInTask(const RefPtr<OverlayManager>& overlayManager, const RefPtr<Container>& container,
50 const WeakPtr<AceType>& controller, RefPtr<NG::FrameNode>& dialog, DialogProperties& dialogProperties,
51 std::function<void()>&& func, bool& isShown)
52 {
53 if (!overlayManager || !container) {
54 TAG_LOGE(AceLogTag::ACE_DIALOG, "set open dialog in task, manager or container is null.");
55 return;
56 }
57 dialogProperties.onStatusChanged = [&isShown](bool isShownStatus) {
58 if (!isShownStatus) {
59 isShown = isShownStatus;
60 }
61 };
62 dialogProperties.isUserCreatedDialog = true;
63 auto controllerPtr = controller.Upgrade();
64 if (!controllerPtr) {
65 TAG_LOGE(AceLogTag::ACE_DIALOG, "set open dialog in task, controller is null.");
66 return;
67 }
68 if (dialogProperties.isShowInSubWindow) {
69 dialog = SubwindowManager::GetInstance()->ShowDialogNG(dialogProperties, std::move(func));
70 CHECK_NULL_VOID(dialog);
71 if (dialogProperties.isModal && !dialogProperties.isSceneBoardDialog &&
72 !container->IsUIExtensionWindow()) {
73 auto mask = overlayManager->SetDialogMask(dialogProperties);
74 if (!mask) {
75 TAG_LOGW(AceLogTag::ACE_DIALOG, "fail to set mask dialog.");
76 return;
77 }
78 overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
79 }
80 } else {
81 dialog = overlayManager->ShowDialog(dialogProperties, std::move(func), false);
82 }
83 }
84
ParseOpenDialogTask(int32_t currentId,const WeakPtr<AceType> & controller,DialogProperties & dialogProperties,std::vector<WeakPtr<AceType>> & dialogs,std::function<void ()> && buildFunc,bool & hasBind,bool & isShown)85 TaskExecutor::Task CustomDialogControllerModelNG::ParseOpenDialogTask(int32_t currentId,
86 const WeakPtr<AceType>& controller, DialogProperties& dialogProperties, std::vector<WeakPtr<AceType>>& dialogs,
87 std::function<void()>&& buildFunc, bool& hasBind, bool& isShown)
88 {
89 auto task = [currentId, controller, &dialogProperties, &dialogs, func = std::move(buildFunc),
90 &hasBind, isShown]() mutable {
91 auto controllerPtr = controller.Upgrade();
92 if (!controllerPtr) {
93 TAG_LOGE(AceLogTag::ACE_DIALOG, "parse open dialog, controller is null.");
94 return;
95 }
96 auto container = AceEngine::Get().GetContainer(currentId);
97 CHECK_NULL_VOID(container);
98 auto isSubContainer = container->IsSubContainer();
99 auto expandDisplay = SubwindowManager::GetInstance()->GetIsExpandDisplay();
100 auto enableOpenSubwindowInSubwindow = expandDisplay || container->IsPcOrFreeMultiWindowCapability();
101 if (!enableOpenSubwindowInSubwindow && isSubContainer && dialogProperties.isShowInSubWindow) {
102 TAG_LOGW(AceLogTag::ACE_DIALOG, "subwindow can not open dialog in subwindow");
103 return;
104 }
105 if (isSubContainer && (!dialogProperties.isShowInSubWindow || enableOpenSubwindowInSubwindow)) {
106 currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
107 container = AceEngine::Get().GetContainer(currentId);
108 if (!container) {
109 TAG_LOGE(AceLogTag::ACE_DIALOG, "ParentContainer is null.");
110 return;
111 }
112 }
113 ContainerScope scope(currentId);
114 auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
115 CHECK_NULL_VOID(context);
116 auto overlayManager = context->GetOverlayManager();
117 CHECK_NULL_VOID(overlayManager);
118 if (dialogProperties.dialogLevelMode == LevelMode::EMBEDDED) {
119 auto embeddedOverlay = NG::DialogManager::GetEmbeddedOverlay(dialogProperties.dialogLevelUniqueId, context);
120 if (embeddedOverlay) {
121 overlayManager = embeddedOverlay;
122 }
123 }
124 RefPtr<NG::FrameNode> dialog;
125 CustomDialogControllerModelNG::SetOpenDialogInTask(overlayManager, container, controller, dialog,
126 dialogProperties, std::move(func), isShown);
127 if (!dialog) {
128 TAG_LOGE(AceLogTag::ACE_DIALOG, "fail to show dialog.");
129 return;
130 }
131 TAG_LOGI(AceLogTag::ACE_DIALOG, "Controller/%{public}d create dialog node/%{public}d successfully.",
132 dialogProperties.controllerId.value_or(-1), dialog->GetId());
133 dialogs.emplace_back(dialog);
134 hasBind = true;
135 };
136 return task;
137 }
138
SetOpenDialogWithNode(DialogProperties & dialogProperties,const RefPtr<UINode> & customNode)139 RefPtr<UINode> CustomDialogControllerModelNG::SetOpenDialogWithNode(DialogProperties& dialogProperties,
140 const RefPtr<UINode>& customNode)
141 {
142 ContainerScope scope(Container::CurrentIdSafely());
143 auto container = Container::Current();
144 CHECK_NULL_RETURN(container, nullptr);
145 if (container->IsSubContainer() && !dialogProperties.isShowInSubWindow) {
146 auto currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
147 container = AceEngine::Get().GetContainer(currentId);
148 CHECK_NULL_RETURN(container, nullptr);
149 }
150 auto pipelineContext = container->GetPipelineContext();
151 CHECK_NULL_RETURN(pipelineContext, nullptr);
152 auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
153 CHECK_NULL_RETURN(context, nullptr);
154 auto overlayManager = context->GetOverlayManager();
155 CHECK_NULL_RETURN(overlayManager, nullptr);
156 if (dialogProperties.dialogLevelMode == LevelMode::EMBEDDED) {
157 auto embeddedOverlay = NG::DialogManager::GetEmbeddedOverlay(dialogProperties.dialogLevelUniqueId, context);
158 if (embeddedOverlay) {
159 overlayManager = embeddedOverlay;
160 }
161 }
162 dialogProperties.isUserCreatedDialog = true;
163 RefPtr<NG::FrameNode> dialog;
164 if (dialogProperties.isShowInSubWindow) {
165 dialog = SubwindowManager::GetInstance()->ShowDialogNGWithNode(dialogProperties, customNode);
166 CHECK_NULL_RETURN(dialog, nullptr);
167 if (dialogProperties.isModal && !dialogProperties.isSceneBoardDialog && !container->IsUIExtensionWindow()) {
168 DialogProperties Maskarg;
169 Maskarg.isMask = true;
170 Maskarg.autoCancel = dialogProperties.autoCancel;
171 Maskarg.maskColor = dialogProperties.maskColor;
172 auto mask = overlayManager->ShowDialogWithNode(Maskarg, nullptr, false);
173 CHECK_NULL_RETURN(mask, dialog);
174 overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
175 }
176 } else {
177 dialog = overlayManager->ShowDialogWithNode(dialogProperties, customNode, false);
178 }
179 return dialog;
180 }
181
SetCloseDialog(DialogProperties & dialogProperties,const WeakPtr<AceType> & controller,std::vector<WeakPtr<AceType>> & dialogs,bool & pending,bool & isShown,std::function<void ()> && cancelTask,RefPtr<AceType> & dialogComponent,RefPtr<AceType> & customDialog,std::list<DialogOperation> & dialogOperation)182 void CustomDialogControllerModelNG::SetCloseDialog(DialogProperties& dialogProperties,
183 const WeakPtr<AceType>& controller, std::vector<WeakPtr<AceType>>& dialogs,
184 bool& pending, bool& isShown, std::function<void()>&& cancelTask, RefPtr<AceType>& dialogComponent,
185 RefPtr<AceType>& customDialog, std::list<DialogOperation>& dialogOperation)
186 {
187 TAG_LOGI(AceLogTag::ACE_DIALOG, "CustomDialogController SetCloseDialog enter.");
188 auto container = Container::Current();
189 auto currentId = Container::CurrentId();
190 if (!container) {
191 TAG_LOGE(AceLogTag::ACE_DIALOG, "Container is null.");
192 return;
193 }
194 if (container->IsSubContainer() && !dialogProperties.isShowInSubWindow) {
195 currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
196 container = AceEngine::Get().GetContainer(currentId);
197 if (!container) {
198 TAG_LOGE(AceLogTag::ACE_DIALOG, "ParentContainer is null.");
199 return;
200 }
201 }
202 ContainerScope scope(currentId);
203 auto pipelineContext = container->GetPipelineContext();
204 CHECK_NULL_VOID(pipelineContext);
205 auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
206 CHECK_NULL_VOID(context);
207 auto overlayManager = context->GetOverlayManager();
208 CHECK_NULL_VOID(overlayManager);
209 auto executor = context->GetTaskExecutor();
210 CHECK_NULL_VOID(executor);
211 auto task = ParseCloseDialogTask(controller, dialogProperties, dialogs, overlayManager);
212 executor->PostTask(task, TaskExecutor::TaskType::UI, "ArkUIDialogCloseCustomDialog");
213 }
214
ParseCloseDialogTask(const WeakPtr<AceType> & controller,DialogProperties & dialogProperties,std::vector<WeakPtr<AceType>> & dialogs,const RefPtr<OverlayManager> & overlayManager)215 TaskExecutor::Task CustomDialogControllerModelNG::ParseCloseDialogTask(const WeakPtr<AceType>& controller,
216 DialogProperties& dialogProperties, std::vector<WeakPtr<AceType>>& dialogs,
217 const RefPtr<OverlayManager>& overlayManager)
218 {
219 auto task = [controller, &dialogs, &dialogProperties,
220 weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager))]() {
221 auto overlayManager = weakOverlayManager.Upgrade();
222 if (!overlayManager) {
223 TAG_LOGE(AceLogTag::ACE_DIALOG, "OverlayManager is null.");
224 return;
225 }
226 auto controllerPtr = controller.Upgrade();
227 if (!controllerPtr) {
228 TAG_LOGE(AceLogTag::ACE_DIALOG, "CustomDialogController is null.");
229 return;
230 }
231 RefPtr<NG::FrameNode> dialog;
232 while (!dialogs.empty()) {
233 dialog = AceType::DynamicCast<NG::FrameNode>(dialogs.back().Upgrade());
234 if (dialog && !dialog->IsRemoving()) {
235 // get the dialog not removed currently
236 break;
237 }
238 dialogs.pop_back();
239 }
240 if (dialogs.empty()) {
241 TAG_LOGW(AceLogTag::ACE_DIALOG, "Controller%{public}d dialog map is empty.",
242 dialogProperties.controllerId.value_or(-1));
243 return;
244 }
245 CHECK_NULL_VOID(dialog);
246 if (dialogProperties.isShowInSubWindow) {
247 SubwindowManager::GetInstance()->CloseDialogNG(dialog);
248 dialogs.pop_back();
249 } else {
250 auto dialogPattern = dialog->GetPattern<DialogPattern>();
251 if (dialogProperties.dialogLevelMode == LevelMode::EMBEDDED && dialogPattern) {
252 overlayManager = dialogPattern->GetEmbeddedOverlay(overlayManager);
253 }
254 overlayManager->CloseDialog(dialog);
255 }
256 };
257 return task;
258 }
259
SetCloseDialogForNDK(FrameNode * dialogNode)260 void CustomDialogControllerModelNG::SetCloseDialogForNDK(FrameNode* dialogNode)
261 {
262 CHECK_NULL_VOID(dialogNode);
263 dialogNode->SetIsUseTransitionAnimator(true);
264 auto dialogRef = AceType::Claim(dialogNode);
265 if (!Container::Current()) {
266 // close dialog when current container is null, so we should get container through current safelyId
267 ContainerScope scope(Container::CurrentIdSafely());
268 auto container = Container::Current();
269 CHECK_NULL_VOID(container);
270 auto pipelineContext = container->GetPipelineContext();
271 CHECK_NULL_VOID(pipelineContext);
272 auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
273 CHECK_NULL_VOID(context);
274 auto overlayManager = context->GetOverlayManager();
275 CHECK_NULL_VOID(overlayManager);
276 auto currentOverlay = DialogManager::GetInstance().GetEmbeddedOverlayWithNode(dialogRef);
277 if (currentOverlay) {
278 overlayManager = currentOverlay;
279 }
280 overlayManager->CloseDialog(dialogRef);
281 } else {
282 // close dialog when current container is not null, so we should get pipelineContext through dialogNode
283 auto nodeContext = dialogNode->GetContextWithCheck();
284 CHECK_NULL_VOID(nodeContext);
285 auto overlay = nodeContext->GetOverlayManager();
286 CHECK_NULL_VOID(overlay);
287 auto currentOverlay = DialogManager::GetInstance().GetEmbeddedOverlayWithNode(dialogRef);
288 if (currentOverlay) {
289 overlay = currentOverlay;
290 }
291 overlay->CloseDialog(dialogRef);
292 }
293 }
294
GetState(std::vector<WeakPtr<AceType>> & dialogs,bool & hasBind)295 PromptActionCommonState CustomDialogControllerModelNG::GetState(std::vector<WeakPtr<AceType>>& dialogs, bool& hasBind)
296 {
297 RefPtr<NG::FrameNode> dialog;
298 PromptActionCommonState state = PromptActionCommonState::UNINITIALIZED;
299 if (hasBind) {
300 state = PromptActionCommonState::INITIALIZED;
301 }
302 while (!dialogs.empty()) {
303 dialog = AceType::DynamicCast<NG::FrameNode>(dialogs.back().Upgrade());
304 if (dialog) {
305 // get the dialog not removed currently
306 break;
307 }
308 dialogs.pop_back();
309 }
310 if (!dialog) {
311 if (hasBind) {
312 return PromptActionCommonState::DISAPPEARED;
313 }
314 return state;
315 }
316 auto dialogPattern = dialog->GetPattern<DialogPattern>();
317 if (!dialogPattern) {
318 return state;
319 }
320 state = dialogPattern->GetState();
321 return state;
322 }
323
GetStateWithNode(FrameNode * dialogNode)324 PromptActionCommonState CustomDialogControllerModelNG::GetStateWithNode(FrameNode* dialogNode)
325 {
326 PromptActionCommonState state = PromptActionCommonState::INITIALIZED;
327 CHECK_NULL_RETURN(dialogNode, state);
328 auto dialogRef = AceType::Claim(dialogNode);
329 auto dialogPattern = dialogRef->GetPattern<DialogPattern>();
330 CHECK_NULL_RETURN(dialogPattern, state);
331 state = dialogPattern->GetState();
332 return state;
333 }
334 } // namespace OHOS::Ace::NG
335