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