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