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