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