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