• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 <string>
20 #include <utility>
21 #include <vector>
22 #if defined(OHOS_STANDARD_SYSTEM) and !defined(ACE_UNITTEST)
23 #include "want.h"
24 #endif
25 
26 #include "base/error/error_code.h"
27 #include "base/geometry/ng/offset_t.h"
28 #include "base/geometry/ng/size_t.h"
29 #include "base/log/dump_log.h"
30 #include "base/log/log.h"
31 #include "base/memory/ace_type.h"
32 #include "base/memory/referenced.h"
33 #include "base/subwindow/subwindow_manager.h"
34 #include "base/utils/measure_util.h"
35 #include "base/utils/system_properties.h"
36 #include "base/utils/utils.h"
37 #include "base/window/foldable_window.h"
38 #include "core/animation/animation_pub.h"
39 #include "core/animation/spring_curve.h"
40 #include "core/common/ace_application_info.h"
41 #include "core/common/ace_engine.h"
42 #include "core/common/container.h"
43 #include "core/common/ime/input_method_manager.h"
44 #include "core/common/interaction/interaction_interface.h"
45 #include "core/common/modal_ui_extension.h"
46 #include "core/common/recorder/event_recorder.h"
47 #include "core/components/common/properties/color.h"
48 #include "core/components/select/select_theme.h"
49 #include "core/components/text_overlay/text_overlay_theme.h"
50 #include "core/components/toast/toast_theme.h"
51 #include "core/components_ng/animation/geometry_transition.h"
52 #include "core/components_ng/base/frame_node.h"
53 #include "core/components_ng/base/ui_node.h"
54 #include "core/components_ng/base/view_abstract.h"
55 #include "core/components_ng/base/view_stack_processor.h"
56 #include "core/components_ng/event/focus_hub.h"
57 #include "core/components_ng/manager/focus/focus_view.h"
58 #include "core/components_ng/pattern/bubble/bubble_event_hub.h"
59 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
60 #include "core/components_ng/pattern/calendar_picker/calendar_dialog_view.h"
61 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
62 #include "core/components_ng/pattern/dialog/dialog_view.h"
63 #include "core/components_ng/pattern/menu/menu_item/menu_item_model_ng.h"
64 #include "core/components_ng/pattern/menu/menu_item/menu_item_pattern.h"
65 #include "core/components_ng/pattern/menu/menu_item_group/menu_item_group_view.h"
66 #include "core/components_ng/pattern/menu/menu_layout_property.h"
67 #include "core/components_ng/pattern/menu/menu_pattern.h"
68 #include "core/components_ng/pattern/menu/menu_theme.h"
69 #include "core/components_ng/pattern/menu/menu_view.h"
70 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
71 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
72 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
73 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
74 #include "core/components_ng/pattern/overlay/keyboard_base_pattern.h"
75 #include "core/components_ng/pattern/overlay/keyboard_view.h"
76 #include "core/components_ng/pattern/overlay/modal_presentation_pattern.h"
77 #include "core/components_ng/pattern/overlay/overlay_container_pattern.h"
78 #include "core/components_ng/pattern/overlay/popup_base_pattern.h"
79 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
80 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
81 #include "core/components_ng/pattern/overlay/sheet_presentation_property.h"
82 #include "core/components_ng/pattern/overlay/sheet_style.h"
83 #include "core/components_ng/pattern/overlay/sheet_view.h"
84 #include "core/components_ng/pattern/overlay/sheet_wrapper_pattern.h"
85 #include "core/components_ng/pattern/picker/datepicker_dialog_view.h"
86 #include "core/components_ng/pattern/stage/stage_pattern.h"
87 #include "core/components_ng/pattern/text_field/text_field_manager.h"
88 #include "core/components_ng/pattern/text_picker/textpicker_dialog_view.h"
89 #include "core/components_ng/pattern/time_picker/timepicker_dialog_view.h"
90 #include "core/components_ng/pattern/toast/toast_pattern.h"
91 #include "core/components_ng/pattern/ui_extension/ui_extension_model.h"
92 #include "core/components_ng/pattern/video/video_full_screen_pattern.h"
93 #include "core/components_ng/property/measure_property.h"
94 #include "core/components_ng/property/property.h"
95 #include "core/components_v2/inspector/inspector_constants.h"
96 #include "core/pipeline/pipeline_base.h"
97 #include "core/pipeline/pipeline_context.h"
98 #ifdef WEB_SUPPORTED
99 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
100 #include "core/components_ng/pattern/web/web_pattern.h"
101 #else
102 #include "core/components_ng/pattern/web/cross_platform/web_pattern.h"
103 #endif
104 #endif
105 
106 namespace OHOS::Ace::NG {
107 namespace {
108 // should be moved to theme.
109 constexpr int32_t TOAST_ANIMATION_DURATION = 100;
110 constexpr int32_t MENU_ANIMATION_DURATION = 150;
111 constexpr float TOAST_ANIMATION_POSITION = 15.0f;
112 
113 constexpr float PIXELMAP_DRAG_SCALE = 1.0f;
114 constexpr float NUM_FLOAT_2 = 2.0f;
115 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 250;
116 constexpr float PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE = 0.5f;
117 
118 constexpr int32_t FULL_MODAL_ALPHA_ANIMATION_DURATION = 200;
119 
120 constexpr int32_t SHEET_HALF_SIZE = 2;
121 // dialog animation params
122 const RefPtr<Curve> SHOW_SCALE_ANIMATION_CURVE = AceType::MakeRefPtr<CubicCurve>(0.38f, 1.33f, 0.6f, 1.0f);
123 
124 constexpr int32_t ROOT_MIN_NODE = 1;
125 constexpr int32_t ATOMIC_SERVICE_MIN_SIZE = 2;
126 
127 //  OVERLAY_EXISTS:  overlay was removed
128 // OVERLAY_REMOVE:: overlay exists
129 // OVERLAY_NOTHING:nothing
130 constexpr int32_t OVERLAY_EXISTS = 0;
131 constexpr int32_t OVERLAY_REMOVE = 1;
132 constexpr int32_t OVERLAY_NOTHING = 2;
133 
134 // custom keyboard animation params
135 const RefPtr<Curve> SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE =
136     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f);
137 const RefPtr<Curve> HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE =
138     AceType::MakeRefPtr<InterpolatingSpring>(4.0f, 1.0f, 342.0f, 37.0f);
139 
140 const RefPtr<InterpolatingSpring> MENU_ANIMATION_CURVE =
141     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 528.0f, 35.0f);
142 
143 const RefPtr<Curve> CUSTOM_PREVIEW_ANIMATION_CURVE =
144     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 280.0f, 30.0f);
145 const std::string HOVER_IMAGE_CLIP_DISAPPEAR_PROPERTY_NAME = "hoverImageClipDisAppear";
146 constexpr double MENU_ORIGINAL_SCALE = 0.6f;
147 constexpr int32_t DUMP_LOG_DEPTH_1 = 1;
148 constexpr int32_t DUMP_LOG_DEPTH_2 = 2;
149 
150 constexpr int32_t EVENT_COLUMN_SLOT = -2;
151 
152 const float MINIMUM_AMPLITUDE_RATION = 0.08f;
153 
154 // UIExtensionComponent Transform param key
155 #if defined(OHOS_STANDARD_SYSTEM) and !defined(ACE_UNITTEST)
156 constexpr char WANT_PARAM_UIEXTNODE_ANGLE_KEY[] = "modalUIExtNodeAngle";
157 constexpr char WANT_PARAM_UIEXTNODE_WIDTH_KEY[] = "modalUIExtNodeWidth";
158 constexpr char WANT_PARAM_UIEXTNODE_HEIGHT_KEY[] = "modalUIExtNodeHeight";
159 #endif
160 constexpr int32_t UIEXTNODE_ANGLE_90 = 90;
161 constexpr int32_t UIEXTNODE_ANGLE_180 = 180;
162 constexpr int32_t UIEXTNODE_ANGLE_270 = 270;
163 
164 constexpr double DISTANCE_THRESHOLD = 20.0;
165 
GetLastPage()166 RefPtr<FrameNode> GetLastPage()
167 {
168     auto pipelineContext = PipelineContext::GetCurrentContext();
169     CHECK_NULL_RETURN(pipelineContext, nullptr);
170     auto stageManager = pipelineContext->GetStageManager();
171     CHECK_NULL_RETURN(stageManager, nullptr);
172     auto pageNode = stageManager->GetLastPage();
173     return pageNode;
174 }
175 
ShowPreviewBgDisappearAnimationProc(const RefPtr<RenderContext> & previewRenderContext,const RefPtr<MenuTheme> & menuTheme,bool isShowHoverImage)176 void ShowPreviewBgDisappearAnimationProc(const RefPtr<RenderContext>& previewRenderContext,
177     const RefPtr<MenuTheme>& menuTheme, bool isShowHoverImage)
178 {
179     auto shadow = previewRenderContext->GetBackShadow();
180     if (!shadow.has_value()) {
181         shadow = Shadow::CreateShadow(ShadowStyle::None);
182     }
183     previewRenderContext->UpdateBackShadow(shadow.value());
184     auto disappearDuration = menuTheme->GetDisappearDuration();
185     AnimationOption previewOption;
186     if (isShowHoverImage) {
187         previewOption.SetCurve(CUSTOM_PREVIEW_ANIMATION_CURVE);
188     } else {
189         previewOption.SetCurve(Curves::SHARP);
190         previewOption.SetDuration(disappearDuration);
191     }
192     AnimationUtils::Animate(previewOption, [previewRenderContext, shadow]() mutable {
193         CHECK_NULL_VOID(previewRenderContext);
194         auto color = shadow->GetColor();
195         auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue());
196         shadow->SetColor(newColor);
197         previewRenderContext->UpdateBackShadow(shadow.value());
198         BorderRadiusProperty borderRadius;
199         borderRadius.SetRadius(0.0_vp);
200         previewRenderContext->UpdateBorderRadius(borderRadius);
201     });
202 }
203 
UpdateHoverImagePreviewOpacityAnimation(const RefPtr<MenuTheme> & menuTheme,const RefPtr<MenuPattern> & menuPattern,RefPtr<FrameNode> & previewChild)204 void UpdateHoverImagePreviewOpacityAnimation(const RefPtr<MenuTheme>& menuTheme,
205     const RefPtr<MenuPattern>& menuPattern, RefPtr<FrameNode>& previewChild)
206 {
207     CHECK_NULL_VOID(menuPattern);
208     CHECK_NULL_VOID(menuPattern->GetIsShowHoverImage());
209 
210     CHECK_NULL_VOID(previewChild);
211     auto previewRenderContext = previewChild->GetRenderContext();
212     CHECK_NULL_VOID(previewRenderContext);
213 
214     bool isCustomPreview = previewChild->GetTag() == V2::MENU_PREVIEW_ETS_TAG;
215     // only update custom preview opacity
216     CHECK_NULL_VOID(isCustomPreview);
217 
218     AnimationOption option;
219     option.SetDuration(menuTheme->GetHoverImagePreviewDisAppearDuration());
220     option.SetCurve(Curves::FRICTION);
221     AnimationUtils::Animate(
222         option, [previewRenderContext]() {
223             CHECK_NULL_VOID(previewRenderContext);
224             previewRenderContext->UpdateOpacity(0.0);
225         });
226 }
227 
ShowPreviewDisappearAnimationProc(const RefPtr<MenuWrapperPattern> & menuWrapperPattern,RefPtr<FrameNode> & previewChild)228 void ShowPreviewDisappearAnimationProc(const RefPtr<MenuWrapperPattern>& menuWrapperPattern,
229     RefPtr<FrameNode>& previewChild)
230 {
231     CHECK_NULL_VOID(menuWrapperPattern);
232     CHECK_NULL_VOID(previewChild);
233     auto previewRenderContext = previewChild->GetRenderContext();
234     CHECK_NULL_VOID(previewRenderContext);
235     if (menuWrapperPattern->HasPreviewTransitionEffect()) {
236         auto layoutProperty = previewChild->GetLayoutProperty();
237         CHECK_NULL_VOID(layoutProperty);
238         layoutProperty->UpdateVisibility(VisibleType::INVISIBLE, true);
239         return;
240     }
241 
242     auto menuChild = menuWrapperPattern->GetMenu();
243     CHECK_NULL_VOID(menuChild);
244     auto menuPattern = menuChild->GetPattern<MenuPattern>();
245     CHECK_NULL_VOID(menuPattern);
246     auto previewPosition = menuPattern->GetPreviewOriginOffset();
247 
248     auto pipelineContext = menuChild->GetContext();
249     CHECK_NULL_VOID(pipelineContext);
250     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
251     CHECK_NULL_VOID(menuTheme);
252     UpdateHoverImagePreviewOpacityAnimation(menuTheme, menuPattern, previewChild);
253 
254     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
255     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
256     AnimationOption scaleOption;
257     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
258     scaleOption.SetCurve(motion);
259     float previewScale = 1.0f;
260     if (menuPattern->GetPreviewMode() == MenuPreviewMode::IMAGE) {
261         auto previewGeometryNode = previewChild->GetGeometryNode();
262         CHECK_NULL_VOID(previewGeometryNode);
263         auto preivewSize = previewGeometryNode->GetFrameSize();
264         if (!NearEqual(menuPattern->GetTargetSize().Width(), preivewSize.Width())) {
265             previewScale = menuPattern->GetTargetSize().Width() / preivewSize.Width();
266         }
267     }
268     ShowPreviewBgDisappearAnimationProc(previewRenderContext, menuTheme, menuWrapperPattern->GetIsShowHoverImage());
269 
270     CHECK_NULL_VOID(!menuPattern->GetIsShowHoverImage());
271     AnimationUtils::Animate(scaleOption,
272         [previewRenderContext, previewPosition, previewScale]() {
273         CHECK_NULL_VOID(previewRenderContext);
274         previewRenderContext->UpdatePosition(
275             OffsetT<Dimension>(Dimension(previewPosition.GetX()), Dimension(previewPosition.GetY())));
276         previewRenderContext->UpdateTransformScale(VectorF(previewScale, previewScale));
277     });
278 }
279 
UpdatePreviewVisibleAreaByFrameWhenDisappear(const RefPtr<RenderContext> & clipContext,const RefPtr<MenuPreviewPattern> & previewPattern,float value,float radius,float distVal)280 void UpdatePreviewVisibleAreaByFrameWhenDisappear(const RefPtr<RenderContext>& clipContext,
281     const RefPtr<MenuPreviewPattern>& previewPattern, float value, float radius, float distVal)
282 {
283     CHECK_NULL_VOID(previewPattern);
284     CHECK_NULL_VOID(!NearZero(distVal));
285     auto rate = (value - previewPattern->GetClipEndValue()) / distVal;
286 
287     auto clipStartWidth = previewPattern->GetStackAfterScaleActualWidth();
288     auto clipStartHeight = previewPattern->GetStackAfterScaleActualHeight();
289     auto clipEndWidth = previewPattern->GetHoverImageAfterScaleWidth();
290     auto clipEndHeight = previewPattern->GetHoverImageAfterScaleHeight();
291 
292     auto curentClipAreaWidth = rate * (clipEndWidth - clipStartWidth) + clipStartWidth;
293     auto curentClipAreaHeight = rate * (clipEndHeight - clipStartHeight) + clipStartHeight;
294 
295     auto clipOffset = previewPattern->GetHoverImageAfterScaleOffset();
296     RoundRect roundRectInstance;
297     roundRectInstance.SetRect(RectF(OffsetF(rate * clipOffset.GetX(), rate * clipOffset.GetY()),
298         SizeF(curentClipAreaWidth, curentClipAreaHeight)));
299     roundRectInstance.SetCornerRadius((1 - rate) * radius);
300     CHECK_NULL_VOID(clipContext);
301     clipContext->ClipWithRoundRect(roundRectInstance);
302 }
303 
UpdatePreivewVisibleAreaWhenDisappear(const RefPtr<FrameNode> & hoverImageStackNode,const RefPtr<FrameNode> & previewNode)304 void UpdatePreivewVisibleAreaWhenDisappear(const RefPtr<FrameNode>& hoverImageStackNode,
305     const RefPtr<FrameNode>& previewNode)
306 {
307     CHECK_NULL_VOID(hoverImageStackNode && previewNode);
308     auto previewPattern = previewNode->GetPattern<MenuPreviewPattern>();
309     CHECK_NULL_VOID(previewPattern);
310 
311     // reverse
312     auto clipStartValue = previewPattern->GetClipEndValue();
313     auto clipEndValue = previewPattern->GetClipStartValue();
314     clipEndValue += NearEqual(clipStartValue, clipEndValue) ? 1.0f : 0;
315     auto dist = clipEndValue - clipStartValue;
316 
317     auto pipelineContext = previewNode->GetContext();
318     CHECK_NULL_VOID(pipelineContext);
319     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
320     CHECK_NULL_VOID(menuTheme);
321     hoverImageStackNode->CreateAnimatablePropertyFloat(HOVER_IMAGE_CLIP_DISAPPEAR_PROPERTY_NAME, 0,
322         [weak = AceType::WeakClaim(AceType::RawPtr(hoverImageStackNode)),
323             previewWeak = AceType::WeakClaim(AceType::RawPtr(previewNode)),
324             radius = menuTheme->GetPreviewBorderRadius().ConvertToPx(), distVal = dist](float value) {
325             auto clipNode = weak.Upgrade();
326             CHECK_NULL_VOID(clipNode);
327             auto clipContext = clipNode->GetRenderContext();
328             CHECK_NULL_VOID(clipContext);
329 
330             auto preview = previewWeak.Upgrade();
331             CHECK_NULL_VOID(preview);
332             auto previewPattern = preview->GetPattern<MenuPreviewPattern>();
333             CHECK_NULL_VOID(previewPattern);
334             UpdatePreviewVisibleAreaByFrameWhenDisappear(clipContext, previewPattern, value, radius, distVal);
335         });
336     AnimationOption option;
337     option.SetCurve(CUSTOM_PREVIEW_ANIMATION_CURVE);
338     hoverImageStackNode->UpdateAnimatablePropertyFloat(HOVER_IMAGE_CLIP_DISAPPEAR_PROPERTY_NAME, clipStartValue);
339     auto clipAnimation_ = AnimationUtils::StartAnimation(option, [hoverImageStackNode, clipEndValue]() {
340         CHECK_NULL_VOID(hoverImageStackNode);
341         hoverImageStackNode->UpdateAnimatablePropertyFloat(HOVER_IMAGE_CLIP_DISAPPEAR_PROPERTY_NAME, clipEndValue);
342     });
343 }
344 
UpdateHoverImageDisappearScaleAndPosition(const RefPtr<MenuWrapperPattern> & menuWrapperPattern,const RefPtr<MenuPreviewPattern> & previewPattern)345 void UpdateHoverImageDisappearScaleAndPosition(const RefPtr<MenuWrapperPattern>& menuWrapperPattern,
346     const RefPtr<MenuPreviewPattern>& previewPattern)
347 {
348     CHECK_NULL_VOID(menuWrapperPattern);
349     CHECK_NULL_VOID(menuWrapperPattern->GetIsShowHoverImage());
350 
351     CHECK_NULL_VOID(previewPattern);
352     // reverse scale
353     auto scaleTo = previewPattern->GetHoverImageScaleFrom();
354     auto pipelineContext = PipelineContext::GetCurrentContext();
355     CHECK_NULL_VOID(pipelineContext);
356     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
357     CHECK_NULL_VOID(menuTheme);
358     auto scaleAfter = LessNotEqual(scaleTo, 0.0) ? menuTheme->GetPreviewBeforeAnimationScale() : scaleTo;
359 
360     auto stackNode = menuWrapperPattern->GetHoverImageStackNode();
361     CHECK_NULL_VOID(stackNode);
362     auto stackContext = stackNode->GetRenderContext();
363     CHECK_NULL_VOID(stackContext);
364 
365     auto flexNode = menuWrapperPattern->GetHoverImageFlexNode();
366     CHECK_NULL_VOID(flexNode);
367     auto flexContext = flexNode->GetRenderContext();
368     CHECK_NULL_VOID(flexContext);
369 
370     auto menuChild = menuWrapperPattern->GetMenu();
371     CHECK_NULL_VOID(menuChild);
372     auto menuPattern = menuChild->GetPattern<MenuPattern>();
373     CHECK_NULL_VOID(menuPattern);
374     auto previewPosition = menuPattern->GetPreviewOriginOffset();
375 
376     menuWrapperPattern->StopHoverImageToPreviewAnimation();
377     AnimationOption option = AnimationOption();
378     option.SetCurve(CUSTOM_PREVIEW_ANIMATION_CURVE);
379     AnimationUtils::Animate(
380         option, [stackContext, scaleAfter, flexContext, previewPosition]() {
381             CHECK_NULL_VOID(stackContext);
382             stackContext->UpdateTransformScale(VectorF(scaleAfter, scaleAfter));
383 
384             CHECK_NULL_VOID(flexContext);
385             flexContext->UpdatePosition(
386                 OffsetT<Dimension>(Dimension(previewPosition.GetX()), Dimension(previewPosition.GetY())));
387         });
388 
389     ShowPreviewBgDisappearAnimationProc(stackContext, menuTheme, menuWrapperPattern->GetHoverImageStackNode());
390 }
391 
ShowPreviewDisappearAnimation(const RefPtr<MenuWrapperPattern> & menuWrapperPattern)392 void ShowPreviewDisappearAnimation(const RefPtr<MenuWrapperPattern>& menuWrapperPattern)
393 {
394     CHECK_NULL_VOID(menuWrapperPattern);
395     auto previewChild = menuWrapperPattern->GetPreview();
396     CHECK_NULL_VOID(previewChild);
397     ShowPreviewDisappearAnimationProc(menuWrapperPattern, previewChild);
398 
399     CHECK_NULL_VOID(menuWrapperPattern->GetIsShowHoverImage());
400     auto hoverImagePreview = menuWrapperPattern->GetHoverImagePreview();
401     CHECK_NULL_VOID(hoverImagePreview);
402     ShowPreviewDisappearAnimationProc(menuWrapperPattern, hoverImagePreview);
403 
404     auto previewPattern = previewChild->GetPattern<MenuPreviewPattern>();
405     CHECK_NULL_VOID(previewPattern);
406     if (previewPattern->IsHoverImageAnimationPlaying()) {
407         menuWrapperPattern->SetIsStopHoverImageAnimation(true);
408         previewPattern->SetIsHoverImageAnimationPlaying(false);
409     } else {
410         UpdatePreivewVisibleAreaWhenDisappear(menuWrapperPattern->GetHoverImageStackNode(), previewChild);
411     }
412     UpdateHoverImageDisappearScaleAndPosition(menuWrapperPattern, previewPattern);
413 }
414 
UpdateContextMenuDisappearPositionAnimation(const RefPtr<FrameNode> & menu,const NG::OffsetF & offset,float menuScale)415 void UpdateContextMenuDisappearPositionAnimation(const RefPtr<FrameNode>& menu, const NG::OffsetF& offset,
416     float menuScale)
417 {
418     CHECK_NULL_VOID(menu);
419     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
420     CHECK_NULL_VOID(menuWrapperPattern);
421     auto menuChild = menuWrapperPattern->GetMenu();
422     CHECK_NULL_VOID(menuChild);
423     auto menuRenderContext = menuChild->GetRenderContext();
424     CHECK_NULL_VOID(menuRenderContext);
425     auto menuPattern = menuChild->GetPattern<MenuPattern>();
426     CHECK_NULL_VOID(menuPattern);
427     auto menuPosition = menuChild->GetGeometryNode()->GetFrameOffset();
428     menuPosition += offset;
429     menuChild->GetGeometryNode()->SetFrameOffset(menuPosition);
430     menuPattern->SetEndOffset(menuPosition);
431 
432     auto pipelineContext = PipelineContext::GetCurrentContext();
433     CHECK_NULL_VOID(pipelineContext);
434     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
435     CHECK_NULL_VOID(menuTheme);
436 
437     auto scaleAfter = LessNotEqual(menuScale, 0.0) ? 1.0f : menuScale;
438     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
439     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
440     AnimationOption positionOption;
441     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
442     positionOption.SetCurve(motion);
443     AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition, scaleAfter]() {
444         CHECK_NULL_VOID(menuRenderContext);
445         menuRenderContext->UpdatePosition(
446             OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
447         // menuScale default value is 1.0f, only update menu scale with not the default value
448         if (scaleAfter != 1.0f) {
449             menuRenderContext->UpdateTransformScale(VectorF(scaleAfter, scaleAfter));
450         }
451     });
452 }
453 
ContextMenuSwitchDragPreviewScaleAnimationProc(const RefPtr<RenderContext> & dragPreviewContext,const RefPtr<RenderContext> & previewRenderContext,const RefPtr<FrameNode> & previewChild,const NG::OffsetF & offset,int32_t duration)454 void ContextMenuSwitchDragPreviewScaleAnimationProc(const RefPtr<RenderContext>& dragPreviewContext,
455     const RefPtr<RenderContext>& previewRenderContext, const RefPtr<FrameNode>& previewChild,
456     const NG::OffsetF& offset, int32_t duration)
457 {
458     CHECK_NULL_VOID(previewChild);
459     auto previewPattern = previewChild->GetPattern<MenuPreviewPattern>();
460     CHECK_NULL_VOID(previewPattern);
461     CHECK_NULL_VOID(previewPattern->GetIsShowHoverImage());
462 
463     CHECK_NULL_VOID(dragPreviewContext);
464     auto width = dragPreviewContext->GetPaintRectWithTransform().Width();
465     auto height = dragPreviewContext->GetPaintRectWithTransform().Height();
466 
467     CHECK_NULL_VOID(previewRenderContext);
468     auto previewWidth = previewPattern->GetCustomPreviewWidth();
469     auto previewHeight = previewPattern->GetCustomPreviewHeight();
470 
471     // reverse scale
472     float scaleTo = 1.0f;
473     if (previewWidth - width < previewHeight - height) {
474         CHECK_EQUAL_VOID(previewWidth, 0);
475         scaleTo = width / previewWidth;
476     } else {
477         CHECK_EQUAL_VOID(previewHeight, 0);
478         scaleTo = height / previewHeight;
479     }
480     auto scaleAfter = LessNotEqual(scaleTo, 0.0) ? 1.0f : scaleTo;
481     AnimationOption option = AnimationOption();
482     option.SetDuration(duration);
483     option.SetCurve(Curves::FRICTION);
484     AnimationUtils::Animate(
485         option,
486         [previewRenderContext, dragPreviewContext, scaleAfter, offset]() {
487             CHECK_NULL_VOID(previewRenderContext);
488             previewRenderContext->UpdateTransformScale(VectorF(scaleAfter, scaleAfter));
489             previewRenderContext->UpdateTransformTranslate({ offset.GetX(), offset.GetY(), 0.0f });
490 
491             CHECK_NULL_VOID(dragPreviewContext);
492             dragPreviewContext->UpdateTransformTranslate({ offset.GetX(), offset.GetY(), 0.0f });
493         });
494 }
495 
UpdateContextMenuSwitchDragPreviewBefore(const RefPtr<FrameNode> & menu)496 void UpdateContextMenuSwitchDragPreviewBefore(const RefPtr<FrameNode>& menu)
497 {
498     CHECK_NULL_VOID(menu);
499     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
500     CHECK_NULL_VOID(menuWrapperPattern && menuWrapperPattern->GetIsShowHoverImage());
501     auto previewChild = menuWrapperPattern->GetPreview();
502     CHECK_NULL_VOID(previewChild);
503     auto previewPattern = previewChild->GetPattern<MenuPreviewPattern>();
504     CHECK_NULL_VOID(previewPattern);
505 
506     if (previewPattern->IsHoverImageScalePlaying()) {
507         auto previewRenderContext = previewChild->GetRenderContext();
508         CHECK_NULL_VOID(previewRenderContext);
509         previewRenderContext->UpdateOpacity(0.0);
510     }
511 }
512 
ContextMenuSwitchDragPreviewAnimationProc(const RefPtr<FrameNode> & menu,const RefPtr<NG::FrameNode> & dragPreviewNode,const NG::OffsetF & offset)513 void ContextMenuSwitchDragPreviewAnimationProc(const RefPtr<FrameNode>& menu,
514     const RefPtr<NG::FrameNode>& dragPreviewNode, const NG::OffsetF& offset)
515 {
516     CHECK_NULL_VOID(dragPreviewNode && menu);
517     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
518     CHECK_NULL_VOID(menuWrapperPattern && menuWrapperPattern->GetIsShowHoverImage());
519 
520     auto pipelineContext = PipelineContext::GetCurrentContext();
521     CHECK_NULL_VOID(pipelineContext);
522     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
523     CHECK_NULL_VOID(menuTheme);
524     // consistent with the menu disappear duration
525     auto duration = menuTheme->GetDisappearDuration();
526 
527     auto previewChild = menuWrapperPattern->GetPreview();
528     CHECK_NULL_VOID(previewChild);
529     auto previewRenderContext = previewChild->GetRenderContext();
530     CHECK_NULL_VOID(previewRenderContext);
531     auto dragPreviewContext = dragPreviewNode->GetRenderContext();
532     CHECK_NULL_VOID(dragPreviewContext);
533 
534     // update custom preview scale and position
535     ContextMenuSwitchDragPreviewScaleAnimationProc(dragPreviewContext, previewRenderContext, previewChild, offset,
536         duration);
537 
538     // custom preview and drag preview update Opacity
539     CHECK_NULL_VOID(!menuWrapperPattern->GetIsShowHoverImagePreviewStartDrag());
540     menuWrapperPattern->SetIsShowHoverImagePreviewStartDrag(true);
541     auto imageNode = menuWrapperPattern->GetHoverImagePreview();
542     CHECK_NULL_VOID(imageNode);
543     auto imageContext = imageNode->GetRenderContext();
544     CHECK_NULL_VOID(imageContext);
545     imageContext->UpdateOpacity(0.0);
546 
547     previewRenderContext->UpdateOpacity(1.0);
548     dragPreviewContext->UpdateOpacity(0.0);
549     AnimationOption option;
550     option.SetDuration(duration);
551     option.SetCurve(Curves::FRICTION);
552     option.SetOnFinishEvent(
553         [id = Container::CurrentId(), menuWrapperPattern] {
554             ContainerScope scope(id);
555             menuWrapperPattern->SetIsShowHoverImagePreviewStartDrag(false);
556         });
557     AnimationUtils::Animate(
558         option, [previewRenderContext, dragPreviewContext]() mutable {
559             CHECK_NULL_VOID(previewRenderContext);
560             previewRenderContext->UpdateOpacity(0.0);
561 
562             BorderRadiusProperty borderRadius;
563             borderRadius.SetRadius(0.0_vp);
564             previewRenderContext->UpdateBorderRadius(borderRadius);
565 
566             CHECK_NULL_VOID(dragPreviewContext);
567             dragPreviewContext->UpdateOpacity(1.0);
568         },
569         option.GetOnFinishEvent());
570 }
571 
ShowContextMenuDisappearAnimation(AnimationOption & option,const RefPtr<MenuWrapperPattern> & menuWrapperPattern,bool startDrag=false)572 void ShowContextMenuDisappearAnimation(
573     AnimationOption& option, const RefPtr<MenuWrapperPattern>& menuWrapperPattern, bool startDrag = false)
574 {
575     CHECK_NULL_VOID(menuWrapperPattern);
576     auto menuChild = menuWrapperPattern->GetMenu();
577     CHECK_NULL_VOID(menuChild);
578     auto menuRenderContext = menuChild->GetRenderContext();
579     CHECK_NULL_VOID(menuRenderContext);
580     auto menuPattern = menuChild->GetPattern<MenuPattern>();
581     CHECK_NULL_VOID(menuPattern);
582     auto menuPosition = menuPattern->GetEndOffset();
583     menuWrapperPattern->ClearAllSubMenu();
584 
585     auto pipelineContext = PipelineContext::GetCurrentContext();
586     CHECK_NULL_VOID(pipelineContext);
587     auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
588     CHECK_NULL_VOID(menuTheme);
589     if (startDrag) {
590         menuRenderContext->UpdateTransformScale(
591             VectorF(menuTheme->GetMenuDragAnimationScale(), menuTheme->GetMenuDragAnimationScale()));
592     }
593     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
594     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
595     AnimationOption positionOption;
596     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
597     positionOption.SetCurve(motion);
598     AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition]() {
599         CHECK_NULL_VOID(menuRenderContext);
600         menuRenderContext->UpdatePosition(
601             OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
602     });
603 
604     auto disappearDuration = menuTheme->GetDisappearDuration();
605     auto menuAnimationScale = menuTheme->GetMenuAnimationScale();
606     AnimationOption scaleOption;
607     scaleOption.SetCurve(Curves::FAST_OUT_LINEAR_IN);
608     scaleOption.SetDuration(disappearDuration);
609     AnimationUtils::Animate(scaleOption, [menuRenderContext, menuAnimationScale]() {
610         CHECK_NULL_VOID(menuRenderContext);
611         menuRenderContext->UpdateTransformScale({ menuAnimationScale, menuAnimationScale });
612     });
613 
614     option.SetDuration(disappearDuration);
615     option.SetCurve(Curves::FRICTION);
616     AnimationUtils::Animate(
617         option,
618         [menuRenderContext]() {
619             CHECK_NULL_VOID(menuRenderContext);
620             menuRenderContext->UpdateOpacity(0.0);
621         },
622         option.GetOnFinishEvent());
623 }
624 
FireMenuDisappear(AnimationOption & option,const RefPtr<MenuWrapperPattern> & menuWrapperPattern)625 void FireMenuDisappear(AnimationOption& option, const RefPtr<MenuWrapperPattern>& menuWrapperPattern)
626 {
627     CHECK_NULL_VOID(menuWrapperPattern);
628     auto menuNode = menuWrapperPattern->GetMenu();
629     CHECK_NULL_VOID(menuNode);
630     auto menuRenderContext = menuNode->GetRenderContext();
631     CHECK_NULL_VOID(menuRenderContext);
632     MENU_ANIMATION_CURVE->UpdateMinimumAmplitudeRatio(MINIMUM_AMPLITUDE_RATION);
633     option.SetCurve(MENU_ANIMATION_CURVE);
634     AnimationUtils::Animate(option, [menuRenderContext]() {
635         if (menuRenderContext) {
636             menuRenderContext->UpdateTransformScale(VectorF(MENU_ORIGINAL_SCALE, MENU_ORIGINAL_SCALE));
637             menuRenderContext->UpdateOpacity(0.0f);
638         }
639     }, option.GetOnFinishEvent());
640 }
641 
SendPopupAccessibilityPageOpen(const RefPtr<FrameNode> & popupNode)642 void SendPopupAccessibilityPageOpen(const RefPtr<FrameNode>& popupNode)
643 {
644     CHECK_NULL_VOID(popupNode);
645     auto accessibilityProperty = popupNode->GetAccessibilityProperty<BubbleAccessibilityProperty>();
646     CHECK_NULL_VOID(accessibilityProperty);
647     accessibilityProperty->SetShowedState(1);
648     popupNode->OnAccessibilityEvent(
649         AccessibilityEventType::PAGE_OPEN, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
650 }
651 } // namespace
652 
~OverlayManager()653 OverlayManager::~OverlayManager()
654 {
655     TAG_LOGI(AceLogTag::ACE_OVERLAY, "OverlayManager destroyed");
656     popupMap_.clear();
657 }
658 
UpdateContextMenuDisappearPosition(const NG::OffsetF & offset,float menuScale,bool isRedragStart,int32_t menuWrapperId)659 void OverlayManager::UpdateContextMenuDisappearPosition(
660     const NG::OffsetF& offset, float menuScale, bool isRedragStart, int32_t menuWrapperId)
661 {
662     auto pipelineContext = PipelineContext::GetCurrentContext();
663     CHECK_NULL_VOID(pipelineContext);
664     auto overlayManager = pipelineContext->GetOverlayManager();
665     CHECK_NULL_VOID(overlayManager);
666     if (isRedragStart) {
667         overlayManager->ResetContextMenuRestartDragVector();
668     }
669 
670     if (menuMap_.empty()) {
671         return;
672     }
673 
674     RefPtr<FrameNode> menuWrapper = nullptr;
675     for (auto [targetId, node] : menuMap_) {
676         if (node && node->GetId() == menuWrapperId) {
677             menuWrapper = node;
678         }
679     }
680 
681     CHECK_NULL_VOID(menuWrapper && menuWrapper->GetTag() == V2::MENU_WRAPPER_ETS_TAG);
682     overlayManager->UpdateDragMoveVector(offset);
683 
684     if (overlayManager->IsOriginDragMoveVector() || !overlayManager->IsUpdateDragMoveVector()) {
685         return;
686     }
687 
688     UpdateContextMenuDisappearPositionAnimation(menuWrapper, overlayManager->GetUpdateDragMoveVector(), menuScale);
689 }
690 
CalculateMenuPosition(const RefPtr<FrameNode> & menuWrapperNode,const OffsetF & offset)691 OffsetF OverlayManager::CalculateMenuPosition(const RefPtr<FrameNode>& menuWrapperNode, const OffsetF& offset)
692 {
693     CHECK_NULL_RETURN(menuWrapperNode, OffsetF(0.0f, 0.0f));
694     if (IsContextMenuDragHideFinished()) {
695         return OffsetF(0.0f, 0.0f);
696     }
697     UpdateDragMoveVector(offset);
698     if (IsOriginDragMoveVector() || !IsUpdateDragMoveVector()) {
699         return OffsetF(0.0f, 0.0f);
700     }
701 
702     auto menuWrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
703     CHECK_NULL_RETURN(menuWrapperPattern, OffsetF(0.0f, 0.0f));
704     auto menuNode = menuWrapperPattern->GetMenu();
705     CHECK_NULL_RETURN(menuNode, OffsetF(0.0f, 0.0f));
706     auto menuOffset = GetUpdateDragMoveVector();
707     auto menuPattern = menuNode->GetPattern<MenuPattern>();
708     CHECK_NULL_RETURN(menuPattern, OffsetF(0.0f, 0.0f));
709     auto menuGeometryNode = menuNode->GetGeometryNode();
710     CHECK_NULL_RETURN(menuGeometryNode, OffsetF(0.0f, 0.0f));
711     auto menuPosition = menuGeometryNode->GetFrameOffset();
712     menuPosition += menuOffset;
713     menuGeometryNode->SetFrameOffset(menuPosition);
714     menuPattern->SetEndOffset(menuPosition);
715     return menuPosition;
716 }
717 
GetMenuPreviewCenter(NG::OffsetF & offset)718 bool OverlayManager::GetMenuPreviewCenter(NG::OffsetF& offset)
719 {
720     auto rootNode = rootNodeWeak_.Upgrade();
721     CHECK_NULL_RETURN(rootNode, false);
722     for (const auto& child : rootNode->GetChildren()) {
723         auto node = DynamicCast<FrameNode>(child);
724         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
725             auto menuWarpperPattern = node->GetPattern<MenuWrapperPattern>();
726             CHECK_NULL_RETURN(menuWarpperPattern, false);
727             auto previewChild = menuWarpperPattern->GetPreview();
728             CHECK_NULL_RETURN(previewChild, false);
729             auto geometryNode = previewChild->GetGeometryNode();
730             if (geometryNode && geometryNode->GetFrameRect().IsEmpty()) {
731                 return false;
732             }
733             auto previewOffset = previewChild->GetPaintRectCenter();
734             offset.SetX(previewOffset.GetX());
735             offset.SetY(previewOffset.GetY());
736             return true;
737         }
738     }
739     return false;
740 }
741 
ContextMenuSwitchDragPreviewAnimation(const RefPtr<NG::FrameNode> & dragPreviewNode,const NG::OffsetF & offset)742 void OverlayManager::ContextMenuSwitchDragPreviewAnimation(const RefPtr<NG::FrameNode>& dragPreviewNode,
743     const NG::OffsetF& offset)
744 {
745     CHECK_NULL_VOID(dragPreviewNode);
746     if (menuMap_.empty()) {
747         return;
748     }
749     auto rootNode = rootNodeWeak_.Upgrade();
750     for (const auto& child : rootNode->GetChildren()) {
751         auto node = DynamicCast<FrameNode>(child);
752         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
753             UpdateContextMenuSwitchDragPreviewBefore(node);
754             ContextMenuSwitchDragPreviewAnimationProc(node, dragPreviewNode, offset);
755         }
756     }
757 }
758 
PostDialogFinishEvent(const WeakPtr<FrameNode> & nodeWk)759 void OverlayManager::PostDialogFinishEvent(const WeakPtr<FrameNode>& nodeWk)
760 {
761     TAG_LOGI(AceLogTag::ACE_DIALOG, "post dialog finish event enter");
762     auto context = PipelineContext::GetCurrentContext();
763     CHECK_NULL_VOID(context);
764     auto taskExecutor = context->GetTaskExecutor();
765     CHECK_NULL_VOID(taskExecutor);
766     // animation finish event should be posted to UI thread.
767     taskExecutor->PostTask(
768         [weak = WeakClaim(this), nodeWk, id = Container::CurrentId()]() {
769             ContainerScope scope(id);
770             auto overlayManager = weak.Upgrade();
771             auto node = nodeWk.Upgrade();
772             CHECK_NULL_VOID(overlayManager && node);
773             SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_NONE };
774             node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
775             overlayManager->OnDialogCloseEvent(node);
776         },
777         TaskExecutor::TaskType::UI, "ArkUIOverlayDialogCloseEvent");
778 }
779 
FireDialogAutoSave(const RefPtr<FrameNode> & ContainerNode)780 void OverlayManager::FireDialogAutoSave(const RefPtr<FrameNode>& ContainerNode)
781 {
782     TAG_LOGD(AceLogTag::ACE_OVERLAY, "fire dialog auto save enter");
783     CHECK_NULL_VOID(ContainerNode);
784     if (!ContainerNode->NeedRequestAutoSave()) {
785         return;
786     }
787     auto container = Container::Current();
788     auto currentId = Container::CurrentId();
789     CHECK_NULL_VOID(container);
790     if (container->IsSubContainer()) {
791         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
792     }
793     container->RequestAutoSave(ContainerNode, nullptr, nullptr, true, currentId);
794 }
795 
OnDialogCloseEvent(const RefPtr<FrameNode> & node)796 void OverlayManager::OnDialogCloseEvent(const RefPtr<FrameNode>& node)
797 {
798     CHECK_NULL_VOID(node);
799     TAG_LOGI(AceLogTag::ACE_DIALOG, "on dialog/%{public}d close event enter", node->GetId());
800 
801     BlurOverlayNode(node);
802     FireDialogAutoSave(node);
803 
804     auto dialogPattern = node->GetPattern<DialogPattern>();
805     CHECK_NULL_VOID(dialogPattern);
806     auto option = dialogPattern->GetCloseAnimation().value_or(AnimationOption());
807     auto onFinish = option.GetOnFinishEvent();
808 
809     auto dialogLayoutProp = dialogPattern->GetLayoutProperty<DialogLayoutProperty>();
810     bool isShowInSubWindow = false;
811     if (dialogLayoutProp) {
812         isShowInSubWindow = dialogLayoutProp->GetShowInSubWindowValue(false);
813     }
814     if (onFinish != nullptr) {
815         onFinish();
816     }
817 
818     auto container = Container::Current();
819     auto currentId = Container::CurrentId();
820     CHECK_NULL_VOID(container);
821     if (isShowInSubWindow && !container->IsSubContainer()) {
822         currentId = SubwindowManager::GetInstance()->GetSubContainerId(currentId);
823     }
824 
825     ContainerScope scope(currentId);
826     auto root = node->GetParent();
827     CHECK_NULL_VOID(root);
828     node->OnAccessibilityEvent(
829         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
830     DeleteDialogHotAreas(node);
831     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove DialogNode/%{public}d from RootNode/%{public}d",
832         node->GetId(), root->GetId());
833     root->RemoveChild(node, node->GetIsUseTransitionAnimator());
834     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
835 
836     if (container->IsDialogContainer() || isShowInSubWindow) {
837         SubwindowManager::GetInstance()->HideSubWindowNG();
838     }
839 }
840 
OpenDialogAnimation(const RefPtr<FrameNode> & node)841 void OverlayManager::OpenDialogAnimation(const RefPtr<FrameNode>& node)
842 {
843     TAG_LOGD(AceLogTag::ACE_OVERLAY, "open dialog animation");
844     CHECK_NULL_VOID(node);
845     auto pipeline = PipelineContext::GetCurrentContext();
846     CHECK_NULL_VOID(pipeline);
847     auto theme = pipeline->GetTheme<DialogTheme>();
848     CHECK_NULL_VOID(theme);
849     auto root = rootNodeWeak_.Upgrade();
850     auto dialogPattern = node->GetPattern<DialogPattern>();
851     dialogPattern->CallDialogWillAppearCallback();
852     auto container = Container::Current();
853     if (container && container->IsScenceBoardWindow()) {
854         root = dialogPattern->GetDialogProperties().windowScene.Upgrade();
855     }
856     CHECK_NULL_VOID(root);
857     MountToParentWithService(root, node);
858     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
859     BlurLowerNode(node);
860 
861     AnimationOption option;
862     // default opacity animation params
863     option.SetCurve(Curves::SHARP);
864     option.SetDuration(theme->GetOpacityAnimationDurIn());
865     option.SetFillMode(FillMode::FORWARDS);
866     option = dialogPattern->GetOpenAnimation().value_or(option);
867     option.SetIteration(1);
868     option.SetAnimationDirection(AnimationDirection::NORMAL);
869     auto onFinish = option.GetOnFinishEvent();
870     option.SetOnFinishEvent(
871         [weak = WeakClaim(this), nodeWK = WeakPtr<FrameNode>(node), onFinish] {
872             if (onFinish) {
873                 onFinish();
874             }
875             auto overlayManager = weak.Upgrade();
876             auto node = nodeWK.Upgrade();
877             CHECK_NULL_VOID(overlayManager && node);
878             overlayManager->FocusOverlayNode(node);
879             auto dialogPattern = node->GetPattern<DialogPattern>();
880             dialogPattern->CallDialogDidAppearCallback();
881         });
882     auto ctx = node->GetRenderContext();
883     option.SetFinishCallbackType(dialogPattern->GetOpenAnimation().has_value()
884                             ? dialogPattern->GetOpenAnimation().value().GetFinishCallbackType()
885                             : FinishCallbackType::REMOVED);
886     CHECK_NULL_VOID(ctx);
887     ctx->OpacityAnimation(option, theme->GetOpacityStart(), theme->GetOpacityEnd());
888     // scale animation on dialog content
889     auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
890     CHECK_NULL_VOID(contentNode);
891     ctx = contentNode->GetRenderContext();
892     CHECK_NULL_VOID(ctx);
893     option.SetOnFinishEvent(nullptr);
894     option.SetCurve(SHOW_SCALE_ANIMATION_CURVE);
895     option.SetDuration(dialogPattern->GetOpenAnimation().has_value()
896                            ? dialogPattern->GetOpenAnimation().value().GetDuration()
897                            : theme->GetAnimationDurationIn());
898     ctx->ScaleAnimation(option, theme->GetScaleStart(), theme->GetScaleEnd());
899     node->OnAccessibilityEvent(
900         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
901 }
902 
CloseDialogAnimation(const RefPtr<FrameNode> & node)903 void OverlayManager::CloseDialogAnimation(const RefPtr<FrameNode>& node)
904 {
905     TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog animation");
906     CHECK_NULL_VOID(node);
907     auto pipeline = PipelineContext::GetCurrentContext();
908     CHECK_NULL_VOID(pipeline);
909     auto theme = pipeline->GetTheme<DialogTheme>();
910     CHECK_NULL_VOID(theme);
911     SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_KEYBOARD };
912     node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
913 
914     // default opacity animation params
915     AnimationOption option;
916     option.SetFillMode(FillMode::FORWARDS);
917     option.SetCurve(Curves::SHARP);
918     option.SetDuration(theme->GetAnimationDurationOut());
919     // get customized animation params
920     auto dialogPattern = node->GetPattern<DialogPattern>();
921     dialogPattern->CallDialogWillDisappearCallback();
922     option = dialogPattern->GetCloseAnimation().value_or(option);
923     option.SetIteration(1);
924     option.SetAnimationDirection(AnimationDirection::NORMAL);
925     option.SetOnFinishEvent(
926         [weak = WeakClaim(this), nodeWk = WeakPtr<FrameNode>(node), dialogPattern, id = Container::CurrentId()] {
927             ContainerScope scope(id);
928             auto overlayManager = weak.Upgrade();
929             CHECK_NULL_VOID(overlayManager);
930             overlayManager->PostDialogFinishEvent(nodeWk);
931             dialogPattern->CallDialogDidDisappearCallback();
932         });
933     auto ctx = node->GetRenderContext();
934     if (!ctx) {
935         TAG_LOGW(AceLogTag::ACE_OVERLAY, "not find render context when closing dialog");
936         return;
937     }
938     option.SetFinishCallbackType(dialogPattern->GetOpenAnimation().has_value()
939                             ? dialogPattern->GetOpenAnimation().value().GetFinishCallbackType()
940                             : FinishCallbackType::REMOVED);
941     ctx->OpacityAnimation(option, theme->GetOpacityEnd(), theme->GetOpacityStart());
942 
943     // scale animation
944     auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
945     CHECK_NULL_VOID(contentNode);
946     ctx = contentNode->GetRenderContext();
947     CHECK_NULL_VOID(ctx);
948     option.SetOnFinishEvent(nullptr);
949     option.SetCurve(Curves::FRICTION);
950     ctx->ScaleAnimation(option, theme->GetScaleEnd(), theme->GetScaleStart());
951     // start animation immediately
952     pipeline->RequestFrame();
953 }
954 
SetDialogTransitionEffect(const RefPtr<FrameNode> & node)955 void OverlayManager::SetDialogTransitionEffect(const RefPtr<FrameNode>& node)
956 {
957     TAG_LOGD(AceLogTag::ACE_OVERLAY, "set dialog transition");
958     CHECK_NULL_VOID(node);
959     auto root = rootNodeWeak_.Upgrade();
960     auto dialogPattern = node->GetPattern<DialogPattern>();
961     dialogPattern->CallDialogWillAppearCallback();
962 
963     auto layoutProperty = node->GetLayoutProperty();
964     layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true);
965 
966     auto ctx = node->GetRenderContext();
967     CHECK_NULL_VOID(ctx);
968     ctx->SetTransitionInCallback(
969         [weak = WeakClaim(this), nodeWK = WeakPtr<FrameNode>(node)] {
970             auto overlayManager = weak.Upgrade();
971             auto node = nodeWK.Upgrade();
972             CHECK_NULL_VOID(overlayManager && node);
973             overlayManager->FocusOverlayNode(node);
974             auto dialogPattern = node->GetPattern<DialogPattern>();
975             dialogPattern->CallDialogDidAppearCallback();
976         }
977     );
978 
979     auto container = Container::Current();
980     if (container && container->IsScenceBoardWindow()) {
981         root = dialogPattern->GetDialogProperties().windowScene.Upgrade();
982     }
983 
984     CHECK_NULL_VOID(root);
985     MountToParentWithService(root, node);
986     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
987     BlurLowerNode(node);
988     node->OnAccessibilityEvent(
989         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
990 }
991 
CloseDialogMatchTransition(const RefPtr<FrameNode> & node)992 void OverlayManager::CloseDialogMatchTransition(const RefPtr<FrameNode>& node)
993 {
994     TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog match transition");
995     CHECK_NULL_VOID(node);
996     SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_KEYBOARD };
997     node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
998     auto dialogPattern = node->GetPattern<DialogPattern>();
999     dialogPattern->CallDialogWillDisappearCallback();
1000 
1001     auto ctx = node->GetRenderContext();
1002     if (!ctx) {
1003         TAG_LOGW(AceLogTag::ACE_OVERLAY, "not find render context when closing dialog");
1004         return;
1005     }
1006     auto layoutProperty = node->GetLayoutProperty();
1007     layoutProperty->UpdateVisibility(VisibleType::INVISIBLE, true);
1008     if (ctx->HasDisappearTransition()) {
1009         ctx->SetTransitionOutCallback(
1010             [weak = WeakClaim(this), nodeWk = WeakPtr<FrameNode>(node), id = Container::CurrentId()] {
1011                 ContainerScope scope(id);
1012                 auto overlayManager = weak.Upgrade();
1013                 CHECK_NULL_VOID(overlayManager);
1014                 overlayManager->PostDialogFinishEvent(nodeWk);
1015                 auto node = nodeWk.Upgrade();
1016                 CHECK_NULL_VOID(node);
1017                 auto dialogPattern = node->GetPattern<DialogPattern>();
1018                 dialogPattern->CallDialogDidDisappearCallback();
1019         });
1020     } else {
1021         auto id = Container::CurrentId();
1022         ContainerScope scope(id);
1023         auto overlayManager = WeakClaim(this).Upgrade();
1024         CHECK_NULL_VOID(overlayManager);
1025         auto nodeWk = WeakPtr<FrameNode>(node);
1026         overlayManager->PostDialogFinishEvent(nodeWk);
1027         dialogPattern->CallDialogDidDisappearCallback();
1028     }
1029 }
1030 
SetContainerButtonEnable(bool isEnabled)1031 void OverlayManager::SetContainerButtonEnable(bool isEnabled)
1032 {
1033     auto pipeline = PipelineContext::GetCurrentContext();
1034     CHECK_NULL_VOID(pipeline);
1035     pipeline->SetCloseButtonStatus(isEnabled);
1036 }
1037 
UpdateMenuVisibility(const RefPtr<FrameNode> & menu)1038 void OverlayManager::UpdateMenuVisibility(const RefPtr<FrameNode>& menu)
1039 {
1040     auto layoutProperty = menu->GetLayoutProperty();
1041     CHECK_NULL_VOID(layoutProperty);
1042     layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true);
1043 }
1044 
OnShowMenuAnimationFinished(const WeakPtr<FrameNode> menuWK,const WeakPtr<OverlayManager> weak,int32_t instanceId)1045 void OverlayManager::OnShowMenuAnimationFinished(const WeakPtr<FrameNode> menuWK, const WeakPtr<OverlayManager> weak,
1046     int32_t instanceId)
1047 {
1048     auto menu = menuWK.Upgrade();
1049     auto overlayManager = weak.Upgrade();
1050     CHECK_NULL_VOID(menu && overlayManager);
1051     ContainerScope scope(instanceId);
1052     auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
1053     CHECK_NULL_VOID(menuNode);
1054     auto menuLayoutProp = menuNode->GetLayoutProperty<MenuLayoutProperty>();
1055     CHECK_NULL_VOID(menuLayoutProp);
1056     if (!menuLayoutProp->GetIsRectInTargetValue(false)) {
1057         overlayManager->FocusOverlayNode(menu);
1058     }
1059     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1060     menuWrapperPattern->CallMenuAppearCallback();
1061     menuWrapperPattern->SetMenuStatus(MenuStatus::SHOW);
1062 }
1063 
ShowMenuAnimation(const RefPtr<FrameNode> & menu)1064 void OverlayManager::ShowMenuAnimation(const RefPtr<FrameNode>& menu)
1065 {
1066     BlurLowerNode(menu);
1067     auto wrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1068     CHECK_NULL_VOID(wrapperPattern);
1069     wrapperPattern->CallMenuAboutToAppearCallback();
1070     wrapperPattern->SetMenuStatus(MenuStatus::ON_SHOW_ANIMATION);
1071     SetIsMenuShow(true);
1072     if (wrapperPattern->HasTransitionEffect()) {
1073         UpdateMenuVisibility(menu);
1074         auto renderContext = menu->GetRenderContext();
1075         CHECK_NULL_VOID(renderContext);
1076         renderContext->SetTransitionInCallback(
1077             [weak = WeakClaim(this), menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId()] {
1078                 auto overlayManager = weak.Upgrade();
1079                 CHECK_NULL_VOID(overlayManager);
1080                 overlayManager->OnShowMenuAnimationFinished(menuWK, weak, id);
1081                 overlayManager->SendToAccessibility(menuWK, true);
1082             });
1083         return;
1084     }
1085     AnimationOption option;
1086     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
1087     option.SetDuration(MENU_ANIMATION_DURATION);
1088     option.SetFillMode(FillMode::FORWARDS);
1089     option.SetOnFinishEvent(
1090         [weak = WeakClaim(this), menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId()] {
1091             auto overlayManager = weak.Upgrade();
1092             CHECK_NULL_VOID(overlayManager);
1093             overlayManager->OnShowMenuAnimationFinished(menuWK, weak, id);
1094             overlayManager->SendToAccessibility(menuWK, true);
1095         });
1096     if (wrapperPattern->GetPreviewMode() == MenuPreviewMode::CUSTOM) {
1097         auto pipelineContext = PipelineContext::GetCurrentContext();
1098         CHECK_NULL_VOID(pipelineContext);
1099         auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
1100         CHECK_NULL_VOID(menuTheme);
1101         option.SetDuration(menuTheme->GetContextMenuAppearDuration());
1102         auto previewChild = wrapperPattern->GetPreview();
1103         if (previewChild) {
1104             auto previewPattern = AceType::DynamicCast<MenuPreviewPattern>(previewChild->GetPattern());
1105             if (previewPattern) {
1106                 previewPattern->SetFirstShow();
1107             }
1108         }
1109     }
1110     wrapperPattern->SetAniamtinOption(option);
1111     SetPatternFirstShow(menu);
1112 }
1113 
SendToAccessibility(const WeakPtr<FrameNode> node,bool isShow)1114 void OverlayManager::SendToAccessibility(const WeakPtr<FrameNode> node, bool isShow)
1115 {
1116     auto menuWrapper = node.Upgrade();
1117     CHECK_NULL_VOID(menuWrapper);
1118     auto wrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
1119     CHECK_NULL_VOID(wrapperPattern);
1120     auto menu = wrapperPattern->GetMenu();
1121     CHECK_NULL_VOID(menu);
1122     auto accessibilityProperty = menu->GetAccessibilityProperty<MenuAccessibilityProperty>();
1123     CHECK_NULL_VOID(accessibilityProperty);
1124     accessibilityProperty->SetAccessibilityIsShow(isShow);
1125     if (isShow) {
1126         menu->OnAccessibilityEvent(AccessibilityEventType::PAGE_OPEN,
1127             WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1128         TAG_LOGI(AceLogTag::ACE_OVERLAY, "Send event to %{public}d",
1129             static_cast<int32_t>(AccessibilityEventType::PAGE_OPEN));
1130     } else {
1131         menu->OnAccessibilityEvent(AccessibilityEventType::PAGE_CLOSE,
1132             WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1133         TAG_LOGI(AceLogTag::ACE_OVERLAY, "Send event to %{public}d",
1134             static_cast<int32_t>(AccessibilityEventType::PAGE_CLOSE));
1135     }
1136 }
1137 
SetPatternFirstShow(const RefPtr<FrameNode> & menu)1138 void OverlayManager::SetPatternFirstShow(const RefPtr<FrameNode>& menu)
1139 {
1140     auto wrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1141     CHECK_NULL_VOID(wrapperPattern);
1142     wrapperPattern->SetFirstShow();
1143     auto menuChild = wrapperPattern->GetMenu();
1144     CHECK_NULL_VOID(menuChild);
1145     auto menuPattern = AceType::DynamicCast<MenuPattern>(menuChild->GetPattern());
1146     CHECK_NULL_VOID(menuPattern);
1147     menuPattern->SetFirstShow();
1148     menuPattern->SetMenuShow();
1149 }
1150 
OnPopMenuAnimationFinished(const WeakPtr<FrameNode> menuWK,const WeakPtr<UINode> rootWeak,const WeakPtr<OverlayManager> weak,int32_t instanceId)1151 void OverlayManager::OnPopMenuAnimationFinished(const WeakPtr<FrameNode> menuWK, const WeakPtr<UINode> rootWeak,
1152     const WeakPtr<OverlayManager> weak, int32_t instanceId)
1153 {
1154     TAG_LOGI(AceLogTag::ACE_OVERLAY, "close menu animation finished");
1155     auto menu = menuWK.Upgrade();
1156     CHECK_NULL_VOID(menu);
1157     auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
1158     CHECK_NULL_VOID(menuNode);
1159     auto eventHub = menuNode->GetEventHub<EventHub>();
1160     CHECK_NULL_VOID(eventHub);
1161     eventHub->SetEnabledInternal(true);
1162     auto menuPattern = menuNode->GetPattern<MenuPattern>();
1163     CHECK_NULL_VOID(menuPattern);
1164     auto root = rootWeak.Upgrade();
1165     auto overlayManager = weak.Upgrade();
1166     CHECK_NULL_VOID(overlayManager);
1167 
1168     overlayManager->SetContextMenuDragHideFinished(true);
1169     DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LANDING_FINISHED);
1170     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1171     menuWrapperPattern->CallMenuDisappearCallback();
1172     menuWrapperPattern->SetMenuStatus(MenuStatus::HIDE);
1173     auto mainPipeline = PipelineContext::GetMainPipelineContext();
1174     if (mainPipeline && menuWrapperPattern->GetMenuDisappearCallback()) {
1175         ContainerScope scope(mainPipeline->GetInstanceId());
1176         mainPipeline->FlushPipelineImmediately();
1177     }
1178     // clear contextMenu then return
1179     auto pipeline = PipelineBase::GetCurrentContext();
1180     CHECK_NULL_VOID(pipeline);
1181     auto theme = pipeline->GetTheme<SelectTheme>();
1182     CHECK_NULL_VOID(theme);
1183     auto expandDisplay = theme->GetExpandDisplay();
1184     auto menuLayoutProp = menuPattern->GetLayoutProperty<MenuLayoutProperty>();
1185     CHECK_NULL_VOID(menuLayoutProp);
1186     bool isShowInSubWindow = menuLayoutProp->GetShowInSubWindowValue(true);
1187     auto targetId = menuWrapperPattern->GetTargetId();
1188     overlayManager->EraseMenuInfo(targetId);
1189     if (((menuWrapperPattern && menuWrapperPattern->IsContextMenu()) || (isShowInSubWindow && expandDisplay)) &&
1190         (menuPattern->GetTargetTag() != V2::SELECT_ETS_TAG)) {
1191         SubwindowManager::GetInstance()->ClearMenuNG(instanceId, menuWrapperPattern->GetTargetId());
1192         overlayManager->ResetContextMenuDragHideFinished();
1193         overlayManager->SetIsMenuShow(false);
1194         return;
1195     }
1196     overlayManager->RemoveMenuNotInSubWindow(menuWK, rootWeak, weak);
1197     overlayManager->SetIsMenuShow(false);
1198 }
1199 
PopMenuAnimation(const RefPtr<FrameNode> & menu,bool showPreviewAnimation,bool startDrag)1200 void OverlayManager::PopMenuAnimation(const RefPtr<FrameNode>& menu, bool showPreviewAnimation, bool startDrag)
1201 {
1202     TAG_LOGI(AceLogTag::ACE_OVERLAY, "pop menu animation enter");
1203     CHECK_NULL_VOID(menu);
1204     auto wrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1205     CHECK_NULL_VOID(wrapperPattern);
1206 
1207     if (wrapperPattern->GetMenuStatus() == MenuStatus::ON_HIDE_ANIMATION) {
1208         return;
1209     }
1210 
1211     ResetLowerNodeFocusable(menu);
1212     ResetContextMenuDragHideFinished();
1213     RemoveMenuBadgeNode(menu);
1214 
1215     auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
1216     CHECK_NULL_VOID(menuNode);
1217     auto eventHub = menuNode->GetEventHub<EventHub>();
1218     CHECK_NULL_VOID(eventHub);
1219     eventHub->SetEnabledInternal(false);
1220 
1221     wrapperPattern->CallMenuAboutToDisappearCallback();
1222     wrapperPattern->SetMenuStatus(MenuStatus::ON_HIDE_ANIMATION);
1223     if (wrapperPattern->HasTransitionEffect() || wrapperPattern->HasFoldModeChangedTransition()) {
1224         if (wrapperPattern->GetPreviewMode() != MenuPreviewMode::NONE) {
1225             ShowPreviewDisappearAnimation(wrapperPattern);
1226         }
1227         auto layoutProperty = menu->GetLayoutProperty();
1228         CHECK_NULL_VOID(layoutProperty);
1229         layoutProperty->UpdateVisibility(VisibleType::INVISIBLE, true);
1230         auto renderContext = menu->GetRenderContext();
1231         CHECK_NULL_VOID(renderContext);
1232         if (wrapperPattern->HasFoldModeChangedTransition()) {
1233             TAG_LOGI(AceLogTag::ACE_OVERLAY, "Close menu when foldMode is changed, disappear transiton is %{public}d",
1234                 renderContext->HasDisappearTransition());
1235         }
1236 
1237         if (renderContext->HasDisappearTransition()) {
1238             renderContext->SetTransitionOutCallback(
1239                 [rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
1240                                     weak = WeakClaim(this)] {
1241                     ContainerScope scope(id);
1242                     auto overlayManager = weak.Upgrade();
1243                     CHECK_NULL_VOID(overlayManager);
1244                     overlayManager->SendToAccessibility(menuWK, false);
1245                     overlayManager->OnPopMenuAnimationFinished(menuWK, rootWeak, weak, id);
1246                 });
1247         } else {
1248             auto context = PipelineContext::GetCurrentContext();
1249             CHECK_NULL_VOID(context);
1250             auto taskExecutor = context->GetTaskExecutor();
1251             CHECK_NULL_VOID(taskExecutor);
1252             taskExecutor->PostTask(
1253                 [rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
1254                     weak = WeakClaim(this)] {
1255                     ContainerScope scope(id);
1256                     auto overlayManager = weak.Upgrade();
1257                     CHECK_NULL_VOID(overlayManager);
1258                     overlayManager->SendToAccessibility(menuWK, false);
1259                     overlayManager->OnPopMenuAnimationFinished(menuWK, rootWeak, weak, id);
1260                 },
1261                 TaskExecutor::TaskType::UI, "ArkUIOverlayPopMenuAnimation");
1262         }
1263         return;
1264     }
1265 
1266     AnimationOption option;
1267     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
1268     option.SetDuration(MENU_ANIMATION_DURATION);
1269     option.SetFillMode(FillMode::FORWARDS);
1270     if (!startDrag) {
1271         DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LANDING_STARTED);
1272     }
1273     option.SetOnFinishEvent([rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
1274                                 weak = WeakClaim(this)] {
1275         ContainerScope scope(id);
1276         auto overlayManager = weak.Upgrade();
1277         CHECK_NULL_VOID(overlayManager);
1278         overlayManager->SendToAccessibility(menuWK, false);
1279         overlayManager->OnPopMenuAnimationFinished(menuWK, rootWeak, weak, id);
1280     });
1281     ShowMenuClearAnimation(menu, option, showPreviewAnimation, startDrag);
1282 }
1283 
ClearMenuAnimation(const RefPtr<FrameNode> & menu,bool showPreviewAnimation,bool startDrag)1284 void OverlayManager::ClearMenuAnimation(const RefPtr<FrameNode>& menu, bool showPreviewAnimation, bool startDrag)
1285 {
1286     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear menu animation enter");
1287     ResetLowerNodeFocusable(menu);
1288     RemoveMenuBadgeNode(menu);
1289     AnimationOption option;
1290     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
1291     option.SetDuration(MENU_ANIMATION_DURATION);
1292     option.SetFillMode(FillMode::FORWARDS);
1293     option.SetOnFinishEvent([rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
1294                                 weak = WeakClaim(this)] {
1295         auto menu = menuWK.Upgrade();
1296         auto root = rootWeak.Upgrade();
1297         auto overlayManager = weak.Upgrade();
1298         CHECK_NULL_VOID(menu && overlayManager);
1299         ContainerScope scope(id);
1300         auto container = Container::Current();
1301         if (container && container->IsScenceBoardWindow()) {
1302             root = overlayManager->FindWindowScene(menu);
1303         }
1304         CHECK_NULL_VOID(root);
1305         auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1306         // clear contextMenu then return
1307         if ((menuWrapperPattern && menuWrapperPattern->IsContextMenu())) {
1308             return;
1309         }
1310         overlayManager->BlurOverlayNode(menu);
1311         root->RemoveChild(menu);
1312         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1313     });
1314     ShowMenuClearAnimation(menu, option, showPreviewAnimation, startDrag);
1315 }
1316 
ShowMenuClearAnimation(const RefPtr<FrameNode> & menuWrapper,AnimationOption & option,bool showPreviewAnimation,bool startDrag)1317 void OverlayManager::ShowMenuClearAnimation(const RefPtr<FrameNode>& menuWrapper, AnimationOption& option,
1318     bool showPreviewAnimation, bool startDrag)
1319 {
1320     TAG_LOGI(AceLogTag::ACE_OVERLAY, "show menuWrapper clear animation enter");
1321     auto context = menuWrapper->GetRenderContext();
1322     CHECK_NULL_VOID(context);
1323     auto pipeline = PipelineBase::GetCurrentContext();
1324     CHECK_NULL_VOID(pipeline);
1325     auto menuWrapperPattern = menuWrapper->GetPattern<MenuWrapperPattern>();
1326     CHECK_NULL_VOID(menuWrapperPattern);
1327     auto menuAnimationOffset = menuWrapperPattern->GetAnimationOffset();
1328     auto outterMenu = menuWrapperPattern->GetMenu();
1329     CHECK_NULL_VOID(outterMenu);
1330     auto outterMenuPattern = outterMenu->GetPattern<MenuPattern>();
1331     CHECK_NULL_VOID(outterMenuPattern);
1332     bool isShow = outterMenuPattern->GetDisappearAnimation();
1333     bool isPreviewModeNone = menuWrapperPattern->GetPreviewMode() == MenuPreviewMode::NONE;
1334     if (!isPreviewModeNone
1335         || (isPreviewModeNone && IsContextMenuBindedOnOrigNode() && !showPreviewAnimation && startDrag)) {
1336         if (!showPreviewAnimation) {
1337             CleanPreviewInSubWindow();
1338         } else {
1339             ShowPreviewDisappearAnimation(menuWrapperPattern);
1340         }
1341         ShowContextMenuDisappearAnimation(option, menuWrapperPattern, startDrag);
1342     } else if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) && isShow) {
1343         FireMenuDisappear(option, menuWrapperPattern);
1344     } else {
1345         AnimationUtils::Animate(
1346             option,
1347             [context, menuAnimationOffset]() {
1348                 context->UpdateOpacity(0.0);
1349                 context->UpdateOffset(menuAnimationOffset);
1350             },
1351             option.GetOnFinishEvent());
1352 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1353         auto* transactionProxy = Rosen::RSTransactionProxy::GetInstance();
1354         if (transactionProxy != nullptr) {
1355             transactionProxy->FlushImplicitTransaction();
1356         }
1357 #endif
1358     }
1359     // start animation immediately
1360     pipeline->RequestFrame();
1361 }
1362 
1363 // check if there is a bound menu on the current floating node on the main window
IsContextMenuBindedOnOrigNode()1364 bool OverlayManager::IsContextMenuBindedOnOrigNode()
1365 {
1366     auto mainPipeline = PipelineContext::GetMainPipelineContext();
1367     CHECK_NULL_RETURN(mainPipeline, false);
1368     auto dragDropManager = mainPipeline->GetDragDropManager();
1369     CHECK_NULL_RETURN(dragDropManager, false);
1370     auto draggingNode = dragDropManager->GetPrepareDragFrameNode().Upgrade();
1371     CHECK_NULL_RETURN(draggingNode, false);
1372     auto eventHub = draggingNode->GetEventHub<EventHub>();
1373     CHECK_NULL_RETURN(eventHub, false);
1374     auto frameNode = eventHub->GetFrameNode();
1375     CHECK_NULL_RETURN(frameNode, false);
1376     auto focusHub = frameNode->GetFocusHub();
1377     CHECK_NULL_RETURN(focusHub, false);
1378     return focusHub->FindContextMenuOnKeyEvent(OnKeyEventType::CONTEXT_MENU);
1379 }
1380 
ShowToast(const NG::ToastInfo & toastInfo)1381 void OverlayManager::ShowToast(const NG::ToastInfo& toastInfo)
1382 {
1383     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show toast enter");
1384     auto context = PipelineContext::GetCurrentContext();
1385     CHECK_NULL_VOID(context);
1386     auto rootNode = context->GetRootElement();
1387     CHECK_NULL_VOID(rootNode);
1388 
1389     // only one toast
1390     for (auto [id, toastNodeWeak] : toastMap_) {
1391         rootNode->RemoveChild(toastNodeWeak.Upgrade());
1392     }
1393     toastMap_.clear();
1394     auto toastNode = ToastView::CreateToastNode(toastInfo);
1395     CHECK_NULL_VOID(toastNode);
1396     auto toastId = toastNode->GetId();
1397     // mount to parent
1398     TAG_LOGD(AceLogTag::ACE_OVERLAY, "toast mount to root");
1399     toastNode->MountToParent(rootNode);
1400     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1401     toastMap_[toastId] = toastNode;
1402     OpenToastAnimation(toastNode, toastInfo.duration);
1403     if (toastInfo.showMode == NG::ToastShowMode::DEFAULT) {
1404         TAG_LOGD(AceLogTag::ACE_OVERLAY, "show toast DEFAULT");
1405     } else if (toastInfo.showMode == NG::ToastShowMode::TOP_MOST) {
1406         TAG_LOGD(AceLogTag::ACE_OVERLAY, "show toast TOP_MOST");
1407     } else if (toastInfo.showMode == NG::ToastShowMode::SYSTEM_TOP_MOST) {
1408         TAG_LOGD(AceLogTag::ACE_OVERLAY, "show toast SYSTEM_TOP_MOST");
1409     }
1410 }
1411 
OpenToastAnimation(const RefPtr<FrameNode> & toastNode,int32_t duration)1412 void OverlayManager::OpenToastAnimation(const RefPtr<FrameNode>& toastNode, int32_t duration)
1413 {
1414     TAG_LOGD(AceLogTag::ACE_OVERLAY, "open toast animation enter");
1415     auto toastId = toastNode->GetId();
1416     AnimationOption option;
1417     auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
1418     option.SetCurve(curve);
1419     option.SetDuration(TOAST_ANIMATION_DURATION);
1420     option.SetFillMode(FillMode::FORWARDS);
1421     duration = std::max(duration, AceApplicationInfo::GetInstance().GetBarrierfreeDuration());
1422     continuousTask_.Reset([weak = WeakClaim(this), toastId, duration, id = Container::CurrentId()]() {
1423         auto overlayManager = weak.Upgrade();
1424         CHECK_NULL_VOID(overlayManager);
1425         ContainerScope scope(id);
1426         overlayManager->PopToast(toastId);
1427     });
1428     option.SetOnFinishEvent([continuousTask = continuousTask_, duration, id = Container::CurrentId()] {
1429         ContainerScope scope(id);
1430         auto context = PipelineContext::GetCurrentContext();
1431         CHECK_NULL_VOID(context);
1432         auto taskExecutor = context->GetTaskExecutor();
1433         CHECK_NULL_VOID(taskExecutor);
1434         taskExecutor->PostDelayedTask(
1435             continuousTask, TaskExecutor::TaskType::UI, duration, "ArkUIOverlayContinuousPopToast");
1436     });
1437     auto ctx = toastNode->GetRenderContext();
1438     CHECK_NULL_VOID(ctx);
1439     ctx->UpdateOpacity(0.0);
1440     ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
1441     AnimationUtils::Animate(
1442         option,
1443         [ctx]() {
1444             if (ctx) {
1445                 ctx->UpdateOpacity(1.0);
1446                 ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
1447             }
1448         },
1449         option.GetOnFinishEvent());
1450     auto toastProperty = toastNode->GetLayoutProperty<ToastLayoutProperty>();
1451     CHECK_NULL_VOID(toastProperty);
1452     toastProperty->SetSelectStatus(ToastLayoutProperty::SelectStatus::ON);
1453     toastNode->OnAccessibilityEvent(
1454         AccessibilityEventType::PAGE_OPEN, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1455 }
1456 
PopToast(int32_t toastId)1457 void OverlayManager::PopToast(int32_t toastId)
1458 {
1459     TAG_LOGD(AceLogTag::ACE_OVERLAY, "pop toast enter");
1460     AnimationOption option;
1461     auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
1462     option.SetCurve(curve);
1463     option.SetDuration(TOAST_ANIMATION_DURATION);
1464     option.SetFillMode(FillMode::FORWARDS);
1465     // OnFinishEvent should be executed in UI thread.
1466     option.SetOnFinishEvent([weak = WeakClaim(this), toastId] {
1467         TAG_LOGD(AceLogTag::ACE_OVERLAY, "start toast exit finish event");
1468         auto overlayManager = weak.Upgrade();
1469         CHECK_NULL_VOID(overlayManager);
1470         auto toastIter = overlayManager->toastMap_.find(toastId);
1471         if (toastIter == overlayManager->toastMap_.end()) {
1472             return;
1473         }
1474         auto toastUnderPop = toastIter->second.Upgrade();
1475         CHECK_NULL_VOID(toastUnderPop);
1476         auto context = PipelineContext::GetCurrentContext();
1477         CHECK_NULL_VOID(context);
1478         auto rootNode = context->GetRootElement();
1479         CHECK_NULL_VOID(rootNode);
1480         TAG_LOGI(AceLogTag::ACE_OVERLAY, "toast remove from root");
1481         rootNode->RemoveChild(toastUnderPop);
1482         overlayManager->toastMap_.erase(toastId);
1483         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1484 
1485         auto container = Container::Current();
1486         CHECK_NULL_VOID(container);
1487         if (container->IsDialogContainer() || (container->IsSubContainer() && rootNode->GetChildren().empty())) {
1488             auto pattern = toastUnderPop->GetPattern<ToastPattern>();
1489             CHECK_NULL_VOID(pattern);
1490             auto toastInfo = pattern->GetToastInfo();
1491             // hide window when toast show in subwindow.
1492             if (toastInfo.showMode == NG::ToastShowMode::SYSTEM_TOP_MOST) {
1493                 SubwindowManager::GetInstance()->HideSystemTopMostWindow();
1494             } else {
1495                 SubwindowManager::GetInstance()->HideToastSubWindowNG();
1496             }
1497         }
1498     });
1499     auto toastIter = toastMap_.find(toastId);
1500     if (toastIter == toastMap_.end()) {
1501         return;
1502     }
1503     auto toastUnderPop = toastIter->second.Upgrade();
1504     CHECK_NULL_VOID(toastUnderPop);
1505     auto ctx = toastUnderPop->GetRenderContext();
1506     CHECK_NULL_VOID(ctx);
1507     ctx->UpdateOpacity(1.0);
1508     ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
1509     AnimationUtils::Animate(
1510         option,
1511         [ctx]() {
1512             if (ctx) {
1513                 ctx->UpdateOpacity(0.0);
1514                 ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
1515             }
1516         },
1517         option.GetOnFinishEvent());
1518 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1519     auto* transactionProxy = Rosen::RSTransactionProxy::GetInstance();
1520     if (transactionProxy != nullptr) {
1521         transactionProxy->FlushImplicitTransaction();
1522     }
1523 #endif
1524     // start animation immediately
1525     auto pipeline = PipelineContext::GetCurrentContext();
1526     CHECK_NULL_VOID(pipeline);
1527     pipeline->RequestFrame();
1528     auto toastProperty = toastUnderPop->GetLayoutProperty<ToastLayoutProperty>();
1529     CHECK_NULL_VOID(toastProperty);
1530     toastProperty->SetSelectStatus(ToastLayoutProperty::SelectStatus::OFF);
1531     toastUnderPop->OnAccessibilityEvent(
1532         AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1533 }
1534 
ClearToastInSubwindow()1535 void OverlayManager::ClearToastInSubwindow()
1536 {
1537     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear toast in subwindow enter");
1538     SubwindowManager::GetInstance()->ClearToastInSubwindow();
1539 }
1540 
ClearToast()1541 void OverlayManager::ClearToast()
1542 {
1543     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear toast enter");
1544     auto context = PipelineContext::GetCurrentContext();
1545     CHECK_NULL_VOID(context);
1546     auto rootNode = context->GetRootElement();
1547     CHECK_NULL_VOID(rootNode);
1548     for (auto [id, toastNodeWeak] : toastMap_) {
1549         PopToast(id);
1550     }
1551 }
1552 
ShowPopupAnimation(const RefPtr<FrameNode> & popupNode)1553 void OverlayManager::ShowPopupAnimation(const RefPtr<FrameNode>& popupNode)
1554 {
1555     auto popupPattern = popupNode->GetPattern<BubblePattern>();
1556     CHECK_NULL_VOID(popupPattern);
1557     popupPattern->ResetFocusState();
1558     BlurLowerNode(popupNode);
1559     auto onFinish = [popupNodeWk = WeakPtr<FrameNode>(popupNode), weak = WeakClaim(this)]() {
1560         auto overlayManager = weak.Upgrade();
1561         auto popupNode = popupNodeWk.Upgrade();
1562         CHECK_NULL_VOID(overlayManager && popupNode);
1563         overlayManager->FocusOverlayNode(popupNode);
1564     };
1565     if (popupPattern->GetHasTransition()) {
1566         popupPattern->StartEnteringTransitionEffects(popupNode, onFinish);
1567     } else {
1568         popupPattern->StartEnteringAnimation(onFinish);
1569     }
1570 }
1571 
ShowPopupAnimationNG(const RefPtr<FrameNode> & popupNode)1572 void OverlayManager::ShowPopupAnimationNG(const RefPtr<FrameNode>& popupNode)
1573 {
1574     auto popupPattern = popupNode->GetPattern<BubblePattern>();
1575     CHECK_NULL_VOID(popupPattern);
1576     if (popupPattern->GetHasTransition()) {
1577         popupPattern->StartEnteringTransitionEffects(popupNode, nullptr);
1578     } else {
1579         popupPattern->StartEnteringAnimation(nullptr);
1580     }
1581 }
1582 
HidePopupAnimation(const RefPtr<FrameNode> & popupNode,const std::function<void ()> & finish)1583 void OverlayManager::HidePopupAnimation(const RefPtr<FrameNode>& popupNode, const std::function<void()>& finish)
1584 {
1585     auto rootNode = rootNodeWeak_.Upgrade();
1586     auto popupPattern = popupNode->GetPattern<BubblePattern>();
1587     if (popupPattern->GetHasTransition()) {
1588         if (!popupNode->GetRenderContext()->HasDisappearTransition()) {
1589             popupPattern->SetTransitionStatus(TransitionStatus::INVISIABLE);
1590             popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1591             RemoveChildWithService(rootNode, popupNode);
1592             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1593             auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1594             CHECK_NULL_VOID(layoutProp);
1595             auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1596             if (isShowInSubWindow) {
1597                 auto subwindowMgr = SubwindowManager::GetInstance();
1598                 subwindowMgr->DeleteHotAreas(Container::CurrentId(), popupNode->GetId());
1599             }
1600         } else {
1601             popupPattern->StartExitingTransitionEffects(popupNode, finish);
1602         }
1603     } else {
1604         popupPattern->StartExitingAnimation(finish);
1605     }
1606 }
1607 
ShowPopup(int32_t targetId,const PopupInfo & popupInfo,const std::function<void (int32_t)> && onWillDismiss,bool interactiveDismiss)1608 void OverlayManager::ShowPopup(int32_t targetId, const PopupInfo& popupInfo,
1609     const std::function<void(int32_t)>&& onWillDismiss, bool interactiveDismiss)
1610 {
1611     if (!UpdatePopupMap(targetId, popupInfo)) {
1612         TAG_LOGE(AceLogTag::ACE_OVERLAY, "failed to update popup map, tag:%{public}s",
1613             popupInfo.target.Upgrade()->GetTag().c_str());
1614         return;
1615     }
1616     auto rootNode = rootNodeWeak_.Upgrade();
1617     CHECK_NULL_VOID(rootNode);
1618     auto frameNode = AceType::DynamicCast<FrameNode>(rootNode);
1619     if (frameNode && !frameNode->IsLayoutComplete()) {
1620         auto context = PipelineContext::GetCurrentContext();
1621         CHECK_NULL_VOID(context);
1622         auto taskExecutor = context->GetTaskExecutor();
1623         CHECK_NULL_VOID(taskExecutor);
1624         taskExecutor->PostTask(
1625             [targetId, popupInfo, weak = WeakClaim(this), callback = std::move(onWillDismiss), interactiveDismiss]() {
1626                 auto overlayManager = weak.Upgrade();
1627                 CHECK_NULL_VOID(overlayManager);
1628                 overlayManager->MountPopup(targetId, popupInfo, std::move(callback), interactiveDismiss);
1629             },
1630             TaskExecutor::TaskType::UI, "ArkUIOverlayShowPopup");
1631     } else {
1632         MountPopup(targetId, popupInfo, std::move(onWillDismiss), interactiveDismiss);
1633     }
1634 }
1635 
UpdatePopupMap(int32_t targetId,const PopupInfo & popupInfo)1636 bool OverlayManager::UpdatePopupMap(int32_t targetId, const PopupInfo& popupInfo)
1637 {
1638     popupMap_[targetId] = popupInfo;
1639     if (!popupInfo.markNeedUpdate) {
1640         TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
1641         return false;
1642     }
1643     popupMap_[targetId].markNeedUpdate = false;
1644     return true;
1645 }
1646 
MountPopup(int32_t targetId,const PopupInfo & popupInfo,const std::function<void (int32_t)> && onWillDismiss,bool interactiveDismiss)1647 void OverlayManager::MountPopup(int32_t targetId, const PopupInfo& popupInfo,
1648     const std::function<void(int32_t)>&& onWillDismiss, bool interactiveDismiss)
1649 {
1650     // TargetNode may be destroyed when MontPopup is thrown thread.
1651     auto targetNode = popupInfo.target.Upgrade();
1652     CHECK_NULL_VOID(targetNode);
1653     auto popupNode = popupInfo.popupNode;
1654     CHECK_NULL_VOID(popupNode);
1655     auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1656     CHECK_NULL_VOID(layoutProp);
1657     auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1658     auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
1659     CHECK_NULL_VOID(paintProperty);
1660     auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
1661     auto isUseCustom = paintProperty->GetUseCustom().value_or(false);
1662 
1663     auto rootNode = rootNodeWeak_.Upgrade();
1664     auto container = Container::Current();
1665     if (container && container->IsScenceBoardWindow()) {
1666         rootNode = FindWindowScene(popupInfo.target.Upgrade());
1667     }
1668     CHECK_NULL_VOID(rootNode);
1669     CHECK_NULL_VOID(popupInfo.markNeedUpdate);
1670     CHECK_NULL_VOID(popupInfo.popupNode);
1671 
1672     const auto& rootChildren = rootNode->GetChildren();
1673     auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
1674     if (iter == rootChildren.rend()) {
1675         MountToParentWithService(rootNode, popupNode);
1676     }
1677 
1678     // attach popupNode before entering animation
1679     popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(true);
1680     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1681     popupMap_[targetId].isCurrentOnShow = true;
1682 
1683     auto popupPattern = popupNode->GetPattern<BubblePattern>();
1684     CHECK_NULL_VOID(popupPattern);
1685     popupPattern->AddPipelineCallBack();
1686     popupPattern->SetInteractiveDismiss(interactiveDismiss);
1687     popupPattern->UpdateOnWillDismiss(move(onWillDismiss));
1688     if ((isTypeWithOption && !isShowInSubWindow) ||
1689         (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && popupInfo.focusable)) {
1690         ShowPopupAnimation(popupNode);
1691     } else {
1692         ShowPopupAnimationNG(popupNode);
1693     }
1694     SetPopupHotAreas(popupNode);
1695     SendPopupAccessibilityPageOpen(popupNode);
1696 }
1697 
SetPopupHotAreas(RefPtr<FrameNode> popupNode)1698 void OverlayManager::SetPopupHotAreas(RefPtr<FrameNode> popupNode)
1699 {
1700     CHECK_NULL_VOID(popupNode);
1701     auto popupId = popupNode->GetId();
1702     auto popupPattern = popupNode->GetPattern<BubblePattern>();
1703     CHECK_NULL_VOID(popupPattern);
1704     auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1705     CHECK_NULL_VOID(layoutProp);
1706     auto isBlock = layoutProp->GetBlockEventValue(true);
1707     auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1708     if (isShowInSubWindow && popupPattern->IsOnShow()) {
1709         std::vector<Rect> rects;
1710         if (!isBlock) {
1711             auto rect = Rect(popupPattern->GetChildOffset().GetX(), popupPattern->GetChildOffset().GetY(),
1712                 popupPattern->GetChildSize().Width(), popupPattern->GetChildSize().Height());
1713             rects.emplace_back(rect);
1714         } else {
1715             auto parentWindowRect = SubwindowManager::GetInstance()->GetParentWindowRect();
1716             auto rect = Rect(popupPattern->GetChildOffset().GetX(), popupPattern->GetChildOffset().GetY(),
1717                 popupPattern->GetChildSize().Width(), popupPattern->GetChildSize().Height());
1718             rects.emplace_back(parentWindowRect);
1719             rects.emplace_back(rect);
1720         }
1721         auto subWindowMgr = SubwindowManager::GetInstance();
1722         subWindowMgr->SetHotAreas(rects, popupId, popupPattern->GetContainerId());
1723     }
1724 }
1725 
HidePopup(int32_t targetId,const PopupInfo & popupInfo)1726 void OverlayManager::HidePopup(int32_t targetId, const PopupInfo& popupInfo)
1727 {
1728     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide popup enter");
1729     popupMap_[targetId] = popupInfo;
1730     if (!popupInfo.markNeedUpdate) {
1731         TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
1732         return;
1733     }
1734     popupMap_[targetId].markNeedUpdate = false;
1735     auto focusable = popupInfo.focusable;
1736     auto popupNode = popupInfo.popupNode;
1737     CHECK_NULL_VOID(popupNode);
1738     auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1739     CHECK_NULL_VOID(layoutProp);
1740     auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1741     auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
1742     CHECK_NULL_VOID(paintProperty);
1743     auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
1744     auto isUseCustom = paintProperty->GetUseCustom().value_or(false);
1745 
1746     auto rootNode = rootNodeWeak_.Upgrade();
1747     auto container = Container::Current();
1748     if (container && container->IsScenceBoardWindow()) {
1749         rootNode = FindWindowScene(popupInfo.target.Upgrade());
1750     }
1751     CHECK_NULL_VOID(rootNode);
1752 
1753     auto pipeline = rootNode->GetContextRefPtr();
1754     CHECK_NULL_VOID(pipeline);
1755     const auto& rootChildren = rootNode->GetChildren();
1756     auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
1757     // There is no overlay under the root node or it is not in atomicservice
1758     if (iter == rootChildren.rend() && !pipeline->GetInstallationFree()) {
1759         return;
1760     }
1761 
1762     auto popupPattern = popupNode->GetPattern<BubblePattern>();
1763     CHECK_NULL_VOID(popupPattern);
1764     if (popupPattern->GetTransitionStatus() == TransitionStatus::EXITING) {
1765         return;
1766     }
1767     popupPattern->SetTransitionStatus(TransitionStatus::EXITING);
1768     if ((isTypeWithOption && !isShowInSubWindow) ||
1769         (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && focusable)) {
1770         ResetLowerNodeFocusable(popupNode);
1771     }
1772     CheckReturnFocus(popupNode);
1773     auto accessibilityProperty = popupNode->GetAccessibilityProperty<BubbleAccessibilityProperty>();
1774     CHECK_NULL_VOID(accessibilityProperty);
1775     accessibilityProperty->SetShowedState(0);
1776     popupNode->OnAccessibilityEvent(
1777         AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1778     // detach popupNode after exiting animation
1779     popupMap_[targetId].isCurrentOnShow = false;
1780     auto onFinish = [isShowInSubWindow, isTypeWithOption, isUseCustom, focusable,
1781         targetId, popupNodeWk = WeakPtr<FrameNode>(popupNode),
1782         rootNodeWk = WeakPtr<UINode>(rootNode), weak = WeakClaim(this)]() {
1783         auto rootNode = rootNodeWk.Upgrade();
1784         auto popupNode = popupNodeWk.Upgrade();
1785         auto overlayManager = weak.Upgrade();
1786         CHECK_NULL_VOID(rootNode && popupNode && overlayManager);
1787         if (overlayManager->popupMap_[targetId].isCurrentOnShow) {
1788             return;
1789         }
1790         auto popupPattern = popupNode->GetPattern<BubblePattern>();
1791         CHECK_NULL_VOID(popupPattern);
1792         popupPattern->SetTransitionStatus(TransitionStatus::INVISIABLE);
1793         popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1794         popupNode->GetRenderContext()->UpdateChainedTransition(nullptr);
1795         overlayManager->RemoveChildWithService(rootNode, popupNode);
1796         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1797         overlayManager->ErasePopupInfo(targetId);
1798         if ((isTypeWithOption && !isShowInSubWindow) ||
1799             (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && focusable)) {
1800             overlayManager->BlurOverlayNode(popupNode);
1801         }
1802         if (isShowInSubWindow) {
1803             auto subwindow = SubwindowManager::GetInstance();
1804             subwindow->DeleteHotAreas(Container::CurrentId(), popupNode->GetId());
1805             subwindow->HideSubWindowNG();
1806         }
1807     };
1808     HidePopupAnimation(popupNode, onFinish);
1809     RemoveEventColumn();
1810     RemovePixelMapAnimation(false, 0, 0);
1811     RemoveGatherNodeWithAnimation();
1812     RemoveFilter();
1813 }
1814 
HidePopupWithoutAnimation(int32_t targetId,const PopupInfo & popupInfo)1815 RefPtr<FrameNode> OverlayManager::HidePopupWithoutAnimation(int32_t targetId, const PopupInfo& popupInfo)
1816 {
1817     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide popup without animation enter");
1818     popupMap_[targetId] = popupInfo;
1819     CHECK_NULL_RETURN(popupInfo.markNeedUpdate, nullptr);
1820     if (!popupInfo.markNeedUpdate) {
1821         TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
1822         return nullptr;
1823     }
1824     CHECK_NULL_RETURN(popupInfo.popupNode, nullptr);
1825     auto bubbleRenderProp = popupInfo.popupNode->GetPaintProperty<BubbleRenderProperty>();
1826     CHECK_NULL_RETURN(bubbleRenderProp, nullptr);
1827     auto autoCancel = bubbleRenderProp->GetAutoCancel().value_or(true);
1828     if (!autoCancel) {
1829         return nullptr;
1830     }
1831     popupInfo.popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1832     CHECK_NULL_RETURN(popupInfo.isCurrentOnShow, nullptr);
1833     popupMap_[targetId].isCurrentOnShow = false;
1834     auto pattern = popupInfo.popupNode->GetPattern<BubblePattern>();
1835     CHECK_NULL_RETURN(pattern, nullptr);
1836     pattern->SetTransitionStatus(TransitionStatus::INVISIABLE);
1837     auto rootNode = rootNodeWeak_.Upgrade();
1838     CHECK_NULL_RETURN(rootNode, nullptr);
1839     auto rootChildren = rootNode->GetChildren();
1840     auto iter = std::find(rootChildren.begin(), rootChildren.end(), popupInfo.popupNode);
1841     if (iter != rootChildren.end()) {
1842         return popupMap_[targetId].popupNode;
1843     }
1844     return nullptr;
1845 }
1846 
ShowIndexerPopup(int32_t targetId,RefPtr<FrameNode> & customNode)1847 void OverlayManager::ShowIndexerPopup(int32_t targetId, RefPtr<FrameNode>& customNode)
1848 {
1849     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show indexer popup enter");
1850     CHECK_NULL_VOID(customNode);
1851     auto rootNode = rootNodeWeak_.Upgrade();
1852     CHECK_NULL_VOID(rootNode);
1853     if (!customPopupMap_[targetId] || customPopupMap_[targetId] != customNode) {
1854         customPopupMap_[targetId] = customNode;
1855         customNode->MountToParent(rootNode);
1856         customNode->MarkModifyDone();
1857         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1858     }
1859 }
1860 
RemoveIndexerPopupById(int32_t targetId)1861 void OverlayManager::RemoveIndexerPopupById(int32_t targetId)
1862 {
1863     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove indexer popup by id enter");
1864     if (customPopupMap_.empty()) {
1865         return;
1866     }
1867     auto rootNode = rootNodeWeak_.Upgrade();
1868     CHECK_NULL_VOID(rootNode);
1869     auto iter = customPopupMap_.find(targetId);
1870     if (iter != customPopupMap_.end()) {
1871         RemoveChildWithService(rootNode, iter->second);
1872         customPopupMap_.erase(iter);
1873         rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1874     }
1875 }
1876 
RemoveIndexerPopup()1877 void OverlayManager::RemoveIndexerPopup()
1878 {
1879     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove indexer popup enter");
1880     if (customPopupMap_.empty()) {
1881         return;
1882     }
1883     auto rootNode = rootNodeWeak_.Upgrade();
1884     CHECK_NULL_VOID(rootNode);
1885     for (const auto& popup : customPopupMap_) {
1886         auto popupNode = popup.second;
1887         RemoveChildWithService(rootNode, popupNode);
1888     }
1889     customPopupMap_.clear();
1890     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1891 }
1892 
HideCustomPopups()1893 void OverlayManager::HideCustomPopups()
1894 {
1895     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide custom popup enter");
1896     if (popupMap_.empty()) {
1897         return;
1898     }
1899     for (const auto& popup : popupMap_) {
1900         auto popupInfo = popup.second;
1901         if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
1902             auto targetNodeId = popupInfo.target.Upgrade()->GetId();
1903             auto popupNode = popupInfo.popupNode;
1904             CHECK_NULL_VOID(popupNode);
1905             auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1906             CHECK_NULL_VOID(layoutProp);
1907             auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
1908             CHECK_NULL_VOID(paintProperty);
1909             auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
1910             popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1911             // if use popup with option, skip
1912             if (isTypeWithOption) {
1913                 continue;
1914             }
1915             popupInfo.markNeedUpdate = true;
1916             auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1917             if (showInSubWindow) {
1918                 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
1919             } else {
1920                 HidePopup(targetNodeId, popupInfo);
1921             }
1922         }
1923     }
1924 }
1925 
HideAllPopups()1926 void OverlayManager::HideAllPopups()
1927 {
1928     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide all popup enter");
1929     if (popupMap_.empty()) {
1930         return;
1931     }
1932     auto tempPopupMap = popupMap_;
1933     for (const auto& popup : tempPopupMap) {
1934         auto popupInfo = popup.second;
1935         if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
1936             auto targetNodeId = popupInfo.target.Upgrade()->GetId();
1937             auto popupNode = popupInfo.popupNode;
1938             CHECK_NULL_VOID(popupNode);
1939             auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1940             CHECK_NULL_VOID(layoutProp);
1941             popupInfo.markNeedUpdate = true;
1942             auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1943             if (showInSubWindow) {
1944                 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
1945             } else {
1946                 HidePopup(targetNodeId, popupInfo);
1947             }
1948         }
1949     }
1950 }
1951 
ErasePopup(int32_t targetId)1952 void OverlayManager::ErasePopup(int32_t targetId)
1953 {
1954     TAG_LOGD(AceLogTag::ACE_OVERLAY, "erase popup enter");
1955     auto it = popupMap_.find(targetId);
1956     if (it != popupMap_.end()) {
1957         auto rootNode = rootNodeWeak_.Upgrade();
1958         CHECK_NULL_VOID(rootNode);
1959         auto popupNode = it->second.popupNode;
1960         CHECK_NULL_VOID(popupNode);
1961         auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1962         CHECK_NULL_VOID(layoutProp);
1963         auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1964         auto accessibilityProperty = popupNode->GetAccessibilityProperty<BubbleAccessibilityProperty>();
1965         CHECK_NULL_VOID(accessibilityProperty);
1966         accessibilityProperty->SetShowedState(0);
1967         popupNode->OnAccessibilityEvent(
1968             AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1969         if (isShowInSubWindow) {
1970             auto subwindowMgr = SubwindowManager::GetInstance();
1971             subwindowMgr->DeleteHotAreas(Container::CurrentId(), popupNode->GetId());
1972         }
1973         RemoveChildWithService(rootNode, popupNode);
1974         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1975         popupMap_.erase(targetId);
1976     }
1977 }
1978 
DismissPopup()1979 void OverlayManager::DismissPopup()
1980 {
1981     auto iter = popupMap_.find(dismissPopupId_);
1982     if (iter == popupMap_.end()) {
1983         return;
1984     }
1985     auto popupInfo = iter->second;
1986     popupInfo.markNeedUpdate = true;
1987     HidePopup(dismissPopupId_, popupInfo);
1988 }
1989 
ShowMenuHelper(RefPtr<FrameNode> & menu,int32_t targetId,const NG::OffsetF & offset)1990 bool OverlayManager::ShowMenuHelper(RefPtr<FrameNode>& menu, int32_t targetId, const NG::OffsetF& offset)
1991 {
1992     TAG_LOGI(AceLogTag::ACE_OVERLAY, "show menu helper enter");
1993     if (!menu) {
1994         // get existing menuNode
1995         auto it = menuMap_.find(targetId);
1996         if (it != menuMap_.end()) {
1997             menu = it->second;
1998         }
1999     } else {
2000         // creating new menu
2001         menuMap_[targetId] = menu;
2002     }
2003     CHECK_NULL_RETURN(menu, false);
2004 
2005     RefPtr<FrameNode> menuFrameNode = menu;
2006     if (menu->GetTag() != V2::MENU_ETS_TAG) {
2007         auto menuChild = menu->GetChildAtIndex(0);
2008         CHECK_NULL_RETURN(menuChild, false);
2009         menuFrameNode = DynamicCast<FrameNode>(menuChild);
2010     }
2011 
2012     auto props = menuFrameNode->GetLayoutProperty<MenuLayoutProperty>();
2013     CHECK_NULL_RETURN(props, false);
2014     props->UpdateMenuOffset(offset);
2015     menuFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
2016     return true;
2017 }
2018 
ShowMenu(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)2019 void OverlayManager::ShowMenu(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
2020 {
2021     TAG_LOGI(AceLogTag::ACE_OVERLAY, "show menu enter");
2022     if (!ShowMenuHelper(menu, targetId, offset)) {
2023         TAG_LOGW(AceLogTag::ACE_OVERLAY, "show menu helper failed");
2024         return;
2025     }
2026     auto rootNode = rootNodeWeak_.Upgrade();
2027     auto container = Container::Current();
2028     if (container && container->IsScenceBoardWindow()) {
2029         auto wrapperPattern = AceType::DynamicCast<MenuWrapperPattern>(menu->GetPattern());
2030         CHECK_NULL_VOID(wrapperPattern);
2031         auto menuChild = wrapperPattern->GetMenu();
2032         CHECK_NULL_VOID(menuChild);
2033         auto menuPattern = AceType::DynamicCast<MenuPattern>(menuChild->GetPattern());
2034         CHECK_NULL_VOID(menuPattern);
2035         rootNode = FindWindowScene(FrameNode::GetFrameNode(menuPattern->GetTargetTag(), menuPattern->GetTargetId()));
2036     }
2037     CHECK_NULL_VOID(rootNode);
2038     auto rootChildren = rootNode->GetChildren();
2039     auto iter = std::find(rootChildren.begin(), rootChildren.end(), menu);
2040     // menuNode already showing
2041     if (iter == rootChildren.end()) {
2042         MountToParentWithService(rootNode, menu);
2043         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2044         menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2045         ShowMenuAnimation(menu);
2046         menu->MarkModifyDone();
2047     }
2048 }
2049 
2050 // subwindow only contains one menu instance.
ShowMenuInSubWindow(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)2051 void OverlayManager::ShowMenuInSubWindow(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
2052 {
2053     TAG_LOGI(AceLogTag::ACE_OVERLAY, "show menu insubwindow enter");
2054     auto menuOffset = offset;
2055     auto currentSubwindow = SubwindowManager::GetInstance()->GetCurrentWindow();
2056     if (currentSubwindow) {
2057         auto subwindowRect = currentSubwindow->GetRect();
2058         menuOffset -= subwindowRect.GetOffset();
2059     }
2060     if (!ShowMenuHelper(menu, targetId, menuOffset)) {
2061         TAG_LOGW(AceLogTag::ACE_OVERLAY, "show menu helper failed");
2062         return;
2063     }
2064     auto rootNode = rootNodeWeak_.Upgrade();
2065     CHECK_NULL_VOID(rootNode);
2066 
2067     std::vector<int32_t> idsNeedClean;
2068     for (auto child: rootNode->GetChildren()) {
2069         idsNeedClean.push_back(child->GetId());
2070     }
2071     auto pipeline = rootNode->GetContext();
2072     CHECK_NULL_VOID(pipeline);
2073     pipeline->AddAfterLayoutTask([idsNeedClean, containerId = Container::CurrentId()] {
2074         auto subwindowMgr = SubwindowManager::GetInstance();
2075         for (auto child : idsNeedClean) {
2076             subwindowMgr->DeleteHotAreas(containerId, child);
2077         }
2078     });
2079     rootNode->Clean();
2080 
2081     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
2082     CHECK_NULL_VOID(menuWrapperPattern);
2083     if (menuWrapperPattern->IsContextMenu() && menuWrapperPattern->GetPreviewMode() != MenuPreviewMode::NONE) {
2084         auto filterNode = menuWrapperPattern->GetFilterColumnNode();
2085         if (filterNode) {
2086             SetHasFilter(true);
2087             SetFilterColumnNode(filterNode);
2088             filterNode->MountToParent(rootNode);
2089             ShowFilterAnimation(filterNode);
2090             filterNode->MarkModifyDone();
2091         }
2092     }
2093     menu->MountToParent(rootNode);
2094     ShowMenuAnimation(menu);
2095     menu->MarkModifyDone();
2096     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2097     pipeline->FlushUITasks();
2098 
2099     // set subwindow container id in menu.
2100     auto menuPattern = menu->GetPattern<PopupBasePattern>();
2101     CHECK_NULL_VOID(menuPattern);
2102     menuPattern->SetContainerId(Container::CurrentId());
2103 }
2104 
HideMenuInSubWindow(const RefPtr<FrameNode> & menu,int32_t targetId)2105 void OverlayManager::HideMenuInSubWindow(const RefPtr<FrameNode>& menu, int32_t targetId)
2106 {
2107     TAG_LOGI(AceLogTag::ACE_OVERLAY, "hide menu insubwindow enter");
2108     CHECK_NULL_VOID(menu);
2109     if (menu->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
2110         auto wrapperPattern = menu->GetPattern<MenuWrapperPattern>();
2111         CHECK_NULL_VOID(wrapperPattern);
2112         wrapperPattern->UpdateMenuAnimation(menu);
2113     }
2114     PopMenuAnimation(menu);
2115 }
2116 
HideMenuInSubWindow(bool showPreviewAnimation,bool startDrag)2117 void OverlayManager::HideMenuInSubWindow(bool showPreviewAnimation, bool startDrag)
2118 {
2119     TAG_LOGI(AceLogTag::ACE_OVERLAY, "hide menu insubwindow enter");
2120     if (menuMap_.empty()) {
2121         return;
2122     }
2123     auto rootNode = rootNodeWeak_.Upgrade();
2124     for (const auto& child : rootNode->GetChildren()) {
2125         auto node = DynamicCast<FrameNode>(child);
2126         if (node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
2127             PopMenuAnimation(node, showPreviewAnimation, startDrag);
2128         }
2129     }
2130 }
2131 
GetMenuNode(int32_t targetId)2132 RefPtr<FrameNode> OverlayManager::GetMenuNode(int32_t targetId)
2133 {
2134     auto it = menuMap_.find(targetId);
2135     if (it != menuMap_.end()) {
2136         return it->second;
2137     }
2138     return nullptr;
2139 }
2140 
HideMenu(const RefPtr<FrameNode> & menu,int32_t targetId,bool isMenuOnTouch)2141 void OverlayManager::HideMenu(const RefPtr<FrameNode>& menu, int32_t targetId, bool isMenuOnTouch)
2142 {
2143     TAG_LOGI(AceLogTag::ACE_OVERLAY, "hide menu enter");
2144     PopMenuAnimation(menu);
2145     RemoveEventColumn();
2146     if (isMenuOnTouch) {
2147         RemovePixelMap();
2148         RemoveGatherNode();
2149     } else {
2150         RemovePixelMapAnimation(false, 0, 0);
2151         RemoveGatherNodeWithAnimation();
2152     }
2153     RemoveFilterAnimation();
2154 }
2155 
HideAllMenus()2156 void OverlayManager::HideAllMenus()
2157 {
2158     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide all menus enter");
2159     auto container = Container::Current();
2160     if (container && container->IsScenceBoardWindow()) {
2161         for (const auto& windowScene : windowSceneSet_) {
2162             if (!windowScene.Upgrade()) {
2163                 continue;
2164             }
2165             for (const auto& child : windowScene.Upgrade()->GetChildren()) {
2166                 auto node = DynamicCast<FrameNode>(child);
2167                 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
2168                     PopMenuAnimation(node);
2169                 }
2170             }
2171         }
2172         return;
2173     }
2174 
2175     auto rootNode = rootNodeWeak_.Upgrade();
2176     CHECK_NULL_VOID(rootNode);
2177     for (const auto& child : rootNode->GetChildren()) {
2178         auto node = DynamicCast<FrameNode>(child);
2179         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
2180             auto wrapperPattern = node->GetPattern<MenuWrapperPattern>();
2181             CHECK_NULL_VOID(wrapperPattern);
2182             wrapperPattern->UpdateMenuAnimation(node);
2183             PopMenuAnimation(node);
2184         }
2185     }
2186 }
2187 
DeleteMenu(int32_t targetId)2188 void OverlayManager::DeleteMenu(int32_t targetId)
2189 {
2190     TAG_LOGI(AceLogTag::ACE_OVERLAY, "delete menu enter");
2191     auto it = menuMap_.find(targetId);
2192     if (it == menuMap_.end()) {
2193         return;
2194     }
2195     auto node = AceType::DynamicCast<FrameNode>(it->second);
2196     if (node->GetParent()) {
2197         auto id = Container::CurrentId();
2198         SubwindowManager::GetInstance()->ClearMenu();
2199         SubwindowManager::GetInstance()->ClearMenuNG(id, targetId);
2200 
2201         if (node->GetParent()) {
2202             RemoveEventColumn();
2203             RemoveMenuNotInSubWindow(WeakClaim(RawPtr(node)), rootNodeWeak_, WeakClaim(this));
2204         }
2205     }
2206     EraseMenuInfo(targetId);
2207 }
2208 
CleanMenuInSubWindowWithAnimation()2209 void OverlayManager::CleanMenuInSubWindowWithAnimation()
2210 {
2211     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean menu insubwindow with animation enter");
2212     auto rootNode = rootNodeWeak_.Upgrade();
2213     CHECK_NULL_VOID(rootNode);
2214     RefPtr<FrameNode> menu;
2215     for (const auto& child : rootNode->GetChildren()) {
2216         auto node = DynamicCast<FrameNode>(child);
2217         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
2218             menu = node;
2219             break;
2220         }
2221     }
2222     CHECK_NULL_VOID(menu);
2223     PopMenuAnimation(menu);
2224 }
2225 
CleanHoverImagePreviewInSubWindow(const RefPtr<FrameNode> & flexNode)2226 void OverlayManager::CleanHoverImagePreviewInSubWindow(const RefPtr<FrameNode>& flexNode)
2227 {
2228     CHECK_NULL_VOID(flexNode && flexNode->GetTag() == V2::FLEX_ETS_TAG);
2229     for (const auto& child : flexNode->GetChildren()) {
2230         auto node = DynamicCast<FrameNode>(child);
2231         CHECK_NULL_VOID(node && node->GetTag() == V2::STACK_ETS_TAG);
2232 
2233         auto previewNode = node->GetLastChild();
2234         if (previewNode && previewNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG) {
2235             node->RemoveChild(previewNode);
2236         }
2237 
2238         auto imageNode = node->GetFirstChild();
2239         if (imageNode && imageNode->GetTag() == V2::IMAGE_ETS_TAG) {
2240             node->RemoveChild(imageNode);
2241         }
2242 
2243         flexNode->RemoveChild(node);
2244         flexNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2245         break;
2246     }
2247 }
2248 
CleanPreviewInSubWindow()2249 void OverlayManager::CleanPreviewInSubWindow()
2250 {
2251     auto rootNode = rootNodeWeak_.Upgrade();
2252     CHECK_NULL_VOID(rootNode);
2253     for (const auto& child : rootNode->GetChildren()) {
2254         auto node = DynamicCast<FrameNode>(child);
2255         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
2256             for (auto& childNode : node->GetChildren()) {
2257                 auto frameNode = DynamicCast<FrameNode>(childNode);
2258                 if (frameNode && (frameNode->GetTag() == V2::FLEX_ETS_TAG ||
2259                     frameNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG || frameNode->GetTag() == V2::IMAGE_ETS_TAG)) {
2260                     CleanHoverImagePreviewInSubWindow(frameNode);
2261                     auto imagelayoutProperty = frameNode->GetLayoutProperty();
2262                     if (imagelayoutProperty) {
2263                         imagelayoutProperty->UpdateVisibility(VisibleType::GONE);
2264                     } else {
2265                         TAG_LOGW(AceLogTag::ACE_OVERLAY, "Preview image failed to set invisible.");
2266                     }
2267                     break;
2268                 }
2269             }
2270             break;
2271         }
2272     }
2273 }
2274 
CleanMenuInSubWindow(int32_t targetId)2275 void OverlayManager::CleanMenuInSubWindow(int32_t targetId)
2276 {
2277     TAG_LOGI(AceLogTag::ACE_OVERLAY, "clean menu insubwindow enter");
2278     auto rootNode = rootNodeWeak_.Upgrade();
2279     CHECK_NULL_VOID(rootNode);
2280 
2281     for (const auto& child : rootNode->GetChildren()) {
2282         auto node = DynamicCast<FrameNode>(child);
2283         if (node && node->GetTag() != V2::MENU_WRAPPER_ETS_TAG) {
2284             continue;
2285         }
2286 
2287         auto menuWrapperPattern = node->GetPattern<MenuWrapperPattern>();
2288         CHECK_NULL_VOID(menuWrapperPattern);
2289         if (menuWrapperPattern->GetTargetId() != targetId) {
2290             continue;
2291         }
2292 
2293         for (auto& childNode : node->GetChildren()) {
2294             auto frameNode = DynamicCast<FrameNode>(childNode);
2295             if (frameNode && (frameNode->GetTag() == V2::FLEX_ETS_TAG ||
2296                 frameNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG || frameNode->GetTag() == V2::IMAGE_ETS_TAG)) {
2297                 CleanHoverImagePreviewInSubWindow(frameNode);
2298                 node->RemoveChild(frameNode);
2299                 break;
2300             }
2301         }
2302         rootNode->RemoveChild(node);
2303         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2304         auto subwindowMgr = SubwindowManager::GetInstance();
2305         subwindowMgr->DeleteHotAreas(Container::CurrentId(), node->GetId());
2306         menuWrapperPattern->SetMenuStatus(MenuStatus::HIDE);
2307         break;
2308     }
2309 }
2310 
CleanPopupInSubWindow()2311 void OverlayManager::CleanPopupInSubWindow()
2312 {
2313     TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean popup insubwindow enter");
2314     auto rootNode = rootNodeWeak_.Upgrade();
2315     CHECK_NULL_VOID(rootNode);
2316     std::vector<RefPtr<FrameNode>> removeNodes;
2317     for (const auto& child : rootNode->GetChildren()) {
2318         if (!child || child->GetTag() != V2::POPUP_ETS_TAG) {
2319             continue;
2320         }
2321         auto id = child->GetId();
2322         for (const auto& popup : popupMap_) {
2323             auto popupInfo = popup.second;
2324             auto target = popup.first;
2325             if (id != popupInfo.popupId) {
2326                 continue;
2327             }
2328             popupInfo.markNeedUpdate = true;
2329             auto removeNode = HidePopupWithoutAnimation(target, popupInfo);
2330             if (removeNode) {
2331                 removeNodes.emplace_back(removeNode);
2332                 auto subwindowMgr = SubwindowManager::GetInstance();
2333                 subwindowMgr->DeleteHotAreas(Container::CurrentId(), removeNode->GetId());
2334                 ErasePopupInfo(target);
2335             }
2336             break;
2337         }
2338     }
2339     for (const auto& removeNode : removeNodes) {
2340         rootNode->RemoveChild(removeNode);
2341     }
2342     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2343 }
2344 
BeforeShowDialog(const RefPtr<FrameNode> & node)2345 void OverlayManager::BeforeShowDialog(const RefPtr<FrameNode>& node)
2346 {
2347     TAG_LOGD(AceLogTag::ACE_OVERLAY, "before show dialog");
2348     CHECK_NULL_VOID(node);
2349     if (dialogMap_.find(node->GetId()) != dialogMap_.end()) {
2350         return;
2351     }
2352     dialogMap_[node->GetId()] = node;
2353 }
2354 
SetDialogMask(const DialogProperties & dialogProps)2355 RefPtr<FrameNode> OverlayManager::SetDialogMask(const DialogProperties& dialogProps)
2356 {
2357     DialogProperties Maskarg;
2358     Maskarg.isMask = true;
2359     Maskarg.autoCancel = dialogProps.autoCancel;
2360     Maskarg.onWillDismiss = dialogProps.onWillDismiss;
2361     Maskarg.maskColor = dialogProps.maskColor;
2362     return ShowDialog(Maskarg, nullptr, false);
2363 }
2364 
ShowDialog(const DialogProperties & dialogProps,std::function<void ()> && buildFunc,bool isRightToLeft)2365 RefPtr<FrameNode> OverlayManager::ShowDialog(
2366     const DialogProperties& dialogProps, std::function<void()>&& buildFunc, bool isRightToLeft)
2367 {
2368     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
2369     RefPtr<UINode> customNode;
2370     // create custom builder content
2371     if (buildFunc) {
2372         NG::ScopedViewStackProcessor builderViewStackProcessor;
2373         buildFunc();
2374         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
2375         CHECK_NULL_RETURN(customNode, nullptr);
2376     }
2377 
2378     auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
2379     CHECK_NULL_RETURN(dialog, nullptr);
2380     BeforeShowDialog(dialog);
2381     if (dialogProps.transitionEffect != nullptr) {
2382         SetDialogTransitionEffect(dialog);
2383     } else {
2384         OpenDialogAnimation(dialog);
2385     }
2386     dialogCount_++;
2387     // set close button disable
2388     SetContainerButtonEnable(false);
2389     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
2390         Recorder::EventParamsBuilder builder;
2391         builder
2392             .SetType("Dialog")
2393             .SetEventType(Recorder::EventType::DIALOG_SHOW)
2394             .SetExtra(Recorder::KEY_TITLE, dialogProps.title)
2395             .SetExtra(Recorder::KEY_SUB_TITLE, dialogProps.subtitle);
2396         Recorder::EventRecorder::Get().OnEvent(std::move(builder));
2397     }
2398     return dialog;
2399 }
2400 
ShowDialogWithNode(const DialogProperties & dialogProps,const RefPtr<UINode> & customNode,bool isRightToLeft)2401 RefPtr<FrameNode> OverlayManager::ShowDialogWithNode(
2402     const DialogProperties& dialogProps, const RefPtr<UINode>& customNode, bool isRightToLeft)
2403 {
2404     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
2405     CHECK_NULL_RETURN(customNode, nullptr);
2406     auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
2407     CHECK_NULL_RETURN(dialog, nullptr);
2408     BeforeShowDialog(dialog);
2409     if (dialogProps.transitionEffect != nullptr) {
2410         SetDialogTransitionEffect(dialog);
2411     } else {
2412         OpenDialogAnimation(dialog);
2413     }
2414     dialogCount_++;
2415     // set close button disable
2416     SetContainerButtonEnable(false);
2417     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
2418         Recorder::EventParamsBuilder builder;
2419         builder
2420             .SetType("Dialog")
2421             .SetEventType(Recorder::EventType::DIALOG_SHOW)
2422             .SetExtra(Recorder::KEY_TITLE, dialogProps.title)
2423             .SetExtra(Recorder::KEY_SUB_TITLE, dialogProps.subtitle);
2424         Recorder::EventRecorder::Get().OnEvent(std::move(builder));
2425     }
2426     return dialog;
2427 }
2428 
GetDialogNodeWithExistContent(const RefPtr<UINode> & node)2429 RefPtr<FrameNode> OverlayManager::GetDialogNodeWithExistContent(const RefPtr<UINode>& node)
2430 {
2431     auto iter = dialogMap_.begin();
2432     while (iter != dialogMap_.end()) {
2433         auto dialogNode = (*iter).second;
2434         CHECK_NULL_RETURN(dialogNode, nullptr);
2435         auto dialogPattern = dialogNode->GetPattern<DialogPattern>();
2436         CHECK_NULL_RETURN(dialogPattern, nullptr);
2437         if (dialogPattern->GetCustomNode() == node) {
2438             return dialogNode;
2439         }
2440         iter++;
2441     }
2442     return nullptr;
2443 }
2444 
RegisterDialogLifeCycleCallback(const RefPtr<FrameNode> & dialog,const DialogProperties & dialogProps)2445 void OverlayManager::RegisterDialogLifeCycleCallback(
2446     const RefPtr<FrameNode>& dialog, const DialogProperties& dialogProps)
2447 {
2448     auto dialogPattern = dialog->GetPattern<DialogPattern>();
2449     CHECK_NULL_VOID(dialogPattern);
2450     auto onDidAppearEvent = dialogProps.onDidAppear;
2451     dialogPattern->RegisterDialogDidAppearCallback(std::move(onDidAppearEvent));
2452     auto onDidDisappearEvent = dialogProps.onDidDisappear;
2453     dialogPattern->RegisterDialogDidDisappearCallback(std::move(onDidDisappearEvent));
2454     auto onWillAppearEvent = dialogProps.onWillAppear;
2455     dialogPattern->RegisterDialogWillAppearCallback(std::move(onWillAppearEvent));
2456     auto onWillDisappearEvent = dialogProps.onWillDisappear;
2457     dialogPattern->RegisterDialogWillDisappearCallback(std::move(onWillDisappearEvent));
2458 }
2459 
CustomDialogRecordEvent(const DialogProperties & dialogProps)2460 void OverlayManager::CustomDialogRecordEvent(const DialogProperties& dialogProps)
2461 {
2462     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
2463         Recorder::EventParamsBuilder builder;
2464         builder
2465             .SetType("Dialog")
2466             .SetEventType(Recorder::EventType::DIALOG_SHOW)
2467             .SetExtra(Recorder::KEY_TITLE, dialogProps.title)
2468             .SetExtra(Recorder::KEY_SUB_TITLE, dialogProps.subtitle);
2469         Recorder::EventRecorder::Get().OnEvent(std::move(builder));
2470     }
2471 }
2472 
RebuildCustomBuilder(RefPtr<UINode> & contentNode)2473 RefPtr<UINode> OverlayManager::RebuildCustomBuilder(RefPtr<UINode>& contentNode)
2474 {
2475     auto currentId = Container::CurrentId();
2476     if (!(currentId >= MIN_SUBCONTAINER_ID && currentId < MIN_PLUGIN_SUBCONTAINER_ID)) {
2477         return contentNode;
2478     }
2479 
2480     RefPtr<UINode> customNode;
2481     auto lazyBuilderFunc = contentNode->GetBuilderFunc();
2482     if (lazyBuilderFunc) {
2483         NG::ScopedViewStackProcessor builderViewStackProcessor;
2484         lazyBuilderFunc();
2485         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
2486     } else {
2487         customNode = contentNode;
2488     }
2489 
2490     auto updateNodeFunc = contentNode->GetUpdateNodeFunc();
2491     if (updateNodeFunc) {
2492         updateNodeFunc(currentId, customNode);
2493     }
2494     auto updateNodeConfig = contentNode->GetUpdateNodeConfig();
2495     if (updateNodeConfig) {
2496         customNode->SetUpdateNodeConfig(std::move(updateNodeConfig));
2497     }
2498     return customNode;
2499 }
2500 
ReloadBuilderNodeConfig()2501 void OverlayManager::ReloadBuilderNodeConfig()
2502 {
2503     if (dialogMap_.empty()) {
2504         return;
2505     }
2506     auto iter = dialogMap_.begin();
2507     while (iter != dialogMap_.end()) {
2508         auto dialogNode = (*iter).second;
2509         if (dialogNode) {
2510             auto dialogPattern = dialogNode->GetPattern<DialogPattern>();
2511             CHECK_NULL_VOID(dialogPattern);
2512             auto customNode = dialogPattern->GetCustomNode();
2513             if (customNode && customNode->GetUpdateNodeConfig()) {
2514                 customNode->GetUpdateNodeConfig()();
2515             }
2516         }
2517         iter++;
2518     }
2519 }
2520 
OpenCustomDialog(const DialogProperties & dialogProps,std::function<void (int32_t)> && callback)2521 void OverlayManager::OpenCustomDialog(const DialogProperties& dialogProps, std::function<void(int32_t)> &&callback)
2522 {
2523     RefPtr<UINode> customNode;
2524     bool showComponentContent = false;
2525     if (!callback) {
2526         TAG_LOGE(AceLogTag::ACE_DIALOG, "Parameters of OpenCustomDialog are incomplete because of no callback.");
2527         return;
2528     }
2529     if (dialogProps.customBuilder) {
2530         TAG_LOGD(AceLogTag::ACE_DIALOG, "open custom dialog with custom builder.");
2531         NG::ScopedViewStackProcessor builderViewStackProcessor(Container::CurrentId());
2532         dialogProps.customBuilder();
2533         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
2534         if (!customNode) {
2535             TAG_LOGE(AceLogTag::ACE_DIALOG, "Fail to build custom node.");
2536             callback(-1);
2537             return;
2538         }
2539     } else {
2540         auto contentNode = dialogProps.contentNode.Upgrade();
2541         if (!contentNode) {
2542             TAG_LOGE(AceLogTag::ACE_DIALOG, "Content of custom dialog is null");
2543             callback(ERROR_CODE_DIALOG_CONTENT_ERROR);
2544             return;
2545         }
2546         if (GetDialogNodeWithExistContent(contentNode)) {
2547             TAG_LOGW(AceLogTag::ACE_DIALOG, "Content of custom dialog already existed.");
2548             callback(ERROR_CODE_DIALOG_CONTENT_ALREADY_EXIST);
2549             return;
2550         }
2551         TAG_LOGD(AceLogTag::ACE_DIALOG, "OpenCustomDialog ComponentContent id: %{public}d", contentNode->GetId());
2552         customNode = RebuildCustomBuilder(contentNode);
2553         showComponentContent = true;
2554     }
2555     auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
2556     if (!dialog) {
2557         TAG_LOGE(AceLogTag::ACE_DIALOG, "Fail to create dialog node.");
2558         callback(showComponentContent ? ERROR_CODE_DIALOG_CONTENT_ERROR : -1);
2559         return;
2560     }
2561     RegisterDialogLifeCycleCallback(dialog, dialogProps);
2562     BeforeShowDialog(dialog);
2563 
2564     callback(showComponentContent ? ERROR_CODE_NO_ERROR : dialog->GetId());
2565 
2566     if (dialogProps.transitionEffect != nullptr) {
2567         SetDialogTransitionEffect(dialog);
2568     } else {
2569         OpenDialogAnimation(dialog);
2570     }
2571 
2572     dialogCount_++;
2573     CustomDialogRecordEvent(dialogProps);
2574     return;
2575 }
2576 
CloseCustomDialog(const int32_t dialogId)2577 void OverlayManager::CloseCustomDialog(const int32_t dialogId)
2578 {
2579     auto iter = dialogMap_.end();
2580     if (dialogId == -1) {
2581         int32_t tmpNodeId = -1;
2582         RefPtr<FrameNode> tmpNode;
2583         iter = dialogMap_.begin();
2584         while (iter != dialogMap_.end()) {
2585             auto dialogNode = (*iter).second;
2586             if (dialogNode && dialogNode->GetId() > tmpNodeId) {
2587                 tmpNodeId = dialogNode->GetId();
2588                 tmpNode = dialogNode;
2589             }
2590             iter++;
2591         }
2592         if (tmpNode) {
2593             DeleteDialogHotAreas(tmpNode);
2594             CloseDialogInner(tmpNode);
2595         } else {
2596             TAG_LOGE(AceLogTag::ACE_DIALOG, "not find dialog when no dialog id");
2597         }
2598     } else {
2599         iter = dialogMap_.find(dialogId);
2600         if (iter == dialogMap_.end()) {
2601             TAG_LOGE(AceLogTag::ACE_DIALOG, "not find dialog by id %{public}d", dialogId);
2602             return;
2603         }
2604         RefPtr<FrameNode> tmpDialog = (*iter).second;
2605         DeleteDialogHotAreas(tmpDialog);
2606         CloseDialogInner(tmpDialog);
2607     }
2608     return;
2609 }
2610 
CloseCustomDialog(const WeakPtr<NG::UINode> & node,std::function<void (int32_t)> && callback)2611 void OverlayManager::CloseCustomDialog(const WeakPtr<NG::UINode>& node, std::function<void(int32_t)> &&callback)
2612 {
2613     if (!callback) {
2614         TAG_LOGE(AceLogTag::ACE_DIALOG, "Parameters of CloseCustomDialog are incomplete because of no callback.");
2615         return;
2616     }
2617     auto contentNode = node.Upgrade();
2618     if (!contentNode) {
2619         TAG_LOGE(AceLogTag::ACE_DIALOG, "Content of custom dialog is null");
2620         callback(ERROR_CODE_DIALOG_CONTENT_ERROR);
2621         return;
2622     }
2623     TAG_LOGD(AceLogTag::ACE_DIALOG, "CloseCustomDialog ComponentContent id: %{public}d", contentNode->GetId());
2624     auto dialogNode = GetDialogNodeWithExistContent(contentNode);
2625     if (!dialogNode) {
2626         dialogNode = SubwindowManager::GetInstance()->GetSubwindowDialogNodeWithExistContent(contentNode);
2627     }
2628     if (dialogNode) {
2629         DeleteDialogHotAreas(dialogNode);
2630         CloseDialogInner(dialogNode);
2631         callback(ERROR_CODE_NO_ERROR);
2632         return;
2633     }
2634     TAG_LOGE(AceLogTag::ACE_DIALOG, "UpdateCustomDialog failed because cannot find dialog.");
2635     callback(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND);
2636 }
2637 
UpdateCustomDialog(const WeakPtr<NG::UINode> & node,const DialogProperties & dialogProps,std::function<void (int32_t)> && callback)2638 void OverlayManager::UpdateCustomDialog(
2639     const WeakPtr<NG::UINode>& node, const DialogProperties& dialogProps, std::function<void(int32_t)> &&callback)
2640 {
2641     if (!callback) {
2642         TAG_LOGE(AceLogTag::ACE_DIALOG, "Parameters of UpdateCustomDialog are incomplete because of no callback.");
2643         return;
2644     }
2645     auto contentNode = node.Upgrade();
2646     if (!contentNode) {
2647         TAG_LOGE(AceLogTag::ACE_DIALOG, "Content of custom dialog is null");
2648         callback(ERROR_CODE_DIALOG_CONTENT_ERROR);
2649         return;
2650     }
2651     TAG_LOGD(AceLogTag::ACE_DIALOG, "UpdateCustomDialog ComponentContent id: %{public}d", contentNode->GetId());
2652     auto dialogNode = GetDialogNodeWithExistContent(contentNode);
2653     if (!dialogNode) {
2654         dialogNode = SubwindowManager::GetInstance()->GetSubwindowDialogNodeWithExistContent(contentNode);
2655     }
2656     if (dialogNode) {
2657         auto dialogLayoutProp = AceType::DynamicCast<DialogLayoutProperty>(dialogNode->GetLayoutProperty());
2658         CHECK_NULL_VOID(dialogLayoutProp);
2659         dialogLayoutProp->UpdateDialogAlignment(dialogProps.alignment);
2660         dialogLayoutProp->UpdateDialogOffset(dialogProps.offset);
2661         dialogLayoutProp->UpdateAutoCancel(dialogProps.autoCancel);
2662         auto dialogContext = dialogNode->GetRenderContext();
2663         CHECK_NULL_VOID(dialogContext);
2664         auto pipelineContext = dialogNode->GetContext();
2665         CHECK_NULL_VOID(pipelineContext);
2666         auto dialogTheme = pipelineContext->GetTheme<DialogTheme>();
2667         CHECK_NULL_VOID(dialogTheme);
2668         dialogContext->UpdateBackgroundColor(dialogProps.maskColor.value_or(dialogTheme->GetMaskColorEnd()));
2669         dialogNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2670 
2671         callback(ERROR_CODE_NO_ERROR);
2672         return;
2673     }
2674     TAG_LOGE(AceLogTag::ACE_DIALOG, "CloseCustomDialog failed because cannot find dialog.");
2675     callback(ERROR_CODE_DIALOG_CONTENT_NOT_FOUND);
2676 }
2677 
ShowCustomDialog(const RefPtr<FrameNode> & customNode)2678 void OverlayManager::ShowCustomDialog(const RefPtr<FrameNode>& customNode)
2679 {
2680     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show custom dialog enter");
2681     BeforeShowDialog(customNode);
2682     OpenDialogAnimation(customNode);
2683 }
2684 
RegisterDialogCallback(const RefPtr<FrameNode> & node,std::map<std::string,NG::DialogCancelEvent> dialogLifeCycleEvent)2685 void RegisterDialogCallback(
2686     const RefPtr<FrameNode>& node, std::map<std::string, NG::DialogCancelEvent> dialogLifeCycleEvent)
2687 {
2688     CHECK_NULL_VOID(node);
2689     auto pipeline = PipelineContext::GetCurrentContext();
2690     CHECK_NULL_VOID(pipeline);
2691     auto theme = pipeline->GetTheme<DialogTheme>();
2692     CHECK_NULL_VOID(theme);
2693     auto dialogPattern = node->GetPattern<DialogPattern>();
2694     if (!dialogLifeCycleEvent.empty()) {
2695         auto didAppearEvent = dialogLifeCycleEvent["didAppearId"];
2696         auto didDisappearEvent = dialogLifeCycleEvent["didDisappearId"];
2697         auto willAppearEvent = dialogLifeCycleEvent["willAppearId"];
2698         auto willDisappearEvent = dialogLifeCycleEvent["willDisappearId"];
2699         dialogPattern->RegisterDialogDidAppearCallback(std::move(didAppearEvent));
2700         dialogPattern->RegisterDialogDidDisappearCallback(std::move(didDisappearEvent));
2701         dialogPattern->RegisterDialogWillAppearCallback(std::move(willAppearEvent));
2702         dialogPattern->RegisterDialogWillDisappearCallback(std::move(willDisappearEvent));
2703     }
2704 }
2705 
ShowDateDialog(const DialogProperties & dialogProps,const DatePickerSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent,std::map<std::string,NG::DialogCancelEvent> dialogLifeCycleEvent,const std::vector<ButtonInfo> & buttonInfos)2706 void OverlayManager::ShowDateDialog(const DialogProperties& dialogProps, const DatePickerSettingData& settingData,
2707     std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent,
2708     std::map<std::string, NG::DialogCancelEvent> dialogLifeCycleEvent, const std::vector<ButtonInfo>& buttonInfos)
2709 {
2710     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show date dialog enter");
2711     auto dialogNode = DatePickerDialogView::Show(
2712         dialogProps, std::move(settingData), buttonInfos, std::move(dialogEvent), std::move(dialogCancelEvent));
2713     RegisterDialogCallback(dialogNode, std::move(dialogLifeCycleEvent));
2714     BeforeShowDialog(dialogNode);
2715     OpenDialogAnimation(dialogNode);
2716 }
2717 
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,std::map<std::string,NG::DialogCancelEvent> dialogLifeCycleEvent,const std::vector<ButtonInfo> & buttonInfos)2718 void OverlayManager::ShowTimeDialog(const DialogProperties& dialogProps, const TimePickerSettingData& settingData,
2719     std::map<std::string, PickerTime> timePickerProperty, std::map<std::string, NG::DialogEvent> dialogEvent,
2720     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent,
2721     std::map<std::string, NG::DialogCancelEvent> dialogLifeCycleEvent, const std::vector<ButtonInfo>& buttonInfos)
2722 {
2723     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show time dialog enter");
2724     auto dialogNode = TimePickerDialogView::Show(dialogProps, settingData, buttonInfos, std::move(timePickerProperty),
2725         std::move(dialogEvent), std::move(dialogCancelEvent));
2726     RegisterDialogCallback(dialogNode, std::move(dialogLifeCycleEvent));
2727     BeforeShowDialog(dialogNode);
2728     OpenDialogAnimation(dialogNode);
2729 }
2730 
ShowTextDialog(const DialogProperties & dialogProps,const TextPickerSettingData & settingData,std::map<std::string,NG::DialogTextEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent,std::map<std::string,NG::DialogCancelEvent> dialogLifeCycleEvent,const std::vector<ButtonInfo> & buttonInfos)2731 void OverlayManager::ShowTextDialog(const DialogProperties& dialogProps, const TextPickerSettingData& settingData,
2732     std::map<std::string, NG::DialogTextEvent> dialogEvent,
2733     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent,
2734     std::map<std::string, NG::DialogCancelEvent> dialogLifeCycleEvent, const std::vector<ButtonInfo>& buttonInfos)
2735 {
2736     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show text dialog enter");
2737     auto dialogNode = TextPickerDialogView::Show(
2738         dialogProps, settingData, buttonInfos, std::move(dialogEvent), std::move(dialogCancelEvent));
2739     RegisterDialogCallback(dialogNode, std::move(dialogLifeCycleEvent));
2740     BeforeShowDialog(dialogNode);
2741     OpenDialogAnimation(dialogNode);
2742     if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
2743         Recorder::EventParamsBuilder builder;
2744         builder.SetType("TextPickerDialog").SetEventType(Recorder::EventType::DIALOG_SHOW);
2745         Recorder::EventRecorder::Get().OnEvent(std::move(builder));
2746     }
2747 }
2748 
ShowCalendarDialog(const DialogProperties & dialogProps,const CalendarSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent,std::map<std::string,NG::DialogCancelEvent> dialogLifeCycleEvent,const std::vector<ButtonInfo> & buttonInfos)2749 void OverlayManager::ShowCalendarDialog(const DialogProperties& dialogProps, const CalendarSettingData& settingData,
2750     std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent,
2751     std::map<std::string, NG::DialogCancelEvent> dialogLifeCycleEvent, const std::vector<ButtonInfo>& buttonInfos)
2752 {
2753     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show calendar dialog enter");
2754     auto dialogNode = CalendarDialogView::Show(dialogProps, settingData,
2755         buttonInfos, std::move(dialogEvent), std::move(dialogCancelEvent));
2756     RegisterDialogCallback(dialogNode, std::move(dialogLifeCycleEvent));
2757     BeforeShowDialog(dialogNode);
2758     OpenDialogAnimation(dialogNode);
2759 }
2760 
PopModalDialog(int32_t maskId)2761 void OverlayManager::PopModalDialog(int32_t maskId)
2762 {
2763     TAG_LOGD(AceLogTag::ACE_OVERLAY, "pop modal dialog enter");
2764     int32_t dialogId = -1;
2765     for (auto it = maskNodeIdMap_.begin(); it != maskNodeIdMap_.end(); it++) {
2766         if (maskId == it->second) {
2767             dialogId = it->first;
2768             break;
2769         }
2770     }
2771     auto subWindow = SubwindowManager::GetInstance()->GetSubwindow(subWindowId_);
2772     CHECK_NULL_VOID(subWindow);
2773     auto subOverlayManager = subWindow->GetOverlayManager();
2774     CHECK_NULL_VOID(subOverlayManager);
2775     std::map<int32_t, RefPtr<FrameNode>> DialogMap(
2776         subOverlayManager->GetDialogMap().begin(), subOverlayManager->GetDialogMap().end());
2777     for (auto it = DialogMap.begin(); it != DialogMap.end(); it++) {
2778         auto dialogProp = DynamicCast<DialogLayoutProperty>(it->second->GetLayoutProperty());
2779         if (dialogId == it->first) {
2780             auto hub = it->second->GetEventHub<DialogEventHub>();
2781             if (hub) {
2782                 hub->FireCancelEvent();
2783             }
2784             subOverlayManager->CloseDialog(it->second);
2785         }
2786     }
2787 }
2788 
RemoveDialogFromMap(const RefPtr<FrameNode> & node)2789 void OverlayManager::RemoveDialogFromMap(const RefPtr<FrameNode>& node)
2790 {
2791     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove dialog from map enter");
2792     CHECK_NULL_VOID(node);
2793     if (dialogMap_.find(node->GetId()) == dialogMap_.end()) {
2794         return;
2795     }
2796     dialogMap_.erase(node->GetId());
2797 }
2798 
RemoveMaskFromMap(const RefPtr<FrameNode> & dialogNode)2799 void OverlayManager::RemoveMaskFromMap(const RefPtr<FrameNode>& dialogNode)
2800 {
2801     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove mask from map enter");
2802     CHECK_NULL_VOID(dialogNode);
2803     if (maskNodeIdMap_.find(dialogNode->GetId()) == maskNodeIdMap_.end()) {
2804         return;
2805     }
2806     maskNodeIdMap_.erase(dialogNode->GetId());
2807 }
2808 
DialogInMapHoldingFocus()2809 bool OverlayManager::DialogInMapHoldingFocus()
2810 {
2811     TAG_LOGD(AceLogTag::ACE_OVERLAY, "dialog in map holding focus enter");
2812     if (dialogMap_.empty()) {
2813         return false;
2814     }
2815     auto iter = dialogMap_.begin();
2816     while (iter != dialogMap_.end()) {
2817         auto dialogNode = (*iter).second;
2818         if (dialogNode && dialogNode->GetFocusHub() && dialogNode->GetFocusHub()->IsCurrentFocus()) {
2819             return true;
2820         }
2821         iter++;
2822     }
2823     return false;
2824 }
2825 
HasModalPage()2826 bool OverlayManager::HasModalPage()
2827 {
2828     if (modalList_.empty()) {
2829         return false;
2830     }
2831     for (auto modal : modalList_) {
2832         if (modal.Upgrade() && modal.Upgrade()->GetTag() == V2::MODAL_PAGE_TAG) {
2833             return true;
2834         }
2835     }
2836     return false;
2837 }
2838 
GetDialog(int32_t dialogId)2839 RefPtr<FrameNode> OverlayManager::GetDialog(int32_t dialogId)
2840 {
2841     TAG_LOGD(AceLogTag::ACE_OVERLAY, "get dialog enter");
2842     for (auto it = dialogMap_.begin(); it != dialogMap_.end(); it++) {
2843         if (dialogId == it->second->GetId()) {
2844             return it->second;
2845         }
2846     }
2847     return nullptr;
2848 }
2849 
CloseDialog(const RefPtr<FrameNode> & dialogNode)2850 void OverlayManager::CloseDialog(const RefPtr<FrameNode>& dialogNode)
2851 {
2852     TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog enter");
2853     DeleteDialogHotAreas(dialogNode);
2854     auto dialogLayoutProp = AceType::DynamicCast<DialogLayoutProperty>(dialogNode->GetLayoutProperty());
2855     CHECK_NULL_VOID(dialogLayoutProp);
2856     if (dialogLayoutProp && dialogLayoutProp->GetShowInSubWindowValue(false) &&
2857         dialogLayoutProp->GetIsModal().value_or(true)) {
2858         RefPtr<OverlayManager> parentOverlayManager = nullptr;
2859 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
2860         auto container = Container::Current();
2861         auto currentId = Container::CurrentId();
2862         CHECK_NULL_VOID(container);
2863         if (container->IsSubContainer()) {
2864             currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
2865             container = AceEngine::Get().GetContainer(currentId);
2866             CHECK_NULL_VOID(container);
2867         }
2868         ContainerScope scope(currentId);
2869         auto pipelineContext = container->GetPipelineContext();
2870         CHECK_NULL_VOID(pipelineContext);
2871         auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
2872         CHECK_NULL_VOID(context);
2873         parentOverlayManager = context->GetOverlayManager();
2874 #else
2875         auto parentPipelineContext = PipelineContext::GetMainPipelineContext();
2876         CHECK_NULL_VOID(parentPipelineContext);
2877         parentOverlayManager = parentPipelineContext->GetOverlayManager();
2878 #endif
2879         CHECK_NULL_VOID(parentOverlayManager);
2880         RefPtr<FrameNode> maskNode =
2881             parentOverlayManager->GetDialog(parentOverlayManager->GetMaskNodeIdWithDialogId(dialogNode->GetId()));
2882         if (maskNode) {
2883             parentOverlayManager->CloseDialog(maskNode);
2884         } else {
2885             TAG_LOGD(AceLogTag::ACE_OVERLAY, "no maskNode in currentDialog/%{public}d", dialogNode->GetId());
2886         }
2887     }
2888     CloseDialogInner(dialogNode);
2889 }
2890 
DeleteDialogHotAreas(const RefPtr<FrameNode> & dialogNode)2891 void OverlayManager::DeleteDialogHotAreas(const RefPtr<FrameNode>& dialogNode)
2892 {
2893     auto dialogLayoutProp = AceType::DynamicCast<DialogLayoutProperty>(dialogNode->GetLayoutProperty());
2894     CHECK_NULL_VOID(dialogLayoutProp);
2895     if (dialogLayoutProp->GetShowInSubWindowValue(false)) {
2896         SubwindowManager::GetInstance()->DeleteHotAreas(
2897             SubwindowManager::GetInstance()->GetDialogSubWindowId(), dialogNode->GetId());
2898         SubwindowManager::GetInstance()->HideDialogSubWindow(
2899             SubwindowManager::GetInstance()->GetDialogSubWindowId());
2900     }
2901 }
2902 
CloseDialogInner(const RefPtr<FrameNode> & dialogNode)2903 void OverlayManager::CloseDialogInner(const RefPtr<FrameNode>& dialogNode)
2904 {
2905     RemoveDialogFromMap(dialogNode);
2906     if (dialogNode->IsRemoving()) {
2907         // already in close animation
2908         TAG_LOGW(AceLogTag::ACE_DIALOG, "dialogNode/%{public}d is removing", dialogNode->GetId());
2909         return;
2910     }
2911     dialogNode->MarkRemoving();
2912 
2913     auto container = Container::Current();
2914     auto currentId = Container::CurrentId();
2915     CHECK_NULL_VOID(container);
2916     if (container->IsSubContainer()) {
2917         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
2918         container = AceEngine::Get().GetContainer(currentId);
2919         CHECK_NULL_VOID(container);
2920     }
2921     ContainerScope scope(currentId);
2922     auto pipelineContext = container->GetPipelineContext();
2923     CHECK_NULL_VOID(pipelineContext);
2924     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
2925     CHECK_NULL_VOID(context);
2926     auto overlayManager = context->GetOverlayManager();
2927     CHECK_NULL_VOID(overlayManager);
2928     overlayManager->ResetLowerNodeFocusable(dialogNode);
2929     auto dialogPattern = dialogNode->GetPattern<DialogPattern>();
2930     CHECK_NULL_VOID(dialogPattern);
2931     auto transitionEffect = dialogPattern->GetDialogProperties().transitionEffect;
2932     if (transitionEffect != nullptr) {
2933         CloseDialogMatchTransition(dialogNode);
2934     } else {
2935         CloseDialogAnimation(dialogNode);
2936     }
2937     dialogCount_--;
2938     overlayManager->RemoveMaskFromMap(dialogNode);
2939     // set close button enable
2940     if (dialogCount_ == 0) {
2941         SetContainerButtonEnable(true);
2942     }
2943     CallOnHideDialogCallback();
2944 }
2945 
RemoveDialog(const RefPtr<FrameNode> & overlay,bool isBackPressed,bool isPageRouter)2946 bool OverlayManager::RemoveDialog(const RefPtr<FrameNode>& overlay, bool isBackPressed, bool isPageRouter)
2947 {
2948     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove dialog enter");
2949     if (overlay->IsRemoving()) {
2950         return false;
2951     }
2952     if (FireBackPressEvent()) {
2953         return true;
2954     }
2955     auto hub = overlay->GetEventHub<DialogEventHub>();
2956     if (!isPageRouter && hub) {
2957         hub->FireCancelEvent();
2958     }
2959     CloseDialog(overlay);
2960     if (isBackPressed) {
2961         SetBackPressEvent(nullptr);
2962     }
2963     return true;
2964 }
2965 
PopupInteractiveDismiss(const RefPtr<FrameNode> & overlay)2966 bool OverlayManager::PopupInteractiveDismiss(const RefPtr<FrameNode>& overlay)
2967 {
2968     auto bubblePattern = overlay->GetPattern<BubblePattern>();
2969     CHECK_NULL_RETURN(bubblePattern, false);
2970     return !bubblePattern->GetInteractiveDismiss();
2971 }
2972 
PopupCallBackOnWillDismiss(const RefPtr<FrameNode> & overlay)2973 bool OverlayManager::PopupCallBackOnWillDismiss(const RefPtr<FrameNode>& overlay)
2974 {
2975     auto bubblePattern = overlay->GetPattern<BubblePattern>();
2976     CHECK_NULL_RETURN(bubblePattern, false);
2977     if (bubblePattern->HasOnWillDismiss()) {
2978         int32_t dismissPopupId = GetPopupIdByNode(overlay);
2979         SetDismissPopupId(dismissPopupId);
2980         bubblePattern->CallOnWillDismiss(static_cast<int32_t>(DismissReason::BACK_PRESSED));
2981         return true;
2982     }
2983     return false;
2984 }
2985 
RemoveBubble(const RefPtr<FrameNode> & overlay)2986 bool OverlayManager::RemoveBubble(const RefPtr<FrameNode>& overlay)
2987 {
2988     TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove bubble enter");
2989     if (PopupInteractiveDismiss(overlay)) {
2990         return true;
2991     }
2992     if (PopupCallBackOnWillDismiss(overlay)) {
2993         return true;
2994     }
2995     for (const auto& popup : popupMap_) {
2996         auto targetId = popup.first;
2997         auto popupInfo = popup.second;
2998         if (overlay == popupInfo.popupNode) {
2999             popupInfo.markNeedUpdate = true;
3000             HidePopup(targetId, popupInfo);
3001             return true;
3002         }
3003     }
3004     return false;
3005 }
3006 
RemoveMenu(const RefPtr<FrameNode> & overlay)3007 bool OverlayManager::RemoveMenu(const RefPtr<FrameNode>& overlay)
3008 {
3009     TAG_LOGI(AceLogTag::ACE_OVERLAY, "remove menu enter");
3010     auto menuWrapperPattern = overlay->GetPattern<MenuWrapperPattern>();
3011     CHECK_NULL_RETURN(menuWrapperPattern, false);
3012     menuWrapperPattern->UpdateMenuAnimation(overlay);
3013     menuWrapperPattern->HideMenu();
3014     return true;
3015 }
3016 
RemoveDragPreview(const RefPtr<FrameNode> & overlay)3017 bool OverlayManager::RemoveDragPreview(const RefPtr<FrameNode>& overlay)
3018 {
3019     TAG_LOGI(AceLogTag::ACE_OVERLAY, "remove dragPreview enter");
3020     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
3021     if (columnNode != overlay) {
3022         return false;
3023     }
3024     RemoveEventColumn();
3025     RemovePixelMap();
3026     RemoveGatherNode();
3027     return true;
3028 }
3029 
GetPopupIdByNode(const RefPtr<FrameNode> & overlay)3030 int32_t OverlayManager::GetPopupIdByNode(const RefPtr<FrameNode>& overlay)
3031 {
3032     TAG_LOGD(AceLogTag::ACE_OVERLAY, "GetPopupIdByNode IN");
3033     int32_t targetId = -1;
3034     for (const auto& popup : popupMap_) {
3035         targetId = popup.first;
3036         auto popupInfo = popup.second;
3037         if (overlay == popupInfo.popupNode) {
3038             return targetId;
3039         }
3040     }
3041     return targetId;
3042 }
3043 
RemoveOverlayCommon(const RefPtr<NG::UINode> & rootNode,RefPtr<NG::FrameNode> & overlay,RefPtr<Pattern> & pattern,bool isBackPressed,bool isPageRouter)3044 int32_t OverlayManager::RemoveOverlayCommon(const RefPtr<NG::UINode>& rootNode, RefPtr<NG::FrameNode>& overlay,
3045     RefPtr<Pattern>& pattern, bool isBackPressed, bool isPageRouter)
3046 {
3047     const size_t size = rootNode->GetChildren().size();
3048     if (size == 0) {
3049         return OVERLAY_EXISTS;
3050     }
3051     auto currentIndex = size - 1;
3052     while (InstanceOf<ToastPattern>(pattern)) {
3053         // still have nodes on root expect stage and toast node.
3054         if (currentIndex > 0) {
3055             currentIndex = currentIndex - 1;
3056             overlay = DynamicCast<FrameNode>(rootNode->GetChildAtIndex(currentIndex));
3057             CHECK_NULL_RETURN(overlay, OVERLAY_EXISTS);
3058             pattern = overlay->GetPattern();
3059         } else {
3060             return OVERLAY_EXISTS;
3061         }
3062     }
3063     CHECK_EQUAL_RETURN(overlay->GetTag(), V2::STAGE_ETS_TAG, OVERLAY_EXISTS);
3064     CHECK_EQUAL_RETURN(overlay->GetTag(), V2::OVERLAY_ETS_TAG, OVERLAY_EXISTS);
3065     CHECK_EQUAL_RETURN(overlay->GetTag(), V2::ATOMIC_SERVICE_ETS_TAG, OVERLAY_EXISTS);
3066     // close dialog with animation
3067     if (InstanceOf<DialogPattern>(pattern)) {
3068         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) && isPageRouter) {
3069             return OVERLAY_EXISTS;
3070         }
3071         auto dialogPattern = DynamicCast<DialogPattern>(pattern);
3072         CHECK_NULL_RETURN(dialogPattern, OVERLAY_EXISTS);
3073         if (dialogPattern->CallDismissInNDK(static_cast<int32_t>(DialogDismissReason::DIALOG_PRESS_BACK))) {
3074             return OVERLAY_REMOVE;
3075         } else if (dialogPattern->ShouldDismiss()) {
3076             SetDismissDialogId(overlay->GetId());
3077             dialogPattern->CallOnWillDismiss(static_cast<int32_t>(DialogDismissReason::DIALOG_PRESS_BACK));
3078             TAG_LOGI(AceLogTag::ACE_OVERLAY, "Dialog Should Dismiss");
3079             return OVERLAY_REMOVE;
3080         }
3081         return RemoveDialog(overlay, isBackPressed, isPageRouter) ? OVERLAY_REMOVE : OVERLAY_EXISTS;
3082     }
3083     if (InstanceOf<BubblePattern>(pattern)) {
3084         return RemoveBubble(overlay) ? OVERLAY_REMOVE : OVERLAY_EXISTS;
3085     }
3086     if (InstanceOf<MenuWrapperPattern>(pattern)) {
3087         RemoveDragPreview(overlay);
3088         return RemoveMenu(overlay) ? OVERLAY_REMOVE : OVERLAY_EXISTS;
3089     }
3090     if (InstanceOf<LinearLayoutPattern>(pattern)) {
3091         return RemoveDragPreview(overlay) ? OVERLAY_REMOVE : OVERLAY_NOTHING;
3092     }
3093     return OVERLAY_NOTHING;
3094 }
3095 
RemoveOverlay(bool isBackPressed,bool isPageRouter)3096 bool OverlayManager::RemoveOverlay(bool isBackPressed, bool isPageRouter)
3097 {
3098     auto rootNode = rootNodeWeak_.Upgrade();
3099     CHECK_NULL_RETURN(rootNode, true);
3100     RemoveIndexerPopup();
3101     SetDragNodeNeedClean();
3102     auto pipeline = rootNode->GetContextRefPtr();
3103     CHECK_NULL_RETURN(pipeline, false);
3104     // There is overlay under the root node or it is in atomicservice
3105     if (rootNode->GetChildren().size() > ROOT_MIN_NODE || pipeline->GetInstallationFree()) {
3106         // stage node is at index 0, remove overlay at last
3107         auto overlay = GetOverlayFrameNode();
3108         CHECK_NULL_RETURN(overlay, false);
3109         auto pattern = overlay->GetPattern();
3110         auto ret = RemoveOverlayCommon(rootNode, overlay, pattern, isBackPressed, isPageRouter);
3111         if (ret == OVERLAY_REMOVE) {
3112             return true;
3113         } else if (ret == OVERLAY_EXISTS) {
3114             return false;
3115         }
3116         ret = ExceptComponent(rootNode, overlay, isBackPressed, isPageRouter);
3117         if (ret == OVERLAY_REMOVE) {
3118             return true;
3119         } else if (ret == OVERLAY_EXISTS) {
3120             return false;
3121         }
3122         // remove navDestination in navigation first
3123         do {
3124             CHECK_NULL_BREAK(rootNode->GetTag() != V2::NAVDESTINATION_VIEW_ETS_TAG);
3125             bool isEntry = false;
3126             auto navigationGroupNode =
3127                 AceType::DynamicCast<NavigationGroupNode>(pipeline->FindNavigationNodeToHandleBack(overlay, isEntry));
3128             CHECK_NULL_BREAK(navigationGroupNode);
3129             return true;
3130         } while (0);
3131         if (!modalStack_.empty()) {
3132             TAG_LOGI(AceLogTag::ACE_SHEET, "Modal consumed backpressed event");
3133             if (isPageRouter) {
3134                 return RemoveAllModalInOverlay();
3135             } else {
3136                 return RemoveModalInOverlay();
3137             }
3138         }
3139         if (!InstanceOf<KeyboardPattern>(pattern)) {
3140             if (overlay->GetTag() != V2::SHEET_WRAPPER_TAG) {
3141                 rootNode->RemoveChild(overlay);
3142             }
3143             rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3144             return true;
3145         }
3146     }
3147     return false;
3148 }
3149 
GetOverlayFrameNode()3150 RefPtr<FrameNode> OverlayManager::GetOverlayFrameNode()
3151 {
3152     auto rootNode = rootNodeWeak_.Upgrade();
3153     CHECK_NULL_RETURN(rootNode, nullptr);
3154     auto pipeline = rootNode->GetContextRefPtr();
3155     CHECK_NULL_RETURN(pipeline, nullptr);
3156     auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
3157     // There is no overlay under the root node or it is not in atomicservice
3158     if (!pipeline->GetInstallationFree() || rootNode->GetChildren().size() > ROOT_MIN_NODE) {
3159         return overlay;
3160     }
3161     for (auto child : rootNode->GetChildren()) {
3162         if (child->GetTag() == V2::ATOMIC_SERVICE_ETS_TAG) {
3163             auto atomicNode = child;
3164             CHECK_NULL_RETURN(atomicNode, nullptr);
3165             if (atomicNode->GetChildren().size() <= ATOMIC_SERVICE_MIN_SIZE) {
3166                 return nullptr;
3167             }
3168             overlay = DynamicCast<FrameNode>(
3169                 atomicNode->GetChildAtIndex(atomicNode->GetChildren().size() - ATOMIC_SERVICE_MIN_SIZE));
3170             break;
3171         }
3172     }
3173     return overlay;
3174 }
3175 
ExceptComponent(const RefPtr<NG::UINode> & rootNode,RefPtr<NG::FrameNode> & overlay,bool isBackPressed,bool isPageRouter)3176 int32_t OverlayManager::ExceptComponent(const RefPtr<NG::UINode>& rootNode, RefPtr<NG::FrameNode>& overlay,
3177     bool isBackPressed, bool isPageRouter)
3178 {
3179     auto pattern = overlay->GetPattern();
3180     if (InstanceOf<VideoFullScreenPattern>(pattern)) {
3181         auto videoPattern = DynamicCast<VideoFullScreenPattern>(pattern);
3182         CHECK_NULL_RETURN(videoPattern, OVERLAY_EXISTS);
3183         return videoPattern->ExitFullScreen() ? OVERLAY_REMOVE : OVERLAY_EXISTS;
3184     }
3185     // OVERLAY_REMOVE if popup was removed, OVERLAY_NOTHING if not handle it
3186     if (overlay->GetTag() == V2::SHEET_WRAPPER_TAG) {
3187         return WebBackward(overlay);
3188     }
3189     return OVERLAY_NOTHING;
3190 }
3191 
WebBackward(RefPtr<NG::FrameNode> & overlay)3192 int32_t OverlayManager::WebBackward(RefPtr<NG::FrameNode>& overlay)
3193 {
3194 #ifdef WEB_SUPPORTED
3195     RefPtr<NG::FrameNode> webNode;
3196     FindWebNode(overlay, webNode);
3197     if (webNode && InstanceOf<WebPattern>(webNode->GetPattern())) {
3198         auto webPattern = DynamicCast<WebPattern>(webNode->GetPattern());
3199         CHECK_NULL_RETURN(webPattern, OVERLAY_EXISTS);
3200         if (webPattern->Backward()) {
3201             return OVERLAY_REMOVE;
3202         }
3203     }
3204 #endif
3205     return OVERLAY_NOTHING;
3206 }
3207 
FindWebNode(const RefPtr<NG::UINode> & node,RefPtr<NG::FrameNode> & webNode)3208 void OverlayManager::FindWebNode(const RefPtr<NG::UINode>& node, RefPtr<NG::FrameNode>& webNode)
3209 {
3210     CHECK_NULL_VOID(node);
3211 
3212     if (webNode) {
3213         return;
3214     }
3215 
3216     auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
3217     if (frameNode && !frameNode->IsInternal() && frameNode->GetTag() == V2::WEB_ETS_TAG) {
3218         webNode = frameNode;
3219         return;
3220     }
3221 
3222     if (!node->GetChildren().empty()) {
3223         for (const auto& child : node->GetChildren()) {
3224             FindWebNode(child, webNode);
3225         }
3226     }
3227 }
3228 
RemoveModalInOverlay()3229 bool OverlayManager::RemoveModalInOverlay()
3230 {
3231     auto topModalNode = modalStack_.top().Upgrade();
3232     CHECK_NULL_RETURN(topModalNode, false);
3233     auto rootNode = FindWindowScene(topModalNode);
3234     CHECK_NULL_RETURN(rootNode, true);
3235     auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
3236     if (overlay && overlay->GetTag() == V2::SHEET_WRAPPER_TAG && overlay->GetFirstChild() != topModalNode) {
3237         TAG_LOGD(AceLogTag::ACE_SHEET, "Refuse to back because sheet is in animation");
3238         return true;
3239     }
3240     if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
3241         auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
3242         CHECK_NULL_RETURN(sheetPattern, false);
3243         sheetPattern->SheetInteractiveDismiss(BindSheetDismissReason::BACK_PRESSED);
3244         return true;
3245     } else if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
3246         auto modalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
3247         CHECK_NULL_RETURN(modalPattern, false);
3248         if (modalPattern->HasOnWillDismiss()) {
3249             modalPattern->ModalInteractiveDismiss();
3250             return true;
3251         }
3252     }
3253     ModalPageLostFocus(topModalNode);
3254     auto pattern = topModalNode->GetPattern<PopupBasePattern>();
3255     if (isProhibitBack_ && pattern->GetTargetId() < 0) {
3256         return true;
3257     }
3258     auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
3259     CHECK_NULL_RETURN(builder, false);
3260     if (!ModalExitProcess(topModalNode)) {
3261         return false;
3262     }
3263     PopTopModalNode();
3264     auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
3265     if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG && sheetPattern) {
3266         sheetMap_.erase(sheetPattern->GetSheetKey());
3267     }
3268     if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
3269         auto modalPattern = AceType::DynamicCast<ModalPresentationPattern>(pattern);
3270         CHECK_NULL_RETURN(modalPattern, false);
3271         auto modalTransition = modalPattern->GetType();
3272         if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
3273             // Fire shown event of navdestination under the disappeared modal
3274             FireNavigationStateChange(true);
3275         }
3276     }
3277     FireModalPageHide();
3278     SaveLastModalNode();
3279     return true;
3280 }
3281 
RemoveAllModalInOverlay()3282 bool OverlayManager::RemoveAllModalInOverlay()
3283 {
3284     if (modalStack_.empty()) {
3285         return true;
3286     }
3287 
3288     auto topModalNode = modalStack_.top().Upgrade();
3289     bool isModalUiextensionNode = IsModalUiextensionNode(topModalNode);
3290     bool isProhibitedRemoveByRouter = IsProhibitedRemoveByRouter(topModalNode);
3291     TAG_LOGI(AceLogTag::ACE_OVERLAY,
3292         "isModalUiextensionNode: %{public}d, isProhibitedRemoveByRouter: %{public}d,",
3293         isModalUiextensionNode, isProhibitedRemoveByRouter);
3294     if (isModalUiextensionNode && isProhibitedRemoveByRouter) {
3295         return RemoveAllModalInOverlayByList();
3296     }
3297 
3298     return RemoveAllModalInOverlayByStack();
3299 }
3300 
RemoveAllModalInOverlayByStack()3301 bool OverlayManager::RemoveAllModalInOverlayByStack()
3302 {
3303     while (!modalStack_.empty()) {
3304         auto topModalNode = modalStack_.top().Upgrade();
3305         if (!topModalNode) {
3306             modalStack_.pop();
3307             continue;
3308         }
3309         auto rootNode = FindWindowScene(topModalNode);
3310         CHECK_NULL_RETURN(rootNode, true);
3311         auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
3312         CHECK_NULL_RETURN(builder, false);
3313         ModalPageLostFocus(topModalNode);
3314         if (!ModalExitProcess(topModalNode)) {
3315             continue;
3316         }
3317         if (!modalStack_.empty()) {
3318             modalStack_.pop();
3319         }
3320         if (!modalList_.empty()) {
3321             modalList_.pop_back();
3322         }
3323 
3324         if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
3325             auto modalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
3326             CHECK_NULL_RETURN(modalPattern, false);
3327             auto modalTransition = modalPattern->GetType();
3328             if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
3329                 // Fire shown event of navdestination under the disappeared modal
3330                 FireNavigationStateChange(true);
3331             }
3332         }
3333         auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
3334         if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG && sheetPattern) {
3335             sheetMap_.erase(sheetPattern->GetSheetKey());
3336         }
3337         FireModalPageHide();
3338         SaveLastModalNode();
3339     }
3340     return true;
3341 }
3342 
RemoveAllModalInOverlayByList()3343 bool OverlayManager::RemoveAllModalInOverlayByList()
3344 {
3345     TAG_LOGI(AceLogTag::ACE_OVERLAY,
3346         "RemoveAllModalInOverlayByList modalStack size: %{public}zu, "
3347         "modalList size: %{public}zu", modalStack_.size(), modalList_.size());
3348     if (modalStack_.size() != modalList_.size()) {
3349         TAG_LOGI(AceLogTag::ACE_OVERLAY,
3350             "Not RemoveAllModalInOverlayByList due to modalStack not same with modalList.");
3351         return true;
3352     }
3353 
3354     bool ret = OnRemoveAllModalInOverlayByList();
3355     // To keep the modalStack consistent with the modalList
3356     AfterRemoveAllModalInOverlayByList();
3357     return ret;
3358 }
3359 
OnRemoveAllModalInOverlayByList()3360 bool OverlayManager::OnRemoveAllModalInOverlayByList()
3361 {
3362     auto modalIter = modalList_.begin();
3363     while (modalIter != modalList_.end()) {
3364         auto topModalNode = (*modalIter).Upgrade();
3365         if (!topModalNode) {
3366             modalIter = modalList_.erase(modalIter);
3367             continue;
3368         }
3369         if (IsModalUiextensionNode(topModalNode)) {
3370             break;
3371         }
3372         auto rootNode = FindWindowScene(topModalNode);
3373         CHECK_NULL_RETURN(rootNode, true);
3374         auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
3375         CHECK_NULL_RETURN(builder, false);
3376         ModalPageLostFocus(topModalNode);
3377         if (!ModalExitProcess(topModalNode)) {
3378             modalIter = modalList_.erase(modalIter);
3379             continue;
3380         }
3381         if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
3382             auto modalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
3383             CHECK_NULL_RETURN(modalPattern, false);
3384             auto modalTransition = modalPattern->GetType();
3385             if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
3386                 // Fire shown event of navdestination under the disappeared modal
3387                 FireNavigationStateChange(true);
3388             }
3389         }
3390         auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
3391         if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG && sheetPattern) {
3392             sheetMap_.erase(sheetPattern->GetSheetKey());
3393         }
3394         modalIter = modalList_.erase(modalIter);
3395     }
3396     return true;
3397 }
3398 
AfterRemoveAllModalInOverlayByList()3399 void OverlayManager::AfterRemoveAllModalInOverlayByList()
3400 {
3401     TAG_LOGI(AceLogTag::ACE_OVERLAY,
3402         "AfterRemoveAllModalInOverlayByList modalList size: %{public}zu", modalList_.size());
3403     std::stack<WeakPtr<FrameNode>> modalStack;
3404     modalStack_.swap(modalStack);
3405     for (auto modal = modalList_.begin(); modal != modalList_.end(); ++modal) {
3406         modalStack_.push(*modal);
3407     }
3408 }
3409 
IsModalUiextensionNode(const RefPtr<FrameNode> & topModalNode)3410 bool OverlayManager::IsModalUiextensionNode(const RefPtr<FrameNode>& topModalNode)
3411 {
3412     if (topModalNode == nullptr) {
3413         TAG_LOGI(AceLogTag::ACE_OVERLAY, "topModalNode is null,");
3414         return false;
3415     }
3416 
3417     if (topModalNode->GetTag() != V2::MODAL_PAGE_TAG) {
3418         TAG_LOGI(AceLogTag::ACE_OVERLAY, "topModalNode is not modalPage");
3419         return false;
3420     }
3421 
3422     auto modalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
3423     CHECK_NULL_RETURN(modalPattern, false);
3424     return modalPattern->IsUIExtension();
3425 }
3426 
IsProhibitedRemoveByRouter(const RefPtr<FrameNode> & topModalNode)3427 bool OverlayManager::IsProhibitedRemoveByRouter(const RefPtr<FrameNode>& topModalNode)
3428 {
3429     if (topModalNode == nullptr) {
3430         TAG_LOGI(AceLogTag::ACE_OVERLAY, "topModalNode is null,");
3431         return false;
3432     }
3433 
3434     if (topModalNode->GetTag() != V2::MODAL_PAGE_TAG) {
3435         TAG_LOGI(AceLogTag::ACE_OVERLAY, "topModalNode is not modalPage");
3436         return false;
3437     }
3438 
3439     auto modalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
3440     CHECK_NULL_RETURN(modalPattern, false);
3441     return modalPattern->IsProhibitedRemoveByRouter();
3442 }
3443 
3444 
ModalExitProcess(const RefPtr<FrameNode> & topModalNode)3445 bool OverlayManager::ModalExitProcess(const RefPtr<FrameNode>& topModalNode)
3446 {
3447     auto rootNode = FindWindowScene(topModalNode);
3448     CHECK_NULL_RETURN(rootNode, true);
3449     if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
3450         return ModalPageExitProcess(topModalNode);
3451     }
3452     if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
3453         return SheetPageExitProcess(topModalNode);
3454     }
3455     return true;
3456 }
3457 
PlayTransitionEffectOut(const RefPtr<FrameNode> & topModalNode)3458 void OverlayManager::PlayTransitionEffectOut(const RefPtr<FrameNode>& topModalNode)
3459 {
3460     const auto& layoutProperty = topModalNode->GetLayoutProperty();
3461     layoutProperty->UpdateVisibility(VisibleType::INVISIBLE, true);
3462 
3463     const auto& renderContext = topModalNode->GetRenderContext();
3464     if (!renderContext->HasDisappearTransition()) {
3465         const auto& topModalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
3466         if (!topModalPattern->IsExecuteOnDisappear()) {
3467             topModalPattern->OnDisappear();
3468             // Fire hidden event of navdestination on the disappeared modal
3469             FireNavigationStateChange(false, topModalNode);
3470         }
3471         auto rootNode = FindWindowScene(topModalNode);
3472         RemoveChildWithService(rootNode, topModalNode);
3473         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3474         // Fire shown event of navdestination under the disappeared modal
3475         FireNavigationStateChange(true);
3476     } else {
3477         topModalNode->GetRenderContext()->SetTransitionOutCallback(
3478             [modalWK = WeakClaim(RawPtr(topModalNode)), overlayWeak = WeakClaim(this)] {
3479                 auto modal = modalWK.Upgrade();
3480                 auto overlayManager = overlayWeak.Upgrade();
3481                 CHECK_NULL_VOID(modal && overlayManager);
3482                 auto root = overlayManager->FindWindowScene(modal);
3483                 CHECK_NULL_VOID(root);
3484                 const auto& modalPattern = modal->GetPattern<ModalPresentationPattern>();
3485                 if (!modalPattern->IsExecuteOnDisappear()) {
3486                     modalPattern->OnDisappear();
3487                     // Fire hidden event of navdestination on the disappeared modal
3488                     overlayManager->FireNavigationStateChange(false, modal);
3489                 }
3490                 overlayManager->RemoveChildWithService(root, modal);
3491                 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3492                 // Fire shown event of navdestination under the disappeared modal
3493                 overlayManager->FireNavigationStateChange(true);
3494             });
3495     }
3496 }
3497 
ModalPageExitProcess(const RefPtr<FrameNode> & topModalNode)3498 bool OverlayManager::ModalPageExitProcess(const RefPtr<FrameNode>& topModalNode)
3499 {
3500     auto rootNode = FindWindowScene(topModalNode);
3501     CHECK_NULL_RETURN(rootNode, true);
3502     auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
3503     CHECK_NULL_RETURN(builder, false);
3504     topModalNode->GetPattern<ModalPresentationPattern>()->OnWillDisappear();
3505     auto modalTransition = topModalNode->GetPattern<ModalPresentationPattern>()->GetType();
3506     if (builder->GetRenderContext()->HasDisappearTransition()) {
3507         if (!topModalNode->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
3508             topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
3509             // Fire hidden event of navdestination on the disappeared modal
3510             FireNavigationStateChange(false, topModalNode);
3511         }
3512         topModalNode->Clean(false, true);
3513         topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3514     }
3515     topModalNode->OnAccessibilityEvent(
3516         AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
3517     if (topModalNode->GetPattern<ModalPresentationPattern>()->HasTransitionEffect()) {
3518         PlayTransitionEffectOut(topModalNode);
3519     } else if (modalTransition == ModalTransition::DEFAULT) {
3520         PlayDefaultModalTransition(topModalNode, false);
3521     } else if (modalTransition == ModalTransition::ALPHA) {
3522         PlayAlphaModalTransition(topModalNode, false);
3523     } else if (!builder->GetRenderContext()->HasDisappearTransition()) {
3524         topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
3525         // Fire hidden event of navdestination on the disappeared modal
3526         FireNavigationStateChange(false, topModalNode);
3527         RemoveChildWithService(rootNode, topModalNode);
3528         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3529     }
3530     topModalNode->GetPattern<ModalPresentationPattern>()->FireCallback("false");
3531     return true;
3532 }
3533 
SheetPageExitProcess(const RefPtr<FrameNode> & topModalNode)3534 bool OverlayManager::SheetPageExitProcess(const RefPtr<FrameNode>& topModalNode)
3535 {
3536     auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetLastChild());
3537     CHECK_NULL_RETURN(builder, false);
3538     topModalNode->GetPattern<SheetPresentationPattern>()->OnWillDisappear();
3539     if (builder->GetRenderContext()->HasDisappearTransition()) {
3540         if (!topModalNode->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
3541             topModalNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
3542         }
3543         topModalNode->Clean(false, true);
3544         topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3545     }
3546     auto maskNode = GetSheetMask(topModalNode);
3547     if (maskNode) {
3548         PlaySheetMaskTransition(maskNode, false);
3549     }
3550     auto sheetType = topModalNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
3551     if (sheetType == SheetType::SHEET_POPUP) {
3552         PlayBubbleStyleSheetTransition(topModalNode, false);
3553     } else {
3554         PlaySheetTransition(topModalNode, false);
3555     }
3556     topModalNode->GetPattern<SheetPresentationPattern>()->FireCallback("false");
3557     return true;
3558 }
3559 
RemovePopupInSubwindow(const RefPtr<Pattern> & pattern,const RefPtr<FrameNode> & overlay,const RefPtr<UINode> & rootNode)3560 bool OverlayManager::RemovePopupInSubwindow(const RefPtr<Pattern>& pattern, const RefPtr<FrameNode>& overlay,
3561     const RefPtr<UINode>& rootNode)
3562 {
3563     if (PopupInteractiveDismiss(overlay)) {
3564         return true;
3565     }
3566     if (PopupCallBackOnWillDismiss(overlay)) {
3567         return true;
3568     }
3569     auto popupPattern = DynamicCast<BubblePattern>(pattern);
3570     overlay->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
3571     auto container = Container::Current();
3572     auto currentId = Container::CurrentId();
3573     CHECK_NULL_RETURN(container, false);
3574     if (container->IsSubContainer()) {
3575         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
3576     }
3577     ContainerScope scope(currentId);
3578     for (const auto& popup : popupMap_) {
3579         auto targetId = popup.first;
3580         auto popupInfo = popup.second;
3581         if (overlay == popupInfo.popupNode) {
3582             popupMap_.erase(targetId);
3583             rootNode->RemoveChild(overlay);
3584             rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3585             auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(currentId);
3586             CHECK_NULL_RETURN(subwindow, false);
3587             subwindow->DeleteHotAreas(overlay->GetId());
3588             if (rootNode->GetChildren().empty()) {
3589                 subwindow->HideSubWindowNG();
3590             }
3591             return true;
3592         }
3593     }
3594     return false;
3595 }
3596 
RemoveOverlayInSubwindow()3597 bool OverlayManager::RemoveOverlayInSubwindow()
3598 {
3599     auto rootNode = rootNodeWeak_.Upgrade();
3600     CHECK_NULL_RETURN(rootNode, false);
3601     if (rootNode->GetChildren().empty()) {
3602         return false;
3603     }
3604 
3605     // remove the overlay node just mounted in subwindow
3606     auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
3607     CHECK_NULL_RETURN(overlay, false);
3608     auto pattern = overlay->GetPattern();
3609     auto ret = RemoveOverlayCommon(rootNode, overlay, pattern, false, false);
3610     if (ret == OVERLAY_EXISTS) {
3611         return false;
3612     } else if (ret == OVERLAY_REMOVE) {
3613         return true;
3614     }
3615     rootNode->RemoveChild(overlay);
3616     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3617     if (rootNode->GetChildren().empty()) {
3618         SubwindowManager::GetInstance()->HideSubWindowNG();
3619     }
3620     if (InstanceOf<KeyboardPattern>(pattern)) {
3621         FocusHub::LostFocusToViewRoot();
3622     }
3623     return true;
3624 }
3625 
FocusOverlayNode(const RefPtr<FrameNode> & overlayNode,bool isInSubWindow)3626 void OverlayManager::FocusOverlayNode(const RefPtr<FrameNode>& overlayNode, bool isInSubWindow)
3627 {
3628     CHECK_NULL_VOID(overlayNode);
3629     auto overlayHub = overlayNode->GetFocusHub();
3630     CHECK_NULL_VOID(overlayHub);
3631     auto focusView = overlayHub->GetFirstChildFocusView();
3632     CHECK_NULL_VOID(focusView);
3633     focusView->FocusViewShow();
3634 }
3635 
BlurOverlayNode(const RefPtr<FrameNode> & currentOverlay,bool isInSubWindow)3636 void OverlayManager::BlurOverlayNode(const RefPtr<FrameNode>& currentOverlay, bool isInSubWindow) {}
3637 
BlurLowerNode(const RefPtr<FrameNode> & currentOverlay)3638 void OverlayManager::BlurLowerNode(const RefPtr<FrameNode>& currentOverlay) {}
3639 
ResetLowerNodeFocusable(const RefPtr<FrameNode> & currentOverlay)3640 void OverlayManager::ResetLowerNodeFocusable(const RefPtr<FrameNode>& currentOverlay) {}
3641 
SaveLastModalNode()3642 void OverlayManager::SaveLastModalNode()
3643 {
3644     auto pipeline = PipelineContext::GetCurrentContext();
3645     CHECK_NULL_VOID(pipeline);
3646     auto stageManager = pipeline->GetStageManager();
3647     CHECK_NULL_VOID(stageManager);
3648     auto pageNode = stageManager->GetLastPage();
3649     CHECK_NULL_VOID(pageNode);
3650     if (modalStack_.empty()) {
3651         lastModalNode_ = WeakClaim(RawPtr(pageNode));
3652     } else {
3653         auto topModalNode = modalStack_.top().Upgrade();
3654         modalStack_.pop();
3655         if (modalStack_.empty()) {
3656             lastModalNode_ = WeakClaim(RawPtr(pageNode));
3657         } else {
3658             lastModalNode_ = modalStack_.top();
3659         }
3660         modalStack_.push(topModalNode);
3661     }
3662 }
3663 
FireNavigationStateChange(bool show,const RefPtr<UINode> & node)3664 void OverlayManager::FireNavigationStateChange(bool show, const RefPtr<UINode>& node)
3665 {
3666     if (!show && node) {
3667         // Only check node When it is appointed
3668         NavigationPattern::FireNavigationStateChange(node, show);
3669         return;
3670     }
3671 
3672     // Fire show event with non-empty stack. Only Check top modal node.
3673     RefPtr<FrameNode> topModalNode;
3674     if (!modalStack_.empty()) {
3675         topModalNode = GetModalNodeInStack(modalStack_);
3676     }
3677     if (show && topModalNode) {
3678         // Modal always displays on top of stage. If it existed, only need to check the top of modal stack.
3679         NavigationPattern::FireNavigationStateChange(topModalNode, show);
3680         return;
3681     }
3682 
3683     auto lastPage = GetLastPage();
3684     CHECK_NULL_VOID(lastPage);
3685     auto pagePattern = lastPage->GetPattern<PagePattern>();
3686     bool notTriggerNavigationStateChange = show && pagePattern && !pagePattern->IsOnShow();
3687     if (notTriggerNavigationStateChange) {
3688         // navdestination will not fire onShow When parent page is hide.
3689         return;
3690     }
3691     NavigationPattern::FireNavigationStateChange(lastPage, show);
3692 }
3693 
GetModalNodeInStack(std::stack<WeakPtr<FrameNode>> & stack)3694 RefPtr<FrameNode> OverlayManager::GetModalNodeInStack(std::stack<WeakPtr<FrameNode>>& stack)
3695 {
3696     if (stack.empty()) {
3697         return nullptr;
3698     }
3699     auto topModalNode = stack.top().Upgrade();
3700     CHECK_NULL_RETURN(topModalNode, nullptr);
3701     if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
3702         return topModalNode;
3703     } else {
3704         stack.pop();
3705         auto modalNode = GetModalNodeInStack(stack);
3706         stack.push(topModalNode);
3707         return modalNode;
3708     }
3709 }
3710 
PlayTransitionEffectIn(const RefPtr<FrameNode> & modalNode)3711 void OverlayManager::PlayTransitionEffectIn(const RefPtr<FrameNode>& modalNode)
3712 {
3713     const auto& layoutProperty = modalNode->GetLayoutProperty();
3714     layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true);
3715 
3716     modalNode->GetRenderContext()->SetTransitionInCallback([modalWK = WeakClaim(RawPtr(modalNode))] {
3717         auto modal = modalWK.Upgrade();
3718         CHECK_NULL_VOID(modal);
3719         modal->GetPattern<ModalPresentationPattern>()->OnAppear();
3720     });
3721 
3722     // Fire hidden event of navdestination under the appeared modal
3723     FireNavigationStateChange(false);
3724 }
3725 
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,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,const NG::ContentCoverParam & contentCoverParam,const RefPtr<FrameNode> & targetNode,int32_t sessionId)3726 void OverlayManager::BindContentCover(bool isShow, std::function<void(const std::string&)>&& callback,
3727     std::function<RefPtr<UINode>()>&& buildNodeFunc, NG::ModalStyle& modalStyle, std::function<void()>&& onAppear,
3728     std::function<void()>&& onDisappear, std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
3729     const NG::ContentCoverParam& contentCoverParam, const RefPtr<FrameNode>& targetNode, int32_t sessionId)
3730 {
3731     return OnBindContentCover(isShow, std::move(callback), std::move(buildNodeFunc), modalStyle,
3732         std::move(onAppear), std::move(onDisappear), std::move(onWillAppear), std::move(onWillDisappear),
3733         contentCoverParam, targetNode, sessionId);
3734 }
3735 
OnBindContentCover(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,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,const NG::ContentCoverParam & contentCoverParam,const RefPtr<FrameNode> & targetNode,int32_t sessionId)3736 void OverlayManager::OnBindContentCover(bool isShow, std::function<void(const std::string&)>&& callback,
3737     std::function<RefPtr<UINode>()>&& buildNodeFunc, NG::ModalStyle& modalStyle, std::function<void()>&& onAppear,
3738     std::function<void()>&& onDisappear, std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
3739     const NG::ContentCoverParam& contentCoverParam, const RefPtr<FrameNode>& targetNode, int32_t sessionId)
3740 {
3741     int32_t targetId = targetNode ? targetNode->GetId() : sessionId;
3742     auto rootNode = FindWindowScene(targetNode);
3743     CHECK_NULL_VOID(rootNode);
3744     if (isShow) {
3745         auto modalTransition = modalStyle.modalTransition;
3746         if (!modalTransition.has_value()) {
3747             modalTransition = ModalTransition::DEFAULT;
3748         }
3749         auto targetModalNode = GetModal(targetId);
3750         if (targetModalNode) {
3751             const auto& targetModalPattern = targetModalNode->GetPattern<ModalPresentationPattern>();
3752             CHECK_NULL_VOID(targetModalPattern);
3753             auto modalRenderContext = targetModalNode->GetRenderContext();
3754             CHECK_NULL_VOID(modalRenderContext);
3755             if (modalStyle.backgroundColor.has_value()) {
3756                 modalRenderContext->UpdateBackgroundColor(modalStyle.backgroundColor.value());
3757             }
3758             targetModalPattern->UpdateOnDisappear(std::move(onDisappear));
3759             targetModalPattern->UpdateOnWillDisappear(std::move(onWillDisappear));
3760             targetModalPattern->UpdateOnAppear(std::move(onAppear));
3761             targetModalPattern->UpdateOnWillDismiss(std::move(contentCoverParam.onWillDismiss));
3762             targetModalPattern->SetType(modalTransition.value());
3763             targetModalPattern->SetHasTransitionEffect(contentCoverParam.transitionEffect != nullptr);
3764             modalRenderContext->UpdateChainedTransition(contentCoverParam.transitionEffect);
3765             return;
3766         }
3767         if (onWillAppear) {
3768             onWillAppear();
3769         }
3770         HandleModalShow(std::move(callback), std::move(buildNodeFunc), modalStyle, std::move(onAppear),
3771             std::move(onDisappear), std::move(onWillDisappear), rootNode, contentCoverParam, targetId, modalTransition);
3772         return;
3773     }
3774 
3775     // isShow = false, Pop ModalPage
3776     if (!modalStack_.empty()) {
3777         HandleModalPop(std::move(onWillDisappear), rootNode, targetId);
3778     }
3779 }
3780 
HandleModalShow(std::function<void (const std::string &)> && callback,std::function<RefPtr<UINode> ()> && buildNodeFunc,NG::ModalStyle & modalStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && onWillDisappear,const RefPtr<UINode> rootNode,const NG::ContentCoverParam & contentCoverParam,int32_t targetId,std::optional<ModalTransition> modalTransition)3781 void OverlayManager::HandleModalShow(std::function<void(const std::string&)>&& callback,
3782     std::function<RefPtr<UINode>()>&& buildNodeFunc, NG::ModalStyle& modalStyle, std::function<void()>&& onAppear,
3783     std::function<void()>&& onDisappear, std::function<void()>&& onWillDisappear, const RefPtr<UINode> rootNode,
3784     const NG::ContentCoverParam& contentCoverParam, int32_t targetId, std::optional<ModalTransition> modalTransition)
3785 {
3786     // builder content
3787     auto builder = AceType::DynamicCast<FrameNode>(buildNodeFunc());
3788     CHECK_NULL_VOID(builder);
3789     builder->GetRenderContext()->SetIsModalRootNode(true);
3790 
3791     // create modal page
3792     auto modalNode = FrameNode::CreateFrameNode(V2::MODAL_PAGE_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
3793         AceType::MakeRefPtr<ModalPresentationPattern>(
3794             targetId, static_cast<ModalTransition>(modalTransition.value()), std::move(callback)));
3795     if (modalStyle.backgroundColor.has_value()) {
3796         modalNode->GetRenderContext()->UpdateBackgroundColor(modalStyle.backgroundColor.value());
3797     }
3798     auto modalPagePattern = modalNode->GetPattern<ModalPresentationPattern>();
3799     CHECK_NULL_VOID(modalPagePattern);
3800     modalPagePattern->UpdateOnDisappear(std::move(onDisappear));
3801     modalPagePattern->UpdateOnWillDisappear(std::move(onWillDisappear));
3802     modalPagePattern->UpdateOnAppear(std::move(onAppear));
3803     modalPagePattern->UpdateOnWillDismiss(std::move(contentCoverParam.onWillDismiss));
3804     modalPagePattern->UpdateUIExtensionMode(modalStyle.isUIExtension);
3805     modalPagePattern->SetProhibitedRemoveByRouter(modalStyle.prohibitedRemoveByRouter);
3806     modalPagePattern->SetHasTransitionEffect(contentCoverParam.transitionEffect != nullptr);
3807     modalNode->GetRenderContext()->UpdateChainedTransition(contentCoverParam.transitionEffect);
3808     modalStack_.push(WeakClaim(RawPtr(modalNode)));
3809     modalList_.emplace_back(WeakClaim(RawPtr(modalNode)));
3810     SaveLastModalNode();
3811     if (targetId < 0) {
3812         // modaluiextention node mounting
3813         modalNode->MountToParent(rootNode, DEFAULT_NODE_SLOT, false, false, true);
3814     } else {
3815         MountToParentWithService(rootNode, modalNode);
3816     }
3817     modalNode->AddChild(builder);
3818     if (!isAllowedBeCovered_ && modalNode->GetParent()) {
3819         TAG_LOGI(AceLogTag::ACE_OVERLAY,
3820             "modalNode->GetParent() %{public}d mark IsProhibitedAddChildNode when sessionId %{public}d,"
3821             "prohibitedRemoveByRouter: %{public}d.",
3822             modalNode->GetParent()->GetId(), targetId, modalStyle.prohibitedRemoveByRouter);
3823         if (AddCurSessionId(targetId)) {
3824             modalNode->GetParent()->UpdateModalUiextensionCount(true);
3825         }
3826     }
3827 
3828     FireModalPageShow();
3829     modalNode->GetParent()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3830     if (contentCoverParam.transitionEffect != nullptr) {
3831         PlayTransitionEffectIn(modalNode);
3832         return;
3833     }
3834     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) ||
3835         modalTransition == ModalTransition::NONE) {
3836         modalPagePattern->OnAppear();
3837         // Fire hidden event of navdestination under the appeared modal
3838         FireNavigationStateChange(false);
3839     }
3840     modalNode->OnAccessibilityEvent(
3841         AccessibilityEventType::PAGE_OPEN, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
3842     if (modalTransition == ModalTransition::DEFAULT) {
3843         PlayDefaultModalTransition(modalNode, true);
3844     } else if (modalTransition == ModalTransition::ALPHA) {
3845         PlayAlphaModalTransition(modalNode, true);
3846     }
3847 }
3848 
HandleModalPop(std::function<void ()> && onWillDisappear,const RefPtr<UINode> rootNode,int32_t targetId)3849 void OverlayManager::HandleModalPop(
3850     std::function<void()>&& onWillDisappear, const RefPtr<UINode> rootNode, int32_t targetId)
3851 {
3852     auto topModalNode = GetModal(targetId);
3853     CHECK_NULL_VOID(topModalNode);
3854     if (!CheckTopModalNode(topModalNode, targetId)) {
3855         return;
3856     }
3857     auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
3858     CHECK_NULL_VOID(builder);
3859     if (builder->GetRenderContext()->HasDisappearTransition()) {
3860         if (!topModalNode->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
3861             topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
3862             // Fire hidden event of navdestination on the disappeared modal
3863             FireNavigationStateChange(false, topModalNode);
3864         }
3865         topModalNode->Clean(false, true);
3866         topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3867     }
3868     auto modalPresentationPattern = topModalNode->GetPattern<ModalPresentationPattern>();
3869     CHECK_NULL_VOID(modalPresentationPattern);
3870     auto modalTransition = modalPresentationPattern->GetType();
3871     // lost focus
3872     ModalPageLostFocus(topModalNode);
3873     if (onWillDisappear) {
3874         onWillDisappear();
3875     }
3876     topModalNode->OnAccessibilityEvent(
3877         AccessibilityEventType::PAGE_CLOSE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
3878     if (modalPresentationPattern->HasTransitionEffect()) {
3879         PlayTransitionEffectOut(topModalNode);
3880     } else if (modalTransition == ModalTransition::DEFAULT) {
3881         PlayDefaultModalTransition(topModalNode, false);
3882     } else if (modalTransition == ModalTransition::ALPHA) {
3883         PlayAlphaModalTransition(topModalNode, false);
3884     } else if (!builder->GetRenderContext()->HasDisappearTransition()) {
3885         if (!modalPresentationPattern->IsExecuteOnDisappear()) {
3886             modalPresentationPattern->OnDisappear();
3887             // Fire hidden event of navdestination on the disappeared modal
3888             FireNavigationStateChange(false, topModalNode);
3889         }
3890         RemoveChildWithService(rootNode, topModalNode);
3891         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3892     }
3893     RemoveModal(targetId);
3894     if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
3895         // Fire shown event of navdestination under the disappeared modal
3896         FireNavigationStateChange(true);
3897     }
3898     FireModalPageHide();
3899     SaveLastModalNode();
3900 }
3901 
FireModalPageShow()3902 void OverlayManager::FireModalPageShow()
3903 {
3904     auto topModalNode = modalList_.back().Upgrade();
3905     CHECK_NULL_VOID(topModalNode);
3906     auto topModalFocusView = topModalNode->GetPattern<FocusView>();
3907     CHECK_NULL_VOID(topModalFocusView);
3908     topModalFocusView->FocusViewShow();
3909 }
3910 
ModalPageLostFocus(const RefPtr<FrameNode> & node)3911 void OverlayManager::ModalPageLostFocus(const RefPtr<FrameNode>& node)
3912 {
3913     InputMethodManager::GetInstance()->ProcessModalPageScene();
3914 }
3915 
FireModalPageHide()3916 void OverlayManager::FireModalPageHide() {}
3917 
PlayDefaultModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)3918 void OverlayManager::PlayDefaultModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
3919 {
3920     // current modal animation
3921     AnimationOption option;
3922     const RefPtr<InterpolatingSpring> curve =
3923         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
3924     option.SetCurve(curve);
3925     option.SetFillMode(FillMode::FORWARDS);
3926     auto context = modalNode->GetRenderContext();
3927     CHECK_NULL_VOID(context);
3928 
3929     auto rootHeight = GetRootHeight();
3930     auto modalPositionY = modalNode->GetGeometryNode()->GetFrameRect().GetY();
3931     auto showHeight = rootHeight - modalPositionY;
3932 
3933     if (isTransitionIn) {
3934         PlayDefaultModalIn(modalNode, context, option, showHeight);
3935     } else {
3936         PlayDefaultModalOut(modalNode, context, option, showHeight);
3937     }
3938 }
3939 
PlayDefaultModalIn(const RefPtr<FrameNode> & modalNode,const RefPtr<RenderContext> & context,AnimationOption option,float showHeight)3940 void OverlayManager::PlayDefaultModalIn(
3941     const RefPtr<FrameNode>& modalNode, const RefPtr<RenderContext>& context, AnimationOption option, float showHeight)
3942 {
3943     context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
3944     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
3945         option.SetOnFinishEvent([modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
3946             auto modal = modalWK.Upgrade();
3947             auto overlayManager = overlayWeak.Upgrade();
3948             CHECK_NULL_VOID(modal && overlayManager);
3949             modal->GetPattern<ModalPresentationPattern>()->OnAppear();
3950             // Fire hidden event of navdestination on the disappeared modal
3951             overlayManager->FireNavigationStateChange(false);
3952         });
3953     }
3954     AnimationUtils::Animate(
3955         option,
3956         [context]() {
3957             if (context) {
3958                 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
3959             }
3960         },
3961         option.GetOnFinishEvent());
3962 }
3963 
PlayDefaultModalOut(const RefPtr<FrameNode> & modalNode,const RefPtr<RenderContext> & context,AnimationOption option,float showHeight)3964 void OverlayManager::PlayDefaultModalOut(
3965     const RefPtr<FrameNode>& modalNode, const RefPtr<RenderContext>& context, AnimationOption option, float showHeight)
3966 {
3967     auto lastModalNode = lastModalNode_.Upgrade();
3968     CHECK_NULL_VOID(lastModalNode);
3969     auto lastModalContext = lastModalNode->GetRenderContext();
3970     CHECK_NULL_VOID(lastModalContext);
3971     lastModalContext->UpdateOpacity(1.0);
3972     option.SetOnFinishEvent(
3973         [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
3974             auto modal = modalWK.Upgrade();
3975             auto overlayManager = overlayWeak.Upgrade();
3976             CHECK_NULL_VOID(modal && overlayManager);
3977             auto root = overlayManager->FindWindowScene(modal);
3978             CHECK_NULL_VOID(root);
3979             if (!modal->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
3980                 modal->GetPattern<ModalPresentationPattern>()->OnDisappear();
3981                 // Fire hidden event of navdestination on the disappeared modal
3982                 overlayManager->FireNavigationStateChange(false, modal);
3983             }
3984             overlayManager->RemoveChildWithService(root, modal);
3985             root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3986             // Fire shown event of navdestination under the disappeared modal
3987             overlayManager->FireNavigationStateChange(true);
3988         });
3989     context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
3990     AnimationUtils::Animate(
3991         option,
3992         [context, showHeight]() {
3993             if (context) {
3994                 context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
3995             }
3996         },
3997         option.GetOnFinishEvent());
3998 }
3999 
PlayAlphaModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)4000 void OverlayManager::PlayAlphaModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
4001 {
4002     AnimationOption option;
4003     option.SetCurve(Curves::FRICTION);
4004     option.SetDuration(FULL_MODAL_ALPHA_ANIMATION_DURATION);
4005     option.SetFillMode(FillMode::FORWARDS);
4006     auto lastModalNode = lastModalNode_.Upgrade();
4007     CHECK_NULL_VOID(lastModalNode);
4008     auto lastModalContext = lastModalNode->GetRenderContext();
4009     CHECK_NULL_VOID(lastModalContext);
4010     auto context = modalNode->GetRenderContext();
4011     CHECK_NULL_VOID(context);
4012     if (isTransitionIn) {
4013         // last page animation
4014         lastModalContext->OpacityAnimation(option, 1, 0);
4015         lastModalContext->UpdateOpacity(0);
4016         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
4017             option.SetOnFinishEvent([modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
4018                 auto modal = modalWK.Upgrade();
4019                 auto overlayManager = overlayWeak.Upgrade();
4020                 CHECK_NULL_VOID(modal && overlayManager);
4021                 modal->GetPattern<ModalPresentationPattern>()->OnAppear();
4022                 // Fire hidden event of navdestination on the disappeared modal
4023                 overlayManager->FireNavigationStateChange(false);
4024             });
4025         }
4026         // current modal page animation
4027         context->OpacityAnimation(option, 0, 1);
4028     } else {
4029         // last page animation
4030         lastModalContext->OpacityAnimation(option, 0, 1);
4031 
4032         // current modal page animation
4033         option.SetOnFinishEvent(
4034             [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
4035                 auto modal = modalWK.Upgrade();
4036                 auto overlayManager = overlayWeak.Upgrade();
4037                 CHECK_NULL_VOID(modal && overlayManager);
4038                 auto root = overlayManager->FindWindowScene(modal);
4039                 CHECK_NULL_VOID(root);
4040                 if (!modal->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
4041                     modal->GetPattern<ModalPresentationPattern>()->OnDisappear();
4042                     // Fire hidden event of navdestination on the disappeared modal
4043                     overlayManager->FireNavigationStateChange(false, modal);
4044                 }
4045                 overlayManager->RemoveChildWithService(root, modal);
4046                 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4047                 // Fire shown event of navdestination under the disappeared modal
4048                 overlayManager->FireNavigationStateChange(true);
4049             });
4050         context->OpacityAnimation(option, 1, 0);
4051     }
4052 }
4053 
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,std::function<void (const int32_t)> && onWillDismiss,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,std::function<void (const float)> && onHeightDidChange,std::function<void (const float)> && onDetentsDidChange,std::function<void (const float)> && onWidthDidChange,std::function<void (const float)> && onTypeDidChange,std::function<void ()> && sheetSpringBack,const RefPtr<FrameNode> & targetNode)4054 void OverlayManager::BindSheet(bool isShow, std::function<void(const std::string&)>&& callback,
4055     std::function<RefPtr<UINode>()>&& buildNodeFunc, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
4056     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
4057     std::function<void()>&& shouldDismiss, std::function<void(const int32_t)>&& onWillDismiss,
4058     std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
4059     std::function<void(const float)>&& onHeightDidChange, std::function<void(const float)>&& onDetentsDidChange,
4060     std::function<void(const float)>&& onWidthDidChange, std::function<void(const float)>&& onTypeDidChange,
4061     std::function<void()>&& sheetSpringBack, const RefPtr<FrameNode>& targetNode)
4062 {
4063     auto instanceId = sheetStyle.instanceId.has_value() ? sheetStyle.instanceId.value() : Container::CurrentId();
4064     ContainerScope scope(instanceId);
4065     auto pipeline = PipelineContext::GetCurrentContext();
4066     CHECK_NULL_VOID(pipeline);
4067     auto bindSheetTask = [weak = AceType::WeakClaim(this), isShow, callback = std::move(callback),
4068                              buildNodeFunc = std::move(buildNodeFunc),
4069                              buildtitleNodeFunc = std::move(buildtitleNodeFunc), sheetStyle,
4070                              onAppear = std::move(onAppear), onDisappear = std::move(onDisappear),
4071                              shouldDismiss = std::move(shouldDismiss), onWillDismiss = std::move(onWillDismiss),
4072                              onWillAppear = std::move(onWillAppear), onWillDisappear = std::move(onWillDisappear),
4073                              onHeightDidChange = std::move(onHeightDidChange),
4074                              onDetentsDidChange = std::move(onDetentsDidChange),
4075                              onWidthDidChange = std::move(onWidthDidChange),
4076                              onTypeDidChange = std::move(onTypeDidChange), sheetSpringBack = std::move(sheetSpringBack),
4077                              targetNode, instanceId]() mutable {
4078         ContainerScope scope(instanceId);
4079         auto overlay = weak.Upgrade();
4080         CHECK_NULL_VOID(overlay);
4081         overlay->OnBindSheet(isShow, std::move(callback), std::move(buildNodeFunc), std::move(buildtitleNodeFunc),
4082             sheetStyle, std::move(onAppear), std::move(onDisappear), std::move(shouldDismiss), std::move(onWillDismiss),
4083             std::move(onWillAppear), std::move(onWillDisappear), std::move(onHeightDidChange),
4084             std::move(onDetentsDidChange), std::move(onWidthDidChange), std::move(onTypeDidChange),
4085             std::move(sheetSpringBack), targetNode);
4086         auto pipeline = PipelineContext::GetCurrentContext();
4087         CHECK_NULL_VOID(pipeline);
4088         pipeline->FlushUITasks();
4089     };
4090     pipeline->RequestFrame();
4091     pipeline->AddAnimationClosure(bindSheetTask);
4092 }
4093 
UpdateSheetMaskBackgroundColor(const RefPtr<FrameNode> & maskNode,const RefPtr<RenderContext> & maskRenderContext,const SheetStyle & sheetStyle)4094 void OverlayManager::UpdateSheetMaskBackgroundColor(
4095     const RefPtr<FrameNode>& maskNode, const RefPtr<RenderContext>& maskRenderContext, const SheetStyle& sheetStyle)
4096 {
4097     if (sheetStyle.maskColor.has_value()) {
4098         maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value());
4099     } else {
4100         maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
4101             HitTestMode::HTMTRANSPARENT);
4102         maskRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
4103     }
4104 }
4105 
InitSheetMask(const RefPtr<FrameNode> & maskNode,const RefPtr<FrameNode> & sheetNode,const SheetStyle & sheetStyle)4106 void OverlayManager::InitSheetMask(
4107     const RefPtr<FrameNode>& maskNode, const RefPtr<FrameNode>& sheetNode, const SheetStyle& sheetStyle)
4108 {
4109     auto maskRenderContext = maskNode->GetRenderContext();
4110     CHECK_NULL_VOID(maskRenderContext);
4111     auto pipeline = PipelineContext::GetCurrentContext();
4112     CHECK_NULL_VOID(pipeline);
4113     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
4114     CHECK_NULL_VOID(sheetTheme);
4115     auto sheetLayoutProps = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
4116     CHECK_NULL_VOID(sheetLayoutProps);
4117     maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMDEFAULT);
4118     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
4119         UpdateSheetMaskBackgroundColor(maskNode, maskRenderContext, sheetStyle);
4120     } else {
4121         auto eventConfirmHub = maskNode->GetOrCreateGestureEventHub();
4122         CHECK_NULL_VOID(eventConfirmHub);
4123         auto sheetMaskClickEvent = AceType::MakeRefPtr<NG::ClickEvent>(
4124             [weak = AceType::WeakClaim(AceType::RawPtr(sheetNode))](const GestureEvent& /* info */) {
4125                 auto sheet = weak.Upgrade();
4126                 CHECK_NULL_VOID(sheet);
4127                 auto sheetPattern = sheet->GetPattern<SheetPresentationPattern>();
4128                 CHECK_NULL_VOID(sheetPattern);
4129                 if (sheetPattern->IsDragging()) {
4130                     return;
4131                 }
4132                 sheetPattern->SheetInteractiveDismiss(BindSheetDismissReason::TOUCH_OUTSIDE);
4133             });
4134         auto maskNodeId = maskNode->GetId();
4135         sheetMaskClickEventMap_.emplace(maskNodeId, sheetMaskClickEvent);
4136         eventConfirmHub->AddClickEvent(sheetMaskClickEvent, DISTANCE_THRESHOLD);
4137         if (!sheetStyle.interactive.has_value()) {
4138             if (sheetNode->GetPattern<SheetPresentationPattern>()->GetSheetType() == SheetType::SHEET_POPUP) {
4139                 maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
4140                     HitTestMode::HTMTRANSPARENT);
4141                 eventConfirmHub->RemoveClickEvent(sheetMaskClickEvent);
4142                 sheetMaskClickEventMap_.erase(maskNodeId);
4143             }
4144         } else if (sheetStyle.interactive == true) {
4145             maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
4146                 HitTestMode::HTMTRANSPARENT);
4147             eventConfirmHub->RemoveClickEvent(sheetMaskClickEvent);
4148             sheetMaskClickEventMap_.erase(maskNodeId);
4149         }
4150     }
4151 }
4152 
CleanInvalidModalNode(const WeakPtr<FrameNode> & invalidNode)4153 void OverlayManager::CleanInvalidModalNode(const WeakPtr<FrameNode>& invalidNode)
4154 {
4155     // When a modalNode.Upgrade() == nullptr, the modalNode is invalid
4156     modalList_.remove(invalidNode);
4157     std::vector<WeakPtr<FrameNode>> sheetVector;
4158     while (!modalStack_.empty()) {
4159         if (modalStack_.top() != invalidNode) {
4160             sheetVector.push_back(modalStack_.top());
4161         }
4162         modalStack_.pop();
4163     }
4164     for (auto iter = sheetVector.rbegin(); iter != sheetVector.rend(); ++iter) {
4165         modalStack_.push(*iter);
4166     }
4167 }
4168 
CloseSheet(const SheetKey & sheetKey)4169 void OverlayManager::CloseSheet(const SheetKey& sheetKey)
4170 {
4171     if (modalStack_.empty()) {
4172         return;
4173     }
4174     auto iter = sheetMap_.find(sheetKey);
4175     if (sheetMap_.empty() || iter == sheetMap_.end()) {
4176         DeleteModal(sheetKey.targetId);
4177         return;
4178     }
4179     auto sheetNode = iter->second.Upgrade();
4180     if (sheetNode == nullptr) {
4181         TAG_LOGE(AceLogTag::ACE_SHEET, "The sheetNode is null, clean it.");
4182         CleanViewContextMap(Container::CurrentId(), sheetKey.contentId);
4183         CleanInvalidModalNode(iter->second);
4184         sheetMap_.erase(sheetKey);
4185         SaveLastModalNode();
4186         return;
4187     }
4188     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
4189     CHECK_NULL_VOID(sheetPattern);
4190     sheetPattern->SetShowState(false);
4191     auto buildContent = sheetPattern->GetFirstFrameNodeOfBuilder();
4192     CHECK_NULL_VOID(buildContent);
4193     auto buildRenderContext = buildContent->GetRenderContext();
4194     CHECK_NULL_VOID(buildRenderContext);
4195     sheetPattern->OnWillDisappear();
4196     if (buildRenderContext->HasDisappearTransition()) {
4197         if (!sheetPattern->IsExecuteOnDisappear()) {
4198             sheetPattern->OnDisappear();
4199         }
4200         sheetPattern->OnDisappear();
4201         sheetNode->Clean(false, true);
4202         sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4203     }
4204     ModalPageLostFocus(sheetNode);
4205     PlaySheetTransitionWhenClose(sheetNode);
4206     sheetPattern->SetDismissProcess(true);
4207     sheetMap_.erase(sheetKey);
4208     CleanViewContextMap(Container::CurrentId(), sheetKey.contentId);
4209     RemoveSheetNode(sheetNode);
4210     FireModalPageHide();
4211     SaveLastModalNode();
4212 }
4213 
PlaySheetTransitionWhenClose(const RefPtr<FrameNode> & sheetNode)4214 void OverlayManager::PlaySheetTransitionWhenClose(const RefPtr<FrameNode>& sheetNode)
4215 {
4216     CHECK_NULL_VOID(sheetNode);
4217     auto maskNode = GetSheetMask(sheetNode);
4218     if (maskNode) {
4219         PlaySheetMaskTransition(maskNode, false);
4220     }
4221     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
4222     CHECK_NULL_VOID(sheetPattern);
4223     auto sheetType = sheetPattern->GetSheetType();
4224     if (sheetType == SheetType::SHEET_POPUP) {
4225         PlayBubbleStyleSheetTransition(sheetNode, false);
4226     } else {
4227         PlaySheetTransition(sheetNode, false);
4228     }
4229 }
4230 
DismissSheet()4231 void OverlayManager::DismissSheet()
4232 {
4233     if (modalStack_.empty()) {
4234         return;
4235     }
4236     auto iter = sheetMap_.find(dismissTarget_.sheetKey);
4237     if (sheetMap_.empty() || iter == sheetMap_.end()) {
4238         DeleteModal(dismissTarget_.GetTargetId());
4239         return;
4240     }
4241     auto sheetNode = iter->second.Upgrade();
4242     CHECK_NULL_VOID(sheetNode);
4243     if (sheetNode->GetTag() == V2::SHEET_PAGE_TAG) {
4244         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
4245         CHECK_NULL_VOID(sheetPattern);
4246         sheetPattern->DismissSheet();
4247     }
4248 }
4249 
DismissContentCover()4250 void OverlayManager::DismissContentCover()
4251 {
4252     if (modalStack_.empty()) {
4253         return;
4254     }
4255     const auto& modalNode = GetModal(dismissTarget_.GetTargetId());
4256     if (modalNode == nullptr) {
4257         DeleteModal(dismissTarget_.GetTargetId());
4258         return;
4259     }
4260     if (modalNode->GetTag() == V2::MODAL_PAGE_TAG) {
4261         ModalPageLostFocus(modalNode);
4262         auto builder = AceType::DynamicCast<FrameNode>(modalNode->GetFirstChild());
4263         if (!ModalPageExitProcess(modalNode)) {
4264             return;
4265         }
4266         RemoveModal(dismissTarget_.GetTargetId());
4267         auto modalPattern = modalNode->GetPattern<ModalPresentationPattern>();
4268         CHECK_NULL_VOID(modalPattern);
4269         auto modalTransition = modalPattern->GetType();
4270         if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
4271             FireNavigationStateChange(true);
4272         }
4273         FireModalPageHide();
4274         SaveLastModalNode();
4275     }
4276 }
4277 
SheetSpringBack()4278 void OverlayManager::SheetSpringBack()
4279 {
4280     auto sheetNode = sheetMap_[dismissTarget_.sheetKey].Upgrade();
4281     CHECK_NULL_VOID(sheetNode);
4282     if (sheetNode->GetTag() == V2::SHEET_PAGE_TAG) {
4283         auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
4284         CHECK_NULL_VOID(sheetPattern);
4285         sheetPattern->SheetSpringBack();
4286     }
4287 }
4288 
GetModal(int32_t targetId)4289 RefPtr<FrameNode> OverlayManager::GetModal(int32_t targetId)
4290 {
4291     for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
4292         auto modalNode = (*modal).Upgrade();
4293         if (!modalNode) {
4294             continue;
4295         }
4296         int32_t modalTargetId = -1;
4297         if (modalNode->GetTag() == V2::MODAL_PAGE_TAG) {
4298             modalTargetId = modalNode->GetPattern<ModalPresentationPattern>()->GetTargetId();
4299         } else {
4300             continue;
4301         }
4302         if (modalTargetId == targetId) {
4303             return modalNode;
4304         }
4305     }
4306     return nullptr;
4307 }
4308 
RemoveModal(int32_t targetId)4309 void OverlayManager::RemoveModal(int32_t targetId)
4310 {
4311     bool isDelete = false;
4312     for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
4313         auto modalNode = (*modal).Upgrade();
4314         if (!modalNode) {
4315             continue;
4316         }
4317         int32_t modalTargetId = -1;
4318         if (modalNode->GetTag() == V2::MODAL_PAGE_TAG) {
4319             modalTargetId = modalNode->GetPattern<ModalPresentationPattern>()->GetTargetId();
4320         } else {
4321             continue;
4322         }
4323         if (modalTargetId == targetId) {
4324             isDelete = true;
4325             modalList_.erase(modal);
4326             break;
4327         }
4328     }
4329     if (isDelete) {
4330         while (!modalStack_.empty()) {
4331             modalStack_.pop();
4332         }
4333         for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
4334             modalStack_.push(*modal);
4335         }
4336     }
4337 }
4338 
RemoveSheetNode(const RefPtr<FrameNode> & sheetNode)4339 void OverlayManager::RemoveSheetNode(const RefPtr<FrameNode>& sheetNode)
4340 {
4341     CHECK_NULL_VOID(sheetNode);
4342     if (!modalList_.empty()) {
4343         modalList_.remove(WeakClaim(RawPtr(sheetNode)));
4344     }
4345     std::vector<WeakPtr<FrameNode>> sheetVector;
4346     while (!modalStack_.empty()) {
4347         if (modalStack_.top() != WeakClaim(RawPtr(sheetNode))) {
4348             sheetVector.push_back(modalStack_.top());
4349         }
4350         modalStack_.pop();
4351     }
4352     for (auto iter = sheetVector.rbegin(); iter != sheetVector.rend(); ++iter) {
4353         modalStack_.push(*iter);
4354     }
4355 }
4356 
PlaySheetTransition(RefPtr<FrameNode> sheetNode,bool isTransitionIn,bool isFirstTransition)4357 void OverlayManager::PlaySheetTransition(
4358     RefPtr<FrameNode> sheetNode, bool isTransitionIn, bool isFirstTransition)
4359 {
4360     CHECK_NULL_VOID(sheetNode);
4361     sheetNode->OnAccessibilityEvent(
4362         isTransitionIn ? AccessibilityEventType::PAGE_OPEN : AccessibilityEventType::PAGE_CLOSE,
4363         WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
4364 
4365     // current sheet animation
4366     AnimationOption option;
4367     const RefPtr<InterpolatingSpring> curve =
4368         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
4369     option.SetCurve(curve);
4370     option.SetFillMode(FillMode::FORWARDS);
4371     auto context = sheetNode->GetRenderContext();
4372     CHECK_NULL_VOID(context);
4373     context->UpdateRenderGroup(true, false, true);
4374     TAG_LOGD(AceLogTag::ACE_SHEET, "UpdateRenderGroup start");
4375     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
4376     CHECK_NULL_VOID(sheetPattern);
4377     auto sheetMaxHeight = sheetPattern->GetPageHeightWithoutOffset();
4378     auto sheetParent = DynamicCast<FrameNode>(sheetNode->GetParent());
4379     CHECK_NULL_VOID(sheetParent);
4380     if (isTransitionIn) {
4381         sheetPattern->SetCurrentHeight(sheetHeight_);
4382         float offset = 0.0f;
4383         if (sheetPattern->GetSheetType() == SheetType::SHEET_POPUP) {
4384             offset = sheetPattern->GetSheetOffset();
4385         } else {
4386             offset = sheetMaxHeight - sheetHeight_;
4387         }
4388         if (isFirstTransition) {
4389             context->UpdateTransformTranslate({ 0.0f, sheetMaxHeight, 0.0f });
4390             if (NearZero(sheetHeight_)) {
4391                 return;
4392             }
4393         }
4394         if (sheetPattern->IsFoldStatusChanged()) {
4395             option.SetDuration(0);
4396             option.SetCurve(Curves::LINEAR);
4397         }
4398         sheetPattern->FireOnTypeDidChange();
4399         sheetPattern->FireOnWidthDidChange(sheetNode);
4400         option.SetOnFinishEvent(
4401             [sheetWK = WeakClaim(RawPtr(sheetNode)), weak = AceType::WeakClaim(this), isFirst = isFirstTransition] {
4402                 auto sheetNode = sheetWK.Upgrade();
4403                 CHECK_NULL_VOID(sheetNode);
4404                 auto context = sheetNode->GetRenderContext();
4405                 CHECK_NULL_VOID(context);
4406                 context->UpdateRenderGroup(false, false, true);
4407                 TAG_LOGD(AceLogTag::ACE_SHEET, "UpdateRenderGroup finished");
4408                 auto pattern = sheetNode->GetPattern<SheetPresentationPattern>();
4409                 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
4410                     isFirst) {
4411                     pattern->OnAppear();
4412                 }
4413                 pattern->AvoidAiBar();
4414                 auto overlay = weak.Upgrade();
4415                 CHECK_NULL_VOID(overlay);
4416                 pattern->FireOnDetentsDidChange(overlay->sheetHeight_);
4417                 pattern->FireOnHeightDidChange(overlay->sheetHeight_);
4418             });
4419         ACE_SCOPED_TRACE("Sheet start admission");
4420         AnimationUtils::Animate(
4421             option,
4422             [context, offset]() {
4423                 if (context) {
4424                     context->UpdateTransformTranslate({ 0.0f, offset, 0.0f });
4425                 }
4426             },
4427             option.GetOnFinishEvent());
4428     } else {
4429         option.SetOnFinishEvent(
4430             [rootWeak = rootNodeWeak_, sheetWK = WeakClaim(RawPtr(sheetNode)), weakOverlayManager = WeakClaim(this)] {
4431                 auto sheet = sheetWK.Upgrade();
4432                 auto overlayManager = weakOverlayManager.Upgrade();
4433                 CHECK_NULL_VOID(sheet && overlayManager);
4434                 if (!sheet->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
4435                     sheet->GetPattern<SheetPresentationPattern>()->OnDisappear();
4436                 }
4437                 auto root = overlayManager->FindWindowScene(sheet);
4438                 CHECK_NULL_VOID(root);
4439                 auto sheetParent = DynamicCast<FrameNode>(sheet->GetParent());
4440                 CHECK_NULL_VOID(sheetParent);
4441                 overlayManager->RemoveChildWithService(root, sheetParent);
4442                 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4443             });
4444         sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMTRANSPARENT);
4445         AnimationUtils::Animate(
4446             option,
4447             [context, sheetMaxHeight]() {
4448                 if (context) {
4449                     context->UpdateTransformTranslate({ 0.0f, sheetMaxHeight, 0.0f });
4450                 }
4451             },
4452             option.GetOnFinishEvent());
4453     }
4454 }
4455 
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,std::function<void (const int32_t)> && onWillDismiss,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,std::function<void (const float)> && onHeightDidChange,std::function<void (const float)> && onDetentsDidChange,std::function<void (const float)> && onWidthDidChange,std::function<void (const float)> && onTypeDidChange,std::function<void ()> && sheetSpringBack,const RefPtr<FrameNode> & targetNode)4456 void OverlayManager::OnBindSheet(bool isShow, std::function<void(const std::string&)>&& callback,
4457     std::function<RefPtr<UINode>()>&& buildNodeFunc, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
4458     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
4459     std::function<void()>&& shouldDismiss, std::function<void(const int32_t)>&& onWillDismiss,
4460     std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
4461     std::function<void(const float)>&& onHeightDidChange, std::function<void(const float)>&& onDetentsDidChange,
4462     std::function<void(const float)>&& onWidthDidChange, std::function<void(const float)>&& onTypeDidChange,
4463     std::function<void()>&& sheetSpringBack, const RefPtr<FrameNode>& targetNode)
4464 {
4465     int32_t targetId = targetNode->GetId();
4466     if (!isShow) {
4467         CloseSheet(SheetKey(targetId));
4468         return;
4469     }
4470     SheetKey sheetKey(targetId);
4471     auto iter = sheetMap_.find(sheetKey);
4472     if (iter != sheetMap_.end()) {
4473         auto sheetNode = iter->second.Upgrade();
4474         CHECK_NULL_VOID(sheetNode);
4475         UpdateSheetPage(sheetNode, sheetStyle, targetId, false, false,
4476             std::move(onAppear), std::move(onDisappear), std::move(shouldDismiss), std::move(onWillDismiss),
4477             std::move(onWillDisappear), std::move(onHeightDidChange),
4478             std::move(onDetentsDidChange), std::move(onWidthDidChange),
4479             std::move(onTypeDidChange), std::move(sheetSpringBack));
4480         return;
4481     }
4482     // build content
4483     RefPtr<UINode> sheetContentNode = buildNodeFunc();
4484     CHECK_NULL_VOID(sheetContentNode);
4485     auto frameChildNode = sheetContentNode->GetFrameChildByIndex(0, true);
4486     if (!frameChildNode) {
4487         // The function should return if the frameNodeChild of the builder is empty,
4488         // otherwise an exception will occur when unmount an empty node.
4489         TAG_LOGE(AceLogTag::ACE_SHEET, "sheet buildNode is nullptr");
4490         return;
4491     }
4492     OnBindSheetInner(std::move(callback), sheetContentNode, std::move(buildtitleNodeFunc),
4493         sheetStyle, std::move(onAppear), std::move(onDisappear), std::move(shouldDismiss), std::move(onWillDismiss),
4494         std::move(onWillAppear), std::move(onWillDisappear), std::move(onHeightDidChange),
4495         std::move(onDetentsDidChange), std::move(onWidthDidChange),
4496         std::move(onTypeDidChange), std::move(sheetSpringBack), targetNode);
4497 }
4498 
OpenBindSheetByUIContext(const RefPtr<FrameNode> & sheetContentNode,std::function<RefPtr<UINode> ()> && buildtitleNodeFunc,NG::SheetStyle & sheetStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && shouldDismiss,std::function<void (const int32_t)> && onWillDismiss,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,std::function<void (const float)> && onHeightDidChange,std::function<void (const float)> && onDetentsDidChange,std::function<void (const float)> && onWidthDidChange,std::function<void (const float)> && onTypeDidChange,std::function<void ()> && sheetSpringBack,std::function<void (const int32_t,const int32_t)> cleanViewContextMapCallback,const RefPtr<FrameNode> & targetNode)4499 void OverlayManager::OpenBindSheetByUIContext(
4500     const RefPtr<FrameNode>& sheetContentNode, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
4501     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
4502     std::function<void()>&& shouldDismiss, std::function<void(const int32_t)>&& onWillDismiss,
4503     std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
4504     std::function<void(const float)>&& onHeightDidChange,
4505     std::function<void(const float)>&& onDetentsDidChange,
4506     std::function<void(const float)>&& onWidthDidChange,
4507     std::function<void(const float)>&& onTypeDidChange,
4508     std::function<void()>&& sheetSpringBack,
4509     std::function<void(const int32_t, const int32_t)> cleanViewContextMapCallback,
4510     const RefPtr<FrameNode>& targetNode)
4511 {
4512     if (cleanViewContextMapCallback_ == nullptr) {
4513         cleanViewContextMapCallback_ = cleanViewContextMapCallback;
4514     }
4515     auto instanceId = sheetStyle.instanceId.has_value() ? sheetStyle.instanceId.value() : Container::CurrentId();
4516     ContainerScope scope(instanceId);
4517     OnBindSheetInner(nullptr, sheetContentNode, std::move(buildtitleNodeFunc),
4518         sheetStyle, std::move(onAppear), std::move(onDisappear), std::move(shouldDismiss), std::move(onWillDismiss),
4519         std::move(onWillAppear), std::move(onWillDisappear), std::move(onHeightDidChange),
4520         std::move(onDetentsDidChange), std::move(onWidthDidChange),
4521         std::move(onTypeDidChange), std::move(sheetSpringBack), targetNode, true);
4522 }
4523 
UpdateBindSheetByUIContext(const RefPtr<NG::FrameNode> & sheetContentNode,NG::SheetStyle & sheetStyle,int32_t targetId,bool isPartialUpdate)4524 void OverlayManager::UpdateBindSheetByUIContext(
4525     const RefPtr<NG::FrameNode>& sheetContentNode, NG::SheetStyle& sheetStyle, int32_t targetId, bool isPartialUpdate)
4526 {
4527     SheetKey sheetKey;
4528     if (!CreateSheetKey(sheetContentNode, targetId, sheetKey)) {
4529         TAG_LOGE(AceLogTag::ACE_SHEET, "CreateSheetKey failed");
4530         return;
4531     }
4532     targetId = sheetKey.targetId;
4533     auto iter = sheetMap_.find(sheetKey);
4534     if (iter != sheetMap_.end()) {
4535         auto sheetNode = iter->second.Upgrade();
4536         CHECK_NULL_VOID(sheetNode);
4537         UpdateSheetPage(sheetNode, sheetStyle, targetId, true, isPartialUpdate);
4538     }
4539     TAG_LOGE(AceLogTag::ACE_SHEET, "Can not find sheet.");
4540     return;
4541 }
4542 
UpdateSheetRender(const RefPtr<FrameNode> & sheetPageNode,NG::SheetStyle & sheetStyle,bool isPartialUpdate)4543 void OverlayManager::UpdateSheetRender(
4544     const RefPtr<FrameNode>& sheetPageNode, NG::SheetStyle& sheetStyle, bool isPartialUpdate)
4545 {
4546     CHECK_NULL_VOID(sheetPageNode);
4547     auto sheetRenderContext = sheetPageNode->GetRenderContext();
4548     CHECK_NULL_VOID(sheetRenderContext);
4549     auto pipeline = sheetPageNode->GetContext();
4550     CHECK_NULL_VOID(pipeline);
4551     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
4552     CHECK_NULL_VOID(sheetTheme);
4553     SetSheetBackgroundColor(sheetPageNode, sheetTheme, sheetStyle);
4554     if (sheetStyle.backgroundBlurStyle.has_value()) {
4555         SetSheetBackgroundBlurStyle(sheetPageNode, sheetStyle.backgroundBlurStyle.value());
4556     }
4557     auto sheetNodePattern = sheetPageNode->GetPattern<SheetPresentationPattern>();
4558     CHECK_NULL_VOID(sheetNodePattern);
4559     sheetNodePattern->SetSheetBorderWidth();
4560     if (sheetStyle.borderStyle.has_value()) {
4561         sheetRenderContext->UpdateBorderStyle(sheetStyle.borderStyle.value());
4562     }
4563     if (sheetStyle.borderColor.has_value()) {
4564         sheetRenderContext->UpdateBorderColor(sheetStyle.borderColor.value());
4565     }
4566     if (sheetStyle.shadow.has_value()) {
4567         sheetRenderContext->UpdateBackShadow(sheetStyle.shadow.value());
4568     } else if (!isPartialUpdate) {
4569         sheetRenderContext->UpdateBackShadow(ShadowConfig::NoneShadow);
4570     }
4571     sheetNodePattern->UpdateMaskBackgroundColor();
4572 }
UpdateSheetProperty(const RefPtr<FrameNode> & sheetNode,NG::SheetStyle & currentStyle,bool isPartialUpdate)4573 void OverlayManager::UpdateSheetProperty(const RefPtr<FrameNode>& sheetNode,
4574     NG::SheetStyle& currentStyle, bool isPartialUpdate)
4575 {
4576     auto pipeline = sheetNode->GetContext();
4577     CHECK_NULL_VOID(pipeline);
4578     UpdateSheetRender(sheetNode, currentStyle, isPartialUpdate);
4579     auto maskNode = GetSheetMask(sheetNode);
4580     if (maskNode) {
4581         UpdateSheetMask(maskNode, sheetNode, currentStyle, isPartialUpdate);
4582     }
4583     sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4584     pipeline->FlushUITasks();
4585     ComputeSheetOffset(currentStyle, sheetNode);
4586 }
4587 
UpdateSheetPage(const RefPtr<FrameNode> & sheetNode,NG::SheetStyle & sheetStyle,int32_t targetId,bool isStartByUIContext,bool isPartialUpdate,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && shouldDismiss,std::function<void (const int32_t)> && onWillDismiss,std::function<void ()> && onWillDisappear,std::function<void (const float)> && onHeightDidChange,std::function<void (const float)> && onDetentsDidChange,std::function<void (const float)> && onWidthDidChange,std::function<void (const float)> && onTypeDidChange,std::function<void ()> && sheetSpringBack)4588 void OverlayManager::UpdateSheetPage(const RefPtr<FrameNode>& sheetNode, NG::SheetStyle& sheetStyle,
4589     int32_t targetId, bool isStartByUIContext, bool isPartialUpdate,
4590     std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
4591     std::function<void()>&& shouldDismiss, std::function<void(const int32_t)>&& onWillDismiss,
4592     std::function<void()>&& onWillDisappear, std::function<void(const float)>&& onHeightDidChange,
4593     std::function<void(const float)>&& onDetentsDidChange,
4594     std::function<void(const float)>&& onWidthDidChange,
4595     std::function<void(const float)>&& onTypeDidChange,
4596     std::function<void()>&& sheetSpringBack)
4597 {
4598     if (sheetNode->GetTag() != V2::SHEET_PAGE_TAG ||
4599         sheetNode->GetPattern<SheetPresentationPattern>()->GetTargetId() != targetId) {
4600         return;
4601     }
4602     auto sheetNodePattern = sheetNode->GetPattern<SheetPresentationPattern>();
4603     CHECK_NULL_VOID(sheetNodePattern);
4604     auto customHeightOrDetentsChanged = sheetNodePattern->IsCustomHeightOrDetentsChanged(sheetStyle);
4605     if (isStartByUIContext) {
4606         auto currentStyle = UpdateSheetStyle(sheetNode, sheetStyle, isPartialUpdate);
4607         UpdateSheetProperty(sheetNode, currentStyle, isPartialUpdate);
4608     } else {
4609         sheetNodePattern->UpdateOnAppear(std::move(onAppear));
4610         sheetNodePattern->UpdateOnDisappear(std::move(onDisappear));
4611         sheetNodePattern->UpdateShouldDismiss(std::move(shouldDismiss));
4612         sheetNodePattern->UpdateOnWillDismiss(std::move(onWillDismiss));
4613         sheetNodePattern->UpdateOnWillDisappear(std::move(onWillDisappear));
4614         sheetNodePattern->UpdateOnHeightDidChange(std::move(onHeightDidChange));
4615         sheetNodePattern->UpdateOnDetentsDidChange(std::move(onDetentsDidChange));
4616         sheetNodePattern->UpdateOnWidthDidChange(std::move(onWidthDidChange));
4617         sheetNodePattern->UpdateOnTypeDidChange(std::move(onTypeDidChange));
4618         sheetNodePattern->UpdateSheetSpringBack(std::move(sheetSpringBack));
4619         auto layoutProperty = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
4620         layoutProperty->UpdateSheetStyle(sheetStyle);
4621         UpdateSheetProperty(sheetNode, sheetStyle, isPartialUpdate);
4622     }
4623     sheetNode->MarkModifyDone();
4624     auto sheetType = sheetNodePattern->GetSheetType();
4625     if (sheetType != SheetType::SHEET_POPUP && !sheetNodePattern->GetDismissProcess() && customHeightOrDetentsChanged) {
4626         PlaySheetTransition(sheetNode, true, false);
4627     }
4628 }
4629 
UpdateSheetStyle(const RefPtr<FrameNode> & sheetNode,const SheetStyle & sheetStyle,bool isPartialUpdate)4630 SheetStyle OverlayManager::UpdateSheetStyle(
4631     const RefPtr<FrameNode>& sheetNode, const SheetStyle& sheetStyle, bool isPartialUpdate)
4632 {
4633     auto layoutProperty = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
4634     CHECK_NULL_RETURN(layoutProperty, sheetStyle);
4635     auto currentStyle = layoutProperty->GetSheetStyleValue();
4636     if (isPartialUpdate) {
4637         currentStyle.PartialUpdate(sheetStyle);
4638     } else {
4639         auto currentShowInPage = currentStyle.showInPage;
4640         auto currentInstanceId = currentStyle.instanceId;
4641         currentStyle = sheetStyle;
4642         currentStyle.showInPage = currentShowInPage;
4643         currentStyle.instanceId = currentInstanceId;
4644     }
4645     layoutProperty->UpdateSheetStyle(currentStyle);
4646     return currentStyle;
4647 }
4648 
CloseBindSheetByUIContext(const RefPtr<NG::FrameNode> & sheetContentNode,int32_t targetId)4649 void OverlayManager::CloseBindSheetByUIContext(const RefPtr<NG::FrameNode>& sheetContentNode, int32_t targetId)
4650 {
4651     SheetKey sheetKey;
4652     if (!CreateSheetKey(sheetContentNode, targetId, sheetKey)) {
4653         TAG_LOGE(AceLogTag::ACE_SHEET, "CreateSheetKey failed");
4654         return;
4655     }
4656     CloseSheet(sheetKey);
4657 }
4658 
OnBindSheetInner(std::function<void (const std::string &)> && callback,const RefPtr<UINode> & sheetContentNode,std::function<RefPtr<UINode> ()> && buildtitleNodeFunc,NG::SheetStyle & sheetStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && shouldDismiss,std::function<void (const int32_t)> && onWillDismiss,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,std::function<void (const float)> && onHeightDidChange,std::function<void (const float)> && onDetentsDidChange,std::function<void (const float)> && onWidthDidChange,std::function<void (const float)> && onTypeDidChange,std::function<void ()> && sheetSpringBack,const RefPtr<FrameNode> & targetNode,bool isStartByUIContext)4659 void OverlayManager::OnBindSheetInner(std::function<void(const std::string&)>&& callback,
4660     const RefPtr<UINode>& sheetContentNode, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
4661     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
4662     std::function<void()>&& shouldDismiss, std::function<void(const int32_t)>&& onWillDismiss,
4663     std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
4664     std::function<void(const float)>&& onHeightDidChange, std::function<void(const float)>&& onDetentsDidChange,
4665     std::function<void(const float)>&& onWidthDidChange,
4666     std::function<void(const float)>&& onTypeDidChange,
4667     std::function<void()>&& sheetSpringBack, const RefPtr<FrameNode>& targetNode, bool isStartByUIContext)
4668 {
4669     CHECK_NULL_VOID(sheetContentNode);
4670     auto titleBuilder = AceType::DynamicCast<FrameNode>(buildtitleNodeFunc());
4671     if (titleBuilder) {
4672         titleBuilder->GetRenderContext()->SetIsModalRootNode(true);
4673     }
4674 
4675     CHECK_NULL_VOID(targetNode);
4676     auto sheetNode = SheetView::CreateSheetPage(
4677         targetNode->GetId(), targetNode->GetTag(), sheetContentNode, titleBuilder, std::move(callback), sheetStyle);
4678     CHECK_NULL_VOID(sheetNode);
4679     SetSheetProperty(sheetNode, sheetStyle, std::move(onAppear), std::move(onDisappear),
4680         std::move(shouldDismiss), std::move(onWillDismiss),
4681         std::move(onWillAppear), std::move(onWillDisappear), std::move(onHeightDidChange),
4682         std::move(onDetentsDidChange), std::move(onWidthDidChange),
4683         std::move(onTypeDidChange), std::move(sheetSpringBack));
4684     SaveSheePageNode(sheetNode, sheetContentNode, targetNode, isStartByUIContext);
4685     auto maskNode = CreateSheetMask(sheetNode, targetNode, sheetStyle);
4686     CHECK_NULL_VOID(maskNode);
4687 
4688     auto sheetNodePattern = sheetNode->GetPattern<SheetPresentationPattern>();
4689     CHECK_NULL_VOID(sheetNodePattern);
4690     if (onWillAppear) {
4691         TAG_LOGI(AceLogTag::ACE_SHEET, "bindSheet lifecycle change to onWillAppear state.");
4692         onWillAppear();
4693     }
4694     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
4695         sheetNodePattern->OnAppear();
4696     }
4697 
4698     // start transition animation
4699     auto sheetType = sheetNodePattern->GetSheetType();
4700     if (sheetType == SheetType::SHEET_POPUP) {
4701         PlayBubbleStyleSheetTransition(sheetNode, true);
4702     } else {
4703         PlaySheetTransition(sheetNode, true);
4704     }
4705 
4706     auto pageNode = AceType::DynamicCast<FrameNode>(maskNode->GetParent());
4707     CHECK_NULL_VOID(pageNode);
4708     //when sheet shows in page
4709     if (pageNode->GetTag() == V2::PAGE_ETS_TAG) {
4710         //set focus on sheet when page has more than one child
4711         auto focusView = pageNode->GetPattern<FocusView>();
4712         CHECK_NULL_VOID(focusView);
4713         auto focusHub = sheetNode->GetFocusHub();
4714         CHECK_NULL_VOID(focusHub);
4715         focusView->SetViewRootScope(focusHub);
4716     }
4717 }
4718 
SetSheetProperty(const RefPtr<FrameNode> & sheetPageNode,NG::SheetStyle & sheetStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && shouldDismiss,std::function<void (const int32_t)> && onWillDismiss,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,std::function<void (const float)> && onHeightDidChange,std::function<void (const float)> && onDetentsDidChange,std::function<void (const float)> && onWidthDidChange,std::function<void (const float)> && onTypeDidChange,std::function<void ()> && sheetSpringBack)4719 void OverlayManager::SetSheetProperty(
4720     const RefPtr<FrameNode>& sheetPageNode,
4721     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
4722     std::function<void()>&& shouldDismiss, std::function<void(const int32_t)>&& onWillDismiss,
4723     std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
4724     std::function<void(const float)>&& onHeightDidChange, std::function<void(const float)>&& onDetentsDidChange,
4725     std::function<void(const float)>&& onWidthDidChange,
4726     std::function<void(const float)>&& onTypeDidChange,
4727     std::function<void()>&& sheetSpringBack)
4728 {
4729     UpdateSheetRender(sheetPageNode, sheetStyle, true);
4730     auto sheetNodePattern = sheetPageNode->GetPattern<SheetPresentationPattern>();
4731     CHECK_NULL_VOID(sheetNodePattern);
4732     sheetNodePattern->UpdateOnAppear(std::move(onAppear));
4733     sheetNodePattern->UpdateOnDisappear(std::move(onDisappear));
4734     sheetNodePattern->UpdateShouldDismiss(std::move(shouldDismiss));
4735     sheetNodePattern->UpdateOnWillDismiss(std::move(onWillDismiss));
4736     sheetNodePattern->UpdateOnWillDisappear(std::move(onWillDisappear));
4737     sheetNodePattern->UpdateOnHeightDidChange(std::move(onHeightDidChange));
4738     sheetNodePattern->UpdateOnDetentsDidChange(std::move(onDetentsDidChange));
4739     sheetNodePattern->UpdateOnWidthDidChange(std::move(onWidthDidChange));
4740     sheetNodePattern->UpdateOnTypeDidChange(std::move(onTypeDidChange));
4741     sheetNodePattern->UpdateSheetSpringBack(std::move(sheetSpringBack));
4742 }
4743 
SaveSheePageNode(const RefPtr<FrameNode> & sheetPageNode,const RefPtr<UINode> & sheetContentNode,const RefPtr<FrameNode> & targetNode,bool isStartByUIContext)4744 void OverlayManager::SaveSheePageNode(
4745     const RefPtr<FrameNode>& sheetPageNode, const RefPtr<UINode>& sheetContentNode,
4746     const RefPtr<FrameNode>& targetNode, bool isStartByUIContext)
4747 {
4748     int32_t targetId = targetNode->GetId();
4749     auto root = AceType::DynamicCast<FrameNode>(rootNodeWeak_.Upgrade());
4750     CHECK_NULL_VOID(root);
4751     bool isValidTarget = CheckTargetIdIsValid(targetId);
4752     SheetKey sheetKey;
4753     if (isStartByUIContext) {
4754         sheetKey = SheetKey(isValidTarget, sheetContentNode->GetId(), targetId);
4755     } else {
4756         sheetKey = SheetKey(targetId);
4757     }
4758     auto sheetNodePattern = sheetPageNode->GetPattern<SheetPresentationPattern>();
4759     CHECK_NULL_VOID(sheetNodePattern);
4760     sheetNodePattern->SetSheetKey(sheetKey);
4761     sheetMap_.emplace(sheetKey, WeakClaim(RawPtr(sheetPageNode)));
4762     modalStack_.push(WeakClaim(RawPtr(sheetPageNode)));
4763     modalList_.emplace_back(WeakClaim(RawPtr(sheetPageNode)));
4764     SaveLastModalNode();
4765     sheetNodePattern->SetOverlay(AceType::WeakClaim(this));
4766 }
4767 
CheckTargetIdIsValid(int32_t targetId)4768 bool OverlayManager::CheckTargetIdIsValid(int32_t targetId)
4769 {
4770     if (targetId < 0) {
4771         return false;
4772     }
4773     auto rootNode = rootNodeWeak_.Upgrade();
4774     CHECK_NULL_RETURN(rootNode, false);
4775     auto rootId = rootNode->GetId();
4776     return rootId != targetId;
4777 }
4778 
CreateSheetMask(const RefPtr<FrameNode> & sheetPageNode,const RefPtr<FrameNode> & targetNode,NG::SheetStyle & sheetStyle)4779 RefPtr<FrameNode> OverlayManager::CreateSheetMask(const RefPtr<FrameNode>& sheetPageNode,
4780     const RefPtr<FrameNode>& targetNode, NG::SheetStyle& sheetStyle)
4781 {
4782     // create maskColor node(sheetWrapper)
4783     auto maskNode = FrameNode::CreateFrameNode(V2::SHEET_WRAPPER_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
4784         AceType::MakeRefPtr<SheetWrapperPattern>());
4785     CHECK_NULL_RETURN(maskNode, nullptr);
4786     auto maskLayoutProps = maskNode->GetLayoutProperty();
4787     CHECK_NULL_RETURN(maskLayoutProps, nullptr);
4788     maskLayoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT);
4789     maskLayoutProps->UpdateAlignment(Alignment::TOP_LEFT);
4790     auto maskRenderContext = maskNode->GetRenderContext();
4791     CHECK_NULL_RETURN(maskRenderContext, nullptr);
4792     maskRenderContext->UpdateClipEdge(true);
4793     sheetPageNode->MountToParent(maskNode);
4794     InitSheetMask(maskNode, sheetPageNode, sheetStyle);
4795     auto rootNode = FindWindowScene(targetNode);
4796     CHECK_NULL_RETURN(rootNode, nullptr);
4797     MountToParentWithService(rootNode, maskNode);
4798     FireModalPageShow();
4799     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4800     auto pipeline = sheetPageNode->GetContext();
4801     CHECK_NULL_RETURN(pipeline, nullptr);
4802     pipeline->FlushUITasks();
4803     PlaySheetMaskTransition(maskNode, true);
4804     ComputeSheetOffset(sheetStyle, sheetPageNode);
4805     return maskNode;
4806 }
4807 
CreateSheetKey(const RefPtr<NG::FrameNode> & sheetContentNode,int32_t targetId,SheetKey & sheetKey)4808 bool OverlayManager::CreateSheetKey(const RefPtr<NG::FrameNode>& sheetContentNode, int32_t targetId,
4809     SheetKey& sheetKey)
4810 {
4811     CHECK_NULL_RETURN(sheetContentNode, false);
4812     bool isTargetIdValid = CheckTargetIdIsValid(targetId);
4813     if (!isTargetIdValid) {
4814         auto rootNode = rootNodeWeak_.Upgrade();
4815         CHECK_NULL_RETURN(rootNode, false);
4816         targetId = rootNode->GetId();
4817     }
4818     sheetKey = SheetKey(isTargetIdValid, sheetContentNode->GetId(), targetId);
4819     return true;
4820 }
4821 
UpdateSheetMask(const RefPtr<FrameNode> & maskNode,const RefPtr<FrameNode> & sheetNode,const SheetStyle & sheetStyle,bool isPartialUpdate)4822 void OverlayManager::UpdateSheetMask(const RefPtr<FrameNode>& maskNode,
4823     const RefPtr<FrameNode>& sheetNode, const SheetStyle& sheetStyle, bool isPartialUpdate)
4824 {
4825     auto maskRenderContext = maskNode->GetRenderContext();
4826     CHECK_NULL_VOID(maskRenderContext);
4827     auto pipeline = PipelineContext::GetCurrentContext();
4828     CHECK_NULL_VOID(pipeline);
4829     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
4830     CHECK_NULL_VOID(sheetTheme);
4831     auto sheetLayoutProps = sheetNode->GetLayoutProperty<SheetPresentationProperty>();
4832     CHECK_NULL_VOID(sheetLayoutProps);
4833     maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMDEFAULT);
4834 
4835     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
4836         UpdateSheetMaskBackgroundColor(maskNode, maskRenderContext, sheetStyle);
4837     } else {
4838         if (sheetStyle.maskColor.has_value() || !isPartialUpdate) {
4839             maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor()));
4840         }
4841         auto eventConfirmHub = maskNode->GetOrCreateGestureEventHub();
4842         CHECK_NULL_VOID(eventConfirmHub);
4843 
4844         auto maskNodeId = maskNode->GetId();
4845         auto iter = sheetMaskClickEventMap_.find(maskNodeId);
4846         if (iter == sheetMaskClickEventMap_.end() &&
4847             sheetStyle.interactive.has_value() && !sheetStyle.interactive.value()) {
4848             auto sheetMaskClickEvent = AceType::MakeRefPtr<NG::ClickEvent>(
4849                 [weak = AceType::WeakClaim(AceType::RawPtr(sheetNode))](const GestureEvent& /* info */) {
4850                     auto sheet = weak.Upgrade();
4851                     CHECK_NULL_VOID(sheet);
4852                     auto sheetPattern = sheet->GetPattern<SheetPresentationPattern>();
4853                     CHECK_NULL_VOID(sheetPattern);
4854                     if (sheetPattern->IsDragging()) {
4855                         return;
4856                     }
4857                     sheetPattern->SheetInteractiveDismiss(BindSheetDismissReason::TOUCH_OUTSIDE);
4858                 });
4859             sheetMaskClickEventMap_.emplace(maskNodeId, sheetMaskClickEvent);
4860             eventConfirmHub->AddClickEvent(sheetMaskClickEvent, DISTANCE_THRESHOLD);
4861             return;
4862         }
4863 
4864         if ((!sheetStyle.interactive.has_value() && !isPartialUpdate &&
4865                 sheetNode->GetPattern<SheetPresentationPattern>()->GetSheetType() == SheetType::SHEET_POPUP) ||
4866             sheetStyle.interactive.value_or(false)) {
4867             maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
4868                 HitTestMode::HTMTRANSPARENT);
4869             maskRenderContext->UpdateBackgroundColor(Color::TRANSPARENT);
4870             eventConfirmHub->RemoveClickEvent(iter->second);
4871             sheetMaskClickEventMap_.erase(maskNodeId);
4872         }
4873     }
4874 }
4875 
PlayBubbleStyleSheetTransition(RefPtr<FrameNode> sheetNode,bool isTransitionIn)4876 void OverlayManager::PlayBubbleStyleSheetTransition(RefPtr<FrameNode> sheetNode, bool isTransitionIn)
4877 {
4878     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
4879     CHECK_NULL_VOID(sheetPattern);
4880     if (isTransitionIn) {
4881         sheetPattern->ResetToInvisible();
4882         sheetPattern->SetCurrentHeight(sheetHeight_);
4883         sheetPattern->StartOffsetEnteringAnimation();
4884         sheetPattern->FireOnHeightDidChange(sheetHeight_);
4885         sheetPattern->StartAlphaEnteringAnimation([sheetWK = WeakClaim(RawPtr(sheetNode))] {
4886             auto sheet = sheetWK.Upgrade();
4887             CHECK_NULL_VOID(sheet);
4888             auto sheetPattern = sheet->GetPattern<SheetPresentationPattern>();
4889             CHECK_NULL_VOID(sheetPattern);
4890             sheetPattern->ProcessColumnRect();
4891             if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
4892                 sheetPattern->OnAppear();
4893             }
4894         });
4895     } else {
4896         sheetPattern->StartOffsetExitingAnimation();
4897         sheetPattern->StartAlphaExitingAnimation(
4898             [rootWeak = rootNodeWeak_, sheetWK = WeakClaim(RawPtr(sheetNode)), id = Container::CurrentId(),
4899                     weakOverlayManager = WeakClaim(this)] {
4900                 ContainerScope scope(id);
4901                 auto context = PipelineContext::GetCurrentContext();
4902                 CHECK_NULL_VOID(context);
4903                 auto taskExecutor = context->GetTaskExecutor();
4904                 CHECK_NULL_VOID(taskExecutor);
4905                 // animation finish event should be posted to UI thread.
4906                 taskExecutor->PostTask(
4907                     [rootWeak, sheetWK, id, weakOverlayManager]() {
4908                         auto sheet = sheetWK.Upgrade();
4909                         auto overlayManager = weakOverlayManager.Upgrade();
4910                         CHECK_NULL_VOID(sheet && overlayManager);
4911 
4912                         ContainerScope scope(id);
4913                         if (!sheet->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
4914                             sheet->GetPattern<SheetPresentationPattern>()->OnDisappear();
4915                         }
4916                         auto root = overlayManager->FindWindowScene(sheet);
4917                         CHECK_NULL_VOID(root);
4918                         auto sheetParent = DynamicCast<FrameNode>(sheet->GetParent());
4919                         CHECK_NULL_VOID(sheetParent);
4920                          overlayManager->RemoveChildWithService(root, sheetParent);
4921                         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4922                     },
4923                     TaskExecutor::TaskType::UI, "ArkUIOverlaySheetExitingAnimation");
4924             });
4925     }
4926 }
4927 
PlaySheetMaskTransition(RefPtr<FrameNode> maskNode,bool isTransitionIn)4928 void OverlayManager::PlaySheetMaskTransition(RefPtr<FrameNode> maskNode, bool isTransitionIn)
4929 {
4930     AnimationOption option;
4931     const RefPtr<InterpolatingSpring> curve =
4932         AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
4933     option.SetCurve(curve);
4934     option.SetFillMode(FillMode::FORWARDS);
4935     auto context = maskNode->GetRenderContext();
4936     CHECK_NULL_VOID(context);
4937     auto sheetNode = AceType::DynamicCast<FrameNode>(maskNode->GetChildAtIndex(0));
4938     CHECK_NULL_VOID(sheetNode);
4939     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
4940     CHECK_NULL_VOID(sheetPattern);
4941     auto backgroundColor = sheetPattern->GetMaskBackgroundColor();
4942     if (isTransitionIn) {
4943         context->UpdateBackgroundColor(backgroundColor.ChangeOpacity(0.0f));
4944         AnimationUtils::Animate(
4945             option,
4946             [context, backgroundColor]() {
4947                 CHECK_NULL_VOID(context);
4948                 context->UpdateBackgroundColor(backgroundColor);
4949             });
4950     } else {
4951         auto iter = sheetMaskClickEventMap_.find(maskNode->GetId());
4952         if (iter != sheetMaskClickEventMap_.end()) {
4953             auto eventConfirmHub = maskNode->GetOrCreateGestureEventHub();
4954             CHECK_NULL_VOID(eventConfirmHub);
4955             eventConfirmHub->RemoveClickEvent(iter->second);
4956         }
4957         maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMTRANSPARENT);
4958         context->UpdateBackgroundColor(backgroundColor);
4959         AnimationUtils::Animate(
4960             option,
4961             [context, backgroundColor]() {
4962                 CHECK_NULL_VOID(context);
4963                 context->UpdateBackgroundColor(backgroundColor.ChangeOpacity(0.0f));
4964             });
4965     }
4966 }
4967 
SetSheetBackgroundColor(const RefPtr<FrameNode> & sheetNode,const RefPtr<SheetTheme> & sheetTheme,const NG::SheetStyle & sheetStyle,bool isPartialUpdate)4968 void OverlayManager::SetSheetBackgroundColor(const RefPtr<FrameNode>& sheetNode, const RefPtr<SheetTheme>& sheetTheme,
4969     const NG::SheetStyle& sheetStyle, bool isPartialUpdate)
4970 {
4971     if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
4972         if (sheetStyle.backgroundColor.has_value()) {
4973             sheetNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value());
4974         }
4975     } else if (sheetStyle.backgroundColor.has_value() || !isPartialUpdate) {
4976         sheetNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value_or(
4977             sheetTheme->GetSheetBackgoundColor()));
4978     }
4979 }
4980 
SetSheetBackgroundBlurStyle(const RefPtr<FrameNode> & sheetNode,const BlurStyleOption & bgBlurStyle)4981 void OverlayManager::SetSheetBackgroundBlurStyle(const RefPtr<FrameNode>& sheetNode, const BlurStyleOption& bgBlurStyle)
4982 {
4983     auto renderContext = sheetNode->GetRenderContext();
4984     CHECK_NULL_VOID(renderContext);
4985 
4986     if (renderContext->GetBackgroundEffect().has_value()) {
4987         renderContext->UpdateBackgroundEffect(std::nullopt);
4988     }
4989     renderContext->UpdateBackBlurStyle(bgBlurStyle);
4990     if (renderContext->GetBackBlurRadius().has_value()) {
4991         renderContext->UpdateBackBlurRadius(Dimension());
4992     }
4993 }
4994 
CheckTopModalNode(const RefPtr<FrameNode> & topModalNode,int32_t targetId)4995 bool OverlayManager::CheckTopModalNode(const RefPtr<FrameNode>& topModalNode, int32_t targetId)
4996 {
4997     if (topModalNode->GetTag() != V2::SHEET_PAGE_TAG && topModalNode->GetTag() != V2::MODAL_PAGE_TAG) {
4998         return false;
4999     }
5000     if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG ||
5001         topModalNode->GetPattern<ModalPresentationPattern>()->GetTargetId() != targetId) {
5002         DeleteModal(targetId);
5003         return false;
5004     }
5005     return true;
5006 }
5007 
ComputeSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)5008 void OverlayManager::ComputeSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
5009 {
5010     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
5011     CHECK_NULL_VOID(sheetPattern);
5012     auto sheetMaxHeight = sheetPattern->GetPageHeightWithoutOffset();
5013     auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
5014     auto geometryNode = sheetNode->GetGeometryNode();
5015     CHECK_NULL_VOID(geometryNode);
5016     auto sheetHeight = geometryNode->GetFrameSize().Height();
5017 
5018     auto sheetType = sheetPattern->GetSheetType();
5019     switch (sheetType) {
5020         case SheetType::SHEET_BOTTOMLANDSPACE:
5021             if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
5022                 sheetHeight_ = largeHeight;
5023                 break;
5024             }
5025         case SheetType::SHEET_BOTTOM:
5026         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
5027             if (!sheetStyle.detents.empty()) {
5028                 ComputeDetentsSheetOffset(sheetStyle, sheetNode);
5029             } else {
5030                 ComputeSingleGearSheetOffset(sheetStyle, sheetNode);
5031             }
5032             break;
5033         case SheetType::SHEET_CENTER:
5034             sheetHeight_ = (sheetHeight + sheetMaxHeight) / SHEET_HALF_SIZE;
5035             break;
5036         case SheetType::SHEET_POPUP:
5037             sheetHeight_ = sheetMaxHeight;
5038             break;
5039         default:
5040             break;
5041     }
5042 }
5043 
5044 // if device is phone, fold status, screen is in landscape mode, preferType is BOTTOM
CheckDeviceInLandscape(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode,float & sheetTopSafeArea)5045 void OverlayManager::CheckDeviceInLandscape(
5046     NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode, float& sheetTopSafeArea)
5047 {
5048     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
5049     CHECK_NULL_VOID(sheetPattern);
5050     if (sheetStyle.sheetType.has_value() && sheetStyle.sheetType.value() == SheetType::SHEET_BOTTOM &&
5051         sheetPattern->IsPhoneInLandScape()) {
5052         sheetTopSafeArea = 0.0f;
5053     }
5054 }
5055 
ComputeSingleGearSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)5056 void OverlayManager::ComputeSingleGearSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
5057 {
5058     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
5059     CHECK_NULL_VOID(sheetPattern);
5060     auto sheetMaxHeight = sheetPattern->GetPageHeightWithoutOffset();
5061     auto sheetTopSafeArea = sheetPattern->GetSheetTopSafeArea();
5062 
5063     CheckDeviceInLandscape(sheetStyle, sheetNode, sheetTopSafeArea);
5064     auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - sheetTopSafeArea;
5065     if (sheetStyle.sheetMode.has_value()) {
5066         if (sheetStyle.sheetMode == SheetMode::MEDIUM) {
5067             sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE;
5068             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
5069                 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE_PRE;
5070             }
5071         } else if (sheetStyle.sheetMode == SheetMode::LARGE) {
5072             sheetHeight_ = largeHeight;
5073         } else if (sheetStyle.sheetMode == SheetMode::AUTO) {
5074             sheetHeight_ = sheetPattern->GetFitContentHeight();
5075             if (GreatNotEqual(sheetHeight_, largeHeight)) {
5076                 sheetHeight_ = largeHeight;
5077             }
5078         }
5079     } else {
5080         float height = 0.0f;
5081         if (sheetStyle.height->Unit() == DimensionUnit::PERCENT) {
5082             height = sheetStyle.height->ConvertToPxWithSize(sheetMaxHeight - sheetTopSafeArea);
5083         } else {
5084             height = sheetStyle.height->ConvertToPx();
5085         }
5086         if (height > largeHeight) {
5087             sheetHeight_ = largeHeight;
5088         } else if (height < 0) {
5089             sheetHeight_ = largeHeight;
5090         } else {
5091             sheetHeight_ = height;
5092         }
5093     }
5094 }
5095 
ComputeDetentsSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)5096 void OverlayManager::ComputeDetentsSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
5097 {
5098     auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
5099     CHECK_NULL_VOID(sheetPattern);
5100     auto sheetMaxHeight = sheetPattern->GetPageHeightWithoutOffset();
5101     auto sheetTopSafeArea = sheetPattern->GetSheetTopSafeArea();
5102     CheckDeviceInLandscape(sheetStyle, sheetNode, sheetTopSafeArea);
5103     auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - sheetTopSafeArea;
5104     auto selection = sheetStyle.detents[sheetPattern->GetDetentsIndex()];
5105     if (selection.sheetMode.has_value()) {
5106         if (selection.sheetMode == SheetMode::MEDIUM) {
5107             sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE;
5108             if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
5109                 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE_PRE;
5110             }
5111         } else if (selection.sheetMode == SheetMode::LARGE) {
5112             sheetHeight_ = largeHeight;
5113         } else if (selection.sheetMode == SheetMode::AUTO) {
5114             sheetHeight_ = sheetPattern->GetFitContentHeight();
5115             if (GreatNotEqual(sheetHeight_, largeHeight)) {
5116                 sheetHeight_ = largeHeight;
5117             }
5118         }
5119     } else {
5120         float height = 0.0f;
5121         if (selection.height->Unit() == DimensionUnit::PERCENT) {
5122             height = selection.height->ConvertToPxWithSize(sheetMaxHeight - sheetTopSafeArea);
5123         } else {
5124             height = selection.height->ConvertToPx();
5125         }
5126         if (height > largeHeight) {
5127             sheetHeight_ = largeHeight;
5128         } else if (height < 0) {
5129             sheetHeight_ = largeHeight;
5130         } else {
5131             sheetHeight_ = height;
5132         }
5133     }
5134 }
5135 
CleanSheet(const RefPtr<FrameNode> & sheetNode,const SheetKey & sheetKey)5136 void OverlayManager::CleanSheet(const RefPtr<FrameNode>& sheetNode, const SheetKey& sheetKey)
5137 {
5138     if (modalStack_.empty()) {
5139         return;
5140     }
5141     auto iter = sheetMap_.find(sheetKey);
5142     if (sheetMap_.empty() || iter == sheetMap_.end()) {
5143         DeleteModal(sheetKey.targetId, false);
5144         return;
5145     }
5146     auto mapSheetNode = iter->second.Upgrade();
5147     CHECK_NULL_VOID(mapSheetNode);
5148     if (mapSheetNode->GetTag() != V2::SHEET_PAGE_TAG) {
5149         return;
5150     }
5151     if (mapSheetNode->GetPattern<SheetPresentationPattern>()->GetTargetId() != sheetKey.targetId) {
5152         return;
5153     }
5154     ModalPageLostFocus(mapSheetNode);
5155     sheetMap_.erase(sheetKey);
5156     CleanViewContextMap(Container::CurrentId(), sheetKey.contentId);
5157     RemoveSheetNode(sheetNode);
5158     FireModalPageHide();
5159     SaveLastModalNode();
5160 }
5161 
DestroySheet(const RefPtr<FrameNode> & sheetNode,const SheetKey & sheetKey)5162 void OverlayManager::DestroySheet(const RefPtr<FrameNode>& sheetNode, const SheetKey& sheetKey)
5163 {
5164     auto rootNode = FindWindowScene(sheetNode);
5165     CHECK_NULL_VOID(rootNode);
5166     auto root = DynamicCast<FrameNode>(rootNode);
5167     sheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
5168     auto sheetParent = DynamicCast<FrameNode>(sheetNode->GetParent());
5169     CHECK_NULL_VOID(sheetParent);
5170     RemoveChildWithService(root, sheetParent);
5171     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5172 }
5173 
DeleteModal(int32_t targetId,bool needOnWillDisappear)5174 void OverlayManager::DeleteModal(int32_t targetId, bool needOnWillDisappear)
5175 {
5176     bool isDelete = false;
5177     bool isModal = true;
5178     for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
5179         auto modalNode = (*modal).Upgrade();
5180         if (!modalNode) {
5181             continue;
5182         }
5183         int32_t currentTargetId = -1;
5184         if (modalNode->GetTag() == V2::MODAL_PAGE_TAG) {
5185             isModal = true;
5186             currentTargetId = modalNode->GetPattern<ModalPresentationPattern>()->GetTargetId();
5187         } else if (modalNode->GetTag() == V2::SHEET_PAGE_TAG) {
5188             isModal = false;
5189             currentTargetId = modalNode->GetPattern<SheetPresentationPattern>()->GetTargetId();
5190         } else {
5191             return;
5192         }
5193         if (currentTargetId == targetId) {
5194             isDelete = true;
5195             modalList_.erase(modal);
5196             DeleteModalNode(targetId, modalNode, isModal, needOnWillDisappear);
5197             break;
5198         }
5199     }
5200     if (isDelete) {
5201         while (!modalStack_.empty()) {
5202             modalStack_.pop();
5203         }
5204         for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
5205             modalStack_.push(*modal);
5206         }
5207         SaveLastModalNode();
5208     }
5209 }
5210 
DeleteModalNode(int32_t targetId,RefPtr<FrameNode> & modalNode,bool isModal,bool needOnWillDisappear)5211 void OverlayManager::DeleteModalNode(
5212     int32_t targetId, RefPtr<FrameNode>& modalNode, bool isModal, bool needOnWillDisappear)
5213 {
5214     auto rootNode = FindWindowScene(modalNode);
5215     CHECK_NULL_VOID(rootNode);
5216     if (isModal) {
5217         if (needOnWillDisappear) {
5218             modalNode->GetPattern<ModalPresentationPattern>()->OnWillDisappear();
5219         }
5220         modalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
5221         modalNode->GetPattern<ModalPresentationPattern>()->FireCallback("false");
5222         // Fire hidden event of navdestination on the disappeared modal
5223         FireNavigationStateChange(false, modalNode);
5224         RemoveChildWithService(rootNode, modalNode);
5225     } else {
5226         auto sheetPattern = modalNode->GetPattern<SheetPresentationPattern>();
5227         CHECK_NULL_VOID(sheetPattern);
5228         if (needOnWillDisappear) {
5229             sheetPattern->OnWillDisappear();
5230         }
5231         sheetPattern->OnDisappear();
5232         sheetPattern->FireCallback("false");
5233         sheetMap_.erase(sheetPattern->GetSheetKey());
5234         auto sheetParent = DynamicCast<FrameNode>(modalNode->GetParent());
5235         CHECK_NULL_VOID(sheetParent);
5236         RemoveChildWithService(rootNode, sheetParent);
5237     }
5238     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
5239 }
5240 
PopTopModalNode()5241 void OverlayManager::PopTopModalNode()
5242 {
5243     if (!modalStack_.empty()) {
5244         modalStack_.pop();
5245     }
5246     if (!modalList_.empty()) {
5247         modalList_.pop_back();
5248     }
5249 }
5250 
GetSheetMask(const RefPtr<FrameNode> & sheetNode)5251 RefPtr<FrameNode> OverlayManager::GetSheetMask(const RefPtr<FrameNode>& sheetNode)
5252 {
5253     // get bindsheet masknode
5254     CHECK_NULL_RETURN(sheetNode, nullptr);
5255     auto sheetParent = sheetNode->GetParent();
5256     CHECK_NULL_RETURN(sheetParent, nullptr);
5257     return DynamicCast<FrameNode>(sheetParent);
5258 }
5259 
SetCustomKeyboardOption(bool supportAvoidance)5260 void OverlayManager::SetCustomKeyboardOption(bool supportAvoidance)
5261 {
5262     auto pipeline = PipelineContext::GetMainPipelineContext();
5263     CHECK_NULL_VOID(pipeline);
5264     keyboardAvoidance_ = supportAvoidance;
5265 }
5266 
PlayKeyboardTransition(const RefPtr<FrameNode> & customKeyboard,bool isTransitionIn)5267 void OverlayManager::PlayKeyboardTransition(const RefPtr<FrameNode>& customKeyboard, bool isTransitionIn)
5268 {
5269     CHECK_NULL_VOID(customKeyboard);
5270     AnimationOption option;
5271     if (isTransitionIn) {
5272         option.SetCurve(SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE);
5273     } else {
5274         option.SetCurve(HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE);
5275     }
5276     option.SetFillMode(FillMode::FORWARDS);
5277     auto context = customKeyboard->GetRenderContext();
5278     CHECK_NULL_VOID(context);
5279     auto keyboardOffsetInfo = CalcCustomKeyboardOffset(customKeyboard);
5280     if (isTransitionIn) {
5281         context->OnTransformTranslateUpdate({ 0.0f, keyboardOffsetInfo.inAniStartOffset, 0.0f });
5282         AnimationUtils::Animate(option, [context, finalOffset = keyboardOffsetInfo.finalOffset]() {
5283             if (context) {
5284                 context->OnTransformTranslateUpdate({ 0.0f, finalOffset, 0.0f });
5285             }
5286         });
5287     } else {
5288         context->UpdateOpacity(1.0);
5289         option.SetOnFinishEvent([customKeyboard] {
5290             auto parent = customKeyboard->GetParent();
5291             CHECK_NULL_VOID(parent);
5292             parent->RemoveChild(customKeyboard);
5293         });
5294         AnimationUtils::Animate(
5295             option,
5296             [context, outAniEndOffset = keyboardOffsetInfo.outAniEndOffset]() {
5297                 if (context) {
5298                     context->OnTransformTranslateUpdate({ 0.0f, outAniEndOffset, 0.0f });
5299                 }
5300             },
5301             option.GetOnFinishEvent());
5302     }
5303 }
5304 
UpdateCustomKeyboardPosition()5305 void OverlayManager::UpdateCustomKeyboardPosition()
5306 {
5307     for (auto iter = customKeyboardMap_.begin(); iter != customKeyboardMap_.end(); iter++) {
5308         auto customKeyboardNode = iter->second;
5309         if (!customKeyboardNode) {
5310             continue;
5311         }
5312         auto parent = customKeyboardNode->GetParent();
5313         if (!parent) {
5314             continue;
5315         }
5316         auto renderContext = customKeyboardNode->GetRenderContext();
5317         CHECK_NULL_VOID(renderContext);
5318         auto keyboardOffsetInfo = CalcCustomKeyboardOffset(customKeyboardNode);
5319         renderContext->OnTransformTranslateUpdate({ 0.0f, keyboardOffsetInfo.finalOffset, 0.0f });
5320     }
5321 }
5322 
CalcCustomKeyboardOffset(const RefPtr<FrameNode> & customKeyboard)5323 CustomKeyboardOffsetInfo OverlayManager::CalcCustomKeyboardOffset(const RefPtr<FrameNode>& customKeyboard)
5324 {
5325     CustomKeyboardOffsetInfo keyboardOffsetInfo;
5326     CHECK_NULL_RETURN(customKeyboard, keyboardOffsetInfo);
5327     auto pipeline = customKeyboard->GetContext();
5328     CHECK_NULL_RETURN(pipeline, keyboardOffsetInfo);
5329     auto pageNode = pipeline->GetStageManager()->GetLastPage();
5330     CHECK_NULL_RETURN(pageNode, keyboardOffsetInfo);
5331     auto pageHeight = pageNode->GetGeometryNode()->GetFrameSize().Height();
5332     auto keyboardHeight = customKeyboard->GetGeometryNode()->GetFrameSize().Height();
5333     auto rootNode = rootNodeWeak_.Upgrade();
5334     CHECK_NULL_RETURN(rootNode, keyboardOffsetInfo);
5335     auto finalOffset = 0.0f;
5336     if (rootNode->GetTag() == V2::STACK_ETS_TAG) {
5337         auto rootNd = AceType::DynamicCast<FrameNode>(rootNode);
5338         pageHeight = rootNd->GetGeometryNode()->GetFrameSize().Height();
5339         finalOffset = (pageHeight - keyboardHeight) - (pageHeight - keyboardHeight) / NUM_FLOAT_2;
5340     }
5341     keyboardOffsetInfo.finalOffset = finalOffset;
5342     keyboardOffsetInfo.inAniStartOffset = pageHeight;
5343     keyboardOffsetInfo.outAniEndOffset = finalOffset + keyboardHeight;
5344     return keyboardOffsetInfo;
5345 }
5346 
BindKeyboard(const std::function<void ()> & keyboardBuilder,int32_t targetId)5347 void OverlayManager::BindKeyboard(const std::function<void()>& keyboardBuilder, int32_t targetId)
5348 {
5349     if (customKeyboardMap_.find(targetId) != customKeyboardMap_.end()) {
5350         return;
5351     }
5352     auto rootNode = rootNodeWeak_.Upgrade();
5353     CHECK_NULL_VOID(rootNode);
5354     auto customKeyboard = KeyboardView::CreateKeyboard(targetId, keyboardBuilder);
5355     if (!customKeyboard) {
5356         return;
5357     }
5358     ACE_LAYOUT_SCOPED_TRACE("BindKeyboard[targetId:%d]", targetId);
5359     customKeyboard->MountToParent(rootNode);
5360     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5361     customKeyboardMap_[targetId] = customKeyboard;
5362     auto pipeline = PipelineContext::GetCurrentContext();
5363     CHECK_NULL_VOID(pipeline);
5364     pipeline->AddAfterLayoutTask([weak = WeakClaim(this), customKeyboard] {
5365         auto overlayManager = weak.Upgrade();
5366         CHECK_NULL_VOID(overlayManager);
5367         overlayManager->PlayKeyboardTransition(customKeyboard, true);
5368     });
5369 }
5370 
BindKeyboardWithNode(const RefPtr<UINode> & keyboard,int32_t targetId)5371 void OverlayManager::BindKeyboardWithNode(const RefPtr<UINode>& keyboard, int32_t targetId)
5372 {
5373     if (customKeyboardMap_.find(targetId) != customKeyboardMap_.end()) {
5374         return;
5375     }
5376     ACE_LAYOUT_SCOPED_TRACE("BindKeyboardWithNode[targetId:%d]", targetId);
5377     auto rootNode = rootNodeWeak_.Upgrade();
5378     CHECK_NULL_VOID(rootNode);
5379     auto customKeyboard = KeyboardView::CreateKeyboardWithNode(targetId, keyboard);
5380     if (!customKeyboard) {
5381         return;
5382     }
5383     customKeyboard->MountToParent(rootNode);
5384     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5385     customKeyboardMap_[targetId] = customKeyboard;
5386     PlayKeyboardTransition(customKeyboard, true);
5387 }
5388 
CloseKeyboard(int32_t targetId)5389 void OverlayManager::CloseKeyboard(int32_t targetId)
5390 {
5391     auto it = customKeyboardMap_.find(targetId);
5392     if (it == customKeyboardMap_.end()) {
5393         return;
5394     }
5395     ACE_LAYOUT_SCOPED_TRACE("CloseKeyboard[targetId:%d]", targetId);
5396     auto customKeyboard = it->second;
5397     CHECK_NULL_VOID(customKeyboard);
5398     auto pipeline = customKeyboard->GetContext();
5399     CHECK_NULL_VOID(pipeline);
5400     auto pattern = customKeyboard->GetPattern<KeyboardPattern>();
5401     CHECK_NULL_VOID(pattern);
5402     customKeyboardMap_.erase(pattern->GetTargetId());
5403     PlayKeyboardTransition(customKeyboard, false);
5404     Rect keyboardRect = Rect(0.0f, 0.0f, 0.0f, 0.0f);
5405     pipeline->OnVirtualKeyboardAreaChange(keyboardRect);
5406 }
5407 
AvoidCustomKeyboard(int32_t targetId,float safeHeight)5408 void OverlayManager::AvoidCustomKeyboard(int32_t targetId, float safeHeight)
5409 {
5410     auto it = customKeyboardMap_.find(targetId);
5411     if (it == customKeyboardMap_.end()) {
5412         return;
5413     }
5414     auto customKeyboard = it->second;
5415     CHECK_NULL_VOID(customKeyboard);
5416     auto pattern = customKeyboard->GetPattern<KeyboardPattern>();
5417     CHECK_NULL_VOID(pattern);
5418     pattern->SetKeyboardSafeHeight(safeHeight);
5419     pattern->SetKeyboardAreaChange(keyboardAvoidance_);
5420     pattern->SetKeyboardOption(keyboardAvoidance_);
5421 }
5422 
5423 // This function will be used in SceneBoard Thread only.
5424 // if need to show the pop-up component,
5425 //   it expects to receive the target component bound by the pop-up component to find the windowScene component.
5426 // if need to hide the pop-up component,
5427 //   it expects to receive the the pop-up component to return the parent component.
5428 //   And the parent component will be the windowScene component exactly.
FindWindowScene(RefPtr<FrameNode> targetNode)5429 RefPtr<UINode> OverlayManager::FindWindowScene(RefPtr<FrameNode> targetNode)
5430 {
5431     auto container = Container::Current();
5432     if (!container || !container->IsScenceBoardWindow() || isAttachToCustomNode_) {
5433         return rootNodeWeak_.Upgrade();
5434     }
5435     CHECK_NULL_RETURN(targetNode, nullptr);
5436     auto parent = targetNode->GetParent();
5437     while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
5438         parent = parent->GetParent();
5439     }
5440     CHECK_NULL_RETURN(parent, nullptr);
5441     windowSceneSet_.insert(parent);
5442     return parent;
5443 }
5444 
MountFilterToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)5445 void OverlayManager::MountFilterToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
5446 {
5447     CHECK_NULL_VOID(windowScene);
5448     columnNode->MountToParent(windowScene);
5449     columnNode->OnMountToParentDone();
5450     windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
5451     filterColumnNodeWeak_ = columnNode;
5452     hasFilter_ = true;
5453 }
5454 
5455 /**
5456  * Mount pixelMap to wndow scene for lifting or for drag moving.
5457  * When isDragPixelMap is true, the pixelMap is saved by dragPixmapColumnNodeWeak_ used for moving with drag finger or
5458  * mouse, etc.
5459  * When isDragPixelMap is false, the pixelMap is saved by pixmapColumnNodeWeak_ used for lifting.
5460  */
MountPixelMapToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene,bool isDragPixelMap)5461 void OverlayManager::MountPixelMapToWindowScene(
5462     const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene, bool isDragPixelMap)
5463 {
5464     CHECK_NULL_VOID(windowScene);
5465     columnNode->MountToParent(windowScene);
5466     columnNode->OnMountToParentDone();
5467     windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
5468     if (isDragPixelMap) {
5469         dragPixmapColumnNodeWeak_ = columnNode;
5470         hasDragPixelMap_ = true;
5471     } else {
5472         pixmapColumnNodeWeak_ = columnNode;
5473         hasPixelMap_ = true;
5474     }
5475 }
5476 
MountEventToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)5477 void OverlayManager::MountEventToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
5478 {
5479     CHECK_NULL_VOID(windowScene);
5480     columnNode->MountToParent(windowScene);
5481     columnNode->OnMountToParentDone();
5482     eventColumnNodeWeak_ = columnNode;
5483     hasEvent_ = true;
5484 }
5485 
5486 /**
5487  * Mount pixelMap to root node for lifting or for drag moving.
5488  * When isDragPixelMap is true, the pixelMap is saved by dragPixmapColumnNodeWeak_ used for moving with drag finger or
5489  * mouse, etc.
5490  * When isDragPixelMap is false, the pixelMap is saved by pixmapColumnNodeWeak_ used for lifting.
5491  */
MountPixelMapToRootNode(const RefPtr<FrameNode> & columnNode,bool isDragPixelMap)5492 void OverlayManager::MountPixelMapToRootNode(const RefPtr<FrameNode>& columnNode, bool isDragPixelMap)
5493 {
5494     auto rootNode = rootNodeWeak_.Upgrade();
5495     CHECK_NULL_VOID(rootNode);
5496     columnNode->MountToParent(rootNode);
5497     columnNode->OnMountToParentDone();
5498     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
5499     if (isDragPixelMap) {
5500         dragPixmapColumnNodeWeak_ = columnNode;
5501         hasDragPixelMap_ = true;
5502     } else {
5503         pixmapColumnNodeWeak_ = columnNode;
5504         hasPixelMap_ = true;
5505     }
5506 }
5507 
MountEventToRootNode(const RefPtr<FrameNode> & columnNode)5508 void OverlayManager::MountEventToRootNode(const RefPtr<FrameNode>& columnNode)
5509 {
5510     auto rootNode = rootNodeWeak_.Upgrade();
5511     CHECK_NULL_VOID(rootNode);
5512     columnNode->MountToParent(rootNode, EVENT_COLUMN_SLOT);
5513     columnNode->OnMountToParentDone();
5514     eventColumnNodeWeak_ = columnNode;
5515     hasEvent_ = true;
5516 }
5517 
RemovePixelMap()5518 void OverlayManager::RemovePixelMap()
5519 {
5520     if (!hasPixelMap_) {
5521         return;
5522     }
5523     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
5524     if (!columnNode) {
5525         hasPixelMap_ = false;
5526         isOnAnimation_ = false;
5527         return;
5528     }
5529     auto rootNode = columnNode->GetParent();
5530     CHECK_NULL_VOID(rootNode);
5531     rootNode->RemoveChild(columnNode);
5532     rootNode->RebuildRenderContextTree();
5533     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
5534     hasPixelMap_ = false;
5535     isOnAnimation_ = false;
5536 }
5537 
RemovePixelMapAnimation(bool startDrag,double x,double y,bool isSubwindowOverlay)5538 void OverlayManager::RemovePixelMapAnimation(bool startDrag, double x, double y, bool isSubwindowOverlay)
5539 {
5540     if (isOnAnimation_ || !hasPixelMap_) {
5541         return;
5542     }
5543     if (startDrag) {
5544         if (!isSubwindowOverlay) {
5545             RemovePixelMap();
5546         }
5547         return;
5548     }
5549     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
5550     if (!columnNode) {
5551         RemoveEventColumn();
5552         hasPixelMap_ = false;
5553         return;
5554     }
5555     auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetFirstChild());
5556     CHECK_NULL_VOID(imageNode);
5557     auto imageContext = imageNode->GetRenderContext();
5558     CHECK_NULL_VOID(imageContext);
5559     auto hub = columnNode->GetOrCreateGestureEventHub();
5560     CHECK_NULL_VOID(hub);
5561     auto frameNode = hub->GetFrameNode();
5562     CHECK_NULL_VOID(frameNode);
5563     RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
5564     CHECK_NULL_VOID(pixelMap);
5565     float scale = PIXELMAP_DRAG_SCALE;
5566     UpdatePixelMapScale(scale);
5567     int32_t width = pixelMap->GetWidth();
5568     int32_t height = pixelMap->GetHeight();
5569 
5570     auto shadow = imageContext->GetBackShadow();
5571     if (!shadow.has_value()) {
5572         shadow = Shadow::CreateShadow(ShadowStyle::None);
5573     }
5574     imageContext->UpdateBackShadow(shadow.value());
5575     AnimationOption option;
5576     option.SetCurve(Curves::SHARP);
5577     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
5578     AnimationUtils::Animate(option, [imageContext, shadow]() mutable {
5579         if (imageContext) {
5580             auto color = shadow->GetColor();
5581             auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue());
5582             shadow->SetColor(newColor);
5583             imageContext->UpdateBackShadow(shadow.value());
5584             BorderRadiusProperty borderRadius;
5585             borderRadius.SetRadius(0.0_vp);
5586             imageContext->UpdateBorderRadius(borderRadius);
5587         }
5588     });
5589 
5590     auto pipelineContext = PipelineContext::GetCurrentContext();
5591     CHECK_NULL_VOID(pipelineContext);
5592     auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
5593     CHECK_NULL_VOID(menuTheme);
5594     auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
5595     auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
5596 
5597     AnimationOption scaleOption;
5598     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
5599     scaleOption.SetCurve(motion);
5600 
5601     DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LANDING_STARTED);
5602     scaleOption.SetOnFinishEvent([weak = WeakClaim(this), isSubwindowOverlay] {
5603         auto pipeline = PipelineContext::GetCurrentContext();
5604         CHECK_NULL_VOID(pipeline);
5605         auto dragDropManager = pipeline->GetDragDropManager();
5606         CHECK_NULL_VOID(dragDropManager);
5607         DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LANDING_FINISHED);
5608         if (!dragDropManager->IsNeedDisplayInSubwindow() && !isSubwindowOverlay) {
5609             InteractionInterface::GetInstance()->SetDragWindowVisible(true);
5610         }
5611         auto overlayManager = weak.Upgrade();
5612         CHECK_NULL_VOID(overlayManager);
5613         if (overlayManager->hasEvent_) {
5614             overlayManager->RemoveEventColumn();
5615         }
5616         overlayManager->RemovePixelMap();
5617     });
5618 
5619     auto coordinateX = imageNode->GetOffsetRelativeToWindow().GetX() - frameNode->GetOffsetRelativeToWindow().GetX();
5620     auto coordinateY = imageNode->GetOffsetRelativeToWindow().GetY() - frameNode->GetOffsetRelativeToWindow().GetY();
5621     AnimationUtils::Animate(
5622         scaleOption,
5623         [imageContext, startDrag, x, y, width, height, scale, coordinateX, coordinateY]() {
5624             if (startDrag) {
5625                 imageContext->UpdatePosition(OffsetT<Dimension>(
5626                     Dimension(x - (x - coordinateX) * scale +
5627                               PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * width * (scale - PIXELMAP_DRAG_SCALE)),
5628                     Dimension(y - (y - coordinateY) * scale +
5629                               PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * height * (scale - PIXELMAP_DRAG_SCALE))));
5630                 imageContext->UpdateTransformScale({ scale, scale });
5631                 imageContext->OnModifyDone();
5632             } else {
5633                 imageContext->UpdateTransformScale(VectorF(1.0f, 1.0f));
5634             }
5635         },
5636         scaleOption.GetOnFinishEvent());
5637     isOnAnimation_ = true;
5638 }
5639 
RemoveDragPixelMap()5640 void OverlayManager::RemoveDragPixelMap()
5641 {
5642     TAG_LOGI(AceLogTag::ACE_DRAG, "remove drag pixelMap enter");
5643     if (!hasDragPixelMap_) {
5644         return;
5645     }
5646     auto columnNode = dragPixmapColumnNodeWeak_.Upgrade();
5647     if (!columnNode) {
5648         hasDragPixelMap_ = false;
5649         return;
5650     }
5651     auto rootNode = columnNode->GetParent();
5652     CHECK_NULL_VOID(rootNode);
5653     rootNode->RemoveChild(columnNode);
5654     rootNode->RebuildRenderContextTree();
5655     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
5656     hasDragPixelMap_ = false;
5657 }
5658 
UpdatePixelMapScale(float & scale)5659 void OverlayManager::UpdatePixelMapScale(float& scale)
5660 {
5661     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
5662     CHECK_NULL_VOID(columnNode);
5663     auto hub = columnNode->GetOrCreateGestureEventHub();
5664     CHECK_NULL_VOID(hub);
5665     RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
5666     CHECK_NULL_VOID(pixelMap);
5667     int32_t height = pixelMap->GetHeight();
5668     int32_t width = pixelMap->GetWidth();
5669     if (height == 0 || width == 0) {
5670         return;
5671     }
5672     int32_t deviceWidth = SystemProperties::GetDeviceWidth();
5673     int32_t deviceHeight = SystemProperties::GetDeviceHeight();
5674     int32_t maxDeviceLength = std::max(deviceHeight, deviceWidth);
5675     int32_t minDeviceLength = std::min(deviceHeight, deviceWidth);
5676     if (maxDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE > minDeviceLength) {
5677         if (height > minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) {
5678             scale = static_cast<float>(minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) / height;
5679         }
5680     } else {
5681         if (hub->GetTextDraggable() && height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
5682             width > minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) {
5683             scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
5684                 static_cast<float>(minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) / width);
5685         } else if (height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
5686                    width > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) {
5687             scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
5688                 static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / width);
5689         }
5690     }
5691 }
5692 
RemoveFilterAnimation()5693 void OverlayManager::RemoveFilterAnimation()
5694 {
5695     if (!hasFilter_) {
5696         return;
5697     }
5698     auto filterNode = filterColumnNodeWeak_.Upgrade();
5699     CHECK_NULL_VOID(filterNode);
5700     auto filterContext = filterNode->GetRenderContext();
5701     CHECK_NULL_VOID(filterContext);
5702     auto pipelineContext = PipelineContext::GetCurrentContext();
5703     CHECK_NULL_VOID(pipelineContext);
5704     auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
5705     CHECK_NULL_VOID(menuTheme);
5706     AnimationOption option;
5707     option.SetOnFinishEvent([weak = WeakClaim(this)] {
5708         auto overlayManager = weak.Upgrade();
5709         CHECK_NULL_VOID(overlayManager);
5710         if (!overlayManager->hasFilterActived) {
5711             overlayManager->RemoveFilter();
5712         }
5713     });
5714     option.SetDuration(menuTheme->GetFilterAnimationDuration());
5715     option.SetCurve(Curves::SHARP);
5716     AnimationUtils::Animate(
5717         option,
5718         [filterContext]() {
5719             CHECK_NULL_VOID(filterContext);
5720             BlurStyleOption styleOption;
5721             styleOption.blurStyle = BlurStyle::NO_MATERIAL;
5722             filterContext->UpdateBackBlurStyle(styleOption);
5723         },
5724         option.GetOnFinishEvent());
5725 }
5726 
RemoveFilter()5727 void OverlayManager::RemoveFilter()
5728 {
5729     if (!hasFilter_) {
5730         return;
5731     }
5732     auto columnNode = filterColumnNodeWeak_.Upgrade();
5733     if (columnNode) {
5734         auto rootNode = columnNode->GetParent();
5735         CHECK_NULL_VOID(rootNode);
5736         rootNode->RemoveChild(columnNode);
5737         rootNode->RebuildRenderContextTree();
5738     }
5739     hasFilter_ = false;
5740 }
5741 
RemoveEventColumn()5742 void OverlayManager::RemoveEventColumn()
5743 {
5744     if (!hasEvent_) {
5745         TAG_LOGI(AceLogTag::ACE_DRAG, "remove eventColumn, hasEvent is false.");
5746         return;
5747     }
5748     auto columnNode = eventColumnNodeWeak_.Upgrade();
5749     if (!columnNode) {
5750         hasEvent_ = false;
5751         TAG_LOGI(AceLogTag::ACE_DRAG, "remove eventColumn, columnNode is null.");
5752         return;
5753     }
5754     auto rootNode = columnNode->GetParent();
5755     CHECK_NULL_VOID(rootNode);
5756     rootNode->RemoveChild(columnNode);
5757     hasEvent_ = false;
5758     TAG_LOGI(AceLogTag::ACE_DRAG, "remove eventColumn success, id %{public}d.", columnNode->GetId());
5759 }
5760 
ResetRootNode(int32_t sessionId)5761 void OverlayManager::ResetRootNode(int32_t sessionId)
5762 {
5763     if (curSessionIds_.find(sessionId) == curSessionIds_.end()) {
5764         return;
5765     }
5766 
5767     TAG_LOGI(AceLogTag::ACE_OVERLAY, "ResetRootNode %{public}d.", sessionId);
5768     curSessionIds_.erase(sessionId);
5769     auto rootNode = FindWindowScene(nullptr);
5770     CHECK_NULL_VOID(rootNode);
5771     rootNode->UpdateModalUiextensionCount(false);
5772 }
5773 
SetIsAllowedBeCovered(bool isAllowedBeCovered)5774 void OverlayManager::SetIsAllowedBeCovered(bool isAllowedBeCovered)
5775 {
5776     isAllowedBeCovered_ = isAllowedBeCovered;
5777 }
5778 
AddCurSessionId(int32_t sessionId)5779 bool OverlayManager::AddCurSessionId(int32_t sessionId)
5780 {
5781     if (curSessionIds_.find(sessionId) != curSessionIds_.end()) {
5782         return false;
5783     }
5784 
5785     curSessionIds_.insert(sessionId);
5786     return true;
5787 }
5788 
CreateModalUIExtension(const RefPtr<WantWrap> & wantWrap,const ModalUIExtensionCallbacks & callbacks,const ModalUIExtensionConfig & config)5789 int32_t OverlayManager::CreateModalUIExtension(const RefPtr<WantWrap>& wantWrap,
5790     const ModalUIExtensionCallbacks& callbacks, const ModalUIExtensionConfig& config)
5791 {
5792     auto& want = wantWrap->GetWant();
5793     return CreateModalUIExtension(want, callbacks, config);
5794 }
5795 
HandleUIExtNodeSize(const AAFwk::Want & want,RefPtr<FrameNode> uiExtNode)5796 bool OverlayManager::HandleUIExtNodeSize(const AAFwk::Want& want, RefPtr<FrameNode> uiExtNode)
5797 {
5798 #if defined(OHOS_STANDARD_SYSTEM) and !defined(ACE_UNITTEST)
5799     auto uiExtNodeWidth = want.GetIntParam(WANT_PARAM_UIEXTNODE_WIDTH_KEY, 0);
5800     auto uiExtNodeHeight = want.GetIntParam(WANT_PARAM_UIEXTNODE_HEIGHT_KEY, 0);
5801 #else
5802     auto uiExtNodeWidth = 0;
5803     auto uiExtNodeHeight = 0;
5804 #endif
5805     auto layoutProperty = uiExtNode->GetLayoutProperty();
5806     CHECK_NULL_RETURN(layoutProperty, false);
5807     auto calcWidth =
5808         CalcLength((uiExtNodeWidth > 0) ? Dimension(uiExtNodeWidth) : Dimension(1.0, DimensionUnit::PERCENT));
5809     auto calcHeight =
5810         CalcLength((uiExtNodeHeight > 0) ? Dimension(uiExtNodeHeight) : Dimension(1.0, DimensionUnit::PERCENT));
5811     TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT,
5812         "UIExtensionNode Size[%{public}d, [%{public}d].", uiExtNodeWidth, uiExtNodeHeight);
5813     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(calcWidth, calcHeight));
5814     return true;
5815 }
5816 
HandleUIExtNodeAngle(int32_t uiExtNodeAngle,RefPtr<FrameNode> uiExtNode)5817 bool OverlayManager::HandleUIExtNodeAngle(int32_t uiExtNodeAngle, RefPtr<FrameNode> uiExtNode)
5818 {
5819     auto layoutProperty = uiExtNode->GetLayoutProperty();
5820     CHECK_NULL_RETURN(layoutProperty, false);
5821     const auto& renderContext = uiExtNode->GetRenderContext();
5822     CHECK_NULL_RETURN(renderContext, false);
5823     TAG_LOGD(AceLogTag::ACE_UIEXTENSIONCOMPONENT, "RootSize[%{public}f, %{public}f], Angle[%{public}d].",
5824         GetRootWidth(), GetRootHeight(), uiExtNodeAngle);
5825     switch (uiExtNodeAngle) {
5826         case UIEXTNODE_ANGLE_90: {
5827             layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(Dimension(GetRootHeight())),
5828                 CalcLength(Dimension(GetRootWidth()))));
5829             TranslateOptions translate(GetRootWidth(), 0, 0);
5830             renderContext->UpdateTransformTranslate(translate);
5831             NG::Vector5F rotate(0.0f, 0.0f, 1.0f, 90.0f, 0.0f);
5832             DimensionOffset offset(Dimension(0), Dimension(0));
5833             renderContext->UpdateTransformRotate(rotate);
5834             renderContext->UpdateTransformCenter(offset);
5835             break;
5836         }
5837         case UIEXTNODE_ANGLE_180: {
5838             auto full = CalcLength(Dimension(1.0, DimensionUnit::PERCENT));
5839             layoutProperty->UpdateUserDefinedIdealSize(CalcSize(full, full));
5840             NG::Vector5F rotate(0.0f, 0.0f, 1.0f, 180.0f, 0.0f);
5841             DimensionOffset offset(0.5_pct, 0.5_pct);
5842             renderContext->UpdateTransformRotate(rotate);
5843             renderContext->UpdateTransformCenter(offset);
5844             break;
5845         }
5846         case UIEXTNODE_ANGLE_270: {
5847             layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(Dimension(GetRootHeight())),
5848                 CalcLength(Dimension(GetRootWidth()))));
5849             TranslateOptions translate(0, GetRootHeight(), 0);
5850             renderContext->UpdateTransformTranslate(translate);
5851             NG::Vector5F rotate(0.0f, 0.0f, 1.0f, 270.0f, 0.0f);
5852             DimensionOffset offset(Dimension(0), Dimension(0));
5853             renderContext->UpdateTransformRotate(rotate);
5854             renderContext->UpdateTransformCenter(offset);
5855             break;
5856         }
5857     }
5858     return true;
5859 }
5860 
HandleUIExtNodeTransform(const AAFwk::Want & want,RefPtr<FrameNode> uiExtNode)5861 bool OverlayManager::HandleUIExtNodeTransform(const AAFwk::Want& want, RefPtr<FrameNode> uiExtNode)
5862 {
5863     auto containerId = Container::CurrentId();
5864     auto foldWindow = FoldableWindow::CreateFoldableWindow(containerId);
5865     bool isFoldExpand = foldWindow && (foldWindow->IsFoldExpand());
5866 #if defined(OHOS_STANDARD_SYSTEM) and !defined(ACE_UNITTEST)
5867     auto uiExtNodeAngle = want.GetIntParam(WANT_PARAM_UIEXTNODE_ANGLE_KEY, 0);
5868 #else
5869     auto uiExtNodeAngle = 0;
5870 #endif
5871     if (!(isFoldExpand) && UIExtNodeAngleValid(uiExtNodeAngle)) {
5872         return HandleUIExtNodeAngle(uiExtNodeAngle, uiExtNode);
5873     } else if (!UIExtNodeAngleValid(uiExtNodeAngle)) {
5874         return HandleUIExtNodeSize(want, uiExtNode);
5875     }
5876     return true;
5877 }
5878 
UIExtNodeAngleValid(int32_t uiExtNodeAngle)5879 bool OverlayManager::UIExtNodeAngleValid(int32_t uiExtNodeAngle)
5880 {
5881     return (uiExtNodeAngle == UIEXTNODE_ANGLE_90) ||
5882         (uiExtNodeAngle == UIEXTNODE_ANGLE_180) || (uiExtNodeAngle == UIEXTNODE_ANGLE_270);
5883 }
5884 
CreateModalUIExtension(const AAFwk::Want & want,const ModalUIExtensionCallbacks & callbacks,const ModalUIExtensionConfig & config)5885 int32_t OverlayManager::CreateModalUIExtension(
5886     const AAFwk::Want& want, const ModalUIExtensionCallbacks& callbacks,
5887     const ModalUIExtensionConfig& config)
5888 {
5889     isProhibitBack_ = config.isProhibitBack;
5890     NG::InnerModalUIExtensionConfig innerModalUIExtensionConfig = { .isAsyncModalBinding = config.isAsyncModalBinding,
5891         .isDensityFollowHost = config.isDensityFollowHost };
5892     auto uiExtNode = ModalUIExtension::Create(want, callbacks, innerModalUIExtensionConfig);
5893     if (!HandleUIExtNodeTransform(want, uiExtNode)) {
5894         return 0;
5895     }
5896     auto buildNodeFunc = [uiExtNode]() -> RefPtr<UINode> {
5897         uiExtNode->MarkModifyDone();
5898         return uiExtNode;
5899     };
5900     auto sessionId = ModalUIExtension::GetSessionId(uiExtNode);
5901     if (!config.isAsyncModalBinding) {
5902         ModalStyle modalStyle;
5903         modalStyle.modalTransition = NG::ModalTransition::NONE;
5904         modalStyle.isUIExtension = true;
5905         modalStyle.prohibitedRemoveByRouter = config.prohibitedRemoveByRouter;
5906         SetIsAllowedBeCovered(config.isAllowedBeCovered);
5907         // Convert the sessionId into a negative number to distinguish it from the targetId of other modal pages
5908         BindContentCover(true, nullptr, std::move(buildNodeFunc), modalStyle, nullptr, nullptr, nullptr, nullptr,
5909             ContentCoverParam(), nullptr, -(sessionId));
5910         SetIsAllowedBeCovered(true); // Reset isAllowedBeCovered
5911     } else {
5912         auto bindModalCallback = [weak = WeakClaim(this), buildNodeFunc, sessionId, id = Container::CurrentId(),
5913             isAllowedBeCovered = config.isAllowedBeCovered,
5914             prohibitedRemoveByRouter = config.prohibitedRemoveByRouter,
5915             doAfterAsyncModalBinding = std::move(config.doAfterAsyncModalBinding)]() {
5916             ContainerScope scope(id);
5917             auto overlayManager = weak.Upgrade();
5918             CHECK_NULL_VOID(overlayManager);
5919             overlayManager->SetIsAllowedBeCovered(isAllowedBeCovered);
5920             ModalStyle modalStyle;
5921             modalStyle.modalTransition = NG::ModalTransition::NONE;
5922             modalStyle.isUIExtension = true;
5923             modalStyle.prohibitedRemoveByRouter = prohibitedRemoveByRouter;
5924             overlayManager->BindContentCover(true, nullptr, std::move(buildNodeFunc), modalStyle, nullptr, nullptr,
5925                 nullptr, nullptr, ContentCoverParam(), nullptr, -(sessionId));
5926             overlayManager->SetIsAllowedBeCovered(true);
5927             if (doAfterAsyncModalBinding) {
5928                 doAfterAsyncModalBinding();
5929             }
5930         };
5931         ModalUIExtension::SetBindModalCallback(uiExtNode, std::move(bindModalCallback));
5932         uiExtNodes_[sessionId] = WeakClaim(RawPtr(uiExtNode));
5933     }
5934     return sessionId;
5935 }
5936 
ClearUIExtensionNode()5937 void OverlayManager::ClearUIExtensionNode()
5938 {
5939     for (auto& item: uiExtNodes_) {
5940         auto uiExtNode = item.second.Upgrade();
5941         if (uiExtNode) {
5942             ModalUIExtension::SetBindModalCallback(uiExtNode, nullptr);
5943         }
5944     }
5945     uiExtNodes_.clear();
5946 }
5947 
DeleteUIExtensionNode(int32_t sessionId)5948 void OverlayManager::DeleteUIExtensionNode(int32_t sessionId)
5949 {
5950     auto iter = uiExtNodes_.find(sessionId);
5951     if (iter != uiExtNodes_.end()) {
5952         auto uiExtNode = iter->second.Upgrade();
5953         if (uiExtNode) {
5954             ModalUIExtension::SetBindModalCallback(uiExtNode, nullptr);
5955         }
5956         uiExtNodes_.erase(sessionId);
5957     }
5958 }
5959 
CloseModalUIExtension(int32_t sessionId)5960 void OverlayManager::CloseModalUIExtension(int32_t sessionId)
5961 {
5962     DeleteUIExtensionNode(sessionId);
5963     ModalStyle modalStyle;
5964     modalStyle.modalTransition = NG::ModalTransition::NONE;
5965     BindContentCover(false, nullptr, nullptr, modalStyle, nullptr, nullptr, nullptr, nullptr, ContentCoverParam(),
5966         nullptr, -(sessionId));
5967     ResetRootNode(-(sessionId));
5968 }
5969 
BuildAIEntityMenu(const std::vector<std::pair<std::string,std::function<void ()>>> & menuOptions)5970 RefPtr<FrameNode> OverlayManager::BuildAIEntityMenu(
5971     const std::vector<std::pair<std::string, std::function<void()>>>& menuOptions)
5972 {
5973     TAG_LOGI(AceLogTag::ACE_OVERLAY, "build AI entity menu enter");
5974     auto menuNode = FrameNode::CreateFrameNode(V2::MENU_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
5975         AceType::MakeRefPtr<InnerMenuPattern>(-1, V2::MENU_ETS_TAG, MenuType::MULTI_MENU));
5976     CHECK_NULL_RETURN(menuNode, nullptr);
5977     for (const auto& menuOption : menuOptions) {
5978         MenuItemGroupView::Create();
5979         auto menuItemGroupNode = DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
5980         CHECK_NULL_RETURN(menuItemGroupNode, nullptr);
5981         MenuItemProperties menuItemProperties;
5982         menuItemProperties.content = menuOption.first;
5983         MenuItemModelNG menuItemModel;
5984         menuItemModel.Create(menuItemProperties);
5985         auto menuItemNode = DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
5986         CHECK_NULL_RETURN(menuItemNode, nullptr);
5987         auto menuItemPattern = menuItemNode->GetPattern<MenuItemPattern>();
5988         CHECK_NULL_RETURN(menuItemPattern, nullptr);
5989         menuItemPattern->SetOnClickAIMenuItem(menuOption.second);
5990         menuItemNode->MountToParent(menuItemGroupNode);
5991         menuItemGroupNode->MountToParent(menuNode);
5992     }
5993     return menuNode;
5994 }
5995 
CreateAIEntityMenu(const std::vector<std::pair<std::string,std::function<void ()>>> & menuOptions,const RefPtr<FrameNode> & targetNode)5996 RefPtr<FrameNode> OverlayManager::CreateAIEntityMenu(
5997     const std::vector<std::pair<std::string, std::function<void()>>>& menuOptions, const RefPtr<FrameNode>& targetNode)
5998 {
5999     TAG_LOGI(AceLogTag::ACE_OVERLAY, "create AI entity menu enter");
6000     CHECK_NULL_RETURN(targetNode, nullptr);
6001     auto pipeline = PipelineContext::GetCurrentContext();
6002     CHECK_NULL_RETURN(pipeline, nullptr);
6003     MenuParam menuParam;
6004     menuParam.type = MenuType::MENU;
6005     menuParam.placement = Placement::BOTTOM_LEFT;
6006     auto menuWrapperNode =
6007         MenuView::Create(BuildAIEntityMenu(menuOptions), targetNode->GetId(), targetNode->GetTag(), menuParam, true);
6008     return menuWrapperNode;
6009 }
6010 
ShowAIEntityMenu(const std::vector<std::pair<std::string,std::function<void ()>>> & menuOptions,const RectF & aiRect,const RefPtr<FrameNode> & targetNode)6011 bool OverlayManager::ShowAIEntityMenu(const std::vector<std::pair<std::string, std::function<void()>>>& menuOptions,
6012     const RectF& aiRect, const RefPtr<FrameNode>& targetNode)
6013 {
6014     TAG_LOGI(AceLogTag::ACE_OVERLAY, "show AI entity menu enter");
6015     CHECK_NULL_RETURN(targetNode, false);
6016     auto menuWrapperNode = CreateAIEntityMenu(menuOptions, targetNode);
6017     CHECK_NULL_RETURN(menuWrapperNode, false);
6018     menuWrapperNode->GetOrCreateFocusHub()->SetFocusable(false);
6019     auto wrapperPattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
6020     CHECK_NULL_RETURN(wrapperPattern, false);
6021     auto pipeline = targetNode->GetContext();
6022     CHECK_NULL_RETURN(pipeline, false);
6023     auto safeAreaManager = pipeline->GetSafeAreaManager();
6024     CHECK_NULL_RETURN(safeAreaManager, false);
6025     auto targetId = targetNode->GetId();
6026     wrapperPattern->RegisterMenuAppearCallback([overlayWk = WeakClaim(this),
6027         safeAreaWK = WeakClaim(RawPtr(safeAreaManager)), targetId, containerId = Container::CurrentId()]() {
6028             ContainerScope scope(containerId);
6029             auto safeAreaManager = safeAreaWK.Upgrade();
6030             CHECK_NULL_VOID(safeAreaManager);
6031             safeAreaManager->AddKeyboardChangeCallbackConsideringUIExt(targetId, [overlayWk, targetId, containerId]() {
6032                     ContainerScope scope(containerId);
6033                     auto overlayManager = overlayWk.Upgrade();
6034                     CHECK_NULL_VOID(overlayManager);
6035                     overlayManager->CloseAIEntityMenu(targetId);
6036                 });
6037         });
6038     wrapperPattern->RegisterMenuDisappearCallback(
6039         [safeAreaWK = WeakClaim(RawPtr(safeAreaManager)), targetId, containerId = Container::CurrentId()]() {
6040             ContainerScope scope(containerId);
6041             auto safeAreaManager = safeAreaWK.Upgrade();
6042             CHECK_NULL_VOID(safeAreaManager);
6043             safeAreaManager->RemoveKeyboardChangeCallbackConsideringUIExt(targetId);
6044         });
6045     auto menuNode = DynamicCast<FrameNode>(menuWrapperNode->GetFirstChild());
6046     CHECK_NULL_RETURN(menuNode, false);
6047     auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
6048     CHECK_NULL_RETURN(menuLayoutProperty, false);
6049     menuLayoutProperty->UpdateIsRectInTarget(true);
6050     menuLayoutProperty->UpdateTargetSize(aiRect.GetSize());
6051 
6052     auto theme = pipeline->GetTheme<SelectTheme>();
6053     CHECK_NULL_RETURN(theme, false);
6054     if (theme->GetExpandDisplay()) {
6055         MenuParam menuParam {};
6056         SubwindowManager::GetInstance()->ShowMenuNG(menuWrapperNode, menuParam, targetNode, aiRect.GetOffset());
6057     } else {
6058         ShowMenu(targetNode->GetId(), aiRect.GetOffset(), menuWrapperNode);
6059     }
6060     return true;
6061 }
6062 
CloseAIEntityMenu(int32_t targetId)6063 void OverlayManager::CloseAIEntityMenu(int32_t targetId)
6064 {
6065     auto pipeline = PipelineContext::GetCurrentContextSafely();
6066     CHECK_NULL_VOID(pipeline);
6067     auto theme = pipeline->GetTheme<SelectTheme>();
6068     CHECK_NULL_VOID(theme);
6069     auto expandDisplay = theme->GetExpandDisplay();
6070     if (expandDisplay) {
6071         SubwindowManager::GetInstance()->ClearMenu();
6072         SubwindowManager::GetInstance()->ClearMenuNG(Container::CurrentId(), targetId);
6073     } else {
6074         auto menuNode = GetMenuNode(targetId);
6075         CHECK_NULL_VOID(menuNode);
6076         HideMenu(menuNode, targetId);
6077     }
6078 }
6079 
CreateOverlayNode()6080 void OverlayManager::CreateOverlayNode()
6081 {
6082     TAG_LOGD(AceLogTag::ACE_OVERLAY, "create overlay node enter");
6083     if (overlayNode_) {
6084         return;
6085     }
6086     auto rootNode = rootNodeWeak_.Upgrade();
6087     CHECK_NULL_VOID(rootNode);
6088     auto pipelineContext = PipelineContext::GetCurrentContext();
6089     CHECK_NULL_VOID(pipelineContext);
6090     auto stageManager = pipelineContext->GetStageManager();
6091     CHECK_NULL_VOID(stageManager);
6092     auto stageNode = stageManager->GetStageNode();
6093     CHECK_NULL_VOID(stageNode);
6094     overlayNode_ = FrameNode::CreateFrameNode(V2::OVERLAY_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
6095         AceType::MakeRefPtr<OverlayContainerPattern>());
6096     CHECK_NULL_VOID(overlayNode_);
6097     overlayNode_->SetHitTestMode(HitTestMode::HTMTRANSPARENT_SELF);
6098     auto layoutProperty = overlayNode_->GetLayoutProperty();
6099     CHECK_NULL_VOID(layoutProperty);
6100     auto full = CalcLength(Dimension(1.0, DimensionUnit::PERCENT));
6101     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(full, full));
6102     rootNode->AddChildAfter(overlayNode_, stageNode);
6103 }
6104 
AddFrameNodeToOverlay(const RefPtr<NG::FrameNode> & node,std::optional<int32_t> index)6105 void OverlayManager::AddFrameNodeToOverlay(const RefPtr<NG::FrameNode>& node, std::optional<int32_t> index)
6106 {
6107     TAG_LOGD(AceLogTag::ACE_OVERLAY, "add FrameNode to the overlay node enter");
6108     CHECK_NULL_VOID(node);
6109     int32_t level = -1;
6110     if (index.has_value() && index.value() >= 0) {
6111         level = index.value();
6112     }
6113     CreateOverlayNode();
6114     CHECK_NULL_VOID(overlayNode_);
6115     if (frameNodeMapOnOverlay_.find(node->GetId()) != frameNodeMapOnOverlay_.end()) {
6116         overlayNode_->RemoveChild(node);
6117         frameNodeMapOnOverlay_.erase(node->GetId());
6118     }
6119     const auto& children = overlayNode_->GetChildren();
6120     if (level == -1) {
6121         overlayNode_->AddChild(node);
6122     } else if (children.empty() || frameNodeMapOnOverlay_[overlayNode_->GetFirstChild()->GetId()] == -1 ||
6123                level < frameNodeMapOnOverlay_[overlayNode_->GetFirstChild()->GetId()]) {
6124         overlayNode_->AddChild(node, 0);
6125     } else {
6126         for (auto it = children.rbegin(); it != children.rend(); ++it) {
6127             auto childLevel = frameNodeMapOnOverlay_[(*it)->GetId()];
6128             if (childLevel < 0) {
6129                 continue;
6130             }
6131             if (childLevel <= level) {
6132                 auto beforeNode = DynamicCast<FrameNode>(*it);
6133                 CHECK_NULL_VOID(beforeNode);
6134                 overlayNode_->AddChildAfter(node, beforeNode);
6135                 break;
6136             }
6137         }
6138     }
6139     overlayNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6140     frameNodeMapOnOverlay_[node->GetId()] = level;
6141     auto focusHub = node->GetFocusHub();
6142     CHECK_NULL_VOID(focusHub);
6143     focusHub->RequestFocus();
6144 }
6145 
RemoveFrameNodeOnOverlay(const RefPtr<NG::FrameNode> & node)6146 void OverlayManager::RemoveFrameNodeOnOverlay(const RefPtr<NG::FrameNode>& node)
6147 {
6148     TAG_LOGD(AceLogTag::ACE_OVERLAY, "delete the FrameNode on the overlay node enter");
6149     CHECK_NULL_VOID(node);
6150     if (frameNodeMapOnOverlay_.find(node->GetId()) == frameNodeMapOnOverlay_.end()) {
6151         TAG_LOGW(AceLogTag::ACE_OVERLAY, "the node does not exist in the overlay");
6152         return;
6153     }
6154     CHECK_NULL_VOID(overlayNode_);
6155     overlayNode_->RemoveChild(node);
6156     frameNodeMapOnOverlay_.erase(node->GetId());
6157     if (overlayNode_->GetChildren().empty()) {
6158         auto rootNode = rootNodeWeak_.Upgrade();
6159         CHECK_NULL_VOID(rootNode);
6160         rootNode->RemoveChild(overlayNode_);
6161         overlayNode_.Reset();
6162         frameNodeMapOnOverlay_.clear();
6163         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6164         return;
6165     }
6166     overlayNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6167 }
6168 
ShowNodeOnOverlay(const RefPtr<NG::FrameNode> & node)6169 void OverlayManager::ShowNodeOnOverlay(const RefPtr<NG::FrameNode>& node)
6170 {
6171     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show the FrameNode on the overlay node enter");
6172     CHECK_NULL_VOID(node);
6173     CHECK_NULL_VOID(overlayNode_);
6174     auto layoutProperty = node->GetLayoutProperty();
6175     CHECK_NULL_VOID(layoutProperty);
6176     if (layoutProperty->GetVisibility().has_value() && layoutProperty->GetVisibilityValue() == VisibleType::VISIBLE) {
6177         return;
6178     }
6179     layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
6180     node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6181     auto focusHub = node->GetFocusHub();
6182     CHECK_NULL_VOID(focusHub);
6183     focusHub->RequestFocus();
6184 }
6185 
HideNodeOnOverlay(const RefPtr<NG::FrameNode> & node)6186 void OverlayManager::HideNodeOnOverlay(const RefPtr<NG::FrameNode>& node)
6187 {
6188     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide the FrameNode on the overlay node enter");
6189     CHECK_NULL_VOID(node);
6190     CHECK_NULL_VOID(overlayNode_);
6191     auto layoutProperty = node->GetLayoutProperty();
6192     CHECK_NULL_VOID(layoutProperty);
6193     if (layoutProperty->GetVisibility().has_value() && layoutProperty->GetVisibilityValue() == VisibleType::GONE) {
6194         return;
6195     }
6196     layoutProperty->UpdateVisibility(VisibleType::GONE);
6197     node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6198     auto focusHub = node->GetFocusHub();
6199     CHECK_NULL_VOID(focusHub);
6200     focusHub->LostFocusToViewRoot();
6201 }
6202 
ShowAllNodesOnOverlay()6203 void OverlayManager::ShowAllNodesOnOverlay()
6204 {
6205     TAG_LOGD(AceLogTag::ACE_OVERLAY, "show all FrameNodes on the overlay node enter");
6206     CHECK_NULL_VOID(overlayNode_);
6207     for (auto& child : overlayNode_->GetChildren()) {
6208         auto frameNode = DynamicCast<FrameNode>(child);
6209         CHECK_NULL_VOID(frameNode);
6210         auto layoutProperty = frameNode->GetLayoutProperty();
6211         CHECK_NULL_VOID(layoutProperty);
6212         layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
6213     }
6214     overlayNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6215     auto focusView = overlayNode_->GetPattern<FocusView>();
6216     CHECK_NULL_VOID(focusView);
6217     focusView->FocusViewShow();
6218 }
6219 
HideAllNodesOnOverlay()6220 void OverlayManager::HideAllNodesOnOverlay()
6221 {
6222     TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide all FrameNodes on the overlay node enter");
6223     CHECK_NULL_VOID(overlayNode_);
6224     for (auto& child : overlayNode_->GetChildren()) {
6225         auto frameNode = DynamicCast<FrameNode>(child);
6226         CHECK_NULL_VOID(frameNode);
6227         auto layoutProperty = frameNode->GetLayoutProperty();
6228         CHECK_NULL_VOID(layoutProperty);
6229         layoutProperty->UpdateVisibility(VisibleType::GONE);
6230     }
6231     overlayNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
6232     auto focusView = overlayNode_->GetPattern<FocusView>();
6233     CHECK_NULL_VOID(focusView);
6234     focusView->FocusViewClose();
6235 }
6236 
MarkDirty(PropertyChangeFlag flag)6237 void OverlayManager::MarkDirty(PropertyChangeFlag flag)
6238 {
6239     auto root = rootNodeWeak_.Upgrade();
6240     CHECK_NULL_VOID(root);
6241     auto pipeline = PipelineContext::GetCurrentContext();
6242     CHECK_NULL_VOID(pipeline);
6243     auto markNode = root;
6244     if (pipeline->GetInstallationFree()) {
6245         markNode = root->GetFirstChild();
6246         TAG_LOGD(AceLogTag::ACE_OVERLAY, "atomicService node need marked");
6247     }
6248     for (auto&& child : markNode->GetChildren()) {
6249         // first child is Stage node in main window, subwindow not has Stage node.
6250         if (child != root->GetFirstChild() || pipeline->IsSubPipeline()) {
6251             child->MarkDirtyNode(flag);
6252             // sheetPage Node will MarkDirty when VirtualKeyboard Height Changes
6253             auto sheetParent = DynamicCast<FrameNode>(child);
6254             if (sheetParent && sheetParent->GetTag() == V2::SHEET_WRAPPER_TAG) {
6255                 auto sheet = sheetParent->GetChildAtIndex(0);
6256                 if (sheet) {
6257                     sheet->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
6258                 }
6259             }
6260         }
6261     }
6262 }
6263 
MarkDirtyOverlay()6264 void OverlayManager::MarkDirtyOverlay()
6265 {
6266     auto root = rootNodeWeak_.Upgrade();
6267     CHECK_NULL_VOID(root);
6268     auto child = root->GetLastChild();
6269     CHECK_NULL_VOID(child);
6270     // sheetPage Node will MarkDirty when VirtualKeyboard Height Changes
6271     auto sheetParent = DynamicCast<FrameNode>(child);
6272     if (sheetParent && sheetParent->GetTag() == V2::SHEET_WRAPPER_TAG) {
6273         auto sheet = sheetParent->GetChildAtIndex(0);
6274         if (sheet) {
6275             sheet->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
6276         }
6277     }
6278 }
6279 
CheckPageNeedAvoidKeyboard() const6280 bool OverlayManager::CheckPageNeedAvoidKeyboard() const
6281 {
6282     auto root = rootNodeWeak_.Upgrade();
6283     CHECK_NULL_RETURN(root, true);
6284     auto child = root->GetLastChild();
6285     CHECK_NULL_RETURN(child, true);
6286     // page will not avoid keyboard when lastChild is sheet
6287     if (child->GetTag() != V2::SHEET_WRAPPER_TAG) {
6288         return true;
6289     }
6290     auto frameNode = DynamicCast<FrameNode>(child);
6291     return !(frameNode && frameNode->GetFocusHub() && frameNode->GetFocusHub()->IsCurrentFocus());
6292 }
6293 
GetRootWidth() const6294 float OverlayManager::GetRootWidth() const
6295 {
6296     auto rootNode = rootNodeWeak_.Upgrade();
6297     CHECK_NULL_RETURN(rootNode, 0.0);
6298     auto rootGeometryNode = AceType::DynamicCast<FrameNode>(rootNode)->GetGeometryNode();
6299     CHECK_NULL_RETURN(rootGeometryNode, 0.0);
6300     auto rootWidth = rootGeometryNode->GetFrameSize().Width();
6301     return rootWidth;
6302 }
6303 
GetRootHeight() const6304 float OverlayManager::GetRootHeight() const
6305 {
6306     auto rootNode = rootNodeWeak_.Upgrade();
6307     CHECK_NULL_RETURN(rootNode, 0.0);
6308     auto rootGeometryNode = AceType::DynamicCast<FrameNode>(rootNode)->GetGeometryNode();
6309     CHECK_NULL_RETURN(rootGeometryNode, 0.0);
6310     auto rootHeight = rootGeometryNode->GetFrameSize().Height();
6311     return rootHeight;
6312 }
6313 
CheckReturnFocus(RefPtr<FrameNode> node)6314 void OverlayManager::CheckReturnFocus(RefPtr<FrameNode> node) {}
6315 
isMaskNode(int32_t maskId)6316 bool OverlayManager::isMaskNode(int32_t maskId)
6317 {
6318     for (const auto& [key, value] : maskNodeIdMap_) {
6319         if (value == maskId) {
6320             return true;
6321         }
6322     }
6323     return false;
6324 }
6325 
GetMaskNodeIdWithDialogId(int32_t dialogId)6326 int32_t OverlayManager::GetMaskNodeIdWithDialogId(int32_t dialogId)
6327 {
6328     auto iter = maskNodeIdMap_.find(dialogId);
6329     return (iter == maskNodeIdMap_.end()) ? -1 : iter->second;
6330 }
6331 
MountGatherNodeToRootNode(const RefPtr<FrameNode> & frameNode,const std::vector<GatherNodeChildInfo> & gatherNodeChildrenInfo)6332 void OverlayManager::MountGatherNodeToRootNode(const RefPtr<FrameNode>& frameNode,
6333     const std::vector<GatherNodeChildInfo>& gatherNodeChildrenInfo)
6334 {
6335     auto rootNode = rootNodeWeak_.Upgrade();
6336     CHECK_NULL_VOID(rootNode);
6337     frameNode->MountToParent(rootNode);
6338     frameNode->OnMountToParentDone();
6339     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
6340     gatherNodeWeak_ = frameNode;
6341     hasGatherNode_ = true;
6342     gatherNodeChildrenInfo_ = gatherNodeChildrenInfo;
6343 }
6344 
MountGatherNodeToWindowScene(const RefPtr<FrameNode> & frameNode,const std::vector<GatherNodeChildInfo> & gatherNodeChildrenInfo,const RefPtr<UINode> & windowScene)6345 void OverlayManager::MountGatherNodeToWindowScene(const RefPtr<FrameNode>& frameNode,
6346     const std::vector<GatherNodeChildInfo>& gatherNodeChildrenInfo,
6347     const RefPtr<UINode>& windowScene)
6348 {
6349     CHECK_NULL_VOID(windowScene);
6350     frameNode->MountToParent(windowScene);
6351     frameNode->OnMountToParentDone();
6352     windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
6353     gatherNodeWeak_ = frameNode;
6354     hasGatherNode_ = true;
6355     gatherNodeChildrenInfo_ = gatherNodeChildrenInfo;
6356 }
6357 
RemoveGatherNode()6358 void OverlayManager::RemoveGatherNode()
6359 {
6360     CHECK_EQUAL_VOID(hasGatherNode_, false);
6361     auto frameNode = gatherNodeWeak_.Upgrade();
6362     CHECK_NULL_VOID(frameNode);
6363     TAG_LOGI(AceLogTag::ACE_DRAG, "Remove gather node");
6364     auto rootNode = frameNode->GetParent();
6365     CHECK_NULL_VOID(rootNode);
6366     rootNode->RemoveChild(frameNode);
6367     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
6368     hasGatherNode_ = false;
6369     gatherNodeWeak_ = nullptr;
6370     gatherNodeChildrenInfo_.clear();
6371 }
6372 
RemoveGatherNodeWithAnimation()6373 void OverlayManager::RemoveGatherNodeWithAnimation()
6374 {
6375     if (!hasGatherNode_) {
6376         return;
6377     }
6378     TAG_LOGI(AceLogTag::ACE_DRAG, "Remove gather node with animation");
6379     AnimationOption option;
6380     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
6381     option.SetCurve(Curves::SHARP);
6382 
6383     option.SetOnFinishEvent([weak = gatherNodeWeak_] {
6384         auto context = PipelineContext::GetCurrentContext();
6385         CHECK_NULL_VOID(context);
6386         auto taskExecutor = context->GetTaskExecutor();
6387         CHECK_NULL_VOID(taskExecutor);
6388         // animation finish event should be posted to UI thread.
6389         taskExecutor->PostTask(
6390             [weak, id = Container::CurrentId()]() {
6391                 ContainerScope scope(id);
6392                 auto frameNode = weak.Upgrade();
6393                 CHECK_NULL_VOID(frameNode);
6394                 auto rootNode = frameNode->GetParent();
6395                 CHECK_NULL_VOID(rootNode);
6396                 rootNode->RemoveChild(frameNode);
6397                 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
6398             },
6399             TaskExecutor::TaskType::UI, "ArkUIOverlayRemoveGatherNodeEvent");
6400     });
6401     gatherNodeWeak_ = nullptr;
6402     hasGatherNode_ = false;
6403     AnimationUtils::Animate(
6404         option,
6405         [gatherNodeChildrenInfo = gatherNodeChildrenInfo_]() {
6406             for (auto& child : gatherNodeChildrenInfo) {
6407                 auto imageNode = child.imageNode.Upgrade();
6408                 CHECK_NULL_VOID(imageNode);
6409                 auto imageContext = imageNode->GetRenderContext();
6410                 CHECK_NULL_VOID(imageContext);
6411                 imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(child.offset.GetX()),
6412                     Dimension(child.offset.GetY())));
6413                 imageContext->UpdateTransformScale({ 1.0f, 1.0f });
6414                 Vector5F rotate = Vector5F(0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
6415                 imageContext->UpdateTransformRotate(rotate);
6416                 imageContext->UpdateOpacity(1.0);
6417                 BorderRadiusProperty borderRadius;
6418                 borderRadius.SetRadius(0.0_vp);
6419                 imageContext->UpdateBorderRadius(borderRadius);
6420             }
6421         },
6422         option.GetOnFinishEvent());
6423 }
6424 
UpdateGatherNodeToTop()6425 void OverlayManager::UpdateGatherNodeToTop()
6426 {
6427     auto frameNode = gatherNodeWeak_.Upgrade();
6428     CHECK_NULL_VOID(frameNode);
6429     auto rootNode = frameNode->GetParent();
6430     CHECK_NULL_VOID(rootNode);
6431     rootNode->RemoveChild(frameNode);
6432     frameNode->MountToParent(rootNode);
6433     frameNode->OnMountToParentDone();
6434     rootNode->RebuildRenderContextTree();
6435     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
6436 }
6437 
GetPixelMapContentNode(bool isSubwindowOverlay) const6438 RefPtr<FrameNode> OverlayManager::GetPixelMapContentNode(bool isSubwindowOverlay) const
6439 {
6440     if (isSubwindowOverlay) {
6441         RefPtr<FrameNode> imageNode = GetPixelMapContentNodeForSubwindow();
6442         return imageNode;
6443     }
6444     auto column = pixmapColumnNodeWeak_.Upgrade();
6445     CHECK_NULL_RETURN(column, nullptr);
6446     auto imageNode = AceType::DynamicCast<FrameNode>(column->GetFirstChild());
6447     return imageNode;
6448 }
6449 
GetPixelMapContentNodeForSubwindow() const6450 RefPtr<FrameNode> OverlayManager::GetPixelMapContentNodeForSubwindow() const
6451 {
6452     auto rootNode = rootNodeWeak_.Upgrade();
6453     CHECK_NULL_RETURN(rootNode, nullptr);
6454     for (const auto& child : rootNode->GetChildren()) {
6455         auto node = DynamicCast<FrameNode>(child);
6456         if (node && node->GetTag() != V2::MENU_WRAPPER_ETS_TAG) {
6457             continue;
6458         }
6459         for (auto& childNode : node->GetChildren()) {
6460             auto frameNode = DynamicCast<FrameNode>(childNode);
6461             if (frameNode &&
6462                 (frameNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG || frameNode->GetTag() == V2::IMAGE_ETS_TAG)) {
6463                 return frameNode;
6464             }
6465         }
6466     }
6467     return nullptr;
6468 }
6469 
UpdatePixelMapPosition(bool isSubwindowOverlay)6470 void OverlayManager::UpdatePixelMapPosition(bool isSubwindowOverlay)
6471 {
6472     if (!isSubwindowOverlay && !hasPixelMap_) {
6473         return;
6474     }
6475     if (IsOriginDragMoveVector() || !IsUpdateDragMoveVector()) {
6476         return;
6477     }
6478     auto moveVector = GetUpdateDragMoveVector();
6479     RefPtr<FrameNode> imageNode = GetPixelMapContentNode(isSubwindowOverlay);
6480     CHECK_NULL_VOID(imageNode);
6481     auto imageContext = imageNode->GetRenderContext();
6482     CHECK_NULL_VOID(imageContext);
6483     auto rect = imageNode->GetOffsetRelativeToWindow();
6484     imageContext->UpdatePosition(OffsetT<Dimension>(Dimension(moveVector.GetX() + rect.GetX()),
6485         Dimension(moveVector.GetY() + rect.GetY())));
6486     imageContext->OnModifyDone();
6487 }
6488 
GetDragPixelMapContentNode() const6489 RefPtr<FrameNode> OverlayManager::GetDragPixelMapContentNode() const
6490 {
6491     auto column = dragPixmapColumnNodeWeak_.Upgrade();
6492     CHECK_NULL_RETURN(column, nullptr);
6493     auto imageNode = AceType::DynamicCast<FrameNode>(column->GetFirstChild());
6494     return imageNode;
6495 }
6496 
GetPixelMapBadgeNode() const6497 RefPtr<FrameNode> OverlayManager::GetPixelMapBadgeNode() const
6498 {
6499     auto column = pixmapColumnNodeWeak_.Upgrade();
6500     CHECK_NULL_RETURN(column, nullptr);
6501     auto textNode = AceType::DynamicCast<FrameNode>(column->GetLastChild());
6502     CHECK_NULL_RETURN(textNode, nullptr);
6503     return textNode;
6504 }
6505 
GetDragPixelMapBadgeNode() const6506 RefPtr<FrameNode> OverlayManager::GetDragPixelMapBadgeNode() const
6507 {
6508     auto column = dragPixmapColumnNodeWeak_.Upgrade();
6509     CHECK_NULL_RETURN(column, nullptr);
6510     auto textNode = AceType::DynamicCast<FrameNode>(column->GetLastChild());
6511     CHECK_NULL_RETURN(textNode, nullptr);
6512     return textNode;
6513 }
6514 
RemoveMenuBadgeNode(const RefPtr<FrameNode> & menuWrapperNode)6515 void OverlayManager::RemoveMenuBadgeNode(const RefPtr<FrameNode>& menuWrapperNode)
6516 {
6517     CHECK_NULL_VOID(menuWrapperNode);
6518     auto pattern = menuWrapperNode->GetPattern<MenuWrapperPattern>();
6519     CHECK_NULL_VOID(pattern);
6520     auto badgeNode = pattern->GetBadgeNode();
6521     CHECK_NULL_VOID(badgeNode);
6522     menuWrapperNode->RemoveChild(badgeNode);
6523     menuWrapperNode->RebuildRenderContextTree();
6524     menuWrapperNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
6525 }
6526 
RemovePreviewBadgeNode()6527 void OverlayManager::RemovePreviewBadgeNode()
6528 {
6529     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
6530     CHECK_NULL_VOID(columnNode);
6531     auto textNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildAtIndex(1));
6532     CHECK_NULL_VOID(textNode);
6533     columnNode->RemoveChild(textNode);
6534     columnNode->RebuildRenderContextTree();
6535     columnNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
6536 }
6537 
GetRootNode() const6538 const WeakPtr<UINode>& OverlayManager::GetRootNode() const
6539 {
6540     return rootNodeWeak_;
6541 }
6542 
GetGroupManager() const6543 const RefPtr<GroupManager>& OverlayManager::GetGroupManager() const
6544 {
6545     return groupManager_;
6546 }
6547 
ShowFilterAnimation(const RefPtr<FrameNode> & columnNode)6548 void OverlayManager::ShowFilterAnimation(const RefPtr<FrameNode>& columnNode)
6549 {
6550     CHECK_NULL_VOID(columnNode);
6551 
6552     auto filterRenderContext = columnNode->GetRenderContext();
6553     CHECK_NULL_VOID(filterRenderContext);
6554 
6555     auto pipelineContext = PipelineContext::GetCurrentContext();
6556     CHECK_NULL_VOID(pipelineContext);
6557     auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
6558     CHECK_NULL_VOID(menuTheme);
6559 
6560     auto maskColor = menuTheme->GetPreviewMenuMaskColor();
6561     BlurStyleOption styleOption;
6562     styleOption.blurStyle = BlurStyle::BACKGROUND_THIN;
6563     styleOption.colorMode = ThemeColorMode::SYSTEM;
6564 
6565     AnimationOption option;
6566     option.SetDuration(menuTheme->GetFilterAnimationDuration());
6567     option.SetCurve(Curves::SHARP);
6568     option.SetOnFinishEvent([] {
6569         auto pipelineContext = PipelineContext::GetCurrentContext();
6570         auto manager = pipelineContext->GetOverlayManager();
6571         CHECK_NULL_VOID(manager);
6572         manager->SetFilterActive(false);
6573     });
6574     filterRenderContext->UpdateBackBlurRadius(Dimension(0.0f));
6575     AnimationUtils::Animate(
6576         option,
6577         [filterRenderContext, styleOption, maskColor, menuTheme]() {
6578             CHECK_NULL_VOID(filterRenderContext);
6579             if (menuTheme->GetHasBackBlur()) {
6580                 filterRenderContext->UpdateBackBlurStyle(styleOption);
6581             } else {
6582                 filterRenderContext->UpdateBackgroundColor(maskColor);
6583             }
6584         },
6585         option.GetOnFinishEvent());
6586 }
6587 
RemoveMenuNotInSubWindow(const WeakPtr<FrameNode> & menuWK,const WeakPtr<UINode> & rootWeak,const WeakPtr<OverlayManager> & overlayWeak)6588 void OverlayManager::RemoveMenuNotInSubWindow(
6589     const WeakPtr<FrameNode>& menuWK, const WeakPtr<UINode>& rootWeak, const WeakPtr<OverlayManager>& overlayWeak)
6590 {
6591     auto menu = menuWK.Upgrade();
6592     CHECK_NULL_VOID(menu);
6593     auto rootNode = rootWeak.Upgrade();
6594     CHECK_NULL_VOID(rootNode);
6595     auto overlayManager = overlayWeak.Upgrade();
6596     CHECK_NULL_VOID(overlayManager);
6597 
6598     auto container = Container::Current();
6599     if (container && container->IsScenceBoardWindow()) {
6600         rootNode = overlayManager->FindWindowScene(menu);
6601     }
6602     CHECK_NULL_VOID(rootNode);
6603     RemoveChildWithService(rootNode, menu);
6604     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
6605 }
6606 
DumpOverlayInfo() const6607 void OverlayManager::DumpOverlayInfo() const
6608 {
6609     auto container = Container::Current();
6610     if (container) {
6611         DumpLog::GetInstance().Print("Container: ");
6612         DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "ContainerId: " + std::to_string(container->GetInstanceId()));
6613         DumpLog::GetInstance().Print(
6614             DUMP_LOG_DEPTH_1, "IsSubContainer: " + std::string(container->IsSubContainer() ? "true" : "false"));
6615     }
6616 
6617     DumpLog::GetInstance().Print("----------PopupMapInfo----------");
6618     DumpPopupMapInfo();
6619 
6620     DumpLog::GetInstance().Print("----------MenuMapInfo----------");
6621     DumpMapInfo(menuMap_, "MenuMap");
6622 
6623     DumpLog::GetInstance().Print("----------DialogMapInfo----------");
6624     DumpMapInfo(dialogMap_, "DialogMap", false);
6625 
6626     DumpLog::GetInstance().Print("----------CustomPopupMapInfo----------");
6627     DumpMapInfo(customPopupMap_, "CustomPopupMap");
6628 
6629     DumpLog::GetInstance().Print("----------CustomKeyboardMapInfo----------");
6630     DumpMapInfo(customKeyboardMap_, "CustomKeyboardMap");
6631 
6632     DumpLog::GetInstance().Print("----------ToastMapInfo----------");
6633     DumpMapInfo(toastMap_, "ToastMap", false);
6634 
6635     DumpLog::GetInstance().Print("----------SheetMapInfo----------");
6636     DumpSheetMapInfo(sheetMap_, "SheetMap");
6637 
6638     DumpLog::GetInstance().Print("----------MaskNodeIdMapInfo----------");
6639     DumpMaskNodeIdMapInfo();
6640 
6641     DumpLog::GetInstance().Print("----------ModalListInfo----------");
6642     DumpModalListInfo();
6643 }
6644 
DumpPopupMapInfo() const6645 void OverlayManager::DumpPopupMapInfo() const
6646 {
6647     DumpLog::GetInstance().Print("PopupMap: ");
6648     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Size: " + std::to_string(popupMap_.size()));
6649     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Entries: [");
6650 
6651     for (const auto& entry : popupMap_) {
6652         std::string entryLog = "";
6653         auto targetId = entry.first;
6654         auto targetNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(targetId);
6655         auto popupInfo = entry.second;
6656         auto popupNode = popupInfo.popupNode;
6657         DumpEntry(targetNode, targetId, popupNode);
6658     }
6659 
6660     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "]");
6661 }
6662 
DumpMapInfo(std::unordered_map<int32_t,RefPtr<FrameNode>> map,const std::string mapName,bool hasTarget) const6663 void OverlayManager::DumpMapInfo(
6664     std::unordered_map<int32_t, RefPtr<FrameNode>> map, const std::string mapName, bool hasTarget) const
6665 {
6666     DumpLog::GetInstance().Print(mapName + ": ");
6667     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Size: " + std::to_string(map.size()));
6668     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Entries: [");
6669 
6670     for (const auto& entry : map) {
6671         auto targetId = entry.first;
6672         auto targetNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(targetId);
6673         auto node = entry.second;
6674 
6675         if (hasTarget) {
6676             DumpEntry(targetNode, targetId, node);
6677         } else {
6678             std::string entryLog = GetMapNodeLog(node, hasTarget);
6679             DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_2, entryLog);
6680         }
6681     }
6682 
6683     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "]");
6684 }
6685 
DumpMapInfo(std::unordered_map<int32_t,WeakPtr<FrameNode>> map,const std::string mapName,bool hasTarget) const6686 void OverlayManager::DumpMapInfo(
6687     std::unordered_map<int32_t, WeakPtr<FrameNode>> map, const std::string mapName, bool hasTarget) const
6688 {
6689     DumpLog::GetInstance().Print(mapName + ": ");
6690     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Size: " + std::to_string(map.size()));
6691     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Entries: [");
6692 
6693     for (const auto& entry : map) {
6694         auto targetId = entry.first;
6695         auto targetNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(targetId);
6696         auto node = entry.second.Upgrade();
6697         if (hasTarget) {
6698             DumpEntry(targetNode, targetId, node);
6699         } else {
6700             std::string entryLog = GetMapNodeLog(node, hasTarget);
6701             DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_2, entryLog);
6702         }
6703     }
6704 
6705     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "]");
6706 }
6707 
DumpSheetMapInfo(const std::unordered_map<SheetKey,WeakPtr<FrameNode>,SheetKeyHash> & map,const std::string mapName) const6708 void OverlayManager::DumpSheetMapInfo(
6709     const std::unordered_map<SheetKey, WeakPtr<FrameNode>, SheetKeyHash>& map,
6710     const std::string mapName) const
6711 {
6712     DumpLog::GetInstance().Print(mapName + ": ");
6713     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Size: " + std::to_string(map.size()));
6714     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Entries: [");
6715 
6716     for (const auto& entry : map) {
6717         auto targetId = entry.first.targetId;
6718         auto targetNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(targetId);
6719         auto node = entry.second.Upgrade();
6720         DumpEntry(targetNode, targetId, node);
6721     }
6722 
6723     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "]");
6724 }
6725 
DumpMaskNodeIdMapInfo() const6726 void OverlayManager::DumpMaskNodeIdMapInfo() const
6727 {
6728     DumpLog::GetInstance().Print("MaskNodeIdMap: ");
6729     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Size: " + std::to_string(maskNodeIdMap_.size()));
6730     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Entries: [");
6731 
6732     for (const auto& entry : maskNodeIdMap_) {
6733         auto targetId = entry.first;
6734         auto targetNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(targetId);
6735         auto nodeId = entry.second;
6736         auto node = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
6737         std::string entryLog = "DialogId: " + std::to_string(targetId);
6738         entryLog += ", DialogTag: " + (targetNode ? targetNode->GetTag() : "NULL");
6739         entryLog += ", NodeId: " + std::to_string(nodeId);
6740         entryLog += ", NodeTag: " + (node ? node->GetTag() : "NULL");
6741         DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_2, entryLog);
6742     }
6743 
6744     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "]");
6745 }
6746 
DumpModalListInfo() const6747 void OverlayManager::DumpModalListInfo() const
6748 {
6749     DumpLog::GetInstance().Print("ModalList: ");
6750     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Size: " + std::to_string(modalList_.size()));
6751     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "Entries: [");
6752 
6753     for (auto modal = modalList_.begin(); modal != modalList_.end(); ++modal) {
6754         std::string entryLog = "";
6755         auto modalNode = modal->Upgrade();
6756         entryLog += GetMapNodeLog(modalNode, false);
6757         DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_2, entryLog);
6758     }
6759 
6760     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_1, "]");
6761 }
6762 
DumpEntry(const RefPtr<FrameNode> & targetNode,int32_t targetId,const RefPtr<FrameNode> & node) const6763 void OverlayManager::DumpEntry(
6764     const RefPtr<FrameNode>& targetNode, int32_t targetId, const RefPtr<FrameNode>& node) const
6765 {
6766     std::string entryLog = "TargetId: " + std::to_string(targetId);
6767     entryLog += ", TargetTag: " + (targetNode ? targetNode->GetTag() : "NULL");
6768     entryLog += GetMapNodeLog(node);
6769     DumpLog::GetInstance().Print(DUMP_LOG_DEPTH_2, entryLog);
6770 }
6771 
GetMapNodeLog(const RefPtr<FrameNode> & node,bool hasTarget) const6772 std::string OverlayManager::GetMapNodeLog(const RefPtr<FrameNode>& node, bool hasTarget) const
6773 {
6774     CHECK_NULL_RETURN(node, "");
6775     std::string entryLog = (hasTarget ? ", " : "");
6776     entryLog += "NodeId: " + std::to_string(node->GetId()) + ", NodeTag: " + node->GetTag();
6777     return entryLog;
6778 }
6779 
OnUIExtensionWindowSizeChange()6780 void OverlayManager::OnUIExtensionWindowSizeChange()
6781 {
6782     for (auto iter = dialogMap_.begin(); iter != dialogMap_.end(); iter++) {
6783         auto dialogNode = (*iter).second;
6784         CHECK_NULL_VOID(dialogNode);
6785         auto dialogPattern = dialogNode->GetPattern<DialogPattern>();
6786         CHECK_NULL_VOID(dialogPattern);
6787         dialogPattern->InitHostWindowRect();
6788         dialogNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
6789     }
6790 }
6791 
MountToParentWithService(const RefPtr<UINode> & rootNode,const RefPtr<FrameNode> & node)6792 void OverlayManager::MountToParentWithService(const RefPtr<UINode>& rootNode, const RefPtr<FrameNode>& node)
6793 {
6794     CHECK_NULL_VOID(node);
6795     CHECK_NULL_VOID(rootNode);
6796     auto pipeline = rootNode->GetContextRefPtr();
6797     CHECK_NULL_VOID(pipeline);
6798     if (pipeline->GetInstallationFree()) {
6799         // it is in atomicservice
6800         SetNodeBeforeAppbar(rootNode, node);
6801     } else {
6802         node->MountToParent(rootNode);
6803     }
6804 }
6805 
RemoveChildWithService(const RefPtr<UINode> & rootNode,const RefPtr<FrameNode> & node)6806 void OverlayManager::RemoveChildWithService(const RefPtr<UINode>& rootNode, const RefPtr<FrameNode>& node)
6807 {
6808     CHECK_NULL_VOID(rootNode);
6809     CHECK_NULL_VOID(node);
6810     auto parent = node->GetParent();
6811     CHECK_NULL_VOID(parent);
6812     parent->RemoveChild(node);
6813 }
6814 
SetNodeBeforeAppbar(const RefPtr<NG::UINode> & rootNode,const RefPtr<FrameNode> & node)6815 void OverlayManager::SetNodeBeforeAppbar(const RefPtr<NG::UINode>& rootNode, const RefPtr<FrameNode>& node)
6816 {
6817     CHECK_NULL_VOID(rootNode);
6818     CHECK_NULL_VOID(node);
6819     for (auto child : rootNode->GetChildren()) {
6820         CHECK_NULL_VOID(child);
6821         if (child->GetTag() != V2::ATOMIC_SERVICE_ETS_TAG) {
6822             continue;
6823         }
6824         for (auto childNode : child->GetChildren()) {
6825             CHECK_NULL_VOID(childNode);
6826             if (childNode->GetTag() == V2::APP_BAR_ETS_TAG) {
6827                 TAG_LOGD(AceLogTag::ACE_OVERLAY, "setNodeBeforeAppbar AddChildBefore");
6828                 child->AddChildBefore(node, childNode);
6829                 return;
6830             }
6831         }
6832     }
6833 }
6834 
IsRootExpansive() const6835 bool OverlayManager::IsRootExpansive() const
6836 {
6837     auto rootNode = rootNodeWeak_.Upgrade();
6838     CHECK_NULL_RETURN(rootNode, false);
6839     auto pipelineContext = rootNode->GetContext();
6840     CHECK_NULL_RETURN(pipelineContext, false);
6841     auto manager = pipelineContext->GetSafeAreaManager();
6842     CHECK_NULL_RETURN(manager, false);
6843     if (manager->IsFullScreen()) {
6844         // if window is full screen, sheetPage should layout under 8vp + status bar height under parent
6845         return false;
6846     }
6847 
6848     // if page parent is full screen, sheetPage should layout 8vp under parent
6849     auto layoutProp = DynamicCast<FrameNode>(rootNode)->GetLayoutProperty();
6850     CHECK_NULL_RETURN(layoutProp, false);
6851     const auto& opts = layoutProp->GetSafeAreaExpandOpts();
6852     return opts && opts->Expansive();
6853 }
6854 
SetDragNodeNeedClean()6855 void OverlayManager::SetDragNodeNeedClean()
6856 {
6857     auto mainPipeline = PipelineContext::GetMainPipelineContext();
6858     CHECK_NULL_VOID(mainPipeline);
6859     auto dragDropManager = mainPipeline->GetDragDropManager();
6860     CHECK_NULL_VOID(dragDropManager);
6861     dragDropManager->SetIsDragNodeNeedClean(true);
6862 }
6863 } // namespace OHOS::Ace::NG
6864