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