1 /*
2 * Copyright (c) 2022-2023 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 <utility>
20 #include <vector>
21
22 #include "base/geometry/ng/offset_t.h"
23 #include "base/geometry/ng/size_t.h"
24 #include "base/log/log.h"
25 #include "base/memory/ace_type.h"
26 #include "base/memory/referenced.h"
27 #include "base/subwindow/subwindow_manager.h"
28 #include "base/utils/measure_util.h"
29 #include "base/utils/system_properties.h"
30 #include "base/utils/utils.h"
31 #include "core/animation/animation_pub.h"
32 #include "core/animation/spring_curve.h"
33 #include "core/common/ace_application_info.h"
34 #include "core/common/ace_engine.h"
35 #include "core/common/container.h"
36 #include "core/common/interaction/interaction_interface.h"
37 #include "core/common/modal_ui_extension.h"
38 #include "core/common/recorder/event_recorder.h"
39 #include "core/components/common/properties/color.h"
40 #include "core/components/select/select_theme.h"
41 #include "core/components/text_overlay/text_overlay_theme.h"
42 #include "core/components/toast/toast_theme.h"
43 #include "core/components_ng/animation/geometry_transition.h"
44 #include "core/components_ng/base/frame_node.h"
45 #include "core/components_ng/base/ui_node.h"
46 #include "core/components_ng/base/view_abstract.h"
47 #include "core/components_ng/base/view_stack_processor.h"
48 #include "core/components_ng/pattern/bubble/bubble_event_hub.h"
49 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
50 #include "core/components_ng/pattern/calendar_picker/calendar_dialog_view.h"
51 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
52 #include "core/components_ng/pattern/dialog/dialog_view.h"
53 #include "core/components_ng/pattern/menu/menu_layout_property.h"
54 #include "core/components_ng/pattern/menu/menu_pattern.h"
55 #include "core/components_ng/pattern/menu/menu_theme.h"
56 #include "core/components_ng/pattern/menu/menu_view.h"
57 #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h"
58 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
59 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
60 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
61 #include "core/components_ng/pattern/overlay/keyboard_base_pattern.h"
62 #include "core/components_ng/pattern/overlay/keyboard_view.h"
63 #include "core/components_ng/pattern/overlay/modal_presentation_pattern.h"
64 #include "core/components_ng/pattern/overlay/popup_base_pattern.h"
65 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
66 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
67 #include "core/components_ng/pattern/overlay/sheet_presentation_property.h"
68 #include "core/components_ng/pattern/overlay/sheet_view.h"
69 #include "core/components_ng/pattern/picker/datepicker_dialog_view.h"
70 #include "core/components_ng/pattern/stage/stage_pattern.h"
71 #include "core/components_ng/pattern/text_picker/textpicker_dialog_view.h"
72 #include "core/components_ng/pattern/time_picker/timepicker_dialog_view.h"
73 #include "core/components_ng/pattern/toast/toast_pattern.h"
74 #include "core/components_ng/pattern/video/video_full_screen_pattern.h"
75 #include "core/components_ng/property/measure_property.h"
76 #include "core/components_ng/property/property.h"
77 #include "core/components_v2/inspector/inspector_constants.h"
78 #include "core/pipeline/pipeline_base.h"
79 #include "core/pipeline/pipeline_context.h"
80
81 namespace OHOS::Ace::NG {
82 namespace {
83 // should be moved to theme.
84 constexpr int32_t TOAST_ANIMATION_DURATION = 100;
85 constexpr int32_t MENU_ANIMATION_DURATION = 150;
86 constexpr float TOAST_ANIMATION_POSITION = 15.0f;
87
88 constexpr float PIXELMAP_DRAG_SCALE = 1.0f;
89 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 250;
90 constexpr float PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE = 0.5f;
91
92 constexpr int32_t FULL_MODAL_ALPHA_ANIMATION_DURATION = 200;
93
94 constexpr int32_t SHEET_HALF_SIZE = 2;
95 // dialog animation params
96 const RefPtr<Curve> SHOW_SCALE_ANIMATION_CURVE = AceType::MakeRefPtr<CubicCurve>(0.38f, 1.33f, 0.6f, 1.0f);
97
98 // custom keyboard animation params
99 const RefPtr<Curve> SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE =
100 AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f);
101 const RefPtr<Curve> HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE =
102 AceType::MakeRefPtr<InterpolatingSpring>(4.0f, 1.0f, 342.0f, 37.0f);
103
GetLastPage()104 RefPtr<FrameNode> GetLastPage()
105 {
106 auto pipelineContext = PipelineContext::GetCurrentContext();
107 CHECK_NULL_RETURN(pipelineContext, nullptr);
108 auto stageManager = pipelineContext->GetStageManager();
109 CHECK_NULL_RETURN(stageManager, nullptr);
110 auto pageNode = stageManager->GetLastPage();
111 return pageNode;
112 }
113
ShowPreviewDisappearAnimation(const RefPtr<MenuWrapperPattern> & menuWrapperPattern)114 void ShowPreviewDisappearAnimation(const RefPtr<MenuWrapperPattern>& menuWrapperPattern)
115 {
116 CHECK_NULL_VOID(menuWrapperPattern);
117 auto previewChild = menuWrapperPattern->GetPreview();
118 CHECK_NULL_VOID(previewChild);
119 auto previewRenderContext = previewChild->GetRenderContext();
120 CHECK_NULL_VOID(previewRenderContext);
121
122 auto menuChild = menuWrapperPattern->GetMenu();
123 CHECK_NULL_VOID(menuChild);
124 auto menuPattern = menuChild->GetPattern<MenuPattern>();
125 CHECK_NULL_VOID(menuPattern);
126 auto previewPosition = menuPattern->GetPreviewOriginOffset();
127
128 auto pipelineContext = PipelineContext::GetCurrentContext();
129 CHECK_NULL_VOID(pipelineContext);
130 auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
131 CHECK_NULL_VOID(menuTheme);
132 auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
133 auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
134 AnimationOption scaleOption;
135 auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
136 scaleOption.SetCurve(motion);
137 float previewScale = 1.0f;
138 if (menuPattern->GetPreviewMode() == MenuPreviewMode::IMAGE) {
139 auto previewGeometryNode = previewChild->GetGeometryNode();
140 CHECK_NULL_VOID(previewGeometryNode);
141 auto preivewSize = previewGeometryNode->GetFrameSize();
142 if (!NearEqual(menuPattern->GetTargetSize().Width(), preivewSize.Width())) {
143 previewScale = menuPattern->GetTargetSize().Width() / preivewSize.Width();
144 }
145 }
146 AnimationUtils::Animate(scaleOption, [previewRenderContext, previewPosition, previewScale]() {
147 if (previewRenderContext) {
148 previewRenderContext->UpdateTransformScale(VectorF(previewScale, previewScale));
149 previewRenderContext->UpdatePosition(
150 OffsetT<Dimension>(Dimension(previewPosition.GetX()), Dimension(previewPosition.GetY())));
151 }
152 });
153
154 auto shadow = previewRenderContext->GetBackShadow();
155 if (!shadow.has_value()) {
156 shadow = Shadow::CreateShadow(ShadowStyle::None);
157 }
158 previewRenderContext->UpdateBackShadow(shadow.value());
159 auto disappearDuration = menuTheme->GetDisappearDuration();
160 AnimationOption previewOption;
161 previewOption.SetCurve(Curves::SHARP);
162 previewOption.SetDuration(disappearDuration);
163 AnimationUtils::Animate(previewOption, [previewRenderContext, shadow]() mutable {
164 if (previewRenderContext) {
165 auto color = shadow->GetColor();
166 auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue());
167 shadow->SetColor(newColor);
168 previewRenderContext->UpdateBackShadow(shadow.value());
169 BorderRadiusProperty borderRadius;
170 borderRadius.SetRadius(0.0_vp);
171 previewRenderContext->UpdateBorderRadius(borderRadius);
172 }
173 });
174 }
175
UpdateContextMenuDisappearPositionAnimation(const RefPtr<FrameNode> & menu,const NG::OffsetF & offset)176 void UpdateContextMenuDisappearPositionAnimation(const RefPtr<FrameNode>& menu, const NG::OffsetF& offset)
177 {
178 CHECK_NULL_VOID(menu);
179 auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
180 CHECK_NULL_VOID(menuWrapperPattern);
181 auto menuChild = menuWrapperPattern->GetMenu();
182 CHECK_NULL_VOID(menuChild);
183 auto menuRenderContext = menuChild->GetRenderContext();
184 CHECK_NULL_VOID(menuRenderContext);
185 auto menuPattern = menuChild->GetPattern<MenuPattern>();
186 CHECK_NULL_VOID(menuPattern);
187 auto menuPosition = menuPattern->GetEndOffset();
188 menuPosition += offset;
189 menuPattern->SetEndOffset(menuPosition);
190
191 auto pipelineContext = PipelineContext::GetCurrentContext();
192 CHECK_NULL_VOID(pipelineContext);
193 auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
194 CHECK_NULL_VOID(menuTheme);
195
196 auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
197 auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
198 AnimationOption positionOption;
199 auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
200 positionOption.SetCurve(motion);
201 AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition]() {
202 if (menuRenderContext) {
203 menuRenderContext->UpdatePosition(
204 OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
205 }
206 });
207 }
208
ShowContextMenuDisappearAnimation(AnimationOption & option,const RefPtr<MenuWrapperPattern> & menuWrapperPattern,bool startDrag=false)209 void ShowContextMenuDisappearAnimation(
210 AnimationOption& option, const RefPtr<MenuWrapperPattern>& menuWrapperPattern, bool startDrag = false)
211 {
212 CHECK_NULL_VOID(menuWrapperPattern);
213 auto menuChild = menuWrapperPattern->GetMenu();
214 CHECK_NULL_VOID(menuChild);
215 auto menuRenderContext = menuChild->GetRenderContext();
216 CHECK_NULL_VOID(menuRenderContext);
217 auto menuPattern = menuChild->GetPattern<MenuPattern>();
218 CHECK_NULL_VOID(menuPattern);
219 auto menuPosition = menuPattern->GetEndOffset();
220
221 auto pipelineContext = PipelineContext::GetCurrentContext();
222 CHECK_NULL_VOID(pipelineContext);
223 auto menuTheme = pipelineContext->GetTheme<MenuTheme>();
224 CHECK_NULL_VOID(menuTheme);
225 if (startDrag) {
226 menuRenderContext->UpdateTransformScale(
227 VectorF(menuTheme->GetMenuDragAnimationScale(), menuTheme->GetMenuDragAnimationScale()));
228 }
229 auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
230 auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
231 AnimationOption positionOption;
232 auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
233 positionOption.SetCurve(motion);
234 AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition]() {
235 if (menuRenderContext) {
236 menuRenderContext->UpdatePosition(
237 OffsetT<Dimension>(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY())));
238 }
239 });
240
241 auto disappearDuration = menuTheme->GetDisappearDuration();
242 auto menuAnimationScale = menuTheme->GetMenuAnimationScale();
243 AnimationOption scaleOption;
244 scaleOption.SetCurve(Curves::FAST_OUT_LINEAR_IN);
245 scaleOption.SetDuration(disappearDuration);
246 AnimationUtils::Animate(scaleOption, [menuRenderContext, menuAnimationScale]() {
247 if (menuRenderContext) {
248 menuRenderContext->UpdateTransformScale({ menuAnimationScale, menuAnimationScale });
249 }
250 });
251
252 option.SetDuration(disappearDuration);
253 option.SetCurve(Curves::FRICTION);
254 AnimationUtils::Animate(
255 option,
256 [menuRenderContext]() {
257 if (menuRenderContext) {
258 menuRenderContext->UpdateOpacity(0.0);
259 }
260 },
261 option.GetOnFinishEvent());
262 }
263 } // namespace
264
UpdateContextMenuDisappearPosition(const NG::OffsetF & offset)265 void OverlayManager::UpdateContextMenuDisappearPosition(const NG::OffsetF& offset)
266 {
267 auto pipelineContext = PipelineContext::GetCurrentContext();
268 CHECK_NULL_VOID(pipelineContext);
269 auto overlayManager = pipelineContext->GetOverlayManager();
270 CHECK_NULL_VOID(overlayManager);
271 overlayManager->UpdateDragMoveVector(offset);
272
273 if (overlayManager->IsOriginDragMoveVector() || !overlayManager->IsUpdateDragMoveVector()) {
274 return;
275 }
276
277 if (menuMap_.empty()) {
278 return;
279 }
280 auto rootNode = rootNodeWeak_.Upgrade();
281 for (const auto& child : rootNode->GetChildren()) {
282 auto node = DynamicCast<FrameNode>(child);
283 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
284 UpdateContextMenuDisappearPositionAnimation(node, overlayManager->GetUpdateDragMoveVector());
285 }
286 }
287 }
288
PostDialogFinishEvent(const WeakPtr<FrameNode> & nodeWk)289 void OverlayManager::PostDialogFinishEvent(const WeakPtr<FrameNode>& nodeWk)
290 {
291 TAG_LOGD(AceLogTag::ACE_OVERLAY, "post dialog finishi event enter");
292 auto context = PipelineContext::GetCurrentContext();
293 CHECK_NULL_VOID(context);
294 auto taskExecutor = context->GetTaskExecutor();
295 CHECK_NULL_VOID(taskExecutor);
296 // animation finish event should be posted to UI thread.
297 taskExecutor->PostTask(
298 [weak = WeakClaim(this), nodeWk, id = Container::CurrentId()]() {
299 ContainerScope scope(id);
300 auto overlayManager = weak.Upgrade();
301 auto node = nodeWk.Upgrade();
302 CHECK_NULL_VOID(overlayManager && node);
303 SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_NONE };
304 node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
305 overlayManager->OnDialogCloseEvent(node);
306 },
307 TaskExecutor::TaskType::UI);
308 }
309
OnDialogCloseEvent(const RefPtr<FrameNode> & node)310 void OverlayManager::OnDialogCloseEvent(const RefPtr<FrameNode>& node)
311 {
312 TAG_LOGD(AceLogTag::ACE_OVERLAY, "on dialog close event enter");
313 CHECK_NULL_VOID(node);
314
315 BlurOverlayNode(node);
316
317 auto dialogPattern = node->GetPattern<DialogPattern>();
318 CHECK_NULL_VOID(dialogPattern);
319 auto option = dialogPattern->GetCloseAnimation().value_or(AnimationOption());
320 auto onFinish = option.GetOnFinishEvent();
321
322 auto dialogLayoutProp = dialogPattern->GetLayoutProperty<DialogLayoutProperty>();
323 bool isShowInSubWindow = false;
324 if (dialogLayoutProp) {
325 isShowInSubWindow = dialogLayoutProp->GetShowInSubWindowValue(false);
326 }
327 if (onFinish != nullptr) {
328 onFinish();
329 }
330
331 auto root = node->GetParent();
332 CHECK_NULL_VOID(root);
333 root->RemoveChild(node);
334 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
335 auto lastChild = AceType::DynamicCast<FrameNode>(root->GetLastChild());
336 if (lastChild) {
337 auto pattern = lastChild->GetPattern();
338 if (!AceType::InstanceOf<StagePattern>(pattern)) {
339 return;
340 }
341 }
342
343 auto container = Container::Current();
344 CHECK_NULL_VOID(container);
345 if (container->IsDialogContainer() || isShowInSubWindow) {
346 SubwindowManager::GetInstance()->HideSubWindowNG();
347 }
348 }
349
OpenDialogAnimation(const RefPtr<FrameNode> & node)350 void OverlayManager::OpenDialogAnimation(const RefPtr<FrameNode>& node)
351 {
352 TAG_LOGD(AceLogTag::ACE_OVERLAY, "open dialog animation");
353 CHECK_NULL_VOID(node);
354 auto pipeline = PipelineContext::GetCurrentContext();
355 CHECK_NULL_VOID(pipeline);
356 auto theme = pipeline->GetTheme<DialogTheme>();
357 CHECK_NULL_VOID(theme);
358 auto root = rootNodeWeak_.Upgrade();
359 auto dialogPattern = node->GetPattern<DialogPattern>();
360 auto container = Container::Current();
361 if (container && container->IsScenceBoardWindow()) {
362 root = dialogPattern->GetDialogProperties().windowScene.Upgrade();
363 }
364 CHECK_NULL_VOID(root);
365 node->MountToParent(root);
366 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
367 BlurLowerNode(node);
368
369 AnimationOption option;
370 // default opacity animation params
371 option.SetCurve(Curves::SHARP);
372 option.SetDuration(theme->GetOpacityAnimationDurIn());
373 option.SetFillMode(FillMode::FORWARDS);
374 option = dialogPattern->GetOpenAnimation().value_or(option);
375 option.SetIteration(1);
376 option.SetAnimationDirection(AnimationDirection::NORMAL);
377 auto onFinish = option.GetOnFinishEvent();
378 option.SetOnFinishEvent(
379 [weak = WeakClaim(this), nodeWK = WeakPtr<FrameNode>(node), onFinish] {
380 if (onFinish) {
381 onFinish();
382 }
383 auto overlayManager = weak.Upgrade();
384 auto node = nodeWK.Upgrade();
385 CHECK_NULL_VOID(overlayManager && node);
386 overlayManager->FocusOverlayNode(node);
387 });
388 auto ctx = node->GetRenderContext();
389 option.SetFinishCallbackType(dialogPattern->GetOpenAnimation().has_value()
390 ? dialogPattern->GetOpenAnimation().value().GetFinishCallbackType()
391 : FinishCallbackType::REMOVED);
392 CHECK_NULL_VOID(ctx);
393 ctx->OpacityAnimation(option, theme->GetOpacityStart(), theme->GetOpacityEnd());
394 // scale animation on dialog content
395 auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
396 CHECK_NULL_VOID(contentNode);
397 ctx = contentNode->GetRenderContext();
398 CHECK_NULL_VOID(ctx);
399 option.SetOnFinishEvent(nullptr);
400 option.SetCurve(SHOW_SCALE_ANIMATION_CURVE);
401 option.SetDuration(dialogPattern->GetOpenAnimation().has_value()
402 ? dialogPattern->GetOpenAnimation().value().GetDuration()
403 : theme->GetAnimationDurationIn());
404 ctx->ScaleAnimation(option, theme->GetScaleStart(), theme->GetScaleEnd());
405 node->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
406 }
407
CloseDialogAnimation(const RefPtr<FrameNode> & node)408 void OverlayManager::CloseDialogAnimation(const RefPtr<FrameNode>& node)
409 {
410 TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog animation");
411 CHECK_NULL_VOID(node);
412 auto pipeline = PipelineContext::GetCurrentContext();
413 CHECK_NULL_VOID(pipeline);
414 auto theme = pipeline->GetTheme<DialogTheme>();
415 CHECK_NULL_VOID(theme);
416 SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_KEYBOARD };
417 node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
418
419 // default opacity animation params
420 AnimationOption option;
421 option.SetFillMode(FillMode::FORWARDS);
422 option.SetCurve(Curves::SHARP);
423 option.SetDuration(theme->GetAnimationDurationOut());
424 // get customized animation params
425 auto dialogPattern = node->GetPattern<DialogPattern>();
426 option = dialogPattern->GetCloseAnimation().value_or(option);
427 option.SetIteration(1);
428 option.SetAnimationDirection(AnimationDirection::NORMAL);
429 option.SetOnFinishEvent([weak = WeakClaim(this), nodeWk = WeakPtr<FrameNode>(node), id = Container::CurrentId()] {
430 ContainerScope scope(id);
431 auto overlayManager = weak.Upgrade();
432 CHECK_NULL_VOID(overlayManager);
433 overlayManager->PostDialogFinishEvent(nodeWk);
434 });
435 auto ctx = node->GetRenderContext();
436 CHECK_NULL_VOID(ctx);
437 option.SetFinishCallbackType(dialogPattern->GetOpenAnimation().has_value()
438 ? dialogPattern->GetOpenAnimation().value().GetFinishCallbackType()
439 : FinishCallbackType::REMOVED);
440 ctx->OpacityAnimation(option, theme->GetOpacityEnd(), theme->GetOpacityStart());
441
442 // scale animation
443 auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
444 CHECK_NULL_VOID(contentNode);
445 ctx = contentNode->GetRenderContext();
446 CHECK_NULL_VOID(ctx);
447 option.SetOnFinishEvent(nullptr);
448 option.SetCurve(Curves::FRICTION);
449 ctx->ScaleAnimation(option, theme->GetScaleEnd(), theme->GetScaleStart());
450 // start animation immediately
451 pipeline->RequestFrame();
452 }
453
SetContainerButtonEnable(bool isEnabled)454 void OverlayManager::SetContainerButtonEnable(bool isEnabled)
455 {
456 auto pipeline = PipelineContext::GetCurrentContext();
457 CHECK_NULL_VOID(pipeline);
458 pipeline->SetCloseButtonStatus(isEnabled);
459 }
460
ShowMenuAnimation(const RefPtr<FrameNode> & menu)461 void OverlayManager::ShowMenuAnimation(const RefPtr<FrameNode>& menu)
462 {
463 BlurLowerNode(menu);
464 auto menuWrapper = menu->GetPattern<MenuWrapperPattern>();
465 CHECK_NULL_VOID(menuWrapper);
466 menuWrapper->CallMenuAboutToAppearCallback();
467 AnimationOption option;
468 option.SetCurve(Curves::FAST_OUT_SLOW_IN);
469 option.SetDuration(MENU_ANIMATION_DURATION);
470 option.SetFillMode(FillMode::FORWARDS);
471 option.SetOnFinishEvent(
472 [weak = WeakClaim(this), menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId()] {
473 auto menu = menuWK.Upgrade();
474 auto overlayManager = weak.Upgrade();
475 CHECK_NULL_VOID(menu && overlayManager);
476 ContainerScope scope(id);
477 overlayManager->FocusOverlayNode(menu);
478 auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
479 menuWrapperPattern->CallMenuAppearCallback();
480 });
481
482 auto pattern = menu->GetPattern<MenuWrapperPattern>();
483 if (pattern->GetPreviewMode() == MenuPreviewMode::CUSTOM) {
484 auto pipelineContext = PipelineContext::GetCurrentContext();
485 CHECK_NULL_VOID(pipelineContext);
486 auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
487 CHECK_NULL_VOID(menuTheme);
488 option.SetDuration(menuTheme->GetContextMenuAppearDuration());
489 auto previewChild = pattern->GetPreview();
490 if (previewChild) {
491 auto previewPattern = AceType::DynamicCast<MenuPreviewPattern>(previewChild->GetPattern());
492 if (previewPattern) {
493 previewPattern->SetFirstShow();
494 }
495 }
496 }
497 pattern->SetAniamtinOption(option);
498 pattern->SetFirstShow();
499 auto menuChild = pattern->GetMenu();
500 CHECK_NULL_VOID(menuChild);
501 auto menuPattern = AceType::DynamicCast<MenuPattern>(menuChild->GetPattern());
502 CHECK_NULL_VOID(menuPattern);
503 menuPattern->SetFirstShow();
504 }
505
PopMenuAnimation(const RefPtr<FrameNode> & menu,bool showPreviewAnimation,bool startDrag)506 void OverlayManager::PopMenuAnimation(const RefPtr<FrameNode>& menu, bool showPreviewAnimation, bool startDrag)
507 {
508 TAG_LOGD(AceLogTag::ACE_OVERLAY, "pop menu animation enter");
509 ResetLowerNodeFocusable(menu);
510 ResetContextMenuDragHideFinished();
511
512 auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
513 CHECK_NULL_VOID(menuNode);
514 auto eventHub = menuNode->GetEventHub<EventHub>();
515 CHECK_NULL_VOID(eventHub);
516 eventHub->SetEnabledInternal(false);
517 auto menuWrapper = menu->GetPattern<MenuWrapperPattern>();
518 CHECK_NULL_VOID(menuWrapper);
519 menuWrapper->CallMenuAboutToDisappearCallback();
520 AnimationOption option;
521 option.SetCurve(Curves::FAST_OUT_SLOW_IN);
522 option.SetDuration(MENU_ANIMATION_DURATION);
523 option.SetFillMode(FillMode::FORWARDS);
524 option.SetOnFinishEvent([rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
525 weak = WeakClaim(this)] {
526 ContainerScope scope(id);
527 auto menu = menuWK.Upgrade();
528 CHECK_NULL_VOID(menu);
529 auto menuNode = AceType::DynamicCast<FrameNode>(menu->GetChildAtIndex(0));
530 CHECK_NULL_VOID(menuNode);
531 auto eventHub = menuNode->GetEventHub<EventHub>();
532 CHECK_NULL_VOID(eventHub);
533 eventHub->SetEnabledInternal(true);
534 auto menuPattern = menuNode->GetPattern<MenuPattern>();
535 CHECK_NULL_VOID(menuPattern);
536 auto root = rootWeak.Upgrade();
537 auto overlayManager = weak.Upgrade();
538 CHECK_NULL_VOID(overlayManager);
539 overlayManager->SetContextMenuDragHideFinished(true);
540 auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
541 menuWrapperPattern->CallMenuDisappearCallback();
542 auto mainPipeline = PipelineContext::GetMainPipelineContext();
543 if (mainPipeline && menuWrapperPattern->GetMenuDisappearCallback()) {
544 mainPipeline->FlushPipelineImmediately();
545 }
546 // clear contextMenu then return
547 auto pipeline = PipelineBase::GetCurrentContext();
548 CHECK_NULL_VOID(pipeline);
549 auto theme = pipeline->GetTheme<SelectTheme>();
550 CHECK_NULL_VOID(theme);
551 auto expandDisplay = theme->GetExpandDisplay();
552 auto menuLayoutProp = menuPattern->GetLayoutProperty<MenuLayoutProperty>();
553 CHECK_NULL_VOID(menuLayoutProp);
554 bool isShowInSubWindow = menuLayoutProp->GetShowInSubWindowValue(true);
555 if (((menuWrapperPattern && menuWrapperPattern->IsContextMenu()) || (isShowInSubWindow && expandDisplay)) &&
556 (menuPattern->GetTargetTag() != V2::SELECT_ETS_TAG)) {
557 SubwindowManager::GetInstance()->ClearMenuNG(id);
558 overlayManager->ResetContextMenuDragHideFinished();
559 return;
560 }
561 auto container = Container::Current();
562 if (container && container->IsScenceBoardWindow()) {
563 root = overlayManager->FindWindowScene(menu);
564 }
565 CHECK_NULL_VOID(root);
566 overlayManager->BlurOverlayNode(menu);
567 root->RemoveChild(menu);
568 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
569 });
570 ShowMenuClearAnimation(menu, option, showPreviewAnimation, startDrag);
571 }
572
ClearMenuAnimation(const RefPtr<FrameNode> & menu,bool showPreviewAnimation,bool startDrag)573 void OverlayManager::ClearMenuAnimation(const RefPtr<FrameNode>& menu, bool showPreviewAnimation, bool startDrag)
574 {
575 TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear menu animation enter");
576 ResetLowerNodeFocusable(menu);
577 AnimationOption option;
578 option.SetCurve(Curves::FAST_OUT_SLOW_IN);
579 option.SetDuration(MENU_ANIMATION_DURATION);
580 option.SetFillMode(FillMode::FORWARDS);
581 option.SetOnFinishEvent([rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
582 weak = WeakClaim(this)] {
583 auto menu = menuWK.Upgrade();
584 auto root = rootWeak.Upgrade();
585 auto overlayManager = weak.Upgrade();
586 CHECK_NULL_VOID(menu && overlayManager);
587 ContainerScope scope(id);
588 auto container = Container::Current();
589 if (container && container->IsScenceBoardWindow()) {
590 root = overlayManager->FindWindowScene(menu);
591 }
592 CHECK_NULL_VOID(root);
593 auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
594 // clear contextMenu then return
595 if ((menuWrapperPattern && menuWrapperPattern->IsContextMenu())) {
596 return;
597 }
598 overlayManager->BlurOverlayNode(menu);
599 root->RemoveChild(menu);
600 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
601 });
602 ShowMenuClearAnimation(menu, option, showPreviewAnimation, startDrag);
603 }
604
ShowMenuClearAnimation(const RefPtr<FrameNode> & menu,AnimationOption & option,bool showPreviewAnimation,bool startDrag)605 void OverlayManager::ShowMenuClearAnimation(const RefPtr<FrameNode>& menu, AnimationOption& option,
606 bool showPreviewAnimation, bool startDrag)
607 {
608 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu clear animation enter");
609 auto context = menu->GetRenderContext();
610 CHECK_NULL_VOID(context);
611 auto pipeline = PipelineBase::GetCurrentContext();
612 CHECK_NULL_VOID(pipeline);
613 auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
614 CHECK_NULL_VOID(menuWrapperPattern);
615 auto menuAnimationOffset = menuWrapperPattern->GetAnimationOffset();
616 if (menuWrapperPattern->GetPreviewMode() != MenuPreviewMode::NONE) {
617 if (!showPreviewAnimation) {
618 CleanPreviewInSubWindow();
619 } else {
620 ShowPreviewDisappearAnimation(menuWrapperPattern);
621 }
622 ShowContextMenuDisappearAnimation(option, menuWrapperPattern, startDrag);
623 } else {
624 AnimationUtils::Animate(
625 option,
626 [context, menuAnimationOffset]() {
627 context->UpdateOpacity(0.0);
628 context->UpdateOffset(menuAnimationOffset);
629 },
630 option.GetOnFinishEvent());
631 }
632 // start animation immediately
633 pipeline->RequestFrame();
634 }
635
ShowToast(const std::string & message,int32_t duration,const std::string & bottom,bool isRightToLeft,const ToastShowMode & showMode)636 void OverlayManager::ShowToast(const std::string& message, int32_t duration, const std::string& bottom,
637 bool isRightToLeft, const ToastShowMode& showMode)
638 {
639 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show toast enter");
640 auto context = PipelineContext::GetCurrentContext();
641 CHECK_NULL_VOID(context);
642 auto rootNode = context->GetRootElement();
643 CHECK_NULL_VOID(rootNode);
644
645 // only one toast
646 for (auto [id, toastNodeWeak] : toastMap_) {
647 rootNode->RemoveChild(toastNodeWeak.Upgrade());
648 }
649 toastMap_.clear();
650
651 auto toastNode = ToastView::CreateToastNode(message, bottom, isRightToLeft, showMode);
652 CHECK_NULL_VOID(toastNode);
653 auto toastId = toastNode->GetId();
654 // mount to parent
655 toastNode->MountToParent(rootNode);
656 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
657 toastMap_[toastId] = toastNode;
658 AnimationOption option;
659 auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
660 option.SetCurve(curve);
661 option.SetDuration(TOAST_ANIMATION_DURATION);
662 option.SetFillMode(FillMode::FORWARDS);
663 duration = std::max(duration, AceApplicationInfo::GetInstance().GetBarrierfreeDuration());
664 auto&& callback = [weak = WeakClaim(this), toastId, duration, id = Container::CurrentId()]() {
665 auto overlayManager = weak.Upgrade();
666 CHECK_NULL_VOID(overlayManager);
667 ContainerScope scope(id);
668 overlayManager->PopToast(toastId);
669 };
670 continuousTask_.Reset(callback);
671 option.SetOnFinishEvent([continuousTask = continuousTask_, duration, id = Container::CurrentId()] {
672 ContainerScope scope(id);
673 auto context = PipelineContext::GetCurrentContext();
674 CHECK_NULL_VOID(context);
675 auto taskExecutor = context->GetTaskExecutor();
676 CHECK_NULL_VOID(taskExecutor);
677 taskExecutor->PostDelayedTask(continuousTask, TaskExecutor::TaskType::UI, duration);
678 });
679 auto ctx = toastNode->GetRenderContext();
680 CHECK_NULL_VOID(ctx);
681 ctx->UpdateOpacity(0.0);
682 ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
683 AnimationUtils::Animate(
684 option,
685 [ctx]() {
686 if (ctx) {
687 ctx->UpdateOpacity(1.0);
688 ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
689 }
690 },
691 option.GetOnFinishEvent());
692 toastNode->OnAccessibilityEvent(
693 AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
694 }
695
PopToast(int32_t toastId)696 void OverlayManager::PopToast(int32_t toastId)
697 {
698 AnimationOption option;
699 auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
700 option.SetCurve(curve);
701 option.SetDuration(TOAST_ANIMATION_DURATION);
702 option.SetFillMode(FillMode::FORWARDS);
703 // OnFinishEvent should be executed in UI thread.
704 option.SetOnFinishEvent([weak = WeakClaim(this), toastId] {
705 auto overlayManager = weak.Upgrade();
706 CHECK_NULL_VOID(overlayManager);
707 auto toastIter = overlayManager->toastMap_.find(toastId);
708 if (toastIter == overlayManager->toastMap_.end()) {
709 return;
710 }
711 auto toastUnderPop = toastIter->second.Upgrade();
712 CHECK_NULL_VOID(toastUnderPop);
713 auto context = PipelineContext::GetCurrentContext();
714 CHECK_NULL_VOID(context);
715 auto rootNode = context->GetRootElement();
716 CHECK_NULL_VOID(rootNode);
717 rootNode->RemoveChild(toastUnderPop);
718 overlayManager->toastMap_.erase(toastId);
719 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
720
721 auto container = Container::Current();
722 CHECK_NULL_VOID(container);
723 if (container->IsDialogContainer() ||
724 (container->IsSubContainer() && rootNode->GetChildren().empty())) {
725 // hide window when toast show in subwindow.
726 SubwindowManager::GetInstance()->HideSubWindowNG();
727 }
728 });
729 auto toastIter = toastMap_.find(toastId);
730 if (toastIter == toastMap_.end()) {
731 return;
732 }
733 auto toastUnderPop = toastIter->second.Upgrade();
734 CHECK_NULL_VOID(toastUnderPop);
735 auto ctx = toastUnderPop->GetRenderContext();
736 CHECK_NULL_VOID(ctx);
737 ctx->UpdateOpacity(1.0);
738 ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
739 AnimationUtils::Animate(
740 option,
741 [ctx]() {
742 if (ctx) {
743 ctx->UpdateOpacity(0.0);
744 ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
745 }
746 },
747 option.GetOnFinishEvent());
748 // start animation immediately
749 auto pipeline = PipelineContext::GetCurrentContext();
750 CHECK_NULL_VOID(pipeline);
751 pipeline->RequestFrame();
752 AccessibilityEvent event;
753 event.type = AccessibilityEventType::CHANGE;
754 event.windowContentChangeTypes = WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE;
755 pipeline->SendEventToAccessibility(event);
756 }
757
ClearToastInSubwindow()758 void OverlayManager::ClearToastInSubwindow()
759 {
760 TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear toast in subwindow enter");
761 SubwindowManager::GetInstance()->ClearToastInSubwindow();
762 }
763
ClearToast()764 void OverlayManager::ClearToast()
765 {
766 TAG_LOGD(AceLogTag::ACE_OVERLAY, "clear toast enter");
767 auto context = PipelineContext::GetCurrentContext();
768 CHECK_NULL_VOID(context);
769 auto rootNode = context->GetRootElement();
770 CHECK_NULL_VOID(rootNode);
771 for (auto [id, toastNodeWeak] : toastMap_) {
772 PopToast(id);
773 }
774 }
775
ShowPopup(int32_t targetId,const PopupInfo & popupInfo)776 void OverlayManager::ShowPopup(int32_t targetId, const PopupInfo& popupInfo)
777 {
778 auto rootNode = rootNodeWeak_.Upgrade();
779 CHECK_NULL_VOID(rootNode);
780 auto frameNode = AceType::DynamicCast<FrameNode>(rootNode);
781 if (frameNode && !frameNode->IsLayoutComplete()) {
782 auto context = PipelineContext::GetCurrentContext();
783 CHECK_NULL_VOID(context);
784 auto taskExecutor = context->GetTaskExecutor();
785 CHECK_NULL_VOID(taskExecutor);
786 taskExecutor->PostTask(
787 [targetId, popupInfo, weak = WeakClaim(this)]() {
788 auto overlayManager = weak.Upgrade();
789 CHECK_NULL_VOID(overlayManager);
790 overlayManager->MountPopup(targetId, popupInfo);
791 },
792 TaskExecutor::TaskType::UI);
793 } else {
794 MountPopup(targetId, popupInfo);
795 }
796 }
797
MountPopup(int32_t targetId,const PopupInfo & popupInfo)798 void OverlayManager::MountPopup(int32_t targetId, const PopupInfo& popupInfo)
799 {
800 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show popup enter");
801 popupMap_[targetId] = popupInfo;
802 if (!popupInfo.markNeedUpdate) {
803 TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
804 return;
805 }
806 popupMap_[targetId].markNeedUpdate = false;
807 auto popupNode = popupInfo.popupNode;
808 CHECK_NULL_VOID(popupNode);
809 auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
810 CHECK_NULL_VOID(layoutProp);
811 auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
812 auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
813 CHECK_NULL_VOID(paintProperty);
814 auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
815 auto isUseCustom = paintProperty->GetUseCustom().value_or(false);
816
817 auto rootNode = rootNodeWeak_.Upgrade();
818 auto container = Container::Current();
819 if (container && container->IsScenceBoardWindow()) {
820 rootNode = FindWindowScene(popupInfo.target.Upgrade());
821 }
822 CHECK_NULL_VOID(rootNode);
823 CHECK_NULL_VOID(popupInfo.markNeedUpdate);
824 CHECK_NULL_VOID(popupInfo.popupNode);
825
826 const auto& rootChildren = rootNode->GetChildren();
827 auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
828 if (iter == rootChildren.rend()) {
829 popupNode->MountToParent(rootNode);
830 }
831
832 // attach popupNode before entering animation
833 popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(true);
834 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
835 popupMap_[targetId].isCurrentOnShow = true;
836
837 auto popupPattern = popupNode->GetPattern<BubblePattern>();
838 CHECK_NULL_VOID(popupPattern);
839 if ((isTypeWithOption && !isShowInSubWindow) ||
840 (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && popupInfo.focusable)) {
841 BlurLowerNode(popupNode);
842 auto onFinish = [popupNodeWk = WeakPtr<FrameNode>(popupNode), weak = WeakClaim(this)]() {
843 auto overlayManager = weak.Upgrade();
844 auto popupNode = popupNodeWk.Upgrade();
845 CHECK_NULL_VOID(overlayManager && popupNode);
846 overlayManager->FocusOverlayNode(popupNode);
847 };
848 popupPattern->StartEnteringAnimation(onFinish);
849 } else {
850 popupPattern->StartEnteringAnimation(nullptr);
851 }
852 }
853
HidePopup(int32_t targetId,const PopupInfo & popupInfo)854 void OverlayManager::HidePopup(int32_t targetId, const PopupInfo& popupInfo)
855 {
856 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide popup enter");
857 popupMap_[targetId] = popupInfo;
858 if (!popupInfo.markNeedUpdate) {
859 TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
860 return;
861 }
862 popupMap_[targetId].markNeedUpdate = false;
863 auto focusable = popupInfo.focusable;
864 auto popupNode = popupInfo.popupNode;
865 CHECK_NULL_VOID(popupNode);
866 auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
867 CHECK_NULL_VOID(layoutProp);
868 auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
869 auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
870 CHECK_NULL_VOID(paintProperty);
871 auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
872 auto isUseCustom = paintProperty->GetUseCustom().value_or(false);
873
874 auto rootNode = rootNodeWeak_.Upgrade();
875 auto container = Container::Current();
876 if (container && container->IsScenceBoardWindow()) {
877 rootNode = FindWindowScene(popupInfo.target.Upgrade());
878 }
879 CHECK_NULL_VOID(rootNode);
880
881 const auto& rootChildren = rootNode->GetChildren();
882 auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
883 if (iter == rootChildren.rend()) {
884 return;
885 }
886
887 auto popupPattern = popupNode->GetPattern<BubblePattern>();
888 CHECK_NULL_VOID(popupPattern);
889 if (popupPattern->GetTransitionStatus() == TransitionStatus::EXITING) {
890 return;
891 }
892 popupPattern->SetTransitionStatus(TransitionStatus::EXITING);
893 if ((isTypeWithOption && !isShowInSubWindow) ||
894 (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && focusable)) {
895 ResetLowerNodeFocusable(popupNode);
896 }
897 CheckReturnFocus(popupNode);
898 // detach popupNode after exiting animation
899 popupMap_[targetId].isCurrentOnShow = false;
900 popupPattern->StartExitingAnimation(
901 [isShowInSubWindow, isTypeWithOption, isUseCustom, focusable, popupNodeWk = WeakPtr<FrameNode>(popupNode),
902 rootNodeWk = WeakPtr<UINode>(rootNode), weak = WeakClaim(this)]() {
903 auto rootNode = rootNodeWk.Upgrade();
904 auto popupNode = popupNodeWk.Upgrade();
905 auto overlayManager = weak.Upgrade();
906 CHECK_NULL_VOID(rootNode && popupNode && overlayManager);
907
908 auto popupPattern = popupNode->GetPattern<BubblePattern>();
909 CHECK_NULL_VOID(popupPattern);
910 popupPattern->SetTransitionStatus(TransitionStatus::INVISIABLE);
911 popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
912 rootNode->RemoveChild(popupNode);
913 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
914 if ((isTypeWithOption && !isShowInSubWindow) ||
915 (!Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN) && isUseCustom && focusable)) {
916 overlayManager->BlurOverlayNode(popupNode);
917 }
918 if (isShowInSubWindow) {
919 auto subwindow = SubwindowManager::GetInstance();
920 CHECK_NULL_VOID(subwindow);
921 subwindow->HideSubWindowNG();
922 }
923 });
924 popupNode->OnAccessibilityEvent(
925 AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
926 RemoveEventColumn();
927 RemovePixelMapAnimation(false, 0, 0);
928 RemoveFilter();
929 }
930
HidePopupWithoutAnimation(int32_t targetId,const PopupInfo & popupInfo)931 RefPtr<FrameNode> OverlayManager::HidePopupWithoutAnimation(int32_t targetId, const PopupInfo& popupInfo)
932 {
933 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide popup without animation enter");
934 popupMap_[targetId] = popupInfo;
935 CHECK_NULL_RETURN(popupInfo.markNeedUpdate, nullptr);
936 if (!popupInfo.markNeedUpdate) {
937 TAG_LOGW(AceLogTag::ACE_OVERLAY, "mark need update failed");
938 return nullptr;
939 }
940 CHECK_NULL_RETURN(popupInfo.popupNode, nullptr);
941 popupInfo.popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
942 CHECK_NULL_RETURN(popupInfo.isCurrentOnShow, nullptr);
943 popupMap_[targetId].isCurrentOnShow = false;
944 auto pattern = popupInfo.popupNode->GetPattern<BubblePattern>();
945 CHECK_NULL_RETURN(pattern, nullptr);
946 pattern->SetTransitionStatus(TransitionStatus::INVISIABLE);
947 auto rootNode = rootNodeWeak_.Upgrade();
948 CHECK_NULL_RETURN(rootNode, nullptr);
949 auto rootChildren = rootNode->GetChildren();
950 auto iter = std::find(rootChildren.begin(), rootChildren.end(), popupInfo.popupNode);
951 if (iter != rootChildren.end()) {
952 return popupMap_[targetId].popupNode;
953 }
954 return nullptr;
955 }
956
ShowIndexerPopup(int32_t targetId,RefPtr<FrameNode> & customNode)957 void OverlayManager::ShowIndexerPopup(int32_t targetId, RefPtr<FrameNode>& customNode)
958 {
959 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show indexer popup enter");
960 CHECK_NULL_VOID(customNode);
961 auto rootNode = rootNodeWeak_.Upgrade();
962 CHECK_NULL_VOID(rootNode);
963 if (!customPopupMap_[targetId] || customPopupMap_[targetId] != customNode) {
964 customPopupMap_[targetId] = customNode;
965 customNode->MountToParent(rootNode);
966 customNode->MarkModifyDone();
967 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
968 }
969 }
970
RemoveIndexerPopupById(int32_t targetId)971 void OverlayManager::RemoveIndexerPopupById(int32_t targetId)
972 {
973 TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove indexer popup byid enter");
974 if (customPopupMap_.empty()) {
975 return;
976 }
977 auto rootNode = rootNodeWeak_.Upgrade();
978 CHECK_NULL_VOID(rootNode);
979 auto iter = customPopupMap_.find(targetId);
980 if (iter != customPopupMap_.end()) {
981 rootNode->RemoveChild(iter->second);
982 customPopupMap_.erase(iter);
983 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
984 }
985 }
986
RemoveIndexerPopup()987 void OverlayManager::RemoveIndexerPopup()
988 {
989 TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove indexer popup enter");
990 if (customPopupMap_.empty()) {
991 return;
992 }
993 auto rootNode = rootNodeWeak_.Upgrade();
994 CHECK_NULL_VOID(rootNode);
995 for (const auto& popup : customPopupMap_) {
996 auto popupNode = popup.second;
997 rootNode->RemoveChild(popupNode);
998 }
999 customPopupMap_.clear();
1000 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1001 }
1002
HideCustomPopups()1003 void OverlayManager::HideCustomPopups()
1004 {
1005 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide custom popup enter");
1006 if (popupMap_.empty()) {
1007 return;
1008 }
1009 for (const auto& popup : popupMap_) {
1010 auto popupInfo = popup.second;
1011 if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
1012 auto targetNodeId = popupInfo.target.Upgrade()->GetId();
1013 auto popupNode = popupInfo.popupNode;
1014 CHECK_NULL_VOID(popupNode);
1015 auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1016 CHECK_NULL_VOID(layoutProp);
1017 auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
1018 CHECK_NULL_VOID(paintProperty);
1019 auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
1020 popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1021 // if use popup with option, skip
1022 if (isTypeWithOption) {
1023 continue;
1024 }
1025 popupInfo.markNeedUpdate = true;
1026 auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1027 if (showInSubWindow) {
1028 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
1029 } else {
1030 HidePopup(targetNodeId, popupInfo);
1031 }
1032 }
1033 }
1034 }
1035
HideAllPopups()1036 void OverlayManager::HideAllPopups()
1037 {
1038 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide all popup enter");
1039 if (popupMap_.empty()) {
1040 return;
1041 }
1042 for (const auto& popup : popupMap_) {
1043 auto popupInfo = popup.second;
1044 if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
1045 auto targetNodeId = popupInfo.target.Upgrade()->GetId();
1046 auto popupNode = popupInfo.popupNode;
1047 CHECK_NULL_VOID(popupNode);
1048 auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
1049 CHECK_NULL_VOID(layoutProp);
1050 popupInfo.markNeedUpdate = true;
1051 auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
1052 if (showInSubWindow) {
1053 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
1054 } else {
1055 HidePopup(targetNodeId, popupInfo);
1056 }
1057 }
1058 }
1059 }
1060
ErasePopup(int32_t targetId)1061 void OverlayManager::ErasePopup(int32_t targetId)
1062 {
1063 TAG_LOGD(AceLogTag::ACE_OVERLAY, "erase popup enter");
1064 if (popupMap_.find(targetId) != popupMap_.end()) {
1065 auto rootNode = rootNodeWeak_.Upgrade();
1066 CHECK_NULL_VOID(rootNode);
1067 rootNode->RemoveChild(popupMap_[targetId].popupNode);
1068 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1069 popupMap_.erase(targetId);
1070 }
1071 }
1072
ShowMenuHelper(RefPtr<FrameNode> & menu,int32_t targetId,const NG::OffsetF & offset)1073 bool OverlayManager::ShowMenuHelper(RefPtr<FrameNode>& menu, int32_t targetId, const NG::OffsetF& offset)
1074 {
1075 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu helper enter");
1076 if (!menu) {
1077 // get existing menuNode
1078 auto it = menuMap_.find(targetId);
1079 if (it != menuMap_.end()) {
1080 menu = it->second;
1081 }
1082 } else {
1083 // creating new menu
1084 menuMap_[targetId] = menu;
1085 }
1086 CHECK_NULL_RETURN(menu, false);
1087
1088 RefPtr<FrameNode> menuFrameNode = menu;
1089 if (menu->GetTag() != V2::MENU_ETS_TAG) {
1090 auto menuChild = menu->GetChildAtIndex(0);
1091 CHECK_NULL_RETURN(menuChild, false);
1092 menuFrameNode = DynamicCast<FrameNode>(menuChild);
1093 }
1094
1095 auto props = menuFrameNode->GetLayoutProperty<MenuLayoutProperty>();
1096 CHECK_NULL_RETURN(props, false);
1097 props->UpdateMenuOffset(offset);
1098 menuFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1099 return true;
1100 }
1101
ShowMenu(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)1102 void OverlayManager::ShowMenu(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
1103 {
1104 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu enter");
1105 if (!ShowMenuHelper(menu, targetId, offset)) {
1106 TAG_LOGW(AceLogTag::ACE_OVERLAY, "show menu helper failed");
1107 return;
1108 }
1109 auto rootNode = rootNodeWeak_.Upgrade();
1110 auto container = Container::Current();
1111 if (container && container->IsScenceBoardWindow()) {
1112 auto wrapperPattern = AceType::DynamicCast<MenuWrapperPattern>(menu->GetPattern());
1113 CHECK_NULL_VOID(wrapperPattern);
1114 auto menuChild = wrapperPattern->GetMenu();
1115 CHECK_NULL_VOID(menuChild);
1116 auto menuPattern = AceType::DynamicCast<MenuPattern>(menuChild->GetPattern());
1117 CHECK_NULL_VOID(menuPattern);
1118 rootNode = FindWindowScene(FrameNode::GetFrameNode(menuPattern->GetTargetTag(), menuPattern->GetTargetId()));
1119 }
1120 CHECK_NULL_VOID(rootNode);
1121 auto rootChildren = rootNode->GetChildren();
1122 auto iter = std::find(rootChildren.begin(), rootChildren.end(), menu);
1123 // menuNode already showing
1124 if (iter == rootChildren.end()) {
1125 menu->MountToParent(rootNode);
1126 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1127 menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1128 ShowMenuAnimation(menu);
1129 menu->MarkModifyDone();
1130 }
1131 menu->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1132 auto pattern = menu->GetPattern<MenuWrapperPattern>();
1133 CHECK_NULL_VOID(pattern);
1134 pattern->SetShow(true);
1135 }
1136
1137 // subwindow only contains one menu instance.
ShowMenuInSubWindow(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)1138 void OverlayManager::ShowMenuInSubWindow(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
1139 {
1140 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show menu insubwindow enter");
1141 auto menuOffset = offset;
1142 auto currentSubwindow = SubwindowManager::GetInstance()->GetCurrentWindow();
1143 if (currentSubwindow) {
1144 auto subwindowRect = currentSubwindow->GetRect();
1145 menuOffset -= subwindowRect.GetOffset();
1146 }
1147 if (!ShowMenuHelper(menu, targetId, menuOffset)) {
1148 TAG_LOGW(AceLogTag::ACE_OVERLAY, "show menu helper failed");
1149 return;
1150 }
1151 auto rootNode = rootNodeWeak_.Upgrade();
1152 CHECK_NULL_VOID(rootNode);
1153 rootNode->Clean();
1154 menu->MountToParent(rootNode);
1155 ShowMenuAnimation(menu);
1156 menu->MarkModifyDone();
1157 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1158
1159 // set subwindow container id in menu.
1160 auto menuPattern = menu->GetPattern<PopupBasePattern>();
1161 CHECK_NULL_VOID(menuPattern);
1162 menuPattern->SetContainerId(Container::CurrentId());
1163 }
1164
HideMenuInSubWindow(const RefPtr<FrameNode> & menu,int32_t targetId)1165 void OverlayManager::HideMenuInSubWindow(const RefPtr<FrameNode>& menu, int32_t targetId)
1166 {
1167 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide menu insubwindow enter");
1168 CHECK_NULL_VOID(menu);
1169 PopMenuAnimation(menu);
1170 }
1171
HideMenuInSubWindow(bool showPreviewAnimation,bool startDrag)1172 void OverlayManager::HideMenuInSubWindow(bool showPreviewAnimation, bool startDrag)
1173 {
1174 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide menu insubwindow enter");
1175 if (menuMap_.empty()) {
1176 return;
1177 }
1178 auto rootNode = rootNodeWeak_.Upgrade();
1179 for (const auto& child : rootNode->GetChildren()) {
1180 auto node = DynamicCast<FrameNode>(child);
1181 if (node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1182 PopMenuAnimation(node, showPreviewAnimation, startDrag);
1183 }
1184 }
1185 }
1186
GetMenuNode(int32_t targetId)1187 RefPtr<FrameNode> OverlayManager::GetMenuNode(int32_t targetId)
1188 {
1189 auto it = menuMap_.find(targetId);
1190 if (it != menuMap_.end()) {
1191 return it->second;
1192 }
1193 return nullptr;
1194 }
1195
HideMenu(const RefPtr<FrameNode> & menu,int32_t targetId,bool isMenuOnTouch)1196 void OverlayManager::HideMenu(const RefPtr<FrameNode>& menu, int32_t targetId, bool isMenuOnTouch)
1197 {
1198 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide menu enter");
1199 auto pattern = menu->GetPattern<MenuWrapperPattern>();
1200 CHECK_NULL_VOID(pattern);
1201 pattern->SetShow(false);
1202 PopMenuAnimation(menu);
1203 menu->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1204 RemoveEventColumn();
1205 if (isMenuOnTouch) {
1206 RemovePixelMap();
1207 } else {
1208 RemovePixelMapAnimation(false, 0, 0);
1209 }
1210 RemoveFilterAnimation();
1211 }
1212
HideAllMenus()1213 void OverlayManager::HideAllMenus()
1214 {
1215 TAG_LOGD(AceLogTag::ACE_OVERLAY, "hide all menus enter");
1216 auto container = Container::Current();
1217 if (container && container->IsScenceBoardWindow()) {
1218 for (const auto& windowScene : windowSceneSet_) {
1219 if (!windowScene.Upgrade()) {
1220 continue;
1221 }
1222 for (const auto& child : windowScene.Upgrade()->GetChildren()) {
1223 auto node = DynamicCast<FrameNode>(child);
1224 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1225 PopMenuAnimation(node);
1226 }
1227 }
1228 }
1229 return;
1230 }
1231
1232 auto rootNode = rootNodeWeak_.Upgrade();
1233 CHECK_NULL_VOID(rootNode);
1234 for (const auto& child : rootNode->GetChildren()) {
1235 auto node = DynamicCast<FrameNode>(child);
1236 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1237 PopMenuAnimation(node);
1238 }
1239 }
1240 }
1241
DeleteMenu(int32_t targetId)1242 void OverlayManager::DeleteMenu(int32_t targetId)
1243 {
1244 TAG_LOGD(AceLogTag::ACE_OVERLAY, "delete menu enter");
1245 auto it = menuMap_.find(targetId);
1246 if (it == menuMap_.end()) {
1247 return;
1248 }
1249 auto node = AceType::DynamicCast<FrameNode>(it->second);
1250 if (node->GetParent()) {
1251 auto id = Container::CurrentId();
1252 SubwindowManager::GetInstance()->ClearMenu();
1253 SubwindowManager::GetInstance()->ClearMenuNG(id);
1254 }
1255 menuMap_.erase(it);
1256 }
1257
CleanMenuInSubWindowWithAnimation()1258 void OverlayManager::CleanMenuInSubWindowWithAnimation()
1259 {
1260 TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean menu insubwindow with animation enter");
1261 auto rootNode = rootNodeWeak_.Upgrade();
1262 CHECK_NULL_VOID(rootNode);
1263 RefPtr<FrameNode> menu;
1264 for (const auto& child : rootNode->GetChildren()) {
1265 auto node = DynamicCast<FrameNode>(child);
1266 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1267 menu = node;
1268 break;
1269 }
1270 }
1271 CHECK_NULL_VOID(menu);
1272 auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
1273 CHECK_NULL_VOID(menuWrapperPattern);
1274 menuWrapperPattern->SetMenuHide();
1275 ClearMenuAnimation(menu);
1276 }
1277
CleanPreviewInSubWindow()1278 void OverlayManager::CleanPreviewInSubWindow()
1279 {
1280 auto rootNode = rootNodeWeak_.Upgrade();
1281 CHECK_NULL_VOID(rootNode);
1282 for (const auto& child : rootNode->GetChildren()) {
1283 auto node = DynamicCast<FrameNode>(child);
1284 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1285 for (auto& childNode : node->GetChildren()) {
1286 auto frameNode = DynamicCast<FrameNode>(childNode);
1287 if (frameNode &&
1288 (frameNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG || frameNode->GetTag() == V2::IMAGE_ETS_TAG)) {
1289 node->RemoveChild(frameNode);
1290 break;
1291 }
1292 }
1293 break;
1294 }
1295 }
1296 }
1297
CleanMenuInSubWindow()1298 void OverlayManager::CleanMenuInSubWindow()
1299 {
1300 TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean menu insubwindow enter");
1301 auto rootNode = rootNodeWeak_.Upgrade();
1302 CHECK_NULL_VOID(rootNode);
1303 for (const auto& child : rootNode->GetChildren()) {
1304 auto node = DynamicCast<FrameNode>(child);
1305 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
1306 for (auto& childNode : node->GetChildren()) {
1307 auto frameNode = DynamicCast<FrameNode>(childNode);
1308 if (frameNode &&
1309 (frameNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG || frameNode->GetTag() == V2::IMAGE_ETS_TAG)) {
1310 node->RemoveChild(frameNode);
1311 break;
1312 }
1313 }
1314 rootNode->RemoveChild(node);
1315 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1316 break;
1317 }
1318 }
1319
1320 for (const auto& child : rootNode->GetChildren()) {
1321 auto node = DynamicCast<FrameNode>(child);
1322 if (node && node->GetTag() == V2::COLUMN_ETS_TAG) {
1323 rootNode->RemoveChild(node);
1324 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1325 break;
1326 }
1327 }
1328 }
1329
CleanPopupInSubWindow()1330 void OverlayManager::CleanPopupInSubWindow()
1331 {
1332 TAG_LOGD(AceLogTag::ACE_OVERLAY, "clean popup insubwindow enter");
1333 auto rootNode = rootNodeWeak_.Upgrade();
1334 CHECK_NULL_VOID(rootNode);
1335 std::vector<RefPtr<FrameNode>> removeNodes;
1336 for (const auto& child : rootNode->GetChildren()) {
1337 if (!child || child->GetTag() != V2::POPUP_ETS_TAG) {
1338 continue;
1339 }
1340 auto id = child->GetId();
1341 for (const auto& popup : popupMap_) {
1342 auto popupInfo = popup.second;
1343 auto target = popup.first;
1344 if (id != popupInfo.popupId) {
1345 continue;
1346 }
1347 popupInfo.markNeedUpdate = true;
1348 auto removeNode = HidePopupWithoutAnimation(target, popupInfo);
1349 if (removeNode) {
1350 removeNodes.emplace_back(removeNode);
1351 }
1352 break;
1353 }
1354 }
1355 for (const auto& removeNode : removeNodes) {
1356 rootNode->RemoveChild(removeNode);
1357 }
1358 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1359 }
1360
BeforeShowDialog(const RefPtr<FrameNode> & node)1361 void OverlayManager::BeforeShowDialog(const RefPtr<FrameNode>& node)
1362 {
1363 TAG_LOGD(AceLogTag::ACE_OVERLAY, "before show dialog");
1364 CHECK_NULL_VOID(node);
1365 if (dialogMap_.find(node->GetId()) != dialogMap_.end()) {
1366 return;
1367 }
1368 dialogMap_[node->GetId()] = node;
1369 }
1370
ShowDialog(const DialogProperties & dialogProps,std::function<void ()> && buildFunc,bool isRightToLeft)1371 RefPtr<FrameNode> OverlayManager::ShowDialog(
1372 const DialogProperties& dialogProps, std::function<void()>&& buildFunc, bool isRightToLeft)
1373 {
1374 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show dialog enter");
1375 RefPtr<UINode> customNode;
1376 // create custom builder content
1377 if (buildFunc) {
1378 NG::ScopedViewStackProcessor builderViewStackProcessor;
1379 buildFunc();
1380 customNode = NG::ViewStackProcessor::GetInstance()->Finish();
1381 CHECK_NULL_RETURN(customNode, nullptr);
1382 }
1383
1384 auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
1385 CHECK_NULL_RETURN(dialog, nullptr);
1386 BeforeShowDialog(dialog);
1387 OpenDialogAnimation(dialog);
1388 dialogCount_++;
1389 // set close button disable
1390 SetContainerButtonEnable(false);
1391 if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
1392 Recorder::EventParamsBuilder builder;
1393 builder
1394 .SetType("Dialog")
1395 .SetEventType(Recorder::EventType::DIALOG_SHOW)
1396 .SetExtra(Recorder::KEY_TITLE, dialogProps.title)
1397 .SetExtra(Recorder::KEY_SUB_TITLE, dialogProps.subtitle);
1398 Recorder::EventRecorder::Get().OnEvent(std::move(builder));
1399 }
1400 return dialog;
1401 }
1402
OpenCustomDialog(const DialogProperties & dialogProps,std::function<void (int32_t)> && callback)1403 void OverlayManager::OpenCustomDialog(const DialogProperties& dialogProps, std::function<void(int32_t)> &&callback)
1404 {
1405 RefPtr<UINode> customNode;
1406 if (dialogProps.customBuilder) {
1407 NG::ScopedViewStackProcessor builderViewStackProcessor;
1408 dialogProps.customBuilder();
1409 customNode = NG::ViewStackProcessor::GetInstance()->Finish();
1410 CHECK_NULL_VOID(customNode);
1411 }
1412 auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
1413 CHECK_NULL_VOID(dialog);
1414
1415 BeforeShowDialog(dialog);
1416
1417 // callback dialogId
1418 if (callback) {
1419 callback(dialog->GetId());
1420 }
1421
1422 OpenDialogAnimation(dialog);
1423 dialogCount_++;
1424
1425 if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
1426 Recorder::EventParamsBuilder builder;
1427 builder
1428 .SetType("Dialog")
1429 .SetEventType(Recorder::EventType::DIALOG_SHOW)
1430 .SetExtra(Recorder::KEY_TITLE, dialogProps.title)
1431 .SetExtra(Recorder::KEY_SUB_TITLE, dialogProps.subtitle);
1432 Recorder::EventRecorder::Get().OnEvent(std::move(builder));
1433 }
1434 return;
1435 }
1436
CloseCustomDialog(const int32_t dialogId)1437 void OverlayManager::CloseCustomDialog(const int32_t dialogId)
1438 {
1439 auto iter = dialogMap_.end();
1440 if (dialogId == -1) {
1441 int32_t tmpNodeId = -1;
1442 RefPtr<FrameNode> tmpNode;
1443 iter = dialogMap_.begin();
1444 while (iter != dialogMap_.end()) {
1445 auto dialogNode = (*iter).second;
1446 if (dialogNode && dialogNode->GetId() > tmpNodeId) {
1447 tmpNodeId = dialogNode->GetId();
1448 tmpNode = dialogNode;
1449 }
1450 iter++;
1451 }
1452 if (tmpNode) {
1453 CloseDialogInner(tmpNode);
1454 } else {
1455 LOGE("not find dialog when no dialog id");
1456 }
1457 } else {
1458 iter = dialogMap_.find(dialogId);
1459 if (iter == dialogMap_.end()) {
1460 LOGE("not find dialog by id %{public}d", dialogId);
1461 return;
1462 }
1463 RefPtr<FrameNode> tmpDialog = (*iter).second;
1464 CloseDialogInner(tmpDialog);
1465 }
1466 return;
1467 }
1468
ShowCustomDialog(const RefPtr<FrameNode> & customNode)1469 void OverlayManager::ShowCustomDialog(const RefPtr<FrameNode>& customNode)
1470 {
1471 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show custom dialog enter");
1472 BeforeShowDialog(customNode);
1473 OpenDialogAnimation(customNode);
1474 }
1475
ShowDateDialog(const DialogProperties & dialogProps,const DatePickerSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1476 void OverlayManager::ShowDateDialog(const DialogProperties& dialogProps, const DatePickerSettingData& settingData,
1477 std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1478 {
1479 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show date dialog enter");
1480 auto dialogNode = DatePickerDialogView::Show(
1481 dialogProps, std::move(settingData), std::move(dialogEvent), std::move(dialogCancelEvent));
1482 BeforeShowDialog(dialogNode);
1483 OpenDialogAnimation(dialogNode);
1484 }
1485
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)1486 void OverlayManager::ShowTimeDialog(const DialogProperties& dialogProps, const TimePickerSettingData& settingData,
1487 std::map<std::string, PickerTime> timePickerProperty, std::map<std::string, NG::DialogEvent> dialogEvent,
1488 std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1489 {
1490 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show time dialog enter");
1491 auto dialogNode = TimePickerDialogView::Show(
1492 dialogProps, settingData, std::move(timePickerProperty), std::move(dialogEvent), std::move(dialogCancelEvent));
1493 BeforeShowDialog(dialogNode);
1494 OpenDialogAnimation(dialogNode);
1495 }
1496
ShowTextDialog(const DialogProperties & dialogProps,const TextPickerSettingData & settingData,std::map<std::string,NG::DialogTextEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1497 void OverlayManager::ShowTextDialog(const DialogProperties& dialogProps, const TextPickerSettingData& settingData,
1498 std::map<std::string, NG::DialogTextEvent> dialogEvent,
1499 std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1500 {
1501 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show text dialog enter");
1502 auto dialogNode =
1503 TextPickerDialogView::Show(dialogProps, settingData, std::move(dialogEvent), std::move(dialogCancelEvent));
1504 BeforeShowDialog(dialogNode);
1505 OpenDialogAnimation(dialogNode);
1506 if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
1507 Recorder::EventParamsBuilder builder;
1508 builder.SetType("TextPickerDialog").SetEventType(Recorder::EventType::DIALOG_SHOW);
1509 Recorder::EventRecorder::Get().OnEvent(std::move(builder));
1510 }
1511 }
1512
ShowCalendarDialog(const DialogProperties & dialogProps,const CalendarSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1513 void OverlayManager::ShowCalendarDialog(const DialogProperties& dialogProps, const CalendarSettingData& settingData,
1514 std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1515 {
1516 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show calendar dialog enter");
1517 auto dialogNode =
1518 CalendarDialogView::Show(dialogProps, settingData, std::move(dialogEvent), std::move(dialogCancelEvent));
1519 BeforeShowDialog(dialogNode);
1520 OpenDialogAnimation(dialogNode);
1521 }
1522
PopModalDialog(int32_t maskId)1523 void OverlayManager::PopModalDialog(int32_t maskId)
1524 {
1525 TAG_LOGD(AceLogTag::ACE_OVERLAY, "pop modal dialog enter");
1526 int32_t dialogId = -1;
1527 for (auto it = maskNodeIdMap_.begin(); it != maskNodeIdMap_.end(); it++) {
1528 if (maskId == it->second) {
1529 dialogId = it->first;
1530 break;
1531 }
1532 }
1533 auto subWindow = SubwindowManager::GetInstance()->GetSubwindow(subWindowId_);
1534 CHECK_NULL_VOID(subWindow);
1535 auto subOverlayManager = subWindow->GetOverlayManager();
1536 CHECK_NULL_VOID(subOverlayManager);
1537 std::map<int32_t, RefPtr<FrameNode>> DialogMap(
1538 subOverlayManager->GetDialogMap().begin(), subOverlayManager->GetDialogMap().end());
1539 for (auto it = DialogMap.begin(); it != DialogMap.end(); it++) {
1540 auto dialogProp = DynamicCast<DialogLayoutProperty>(it->second->GetLayoutProperty());
1541 if (dialogId == it->first) {
1542 auto hub = it->second->GetEventHub<DialogEventHub>();
1543 if (hub) {
1544 hub->FireCancelEvent();
1545 }
1546 subOverlayManager->CloseDialog(it->second);
1547 }
1548 }
1549 }
1550
RemoveDialogFromMap(const RefPtr<FrameNode> & node)1551 void OverlayManager::RemoveDialogFromMap(const RefPtr<FrameNode>& node)
1552 {
1553 TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove dialog from map enter");
1554 CHECK_NULL_VOID(node);
1555 if (dialogMap_.find(node->GetId()) == dialogMap_.end()) {
1556 return;
1557 }
1558 dialogMap_.erase(node->GetId());
1559 }
1560
DialogInMapHoldingFocus()1561 bool OverlayManager::DialogInMapHoldingFocus()
1562 {
1563 TAG_LOGD(AceLogTag::ACE_OVERLAY, "dialog in map holding focus enter");
1564 if (dialogMap_.empty()) {
1565 return false;
1566 }
1567 auto iter = dialogMap_.begin();
1568 while (iter != dialogMap_.end()) {
1569 auto dialogNode = (*iter).second;
1570 if (dialogNode && dialogNode->GetFocusHub() && dialogNode->GetFocusHub()->IsCurrentFocus()) {
1571 return true;
1572 }
1573 iter++;
1574 }
1575 return false;
1576 }
1577
GetDialog(int32_t dialogId)1578 RefPtr<FrameNode> OverlayManager::GetDialog(int32_t dialogId)
1579 {
1580 TAG_LOGD(AceLogTag::ACE_OVERLAY, "get dialog enter");
1581 for (auto it = dialogMap_.begin(); it != dialogMap_.end(); it++) {
1582 if (dialogId == it->second->GetId()) {
1583 return it->second;
1584 }
1585 }
1586 return nullptr;
1587 }
1588
CloseDialog(const RefPtr<FrameNode> & dialogNode)1589 void OverlayManager::CloseDialog(const RefPtr<FrameNode>& dialogNode)
1590 {
1591 TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog enter");
1592 auto dialogLayoutProp = AceType::DynamicCast<DialogLayoutProperty>(dialogNode->GetLayoutProperty());
1593 CHECK_NULL_VOID(dialogLayoutProp);
1594 if (dialogLayoutProp->GetShowInSubWindowValue(false)) {
1595 SubwindowManager::GetInstance()->DeleteHotAreas(
1596 SubwindowManager::GetInstance()->GetDialogSubWindowId(), dialogNode->GetId());
1597 SubwindowManager::GetInstance()->HideDialogSubWindow(
1598 SubwindowManager::GetInstance()->GetDialogSubWindowId());
1599 }
1600 if (dialogLayoutProp->GetShowInSubWindowValue(false) && dialogLayoutProp->GetIsModal().value_or(true)) {
1601 auto parentPipelineContext = PipelineContext::GetMainPipelineContext();
1602 CHECK_NULL_VOID(parentPipelineContext);
1603 auto parentOverlayManager = parentPipelineContext->GetOverlayManager();
1604 CHECK_NULL_VOID(parentOverlayManager);
1605 RefPtr<FrameNode> maskNode =
1606 parentOverlayManager->GetDialog(parentOverlayManager->GetMaskNodeIdWithDialogId(dialogNode->GetId()));
1607 if (maskNode) {
1608 parentOverlayManager->CloseDialog(maskNode);
1609 }
1610 }
1611 CloseDialogInner(dialogNode);
1612 }
1613
CloseDialogInner(const RefPtr<FrameNode> & dialogNode)1614 void OverlayManager::CloseDialogInner(const RefPtr<FrameNode>& dialogNode)
1615 {
1616 RemoveDialogFromMap(dialogNode);
1617 if (dialogNode->IsRemoving()) {
1618 // already in close animation
1619 return;
1620 }
1621 dialogNode->MarkRemoving();
1622
1623 auto container = Container::Current();
1624 auto currentId = Container::CurrentId();
1625 CHECK_NULL_VOID(container);
1626 if (container->IsSubContainer()) {
1627 currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
1628 container = AceEngine::Get().GetContainer(currentId);
1629 }
1630 ContainerScope scope(currentId);
1631 auto pipelineContext = container->GetPipelineContext();
1632 CHECK_NULL_VOID(pipelineContext);
1633 auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
1634 CHECK_NULL_VOID(context);
1635 auto overlayManager = context->GetOverlayManager();
1636 CHECK_NULL_VOID(overlayManager);
1637 overlayManager->ResetLowerNodeFocusable(dialogNode);
1638 CloseDialogAnimation(dialogNode);
1639 dialogCount_--;
1640 // set close button enable
1641 if (dialogCount_ == 0) {
1642 SetContainerButtonEnable(true);
1643 }
1644 dialogNode->OnAccessibilityEvent(
1645 AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1646 CallOnHideDialogCallback();
1647 }
1648
RemoveDialog(const RefPtr<FrameNode> & overlay,bool isBackPressed,bool isPageRouter)1649 bool OverlayManager::RemoveDialog(const RefPtr<FrameNode>& overlay, bool isBackPressed, bool isPageRouter)
1650 {
1651 TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove dialog enter");
1652 if (overlay->IsRemoving()) {
1653 return false;
1654 }
1655 if (FireBackPressEvent()) {
1656 return true;
1657 }
1658 auto hub = overlay->GetEventHub<DialogEventHub>();
1659 if (!isPageRouter && hub) {
1660 hub->FireCancelEvent();
1661 }
1662 CloseDialog(overlay);
1663 if (isBackPressed) {
1664 SetBackPressEvent(nullptr);
1665 }
1666 return true;
1667 }
1668
RemoveBubble(const RefPtr<FrameNode> & overlay)1669 bool OverlayManager::RemoveBubble(const RefPtr<FrameNode>& overlay)
1670 {
1671 TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove bubble enter");
1672 for (const auto& popup : popupMap_) {
1673 auto targetId = popup.first;
1674 auto popupInfo = popup.second;
1675 if (overlay == popupInfo.popupNode) {
1676 popupInfo.markNeedUpdate = true;
1677 HidePopup(targetId, popupInfo);
1678 return true;
1679 }
1680 }
1681 return false;
1682 }
1683
RemoveMenu(const RefPtr<FrameNode> & overlay)1684 bool OverlayManager::RemoveMenu(const RefPtr<FrameNode>& overlay)
1685 {
1686 TAG_LOGD(AceLogTag::ACE_OVERLAY, "remove menu enter");
1687 auto menuWrapperPattern = overlay->GetPattern<MenuWrapperPattern>();
1688 CHECK_NULL_RETURN(menuWrapperPattern, false);
1689 menuWrapperPattern->HideMenu();
1690 return true;
1691 }
1692
RemoveOverlay(bool isBackPressed,bool isPageRouter)1693 bool OverlayManager::RemoveOverlay(bool isBackPressed, bool isPageRouter)
1694 {
1695 auto rootNode = rootNodeWeak_.Upgrade();
1696 CHECK_NULL_RETURN(rootNode, true);
1697 RemoveIndexerPopup();
1698 DestroyKeyboard();
1699 if (rootNode->GetChildren().size() > 1) {
1700 // stage node is at index 0, remove overlay at last
1701 auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
1702 CHECK_NULL_RETURN(overlay, false);
1703 // close dialog with animation
1704 auto pattern = overlay->GetPattern();
1705 if (InstanceOf<ToastPattern>(pattern)) {
1706 // still have nodes on root expect stage and toast node.
1707 if (rootNode->GetChildren().size() > 2) {
1708 // If the current node is a toast, the last second overlay's node should be processed.
1709 overlay = DynamicCast<FrameNode>(rootNode->GetChildAtIndex(rootNode->GetChildren().size() - 2));
1710 CHECK_NULL_RETURN(overlay, false);
1711 pattern = overlay->GetPattern();
1712 } else {
1713 return false;
1714 }
1715 }
1716 if (InstanceOf<DialogPattern>(pattern)) {
1717 return RemoveDialog(overlay, isBackPressed, isPageRouter);
1718 }
1719 if (InstanceOf<BubblePattern>(pattern)) {
1720 return RemoveBubble(overlay);
1721 }
1722 if (InstanceOf<MenuWrapperPattern>(pattern)) {
1723 return RemoveMenu(overlay);
1724 }
1725 if (InstanceOf<VideoFullScreenPattern>(pattern)) {
1726 auto videoPattern = DynamicCast<VideoFullScreenPattern>(pattern);
1727 CHECK_NULL_RETURN(videoPattern, false);
1728 return videoPattern->ExitFullScreen();
1729 }
1730
1731 // remove navDestination in navigation first
1732 do {
1733 auto pipeline = PipelineContext::GetCurrentContext();
1734 CHECK_NULL_BREAK(pipeline);
1735 auto navigationGroupNode =
1736 AceType::DynamicCast<NavigationGroupNode>(pipeline->FindNavigationNodeToHandleBack(overlay));
1737 CHECK_NULL_BREAK(navigationGroupNode);
1738 return true;
1739 } while (0);
1740 if (!modalStack_.empty()) {
1741 if (isPageRouter) {
1742 return RemoveAllModalInOverlay();
1743 } else {
1744 return RemoveModalInOverlay();
1745 }
1746 }
1747 rootNode->RemoveChild(overlay);
1748 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1749 return true;
1750 }
1751 return false;
1752 }
1753
RemoveModalInOverlay()1754 bool OverlayManager::RemoveModalInOverlay()
1755 {
1756 auto topModalNode = modalStack_.top().Upgrade();
1757 CHECK_NULL_RETURN(topModalNode, false);
1758 if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
1759 auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
1760 CHECK_NULL_RETURN(sheetPattern, false);
1761 if (sheetPattern->hasShouldDismiss()) {
1762 sheetPattern->SheetInteractiveDismiss(false);
1763 return true;
1764 }
1765 }
1766
1767 auto rootNode = FindWindowScene(topModalNode);
1768 CHECK_NULL_RETURN(rootNode, true);
1769
1770 ModalPageLostFocus(topModalNode);
1771 auto pattern = topModalNode->GetPattern<PopupBasePattern>();
1772 if (isProhibitBack_ && pattern->GetTargetId() < 0) {
1773 return true;
1774 }
1775 auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1776 CHECK_NULL_RETURN(builder, false);
1777 if (!ModalExitProcess(topModalNode)) {
1778 return false;
1779 }
1780 if (!modalStack_.empty()) {
1781 modalStack_.pop();
1782 }
1783 if (!modalList_.empty()) {
1784 modalList_.pop_back();
1785 }
1786 auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
1787 if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG && sheetPattern) {
1788 sheetMap_.erase(sheetPattern->GetTargetId());
1789 }
1790 if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1791 auto modalPattern = AceType::DynamicCast<ModalPresentationPattern>(pattern);
1792 CHECK_NULL_RETURN(modalPattern, false);
1793 auto modalTransition = modalPattern->GetType();
1794 if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
1795 // Fire shown event of navdestination under the disappeared modal
1796 FireNavigationStateChange(true);
1797 }
1798 }
1799
1800 FireModalPageHide();
1801 SaveLastModalNode();
1802 return true;
1803 }
1804
RemoveAllModalInOverlay()1805 bool OverlayManager::RemoveAllModalInOverlay()
1806 {
1807 while (!modalStack_.empty()) {
1808 auto topModalNode = modalStack_.top().Upgrade();
1809 if (!topModalNode) {
1810 modalStack_.pop();
1811 continue;
1812 }
1813 auto rootNode = FindWindowScene(topModalNode);
1814 CHECK_NULL_RETURN(rootNode, true);
1815 auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1816 CHECK_NULL_RETURN(builder, false);
1817 ModalPageLostFocus(topModalNode);
1818 if (!ModalExitProcess(topModalNode)) {
1819 continue;
1820 }
1821 if (!modalStack_.empty()) {
1822 modalStack_.pop();
1823 }
1824 if (!modalList_.empty()) {
1825 modalList_.pop_back();
1826 }
1827
1828 if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1829 auto modalPattern = topModalNode->GetPattern<ModalPresentationPattern>();
1830 CHECK_NULL_RETURN(modalPattern, false);
1831 auto modalTransition = modalPattern->GetType();
1832 if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
1833 // Fire shown event of navdestination under the disappeared modal
1834 FireNavigationStateChange(true);
1835 }
1836 }
1837 auto sheetPattern = topModalNode->GetPattern<SheetPresentationPattern>();
1838 if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG && sheetPattern) {
1839 sheetMap_.erase(sheetPattern->GetTargetId());
1840 }
1841 FireModalPageHide();
1842 SaveLastModalNode();
1843 }
1844 return true;
1845 }
1846
ModalExitProcess(const RefPtr<FrameNode> & topModalNode)1847 bool OverlayManager::ModalExitProcess(const RefPtr<FrameNode>& topModalNode)
1848 {
1849 auto rootNode = FindWindowScene(topModalNode);
1850 CHECK_NULL_RETURN(rootNode, true);
1851 if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1852 return ModalPageExitProcess(topModalNode);
1853 }
1854 if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
1855 return SheetPageExitProcess(topModalNode);
1856 }
1857 return true;
1858 }
1859
ModalPageExitProcess(const RefPtr<FrameNode> & topModalNode)1860 bool OverlayManager::ModalPageExitProcess(const RefPtr<FrameNode>& topModalNode)
1861 {
1862 auto rootNode = FindWindowScene(topModalNode);
1863 CHECK_NULL_RETURN(rootNode, true);
1864 auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1865 CHECK_NULL_RETURN(builder, false);
1866 auto modalTransition = topModalNode->GetPattern<ModalPresentationPattern>()->GetType();
1867 if (builder->GetRenderContext()->HasDisappearTransition()) {
1868 if (!topModalNode->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
1869 topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
1870 // Fire hidden event of navdestination on the disappeared modal
1871 FireNavigationStateChange(false, topModalNode);
1872 }
1873 topModalNode->Clean(false, true);
1874 topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1875 }
1876 if (modalTransition == ModalTransition::DEFAULT) {
1877 PlayDefaultModalTransition(topModalNode, false);
1878 } else if (modalTransition == ModalTransition::ALPHA) {
1879 PlayAlphaModalTransition(topModalNode, false);
1880 } else if (!builder->GetRenderContext()->HasDisappearTransition()) {
1881 topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
1882 // Fire hidden event of navdestination on the disappeared modal
1883 FireNavigationStateChange(false, topModalNode);
1884 rootNode->RemoveChild(topModalNode);
1885 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1886 }
1887 topModalNode->GetPattern<ModalPresentationPattern>()->FireCallback("false");
1888 return true;
1889 }
1890
SheetPageExitProcess(const RefPtr<FrameNode> & topModalNode)1891 bool OverlayManager::SheetPageExitProcess(const RefPtr<FrameNode>& topModalNode)
1892 {
1893 auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetLastChild());
1894 CHECK_NULL_RETURN(builder, false);
1895 if (builder->GetRenderContext()->HasDisappearTransition()) {
1896 if (!topModalNode->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
1897 topModalNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
1898 }
1899 topModalNode->Clean(false, true);
1900 topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1901 }
1902 auto maskNode = GetSheetMask(topModalNode);
1903 if (maskNode) {
1904 PlaySheetMaskTransition(
1905 maskNode, false, topModalNode->GetPattern<SheetPresentationPattern>()->HasCallback());
1906 }
1907 auto sheetType = topModalNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
1908 if (sheetType == SheetType::SHEET_POPUP) {
1909 PlayBubbleStyleSheetTransition(topModalNode, false);
1910 } else {
1911 PlaySheetTransition(topModalNode, false);
1912 }
1913 topModalNode->GetPattern<SheetPresentationPattern>()->FireCallback("false");
1914 return true;
1915 }
1916
RemoveOverlayInSubwindow()1917 bool OverlayManager::RemoveOverlayInSubwindow()
1918 {
1919 auto rootNode = rootNodeWeak_.Upgrade();
1920 CHECK_NULL_RETURN(rootNode, false);
1921 if (rootNode->GetChildren().empty()) {
1922 return false;
1923 }
1924
1925 // remove the overlay node just mounted in subwindow
1926 auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
1927 CHECK_NULL_RETURN(overlay, false);
1928 // close dialog with animation
1929 auto pattern = overlay->GetPattern();
1930 if (InstanceOf<DialogPattern>(pattern)) {
1931 return RemoveDialog(overlay, false, false);
1932 }
1933 if (InstanceOf<BubblePattern>(pattern)) {
1934 auto popupPattern = DynamicCast<BubblePattern>(pattern);
1935 overlay->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1936 for (const auto& popup : popupMap_) {
1937 auto targetId = popup.first;
1938 auto popupInfo = popup.second;
1939 if (overlay == popupInfo.popupNode) {
1940 popupMap_.erase(targetId);
1941 rootNode->RemoveChild(overlay);
1942 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1943 if (rootNode->GetChildren().empty()) {
1944 auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(popupPattern->GetContainerId());
1945 CHECK_NULL_RETURN(subwindow, false);
1946 subwindow->HideSubWindowNG();
1947 }
1948 return true;
1949 }
1950 }
1951 return false;
1952 }
1953 if (InstanceOf<MenuWrapperPattern>(pattern)) {
1954 return RemoveMenu(overlay);
1955 }
1956 rootNode->RemoveChild(overlay);
1957 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1958 if (rootNode->GetChildren().empty()) {
1959 SubwindowManager::GetInstance()->HideSubWindowNG();
1960 }
1961 return true;
1962 }
1963
FocusOverlayNode(const RefPtr<FrameNode> & overlayNode,bool isInSubWindow)1964 void OverlayManager::FocusOverlayNode(const RefPtr<FrameNode>& overlayNode, bool isInSubWindow)
1965 {
1966 CHECK_NULL_VOID(overlayNode);
1967 auto focusHub = overlayNode->GetOrCreateFocusHub();
1968 CHECK_NULL_VOID(focusHub);
1969 focusHub->SetParentFocusable(true);
1970 focusHub->RequestFocusWithDefaultFocusFirstly();
1971 }
1972
BlurOverlayNode(const RefPtr<FrameNode> & currentOverlay,bool isInSubWindow)1973 void OverlayManager::BlurOverlayNode(const RefPtr<FrameNode>& currentOverlay, bool isInSubWindow)
1974 {
1975 auto currentFocusHub = currentOverlay->GetOrCreateFocusHub();
1976 CHECK_NULL_VOID(currentFocusHub);
1977 currentFocusHub->SetParentFocusable(false);
1978 currentFocusHub->LostFocus();
1979
1980 auto rootNode = rootNodeWeak_.Upgrade();
1981 CHECK_NULL_VOID(rootNode);
1982 if (rootNode->GetChildren().size() > 1) {
1983 auto collection = rootNode->GetChildren();
1984 for (auto iter = collection.rbegin(); iter != collection.rend(); ++iter) {
1985 auto overlay = DynamicCast<FrameNode>(*iter);
1986 CHECK_NULL_VOID(overlay);
1987 auto pattern = overlay->GetPattern();
1988 if (currentOverlay != overlay &&
1989 (InstanceOf<DialogPattern>(pattern) || InstanceOf<MenuWrapperPattern>(pattern) ||
1990 InstanceOf<SheetPresentationPattern>(pattern) || InstanceOf<ModalPresentationPattern>(pattern)) &&
1991 overlay->GetTag() != V2::SELECT_OVERLAY_ETS_TAG &&
1992 !overlay->IsRemoving()) {
1993 // Focus returns to the previous in the overlay
1994 FocusOverlayNode(overlay, isInSubWindow);
1995 return;
1996 }
1997 }
1998 }
1999 if (isInSubWindow) {
2000 // no need to set page request focus in sub window.
2001 return;
2002 }
2003
2004 auto pageNode = GetLastPage();
2005 CHECK_NULL_VOID(pageNode);
2006 auto pageFocusHub = pageNode->GetFocusHub();
2007 CHECK_NULL_VOID(pageFocusHub);
2008 pageFocusHub->SetParentFocusable(true);
2009 pageFocusHub->RequestFocus();
2010 }
2011
BlurLowerNode(const RefPtr<FrameNode> & currentOverlay)2012 void OverlayManager::BlurLowerNode(const RefPtr<FrameNode>& currentOverlay)
2013 {
2014 auto root = DynamicCast<FrameNode>(currentOverlay->GetParent());
2015 CHECK_NULL_VOID(root);
2016 auto children = root->GetChildren();
2017 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2018 auto node = DynamicCast<FrameNode>(*iter);
2019 CHECK_NULL_VOID(node);
2020 if (currentOverlay == node) {
2021 continue;
2022 }
2023 if (node->GetTag() == V2::STAGE_ETS_TAG) {
2024 auto pageNode = GetLastPage();
2025 CHECK_NULL_VOID(pageNode);
2026 auto pageFocusHub = pageNode->GetFocusHub();
2027 CHECK_NULL_VOID(pageFocusHub);
2028 pageFocusHub->SetParentFocusable(false);
2029 pageFocusHub->LostFocus();
2030 return;
2031 }
2032 auto focusHub = node->GetOrCreateFocusHub();
2033 if (focusHub->IsCurrentFocus()) {
2034 focusHub->SetParentFocusable(false);
2035 focusHub->LostFocus();
2036 return;
2037 }
2038 }
2039 }
2040
ResetLowerNodeFocusable(const RefPtr<FrameNode> & currentOverlay)2041 void OverlayManager::ResetLowerNodeFocusable(const RefPtr<FrameNode>& currentOverlay)
2042 {
2043 CHECK_NULL_VOID(currentOverlay);
2044 auto root = DynamicCast<FrameNode>(currentOverlay->GetParent());
2045 CHECK_NULL_VOID(root);
2046 auto children = root->GetChildren();
2047 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2048 auto node = DynamicCast<FrameNode>(*iter);
2049 CHECK_NULL_VOID(node);
2050 if (currentOverlay == node) {
2051 continue;
2052 }
2053 if (node->GetTag() == V2::STAGE_ETS_TAG) {
2054 auto parent = node->GetParent();
2055 if (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
2056 return;
2057 }
2058 auto pageNode = GetLastPage();
2059 CHECK_NULL_VOID(pageNode);
2060 auto pageFocusHub = pageNode->GetFocusHub();
2061 CHECK_NULL_VOID(pageFocusHub);
2062 pageFocusHub->SetParentFocusable(true);
2063 return;
2064 }
2065 if (node->GetTag() == V2::ATOMIC_SERVICE_ETS_TAG) {
2066 auto serviceFocusHub = node->GetFocusHub();
2067 CHECK_NULL_VOID(serviceFocusHub);
2068 serviceFocusHub->SetParentFocusable(true);
2069 return;
2070 }
2071 auto focusHub = node->GetOrCreateFocusHub();
2072 if (focusHub->IsCurrentFocus()) {
2073 focusHub->SetParentFocusable(true);
2074 return;
2075 }
2076 }
2077 }
2078
SaveLastModalNode()2079 void OverlayManager::SaveLastModalNode()
2080 {
2081 auto pipeline = PipelineContext::GetCurrentContext();
2082 CHECK_NULL_VOID(pipeline);
2083 auto stageManager = pipeline->GetStageManager();
2084 CHECK_NULL_VOID(stageManager);
2085 auto pageNode = stageManager->GetLastPage();
2086 CHECK_NULL_VOID(pageNode);
2087 if (modalStack_.empty()) {
2088 lastModalNode_ = WeakClaim(RawPtr(pageNode));
2089 } else {
2090 auto topModalNode = modalStack_.top().Upgrade();
2091 modalStack_.pop();
2092 if (modalStack_.empty()) {
2093 lastModalNode_ = WeakClaim(RawPtr(pageNode));
2094 } else {
2095 lastModalNode_ = modalStack_.top();
2096 }
2097 modalStack_.push(topModalNode);
2098 }
2099 }
2100
FireNavigationStateChange(bool show,const RefPtr<UINode> & node)2101 void OverlayManager::FireNavigationStateChange(bool show, const RefPtr<UINode>& node)
2102 {
2103 if (!show && node) {
2104 // Only check node When it is appointed
2105 NavigationPattern::FireNavigationStateChange(node, show);
2106 return;
2107 }
2108
2109 // Fire show event with non-empty stack. Only Check top modal node.
2110 RefPtr<FrameNode> topModalNode;
2111 if (!modalStack_.empty()) {
2112 topModalNode = GetModalNodeInStack(modalStack_);
2113 }
2114 if (show && topModalNode) {
2115 // Modal always displays on top of stage. If it existed, only need to check the top of modal stack.
2116 NavigationPattern::FireNavigationStateChange(topModalNode, show);
2117 return;
2118 }
2119
2120 auto lastPage = GetLastPage();
2121 NavigationPattern::FireNavigationStateChange(lastPage, show);
2122 }
2123
GetModalNodeInStack(std::stack<WeakPtr<FrameNode>> & stack)2124 RefPtr<FrameNode> OverlayManager::GetModalNodeInStack(std::stack<WeakPtr<FrameNode>>& stack)
2125 {
2126 if (stack.empty()) {
2127 return nullptr;
2128 }
2129 auto topModalNode = stack.top().Upgrade();
2130 if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
2131 return topModalNode;
2132 } else {
2133 stack.pop();
2134 auto modalNode = GetModalNodeInStack(stack);
2135 stack.push(topModalNode);
2136 return modalNode;
2137 }
2138 }
2139
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,const RefPtr<FrameNode> & targetNode,int32_t sessionId)2140 void OverlayManager::BindContentCover(bool isShow, std::function<void(const std::string&)>&& callback,
2141 std::function<RefPtr<UINode>()>&& buildNodeFunc, NG::ModalStyle& modalStyle, std::function<void()>&& onAppear,
2142 std::function<void()>&& onDisappear, const RefPtr<FrameNode>& targetNode, int32_t sessionId)
2143 {
2144 int32_t targetId = targetNode ? targetNode->GetId() : sessionId;
2145 auto rootNode = FindWindowScene(targetNode);
2146 CHECK_NULL_VOID(rootNode);
2147 auto modalTransition = modalStyle.modalTransition;
2148 if (!modalTransition.has_value()) {
2149 modalTransition = ModalTransition::DEFAULT;
2150 }
2151 if (isShow) {
2152 if (!modalStack_.empty()) {
2153 auto topModalNode = modalStack_.top().Upgrade();
2154 CHECK_NULL_VOID(topModalNode);
2155 if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
2156 if (topModalNode->GetPattern<ModalPresentationPattern>()->GetTargetId() == targetId) {
2157 if (modalStyle.backgroundColor.has_value()) {
2158 topModalNode->GetRenderContext()->UpdateBackgroundColor(modalStyle.backgroundColor.value());
2159 }
2160 topModalNode->GetPattern<ModalPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
2161 topModalNode->GetPattern<ModalPresentationPattern>()->SetType(modalTransition.value());
2162 return;
2163 }
2164 }
2165 }
2166 // builder content
2167 auto builder = AceType::DynamicCast<FrameNode>(buildNodeFunc());
2168 CHECK_NULL_VOID(builder);
2169 builder->GetRenderContext()->SetIsModalRootNode(true);
2170
2171 // create modal page
2172 auto modalNode = FrameNode::CreateFrameNode(V2::MODAL_PAGE_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
2173 AceType::MakeRefPtr<ModalPresentationPattern>(
2174 targetId, static_cast<ModalTransition>(modalTransition.value()), std::move(callback)));
2175 if (modalStyle.backgroundColor.has_value()) {
2176 modalNode->GetRenderContext()->UpdateBackgroundColor(modalStyle.backgroundColor.value());
2177 }
2178 auto modalPagePattern = modalNode->GetPattern<ModalPresentationPattern>();
2179 CHECK_NULL_VOID(modalPagePattern);
2180 modalPagePattern->UpdateOnDisappear(std::move(onDisappear));
2181 modalPagePattern->UpdateUIExtensionMode(modalStyle.isUIExtension);
2182 modalStack_.push(WeakClaim(RawPtr(modalNode)));
2183 modalList_.emplace_back(WeakClaim(RawPtr(modalNode)));
2184 SaveLastModalNode();
2185 modalNode->MountToParent(rootNode);
2186 modalNode->AddChild(builder);
2187 FireModalPageShow();
2188 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2189 if (onAppear != nullptr) {
2190 onAppear();
2191 }
2192 // Fire hidden event of navdestination under the appeared modal
2193 FireNavigationStateChange(false);
2194 if (modalTransition == ModalTransition::DEFAULT) {
2195 PlayDefaultModalTransition(modalNode, true);
2196 } else if (modalTransition == ModalTransition::ALPHA) {
2197 PlayAlphaModalTransition(modalNode, true);
2198 }
2199 return;
2200 }
2201
2202 // isShow = false, Pop ModalPage
2203 if (!modalStack_.empty()) {
2204 auto topModalNode = modalStack_.top().Upgrade();
2205 CHECK_NULL_VOID(topModalNode);
2206 if (topModalNode->GetTag() != V2::SHEET_PAGE_TAG && topModalNode->GetTag() != V2::MODAL_PAGE_TAG) {
2207 return;
2208 }
2209 if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG ||
2210 topModalNode->GetPattern<ModalPresentationPattern>()->GetTargetId() != targetId) {
2211 DeleteModal(targetId);
2212 return;
2213 }
2214 auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
2215 CHECK_NULL_VOID(builder);
2216 if (builder->GetRenderContext()->HasDisappearTransition()) {
2217 if (!topModalNode->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
2218 topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
2219 // Fire hidden event of navdestination on the disappeared modal
2220 FireNavigationStateChange(false, topModalNode);
2221 }
2222 topModalNode->Clean(false, true);
2223 topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2224 }
2225 auto modalPresentationPattern = topModalNode->GetPattern<ModalPresentationPattern>();
2226 CHECK_NULL_VOID(modalPresentationPattern);
2227 modalTransition = modalPresentationPattern->GetType();
2228 // lost focus
2229 ModalPageLostFocus(topModalNode);
2230 if (modalTransition == ModalTransition::DEFAULT) {
2231 PlayDefaultModalTransition(topModalNode, false);
2232 } else if (modalTransition == ModalTransition::ALPHA) {
2233 PlayAlphaModalTransition(topModalNode, false);
2234 } else if (!builder->GetRenderContext()->HasDisappearTransition()) {
2235 if (!modalPresentationPattern->IsExecuteOnDisappear()) {
2236 modalPresentationPattern->OnDisappear();
2237 // Fire hidden event of navdestination on the disappeared modal
2238 FireNavigationStateChange(false, topModalNode);
2239 }
2240 rootNode->RemoveChild(topModalNode);
2241 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2242 }
2243 modalStack_.pop();
2244 if (!modalList_.empty()) {
2245 modalList_.pop_back();
2246 }
2247 if (modalTransition == ModalTransition::NONE || builder->GetRenderContext()->HasDisappearTransition()) {
2248 // Fire shown event of navdestination under the disappeared modal
2249 FireNavigationStateChange(true);
2250 }
2251 FireModalPageHide();
2252 SaveLastModalNode();
2253 }
2254 }
2255
FireModalPageShow()2256 void OverlayManager::FireModalPageShow()
2257 {
2258 auto pipeline = PipelineContext::GetCurrentContext();
2259 CHECK_NULL_VOID(pipeline);
2260 auto pageNode = pipeline->GetStageManager()->GetLastPage();
2261 CHECK_NULL_VOID(pageNode);
2262 auto pageFocusHub = pageNode->GetFocusHub();
2263 CHECK_NULL_VOID(pageFocusHub);
2264 pageFocusHub->SetParentFocusable(false);
2265 pageFocusHub->LostFocus();
2266 for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
2267 auto modalNode = (*modal).Upgrade();
2268 CHECK_NULL_VOID(modalNode);
2269 auto modalFocusHub = modalNode->GetFocusHub();
2270 CHECK_NULL_VOID(modalFocusHub);
2271 modalFocusHub->SetParentFocusable(false);
2272 modalFocusHub->LostFocus();
2273 }
2274 if (modalList_.empty()) {
2275 return;
2276 }
2277 auto topModalNode = modalList_.back().Upgrade();
2278 CHECK_NULL_VOID(topModalNode);
2279 auto topModalFocusHub = topModalNode->GetFocusHub();
2280 CHECK_NULL_VOID(topModalFocusHub);
2281 topModalFocusHub->SetParentFocusable(true);
2282 topModalFocusHub->RequestFocusWithDefaultFocusFirstly();
2283 }
2284
ModalPageLostFocus(const RefPtr<FrameNode> & node)2285 void OverlayManager::ModalPageLostFocus(const RefPtr<FrameNode>& node)
2286 {
2287 auto modalFocusHub = node->GetFocusHub();
2288 CHECK_NULL_VOID(modalFocusHub);
2289 modalFocusHub->SetParentFocusable(false);
2290 modalFocusHub->LostFocus();
2291 }
2292
FireModalPageHide()2293 void OverlayManager::FireModalPageHide()
2294 {
2295 auto lastModalNode = lastModalNode_.Upgrade();
2296 CHECK_NULL_VOID(lastModalNode);
2297 auto lastModalFocusHub = lastModalNode->GetFocusHub();
2298 CHECK_NULL_VOID(lastModalFocusHub);
2299 lastModalFocusHub->SetParentFocusable(true);
2300 lastModalFocusHub->RequestFocus();
2301 }
2302
PlayDefaultModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)2303 void OverlayManager::PlayDefaultModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
2304 {
2305 // current modal animation
2306 AnimationOption option;
2307 const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 100.0f, 20.0f);
2308 option.SetCurve(curve);
2309 option.SetFillMode(FillMode::FORWARDS);
2310 auto context = modalNode->GetRenderContext();
2311 CHECK_NULL_VOID(context);
2312
2313 auto rootHeight = GetRootHeight();
2314 auto modalPositionY = modalNode->GetGeometryNode()->GetFrameRect().GetY();
2315 auto showHeight = rootHeight - modalPositionY;
2316
2317 if (isTransitionIn) {
2318 context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
2319 AnimationUtils::Animate(option, [context]() {
2320 if (context) {
2321 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
2322 }
2323 });
2324 } else {
2325 auto lastModalNode = lastModalNode_.Upgrade();
2326 CHECK_NULL_VOID(lastModalNode);
2327 auto lastModalContext = lastModalNode->GetRenderContext();
2328 CHECK_NULL_VOID(lastModalContext);
2329 lastModalContext->UpdateOpacity(1.0);
2330 option.SetOnFinishEvent(
2331 [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
2332 auto modal = modalWK.Upgrade();
2333 auto overlayManager = overlayWeak.Upgrade();
2334 CHECK_NULL_VOID(modal && overlayManager);
2335 auto root = overlayManager->FindWindowScene(modal);
2336 CHECK_NULL_VOID(root);
2337 if (!modal->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
2338 modal->GetPattern<ModalPresentationPattern>()->OnDisappear();
2339 // Fire hidden event of navdestination on the disappeared modal
2340 overlayManager->FireNavigationStateChange(false, modal);
2341 }
2342 root->RemoveChild(modal);
2343 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2344 // Fire shown event of navdestination under the disappeared modal
2345 overlayManager->FireNavigationStateChange(true);
2346 });
2347 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
2348 AnimationUtils::Animate(
2349 option,
2350 [context, showHeight]() {
2351 if (context) {
2352 context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
2353 }
2354 },
2355 option.GetOnFinishEvent());
2356 }
2357 }
2358
PlayAlphaModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)2359 void OverlayManager::PlayAlphaModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
2360 {
2361 AnimationOption option;
2362 option.SetCurve(Curves::FRICTION);
2363 option.SetDuration(FULL_MODAL_ALPHA_ANIMATION_DURATION);
2364 option.SetFillMode(FillMode::FORWARDS);
2365 auto lastModalNode = lastModalNode_.Upgrade();
2366 CHECK_NULL_VOID(lastModalNode);
2367 auto lastModalContext = lastModalNode->GetRenderContext();
2368 CHECK_NULL_VOID(lastModalContext);
2369 auto context = modalNode->GetRenderContext();
2370 CHECK_NULL_VOID(context);
2371 if (isTransitionIn) {
2372 // last page animation
2373 lastModalContext->OpacityAnimation(option, 1, 0);
2374 lastModalContext->UpdateOpacity(0);
2375
2376 // current modal page animation
2377 context->OpacityAnimation(option, 0, 1);
2378 } else {
2379 // last page animation
2380 lastModalContext->OpacityAnimation(option, 0, 1);
2381
2382 // current modal page animation
2383 option.SetOnFinishEvent(
2384 [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), overlayWeak = WeakClaim(this)] {
2385 auto modal = modalWK.Upgrade();
2386 auto overlayManager = overlayWeak.Upgrade();
2387 CHECK_NULL_VOID(modal && overlayManager);
2388 auto root = overlayManager->FindWindowScene(modal);
2389 CHECK_NULL_VOID(root);
2390 if (!modal->GetPattern<ModalPresentationPattern>()->IsExecuteOnDisappear()) {
2391 modal->GetPattern<ModalPresentationPattern>()->OnDisappear();
2392 // Fire hidden event of navdestination on the disappeared modal
2393 overlayManager->FireNavigationStateChange(false, modal);
2394 }
2395 root->RemoveChild(modal);
2396 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2397 // Fire shown event of navdestination under the disappeared modal
2398 overlayManager->FireNavigationStateChange(true);
2399 });
2400 context->OpacityAnimation(option, 1, 0);
2401 }
2402 }
2403
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,const RefPtr<FrameNode> & targetNode)2404 void OverlayManager::BindSheet(bool isShow, std::function<void(const std::string&)>&& callback,
2405 std::function<RefPtr<UINode>()>&& buildNodeFunc, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
2406 NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
2407 std::function<void()>&& shouldDismiss, const RefPtr<FrameNode>& targetNode)
2408 {
2409 auto pipeline = PipelineContext::GetCurrentContext();
2410 CHECK_NULL_VOID(pipeline);
2411 auto bindSheetTask = [weak = AceType::WeakClaim(this), isShow, callback = std::move(callback),
2412 buildNodeFunc = std::move(buildNodeFunc),
2413 buildtitleNodeFunc = std::move(buildtitleNodeFunc), sheetStyle,
2414 onAppear = std::move(onAppear), onDisappear = std::move(onDisappear),
2415 shouldDismiss = std::move(shouldDismiss), targetNode]() mutable {
2416 auto overlay = weak.Upgrade();
2417 CHECK_NULL_VOID(overlay);
2418 overlay->OnBindSheet(isShow, std::move(callback), std::move(buildNodeFunc), std::move(buildtitleNodeFunc),
2419 sheetStyle, std::move(onAppear), std::move(onDisappear), std::move(shouldDismiss), targetNode);
2420 auto pipeline = PipelineContext::GetCurrentContext();
2421 CHECK_NULL_VOID(pipeline);
2422 pipeline->FlushUITasks();
2423 };
2424 pipeline->AddAnimationClosure(bindSheetTask);
2425 }
2426
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,const RefPtr<FrameNode> & targetNode)2427 void OverlayManager::OnBindSheet(bool isShow, std::function<void(const std::string&)>&& callback,
2428 std::function<RefPtr<UINode>()>&& buildNodeFunc, std::function<RefPtr<UINode>()>&& buildtitleNodeFunc,
2429 NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
2430 std::function<void()>&& shouldDismiss, const RefPtr<FrameNode>& targetNode)
2431 {
2432 int32_t targetId = targetNode->GetId();
2433 auto rootNode = FindWindowScene(targetNode);
2434 CHECK_NULL_VOID(rootNode);
2435 auto pipeline = PipelineContext::GetCurrentContext();
2436 CHECK_NULL_VOID(pipeline);
2437 auto sheetTheme = pipeline->GetTheme<SheetTheme>();
2438 CHECK_NULL_VOID(sheetTheme);
2439 if (!isShow) {
2440 CloseSheet(targetId);
2441 return;
2442 }
2443 if (sheetMap_.count(targetId)) {
2444 auto topModalNode = sheetMap_[targetId].Upgrade();
2445 CHECK_NULL_VOID(topModalNode);
2446 if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG &&
2447 topModalNode->GetPattern<SheetPresentationPattern>()->GetTargetId() == targetId) {
2448 if (sheetStyle.backgroundColor.has_value()) {
2449 topModalNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value());
2450 }
2451 if (sheetStyle.backgroundBlurStyle.has_value()) {
2452 SetSheetBackgroundBlurStyle(topModalNode, sheetStyle.backgroundBlurStyle.value());
2453 }
2454 auto maskNode = GetSheetMask(topModalNode);
2455 if (maskNode) {
2456 auto maskRenderContext = maskNode->GetRenderContext();
2457 CHECK_NULL_VOID(maskRenderContext);
2458 maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor()));
2459 }
2460 topModalNode->GetPattern<SheetPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
2461 topModalNode->GetPattern<SheetPresentationPattern>()->UpdateShouldDismiss(std::move(shouldDismiss));
2462 auto layoutProperty = topModalNode->GetLayoutProperty<SheetPresentationProperty>();
2463 layoutProperty->UpdateSheetStyle(sheetStyle);
2464 topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2465 pipeline->FlushUITasks();
2466 ComputeSheetOffset(sheetStyle, topModalNode);
2467 auto sheetType = topModalNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
2468 if (sheetType != SheetType::SHEET_POPUP) {
2469 PlaySheetTransition(topModalNode, true, false, false);
2470 }
2471 return;
2472 }
2473 }
2474 // builder content
2475 auto builder = AceType::DynamicCast<FrameNode>(buildNodeFunc());
2476 CHECK_NULL_VOID(builder);
2477 builder->GetRenderContext()->SetIsModalRootNode(true);
2478
2479 auto titlebuilder = AceType::DynamicCast<FrameNode>(buildtitleNodeFunc());
2480 if (titlebuilder) {
2481 titlebuilder->GetRenderContext()->SetIsModalRootNode(true);
2482 }
2483 // create modal page
2484 auto sheetNode = SheetView::CreateSheetPage(
2485 targetId, targetNode->GetTag(), builder, titlebuilder, std::move(callback), sheetStyle);
2486 CHECK_NULL_VOID(sheetNode);
2487 if (sheetStyle.backgroundColor.has_value()) {
2488 sheetNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value());
2489 }
2490 if (sheetStyle.backgroundBlurStyle.has_value()) {
2491 SetSheetBackgroundBlurStyle(sheetNode, sheetStyle.backgroundBlurStyle.value());
2492 }
2493 sheetNode->GetPattern<SheetPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
2494 sheetNode->GetPattern<SheetPresentationPattern>()->UpdateShouldDismiss(std::move(shouldDismiss));
2495 sheetMap_[targetId] = WeakClaim(RawPtr(sheetNode));
2496 modalStack_.push(WeakClaim(RawPtr(sheetNode)));
2497 SaveLastModalNode();
2498 // create maskColor node
2499 auto sheetType = sheetNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
2500 auto maskNode = FrameNode::CreateFrameNode(
2501 V2::SHEET_MASK_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>());
2502 CHECK_NULL_VOID(maskNode);
2503 auto maskLayoutProps = maskNode->GetLayoutProperty();
2504 CHECK_NULL_VOID(maskLayoutProps);
2505 maskLayoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT);
2506 auto maskRenderContext = maskNode->GetRenderContext();
2507 CHECK_NULL_VOID(maskRenderContext);
2508 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2509 if (sheetStyle.maskColor.has_value()) {
2510 maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value());
2511 } else {
2512 maskLayoutProps->UpdateVisibility(VisibleType::INVISIBLE);
2513 }
2514 } else {
2515 maskRenderContext->UpdateBackgroundColor(sheetStyle.maskColor.value_or(sheetTheme->GetMaskColor()));
2516 auto eventConfirmHub = maskNode->GetOrCreateGestureEventHub();
2517 CHECK_NULL_VOID(eventConfirmHub);
2518 sheetMaskClickEvent_ = AceType::MakeRefPtr<NG::ClickEvent>(
2519 [weak = AceType::WeakClaim(AceType::RawPtr(sheetNode))](const GestureEvent& /* info */) {
2520 auto sheet = weak.Upgrade();
2521 CHECK_NULL_VOID(sheet);
2522 auto sheetPattern = sheet->GetPattern<SheetPresentationPattern>();
2523 CHECK_NULL_VOID(sheetPattern);
2524 sheetPattern->SheetInteractiveDismiss(false);
2525 });
2526 eventConfirmHub->AddClickEvent(sheetMaskClickEvent_);
2527 }
2528 maskNode->MountToParent(rootNode);
2529 PlaySheetMaskTransition(maskNode, true, static_cast<bool>(callback));
2530 auto columnNode = FrameNode::CreateFrameNode(V2::SHEET_WRAPPER_TAG,
2531 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
2532 CHECK_NULL_VOID(columnNode);
2533 auto columnLayoutProps = columnNode->GetLayoutProperty();
2534 CHECK_NULL_VOID(columnLayoutProps);
2535 columnLayoutProps->UpdateMeasureType(MeasureType::MATCH_PARENT);
2536 columnLayoutProps->UpdateAlignment(Alignment::TOP_LEFT);
2537 sheetNode->MountToParent(columnNode);
2538 columnNode->MountToParent(rootNode);
2539 modalList_.emplace_back(WeakClaim(RawPtr(sheetNode)));
2540 FireModalPageShow();
2541 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2542 pipeline->FlushUITasks();
2543 ComputeSheetOffset(sheetStyle, sheetNode);
2544 if (onAppear != nullptr) {
2545 onAppear();
2546 }
2547
2548 // start transition animation
2549 if (sheetType == SheetType::SHEET_POPUP) {
2550 PlayBubbleStyleSheetTransition(sheetNode, true);
2551 } else {
2552 PlaySheetTransition(sheetNode, true);
2553 }
2554 }
2555
CloseSheet(int32_t targetId)2556 void OverlayManager::CloseSheet(int32_t targetId)
2557 {
2558 if (modalStack_.empty()) {
2559 return;
2560 }
2561 if (sheetMap_.empty() || !sheetMap_.count(targetId)) {
2562 DeleteModal(targetId);
2563 return;
2564 }
2565 auto sheetNode = sheetMap_[targetId].Upgrade();
2566 CHECK_NULL_VOID(sheetNode);
2567 sheetNode->GetPattern<SheetPresentationPattern>()->SetShowState(false);
2568 auto scrollNode = AceType::DynamicCast<FrameNode>(sheetNode->GetChildAtIndex(1));
2569 CHECK_NULL_VOID(scrollNode);
2570 auto builder = AceType::DynamicCast<FrameNode>(scrollNode->GetChildAtIndex(0));
2571 CHECK_NULL_VOID(builder);
2572 if (builder->GetRenderContext()->HasDisappearTransition()) {
2573 if (!sheetNode->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
2574 sheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2575 }
2576 sheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2577 sheetNode->Clean(false, true);
2578 sheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2579 }
2580 ModalPageLostFocus(sheetNode);
2581 auto maskNode = GetSheetMask(sheetNode);
2582 if (maskNode) {
2583 PlaySheetMaskTransition(maskNode, false, sheetNode->GetPattern<SheetPresentationPattern>()->HasCallback());
2584 }
2585 auto sheetType = sheetNode->GetPattern<SheetPresentationPattern>()->GetSheetType();
2586 if (sheetType == SheetType::SHEET_POPUP) {
2587 PlayBubbleStyleSheetTransition(sheetNode, false);
2588 } else {
2589 PlaySheetTransition(sheetNode, false);
2590 }
2591 sheetMap_.erase(targetId);
2592 RemoveSheetNode(sheetNode);
2593 FireModalPageHide();
2594 SaveLastModalNode();
2595 }
2596
DismissSheet()2597 void OverlayManager::DismissSheet()
2598 {
2599 if (modalStack_.empty()) {
2600 return;
2601 }
2602 if (sheetMap_.empty() || !sheetMap_.count(dismissTargetId_)) {
2603 DeleteModal(dismissTargetId_);
2604 return;
2605 }
2606 auto sheetNode = sheetMap_[dismissTargetId_].Upgrade();
2607 CHECK_NULL_VOID(sheetNode);
2608 if (sheetNode->GetTag() == V2::SHEET_PAGE_TAG) {
2609 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2610 CHECK_NULL_VOID(sheetPattern);
2611 sheetPattern->DismissSheet();
2612 }
2613 }
2614
RemoveSheetNode(const RefPtr<FrameNode> & sheetNode)2615 void OverlayManager::RemoveSheetNode(const RefPtr<FrameNode>& sheetNode)
2616 {
2617 CHECK_NULL_VOID(sheetNode);
2618 if (!modalList_.empty()) {
2619 modalList_.remove(WeakClaim(RawPtr(sheetNode)));
2620 }
2621 std::vector<WeakPtr<FrameNode>> sheetVector;
2622 while (!modalStack_.empty()) {
2623 if (modalStack_.top() != WeakClaim(RawPtr(sheetNode))) {
2624 sheetVector.push_back(modalStack_.top());
2625 }
2626 modalStack_.pop();
2627 }
2628 for (auto iter : sheetVector) {
2629 modalStack_.push(iter);
2630 }
2631 }
2632
PlaySheetTransition(RefPtr<FrameNode> sheetNode,bool isTransitionIn,bool isFirstTransition,bool isModeChangeToAuto)2633 void OverlayManager::PlaySheetTransition(
2634 RefPtr<FrameNode> sheetNode, bool isTransitionIn, bool isFirstTransition, bool isModeChangeToAuto)
2635 {
2636 // current sheet animation
2637 AnimationOption option;
2638 const RefPtr<InterpolatingSpring> curve =
2639 AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
2640 option.SetCurve(curve);
2641 option.SetFillMode(FillMode::FORWARDS);
2642 auto context = sheetNode->GetRenderContext();
2643 CHECK_NULL_VOID(context);
2644 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2645 CHECK_NULL_VOID(sheetPattern);
2646 auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2647 auto sheetParent = DynamicCast<FrameNode>(sheetNode->GetParent());
2648 CHECK_NULL_VOID(sheetParent);
2649 if (isTransitionIn) {
2650 sheetPattern->SetCurrentHeight(sheetHeight_);
2651 float offset = 0.0f;
2652 if (sheetPattern->GetSheetType() == SheetType::SHEET_POPUP) {
2653 offset = sheetPattern->GetSheetOffset();
2654 } else {
2655 offset = sheetMaxHeight - sheetHeight_;
2656 }
2657 if (isFirstTransition) {
2658 context->OnTransformTranslateUpdate({ 0.0f, sheetMaxHeight, 0.0f });
2659 if (NearZero(sheetHeight_)) {
2660 return;
2661 }
2662 }
2663 if (isModeChangeToAuto) {
2664 option.SetDuration(0);
2665 option.SetCurve(Curves::LINEAR);
2666 }
2667 sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMDEFAULT);
2668 AnimationUtils::Animate(
2669 option,
2670 [context, offset]() {
2671 if (context) {
2672 context->OnTransformTranslateUpdate({ 0.0f, offset, 0.0f });
2673 }
2674 });
2675 } else {
2676 option.SetOnFinishEvent(
2677 [rootWeak = rootNodeWeak_, sheetWK = WeakClaim(RawPtr(sheetNode)),
2678 weakOverlayManager = WeakClaim(this)] {
2679 auto sheet = sheetWK.Upgrade();
2680 auto overlayManager = weakOverlayManager.Upgrade();
2681 CHECK_NULL_VOID(sheet && overlayManager);
2682 if (!sheet->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
2683 sheet->GetPattern<SheetPresentationPattern>()->OnDisappear();
2684 }
2685 auto root = overlayManager->FindWindowScene(sheet);
2686 CHECK_NULL_VOID(root);
2687 auto sheetParent = DynamicCast<FrameNode>(sheet->GetParent());
2688 CHECK_NULL_VOID(sheetParent);
2689 root->RemoveChild(sheetParent);
2690 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2691 });
2692 if (sheetPattern->HasCallback()) {
2693 sheetParent->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
2694 HitTestMode::HTMTRANSPARENT);
2695 }
2696 AnimationUtils::Animate(
2697 option,
2698 [context, sheetMaxHeight]() {
2699 if (context) {
2700 context->OnTransformTranslateUpdate({ 0.0f, sheetMaxHeight, 0.0f });
2701 }
2702 },
2703 option.GetOnFinishEvent());
2704 }
2705 }
2706
PlayBubbleStyleSheetTransition(RefPtr<FrameNode> sheetNode,bool isTransitionIn)2707 void OverlayManager::PlayBubbleStyleSheetTransition(RefPtr<FrameNode> sheetNode, bool isTransitionIn)
2708 {
2709 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2710 CHECK_NULL_VOID(sheetPattern);
2711 if (isTransitionIn) {
2712 sheetPattern->ResetToInvisible();
2713 sheetPattern->SetCurrentHeight(sheetHeight_);
2714 sheetPattern->StartOffsetEnteringAnimation();
2715 sheetPattern->StartAlphaEnteringAnimation([sheetWK = WeakClaim(RawPtr(sheetNode))] {
2716 auto sheet = sheetWK.Upgrade();
2717 CHECK_NULL_VOID(sheet);
2718 auto sheetPattern = sheet->GetPattern<SheetPresentationPattern>();
2719 CHECK_NULL_VOID(sheetPattern);
2720 sheetPattern->ProcessColumnRect();
2721 });
2722 } else {
2723 sheetPattern->StartOffsetExitingAnimation();
2724 sheetPattern->StartAlphaExitingAnimation(
2725 [rootWeak = rootNodeWeak_, sheetWK = WeakClaim(RawPtr(sheetNode)), id = Container::CurrentId(),
2726 weakOverlayManager = WeakClaim(this)] {
2727 ContainerScope scope(id);
2728 auto context = PipelineContext::GetCurrentContext();
2729 CHECK_NULL_VOID(context);
2730 auto taskExecutor = context->GetTaskExecutor();
2731 CHECK_NULL_VOID(taskExecutor);
2732 // animation finish event should be posted to UI thread.
2733 taskExecutor->PostTask(
2734 [rootWeak, sheetWK, id, weakOverlayManager]() {
2735 auto sheet = sheetWK.Upgrade();
2736 auto overlayManager = weakOverlayManager.Upgrade();
2737 CHECK_NULL_VOID(sheet && overlayManager);
2738
2739 ContainerScope scope(id);
2740 if (!sheet->GetPattern<SheetPresentationPattern>()->IsExecuteOnDisappear()) {
2741 sheet->GetPattern<SheetPresentationPattern>()->OnDisappear();
2742 }
2743 auto root = overlayManager->FindWindowScene(sheet);
2744 CHECK_NULL_VOID(root);
2745 auto sheetParent = DynamicCast<FrameNode>(sheet->GetParent());
2746 CHECK_NULL_VOID(sheetParent);
2747 root->RemoveChild(sheetParent);
2748 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2749 },
2750 TaskExecutor::TaskType::UI);
2751 });
2752 }
2753 }
2754
PlaySheetMaskTransition(RefPtr<FrameNode> maskNode,bool isTransitionIn,bool needTransparent)2755 void OverlayManager::PlaySheetMaskTransition(RefPtr<FrameNode> maskNode, bool isTransitionIn, bool needTransparent)
2756 {
2757 AnimationOption option;
2758 const RefPtr<InterpolatingSpring> curve =
2759 AceType::MakeRefPtr<InterpolatingSpring>(0.0f, CURVE_MASS, CURVE_STIFFNESS, CURVE_DAMPING);
2760 option.SetCurve(curve);
2761 option.SetFillMode(FillMode::FORWARDS);
2762 auto context = maskNode->GetRenderContext();
2763 CHECK_NULL_VOID(context);
2764 if (isTransitionIn) {
2765 maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMDEFAULT);
2766 context->OpacityAnimation(option, 0.0, 1.0);
2767 } else {
2768 if (sheetMaskClickEvent_) {
2769 auto eventConfirmHub = maskNode->GetOrCreateGestureEventHub();
2770 CHECK_NULL_VOID(eventConfirmHub);
2771 eventConfirmHub->RemoveClickEvent(sheetMaskClickEvent_);
2772 }
2773 option.SetOnFinishEvent(
2774 [rootWeak = rootNodeWeak_, maskNodeWK = WeakClaim(RawPtr(maskNode)),
2775 weakOverlayManager = WeakClaim(this)] {
2776 auto mask = maskNodeWK.Upgrade();
2777 auto overlayManager = weakOverlayManager.Upgrade();
2778 CHECK_NULL_VOID(mask && overlayManager);
2779
2780 auto root = overlayManager->FindWindowScene(mask);
2781 CHECK_NULL_VOID(root);
2782 root->RemoveChild(mask);
2783 });
2784 if (needTransparent) {
2785 maskNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(
2786 HitTestMode::HTMTRANSPARENT);
2787 }
2788 context->OpacityAnimation(option, 1.0, 0.0);
2789 }
2790 }
2791
SetSheetBackgroundBlurStyle(const RefPtr<FrameNode> & sheetNode,const BlurStyleOption & bgBlurStyle)2792 void OverlayManager::SetSheetBackgroundBlurStyle(const RefPtr<FrameNode>& sheetNode, const BlurStyleOption& bgBlurStyle)
2793 {
2794 auto renderContext = sheetNode->GetRenderContext();
2795 CHECK_NULL_VOID(renderContext);
2796
2797 if (renderContext->GetBackgroundEffect().has_value()) {
2798 renderContext->UpdateBackgroundEffect(std::nullopt);
2799 }
2800 renderContext->UpdateBackBlurStyle(bgBlurStyle);
2801 if (renderContext->GetBackBlurRadius().has_value()) {
2802 renderContext->UpdateBackBlurRadius(Dimension());
2803 }
2804 }
2805
ComputeSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)2806 void OverlayManager::ComputeSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
2807 {
2808 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2809 CHECK_NULL_VOID(sheetPattern);
2810 auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2811 auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
2812 auto geometryNode = sheetNode->GetGeometryNode();
2813 CHECK_NULL_VOID(geometryNode);
2814 auto sheetHeight = geometryNode->GetFrameSize().Height();
2815
2816 auto sheetType = sheetPattern->GetSheetType();
2817 switch (sheetType) {
2818 case SheetType::SHEET_BOTTOM:
2819 case SheetType::SHEET_BOTTOM_FREE_WINDOW:
2820 if (sheetStyle.detents.size() > 0) {
2821 ComputeDetentsSheetOffset(sheetStyle, sheetNode);
2822 } else {
2823 ComputeSingleGearSheetOffset(sheetStyle, sheetNode);
2824 }
2825 break;
2826 case SheetType::SHEET_BOTTOMLANDSPACE:
2827 sheetHeight_ = largeHeight;
2828 break;
2829 case SheetType::SHEET_CENTER:
2830 sheetHeight_ = (sheetHeight + sheetMaxHeight) / SHEET_HALF_SIZE;
2831 break;
2832 case SheetType::SHEET_POPUP:
2833 sheetHeight_ = sheetMaxHeight;
2834 break;
2835 default:
2836 break;
2837 }
2838 }
2839
ComputeSingleGearSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)2840 void OverlayManager::ComputeSingleGearSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
2841 {
2842 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2843 CHECK_NULL_VOID(sheetPattern);
2844 auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2845 auto context = PipelineContext::GetCurrentContext();
2846 CHECK_NULL_VOID(context);
2847 auto manager = context->GetSafeAreaManager();
2848 CHECK_NULL_VOID(manager);
2849 auto statusBarHeight = manager->GetSystemSafeArea().top_.Length();
2850 auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - statusBarHeight;
2851 if (sheetStyle.sheetMode.has_value()) {
2852 if (sheetStyle.sheetMode == SheetMode::MEDIUM) {
2853 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE;
2854 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2855 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE_PRE;
2856 }
2857 } else if (sheetStyle.sheetMode == SheetMode::LARGE) {
2858 sheetHeight_ = largeHeight;
2859 } else if (sheetStyle.sheetMode == SheetMode::AUTO) {
2860 sheetHeight_ = sheetPattern->GetFitContentHeight();
2861 if (GreatNotEqual(sheetHeight_, largeHeight)) {
2862 sheetHeight_ = largeHeight;
2863 }
2864 }
2865 } else {
2866 float height = 0.0f;
2867 if (sheetStyle.height->Unit() == DimensionUnit::PERCENT) {
2868 height = sheetStyle.height->ConvertToPxWithSize(sheetMaxHeight - statusBarHeight);
2869 } else {
2870 height = sheetStyle.height->ConvertToPx();
2871 }
2872 if (height > largeHeight) {
2873 sheetHeight_ = largeHeight;
2874 } else if (height < 0) {
2875 sheetHeight_ = largeHeight;
2876 } else {
2877 sheetHeight_ = height;
2878 }
2879 }
2880 }
2881
ComputeDetentsSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)2882 void OverlayManager::ComputeDetentsSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
2883 {
2884 auto sheetPattern = sheetNode->GetPattern<SheetPresentationPattern>();
2885 CHECK_NULL_VOID(sheetPattern);
2886 auto sheetMaxHeight = sheetPattern->GetSheetMaxHeight();
2887 auto context = PipelineContext::GetCurrentContext();
2888 CHECK_NULL_VOID(context);
2889 auto manager = context->GetSafeAreaManager();
2890 CHECK_NULL_VOID(manager);
2891 auto statusBarHeight = manager->GetSystemSafeArea().top_.Length();
2892 auto largeHeight = sheetMaxHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx() - statusBarHeight;
2893 auto selection = sheetStyle.detents[0];
2894 if (selection.sheetMode.has_value()) {
2895 if (selection.sheetMode == SheetMode::MEDIUM) {
2896 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE;
2897 if (!Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2898 sheetHeight_ = sheetMaxHeight * MEDIUM_SIZE_PRE;
2899 }
2900 } else if (selection.sheetMode == SheetMode::LARGE) {
2901 sheetHeight_ = largeHeight;
2902 } else if (selection.sheetMode == SheetMode::AUTO) {
2903 sheetHeight_ = sheetPattern->GetFitContentHeight();
2904 if (GreatNotEqual(sheetHeight_, largeHeight)) {
2905 sheetHeight_ = largeHeight;
2906 }
2907 }
2908 } else {
2909 float height = 0.0f;
2910 if (selection.height->Unit() == DimensionUnit::PERCENT) {
2911 height = selection.height->ConvertToPxWithSize(sheetMaxHeight - statusBarHeight);
2912 } else {
2913 height = selection.height->ConvertToPx();
2914 }
2915 if (height > largeHeight) {
2916 sheetHeight_ = largeHeight;
2917 } else if (height < 0) {
2918 sheetHeight_ = largeHeight;
2919 } else {
2920 sheetHeight_ = height;
2921 }
2922 }
2923
2924 }
2925
DestroySheet(const RefPtr<FrameNode> & sheetNode,int32_t targetId)2926 void OverlayManager::DestroySheet(const RefPtr<FrameNode>& sheetNode, int32_t targetId)
2927 {
2928 if (modalStack_.empty()) {
2929 return;
2930 }
2931 if (sheetMap_.empty() || !sheetMap_.count(targetId)) {
2932 DeleteModal(targetId);
2933 return;
2934 }
2935 auto mapSheetNode = sheetMap_[targetId].Upgrade();
2936 CHECK_NULL_VOID(mapSheetNode);
2937 if (mapSheetNode->GetTag() != V2::SHEET_PAGE_TAG) {
2938 return;
2939 }
2940 if (mapSheetNode->GetPattern<SheetPresentationPattern>()->GetTargetId() != targetId) {
2941 return;
2942 }
2943 auto rootNode = FindWindowScene(sheetNode);
2944 CHECK_NULL_VOID(rootNode);
2945 auto root = DynamicCast<FrameNode>(rootNode);
2946 ModalPageLostFocus(mapSheetNode);
2947 auto maskNode = GetSheetMask(sheetNode);
2948 if (maskNode) {
2949 root->RemoveChild(maskNode);
2950 }
2951 sheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2952 auto sheetParent = DynamicCast<FrameNode>(sheetNode->GetParent());
2953 CHECK_NULL_VOID(sheetParent);
2954 root->RemoveChild(sheetParent);
2955 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2956 sheetMap_.erase(targetId);
2957 RemoveSheetNode(sheetNode);
2958 FireModalPageHide();
2959 SaveLastModalNode();
2960 }
2961
DeleteModal(int32_t targetId)2962 void OverlayManager::DeleteModal(int32_t targetId)
2963 {
2964 bool isDelete = false;
2965 bool isModal = true;
2966 for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
2967 auto modalNode = (*modal).Upgrade();
2968 if (!modalNode) {
2969 continue;
2970 }
2971 int32_t currentTargetId = -1;
2972 if (modalNode->GetTag() == V2::MODAL_PAGE_TAG) {
2973 isModal = true;
2974 currentTargetId = modalNode->GetPattern<ModalPresentationPattern>()->GetTargetId();
2975 } else if (modalNode->GetTag() == V2::SHEET_PAGE_TAG) {
2976 isModal = false;
2977 currentTargetId = modalNode->GetPattern<SheetPresentationPattern>()->GetTargetId();
2978 } else {
2979 return;
2980 }
2981 if (currentTargetId == targetId) {
2982 isDelete = true;
2983 modalList_.erase(modal);
2984 auto rootNode = FindWindowScene(modalNode);
2985 CHECK_NULL_VOID(rootNode);
2986 if (isModal) {
2987 modalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
2988 modalNode->GetPattern<ModalPresentationPattern>()->FireCallback("false");
2989 // Fire hidden event of navdestination on the disappeared modal
2990 FireNavigationStateChange(false, modalNode);
2991 rootNode->RemoveChild(modalNode);
2992 } else {
2993 RemoveSheetMask(modalNode, rootNode);
2994 modalNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
2995 modalNode->GetPattern<SheetPresentationPattern>()->FireCallback("false");
2996 sheetMap_.erase(targetId);
2997 auto sheetParent = DynamicCast<FrameNode>(modalNode->GetParent());
2998 CHECK_NULL_VOID(sheetParent);
2999 rootNode->RemoveChild(sheetParent);
3000 }
3001 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3002 break;
3003 }
3004 }
3005 if (isDelete) {
3006 while (!modalStack_.empty()) {
3007 modalStack_.pop();
3008 }
3009 for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
3010 modalStack_.push(*modal);
3011 }
3012 SaveLastModalNode();
3013 }
3014 }
3015
RemoveSheetMask(RefPtr<FrameNode> & sheetNode,RefPtr<UINode> & rootNode)3016 void OverlayManager::RemoveSheetMask(RefPtr<FrameNode>& sheetNode, RefPtr<UINode>& rootNode)
3017 {
3018 auto maskNode = GetSheetMask(sheetNode);
3019 if (maskNode) {
3020 rootNode->RemoveChild(maskNode);
3021 }
3022 }
3023
GetSheetMask(const RefPtr<FrameNode> & sheetNode)3024 RefPtr<FrameNode> OverlayManager::GetSheetMask(const RefPtr<FrameNode>& sheetNode)
3025 {
3026 // get bindsheet masknode
3027 CHECK_NULL_RETURN(sheetNode, NULL);
3028 auto sheetParent = sheetNode->GetParent();
3029 CHECK_NULL_RETURN(sheetParent, NULL);
3030 auto rootNode = sheetParent->GetParent();
3031 CHECK_NULL_RETURN(rootNode, NULL);
3032 auto sheetChildIter = std::find(rootNode->GetChildren().begin(), rootNode->GetChildren().end(), sheetParent);
3033 if (sheetChildIter == rootNode->GetChildren().end()) {
3034 return NULL;
3035 }
3036 --sheetChildIter;
3037 CHECK_NULL_RETURN((*sheetChildIter), NULL);
3038 auto sheetChildFrameNode = DynamicCast<FrameNode>(*sheetChildIter);
3039 if (sheetChildFrameNode && sheetChildFrameNode->GetTag() != V2::SHEET_MASK_TAG) {
3040 return NULL;
3041 }
3042 return sheetChildFrameNode;
3043 }
3044
PlayKeyboardTransition(RefPtr<FrameNode> customKeyboard,bool isTransitionIn)3045 void OverlayManager::PlayKeyboardTransition(RefPtr<FrameNode> customKeyboard, bool isTransitionIn)
3046 {
3047 CHECK_NULL_VOID(customKeyboard);
3048 AnimationOption option;
3049 if (isTransitionIn) {
3050 option.SetCurve(SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE);
3051 } else {
3052 option.SetCurve(HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE);
3053 }
3054 option.SetFillMode(FillMode::FORWARDS);
3055 auto context = customKeyboard->GetRenderContext();
3056 CHECK_NULL_VOID(context);
3057 auto pipeline = PipelineContext::GetMainPipelineContext();
3058 CHECK_NULL_VOID(pipeline);
3059 auto pageNode = pipeline->GetStageManager()->GetLastPage();
3060 if (pageNode == nullptr) {
3061 auto parent = customKeyboard->GetParent();
3062 CHECK_NULL_VOID(parent);
3063 parent->RemoveChild(customKeyboard);
3064 return;
3065 }
3066 auto pageHeight = pageNode->GetGeometryNode()->GetFrameSize().Height();
3067 if (isTransitionIn) {
3068 context->OnTransformTranslateUpdate({ 0.0f, pageHeight, 0.0f });
3069 AnimationUtils::Animate(option, [context]() {
3070 if (context) {
3071 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
3072 }
3073 });
3074 } else {
3075 context->UpdateOpacity(1.0);
3076 option.SetOnFinishEvent([customKeyboard] {
3077 auto parent = customKeyboard->GetParent();
3078 CHECK_NULL_VOID(parent);
3079 parent->RemoveChild(customKeyboard);
3080 });
3081 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
3082 AnimationUtils::Animate(option, [context, pageHeight]() {
3083 if (context) {
3084 context->OnTransformTranslateUpdate({ 0.0f, pageHeight, 0.0f });
3085 }
3086 },
3087 option.GetOnFinishEvent());
3088 }
3089 }
3090
BindKeyboard(const std::function<void ()> & keyboardBuilder,int32_t targetId)3091 void OverlayManager::BindKeyboard(const std::function<void()>& keyboardBuilder, int32_t targetId)
3092 {
3093 if (customKeyboardMap_.find(targetId) != customKeyboardMap_.end()) {
3094 return;
3095 }
3096 auto rootNode = rootNodeWeak_.Upgrade();
3097 CHECK_NULL_VOID(rootNode);
3098 auto customKeyboard = KeyboardView::CreateKeyboard(targetId, keyboardBuilder);
3099 if (!customKeyboard) {
3100 return;
3101 }
3102 customKeyboard->MountToParent(rootNode);
3103 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3104 customKeyboardMap_[targetId] = customKeyboard;
3105 PlayKeyboardTransition(customKeyboard, true);
3106 }
3107
CloseKeyboard(int32_t targetId)3108 void OverlayManager::CloseKeyboard(int32_t targetId)
3109 {
3110 auto it = customKeyboardMap_.find(targetId);
3111 if (it == customKeyboardMap_.end()) {
3112 return;
3113 }
3114 auto customKeyboard = it->second;
3115 CHECK_NULL_VOID(customKeyboard);
3116 auto pattern = customKeyboard->GetPattern<KeyboardPattern>();
3117 CHECK_NULL_VOID(pattern);
3118 customKeyboardMap_.erase(pattern->GetTargetId());
3119 PlayKeyboardTransition(customKeyboard, false);
3120 }
3121
DestroyKeyboard()3122 void OverlayManager::DestroyKeyboard()
3123 {
3124 auto rootNode = rootNodeWeak_.Upgrade();
3125 CHECK_NULL_VOID(rootNode);
3126 if (customKeyboardMap_.empty()) {
3127 return;
3128 }
3129 for (auto it = customKeyboardMap_.begin(); it != customKeyboardMap_.end();) {
3130 auto keyboard = it->second;
3131 rootNode->RemoveChild(keyboard);
3132 it = customKeyboardMap_.erase(it);
3133 }
3134 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3135 }
3136
3137 // This function will be used in SceneBoard Thread only.
3138 // if need to show the pop-up component,
3139 // it expects to receive the target component bound by the pop-up component to find the windowScene component.
3140 // if need to hide the pop-up component,
3141 // it expects to receive the the pop-up component to return the parent component.
3142 // And the parent component will be the windowScene component exactly.
FindWindowScene(RefPtr<FrameNode> targetNode)3143 RefPtr<UINode> OverlayManager::FindWindowScene(RefPtr<FrameNode> targetNode)
3144 {
3145 auto container = Container::Current();
3146 if (!container || !container->IsScenceBoardWindow()) {
3147 return rootNodeWeak_.Upgrade();
3148 }
3149 CHECK_NULL_RETURN(targetNode, nullptr);
3150 auto parent = targetNode->GetParent();
3151 while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
3152 parent = parent->GetParent();
3153 }
3154 CHECK_NULL_RETURN(parent, nullptr);
3155 windowSceneSet_.insert(parent);
3156 return parent;
3157 }
3158
MountFilterToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)3159 void OverlayManager::MountFilterToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
3160 {
3161 CHECK_NULL_VOID(windowScene);
3162 columnNode->MountToParent(windowScene);
3163 columnNode->OnMountToParentDone();
3164 windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3165 filterColumnNodeWeak_ = columnNode;
3166 hasFilter_ = true;
3167 }
3168
MountPixelMapToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)3169 void OverlayManager::MountPixelMapToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
3170 {
3171 CHECK_NULL_VOID(windowScene);
3172 columnNode->MountToParent(windowScene);
3173 columnNode->OnMountToParentDone();
3174 windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3175 pixmapColumnNodeWeak_ = columnNode;
3176 hasPixelMap_ = true;
3177 }
3178
MountEventToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)3179 void OverlayManager::MountEventToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
3180 {
3181 CHECK_NULL_VOID(windowScene);
3182 columnNode->MountToParent(windowScene);
3183 columnNode->OnMountToParentDone();
3184 eventColumnNodeWeak_ = columnNode;
3185 hasEvent_ = true;
3186 }
3187
MountPixelMapToRootNode(const RefPtr<FrameNode> & columnNode)3188 void OverlayManager::MountPixelMapToRootNode(const RefPtr<FrameNode>& columnNode)
3189 {
3190 auto rootNode = rootNodeWeak_.Upgrade();
3191 CHECK_NULL_VOID(rootNode);
3192 columnNode->MountToParent(rootNode);
3193 columnNode->OnMountToParentDone();
3194 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3195 pixmapColumnNodeWeak_ = columnNode;
3196 hasPixelMap_ = true;
3197 }
3198
MountEventToRootNode(const RefPtr<FrameNode> & columnNode)3199 void OverlayManager::MountEventToRootNode(const RefPtr<FrameNode>& columnNode)
3200 {
3201 auto rootNode = rootNodeWeak_.Upgrade();
3202 CHECK_NULL_VOID(rootNode);
3203 columnNode->MountToParent(rootNode, 1);
3204 columnNode->OnMountToParentDone();
3205 eventColumnNodeWeak_ = columnNode;
3206 hasEvent_ = true;
3207 }
3208
RemovePixelMap()3209 void OverlayManager::RemovePixelMap()
3210 {
3211 if (!hasPixelMap_) {
3212 return;
3213 }
3214 auto columnNode = pixmapColumnNodeWeak_.Upgrade();
3215 CHECK_NULL_VOID(columnNode);
3216 auto rootNode = columnNode->GetParent();
3217 CHECK_NULL_VOID(rootNode);
3218 rootNode->RemoveChild(columnNode);
3219 rootNode->RebuildRenderContextTree();
3220 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
3221 hasPixelMap_ = false;
3222 isOnAnimation_ = false;
3223 }
3224
RemovePixelMapAnimation(bool startDrag,double x,double y)3225 void OverlayManager::RemovePixelMapAnimation(bool startDrag, double x, double y)
3226 {
3227 if (isOnAnimation_ || !hasPixelMap_) {
3228 return;
3229 }
3230 if (startDrag) {
3231 return;
3232 }
3233 auto columnNode = pixmapColumnNodeWeak_.Upgrade();
3234 CHECK_NULL_VOID(columnNode);
3235 auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetFirstChild());
3236 CHECK_NULL_VOID(imageNode);
3237 auto imageContext = imageNode->GetRenderContext();
3238 CHECK_NULL_VOID(imageContext);
3239 auto hub = columnNode->GetOrCreateGestureEventHub();
3240 CHECK_NULL_VOID(hub);
3241 auto frameNode = hub->GetFrameNode();
3242 CHECK_NULL_VOID(frameNode);
3243 RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
3244 CHECK_NULL_VOID(pixelMap);
3245 float scale = PIXELMAP_DRAG_SCALE;
3246 UpdatePixelMapScale(scale);
3247 int32_t width = pixelMap->GetWidth();
3248 int32_t height = pixelMap->GetHeight();
3249
3250 auto shadow = imageContext->GetBackShadow();
3251 if (!shadow.has_value()) {
3252 shadow = Shadow::CreateShadow(ShadowStyle::None);
3253 }
3254 imageContext->UpdateBackShadow(shadow.value());
3255 AnimationOption option;
3256 option.SetCurve(Curves::SHARP);
3257 option.SetDuration(PIXELMAP_ANIMATION_DURATION);
3258 AnimationUtils::Animate(option, [imageContext, shadow]() mutable {
3259 if (imageContext) {
3260 auto color = shadow->GetColor();
3261 auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue());
3262 shadow->SetColor(newColor);
3263 imageContext->UpdateBackShadow(shadow.value());
3264 BorderRadiusProperty borderRadius;
3265 borderRadius.SetRadius(0.0_vp);
3266 imageContext->UpdateBorderRadius(borderRadius);
3267 }
3268 });
3269
3270 auto pipelineContext = PipelineContext::GetCurrentContext();
3271 CHECK_NULL_VOID(pipelineContext);
3272 auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
3273 CHECK_NULL_VOID(menuTheme);
3274 auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse();
3275 auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction();
3276
3277 AnimationOption scaleOption;
3278 auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(springMotionResponse, springMotionDampingFraction);
3279 scaleOption.SetCurve(motion);
3280
3281 scaleOption.SetOnFinishEvent([this] {
3282 auto pipeline = PipelineContext::GetCurrentContext();
3283 CHECK_NULL_VOID(pipeline);
3284 auto dragDropManager = pipeline->GetDragDropManager();
3285 CHECK_NULL_VOID(dragDropManager);
3286 if (!dragDropManager->IsNeedScaleDragPreview()) {
3287 InteractionInterface::GetInstance()->SetDragWindowVisible(true);
3288 }
3289 auto overlayManager = AceType::Claim(this);
3290 CHECK_NULL_VOID(overlayManager);
3291 if (overlayManager->hasEvent_) {
3292 overlayManager->RemoveEventColumn();
3293 }
3294 overlayManager->RemovePixelMap();
3295 });
3296
3297 auto coordinateX = imageNode->GetOffsetRelativeToWindow().GetX() - frameNode->GetOffsetRelativeToWindow().GetX();
3298 auto coordinateY = imageNode->GetOffsetRelativeToWindow().GetY() - frameNode->GetOffsetRelativeToWindow().GetY();
3299 AnimationUtils::Animate(
3300 scaleOption,
3301 [imageContext, startDrag, x, y, width, height, scale, coordinateX, coordinateY]() {
3302 if (startDrag) {
3303 imageContext->UpdatePosition(OffsetT<Dimension>(
3304 Dimension(x - (x - coordinateX) * scale +
3305 PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * width * (scale - PIXELMAP_DRAG_SCALE)),
3306 Dimension(y - (y - coordinateY) * scale +
3307 PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * height * (scale - PIXELMAP_DRAG_SCALE))));
3308 imageContext->UpdateTransformScale({ scale, scale });
3309 imageContext->OnModifyDone();
3310 } else {
3311 imageContext->UpdateTransformScale(VectorF(1.0f, 1.0f));
3312 }
3313 },
3314 scaleOption.GetOnFinishEvent());
3315 isOnAnimation_ = true;
3316 }
3317
UpdatePixelMapScale(float & scale)3318 void OverlayManager::UpdatePixelMapScale(float& scale)
3319 {
3320 auto columnNode = pixmapColumnNodeWeak_.Upgrade();
3321 CHECK_NULL_VOID(columnNode);
3322 auto hub = columnNode->GetOrCreateGestureEventHub();
3323 CHECK_NULL_VOID(hub);
3324 RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
3325 CHECK_NULL_VOID(pixelMap);
3326 int32_t height = pixelMap->GetHeight();
3327 int32_t width = pixelMap->GetWidth();
3328 if (height == 0 || width == 0) {
3329 return;
3330 }
3331 int32_t deviceWidth = SystemProperties::GetDeviceWidth();
3332 int32_t deviceHeight = SystemProperties::GetDeviceHeight();
3333 int32_t maxDeviceLength = std::max(deviceHeight, deviceWidth);
3334 int32_t minDeviceLength = std::min(deviceHeight, deviceWidth);
3335 if (maxDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE > minDeviceLength) {
3336 if (height > minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) {
3337 scale = static_cast<float>(minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) / height;
3338 }
3339 } else {
3340 if (hub->GetTextDraggable() && height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
3341 width > minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) {
3342 scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
3343 static_cast<float>(minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) / width);
3344 } else if (height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
3345 width > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) {
3346 scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
3347 static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / width);
3348 }
3349 }
3350 }
3351
RemoveFilterAnimation()3352 void OverlayManager::RemoveFilterAnimation()
3353 {
3354 if (!hasFilter_) {
3355 return;
3356 }
3357 auto filterNode = filterColumnNodeWeak_.Upgrade();
3358 CHECK_NULL_VOID(filterNode);
3359 auto filterContext = filterNode->GetRenderContext();
3360 CHECK_NULL_VOID(filterContext);
3361 auto pipelineContext = PipelineContext::GetCurrentContext();
3362 CHECK_NULL_VOID(pipelineContext);
3363 auto menuTheme = pipelineContext->GetTheme<NG::MenuTheme>();
3364 CHECK_NULL_VOID(menuTheme);
3365 AnimationOption option;
3366 option.SetOnFinishEvent([weak = WeakClaim(this)] {
3367 auto overlayManager = weak.Upgrade();
3368 CHECK_NULL_VOID(overlayManager);
3369 overlayManager->RemoveFilter();
3370 });
3371 option.SetDuration(menuTheme->GetFilterAnimationDuration());
3372 option.SetCurve(Curves::SHARP);
3373 AnimationUtils::Animate(
3374 option,
3375 [filterContext]() {
3376 CHECK_NULL_VOID(filterContext);
3377 BlurStyleOption styleOption;
3378 styleOption.blurStyle = BlurStyle::NO_MATERIAL;
3379 filterContext->UpdateBackBlurStyle(styleOption);
3380 },
3381 option.GetOnFinishEvent());
3382 }
3383
RemoveFilter()3384 void OverlayManager::RemoveFilter()
3385 {
3386 if (!hasFilter_) {
3387 return;
3388 }
3389 auto columnNode = filterColumnNodeWeak_.Upgrade();
3390 if (columnNode) {
3391 auto rootNode = columnNode->GetParent();
3392 CHECK_NULL_VOID(rootNode);
3393 rootNode->RemoveChild(columnNode);
3394 rootNode->RebuildRenderContextTree();
3395 }
3396 hasFilter_ = false;
3397 }
3398
RemoveEventColumn()3399 void OverlayManager::RemoveEventColumn()
3400 {
3401 if (!hasEvent_) {
3402 return;
3403 }
3404 auto columnNode = eventColumnNodeWeak_.Upgrade();
3405 CHECK_NULL_VOID(columnNode);
3406 auto rootNode = columnNode->GetParent();
3407 CHECK_NULL_VOID(rootNode);
3408 rootNode->RemoveChild(columnNode);
3409 hasEvent_ = false;
3410 }
3411
CreateModalUIExtension(const AAFwk::Want & want,const ModalUIExtensionCallbacks & callbacks,bool isProhibitBack,bool isAsyncModalBinding)3412 int32_t OverlayManager::CreateModalUIExtension(
3413 const AAFwk::Want& want, const ModalUIExtensionCallbacks& callbacks, bool isProhibitBack, bool isAsyncModalBinding)
3414 {
3415 isProhibitBack_ = isProhibitBack;
3416 auto uiExtNode = ModalUIExtension::Create(want, callbacks, isAsyncModalBinding);
3417 auto layoutProperty = uiExtNode->GetLayoutProperty();
3418 CHECK_NULL_RETURN(layoutProperty, 0);
3419 auto full = CalcLength(Dimension(1.0, DimensionUnit::PERCENT));
3420 layoutProperty->UpdateUserDefinedIdealSize(CalcSize(full, full));
3421 auto buildNodeFunc = [uiExtNode]() -> RefPtr<UINode> {
3422 uiExtNode->MarkModifyDone();
3423 return uiExtNode;
3424 };
3425 auto sessionId = ModalUIExtension::GetSessionId(uiExtNode);
3426 if (!isAsyncModalBinding) {
3427 ModalStyle modalStyle;
3428 modalStyle.modalTransition = NG::ModalTransition::NONE;
3429 modalStyle.isUIExtension = true;
3430 // Convert the sessionId into a negative number to distinguish it from the targetId of other modal pages
3431 BindContentCover(true, nullptr, std::move(buildNodeFunc), modalStyle, nullptr, nullptr, nullptr, -(sessionId));
3432 } else {
3433 auto bindModalCallback = [weak = WeakClaim(this), buildNodeFunc, sessionId, id = Container::CurrentId()]() {
3434 ContainerScope scope(id);
3435 auto overlayManager = weak.Upgrade();
3436 CHECK_NULL_VOID(overlayManager);
3437 ModalStyle modalStyle;
3438 modalStyle.modalTransition = NG::ModalTransition::NONE;
3439 modalStyle.isUIExtension = true;
3440 overlayManager->BindContentCover(
3441 true, nullptr, std::move(buildNodeFunc), modalStyle, nullptr, nullptr, nullptr, -(sessionId));
3442 };
3443 ModalUIExtension::SetBindModalCallback(uiExtNode, std::move(bindModalCallback));
3444 uiExtNodes_[sessionId] = WeakClaim(RawPtr(uiExtNode));
3445 }
3446 return sessionId;
3447 }
3448
CloseModalUIExtension(int32_t sessionId)3449 void OverlayManager::CloseModalUIExtension(int32_t sessionId)
3450 {
3451 if (uiExtNodes_.find(sessionId) != uiExtNodes_.end()) {
3452 auto uiExtNode = uiExtNodes_[sessionId].Upgrade();
3453 if (uiExtNode) {
3454 ModalUIExtension::SetBindModalCallback(uiExtNode, nullptr);
3455 }
3456 uiExtNodes_.erase(sessionId);
3457 }
3458 ModalStyle modalStyle;
3459 modalStyle.modalTransition = NG::ModalTransition::NONE;
3460 BindContentCover(false, nullptr, nullptr, modalStyle, nullptr, nullptr, nullptr, -(sessionId));
3461 }
3462
BindUIExtensionToMenu(const RefPtr<FrameNode> & uiExtNode,const RefPtr<NG::FrameNode> & targetNode,std::string longestContent,int32_t menuSize)3463 RefPtr<FrameNode> OverlayManager::BindUIExtensionToMenu(const RefPtr<FrameNode>& uiExtNode,
3464 const RefPtr<NG::FrameNode>& targetNode, std::string longestContent, int32_t menuSize)
3465 {
3466 CHECK_NULL_RETURN(uiExtNode, nullptr);
3467 CHECK_NULL_RETURN(targetNode, nullptr);
3468 auto pipeline = PipelineContext::GetCurrentContext();
3469 CHECK_NULL_RETURN(pipeline, nullptr);
3470 MenuParam menuParam;
3471 menuParam.type = MenuType::MENU;
3472 menuParam.placement = Placement::BOTTOM_LEFT;
3473 auto menuWrapperNode =
3474 MenuView::Create(uiExtNode, targetNode->GetId(), targetNode->GetTag(), menuParam, true);
3475 CHECK_NULL_RETURN(menuWrapperNode, nullptr);
3476 auto menuNode = DynamicCast<FrameNode>(menuWrapperNode->GetFirstChild());
3477 CHECK_NULL_RETURN(menuNode, nullptr);
3478 auto idealSize = CaculateMenuSize(menuNode, longestContent, menuSize);
3479 auto uiExtLayoutProperty = uiExtNode->GetLayoutProperty();
3480 CHECK_NULL_RETURN(uiExtLayoutProperty, nullptr);
3481 uiExtLayoutProperty->UpdateUserDefinedIdealSize(
3482 CalcSize(CalcLength(idealSize.Width()), CalcLength(idealSize.Height())));
3483 auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
3484 CHECK_NULL_RETURN(menuLayoutProperty, nullptr);
3485 menuLayoutProperty->UpdateMargin(MarginProperty());
3486 menuLayoutProperty->UpdatePadding(PaddingProperty());
3487 auto scollNode = DynamicCast<FrameNode>(menuNode->GetFirstChild());
3488 CHECK_NULL_RETURN(scollNode, menuNode);
3489 auto scollLayoutProperty = scollNode->GetLayoutProperty();
3490 CHECK_NULL_RETURN(scollLayoutProperty, menuNode);
3491 scollLayoutProperty->UpdateMargin(MarginProperty());
3492 scollLayoutProperty->UpdatePadding(PaddingProperty());
3493
3494 auto destructor = [id = targetNode->GetId()]() {
3495 auto pipeline = NG::PipelineContext::GetCurrentContext();
3496 CHECK_NULL_VOID(pipeline);
3497 auto overlayManager = pipeline->GetOverlayManager();
3498 CHECK_NULL_VOID(overlayManager);
3499 overlayManager->DeleteMenu(id);
3500 };
3501 targetNode->PushDestroyCallback(destructor);
3502 return menuNode;
3503 }
3504
CaculateMenuSize(const RefPtr<FrameNode> & menuNode,std::string longestContent,int32_t menuSize)3505 SizeF OverlayManager::CaculateMenuSize(
3506 const RefPtr<FrameNode>& menuNode, std::string longestContent, int32_t menuSize)
3507 {
3508 TAG_LOGD(AceLogTag::ACE_OVERLAY, "caculate menu size enter");
3509 auto pipeline = PipelineContext::GetCurrentContext();
3510 CHECK_NULL_RETURN(pipeline, SizeF());
3511 auto textTheme = pipeline->GetTheme<TextTheme>();
3512 CHECK_NULL_RETURN(textTheme, SizeF());
3513 TextStyle textStyle = textTheme ? textTheme->GetTextStyle() : TextStyle();
3514 MeasureContext measureContext;
3515 measureContext.textContent = longestContent;
3516 measureContext.fontSize = textStyle.GetFontSize();
3517 auto fontweight = StringUtils::FontWeightToString(textStyle.GetFontWeight());
3518 measureContext.fontWeight = fontweight;
3519 auto fontFamilies = textStyle.GetFontFamilies();
3520 measureContext.fontFamily = V2::ConvertFontFamily(fontFamilies);
3521 auto measureSize = MeasureUtil::MeasureTextSize(measureContext);
3522 auto selectTheme = pipeline->GetTheme<SelectTheme>();
3523 CHECK_NULL_RETURN(selectTheme, SizeF());
3524 auto minItemHeight = static_cast<float>(selectTheme->GetOptionMinHeight().ConvertToPx());
3525 auto menuItemHeight = std::max(minItemHeight, static_cast<float>(measureSize.Height()));
3526 auto groupDividerPadding = static_cast<float>(selectTheme->GetDividerPaddingVertical().ConvertToPx()) * 2 +
3527 static_cast<float>(selectTheme->GetDefaultDividerWidth().ConvertToPx());
3528 auto groupHeight = menuItemHeight + groupDividerPadding;
3529
3530 auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
3531 CHECK_NULL_RETURN(menuLayoutProperty, SizeF());
3532 const auto& padding = menuLayoutProperty->CreatePaddingAndBorder();
3533 auto middleSpace = static_cast<float>(selectTheme->GetIconContentPadding().ConvertToPx());
3534 float contentWidth = static_cast<float>(measureSize.Width()) + padding.Width() + middleSpace;
3535
3536 auto childConstraint = menuLayoutProperty->CreateChildConstraint();
3537 auto columnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::MENU);
3538 CHECK_NULL_RETURN(columnInfo, SizeF());
3539 CHECK_NULL_RETURN(columnInfo->GetParent(), SizeF());
3540 columnInfo->GetParent()->BuildColumnWidth();
3541 auto minWidth = static_cast<float>(columnInfo->GetWidth()) - padding.Width();
3542 childConstraint.minSize.SetWidth(minWidth);
3543 auto idealWidth = std::max(contentWidth, childConstraint.minSize.Width());
3544 auto idealHeight = groupHeight * (menuSize - 1) +
3545 menuItemHeight + static_cast<float>(selectTheme->GetOutPadding().ConvertToPx()) * 2;
3546 return SizeF(idealWidth, idealHeight);
3547 }
3548
ShowUIExtensionMenu(const RefPtr<NG::FrameNode> & uiExtNode,NG::RectF aiRect,std::string longestContent,int32_t menuSize,const RefPtr<NG::FrameNode> & targetNode)3549 bool OverlayManager::ShowUIExtensionMenu(const RefPtr<NG::FrameNode>& uiExtNode, NG::RectF aiRect,
3550 std::string longestContent, int32_t menuSize, const RefPtr<NG::FrameNode>& targetNode)
3551 {
3552 TAG_LOGD(AceLogTag::ACE_OVERLAY, "show ui extension menu enter");
3553 CHECK_NULL_RETURN(uiExtNode, false);
3554 auto root = rootNodeWeak_.Upgrade();
3555 CHECK_NULL_RETURN(root, false);
3556 for (const auto& child : root->GetChildren()) {
3557 if (child->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
3558 return false;
3559 }
3560 }
3561 auto menuNode = BindUIExtensionToMenu(uiExtNode, targetNode, longestContent, menuSize);
3562 CHECK_NULL_RETURN(menuNode, false);
3563 auto menuLayoutProperty = menuNode->GetLayoutProperty<MenuLayoutProperty>();
3564 CHECK_NULL_RETURN(menuLayoutProperty, false);
3565 menuLayoutProperty->UpdateIsRectInTarget(true);
3566 menuLayoutProperty->UpdateTargetSize(aiRect.GetSize());
3567 auto menuWrapperNode = DynamicCast<FrameNode>(menuNode->GetParent());
3568 CHECK_NULL_RETURN(menuWrapperNode, false);
3569 ShowMenu(targetNode->GetId(), aiRect.GetOffset(), menuWrapperNode);
3570 return true;
3571 }
3572
MarkDirty(PropertyChangeFlag flag)3573 void OverlayManager::MarkDirty(PropertyChangeFlag flag)
3574 {
3575 auto root = rootNodeWeak_.Upgrade();
3576 CHECK_NULL_VOID(root);
3577 auto pipeline = PipelineContext::GetCurrentContext();
3578 CHECK_NULL_VOID(pipeline);
3579 for (auto&& child : root->GetChildren()) {
3580 // first child is Stage node in main window, subwindow not has Stage node.
3581 if (child != root->GetFirstChild() || pipeline->IsSubPipeline()) {
3582 child->MarkDirtyNode(flag);
3583 }
3584 }
3585 }
3586
GetRootHeight() const3587 float OverlayManager::GetRootHeight() const
3588 {
3589 auto rootNode = rootNodeWeak_.Upgrade();
3590 CHECK_NULL_RETURN(rootNode, 0.0);
3591 auto rootGeometryNode = AceType::DynamicCast<FrameNode>(rootNode)->GetGeometryNode();
3592 CHECK_NULL_RETURN(rootGeometryNode, 0.0);
3593 auto rootHeight = rootGeometryNode->GetFrameSize().Height();
3594 return rootHeight;
3595 }
3596
CheckReturnFocus(RefPtr<FrameNode> node)3597 void OverlayManager::CheckReturnFocus(RefPtr<FrameNode> node)
3598 {
3599 auto focusHub = node->GetFocusHub();
3600 CHECK_NULL_VOID(focusHub);
3601 if (focusHub->IsCurrentFocus()) {
3602 auto pageNode = GetLastPage();
3603 CHECK_NULL_VOID(pageNode);
3604 auto pageFocusHub = pageNode->GetFocusHub();
3605 CHECK_NULL_VOID(pageFocusHub);
3606 pageFocusHub->RequestFocusWithDefaultFocusFirstly();
3607 }
3608 }
3609 } // namespace OHOS::Ace::NG
3610