• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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/pipeline/pipeline_context.h"
17 #include <cstdlib>
18 #include "base/utils/utils.h"
19 
20 #ifdef ENABLE_ROSEN_BACKEND
21 #include "render_service_base/include/platform/common/rs_system_properties.h"
22 #include "render_service_client/core/ui/rs_node.h"
23 #include "render_service_client/core/ui/rs_root_node.h"
24 #include "render_service_client/core/ui/rs_surface_node.h"
25 #include "render_service_client/core/ui/rs_ui_director.h"
26 #include "render_service_client/core/transaction/rs_transaction.h"
27 
28 #include "core/animation/native_curve_helper.h"
29 #endif
30 
31 #include "base/log/ace_tracker.h"
32 #include "base/log/dump_log.h"
33 #include "base/log/event_report.h"
34 #include "base/ressched/ressched_report.h"
35 #include "core/animation/card_transition_controller.h"
36 #include "core/animation/shared_transition_controller.h"
37 #include "core/common/font_manager.h"
38 #include "core/common/layout_inspector.h"
39 #include "core/common/text_field_manager.h"
40 #include "core/components/container_modal/container_modal_element.h"
41 #include "core/components/dialog/dialog_component.h"
42 #include "core/components/dialog_modal/dialog_modal_component.h"
43 #include "core/components/dialog_modal/dialog_modal_element.h"
44 #include "core/components/focus_animation/render_focus_animation.h"
45 #include "core/components/overlay/overlay_component.h"
46 #include "core/components/root/render_root.h"
47 #include "core/components/root/root_component.h"
48 #include "core/components/root/root_element.h"
49 #include "core/components/select_popup/select_popup_component.h"
50 #include "core/components/semi_modal/semi_modal_component.h"
51 #include "core/components/semi_modal/semi_modal_element.h"
52 #include "core/components/semi_modal/semi_modal_theme.h"
53 #include "core/components/stage/stage_component.h"
54 #include "core/components/theme/app_theme.h"
55 #include "core/components_v2/inspector/shape_composed_element.h"
56 #include "core/components_v2/list/render_list.h"
57 #include "core/pipeline/base/factories/flutter_render_factory.h"
58 
59 namespace OHOS::Ace {
60 namespace {
61 
62 constexpr int64_t SEC_TO_NANOSEC = 1000000000;
63 constexpr char JS_THREAD_NAME[] = "JS";
64 constexpr char UI_THREAD_NAME[] = "UI";
65 constexpr uint32_t DEFAULT_MODAL_COLOR = 0x00000000;
66 constexpr float ZOOM_DISTANCE_DEFAULT = 50.0;
67 constexpr float ZOOM_DISTANCE_MOVE_PER_WHEEL = 5.0;
68 constexpr int32_t FLUSH_RELOAD_TRANSITION_DURATION_MS = 400;
69 
__anon0b317bc10202() 70 PipelineContext::TimeProvider g_defaultTimeProvider = []() -> uint64_t {
71     struct timespec ts;
72     clock_gettime(CLOCK_MONOTONIC, &ts);
73     return (ts.tv_sec * SEC_TO_NANOSEC + ts.tv_nsec);
74 };
75 
GetGlobalRect(const RefPtr<Element> & element)76 Rect GetGlobalRect(const RefPtr<Element>& element)
77 {
78     if (!element) {
79         LOGE("element is null!");
80         return Rect();
81     }
82     const auto& renderNode = element->GetRenderNode();
83     if (!renderNode) {
84         LOGE("Get render node failed!");
85         return Rect();
86     }
87     return Rect(renderNode->GetGlobalOffset(), renderNode->GetLayoutSize());
88 }
89 
ThreadStuckTask(int32_t seconds)90 void ThreadStuckTask(int32_t seconds)
91 {
92     std::this_thread::sleep_for(std::chrono::seconds(seconds));
93 }
94 
95 } // namespace
96 
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,RefPtr<PlatformResRegister> platformResRegister,const RefPtr<Frontend> & frontend,int32_t instanceId)97 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
98     RefPtr<AssetManager> assetManager, RefPtr<PlatformResRegister> platformResRegister,
99     const RefPtr<Frontend>& frontend, int32_t instanceId)
100     : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId,
101           (std::move(platformResRegister))),
102       timeProvider_(g_defaultTimeProvider)
103 {
104     RegisterEventHandler(frontend->GetEventHandler());
105     focusAnimationManager_ = AceType::MakeRefPtr<FocusAnimationManager>();
106     sharedTransitionController_ = AceType::MakeRefPtr<SharedTransitionController>(AceType::WeakClaim(this));
107     cardTransitionController_ = AceType::MakeRefPtr<CardTransitionController>(AceType::WeakClaim(this));
108     if (frontend->GetType() == FrontendType::JS_CARD) {
109         imageCache_.Reset();
110     }
111     renderFactory_ = AceType::MakeRefPtr<FlutterRenderFactory>();
112     eventManager_ = AceType::MakeRefPtr<EventManager>();
113     UpdateFontWeightScale();
114     eventManager_->SetInstanceId(instanceId);
115     textOverlayManager_ = AceType::MakeRefPtr<TextOverlayManager>(WeakClaim(this));
116 }
117 
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> & taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend)118 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor>& taskExecutor,
119     RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend)
120     : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, 0),
121       timeProvider_(g_defaultTimeProvider)
122 {
123     RegisterEventHandler(frontend->GetEventHandler());
124 
125     focusAnimationManager_ = AceType::MakeRefPtr<FocusAnimationManager>();
126     sharedTransitionController_ = AceType::MakeRefPtr<SharedTransitionController>(AceType::WeakClaim(this));
127     cardTransitionController_ = AceType::MakeRefPtr<CardTransitionController>(AceType::WeakClaim(this));
128     renderFactory_ = AceType::MakeRefPtr<FlutterRenderFactory>();
129     UpdateFontWeightScale();
130     textOverlayManager_ = AceType::MakeRefPtr<TextOverlayManager>(WeakClaim(this));
131 }
132 
~PipelineContext()133 PipelineContext::~PipelineContext()
134 {
135     LOGI("PipelineContext destroyed");
136 }
137 
FlushPipelineWithoutAnimation()138 void PipelineContext::FlushPipelineWithoutAnimation()
139 {
140     FlushBuild();
141     FlushPostAnimation();
142     FlushLayout();
143     FlushRender();
144     FlushRenderFinish();
145     FlushWindowBlur();
146     if (onShow_ && onFocus_) {
147         FlushFocus();
148     }
149     FireVisibleChangeEvent();
150     ProcessPostFlush();
151     ClearDeactivateElements();
152     FlushMessages();
153 }
154 
FlushMessages(std::function<void ()> callback)155 void PipelineContext::FlushMessages(std::function<void()> callback)
156 {
157     ACE_FUNCTION_TRACK();
158     if (isFirstPage_) {
159         LOGI("page not loaded, wait..");
160         return;
161     }
162 #ifdef ENABLE_ROSEN_BACKEND
163     if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_) {
164         if (!callback) {
165             rsUIDirector_->SendMessages();
166         } else {
167             rsUIDirector_->SendMessages(callback);
168         }
169     }
170 #endif
171 }
172 
FlushBuild()173 void PipelineContext::FlushBuild()
174 {
175     CHECK_RUN_ON(UI);
176     ACE_FUNCTION_TRACK();
177     ACE_FUNCTION_TRACE();
178     if (vsyncListener_) {
179         ACE_SCOPED_TRACE("arkoala build");
180         vsyncListener_();
181     }
182 
183     if (FrameReport::GetInstance().GetEnable()) {
184         FrameReport::GetInstance().BeginFlushBuild();
185     }
186 
187     isRebuildFinished_ = false;
188     if (dirtyElements_.empty()) {
189         isRebuildFinished_ = true;
190         if (FrameReport::GetInstance().GetEnable()) {
191             FrameReport::GetInstance().EndFlushBuild();
192         }
193         return;
194     }
195     decltype(dirtyElements_) dirtyElements(std::move(dirtyElements_));
196     for (const auto& elementWeak : dirtyElements) {
197         auto element = elementWeak.Upgrade();
198         // maybe unavailable when update parent
199         if (element && element->IsActive()) {
200             auto stageElement = AceType::DynamicCast<StageElement>(element);
201             if (stageElement && stageElement->GetStackOperation() == StackOperation::POP) {
202                 stageElement->PerformBuild();
203             } else {
204                 element->Rebuild();
205             }
206         }
207     }
208     isRebuildFinished_ = true;
209     if (!buildAfterCallback_.empty()) {
210         for (const auto& item : buildAfterCallback_) {
211             item();
212         }
213         buildAfterCallback_.clear();
214     }
215     buildingFirstPage_ = false;
216 
217     if (FrameReport::GetInstance().GetEnable()) {
218         FrameReport::GetInstance().EndFlushBuild();
219     }
220 #if !defined(PREVIEW)
221     LayoutInspector::SupportInspector();
222 #endif
223 }
224 
FlushPredictLayout(int64_t deadline)225 void PipelineContext::FlushPredictLayout(int64_t deadline)
226 {
227     CHECK_RUN_ON(UI);
228     if (predictLayoutNodes_.empty()) {
229         return;
230     }
231     ACE_FUNCTION_TRACE();
232     decltype(predictLayoutNodes_) dirtyNodes(std::move(predictLayoutNodes_));
233     for (const auto& dirtyNode : dirtyNodes) {
234         dirtyNode->OnPredictLayout(deadline);
235     }
236 }
237 
FlushFocus()238 void PipelineContext::FlushFocus()
239 {
240     CHECK_RUN_ON(UI);
241     ACE_FUNCTION_TRACK();
242     auto focusNode = dirtyFocusNode_.Upgrade();
243     if (!focusNode) {
244         dirtyFocusNode_.Reset();
245     } else {
246         focusNode->RequestFocusImmediately();
247         dirtyFocusNode_.Reset();
248         dirtyFocusScope_.Reset();
249         return;
250     }
251     auto focusScope = dirtyFocusScope_.Upgrade();
252     if (!focusScope) {
253         dirtyFocusScope_.Reset();
254     } else {
255         focusScope->RequestFocusImmediately();
256         dirtyFocusNode_.Reset();
257         dirtyFocusScope_.Reset();
258         return;
259     }
260     if (!RequestDefaultFocus()) {
261         if (rootElement_ && !rootElement_->IsCurrentFocus()) {
262             rootElement_->RequestFocusImmediately();
263         }
264     }
265 
266     if (GetIsDeclarative()) {
267         return;
268     }
269     decltype(needRebuildFocusElement_) rebuildElements(std::move(needRebuildFocusElement_));
270     for (const auto& elementWeak : rebuildElements) {
271         auto element = elementWeak.Upgrade();
272         if (element) {
273             element->RebuildFocusTree();
274         }
275     }
276 }
277 
FireVisibleChangeEvent()278 void PipelineContext::FireVisibleChangeEvent()
279 {
280     ACE_FUNCTION_TRACK();
281     if (GetIsDeclarative()) {
282         HandleVisibleAreaChangeEvent();
283         return;
284     }
285 
286     auto accessibilityManager = GetAccessibilityManager();
287     if (accessibilityManager) {
288         accessibilityManager->TriggerVisibleChangeEvent();
289     }
290 }
291 
HandleVisibleAreaChangeEvent()292 void PipelineContext::HandleVisibleAreaChangeEvent()
293 {
294     if (visibleAreaChangeNodes_.empty()) {
295         return;
296     }
297     for (auto& visibleChangeNode : visibleAreaChangeNodes_) {
298         auto visibleNodeId = visibleChangeNode.first;
299         auto composedElement = GetComposedElementById(visibleNodeId);
300         if (!composedElement) {
301             continue;
302         }
303 
304         auto inspectorComposedElement = AceType::DynamicCast<V2::InspectorComposedElement>(composedElement);
305         if (inspectorComposedElement) {
306             inspectorComposedElement->TriggerVisibleAreaChangeCallback(visibleChangeNode.second);
307         }
308     }
309 }
310 
RefreshStageFocus()311 void PipelineContext::RefreshStageFocus()
312 {
313     CHECK_RUN_ON(UI);
314     if (!rootElement_) {
315         LOGE("Root element is null!");
316         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
317         return;
318     }
319     const auto& stageElement = GetStageElement();
320     if (!stageElement) {
321         LOGE("Get stage element failed!");
322         return;
323     }
324 
325     stageElement->RefreshFocus();
326 }
327 
ShowContainerTitle(bool isShow,bool hasDeco,bool needUpdate)328 void PipelineContext::ShowContainerTitle(bool isShow, bool hasDeco, bool needUpdate)
329 {
330     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
331         LOGW("ShowContainerTitle failed, Window modal is not container.");
332         return;
333     }
334     if (!rootElement_) {
335         LOGW("ShowContainerTitle failed, rootElement_ is null.");
336         return;
337     }
338     auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
339     if (containerModal) {
340         containerModal->ShowTitle(isShow, hasDeco);
341     }
342 }
343 
SetContainerButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize,bool hideClose)344 void PipelineContext::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
345 {
346     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
347         LOGW("Window modal is not container.");
348         return;
349     }
350     if (!rootElement_) {
351         LOGE("rootElement_ is null.");
352         return;
353     }
354     auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
355     if (containerModal) {
356         containerModal->SetTitleButtonHide(hideSplit, hideMaximize, hideMinimize, hideClose);
357     }
358 }
359 
GetStageElement() const360 RefPtr<StageElement> PipelineContext::GetStageElement() const
361 {
362     CHECK_RUN_ON(UI);
363     if (!rootElement_) {
364         LOGE("Root element is null!");
365         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
366         return {};
367     }
368 
369     if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
370         auto semiElement = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
371         if (semiElement) {
372             return semiElement->GetStageElement();
373         }
374     } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
375         auto dialogElement = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
376         if (dialogElement) {
377             return dialogElement->GetStageElement();
378         }
379     } else if (windowModal_ == WindowModal::CONTAINER_MODAL) {
380         auto containerElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
381         if (containerElement) {
382             return containerElement->GetStageElement();
383         }
384     } else {
385         auto stack = rootElement_->GetFirstChild();
386         if (stack) {
387             return AceType::DynamicCast<StageElement>(stack->GetFirstChild());
388         }
389     }
390     LOGE("Get stage element failed.");
391     EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
392     return {};
393 }
394 
GetRootRect() const395 Rect PipelineContext::GetRootRect() const
396 {
397     return Rect(0.0, 0.0, rootWidth_, rootHeight_);
398 }
399 
GetStageRect() const400 Rect PipelineContext::GetStageRect() const
401 {
402     return GetGlobalRect(GetStageElement());
403 }
404 
GetPageRect() const405 Rect PipelineContext::GetPageRect() const
406 {
407     return GetGlobalRect(GetLastStack());
408 }
409 
IsLastPage()410 bool PipelineContext::IsLastPage()
411 {
412     const auto& stageElement = GetStageElement();
413     if (!stageElement) {
414         LOGE("Get stage element failed!");
415         return true;
416     }
417 
418     if (stageElement->GetChildrenList().size() <= 1) {
419         return true;
420     }
421 
422     return false;
423 }
424 
GetComposedElementById(const ComposeId & id)425 RefPtr<ComposedElement> PipelineContext::GetComposedElementById(const ComposeId& id)
426 {
427     CHECK_RUN_ON(UI);
428     const auto& it = composedElementMap_.find(id);
429     if (it != composedElementMap_.end() && !it->second.empty()) {
430         return it->second.front();
431     }
432     return RefPtr<ComposedElement>();
433 }
434 
CreateGeometryTransition()435 void PipelineContext::CreateGeometryTransition()
436 {
437     const auto& pageElement = GetLastPage();
438     if (pageElement) {
439         const auto& geometryTransitionMap = pageElement->GetGeometryTransition();
440         std::vector<std::string> ids;
441         for (const auto& [id, transformerInfo] : geometryTransitionMap) {
442             ids.push_back(id);
443         }
444         for (const auto& id : ids) {
445             const auto& transformerInfo = geometryTransitionMap.at(id);
446             RefPtr<BoxElement> appearElement = transformerInfo.appearElement.Upgrade();
447             RefPtr<BoxElement> disappearElement = transformerInfo.disappearElement.Upgrade();
448             if (!appearElement) {
449                 pageElement->RemoveGeometryTransition(id);
450                 continue;
451             }
452             if (!disappearElement || !transformerInfo.isNeedCreate) {
453                 continue;
454             }
455             RefPtr<RenderNode> appearNode = appearElement->GetRenderNode();
456             RefPtr<RenderNode> disappearNode = disappearElement->GetRenderNode();
457             AnimationOption sharedOption = transformerInfo.sharedAnimationOption;
458             if (!appearNode || !disappearNode) {
459                 continue;
460             }
461             appearNode->CreateGeometryTransitionFrom(disappearNode, sharedOption);
462             disappearNode->CreateGeometryTransitionTo(appearNode, sharedOption);
463             pageElement->FinishCreateGeometryTransition(id);
464         }
465     }
466 }
467 
FlushLayout()468 void PipelineContext::FlushLayout()
469 {
470     CHECK_RUN_ON(UI);
471     ACE_FUNCTION_TRACK();
472     ACE_FUNCTION_TRACE();
473 
474     if (FrameReport::GetInstance().GetEnable()) {
475         FrameReport::GetInstance().BeginFlushLayout();
476     }
477 
478     if (dirtyLayoutNodes_.empty()) {
479         FlushGeometryProperties();
480         if (FrameReport::GetInstance().GetEnable()) {
481             FrameReport::GetInstance().EndFlushLayout();
482         }
483         return;
484     }
485     decltype(dirtyLayoutNodes_) dirtyNodes(std::move(dirtyLayoutNodes_));
486     for (const auto& dirtyNode : dirtyNodes) {
487         SaveExplicitAnimationOption(dirtyNode->GetExplicitAnimationOption());
488         dirtyNode->OnLayout();
489         ClearExplicitAnimationOption();
490     }
491     decltype(layoutTransitionNodeSet_) transitionNodes(std::move(layoutTransitionNodeSet_));
492     for (const auto& transitionNode : transitionNodes) {
493         transitionNode->CreateLayoutTransition();
494     }
495     for (const auto& dirtyNode : dirtyNodes) {
496         dirtyNode->ClearExplicitAnimationOption();
497     }
498     alignDeclarationNodeList_.clear();
499 
500     CreateGeometryTransition();
501     FlushGeometryProperties();
502     TryCallNextFrameLayoutCallback();
503     if (FrameReport::GetInstance().GetEnable()) {
504         FrameReport::GetInstance().EndFlushLayout();
505     }
506 }
507 
FlushGeometryProperties()508 void PipelineContext::FlushGeometryProperties()
509 {
510     if (geometryChangedNodes_.empty()) {
511         return;
512     }
513 
514     decltype(dirtyLayoutNodes_) geometryChangedNodes(std::move(geometryChangedNodes_));
515     for (const auto& dirtyNode : geometryChangedNodes) {
516         dirtyNode->SyncGeometryProperties();
517     }
518 }
519 
CorrectPosition()520 void PipelineContext::CorrectPosition()
521 {
522     const auto& pageElement = GetLastPage();
523     if (pageElement) {
524         const auto& geometryTransitionMap = pageElement->GetGeometryTransition();
525         for (const auto& [id, transformerInfo] : geometryTransitionMap) {
526             RefPtr<BoxElement> appearElement = transformerInfo.appearElement.Upgrade();
527             RefPtr<BoxElement> disappearElement = transformerInfo.disappearElement.Upgrade();
528             if (!appearElement || !disappearElement) {
529                 continue;
530             }
531             RefPtr<RenderNode> appearNode = appearElement->GetRenderNode();
532             RefPtr<RenderNode> disappearNode = disappearElement->GetRenderNode();
533             if (!appearNode || !disappearNode) {
534                 continue;
535             }
536             appearNode->UpdatePosition();
537             disappearNode->UpdatePosition();
538         }
539     }
540 }
541 
FlushRender()542 void PipelineContext::FlushRender()
543 {
544     CHECK_RUN_ON(UI);
545     ACE_FUNCTION_TRACK();
546     ACE_FUNCTION_TRACE();
547 
548     if (FrameReport::GetInstance().GetEnable()) {
549         FrameReport::GetInstance().BeginFlushRender();
550     }
551 
552     if (dirtyRenderNodes_.empty() && dirtyRenderNodesInOverlay_.empty() && !needForcedRefresh_) {
553         if (FrameReport::GetInstance().GetEnable()) {
554             FrameReport::GetInstance().EndFlushRender();
555         }
556         return;
557     }
558 
559     CorrectPosition();
560 
561     Rect curDirtyRect;
562     bool isDirtyRootRect = false;
563     if (needForcedRefresh_) {
564         curDirtyRect.SetRect(0.0, 0.0, rootWidth_, rootHeight_);
565         isDirtyRootRect = true;
566     }
567 
568     UpdateNodesNeedDrawOnPixelMap();
569 
570     auto context = RenderContext::Create();
571     if (transparentHole_.IsValid()) {
572         context->SetClipHole(transparentHole_);
573     }
574     if (!dirtyRenderNodes_.empty()) {
575         decltype(dirtyRenderNodes_) dirtyNodes(std::move(dirtyRenderNodes_));
576         for (const auto& dirtyNode : dirtyNodes) {
577             context->Repaint(dirtyNode);
578             if (!isDirtyRootRect) {
579                 Rect curRect = dirtyNode->GetDirtyRect();
580                 if (curRect == GetRootRect()) {
581                     curDirtyRect = curRect;
582                     isDirtyRootRect = true;
583                     continue;
584                 }
585                 curDirtyRect = curDirtyRect.IsValid() ? curDirtyRect.CombineRect(curRect) : curRect;
586             }
587         }
588     }
589     if (!dirtyRenderNodesInOverlay_.empty()) {
590         decltype(dirtyRenderNodesInOverlay_) dirtyNodesInOverlay(std::move(dirtyRenderNodesInOverlay_));
591         for (const auto& dirtyNodeInOverlay : dirtyNodesInOverlay) {
592             context->Repaint(dirtyNodeInOverlay);
593             if (!isDirtyRootRect) {
594                 Rect curRect = dirtyNodeInOverlay->GetDirtyRect();
595                 if (curRect == GetRootRect()) {
596                     curDirtyRect = curRect;
597                     isDirtyRootRect = true;
598                     continue;
599                 }
600                 curDirtyRect = curDirtyRect.IsValid() ? curDirtyRect.CombineRect(curRect) : curRect;
601             }
602         }
603     }
604 
605     NotifyDrawOnPixelMap();
606 
607     if (rootElement_) {
608         auto renderRoot = rootElement_->GetRenderNode();
609         curDirtyRect = curDirtyRect * viewScale_;
610         renderRoot->FinishRender(drawDelegate_, dirtyRect_.CombineRect(curDirtyRect));
611         dirtyRect_ = curDirtyRect;
612         if (isFirstLoaded_) {
613             isFirstLoaded_ = false;
614         }
615     }
616     needForcedRefresh_ = false;
617 
618     if (FrameReport::GetInstance().GetEnable()) {
619         FrameReport::GetInstance().EndFlushRender();
620     }
621 }
622 
FlushRenderFinish()623 void PipelineContext::FlushRenderFinish()
624 {
625     CHECK_RUN_ON(UI);
626     ACE_FUNCTION_TRACK();
627     ACE_FUNCTION_TRACE();
628 
629     if (FrameReport::GetInstance().GetEnable()) {
630         FrameReport::GetInstance().BeginFlushRenderFinish();
631     }
632     if (!needPaintFinishNodes_.empty()) {
633         decltype(needPaintFinishNodes_) Nodes(std::move(needPaintFinishNodes_));
634         for (const auto& node : Nodes) {
635             node->OnPaintFinish();
636         }
637     }
638     if (FrameReport::GetInstance().GetEnable()) {
639         FrameReport::GetInstance().EndFlushRenderFinish();
640     }
641 }
642 
DispatchDisplaySync(uint64_t nanoTimestamp)643 void PipelineContext::DispatchDisplaySync(uint64_t nanoTimestamp) {}
644 
FlushAnimation(uint64_t nanoTimestamp)645 void PipelineContext::FlushAnimation(uint64_t nanoTimestamp)
646 {
647     CHECK_RUN_ON(UI);
648     ACE_FUNCTION_TRACK();
649     ACE_FUNCTION_TRACE();
650 
651     if (FrameReport::GetInstance().GetEnable()) {
652         FrameReport::GetInstance().BeginFlushAnimation();
653     }
654     flushAnimationTimestamp_ = nanoTimestamp;
655     isFlushingAnimation_ = true;
656 
657     ProcessPreFlush();
658     if (scheduleTasks_.empty()) {
659         isFlushingAnimation_ = false;
660         if (FrameReport::GetInstance().GetEnable()) {
661             FrameReport::GetInstance().EndFlushAnimation();
662         }
663         return;
664     }
665     decltype(scheduleTasks_) temp(std::move(scheduleTasks_));
666     for (const auto& scheduleTask : temp) {
667         scheduleTask.second->OnFrame(nanoTimestamp);
668     }
669     isFlushingAnimation_ = false;
670 
671     if (FrameReport::GetInstance().GetEnable()) {
672         FrameReport::GetInstance().EndFlushAnimation();
673     }
674 }
675 
FlushReloadTransition()676 void PipelineContext::FlushReloadTransition()
677 {
678     AnimationOption option;
679     option.SetDuration(FLUSH_RELOAD_TRANSITION_DURATION_MS);
680     option.SetCurve(Curves::FRICTION);
681     Animate(option, Curves::FRICTION, [this]() {
682         FlushBuild();
683         FlushPostAnimation();
684         FlushLayout();
685     });
686 }
687 
FlushReload(const ConfigurationChange & configurationChange,bool fullUpdate)688 void PipelineContext::FlushReload(const ConfigurationChange& configurationChange, bool fullUpdate)
689 {
690     if (!rootElement_) {
691         LOGE("PipelineContext::FlushReload rootElement is nullptr");
692         return;
693     }
694     auto containerElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
695     if (containerElement) {
696         containerElement->FlushReload();
697     }
698 }
699 
FlushPostAnimation()700 void PipelineContext::FlushPostAnimation()
701 {
702     CHECK_RUN_ON(UI);
703     ACE_FUNCTION_TRACK();
704     ACE_FUNCTION_TRACE();
705 
706     if (postAnimationFlushListeners_.empty()) {
707         return;
708     }
709     decltype(postAnimationFlushListeners_) listeners(std::move(postAnimationFlushListeners_));
710     for (const auto& listener : listeners) {
711         listener->OnPostAnimationFlush();
712     }
713 }
714 
FlushPageUpdateTasks()715 void PipelineContext::FlushPageUpdateTasks()
716 {
717     CHECK_RUN_ON(UI);
718     while (!pageUpdateTasks_.empty()) {
719         const auto& task = pageUpdateTasks_.front();
720         if (task) {
721             task();
722         }
723         pageUpdateTasks_.pop();
724     }
725 }
726 
FlushAnimationTasks()727 void PipelineContext::FlushAnimationTasks()
728 {
729     CHECK_RUN_ON(UI);
730     ACE_FUNCTION_TRACK();
731     if (animationCallback_) {
732         taskExecutor_->PostTask(animationCallback_, TaskExecutor::TaskType::JS, "ArkUIFlushAnimationTask");
733     }
734 }
735 
ProcessPreFlush()736 void PipelineContext::ProcessPreFlush()
737 {
738     CHECK_RUN_ON(UI);
739     ACE_FUNCTION_TRACE();
740 
741     // if we need clip hole
742     if (transparentHole_.IsValid()) {
743         hasMeetSubWindowNode_ = false;
744         hasClipHole_ = false;
745         isHoleValid_ = true;
746         needForcedRefresh_ = true;
747     } else {
748         hasMeetSubWindowNode_ = false;
749         hasClipHole_ = false;
750         isHoleValid_ = false;
751     }
752     if (preFlushListeners_.empty()) {
753         return;
754     }
755     decltype(preFlushListeners_) temp(std::move(preFlushListeners_));
756     for (const auto& listener : temp) {
757         listener->OnPreFlush();
758     }
759 }
760 
ProcessPostFlush()761 void PipelineContext::ProcessPostFlush()
762 {
763     CHECK_RUN_ON(UI);
764     ACE_FUNCTION_TRACK();
765     ACE_FUNCTION_TRACE();
766 
767     if (FrameReport::GetInstance().GetEnable()) {
768         FrameReport::GetInstance().BeginProcessPostFlush();
769     }
770 
771     if (postFlushListeners_.empty()) {
772         return;
773     }
774     decltype(postFlushListeners_) temp(std::move(postFlushListeners_));
775     for (const auto& listener : temp) {
776         listener->OnPostFlush();
777     }
778 }
779 
SetClipHole(double left,double top,double width,double height)780 void PipelineContext::SetClipHole(double left, double top, double width, double height)
781 {
782     if (!rootElement_) {
783         return;
784     }
785 
786     transparentHole_.SetLeft(left);
787     transparentHole_.SetTop(top);
788     transparentHole_.SetWidth(width);
789     transparentHole_.SetHeight(height);
790 }
791 
SetupRootElement()792 void PipelineContext::SetupRootElement()
793 {
794     CHECK_RUN_ON(UI);
795     RefPtr<StageComponent> rootStage = AceType::MakeRefPtr<StageComponent>(std::list<RefPtr<Component>>());
796     if (isRightToLeft_) {
797         rootStage->SetTextDirection(TextDirection::RTL);
798     }
799     if (GetIsDeclarative()) {
800         rootStage->SetMainStackSize(MainStackSize::MAX);
801     } else {
802         rootStage->SetMainStackSize(MainStackSize::LAST_CHILD_HEIGHT);
803     }
804 
805     auto stack = AceType::MakeRefPtr<StackComponent>(
806         Alignment::TOP_LEFT, StackFit::INHERIT, Overflow::OBSERVABLE, std::list<RefPtr<Component>>());
807     auto overlay = AceType::MakeRefPtr<OverlayComponent>(std::list<RefPtr<Component>>());
808     overlay->SetTouchable(false);
809     Component::MergeRSNode(overlay);
810     stack->AppendChild(rootStage);
811     stack->AppendChild(overlay);
812     RefPtr<RootComponent> rootComponent;
813     if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
814         if (modalColor_ == DEFAULT_MODAL_COLOR) {
815             auto semiModalTheme = themeManager_->GetTheme<SemiModalTheme>();
816             if (semiModalTheme) {
817                 SetModalColor(semiModalTheme->GetBgColor().GetValue());
818             }
819         }
820         auto semiModal = SemiModalComponent::Create(
821             stack, windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN, modalHeight_, modalColor_);
822         rootComponent = RootComponent::Create(semiModal);
823     } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
824         rootStage->SetMainStackSize(MainStackSize::MAX);
825         rootStage->SetAlignment(Alignment::BOTTOM_LEFT);
826         auto dialogModal = DialogModalComponent::Create(stack);
827         rootComponent = RootComponent::Create(dialogModal);
828     } else if (windowModal_ == WindowModal::CONTAINER_MODAL) {
829         auto containerModal = ContainerModalComponent::Create(AceType::WeakClaim(this), stack);
830         rootComponent = RootComponent::Create(containerModal);
831     } else {
832         rootComponent = RootComponent::Create(stack);
833     }
834     rootElement_ = rootComponent->SetupElementTree(AceType::Claim(this));
835     if (!rootElement_) {
836         LOGE("SetupRootElement failed!");
837         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
838         return;
839     }
840     const auto& rootRenderNode = rootElement_->GetRenderNode();
841     window_->SetRootRenderNode(rootRenderNode);
842     auto renderRoot = AceType::DynamicCast<RenderRoot>(rootRenderNode);
843     if (!renderRoot) {
844         LOGE("render root is null.");
845         return;
846     }
847     if (appBgColor_ != Color::WHITE) {
848         SetAppBgColor(appBgColor_);
849     } else {
850         renderRoot->SetDefaultBgColor(windowModal_ == WindowModal::CONTAINER_MODAL);
851     }
852 #ifdef ENABLE_ROSEN_BACKEND
853     if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_ && renderRoot) {
854         rsUIDirector_->SetRSRootNode(
855             Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rootRenderNode->GetRSNode()));
856         if (windowModal_ == WindowModal::CONTAINER_MODAL) {
857             rsUIDirector_->SetAbilityBGAlpha(appBgColor_.GetAlpha());
858         } else {
859             rsUIDirector_->SetAbilityBGAlpha(renderRoot->GetBgColor().GetAlpha());
860         }
861     }
862 #endif
863     sharedTransitionController_->RegisterTransitionListener();
864     cardTransitionController_->RegisterTransitionListener();
865     if (windowModal_ == WindowModal::DIALOG_MODAL) {
866         auto dialog = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
867         if (dialog) {
868             dialog->RegisterTransitionListener();
869         }
870     }
871 
872     requestedRenderNode_.Reset();
873 }
874 
SetupSubRootElement()875 RefPtr<Element> PipelineContext::SetupSubRootElement()
876 {
877     LOGI("Set up SubRootElement!");
878 
879     RefPtr<StageComponent> rootStage = AceType::MakeRefPtr<StageComponent>(std::list<RefPtr<Component>>());
880     if (isRightToLeft_) {
881         rootStage->SetTextDirection(TextDirection::RTL);
882     }
883     if (GetIsDeclarative()) {
884         rootStage->SetMainStackSize(MainStackSize::MAX);
885     } else {
886         rootStage->SetMainStackSize(MainStackSize::LAST_CHILD_HEIGHT);
887     }
888     auto stack = AceType::MakeRefPtr<StackComponent>(
889         Alignment::TOP_LEFT, StackFit::KEEP, Overflow::OBSERVABLE, std::list<RefPtr<Component>>());
890 
891     auto overlay = AceType::MakeRefPtr<OverlayComponent>(std::list<RefPtr<Component>>());
892     overlay->SetTouchable(false);
893     stack->AppendChild(rootStage);
894     stack->AppendChild(overlay);
895     RefPtr<RootComponent> rootComponent;
896     rootComponent = RootComponent::Create(stack);
897     rootComponent->MarkContextMenu();
898     rootElement_ = rootComponent->SetupElementTree(AceType::Claim(this));
899     if (!rootElement_) {
900         LOGE("Set up SubRootElement failed!");
901         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
902         return RefPtr<Element>();
903     }
904     const auto& rootRenderNode = rootElement_->GetRenderNode();
905     window_->SetRootRenderNode(rootRenderNode);
906 #ifdef ENABLE_ROSEN_BACKEND
907     if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_) {
908         rsUIDirector_->SetRSRootNode(
909             Rosen::RSNode::ReinterpretCast<Rosen::RSRootNode>(rootRenderNode->GetRSNode()));
910         auto renderRoot = AceType::DynamicCast<RenderRoot>(rootRenderNode);
911         if (renderRoot) {
912             rsUIDirector_->SetAbilityBGAlpha(renderRoot->GetBgColor().GetAlpha());
913         }
914     }
915 #endif
916     sharedTransitionController_->RegisterTransitionListener();
917     cardTransitionController_->RegisterTransitionListener();
918     requestedRenderNode_.Reset();
919     LOGI("Set up SubRootElement success!");
920     return rootElement_;
921 }
922 
OnDumpInfo(const std::vector<std::string> & params) const923 bool PipelineContext::OnDumpInfo(const std::vector<std::string>& params) const
924 {
925     ACE_DCHECK(!params.empty());
926 
927     if (params[0] == "-element") {
928         if (params.size() > 1 && params[1] == "-lastpage") {
929             GetLastPage()->DumpTree(0);
930         } else {
931             rootElement_->DumpTree(0);
932         }
933     } else if (params[0] == "-render") {
934         if (params.size() > 1 && params[1] == "-lastpage") {
935             GetLastPage()->GetRenderNode()->DumpTree(0);
936         } else {
937             rootElement_->GetRenderNode()->DumpTree(0);
938         }
939     } else if (params[0] == "-focus") {
940         rootElement_->GetFocusScope()->DumpFocusTree(0);
941     } else if (params[0] == "-layer") {
942         auto rootNode = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
943         rootNode->DumpLayerTree();
944 #ifndef WEARABLE_PRODUCT
945     } else if (params[0] == "-multimodal") {
946         multiModalManager_->DumpMultimodalScene();
947 #endif
948     } else if (params[0] == "-accessibility" || params[0] == "-inspector") {
949         DumpAccessibility(params);
950     } else if (params[0] == "-rotation" && params.size() >= 2) {
951         DumpLog::GetInstance().Print("Dump rotation");
952         RotationEvent event { static_cast<double>(StringUtils::StringToInt(params[1])) };
953         OnRotationEvent(event);
954     } else if (params[0] == "-animationscale" && params.size() >= 2) {
955         DumpLog::GetInstance().Print(std::string("Set Animation Scale. scale: ") + params[1]);
956         Animator::SetDurationScale(StringUtils::StringToDouble(params[1]));
957     } else if (params[0] == "-velocityscale" && params.size() >= 2) {
958         DumpLog::GetInstance().Print(std::string("Set Velocity Scale. scale: ") + params[1]);
959         Scrollable::SetVelocityScale(StringUtils::StringToDouble(params[1]));
960     } else if (params[0] == "-scrollfriction" && params.size() >= 2) {
961         DumpLog::GetInstance().Print(std::string("Set Scroll Friction. friction: ") + params[1]);
962         Scrollable::SetFriction(StringUtils::StringToDouble(params[1]));
963     } else if (params[0] == "-threadstuck" && params.size() >= 3) {
964         MakeThreadStuck(params);
965     } else {
966         DumpLog::GetInstance().Print("Error: Unsupported dump params!");
967         return false;
968     }
969     return true;
970 }
971 
GetLastStack() const972 RefPtr<StackElement> PipelineContext::GetLastStack() const
973 {
974     if (!rootElement_) {
975         LOGE("Rootelement is null");
976         return RefPtr<StackElement>();
977     }
978     if (isSubPipeline_) {
979         const auto& stack = AceType::DynamicCast<StackElement>(rootElement_->GetFirstChild());
980         if (!stack) {
981             LOGE("Get stack failed, it is null");
982             return RefPtr<StackElement>();
983         }
984         return stack;
985     }
986     const auto& pageElement = GetLastPage();
987     if (!pageElement) {
988         return RefPtr<StackElement>();
989     }
990     const auto& transitionElement = AceType::DynamicCast<PageTransitionElement>(pageElement->GetFirstChild());
991     if (!transitionElement) {
992         return RefPtr<StackElement>();
993     }
994     const auto& focusCollaboration =
995         AceType::DynamicCast<FocusCollaborationElement>(transitionElement->GetContentElement());
996     if (!focusCollaboration) {
997         return RefPtr<StackElement>();
998     }
999     const auto& composedStack = AceType::DynamicCast<ComposedElement>(focusCollaboration->GetFirstChild());
1000     if (!composedStack) {
1001         return RefPtr<StackElement>();
1002     }
1003     const auto& stackElement = AceType::DynamicCast<StackElement>(composedStack->GetLastChild());
1004     if (!stackElement) {
1005         return RefPtr<StackElement>();
1006     }
1007     return stackElement;
1008 }
1009 
GetLastPage() const1010 RefPtr<PageElement> PipelineContext::GetLastPage() const
1011 {
1012     const auto& stageElement = GetStageElement();
1013     if (!stageElement) {
1014         LOGE("Get last page failed, stage element is null.");
1015         return nullptr;
1016     }
1017     return AceType::DynamicCast<PageElement>(stageElement->GetLastChild());
1018 }
1019 
GetLastPageRender() const1020 RefPtr<RenderNode> PipelineContext::GetLastPageRender() const
1021 {
1022     auto lastPage = GetLastPage();
1023     if (!lastPage) {
1024         return nullptr;
1025     }
1026     return lastPage->GetRenderNode();
1027 }
1028 
CanPushPage()1029 bool PipelineContext::CanPushPage()
1030 {
1031     auto stageElement = GetStageElement();
1032     return stageElement && stageElement->CanPushPage();
1033 }
1034 
IsTransitionStop() const1035 bool PipelineContext::IsTransitionStop() const
1036 {
1037     auto stageElement = GetStageElement();
1038     return stageElement && stageElement->IsTransitionStop();
1039 }
1040 
PushPage(const RefPtr<PageComponent> & pageComponent,const RefPtr<StageElement> & stage)1041 void PipelineContext::PushPage(const RefPtr<PageComponent>& pageComponent, const RefPtr<StageElement>& stage)
1042 {
1043     ACE_FUNCTION_TRACE();
1044     CHECK_RUN_ON(UI);
1045     std::unordered_map<std::string, std::string> params { { "pageUrl", pageComponent->GetPageUrl() } };
1046     ResSchedReportScope report("push_page", params);
1047     auto stageElement = stage;
1048     if (!stageElement) {
1049         // if not target stage, use root stage
1050         stageElement = GetStageElement();
1051         if (!stageElement) {
1052             LOGE("Get stage element failed!");
1053             return;
1054         }
1055     }
1056     buildingFirstPage_ = isFirstPage_;
1057     isFirstPage_ = false;
1058     if (PageTransitionComponent::HasTransitionComponent(AceType::DynamicCast<Component>(pageComponent))) {
1059         stageElement->PushPage(pageComponent);
1060     } else {
1061         RefPtr<DisplayComponent> display = AceType::MakeRefPtr<DisplayComponent>(pageComponent);
1062         stageElement->PushPage(display);
1063     }
1064 
1065 #if defined(ENABLE_ROSEN_BACKEND)
1066     if (GetIsDeclarative()) {
1067         FlushBuild();
1068         return;
1069     }
1070 #endif
1071 #if defined(ENABLE_NATIVE_VIEW)
1072     if (GetIsDeclarative()) {
1073         // if not use flutter scheduler, can flush pipeline immediately.
1074         if (isSurfaceReady_) {
1075             FlushPipelineImmediately();
1076         } else {
1077             FlushBuild();
1078         }
1079         return;
1080     }
1081 #endif
1082     FlushBuildAndLayoutBeforeSurfaceReady();
1083 }
1084 
PushPage(const RefPtr<PageComponent> & pageComponent)1085 void PipelineContext::PushPage(const RefPtr<PageComponent>& pageComponent)
1086 {
1087     PushPage(pageComponent, nullptr);
1088 }
1089 
PostponePageTransition()1090 void PipelineContext::PostponePageTransition()
1091 {
1092     CHECK_RUN_ON(UI);
1093     // if not target stage, use root stage
1094     auto stageElement = GetStageElement();
1095     if (!stageElement) {
1096         LOGE("Get stage element failed!");
1097         return;
1098     }
1099     stageElement->PostponePageTransition();
1100 }
1101 
LaunchPageTransition()1102 void PipelineContext::LaunchPageTransition()
1103 {
1104     CHECK_RUN_ON(UI);
1105     // if not target stage, use root stage
1106     auto stageElement = GetStageElement();
1107     if (!stageElement) {
1108         LOGE("Get stage element failed!");
1109         return;
1110     }
1111     stageElement->LaunchPageTransition();
1112 }
1113 
GetBoundingRectData(int32_t nodeId,Rect & rect)1114 void PipelineContext::GetBoundingRectData(int32_t nodeId, Rect& rect)
1115 {
1116     auto composeElement = GetComposedElementById(std::to_string(nodeId));
1117     if (composeElement) {
1118         Rect resultRect = composeElement->GetRenderRect();
1119         rect.SetWidth(resultRect.Width());
1120         rect.SetHeight(resultRect.Height());
1121         rect.SetTop(resultRect.Top());
1122         rect.SetLeft(resultRect.Left());
1123     }
1124 }
1125 
ShowDialog(const DialogProperties & dialogProperties,bool isRightToLeft,const std::string & inspectorTag)1126 RefPtr<DialogComponent> PipelineContext::ShowDialog(
1127     const DialogProperties& dialogProperties, bool isRightToLeft, const std::string& inspectorTag)
1128 {
1129     CHECK_RUN_ON(UI);
1130     const auto& dialog = DialogBuilder::Build(dialogProperties, AceType::WeakClaim(this));
1131     if (!dialog) {
1132         return nullptr;
1133     }
1134     dialog->SetInspectorTag(inspectorTag);
1135     auto customComponent = AceType::DynamicCast<Component>(dialogProperties.customComponent);
1136     if (customComponent) {
1137         dialog->SetCustomChild(customComponent);
1138     }
1139     dialog->SetTextDirection(isRightToLeft ? TextDirection::RTL : TextDirection::LTR);
1140     const auto& lastStack = GetLastStack();
1141     if (!lastStack) {
1142         return nullptr;
1143     }
1144     LOGI("PipelineContext::ShowDialog id is %{public}d", dialog->GetDialogId());
1145     lastStack->PushDialog(dialog);
1146     return dialog;
1147 }
1148 
CloseContextMenu()1149 void PipelineContext::CloseContextMenu()
1150 {
1151     auto menu = AceType::DynamicCast<SelectPopupComponent>(contextMenu_);
1152     if (menu) {
1153         menu->HideDialog(SELECT_INVALID_INDEX);
1154     }
1155 }
1156 
CanPopPage()1157 bool PipelineContext::CanPopPage()
1158 {
1159     auto stageElement = GetStageElement();
1160     return stageElement && stageElement->CanPopPage();
1161 }
1162 
PopPage()1163 void PipelineContext::PopPage()
1164 {
1165     CHECK_RUN_ON(UI);
1166     auto stageElement = GetStageElement();
1167     if (stageElement) {
1168         auto topElement = stageElement->GetTopPage();
1169         if (topElement != nullptr) {
1170             std::unordered_map<std::string, std::string> params { { "pageUrl", topElement->GetPageUrl() } };
1171             ResSchedReport::GetInstance().ResSchedDataReport("pop_page", params);
1172         }
1173         stageElement->Pop();
1174     }
1175     ExitAnimation();
1176 }
1177 
PopToPage(int32_t pageId)1178 void PipelineContext::PopToPage(int32_t pageId)
1179 {
1180     CHECK_RUN_ON(UI);
1181     auto stageElement = GetStageElement();
1182     if (stageElement) {
1183         stageElement->PopToPage(pageId);
1184     }
1185 }
1186 
RestorePopPage(const RefPtr<PageComponent> & pageComponent)1187 void PipelineContext::RestorePopPage(const RefPtr<PageComponent>& pageComponent)
1188 {
1189     CHECK_RUN_ON(UI);
1190     auto stageElement = GetStageElement();
1191     if (stageElement) {
1192         stageElement->RestorePopPage(pageComponent);
1193     }
1194 }
1195 
CanReplacePage()1196 bool PipelineContext::CanReplacePage()
1197 {
1198     auto stageElement = GetStageElement();
1199     return stageElement && stageElement->CanReplacePage();
1200 }
1201 
AddPageTransitionListener(const PageTransitionListenable::CallbackFuncType & funcObject)1202 BaseId::IdType PipelineContext::AddPageTransitionListener(const PageTransitionListenable::CallbackFuncType& funcObject)
1203 {
1204     if (!rootElement_) {
1205         LOGE("add page transition listener failed. root element is null.");
1206         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
1207         return 0;
1208     }
1209     auto stageElement = GetStageElement();
1210     if (!stageElement) {
1211         LOGE("add page transition listener failed. stage is null.");
1212         return 0;
1213     }
1214     return stageElement->AddPageTransitionListener(funcObject);
1215 }
1216 
RemovePageTransitionListener(typename BaseId::IdType id)1217 void PipelineContext::RemovePageTransitionListener(typename BaseId::IdType id)
1218 {
1219     auto stageElement = GetStageElement();
1220     if (stageElement) {
1221         stageElement->RemovePageTransitionListener(id);
1222     }
1223 }
1224 
ClearPageTransitionListeners()1225 void PipelineContext::ClearPageTransitionListeners()
1226 {
1227     auto stageElement = GetStageElement();
1228     if (stageElement) {
1229         return stageElement->ClearPageTransitionListeners();
1230     }
1231 }
1232 
ReplacePage(const RefPtr<PageComponent> & pageComponent,const RefPtr<StageElement> & stage,const std::function<void ()> & listener)1233 void PipelineContext::ReplacePage(const RefPtr<PageComponent>& pageComponent, const RefPtr<StageElement>& stage,
1234     const std::function<void()>& listener)
1235 {
1236     CHECK_RUN_ON(UI);
1237     auto stageElement = stage;
1238     if (!stage) {
1239         stageElement = GetStageElement();
1240         if (!stageElement) {
1241             LOGE("Get stage element failed!");
1242             return;
1243         }
1244     }
1245     if (PageTransitionComponent::HasTransitionComponent(AceType::DynamicCast<Component>(pageComponent))) {
1246         stageElement->Replace(pageComponent, listener);
1247     } else {
1248         RefPtr<DisplayComponent> display = AceType::MakeRefPtr<DisplayComponent>(pageComponent);
1249         stageElement->Replace(display, listener);
1250     }
1251 }
1252 
ReplacePage(const RefPtr<PageComponent> & pageComponent)1253 void PipelineContext::ReplacePage(const RefPtr<PageComponent>& pageComponent)
1254 {
1255     ReplacePage(pageComponent, nullptr);
1256 }
1257 
ClearInvisiblePages(const std::function<void ()> & listener)1258 bool PipelineContext::ClearInvisiblePages(const std::function<void()>& listener)
1259 {
1260     auto stageElement = GetStageElement();
1261     return stageElement && stageElement->ClearOffStage(listener);
1262 }
1263 
ExitAnimation()1264 void PipelineContext::ExitAnimation()
1265 {
1266     CHECK_RUN_ON(UI);
1267     if (IsLastPage()) {
1268         // semi modal use translucent theme and will do exit animation by ACE itself.
1269         if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN ||
1270             windowModal_ == WindowModal::DIALOG_MODAL) {
1271             taskExecutor_->PostTask(
1272                 [weak = AceType::WeakClaim(this)]() {
1273                     auto context = weak.Upgrade();
1274                     if (!context) {
1275                         return;
1276                     }
1277                     context->Finish();
1278                 },
1279                 TaskExecutor::TaskType::UI, "ArkUIExitAnimation");
1280         } else {
1281             // return back to desktop
1282             Finish();
1283         }
1284     }
1285 }
1286 
1287 // return true if user accept or page is not last, return false if others condition
CallRouterBackToPopPage(bool * isUserAccept)1288 bool PipelineContext::CallRouterBackToPopPage(bool* isUserAccept)
1289 {
1290     CHECK_RUN_ON(PLATFORM);
1291     auto frontend = weakFrontend_.Upgrade();
1292     if (!frontend) {
1293         // return back to desktop
1294         return false;
1295     }
1296 
1297     if (frontend->OnBackPressed()) {
1298         // if user accept
1299         LOGI("CallRouterBackToPopPage(): user consume the back key event");
1300         if (isUserAccept) {
1301             *isUserAccept = true;
1302         }
1303         return true;
1304     }
1305     auto stageElement = GetStageElement();
1306     // declarative frontend need use GetRouterSize to judge, others use GetChildrenList
1307     if (frontend->GetRouterSize() <= 1 && stageElement && stageElement->GetChildrenList().size() <= 1) {
1308         LOGI("CallRouterBackToPopPage(): current page is the last page");
1309         return false;
1310     }
1311     frontend->CallRouterBack();
1312     LOGI("CallRouterBackToPopPage(): current page is not the last");
1313     return true;
1314 }
1315 
PopPageStackOverlay()1316 bool PipelineContext::PopPageStackOverlay()
1317 {
1318     auto pageStack = GetLastStack();
1319     if (!pageStack) {
1320         LOGW("No page stack in page.");
1321         return false;
1322     }
1323     if (!pageStack->HasOverlayChild()) {
1324         LOGI("No overlay in page, try to pop page.");
1325         return false;
1326     }
1327     LOGI("Pop page overlays");
1328     // If last child is popup, use PopPopup to trigger state change event.
1329     if (pageStack->PopPopupIfExist()) {
1330         return true;
1331     }
1332 
1333     if (pageStack->PopDialogIfExist()) {
1334         return true;
1335     }
1336 
1337     pageStack->PopComponent();
1338     return true;
1339 }
1340 
HideOverlays()1341 void PipelineContext::HideOverlays()
1342 {
1343     CloseContextMenu();
1344     if (textOverlayManager_) {
1345         textOverlayManager_->PopTextOverlay();
1346     }
1347 }
1348 
ScheduleUpdate(const RefPtr<ComposedComponent> & compose)1349 void PipelineContext::ScheduleUpdate(const RefPtr<ComposedComponent>& compose)
1350 {
1351     CHECK_RUN_ON(UI);
1352     ComposeId id = compose->GetId();
1353     const auto& it = composedElementMap_.find(id);
1354     if (it != composedElementMap_.end()) {
1355         for (const auto& composedElement : it->second) {
1356             composedElement->SetUpdateComponent(compose);
1357         }
1358     }
1359     FlushBuildAndLayoutBeforeSurfaceReady();
1360 }
1361 
AddComposedElement(const ComposeId & id,const RefPtr<ComposedElement> & element)1362 void PipelineContext::AddComposedElement(const ComposeId& id, const RefPtr<ComposedElement>& element)
1363 {
1364     CHECK_RUN_ON(UI);
1365     auto it = composedElementMap_.find(id);
1366     if (it != composedElementMap_.end()) {
1367         it->second.emplace_back(element);
1368     } else {
1369         std::list<RefPtr<ComposedElement>> elements;
1370         elements.emplace_back(element);
1371         composedElementMap_[id] = std::move(elements);
1372     }
1373 }
1374 
RemoveComposedElement(const ComposeId & id,const RefPtr<ComposedElement> & element)1375 void PipelineContext::RemoveComposedElement(const ComposeId& id, const RefPtr<ComposedElement>& element)
1376 {
1377     CHECK_RUN_ON(UI);
1378     auto it = composedElementMap_.find(id);
1379     if (it != composedElementMap_.end()) {
1380         it->second.remove(element);
1381         if (it->second.empty()) {
1382             composedElementMap_.erase(it);
1383         }
1384     }
1385 }
1386 
AddDirtyElement(const RefPtr<Element> & dirtyElement)1387 void PipelineContext::AddDirtyElement(const RefPtr<Element>& dirtyElement)
1388 {
1389     CHECK_RUN_ON(UI);
1390     if (!dirtyElement) {
1391         LOGW("dirtyElement is null");
1392         return;
1393     }
1394     dirtyElements_.emplace(dirtyElement);
1395     hasIdleTasks_ = true;
1396     window_->RequestFrame();
1397 }
1398 
AddNeedRebuildFocusElement(const RefPtr<Element> & focusElement)1399 void PipelineContext::AddNeedRebuildFocusElement(const RefPtr<Element>& focusElement)
1400 {
1401     CHECK_RUN_ON(UI);
1402     if (!focusElement) {
1403         LOGW("focusElement is null");
1404         return;
1405     }
1406     needRebuildFocusElement_.emplace(focusElement);
1407 }
1408 
AddDirtyRenderNode(const RefPtr<RenderNode> & renderNode,bool overlay)1409 void PipelineContext::AddDirtyRenderNode(const RefPtr<RenderNode>& renderNode, bool overlay)
1410 {
1411     CHECK_RUN_ON(UI);
1412     if (!renderNode) {
1413         LOGW("renderNode is null");
1414         return;
1415     }
1416     if (!overlay) {
1417         dirtyRenderNodes_.emplace(renderNode);
1418     } else {
1419         dirtyRenderNodesInOverlay_.emplace(renderNode);
1420     }
1421     hasIdleTasks_ = true;
1422     window_->RequestFrame();
1423 }
1424 
AddNeedRenderFinishNode(const RefPtr<RenderNode> & renderNode)1425 void PipelineContext::AddNeedRenderFinishNode(const RefPtr<RenderNode>& renderNode)
1426 {
1427     CHECK_RUN_ON(UI);
1428     if (!renderNode) {
1429         LOGW("renderNode is null");
1430         return;
1431     }
1432     needPaintFinishNodes_.emplace(renderNode);
1433 }
1434 
AddDirtyLayoutNode(const RefPtr<RenderNode> & renderNode)1435 void PipelineContext::AddDirtyLayoutNode(const RefPtr<RenderNode>& renderNode)
1436 {
1437     CHECK_RUN_ON(UI);
1438     if (!renderNode) {
1439         LOGW("renderNode is null");
1440         return;
1441     }
1442     renderNode->SaveExplicitAnimationOption(explicitAnimationOption_);
1443     dirtyLayoutNodes_.emplace(renderNode);
1444     ForceLayoutForImplicitAnimation();
1445     hasIdleTasks_ = true;
1446     window_->RequestFrame();
1447 }
1448 
AddPredictLayoutNode(const RefPtr<RenderNode> & renderNode)1449 void PipelineContext::AddPredictLayoutNode(const RefPtr<RenderNode>& renderNode)
1450 {
1451     CHECK_RUN_ON(UI);
1452     if (!renderNode) {
1453         LOGW("renderNode is null");
1454         return;
1455     }
1456     predictLayoutNodes_.emplace(renderNode);
1457     ForceLayoutForImplicitAnimation();
1458     hasIdleTasks_ = true;
1459     window_->RequestFrame();
1460 }
1461 
AddGeometryChangedNode(const RefPtr<RenderNode> & renderNode)1462 void PipelineContext::AddGeometryChangedNode(const RefPtr<RenderNode>& renderNode)
1463 {
1464     geometryChangedNodes_.emplace(renderNode);
1465 }
1466 
AddPreFlushListener(const RefPtr<FlushEvent> & listener)1467 void PipelineContext::AddPreFlushListener(const RefPtr<FlushEvent>& listener)
1468 {
1469     CHECK_RUN_ON(UI);
1470     preFlushListeners_.emplace_back(listener);
1471     window_->RequestFrame();
1472 }
1473 
AddPostAnimationFlushListener(const RefPtr<FlushEvent> & listener)1474 void PipelineContext::AddPostAnimationFlushListener(const RefPtr<FlushEvent>& listener)
1475 {
1476     CHECK_RUN_ON(UI);
1477     postAnimationFlushListeners_.emplace_back(listener);
1478 }
1479 
AddPostFlushListener(const RefPtr<FlushEvent> & listener)1480 void PipelineContext::AddPostFlushListener(const RefPtr<FlushEvent>& listener)
1481 {
1482     CHECK_RUN_ON(UI);
1483     postFlushListeners_.emplace_back(listener);
1484     window_->RequestFrame();
1485 }
1486 
AddScheduleTask(const RefPtr<ScheduleTask> & task)1487 uint32_t PipelineContext::AddScheduleTask(const RefPtr<ScheduleTask>& task)
1488 {
1489     CHECK_RUN_ON(UI);
1490     scheduleTasks_.try_emplace(++nextScheduleTaskId_, task);
1491     window_->RequestFrame();
1492     return nextScheduleTaskId_;
1493 }
1494 
SetRequestedRotationNode(const WeakPtr<RenderNode> & renderNode)1495 void PipelineContext::SetRequestedRotationNode(const WeakPtr<RenderNode>& renderNode)
1496 {
1497     auto node = renderNode.Upgrade();
1498     if (!node) {
1499         return;
1500     }
1501     requestedRenderNode_ = renderNode;
1502 }
1503 
RemoveRequestedRotationNode(const WeakPtr<RenderNode> & renderNode)1504 void PipelineContext::RemoveRequestedRotationNode(const WeakPtr<RenderNode>& renderNode)
1505 {
1506     if (requestedRenderNode_ == renderNode) {
1507         requestedRenderNode_.Reset();
1508     }
1509 }
1510 
RemoveScheduleTask(uint32_t id)1511 void PipelineContext::RemoveScheduleTask(uint32_t id)
1512 {
1513     CHECK_RUN_ON(UI);
1514     scheduleTasks_.erase(id);
1515 }
1516 
DragTestAll(const TouchEvent & point)1517 RefPtr<RenderNode> PipelineContext::DragTestAll(const TouchEvent& point)
1518 {
1519     return DragTest(point, rootElement_->GetRenderNode(), 0);
1520 }
1521 
DragTest(const TouchEvent & point,const RefPtr<RenderNode> & renderNode,int32_t deep)1522 RefPtr<RenderNode> PipelineContext::DragTest(
1523     const TouchEvent& point, const RefPtr<RenderNode>& renderNode, int32_t deep)
1524 {
1525     if (AceType::InstanceOf<RenderBox>(renderNode) && renderNode->onDomDragEnter_ && renderNode->IsPointInBox(point)) {
1526         return renderNode;
1527     }
1528 
1529     std::list<RefPtr<RenderNode>> renderNodeLst = renderNode->GetChildren();
1530     for (auto it = renderNodeLst.begin(); it != renderNodeLst.end(); it++) {
1531         RefPtr<RenderNode> tmp = DragTest(point, *it, deep + 1);
1532         if (tmp != nullptr) {
1533             return tmp;
1534         }
1535     }
1536     return nullptr;
1537 }
1538 
OnTouchEvent(const TouchEvent & point,bool isSubPipe)1539 void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe)
1540 {
1541     CHECK_RUN_ON(UI);
1542     ACE_FUNCTION_TRACE();
1543     if (!rootElement_) {
1544         LOGE("root element is nullptr");
1545         return;
1546     }
1547     auto scalePoint = point.CreateScalePoint(viewScale_);
1548     ReportConfig config;
1549     ResSchedReport::GetInstance().OnTouchEvent(scalePoint, config);
1550     if (scalePoint.type == TouchType::DOWN) {
1551         eventManager_->HandleOutOfRectCallback(
1552             { scalePoint.x, scalePoint.y, scalePoint.sourceType }, rectCallbackList_);
1553         eventManager_->HandleGlobalEvent(scalePoint, textOverlayManager_);
1554         TouchRestrict touchRestrict { TouchRestrict::NONE };
1555         touchRestrict.sourceType = point.sourceType;
1556         auto frontEnd = GetFrontend();
1557         if (frontEnd && (frontEnd->GetType() == FrontendType::JS_CARD)) {
1558             touchRestrict.UpdateForbiddenType(TouchRestrict::LONG_PRESS);
1559         }
1560         eventManager_->TouchTest(
1561             scalePoint, rootElement_->GetRenderNode(), touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe);
1562 
1563         for (size_t i = 0; i < touchPluginPipelineContext_.size(); i++) {
1564             auto pipelineContext = DynamicCast<PipelineContext>(touchPluginPipelineContext_[i].Upgrade());
1565             if (!pipelineContext || !pipelineContext->rootElement_) {
1566                 continue;
1567             }
1568             auto pluginPoint = point.UpdateScalePoint(viewScale_, pipelineContext->GetPluginEventOffset().GetX(),
1569                 pipelineContext->GetPluginEventOffset().GetY(), point.id);
1570             auto eventManager = pipelineContext->GetEventManager();
1571             if (eventManager) {
1572                 eventManager->SetInstanceId(pipelineContext->GetInstanceId());
1573             }
1574             pipelineContext->OnTouchEvent(pluginPoint, true);
1575         }
1576     }
1577     isMoving_ = scalePoint.type == TouchType::MOVE ? true : isMoving_;
1578     if (isKeyEvent_) {
1579         SetIsKeyEvent(false);
1580     }
1581     if (isSubPipe) {
1582         return;
1583     }
1584     if (scalePoint.type == TouchType::MOVE) {
1585         touchEvents_.emplace_back(point);
1586         window_->RequestFrame();
1587         return;
1588     }
1589 
1590     std::optional<TouchEvent> lastMoveEvent;
1591     if (scalePoint.type == TouchType::UP && !touchEvents_.empty()) {
1592         for (auto iter = touchEvents_.begin(); iter != touchEvents_.end();) {
1593             auto movePoint = (*iter).CreateScalePoint(GetViewScale());
1594             if (scalePoint.id == movePoint.id) {
1595                 lastMoveEvent = movePoint;
1596                 iter = touchEvents_.erase(iter);
1597             } else {
1598                 ++iter;
1599             }
1600         }
1601         if (lastMoveEvent.has_value()) {
1602             eventManager_->DispatchTouchEvent(lastMoveEvent.value());
1603         }
1604     }
1605 
1606     eventManager_->DispatchTouchEvent(scalePoint);
1607     if (scalePoint.type == TouchType::UP) {
1608         touchPluginPipelineContext_.clear();
1609         eventManager_->SetInstanceId(GetInstanceId());
1610     }
1611     window_->RequestFrame();
1612 }
1613 
FlushTouchEvents()1614 void PipelineContext::FlushTouchEvents()
1615 {
1616     CHECK_RUN_ON(UI);
1617     ACE_FUNCTION_TRACE();
1618     if (!rootElement_) {
1619         LOGE("root element is nullptr");
1620         return;
1621     }
1622     {
1623         eventManager_->FlushTouchEventsBegin(touchEvents_);
1624         std::unordered_set<int32_t> moveEventIds;
1625         decltype(touchEvents_) touchEvents(std::move(touchEvents_));
1626         if (touchEvents.empty()) {
1627             return;
1628         }
1629         std::list<TouchEvent> touchPoints;
1630         for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter) {
1631             auto scalePoint = (*iter).CreateScalePoint(GetViewScale());
1632             auto result = moveEventIds.emplace(scalePoint.id);
1633             if (result.second) {
1634                 touchPoints.emplace_front(scalePoint);
1635             }
1636         }
1637 
1638         auto maxSize = touchPoints.size();
1639         for (auto iter = touchPoints.rbegin(); iter != touchPoints.rend(); ++iter) {
1640             maxSize--;
1641             if (maxSize == 0) {
1642                 eventManager_->FlushTouchEventsEnd(touchPoints);
1643             }
1644             eventManager_->DispatchTouchEvent(*iter);
1645         }
1646     }
1647 }
1648 
OnKeyEvent(const NonPointerEvent & nonPointerEvent)1649 bool PipelineContext::OnKeyEvent(const NonPointerEvent& nonPointerEvent)
1650 {
1651     CHECK_RUN_ON(UI);
1652     if (nonPointerEvent.eventType != UIInputEventType::KEY) {
1653         return false;
1654     }
1655     const auto& event = static_cast<const KeyEvent&>(nonPointerEvent);
1656     if (!rootElement_) {
1657         LOGE("the root element is nullptr");
1658         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
1659         return false;
1660     }
1661     rootElement_->HandleSpecifiedKey(event);
1662     SetShortcutKey(event);
1663     pressedKeyCodes = event.pressedCodes;
1664     isKeyCtrlPressed_ = !pressedKeyCodes.empty() && (pressedKeyCodes.back() == KeyCode::KEY_CTRL_LEFT ||
1665                                                         pressedKeyCodes.back() == KeyCode::KEY_CTRL_RIGHT);
1666     if ((event.code == KeyCode::KEY_CTRL_LEFT || event.code == KeyCode::KEY_CTRL_RIGHT) &&
1667         event.action == KeyAction::UP) {
1668         if (isOnScrollZoomEvent_) {
1669             zoomEventA_.type = TouchType::UP;
1670             zoomEventB_.type = TouchType::UP;
1671             LOGI("Send TouchEventA(%{public}f, %{public}f, %{public}zu)", zoomEventA_.x, zoomEventA_.y,
1672                 zoomEventA_.type);
1673             OnTouchEvent(zoomEventA_);
1674             LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y,
1675                 zoomEventB_.type);
1676             OnTouchEvent(zoomEventB_);
1677             isOnScrollZoomEvent_ = false;
1678         }
1679     }
1680 
1681     if (event.code == KeyCode::KEY_TAB && event.action == KeyAction::DOWN && !isTabKeyPressed_) {
1682         isTabKeyPressed_ = true;
1683     }
1684     CHECK_NULL_RETURN(rootElement_, false);
1685     auto lastPage = GetLastPage();
1686     bool isHandleByTabIndex = false;
1687     if (lastPage) {
1688         isHandleByTabIndex = rootElement_->HandleFocusByTabIndex(event, lastPage);
1689     } else {
1690         isHandleByTabIndex = rootElement_->HandleFocusByTabIndex(event, rootElement_);
1691     }
1692     if (isHandleByTabIndex) {
1693         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "Tab index focus system handled this event");
1694         return true;
1695     }
1696     if (rootElement_->HandleKeyEvent(event)) {
1697         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "Default focus system handled this event");
1698         return true;
1699     }
1700     return false;
1701 }
1702 
1703 constexpr double ANGULAR_VELOCITY_FACTOR = 0.001f;
1704 constexpr float ANGULAR_VELOCITY_SLOW = 0.07f;
1705 constexpr float ANGULAR_VELOCITY_MEDIUM = 0.2f;
1706 constexpr float ANGULAR_VELOCITY_FAST = 0.54f;
1707 constexpr float DISPLAY_CONTROL_RATIO_VERY_SLOW = 1.19f;
1708 constexpr float DISPLAY_CONTROL_RATIO_SLOW = 1.87f;
1709 constexpr float DISPLAY_CONTROL_RATIO_MEDIUM = 1.67f;
1710 constexpr float DISPLAY_CONTROL_RATIO_FAST = 1.59f;
1711 
GetCrownRotateVP(const CrownEvent & event)1712 double GetCrownRotateVP(const CrownEvent& event)
1713 {
1714     double velocity = std::abs(event.angularVelocity * ANGULAR_VELOCITY_FACTOR);
1715     double vp = 0.0;
1716     if (LessOrEqualCustomPrecision(velocity, ANGULAR_VELOCITY_SLOW, 0.01f)) { // very slow
1717         vp = (Dimension(DISPLAY_CONTROL_RATIO_VERY_SLOW, DimensionUnit::VP) * event.degree).ConvertToVp();
1718     } else if (LessOrEqualCustomPrecision(velocity, ANGULAR_VELOCITY_MEDIUM, 0.01f)) { // slow
1719         vp = (Dimension(DISPLAY_CONTROL_RATIO_SLOW, DimensionUnit::VP) * event.degree).ConvertToVp();
1720     } else if (LessOrEqualCustomPrecision(velocity, ANGULAR_VELOCITY_FAST, 0.01f)) { // medium
1721         vp = (Dimension(DISPLAY_CONTROL_RATIO_MEDIUM, DimensionUnit::VP) * event.degree).ConvertToVp();
1722     } else { // fast
1723         vp = (Dimension(DISPLAY_CONTROL_RATIO_FAST, DimensionUnit::VP) * event.degree).ConvertToVp();
1724     }
1725     return vp;
1726 }
1727 
OnNonPointerEvent(const NonPointerEvent & nonPointerEvent)1728 bool PipelineContext::OnNonPointerEvent(const NonPointerEvent& nonPointerEvent)
1729 {
1730     CHECK_RUN_ON(UI);
1731     if (nonPointerEvent.eventType == UIInputEventType::KEY) {
1732         return OnKeyEvent(nonPointerEvent);
1733     } else if (nonPointerEvent.eventType == UIInputEventType::CROWN) {
1734         const auto& crownEvent = static_cast<const CrownEvent&>(nonPointerEvent);
1735         RotationEvent rotationEvent;
1736         rotationEvent.value = GetCrownRotateVP(crownEvent);
1737         return OnRotationEvent(rotationEvent);
1738     }
1739     return false;
1740 }
1741 
RequestDefaultFocus()1742 bool PipelineContext::RequestDefaultFocus()
1743 {
1744     RefPtr<FocusNode> defaultFocusNode;
1745     std::string mainNodeName;
1746     auto curPageElement = GetLastPage();
1747     if (curPageElement) {
1748         if (curPageElement->IsDefaultHasFocused()) {
1749             return false;
1750         }
1751         curPageElement->SetIsDefaultHasFocused(true);
1752         defaultFocusNode = curPageElement->GetChildDefaultFocusNode();
1753         mainNodeName = std::string(AceType::TypeName(curPageElement));
1754     } else if (rootElement_) {
1755         if (rootElement_->IsDefaultHasFocused()) {
1756             return false;
1757         }
1758         rootElement_->SetIsDefaultHasFocused(true);
1759         defaultFocusNode = rootElement_->GetChildDefaultFocusNode();
1760         mainNodeName = std::string(AceType::TypeName(rootElement_));
1761     } else {
1762         LOGE("RequestDefaultFocus: rootElement or pageElement is nullptr!");
1763         return false;
1764     }
1765     if (!defaultFocusNode) {
1766         return false;
1767     }
1768     if (!defaultFocusNode->IsFocusableWholePath()) {
1769         return false;
1770     }
1771     return defaultFocusNode->RequestFocusImmediately();
1772 }
1773 
SetShortcutKey(const KeyEvent & event)1774 void PipelineContext::SetShortcutKey(const KeyEvent& event)
1775 {
1776     if (event.action == KeyAction::DOWN) {
1777         auto codeValue = static_cast<int32_t>(event.code);
1778         if (codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_LEFT) ||
1779             codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_RIGHT)) {
1780             MarkIsShiftDown(true);
1781         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_LEFT) ||
1782                    codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_RIGHT)) {
1783             MarkIsCtrlDown(true);
1784         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_A)) {
1785             MarkIsKeyboardA(true);
1786             if (subscribeCtrlA_) {
1787                 subscribeCtrlA_();
1788             }
1789         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_C)) {
1790             if (textOverlayManager_) {
1791                 textOverlayManager_->HandleCtrlC();
1792             }
1793         }
1794     } else if (event.action == KeyAction::UP) {
1795         auto codeValue = static_cast<int32_t>(event.code);
1796         if (codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_LEFT) ||
1797             codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_RIGHT)) {
1798             MarkIsShiftDown(false);
1799         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_LEFT) ||
1800                    codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_RIGHT)) {
1801             MarkIsCtrlDown(false);
1802         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_A)) {
1803             MarkIsKeyboardA(false);
1804         }
1805     }
1806 }
1807 
OnMouseEvent(const MouseEvent & event)1808 void PipelineContext::OnMouseEvent(const MouseEvent& event)
1809 {
1810     CHECK_RUN_ON(UI);
1811 
1812     if ((event.action == MouseAction::RELEASE || event.action == MouseAction::PRESS ||
1813             event.action == MouseAction::MOVE) &&
1814         (event.button == MouseButton::LEFT_BUTTON || event.pressedButtons == MOUSE_PRESS_LEFT)) {
1815         auto touchPoint = event.CreateTouchPoint();
1816         OnTouchEvent(touchPoint);
1817     }
1818 
1819     CHECK_NULL_VOID(rootElement_);
1820     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1821     if (event.action == MouseAction::PRESS && event.button != MouseButton::LEFT_BUTTON) {
1822         eventManager_->HandleOutOfRectCallback(
1823             { scaleEvent.x, scaleEvent.y, scaleEvent.sourceType }, rectCallbackList_);
1824     }
1825     eventManager_->MouseTest(scaleEvent, rootElement_->GetRenderNode());
1826     eventManager_->DispatchMouseEvent(scaleEvent);
1827     eventManager_->DispatchMouseHoverAnimation(scaleEvent);
1828     eventManager_->DispatchMouseHoverEvent(scaleEvent);
1829 #ifdef ENABLE_ROSEN_BACKEND
1830     std::chrono::high_resolution_clock::duration epoch_time = event.time.time_since_epoch();
1831     auto eventTimestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch_time);
1832     if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_) {
1833         std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
1834                                       ? AceApplicationInfo::GetInstance().GetPackageName()
1835                                       : AceApplicationInfo::GetInstance().GetProcessName();
1836         rsUIDirector_->SetTimeStamp(eventTimestamp.count(), abilityName);
1837     }
1838 #endif
1839     FlushMessages();
1840 }
1841 
CreateTouchEventOnZoom(const AxisEvent & event)1842 void PipelineContext::CreateTouchEventOnZoom(const AxisEvent& event)
1843 {
1844     zoomEventA_.id = 0;
1845     zoomEventB_.id = 1;
1846     zoomEventA_.type = zoomEventB_.type = TouchType::UNKNOWN;
1847     zoomEventA_.time = zoomEventB_.time = event.time;
1848     zoomEventA_.deviceId = zoomEventB_.deviceId = event.deviceId;
1849     zoomEventA_.sourceType = zoomEventB_.sourceType = SourceType::MOUSE;
1850     if (!isOnScrollZoomEvent_) {
1851         zoomEventA_.x = zoomEventA_.screenX = event.x - ZOOM_DISTANCE_DEFAULT;
1852         zoomEventA_.y = zoomEventA_.screenY = event.y;
1853         zoomEventA_.type = TouchType::DOWN;
1854         zoomEventB_.x = zoomEventB_.screenX = event.x + ZOOM_DISTANCE_DEFAULT;
1855         zoomEventB_.y = zoomEventB_.screenY = event.y;
1856         zoomEventB_.type = TouchType::DOWN;
1857         LOGI("Send TouchEventA(%{public}f, %{public}f, %{public}zu)", zoomEventA_.x, zoomEventA_.y, zoomEventA_.type);
1858         OnTouchEvent(zoomEventA_);
1859         LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y, zoomEventB_.type);
1860         OnTouchEvent(zoomEventB_);
1861         isOnScrollZoomEvent_ = true;
1862     }
1863     if (LessOrEqual(event.verticalAxis, 0.0)) {
1864         zoomEventA_.x = zoomEventA_.screenX -= ZOOM_DISTANCE_MOVE_PER_WHEEL;
1865         zoomEventA_.type = TouchType::MOVE;
1866         LOGI("Send TouchEventA(%{public}f, %{public}f, %{public}zu)", zoomEventA_.x, zoomEventA_.y, zoomEventA_.type);
1867         OnTouchEvent(zoomEventA_);
1868         zoomEventB_.x = zoomEventB_.screenX += ZOOM_DISTANCE_MOVE_PER_WHEEL;
1869         zoomEventB_.type = TouchType::MOVE;
1870         LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y, zoomEventB_.type);
1871         OnTouchEvent(zoomEventB_);
1872     } else {
1873         if (!NearEqual(zoomEventA_.x, event.x)) {
1874             zoomEventA_.x = zoomEventA_.screenX += ZOOM_DISTANCE_MOVE_PER_WHEEL;
1875             zoomEventA_.type = TouchType::MOVE;
1876             LOGI("Send TouchEventA(%{public}f, %{public}f, %{public}zu)", zoomEventA_.x, zoomEventA_.y,
1877                 zoomEventA_.type);
1878             OnTouchEvent(zoomEventA_);
1879         }
1880         if (!NearEqual(zoomEventB_.x, event.x)) {
1881             zoomEventB_.x = zoomEventB_.screenX -= ZOOM_DISTANCE_MOVE_PER_WHEEL;
1882             zoomEventB_.type = TouchType::MOVE;
1883             LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y,
1884                 zoomEventB_.type);
1885             OnTouchEvent(zoomEventB_);
1886         }
1887     }
1888 }
1889 
ConvertAxisToMouse(const AxisEvent & event)1890 MouseEvent ConvertAxisToMouse(const AxisEvent& event)
1891 {
1892     MouseEvent result;
1893     result.x = event.x;
1894     result.y = event.y;
1895     result.action = MouseAction::MOVE;
1896     result.button = MouseButton::NONE_BUTTON;
1897     result.time = event.time;
1898     result.deviceId = event.deviceId;
1899     result.sourceType = event.sourceType;
1900     return result;
1901 }
1902 
OnAxisEvent(const AxisEvent & event)1903 void PipelineContext::OnAxisEvent(const AxisEvent& event)
1904 {
1905     if (isKeyCtrlPressed_ && !NearZero(event.verticalAxis) &&
1906         (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE)) {
1907         CreateTouchEventOnZoom(event);
1908         return;
1909     }
1910 
1911     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1912 
1913     if (event.action == AxisAction::BEGIN) {
1914         TouchRestrict touchRestrict { TouchRestrict::NONE };
1915         eventManager_->TouchTest(scaleEvent, rootElement_->GetRenderNode(), touchRestrict);
1916     }
1917     eventManager_->DispatchTouchEvent(scaleEvent);
1918 
1919     if (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE) {
1920         eventManager_->AxisTest(scaleEvent, rootElement_->GetRenderNode());
1921         eventManager_->DispatchAxisEvent(scaleEvent);
1922     }
1923 
1924     auto mouseEvent = ConvertAxisToMouse(event);
1925     OnMouseEvent(mouseEvent);
1926 }
1927 
AddToHoverList(const RefPtr<RenderNode> & node)1928 void PipelineContext::AddToHoverList(const RefPtr<RenderNode>& node)
1929 {
1930     CHECK_RUN_ON(UI);
1931     int32_t nodeId = node->GetAccessibilityNodeId();
1932     if (nodeId == 0) {
1933         return;
1934     }
1935     if (nodeId != hoverNodeId_) {
1936         // Hover node changed to the next id.
1937         hoverNodes_.clear();
1938         hoverNodes_.emplace_back(node);
1939         hoverNodeId_ = nodeId;
1940     } else {
1941         // Hover node add to current hover list.
1942         hoverNodes_.emplace_back(node);
1943     }
1944 }
1945 
OnRotationEvent(const RotationEvent & event) const1946 bool PipelineContext::OnRotationEvent(const RotationEvent& event) const
1947 {
1948     CHECK_RUN_ON(UI);
1949     if (!rootElement_) {
1950         LOGE("the root element is nullptr");
1951         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
1952         return false;
1953     }
1954 
1955     RefPtr<StackElement> stackElement = GetLastStack();
1956     if (!stackElement) {
1957         LOGE("the stack element is nullptr");
1958         return false;
1959     }
1960     RefPtr<RenderNode> stackRenderNode = stackElement->GetRenderNode();
1961     if (!stackRenderNode) {
1962         LOGE("the stack render node is nullptr");
1963         return false;
1964     }
1965 
1966     return eventManager_->DispatchRotationEvent(event, stackRenderNode, requestedRenderNode_.Upgrade());
1967 }
1968 
SetCardViewPosition(int id,float offsetX,float offsetY)1969 void PipelineContext::SetCardViewPosition(int id, float offsetX, float offsetY)
1970 {
1971     auto accessibilityManager = GetAccessibilityManager();
1972     if (!accessibilityManager) {
1973         return;
1974     }
1975     accessibilityManager->SetCardViewPosition(id, offsetX, offsetY);
1976 }
1977 
SetCardViewAccessibilityParams(const std::string & key,bool focus)1978 void PipelineContext::SetCardViewAccessibilityParams(const std::string& key, bool focus)
1979 {
1980     auto accessibilityManager = GetAccessibilityManager();
1981     if (!accessibilityManager) {
1982         return;
1983     }
1984     accessibilityManager->SetCardViewParams(key, focus);
1985 }
1986 
FlushVsync(uint64_t nanoTimestamp,uint64_t frameCount)1987 void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint64_t frameCount)
1988 {
1989     CHECK_RUN_ON(UI);
1990     ACE_FUNCTION_TRACK();
1991 #if defined(ENABLE_NATIVE_VIEW)
1992     if (frameCount_ < 2) {
1993         frameCount_++;
1994     }
1995 #endif
1996 #ifdef ENABLE_ROSEN_BACKEND
1997     if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_) {
1998         std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
1999                                       ? AceApplicationInfo::GetInstance().GetPackageName()
2000                                       : AceApplicationInfo::GetInstance().GetProcessName();
2001         rsUIDirector_->SetTimeStamp(nanoTimestamp, abilityName);
2002     }
2003 #endif
2004     if (isSurfaceReady_) {
2005         FlushTouchEvents();
2006         FlushAnimation(GetTimeFromExternalTimer());
2007         FlushPipelineWithoutAnimation();
2008         FlushAnimationTasks();
2009         window_->FlushLayoutSize(width_, height_);
2010         hasIdleTasks_ = false;
2011     } else {
2012         LOGW("the surface is not ready, waiting");
2013     }
2014     if (isMoving_) {
2015         window_->RequestFrame();
2016         MarkForcedRefresh();
2017         isMoving_ = false;
2018     }
2019 }
2020 
OnIdle(int64_t deadline)2021 void PipelineContext::OnIdle(int64_t deadline)
2022 {
2023     CHECK_RUN_ON(UI);
2024     ACE_FUNCTION_TRACE();
2025     auto front = GetFrontend();
2026     if (front && GetIsDeclarative()) {
2027         if (deadline != 0) {
2028             FlushPredictLayout(deadline);
2029         }
2030         return;
2031     }
2032     FlushPredictLayout(deadline);
2033     if (hasIdleTasks_) {
2034         FlushPipelineImmediately();
2035         window_->RequestFrame();
2036         MarkForcedRefresh();
2037         hasIdleTasks_ = false;
2038     }
2039     FlushPageUpdateTasks();
2040 }
2041 
OnVirtualKeyboardHeightChange(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance,bool forceChange)2042 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight,
2043     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, const bool supportAvoidance,
2044     bool forceChange)
2045 {
2046     CHECK_RUN_ON(UI);
2047     ACE_FUNCTION_TRACE();
2048 #ifdef ENABLE_ROSEN_BACKEND
2049     if (rsTransaction) {
2050         FlushMessages();
2051         rsTransaction->Begin();
2052     }
2053 #endif
2054 
2055     auto func = [this, keyboardHeight]() {
2056         double positionY = 0;
2057         if (textFieldManager_) {
2058             positionY = textFieldManager_->GetClickPosition().GetY();
2059         }
2060         auto newKeyboardHeight = keyboardHeight / viewScale_;
2061         auto height = height_ / viewScale_;
2062         double offsetFix =
2063             (height - positionY) > 100.0 ? newKeyboardHeight - (height - positionY) / 2.0 : newKeyboardHeight;
2064         LOGI("OnVirtualKeyboardAreaChange positionY:%{public}f safeArea:%{public}f offsetFix:%{public}f", positionY,
2065             (height - newKeyboardHeight), offsetFix);
2066         if (NearZero(newKeyboardHeight)) {
2067             if (textFieldManager_ && AceType::InstanceOf<TextFieldManager>(textFieldManager_)) {
2068                 auto textFieldManager = AceType::DynamicCast<TextFieldManager>(textFieldManager_);
2069                 if (textFieldManager->ResetSlidingPanelParentHeight()) {
2070                     return;
2071                 }
2072             }
2073             SetRootSizeWithWidthHeight(width_, height_, 0);
2074             rootOffset_.SetY(0.0);
2075         } else if (positionY > (height - newKeyboardHeight) && offsetFix > 0.0) {
2076             if (textFieldManager_ && AceType::InstanceOf<TextFieldManager>(textFieldManager_)) {
2077                 auto textFieldManager = AceType::DynamicCast<TextFieldManager>(textFieldManager_);
2078                 if (textFieldManager->UpdatePanelForVirtualKeyboard(-offsetFix, height)) {
2079                     return;
2080                 }
2081             }
2082             SetRootSizeWithWidthHeight(width_, height_, -offsetFix);
2083             rootOffset_.SetY(-offsetFix);
2084         }
2085     };
2086 
2087     AnimationOption option = AnimationUtil::CreateKeyboardAnimationOption(keyboardAnimationConfig_, keyboardHeight);
2088     Animate(option, option.GetCurve(), func);
2089 
2090 #ifdef ENABLE_ROSEN_BACKEND
2091     if (rsTransaction) {
2092         rsTransaction->Commit();
2093     }
2094 #endif
2095 }
2096 
FlushPipelineImmediately()2097 void PipelineContext::FlushPipelineImmediately()
2098 {
2099     CHECK_RUN_ON(UI);
2100     ACE_FUNCTION_TRACE();
2101     if (isSurfaceReady_) {
2102         FlushPipelineWithoutAnimation();
2103     } else {
2104         LOGW("the surface is not ready, waiting");
2105     }
2106 }
2107 
WindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2108 void PipelineContext::WindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type,
2109     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2110 {
2111     static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
2112     if (!rootElement_ || !rootElement_->GetRenderNode() || !IsWindowSizeAnimationEnabled) {
2113         LOGE("RootNodeAnimation: no root element found, no animation configured");
2114         SetRootSizeWithWidthHeight(width, height);
2115         return;
2116     }
2117     auto rootNode = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2118     switch (type) {
2119         case WindowSizeChangeReason::RECOVER:
2120         case WindowSizeChangeReason::MAXIMIZE: {
2121             AnimationOption option;
2122             constexpr int32_t duration = 400;
2123             option.SetDuration(duration);
2124             auto curve = MakeRefPtr<DecelerationCurve>();
2125             option.SetCurve(curve);
2126             Animate(option, curve, [width, height, this]() {
2127                 SetRootSizeWithWidthHeight(width, height);
2128                 FlushLayout();
2129             });
2130             break;
2131         }
2132         case WindowSizeChangeReason::ROTATION: {
2133             SetRootSizeWithWidthHeight(width, height);
2134             FlushLayout();
2135             break;
2136         }
2137         case WindowSizeChangeReason::DRAG_START:
2138         case WindowSizeChangeReason::DRAG:
2139         case WindowSizeChangeReason::DRAG_END:
2140         case WindowSizeChangeReason::RESIZE:
2141         case WindowSizeChangeReason::UNDEFINED:
2142         default: {
2143             SetRootSizeWithWidthHeight(width, height);
2144         }
2145     }
2146 }
2147 
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2148 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type,
2149     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2150 {
2151     CHECK_RUN_ON(UI);
2152     if (width_ == width && height_ == height && type == WindowSizeChangeReason::CUSTOM_ANIMATION) {
2153         TryCallNextFrameLayoutCallback();
2154         return;
2155     }
2156     // Refresh the screen when developers customize the resolution and screen density on the PC preview.
2157 #if !defined(PREVIEW)
2158     if (width_ == width && height_ == height && isSurfaceReady_ && !isDensityUpdate_) {
2159         return;
2160     }
2161 #endif
2162 
2163     for (auto&& [id, callback] : surfaceChangedCallbackMap_) {
2164         if (callback) {
2165             callback(width, height, width_, height_, type);
2166         }
2167     }
2168 
2169     width_ = width;
2170     height_ = height;
2171 
2172     ACE_SCOPED_TRACE("OnSurfaceChanged(%d, %d)", width, height);
2173     LOGI("Surface size changed, [%{public}d * %{public}d]", width, height);
2174     if (!NearZero(rootHeight_)) {
2175         double newRootHeight = height / viewScale_;
2176         double newRootWidth = width / viewScale_;
2177         double offsetHeight = rootHeight_ - newRootHeight;
2178         if (textFieldManager_ && GetLastPage()) {
2179             textFieldManager_->MovePage(GetLastPage()->GetPageId(), { newRootWidth, newRootHeight }, offsetHeight);
2180         }
2181     }
2182 
2183     taskExecutor_->PostTask(
2184         [weakFrontend = weakFrontend_, width, height]() {
2185             auto frontend = weakFrontend.Upgrade();
2186             if (frontend) {
2187                 frontend->OnSurfaceChanged(width, height);
2188             }
2189         },
2190         TaskExecutor::TaskType::JS, "ArkUISurfaceChanged");
2191 
2192     // init transition clip size when surface changed.
2193     const auto& pageElement = GetLastPage();
2194     if (pageElement) {
2195         const auto& transitionElement = AceType::DynamicCast<PageTransitionElement>(pageElement->GetFirstChild());
2196         if (transitionElement) {
2197             transitionElement->InitTransitionClip();
2198         }
2199     }
2200 #ifdef ENABLE_ROSEN_BACKEND
2201     WindowSizeChangeAnimate(width, height, type, rsTransaction);
2202 #else
2203     SetRootSizeWithWidthHeight(width, height);
2204 #endif
2205     if (isSurfaceReady_) {
2206         return;
2207     }
2208     isSurfaceReady_ = true;
2209     FlushPipelineWithoutAnimation();
2210     MarkForcedRefresh();
2211 #ifndef WEARABLE_PRODUCT
2212     multiModalManager_->OpenChannel(Claim(this));
2213 #endif
2214 }
2215 
OnSurfacePositionChanged(int32_t posX,int32_t posY)2216 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
2217 {
2218     for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
2219         if (callback) {
2220             callback(posX, posY);
2221         }
2222     }
2223 }
2224 
OnSurfaceDensityChanged(double density)2225 void PipelineContext::OnSurfaceDensityChanged(double density)
2226 {
2227     CHECK_RUN_ON(UI);
2228     ACE_SCOPED_TRACE("OnSurfaceDensityChanged(%lf)", density);
2229     isDensityUpdate_ = density != density_;
2230     density_ = density;
2231     if (!NearZero(viewScale_)) {
2232         dipScale_ = density_ / viewScale_;
2233     }
2234     if (isDensityUpdate_) {
2235         PipelineBase::OnSurfaceDensityChanged(density);
2236     }
2237 }
2238 
OnSystemBarHeightChanged(double statusBar,double navigationBar)2239 void PipelineContext::OnSystemBarHeightChanged(double statusBar, double navigationBar)
2240 {
2241     CHECK_RUN_ON(UI);
2242     ACE_SCOPED_TRACE("OnSystemBarHeightChanged(%lf, %lf)", statusBar, navigationBar);
2243     double statusBarHeight = 0.0;
2244     double navigationBarHeight = 0.0;
2245     if (!NearZero(viewScale_) && !NearZero(dipScale_)) {
2246         statusBarHeight = statusBar / viewScale_ / dipScale_;
2247         navigationBarHeight = navigationBar / viewScale_ / dipScale_;
2248     }
2249 
2250     if ((!NearEqual(statusBarHeight, statusBarHeight_)) || (!NearEqual(navigationBarHeight, navigationBarHeight_))) {
2251         statusBarHeight_ = statusBarHeight;
2252         navigationBarHeight_ = navigationBarHeight;
2253         if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
2254             auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2255             if (semiModal) {
2256                 semiModal->UpdateSystemBarHeight(statusBarHeight_, navigationBarHeight_);
2257             }
2258         } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
2259             auto dialogModal = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
2260             if (dialogModal) {
2261                 dialogModal->UpdateSystemBarHeight(statusBarHeight_, navigationBarHeight_);
2262             }
2263         } else {
2264             // Normal modal, do nothing.
2265         }
2266     }
2267 }
2268 
OnSurfaceDestroyed()2269 void PipelineContext::OnSurfaceDestroyed()
2270 {
2271     CHECK_RUN_ON(UI);
2272     ACE_SCOPED_TRACE("OnSurfaceDestroyed");
2273     isSurfaceReady_ = false;
2274 }
2275 
SetRootSizeWithWidthHeight(int32_t width,int32_t height,int32_t offset)2276 void PipelineContext::SetRootSizeWithWidthHeight(int32_t width, int32_t height, int32_t offset)
2277 {
2278     CHECK_RUN_ON(UI);
2279     UpdateRootSizeAndScale(width, height);
2280     CHECK_NULL_VOID(rootElement_);
2281     const Rect paintRect(0.0, 0.0, rootWidth_, rootHeight_);
2282     auto rootNode = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2283     if (!rootNode) {
2284         return;
2285     }
2286     auto stack = GetStageElement()->GetElementParent().Upgrade();
2287     if (stack) {
2288         auto renderStack = AceType::DynamicCast<RenderStack>(stack->GetRenderNode());
2289         if (renderStack) {
2290             renderStack->SetTop(Dimension(offset));
2291         }
2292     }
2293     if (!NearEqual(viewScale_, rootNode->GetScale()) || paintRect != rootNode->GetPaintRect() || isDensityUpdate_) {
2294         if (!NearEqual(viewScale_, rootNode->GetScale())) {
2295             rootNode->SetReset(true);
2296         }
2297         rootNode->SetPaintRect(paintRect);
2298         rootNode->SetScale(viewScale_);
2299         rootNode->MarkNeedLayout();
2300         rootNode->MarkNeedRender();
2301         focusAnimationManager_->SetAvailableRect(paintRect);
2302     }
2303     if (IsJsPlugin() || IsJsCard()) {
2304         return;
2305     }
2306     ScreenSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
2307     ScreenSystemManager::GetInstance().OnSurfaceChanged(width);
2308 }
2309 
SetAppBgColor(const Color & color)2310 void PipelineContext::SetAppBgColor(const Color& color)
2311 {
2312     LOGI("Set bgColor %{public}u", color.GetValue());
2313     appBgColor_ = color;
2314 #ifdef ENABLE_ROSEN_BACKEND
2315     if (rsUIDirector_) {
2316         rsUIDirector_->SetAbilityBGAlpha(appBgColor_.GetAlpha());
2317     }
2318 #endif
2319     if (!themeManager_) {
2320         LOGW("themeManager_ is nullptr!");
2321         return;
2322     }
2323     auto appTheme = themeManager_->GetTheme<AppTheme>();
2324     if (!appTheme) {
2325         LOGW("appTheme is nullptr!");
2326         return;
2327     }
2328     appTheme->SetBackgroundColor(appBgColor_);
2329     if (!rootElement_) {
2330         LOGW("rootElement_ is nullptr!");
2331         return;
2332     }
2333     auto renderRoot = DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2334     if (!renderRoot) {
2335         LOGW("renderRoot is nullptr!");
2336         return;
2337     }
2338     if (windowModal_ == WindowModal::CONTAINER_MODAL) {
2339         auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
2340         if (containerModal) {
2341             containerModal->SetAppBgColor(appBgColor_);
2342             renderRoot->SetBgColor(Color::TRANSPARENT);
2343             return;
2344         }
2345     }
2346     renderRoot->SetBgColor(appBgColor_);
2347 }
2348 
Finish(bool autoFinish) const2349 void PipelineContext::Finish(bool autoFinish) const
2350 {
2351     CHECK_RUN_ON(UI);
2352     if (autoFinish && rootElement_ && onShow_) {
2353         if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
2354             auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2355             if (!semiModal) {
2356                 LOGE("SemiModal animate to exit app failed. semi modal is null");
2357                 return;
2358             }
2359             semiModal->AnimateToExitApp();
2360             return;
2361         } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
2362             // dialog modal use translucent theme and will do exit animation by ACE itself.
2363             auto dialogModal = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
2364             if (!dialogModal) {
2365                 LOGE("DialogModal animate to exit app failed. dialog modal is null");
2366                 return;
2367             }
2368             dialogModal->AnimateToExitApp();
2369             return;
2370         } else {
2371             // normal force finish.
2372             Finish(false);
2373         }
2374     } else {
2375         if (finishEventHandler_) {
2376             finishEventHandler_();
2377         } else {
2378             LOGE("fail to finish current context due to handler is nullptr");
2379         }
2380     }
2381 }
2382 
RequestFullWindow(int32_t duration)2383 void PipelineContext::RequestFullWindow(int32_t duration)
2384 {
2385     CHECK_RUN_ON(UI);
2386     if (!rootElement_) {
2387         LOGE("Root element is null!");
2388         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2389         return;
2390     }
2391     auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2392     if (!semiModal) {
2393         LOGI("Get semiModal element failed. SemiModal element is null!");
2394         return;
2395     }
2396     if (semiModal->IsFullWindow()) {
2397         LOGI("Already in full window, skip it.");
2398         return;
2399     }
2400     isFullWindow_ = true;
2401     // when semi modal animating, no more full window request can be handled, so mark it as full window.
2402     semiModal->SetFullWindow(true);
2403     semiModal->AnimateToFullWindow(duration);
2404     NotifyStatusBarBgColor(semiModal->GetBackgroundColor());
2405     auto page = GetLastStack();
2406     if (!page) {
2407         return;
2408     }
2409     auto renderPage = AceType::DynamicCast<RenderStack>(page->GetRenderNode());
2410     if (!renderPage) {
2411         return;
2412     }
2413     // Change to full window, change page stack layout strategy.
2414     renderPage->SetStackFit(StackFit::INHERIT);
2415     renderPage->SetMainStackSize(MainStackSize::MAX);
2416     renderPage->MarkNeedLayout();
2417 }
2418 
ShowFocusAnimation(const RRect & rrect,const Color & color,const Offset & offset,bool isIndented) const2419 void PipelineContext::ShowFocusAnimation(
2420     const RRect& rrect, const Color& color, const Offset& offset, bool isIndented) const
2421 {
2422     focusAnimationManager_->SetFocusAnimationProperties(rrect, color, offset, isIndented);
2423 }
2424 
ShowFocusAnimation(const RRect & rrect,const Color & color,const Offset & offset,const Rect & clipRect) const2425 void PipelineContext::ShowFocusAnimation(
2426     const RRect& rrect, const Color& color, const Offset& offset, const Rect& clipRect) const
2427 {
2428     focusAnimationManager_->SetFocusAnimationProperties(rrect, color, offset, clipRect);
2429 }
2430 
AddDirtyFocus(const RefPtr<FocusNode> & node)2431 void PipelineContext::AddDirtyFocus(const RefPtr<FocusNode>& node)
2432 {
2433     CHECK_RUN_ON(UI);
2434     if (!node) {
2435         LOGW("node is null.");
2436         return;
2437     }
2438     if (node->IsChild()) {
2439         dirtyFocusNode_ = WeakClaim(RawPtr(node));
2440     } else {
2441         dirtyFocusScope_ = WeakClaim(RawPtr(node));
2442     }
2443     window_->RequestFrame();
2444 }
2445 
CancelFocusAnimation() const2446 void PipelineContext::CancelFocusAnimation() const
2447 {
2448     focusAnimationManager_->CancelFocusAnimation();
2449 }
2450 
PopFocusAnimation() const2451 void PipelineContext::PopFocusAnimation() const
2452 {
2453     focusAnimationManager_->PopFocusAnimationElement();
2454 }
2455 
PopRootFocusAnimation() const2456 void PipelineContext::PopRootFocusAnimation() const
2457 {
2458     focusAnimationManager_->PopRootFocusAnimationElement();
2459 }
2460 
PushFocusAnimation(const RefPtr<Element> & element) const2461 void PipelineContext::PushFocusAnimation(const RefPtr<Element>& element) const
2462 {
2463     focusAnimationManager_->PushFocusAnimationElement(element);
2464 }
2465 
Destroy()2466 void PipelineContext::Destroy()
2467 {
2468     CHECK_RUN_ON(UI);
2469     LOGI("PipelineContext::Destroy begin.");
2470     rootElement_.Reset();
2471     composedElementMap_.clear();
2472     dirtyElements_.clear();
2473     deactivateElements_.clear();
2474     dirtyRenderNodes_.clear();
2475     dirtyRenderNodesInOverlay_.clear();
2476     dirtyLayoutNodes_.clear();
2477     predictLayoutNodes_.clear();
2478     geometryChangedNodes_.clear();
2479     needPaintFinishNodes_.clear();
2480     dirtyFocusNode_.Reset();
2481     dirtyFocusScope_.Reset();
2482     postFlushListeners_.clear();
2483     postAnimationFlushListeners_.clear();
2484     preFlushListeners_.clear();
2485     sharedTransitionController_.Reset();
2486     cardTransitionController_.Reset();
2487     while (!pageUpdateTasks_.empty()) {
2488         pageUpdateTasks_.pop();
2489     }
2490     alignDeclarationNodeList_.clear();
2491     hoverNodes_.clear();
2492     renderFactory_.Reset();
2493     nodesToNotifyOnPreDraw_.clear();
2494     nodesNeedDrawOnPixelMap_.clear();
2495     layoutTransitionNodeSet_.clear();
2496     explicitAnimators_.clear();
2497     preTargetRenderNode_.Reset();
2498     sharedImageManager_.Reset();
2499     rectCallbackList_.clear();
2500     PipelineBase::Destroy();
2501     LOGI("PipelineContext::Destroy end.");
2502 }
2503 
SendCallbackMessageToFrontend(const std::string & callbackId,const std::string & data)2504 void PipelineContext::SendCallbackMessageToFrontend(const std::string& callbackId, const std::string& data)
2505 {
2506     auto frontend = weakFrontend_.Upgrade();
2507     if (!frontend) {
2508         LOGE("frontend is nullptr");
2509         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2510         return;
2511     }
2512     frontend->SendCallbackMessage(callbackId, data);
2513 }
2514 
SendEventToFrontend(const EventMarker & eventMarker)2515 void PipelineContext::SendEventToFrontend(const EventMarker& eventMarker)
2516 {
2517     auto frontend = weakFrontend_.Upgrade();
2518     if (!frontend) {
2519         LOGE("frontend is nullptr");
2520         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2521         return;
2522     }
2523     auto handler = frontend->GetEventHandler();
2524     if (!handler) {
2525         LOGE("fail to trigger async event due to event handler is nullptr");
2526         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2527         return;
2528     }
2529     handler->HandleAsyncEvent(eventMarker);
2530 }
2531 
SendEventToFrontend(const EventMarker & eventMarker,const std::string & param)2532 void PipelineContext::SendEventToFrontend(const EventMarker& eventMarker, const std::string& param)
2533 {
2534     auto frontend = weakFrontend_.Upgrade();
2535     if (!frontend) {
2536         LOGE("frontend is nullptr");
2537         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2538         return;
2539     }
2540     auto handler = frontend->GetEventHandler();
2541     if (!handler) {
2542         LOGE("fail to trigger async event due to event handler is nullptr");
2543         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2544         return;
2545     }
2546     handler->HandleAsyncEvent(eventMarker, param);
2547 }
2548 
AccessibilityRequestFocus(const ComposeId & id)2549 bool PipelineContext::AccessibilityRequestFocus(const ComposeId& id)
2550 {
2551     auto targetElement = GetComposedElementById(id);
2552     if (!targetElement) {
2553         LOGE("RequestFocusById targetElement is null.");
2554         EventReport::SendAccessibilityException(AccessibilityExcepType::GET_NODE_ERR);
2555         return false;
2556     }
2557     return RequestFocus(targetElement);
2558 }
2559 
RequestFocus(const RefPtr<Element> & targetElement)2560 bool PipelineContext::RequestFocus(const RefPtr<Element>& targetElement)
2561 {
2562     CHECK_RUN_ON(UI);
2563     if (!targetElement) {
2564         return false;
2565     }
2566     auto children = targetElement->GetChildren();
2567     for (const auto& childElement : children) {
2568         auto focusNode = AceType::DynamicCast<FocusNode>(childElement);
2569         if (focusNode) {
2570             if (focusNode->RequestFocusImmediately()) {
2571                 return true;
2572             } else {
2573                 continue;
2574             }
2575         }
2576         if (RequestFocus(childElement)) {
2577             return true;
2578         }
2579     }
2580     return false;
2581 }
2582 
RequestFocus(const std::string & targetNodeId,bool isSyncRequest)2583 bool PipelineContext::RequestFocus(const std::string& targetNodeId, bool isSyncRequest)
2584 {
2585     CHECK_NULL_RETURN(rootElement_, false);
2586     auto currentFocusChecked = rootElement_->RequestFocusImmediatelyById(targetNodeId);
2587     if (!isSubPipeline_ || currentFocusChecked) {
2588         LOGI("Request focus finish currentFocus is %{public}d", currentFocusChecked);
2589         return currentFocusChecked;
2590     }
2591     LOGI("Search focus in main pipeline");
2592     auto parentPipelineBase = parentPipeline_.Upgrade();
2593     CHECK_NULL_RETURN(parentPipelineBase, false);
2594     auto parentPipelineContext = AceType::DynamicCast<PipelineContext>(parentPipelineBase);
2595     CHECK_NULL_RETURN(parentPipelineContext, false);
2596     return parentPipelineContext->RequestFocus(targetNodeId);
2597 }
2598 
GetRenderFocusAnimation() const2599 RefPtr<RenderFocusAnimation> PipelineContext::GetRenderFocusAnimation() const
2600 {
2601     return focusAnimationManager_->GetRenderFocusAnimation();
2602 }
2603 
ShowShadow(const RRect & rrect,const Offset & offset) const2604 void PipelineContext::ShowShadow(const RRect& rrect, const Offset& offset) const
2605 {
2606     focusAnimationManager_->SetShadowProperties(rrect, offset);
2607 }
2608 
ShowShadow(const RRect & rrect,const Offset & offset,const Rect & clipRect) const2609 void PipelineContext::ShowShadow(const RRect& rrect, const Offset& offset, const Rect& clipRect) const
2610 {
2611     focusAnimationManager_->SetShadowProperties(rrect, offset, clipRect);
2612 }
2613 
PushShadow(const RefPtr<Element> & element) const2614 void PipelineContext::PushShadow(const RefPtr<Element>& element) const
2615 {
2616     focusAnimationManager_->PushShadow(element);
2617 }
2618 
PopShadow() const2619 void PipelineContext::PopShadow() const
2620 {
2621     focusAnimationManager_->PopShadow();
2622 }
2623 
CancelShadow() const2624 void PipelineContext::CancelShadow() const
2625 {
2626     focusAnimationManager_->CancelShadow();
2627 }
2628 
SetUseRootAnimation(bool useRoot)2629 void PipelineContext::SetUseRootAnimation(bool useRoot)
2630 {
2631     focusAnimationManager_->SetUseRoot(useRoot);
2632 }
2633 
2634 #ifndef WEARABLE_PRODUCT
SetMultimodalSubscriber(const RefPtr<MultimodalSubscriber> & multimodalSubscriber)2635 void PipelineContext::SetMultimodalSubscriber(const RefPtr<MultimodalSubscriber>& multimodalSubscriber)
2636 {
2637     multiModalManager_->SetMultimodalSubscriber(multimodalSubscriber);
2638 }
2639 
SetWindowOnShow()2640 void PipelineContext::SetWindowOnShow()
2641 {
2642     window_->OnShow();
2643     window_->RequestFrame();
2644 }
2645 
SetWindowOnHide()2646 void PipelineContext::SetWindowOnHide()
2647 {
2648     window_->RequestFrame();
2649     window_->OnHide();
2650 }
2651 
OnShow()2652 void PipelineContext::OnShow()
2653 {
2654     onShow_ = true;
2655     SetWindowOnShow();
2656     PerfMonitor::GetPerfMonitor()->SetAppForeground(true);
2657     auto multiModalScene = multiModalManager_->GetCurrentMultiModalScene();
2658     if (multiModalScene) {
2659         multiModalScene->Resume();
2660     }
2661     taskExecutor_->PostTask(
2662         [weak = AceType::WeakClaim(this)]() {
2663             auto context = weak.Upgrade();
2664             if (!context) {
2665                 return;
2666             }
2667 #ifdef ENABLE_ROSEN_BACKEND
2668             if (context->rsUIDirector_) {
2669                 context->rsUIDirector_->GoForeground();
2670             }
2671 #endif
2672             const auto& rootElement = context->rootElement_;
2673             if (!rootElement) {
2674                 LOGE("render element is null!");
2675                 return;
2676             }
2677             const auto& renderRoot = AceType::DynamicCast<RenderRoot>(rootElement->GetRenderNode());
2678             if (!renderRoot) {
2679                 LOGE("render root is null!");
2680                 return;
2681             }
2682             if ((context->windowModal_ == WindowModal::SEMI_MODAL) ||
2683                 (context->windowModal_ == WindowModal::DIALOG_MODAL)) {
2684                 renderRoot->SetDefaultBgColor();
2685             }
2686             renderRoot->NotifyOnShow();
2687         },
2688         TaskExecutor::TaskType::UI, "ArkUIRenderRootShow");
2689 }
2690 
OnHide()2691 void PipelineContext::OnHide()
2692 {
2693     onShow_ = false;
2694     SetWindowOnHide();
2695     PerfMonitor::GetPerfMonitor()->SetAppForeground(false);
2696     auto multiModalScene = multiModalManager_->GetCurrentMultiModalScene();
2697     if (multiModalScene) {
2698         multiModalScene->Hide();
2699     }
2700     taskExecutor_->PostTask(
2701         [weak = AceType::WeakClaim(this)]() {
2702             auto context = weak.Upgrade();
2703             if (!context) {
2704                 return;
2705             }
2706             if (context->IsSubPipeline()) {
2707                 context->FlushPipelineImmediately();
2708             }
2709 #ifdef ENABLE_ROSEN_BACKEND
2710             if (context->rsUIDirector_) {
2711                 context->rsUIDirector_->GoBackground();
2712                 context->rsUIDirector_->SendMessages();
2713             }
2714 #endif
2715             context->NotifyPopupDismiss();
2716             context->OnVirtualKeyboardAreaChange(Rect());
2717             const auto& rootElement = context->rootElement_;
2718             if (!rootElement) {
2719                 LOGE("render element is null!");
2720                 return;
2721             }
2722             const auto& renderRoot = AceType::DynamicCast<RenderRoot>(rootElement->GetRenderNode());
2723             if (!renderRoot) {
2724                 LOGE("render root is null!");
2725                 return;
2726             }
2727             renderRoot->NotifyOnHide();
2728         },
2729         TaskExecutor::TaskType::UI, "ArkUIRenderRootHide");
2730 }
2731 #endif
2732 
RefreshRootBgColor() const2733 void PipelineContext::RefreshRootBgColor() const
2734 {
2735     CHECK_RUN_ON(UI);
2736     if (!rootElement_) {
2737         return;
2738     }
2739     const auto& render = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2740     if (render) {
2741         render->SetDefaultBgColor(windowModal_ == WindowModal::CONTAINER_MODAL);
2742     }
2743 }
2744 
OnPageShow()2745 void PipelineContext::OnPageShow()
2746 {
2747     CHECK_RUN_ON(UI);
2748     if (onPageShowCallBack_) {
2749         onPageShowCallBack_();
2750     }
2751 }
2752 
SetTimeProvider(TimeProvider && timeProvider)2753 void PipelineContext::SetTimeProvider(TimeProvider&& timeProvider)
2754 {
2755     if (!timeProvider) {
2756         LOGE("Set time provider failed. provider is null.");
2757         return;
2758     }
2759     timeProvider_ = std::move(timeProvider);
2760 }
2761 
GetTimeFromExternalTimer()2762 uint64_t PipelineContext::GetTimeFromExternalTimer()
2763 {
2764     if (isFlushingAnimation_) {
2765         return flushAnimationTimestamp_;
2766     } else {
2767         if (!timeProvider_) {
2768             LOGE("No time provider has been set.");
2769             return 0;
2770         }
2771         return timeProvider_();
2772     }
2773 }
2774 
LoadSystemFont(const std::function<void ()> & onFondsLoaded)2775 void PipelineContext::LoadSystemFont(const std::function<void()>& onFondsLoaded)
2776 {
2777     GetTaskExecutor()->PostTask(
2778         [weak = WeakClaim(this), fontManager = fontManager_, onFondsLoaded]() {
2779             if (!fontManager) {
2780                 return;
2781             }
2782             fontManager->LoadSystemFont();
2783             auto context = weak.Upgrade();
2784             if (!context) {
2785                 return;
2786             }
2787             context->GetTaskExecutor()->PostTask(
2788                 [onFondsLoaded]() {
2789                     if (onFondsLoaded) {
2790                         onFondsLoaded();
2791                     }
2792                 },
2793                 TaskExecutor::TaskType::UI, "ArkUISystemFondsLoaded");
2794         },
2795         TaskExecutor::TaskType::IO, "ArkUILoadSystemFont");
2796 }
2797 
AddFontNode(const WeakPtr<RenderNode> & node)2798 void PipelineContext::AddFontNode(const WeakPtr<RenderNode>& node)
2799 {
2800     if (fontManager_) {
2801         fontManager_->AddFontNode(node);
2802     }
2803 }
2804 
RemoveFontNode(const WeakPtr<RenderNode> & node)2805 void PipelineContext::RemoveFontNode(const WeakPtr<RenderNode>& node)
2806 {
2807     if (fontManager_) {
2808         fontManager_->RemoveFontNode(node);
2809     }
2810 }
2811 
SetClickPosition(const Offset & position) const2812 void PipelineContext::SetClickPosition(const Offset& position) const
2813 {
2814     LOGI("SetClickPosition position:%{public}s rootOffset:%{public}s", position.ToString().c_str(),
2815         rootOffset_.ToString().c_str());
2816     if (textFieldManager_) {
2817         textFieldManager_->SetClickPosition(position - rootOffset_);
2818     }
2819 }
2820 
GetOverlayElement() const2821 const RefPtr<OverlayElement> PipelineContext::GetOverlayElement() const
2822 {
2823     if (!rootElement_) {
2824         LOGE("Root element is null!");
2825         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2826         return RefPtr<OverlayElement>();
2827     }
2828     auto overlay = AceType::DynamicCast<OverlayElement>(rootElement_->GetOverlayElement(windowModal_));
2829     if (!overlay) {
2830         LOGE("Get overlay element failed. overlay element is null!");
2831         return RefPtr<OverlayElement>();
2832     }
2833     return overlay;
2834 }
2835 
FlushBuildAndLayoutBeforeSurfaceReady()2836 void PipelineContext::FlushBuildAndLayoutBeforeSurfaceReady()
2837 {
2838     if (isSurfaceReady_) {
2839         return;
2840     }
2841     GetTaskExecutor()->PostTask(
2842         [weak = AceType::WeakClaim(this)]() {
2843             auto context = weak.Upgrade();
2844             if (!context || context->isSurfaceReady_) {
2845                 return;
2846             }
2847 
2848             context->FlushBuild();
2849             context->SetRootRect(context->width_, context->height_);
2850             context->FlushLayout();
2851         },
2852         TaskExecutor::TaskType::UI, "ArkUIFlushBuildAndLayout");
2853 }
2854 
RootLostFocus(BlurReason reason) const2855 void PipelineContext::RootLostFocus(BlurReason reason) const
2856 {
2857     if (rootElement_) {
2858         rootElement_->LostFocus(reason);
2859     }
2860 }
2861 
WindowFocus(bool isFocus)2862 void PipelineContext::WindowFocus(bool isFocus)
2863 {
2864     onFocus_ = isFocus;
2865     if (!isFocus) {
2866         RootLostFocus(BlurReason::WINDOW_BLUR);
2867         NotifyPopupDismiss();
2868         OnVirtualKeyboardAreaChange(Rect());
2869     }
2870     if (onFocus_ && onShow_) {
2871         FlushFocus();
2872     }
2873     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
2874         return;
2875     }
2876     if (!rootElement_) {
2877         LOGE("WindowFocus failed, rootElement_ is null.");
2878         return;
2879     }
2880     auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
2881     if (containerModal) {
2882         containerModal->WindowFocus(isFocus);
2883     }
2884 }
2885 
ContainerModalUnFocus()2886 void PipelineContext::ContainerModalUnFocus() {}
2887 
AddPageUpdateTask(std::function<void ()> && task,bool directExecute)2888 void PipelineContext::AddPageUpdateTask(std::function<void()>&& task, bool directExecute)
2889 {
2890     CHECK_RUN_ON(UI);
2891     pageUpdateTasks_.emplace(std::move(task));
2892     if (directExecute) {
2893         FlushPageUpdateTasks();
2894     } else {
2895         window_->RequestFrame();
2896     }
2897 #if defined(ENABLE_NATIVE_VIEW)
2898     if (frameCount_ == 1) {
2899         OnIdle(0);
2900         FlushPipelineImmediately();
2901     }
2902 #endif
2903 }
2904 
MovePage(const Offset & rootRect,double offsetHeight)2905 void PipelineContext::MovePage(const Offset& rootRect, double offsetHeight)
2906 {
2907     if (textFieldManager_ && GetLastPage()) {
2908         textFieldManager_->MovePage(GetLastPage()->GetPageId(), rootRect, offsetHeight);
2909     }
2910 }
2911 
GetDeactivateElement(int32_t componentId) const2912 RefPtr<Element> PipelineContext::GetDeactivateElement(int32_t componentId) const
2913 {
2914     CHECK_RUN_ON(UI);
2915     auto elementIter = deactivateElements_.find(componentId);
2916     if (elementIter != deactivateElements_.end()) {
2917         return elementIter->second;
2918     } else {
2919         return nullptr;
2920     }
2921 }
2922 
AddDeactivateElement(const int32_t id,const RefPtr<Element> & element)2923 void PipelineContext::AddDeactivateElement(const int32_t id, const RefPtr<Element>& element)
2924 {
2925     CHECK_RUN_ON(UI);
2926     deactivateElements_.emplace(id, element);
2927 }
2928 
ClearDeactivateElements()2929 void PipelineContext::ClearDeactivateElements()
2930 {
2931     CHECK_RUN_ON(UI);
2932     ACE_FUNCTION_TRACK();
2933     for (auto iter = deactivateElements_.begin(); iter != deactivateElements_.end();) {
2934         auto element = iter->second;
2935         RefPtr<RenderNode> render = element ? element->GetRenderNode() : nullptr;
2936         if (!render || !render->IsDisappearing()) {
2937             iter = deactivateElements_.erase(iter);
2938         } else {
2939             iter++;
2940         }
2941     }
2942 }
2943 
DumpAccessibility(const std::vector<std::string> & params) const2944 void PipelineContext::DumpAccessibility(const std::vector<std::string>& params) const
2945 {
2946     auto accessibilityManager = GetAccessibilityManager();
2947     if (!accessibilityManager) {
2948         return;
2949     }
2950     accessibilityManager->OnDumpInfo(params);
2951 }
2952 
UpdateWindowBlurRegion(int32_t id,RRect rRect,float progress,WindowBlurStyle style,const std::vector<RRect> & coords)2953 void PipelineContext::UpdateWindowBlurRegion(
2954     int32_t id, RRect rRect, float progress, WindowBlurStyle style, const std::vector<RRect>& coords)
2955 {
2956     CHECK_RUN_ON(UI);
2957     auto pos = windowBlurRegions_.find(id);
2958     if (pos != windowBlurRegions_.end()) {
2959         const auto& old = pos->second;
2960         if (NearEqual(progress, old.progress_) && rRect == old.innerRect_ && style == old.style_) {
2961             return;
2962         }
2963     }
2964     windowBlurRegions_[id] = { .progress_ = progress, .style_ = style, .innerRect_ = rRect, .coords_ = coords };
2965     needWindowBlurRegionRefresh_ = true;
2966 }
2967 
ClearWindowBlurRegion(int32_t id)2968 void PipelineContext::ClearWindowBlurRegion(int32_t id)
2969 {
2970     CHECK_RUN_ON(UI);
2971     auto pos = windowBlurRegions_.find(id);
2972     if (pos != windowBlurRegions_.end()) {
2973         windowBlurRegions_.erase(pos);
2974         needWindowBlurRegionRefresh_ = true;
2975     }
2976 }
2977 
InitDragListener()2978 void PipelineContext::InitDragListener()
2979 {
2980     if (!initDragEventListener_) {
2981         return;
2982     }
2983     initDragEventListener_();
2984 }
2985 
StartSystemDrag(const std::string & str,const RefPtr<PixelMap> & pixmap)2986 void PipelineContext::StartSystemDrag(const std::string& str, const RefPtr<PixelMap>& pixmap)
2987 {
2988     if (!dragEventHandler_) {
2989         return;
2990     }
2991     dragEventHandler_(str, pixmap);
2992 }
2993 
SetPreTargetRenderNode(const RefPtr<DragDropEvent> & preDragDropNode)2994 void PipelineContext::SetPreTargetRenderNode(const RefPtr<DragDropEvent>& preDragDropNode)
2995 {
2996     preTargetRenderNode_ = preDragDropNode;
2997 }
2998 
GetPreTargetRenderNode() const2999 const RefPtr<DragDropEvent>& PipelineContext::GetPreTargetRenderNode() const
3000 {
3001     return preTargetRenderNode_;
3002 }
3003 
SetInitRenderNode(const RefPtr<RenderNode> & initRenderNode)3004 void PipelineContext::SetInitRenderNode(const RefPtr<RenderNode>& initRenderNode)
3005 {
3006     initRenderNode_ = initRenderNode;
3007 }
3008 
GetInitRenderNode() const3009 const RefPtr<RenderNode>& PipelineContext::GetInitRenderNode() const
3010 {
3011     return initRenderNode_;
3012 }
3013 
ProcessDragEvent(const RefPtr<RenderNode> & renderNode,const RefPtr<DragEvent> & event,const Point & globalPoint)3014 void PipelineContext::ProcessDragEvent(
3015     const RefPtr<RenderNode>& renderNode, const RefPtr<DragEvent>& event, const Point& globalPoint)
3016 {
3017     auto targetDragDropNode =
3018         AceType::DynamicCast<DragDropEvent>(renderNode->FindDropChild(globalPoint, globalPoint - pageOffset_));
3019     auto initDragDropNode = AceType::DynamicCast<DragDropEvent>(GetInitRenderNode());
3020     auto extraParams = JsonUtil::Create(true);
3021     extraParams->Put("customDragInfo", customDragInfo_.c_str());
3022     extraParams->Put("selectedText", selectedText_.c_str());
3023     extraParams->Put("imageSrc", imageSrc_.c_str());
3024     auto info = GestureEvent();
3025     info.SetGlobalPoint(globalPoint);
3026     auto preTargetDragDropNode = GetPreTargetRenderNode();
3027     if (targetDragDropNode == preTargetDragDropNode) {
3028         if (targetDragDropNode && targetDragDropNode->GetOnDragMove()) {
3029             auto renderList = renderNode->FindChildNodeOfClass<V2::RenderList>(globalPoint, globalPoint);
3030             if (renderList) {
3031                 insertIndex_ = renderList->CalculateInsertIndex(renderList, info, selectedItemSize_);
3032             }
3033 
3034             if (insertIndex_ == static_cast<int32_t>(RenderNode::DEFAULT_INDEX)) {
3035                 (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
3036                 return;
3037             }
3038 
3039             if (targetDragDropNode != initDragDropNode) {
3040                 extraParams->Put("selectedIndex", -1);
3041             } else {
3042                 extraParams->Put("selectedIndex", selectedIndex_);
3043             }
3044 
3045             extraParams->Put("insertIndex", insertIndex_);
3046             (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
3047         }
3048     } else {
3049         if (preTargetDragDropNode && preTargetDragDropNode->GetOnDragLeave()) {
3050             (preTargetDragDropNode->GetOnDragLeave())(event, extraParams->ToString());
3051         }
3052 
3053         if (targetDragDropNode && targetDragDropNode->GetOnDragEnter()) {
3054             (targetDragDropNode->GetOnDragEnter())(event, extraParams->ToString());
3055         }
3056 
3057         SetPreTargetRenderNode(targetDragDropNode);
3058     }
3059 }
3060 
ProcessDragEventEnd(const RefPtr<RenderNode> & renderNode,const RefPtr<DragEvent> & event,const Point & globalPoint)3061 void PipelineContext::ProcessDragEventEnd(
3062     const RefPtr<RenderNode>& renderNode, const RefPtr<DragEvent>& event, const Point& globalPoint)
3063 {
3064     auto targetDragDropNode =
3065         AceType::DynamicCast<DragDropEvent>(renderNode->FindDropChild(globalPoint, globalPoint - pageOffset_));
3066     auto initDragDropNode = AceType::DynamicCast<DragDropEvent>(GetInitRenderNode());
3067     auto extraParams = JsonUtil::Create(true);
3068     extraParams->Put("customDragInfo", customDragInfo_.c_str());
3069     extraParams->Put("selectedText", selectedText_.c_str());
3070     extraParams->Put("imageSrc", imageSrc_.c_str());
3071     auto info = GestureEvent();
3072     info.SetGlobalPoint(globalPoint);
3073     auto preTargetDragDropNode = GetPreTargetRenderNode();
3074 
3075     auto textfield = renderNode->FindChildNodeOfClass<RenderTextField>(globalPoint, globalPoint);
3076     if (textfield) {
3077         auto value = textfield->GetEditingValue();
3078         value.Append(selectedText_);
3079         textfield->SetEditingValue(std::move(value));
3080     }
3081 
3082     if (targetDragDropNode && targetDragDropNode->GetOnDrop()) {
3083         auto renderList = renderNode->FindChildNodeOfClass<V2::RenderList>(globalPoint, globalPoint);
3084         if (renderList) {
3085             insertIndex_ = renderList->CalculateInsertIndex(renderList, info, selectedItemSize_);
3086         }
3087 
3088         if (insertIndex_ == static_cast<int32_t>(RenderNode::DEFAULT_INDEX)) {
3089             (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
3090             SetPreTargetRenderNode(nullptr);
3091             SetInitRenderNode(nullptr);
3092             return;
3093         }
3094 
3095         if (targetDragDropNode != initDragDropNode) {
3096             extraParams->Put("selectedIndex", -1);
3097         } else {
3098             extraParams->Put("selectedIndex", selectedIndex_);
3099         }
3100 
3101         extraParams->Put("insertIndex", insertIndex_);
3102         (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
3103     }
3104 
3105     if (initDragDropNode && initDragDropNode->GetOnDrop()) {
3106         (initDragDropNode->GetOnDrop())(event, extraParams->ToString());
3107     }
3108 
3109     SetPreTargetRenderNode(nullptr);
3110     SetInitRenderNode(nullptr);
3111 }
3112 
OnDragEvent(const DragPointerEvent & pointerEvent,DragEventAction action,const RefPtr<NG::FrameNode> & node)3113 void PipelineContext::OnDragEvent(const DragPointerEvent& pointerEvent, DragEventAction action,
3114     const RefPtr<NG::FrameNode>& node)
3115 {
3116     if (!clipboard_) {
3117         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(GetTaskExecutor());
3118     }
3119 
3120     if (!clipboardCallback_) {
3121         auto callback = [weakPipelineContext = WeakClaim(this)](const std::string& data) {
3122             auto pipelineContext = weakPipelineContext.Upgrade();
3123             if (pipelineContext) {
3124                 auto json = JsonUtil::ParseJsonString(data);
3125                 auto newData = JsonUtil::ParseJsonString(json->GetString("newData"));
3126                 pipelineContext->selectedItemSize_.SetWidth(newData->GetDouble("width"));
3127                 pipelineContext->selectedItemSize_.SetHeight(newData->GetDouble("height"));
3128                 pipelineContext->selectedIndex_ = newData->GetInt("selectedIndex");
3129                 pipelineContext->customDragInfo_ = newData->GetString("customDragInfo");
3130                 pipelineContext->selectedText_ = newData->GetString("selectedText");
3131                 pipelineContext->imageSrc_ = newData->GetString("imageSrc");
3132             }
3133         };
3134         clipboardCallback_ = callback;
3135     }
3136 
3137     if (clipboardCallback_) {
3138         clipboard_->GetData(clipboardCallback_);
3139     }
3140 
3141     auto renderNode = GetLastPageRender();
3142     if (!renderNode) {
3143         LOGE("PipelineContext::OnDragEvent renderNode is null.");
3144         return;
3145     }
3146 
3147     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
3148     event->SetX(ConvertPxToVp(Dimension(pointerEvent.x, DimensionUnit::PX)));
3149     event->SetY(ConvertPxToVp(Dimension(pointerEvent.y, DimensionUnit::PX)));
3150 
3151     Point globalPoint(pointerEvent.x, pointerEvent.y);
3152 
3153     if (action == DragEventAction::DRAG_EVENT_START) {
3154         pageOffset_ = GetPageRect().GetOffset();
3155     }
3156 
3157     event->SetPressedKeyCodes(pointerEvent.pressedKeyCodes);
3158 
3159     if (action != DragEventAction::DRAG_EVENT_END) {
3160         ProcessDragEvent(renderNode, event, globalPoint);
3161     } else {
3162         ProcessDragEventEnd(renderNode, event, globalPoint);
3163     }
3164 }
3165 
FlushWindowBlur()3166 void PipelineContext::FlushWindowBlur()
3167 {
3168     CHECK_RUN_ON(UI);
3169     ACE_FUNCTION_TRACK();
3170 
3171     if (!updateWindowBlurRegionHandler_) {
3172         return;
3173     }
3174 
3175     if (IsJsPlugin()) {
3176         return;
3177     }
3178 
3179     if (IsJsCard()) {
3180         if (!needWindowBlurRegionRefresh_) {
3181             return;
3182         }
3183         std::vector<std::vector<float>> blurRectangles;
3184         if (!windowBlurRegions_.empty()) {
3185             blurRectangles.push_back(std::vector<float> { 1 });
3186         }
3187         updateWindowBlurRegionHandler_(blurRectangles);
3188         needWindowBlurRegionRefresh_ = false;
3189         return;
3190     }
3191     if (!rootElement_) {
3192         LOGE("root element is null");
3193         return;
3194     }
3195     auto renderNode = rootElement_->GetRenderNode();
3196     if (!renderNode) {
3197         LOGE("get renderNode failed");
3198         return;
3199     }
3200 
3201     if (!windowBlurRegions_.empty()) {
3202         renderNode->WindowBlurTest();
3203     }
3204 
3205     float scale = GetViewScale();
3206     if (needWindowBlurRegionRefresh_) {
3207         std::vector<std::vector<float>> blurRectangles;
3208         for (auto& region : windowBlurRegions_) {
3209             std::vector<float> rectArray;
3210             // progress
3211             rectArray.push_back(region.second.progress_);
3212             // style
3213             rectArray.push_back(static_cast<float>(region.second.style_));
3214             for (auto item : region.second.coords_) {
3215                 item.ApplyScaleAndRound(scale);
3216                 const Rect& rect = item.GetRect();
3217                 // rect
3218                 rectArray.push_back(static_cast<float>(rect.Left()));
3219                 rectArray.push_back(static_cast<float>(rect.Top()));
3220                 rectArray.push_back(static_cast<float>(rect.Right()));
3221                 rectArray.push_back(static_cast<float>(rect.Bottom()));
3222                 const Corner& radius = item.GetCorner();
3223                 // roundX roundY
3224                 rectArray.push_back(static_cast<float>(radius.topLeftRadius.GetX().Value()));
3225                 rectArray.push_back(static_cast<float>(radius.topLeftRadius.GetY().Value()));
3226             }
3227             blurRectangles.push_back(rectArray);
3228         }
3229         updateWindowBlurRegionHandler_(blurRectangles);
3230         needWindowBlurRegionRefresh_ = false;
3231     }
3232     if (updateWindowBlurDrawOpHandler_) {
3233         updateWindowBlurDrawOpHandler_();
3234     }
3235 }
3236 
MakeThreadStuck(const std::vector<std::string> & params) const3237 void PipelineContext::MakeThreadStuck(const std::vector<std::string>& params) const
3238 {
3239     int32_t time = StringUtils::StringToInt(params[2]);
3240     if (time < 0 || (params[1] != JS_THREAD_NAME && params[1] != UI_THREAD_NAME)) {
3241         DumpLog::GetInstance().Print("Params illegal, please check!");
3242         return;
3243     }
3244     DumpLog::GetInstance().Print(params[1] + " thread will stuck for " + params[2] + " seconds.");
3245     if (params[1] == JS_THREAD_NAME) {
3246         taskExecutor_->PostTask([time] { ThreadStuckTask(time); }, TaskExecutor::TaskType::JS, "ArkUIThreadStuck");
3247     } else {
3248         taskExecutor_->PostTask([time] { ThreadStuckTask(time); }, TaskExecutor::TaskType::UI, "ArkUIThreadStuck");
3249     }
3250 }
3251 
SetIsKeyEvent(bool isKeyEvent)3252 void PipelineContext::SetIsKeyEvent(bool isKeyEvent)
3253 {
3254     if (focusAnimationManager_) {
3255         isKeyEvent_ = isKeyEvent;
3256         focusAnimationManager_->SetIsKeyEvent(isKeyEvent_);
3257     }
3258 }
3259 
NavigatePage(uint8_t type,const PageTarget & target,const std::string & params)3260 void PipelineContext::NavigatePage(uint8_t type, const PageTarget& target, const std::string& params)
3261 {
3262     auto frontend = weakFrontend_.Upgrade();
3263     if (!frontend) {
3264         LOGE("frontend is nullptr");
3265         return;
3266     }
3267     frontend->NavigatePage(type, target, params);
3268 }
3269 
AddKeyFrame(float fraction,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback)3270 void PipelineContext::AddKeyFrame(
3271     float fraction, const RefPtr<Curve>& curve, const std::function<void()>& propertyCallback)
3272 {
3273     if (propertyCallback == nullptr) {
3274         LOGE("failed to add key frame, property callback is null!");
3275         return;
3276     }
3277 
3278     pendingImplicitLayout_.push(false);
3279     auto propertyChangeCallback = [weak = AceType::WeakClaim(this), callback = propertyCallback,
3280                                       id = Container::CurrentId()]() {
3281         ContainerScope scope(id);
3282         auto context = weak.Upgrade();
3283         if (context == nullptr) {
3284             LOGE("failed to add key frame, context is null!");
3285             return;
3286         }
3287 
3288         callback();
3289         if (context->pendingImplicitLayout_.top()) {
3290             context->FlushLayout();
3291         }
3292     };
3293     pendingImplicitLayout_.pop();
3294 
3295 #ifdef ENABLE_ROSEN_BACKEND
3296     auto rsUIContext = rsUIDirector_ ? rsUIDirector_->GetRSUIContext() : nullptr;
3297     RSNode::AddKeyFrame(rsUIContext, fraction, NativeCurveHelper::ToNativeCurve(curve), propertyChangeCallback);
3298 #endif
3299 }
3300 
AddKeyFrame(float fraction,const std::function<void ()> & propertyCallback)3301 void PipelineContext::AddKeyFrame(float fraction, const std::function<void()>& propertyCallback)
3302 {
3303     if (propertyCallback == nullptr) {
3304         LOGE("failed to add key frame, property callback is null!");
3305         return;
3306     }
3307 
3308     pendingImplicitLayout_.push(false);
3309     auto propertyChangeCallback = [weak = AceType::WeakClaim(this), callback = propertyCallback,
3310                                       id = Container::CurrentId()]() {
3311         ContainerScope scope(id);
3312         auto context = weak.Upgrade();
3313         if (context == nullptr) {
3314             LOGE("failed to add key frame, context is null!");
3315             return;
3316         }
3317 
3318         callback();
3319         if (context->pendingImplicitLayout_.top()) {
3320             context->FlushLayout();
3321         }
3322     };
3323     pendingImplicitLayout_.pop();
3324 
3325 #ifdef ENABLE_ROSEN_BACKEND
3326     auto rsUIContext = rsUIDirector_ ? rsUIDirector_->GetRSUIContext() : nullptr;
3327     RSNode::AddKeyFrame(rsUIContext, fraction, propertyChangeCallback);
3328 #endif
3329 }
3330 
SaveExplicitAnimationOption(const AnimationOption & option)3331 void PipelineContext::SaveExplicitAnimationOption(const AnimationOption& option)
3332 {
3333     explicitAnimationOption_ = option;
3334 }
3335 
CreateExplicitAnimator(const std::function<void ()> & onFinishEvent)3336 void PipelineContext::CreateExplicitAnimator(const std::function<void()>& onFinishEvent)
3337 {
3338     if (!onFinishEvent) {
3339         return;
3340     }
3341     auto animator = CREATE_ANIMATOR(AceType::WeakClaim(this));
3342     animator->AddStopListener([onFinishEvent, weakContext = AceType::WeakClaim(this), id = animator->GetId()] {
3343         auto context = weakContext.Upgrade();
3344         if (!context) {
3345             return;
3346         }
3347         context->PostAsyncEvent(onFinishEvent, "ArkUIAnimatorFinishEvent");
3348         context->explicitAnimators_.erase(id);
3349     });
3350     animator->SetDuration(explicitAnimationOption_.GetDuration());
3351     animator->SetStartDelay(explicitAnimationOption_.GetDelay());
3352     animator->SetIteration(explicitAnimationOption_.GetIteration());
3353     animator->SetTempo(explicitAnimationOption_.GetTempo());
3354     animator->SetAnimationDirection(explicitAnimationOption_.GetAnimationDirection());
3355     animator->SetFillMode(FillMode::FORWARDS);
3356     animator->Play();
3357     explicitAnimators_.emplace(animator->GetId(), animator);
3358 }
3359 
ClearExplicitAnimationOption()3360 void PipelineContext::ClearExplicitAnimationOption()
3361 {
3362     explicitAnimationOption_ = AnimationOption();
3363 }
3364 
GetExplicitAnimationOption() const3365 AnimationOption PipelineContext::GetExplicitAnimationOption() const
3366 {
3367     return explicitAnimationOption_;
3368 }
3369 
GetIsDeclarative() const3370 bool PipelineContext::GetIsDeclarative() const
3371 {
3372     RefPtr<Frontend> front = GetFrontend();
3373     if (front) {
3374         return (front->GetType() == FrontendType::DECLARATIVE_JS ||
3375                 front->GetType() == FrontendType::JS_PLUGIN ||
3376                 front->GetType() == FrontendType::DECLARATIVE_CJ);
3377     }
3378     return false;
3379 }
3380 
SetForbidPlatformQuit(bool forbidPlatformQuit)3381 void PipelineContext::SetForbidPlatformQuit(bool forbidPlatformQuit)
3382 {
3383     forbidPlatformQuit_ = forbidPlatformQuit;
3384     auto stageElement = GetStageElement();
3385     if (!stageElement) {
3386         LOGE("Stage is null.");
3387         return;
3388     }
3389     auto renderStage = AceType::DynamicCast<RenderStage>(stageElement->GetRenderNode());
3390     if (!renderStage) {
3391         LOGE("RenderStage is null.");
3392         return;
3393     }
3394     renderStage->SetForbidSwipeToRight(forbidPlatformQuit_);
3395 }
3396 
AddLayoutTransitionNode(const RefPtr<RenderNode> & node)3397 void PipelineContext::AddLayoutTransitionNode(const RefPtr<RenderNode>& node)
3398 {
3399     CHECK_RUN_ON(UI);
3400     layoutTransitionNodeSet_.insert(node);
3401 }
3402 
AddAlignDeclarationNode(const RefPtr<RenderNode> & node)3403 void PipelineContext::AddAlignDeclarationNode(const RefPtr<RenderNode>& node)
3404 {
3405     CHECK_RUN_ON(UI);
3406     alignDeclarationNodeList_.emplace_front(node);
3407 }
3408 
GetAlignDeclarationNodeList()3409 std::list<RefPtr<RenderNode>>& PipelineContext::GetAlignDeclarationNodeList()
3410 {
3411     CHECK_RUN_ON(UI);
3412     return alignDeclarationNodeList_;
3413 }
3414 
AddScreenOnEvent(std::function<void ()> && func)3415 void PipelineContext::AddScreenOnEvent(std::function<void()>&& func)
3416 {
3417     taskExecutor_->PostTask(
3418         [wp = WeakClaim(this), screenOnFunc = std::move(func)]() mutable {
3419             auto pipeline = wp.Upgrade();
3420             if (pipeline && pipeline->screenOnCallback_) {
3421                 pipeline->screenOnCallback_(std::move(screenOnFunc));
3422             }
3423         },
3424         TaskExecutor::TaskType::PLATFORM, "ArkUIScreenOnEvent");
3425 }
3426 
AddScreenOffEvent(std::function<void ()> && func)3427 void PipelineContext::AddScreenOffEvent(std::function<void()>&& func)
3428 {
3429     taskExecutor_->PostTask(
3430         [wp = WeakClaim(this), screenOffFunc = std::move(func)]() mutable {
3431             auto pipeline = wp.Upgrade();
3432             if (pipeline && pipeline->screenOffCallback_) {
3433                 pipeline->screenOffCallback_(std::move(screenOffFunc));
3434             }
3435         },
3436         TaskExecutor::TaskType::PLATFORM, "ArkUIScreenOffEvent");
3437 }
3438 
IsWindowInScreen()3439 bool PipelineContext::IsWindowInScreen()
3440 {
3441     if (queryIfWindowInScreenCallback_) {
3442         // We post an async task to do async query to avoid thread deadlock between UI thread and Platform thread
3443         taskExecutor_->PostTask(
3444             [wp = WeakClaim(this)] {
3445                 auto pipeline = wp.Upgrade();
3446                 if (!pipeline) {
3447                     return;
3448                 }
3449                 pipeline->queryIfWindowInScreenCallback_();
3450             },
3451             TaskExecutor::TaskType::PLATFORM, "ArkUIQueryIfWindowInScreen");
3452     }
3453     // Note that the result is not real-time result but the result from previous query
3454     return isWindowInScreen_;
3455 }
3456 
NotifyOnPreDraw()3457 void PipelineContext::NotifyOnPreDraw()
3458 {
3459     decltype(nodesToNotifyOnPreDraw_) nodesToNotifyOnPreDraw(std::move(nodesToNotifyOnPreDraw_));
3460     for (const auto& node : nodesToNotifyOnPreDraw) {
3461         node->OnPreDraw();
3462     }
3463 }
3464 
AddNodesToNotifyOnPreDraw(const RefPtr<RenderNode> & renderNode)3465 void PipelineContext::AddNodesToNotifyOnPreDraw(const RefPtr<RenderNode>& renderNode)
3466 {
3467     nodesToNotifyOnPreDraw_.emplace(renderNode);
3468 }
3469 
UpdateNodesNeedDrawOnPixelMap()3470 void PipelineContext::UpdateNodesNeedDrawOnPixelMap()
3471 {
3472     for (const auto& dirtyNode : dirtyRenderNodes_) {
3473         SearchNodesNeedDrawOnPixelMap(dirtyNode);
3474     }
3475     for (const auto& dirtyNode : dirtyRenderNodesInOverlay_) {
3476         SearchNodesNeedDrawOnPixelMap(dirtyNode);
3477     }
3478 }
3479 
SearchNodesNeedDrawOnPixelMap(const RefPtr<RenderNode> & renderNode)3480 void PipelineContext::SearchNodesNeedDrawOnPixelMap(const RefPtr<RenderNode>& renderNode)
3481 {
3482     auto parent = renderNode;
3483     while (parent) {
3484         auto box = AceType::DynamicCast<RenderBox>(parent);
3485         if (box && box->GetPixelMap()) {
3486             nodesNeedDrawOnPixelMap_.emplace(parent);
3487         }
3488         parent = parent->GetParent().Upgrade();
3489     }
3490 }
3491 
NotifyDrawOnPixelMap()3492 void PipelineContext::NotifyDrawOnPixelMap()
3493 {
3494     decltype(nodesNeedDrawOnPixelMap_) nodesNeedDrawOnPixelMap(std::move(nodesNeedDrawOnPixelMap_));
3495     for (const auto& node : nodesNeedDrawOnPixelMap) {
3496         auto box = AceType::DynamicCast<RenderBox>(node);
3497         if (box) {
3498             box->DrawOnPixelMap();
3499         }
3500     }
3501 }
3502 
PushVisibleCallback(NodeId id,double ratio,std::function<void (bool,double)> && func)3503 void PipelineContext::PushVisibleCallback(NodeId id, double ratio, std::function<void(bool, double)>&& func)
3504 {
3505     auto accessibilityManager = GetAccessibilityManager();
3506     if (!accessibilityManager) {
3507         return;
3508     }
3509     accessibilityManager->AddVisibleChangeNode(id, ratio, func);
3510 }
3511 
AddVisibleAreaChangeNode(const ComposeId & nodeId,double ratio,const VisibleRatioCallback & callback)3512 void PipelineContext::AddVisibleAreaChangeNode(
3513     const ComposeId& nodeId, double ratio, const VisibleRatioCallback& callback)
3514 {
3515     VisibleCallbackInfo info;
3516     info.callback = callback;
3517     info.visibleRatio = ratio;
3518     info.isCurrentVisible = false;
3519     auto iter = visibleAreaChangeNodes_.find(nodeId);
3520     if (iter != visibleAreaChangeNodes_.end()) {
3521         auto& callbackList = iter->second;
3522         callbackList.emplace_back(info);
3523     } else {
3524         std::list<VisibleCallbackInfo> callbackList;
3525         callbackList.emplace_back(info);
3526         visibleAreaChangeNodes_[nodeId] = callbackList;
3527     }
3528 }
3529 
RemoveVisibleChangeNode(NodeId id)3530 void PipelineContext::RemoveVisibleChangeNode(NodeId id)
3531 {
3532     auto accessibilityManager = GetAccessibilityManager();
3533     if (!accessibilityManager) {
3534         return;
3535     }
3536     accessibilityManager->RemoveVisibleChangeNode(id);
3537 }
3538 
IsVisibleChangeNodeExists(NodeId index) const3539 bool PipelineContext::IsVisibleChangeNodeExists(NodeId index) const
3540 {
3541     auto accessibilityManager = GetAccessibilityManager();
3542     if (!accessibilityManager) {
3543         return false;
3544     }
3545     return accessibilityManager->IsVisibleChangeNodeExists(index);
3546 }
3547 
SetRSUIDirector(std::shared_ptr<OHOS::Rosen::RSUIDirector> rsUIDirector)3548 void PipelineContext::SetRSUIDirector(std::shared_ptr<OHOS::Rosen::RSUIDirector> rsUIDirector)
3549 {
3550 #ifdef ENABLE_ROSEN_BACKEND
3551     rsUIDirector_ = rsUIDirector;
3552 #endif
3553 }
3554 
GetRSUIDirector()3555 std::shared_ptr<OHOS::Rosen::RSUIDirector> PipelineContext::GetRSUIDirector()
3556 {
3557 #ifdef ENABLE_ROSEN_BACKEND
3558     return rsUIDirector_;
3559 #else
3560     return nullptr;
3561 #endif
3562 }
3563 
StoreNode(int32_t restoreId,const WeakPtr<RenderElement> & node)3564 void PipelineContext::StoreNode(int32_t restoreId, const WeakPtr<RenderElement>& node)
3565 {
3566     auto ret = storeNode_.try_emplace(restoreId, node);
3567     if (!ret.second) {
3568         LOGW("store restore node fail, id = %{public}d", restoreId);
3569         storeNode_[restoreId] = node;
3570     }
3571 }
3572 
GetStoredNodeInfo()3573 std::unique_ptr<JsonValue> PipelineContext::GetStoredNodeInfo()
3574 {
3575     auto jsonNodeInfo = JsonUtil::Create(true);
3576     auto iter = storeNode_.begin();
3577     while (iter != storeNode_.end()) {
3578         auto RenderElement = (iter->second).Upgrade();
3579         if (RenderElement) {
3580             std::string info = RenderElement->ProvideRestoreInfo();
3581             if (!info.empty()) {
3582                 jsonNodeInfo->Put(std::to_string(iter->first).c_str(), info.c_str());
3583             }
3584         }
3585         ++iter;
3586     }
3587     return jsonNodeInfo;
3588 }
3589 
RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)3590 void PipelineContext::RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)
3591 {
3592     if (!nodeInfo->IsValid() || !nodeInfo->IsObject()) {
3593         LOGW("restore nodeInfo is invalid");
3594     }
3595     auto child = nodeInfo->GetChild();
3596     while (child->IsValid()) {
3597         auto key = child->GetKey();
3598         auto value = child->GetString();
3599         int vital = std::atoi(key.c_str());
3600         if (vital == 0) {
3601             LOGE("input %{public}s can not be converted to number.", key.c_str());
3602         }
3603         restoreNodeInfo_.try_emplace(vital, value);
3604         child = child->GetNext();
3605     }
3606 }
3607 
GetRestoreInfo(int32_t restoreId)3608 std::string PipelineContext::GetRestoreInfo(int32_t restoreId)
3609 {
3610     auto iter = restoreNodeInfo_.find(restoreId);
3611     if (iter != restoreNodeInfo_.end()) {
3612         std::string restoreNodeInfo = iter->second;
3613         restoreNodeInfo_.erase(iter);
3614         return restoreNodeInfo;
3615     }
3616     return "";
3617 }
3618 
SetSinglePageId(int32_t pageId)3619 void PipelineContext::SetSinglePageId(int32_t pageId)
3620 {
3621     auto stageElement = GetStageElement();
3622     if (!stageElement) {
3623         LOGE("Get stage element failed!");
3624         return;
3625     }
3626 
3627     stageElement->SetSinglePageId(pageId);
3628 }
3629 
SetAppTitle(const std::string & title)3630 void PipelineContext::SetAppTitle(const std::string& title)
3631 {
3632     CHECK_NULL_VOID(rootElement_);
3633     auto containerModalElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
3634     CHECK_NULL_VOID(containerModalElement);
3635     containerModalElement->SetAppTitle(title);
3636 }
3637 
SetAppIcon(const RefPtr<PixelMap> & icon)3638 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
3639 {
3640     CHECK_NULL_VOID(rootElement_);
3641     auto containerModalElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
3642     CHECK_NULL_VOID(containerModalElement);
3643     containerModalElement->SetAppIcon(icon);
3644 }
3645 
3646 } // namespace OHOS::Ace
3647