• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 #include "base/geometry/ng/offset_t.h"
22 #include "base/memory/ace_type.h"
23 #include "base/memory/referenced.h"
24 #include "base/subwindow/subwindow_manager.h"
25 #include "base/utils/system_properties.h"
26 #include "base/utils/utils.h"
27 #include "core/animation/animation_pub.h"
28 #include "core/animation/spring_curve.h"
29 #include "core/common/ace_application_info.h"
30 #include "core/common/container.h"
31 #include "core/common/modal_ui_extension.h"
32 #include "core/components/common/properties/color.h"
33 #include "core/components/select/select_theme.h"
34 #include "core/components/toast/toast_theme.h"
35 #include "core/components_ng/base/frame_node.h"
36 #include "core/components_ng/base/ui_node.h"
37 #include "core/components_ng/base/view_stack_processor.h"
38 #include "core/components_ng/pattern/bubble/bubble_event_hub.h"
39 #include "core/components_ng/pattern/bubble/bubble_pattern.h"
40 #include "core/components_ng/pattern/calendar_picker/calendar_dialog_view.h"
41 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
42 #include "core/components_ng/pattern/dialog/dialog_view.h"
43 #include "core/components_ng/pattern/menu/menu_layout_property.h"
44 #include "core/components_ng/pattern/menu/menu_pattern.h"
45 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
46 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
47 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
48 #include "core/components_ng/pattern/overlay/keyboard_base_pattern.h"
49 #include "core/components_ng/pattern/overlay/keyboard_view.h"
50 #include "core/components_ng/pattern/overlay/modal_presentation_pattern.h"
51 #include "core/components_ng/pattern/overlay/popup_base_pattern.h"
52 #include "core/components_ng/pattern/overlay/sheet_drag_bar_pattern.h"
53 #include "core/components_ng/pattern/overlay/sheet_presentation_pattern.h"
54 #include "core/components_ng/pattern/overlay/sheet_presentation_property.h"
55 #include "core/components_ng/pattern/overlay/sheet_view.h"
56 #include "core/components_ng/pattern/picker/datepicker_dialog_view.h"
57 #include "core/components_ng/pattern/stage/stage_pattern.h"
58 #include "core/components_ng/pattern/text_picker/textpicker_dialog_view.h"
59 #include "core/components_ng/pattern/time_picker/timepicker_dialog_view.h"
60 #include "core/components_ng/pattern/toast/toast_view.h"
61 #include "core/components_ng/property/property.h"
62 #include "core/components_v2/inspector/inspector_constants.h"
63 #include "core/pipeline/pipeline_base.h"
64 #include "core/pipeline/pipeline_context.h"
65 
66 #ifdef ENABLE_DRAG_FRAMEWORK
67 #include "base/msdp/device_status/interfaces/innerkits/interaction/include/interaction_manager.h"
68 #endif // ENABLE_DRAG_FRAMEWORK
69 
70 namespace OHOS::Ace::NG {
71 namespace {
72 // should be moved to theme.
73 constexpr int32_t TOAST_ANIMATION_DURATION = 100;
74 constexpr int32_t MENU_ANIMATION_DURATION = 150;
75 constexpr float TOAST_ANIMATION_POSITION = 15.0f;
76 
77 #ifdef ENABLE_DRAG_FRAMEWORK
78 constexpr float PIXELMAP_DRAG_SCALE = 1.0f;
79 constexpr int32_t PIXELMAP_ANIMATION_DURATION = 100;
80 constexpr float PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE = 0.5f;
81 #endif // ENABLE_DRAG_FRAMEWORK
82 
83 constexpr int32_t FULL_MODAL_ALPHA_ANIMATION_DURATION = 200;
84 
85 // dialog animation params
86 const RefPtr<Curve> SHOW_SCALE_ANIMATION_CURVE = AceType::MakeRefPtr<CubicCurve>(0.38f, 1.33f, 0.6f, 1.0f);
87 
88 // custom keyboard animation params
89 const RefPtr<Curve> SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE =
90     AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 342.0f, 37.0f);
91 const RefPtr<Curve> HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE =
92     AceType::MakeRefPtr<InterpolatingSpring>(4.0f, 1.0f, 342.0f, 37.0f);
93 
GetLastPage()94 RefPtr<FrameNode> GetLastPage()
95 {
96     auto pipelineContext = PipelineContext::GetCurrentContext();
97     CHECK_NULL_RETURN(pipelineContext, nullptr);
98     auto stageManager = pipelineContext->GetStageManager();
99     CHECK_NULL_RETURN(stageManager, nullptr);
100     auto pageNode = stageManager->GetLastPage();
101     return pageNode;
102 }
103 } // namespace
104 
PostDialogFinishEvent(const WeakPtr<FrameNode> & nodeWk)105 void OverlayManager::PostDialogFinishEvent(const WeakPtr<FrameNode>& nodeWk)
106 {
107     auto context = PipelineContext::GetCurrentContext();
108     CHECK_NULL_VOID_NOLOG(context);
109     auto taskExecutor = context->GetTaskExecutor();
110     CHECK_NULL_VOID_NOLOG(taskExecutor);
111     // animation finish event should be posted to UI thread.
112     taskExecutor->PostTask(
113         [weak = WeakClaim(this), nodeWk, id = Container::CurrentId()]() {
114             ContainerScope scope(id);
115             LOGD("Execute dialog OnDialogCloseEvent");
116             auto overlayManager = weak.Upgrade();
117             auto node = nodeWk.Upgrade();
118             CHECK_NULL_VOID_NOLOG(overlayManager && node);
119             SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_NONE };
120             node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
121             overlayManager->OnDialogCloseEvent(node);
122         },
123         TaskExecutor::TaskType::UI);
124 }
125 
OnDialogCloseEvent(const RefPtr<FrameNode> & node)126 void OverlayManager::OnDialogCloseEvent(const RefPtr<FrameNode>& node)
127 {
128     CHECK_NULL_VOID(node);
129 
130     BlurOverlayNode(node);
131 
132     auto dialogPattern = node->GetPattern<DialogPattern>();
133     CHECK_NULL_VOID(dialogPattern);
134     auto option = dialogPattern->GetCloseAnimation().value_or(AnimationOption());
135     auto onFinish = option.GetOnFinishEvent();
136 
137     auto dialogLayoutProp = dialogPattern->GetLayoutProperty<DialogLayoutProperty>();
138     bool isShowInSubWindow = false;
139     if (dialogLayoutProp) {
140         isShowInSubWindow = dialogLayoutProp->GetShowInSubWindowValue(false);
141     }
142     if (onFinish != nullptr) {
143         onFinish();
144     }
145 
146     auto root = node->GetParent();
147     CHECK_NULL_VOID(root);
148     root->RemoveChild(node);
149     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
150     auto lastChild = AceType::DynamicCast<FrameNode>(root->GetLastChild());
151     if (lastChild) {
152         auto pattern = lastChild->GetPattern();
153         if (!AceType::InstanceOf<StagePattern>(pattern)) {
154             LOGI("root has other overlay children.");
155             return;
156         }
157     }
158 
159     auto container = Container::Current();
160     CHECK_NULL_VOID_NOLOG(container);
161     if (container->IsDialogContainer() || isShowInSubWindow) {
162         SubwindowManager::GetInstance()->HideSubWindowNG();
163     }
164 }
165 
OpenDialogAnimation(const RefPtr<FrameNode> & node)166 void OverlayManager::OpenDialogAnimation(const RefPtr<FrameNode>& node)
167 {
168     CHECK_NULL_VOID(node);
169     auto pipeline = PipelineContext::GetCurrentContext();
170     CHECK_NULL_VOID(pipeline);
171     auto theme = pipeline->GetTheme<DialogTheme>();
172     CHECK_NULL_VOID(theme);
173     auto root = rootNodeWeak_.Upgrade();
174     auto dialogPattern = node->GetPattern<DialogPattern>();
175     auto container = Container::Current();
176     if (container && container->IsScenceBoardWindow()) {
177         root = dialogPattern->GetDialogProperties().windowScene.Upgrade();
178     }
179     CHECK_NULL_VOID(root);
180     node->MountToParent(root);
181     root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
182     BlurLowerNode(node);
183 
184     AnimationOption option;
185     // default opacity animation params
186     option.SetCurve(Curves::SHARP);
187     option.SetDuration(theme->GetOpacityAnimationDurIn());
188     option.SetFillMode(FillMode::FORWARDS);
189     option = dialogPattern->GetOpenAnimation().value_or(option);
190     option.SetIteration(1);
191     option.SetAnimationDirection(AnimationDirection::NORMAL);
192     auto onFinish = option.GetOnFinishEvent();
193     option.SetOnFinishEvent(
194         [weak = WeakClaim(this), nodeWK = WeakPtr<FrameNode>(node), id = Container::CurrentId(), onFinish] {
195             ContainerScope scope(id);
196             auto context = PipelineContext::GetCurrentContext();
197             CHECK_NULL_VOID_NOLOG(context);
198             auto taskExecutor = context->GetTaskExecutor();
199             CHECK_NULL_VOID_NOLOG(taskExecutor);
200             taskExecutor->PostTask(
201                 [id, weak, nodeWK, onFinish]() {
202                     ContainerScope scope(id);
203                     if (onFinish) {
204                         onFinish();
205                     }
206                     auto overlayManager = weak.Upgrade();
207                     auto node = nodeWK.Upgrade();
208                     CHECK_NULL_VOID(overlayManager && node);
209                     overlayManager->FocusOverlayNode(node);
210                 },
211                 TaskExecutor::TaskType::UI);
212         });
213     auto ctx = node->GetRenderContext();
214     CHECK_NULL_VOID(ctx);
215     ctx->OpacityAnimation(option, theme->GetOpacityStart(), theme->GetOpacityEnd());
216     // scale animation on dialog content
217     auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
218     CHECK_NULL_VOID(contentNode);
219     ctx = contentNode->GetRenderContext();
220     CHECK_NULL_VOID(ctx);
221     option.SetOnFinishEvent(nullptr);
222     option.SetCurve(SHOW_SCALE_ANIMATION_CURVE);
223     option.SetDuration(dialogPattern->GetOpenAnimation().has_value()
224                            ? dialogPattern->GetOpenAnimation().value().GetDuration()
225                            : theme->GetAnimationDurationIn());
226     ctx->ScaleAnimation(option, theme->GetScaleStart(), theme->GetScaleEnd());
227     node->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
228 }
229 
CloseDialogAnimation(const RefPtr<FrameNode> & node)230 void OverlayManager::CloseDialogAnimation(const RefPtr<FrameNode>& node)
231 {
232     CHECK_NULL_VOID(node);
233     auto pipeline = PipelineContext::GetCurrentContext();
234     CHECK_NULL_VOID(pipeline);
235     auto theme = pipeline->GetTheme<DialogTheme>();
236     CHECK_NULL_VOID(theme);
237 
238     ResetLowerNodeFocusable(node);
239     SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_KEYBOARD };
240     node->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
241 
242     // default opacity animation params
243     AnimationOption option;
244     option.SetFillMode(FillMode::FORWARDS);
245     option.SetCurve(Curves::SHARP);
246 
247     option.SetDuration(theme->GetAnimationDurationOut());
248     // get customized animation params
249     auto dialogPattern = node->GetPattern<DialogPattern>();
250     option = dialogPattern->GetCloseAnimation().value_or(option);
251     option.SetIteration(1);
252     option.SetAnimationDirection(AnimationDirection::NORMAL);
253 
254     option.SetOnFinishEvent([weak = WeakClaim(this), nodeWk = WeakPtr<FrameNode>(node), id = Container::CurrentId()] {
255         ContainerScope scope(id);
256         auto overlayManager = weak.Upgrade();
257         CHECK_NULL_VOID_NOLOG(overlayManager);
258         overlayManager->PostDialogFinishEvent(nodeWk);
259     });
260     auto ctx = node->GetRenderContext();
261     CHECK_NULL_VOID(ctx);
262     ctx->OpacityAnimation(option, theme->GetOpacityEnd(), theme->GetOpacityStart());
263 
264     // scale animation
265     auto contentNode = DynamicCast<FrameNode>(node->GetFirstChild());
266     CHECK_NULL_VOID(contentNode);
267     ctx = contentNode->GetRenderContext();
268     CHECK_NULL_VOID(ctx);
269     option.SetOnFinishEvent(nullptr);
270     option.SetCurve(Curves::FRICTION);
271     ctx->ScaleAnimation(option, theme->GetScaleEnd(), theme->GetScaleStart());
272     // start animation immediately
273     pipeline->RequestFrame();
274 }
275 
SetContainerButtonEnable(bool isEnabled)276 void OverlayManager::SetContainerButtonEnable(bool isEnabled)
277 {
278     auto pipeline = PipelineContext::GetCurrentContext();
279     CHECK_NULL_VOID(pipeline);
280     pipeline->SetCloseButtonStatus(isEnabled);
281 }
282 
SetShowMenuAnimation(const RefPtr<FrameNode> & menu,bool isInSubWindow)283 void OverlayManager::SetShowMenuAnimation(const RefPtr<FrameNode>& menu, bool isInSubWindow)
284 {
285     BlurLowerNode(menu);
286 
287     AnimationOption option;
288     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
289     option.SetDuration(MENU_ANIMATION_DURATION);
290     option.SetFillMode(FillMode::FORWARDS);
291     option.SetOnFinishEvent(
292         [weak = WeakClaim(this), menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(), isInSubWindow] {
293             ContainerScope scope(id);
294             auto pipeline = PipelineBase::GetCurrentContext();
295             CHECK_NULL_VOID_NOLOG(pipeline);
296             auto taskExecutor = pipeline->GetTaskExecutor();
297             CHECK_NULL_VOID_NOLOG(taskExecutor);
298             taskExecutor->PostTask(
299                 [weak, menuWK, id, isInSubWindow]() {
300                     auto menu = menuWK.Upgrade();
301                     auto overlayManager = weak.Upgrade();
302                     CHECK_NULL_VOID_NOLOG(menu && overlayManager);
303                     ContainerScope scope(id);
304                     if (isInSubWindow) {
305                         SubwindowManager::GetInstance()->RequestFocusSubwindow(id);
306                     } else {
307                         overlayManager->FocusOverlayNode(menu);
308                     }
309                     overlayManager->CallOnShowMenuCallback();
310                 },
311                 TaskExecutor::TaskType::UI);
312         });
313 
314     auto pattern = menu->GetPattern<MenuWrapperPattern>();
315     pattern->SetAniamtinOption(option);
316     pattern->SetFirstShow();
317 }
318 
PopMenuAnimation(const RefPtr<FrameNode> & menu)319 void OverlayManager::PopMenuAnimation(const RefPtr<FrameNode>& menu)
320 {
321     ResetLowerNodeFocusable(menu);
322 
323     AnimationOption option;
324     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
325     option.SetDuration(MENU_ANIMATION_DURATION);
326     option.SetFillMode(FillMode::FORWARDS);
327     option.SetOnFinishEvent([rootWeak = rootNodeWeak_, menuWK = WeakClaim(RawPtr(menu)), id = Container::CurrentId(),
328                                 weak = WeakClaim(this)] {
329         ContainerScope scope(id);
330         auto pipeline = PipelineBase::GetCurrentContext();
331         CHECK_NULL_VOID_NOLOG(pipeline);
332         auto taskExecutor = pipeline->GetTaskExecutor();
333         CHECK_NULL_VOID_NOLOG(taskExecutor);
334         taskExecutor->PostTask(
335             [rootWeak, menuWK, id, weak]() {
336                 auto menu = menuWK.Upgrade();
337                 auto root = rootWeak.Upgrade();
338                 auto overlayManager = weak.Upgrade();
339                 CHECK_NULL_VOID_NOLOG(menu && overlayManager);
340                 ContainerScope scope(id);
341                 auto container = Container::Current();
342                 if (container && container->IsScenceBoardWindow()) {
343                     root = overlayManager->FindWindowScene(menu);
344                 }
345                 CHECK_NULL_VOID(root);
346                 overlayManager->CallOnHideMenuCallback();
347                 auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
348                 // clear contextMenu then return
349                 if (menuWrapperPattern && menuWrapperPattern->IsContextMenu()) {
350                     SubwindowManager::GetInstance()->ClearMenuNG(id);
351                     return;
352                 }
353                 overlayManager->BlurOverlayNode(menu);
354                 root->RemoveChild(menu);
355                 root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
356             },
357             TaskExecutor::TaskType::UI);
358     });
359     auto context = menu->GetRenderContext();
360     CHECK_NULL_VOID(context);
361     auto pipeline = PipelineBase::GetCurrentContext();
362     CHECK_NULL_VOID(pipeline);
363     auto theme = pipeline->GetTheme<SelectTheme>();
364     CHECK_NULL_VOID(theme);
365     auto menuWrapperPattern = menu->GetPattern<MenuWrapperPattern>();
366     CHECK_NULL_VOID(menuWrapperPattern);
367     auto menuAnimationOffset = menuWrapperPattern->GetAnimationOffset();
368     AnimationUtils::Animate(
369         option,
370         [context, menuAnimationOffset]() {
371             context->UpdateOpacity(0.0);
372             context->UpdateOffset(menuAnimationOffset);
373         },
374         option.GetOnFinishEvent());
375     // start animation immediately
376     pipeline->RequestFrame();
377 }
378 
ShowToast(const std::string & message,int32_t duration,const std::string & bottom,bool isRightToLeft)379 void OverlayManager::ShowToast(
380     const std::string& message, int32_t duration, const std::string& bottom, bool isRightToLeft)
381 {
382     LOGI("OverlayManager::ShowToast");
383     auto container = Container::Current();
384     if (container && container->IsScenceBoardWindow()) {
385         SubwindowManager::GetInstance()->ShowToast(message, duration, bottom);
386         return;
387     }
388     auto context = PipelineContext::GetCurrentContext();
389     CHECK_NULL_VOID(context);
390     auto rootNode = context->GetRootElement();
391     CHECK_NULL_VOID(rootNode);
392 
393     // only one toast
394     for (auto [id, toastNodeWeak] : toastMap_) {
395         rootNode->RemoveChild(toastNodeWeak.Upgrade());
396     }
397     toastMap_.clear();
398 
399     auto toastNode = ToastView::CreateToastNode(message, bottom, isRightToLeft);
400     CHECK_NULL_VOID(toastNode);
401     auto toastId = toastNode->GetId();
402     // mount to parent
403     toastNode->MountToParent(rootNode);
404     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
405     toastMap_[toastId] = toastNode;
406     AnimationOption option;
407     auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
408     option.SetCurve(curve);
409     option.SetDuration(TOAST_ANIMATION_DURATION);
410     option.SetFillMode(FillMode::FORWARDS);
411     duration = std::max(duration, AceApplicationInfo::GetInstance().GetBarrierfreeDuration());
412     auto&& callback = [weak = WeakClaim(this), toastId, duration, id = Container::CurrentId()]() {
413         auto overlayManager = weak.Upgrade();
414         CHECK_NULL_VOID(overlayManager);
415         ContainerScope scope(id);
416         overlayManager->PopToast(toastId);
417     };
418     continuousTask_.Reset(callback);
419     option.SetOnFinishEvent([continuousTask = continuousTask_, duration, id = Container::CurrentId()] {
420         ContainerScope scope(id);
421         auto context = PipelineContext::GetCurrentContext();
422         CHECK_NULL_VOID_NOLOG(context);
423         context->GetTaskExecutor()->PostDelayedTask(continuousTask, TaskExecutor::TaskType::UI, duration);
424     });
425     auto ctx = toastNode->GetRenderContext();
426     CHECK_NULL_VOID(ctx);
427     ctx->UpdateOpacity(0.0);
428     ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
429     AnimationUtils::Animate(
430         option,
431         [ctx]() {
432             if (ctx) {
433                 ctx->UpdateOpacity(1.0);
434                 ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
435             }
436         },
437         option.GetOnFinishEvent());
438     toastNode->OnAccessibilityEvent(
439         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
440 }
441 
PopToast(int32_t toastId)442 void OverlayManager::PopToast(int32_t toastId)
443 {
444     LOGI("OverlayManager::PopToast");
445     AnimationOption option;
446     auto curve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
447     option.SetCurve(curve);
448     option.SetDuration(TOAST_ANIMATION_DURATION);
449     option.SetFillMode(FillMode::FORWARDS);
450     // OnFinishEvent should be executed in UI thread.
451     option.SetOnFinishEvent([weak = WeakClaim(this), toastId, id = Container::CurrentId()] {
452         ContainerScope scope(id);
453         auto context = PipelineContext::GetCurrentContext();
454         CHECK_NULL_VOID_NOLOG(context);
455         context->GetTaskExecutor()->PostTask(
456             [weak, toastId, id]() {
457                 ContainerScope scope(id);
458                 auto overlayManager = weak.Upgrade();
459                 CHECK_NULL_VOID_NOLOG(overlayManager);
460                 auto toastIter = overlayManager->toastMap_.find(toastId);
461                 if (toastIter == overlayManager->toastMap_.end()) {
462                     LOGI("No toast under pop");
463                     return;
464                 }
465                 auto toastUnderPop = toastIter->second.Upgrade();
466                 CHECK_NULL_VOID_NOLOG(toastUnderPop);
467                 LOGI("begin to pop toast, id is %{public}d", toastUnderPop->GetId());
468                 auto context = PipelineContext::GetCurrentContext();
469                 CHECK_NULL_VOID_NOLOG(context);
470                 auto rootNode = context->GetRootElement();
471                 CHECK_NULL_VOID_NOLOG(rootNode);
472                 rootNode->RemoveChild(toastUnderPop);
473                 overlayManager->toastMap_.erase(toastId);
474                 rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
475 
476                 auto container = Container::Current();
477                 CHECK_NULL_VOID_NOLOG(container);
478                 if (container->IsDialogContainer() ||
479                     (container->IsSubContainer() && rootNode->GetChildren().empty())) {
480                     // hide window when toast show in subwindow.
481                     SubwindowManager::GetInstance()->HideSubWindowNG();
482                 }
483             },
484             TaskExecutor::TaskType::UI);
485     });
486     auto toastIter = toastMap_.find(toastId);
487     if (toastIter == toastMap_.end()) {
488         LOGI("No toast under pop");
489         return;
490     }
491     auto toastUnderPop = toastIter->second.Upgrade();
492     CHECK_NULL_VOID_NOLOG(toastUnderPop);
493     auto ctx = toastUnderPop->GetRenderContext();
494     CHECK_NULL_VOID(ctx);
495     ctx->UpdateOpacity(1.0);
496     ctx->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
497     AnimationUtils::Animate(
498         option,
499         [ctx]() {
500             if (ctx) {
501                 ctx->UpdateOpacity(0.0);
502                 ctx->OnTransformTranslateUpdate({ 0.0f, TOAST_ANIMATION_POSITION, 0.0f });
503             }
504         },
505         option.GetOnFinishEvent());
506     // start animation immediately
507     auto pipeline = PipelineContext::GetCurrentContext();
508     CHECK_NULL_VOID(pipeline);
509     pipeline->RequestFrame();
510     AccessibilityEvent event;
511     event.type = AccessibilityEventType::CHANGE;
512     event.windowContentChangeTypes = WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE;
513     pipeline->SendEventToAccessibility(event);
514 }
515 
ShowPopup(int32_t targetId,const PopupInfo & popupInfo)516 void OverlayManager::ShowPopup(int32_t targetId, const PopupInfo& popupInfo)
517 {
518     LOGI("Show Popup, target id = %{public}d", targetId);
519     popupMap_[targetId] = popupInfo;
520     if (!popupInfo.markNeedUpdate) {
521         return;
522     }
523     popupMap_[targetId].markNeedUpdate = false;
524     auto popupNode = popupInfo.popupNode;
525     CHECK_NULL_VOID(popupNode);
526     auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
527     CHECK_NULL_VOID(layoutProp);
528     auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
529     CHECK_NULL_VOID(paintProperty);
530     auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
531 
532     auto rootNode = rootNodeWeak_.Upgrade();
533     auto container = Container::Current();
534     if (container && container->IsScenceBoardWindow()) {
535         rootNode = FindWindowScene(popupInfo.target.Upgrade());
536     }
537     CHECK_NULL_VOID(rootNode);
538 
539     const auto& rootChildren = rootNode->GetChildren();
540     auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
541     if (iter != rootChildren.rend()) {
542         return;
543     }
544 
545     // attach popupNode before entering animation
546     LOGI("popup begin push, target id = %{public}d", targetId);
547     popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(true);
548     popupNode->MountToParent(rootNode);
549     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
550     popupMap_[targetId].isCurrentOnShow = true;
551 
552     auto popupPattern = popupNode->GetPattern<BubblePattern>();
553     CHECK_NULL_VOID(popupPattern);
554     if (isTypeWithOption) {
555         BlurLowerNode(popupNode);
556         auto onFinish = [popupNodeWk = WeakPtr<FrameNode>(popupNode), weak = WeakClaim(this)]() {
557             auto overlayManager = weak.Upgrade();
558             auto popupNode = popupNodeWk.Upgrade();
559             CHECK_NULL_VOID(overlayManager && popupNode);
560             overlayManager->FocusOverlayNode(popupNode);
561         };
562         popupPattern->StartEnteringAnimation(onFinish);
563     } else {
564         popupPattern->StartEnteringAnimation(nullptr);
565     }
566 }
567 
HidePopup(int32_t targetId,const PopupInfo & popupInfo)568 void OverlayManager::HidePopup(int32_t targetId, const PopupInfo& popupInfo)
569 {
570     LOGI("Hide Popup, target id = %{public}d", targetId);
571     popupMap_[targetId] = popupInfo;
572     if (!popupInfo.markNeedUpdate) {
573         return;
574     }
575     popupMap_[targetId].markNeedUpdate = false;
576     auto popupNode = popupInfo.popupNode;
577     CHECK_NULL_VOID(popupNode);
578     auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
579     auto isShowInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
580     CHECK_NULL_VOID(layoutProp);
581     auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
582     CHECK_NULL_VOID(paintProperty);
583     auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
584 
585     auto rootNode = rootNodeWeak_.Upgrade();
586     auto container = Container::Current();
587     if (container && container->IsScenceBoardWindow()) {
588         rootNode = FindWindowScene(popupInfo.target.Upgrade());
589     }
590     CHECK_NULL_VOID(rootNode);
591 
592     const auto& rootChildren = rootNode->GetChildren();
593     auto iter = std::find(rootChildren.rbegin(), rootChildren.rend(), popupNode);
594     if (iter == rootChildren.rend()) {
595         return;
596     }
597 
598     auto popupPattern = popupNode->GetPattern<BubblePattern>();
599     CHECK_NULL_VOID(popupPattern);
600     if (popupPattern->GetTransitionStatus() == TransitionStatus::EXITING) {
601         return;
602     }
603     popupPattern->SetTransitionStatus(TransitionStatus::EXITING);
604     if (isTypeWithOption) {
605         ResetLowerNodeFocusable(popupNode);
606     }
607     // detach popupNode after exiting animation
608     popupMap_[targetId].isCurrentOnShow = false;
609     popupNode->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
610     popupPattern->StartExitingAnimation(
611         [isShowInSubWindow, isTypeWithOption, popupNodeWk = WeakPtr<FrameNode>(popupNode),
612             rootNodeWk = WeakPtr<UINode>(rootNode), weak = WeakClaim(this)]() {
613             LOGI("popup begin pop");
614             auto rootNode = rootNodeWk.Upgrade();
615             auto popupNode = popupNodeWk.Upgrade();
616             auto overlayManager = weak.Upgrade();
617             CHECK_NULL_VOID(rootNode && popupNode && overlayManager);
618 
619             auto popupPattern = popupNode->GetPattern<BubblePattern>();
620             CHECK_NULL_VOID(popupPattern);
621             popupPattern->SetSkipHotArea(true);
622             rootNode->RemoveChild(popupNode);
623             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
624             if (isTypeWithOption) {
625                 overlayManager->BlurOverlayNode(popupNode);
626             }
627             if (isShowInSubWindow) {
628                 auto subwindow = SubwindowManager::GetInstance();
629                 CHECK_NULL_VOID(subwindow);
630                 subwindow->HideSubWindowNG();
631             }
632         });
633     popupNode->OnAccessibilityEvent(
634         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
635 #ifdef ENABLE_DRAG_FRAMEWORK
636     RemoveEventColumn();
637     RemovePixelMapAnimation(false, 0, 0);
638     RemoveFilter();
639 #endif // ENABLE_DRAG_FRAMEWORK
640 }
641 
ShowIndexerPopup(int32_t targetId,RefPtr<FrameNode> & customNode)642 void OverlayManager::ShowIndexerPopup(int32_t targetId, RefPtr<FrameNode>& customNode)
643 {
644     CHECK_NULL_VOID(customNode);
645     auto rootNode = rootNodeWeak_.Upgrade();
646     CHECK_NULL_VOID(rootNode);
647     if (!customPopupMap_[targetId] || customPopupMap_[targetId] != customNode) {
648         customPopupMap_[targetId] = customNode;
649         customNode->MountToParent(rootNode);
650         customNode->MarkModifyDone();
651         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
652     }
653 }
654 
RemoveIndexerPopupById(int32_t targetId)655 void OverlayManager::RemoveIndexerPopupById(int32_t targetId)
656 {
657     if (customPopupMap_.empty()) {
658         return;
659     }
660     auto rootNode = rootNodeWeak_.Upgrade();
661     CHECK_NULL_VOID(rootNode);
662     auto iter = customPopupMap_.find(targetId);
663     if (iter != customPopupMap_.end()) {
664         rootNode->RemoveChild(iter->second);
665         customPopupMap_.erase(iter);
666         rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
667     }
668 }
669 
RemoveIndexerPopup()670 void OverlayManager::RemoveIndexerPopup()
671 {
672     if (customPopupMap_.empty()) {
673         return;
674     }
675     auto rootNode = rootNodeWeak_.Upgrade();
676     CHECK_NULL_VOID(rootNode);
677     for (const auto& popup : customPopupMap_) {
678         auto popupNode = popup.second;
679         rootNode->RemoveChild(popupNode);
680     }
681     customPopupMap_.clear();
682     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
683 }
684 
HideCustomPopups()685 void OverlayManager::HideCustomPopups()
686 {
687     if (popupMap_.empty()) {
688         LOGD("OverlayManager: popupMap is empty");
689         return;
690     }
691     for (const auto& popup : popupMap_) {
692         auto popupInfo = popup.second;
693         if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
694             auto targetNodeId = popupInfo.target.Upgrade()->GetId();
695             auto popupNode = popupInfo.popupNode;
696             CHECK_NULL_VOID(popupNode);
697             auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
698             CHECK_NULL_VOID(layoutProp);
699             auto paintProperty = popupNode->GetPaintProperty<BubbleRenderProperty>();
700             CHECK_NULL_VOID(paintProperty);
701             auto isTypeWithOption = paintProperty->GetPrimaryButtonShow().value_or(false);
702             // if use popup with option, skip
703             if (isTypeWithOption) {
704                 continue;
705             }
706             popupInfo.markNeedUpdate = true;
707             popupInfo.popupId = -1;
708             auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
709             if (showInSubWindow) {
710                 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
711             } else {
712                 HidePopup(targetNodeId, popupInfo);
713             }
714         }
715     }
716 }
717 
HideAllPopups()718 void OverlayManager::HideAllPopups()
719 {
720     if (popupMap_.empty()) {
721         LOGD("OverlayManager: popupMap is empty");
722         return;
723     }
724     for (const auto& popup : popupMap_) {
725         auto popupInfo = popup.second;
726         if (popupInfo.isCurrentOnShow && popupInfo.target.Upgrade()) {
727             auto targetNodeId = popupInfo.target.Upgrade()->GetId();
728             auto popupNode = popupInfo.popupNode;
729             CHECK_NULL_VOID(popupNode);
730             auto layoutProp = popupNode->GetLayoutProperty<BubbleLayoutProperty>();
731             CHECK_NULL_VOID(layoutProp);
732             popupInfo.markNeedUpdate = true;
733             popupInfo.popupId = -1;
734             auto showInSubWindow = layoutProp->GetShowInSubWindow().value_or(false);
735             if (showInSubWindow) {
736                 SubwindowManager::GetInstance()->HidePopupNG(targetNodeId);
737             } else {
738                 HidePopup(targetNodeId, popupInfo);
739             }
740         }
741     }
742 }
743 
ErasePopup(int32_t targetId)744 void OverlayManager::ErasePopup(int32_t targetId)
745 {
746     if (popupMap_.find(targetId) != popupMap_.end()) {
747         LOGI("Erase popup id %{public}d when destroyed.", targetId);
748         auto rootNode = rootNodeWeak_.Upgrade();
749         CHECK_NULL_VOID(rootNode);
750         rootNode->RemoveChild(popupMap_[targetId].popupNode);
751         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
752         popupMap_.erase(targetId);
753     }
754 }
755 
ShowMenuHelper(RefPtr<FrameNode> & menu,int32_t targetId,const NG::OffsetF & offset)756 bool OverlayManager::ShowMenuHelper(RefPtr<FrameNode>& menu, int32_t targetId, const NG::OffsetF& offset)
757 {
758     if (!menu) {
759         // get existing menuNode
760         auto it = menuMap_.find(targetId);
761         if (it != menuMap_.end()) {
762             menu = it->second;
763         } else {
764             LOGW("menuNode doesn't exists %{public}d", targetId);
765         }
766     } else {
767         // creating new menu
768         menuMap_[targetId] = menu;
769         LOGI("menuNode %{public}d added to map", targetId);
770     }
771     CHECK_NULL_RETURN(menu, false);
772 
773     RefPtr<FrameNode> menuFrameNode = menu;
774     if (menu->GetTag() != V2::MENU_ETS_TAG) {
775         auto menuChild = menu->GetChildAtIndex(0);
776         CHECK_NULL_RETURN(menuChild, false);
777         menuFrameNode = DynamicCast<FrameNode>(menuChild);
778     }
779 
780     auto props = menuFrameNode->GetLayoutProperty<MenuLayoutProperty>();
781     CHECK_NULL_RETURN(props, false);
782     props->UpdateMenuOffset(offset);
783     menuFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
784     return true;
785 }
786 
ShowMenu(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)787 void OverlayManager::ShowMenu(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
788 {
789     if (!ShowMenuHelper(menu, targetId, offset)) {
790         LOGW("show menu failed");
791         return;
792     }
793     auto rootNode = rootNodeWeak_.Upgrade();
794     auto container = Container::Current();
795     if (container && container->IsScenceBoardWindow()) {
796         auto wrapperPattern = AceType::DynamicCast<MenuWrapperPattern>(menu->GetPattern());
797         CHECK_NULL_VOID(wrapperPattern);
798         auto menuChild = wrapperPattern->GetMenu();
799         CHECK_NULL_VOID(menuChild);
800         auto menuPattern = AceType::DynamicCast<MenuPattern>(menuChild->GetPattern());
801         CHECK_NULL_VOID(menuPattern);
802         rootNode = FindWindowScene(FrameNode::GetFrameNode(menuPattern->GetTargetTag(), menuPattern->GetTargetId()));
803     }
804     CHECK_NULL_VOID(rootNode);
805     auto rootChildren = rootNode->GetChildren();
806     auto iter = std::find(rootChildren.begin(), rootChildren.end(), menu);
807     // menuNode already showing
808     if (iter != rootChildren.end()) {
809         LOGW("menuNode already appended");
810     } else {
811         menu->MountToParent(rootNode);
812         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
813         menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
814         SetShowMenuAnimation(menu);
815         menu->MarkModifyDone();
816     }
817     menu->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
818 }
819 
820 // subwindow only contains one menu instance.
ShowMenuInSubWindow(int32_t targetId,const NG::OffsetF & offset,RefPtr<FrameNode> menu)821 void OverlayManager::ShowMenuInSubWindow(int32_t targetId, const NG::OffsetF& offset, RefPtr<FrameNode> menu)
822 {
823     auto menuOffset = offset;
824     auto currentSubwindow = SubwindowManager::GetInstance()->GetCurrentWindow();
825     if (currentSubwindow) {
826         auto subwindowRect = currentSubwindow->GetRect();
827         menuOffset -= subwindowRect.GetOffset();
828     }
829     if (!ShowMenuHelper(menu, targetId, menuOffset)) {
830         LOGW("show menu failed");
831         return;
832     }
833     auto rootNode = rootNodeWeak_.Upgrade();
834     CHECK_NULL_VOID(rootNode);
835     rootNode->Clean();
836     menu->MountToParent(rootNode);
837     SetShowMenuAnimation(menu, true);
838     menu->MarkModifyDone();
839     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
840 
841     // set subwindow container id in menu.
842     auto menuPattern = menu->GetPattern<PopupBasePattern>();
843     CHECK_NULL_VOID(menuPattern);
844     menuPattern->SetContainerId(Container::CurrentId());
845     LOGI("menuNode mounted in subwindow");
846 }
847 
HideMenuInSubWindow(const RefPtr<FrameNode> & menu,int32_t targetId)848 void OverlayManager::HideMenuInSubWindow(const RefPtr<FrameNode>& menu, int32_t targetId)
849 {
850     LOGI("OverlayManager::HideMenuInSubWindow");
851     if (menuMap_.find(targetId) == menuMap_.end()) {
852         LOGW("OverlayManager: menuNode %{public}d not found in map", targetId);
853     }
854     CHECK_NULL_VOID(menu);
855     PopMenuAnimation(menu);
856 }
857 
HideMenuInSubWindow()858 void OverlayManager::HideMenuInSubWindow()
859 {
860     LOGI("OverlayManager::HideMenuInSubWindow from close");
861     if (menuMap_.empty()) {
862         LOGW("OverlayManager: menuMap is empty");
863         return;
864     }
865     auto rootNode = rootNodeWeak_.Upgrade();
866     for (const auto& child : rootNode->GetChildren()) {
867         auto node = DynamicCast<FrameNode>(child);
868         PopMenuAnimation(node);
869     }
870 }
871 
HideMenu(const RefPtr<FrameNode> & menu,int32_t targetId,bool isMenuOnTouch)872 void OverlayManager::HideMenu(const RefPtr<FrameNode>& menu, int32_t targetId, bool isMenuOnTouch)
873 {
874     LOGI("OverlayManager::HideMenuNode menu targetId is %{public}d", targetId);
875     if (menuMap_.find(targetId) == menuMap_.end()) {
876         LOGW("OverlayManager: menuNode %{public}d not found in map", targetId);
877     }
878     PopMenuAnimation(menu);
879     menu->OnAccessibilityEvent(AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
880 #ifdef ENABLE_DRAG_FRAMEWORK
881     RemoveEventColumn();
882     if (isMenuOnTouch) {
883         RemovePixelMap();
884     } else {
885         RemovePixelMapAnimation(false, 0, 0);
886     }
887     RemoveFilter();
888 #endif // ENABLE_DRAG_FRAMEWORK
889 }
890 
HideAllMenus()891 void OverlayManager::HideAllMenus()
892 {
893     LOGD("OverlayManager::HideAllMenus");
894     auto container = Container::Current();
895     if (container && container->IsScenceBoardWindow()) {
896         for (const auto& windowScene : windowSceneSet_) {
897             if (!windowScene.Upgrade()) {
898                 continue;
899             }
900             for (const auto& child : windowScene.Upgrade()->GetChildren()) {
901                 auto node = DynamicCast<FrameNode>(child);
902                 if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
903                     PopMenuAnimation(node);
904                 }
905             }
906         }
907         return;
908     }
909 
910     auto rootNode = rootNodeWeak_.Upgrade();
911     CHECK_NULL_VOID(rootNode);
912     for (const auto& child : rootNode->GetChildren()) {
913         auto node = DynamicCast<FrameNode>(child);
914         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
915             PopMenuAnimation(node);
916         }
917     }
918 }
919 
DeleteMenu(int32_t targetId)920 void OverlayManager::DeleteMenu(int32_t targetId)
921 {
922     LOGI("OverlayManager::DeleteMenuNode");
923     auto it = menuMap_.find(targetId);
924     if (it == menuMap_.end()) {
925         LOGW("OverlayManager: menuNode %{public}d doesn't exist", targetId);
926         return;
927     }
928     menuMap_.erase(it);
929 }
930 
CleanMenuInSubWindow()931 void OverlayManager::CleanMenuInSubWindow()
932 {
933     LOGI("OverlayManager::CleanMenuInSubWindow");
934     auto rootNode = rootNodeWeak_.Upgrade();
935     CHECK_NULL_VOID(rootNode);
936     for (const auto& child : rootNode->GetChildren()) {
937         auto node = DynamicCast<FrameNode>(child);
938         if (node && node->GetTag() == V2::MENU_WRAPPER_ETS_TAG) {
939             rootNode->RemoveChild(node);
940             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
941             break;
942         }
943     }
944 }
945 
BeforeShowDialog(const RefPtr<FrameNode> & node)946 void OverlayManager::BeforeShowDialog(const RefPtr<FrameNode>& node)
947 {
948     CHECK_NULL_VOID(node);
949     if (dialogMap_.find(node->GetId()) != dialogMap_.end()) {
950         LOGW("dialog #%{public}d exists", node->GetId());
951         return;
952     }
953     dialogMap_[node->GetId()] = node;
954 }
955 
ShowDialog(const DialogProperties & dialogProps,std::function<void ()> && buildFunc,bool isRightToLeft)956 RefPtr<FrameNode> OverlayManager::ShowDialog(
957     const DialogProperties& dialogProps, std::function<void()>&& buildFunc, bool isRightToLeft)
958 {
959     LOGI("OverlayManager::ShowDialog");
960     RefPtr<UINode> customNode;
961     // create custom builder content
962     if (buildFunc) {
963         NG::ScopedViewStackProcessor builderViewStackProcessor;
964         buildFunc();
965         customNode = NG::ViewStackProcessor::GetInstance()->Finish();
966         CHECK_NULL_RETURN(customNode, nullptr);
967     }
968 
969     auto dialog = DialogView::CreateDialogNode(dialogProps, customNode);
970     BeforeShowDialog(dialog);
971     OpenDialogAnimation(dialog);
972     dialogCount_++;
973     // set close button disable
974     SetContainerButtonEnable(false);
975     return dialog;
976 }
977 
ShowCustomDialog(const RefPtr<FrameNode> & customNode)978 void OverlayManager::ShowCustomDialog(const RefPtr<FrameNode>& customNode)
979 {
980     LOGI("OverlayManager::ShowCustomDialog");
981     BeforeShowDialog(customNode);
982     OpenDialogAnimation(customNode);
983 }
984 
ShowDateDialog(const DialogProperties & dialogProps,const DatePickerSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)985 void OverlayManager::ShowDateDialog(const DialogProperties& dialogProps, const DatePickerSettingData& settingData,
986     std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
987 {
988     LOGI("OverlayManager::ShowDateDialogPicker");
989     auto dialogNode = DatePickerDialogView::Show(
990         dialogProps, std::move(settingData), std::move(dialogEvent), std::move(dialogCancelEvent));
991     BeforeShowDialog(dialogNode);
992     OpenDialogAnimation(dialogNode);
993 }
994 
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)995 void OverlayManager::ShowTimeDialog(const DialogProperties& dialogProps, const TimePickerSettingData& settingData,
996     std::map<std::string, PickerTime> timePickerProperty, std::map<std::string, NG::DialogEvent> dialogEvent,
997     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
998 {
999     LOGI("OverlayManager::ShowTimeDialogPicker");
1000     auto dialogNode = TimePickerDialogView::Show(
1001         dialogProps, settingData, std::move(timePickerProperty), std::move(dialogEvent), std::move(dialogCancelEvent));
1002     BeforeShowDialog(dialogNode);
1003     OpenDialogAnimation(dialogNode);
1004 }
1005 
ShowTextDialog(const DialogProperties & dialogProps,const TextPickerSettingData & settingData,std::map<std::string,NG::DialogTextEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1006 void OverlayManager::ShowTextDialog(const DialogProperties& dialogProps, const TextPickerSettingData& settingData,
1007     std::map<std::string, NG::DialogTextEvent> dialogEvent,
1008     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1009 {
1010     LOGI("OverlayManager::ShowTextDialogPicker");
1011     auto dialogNode =
1012         TextPickerDialogView::Show(dialogProps, settingData, std::move(dialogEvent), std::move(dialogCancelEvent));
1013     BeforeShowDialog(dialogNode);
1014     OpenDialogAnimation(dialogNode);
1015 }
1016 
ShowCalendarDialog(const DialogProperties & dialogProps,const CalendarSettingData & settingData,std::map<std::string,NG::DialogEvent> dialogEvent,std::map<std::string,NG::DialogGestureEvent> dialogCancelEvent)1017 void OverlayManager::ShowCalendarDialog(const DialogProperties& dialogProps, const CalendarSettingData& settingData,
1018     std::map<std::string, NG::DialogEvent> dialogEvent, std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent)
1019 {
1020     auto dialogNode =
1021         CalendarDialogView::Show(dialogProps, settingData, std::move(dialogEvent), std::move(dialogCancelEvent));
1022     BeforeShowDialog(dialogNode);
1023     OpenDialogAnimation(dialogNode);
1024 }
1025 
RemoveDialogFromMap(const RefPtr<FrameNode> & node)1026 void OverlayManager::RemoveDialogFromMap(const RefPtr<FrameNode>& node)
1027 {
1028     CHECK_NULL_VOID(node);
1029     if (dialogMap_.find(node->GetId()) == dialogMap_.end()) {
1030         LOGW("dialog #%{public}d node in map", node->GetId());
1031         return;
1032     }
1033     dialogMap_.erase(node->GetId());
1034 }
1035 
DialogInMapHoldingFocus()1036 bool OverlayManager::DialogInMapHoldingFocus()
1037 {
1038     if (dialogMap_.empty()) {
1039         return false;
1040     }
1041     auto iter = dialogMap_.begin();
1042     while (iter != dialogMap_.end()) {
1043         auto dialogNode = (*iter).second;
1044         if (dialogNode && dialogNode->GetFocusHub() && dialogNode->GetFocusHub()->IsCurrentFocus()) {
1045             return true;
1046         }
1047         iter++;
1048     }
1049     return false;
1050 }
1051 
CloseDialog(const RefPtr<FrameNode> & dialogNode)1052 void OverlayManager::CloseDialog(const RefPtr<FrameNode>& dialogNode)
1053 {
1054     LOGI("OverlayManager::CloseDialog");
1055     RemoveDialogFromMap(dialogNode);
1056     if (dialogNode->IsRemoving()) {
1057         // already in close animation
1058         return;
1059     }
1060     dialogNode->MarkRemoving();
1061     CloseDialogAnimation(dialogNode);
1062     dialogCount_--;
1063     // set close button enable
1064     if (dialogCount_ == 0) {
1065         SetContainerButtonEnable(true);
1066     }
1067     dialogNode->OnAccessibilityEvent(
1068         AccessibilityEventType::CHANGE, WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_SUBTREE);
1069     CallOnHideDialogCallback();
1070 }
1071 
RemoveDialog(const RefPtr<FrameNode> & overlay,bool isBackPressed,bool isPageRouter)1072 bool OverlayManager::RemoveDialog(const RefPtr<FrameNode>& overlay, bool isBackPressed, bool isPageRouter)
1073 {
1074     if (overlay->IsRemoving()) {
1075         return false;
1076     }
1077     if (FireBackPressEvent()) {
1078         return true;
1079     }
1080     auto hub = overlay->GetEventHub<DialogEventHub>();
1081     if (!isPageRouter && hub) {
1082         hub->FireCancelEvent();
1083     }
1084     CloseDialog(overlay);
1085     if (isBackPressed) {
1086         SetBackPressEvent(nullptr);
1087     }
1088     return true;
1089 }
1090 
RemoveBubble(const RefPtr<FrameNode> & overlay)1091 bool OverlayManager::RemoveBubble(const RefPtr<FrameNode>& overlay)
1092 {
1093     for (const auto& popup : popupMap_) {
1094         auto targetId = popup.first;
1095         auto popupInfo = popup.second;
1096         if (overlay == popupInfo.popupNode) {
1097             popupInfo.markNeedUpdate = true;
1098             HidePopup(targetId, popupInfo);
1099             return true;
1100         }
1101     }
1102     return false;
1103 }
1104 
RemoveMenu(const RefPtr<FrameNode> & overlay)1105 bool OverlayManager::RemoveMenu(const RefPtr<FrameNode>& overlay)
1106 {
1107     auto menuWrapperPattern = overlay->GetPattern<MenuWrapperPattern>();
1108     CHECK_NULL_RETURN(menuWrapperPattern, false);
1109     menuWrapperPattern->HideMenu();
1110     return true;
1111 }
1112 
RemoveOverlay(bool isBackPressed,bool isPageRouter)1113 bool OverlayManager::RemoveOverlay(bool isBackPressed, bool isPageRouter)
1114 {
1115     auto rootNode = rootNodeWeak_.Upgrade();
1116     CHECK_NULL_RETURN(rootNode, true);
1117     RemoveIndexerPopup();
1118     DestroyKeyboard();
1119     if (rootNode->GetChildren().size() > 1) {
1120         // stage node is at index 0, remove overlay at last
1121         auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
1122         CHECK_NULL_RETURN(overlay, false);
1123         // close dialog with animation
1124         auto pattern = overlay->GetPattern();
1125         if (InstanceOf<DialogPattern>(pattern)) {
1126             return RemoveDialog(overlay, isBackPressed, isPageRouter);
1127         }
1128         if (InstanceOf<BubblePattern>(pattern)) {
1129             return RemoveBubble(overlay);
1130         }
1131         if (InstanceOf<MenuWrapperPattern>(pattern)) {
1132             return RemoveMenu(overlay);
1133         }
1134         // remove navDestination in navigation first
1135         do {
1136             auto pipeline = PipelineContext::GetCurrentContext();
1137             CHECK_NULL_BREAK(pipeline);
1138             auto navigationGroupNode =
1139                 AceType::DynamicCast<NavigationGroupNode>(pipeline->FindNavigationNodeToHandleBack(overlay));
1140             CHECK_NULL_BREAK(navigationGroupNode);
1141             return true;
1142         } while (0);
1143         if (!modalStack_.empty()) {
1144             if (isPageRouter) {
1145                 return RemoveAllModalInOverlay();
1146             } else {
1147                 return RemoveModalInOverlay();
1148             }
1149         }
1150         rootNode->RemoveChild(overlay);
1151         rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1152         LOGI("overlay removed successfully");
1153         return true;
1154     }
1155     LOGI("No overlay in this page.");
1156     return false;
1157 }
1158 
RemoveModalInOverlay()1159 bool OverlayManager::RemoveModalInOverlay()
1160 {
1161     auto rootNode = rootNodeWeak_.Upgrade();
1162     CHECK_NULL_RETURN(rootNode, true);
1163     auto topModalNode = modalStack_.top().Upgrade();
1164     CHECK_NULL_RETURN(topModalNode, false);
1165     ModalPageLostFocus(topModalNode);
1166     if (!ModalExitProcess(topModalNode)) {
1167         return false;
1168     }
1169     modalStack_.pop();
1170     if (!modalList_.empty()) {
1171         modalList_.pop_back();
1172     }
1173     FireModalPageHide();
1174     SaveLastModalNode();
1175     return true;
1176 }
1177 
RemoveAllModalInOverlay()1178 bool OverlayManager::RemoveAllModalInOverlay()
1179 {
1180     auto rootNode = rootNodeWeak_.Upgrade();
1181     CHECK_NULL_RETURN(rootNode, true);
1182     while (!modalStack_.empty()) {
1183         auto topModalNode = modalStack_.top().Upgrade();
1184         if (!topModalNode) {
1185             continue;
1186         }
1187         ModalPageLostFocus(topModalNode);
1188         if (!ModalExitProcess(topModalNode)) {
1189             continue;
1190         }
1191         modalStack_.pop();
1192         if (!modalList_.empty()) {
1193             modalList_.pop_back();
1194         }
1195         FireModalPageHide();
1196         SaveLastModalNode();
1197     }
1198     return true;
1199 }
1200 
ModalExitProcess(const RefPtr<FrameNode> & topModalNode)1201 bool OverlayManager::ModalExitProcess(const RefPtr<FrameNode>& topModalNode)
1202 {
1203     auto rootNode = rootNodeWeak_.Upgrade();
1204     CHECK_NULL_RETURN(rootNode, true);
1205     if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1206         topModalNode->GetPattern<ModalPresentationPattern>()->FireCallback("false");
1207         auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1208         CHECK_NULL_RETURN(builder, false);
1209         auto modalTransition = topModalNode->GetPattern<ModalPresentationPattern>()->GetType();
1210         if (builder->GetRenderContext()->HasTransition()) {
1211             topModalNode->Clean(false, true);
1212             topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1213         }
1214         if (modalTransition == ModalTransition::DEFAULT) {
1215             PlayDefaultModalTransition(topModalNode, false);
1216         } else if (modalTransition == ModalTransition::ALPHA) {
1217             PlayAlphaModalTransition(topModalNode, false);
1218         } else if (!builder->GetRenderContext()->HasTransition()) {
1219             rootNode->RemoveChild(topModalNode);
1220             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1221         }
1222         topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
1223     } else if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
1224         topModalNode->GetPattern<SheetPresentationPattern>()->FireCallback("false");
1225         auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetLastChild());
1226         CHECK_NULL_RETURN(builder, false);
1227         if (builder->GetRenderContext()->HasTransition()) {
1228             topModalNode->Clean(false, true);
1229             topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1230         }
1231         PlaySheetTransition(topModalNode, false);
1232         topModalNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
1233     }
1234     return true;
1235 }
1236 
RemoveOverlayInSubwindow()1237 bool OverlayManager::RemoveOverlayInSubwindow()
1238 {
1239     LOGI("OverlayManager::RemoveOverlayInSubwindow");
1240     auto rootNode = rootNodeWeak_.Upgrade();
1241     CHECK_NULL_RETURN(rootNode, false);
1242     if (rootNode->GetChildren().empty()) {
1243         LOGI("No overlay in this subwindow.");
1244         return false;
1245     }
1246 
1247     // remove the overlay node just mounted in subwindow
1248     auto overlay = DynamicCast<FrameNode>(rootNode->GetLastChild());
1249     CHECK_NULL_RETURN(overlay, false);
1250     // close dialog with animation
1251     auto pattern = overlay->GetPattern();
1252     if (InstanceOf<DialogPattern>(pattern)) {
1253         return RemoveDialog(overlay, false, false);
1254     }
1255     if (InstanceOf<BubblePattern>(pattern)) {
1256         overlay->GetEventHub<BubbleEventHub>()->FireChangeEvent(false);
1257         for (const auto& popup : popupMap_) {
1258             auto targetId = popup.first;
1259             auto popupInfo = popup.second;
1260             if (overlay == popupInfo.popupNode) {
1261                 popupMap_.erase(targetId);
1262                 rootNode->RemoveChild(overlay);
1263                 rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1264                 if (rootNode->GetChildren().empty()) {
1265                     SubwindowManager::GetInstance()->HideSubWindowNG();
1266                 }
1267                 return true;
1268             }
1269         }
1270         return false;
1271     }
1272     if (InstanceOf<MenuWrapperPattern>(pattern)) {
1273         return RemoveMenu(overlay);
1274     }
1275     rootNode->RemoveChild(overlay);
1276     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1277     if (rootNode->GetChildren().empty()) {
1278         SubwindowManager::GetInstance()->HideSubWindowNG();
1279     }
1280     LOGI("overlay removed successfully");
1281     return true;
1282 }
1283 
FocusOverlayNode(const RefPtr<FrameNode> & overlayNode,bool isInSubWindow)1284 void OverlayManager::FocusOverlayNode(const RefPtr<FrameNode>& overlayNode, bool isInSubWindow)
1285 {
1286     LOGI("OverlayManager::FocusOverlayNode when overlay node show");
1287     CHECK_NULL_VOID(overlayNode);
1288     auto focusHub = overlayNode->GetOrCreateFocusHub();
1289     CHECK_NULL_VOID(focusHub);
1290     focusHub->SetParentFocusable(true);
1291     focusHub->RequestFocusWithDefaultFocusFirstly();
1292 }
1293 
BlurOverlayNode(const RefPtr<FrameNode> & currentOverlay,bool isInSubWindow)1294 void OverlayManager::BlurOverlayNode(const RefPtr<FrameNode>& currentOverlay, bool isInSubWindow)
1295 {
1296     LOGI("OverlayManager::BlurOverlayNode");
1297     auto currentFocusHub = currentOverlay->GetOrCreateFocusHub();
1298     CHECK_NULL_VOID(currentFocusHub);
1299     currentFocusHub->SetParentFocusable(false);
1300     currentFocusHub->LostFocus();
1301 
1302     auto rootNode = rootNodeWeak_.Upgrade();
1303     CHECK_NULL_VOID(rootNode);
1304     if (rootNode->GetChildren().size() > 1) {
1305         auto collection = rootNode->GetChildren();
1306         for (auto iter = collection.rbegin(); iter != collection.rend(); ++iter) {
1307             auto overlay = DynamicCast<FrameNode>(*iter);
1308             CHECK_NULL_VOID(overlay);
1309             auto pattern = overlay->GetPattern();
1310             if (currentOverlay != overlay &&
1311                 (InstanceOf<DialogPattern>(pattern) || InstanceOf<MenuWrapperPattern>(pattern)) &&
1312                 !overlay->IsRemoving()) {
1313                 FocusOverlayNode(overlay, isInSubWindow);
1314                 return;
1315             }
1316         }
1317     }
1318     if (isInSubWindow) {
1319         // no need to set page request focus in sub window.
1320         return;
1321     }
1322 
1323     auto pageNode = GetLastPage();
1324     CHECK_NULL_VOID(pageNode);
1325     auto pageFocusHub = pageNode->GetFocusHub();
1326     CHECK_NULL_VOID(pageFocusHub);
1327     pageFocusHub->SetParentFocusable(true);
1328     pageFocusHub->RequestFocus();
1329 }
1330 
BlurLowerNode(const RefPtr<FrameNode> & currentOverlay)1331 void OverlayManager::BlurLowerNode(const RefPtr<FrameNode>& currentOverlay)
1332 {
1333     auto root = DynamicCast<FrameNode>(currentOverlay->GetParent());
1334     CHECK_NULL_VOID(root);
1335     auto children = root->GetChildren();
1336     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1337         auto node = DynamicCast<FrameNode>(*iter);
1338         CHECK_NULL_VOID(node);
1339         if (currentOverlay == node) {
1340             continue;
1341         }
1342         if (node->GetTag() == V2::STAGE_ETS_TAG) {
1343             auto pageNode = GetLastPage();
1344             CHECK_NULL_VOID(pageNode);
1345             auto pageFocusHub = pageNode->GetFocusHub();
1346             CHECK_NULL_VOID(pageFocusHub);
1347             pageFocusHub->SetParentFocusable(false);
1348             pageFocusHub->LostFocus();
1349             return;
1350         }
1351         auto focusHub = node->GetOrCreateFocusHub();
1352         if (focusHub->IsCurrentFocus()) {
1353             focusHub->SetParentFocusable(false);
1354             focusHub->LostFocus();
1355             return;
1356         }
1357     }
1358 }
1359 
ResetLowerNodeFocusable(const RefPtr<FrameNode> & currentOverlay)1360 void OverlayManager::ResetLowerNodeFocusable(const RefPtr<FrameNode>& currentOverlay)
1361 {
1362     CHECK_NULL_VOID(currentOverlay);
1363     auto root = DynamicCast<FrameNode>(currentOverlay->GetParent());
1364     CHECK_NULL_VOID(root);
1365     auto children = root->GetChildren();
1366     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1367         auto node = DynamicCast<FrameNode>(*iter);
1368         CHECK_NULL_VOID(node);
1369         if (currentOverlay == node) {
1370             continue;
1371         }
1372         if (node->GetTag() == V2::STAGE_ETS_TAG) {
1373             auto pageNode = GetLastPage();
1374             CHECK_NULL_VOID(pageNode);
1375             auto pageFocusHub = pageNode->GetFocusHub();
1376             CHECK_NULL_VOID(pageFocusHub);
1377             pageFocusHub->SetParentFocusable(true);
1378             return;
1379         }
1380         auto focusHub = node->GetOrCreateFocusHub();
1381         if (focusHub->IsCurrentFocus()) {
1382             focusHub->SetParentFocusable(true);
1383             return;
1384         }
1385     }
1386 }
1387 
SaveLastModalNode()1388 void OverlayManager::SaveLastModalNode()
1389 {
1390     auto pipeline = PipelineContext::GetCurrentContext();
1391     CHECK_NULL_VOID(pipeline);
1392     auto stageManager = pipeline->GetStageManager();
1393     CHECK_NULL_VOID(stageManager);
1394     auto pageNode = stageManager->GetLastPage();
1395     CHECK_NULL_VOID(pageNode);
1396     if (modalStack_.empty()) {
1397         lastModalNode_ = WeakClaim(RawPtr(pageNode));
1398     } else {
1399         auto topModalNode = modalStack_.top().Upgrade();
1400         modalStack_.pop();
1401         if (modalStack_.empty()) {
1402             lastModalNode_ = WeakClaim(RawPtr(pageNode));
1403         } else {
1404             lastModalNode_ = modalStack_.top();
1405         }
1406         modalStack_.push(topModalNode);
1407     }
1408 }
1409 
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,int32_t targetId)1410 void OverlayManager::BindContentCover(bool isShow, std::function<void(const std::string&)>&& callback,
1411     std::function<RefPtr<UINode>()>&& buildNodeFunc, NG::ModalStyle& modalStyle, std::function<void()>&& onAppear,
1412     std::function<void()>&& onDisappear, int32_t targetId)
1413 {
1414     LOGI("BindContentCover isShow: %{public}d, targetId: %{public}d", isShow, targetId);
1415     auto rootNode = rootNodeWeak_.Upgrade();
1416     CHECK_NULL_VOID(rootNode);
1417     auto modalTransition = modalStyle.modalTransition;
1418     if (!modalTransition.has_value()) {
1419         modalTransition = ModalTransition::DEFAULT;
1420     }
1421     if (isShow) {
1422         if (!modalStack_.empty()) {
1423             auto topModalNode = modalStack_.top().Upgrade();
1424             CHECK_NULL_VOID(topModalNode);
1425             if (topModalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1426                 if (topModalNode->GetPattern<ModalPresentationPattern>()->GetTargetId() == targetId) {
1427                     if (modalStyle.backgroundColor.has_value()) {
1428                         topModalNode->GetRenderContext()->UpdateBackgroundColor(modalStyle.backgroundColor.value());
1429                     }
1430                     topModalNode->GetPattern<ModalPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
1431                     topModalNode->GetPattern<ModalPresentationPattern>()->SetType(modalTransition.value());
1432                     return;
1433                 }
1434             }
1435         }
1436         // builder content
1437         auto builder = AceType::DynamicCast<FrameNode>(buildNodeFunc());
1438         CHECK_NULL_VOID(builder);
1439         builder->GetRenderContext()->SetIsModalRootNode(true);
1440 
1441         // create modal page
1442         auto modalNode = FrameNode::CreateFrameNode(V2::MODAL_PAGE_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1443             AceType::MakeRefPtr<ModalPresentationPattern>(
1444                 targetId, static_cast<ModalTransition>(modalTransition.value()), std::move(callback)));
1445         if (modalStyle.backgroundColor.has_value()) {
1446             modalNode->GetRenderContext()->UpdateBackgroundColor(modalStyle.backgroundColor.value());
1447         }
1448         modalNode->GetPattern<ModalPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
1449         modalStack_.push(WeakClaim(RawPtr(modalNode)));
1450         modalList_.emplace_back(WeakClaim(RawPtr(modalNode)));
1451         SaveLastModalNode();
1452         modalNode->MountToParent(rootNode);
1453         modalNode->AddChild(builder);
1454         FireModalPageShow();
1455         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1456         if (onAppear != nullptr) {
1457             onAppear();
1458         }
1459         if (modalTransition == ModalTransition::DEFAULT) {
1460             PlayDefaultModalTransition(modalNode, true);
1461         } else if (modalTransition == ModalTransition::ALPHA) {
1462             PlayAlphaModalTransition(modalNode, true);
1463         }
1464         return;
1465     }
1466     if (!modalStack_.empty()) {
1467         auto topModalNode = modalStack_.top().Upgrade();
1468         CHECK_NULL_VOID(topModalNode);
1469         if (topModalNode->GetTag() != V2::MODAL_PAGE_TAG) {
1470             return;
1471         }
1472         if (topModalNode->GetPattern<ModalPresentationPattern>()->GetTargetId() != targetId) {
1473             DeleteModal(targetId);
1474             topModalNode->GetPattern<ModalPresentationPattern>()->OnDisappear();
1475             return;
1476         }
1477         auto builder = AceType::DynamicCast<FrameNode>(topModalNode->GetFirstChild());
1478         CHECK_NULL_VOID(builder);
1479         if (builder->GetRenderContext()->HasTransition()) {
1480             topModalNode->Clean(false, true);
1481             topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1482         }
1483         auto modalPresentationPattern = topModalNode->GetPattern<ModalPresentationPattern>();
1484         CHECK_NULL_VOID(modalPresentationPattern);
1485         modalTransition = modalPresentationPattern->GetType();
1486         // lost focus
1487         ModalPageLostFocus(topModalNode);
1488         if (modalTransition == ModalTransition::DEFAULT) {
1489             PlayDefaultModalTransition(topModalNode, false);
1490         } else if (modalTransition == ModalTransition::ALPHA) {
1491             PlayAlphaModalTransition(topModalNode, false);
1492         } else if (!builder->GetRenderContext()->HasTransition()) {
1493             rootNode->RemoveChild(topModalNode);
1494             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1495         }
1496         modalStack_.pop();
1497         if (!modalList_.empty()) {
1498             modalList_.pop_back();
1499         }
1500         FireModalPageHide();
1501         modalPresentationPattern->OnDisappear();
1502         SaveLastModalNode();
1503     }
1504 }
1505 
FireModalPageShow()1506 void OverlayManager::FireModalPageShow()
1507 {
1508     auto pipeline = PipelineContext::GetCurrentContext();
1509     CHECK_NULL_VOID(pipeline);
1510     auto pageNode = pipeline->GetStageManager()->GetLastPage();
1511     CHECK_NULL_VOID(pageNode);
1512     auto pageFocusHub = pageNode->GetFocusHub();
1513     CHECK_NULL_VOID(pageFocusHub);
1514     pageFocusHub->SetParentFocusable(false);
1515     pageFocusHub->LostFocus();
1516     for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
1517         auto modalNode = (*modal).Upgrade();
1518         CHECK_NULL_VOID(modalNode);
1519         auto modalFocusHub = modalNode->GetFocusHub();
1520         CHECK_NULL_VOID(modalFocusHub);
1521         modalFocusHub->SetParentFocusable(false);
1522         modalFocusHub->LostFocus();
1523     }
1524     if (modalList_.empty()) {
1525         return;
1526     }
1527     auto topModalNode = modalList_.back().Upgrade();
1528     CHECK_NULL_VOID(topModalNode);
1529     auto topModalFocusHub = topModalNode->GetFocusHub();
1530     CHECK_NULL_VOID(topModalFocusHub);
1531     topModalFocusHub->SetParentFocusable(true);
1532     topModalFocusHub->RequestFocusWithDefaultFocusFirstly();
1533 }
1534 
ModalPageLostFocus(const RefPtr<FrameNode> & node)1535 void OverlayManager::ModalPageLostFocus(const RefPtr<FrameNode>& node)
1536 {
1537     auto modalFocusHub = node->GetFocusHub();
1538     CHECK_NULL_VOID(modalFocusHub);
1539     modalFocusHub->SetParentFocusable(false);
1540     modalFocusHub->LostFocus();
1541 }
1542 
FireModalPageHide()1543 void OverlayManager::FireModalPageHide()
1544 {
1545     auto lastModalNode = lastModalNode_.Upgrade();
1546     CHECK_NULL_VOID(lastModalNode);
1547     auto lastModalFocusHub = lastModalNode->GetFocusHub();
1548     CHECK_NULL_VOID(lastModalFocusHub);
1549     lastModalFocusHub->SetParentFocusable(true);
1550     lastModalFocusHub->RequestFocus();
1551 }
1552 
PlayDefaultModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)1553 void OverlayManager::PlayDefaultModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
1554 {
1555     // current modal animation
1556     AnimationOption option;
1557     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 100.0f, 20.0f);
1558     option.SetCurve(curve);
1559     option.SetFillMode(FillMode::FORWARDS);
1560     auto context = modalNode->GetRenderContext();
1561     CHECK_NULL_VOID(context);
1562 
1563     auto rootHeight = GetRootHeight();
1564     auto modalPositionY = modalNode->GetGeometryNode()->GetFrameRect().GetY();
1565     auto showHeight = rootHeight - modalPositionY;
1566 
1567     if (isTransitionIn) {
1568         context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
1569         AnimationUtils::Animate(option, [context]() {
1570             if (context) {
1571                 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
1572             }
1573         });
1574     } else {
1575         auto lastModalNode = lastModalNode_.Upgrade();
1576         CHECK_NULL_VOID(lastModalNode);
1577         auto lastModalContext = lastModalNode->GetRenderContext();
1578         CHECK_NULL_VOID(lastModalContext);
1579         lastModalContext->UpdateOpacity(1.0);
1580         option.SetOnFinishEvent(
1581             [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), id = Container::CurrentId()] {
1582                 ContainerScope scope(id);
1583                 auto context = PipelineContext::GetCurrentContext();
1584                 CHECK_NULL_VOID_NOLOG(context);
1585                 auto taskExecutor = context->GetTaskExecutor();
1586                 CHECK_NULL_VOID_NOLOG(taskExecutor);
1587                 // animation finish event should be posted to UI thread.
1588                 taskExecutor->PostTask(
1589                     [rootWeak, modalWK, id]() {
1590                         auto modal = modalWK.Upgrade();
1591                         auto root = rootWeak.Upgrade();
1592                         CHECK_NULL_VOID_NOLOG(modal && root);
1593                         ContainerScope scope(id);
1594                         root->RemoveChild(modal);
1595                         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1596                     },
1597                     TaskExecutor::TaskType::UI);
1598             });
1599         context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
1600         AnimationUtils::Animate(
1601             option,
1602             [context, showHeight]() {
1603                 if (context) {
1604                     context->OnTransformTranslateUpdate({ 0.0f, showHeight, 0.0f });
1605                 }
1606             },
1607             option.GetOnFinishEvent());
1608     }
1609 }
1610 
PlayAlphaModalTransition(const RefPtr<FrameNode> & modalNode,bool isTransitionIn)1611 void OverlayManager::PlayAlphaModalTransition(const RefPtr<FrameNode>& modalNode, bool isTransitionIn)
1612 {
1613     AnimationOption option;
1614     option.SetCurve(Curves::FRICTION);
1615     option.SetDuration(FULL_MODAL_ALPHA_ANIMATION_DURATION);
1616     option.SetFillMode(FillMode::FORWARDS);
1617     auto lastModalNode = lastModalNode_.Upgrade();
1618     CHECK_NULL_VOID(lastModalNode);
1619     auto lastModalContext = lastModalNode->GetRenderContext();
1620     CHECK_NULL_VOID(lastModalContext);
1621     auto context = modalNode->GetRenderContext();
1622     CHECK_NULL_VOID(context);
1623     if (isTransitionIn) {
1624         // last page animation
1625         lastModalContext->OpacityAnimation(option, 1, 0);
1626         lastModalContext->UpdateOpacity(0);
1627 
1628         // current modal page animation
1629         context->OpacityAnimation(option, 0, 1);
1630     } else {
1631         // last page animation
1632         lastModalContext->OpacityAnimation(option, 0, 1);
1633 
1634         // current modal page animation
1635         option.SetOnFinishEvent(
1636             [rootWeak = rootNodeWeak_, modalWK = WeakClaim(RawPtr(modalNode)), id = Container::CurrentId()] {
1637                 ContainerScope scope(id);
1638                 auto context = PipelineContext::GetCurrentContext();
1639                 CHECK_NULL_VOID_NOLOG(context);
1640                 auto taskExecutor = context->GetTaskExecutor();
1641                 CHECK_NULL_VOID_NOLOG(taskExecutor);
1642                 // animation finish event should be posted to UI thread.
1643                 taskExecutor->PostTask(
1644                     [rootWeak, modalWK, id]() {
1645                         auto modal = modalWK.Upgrade();
1646                         auto root = rootWeak.Upgrade();
1647                         CHECK_NULL_VOID_NOLOG(modal && root);
1648                         ContainerScope scope(id);
1649                         root->RemoveChild(modal);
1650                         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1651                     },
1652                     TaskExecutor::TaskType::UI);
1653             });
1654         context->OpacityAnimation(option, 1, 0);
1655     }
1656 }
1657 
BindSheet(bool isShow,std::function<void (const std::string &)> && callback,std::function<RefPtr<UINode> ()> && buildNodeFunc,NG::SheetStyle & sheetStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,int32_t targetId)1658 void OverlayManager::BindSheet(bool isShow, std::function<void(const std::string&)>&& callback,
1659     std::function<RefPtr<UINode>()>&& buildNodeFunc, NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear,
1660     std::function<void()>&& onDisappear, int32_t targetId)
1661 {
1662     LOGI("BindSheet isShow: %{public}d, targetId: %{public}d", isShow, targetId);
1663     auto rootNode = rootNodeWeak_.Upgrade();
1664     CHECK_NULL_VOID(rootNode);
1665     auto pipeline = PipelineContext::GetCurrentContext();
1666     CHECK_NULL_VOID(pipeline);
1667     if (isShow) {
1668         if (!modalStack_.empty()) {
1669             auto topModalNode = modalStack_.top().Upgrade();
1670             CHECK_NULL_VOID(topModalNode);
1671             if (topModalNode->GetTag() == V2::SHEET_PAGE_TAG) {
1672                 if (topModalNode->GetPattern<SheetPresentationPattern>()->GetTargetId() == targetId) {
1673                     if (sheetStyle.backgroundColor.has_value()) {
1674                         topModalNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value());
1675                     }
1676                     topModalNode->GetPattern<SheetPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
1677                     auto layoutProperty = topModalNode->GetLayoutProperty<SheetPresentationProperty>();
1678                     layoutProperty->UpdateSheetStyle(sheetStyle);
1679                     topModalNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1680                     bool isModeChangeToAuto = false;
1681                     if (sheetStyle.sheetMode.has_value() && sheetStyle.sheetMode == SheetMode::AUTO) {
1682                         layoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT_CROSS_AXIS);
1683                         pipeline->FlushUITasks();
1684                         isModeChangeToAuto = true;
1685                     } else {
1686                         layoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
1687                     }
1688                     ComputeSheetOffset(sheetStyle, topModalNode);
1689                     PlaySheetTransition(topModalNode, true, false, isModeChangeToAuto);
1690                     return;
1691                 }
1692             }
1693         }
1694         // builder content
1695         auto builder = AceType::DynamicCast<FrameNode>(buildNodeFunc());
1696         CHECK_NULL_VOID(builder);
1697         builder->GetRenderContext()->SetIsModalRootNode(true);
1698         // create modal page
1699         auto sheetNode = SheetView::CreateSheetPage(targetId, builder, std::move(callback), sheetStyle);
1700         if (sheetStyle.backgroundColor.has_value()) {
1701             sheetNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.backgroundColor.value());
1702         }
1703         sheetNode->GetPattern<SheetPresentationPattern>()->UpdateOnDisappear(std::move(onDisappear));
1704         modalStack_.push(WeakClaim(RawPtr(sheetNode)));
1705         SaveLastModalNode();
1706         // create maskColor node
1707         if (sheetStyle.maskColor.has_value()) {
1708             auto maskNode = FrameNode::CreateFrameNode(
1709                 V2::SHEET_MASK_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>());
1710             maskNode->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
1711             maskNode->GetRenderContext()->UpdateBackgroundColor(sheetStyle.maskColor.value());
1712             maskNode->MountToParent(rootNode);
1713         }
1714         sheetNode->MountToParent(rootNode);
1715         modalList_.emplace_back(WeakClaim(RawPtr(sheetNode)));
1716         FireModalPageShow();
1717         rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1718         pipeline->FlushUITasks();
1719         ComputeSheetOffset(sheetStyle, sheetNode);
1720         if (onAppear != nullptr) {
1721             onAppear();
1722         }
1723 
1724         // start transition animation
1725         PlaySheetTransition(sheetNode, true);
1726         return;
1727     }
1728 
1729     if (!modalStack_.empty()) {
1730         auto topSheetNode = modalStack_.top().Upgrade();
1731         CHECK_NULL_VOID(topSheetNode);
1732         if (topSheetNode->GetTag() != V2::SHEET_PAGE_TAG) {
1733             return;
1734         }
1735         if (topSheetNode->GetPattern<SheetPresentationPattern>()->GetTargetId() != targetId) {
1736             DeleteModal(targetId);
1737             topSheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
1738             return;
1739         }
1740         auto builder = AceType::DynamicCast<FrameNode>(topSheetNode->GetLastChild());
1741         CHECK_NULL_VOID(builder);
1742         if (builder->GetRenderContext()->HasTransition()) {
1743             topSheetNode->Clean(false, true);
1744             topSheetNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1745         }
1746         ModalPageLostFocus(topSheetNode);
1747         PlaySheetTransition(topSheetNode, false);
1748         modalStack_.pop();
1749         if (!modalList_.empty()) {
1750             modalList_.pop_back();
1751         }
1752         FireModalPageHide();
1753         topSheetNode->GetPattern<SheetPresentationPattern>()->OnDisappear();
1754         SaveLastModalNode();
1755     }
1756 }
1757 
PlaySheetTransition(RefPtr<FrameNode> sheetNode,bool isTransitionIn,bool isFirstTransition,bool isModeChangeToAuto)1758 void OverlayManager::PlaySheetTransition(
1759     RefPtr<FrameNode> sheetNode, bool isTransitionIn, bool isFirstTransition, bool isModeChangeToAuto)
1760 {
1761     // current sheet animation
1762     AnimationOption option;
1763     const RefPtr<InterpolatingSpring> curve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 100.0f, 20.0f);
1764     option.SetCurve(curve);
1765     option.SetFillMode(FillMode::FORWARDS);
1766     auto context = sheetNode->GetRenderContext();
1767     CHECK_NULL_VOID(context);
1768     auto rootHeight = GetRootHeight();
1769     if (isTransitionIn) {
1770         auto offset = rootHeight - sheetHeight_;
1771         if (isFirstTransition) {
1772             context->OnTransformTranslateUpdate({ 0.0f, rootHeight, 0.0f });
1773         }
1774         if (isModeChangeToAuto) {
1775             option.SetDuration(0);
1776             option.SetCurve(Curves::LINEAR);
1777         }
1778         AnimationUtils::Animate(option, [context, offset]() {
1779             if (context) {
1780                 context->OnTransformTranslateUpdate({ 0.0f, offset, 0.0f });
1781             }
1782         });
1783     } else {
1784         option.SetOnFinishEvent(
1785             [rootWeak = rootNodeWeak_, sheetWK = WeakClaim(RawPtr(sheetNode)), id = Container::CurrentId()] {
1786                 ContainerScope scope(id);
1787                 auto context = PipelineContext::GetCurrentContext();
1788                 CHECK_NULL_VOID_NOLOG(context);
1789                 auto taskExecutor = context->GetTaskExecutor();
1790                 CHECK_NULL_VOID_NOLOG(taskExecutor);
1791                 // animation finish event should be posted to UI thread.
1792                 taskExecutor->PostTask(
1793                     [rootWeak, sheetWK, id]() {
1794                         auto sheet = sheetWK.Upgrade();
1795                         auto root = rootWeak.Upgrade();
1796                         CHECK_NULL_VOID_NOLOG(sheet && root);
1797                         ContainerScope scope(id);
1798                         OverlayManager::DestroySheetMask(sheet);
1799                         root->RemoveChild(sheet);
1800                         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1801                     },
1802                     TaskExecutor::TaskType::UI);
1803             });
1804         AnimationUtils::Animate(
1805             option,
1806             [context, rootHeight]() {
1807                 if (context) {
1808                     context->OnTransformTranslateUpdate({ 0.0f, rootHeight, 0.0f });
1809                 }
1810             },
1811             option.GetOnFinishEvent());
1812     }
1813 }
1814 
ComputeSheetOffset(NG::SheetStyle & sheetStyle,RefPtr<FrameNode> sheetNode)1815 void OverlayManager::ComputeSheetOffset(NG::SheetStyle& sheetStyle, RefPtr<FrameNode> sheetNode)
1816 {
1817     auto sheetHeight = sheetNode->GetGeometryNode()->GetFrameSize().Height();
1818     auto largeHeight = sheetHeight - SHEET_BLANK_MINI_HEIGHT.ConvertToPx();
1819     if (sheetStyle.sheetMode.has_value()) {
1820         if (sheetStyle.sheetMode == SheetMode::MEDIUM) {
1821             sheetHeight_ = sheetHeight / 2; // 2 : half
1822         } else if (sheetStyle.sheetMode == SheetMode::LARGE) {
1823             sheetHeight_ = largeHeight;
1824         } else if (sheetStyle.sheetMode == SheetMode::AUTO) {
1825             sheetHeight_ = sheetHeight;
1826         }
1827     } else {
1828         double height = 0.0;
1829         if (sheetStyle.height->Unit() == DimensionUnit::PERCENT) {
1830             height = sheetStyle.height->ConvertToPxWithSize(sheetHeight);
1831         } else {
1832             height = sheetStyle.height->ConvertToPx();
1833         }
1834         if (height > largeHeight) {
1835             sheetHeight_ = largeHeight;
1836         } else if (height < 0) {
1837             sheetHeight_ = largeHeight;
1838         } else {
1839             sheetHeight_ = height;
1840         }
1841     }
1842 }
1843 
DestroySheet(const RefPtr<FrameNode> & sheetNode,int32_t targetId)1844 void OverlayManager::DestroySheet(const RefPtr<FrameNode>& sheetNode, int32_t targetId)
1845 {
1846     if (!modalStack_.empty()) {
1847         auto topSheetNode = modalStack_.top().Upgrade();
1848         CHECK_NULL_VOID(topSheetNode);
1849         if (topSheetNode->GetTag() != V2::SHEET_PAGE_TAG) {
1850             return;
1851         }
1852         if (topSheetNode->GetPattern<SheetPresentationPattern>()->GetTargetId() != targetId) {
1853             return;
1854         }
1855         auto rootNode = rootNodeWeak_.Upgrade();
1856         CHECK_NULL_VOID(rootNode);
1857         auto root = DynamicCast<FrameNode>(rootNode);
1858         OverlayManager::DestroySheetMask(sheetNode);
1859         ModalPageLostFocus(topSheetNode);
1860         root->RemoveChild(sheetNode);
1861         root->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1862         modalStack_.pop();
1863         modalList_.pop_back();
1864         FireModalPageHide();
1865         SaveLastModalNode();
1866     }
1867 }
1868 
DeleteModal(int32_t targetId)1869 void OverlayManager::DeleteModal(int32_t targetId)
1870 {
1871     LOGI("OverlayManager::DeleteModal");
1872     bool isDelete = false;
1873     for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
1874         auto modalNode = (*modal).Upgrade();
1875         if (!modalNode) {
1876             continue;
1877         }
1878         int32_t currentTargetId = -1;
1879         if (modalNode->GetTag() == V2::MODAL_PAGE_TAG) {
1880             currentTargetId = modalNode->GetPattern<ModalPresentationPattern>()->GetTargetId();
1881 
1882         } else if (modalNode->GetTag() == V2::SHEET_PAGE_TAG) {
1883             currentTargetId = modalNode->GetPattern<SheetPresentationPattern>()->GetTargetId();
1884         } else {
1885             LOGW("OverlayManager: modalNode %{public}d doesn't exist", targetId);
1886             return;
1887         }
1888         if (currentTargetId == targetId) {
1889             isDelete = true;
1890             modalList_.erase(modal);
1891             auto rootNode = rootNodeWeak_.Upgrade();
1892             CHECK_NULL_VOID(rootNode);
1893             rootNode->RemoveChild(modalNode);
1894             rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1895             break;
1896         }
1897     }
1898     if (isDelete) {
1899         while (!modalStack_.empty()) {
1900             modalStack_.pop();
1901         }
1902         for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) {
1903             modalStack_.push(*modal);
1904         }
1905         SaveLastModalNode();
1906     }
1907 }
1908 
DestroySheetMask(const RefPtr<FrameNode> & sheetNode)1909 void OverlayManager::DestroySheetMask(const RefPtr<FrameNode>& sheetNode)
1910 {
1911     // destory bindsheet masknode
1912     auto rootNode = sheetNode->GetParent();
1913     CHECK_NULL_VOID(rootNode);
1914     auto root = DynamicCast<FrameNode>(rootNode);
1915     auto sheetChild = std::find(root->GetChildren().begin(), root->GetChildren().end(), sheetNode);
1916     if (sheetChild == root->GetChildren().end()) {
1917         return;
1918     }
1919     --sheetChild;
1920     if (DynamicCast<FrameNode>(*sheetChild)->GetTag() != V2::SHEET_MASK_TAG) {
1921         return;
1922     }
1923     root->RemoveChild(*sheetChild);
1924 }
1925 
PlayKeyboardTransition(RefPtr<FrameNode> customKeyboard,bool isTransitionIn)1926 void OverlayManager::PlayKeyboardTransition(RefPtr<FrameNode> customKeyboard, bool isTransitionIn)
1927 {
1928     CHECK_NULL_VOID(customKeyboard);
1929     AnimationOption option;
1930     if (isTransitionIn) {
1931         option.SetCurve(SHOW_CUSTOM_KEYBOARD_ANIMATION_CURVE);
1932     } else {
1933         option.SetCurve(HIDE_CUSTOM_KEYBOARD_ANIMATION_CURVE);
1934     }
1935     option.SetFillMode(FillMode::FORWARDS);
1936     auto context = customKeyboard->GetRenderContext();
1937     CHECK_NULL_VOID(context);
1938     auto pipeline = PipelineContext::GetCurrentContext();
1939     CHECK_NULL_VOID(pipeline);
1940     auto pageNode = pipeline->GetStageManager()->GetLastPage();
1941     auto pageHeight = pageNode->GetGeometryNode()->GetFrameSize().Height();
1942     if (isTransitionIn) {
1943         context->OnTransformTranslateUpdate({ 0.0f, pageHeight, 0.0f });
1944         AnimationUtils::Animate(option, [context]() {
1945             if (context) {
1946                 context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
1947             }
1948         });
1949     } else {
1950         context->UpdateOpacity(1.0);
1951         option.SetOnFinishEvent([id = Container::CurrentId(), customKeyboard] {
1952             ContainerScope scope(id);
1953             auto taskExecutor = Container::CurrentTaskExecutor();
1954             CHECK_NULL_VOID_NOLOG(taskExecutor);
1955             // animation finish event should be posted to UI thread.
1956             taskExecutor->PostTask(
1957                 [customKeyboard]() {
1958                     auto parent = customKeyboard->GetParent();
1959                     CHECK_NULL_VOID(parent);
1960                     parent->RemoveChild(customKeyboard);
1961                 },
1962                 TaskExecutor::TaskType::UI);
1963         });
1964         context->OnTransformTranslateUpdate({ 0.0f, 0.0f, 0.0f });
1965         AnimationUtils::Animate(
1966             option,
1967             [context, pageHeight]() {
1968                 if (context) {
1969                     context->OnTransformTranslateUpdate({ 0.0f, pageHeight, 0.0f });
1970                 }
1971             },
1972             option.GetOnFinishEvent());
1973     }
1974 }
1975 
BindKeyboard(const std::function<void ()> & keybordBuilder,int32_t targetId)1976 void OverlayManager::BindKeyboard(const std::function<void()>& keybordBuilder, int32_t targetId)
1977 {
1978     if (customKeyboardMap_.find(targetId) != customKeyboardMap_.end()) {
1979         return;
1980     }
1981     auto rootNode = rootNodeWeak_.Upgrade();
1982     CHECK_NULL_VOID(rootNode);
1983     auto customKeyboard = KeyboardView::CreateKeyboard(targetId, keybordBuilder);
1984     customKeyboard->MountToParent(rootNode);
1985     rootNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1986     customKeyboardMap_[targetId] = customKeyboard;
1987     PlayKeyboardTransition(customKeyboard, true);
1988 }
1989 
CloseKeyboard(int32_t targetId)1990 void OverlayManager::CloseKeyboard(int32_t targetId)
1991 {
1992     auto it = customKeyboardMap_.find(targetId);
1993     if (it == customKeyboardMap_.end()) {
1994         return;
1995     }
1996     auto customKeyboard = it->second;
1997     CHECK_NULL_VOID(customKeyboard);
1998     auto pattern = customKeyboard->GetPattern<KeyboardPattern>();
1999     CHECK_NULL_VOID(pattern);
2000     customKeyboardMap_.erase(pattern->GetTargetId());
2001     PlayKeyboardTransition(customKeyboard, false);
2002 }
2003 
DestroyKeyboard()2004 void OverlayManager::DestroyKeyboard()
2005 {
2006     auto rootNode = rootNodeWeak_.Upgrade();
2007     CHECK_NULL_VOID(rootNode);
2008     if (customKeyboardMap_.empty()) {
2009         return;
2010     }
2011     for (auto it = customKeyboardMap_.begin(); it != customKeyboardMap_.end();) {
2012         auto keyboard = it->second;
2013         rootNode->RemoveChild(keyboard);
2014         it = customKeyboardMap_.erase(it);
2015     }
2016     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2017 }
2018 
2019 // This function will be used in SceneBoard Thread only.
2020 // if need to show the pop-up component,
2021 //   it expects to receive the target component bound by the pop-up component to find the windowScene component.
2022 // if need to hide the pop-up component,
2023 //   it expects to receive the the pop-up component to return the parent component.
2024 //   And the parent component will be the windowScene component exactly.
FindWindowScene(RefPtr<FrameNode> targetNode)2025 RefPtr<UINode> OverlayManager::FindWindowScene(RefPtr<FrameNode> targetNode)
2026 {
2027     auto container = Container::Current();
2028     if (!container || !container->IsScenceBoardWindow()) {
2029         return rootNodeWeak_.Upgrade();
2030     }
2031     CHECK_NULL_RETURN(targetNode, nullptr);
2032     LOGI("FindWindowScene start");
2033     auto parent = targetNode->GetParent();
2034     while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
2035         parent = parent->GetParent();
2036     }
2037     CHECK_NULL_RETURN(parent, nullptr);
2038     LOGI("FindWindowScene success");
2039     windowSceneSet_.insert(parent);
2040     return parent;
2041 }
2042 
2043 #ifdef ENABLE_DRAG_FRAMEWORK
MountFilterToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)2044 void OverlayManager::MountFilterToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
2045 {
2046     CHECK_NULL_VOID(windowScene);
2047     columnNode->MountToParent(windowScene);
2048     columnNode->OnMountToParentDone();
2049     windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2050     filterColumnNodeWeak_ = columnNode;
2051     hasFilter_ = true;
2052 }
2053 
MountPixelMapToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)2054 void OverlayManager::MountPixelMapToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
2055 {
2056     CHECK_NULL_VOID(windowScene);
2057     columnNode->MountToParent(windowScene);
2058     columnNode->OnMountToParentDone();
2059     windowScene->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2060     pixmapColumnNodeWeak_ = columnNode;
2061     hasPixelMap_ = true;
2062 }
2063 
MountEventToWindowScene(const RefPtr<FrameNode> & columnNode,const RefPtr<UINode> & windowScene)2064 void OverlayManager::MountEventToWindowScene(const RefPtr<FrameNode>& columnNode, const RefPtr<UINode>& windowScene)
2065 {
2066     CHECK_NULL_VOID(windowScene);
2067     columnNode->MountToParent(windowScene);
2068     columnNode->OnMountToParentDone();
2069     eventColumnNodeWeak_ = columnNode;
2070     hasEvent_ = true;
2071 }
2072 
MountPixelMapToRootNode(const RefPtr<FrameNode> & columnNode)2073 void OverlayManager::MountPixelMapToRootNode(const RefPtr<FrameNode>& columnNode)
2074 {
2075     auto rootNode = rootNodeWeak_.Upgrade();
2076     CHECK_NULL_VOID(rootNode);
2077     columnNode->MountToParent(rootNode);
2078     columnNode->OnMountToParentDone();
2079     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2080     pixmapColumnNodeWeak_ = columnNode;
2081     hasPixelMap_ = true;
2082 }
2083 
MountEventToRootNode(const RefPtr<FrameNode> & columnNode)2084 void OverlayManager::MountEventToRootNode(const RefPtr<FrameNode>& columnNode)
2085 {
2086     auto rootNode = rootNodeWeak_.Upgrade();
2087     CHECK_NULL_VOID(rootNode);
2088     columnNode->MountToParent(rootNode, 1);
2089     columnNode->OnMountToParentDone();
2090     eventColumnNodeWeak_ = columnNode;
2091     hasEvent_ = true;
2092 }
2093 
RemovePixelMap()2094 void OverlayManager::RemovePixelMap()
2095 {
2096     if (!hasPixelMap_) {
2097         return;
2098     }
2099     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
2100     CHECK_NULL_VOID(columnNode);
2101     auto rootNode = columnNode->GetParent();
2102     CHECK_NULL_VOID(rootNode);
2103     rootNode->RemoveChild(columnNode);
2104     rootNode->RebuildRenderContextTree();
2105     rootNode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2106     hasPixelMap_ = false;
2107     isOnAnimation_ = false;
2108 }
2109 
RemovePixelMapAnimation(bool startDrag,double x,double y)2110 void OverlayManager::RemovePixelMapAnimation(bool startDrag, double x, double y)
2111 {
2112     if (isOnAnimation_ || !hasPixelMap_) {
2113         return;
2114     }
2115     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
2116     CHECK_NULL_VOID(columnNode);
2117     auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetFirstChild());
2118     CHECK_NULL_VOID(imageNode);
2119     auto imageContext = imageNode->GetRenderContext();
2120     CHECK_NULL_VOID(imageContext);
2121     auto hub = columnNode->GetOrCreateGestureEventHub();
2122     CHECK_NULL_VOID(hub);
2123     auto frameNode = hub->GetFrameNode();
2124     CHECK_NULL_VOID(frameNode);
2125     RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
2126     CHECK_NULL_VOID(pixelMap);
2127     float scale = PIXELMAP_DRAG_SCALE;
2128     UpdatePixelMapScale(scale);
2129     int32_t width = pixelMap->GetWidth();
2130     int32_t height = pixelMap->GetHeight();
2131 
2132     AnimationOption option;
2133     option.SetDuration(PIXELMAP_ANIMATION_DURATION);
2134     option.SetOnFinishEvent([this, id = Container::CurrentId()] {
2135         ContainerScope scope(id);
2136         LOGD("Drag window start with default pixelMap");
2137         Msdp::DeviceStatus::InteractionManager::GetInstance()->SetDragWindowVisible(true);
2138         auto pipeline = PipelineContext::GetCurrentContext();
2139         CHECK_NULL_VOID(pipeline);
2140         auto taskScheduler = pipeline->GetTaskExecutor();
2141         CHECK_NULL_VOID(taskScheduler);
2142         taskScheduler->PostTask(
2143             [overlayManager = AceType::Claim(this)]() {
2144                 CHECK_NULL_VOID(overlayManager);
2145                 overlayManager->RemovePixelMap();
2146             },
2147             TaskExecutor::TaskType::UI);
2148     });
2149     auto shadow = imageContext->GetBackShadow();
2150     if (!shadow.has_value()) {
2151         shadow = Shadow::CreateShadow(ShadowStyle::None);
2152     }
2153     imageContext->UpdateBackShadow(shadow.value());
2154 
2155     auto coordinateX = imageNode->GetOffsetRelativeToWindow().GetX() - frameNode->GetOffsetRelativeToWindow().GetX();
2156     auto coordinateY = imageNode->GetOffsetRelativeToWindow().GetY() - frameNode->GetOffsetRelativeToWindow().GetY();
2157     AnimationUtils::Animate(
2158         option,
2159         [imageContext, shadow, startDrag, x, y, width, height, scale, coordinateX, coordinateY]() mutable {
2160             auto color = shadow->GetColor();
2161             auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue());
2162             if (startDrag) {
2163                 imageContext->UpdatePosition(OffsetT<Dimension>(
2164                     Dimension(x - (x - coordinateX) * scale +
2165                               PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * width * (scale - PIXELMAP_DRAG_SCALE)),
2166                     Dimension(y - (y - coordinateY) * scale +
2167                               PIXELMAP_ANIMATION_DEFAULT_LIMIT_SCALE * height * (scale - PIXELMAP_DRAG_SCALE))));
2168                 imageContext->UpdateTransformScale({ scale, scale });
2169                 imageContext->OnModifyDone();
2170             } else {
2171                 shadow->SetColor(newColor);
2172                 imageContext->UpdateBackShadow(shadow.value());
2173                 imageContext->UpdateTransformScale({ 1.0f, 1.0f });
2174             }
2175         },
2176         option.GetOnFinishEvent());
2177     isOnAnimation_ = true;
2178 }
2179 
UpdatePixelMapScale(float & scale)2180 void OverlayManager::UpdatePixelMapScale(float& scale)
2181 {
2182     auto columnNode = pixmapColumnNodeWeak_.Upgrade();
2183     CHECK_NULL_VOID(columnNode);
2184     auto hub = columnNode->GetOrCreateGestureEventHub();
2185     CHECK_NULL_VOID(hub);
2186     RefPtr<PixelMap> pixelMap = hub->GetPixelMap();
2187     CHECK_NULL_VOID(pixelMap);
2188     int32_t height = pixelMap->GetHeight();
2189     int32_t width = pixelMap->GetWidth();
2190     int32_t deviceWidth = SystemProperties::GetDeviceWidth();
2191     int32_t deviceHeight = SystemProperties::GetDeviceHeight();
2192     int32_t maxDeviceLength = std::max(deviceHeight, deviceWidth);
2193     int32_t minDeviceLength = std::min(deviceHeight, deviceWidth);
2194     if (maxDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE > minDeviceLength) {
2195         if (height > minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) {
2196             scale = static_cast<float>(minDeviceLength * PIXELMAP_DEFALUT_LIMIT_SCALE) / height;
2197         }
2198     } else {
2199         if (hub->GetTextDraggable() && height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
2200             width > minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) {
2201             scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
2202                 static_cast<float>(minDeviceLength * PIXELMAP_DRAG_WGR_TEXT_SCALE / PIXELMAP_DRAG_WGR_SCALE) / width);
2203         } else if (height > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE &&
2204                    width > minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) {
2205             scale = fmin(static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / height,
2206                 static_cast<float>(minDeviceLength / PIXELMAP_DRAG_WGR_SCALE) / width);
2207         }
2208     }
2209 }
2210 
RemoveFilter()2211 void OverlayManager::RemoveFilter()
2212 {
2213     if (!hasFilter_) {
2214         return;
2215     }
2216     auto columnNode = filterColumnNodeWeak_.Upgrade();
2217     CHECK_NULL_VOID(columnNode);
2218     auto rootNode = columnNode->GetParent();
2219     CHECK_NULL_VOID(rootNode);
2220     auto children = columnNode->GetChildren();
2221     rootNode->RemoveChild(columnNode);
2222     rootNode->RebuildRenderContextTree();
2223     hasFilter_ = false;
2224 }
2225 
RemoveEventColumn()2226 void OverlayManager::RemoveEventColumn()
2227 {
2228     if (!hasEvent_) {
2229         return;
2230     }
2231     auto columnNode = eventColumnNodeWeak_.Upgrade();
2232     CHECK_NULL_VOID(columnNode);
2233     auto rootNode = columnNode->GetParent();
2234     CHECK_NULL_VOID(rootNode);
2235     rootNode->RemoveChild(columnNode);
2236     hasEvent_ = false;
2237 }
2238 #endif // ENABLE_DRAG_FRAMEWORK
2239 
CreateModalUIExtension(const AAFwk::Want & want,const ModalUIExtensionCallbacks & callbacks)2240 int32_t OverlayManager::CreateModalUIExtension(const AAFwk::Want& want, const ModalUIExtensionCallbacks& callbacks)
2241 {
2242     ModalStyle modalStyle;
2243     modalStyle.modalTransition = NG::ModalTransition::NONE;
2244     auto uiExtNode = ModalUIExtension::Create(want, callbacks);
2245     auto layoutProperty = uiExtNode->GetLayoutProperty();
2246     CHECK_NULL_RETURN(layoutProperty, 0);
2247     auto full = CalcLength(Dimension(1.0, DimensionUnit::PERCENT));
2248     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(full, full));
2249     auto buildNodeFunc = [uiExtNode]() -> RefPtr<UINode> {
2250         uiExtNode->MarkModifyDone();
2251         return uiExtNode;
2252     };
2253     auto sessionId = ModalUIExtension::GetSessionId(uiExtNode);
2254     // Convert the sessionId into a negative number to distinguish it from the targetId of other modal pages
2255     BindContentCover(true, nullptr, std::move(buildNodeFunc), modalStyle, nullptr, nullptr, -(sessionId));
2256     return sessionId;
2257 }
2258 
CloseModalUIExtension(int32_t sessionId)2259 void OverlayManager::CloseModalUIExtension(int32_t sessionId)
2260 {
2261     ModalStyle modalStyle;
2262     modalStyle.modalTransition = NG::ModalTransition::NONE;
2263     BindContentCover(false, nullptr, nullptr, modalStyle, nullptr, nullptr, -(sessionId));
2264 }
2265 
MarkDirty(PropertyChangeFlag flag)2266 void OverlayManager::MarkDirty(PropertyChangeFlag flag)
2267 {
2268     auto root = rootNodeWeak_.Upgrade();
2269     CHECK_NULL_VOID_NOLOG(root);
2270     auto pipeline = PipelineContext::GetCurrentContext();
2271     CHECK_NULL_VOID_NOLOG(pipeline);
2272     for (auto&& child : root->GetChildren()) {
2273         // first child is Stage node in main window, subwindow not has Stage node.
2274         if (child != root->GetFirstChild() || pipeline->IsSubPipeline()) {
2275             child->MarkDirtyNode(flag);
2276         }
2277     }
2278 }
2279 
GetRootHeight() const2280 float OverlayManager::GetRootHeight() const
2281 {
2282     auto rootNode = rootNodeWeak_.Upgrade();
2283     CHECK_NULL_RETURN(rootNode, 0.0);
2284     auto rootGeometryNode = AceType::DynamicCast<FrameNode>(rootNode)->GetGeometryNode();
2285     CHECK_NULL_RETURN(rootGeometryNode, 0.0);
2286     auto rootHeight = rootGeometryNode->GetFrameSize().Height();
2287     return rootHeight;
2288 }
2289 } // namespace OHOS::Ace::NG
2290