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