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