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