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