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