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