• 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/stage/stage_manager.h"
17 
18 #include <unordered_map>
19 
20 #include "base/geometry/ng/size_t.h"
21 #include "base/log/ace_checker.h"
22 #include "base/log/ace_performance_check.h"
23 #include "base/perfmonitor/perf_monitor.h"
24 #include "base/perfmonitor/perf_constants.h"
25 #include "base/memory/referenced.h"
26 #include "base/utils/time_util.h"
27 #include "base/utils/utils.h"
28 #include "core/animation/page_transition_common.h"
29 #include "core/common/container.h"
30 #include "core/common/ime/input_method_manager.h"
31 #include "core/components/common/layout/constants.h"
32 #include "core/components_ng/base/frame_node.h"
33 
34 #if !defined(ACE_UNITTEST)
35 #include "core/components_ng/base/transparent_node_detector.h"
36 #endif
37 
38 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
39 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
40 #endif
41 
42 #include "core/components_ng/base/ui_node.h"
43 #include "core/components_ng/event/focus_hub.h"
44 #include "core/components_ng/manager/shared_overlay/shared_overlay_manager.h"
45 #include "core/components_ng/pattern/overlay/overlay_manager.h"
46 #include "core/components_ng/pattern/stage/page_pattern.h"
47 #include "core/components_ng/pattern/stage/stage_pattern.h"
48 #include "core/components_ng/property/property.h"
49 #include "core/components_v2/inspector/inspector_constants.h"
50 #include "core/pipeline_ng/pipeline_context.h"
51 #include "core/pipeline_ng/ui_task_scheduler.h"
52 
53 namespace OHOS::Ace::NG {
54 
55 namespace {
FirePageTransition(const RefPtr<FrameNode> & page,PageTransitionType transitionType)56 void FirePageTransition(const RefPtr<FrameNode>& page, PageTransitionType transitionType)
57 {
58     CHECK_NULL_VOID(page);
59     auto pagePattern = page->GetPattern<PagePattern>();
60     CHECK_NULL_VOID(pagePattern);
61     page->GetEventHub<EventHub>()->SetEnabled(false);
62     pagePattern->SetPageInTransition(true);
63     auto context = PipelineContext::GetCurrentContext();
64     CHECK_NULL_VOID(context);
65     auto stageManager = context->GetStageManager();
66     CHECK_NULL_VOID(stageManager);
67     stageManager->SetStageInTrasition(true);
68     if (transitionType == PageTransitionType::EXIT_PUSH || transitionType == PageTransitionType::EXIT_POP) {
69         pagePattern->TriggerPageTransition(
70             transitionType, [weak = WeakPtr<FrameNode>(page), transitionType]() {
71                 auto context = PipelineContext::GetCurrentContext();
72                 CHECK_NULL_VOID(context);
73                 auto page = weak.Upgrade();
74                 CHECK_NULL_VOID(page);
75                 TAG_LOGI(AceLogTag::ACE_ANIMATION, "pageTransition exit finish, nodeId:%{public}d", page->GetId());
76                 auto pattern = page->GetPattern<PagePattern>();
77                 CHECK_NULL_VOID(pattern);
78                 pattern->FocusViewHide();
79                 if (transitionType == PageTransitionType::EXIT_POP && page->GetParent()) {
80                     auto stageNode = page->GetParent();
81                     stageNode->RemoveChild(page);
82                     stageNode->RebuildRenderContextTree();
83                     context->RequestFrame();
84                     return;
85                 }
86                 page->GetEventHub<EventHub>()->SetEnabled(true);
87                 pattern->SetPageInTransition(false);
88                 pattern->ProcessHideState();
89                 context->MarkNeedFlushMouseEvent();
90                 auto stageManager = context->GetStageManager();
91                 CHECK_NULL_VOID(stageManager);
92                 stageManager->SetStageInTrasition(false);
93                 page->GetRenderContext()->RemoveClipWithRRect();
94                 page->GetRenderContext()->ResetPageTransitionEffect();
95             });
96         return;
97     }
98     ACE_SCOPED_TRACE_COMMERCIAL("Router Page Transition Start");
99     PerfMonitor::GetPerfMonitor()->Start(PerfConstants::ABILITY_OR_PAGE_SWITCH, PerfActionType::LAST_UP, "");
100     pagePattern->TriggerPageTransition(
101         transitionType, [weak = WeakPtr<FrameNode>(page)]() {
102             ACE_SCOPED_TRACE_COMMERCIAL("Router Page Transition End");
103             PerfMonitor::GetPerfMonitor()->End(PerfConstants::ABILITY_OR_PAGE_SWITCH, true);
104             auto page = weak.Upgrade();
105             CHECK_NULL_VOID(page);
106             TAG_LOGI(AceLogTag::ACE_ANIMATION, "pageTransition in finish, nodeId:%{public}d", page->GetId());
107             page->GetEventHub<EventHub>()->SetEnabled(true);
108             auto pattern = page->GetPattern<PagePattern>();
109             CHECK_NULL_VOID(pattern);
110             pattern->SetPageInTransition(false);
111 
112             pattern->FocusViewShow();
113             auto context = PipelineContext::GetCurrentContext();
114             CHECK_NULL_VOID(context);
115             context->MarkNeedFlushMouseEvent();
116             page->GetRenderContext()->RemoveClipWithRRect();
117             auto stageManager = context->GetStageManager();
118             CHECK_NULL_VOID(stageManager);
119             stageManager->SetStageInTrasition(false);
120         });
121 }
122 } // namespace
123 
StartTransition(const RefPtr<FrameNode> & srcPage,const RefPtr<FrameNode> & destPage,RouteType type)124 void StageManager::StartTransition(const RefPtr<FrameNode>& srcPage, const RefPtr<FrameNode>& destPage, RouteType type)
125 {
126     auto pipeline = PipelineContext::GetCurrentContext();
127     CHECK_NULL_VOID(pipeline);
128     auto sharedManager = pipeline->GetSharedOverlayManager();
129     CHECK_NULL_VOID(sharedManager);
130     sharedManager->StartSharedTransition(srcPage, destPage);
131     srcPageNode_ = srcPage;
132     destPageNode_ = destPage;
133     TAG_LOGI(AceLogTag::ACE_ANIMATION, "start pageTransition, from node %{public}d to %{public}d",
134         srcPage ? srcPage->GetId() : -1, destPage ? destPage->GetId() : -1);
135     if (type == RouteType::PUSH) {
136         FirePageTransition(srcPage, PageTransitionType::EXIT_PUSH);
137         FirePageTransition(destPage, PageTransitionType::ENTER_PUSH);
138     } else if (type == RouteType::POP) {
139         FirePageTransition(srcPage, PageTransitionType::EXIT_POP);
140         FirePageTransition(destPage, PageTransitionType::ENTER_POP);
141     }
142 }
143 
StageManager(const RefPtr<FrameNode> & stage)144 StageManager::StageManager(const RefPtr<FrameNode>& stage) : stageNode_(stage)
145 {
146     CHECK_NULL_VOID(stageNode_);
147     stagePattern_ = DynamicCast<StagePattern>(stageNode_->GetPattern());
148 }
149 
StopPageTransition()150 void StageManager::StopPageTransition()
151 {
152     auto srcNode = srcPageNode_.Upgrade();
153     if (srcNode) {
154         auto pattern = srcNode->GetPattern<PagePattern>();
155         pattern->StopPageTransition();
156         srcPageNode_ = nullptr;
157     }
158     auto destNode = destPageNode_.Upgrade();
159     if (destNode) {
160         auto pattern = destNode->GetPattern<PagePattern>();
161         pattern->StopPageTransition();
162         destPageNode_ = nullptr;
163     }
164 }
165 
PageChangeCloseKeyboard()166 void StageManager::PageChangeCloseKeyboard()
167 {
168     // close keyboard
169 #if defined (ENABLE_STANDARD_INPUT)
170     // If pushpage, close it
171     if (Container::CurrentId() == CONTAINER_ID_DIVIDE_SIZE) {
172         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "StageManager FrameNode notNeedSoftKeyboard.");
173         auto container = Container::Current();
174         if (!container) {
175             return;
176         }
177         if (!container->IsScenceBoardWindow()) {
178             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Container not ScenceBoardWindow.");
179             InputMethodManager::GetInstance()->CloseKeyboard();
180         }
181     }
182 #endif
183 }
184 
PushPage(const RefPtr<FrameNode> & node,bool needHideLast,bool needTransition)185 bool StageManager::PushPage(const RefPtr<FrameNode>& node, bool needHideLast, bool needTransition)
186 {
187     CHECK_NULL_RETURN(stageNode_, false);
188     CHECK_NULL_RETURN(node, false);
189     int64_t startTime = GetSysTimestamp();
190     auto pipeline = AceType::DynamicCast<NG::PipelineContext>(PipelineBase::GetCurrentContext());
191     CHECK_NULL_RETURN(pipeline, false);
192     StopPageTransition();
193 
194     const auto& children = stageNode_->GetChildren();
195     RefPtr<FrameNode> outPageNode;
196     needTransition &= !children.empty();
197     if (children.empty()) {
198         auto pagePattern = node->GetPattern<NG::PagePattern>();
199         CHECK_NULL_RETURN(pagePattern, false);
200         auto pageInfo = pagePattern->GetPageInfo();
201         CHECK_NULL_RETURN(pageInfo, false);
202         auto pagePath = pageInfo->GetFullPath();
203         ACE_SCOPED_TRACE_COMMERCIAL("Router Main Page: %s", pagePath.c_str());
204 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
205         UiSessionManager::GetInstance().OnRouterChange(pagePath, "routerPushPage");
206 #endif
207     }
208     if (needTransition) {
209         pipeline->FlushPipelineImmediately();
210     }
211     RefPtr<UINode> hidePageNode;
212     auto isNewLifecycle = AceApplicationInfo::GetInstance()
213         .GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE);
214     if (!children.empty() && needHideLast) {
215         hidePageNode = children.back();
216         outPageNode = AceType::DynamicCast<FrameNode>(hidePageNode);
217         FireAutoSave(outPageNode, node);
218         if (!isNewLifecycle) {
219             FirePageHide(hidePageNode, needTransition ? PageTransitionType::EXIT_PUSH : PageTransitionType::NONE);
220         }
221     }
222     auto rect = stageNode_->GetGeometryNode()->GetFrameRect();
223     rect.SetOffset({});
224     node->GetRenderContext()->SyncGeometryProperties(rect);
225     // mount to parent and mark build render tree.
226     node->MountToParent(stageNode_);
227     // then build the total child. Build will trigger page create and onAboutToAppear
228     node->Build(nullptr);
229     // fire new lifecycle
230     if (hidePageNode && needHideLast && isNewLifecycle) {
231         FirePageHide(hidePageNode, needTransition ? PageTransitionType::EXIT_PUSH : PageTransitionType::NONE);
232     }
233     stageNode_->RebuildRenderContextTree();
234     FirePageShow(node, needTransition ? PageTransitionType::ENTER_PUSH : PageTransitionType::NONE);
235 
236     auto pagePattern = node->GetPattern<PagePattern>();
237     CHECK_NULL_RETURN(pagePattern, false);
238     stagePattern_->SetCurrentPageIndex(pagePattern->GetPageInfo()->GetPageId());
239     if (AceChecker::IsPerformanceCheckEnabled()) {
240         // After completing layout tasks at all nodes on the page, perform performance testing and management
241         pipeline->AddAfterLayoutTask([weakStage = WeakClaim(this), weakNode = WeakPtr<FrameNode>(node), startTime]() {
242             auto stage = weakStage.Upgrade();
243             CHECK_NULL_VOID(stage);
244             auto pageNode = weakNode.Upgrade();
245             int64_t endTime = GetSysTimestamp();
246             auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
247             CHECK_NULL_VOID(pagePattern);
248             auto pageInfo = pagePattern->GetPageInfo();
249             CHECK_NULL_VOID(pageInfo);
250             auto pagePath = pageInfo->GetFullPath();
251             stage->PerformanceCheck(pageNode, endTime - startTime, pagePath);
252         });
253     }
254 #if !defined(ACE_UNITTEST)
255     TransparentNodeDetector::GetInstance().PostCheckNodeTransparentTask(node);
256 #endif
257 
258     // close keyboard
259     PageChangeCloseKeyboard();
260     AddPageTransitionTrace(outPageNode, node);
261     if (needTransition) {
262         pipeline->AddAfterLayoutTask([weakStage = WeakClaim(this), weakIn = WeakPtr<FrameNode>(node),
263                                          weakOut = WeakPtr<FrameNode>(outPageNode)]() {
264             auto stage = weakStage.Upgrade();
265             CHECK_NULL_VOID(stage);
266             auto inPageNode = weakIn.Upgrade();
267             auto outPageNode = weakOut.Upgrade();
268             stage->StartTransition(outPageNode, inPageNode, RouteType::PUSH);
269         });
270     }
271 
272     // flush layout task.
273     if (!stageNode_->GetGeometryNode()->GetMarginFrameSize().IsPositive()) {
274         // in first load case, wait for window size.
275         return true;
276     }
277     stageNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
278     node->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
279 
280     return true;
281 }
282 
PerformanceCheck(const RefPtr<FrameNode> & pageNode,int64_t vsyncTimeout,std::string path)283 void StageManager::PerformanceCheck(const RefPtr<FrameNode>& pageNode, int64_t vsyncTimeout, std::string path)
284 {
285     CHECK_NULL_VOID(pageNode);
286     PerformanceCheckNodeMap nodeMap;
287     pageNode->GetPerformanceCheckData(nodeMap);
288     AceScopedPerformanceCheck::RecordPerformanceCheckData(nodeMap, vsyncTimeout, path);
289 }
290 
PopPage(bool needShowNext,bool needTransition)291 bool StageManager::PopPage(bool needShowNext, bool needTransition)
292 {
293     auto pipeline = PipelineContext::GetCurrentContext();
294     CHECK_NULL_RETURN(pipeline, false);
295     CHECK_NULL_RETURN(stageNode_, false);
296     StopPageTransition();
297     const auto& children = stageNode_->GetChildren();
298     if (children.empty()) {
299         TAG_LOGI(AceLogTag::ACE_ROUTER, "router pop page start, children is empty");
300         return false;
301     }
302     auto pageNode = children.back();
303     const size_t transitionPageSize = 2;
304     needTransition &= (children.size() >= transitionPageSize);
305     if (needTransition) {
306         pipeline->FlushPipelineImmediately();
307     }
308     auto outPageNode = AceType::DynamicCast<FrameNode>(pageNode);
309     RefPtr<FrameNode> inPageNode;
310     if (needShowNext && children.size() >= transitionPageSize) {
311         auto newPageNode = *(++children.rbegin());
312         inPageNode = AceType::DynamicCast<FrameNode>(newPageNode);
313     }
314     FireAutoSave(outPageNode, inPageNode);
315     FirePageHide(pageNode, needTransition ? PageTransitionType::EXIT_POP : PageTransitionType::NONE);
316     FirePageShow(inPageNode, needTransition ? PageTransitionType::ENTER_POP : PageTransitionType::NONE);
317 
318     // close keyboard
319     PageChangeCloseKeyboard();
320 
321     AddPageTransitionTrace(outPageNode, inPageNode);
322     if (needTransition) {
323         StartTransition(outPageNode, inPageNode, RouteType::POP);
324         inPageNode->OnAccessibilityEvent(AccessibilityEventType::CHANGE);
325         return true;
326     }
327     stageNode_->RemoveChild(pageNode);
328     pageNode->SetChildrenInDestroying();
329     stageNode_->RebuildRenderContextTree();
330     pipeline->RequestFrame();
331     return true;
332 }
333 
PopPageToIndex(int32_t index,bool needShowNext,bool needTransition)334 bool StageManager::PopPageToIndex(int32_t index, bool needShowNext, bool needTransition)
335 {
336     auto pipeline = PipelineContext::GetCurrentContext();
337     CHECK_NULL_RETURN(pipeline, false);
338     CHECK_NULL_RETURN(stageNode_, false);
339     StopPageTransition();
340     const auto& children = stageNode_->GetChildren();
341     if (children.empty()) {
342         return false;
343     }
344     int32_t popSize = static_cast<int32_t>(children.size()) - index - 1;
345     if (popSize < 0) {
346         return false;
347     }
348     if (popSize == 0) {
349         return true;
350     }
351 
352     if (needTransition) {
353         pipeline->FlushPipelineImmediately();
354     }
355     bool firstPageTransition = true;
356     auto outPageNode = AceType::DynamicCast<FrameNode>(children.back());
357     auto iter = children.rbegin();
358     for (int32_t current = 0; current < popSize; ++current) {
359         auto pageNode = *iter;
360         FirePageHide(
361             pageNode, firstPageTransition && needTransition ? PageTransitionType::EXIT_POP : PageTransitionType::NONE);
362         firstPageTransition = false;
363         ++iter;
364     }
365 
366     RefPtr<FrameNode> inPageNode;
367     if (needShowNext) {
368         const auto& newPageNode = *iter;
369         FirePageShow(newPageNode, needTransition ? PageTransitionType::ENTER_POP : PageTransitionType::NONE);
370         inPageNode = AceType::DynamicCast<FrameNode>(newPageNode);
371     }
372     PageChangeCloseKeyboard();
373     AddPageTransitionTrace(outPageNode, inPageNode);
374 
375     FireAutoSave(outPageNode, inPageNode);
376     if (needTransition) {
377         // from the penultimate node, (popSize - 1) nodes are deleted.
378         // the last node will be deleted after pageTransition
379         for (int32_t current = 1; current < popSize; ++current) {
380             auto pageNode = *(++children.rbegin());
381             stageNode_->RemoveChild(pageNode);
382         }
383         stageNode_->RebuildRenderContextTree();
384         StartTransition(outPageNode, inPageNode, RouteType::POP);
385         return true;
386     }
387     for (int32_t current = 0; current < popSize; ++current) {
388         auto pageNode = children.back();
389         stageNode_->RemoveChild(pageNode);
390     }
391     stageNode_->RebuildRenderContextTree();
392     pipeline->RequestFrame();
393     return true;
394 }
395 
CleanPageStack()396 bool StageManager::CleanPageStack()
397 {
398     auto pipeline = PipelineContext::GetCurrentContext();
399     CHECK_NULL_RETURN(pipeline, false);
400     CHECK_NULL_RETURN(stageNode_, false);
401     const auto& children = stageNode_->GetChildren();
402     if (children.size() <= 1) {
403         return false;
404     }
405     auto popSize = static_cast<int32_t>(children.size()) - 1;
406     for (int32_t count = 1; count <= popSize; ++count) {
407         auto pageNode = children.front();
408         // mark pageNode child as destroying
409         pageNode->SetChildrenInDestroying();
410         stageNode_->RemoveChild(pageNode);
411     }
412     stageNode_->RebuildRenderContextTree();
413     pipeline->RequestFrame();
414     return true;
415 }
416 
MovePageToFront(const RefPtr<FrameNode> & node,bool needHideLast,bool needTransition)417 bool StageManager::MovePageToFront(const RefPtr<FrameNode>& node, bool needHideLast, bool needTransition)
418 {
419     auto pipeline = PipelineContext::GetCurrentContext();
420     CHECK_NULL_RETURN(pipeline, false);
421     CHECK_NULL_RETURN(stageNode_, false);
422     StopPageTransition();
423     const auto& children = stageNode_->GetChildren();
424     if (children.empty()) {
425         return false;
426     }
427     const auto& lastPage = children.back();
428     if (lastPage == node) {
429         return true;
430     }
431     if (needTransition) {
432         pipeline->FlushPipelineImmediately();
433     }
434     if (needHideLast) {
435         FirePageHide(lastPage, needTransition ? PageTransitionType::EXIT_PUSH : PageTransitionType::NONE);
436     }
437     node->MovePosition(static_cast<int32_t>(stageNode_->GetChildren().size()) - 1);
438     node->GetRenderContext()->ResetPageTransitionEffect();
439     FirePageShow(node, needTransition ? PageTransitionType::ENTER_PUSH : PageTransitionType::NONE);
440 
441     stageNode_->RebuildRenderContextTree();
442     auto outPageNode = AceType::DynamicCast<FrameNode>(lastPage);
443     AddPageTransitionTrace(outPageNode, node);
444     FireAutoSave(outPageNode, node);
445     if (needTransition) {
446         StartTransition(outPageNode, node, RouteType::PUSH);
447     }
448     pipeline->RequestFrame();
449     return true;
450 }
451 
FirePageHide(const RefPtr<UINode> & node,PageTransitionType transitionType)452 void StageManager::FirePageHide(const RefPtr<UINode>& node, PageTransitionType transitionType)
453 {
454     auto pageNode = DynamicCast<FrameNode>(node);
455     CHECK_NULL_VOID(pageNode);
456     auto pagePattern = pageNode->GetPattern<PagePattern>();
457     CHECK_NULL_VOID(pagePattern);
458     pagePattern->FocusViewHide();
459     pagePattern->OnHide();
460     if (transitionType == PageTransitionType::NONE) {
461         // If there is a page transition, this function should execute after page transition,
462         // otherwise the page will not be visible
463         pagePattern->ProcessHideState();
464     }
465 
466     auto context = PipelineContext::GetCurrentContext();
467     CHECK_NULL_VOID(context);
468     context->MarkNeedFlushMouseEvent();
469 }
470 
FirePageShow(const RefPtr<UINode> & node,PageTransitionType transitionType,bool needFocus)471 void StageManager::FirePageShow(const RefPtr<UINode>& node, PageTransitionType transitionType, bool needFocus)
472 {
473     auto pageNode = DynamicCast<FrameNode>(node);
474     CHECK_NULL_VOID(pageNode);
475     auto layoutProperty = pageNode->GetLayoutProperty();
476 
477     auto pagePattern = pageNode->GetPattern<PagePattern>();
478     CHECK_NULL_VOID(pagePattern);
479     if (needFocus) {
480         pagePattern->FocusViewShow();
481     }
482     pagePattern->OnShow();
483     // With or without a page transition, we need to make the coming page visible first
484     pagePattern->ProcessShowState();
485 
486     auto context = PipelineContext::GetCurrentContext();
487     CHECK_NULL_VOID(context);
488     context->MarkNeedFlushMouseEvent();
489 #ifdef UICAST_COMPONENT_SUPPORTED
490     do {
491         auto container = Container::Current();
492         CHECK_NULL_BREAK(container);
493         auto distributedUI = container->GetDistributedUI();
494         CHECK_NULL_BREAK(distributedUI);
495         distributedUI->OnPageChanged(node->GetPageId());
496     } while (false);
497 #endif
498 }
499 
FireAutoSave(const RefPtr<FrameNode> & outPageNode,const RefPtr<FrameNode> & inPageNode)500 void StageManager::FireAutoSave(const RefPtr<FrameNode>& outPageNode, const RefPtr<FrameNode>& inPageNode)
501 {
502     CHECK_NULL_VOID(outPageNode);
503     auto outPagePattern = outPageNode->GetPattern<PagePattern>();
504     CHECK_NULL_VOID(outPagePattern);
505     auto onUIExtNodeDestroy = [weak = WeakPtr<FrameNode>(inPageNode)]() {
506         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "called.");
507         auto page = weak.Upgrade();
508         CHECK_NULL_VOID(page);
509         auto pattern = page->GetPattern<PagePattern>();
510         CHECK_NULL_VOID(pattern);
511         pattern->SetIsModalCovered(false);
512     };
513     auto onUIExtNodeBindingCompleted = [weak = WeakPtr<FrameNode>(inPageNode)]() {
514         TAG_LOGI(AceLogTag::ACE_AUTO_FILL, "called.");
515         auto page = weak.Upgrade();
516         CHECK_NULL_VOID(page);
517         auto pattern = page->GetPattern<PagePattern>();
518         CHECK_NULL_VOID(pattern);
519         pattern->SetIsModalCovered(true);
520     };
521     outPagePattern->ProcessAutoSave(onUIExtNodeDestroy, onUIExtNodeBindingCompleted);
522 }
523 
GetLastPage() const524 RefPtr<FrameNode> StageManager::GetLastPage() const
525 {
526     CHECK_NULL_RETURN(stageNode_, nullptr);
527     const auto& children = stageNode_->GetChildren();
528     if (children.empty()) {
529         return nullptr;
530     }
531     return DynamicCast<FrameNode>(children.back());
532 }
533 
GetPageById(int32_t pageId)534 RefPtr<FrameNode> StageManager::GetPageById(int32_t pageId)
535 {
536     CHECK_NULL_RETURN(stageNode_, nullptr);
537     const auto& children = stageNode_->GetChildren();
538     for (const auto& child : children) {
539         if (child->GetPageId() == pageId) {
540             return DynamicCast<FrameNode>(child);
541         }
542     }
543     return nullptr;
544 }
545 
ReloadStage()546 void StageManager::ReloadStage()
547 {
548     CHECK_NULL_VOID(stageNode_);
549     const auto& children = stageNode_->GetChildren();
550     for (const auto& child : children) {
551         auto frameNode = DynamicCast<FrameNode>(child);
552         if (!frameNode) {
553             continue;
554         }
555         auto pagePattern = frameNode->GetPattern<PagePattern>();
556         if (!pagePattern) {
557             continue;
558         }
559         pagePattern->ReloadPage();
560     }
561 }
562 
GetLastPageWithTransition() const563 RefPtr<FrameNode> StageManager::GetLastPageWithTransition() const
564 {
565     CHECK_NULL_RETURN(stageNode_, nullptr);
566     const auto& children = stageNode_->GetChildren();
567     if (children.empty()) {
568         return nullptr;
569     }
570     auto lastChildFrame = DynamicCast<FrameNode>(children.back());
571     auto pagePattern = lastChildFrame->GetPattern<PagePattern>();
572     if (pagePattern && pagePattern->GetPageInTransition()) {
573         return DynamicCast<FrameNode>(destPageNode_.Upgrade());
574     }
575     return lastChildFrame;
576 }
577 
GetPrevPageWithTransition() const578 RefPtr<FrameNode> StageManager::GetPrevPageWithTransition() const
579 {
580     CHECK_NULL_RETURN(stageNode_, nullptr);
581     const auto& children = stageNode_->GetChildren();
582     if (children.empty()) {
583         return nullptr;
584     }
585     if (stageInTrasition_) {
586         return DynamicCast<FrameNode>(srcPageNode_.Upgrade());
587     }
588     return DynamicCast<FrameNode>(children.front());
589 }
590 
AddPageTransitionTrace(const RefPtr<FrameNode> & srcPage,const RefPtr<FrameNode> & destPage)591 void StageManager::AddPageTransitionTrace(const RefPtr<FrameNode>& srcPage, const RefPtr<FrameNode>& destPage)
592 {
593     CHECK_NULL_VOID(srcPage);
594     CHECK_NULL_VOID(destPage);
595 
596     auto srcPattern = srcPage->GetPattern<NG::PagePattern>();
597     CHECK_NULL_VOID(srcPattern);
598     auto srcPageInfo = srcPattern->GetPageInfo();
599     CHECK_NULL_VOID(srcPageInfo);
600     auto srcFullPath = srcPageInfo->GetFullPath();
601 
602     auto destPattern = destPage->GetPattern<NG::PagePattern>();
603     CHECK_NULL_VOID(destPattern);
604     auto destPageInfo = destPattern->GetPageInfo();
605     CHECK_NULL_VOID(destPageInfo);
606     auto destFullPath = destPageInfo->GetFullPath();
607 
608     ACE_SCOPED_TRACE_COMMERCIAL("Router Page from %s to %s", srcFullPath.c_str(), destFullPath.c_str());
609 }
610 
SyncPageSafeArea(bool keyboardSafeArea)611 void StageManager::SyncPageSafeArea(bool keyboardSafeArea)
612 {
613     auto changeType = keyboardSafeArea ? PROPERTY_UPDATE_LAYOUT : PROPERTY_UPDATE_MEASURE;
614     auto lastPage = GetLastPageWithTransition();
615     CHECK_NULL_VOID(lastPage);
616     lastPage->MarkDirtyNode(changeType);
617     auto lastPageOverlay = lastPage->GetPattern<PagePattern>();
618     CHECK_NULL_VOID(lastPageOverlay);
619     lastPageOverlay->MarkDirtyOverlay();
620 
621     auto prevPage = GetPrevPageWithTransition();
622     CHECK_NULL_VOID(prevPage);
623     auto prevPageOverlay = prevPage->GetPattern<PagePattern>();
624     CHECK_NULL_VOID(prevPageOverlay);
625     prevPageOverlay->MarkDirtyOverlay();
626 }
627 
CheckPageFocus()628 bool StageManager::CheckPageFocus()
629 {
630     auto pageNode = GetLastPage();
631     CHECK_NULL_RETURN(pageNode, true);
632     return pageNode->GetFocusHub() && pageNode->GetFocusHub()->IsCurrentFocus();
633 }
634 } // namespace OHOS::Ace::NG
635