• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 
16 #include "core/components_ng/pattern/overlay/overlay_manager.h"
17 
18 #include <cstdint>
19 #include <utility>
20 #include <vector>
21 
22 #include "base/geometry/ng/offset_t.h"
23 #include "base/geometry/ng/size_t.h"
24 #include "base/log/log.h"
25 #include "base/memory/ace_type.h"
26 #include "base/memory/referenced.h"
27 #include "base/subwindow/subwindow_manager.h"
28 #include "base/utils/measure_util.h"
29 #include "base/utils/system_properties.h"
30 #include "base/utils/utils.h"
31 #include "core/animation/animation_pub.h"
32 #include "core/animation/spring_curve.h"
33 #include "core/common/ace_application_info.h"
34 #include "core/common/ace_engine.h"
35 #include "core/common/container.h"
36 #include "core/common/interaction/interaction_interface.h"
37 #include "core/common/modal_ui_extension.h"
38 #include "core/common/recorder/event_recorder.h"
39 #include "core/components/common/properties/color.h"
40 #include "core/components/select/select_theme.h"
41 #include "core/components/text_overlay/text_overlay_theme.h"
42 #include "core/components/toast/toast_theme.h"
43 #include "core/components_ng/animation/geometry_transition.h"
44 #include "core/components_ng/base/frame_node.h"
45 #include "core/components_ng/base/ui_node.h"
46 #include "core/components_ng/base/view_abstract.h"
47 #include "core/components_ng/base/view_stack_processor.h"
48 #include "core/components_ng/pattern/bubble/bubble_event_hub.h"
49 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
50 #include "core/components_ng/pattern/calendar_picker/calendar_dialog_view.h"
51 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
52 #include "core/components_ng/pattern/dialog/dialog_view.h"
53 #include "core/components_ng/pattern/menu/menu_layout_property.h"
54 #include "core/components_ng/pattern/menu/menu_pattern.h"
55 #include "core/components_ng/pattern/menu/menu_theme.h"
56 #include "core/components_ng/pattern/menu/menu_view.h"
57 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
58 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
59 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
60 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
61 #include "core/components_ng/pattern/overlay/keyboard_base_pattern.h"
62 #include "core/components_ng/pattern/overlay/keyboard_view.h"
63 #include "core/components_ng/pattern/overlay/modal_presentation_pattern.h"
64 #include "core/components_ng/pattern/overlay/popup_base_pattern.h"
65 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
66 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
67 #include "core/components_ng/pattern/overlay/sheet_presentation_property.h"
68 #include "core/components_ng/pattern/overlay/sheet_view.h"
69 #include "core/components_ng/pattern/picker/datepicker_dialog_view.h"
70 #include "core/components_ng/pattern/stage/stage_pattern.h"
71 #include "core/components_ng/pattern/text_picker/textpicker_dialog_view.h"
72 #include "core/components_ng/pattern/time_picker/timepicker_dialog_view.h"
73 #include "core/components_ng/pattern/toast/toast_pattern.h"
74 #include "core/components_ng/pattern/video/video_full_screen_pattern.h"
75 #include "core/components_ng/property/measure_property.h"
76 #include "core/components_ng/property/property.h"
77 #include "core/components_v2/inspector/inspector_constants.h"
78 #include "core/pipeline/pipeline_base.h"
79 #include "core/pipeline/pipeline_context.h"
80 
81 namespace OHOS::Ace::NG {
82 namespace {
83 // should be moved to theme.
84 constexpr int32_t TOAST_ANIMATION_DURATION = 100;
85 constexpr int32_t MENU_ANIMATION_DURATION = 150;
86 constexpr float TOAST_ANIMATION_POSITION = 15.0f;
87 
88 constexpr float PIXELMAP_DRAG_SCALE = 1.0f;
89 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 250;
90 constexpr float PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE = 0.5f;
91 
92 constexpr int32_t FULL_MODAL_ALPHA_ANIMATION_DURATION = 200;
93 
94 constexpr int32_t SHEET_HALF_SIZE = 2;
95 // dialog animation params
96 const RefPtr<Curve> SHOW_SCALE_ANIMATION_CURVE = AceType::MakeRefPtr<CubicCurve>(0.38f, 1.33f, 0.6f, 1.0f);
97 
98 // custom keyboard animation params
99 const RefPtr<Curve> SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE =
100     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f);
101 const RefPtr<Curve> HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE =
102     AceType::MakeRefPtr<InterpolatingSpring>(4.0f, 1.0f, 342.0f, 37.0f);
103 
GetLastPage()104 RefPtr<FrameNode> GetLastPage()
105 {
106     auto pipelineContext = PipelineContext::GetCurrentContext();
107     CHECK_NULL_RETURN(pipelineContext, nullptr);
108     auto stageManager = pipelineContext->GetStageManager();
109     CHECK_NULL_RETURN(stageManager, nullptr);
110     auto pageNode = stageManager->GetLastPage();
111     return pageNode;
112 }
113 
ShowPreviewDisappearAnimation(const RefPtr<MenuWrapperPattern> & menuWrapperPattern)114 void ShowPreviewDisappearAnimation(const RefPtr<MenuWrapperPattern>& menuWrapperPattern)
115 {
116     CHECK_NULL_VOID(menuWrapperPattern);
117     auto previewChild = menuWrapperPattern->GetPreview();
118     CHECK_NULL_VOID(previewChild);
119     auto previewRenderContext = previewChild->GetRenderContext();
120     CHECK_NULL_VOID(previewRenderContext);
121 
122     auto menuChild = menuWrapperPattern->GetMenu();
123     CHECK_NULL_VOID(menuChild);
124     auto menuPattern = menuChild->GetPattern<MenuPattern>();
125     CHECK_NULL_VOID(menuPattern);
126     auto previewPosition = menuPattern->GetPreviewOriginOffset();
127 
128     auto pipelineContext = PipelineContext::GetCurrentContext();
129     CHECK_NULL_VOID(pipelineContext);
130     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
131     CHECK_NULL_VOID(menuTheme);
132     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
133     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
134     AnimationOption scaleOption;
135     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
136     scaleOption.SetCurve(motion);
137     float previewScale = 1.0f;
138     if (menuPattern->GetPreviewMode() == MenuPreviewMode::IMAGE) {
139         auto previewGeometryNode = previewChild->GetGeometryNode();
140         CHECK_NULL_VOID(previewGeometryNode);
141         auto preivewSize = previewGeometryNode->GetFrameSize();
142         if (!NearEqual(menuPattern->GetTargetSize().Width(), preivewSize.Width())) {
143             previewScale = menuPattern->GetTargetSize().Width() / preivewSize.Width();
144         }
145     }
146     AnimationUtils::Animate(scaleOption, [previewRenderContext, previewPosition, previewScale]() {
147         if (previewRenderContext) {
148             previewRenderContext->UpdateTransformScale(VectorF(previewScale, previewScale));
149             previewRenderContext->UpdatePosition(
150                 OffsetT<Dimension>(Dimension(previewPosition.GetX()), Dimension(previewPosition.GetY())));
151         }
152     });
153 
154     auto shadow = previewRenderContext->GetBackShadow();
155     if (!shadow.has_value()) {
156         shadow = Shadow::CreateShadow(ShadowStyle::None);
157     }
158     previewRenderContext->UpdateBackShadow(shadow.value());
159     auto disappearDuration = menuTheme->GetDisappearDuration();
160     AnimationOption previewOption;
161     previewOption.SetCurve(Curves::SHARP);
162     previewOption.SetDuration(disappearDuration);
163     AnimationUtils::Animate(previewOption, [previewRenderContext, shadow]() mutable {
164         if (previewRenderContext) {
165             auto color = shadow->GetColor();
166             auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue());
167             shadow->SetColor(newColor);
168             previewRenderContext->UpdateBackShadow(shadow.value());
169             BorderRadiusProperty borderRadius;
170             borderRadius.SetRadius(0.0_vp);
171             previewRenderContext->UpdateBorderRadius(borderRadius);
172         }
173     });
174 }
175 
UpdateContextMenuDisappearPositionAnimation(const RefPtr<FrameNode> & menu,const NG::OffsetF & offset)176 void UpdateContextMenuDisappearPositionAnimation(const RefPtr<FrameNode>& menu, const NG::OffsetF& offset)
177 {
178     CHECK_NULL_VOID(menu);
179     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
180     CHECK_NULL_VOID(menuWrapperPattern);
181     auto menuChild = menuWrapperPattern->GetMenu();
182     CHECK_NULL_VOID(menuChild);
183     auto menuRenderContext = menuChild->GetRenderContext();
184     CHECK_NULL_VOID(menuRenderContext);
185     auto menuPattern = menuChild->GetPattern<MenuPattern>();
186     CHECK_NULL_VOID(menuPattern);
187     auto menuPosition = menuPattern->GetEndOffset();
188     menuPosition += offset;
189     menuPattern->SetEndOffset(menuPosition);
190 
191     auto pipelineContext = PipelineContext::GetCurrentContext();
192     CHECK_NULL_VOID(pipelineContext);
193     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
194     CHECK_NULL_VOID(menuTheme);
195 
196     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
197     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
198     AnimationOption positionOption;
199     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
200     positionOption.SetCurve(motion);
201     AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition]() {
202         if (menuRenderContext) {
203             menuRenderContext->UpdatePosition(
204                 OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
205         }
206     });
207 }
208 
ShowContextMenuDisappearAnimation(AnimationOption & option,const RefPtr<MenuWrapperPattern> & menuWrapperPattern,bool startDrag=false)209 void ShowContextMenuDisappearAnimation(
210     AnimationOption& option, const RefPtr<MenuWrapperPattern>& menuWrapperPattern, bool startDrag = false)
211 {
212     CHECK_NULL_VOID(menuWrapperPattern);
213     auto menuChild = menuWrapperPattern->GetMenu();
214     CHECK_NULL_VOID(menuChild);
215     auto menuRenderContext = menuChild->GetRenderContext();
216     CHECK_NULL_VOID(menuRenderContext);
217     auto menuPattern = menuChild->GetPattern<MenuPattern>();
218     CHECK_NULL_VOID(menuPattern);
219     auto menuPosition = menuPattern->GetEndOffset();
220 
221     auto pipelineContext = PipelineContext::GetCurrentContext();
222     CHECK_NULL_VOID(pipelineContext);
223     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
224     CHECK_NULL_VOID(menuTheme);
225     if (startDrag) {
226         menuRenderContext->UpdateTransformScale(
227             VectorF(menuTheme->GetMenuDragAnimationScale(), menuTheme->GetMenuDragAnimationScale()));
228     }
229     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
230     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
231     AnimationOption positionOption;
232     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
233     positionOption.SetCurve(motion);
234     AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition]() {
235         if (menuRenderContext) {
236             menuRenderContext->UpdatePosition(
237                 OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
238         }
239     });
240 
241     auto disappearDuration = menuTheme->GetDisappearDuration();
242     auto menuAnimationScale = menuTheme->GetMenuAnimationScale();
243     AnimationOption scaleOption;
244     scaleOption.SetCurve(Curves::FAST_OUT_LINEAR_IN);
245     scaleOption.SetDuration(disappearDuration);
246     AnimationUtils::Animate(scaleOption, [menuRenderContext, menuAnimationScale]() {
247         if (menuRenderContext) {
248             menuRenderContext->UpdateTransformScale({ menuAnimationScale, menuAnimationScale });
249         }
250     });
251 
252     option.SetDuration(disappearDuration);
253     option.SetCurve(Curves::FRICTION);
254     AnimationUtils::Animate(
255         option,
256         [menuRenderContext]() {
257             if (menuRenderContext) {
258                 menuRenderContext->UpdateOpacity(0.0);
259             }
260         },
261         option.GetOnFinishEvent());
262 }
263 } // namespace
264 
UpdateContextMenuDisappearPosition(const NG::OffsetF & offset)265 void OverlayManager::UpdateContextMenuDisappearPosition(const NG::OffsetF& offset)
266 {
267     auto pipelineContext = PipelineContext::GetCurrentContext();
268     CHECK_NULL_VOID(pipelineContext);
269     auto overlayManager = pipelineContext->GetOverlayManager();
270     CHECK_NULL_VOID(overlayManager);
271     overlayManager->UpdateDragMoveVector(offset);
272 
273     if (overlayManager->IsOriginDragMoveVector() || !overlayManager->IsUpdateDragMoveVector()) {
274         return;
275     }
276 
277     if (menuMap_.empty()) {
278         return;
279     }
280     auto rootNode = rootNodeWeak_.Upgrade();
281     for (const auto& child : rootNode->GetChildren()) {
282         auto node = DynamicCast<FrameNode>(child);
283         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
284             UpdateContextMenuDisappearPositionAnimation(node, overlayManager->GetUpdateDragMoveVector());
285         }
286     }
287 }
288 
PostDialogFinishEvent(const WeakPtr<FrameNode> & nodeWk)289 void OverlayManager::PostDialogFinishEvent(const WeakPtr<FrameNode>& nodeWk)
290 {
291     TAG_LOGD(AceLogTag::ACE_OVERLAY, "post dialog finishi event enter");
292     auto context = PipelineContext::GetCurrentContext();
293     CHECK_NULL_VOID(context);
294     auto taskExecutor = context->GetTaskExecutor();
295     CHECK_NULL_VOID(taskExecutor);
296     // animation finish event should be posted to UI thread.
297     taskExecutor->PostTask(
298         [weak = WeakClaim(this), nodeWk, id = Container::CurrentId()]() {
299             ContainerScope scope(id);
300             auto overlayManager = weak.Upgrade();
301             auto node = nodeWk.Upgrade();
302             CHECK_NULL_VOID(overlayManager && node);
303             SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_NONE };
304             node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
305             overlayManager->OnDialogCloseEvent(node);
306         },
307         TaskExecutor::TaskType::UI);
308 }
309 
OnDialogCloseEvent(const RefPtr<FrameNode> & node)310 void OverlayManager::OnDialogCloseEvent(const RefPtr<FrameNode>& node)
311 {
312     TAG_LOGD(AceLogTag::ACE_OVERLAY, "on dialog close event enter");
313     CHECK_NULL_VOID(node);
314 
315     BlurOverlayNode(node);
316 
317     auto dialogPattern = node->GetPattern<DialogPattern>();
318     CHECK_NULL_VOID(dialogPattern);
319     auto option = dialogPattern->GetCloseAnimation().value_or(AnimationOption());
320     auto onFinish = option.GetOnFinishEvent();
321 
322     auto dialogLayoutProp = dialogPattern->GetLayoutProperty<DialogLayoutProperty>();
323     bool isShowInSubWindow = false;
324     if (dialogLayoutProp) {
325         isShowInSubWindow = dialogLayoutProp->GetShowInSubWindowValue(false);
326     }
327     if (onFinish != nullptr) {
328         onFinish();
329     }
330 
331     auto root = node->GetParent();
332     CHECK_NULL_VOID(root);
333     root->RemoveChild(node);
334     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
335     auto lastChild = AceType::DynamicCast<FrameNode>(root->GetLastChild());
336     if (lastChild) {
337         auto pattern = lastChild->GetPattern();
338         if (!AceType::InstanceOf<StagePattern>(pattern)) {
339             return;
340         }
341     }
342 
343     auto container = Container::Current();
344     CHECK_NULL_VOID(container);
345     if (container->IsDialogContainer() || isShowInSubWindow) {
346         SubwindowManager::GetInstance()->HideSubWindowNG();
347     }
348 }
349 
OpenDialogAnimation(const RefPtr<FrameNode> & node)350 void OverlayManager::OpenDialogAnimation(const RefPtr<FrameNode>& node)
351 {
352     TAG_LOGD(AceLogTag::ACE_OVERLAY, "open dialog animation");
353     CHECK_NULL_VOID(node);
354     auto pipeline = PipelineContext::GetCurrentContext();
355     CHECK_NULL_VOID(pipeline);
356     auto theme = pipeline->GetTheme<DialogTheme>();
357     CHECK_NULL_VOID(theme);
358     auto root = rootNodeWeak_.Upgrade();
359     auto dialogPattern = node->GetPattern<DialogPattern>();
360     auto container = Container::Current();
361     if (container && container->IsScenceBoardWindow()) {
362         root = dialogPattern->GetDialogProperties().windowScene.Upgrade();
363     }
364     CHECK_NULL_VOID(root);
365     node->MountToParent(root);
366     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
367     BlurLowerNode(node);
368 
369     AnimationOption option;
370     // default opacity animation params
371     option.SetCurve(Curves::SHARP);
372     option.SetDuration(theme->GetOpacityAnimationDurIn());
373     option.SetFillMode(FillMode::FORWARDS);
374     option = dialogPattern->GetOpenAnimation().value_or(option);
375     option.SetIteration(1);
376     option.SetAnimationDirection(AnimationDirection::NORMAL);
377     auto onFinish = option.GetOnFinishEvent();
378     option.SetOnFinishEvent(
379         [weak = WeakClaim(this), nodeWK = WeakPtr<FrameNode>(node), onFinish] {
380             if (onFinish) {
381                 onFinish();
382             }
383             auto overlayManager = weak.Upgrade();
384             auto node = nodeWK.Upgrade();
385             CHECK_NULL_VOID(overlayManager && node);
386             overlayManager->FocusOverlayNode(node);
387         });
388     auto ctx = node->GetRenderContext();
389     option.SetFinishCallbackType(dialogPattern->GetOpenAnimation().has_value()
390                             ? dialogPattern->GetOpenAnimation().value().GetFinishCallbackType()
391                             : FinishCallbackType::REMOVED);
392     CHECK_NULL_VOID(ctx);
393     ctx->OpacityAnimation(option, theme->GetOpacityStart(), theme->GetOpacityEnd());
394     // scale animation on dialog content
395     auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
396     CHECK_NULL_VOID(contentNode);
397     ctx = contentNode->GetRenderContext();
398     CHECK_NULL_VOID(ctx);
399     option.SetOnFinishEvent(nullptr);
400     option.SetCurve(SHOW_SCALE_ANIMATION_CURVE);
401     option.SetDuration(dialogPattern->GetOpenAnimation().has_value()
402                            ? dialogPattern->GetOpenAnimation().value().GetDuration()
403                            : theme->GetAnimationDurationIn());
404     ctx->ScaleAnimation(option, theme->GetScaleStart(), theme->GetScaleEnd());
405     node->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
406 }
407 
CloseDialogAnimation(const RefPtr<FrameNode> & node)408 void OverlayManager::CloseDialogAnimation(const RefPtr<FrameNode>& node)
409 {
410     TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog animation");
411     CHECK_NULL_VOID(node);
412     auto pipeline = PipelineContext::GetCurrentContext();
413     CHECK_NULL_VOID(pipeline);
414     auto theme = pipeline->GetTheme<DialogTheme>();
415     CHECK_NULL_VOID(theme);
416     SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_KEYBOARD };
417     node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
418 
419     // default opacity animation params
420     AnimationOption option;
421     option.SetFillMode(FillMode::FORWARDS);
422     option.SetCurve(Curves::SHARP);
423     option.SetDuration(theme->GetAnimationDurationOut());
424     // get customized animation params
425     auto dialogPattern = node->GetPattern<DialogPattern>();
426     option = dialogPattern->GetCloseAnimation().value_or(option);
427     option.SetIteration(1);
428     option.SetAnimationDirection(AnimationDirection::NORMAL);
429     option.SetOnFinishEvent([weak = WeakClaim(this), nodeWk = WeakPtr<FrameNode>(node), id = Container::CurrentId()] {
430         ContainerScope scope(id);
431         auto overlayManager = weak.Upgrade();
432         CHECK_NULL_VOID(overlayManager);
433         overlayManager->PostDialogFinishEvent(nodeWk);
434     });
435     auto ctx = node->GetRenderContext();
436     CHECK_NULL_VOID(ctx);
437     option.SetFinishCallbackType(dialogPattern->GetOpenAnimation().has_value()
438                             ? dialogPattern->GetOpenAnimation().value().GetFinishCallbackType()
439                             : FinishCallbackType::REMOVED);
440     ctx->OpacityAnimation(option, theme->GetOpacityEnd(), theme->GetOpacityStart());
441 
442     // scale animation
443     auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
444     CHECK_NULL_VOID(contentNode);
445     ctx = contentNode->GetRenderContext();
446     CHECK_NULL_VOID(ctx);
447     option.SetOnFinishEvent(nullptr);
448     option.SetCurve(Curves::FRICTION);
449     ctx->ScaleAnimation(option, theme->GetScaleEnd(), theme->GetScaleStart());
450     // start animation immediately
451     pipeline->RequestFrame();
452 }
453 
SetContainerButtonEnable(bool isEnabled)454 void OverlayManager::SetContainerButtonEnable(bool isEnabled)
455 {
456     auto pipeline = PipelineContext::GetCurrentContext();
457     CHECK_NULL_VOID(pipeline);
458     pipeline->SetCloseButtonStatus(isEnabled);
459 }
460 
ShowMenuAnimation(const RefPtr<FrameNode> & menu)461 void OverlayManager::ShowMenuAnimation(const RefPtr<FrameNode>& menu)
462 {
463     BlurLowerNode(menu);
464     auto menuWrapper = menu->GetPattern<MenuWrapperPattern>();
465     CHECK_NULL_VOID(menuWrapper);
466     menuWrapper->CallMenuAboutToAppearCallback();
467     AnimationOption option;
468     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
469     option.SetDuration(MENU_ANIMATION_DURATION);
470     option.SetFillMode(FillMode::FORWARDS);
471     option.SetOnFinishEvent(
472         [weak = WeakClaim(this), menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId()] {
473             auto menu = menuWK.Upgrade();
474             auto overlayManager = weak.Upgrade();
475             CHECK_NULL_VOID(menu && overlayManager);
476             ContainerScope scope(id);
477             overlayManager->FocusOverlayNode(menu);
478             auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
479             menuWrapperPattern->CallMenuAppearCallback();
480         });
481 
482     auto pattern = menu->GetPattern<MenuWrapperPattern>();
483     if (pattern->GetPreviewMode() == MenuPreviewMode::CUSTOM) {
484         auto pipelineContext = PipelineContext::GetCurrentContext();
485         CHECK_NULL_VOID(pipelineContext);
486         auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
487         CHECK_NULL_VOID(menuTheme);
488         option.SetDuration(menuTheme->GetContextMenuAppearDuration());
489         auto previewChild = pattern->GetPreview();
490         if (previewChild) {
491             auto previewPattern = AceType::DynamicCast<MenuPreviewPattern>(previewChild->GetPattern());
492             if (previewPattern) {
493                 previewPattern->SetFirstShow();
494             }
495         }
496     }
497     pattern->SetAniamtinOption(option);
498     pattern->SetFirstShow();
499     auto menuChild = pattern->GetMenu();
500     CHECK_NULL_VOID(menuChild);
501     auto menuPattern = AceType::DynamicCast<MenuPattern>(menuChild->GetPattern());
502     CHECK_NULL_VOID(menuPattern);
503     menuPattern->SetFirstShow();
504 }
505 
PopMenuAnimation(const RefPtr<FrameNode> & menu,bool showPreviewAnimation,bool startDrag)506 void OverlayManager::PopMenuAnimation(const RefPtr<FrameNode>& menu, bool showPreviewAnimation, bool startDrag)
507 {
508     TAG_LOGD(AceLogTag::ACE_OVERLAY, "pop menu animation enter");
509     ResetLowerNodeFocusable(menu);
510     ResetContextMenuDragHideFinished();
511 
512     auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
513     CHECK_NULL_VOID(menuNode);
514     auto eventHub = menuNode->GetEventHub<EventHub>();
515     CHECK_NULL_VOID(eventHub);
516     eventHub->SetEnabledInternal(false);
517     auto menuWrapper = menu->GetPattern<MenuWrapperPattern>();
518     CHECK_NULL_VOID(menuWrapper);
519     menuWrapper->CallMenuAboutToDisappearCallback();
520     AnimationOption option;
521     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
522     option.SetDuration(MENU_ANIMATION_DURATION);
523     option.SetFillMode(FillMode::FORWARDS);
524     option.SetOnFinishEvent([rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
525                                 weak = WeakClaim(this)] {
526         ContainerScope scope(id);
527         auto menu = menuWK.Upgrade();
528         CHECK_NULL_VOID(menu);
529         auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
530         CHECK_NULL_VOID(menuNode);
531         auto eventHub = menuNode->GetEventHub<EventHub>();
532         CHECK_NULL_VOID(eventHub);
533         eventHub->SetEnabledInternal(true);
534         auto menuPattern = menuNode->GetPattern<MenuPattern>();
535         CHECK_NULL_VOID(menuPattern);
536         auto root = rootWeak.Upgrade();
537         auto overlayManager = weak.Upgrade();
538         CHECK_NULL_VOID(overlayManager);
539         overlayManager->SetContextMenuDragHideFinished(true);
540         auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
541         menuWrapperPattern->CallMenuDisappearCallback();
542         auto mainPipeline = PipelineContext::GetMainPipelineContext();
543         if (mainPipeline && menuWrapperPattern->GetMenuDisappearCallback()) {
544             mainPipeline->FlushPipelineImmediately();
545         }
546         // clear contextMenu then return
547         auto pipeline = PipelineBase::GetCurrentContext();
548         CHECK_NULL_VOID(pipeline);
549         auto theme = pipeline->GetTheme<SelectTheme>();
550         CHECK_NULL_VOID(theme);
551         auto expandDisplay = theme->GetExpandDisplay();
552         auto menuLayoutProp = menuPattern->GetLayoutProperty<MenuLayoutProperty>();
553         CHECK_NULL_VOID(menuLayoutProp);
554         bool isShowInSubWindow = menuLayoutProp->GetShowInSubWindowValue(true);
555         if (((menuWrapperPattern && menuWrapperPattern->IsContextMenu()) || (isShowInSubWindow && expandDisplay)) &&
556             (menuPattern->GetTargetTag() != V2::SELECT_ETS_TAG)) {
557             SubwindowManager::GetInstance()->ClearMenuNG(id);
558             overlayManager->ResetContextMenuDragHideFinished();
559             return;
560         }
561         auto container = Container::Current();
562         if (container && container->IsScenceBoardWindow()) {
563             root = overlayManager->FindWindowScene(menu);
564         }
565         CHECK_NULL_VOID(root);
566         overlayManager->BlurOverlayNode(menu);
567         root->RemoveChild(menu);
568         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
569     });
570     ShowMenuClearAnimation(menu, option, showPreviewAnimation, startDrag);
571 }
572 
ClearMenuAnimation(const RefPtr<FrameNode> & menu,bool showPreviewAnimation,bool startDrag)573 void OverlayManager::ClearMenuAnimation(const RefPtr<FrameNode>& menu, bool showPreviewAnimation, bool startDrag)
574 {
575     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear menu animation enter");
576     ResetLowerNodeFocusable(menu);
577     AnimationOption option;
578     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
579     option.SetDuration(MENU_ANIMATION_DURATION);
580     option.SetFillMode(FillMode::FORWARDS);
581     option.SetOnFinishEvent([rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
582                                 weak = WeakClaim(this)] {
583         auto menu = menuWK.Upgrade();
584         auto root = rootWeak.Upgrade();
585         auto overlayManager = weak.Upgrade();
586         CHECK_NULL_VOID(menu && overlayManager);
587         ContainerScope scope(id);
588         auto container = Container::Current();
589         if (container && container->IsScenceBoardWindow()) {
590             root = overlayManager->FindWindowScene(menu);
591         }
592         CHECK_NULL_VOID(root);
593         auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
594         // clear contextMenu then return
595         if ((menuWrapperPattern && menuWrapperPattern->IsContextMenu())) {
596             return;
597         }
598         overlayManager->BlurOverlayNode(menu);
599         root->RemoveChild(menu);
600         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
601     });
602     ShowMenuClearAnimation(menu, option, showPreviewAnimation, startDrag);
603 }
604 
ShowMenuClearAnimation(const RefPtr<FrameNode> & menu,AnimationOption & option,bool showPreviewAnimation,bool startDrag)605 void OverlayManager::ShowMenuClearAnimation(const RefPtr<FrameNode>& menu, AnimationOption& option,
606     bool showPreviewAnimation, bool startDrag)
607 {
608     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu clear animation enter");
609     auto context = menu->GetRenderContext();
610     CHECK_NULL_VOID(context);
611     auto pipeline = PipelineBase::GetCurrentContext();
612     CHECK_NULL_VOID(pipeline);
613     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
614     CHECK_NULL_VOID(menuWrapperPattern);
615     auto menuAnimationOffset = menuWrapperPattern->GetAnimationOffset();
616     if (menuWrapperPattern->GetPreviewMode() != MenuPreviewMode::NONE) {
617         if (!showPreviewAnimation) {
618             CleanPreviewInSubWindow();
619         } else {
620             ShowPreviewDisappearAnimation(menuWrapperPattern);
621         }
622         ShowContextMenuDisappearAnimation(option, menuWrapperPattern, startDrag);
623     } else {
624         AnimationUtils::Animate(
625             option,
626             [context, menuAnimationOffset]() {
627                 context->UpdateOpacity(0.0);
628                 context->UpdateOffset(menuAnimationOffset);
629             },
630             option.GetOnFinishEvent());
631     }
632     // start animation immediately
633     pipeline->RequestFrame();
634 }
635 
ShowToast(const std::string & message,int32_t duration,const std::string & bottom,bool isRightToLeft,const ToastShowMode & showMode)636 void OverlayManager::ShowToast(const std::string& message, int32_t duration, const std::string& bottom,
637     bool isRightToLeft, const ToastShowMode& showMode)
638 {
639     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show toast enter");
640     auto context = PipelineContext::GetCurrentContext();
641     CHECK_NULL_VOID(context);
642     auto rootNode = context->GetRootElement();
643     CHECK_NULL_VOID(rootNode);
644 
645     // only one toast
646     for (auto [id, toastNodeWeak] : toastMap_) {
647         rootNode->RemoveChild(toastNodeWeak.Upgrade());
648     }
649     toastMap_.clear();
650 
651     auto toastNode = ToastView::CreateToastNode(message, bottom, isRightToLeft, showMode);
652     CHECK_NULL_VOID(toastNode);
653     auto toastId = toastNode->GetId();
654     // mount to parent
655     toastNode->MountToParent(rootNode);
656     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
657     toastMap_[toastId] = toastNode;
658     AnimationOption option;
659     auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
660     option.SetCurve(curve);
661     option.SetDuration(TOAST_ANIMATION_DURATION);
662     option.SetFillMode(FillMode::FORWARDS);
663     duration = std::max(duration, AceApplicationInfo::GetInstance().GetBarrierfreeDuration());
664     auto&& callback = [weak = WeakClaim(this), toastId, duration, id = Container::CurrentId()]() {
665         auto overlayManager = weak.Upgrade();
666         CHECK_NULL_VOID(overlayManager);
667         ContainerScope scope(id);
668         overlayManager->PopToast(toastId);
669     };
670     continuousTask_.Reset(callback);
671     option.SetOnFinishEvent([continuousTask = continuousTask_, duration, id = Container::CurrentId()] {
672         ContainerScope scope(id);
673         auto context = PipelineContext::GetCurrentContext();
674         CHECK_NULL_VOID(context);
675         auto taskExecutor = context->GetTaskExecutor();
676         CHECK_NULL_VOID(taskExecutor);
677         taskExecutor->PostDelayedTask(continuousTask, TaskExecutor::TaskType::UI, duration);
678     });
679     auto ctx = toastNode->GetRenderContext();
680     CHECK_NULL_VOID(ctx);
681     ctx->UpdateOpacity(0.0);
682     ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
683     AnimationUtils::Animate(
684         option,
685         [ctx]() {
686             if (ctx) {
687                 ctx->UpdateOpacity(1.0);
688                 ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
689             }
690         },
691         option.GetOnFinishEvent());
692     toastNode->OnAccessibilityEvent(
693         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
694 }
695 
PopToast(int32_t toastId)696 void OverlayManager::PopToast(int32_t toastId)
697 {
698     AnimationOption option;
699     auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
700     option.SetCurve(curve);
701     option.SetDuration(TOAST_ANIMATION_DURATION);
702     option.SetFillMode(FillMode::FORWARDS);
703     // OnFinishEvent should be executed in UI thread.
704     option.SetOnFinishEvent([weak = WeakClaim(this), toastId] {
705         auto overlayManager = weak.Upgrade();
706         CHECK_NULL_VOID(overlayManager);
707         auto toastIter = overlayManager->toastMap_.find(toastId);
708         if (toastIter == overlayManager->toastMap_.end()) {
709             return;
710         }
711         auto toastUnderPop = toastIter->second.Upgrade();
712         CHECK_NULL_VOID(toastUnderPop);
713         auto context = PipelineContext::GetCurrentContext();
714         CHECK_NULL_VOID(context);
715         auto rootNode = context->GetRootElement();
716         CHECK_NULL_VOID(rootNode);
717         rootNode->RemoveChild(toastUnderPop);
718         overlayManager->toastMap_.erase(toastId);
719         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
720 
721         auto container = Container::Current();
722         CHECK_NULL_VOID(container);
723         if (container->IsDialogContainer() ||
724             (container->IsSubContainer() && rootNode->GetChildren().empty())) {
725             // hide window when toast show in subwindow.
726             SubwindowManager::GetInstance()->HideSubWindowNG();
727         }
728     });
729     auto toastIter = toastMap_.find(toastId);
730     if (toastIter == toastMap_.end()) {
731         return;
732     }
733     auto toastUnderPop = toastIter->second.Upgrade();
734     CHECK_NULL_VOID(toastUnderPop);
735     auto ctx = toastUnderPop->GetRenderContext();
736     CHECK_NULL_VOID(ctx);
737     ctx->UpdateOpacity(1.0);
738     ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
739     AnimationUtils::Animate(
740         option,
741         [ctx]() {
742             if (ctx) {
743                 ctx->UpdateOpacity(0.0);
744                 ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
745             }
746         },
747         option.GetOnFinishEvent());
748     // start animation immediately
749     auto pipeline = PipelineContext::GetCurrentContext();
750     CHECK_NULL_VOID(pipeline);
751     pipeline->RequestFrame();
752     AccessibilityEvent event;
753     event.type = AccessibilityEventType::CHANGE;
754     event.windowContentChangeTypes = WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE;
755     pipeline->SendEventToAccessibility(event);
756 }
757 
ClearToastInSubwindow()758 void OverlayManager::ClearToastInSubwindow()
759 {
760     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear toast in subwindow enter");
761     SubwindowManager::GetInstance()->ClearToastInSubwindow();
762 }
763 
ClearToast()764 void OverlayManager::ClearToast()
765 {
766     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear toast enter");
767     auto context = PipelineContext::GetCurrentContext();
768     CHECK_NULL_VOID(context);
769     auto rootNode = context->GetRootElement();
770     CHECK_NULL_VOID(rootNode);
771     for (auto [id, toastNodeWeak] : toastMap_) {
772         PopToast(id);
773     }
774 }
775 
ShowPopup(int32_t targetId,const PopupInfo & popupInfo)776 void OverlayManager::ShowPopup(int32_t targetId, const PopupInfo& popupInfo)
777 {
778     auto rootNode = rootNodeWeak_.Upgrade();
779     CHECK_NULL_VOID(rootNode);
780     auto frameNode = AceType::DynamicCast<FrameNode>(rootNode);
781     if (frameNode && !frameNode->IsLayoutComplete()) {
782         auto context = PipelineContext::GetCurrentContext();
783         CHECK_NULL_VOID(context);
784         auto taskExecutor = context->GetTaskExecutor();
785         CHECK_NULL_VOID(taskExecutor);
786         taskExecutor->PostTask(
787             [targetId, popupInfo, weak = WeakClaim(this)]() {
788                 auto overlayManager = weak.Upgrade();
789                 CHECK_NULL_VOID(overlayManager);
790                 overlayManager->MountPopup(targetId, popupInfo);
791             },
792             TaskExecutor::TaskType::UI);
793     } else {
794         MountPopup(targetId, popupInfo);
795     }
796 }
797 
MountPopup(int32_t targetId,const PopupInfo & popupInfo)798 void OverlayManager::MountPopup(int32_t targetId, const PopupInfo& popupInfo)
799 {
800     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show popup enter");
801     popupMap_[targetId] = popupInfo;
802     if (!popupInfo.markNeedUpdate) {
803         TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
804         return;
805     }
806     popupMap_[targetId].markNeedUpdate = false;
807     auto popupNode = popupInfo.popupNode;
808     CHECK_NULL_VOID(popupNode);
809     auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
810     CHECK_NULL_VOID(layoutProp);
811     auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
812     auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
813     CHECK_NULL_VOID(paintProperty);
814     auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
815     auto isUseCustom = paintProperty->GetUseCustom().value_or(false);
816 
817     auto rootNode = rootNodeWeak_.Upgrade();
818     auto container = Container::Current();
819     if (container && container->IsScenceBoardWindow()) {
820         rootNode = FindWindowScene(popupInfo.target.Upgrade());
821     }
822     CHECK_NULL_VOID(rootNode);
823     CHECK_NULL_VOID(popupInfo.markNeedUpdate);
824     CHECK_NULL_VOID(popupInfo.popupNode);
825 
826     const auto& rootChildren = rootNode->GetChildren();
827     auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
828     if (iter == rootChildren.rend()) {
829         popupNode->MountToParent(rootNode);
830     }
831 
832     // attach popupNode before entering animation
833     popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(true);
834     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
835     popupMap_[targetId].isCurrentOnShow = true;
836 
837     auto popupPattern = popupNode->GetPattern<BubblePattern>();
838     CHECK_NULL_VOID(popupPattern);
839     if ((isTypeWithOption && !isShowInSubWindow) ||
840         (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && popupInfo.focusable)) {
841         BlurLowerNode(popupNode);
842         auto onFinish = [popupNodeWk = WeakPtr<FrameNode>(popupNode), weak = WeakClaim(this)]() {
843             auto overlayManager = weak.Upgrade();
844             auto popupNode = popupNodeWk.Upgrade();
845             CHECK_NULL_VOID(overlayManager && popupNode);
846             overlayManager->FocusOverlayNode(popupNode);
847         };
848         popupPattern->StartEnteringAnimation(onFinish);
849     } else {
850         popupPattern->StartEnteringAnimation(nullptr);
851     }
852 }
853 
HidePopup(int32_t targetId,const PopupInfo & popupInfo)854 void OverlayManager::HidePopup(int32_t targetId, const PopupInfo& popupInfo)
855 {
856     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide popup enter");
857     popupMap_[targetId] = popupInfo;
858     if (!popupInfo.markNeedUpdate) {
859         TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
860         return;
861     }
862     popupMap_[targetId].markNeedUpdate = false;
863     auto focusable = popupInfo.focusable;
864     auto popupNode = popupInfo.popupNode;
865     CHECK_NULL_VOID(popupNode);
866     auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
867     CHECK_NULL_VOID(layoutProp);
868     auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
869     auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
870     CHECK_NULL_VOID(paintProperty);
871     auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
872     auto isUseCustom = paintProperty->GetUseCustom().value_or(false);
873 
874     auto rootNode = rootNodeWeak_.Upgrade();
875     auto container = Container::Current();
876     if (container && container->IsScenceBoardWindow()) {
877         rootNode = FindWindowScene(popupInfo.target.Upgrade());
878     }
879     CHECK_NULL_VOID(rootNode);
880 
881     const auto& rootChildren = rootNode->GetChildren();
882     auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
883     if (iter == rootChildren.rend()) {
884         return;
885     }
886 
887     auto popupPattern = popupNode->GetPattern<BubblePattern>();
888     CHECK_NULL_VOID(popupPattern);
889     if (popupPattern->GetTransitionStatus() == TransitionStatus::EXITING) {
890         return;
891     }
892     popupPattern->SetTransitionStatus(TransitionStatus::EXITING);
893     if ((isTypeWithOption && !isShowInSubWindow) ||
894         (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && focusable)) {
895         ResetLowerNodeFocusable(popupNode);
896     }
897     CheckReturnFocus(popupNode);
898     // detach popupNode after exiting animation
899     popupMap_[targetId].isCurrentOnShow = false;
900     popupPattern->StartExitingAnimation(
901         [isShowInSubWindow, isTypeWithOption, isUseCustom, focusable, popupNodeWk = WeakPtr<FrameNode>(popupNode),
902             rootNodeWk = WeakPtr<UINode>(rootNode), weak = WeakClaim(this)]() {
903             auto rootNode = rootNodeWk.Upgrade();
904             auto popupNode = popupNodeWk.Upgrade();
905             auto overlayManager = weak.Upgrade();
906             CHECK_NULL_VOID(rootNode && popupNode && overlayManager);
907 
908             auto popupPattern = popupNode->GetPattern<BubblePattern>();
909             CHECK_NULL_VOID(popupPattern);
910             popupPattern->SetTransitionStatus(TransitionStatus::INVISIABLE);
911             popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
912             rootNode->RemoveChild(popupNode);
913             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
914             if ((isTypeWithOption && !isShowInSubWindow) ||
915                 (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && focusable)) {
916                 overlayManager->BlurOverlayNode(popupNode);
917             }
918             if (isShowInSubWindow) {
919                 auto subwindow = SubwindowManager::GetInstance();
920                 CHECK_NULL_VOID(subwindow);
921                 subwindow->HideSubWindowNG();
922             }
923         });
924     popupNode->OnAccessibilityEvent(
925         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
926     RemoveEventColumn();
927     RemovePixelMapAnimation(false, 0, 0);
928     RemoveFilter();
929 }
930 
HidePopupWithoutAnimation(int32_t targetId,const PopupInfo & popupInfo)931 RefPtr<FrameNode> OverlayManager::HidePopupWithoutAnimation(int32_t targetId, const PopupInfo& popupInfo)
932 {
933     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide popup without animation enter");
934     popupMap_[targetId] = popupInfo;
935     CHECK_NULL_RETURN(popupInfo.markNeedUpdate, nullptr);
936     if (!popupInfo.markNeedUpdate) {
937         TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
938         return nullptr;
939     }
940     CHECK_NULL_RETURN(popupInfo.popupNode, nullptr);
941     popupInfo.popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
942     CHECK_NULL_RETURN(popupInfo.isCurrentOnShow, nullptr);
943     popupMap_[targetId].isCurrentOnShow = false;
944     auto pattern = popupInfo.popupNode->GetPattern<BubblePattern>();
945     CHECK_NULL_RETURN(pattern, nullptr);
946     pattern->SetTransitionStatus(TransitionStatus::INVISIABLE);
947     auto rootNode = rootNodeWeak_.Upgrade();
948     CHECK_NULL_RETURN(rootNode, nullptr);
949     auto rootChildren = rootNode->GetChildren();
950     auto iter = std::find(rootChildren.begin(), rootChildren.end(), popupInfo.popupNode);
951     if (iter != rootChildren.end()) {
952         return popupMap_[targetId].popupNode;
953     }
954     return nullptr;
955 }
956 
ShowIndexerPopup(int32_t targetId,RefPtr<FrameNode> & customNode)957 void OverlayManager::ShowIndexerPopup(int32_t targetId, RefPtr<FrameNode>& customNode)
958 {
959     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show indexer popup enter");
960     CHECK_NULL_VOID(customNode);
961     auto rootNode = rootNodeWeak_.Upgrade();
962     CHECK_NULL_VOID(rootNode);
963     if (!customPopupMap_[targetId] || customPopupMap_[targetId] != customNode) {
964         customPopupMap_[targetId] = customNode;
965         customNode->MountToParent(rootNode);
966         customNode->MarkModifyDone();
967         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
968     }
969 }
970 
RemoveIndexerPopupById(int32_t targetId)971 void OverlayManager::RemoveIndexerPopupById(int32_t targetId)
972 {
973     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove indexer popup byid enter");
974     if (customPopupMap_.empty()) {
975         return;
976     }
977     auto rootNode = rootNodeWeak_.Upgrade();
978     CHECK_NULL_VOID(rootNode);
979     auto iter = customPopupMap_.find(targetId);
980     if (iter != customPopupMap_.end()) {
981         rootNode->RemoveChild(iter->second);
982         customPopupMap_.erase(iter);
983         rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
984     }
985 }
986 
RemoveIndexerPopup()987 void OverlayManager::RemoveIndexerPopup()
988 {
989     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove indexer popup enter");
990     if (customPopupMap_.empty()) {
991         return;
992     }
993     auto rootNode = rootNodeWeak_.Upgrade();
994     CHECK_NULL_VOID(rootNode);
995     for (const auto& popup : customPopupMap_) {
996         auto popupNode = popup.second;
997         rootNode->RemoveChild(popupNode);
998     }
999     customPopupMap_.clear();
1000     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1001 }
1002 
HideCustomPopups()1003 void OverlayManager::HideCustomPopups()
1004 {
1005     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide custom popup enter");
1006     if (popupMap_.empty()) {
1007         return;
1008     }
1009     for (const auto& popup : popupMap_) {
1010         auto popupInfo = popup.second;
1011         if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
1012             auto targetNodeId = popupInfo.target.Upgrade()->GetId();
1013             auto popupNode = popupInfo.popupNode;
1014             CHECK_NULL_VOID(popupNode);
1015             auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1016             CHECK_NULL_VOID(layoutProp);
1017             auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
1018             CHECK_NULL_VOID(paintProperty);
1019             auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
1020             popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1021             // if use popup with option, skip
1022             if (isTypeWithOption) {
1023                 continue;
1024             }
1025             popupInfo.markNeedUpdate = true;
1026             auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1027             if (showInSubWindow) {
1028                 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
1029             } else {
1030                 HidePopup(targetNodeId, popupInfo);
1031             }
1032         }
1033     }
1034 }
1035 
HideAllPopups()1036 void OverlayManager::HideAllPopups()
1037 {
1038     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide all popup enter");
1039     if (popupMap_.empty()) {
1040         return;
1041     }
1042     for (const auto& popup : popupMap_) {
1043         auto popupInfo = popup.second;
1044         if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
1045             auto targetNodeId = popupInfo.target.Upgrade()->GetId();
1046             auto popupNode = popupInfo.popupNode;
1047             CHECK_NULL_VOID(popupNode);
1048             auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1049             CHECK_NULL_VOID(layoutProp);
1050             popupInfo.markNeedUpdate = true;
1051             auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1052             if (showInSubWindow) {
1053                 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
1054             } else {
1055                 HidePopup(targetNodeId, popupInfo);
1056             }
1057         }
1058     }
1059 }
1060 
ErasePopup(int32_t targetId)1061 void OverlayManager::ErasePopup(int32_t targetId)
1062 {
1063     TAG_LOGD(AceLogTag::ACE_OVERLAY, "erase popup enter");
1064     if (popupMap_.find(targetId) != popupMap_.end()) {
1065         auto rootNode = rootNodeWeak_.Upgrade();
1066         CHECK_NULL_VOID(rootNode);
1067         rootNode->RemoveChild(popupMap_[targetId].popupNode);
1068         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1069         popupMap_.erase(targetId);
1070     }
1071 }
1072 
ShowMenuHelper(RefPtr<FrameNode> & menu,int32_t targetId,const NG::OffsetF & offset)1073 bool OverlayManager::ShowMenuHelper(RefPtr<FrameNode>& menu, int32_t targetId, const NG::OffsetF& offset)
1074 {
1075     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu helper enter");
1076     if (!menu) {
1077         // get existing menuNode
1078         auto it = menuMap_.find(targetId);
1079         if (it != menuMap_.end()) {
1080             menu = it->second;
1081         }
1082     } else {
1083         // creating new menu
1084         menuMap_[targetId] = menu;
1085     }
1086     CHECK_NULL_RETURN(menu, false);
1087 
1088     RefPtr<FrameNode> menuFrameNode = menu;
1089     if (menu->GetTag() != V2::MENU_ETS_TAG) {
1090         auto menuChild = menu->GetChildAtIndex(0);
1091         CHECK_NULL_RETURN(menuChild, false);
1092         menuFrameNode = DynamicCast<FrameNode>(menuChild);
1093     }
1094 
1095     auto props = menuFrameNode->GetLayoutProperty<MenuLayoutProperty>();
1096     CHECK_NULL_RETURN(props, false);
1097     props->UpdateMenuOffset(offset);
1098     menuFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1099     return true;
1100 }
1101 
ShowMenu(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)1102 void OverlayManager::ShowMenu(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
1103 {
1104     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu enter");
1105     if (!ShowMenuHelper(menu, targetId, offset)) {
1106         TAG_LOGW(AceLogTag::ACE_OVERLAY, "show menu helper failed");
1107         return;
1108     }
1109     auto rootNode = rootNodeWeak_.Upgrade();
1110     auto container = Container::Current();
1111     if (container && container->IsScenceBoardWindow()) {
1112         auto wrapperPattern = AceType::DynamicCast<MenuWrapperPattern>(menu->GetPattern());
1113         CHECK_NULL_VOID(wrapperPattern);
1114         auto menuChild = wrapperPattern->GetMenu();
1115         CHECK_NULL_VOID(menuChild);
1116         auto menuPattern = AceType::DynamicCast<MenuPattern>(menuChild->GetPattern());
1117         CHECK_NULL_VOID(menuPattern);
1118         rootNode = FindWindowScene(FrameNode::GetFrameNode(menuPattern->GetTargetTag(), menuPattern->GetTargetId()));
1119     }
1120     CHECK_NULL_VOID(rootNode);
1121     auto rootChildren = rootNode->GetChildren();
1122     auto iter = std::find(rootChildren.begin(), rootChildren.end(), menu);
1123     // menuNode already showing
1124     if (iter == rootChildren.end()) {
1125         menu->MountToParent(rootNode);
1126         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1127         menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1128         ShowMenuAnimation(menu);
1129         menu->MarkModifyDone();
1130     }
1131     menu->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1132     auto pattern = menu->GetPattern<MenuWrapperPattern>();
1133     CHECK_NULL_VOID(pattern);
1134     pattern->SetShow(true);
1135 }
1136 
1137 // subwindow only contains one menu instance.
ShowMenuInSubWindow(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)1138 void OverlayManager::ShowMenuInSubWindow(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
1139 {
1140     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu insubwindow enter");
1141     auto menuOffset = offset;
1142     auto currentSubwindow = SubwindowManager::GetInstance()->GetCurrentWindow();
1143     if (currentSubwindow) {
1144         auto subwindowRect = currentSubwindow->GetRect();
1145         menuOffset -= subwindowRect.GetOffset();
1146     }
1147     if (!ShowMenuHelper(menu, targetId, menuOffset)) {
1148         TAG_LOGW(AceLogTag::ACE_OVERLAY, "show menu helper failed");
1149         return;
1150     }
1151     auto rootNode = rootNodeWeak_.Upgrade();
1152     CHECK_NULL_VOID(rootNode);
1153     rootNode->Clean();
1154     menu->MountToParent(rootNode);
1155     ShowMenuAnimation(menu);
1156     menu->MarkModifyDone();
1157     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1158 
1159     // set subwindow container id in menu.
1160     auto menuPattern = menu->GetPattern<PopupBasePattern>();
1161     CHECK_NULL_VOID(menuPattern);
1162     menuPattern->SetContainerId(Container::CurrentId());
1163 }
1164 
HideMenuInSubWindow(const RefPtr<FrameNode> & menu,int32_t targetId)1165 void OverlayManager::HideMenuInSubWindow(const RefPtr<FrameNode>& menu, int32_t targetId)
1166 {
1167     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide menu insubwindow enter");
1168     CHECK_NULL_VOID(menu);
1169     PopMenuAnimation(menu);
1170 }
1171 
HideMenuInSubWindow(bool showPreviewAnimation,bool startDrag)1172 void OverlayManager::HideMenuInSubWindow(bool showPreviewAnimation, bool startDrag)
1173 {
1174     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide menu insubwindow enter");
1175     if (menuMap_.empty()) {
1176         return;
1177     }
1178     auto rootNode = rootNodeWeak_.Upgrade();
1179     for (const auto& child : rootNode->GetChildren()) {
1180         auto node = DynamicCast<FrameNode>(child);
1181         if (node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1182             PopMenuAnimation(node, showPreviewAnimation, startDrag);
1183         }
1184     }
1185 }
1186 
GetMenuNode(int32_t targetId)1187 RefPtr<FrameNode> OverlayManager::GetMenuNode(int32_t targetId)
1188 {
1189     auto it = menuMap_.find(targetId);
1190     if (it != menuMap_.end()) {
1191         return it->second;
1192     }
1193     return nullptr;
1194 }
1195 
HideMenu(const RefPtr<FrameNode> & menu,int32_t targetId,bool isMenuOnTouch)1196 void OverlayManager::HideMenu(const RefPtr<FrameNode>& menu, int32_t targetId, bool isMenuOnTouch)
1197 {
1198     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide menu enter");
1199     auto pattern = menu->GetPattern<MenuWrapperPattern>();
1200     CHECK_NULL_VOID(pattern);
1201     pattern->SetShow(false);
1202     PopMenuAnimation(menu);
1203     menu->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1204     RemoveEventColumn();
1205     if (isMenuOnTouch) {
1206         RemovePixelMap();
1207     } else {
1208         RemovePixelMapAnimation(false, 0, 0);
1209     }
1210     RemoveFilterAnimation();
1211 }
1212 
HideAllMenus()1213 void OverlayManager::HideAllMenus()
1214 {
1215     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide all menus enter");
1216     auto container = Container::Current();
1217     if (container && container->IsScenceBoardWindow()) {
1218         for (const auto& windowScene : windowSceneSet_) {
1219             if (!windowScene.Upgrade()) {
1220                 continue;
1221             }
1222             for (const auto& child : windowScene.Upgrade()->GetChildren()) {
1223                 auto node = DynamicCast<FrameNode>(child);
1224                 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1225                     PopMenuAnimation(node);
1226                 }
1227             }
1228         }
1229         return;
1230     }
1231 
1232     auto rootNode = rootNodeWeak_.Upgrade();
1233     CHECK_NULL_VOID(rootNode);
1234     for (const auto& child : rootNode->GetChildren()) {
1235         auto node = DynamicCast<FrameNode>(child);
1236         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1237             PopMenuAnimation(node);
1238         }
1239     }
1240 }
1241 
DeleteMenu(int32_t targetId)1242 void OverlayManager::DeleteMenu(int32_t targetId)
1243 {
1244     TAG_LOGD(AceLogTag::ACE_OVERLAY, "delete menu enter");
1245     auto it = menuMap_.find(targetId);
1246     if (it == menuMap_.end()) {
1247         return;
1248     }
1249     auto node = AceType::DynamicCast<FrameNode>(it->second);
1250     if (node->GetParent()) {
1251         auto id = Container::CurrentId();
1252         SubwindowManager::GetInstance()->ClearMenu();
1253         SubwindowManager::GetInstance()->ClearMenuNG(id);
1254     }
1255     menuMap_.erase(it);
1256 }
1257 
CleanMenuInSubWindowWithAnimation()1258 void OverlayManager::CleanMenuInSubWindowWithAnimation()
1259 {
1260     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean menu insubwindow with animation enter");
1261     auto rootNode = rootNodeWeak_.Upgrade();
1262     CHECK_NULL_VOID(rootNode);
1263     RefPtr<FrameNode> menu;
1264     for (const auto& child : rootNode->GetChildren()) {
1265         auto node = DynamicCast<FrameNode>(child);
1266         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1267             menu = node;
1268             break;
1269         }
1270     }
1271     CHECK_NULL_VOID(menu);
1272     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1273     CHECK_NULL_VOID(menuWrapperPattern);
1274     menuWrapperPattern->SetMenuHide();
1275     ClearMenuAnimation(menu);
1276 }
1277 
CleanPreviewInSubWindow()1278 void OverlayManager::CleanPreviewInSubWindow()
1279 {
1280     auto rootNode = rootNodeWeak_.Upgrade();
1281     CHECK_NULL_VOID(rootNode);
1282     for (const auto& child : rootNode->GetChildren()) {
1283         auto node = DynamicCast<FrameNode>(child);
1284         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1285             for (auto& childNode : node->GetChildren()) {
1286                 auto frameNode = DynamicCast<FrameNode>(childNode);
1287                 if (frameNode &&
1288                     (frameNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG || frameNode->GetTag() == V2::IMAGE_ETS_TAG)) {
1289                     node->RemoveChild(frameNode);
1290                     break;
1291                 }
1292             }
1293             break;
1294         }
1295     }
1296 }
1297 
CleanMenuInSubWindow()1298 void OverlayManager::CleanMenuInSubWindow()
1299 {
1300     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean menu insubwindow enter");
1301     auto rootNode = rootNodeWeak_.Upgrade();
1302     CHECK_NULL_VOID(rootNode);
1303     for (const auto& child : rootNode->GetChildren()) {
1304         auto node = DynamicCast<FrameNode>(child);
1305         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1306             for (auto& childNode : node->GetChildren()) {
1307                 auto frameNode = DynamicCast<FrameNode>(childNode);
1308                 if (frameNode &&
1309                     (frameNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG || frameNode->GetTag() == V2::IMAGE_ETS_TAG)) {
1310                     node->RemoveChild(frameNode);
1311                     break;
1312                 }
1313             }
1314             rootNode->RemoveChild(node);
1315             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1316             break;
1317         }
1318     }
1319 
1320     for (const auto& child : rootNode->GetChildren()) {
1321         auto node = DynamicCast<FrameNode>(child);
1322         if (node && node->GetTag() == V2::COLUMN_ETS_TAG) {
1323             rootNode->RemoveChild(node);
1324             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1325             break;
1326         }
1327     }
1328 }
1329 
CleanPopupInSubWindow()1330 void OverlayManager::CleanPopupInSubWindow()
1331 {
1332     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean popup insubwindow enter");
1333     auto rootNode = rootNodeWeak_.Upgrade();
1334     CHECK_NULL_VOID(rootNode);
1335     std::vector<RefPtr<FrameNode>> removeNodes;
1336     for (const auto& child : rootNode->GetChildren()) {
1337         if (!child || child->GetTag() != V2::POPUP_ETS_TAG) {
1338             continue;
1339         }
1340         auto id = child->GetId();
1341         for (const auto& popup : popupMap_) {
1342             auto popupInfo = popup.second;
1343             auto target = popup.first;
1344             if (id != popupInfo.popupId) {
1345                 continue;
1346             }
1347             popupInfo.markNeedUpdate = true;
1348             auto removeNode = HidePopupWithoutAnimation(target, popupInfo);
1349             if (removeNode) {
1350                 removeNodes.emplace_back(removeNode);
1351             }
1352             break;
1353         }
1354     }
1355     for (const auto& removeNode : removeNodes) {
1356         rootNode->RemoveChild(removeNode);
1357     }
1358     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1359 }
1360 
BeforeShowDialog(const RefPtr<FrameNode> & node)1361 void OverlayManager::BeforeShowDialog(const RefPtr<FrameNode>& node)
1362 {
1363     TAG_LOGD(AceLogTag::ACE_OVERLAY, "before show dialog");
1364     CHECK_NULL_VOID(node);
1365     if (dialogMap_.find(node->GetId()) != dialogMap_.end()) {
1366         return;
1367     }
1368     dialogMap_[node->GetId()] = node;
1369 }
1370 
ShowDialog(const DialogProperties & dialogProps,std::function<void ()> && buildFunc,bool isRightToLeft)1371 RefPtr<FrameNode> OverlayManager::ShowDialog(
1372     const DialogProperties& dialogProps, std::function<void()>&& buildFunc, bool isRightToLeft)
1373 {
1374     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
1375     RefPtr<UINode> customNode;
1376     // create custom builder content
1377     if (buildFunc) {
1378         NG::ScopedViewStackProcessor builderViewStackProcessor;
1379         buildFunc();
1380         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
1381         CHECK_NULL_RETURN(customNode, nullptr);
1382     }
1383 
1384     auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
1385     CHECK_NULL_RETURN(dialog, nullptr);
1386     BeforeShowDialog(dialog);
1387     OpenDialogAnimation(dialog);
1388     dialogCount_++;
1389     // set close button disable
1390     SetContainerButtonEnable(false);
1391     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
1392         Recorder::EventParamsBuilder builder;
1393         builder
1394             .SetType("Dialog")
1395             .SetEventType(Recorder::EventType::DIALOG_SHOW)
1396             .SetExtra(Recorder::KEY_TITLE, dialogProps.title)
1397             .SetExtra(Recorder::KEY_SUB_TITLE, dialogProps.subtitle);
1398         Recorder::EventRecorder::Get().OnEvent(std::move(builder));
1399     }
1400     return dialog;
1401 }
1402 
OpenCustomDialog(const DialogProperties & dialogProps,std::function<void (int32_t)> && callback)1403 void OverlayManager::OpenCustomDialog(const DialogProperties& dialogProps, std::function<void(int32_t)> &&callback)
1404 {
1405     RefPtr<UINode> customNode;
1406     if (dialogProps.customBuilder) {
1407         NG::ScopedViewStackProcessor builderViewStackProcessor;
1408         dialogProps.customBuilder();
1409         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
1410         CHECK_NULL_VOID(customNode);
1411     }
1412     auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
1413     CHECK_NULL_VOID(dialog);
1414 
1415     BeforeShowDialog(dialog);
1416 
1417     // callback dialogId
1418     if (callback) {
1419         callback(dialog->GetId());
1420     }
1421 
1422     OpenDialogAnimation(dialog);
1423     dialogCount_++;
1424 
1425     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
1426         Recorder::EventParamsBuilder builder;
1427         builder
1428             .SetType("Dialog")
1429             .SetEventType(Recorder::EventType::DIALOG_SHOW)
1430             .SetExtra(Recorder::KEY_TITLE, dialogProps.title)
1431             .SetExtra(Recorder::KEY_SUB_TITLE, dialogProps.subtitle);
1432         Recorder::EventRecorder::Get().OnEvent(std::move(builder));
1433     }
1434     return;
1435 }
1436 
CloseCustomDialog(const int32_t dialogId)1437 void OverlayManager::CloseCustomDialog(const int32_t dialogId)
1438 {
1439     auto iter = dialogMap_.end();
1440     if (dialogId == -1) {
1441         int32_t tmpNodeId = -1;
1442         RefPtr<FrameNode> tmpNode;
1443         iter = dialogMap_.begin();
1444         while (iter != dialogMap_.end()) {
1445             auto dialogNode = (*iter).second;
1446             if (dialogNode && dialogNode->GetId() > tmpNodeId) {
1447                 tmpNodeId = dialogNode->GetId();
1448                 tmpNode = dialogNode;
1449             }
1450             iter++;
1451         }
1452         if (tmpNode) {
1453             CloseDialogInner(tmpNode);
1454         } else {
1455             LOGE("not find dialog when no dialog id");
1456         }
1457     } else {
1458         iter = dialogMap_.find(dialogId);
1459         if (iter == dialogMap_.end()) {
1460             LOGE("not find dialog by id %{public}d", dialogId);
1461             return;
1462         }
1463         RefPtr<FrameNode> tmpDialog = (*iter).second;
1464         CloseDialogInner(tmpDialog);
1465     }
1466     return;
1467 }
1468 
ShowCustomDialog(const RefPtr<FrameNode> & customNode)1469 void OverlayManager::ShowCustomDialog(const RefPtr<FrameNode>& customNode)
1470 {
1471     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show custom dialog enter");
1472     BeforeShowDialog(customNode);
1473     OpenDialogAnimation(customNode);
1474 }
1475 
ShowDateDialog(const DialogProperties & dialogProps,const DatePickerSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1476 void OverlayManager::ShowDateDialog(const DialogProperties& dialogProps, const DatePickerSettingData& settingData,
1477     std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1478 {
1479     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show date dialog enter");
1480     auto dialogNode = DatePickerDialogView::Show(
1481         dialogProps, std::move(settingData), std::move(dialogEvent), std::move(dialogCancelEvent));
1482     BeforeShowDialog(dialogNode);
1483     OpenDialogAnimation(dialogNode);
1484 }
1485 
ShowTimeDialog(const DialogProperties & dialogProps,const TimePickerSettingData & settingData,std::map<std::string,PickerTime> timePickerProperty,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1486 void OverlayManager::ShowTimeDialog(const DialogProperties& dialogProps, const TimePickerSettingData& settingData,
1487     std::map<std::string, PickerTime> timePickerProperty, std::map<std::string, NG::DialogEvent> dialogEvent,
1488     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1489 {
1490     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show time dialog enter");
1491     auto dialogNode = TimePickerDialogView::Show(
1492         dialogProps, settingData, std::move(timePickerProperty), std::move(dialogEvent), std::move(dialogCancelEvent));
1493     BeforeShowDialog(dialogNode);
1494     OpenDialogAnimation(dialogNode);
1495 }
1496 
ShowTextDialog(const DialogProperties & dialogProps,const TextPickerSettingData & settingData,std::map<std::string,NG::DialogTextEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1497 void OverlayManager::ShowTextDialog(const DialogProperties& dialogProps, const TextPickerSettingData& settingData,
1498     std::map<std::string, NG::DialogTextEvent> dialogEvent,
1499     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1500 {
1501     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show text dialog enter");
1502     auto dialogNode =
1503         TextPickerDialogView::Show(dialogProps, settingData, std::move(dialogEvent), std::move(dialogCancelEvent));
1504     BeforeShowDialog(dialogNode);
1505     OpenDialogAnimation(dialogNode);
1506     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
1507         Recorder::EventParamsBuilder builder;
1508         builder.SetType("TextPickerDialog").SetEventType(Recorder::EventType::DIALOG_SHOW);
1509         Recorder::EventRecorder::Get().OnEvent(std::move(builder));
1510     }
1511 }
1512 
ShowCalendarDialog(const DialogProperties & dialogProps,const CalendarSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1513 void OverlayManager::ShowCalendarDialog(const DialogProperties& dialogProps, const CalendarSettingData& settingData,
1514     std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1515 {
1516     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show calendar dialog enter");
1517     auto dialogNode =
1518         CalendarDialogView::Show(dialogProps, settingData, std::move(dialogEvent), std::move(dialogCancelEvent));
1519     BeforeShowDialog(dialogNode);
1520     OpenDialogAnimation(dialogNode);
1521 }
1522 
PopModalDialog(int32_t maskId)1523 void OverlayManager::PopModalDialog(int32_t maskId)
1524 {
1525     TAG_LOGD(AceLogTag::ACE_OVERLAY, "pop modal dialog enter");
1526     int32_t dialogId = -1;
1527     for (auto it = maskNodeIdMap_.begin(); it != maskNodeIdMap_.end(); it++) {
1528         if (maskId == it->second) {
1529             dialogId = it->first;
1530             break;
1531         }
1532     }
1533     auto subWindow = SubwindowManager::GetInstance()->GetSubwindow(subWindowId_);
1534     CHECK_NULL_VOID(subWindow);
1535     auto subOverlayManager = subWindow->GetOverlayManager();
1536     CHECK_NULL_VOID(subOverlayManager);
1537     std::map<int32_t, RefPtr<FrameNode>> DialogMap(
1538         subOverlayManager->GetDialogMap().begin(), subOverlayManager->GetDialogMap().end());
1539     for (auto it = DialogMap.begin(); it != DialogMap.end(); it++) {
1540         auto dialogProp = DynamicCast<DialogLayoutProperty>(it->second->GetLayoutProperty());
1541         if (dialogId == it->first) {
1542             auto hub = it->second->GetEventHub<DialogEventHub>();
1543             if (hub) {
1544                 hub->FireCancelEvent();
1545             }
1546             subOverlayManager->CloseDialog(it->second);
1547         }
1548     }
1549 }
1550 
RemoveDialogFromMap(const RefPtr<FrameNode> & node)1551 void OverlayManager::RemoveDialogFromMap(const RefPtr<FrameNode>& node)
1552 {
1553     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove dialog from map enter");
1554     CHECK_NULL_VOID(node);
1555     if (dialogMap_.find(node->GetId()) == dialogMap_.end()) {
1556         return;
1557     }
1558     dialogMap_.erase(node->GetId());
1559 }
1560 
DialogInMapHoldingFocus()1561 bool OverlayManager::DialogInMapHoldingFocus()
1562 {
1563     TAG_LOGD(AceLogTag::ACE_OVERLAY, "dialog in map holding focus enter");
1564     if (dialogMap_.empty()) {
1565         return false;
1566     }
1567     auto iter = dialogMap_.begin();
1568     while (iter != dialogMap_.end()) {
1569         auto dialogNode = (*iter).second;
1570         if (dialogNode && dialogNode->GetFocusHub() && dialogNode->GetFocusHub()->IsCurrentFocus()) {
1571             return true;
1572         }
1573         iter++;
1574     }
1575     return false;
1576 }
1577 
GetDialog(int32_t dialogId)1578 RefPtr<FrameNode> OverlayManager::GetDialog(int32_t dialogId)
1579 {
1580     TAG_LOGD(AceLogTag::ACE_OVERLAY, "get dialog enter");
1581     for (auto it = dialogMap_.begin(); it != dialogMap_.end(); it++) {
1582         if (dialogId == it->second->GetId()) {
1583             return it->second;
1584         }
1585     }
1586     return nullptr;
1587 }
1588 
CloseDialog(const RefPtr<FrameNode> & dialogNode)1589 void OverlayManager::CloseDialog(const RefPtr<FrameNode>& dialogNode)
1590 {
1591     TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog enter");
1592     auto dialogLayoutProp = AceType::DynamicCast<DialogLayoutProperty>(dialogNode->GetLayoutProperty());
1593     CHECK_NULL_VOID(dialogLayoutProp);
1594     if (dialogLayoutProp->GetShowInSubWindowValue(false)) {
1595         SubwindowManager::GetInstance()->DeleteHotAreas(
1596             SubwindowManager::GetInstance()->GetDialogSubWindowId(), dialogNode->GetId());
1597         SubwindowManager::GetInstance()->HideDialogSubWindow(
1598             SubwindowManager::GetInstance()->GetDialogSubWindowId());
1599     }
1600     if (dialogLayoutProp->GetShowInSubWindowValue(false) && dialogLayoutProp->GetIsModal().value_or(true)) {
1601         auto parentPipelineContext = PipelineContext::GetMainPipelineContext();
1602         CHECK_NULL_VOID(parentPipelineContext);
1603         auto parentOverlayManager = parentPipelineContext->GetOverlayManager();
1604         CHECK_NULL_VOID(parentOverlayManager);
1605         RefPtr<FrameNode> maskNode =
1606             parentOverlayManager->GetDialog(parentOverlayManager->GetMaskNodeIdWithDialogId(dialogNode->GetId()));
1607         if (maskNode) {
1608             parentOverlayManager->CloseDialog(maskNode);
1609         }
1610     }
1611     CloseDialogInner(dialogNode);
1612 }
1613 
CloseDialogInner(const RefPtr<FrameNode> & dialogNode)1614 void OverlayManager::CloseDialogInner(const RefPtr<FrameNode>& dialogNode)
1615 {
1616     RemoveDialogFromMap(dialogNode);
1617     if (dialogNode->IsRemoving()) {
1618         // already in close animation
1619         return;
1620     }
1621     dialogNode->MarkRemoving();
1622 
1623     auto container = Container::Current();
1624     auto currentId = Container::CurrentId();
1625     CHECK_NULL_VOID(container);
1626     if (container->IsSubContainer()) {
1627         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
1628         container = AceEngine::Get().GetContainer(currentId);
1629     }
1630     ContainerScope scope(currentId);
1631     auto pipelineContext = container->GetPipelineContext();
1632     CHECK_NULL_VOID(pipelineContext);
1633     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
1634     CHECK_NULL_VOID(context);
1635     auto overlayManager = context->GetOverlayManager();
1636     CHECK_NULL_VOID(overlayManager);
1637     overlayManager->ResetLowerNodeFocusable(dialogNode);
1638     CloseDialogAnimation(dialogNode);
1639     dialogCount_--;
1640     // set close button enable
1641     if (dialogCount_ == 0) {
1642         SetContainerButtonEnable(true);
1643     }
1644     dialogNode->OnAccessibilityEvent(
1645         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1646     CallOnHideDialogCallback();
1647 }
1648 
RemoveDialog(const RefPtr<FrameNode> & overlay,bool isBackPressed,bool isPageRouter)1649 bool OverlayManager::RemoveDialog(const RefPtr<FrameNode>& overlay, bool isBackPressed, bool isPageRouter)
1650 {
1651     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove dialog enter");
1652     if (overlay->IsRemoving()) {
1653         return false;
1654     }
1655     if (FireBackPressEvent()) {
1656         return true;
1657     }
1658     auto hub = overlay->GetEventHub<DialogEventHub>();
1659     if (!isPageRouter && hub) {
1660         hub->FireCancelEvent();
1661     }
1662     CloseDialog(overlay);
1663     if (isBackPressed) {
1664         SetBackPressEvent(nullptr);
1665     }
1666     return true;
1667 }
1668 
RemoveBubble(const RefPtr<FrameNode> & overlay)1669 bool OverlayManager::RemoveBubble(const RefPtr<FrameNode>& overlay)
1670 {
1671     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove bubble enter");
1672     for (const auto& popup : popupMap_) {
1673         auto targetId = popup.first;
1674         auto popupInfo = popup.second;
1675         if (overlay == popupInfo.popupNode) {
1676             popupInfo.markNeedUpdate = true;
1677             HidePopup(targetId, popupInfo);
1678             return true;
1679         }
1680     }
1681     return false;
1682 }
1683 
RemoveMenu(const RefPtr<FrameNode> & overlay)1684 bool OverlayManager::RemoveMenu(const RefPtr<FrameNode>& overlay)
1685 {
1686     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove menu enter");
1687     auto menuWrapperPattern = overlay->GetPattern<MenuWrapperPattern>();
1688     CHECK_NULL_RETURN(menuWrapperPattern, false);
1689     menuWrapperPattern->HideMenu();
1690     return true;
1691 }
1692 
RemoveOverlay(bool isBackPressed,bool isPageRouter)1693 bool OverlayManager::RemoveOverlay(bool isBackPressed, bool isPageRouter)
1694 {
1695     auto rootNode = rootNodeWeak_.Upgrade();
1696     CHECK_NULL_RETURN(rootNode, true);
1697     RemoveIndexerPopup();
1698     DestroyKeyboard();
1699     if (rootNode->GetChildren().size() > 1) {
1700         // stage node is at index 0, remove overlay at last
1701         auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
1702         CHECK_NULL_RETURN(overlay, false);
1703         // close dialog with animation
1704         auto pattern = overlay->GetPattern();
1705         if (InstanceOf<ToastPattern>(pattern)) {
1706             // still have nodes on root expect stage and toast node.
1707             if (rootNode->GetChildren().size() > 2) {
1708                 // If the current node is a toast, the last second overlay's node should be processed.
1709                 overlay = DynamicCast<FrameNode>(rootNode->GetChildAtIndex(rootNode->GetChildren().size() - 2));
1710                 CHECK_NULL_RETURN(overlay, false);
1711                 pattern = overlay->GetPattern();
1712             } else {
1713                 return false;
1714             }
1715         }
1716         if (InstanceOf<DialogPattern>(pattern)) {
1717             return RemoveDialog(overlay, isBackPressed, isPageRouter);
1718         }
1719         if (InstanceOf<BubblePattern>(pattern)) {
1720             return RemoveBubble(overlay);
1721         }
1722         if (InstanceOf<MenuWrapperPattern>(pattern)) {
1723             return RemoveMenu(overlay);
1724         }
1725         if (InstanceOf<VideoFullScreenPattern>(pattern)) {
1726             auto videoPattern = DynamicCast<VideoFullScreenPattern>(pattern);
1727             CHECK_NULL_RETURN(videoPattern, false);
1728             return videoPattern->ExitFullScreen();
1729         }
1730 
1731         // remove navDestination in navigation first
1732         do {
1733             auto pipeline = PipelineContext::GetCurrentContext();
1734             CHECK_NULL_BREAK(pipeline);
1735             auto navigationGroupNode =
1736                 AceType::DynamicCast<NavigationGroupNode>(pipeline->FindNavigationNodeToHandleBack(overlay));
1737             CHECK_NULL_BREAK(navigationGroupNode);
1738             return true;
1739         } while (0);
1740         if (!modalStack_.empty()) {
1741             if (isPageRouter) {
1742                 return RemoveAllModalInOverlay();
1743             } else {
1744                 return RemoveModalInOverlay();
1745             }
1746         }
1747         rootNode->RemoveChild(overlay);
1748         rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1749         return true;
1750     }
1751     return false;
1752 }
1753 
RemoveModalInOverlay()1754 bool OverlayManager::RemoveModalInOverlay()
1755 {
1756     auto topModalNode = modalStack_.top().Upgrade();
1757     CHECK_NULL_RETURN(topModalNode, false);
1758     if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
1759         auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
1760         CHECK_NULL_RETURN(sheetPattern, false);
1761         if (sheetPattern->hasShouldDismiss()) {
1762             sheetPattern->SheetInteractiveDismiss(false);
1763             return true;
1764         }
1765     }
1766 
1767     auto rootNode = FindWindowScene(topModalNode);
1768     CHECK_NULL_RETURN(rootNode, true);
1769 
1770     ModalPageLostFocus(topModalNode);
1771     auto pattern = topModalNode->GetPattern<PopupBasePattern>();
1772     if (isProhibitBack_ && pattern->GetTargetId() < 0) {
1773         return true;
1774     }
1775     auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1776     CHECK_NULL_RETURN(builder, false);
1777     if (!ModalExitProcess(topModalNode)) {
1778         return false;
1779     }
1780     if (!modalStack_.empty()) {
1781         modalStack_.pop();
1782     }
1783     if (!modalList_.empty()) {
1784         modalList_.pop_back();
1785     }
1786     auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
1787     if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG && sheetPattern) {
1788         sheetMap_.erase(sheetPattern->GetTargetId());
1789     }
1790     if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1791         auto modalPattern = AceType::DynamicCast<ModalPresentationPattern>(pattern);
1792         CHECK_NULL_RETURN(modalPattern, false);
1793         auto modalTransition = modalPattern->GetType();
1794         if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
1795             // Fire shown event of navdestination under the disappeared modal
1796             FireNavigationStateChange(true);
1797         }
1798     }
1799 
1800     FireModalPageHide();
1801     SaveLastModalNode();
1802     return true;
1803 }
1804 
RemoveAllModalInOverlay()1805 bool OverlayManager::RemoveAllModalInOverlay()
1806 {
1807     while (!modalStack_.empty()) {
1808         auto topModalNode = modalStack_.top().Upgrade();
1809         if (!topModalNode) {
1810             modalStack_.pop();
1811             continue;
1812         }
1813         auto rootNode = FindWindowScene(topModalNode);
1814         CHECK_NULL_RETURN(rootNode, true);
1815         auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1816         CHECK_NULL_RETURN(builder, false);
1817         ModalPageLostFocus(topModalNode);
1818         if (!ModalExitProcess(topModalNode)) {
1819             continue;
1820         }
1821         if (!modalStack_.empty()) {
1822             modalStack_.pop();
1823         }
1824         if (!modalList_.empty()) {
1825             modalList_.pop_back();
1826         }
1827 
1828         if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1829             auto modalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
1830             CHECK_NULL_RETURN(modalPattern, false);
1831             auto modalTransition = modalPattern->GetType();
1832             if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
1833                 // Fire shown event of navdestination under the disappeared modal
1834                 FireNavigationStateChange(true);
1835             }
1836         }
1837         auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
1838         if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG && sheetPattern) {
1839             sheetMap_.erase(sheetPattern->GetTargetId());
1840         }
1841         FireModalPageHide();
1842         SaveLastModalNode();
1843     }
1844     return true;
1845 }
1846 
ModalExitProcess(const RefPtr<FrameNode> & topModalNode)1847 bool OverlayManager::ModalExitProcess(const RefPtr<FrameNode>& topModalNode)
1848 {
1849     auto rootNode = FindWindowScene(topModalNode);
1850     CHECK_NULL_RETURN(rootNode, true);
1851     if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1852         return ModalPageExitProcess(topModalNode);
1853     }
1854     if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
1855         return SheetPageExitProcess(topModalNode);
1856     }
1857     return true;
1858 }
1859 
ModalPageExitProcess(const RefPtr<FrameNode> & topModalNode)1860 bool OverlayManager::ModalPageExitProcess(const RefPtr<FrameNode>& topModalNode)
1861 {
1862     auto rootNode = FindWindowScene(topModalNode);
1863     CHECK_NULL_RETURN(rootNode, true);
1864     auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1865     CHECK_NULL_RETURN(builder, false);
1866     auto modalTransition = topModalNode->GetPattern<ModalPresentationPattern>()->GetType();
1867     if (builder->GetRenderContext()->HasDisappearTransition()) {
1868         if (!topModalNode->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
1869             topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
1870             // Fire hidden event of navdestination on the disappeared modal
1871             FireNavigationStateChange(false, topModalNode);
1872         }
1873         topModalNode->Clean(false, true);
1874         topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1875     }
1876     if (modalTransition == ModalTransition::DEFAULT) {
1877         PlayDefaultModalTransition(topModalNode, false);
1878     } else if (modalTransition == ModalTransition::ALPHA) {
1879         PlayAlphaModalTransition(topModalNode, false);
1880     } else if (!builder->GetRenderContext()->HasDisappearTransition()) {
1881         topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
1882         // Fire hidden event of navdestination on the disappeared modal
1883         FireNavigationStateChange(false, topModalNode);
1884         rootNode->RemoveChild(topModalNode);
1885         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1886     }
1887     topModalNode->GetPattern<ModalPresentationPattern>()->FireCallback("false");
1888     return true;
1889 }
1890 
SheetPageExitProcess(const RefPtr<FrameNode> & topModalNode)1891 bool OverlayManager::SheetPageExitProcess(const RefPtr<FrameNode>& topModalNode)
1892 {
1893     auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetLastChild());
1894     CHECK_NULL_RETURN(builder, false);
1895     if (builder->GetRenderContext()->HasDisappearTransition()) {
1896         if (!topModalNode->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
1897             topModalNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
1898         }
1899         topModalNode->Clean(false, true);
1900         topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1901     }
1902     auto maskNode = GetSheetMask(topModalNode);
1903     if (maskNode) {
1904         PlaySheetMaskTransition(
1905             maskNode, false, topModalNode->GetPattern<SheetPresentationPattern>()->HasCallback());
1906     }
1907     auto sheetType = topModalNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
1908     if (sheetType == SheetType::SHEET_POPUP) {
1909         PlayBubbleStyleSheetTransition(topModalNode, false);
1910     } else {
1911         PlaySheetTransition(topModalNode, false);
1912     }
1913     topModalNode->GetPattern<SheetPresentationPattern>()->FireCallback("false");
1914     return true;
1915 }
1916 
RemoveOverlayInSubwindow()1917 bool OverlayManager::RemoveOverlayInSubwindow()
1918 {
1919     auto rootNode = rootNodeWeak_.Upgrade();
1920     CHECK_NULL_RETURN(rootNode, false);
1921     if (rootNode->GetChildren().empty()) {
1922         return false;
1923     }
1924 
1925     // remove the overlay node just mounted in subwindow
1926     auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
1927     CHECK_NULL_RETURN(overlay, false);
1928     // close dialog with animation
1929     auto pattern = overlay->GetPattern();
1930     if (InstanceOf<DialogPattern>(pattern)) {
1931         return RemoveDialog(overlay, false, false);
1932     }
1933     if (InstanceOf<BubblePattern>(pattern)) {
1934         auto popupPattern = DynamicCast<BubblePattern>(pattern);
1935         overlay->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1936         for (const auto& popup : popupMap_) {
1937             auto targetId = popup.first;
1938             auto popupInfo = popup.second;
1939             if (overlay == popupInfo.popupNode) {
1940                 popupMap_.erase(targetId);
1941                 rootNode->RemoveChild(overlay);
1942                 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1943                 if (rootNode->GetChildren().empty()) {
1944                     auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(popupPattern->GetContainerId());
1945                     CHECK_NULL_RETURN(subwindow, false);
1946                     subwindow->HideSubWindowNG();
1947                 }
1948                 return true;
1949             }
1950         }
1951         return false;
1952     }
1953     if (InstanceOf<MenuWrapperPattern>(pattern)) {
1954         return RemoveMenu(overlay);
1955     }
1956     rootNode->RemoveChild(overlay);
1957     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1958     if (rootNode->GetChildren().empty()) {
1959         SubwindowManager::GetInstance()->HideSubWindowNG();
1960     }
1961     return true;
1962 }
1963 
FocusOverlayNode(const RefPtr<FrameNode> & overlayNode,bool isInSubWindow)1964 void OverlayManager::FocusOverlayNode(const RefPtr<FrameNode>& overlayNode, bool isInSubWindow)
1965 {
1966     CHECK_NULL_VOID(overlayNode);
1967     auto focusHub = overlayNode->GetOrCreateFocusHub();
1968     CHECK_NULL_VOID(focusHub);
1969     focusHub->SetParentFocusable(true);
1970     focusHub->RequestFocusWithDefaultFocusFirstly();
1971 }
1972 
BlurOverlayNode(const RefPtr<FrameNode> & currentOverlay,bool isInSubWindow)1973 void OverlayManager::BlurOverlayNode(const RefPtr<FrameNode>& currentOverlay, bool isInSubWindow)
1974 {
1975     auto currentFocusHub = currentOverlay->GetOrCreateFocusHub();
1976     CHECK_NULL_VOID(currentFocusHub);
1977     currentFocusHub->SetParentFocusable(false);
1978     currentFocusHub->LostFocus();
1979 
1980     auto rootNode = rootNodeWeak_.Upgrade();
1981     CHECK_NULL_VOID(rootNode);
1982     if (rootNode->GetChildren().size() > 1) {
1983         auto collection = rootNode->GetChildren();
1984         for (auto iter = collection.rbegin(); iter != collection.rend(); ++iter) {
1985             auto overlay = DynamicCast<FrameNode>(*iter);
1986             CHECK_NULL_VOID(overlay);
1987             auto pattern = overlay->GetPattern();
1988             if (currentOverlay != overlay &&
1989                 (InstanceOf<DialogPattern>(pattern) || InstanceOf<MenuWrapperPattern>(pattern) ||
1990                     InstanceOf<SheetPresentationPattern>(pattern) || InstanceOf<ModalPresentationPattern>(pattern)) &&
1991                 overlay->GetTag() != V2::SELECT_OVERLAY_ETS_TAG &&
1992                 !overlay->IsRemoving()) {
1993                 // Focus returns to the previous in the overlay
1994                 FocusOverlayNode(overlay, isInSubWindow);
1995                 return;
1996             }
1997         }
1998     }
1999     if (isInSubWindow) {
2000         // no need to set page request focus in sub window.
2001         return;
2002     }
2003 
2004     auto pageNode = GetLastPage();
2005     CHECK_NULL_VOID(pageNode);
2006     auto pageFocusHub = pageNode->GetFocusHub();
2007     CHECK_NULL_VOID(pageFocusHub);
2008     pageFocusHub->SetParentFocusable(true);
2009     pageFocusHub->RequestFocus();
2010 }
2011 
BlurLowerNode(const RefPtr<FrameNode> & currentOverlay)2012 void OverlayManager::BlurLowerNode(const RefPtr<FrameNode>& currentOverlay)
2013 {
2014     auto root = DynamicCast<FrameNode>(currentOverlay->GetParent());
2015     CHECK_NULL_VOID(root);
2016     auto children = root->GetChildren();
2017     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2018         auto node = DynamicCast<FrameNode>(*iter);
2019         CHECK_NULL_VOID(node);
2020         if (currentOverlay == node) {
2021             continue;
2022         }
2023         if (node->GetTag() == V2::STAGE_ETS_TAG) {
2024             auto pageNode = GetLastPage();
2025             CHECK_NULL_VOID(pageNode);
2026             auto pageFocusHub = pageNode->GetFocusHub();
2027             CHECK_NULL_VOID(pageFocusHub);
2028             pageFocusHub->SetParentFocusable(false);
2029             pageFocusHub->LostFocus();
2030             return;
2031         }
2032         auto focusHub = node->GetOrCreateFocusHub();
2033         if (focusHub->IsCurrentFocus()) {
2034             focusHub->SetParentFocusable(false);
2035             focusHub->LostFocus();
2036             return;
2037         }
2038     }
2039 }
2040 
ResetLowerNodeFocusable(const RefPtr<FrameNode> & currentOverlay)2041 void OverlayManager::ResetLowerNodeFocusable(const RefPtr<FrameNode>& currentOverlay)
2042 {
2043     CHECK_NULL_VOID(currentOverlay);
2044     auto root = DynamicCast<FrameNode>(currentOverlay->GetParent());
2045     CHECK_NULL_VOID(root);
2046     auto children = root->GetChildren();
2047     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2048         auto node = DynamicCast<FrameNode>(*iter);
2049         CHECK_NULL_VOID(node);
2050         if (currentOverlay == node) {
2051             continue;
2052         }
2053         if (node->GetTag() == V2::STAGE_ETS_TAG) {
2054             auto parent = node->GetParent();
2055             if (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
2056                 return;
2057             }
2058             auto pageNode = GetLastPage();
2059             CHECK_NULL_VOID(pageNode);
2060             auto pageFocusHub = pageNode->GetFocusHub();
2061             CHECK_NULL_VOID(pageFocusHub);
2062             pageFocusHub->SetParentFocusable(true);
2063             return;
2064         }
2065         if (node->GetTag() == V2::ATOMIC_SERVICE_ETS_TAG) {
2066             auto serviceFocusHub = node->GetFocusHub();
2067             CHECK_NULL_VOID(serviceFocusHub);
2068             serviceFocusHub->SetParentFocusable(true);
2069             return;
2070         }
2071         auto focusHub = node->GetOrCreateFocusHub();
2072         if (focusHub->IsCurrentFocus()) {
2073             focusHub->SetParentFocusable(true);
2074             return;
2075         }
2076     }
2077 }
2078 
SaveLastModalNode()2079 void OverlayManager::SaveLastModalNode()
2080 {
2081     auto pipeline = PipelineContext::GetCurrentContext();
2082     CHECK_NULL_VOID(pipeline);
2083     auto stageManager = pipeline->GetStageManager();
2084     CHECK_NULL_VOID(stageManager);
2085     auto pageNode = stageManager->GetLastPage();
2086     CHECK_NULL_VOID(pageNode);
2087     if (modalStack_.empty()) {
2088         lastModalNode_ = WeakClaim(RawPtr(pageNode));
2089     } else {
2090         auto topModalNode = modalStack_.top().Upgrade();
2091         modalStack_.pop();
2092         if (modalStack_.empty()) {
2093             lastModalNode_ = WeakClaim(RawPtr(pageNode));
2094         } else {
2095             lastModalNode_ = modalStack_.top();
2096         }
2097         modalStack_.push(topModalNode);
2098     }
2099 }
2100 
FireNavigationStateChange(bool show,const RefPtr<UINode> & node)2101 void OverlayManager::FireNavigationStateChange(bool show, const RefPtr<UINode>& node)
2102 {
2103     if (!show && node) {
2104         // Only check node When it is appointed
2105         NavigationPattern::FireNavigationStateChange(node, show);
2106         return;
2107     }
2108 
2109     // Fire show event with non-empty stack. Only Check top modal node.
2110     RefPtr<FrameNode> topModalNode;
2111     if (!modalStack_.empty()) {
2112         topModalNode = GetModalNodeInStack(modalStack_);
2113     }
2114     if (show && topModalNode) {
2115         // Modal always displays on top of stage. If it existed, only need to check the top of modal stack.
2116         NavigationPattern::FireNavigationStateChange(topModalNode, show);
2117         return;
2118     }
2119 
2120     auto lastPage = GetLastPage();
2121     NavigationPattern::FireNavigationStateChange(lastPage, show);
2122 }
2123 
GetModalNodeInStack(std::stack<WeakPtr<FrameNode>> & stack)2124 RefPtr<FrameNode> OverlayManager::GetModalNodeInStack(std::stack<WeakPtr<FrameNode>>& stack)
2125 {
2126     if (stack.empty()) {
2127         return nullptr;
2128     }
2129     auto topModalNode = stack.top().Upgrade();
2130     if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
2131         return topModalNode;
2132     } else {
2133         stack.pop();
2134         auto modalNode = GetModalNodeInStack(stack);
2135         stack.push(topModalNode);
2136         return modalNode;
2137     }
2138 }
2139 
BindContentCover(bool isShow,std::function<void (const std::string &)> && callback,std::function<RefPtr<UINode> ()> && buildNodeFunc,NG::ModalStyle & modalStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,const RefPtr<FrameNode> & targetNode,int32_t sessionId)2140 void OverlayManager::BindContentCover(bool isShow, std::function<void(const std::string&)>&& callback,
2141     std::function<RefPtr<UINode>()>&& buildNodeFunc, NG::ModalStyle& modalStyle, std::function<void()>&& onAppear,
2142     std::function<void()>&& onDisappear, const RefPtr<FrameNode>& targetNode, int32_t sessionId)
2143 {
2144     int32_t targetId = targetNode ? targetNode->GetId() : sessionId;
2145     auto rootNode = FindWindowScene(targetNode);
2146     CHECK_NULL_VOID(rootNode);
2147     auto modalTransition = modalStyle.modalTransition;
2148     if (!modalTransition.has_value()) {
2149         modalTransition = ModalTransition::DEFAULT;
2150     }
2151     if (isShow) {
2152         if (!modalStack_.empty()) {
2153             auto topModalNode = modalStack_.top().Upgrade();
2154             CHECK_NULL_VOID(topModalNode);
2155             if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
2156                 if (topModalNode->GetPattern<ModalPresentationPattern>()->GetTargetId() == targetId) {
2157                     if (modalStyle.backgroundColor.has_value()) {
2158                         topModalNode->GetRenderContext()->UpdateBackgroundColor(modalStyle.backgroundColor.value());
2159                     }
2160                     topModalNode->GetPattern<ModalPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
2161                     topModalNode->GetPattern<ModalPresentationPattern>()->SetType(modalTransition.value());
2162                     return;
2163                 }
2164             }
2165         }
2166         // builder content
2167         auto builder = AceType::DynamicCast<FrameNode>(buildNodeFunc());
2168         CHECK_NULL_VOID(builder);
2169         builder->GetRenderContext()->SetIsModalRootNode(true);
2170 
2171         // create modal page
2172         auto modalNode = FrameNode::CreateFrameNode(V2::MODAL_PAGE_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
2173             AceType::MakeRefPtr<ModalPresentationPattern>(
2174                 targetId, static_cast<ModalTransition>(modalTransition.value()), std::move(callback)));
2175         if (modalStyle.backgroundColor.has_value()) {
2176             modalNode->GetRenderContext()->UpdateBackgroundColor(modalStyle.backgroundColor.value());
2177         }
2178         auto modalPagePattern = modalNode->GetPattern<ModalPresentationPattern>();
2179         CHECK_NULL_VOID(modalPagePattern);
2180         modalPagePattern->UpdateOnDisappear(std::move(onDisappear));
2181         modalPagePattern->UpdateUIExtensionMode(modalStyle.isUIExtension);
2182         modalStack_.push(WeakClaim(RawPtr(modalNode)));
2183         modalList_.emplace_back(WeakClaim(RawPtr(modalNode)));
2184         SaveLastModalNode();
2185         modalNode->MountToParent(rootNode);
2186         modalNode->AddChild(builder);
2187         FireModalPageShow();
2188         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2189         if (onAppear != nullptr) {
2190             onAppear();
2191         }
2192         // Fire hidden event of navdestination under the appeared modal
2193         FireNavigationStateChange(false);
2194         if (modalTransition == ModalTransition::DEFAULT) {
2195             PlayDefaultModalTransition(modalNode, true);
2196         } else if (modalTransition == ModalTransition::ALPHA) {
2197             PlayAlphaModalTransition(modalNode, true);
2198         }
2199         return;
2200     }
2201 
2202     // isShow = false, Pop ModalPage
2203     if (!modalStack_.empty()) {
2204         auto topModalNode = modalStack_.top().Upgrade();
2205         CHECK_NULL_VOID(topModalNode);
2206         if (topModalNode->GetTag() != V2::SHEET_PAGE_TAG && topModalNode->GetTag() != V2::MODAL_PAGE_TAG) {
2207             return;
2208         }
2209         if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG ||
2210             topModalNode->GetPattern<ModalPresentationPattern>()->GetTargetId() != targetId) {
2211             DeleteModal(targetId);
2212             return;
2213         }
2214         auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
2215         CHECK_NULL_VOID(builder);
2216         if (builder->GetRenderContext()->HasDisappearTransition()) {
2217             if (!topModalNode->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
2218                 topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
2219                 // Fire hidden event of navdestination on the disappeared modal
2220                 FireNavigationStateChange(false, topModalNode);
2221             }
2222             topModalNode->Clean(false, true);
2223             topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2224         }
2225         auto modalPresentationPattern = topModalNode->GetPattern<ModalPresentationPattern>();
2226         CHECK_NULL_VOID(modalPresentationPattern);
2227         modalTransition = modalPresentationPattern->GetType();
2228         // lost focus
2229         ModalPageLostFocus(topModalNode);
2230         if (modalTransition == ModalTransition::DEFAULT) {
2231             PlayDefaultModalTransition(topModalNode, false);
2232         } else if (modalTransition == ModalTransition::ALPHA) {
2233             PlayAlphaModalTransition(topModalNode, false);
2234         } else if (!builder->GetRenderContext()->HasDisappearTransition()) {
2235             if (!modalPresentationPattern->IsExecuteOnDisappear()) {
2236                 modalPresentationPattern->OnDisappear();
2237                 // Fire hidden event of navdestination on the disappeared modal
2238                 FireNavigationStateChange(false, topModalNode);
2239             }
2240             rootNode->RemoveChild(topModalNode);
2241             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2242         }
2243         modalStack_.pop();
2244         if (!modalList_.empty()) {
2245             modalList_.pop_back();
2246         }
2247         if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
2248             // Fire shown event of navdestination under the disappeared modal
2249             FireNavigationStateChange(true);
2250         }
2251         FireModalPageHide();
2252         SaveLastModalNode();
2253     }
2254 }
2255 
FireModalPageShow()2256 void OverlayManager::FireModalPageShow()
2257 {
2258     auto pipeline = PipelineContext::GetCurrentContext();
2259     CHECK_NULL_VOID(pipeline);
2260     auto pageNode = pipeline->GetStageManager()->GetLastPage();
2261     CHECK_NULL_VOID(pageNode);
2262     auto pageFocusHub = pageNode->GetFocusHub();
2263     CHECK_NULL_VOID(pageFocusHub);
2264     pageFocusHub->SetParentFocusable(false);
2265     pageFocusHub->LostFocus();
2266     for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
2267         auto modalNode = (*modal).Upgrade();
2268         CHECK_NULL_VOID(modalNode);
2269         auto modalFocusHub = modalNode->GetFocusHub();
2270         CHECK_NULL_VOID(modalFocusHub);
2271         modalFocusHub->SetParentFocusable(false);
2272         modalFocusHub->LostFocus();
2273     }
2274     if (modalList_.empty()) {
2275         return;
2276     }
2277     auto topModalNode = modalList_.back().Upgrade();
2278     CHECK_NULL_VOID(topModalNode);
2279     auto topModalFocusHub = topModalNode->GetFocusHub();
2280     CHECK_NULL_VOID(topModalFocusHub);
2281     topModalFocusHub->SetParentFocusable(true);
2282     topModalFocusHub->RequestFocusWithDefaultFocusFirstly();
2283 }
2284 
ModalPageLostFocus(const RefPtr<FrameNode> & node)2285 void OverlayManager::ModalPageLostFocus(const RefPtr<FrameNode>& node)
2286 {
2287     auto modalFocusHub = node->GetFocusHub();
2288     CHECK_NULL_VOID(modalFocusHub);
2289     modalFocusHub->SetParentFocusable(false);
2290     modalFocusHub->LostFocus();
2291 }
2292 
FireModalPageHide()2293 void OverlayManager::FireModalPageHide()
2294 {
2295     auto lastModalNode = lastModalNode_.Upgrade();
2296     CHECK_NULL_VOID(lastModalNode);
2297     auto lastModalFocusHub = lastModalNode->GetFocusHub();
2298     CHECK_NULL_VOID(lastModalFocusHub);
2299     lastModalFocusHub->SetParentFocusable(true);
2300     lastModalFocusHub->RequestFocus();
2301 }
2302 
PlayDefaultModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)2303 void OverlayManager::PlayDefaultModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
2304 {
2305     // current modal animation
2306     AnimationOption option;
2307     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 100.0f, 20.0f);
2308     option.SetCurve(curve);
2309     option.SetFillMode(FillMode::FORWARDS);
2310     auto context = modalNode->GetRenderContext();
2311     CHECK_NULL_VOID(context);
2312 
2313     auto rootHeight = GetRootHeight();
2314     auto modalPositionY = modalNode->GetGeometryNode()->GetFrameRect().GetY();
2315     auto showHeight = rootHeight - modalPositionY;
2316 
2317     if (isTransitionIn) {
2318         context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
2319         AnimationUtils::Animate(option, [context]() {
2320             if (context) {
2321                 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
2322             }
2323         });
2324     } else {
2325         auto lastModalNode = lastModalNode_.Upgrade();
2326         CHECK_NULL_VOID(lastModalNode);
2327         auto lastModalContext = lastModalNode->GetRenderContext();
2328         CHECK_NULL_VOID(lastModalContext);
2329         lastModalContext->UpdateOpacity(1.0);
2330         option.SetOnFinishEvent(
2331             [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
2332                 auto modal = modalWK.Upgrade();
2333                 auto overlayManager = overlayWeak.Upgrade();
2334                 CHECK_NULL_VOID(modal && overlayManager);
2335                 auto root = overlayManager->FindWindowScene(modal);
2336                 CHECK_NULL_VOID(root);
2337                 if (!modal->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
2338                     modal->GetPattern<ModalPresentationPattern>()->OnDisappear();
2339                     // Fire hidden event of navdestination on the disappeared modal
2340                     overlayManager->FireNavigationStateChange(false, modal);
2341                 }
2342                 root->RemoveChild(modal);
2343                 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2344                 // Fire shown event of navdestination under the disappeared modal
2345                 overlayManager->FireNavigationStateChange(true);
2346             });
2347         context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
2348         AnimationUtils::Animate(
2349             option,
2350             [context, showHeight]() {
2351                 if (context) {
2352                     context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
2353                 }
2354             },
2355             option.GetOnFinishEvent());
2356     }
2357 }
2358 
PlayAlphaModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)2359 void OverlayManager::PlayAlphaModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
2360 {
2361     AnimationOption option;
2362     option.SetCurve(Curves::FRICTION);
2363     option.SetDuration(FULL_MODAL_ALPHA_ANIMATION_DURATION);
2364     option.SetFillMode(FillMode::FORWARDS);
2365     auto lastModalNode = lastModalNode_.Upgrade();
2366     CHECK_NULL_VOID(lastModalNode);
2367     auto lastModalContext = lastModalNode->GetRenderContext();
2368     CHECK_NULL_VOID(lastModalContext);
2369     auto context = modalNode->GetRenderContext();
2370     CHECK_NULL_VOID(context);
2371     if (isTransitionIn) {
2372         // last page animation
2373         lastModalContext->OpacityAnimation(option, 1, 0);
2374         lastModalContext->UpdateOpacity(0);
2375 
2376         // current modal page animation
2377         context->OpacityAnimation(option, 0, 1);
2378     } else {
2379         // last page animation
2380         lastModalContext->OpacityAnimation(option, 0, 1);
2381 
2382         // current modal page animation
2383         option.SetOnFinishEvent(
2384             [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
2385                 auto modal = modalWK.Upgrade();
2386                 auto overlayManager = overlayWeak.Upgrade();
2387                 CHECK_NULL_VOID(modal && overlayManager);
2388                 auto root = overlayManager->FindWindowScene(modal);
2389                 CHECK_NULL_VOID(root);
2390                 if (!modal->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
2391                     modal->GetPattern<ModalPresentationPattern>()->OnDisappear();
2392                     // Fire hidden event of navdestination on the disappeared modal
2393                     overlayManager->FireNavigationStateChange(false, modal);
2394                 }
2395                 root->RemoveChild(modal);
2396                 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2397                 // Fire shown event of navdestination under the disappeared modal
2398                 overlayManager->FireNavigationStateChange(true);
2399             });
2400         context->OpacityAnimation(option, 1, 0);
2401     }
2402 }
2403 
BindSheet(bool isShow,std::function<void (const std::string &)> && callback,std::function<RefPtr<UINode> ()> && buildNodeFunc,std::function<RefPtr<UINode> ()> && buildtitleNodeFunc,NG::SheetStyle & sheetStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && shouldDismiss,const RefPtr<FrameNode> & targetNode)2404 void OverlayManager::BindSheet(bool isShow, std::function<void(const std::string&)>&& callback,
2405     std::function<RefPtr<UINode>()>&& buildNodeFunc, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
2406     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
2407     std::function<void()>&& shouldDismiss, const RefPtr<FrameNode>& targetNode)
2408 {
2409     auto pipeline = PipelineContext::GetCurrentContext();
2410     CHECK_NULL_VOID(pipeline);
2411     auto bindSheetTask = [weak = AceType::WeakClaim(this), isShow, callback = std::move(callback),
2412                              buildNodeFunc = std::move(buildNodeFunc),
2413                              buildtitleNodeFunc = std::move(buildtitleNodeFunc), sheetStyle,
2414                              onAppear = std::move(onAppear), onDisappear = std::move(onDisappear),
2415                              shouldDismiss = std::move(shouldDismiss), targetNode]() mutable {
2416         auto overlay = weak.Upgrade();
2417         CHECK_NULL_VOID(overlay);
2418         overlay->OnBindSheet(isShow, std::move(callback), std::move(buildNodeFunc), std::move(buildtitleNodeFunc),
2419             sheetStyle, std::move(onAppear), std::move(onDisappear), std::move(shouldDismiss), targetNode);
2420         auto pipeline = PipelineContext::GetCurrentContext();
2421         CHECK_NULL_VOID(pipeline);
2422         pipeline->FlushUITasks();
2423     };
2424     pipeline->AddAnimationClosure(bindSheetTask);
2425 }
2426 
OnBindSheet(bool isShow,std::function<void (const std::string &)> && callback,std::function<RefPtr<UINode> ()> && buildNodeFunc,std::function<RefPtr<UINode> ()> && buildtitleNodeFunc,NG::SheetStyle & sheetStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && shouldDismiss,const RefPtr<FrameNode> & targetNode)2427 void OverlayManager::OnBindSheet(bool isShow, std::function<void(const std::string&)>&& callback,
2428     std::function<RefPtr<UINode>()>&& buildNodeFunc, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
2429     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
2430     std::function<void()>&& shouldDismiss, const RefPtr<FrameNode>& targetNode)
2431 {
2432     int32_t targetId = targetNode->GetId();
2433     auto rootNode = FindWindowScene(targetNode);
2434     CHECK_NULL_VOID(rootNode);
2435     auto pipeline = PipelineContext::GetCurrentContext();
2436     CHECK_NULL_VOID(pipeline);
2437     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
2438     CHECK_NULL_VOID(sheetTheme);
2439     if (!isShow) {
2440         CloseSheet(targetId);
2441         return;
2442     }
2443     if (sheetMap_.count(targetId)) {
2444         auto topModalNode = sheetMap_[targetId].Upgrade();
2445         CHECK_NULL_VOID(topModalNode);
2446         if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG &&
2447             topModalNode->GetPattern<SheetPresentationPattern>()->GetTargetId() == targetId) {
2448             if (sheetStyle.backgroundColor.has_value()) {
2449                 topModalNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value());
2450             }
2451             if (sheetStyle.backgroundBlurStyle.has_value()) {
2452                 SetSheetBackgroundBlurStyle(topModalNode, sheetStyle.backgroundBlurStyle.value());
2453             }
2454             auto maskNode = GetSheetMask(topModalNode);
2455             if (maskNode) {
2456                 auto maskRenderContext = maskNode->GetRenderContext();
2457                 CHECK_NULL_VOID(maskRenderContext);
2458                 maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor()));
2459             }
2460             topModalNode->GetPattern<SheetPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
2461             topModalNode->GetPattern<SheetPresentationPattern>()->UpdateShouldDismiss(std::move(shouldDismiss));
2462             auto layoutProperty = topModalNode->GetLayoutProperty<SheetPresentationProperty>();
2463             layoutProperty->UpdateSheetStyle(sheetStyle);
2464             topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2465             pipeline->FlushUITasks();
2466             ComputeSheetOffset(sheetStyle, topModalNode);
2467             auto sheetType = topModalNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
2468             if (sheetType != SheetType::SHEET_POPUP) {
2469                 PlaySheetTransition(topModalNode, true, false, false);
2470             }
2471             return;
2472         }
2473     }
2474     // builder content
2475     auto builder = AceType::DynamicCast<FrameNode>(buildNodeFunc());
2476     CHECK_NULL_VOID(builder);
2477     builder->GetRenderContext()->SetIsModalRootNode(true);
2478 
2479     auto titlebuilder = AceType::DynamicCast<FrameNode>(buildtitleNodeFunc());
2480     if (titlebuilder) {
2481         titlebuilder->GetRenderContext()->SetIsModalRootNode(true);
2482     }
2483     // create modal page
2484     auto sheetNode = SheetView::CreateSheetPage(
2485         targetId, targetNode->GetTag(), builder, titlebuilder, std::move(callback), sheetStyle);
2486     CHECK_NULL_VOID(sheetNode);
2487     if (sheetStyle.backgroundColor.has_value()) {
2488         sheetNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value());
2489     }
2490     if (sheetStyle.backgroundBlurStyle.has_value()) {
2491         SetSheetBackgroundBlurStyle(sheetNode, sheetStyle.backgroundBlurStyle.value());
2492     }
2493     sheetNode->GetPattern<SheetPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
2494     sheetNode->GetPattern<SheetPresentationPattern>()->UpdateShouldDismiss(std::move(shouldDismiss));
2495     sheetMap_[targetId] = WeakClaim(RawPtr(sheetNode));
2496     modalStack_.push(WeakClaim(RawPtr(sheetNode)));
2497     SaveLastModalNode();
2498     // create maskColor node
2499     auto sheetType = sheetNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
2500     auto maskNode = FrameNode::CreateFrameNode(
2501         V2::SHEET_MASK_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>());
2502     CHECK_NULL_VOID(maskNode);
2503     auto maskLayoutProps = maskNode->GetLayoutProperty();
2504     CHECK_NULL_VOID(maskLayoutProps);
2505     maskLayoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT);
2506     auto maskRenderContext = maskNode->GetRenderContext();
2507     CHECK_NULL_VOID(maskRenderContext);
2508     if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2509         if (sheetStyle.maskColor.has_value()) {
2510             maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value());
2511         } else {
2512             maskLayoutProps->UpdateVisibility(VisibleType::INVISIBLE);
2513         }
2514     } else {
2515         maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor()));
2516         auto eventConfirmHub = maskNode->GetOrCreateGestureEventHub();
2517         CHECK_NULL_VOID(eventConfirmHub);
2518         sheetMaskClickEvent_ = AceType::MakeRefPtr<NG::ClickEvent>(
2519             [weak = AceType::WeakClaim(AceType::RawPtr(sheetNode))](const GestureEvent& /* info */) {
2520                 auto sheet = weak.Upgrade();
2521                 CHECK_NULL_VOID(sheet);
2522                 auto sheetPattern = sheet->GetPattern<SheetPresentationPattern>();
2523                 CHECK_NULL_VOID(sheetPattern);
2524                 sheetPattern->SheetInteractiveDismiss(false);
2525             });
2526         eventConfirmHub->AddClickEvent(sheetMaskClickEvent_);
2527     }
2528     maskNode->MountToParent(rootNode);
2529     PlaySheetMaskTransition(maskNode, true, static_cast<bool>(callback));
2530     auto columnNode = FrameNode::CreateFrameNode(V2::SHEET_WRAPPER_TAG,
2531         ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
2532     CHECK_NULL_VOID(columnNode);
2533     auto columnLayoutProps = columnNode->GetLayoutProperty();
2534     CHECK_NULL_VOID(columnLayoutProps);
2535     columnLayoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT);
2536     columnLayoutProps->UpdateAlignment(Alignment::TOP_LEFT);
2537     sheetNode->MountToParent(columnNode);
2538     columnNode->MountToParent(rootNode);
2539     modalList_.emplace_back(WeakClaim(RawPtr(sheetNode)));
2540     FireModalPageShow();
2541     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2542     pipeline->FlushUITasks();
2543     ComputeSheetOffset(sheetStyle, sheetNode);
2544     if (onAppear != nullptr) {
2545         onAppear();
2546     }
2547 
2548     // start transition animation
2549     if (sheetType == SheetType::SHEET_POPUP) {
2550         PlayBubbleStyleSheetTransition(sheetNode, true);
2551     } else {
2552         PlaySheetTransition(sheetNode, true);
2553     }
2554 }
2555 
CloseSheet(int32_t targetId)2556 void OverlayManager::CloseSheet(int32_t targetId)
2557 {
2558     if (modalStack_.empty()) {
2559         return;
2560     }
2561     if (sheetMap_.empty() || !sheetMap_.count(targetId)) {
2562         DeleteModal(targetId);
2563         return;
2564     }
2565     auto sheetNode = sheetMap_[targetId].Upgrade();
2566     CHECK_NULL_VOID(sheetNode);
2567     sheetNode->GetPattern<SheetPresentationPattern>()->SetShowState(false);
2568     auto scrollNode = AceType::DynamicCast<FrameNode>(sheetNode->GetChildAtIndex(1));
2569     CHECK_NULL_VOID(scrollNode);
2570     auto builder = AceType::DynamicCast<FrameNode>(scrollNode->GetChildAtIndex(0));
2571     CHECK_NULL_VOID(builder);
2572     if (builder->GetRenderContext()->HasDisappearTransition()) {
2573         if (!sheetNode->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
2574             sheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2575         }
2576         sheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2577         sheetNode->Clean(false, true);
2578         sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2579     }
2580     ModalPageLostFocus(sheetNode);
2581     auto maskNode = GetSheetMask(sheetNode);
2582     if (maskNode) {
2583         PlaySheetMaskTransition(maskNode, false, sheetNode->GetPattern<SheetPresentationPattern>()->HasCallback());
2584     }
2585     auto sheetType = sheetNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
2586     if (sheetType == SheetType::SHEET_POPUP) {
2587         PlayBubbleStyleSheetTransition(sheetNode, false);
2588     } else {
2589         PlaySheetTransition(sheetNode, false);
2590     }
2591     sheetMap_.erase(targetId);
2592     RemoveSheetNode(sheetNode);
2593     FireModalPageHide();
2594     SaveLastModalNode();
2595 }
2596 
DismissSheet()2597 void OverlayManager::DismissSheet()
2598 {
2599     if (modalStack_.empty()) {
2600         return;
2601     }
2602     if (sheetMap_.empty() || !sheetMap_.count(dismissTargetId_)) {
2603         DeleteModal(dismissTargetId_);
2604         return;
2605     }
2606     auto sheetNode = sheetMap_[dismissTargetId_].Upgrade();
2607     CHECK_NULL_VOID(sheetNode);
2608     if (sheetNode->GetTag() == V2::SHEET_PAGE_TAG) {
2609         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2610         CHECK_NULL_VOID(sheetPattern);
2611         sheetPattern->DismissSheet();
2612     }
2613 }
2614 
RemoveSheetNode(const RefPtr<FrameNode> & sheetNode)2615 void OverlayManager::RemoveSheetNode(const RefPtr<FrameNode>& sheetNode)
2616 {
2617     CHECK_NULL_VOID(sheetNode);
2618     if (!modalList_.empty()) {
2619         modalList_.remove(WeakClaim(RawPtr(sheetNode)));
2620     }
2621     std::vector<WeakPtr<FrameNode>> sheetVector;
2622     while (!modalStack_.empty()) {
2623         if (modalStack_.top() != WeakClaim(RawPtr(sheetNode))) {
2624             sheetVector.push_back(modalStack_.top());
2625         }
2626         modalStack_.pop();
2627     }
2628     for (auto iter : sheetVector) {
2629         modalStack_.push(iter);
2630     }
2631 }
2632 
PlaySheetTransition(RefPtr<FrameNode> sheetNode,bool isTransitionIn,bool isFirstTransition,bool isModeChangeToAuto)2633 void OverlayManager::PlaySheetTransition(
2634     RefPtr<FrameNode> sheetNode, bool isTransitionIn, bool isFirstTransition, bool isModeChangeToAuto)
2635 {
2636     // current sheet animation
2637     AnimationOption option;
2638     const RefPtr<InterpolatingSpring> curve =
2639         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
2640     option.SetCurve(curve);
2641     option.SetFillMode(FillMode::FORWARDS);
2642     auto context = sheetNode->GetRenderContext();
2643     CHECK_NULL_VOID(context);
2644     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2645     CHECK_NULL_VOID(sheetPattern);
2646     auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2647     auto sheetParent = DynamicCast<FrameNode>(sheetNode->GetParent());
2648     CHECK_NULL_VOID(sheetParent);
2649     if (isTransitionIn) {
2650         sheetPattern->SetCurrentHeight(sheetHeight_);
2651         float offset = 0.0f;
2652         if (sheetPattern->GetSheetType() == SheetType::SHEET_POPUP) {
2653             offset = sheetPattern->GetSheetOffset();
2654         } else {
2655             offset = sheetMaxHeight - sheetHeight_;
2656         }
2657         if (isFirstTransition) {
2658             context->OnTransformTranslateUpdate({ 0.0f, sheetMaxHeight, 0.0f });
2659             if (NearZero(sheetHeight_)) {
2660                 return;
2661             }
2662         }
2663         if (isModeChangeToAuto) {
2664             option.SetDuration(0);
2665             option.SetCurve(Curves::LINEAR);
2666         }
2667         sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMDEFAULT);
2668         AnimationUtils::Animate(
2669             option,
2670             [context, offset]() {
2671                 if (context) {
2672                     context->OnTransformTranslateUpdate({ 0.0f, offset, 0.0f });
2673                 }
2674             });
2675     } else {
2676         option.SetOnFinishEvent(
2677             [rootWeak = rootNodeWeak_, sheetWK = WeakClaim(RawPtr(sheetNode)),
2678                     weakOverlayManager = WeakClaim(this)] {
2679                 auto sheet = sheetWK.Upgrade();
2680                 auto overlayManager = weakOverlayManager.Upgrade();
2681                 CHECK_NULL_VOID(sheet && overlayManager);
2682                 if (!sheet->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
2683                     sheet->GetPattern<SheetPresentationPattern>()->OnDisappear();
2684                 }
2685                 auto root = overlayManager->FindWindowScene(sheet);
2686                 CHECK_NULL_VOID(root);
2687                 auto sheetParent = DynamicCast<FrameNode>(sheet->GetParent());
2688                 CHECK_NULL_VOID(sheetParent);
2689                 root->RemoveChild(sheetParent);
2690                 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2691             });
2692         if (sheetPattern->HasCallback()) {
2693             sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
2694                 HitTestMode::HTMTRANSPARENT);
2695         }
2696         AnimationUtils::Animate(
2697             option,
2698             [context, sheetMaxHeight]() {
2699                 if (context) {
2700                     context->OnTransformTranslateUpdate({ 0.0f, sheetMaxHeight, 0.0f });
2701                 }
2702             },
2703             option.GetOnFinishEvent());
2704     }
2705 }
2706 
PlayBubbleStyleSheetTransition(RefPtr<FrameNode> sheetNode,bool isTransitionIn)2707 void OverlayManager::PlayBubbleStyleSheetTransition(RefPtr<FrameNode> sheetNode, bool isTransitionIn)
2708 {
2709     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2710     CHECK_NULL_VOID(sheetPattern);
2711     if (isTransitionIn) {
2712         sheetPattern->ResetToInvisible();
2713         sheetPattern->SetCurrentHeight(sheetHeight_);
2714         sheetPattern->StartOffsetEnteringAnimation();
2715         sheetPattern->StartAlphaEnteringAnimation([sheetWK = WeakClaim(RawPtr(sheetNode))] {
2716             auto sheet = sheetWK.Upgrade();
2717             CHECK_NULL_VOID(sheet);
2718             auto sheetPattern = sheet->GetPattern<SheetPresentationPattern>();
2719             CHECK_NULL_VOID(sheetPattern);
2720             sheetPattern->ProcessColumnRect();
2721         });
2722     } else {
2723         sheetPattern->StartOffsetExitingAnimation();
2724         sheetPattern->StartAlphaExitingAnimation(
2725             [rootWeak = rootNodeWeak_, sheetWK = WeakClaim(RawPtr(sheetNode)), id = Container::CurrentId(),
2726                     weakOverlayManager = WeakClaim(this)] {
2727                 ContainerScope scope(id);
2728                 auto context = PipelineContext::GetCurrentContext();
2729                 CHECK_NULL_VOID(context);
2730                 auto taskExecutor = context->GetTaskExecutor();
2731                 CHECK_NULL_VOID(taskExecutor);
2732                 // animation finish event should be posted to UI thread.
2733                 taskExecutor->PostTask(
2734                     [rootWeak, sheetWK, id, weakOverlayManager]() {
2735                         auto sheet = sheetWK.Upgrade();
2736                         auto overlayManager = weakOverlayManager.Upgrade();
2737                         CHECK_NULL_VOID(sheet && overlayManager);
2738 
2739                         ContainerScope scope(id);
2740                         if (!sheet->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
2741                             sheet->GetPattern<SheetPresentationPattern>()->OnDisappear();
2742                         }
2743                         auto root = overlayManager->FindWindowScene(sheet);
2744                         CHECK_NULL_VOID(root);
2745                         auto sheetParent = DynamicCast<FrameNode>(sheet->GetParent());
2746                         CHECK_NULL_VOID(sheetParent);
2747                         root->RemoveChild(sheetParent);
2748                         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2749                     },
2750                     TaskExecutor::TaskType::UI);
2751             });
2752     }
2753 }
2754 
PlaySheetMaskTransition(RefPtr<FrameNode> maskNode,bool isTransitionIn,bool needTransparent)2755 void OverlayManager::PlaySheetMaskTransition(RefPtr<FrameNode> maskNode, bool isTransitionIn, bool needTransparent)
2756 {
2757     AnimationOption option;
2758     const RefPtr<InterpolatingSpring> curve =
2759         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
2760     option.SetCurve(curve);
2761     option.SetFillMode(FillMode::FORWARDS);
2762     auto context = maskNode->GetRenderContext();
2763     CHECK_NULL_VOID(context);
2764     if (isTransitionIn) {
2765         maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMDEFAULT);
2766         context->OpacityAnimation(option, 0.0, 1.0);
2767     } else {
2768         if (sheetMaskClickEvent_) {
2769             auto eventConfirmHub = maskNode->GetOrCreateGestureEventHub();
2770             CHECK_NULL_VOID(eventConfirmHub);
2771             eventConfirmHub->RemoveClickEvent(sheetMaskClickEvent_);
2772         }
2773         option.SetOnFinishEvent(
2774             [rootWeak = rootNodeWeak_, maskNodeWK = WeakClaim(RawPtr(maskNode)),
2775                     weakOverlayManager = WeakClaim(this)] {
2776                 auto mask = maskNodeWK.Upgrade();
2777                 auto overlayManager = weakOverlayManager.Upgrade();
2778                 CHECK_NULL_VOID(mask && overlayManager);
2779 
2780                 auto root = overlayManager->FindWindowScene(mask);
2781                 CHECK_NULL_VOID(root);
2782                 root->RemoveChild(mask);
2783             });
2784         if (needTransparent) {
2785             maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
2786                 HitTestMode::HTMTRANSPARENT);
2787         }
2788         context->OpacityAnimation(option, 1.0, 0.0);
2789     }
2790 }
2791 
SetSheetBackgroundBlurStyle(const RefPtr<FrameNode> & sheetNode,const BlurStyleOption & bgBlurStyle)2792 void OverlayManager::SetSheetBackgroundBlurStyle(const RefPtr<FrameNode>& sheetNode, const BlurStyleOption& bgBlurStyle)
2793 {
2794     auto renderContext = sheetNode->GetRenderContext();
2795     CHECK_NULL_VOID(renderContext);
2796 
2797     if (renderContext->GetBackgroundEffect().has_value()) {
2798         renderContext->UpdateBackgroundEffect(std::nullopt);
2799     }
2800     renderContext->UpdateBackBlurStyle(bgBlurStyle);
2801     if (renderContext->GetBackBlurRadius().has_value()) {
2802         renderContext->UpdateBackBlurRadius(Dimension());
2803     }
2804 }
2805 
ComputeSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)2806 void OverlayManager::ComputeSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
2807 {
2808     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2809     CHECK_NULL_VOID(sheetPattern);
2810     auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2811     auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
2812     auto geometryNode = sheetNode->GetGeometryNode();
2813     CHECK_NULL_VOID(geometryNode);
2814     auto sheetHeight = geometryNode->GetFrameSize().Height();
2815 
2816     auto sheetType = sheetPattern->GetSheetType();
2817     switch (sheetType) {
2818         case SheetType::SHEET_BOTTOM:
2819         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
2820             if (sheetStyle.detents.size() > 0) {
2821                 ComputeDetentsSheetOffset(sheetStyle, sheetNode);
2822             } else {
2823                 ComputeSingleGearSheetOffset(sheetStyle, sheetNode);
2824             }
2825             break;
2826         case SheetType::SHEET_BOTTOMLANDSPACE:
2827             sheetHeight_ = largeHeight;
2828             break;
2829         case SheetType::SHEET_CENTER:
2830             sheetHeight_ = (sheetHeight + sheetMaxHeight) / SHEET_HALF_SIZE;
2831             break;
2832         case SheetType::SHEET_POPUP:
2833             sheetHeight_ = sheetMaxHeight;
2834             break;
2835         default:
2836             break;
2837     }
2838 }
2839 
ComputeSingleGearSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)2840 void OverlayManager::ComputeSingleGearSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
2841 {
2842     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2843     CHECK_NULL_VOID(sheetPattern);
2844     auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2845     auto context = PipelineContext::GetCurrentContext();
2846     CHECK_NULL_VOID(context);
2847     auto manager = context->GetSafeAreaManager();
2848     CHECK_NULL_VOID(manager);
2849     auto statusBarHeight = manager->GetSystemSafeArea().top_.Length();
2850     auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - statusBarHeight;
2851     if (sheetStyle.sheetMode.has_value()) {
2852         if (sheetStyle.sheetMode == SheetMode::MEDIUM) {
2853             sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE;
2854             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2855                 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE_PRE;
2856             }
2857         } else if (sheetStyle.sheetMode == SheetMode::LARGE) {
2858             sheetHeight_ = largeHeight;
2859         } else if (sheetStyle.sheetMode == SheetMode::AUTO) {
2860             sheetHeight_ = sheetPattern->GetFitContentHeight();
2861             if (GreatNotEqual(sheetHeight_, largeHeight)) {
2862                 sheetHeight_ = largeHeight;
2863             }
2864         }
2865     } else {
2866         float height = 0.0f;
2867         if (sheetStyle.height->Unit() == DimensionUnit::PERCENT) {
2868             height = sheetStyle.height->ConvertToPxWithSize(sheetMaxHeight - statusBarHeight);
2869         } else {
2870             height = sheetStyle.height->ConvertToPx();
2871         }
2872         if (height > largeHeight) {
2873             sheetHeight_ = largeHeight;
2874         } else if (height < 0) {
2875             sheetHeight_ = largeHeight;
2876         } else {
2877             sheetHeight_ = height;
2878         }
2879     }
2880 }
2881 
ComputeDetentsSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)2882 void OverlayManager::ComputeDetentsSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
2883 {
2884     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2885     CHECK_NULL_VOID(sheetPattern);
2886     auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2887     auto context = PipelineContext::GetCurrentContext();
2888     CHECK_NULL_VOID(context);
2889     auto manager = context->GetSafeAreaManager();
2890     CHECK_NULL_VOID(manager);
2891     auto statusBarHeight = manager->GetSystemSafeArea().top_.Length();
2892     auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - statusBarHeight;
2893     auto selection = sheetStyle.detents[0];
2894     if (selection.sheetMode.has_value()) {
2895         if (selection.sheetMode == SheetMode::MEDIUM) {
2896             sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE;
2897             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2898                 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE_PRE;
2899             }
2900         } else if (selection.sheetMode == SheetMode::LARGE) {
2901             sheetHeight_ = largeHeight;
2902         } else if (selection.sheetMode == SheetMode::AUTO) {
2903             sheetHeight_ = sheetPattern->GetFitContentHeight();
2904             if (GreatNotEqual(sheetHeight_, largeHeight)) {
2905                 sheetHeight_ = largeHeight;
2906             }
2907         }
2908     } else {
2909         float height = 0.0f;
2910         if (selection.height->Unit() == DimensionUnit::PERCENT) {
2911             height = selection.height->ConvertToPxWithSize(sheetMaxHeight - statusBarHeight);
2912         } else {
2913             height = selection.height->ConvertToPx();
2914         }
2915         if (height > largeHeight) {
2916             sheetHeight_ = largeHeight;
2917         } else if (height < 0) {
2918             sheetHeight_ = largeHeight;
2919         } else {
2920             sheetHeight_ = height;
2921         }
2922     }
2923 
2924 }
2925 
DestroySheet(const RefPtr<FrameNode> & sheetNode,int32_t targetId)2926 void OverlayManager::DestroySheet(const RefPtr<FrameNode>& sheetNode, int32_t targetId)
2927 {
2928     if (modalStack_.empty()) {
2929         return;
2930     }
2931     if (sheetMap_.empty() || !sheetMap_.count(targetId)) {
2932         DeleteModal(targetId);
2933         return;
2934     }
2935     auto mapSheetNode = sheetMap_[targetId].Upgrade();
2936     CHECK_NULL_VOID(mapSheetNode);
2937     if (mapSheetNode->GetTag() != V2::SHEET_PAGE_TAG) {
2938         return;
2939     }
2940     if (mapSheetNode->GetPattern<SheetPresentationPattern>()->GetTargetId() != targetId) {
2941         return;
2942     }
2943     auto rootNode = FindWindowScene(sheetNode);
2944     CHECK_NULL_VOID(rootNode);
2945     auto root = DynamicCast<FrameNode>(rootNode);
2946     ModalPageLostFocus(mapSheetNode);
2947     auto maskNode = GetSheetMask(sheetNode);
2948     if (maskNode) {
2949         root->RemoveChild(maskNode);
2950     }
2951     sheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2952     auto sheetParent = DynamicCast<FrameNode>(sheetNode->GetParent());
2953     CHECK_NULL_VOID(sheetParent);
2954     root->RemoveChild(sheetParent);
2955     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2956     sheetMap_.erase(targetId);
2957     RemoveSheetNode(sheetNode);
2958     FireModalPageHide();
2959     SaveLastModalNode();
2960 }
2961 
DeleteModal(int32_t targetId)2962 void OverlayManager::DeleteModal(int32_t targetId)
2963 {
2964     bool isDelete = false;
2965     bool isModal = true;
2966     for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
2967         auto modalNode = (*modal).Upgrade();
2968         if (!modalNode) {
2969             continue;
2970         }
2971         int32_t currentTargetId = -1;
2972         if (modalNode->GetTag() == V2::MODAL_PAGE_TAG) {
2973             isModal = true;
2974             currentTargetId = modalNode->GetPattern<ModalPresentationPattern>()->GetTargetId();
2975         } else if (modalNode->GetTag() == V2::SHEET_PAGE_TAG) {
2976             isModal = false;
2977             currentTargetId = modalNode->GetPattern<SheetPresentationPattern>()->GetTargetId();
2978         } else {
2979             return;
2980         }
2981         if (currentTargetId == targetId) {
2982             isDelete = true;
2983             modalList_.erase(modal);
2984             auto rootNode = FindWindowScene(modalNode);
2985             CHECK_NULL_VOID(rootNode);
2986             if (isModal) {
2987                 modalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
2988                 modalNode->GetPattern<ModalPresentationPattern>()->FireCallback("false");
2989                 // Fire hidden event of navdestination on the disappeared modal
2990                 FireNavigationStateChange(false, modalNode);
2991                 rootNode->RemoveChild(modalNode);
2992             } else {
2993                 RemoveSheetMask(modalNode, rootNode);
2994                 modalNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2995                 modalNode->GetPattern<SheetPresentationPattern>()->FireCallback("false");
2996                 sheetMap_.erase(targetId);
2997                 auto sheetParent = DynamicCast<FrameNode>(modalNode->GetParent());
2998                 CHECK_NULL_VOID(sheetParent);
2999                 rootNode->RemoveChild(sheetParent);
3000             }
3001             rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3002             break;
3003         }
3004     }
3005     if (isDelete) {
3006         while (!modalStack_.empty()) {
3007             modalStack_.pop();
3008         }
3009         for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
3010             modalStack_.push(*modal);
3011         }
3012         SaveLastModalNode();
3013     }
3014 }
3015 
RemoveSheetMask(RefPtr<FrameNode> & sheetNode,RefPtr<UINode> & rootNode)3016 void OverlayManager::RemoveSheetMask(RefPtr<FrameNode>& sheetNode, RefPtr<UINode>& rootNode)
3017 {
3018     auto maskNode = GetSheetMask(sheetNode);
3019     if (maskNode) {
3020         rootNode->RemoveChild(maskNode);
3021     }
3022 }
3023 
GetSheetMask(const RefPtr<FrameNode> & sheetNode)3024 RefPtr<FrameNode> OverlayManager::GetSheetMask(const RefPtr<FrameNode>& sheetNode)
3025 {
3026     // get bindsheet masknode
3027     CHECK_NULL_RETURN(sheetNode, NULL);
3028     auto sheetParent = sheetNode->GetParent();
3029     CHECK_NULL_RETURN(sheetParent, NULL);
3030     auto rootNode = sheetParent->GetParent();
3031     CHECK_NULL_RETURN(rootNode, NULL);
3032     auto sheetChildIter = std::find(rootNode->GetChildren().begin(), rootNode->GetChildren().end(), sheetParent);
3033     if (sheetChildIter == rootNode->GetChildren().end()) {
3034         return NULL;
3035     }
3036     --sheetChildIter;
3037     CHECK_NULL_RETURN((*sheetChildIter), NULL);
3038     auto sheetChildFrameNode = DynamicCast<FrameNode>(*sheetChildIter);
3039     if (sheetChildFrameNode && sheetChildFrameNode->GetTag() != V2::SHEET_MASK_TAG) {
3040         return NULL;
3041     }
3042     return sheetChildFrameNode;
3043 }
3044 
PlayKeyboardTransition(RefPtr<FrameNode> customKeyboard,bool isTransitionIn)3045 void OverlayManager::PlayKeyboardTransition(RefPtr<FrameNode> customKeyboard, bool isTransitionIn)
3046 {
3047     CHECK_NULL_VOID(customKeyboard);
3048     AnimationOption option;
3049     if (isTransitionIn) {
3050         option.SetCurve(SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE);
3051     } else {
3052         option.SetCurve(HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE);
3053     }
3054     option.SetFillMode(FillMode::FORWARDS);
3055     auto context = customKeyboard->GetRenderContext();
3056     CHECK_NULL_VOID(context);
3057     auto pipeline = PipelineContext::GetMainPipelineContext();
3058     CHECK_NULL_VOID(pipeline);
3059     auto pageNode = pipeline->GetStageManager()->GetLastPage();
3060     if (pageNode == nullptr) {
3061         auto parent = customKeyboard->GetParent();
3062         CHECK_NULL_VOID(parent);
3063         parent->RemoveChild(customKeyboard);
3064         return;
3065     }
3066     auto pageHeight = pageNode->GetGeometryNode()->GetFrameSize().Height();
3067     if (isTransitionIn) {
3068         context->OnTransformTranslateUpdate({ 0.0f, pageHeight, 0.0f });
3069         AnimationUtils::Animate(option, [context]() {
3070             if (context) {
3071                 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
3072             }
3073         });
3074     } else {
3075         context->UpdateOpacity(1.0);
3076         option.SetOnFinishEvent([customKeyboard] {
3077             auto parent = customKeyboard->GetParent();
3078             CHECK_NULL_VOID(parent);
3079             parent->RemoveChild(customKeyboard);
3080         });
3081         context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
3082         AnimationUtils::Animate(option, [context, pageHeight]() {
3083                 if (context) {
3084                     context->OnTransformTranslateUpdate({ 0.0f, pageHeight, 0.0f });
3085                 }
3086             },
3087             option.GetOnFinishEvent());
3088     }
3089 }
3090 
BindKeyboard(const std::function<void ()> & keyboardBuilder,int32_t targetId)3091 void OverlayManager::BindKeyboard(const std::function<void()>& keyboardBuilder, int32_t targetId)
3092 {
3093     if (customKeyboardMap_.find(targetId) != customKeyboardMap_.end()) {
3094         return;
3095     }
3096     auto rootNode = rootNodeWeak_.Upgrade();
3097     CHECK_NULL_VOID(rootNode);
3098     auto customKeyboard = KeyboardView::CreateKeyboard(targetId, keyboardBuilder);
3099     if (!customKeyboard) {
3100         return;
3101     }
3102     customKeyboard->MountToParent(rootNode);
3103     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3104     customKeyboardMap_[targetId] = customKeyboard;
3105     PlayKeyboardTransition(customKeyboard, true);
3106 }
3107 
CloseKeyboard(int32_t targetId)3108 void OverlayManager::CloseKeyboard(int32_t targetId)
3109 {
3110     auto it = customKeyboardMap_.find(targetId);
3111     if (it == customKeyboardMap_.end()) {
3112         return;
3113     }
3114     auto customKeyboard = it->second;
3115     CHECK_NULL_VOID(customKeyboard);
3116     auto pattern = customKeyboard->GetPattern<KeyboardPattern>();
3117     CHECK_NULL_VOID(pattern);
3118     customKeyboardMap_.erase(pattern->GetTargetId());
3119     PlayKeyboardTransition(customKeyboard, false);
3120 }
3121 
DestroyKeyboard()3122 void OverlayManager::DestroyKeyboard()
3123 {
3124     auto rootNode = rootNodeWeak_.Upgrade();
3125     CHECK_NULL_VOID(rootNode);
3126     if (customKeyboardMap_.empty()) {
3127         return;
3128     }
3129     for (auto it = customKeyboardMap_.begin(); it != customKeyboardMap_.end();) {
3130         auto keyboard = it->second;
3131         rootNode->RemoveChild(keyboard);
3132         it = customKeyboardMap_.erase(it);
3133     }
3134     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3135 }
3136 
3137 // This function will be used in SceneBoard Thread only.
3138 // if need to show the pop-up component,
3139 //   it expects to receive the target component bound by the pop-up component to find the windowScene component.
3140 // if need to hide the pop-up component,
3141 //   it expects to receive the the pop-up component to return the parent component.
3142 //   And the parent component will be the windowScene component exactly.
FindWindowScene(RefPtr<FrameNode> targetNode)3143 RefPtr<UINode> OverlayManager::FindWindowScene(RefPtr<FrameNode> targetNode)
3144 {
3145     auto container = Container::Current();
3146     if (!container || !container->IsScenceBoardWindow()) {
3147         return rootNodeWeak_.Upgrade();
3148     }
3149     CHECK_NULL_RETURN(targetNode, nullptr);
3150     auto parent = targetNode->GetParent();
3151     while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
3152         parent = parent->GetParent();
3153     }
3154     CHECK_NULL_RETURN(parent, nullptr);
3155     windowSceneSet_.insert(parent);
3156     return parent;
3157 }
3158 
MountFilterToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)3159 void OverlayManager::MountFilterToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
3160 {
3161     CHECK_NULL_VOID(windowScene);
3162     columnNode->MountToParent(windowScene);
3163     columnNode->OnMountToParentDone();
3164     windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3165     filterColumnNodeWeak_ = columnNode;
3166     hasFilter_ = true;
3167 }
3168 
MountPixelMapToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)3169 void OverlayManager::MountPixelMapToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
3170 {
3171     CHECK_NULL_VOID(windowScene);
3172     columnNode->MountToParent(windowScene);
3173     columnNode->OnMountToParentDone();
3174     windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3175     pixmapColumnNodeWeak_ = columnNode;
3176     hasPixelMap_ = true;
3177 }
3178 
MountEventToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)3179 void OverlayManager::MountEventToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
3180 {
3181     CHECK_NULL_VOID(windowScene);
3182     columnNode->MountToParent(windowScene);
3183     columnNode->OnMountToParentDone();
3184     eventColumnNodeWeak_ = columnNode;
3185     hasEvent_ = true;
3186 }
3187 
MountPixelMapToRootNode(const RefPtr<FrameNode> & columnNode)3188 void OverlayManager::MountPixelMapToRootNode(const RefPtr<FrameNode>& columnNode)
3189 {
3190     auto rootNode = rootNodeWeak_.Upgrade();
3191     CHECK_NULL_VOID(rootNode);
3192     columnNode->MountToParent(rootNode);
3193     columnNode->OnMountToParentDone();
3194     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3195     pixmapColumnNodeWeak_ = columnNode;
3196     hasPixelMap_ = true;
3197 }
3198 
MountEventToRootNode(const RefPtr<FrameNode> & columnNode)3199 void OverlayManager::MountEventToRootNode(const RefPtr<FrameNode>& columnNode)
3200 {
3201     auto rootNode = rootNodeWeak_.Upgrade();
3202     CHECK_NULL_VOID(rootNode);
3203     columnNode->MountToParent(rootNode, 1);
3204     columnNode->OnMountToParentDone();
3205     eventColumnNodeWeak_ = columnNode;
3206     hasEvent_ = true;
3207 }
3208 
RemovePixelMap()3209 void OverlayManager::RemovePixelMap()
3210 {
3211     if (!hasPixelMap_) {
3212         return;
3213     }
3214     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
3215     CHECK_NULL_VOID(columnNode);
3216     auto rootNode = columnNode->GetParent();
3217     CHECK_NULL_VOID(rootNode);
3218     rootNode->RemoveChild(columnNode);
3219     rootNode->RebuildRenderContextTree();
3220     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3221     hasPixelMap_ = false;
3222     isOnAnimation_ = false;
3223 }
3224 
RemovePixelMapAnimation(bool startDrag,double x,double y)3225 void OverlayManager::RemovePixelMapAnimation(bool startDrag, double x, double y)
3226 {
3227     if (isOnAnimation_ || !hasPixelMap_) {
3228         return;
3229     }
3230     if (startDrag) {
3231         return;
3232     }
3233     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
3234     CHECK_NULL_VOID(columnNode);
3235     auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetFirstChild());
3236     CHECK_NULL_VOID(imageNode);
3237     auto imageContext = imageNode->GetRenderContext();
3238     CHECK_NULL_VOID(imageContext);
3239     auto hub = columnNode->GetOrCreateGestureEventHub();
3240     CHECK_NULL_VOID(hub);
3241     auto frameNode = hub->GetFrameNode();
3242     CHECK_NULL_VOID(frameNode);
3243     RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
3244     CHECK_NULL_VOID(pixelMap);
3245     float scale = PIXELMAP_DRAG_SCALE;
3246     UpdatePixelMapScale(scale);
3247     int32_t width = pixelMap->GetWidth();
3248     int32_t height = pixelMap->GetHeight();
3249 
3250     auto shadow = imageContext->GetBackShadow();
3251     if (!shadow.has_value()) {
3252         shadow = Shadow::CreateShadow(ShadowStyle::None);
3253     }
3254     imageContext->UpdateBackShadow(shadow.value());
3255     AnimationOption option;
3256     option.SetCurve(Curves::SHARP);
3257     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
3258     AnimationUtils::Animate(option, [imageContext, shadow]() mutable {
3259         if (imageContext) {
3260             auto color = shadow->GetColor();
3261             auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue());
3262             shadow->SetColor(newColor);
3263             imageContext->UpdateBackShadow(shadow.value());
3264             BorderRadiusProperty borderRadius;
3265             borderRadius.SetRadius(0.0_vp);
3266             imageContext->UpdateBorderRadius(borderRadius);
3267         }
3268     });
3269 
3270     auto pipelineContext = PipelineContext::GetCurrentContext();
3271     CHECK_NULL_VOID(pipelineContext);
3272     auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
3273     CHECK_NULL_VOID(menuTheme);
3274     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
3275     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
3276 
3277     AnimationOption scaleOption;
3278     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
3279     scaleOption.SetCurve(motion);
3280 
3281     scaleOption.SetOnFinishEvent([this] {
3282         auto pipeline = PipelineContext::GetCurrentContext();
3283         CHECK_NULL_VOID(pipeline);
3284         auto dragDropManager = pipeline->GetDragDropManager();
3285         CHECK_NULL_VOID(dragDropManager);
3286         if (!dragDropManager->IsNeedScaleDragPreview()) {
3287             InteractionInterface::GetInstance()->SetDragWindowVisible(true);
3288         }
3289         auto overlayManager = AceType::Claim(this);
3290         CHECK_NULL_VOID(overlayManager);
3291         if (overlayManager->hasEvent_) {
3292             overlayManager->RemoveEventColumn();
3293         }
3294         overlayManager->RemovePixelMap();
3295     });
3296 
3297     auto coordinateX = imageNode->GetOffsetRelativeToWindow().GetX() - frameNode->GetOffsetRelativeToWindow().GetX();
3298     auto coordinateY = imageNode->GetOffsetRelativeToWindow().GetY() - frameNode->GetOffsetRelativeToWindow().GetY();
3299     AnimationUtils::Animate(
3300         scaleOption,
3301         [imageContext, startDrag, x, y, width, height, scale, coordinateX, coordinateY]() {
3302             if (startDrag) {
3303                 imageContext->UpdatePosition(OffsetT<Dimension>(
3304                     Dimension(x - (x - coordinateX) * scale +
3305                               PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * width * (scale - PIXELMAP_DRAG_SCALE)),
3306                     Dimension(y - (y - coordinateY) * scale +
3307                               PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * height * (scale - PIXELMAP_DRAG_SCALE))));
3308                 imageContext->UpdateTransformScale({ scale, scale });
3309                 imageContext->OnModifyDone();
3310             } else {
3311                 imageContext->UpdateTransformScale(VectorF(1.0f, 1.0f));
3312             }
3313         },
3314         scaleOption.GetOnFinishEvent());
3315     isOnAnimation_ = true;
3316 }
3317 
UpdatePixelMapScale(float & scale)3318 void OverlayManager::UpdatePixelMapScale(float& scale)
3319 {
3320     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
3321     CHECK_NULL_VOID(columnNode);
3322     auto hub = columnNode->GetOrCreateGestureEventHub();
3323     CHECK_NULL_VOID(hub);
3324     RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
3325     CHECK_NULL_VOID(pixelMap);
3326     int32_t height = pixelMap->GetHeight();
3327     int32_t width = pixelMap->GetWidth();
3328     if (height == 0 || width == 0) {
3329         return;
3330     }
3331     int32_t deviceWidth = SystemProperties::GetDeviceWidth();
3332     int32_t deviceHeight = SystemProperties::GetDeviceHeight();
3333     int32_t maxDeviceLength = std::max(deviceHeight, deviceWidth);
3334     int32_t minDeviceLength = std::min(deviceHeight, deviceWidth);
3335     if (maxDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE > minDeviceLength) {
3336         if (height > minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) {
3337             scale = static_cast<float>(minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) / height;
3338         }
3339     } else {
3340         if (hub->GetTextDraggable() && height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
3341             width > minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) {
3342             scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
3343                 static_cast<float>(minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) / width);
3344         } else if (height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
3345                    width > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) {
3346             scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
3347                 static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / width);
3348         }
3349     }
3350 }
3351 
RemoveFilterAnimation()3352 void OverlayManager::RemoveFilterAnimation()
3353 {
3354     if (!hasFilter_) {
3355         return;
3356     }
3357     auto filterNode = filterColumnNodeWeak_.Upgrade();
3358     CHECK_NULL_VOID(filterNode);
3359     auto filterContext = filterNode->GetRenderContext();
3360     CHECK_NULL_VOID(filterContext);
3361     auto pipelineContext = PipelineContext::GetCurrentContext();
3362     CHECK_NULL_VOID(pipelineContext);
3363     auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
3364     CHECK_NULL_VOID(menuTheme);
3365     AnimationOption option;
3366     option.SetOnFinishEvent([weak = WeakClaim(this)] {
3367         auto overlayManager = weak.Upgrade();
3368         CHECK_NULL_VOID(overlayManager);
3369         overlayManager->RemoveFilter();
3370     });
3371     option.SetDuration(menuTheme->GetFilterAnimationDuration());
3372     option.SetCurve(Curves::SHARP);
3373     AnimationUtils::Animate(
3374         option,
3375         [filterContext]() {
3376             CHECK_NULL_VOID(filterContext);
3377             BlurStyleOption styleOption;
3378             styleOption.blurStyle = BlurStyle::NO_MATERIAL;
3379             filterContext->UpdateBackBlurStyle(styleOption);
3380         },
3381         option.GetOnFinishEvent());
3382 }
3383 
RemoveFilter()3384 void OverlayManager::RemoveFilter()
3385 {
3386     if (!hasFilter_) {
3387         return;
3388     }
3389     auto columnNode = filterColumnNodeWeak_.Upgrade();
3390     if (columnNode) {
3391         auto rootNode = columnNode->GetParent();
3392         CHECK_NULL_VOID(rootNode);
3393         rootNode->RemoveChild(columnNode);
3394         rootNode->RebuildRenderContextTree();
3395     }
3396     hasFilter_ = false;
3397 }
3398 
RemoveEventColumn()3399 void OverlayManager::RemoveEventColumn()
3400 {
3401     if (!hasEvent_) {
3402         return;
3403     }
3404     auto columnNode = eventColumnNodeWeak_.Upgrade();
3405     CHECK_NULL_VOID(columnNode);
3406     auto rootNode = columnNode->GetParent();
3407     CHECK_NULL_VOID(rootNode);
3408     rootNode->RemoveChild(columnNode);
3409     hasEvent_ = false;
3410 }
3411 
CreateModalUIExtension(const AAFwk::Want & want,const ModalUIExtensionCallbacks & callbacks,bool isProhibitBack,bool isAsyncModalBinding)3412 int32_t OverlayManager::CreateModalUIExtension(
3413     const AAFwk::Want& want, const ModalUIExtensionCallbacks& callbacks, bool isProhibitBack, bool isAsyncModalBinding)
3414 {
3415     isProhibitBack_ = isProhibitBack;
3416     auto uiExtNode = ModalUIExtension::Create(want, callbacks, isAsyncModalBinding);
3417     auto layoutProperty = uiExtNode->GetLayoutProperty();
3418     CHECK_NULL_RETURN(layoutProperty, 0);
3419     auto full = CalcLength(Dimension(1.0, DimensionUnit::PERCENT));
3420     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(full, full));
3421     auto buildNodeFunc = [uiExtNode]() -> RefPtr<UINode> {
3422         uiExtNode->MarkModifyDone();
3423         return uiExtNode;
3424     };
3425     auto sessionId = ModalUIExtension::GetSessionId(uiExtNode);
3426     if (!isAsyncModalBinding) {
3427         ModalStyle modalStyle;
3428         modalStyle.modalTransition = NG::ModalTransition::NONE;
3429         modalStyle.isUIExtension = true;
3430         // Convert the sessionId into a negative number to distinguish it from the targetId of other modal pages
3431         BindContentCover(true, nullptr, std::move(buildNodeFunc), modalStyle, nullptr, nullptr, nullptr, -(sessionId));
3432     } else {
3433         auto bindModalCallback = [weak = WeakClaim(this), buildNodeFunc, sessionId, id = Container::CurrentId()]() {
3434             ContainerScope scope(id);
3435             auto overlayManager = weak.Upgrade();
3436             CHECK_NULL_VOID(overlayManager);
3437             ModalStyle modalStyle;
3438             modalStyle.modalTransition = NG::ModalTransition::NONE;
3439             modalStyle.isUIExtension = true;
3440             overlayManager->BindContentCover(
3441                 true, nullptr, std::move(buildNodeFunc), modalStyle, nullptr, nullptr, nullptr, -(sessionId));
3442         };
3443         ModalUIExtension::SetBindModalCallback(uiExtNode, std::move(bindModalCallback));
3444         uiExtNodes_[sessionId] = WeakClaim(RawPtr(uiExtNode));
3445     }
3446     return sessionId;
3447 }
3448 
CloseModalUIExtension(int32_t sessionId)3449 void OverlayManager::CloseModalUIExtension(int32_t sessionId)
3450 {
3451     if (uiExtNodes_.find(sessionId) != uiExtNodes_.end()) {
3452         auto uiExtNode = uiExtNodes_[sessionId].Upgrade();
3453         if (uiExtNode) {
3454             ModalUIExtension::SetBindModalCallback(uiExtNode, nullptr);
3455         }
3456         uiExtNodes_.erase(sessionId);
3457     }
3458     ModalStyle modalStyle;
3459     modalStyle.modalTransition = NG::ModalTransition::NONE;
3460     BindContentCover(false, nullptr, nullptr, modalStyle, nullptr, nullptr, nullptr, -(sessionId));
3461 }
3462 
BindUIExtensionToMenu(const RefPtr<FrameNode> & uiExtNode,const RefPtr<NG::FrameNode> & targetNode,std::string longestContent,int32_t menuSize)3463 RefPtr<FrameNode> OverlayManager::BindUIExtensionToMenu(const RefPtr<FrameNode>& uiExtNode,
3464     const RefPtr<NG::FrameNode>& targetNode, std::string longestContent, int32_t menuSize)
3465 {
3466     CHECK_NULL_RETURN(uiExtNode, nullptr);
3467     CHECK_NULL_RETURN(targetNode, nullptr);
3468     auto pipeline = PipelineContext::GetCurrentContext();
3469     CHECK_NULL_RETURN(pipeline, nullptr);
3470     MenuParam menuParam;
3471     menuParam.type = MenuType::MENU;
3472     menuParam.placement = Placement::BOTTOM_LEFT;
3473     auto menuWrapperNode =
3474         MenuView::Create(uiExtNode, targetNode->GetId(), targetNode->GetTag(), menuParam, true);
3475     CHECK_NULL_RETURN(menuWrapperNode, nullptr);
3476     auto menuNode = DynamicCast<FrameNode>(menuWrapperNode->GetFirstChild());
3477     CHECK_NULL_RETURN(menuNode, nullptr);
3478     auto idealSize = CaculateMenuSize(menuNode, longestContent, menuSize);
3479     auto uiExtLayoutProperty = uiExtNode->GetLayoutProperty();
3480     CHECK_NULL_RETURN(uiExtLayoutProperty, nullptr);
3481     uiExtLayoutProperty->UpdateUserDefinedIdealSize(
3482         CalcSize(CalcLength(idealSize.Width()),  CalcLength(idealSize.Height())));
3483     auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
3484     CHECK_NULL_RETURN(menuLayoutProperty, nullptr);
3485     menuLayoutProperty->UpdateMargin(MarginProperty());
3486     menuLayoutProperty->UpdatePadding(PaddingProperty());
3487     auto scollNode = DynamicCast<FrameNode>(menuNode->GetFirstChild());
3488     CHECK_NULL_RETURN(scollNode, menuNode);
3489     auto scollLayoutProperty = scollNode->GetLayoutProperty();
3490     CHECK_NULL_RETURN(scollLayoutProperty, menuNode);
3491     scollLayoutProperty->UpdateMargin(MarginProperty());
3492     scollLayoutProperty->UpdatePadding(PaddingProperty());
3493 
3494     auto destructor = [id = targetNode->GetId()]() {
3495         auto pipeline = NG::PipelineContext::GetCurrentContext();
3496         CHECK_NULL_VOID(pipeline);
3497         auto overlayManager = pipeline->GetOverlayManager();
3498         CHECK_NULL_VOID(overlayManager);
3499         overlayManager->DeleteMenu(id);
3500     };
3501     targetNode->PushDestroyCallback(destructor);
3502     return menuNode;
3503 }
3504 
CaculateMenuSize(const RefPtr<FrameNode> & menuNode,std::string longestContent,int32_t menuSize)3505 SizeF OverlayManager::CaculateMenuSize(
3506     const RefPtr<FrameNode>& menuNode, std::string longestContent, int32_t menuSize)
3507 {
3508     TAG_LOGD(AceLogTag::ACE_OVERLAY, "caculate menu size enter");
3509     auto pipeline = PipelineContext::GetCurrentContext();
3510     CHECK_NULL_RETURN(pipeline, SizeF());
3511     auto textTheme = pipeline->GetTheme<TextTheme>();
3512     CHECK_NULL_RETURN(textTheme, SizeF());
3513     TextStyle textStyle = textTheme ? textTheme->GetTextStyle() : TextStyle();
3514     MeasureContext measureContext;
3515     measureContext.textContent = longestContent;
3516     measureContext.fontSize = textStyle.GetFontSize();
3517     auto fontweight = StringUtils::FontWeightToString(textStyle.GetFontWeight());
3518     measureContext.fontWeight = fontweight;
3519     auto fontFamilies = textStyle.GetFontFamilies();
3520     measureContext.fontFamily = V2::ConvertFontFamily(fontFamilies);
3521     auto measureSize = MeasureUtil::MeasureTextSize(measureContext);
3522     auto selectTheme = pipeline->GetTheme<SelectTheme>();
3523     CHECK_NULL_RETURN(selectTheme, SizeF());
3524     auto minItemHeight = static_cast<float>(selectTheme->GetOptionMinHeight().ConvertToPx());
3525     auto menuItemHeight = std::max(minItemHeight, static_cast<float>(measureSize.Height()));
3526     auto groupDividerPadding = static_cast<float>(selectTheme->GetDividerPaddingVertical().ConvertToPx()) * 2 +
3527                            static_cast<float>(selectTheme->GetDefaultDividerWidth().ConvertToPx());
3528     auto groupHeight = menuItemHeight + groupDividerPadding;
3529 
3530     auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
3531     CHECK_NULL_RETURN(menuLayoutProperty, SizeF());
3532     const auto& padding = menuLayoutProperty->CreatePaddingAndBorder();
3533     auto middleSpace = static_cast<float>(selectTheme->GetIconContentPadding().ConvertToPx());
3534     float contentWidth = static_cast<float>(measureSize.Width()) + padding.Width() + middleSpace;
3535 
3536     auto childConstraint = menuLayoutProperty->CreateChildConstraint();
3537     auto columnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::MENU);
3538     CHECK_NULL_RETURN(columnInfo, SizeF());
3539     CHECK_NULL_RETURN(columnInfo->GetParent(), SizeF());
3540     columnInfo->GetParent()->BuildColumnWidth();
3541     auto minWidth = static_cast<float>(columnInfo->GetWidth()) - padding.Width();
3542     childConstraint.minSize.SetWidth(minWidth);
3543     auto idealWidth = std::max(contentWidth, childConstraint.minSize.Width());
3544     auto idealHeight = groupHeight * (menuSize - 1) +
3545         menuItemHeight + static_cast<float>(selectTheme->GetOutPadding().ConvertToPx()) * 2;
3546     return SizeF(idealWidth, idealHeight);
3547 }
3548 
ShowUIExtensionMenu(const RefPtr<NG::FrameNode> & uiExtNode,NG::RectF aiRect,std::string longestContent,int32_t menuSize,const RefPtr<NG::FrameNode> & targetNode)3549 bool OverlayManager::ShowUIExtensionMenu(const RefPtr<NG::FrameNode>& uiExtNode, NG::RectF aiRect,
3550     std::string longestContent, int32_t menuSize, const RefPtr<NG::FrameNode>& targetNode)
3551 {
3552     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show ui extension menu enter");
3553     CHECK_NULL_RETURN(uiExtNode, false);
3554     auto root = rootNodeWeak_.Upgrade();
3555     CHECK_NULL_RETURN(root, false);
3556     for (const auto& child : root->GetChildren()) {
3557         if (child->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
3558             return false;
3559         }
3560     }
3561     auto menuNode = BindUIExtensionToMenu(uiExtNode, targetNode, longestContent, menuSize);
3562     CHECK_NULL_RETURN(menuNode, false);
3563     auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
3564     CHECK_NULL_RETURN(menuLayoutProperty, false);
3565     menuLayoutProperty->UpdateIsRectInTarget(true);
3566     menuLayoutProperty->UpdateTargetSize(aiRect.GetSize());
3567     auto menuWrapperNode = DynamicCast<FrameNode>(menuNode->GetParent());
3568     CHECK_NULL_RETURN(menuWrapperNode, false);
3569     ShowMenu(targetNode->GetId(), aiRect.GetOffset(), menuWrapperNode);
3570     return true;
3571 }
3572 
MarkDirty(PropertyChangeFlag flag)3573 void OverlayManager::MarkDirty(PropertyChangeFlag flag)
3574 {
3575     auto root = rootNodeWeak_.Upgrade();
3576     CHECK_NULL_VOID(root);
3577     auto pipeline = PipelineContext::GetCurrentContext();
3578     CHECK_NULL_VOID(pipeline);
3579     for (auto&& child : root->GetChildren()) {
3580         // first child is Stage node in main window, subwindow not has Stage node.
3581         if (child != root->GetFirstChild() || pipeline->IsSubPipeline()) {
3582             child->MarkDirtyNode(flag);
3583         }
3584     }
3585 }
3586 
GetRootHeight() const3587 float OverlayManager::GetRootHeight() const
3588 {
3589     auto rootNode = rootNodeWeak_.Upgrade();
3590     CHECK_NULL_RETURN(rootNode, 0.0);
3591     auto rootGeometryNode = AceType::DynamicCast<FrameNode>(rootNode)->GetGeometryNode();
3592     CHECK_NULL_RETURN(rootGeometryNode, 0.0);
3593     auto rootHeight = rootGeometryNode->GetFrameSize().Height();
3594     return rootHeight;
3595 }
3596 
CheckReturnFocus(RefPtr<FrameNode> node)3597 void OverlayManager::CheckReturnFocus(RefPtr<FrameNode> node)
3598 {
3599     auto focusHub = node->GetFocusHub();
3600     CHECK_NULL_VOID(focusHub);
3601     if (focusHub->IsCurrentFocus()) {
3602         auto pageNode = GetLastPage();
3603         CHECK_NULL_VOID(pageNode);
3604         auto pageFocusHub = pageNode->GetFocusHub();
3605         CHECK_NULL_VOID(pageFocusHub);
3606         pageFocusHub->RequestFocusWithDefaultFocusFirstly();
3607     }
3608 }
3609 } // namespace OHOS::Ace::NG
3610