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 
__anon14f8d7970202() 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,bool hideClose)340 void PipelineContext::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
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, hideClose);
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,bool isEventsPassThrough)1530 void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe, bool isEventsPassThrough)
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         window_->FlushLayoutSize(width_, height_);
1953         hasIdleTasks_ = false;
1954     } else {
1955         LOGW("the surface is not ready, waiting");
1956     }
1957     if (isMoving_) {
1958         window_->RequestFrame();
1959         MarkForcedRefresh();
1960         isMoving_ = false;
1961     }
1962 }
1963 
OnIdle(int64_t deadline)1964 void PipelineContext::OnIdle(int64_t deadline)
1965 {
1966     CHECK_RUN_ON(UI);
1967     ACE_FUNCTION_TRACE();
1968     auto front = GetFrontend();
1969     if (front && GetIsDeclarative()) {
1970         if (deadline != 0) {
1971             FlushPredictLayout(deadline);
1972         }
1973         return;
1974     }
1975     FlushPredictLayout(deadline);
1976     if (hasIdleTasks_) {
1977         FlushPipelineImmediately();
1978         window_->RequestFrame();
1979         MarkForcedRefresh();
1980         hasIdleTasks_ = false;
1981     }
1982     FlushPageUpdateTasks();
1983 }
1984 
OnVirtualKeyboardHeightChange(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance,bool forceChange)1985 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight,
1986     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, const bool supportAvoidance,
1987     bool forceChange)
1988 {
1989     CHECK_RUN_ON(UI);
1990     ACE_FUNCTION_TRACE();
1991 #ifdef ENABLE_ROSEN_BACKEND
1992     if (rsTransaction) {
1993         FlushMessages();
1994         rsTransaction->Begin();
1995     }
1996 #endif
1997 
1998     auto func = [this, keyboardHeight]() {
1999         double positionY = 0;
2000         if (textFieldManager_) {
2001             positionY = textFieldManager_->GetClickPosition().GetY();
2002         }
2003         auto newKeyboardHeight = keyboardHeight / viewScale_;
2004         auto height = height_ / viewScale_;
2005         double offsetFix =
2006             (height - positionY) > 100.0 ? newKeyboardHeight - (height - positionY) / 2.0 : newKeyboardHeight;
2007         LOGI("OnVirtualKeyboardAreaChange positionY:%{public}f safeArea:%{public}f offsetFix:%{public}f", positionY,
2008             (height - newKeyboardHeight), offsetFix);
2009         if (NearZero(newKeyboardHeight)) {
2010             if (textFieldManager_ && AceType::InstanceOf<TextFieldManager>(textFieldManager_)) {
2011                 auto textFieldManager = AceType::DynamicCast<TextFieldManager>(textFieldManager_);
2012                 if (textFieldManager->ResetSlidingPanelParentHeight()) {
2013                     return;
2014                 }
2015             }
2016             SetRootSizeWithWidthHeight(width_, height_, 0);
2017             rootOffset_.SetY(0.0);
2018         } else if (positionY > (height - newKeyboardHeight) && offsetFix > 0.0) {
2019             if (textFieldManager_ && AceType::InstanceOf<TextFieldManager>(textFieldManager_)) {
2020                 auto textFieldManager = AceType::DynamicCast<TextFieldManager>(textFieldManager_);
2021                 if (textFieldManager->UpdatePanelForVirtualKeyboard(-offsetFix, height)) {
2022                     return;
2023                 }
2024             }
2025             SetRootSizeWithWidthHeight(width_, height_, -offsetFix);
2026             rootOffset_.SetY(-offsetFix);
2027         }
2028     };
2029 
2030     AnimationOption option = AnimationUtil::CreateKeyboardAnimationOption(keyboardAnimationConfig_, keyboardHeight);
2031     Animate(option, option.GetCurve(), func);
2032 
2033 #ifdef ENABLE_ROSEN_BACKEND
2034     if (rsTransaction) {
2035         rsTransaction->Commit();
2036     }
2037 #endif
2038 }
2039 
FlushPipelineImmediately()2040 void PipelineContext::FlushPipelineImmediately()
2041 {
2042     CHECK_RUN_ON(UI);
2043     ACE_FUNCTION_TRACE();
2044     if (isSurfaceReady_) {
2045         FlushPipelineWithoutAnimation();
2046     } else {
2047         LOGW("the surface is not ready, waiting");
2048     }
2049 }
2050 
WindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2051 void PipelineContext::WindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type,
2052     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2053 {
2054     static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
2055     if (!rootElement_ || !rootElement_->GetRenderNode() || !IsWindowSizeAnimationEnabled) {
2056         LOGE("RootNodeAnimation: no root element found, no animation configured");
2057         SetRootSizeWithWidthHeight(width, height);
2058         return;
2059     }
2060     auto rootNode = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2061     switch (type) {
2062         case WindowSizeChangeReason::RECOVER:
2063         case WindowSizeChangeReason::MAXIMIZE: {
2064             AnimationOption option;
2065             constexpr int32_t duration = 400;
2066             option.SetDuration(duration);
2067             auto curve = MakeRefPtr<DecelerationCurve>();
2068             option.SetCurve(curve);
2069             Animate(option, curve, [width, height, this]() {
2070                 SetRootSizeWithWidthHeight(width, height);
2071                 FlushLayout();
2072             });
2073             break;
2074         }
2075         case WindowSizeChangeReason::ROTATION: {
2076             SetRootSizeWithWidthHeight(width, height);
2077             FlushLayout();
2078             break;
2079         }
2080         case WindowSizeChangeReason::DRAG_START:
2081         case WindowSizeChangeReason::DRAG:
2082         case WindowSizeChangeReason::DRAG_END:
2083         case WindowSizeChangeReason::RESIZE:
2084         case WindowSizeChangeReason::UNDEFINED:
2085         default: {
2086             SetRootSizeWithWidthHeight(width, height);
2087         }
2088     }
2089 }
2090 
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2091 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type,
2092     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2093 {
2094     CHECK_RUN_ON(UI);
2095     if (width_ == width && height_ == height && type == WindowSizeChangeReason::CUSTOM_ANIMATION) {
2096         TryCallNextFrameLayoutCallback();
2097         return;
2098     }
2099     // Refresh the screen when developers customize the resolution and screen density on the PC preview.
2100 #if !defined(PREVIEW)
2101     if (width_ == width && height_ == height && isSurfaceReady_ && !isDensityUpdate_) {
2102         return;
2103     }
2104 #endif
2105 
2106     for (auto&& [id, callback] : surfaceChangedCallbackMap_) {
2107         if (callback) {
2108             callback(width, height, width_, height_, type);
2109         }
2110     }
2111 
2112     width_ = width;
2113     height_ = height;
2114 
2115     ACE_SCOPED_TRACE("OnSurfaceChanged(%d, %d)", width, height);
2116     LOGI("Surface size changed, [%{public}d * %{public}d]", width, height);
2117     if (!NearZero(rootHeight_)) {
2118         double newRootHeight = height / viewScale_;
2119         double newRootWidth = width / viewScale_;
2120         double offsetHeight = rootHeight_ - newRootHeight;
2121         if (textFieldManager_ && GetLastPage()) {
2122             textFieldManager_->MovePage(GetLastPage()->GetPageId(), { newRootWidth, newRootHeight }, offsetHeight);
2123         }
2124     }
2125 
2126     taskExecutor_->PostTask(
2127         [weakFrontend = weakFrontend_, width, height]() {
2128             auto frontend = weakFrontend.Upgrade();
2129             if (frontend) {
2130                 frontend->OnSurfaceChanged(width, height);
2131             }
2132         },
2133         TaskExecutor::TaskType::JS, "ArkUISurfaceChanged");
2134 
2135     // init transition clip size when surface changed.
2136     const auto& pageElement = GetLastPage();
2137     if (pageElement) {
2138         const auto& transitionElement = AceType::DynamicCast<PageTransitionElement>(pageElement->GetFirstChild());
2139         if (transitionElement) {
2140             transitionElement->InitTransitionClip();
2141         }
2142     }
2143 #ifdef ENABLE_ROSEN_BACKEND
2144     WindowSizeChangeAnimate(width, height, type, rsTransaction);
2145 #else
2146     SetRootSizeWithWidthHeight(width, height);
2147 #endif
2148     if (isSurfaceReady_) {
2149         return;
2150     }
2151     isSurfaceReady_ = true;
2152     FlushPipelineWithoutAnimation();
2153     MarkForcedRefresh();
2154 #ifndef WEARABLE_PRODUCT
2155     multiModalManager_->OpenChannel(Claim(this));
2156 #endif
2157 }
2158 
OnSurfacePositionChanged(int32_t posX,int32_t posY)2159 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
2160 {
2161     for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
2162         if (callback) {
2163             callback(posX, posY);
2164         }
2165     }
2166 }
2167 
OnSurfaceDensityChanged(double density)2168 void PipelineContext::OnSurfaceDensityChanged(double density)
2169 {
2170     CHECK_RUN_ON(UI);
2171     ACE_SCOPED_TRACE("OnSurfaceDensityChanged(%lf)", density);
2172     isDensityUpdate_ = density != density_;
2173     density_ = density;
2174     if (!NearZero(viewScale_)) {
2175         dipScale_ = density_ / viewScale_;
2176     }
2177     if (isDensityUpdate_) {
2178         PipelineBase::OnSurfaceDensityChanged(density);
2179     }
2180 }
2181 
OnSystemBarHeightChanged(double statusBar,double navigationBar)2182 void PipelineContext::OnSystemBarHeightChanged(double statusBar, double navigationBar)
2183 {
2184     CHECK_RUN_ON(UI);
2185     ACE_SCOPED_TRACE("OnSystemBarHeightChanged(%lf, %lf)", statusBar, navigationBar);
2186     double statusBarHeight = 0.0;
2187     double navigationBarHeight = 0.0;
2188     if (!NearZero(viewScale_) && !NearZero(dipScale_)) {
2189         statusBarHeight = statusBar / viewScale_ / dipScale_;
2190         navigationBarHeight = navigationBar / viewScale_ / dipScale_;
2191     }
2192 
2193     if ((!NearEqual(statusBarHeight, statusBarHeight_)) || (!NearEqual(navigationBarHeight, navigationBarHeight_))) {
2194         statusBarHeight_ = statusBarHeight;
2195         navigationBarHeight_ = navigationBarHeight;
2196         if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
2197             auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2198             if (semiModal) {
2199                 semiModal->UpdateSystemBarHeight(statusBarHeight_, navigationBarHeight_);
2200             }
2201         } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
2202             auto dialogModal = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
2203             if (dialogModal) {
2204                 dialogModal->UpdateSystemBarHeight(statusBarHeight_, navigationBarHeight_);
2205             }
2206         } else {
2207             // Normal modal, do nothing.
2208         }
2209     }
2210 }
2211 
OnSurfaceDestroyed()2212 void PipelineContext::OnSurfaceDestroyed()
2213 {
2214     CHECK_RUN_ON(UI);
2215     ACE_SCOPED_TRACE("OnSurfaceDestroyed");
2216     isSurfaceReady_ = false;
2217 }
2218 
SetRootSizeWithWidthHeight(int32_t width,int32_t height,int32_t offset)2219 void PipelineContext::SetRootSizeWithWidthHeight(int32_t width, int32_t height, int32_t offset)
2220 {
2221     CHECK_RUN_ON(UI);
2222     UpdateRootSizeAndScale(width, height);
2223     CHECK_NULL_VOID(rootElement_);
2224     const Rect paintRect(0.0, 0.0, rootWidth_, rootHeight_);
2225     auto rootNode = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2226     if (!rootNode) {
2227         return;
2228     }
2229     auto stack = GetStageElement()->GetElementParent().Upgrade();
2230     if (stack) {
2231         auto renderStack = AceType::DynamicCast<RenderStack>(stack->GetRenderNode());
2232         if (renderStack) {
2233             renderStack->SetTop(Dimension(offset));
2234         }
2235     }
2236     if (!NearEqual(viewScale_, rootNode->GetScale()) || paintRect != rootNode->GetPaintRect() || isDensityUpdate_) {
2237         if (!NearEqual(viewScale_, rootNode->GetScale())) {
2238             rootNode->SetReset(true);
2239         }
2240         rootNode->SetPaintRect(paintRect);
2241         rootNode->SetScale(viewScale_);
2242         rootNode->MarkNeedLayout();
2243         rootNode->MarkNeedRender();
2244         focusAnimationManager_->SetAvailableRect(paintRect);
2245     }
2246     if (IsJsPlugin() || IsJsCard()) {
2247         return;
2248     }
2249     ScreenSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
2250     ScreenSystemManager::GetInstance().OnSurfaceChanged(width);
2251 }
2252 
SetAppBgColor(const Color & color)2253 void PipelineContext::SetAppBgColor(const Color& color)
2254 {
2255     LOGI("Set bgColor %{public}u", color.GetValue());
2256     appBgColor_ = color;
2257 #ifdef ENABLE_ROSEN_BACKEND
2258     if (rsUIDirector_) {
2259         rsUIDirector_->SetAbilityBGAlpha(appBgColor_.GetAlpha());
2260     }
2261 #endif
2262     if (!themeManager_) {
2263         LOGW("themeManager_ is nullptr!");
2264         return;
2265     }
2266     auto appTheme = themeManager_->GetTheme<AppTheme>();
2267     if (!appTheme) {
2268         LOGW("appTheme is nullptr!");
2269         return;
2270     }
2271     appTheme->SetBackgroundColor(appBgColor_);
2272     if (!rootElement_) {
2273         LOGW("rootElement_ is nullptr!");
2274         return;
2275     }
2276     auto renderRoot = DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2277     if (!renderRoot) {
2278         LOGW("renderRoot is nullptr!");
2279         return;
2280     }
2281     if (windowModal_ == WindowModal::CONTAINER_MODAL) {
2282         auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
2283         if (containerModal) {
2284             containerModal->SetAppBgColor(appBgColor_);
2285             renderRoot->SetBgColor(Color::TRANSPARENT);
2286             return;
2287         }
2288     }
2289     renderRoot->SetBgColor(appBgColor_);
2290 }
2291 
Finish(bool autoFinish) const2292 void PipelineContext::Finish(bool autoFinish) const
2293 {
2294     CHECK_RUN_ON(UI);
2295     if (autoFinish && rootElement_ && onShow_) {
2296         if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
2297             auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2298             if (!semiModal) {
2299                 LOGE("SemiModal animate to exit app failed. semi modal is null");
2300                 return;
2301             }
2302             semiModal->AnimateToExitApp();
2303             return;
2304         } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
2305             // dialog modal use translucent theme and will do exit animation by ACE itself.
2306             auto dialogModal = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
2307             if (!dialogModal) {
2308                 LOGE("DialogModal animate to exit app failed. dialog modal is null");
2309                 return;
2310             }
2311             dialogModal->AnimateToExitApp();
2312             return;
2313         } else {
2314             // normal force finish.
2315             Finish(false);
2316         }
2317     } else {
2318         if (finishEventHandler_) {
2319             finishEventHandler_();
2320         } else {
2321             LOGE("fail to finish current context due to handler is nullptr");
2322         }
2323     }
2324 }
2325 
RequestFullWindow(int32_t duration)2326 void PipelineContext::RequestFullWindow(int32_t duration)
2327 {
2328     CHECK_RUN_ON(UI);
2329     if (!rootElement_) {
2330         LOGE("Root element is null!");
2331         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2332         return;
2333     }
2334     auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2335     if (!semiModal) {
2336         LOGI("Get semiModal element failed. SemiModal element is null!");
2337         return;
2338     }
2339     if (semiModal->IsFullWindow()) {
2340         LOGI("Already in full window, skip it.");
2341         return;
2342     }
2343     isFullWindow_ = true;
2344     // when semi modal animating, no more full window request can be handled, so mark it as full window.
2345     semiModal->SetFullWindow(true);
2346     semiModal->AnimateToFullWindow(duration);
2347     NotifyStatusBarBgColor(semiModal->GetBackgroundColor());
2348     auto page = GetLastStack();
2349     if (!page) {
2350         return;
2351     }
2352     auto renderPage = AceType::DynamicCast<RenderStack>(page->GetRenderNode());
2353     if (!renderPage) {
2354         return;
2355     }
2356     // Change to full window, change page stack layout strategy.
2357     renderPage->SetStackFit(StackFit::INHERIT);
2358     renderPage->SetMainStackSize(MainStackSize::MAX);
2359     renderPage->MarkNeedLayout();
2360 }
2361 
ShowFocusAnimation(const RRect & rrect,const Color & color,const Offset & offset,bool isIndented) const2362 void PipelineContext::ShowFocusAnimation(
2363     const RRect& rrect, const Color& color, const Offset& offset, bool isIndented) const
2364 {
2365     focusAnimationManager_->SetFocusAnimationProperties(rrect, color, offset, isIndented);
2366 }
2367 
ShowFocusAnimation(const RRect & rrect,const Color & color,const Offset & offset,const Rect & clipRect) const2368 void PipelineContext::ShowFocusAnimation(
2369     const RRect& rrect, const Color& color, const Offset& offset, const Rect& clipRect) const
2370 {
2371     focusAnimationManager_->SetFocusAnimationProperties(rrect, color, offset, clipRect);
2372 }
2373 
AddDirtyFocus(const RefPtr<FocusNode> & node)2374 void PipelineContext::AddDirtyFocus(const RefPtr<FocusNode>& node)
2375 {
2376     CHECK_RUN_ON(UI);
2377     if (!node) {
2378         LOGW("node is null.");
2379         return;
2380     }
2381     if (node->IsChild()) {
2382         dirtyFocusNode_ = WeakClaim(RawPtr(node));
2383     } else {
2384         dirtyFocusScope_ = WeakClaim(RawPtr(node));
2385     }
2386     window_->RequestFrame();
2387 }
2388 
CancelFocusAnimation() const2389 void PipelineContext::CancelFocusAnimation() const
2390 {
2391     focusAnimationManager_->CancelFocusAnimation();
2392 }
2393 
PopFocusAnimation() const2394 void PipelineContext::PopFocusAnimation() const
2395 {
2396     focusAnimationManager_->PopFocusAnimationElement();
2397 }
2398 
PopRootFocusAnimation() const2399 void PipelineContext::PopRootFocusAnimation() const
2400 {
2401     focusAnimationManager_->PopRootFocusAnimationElement();
2402 }
2403 
PushFocusAnimation(const RefPtr<Element> & element) const2404 void PipelineContext::PushFocusAnimation(const RefPtr<Element>& element) const
2405 {
2406     focusAnimationManager_->PushFocusAnimationElement(element);
2407 }
2408 
Destroy()2409 void PipelineContext::Destroy()
2410 {
2411     CHECK_RUN_ON(UI);
2412     LOGI("PipelineContext::Destroy begin.");
2413     rootElement_.Reset();
2414     composedElementMap_.clear();
2415     dirtyElements_.clear();
2416     deactivateElements_.clear();
2417     dirtyRenderNodes_.clear();
2418     dirtyRenderNodesInOverlay_.clear();
2419     dirtyLayoutNodes_.clear();
2420     predictLayoutNodes_.clear();
2421     geometryChangedNodes_.clear();
2422     needPaintFinishNodes_.clear();
2423     dirtyFocusNode_.Reset();
2424     dirtyFocusScope_.Reset();
2425     postFlushListeners_.clear();
2426     postAnimationFlushListeners_.clear();
2427     preFlushListeners_.clear();
2428     sharedTransitionController_.Reset();
2429     cardTransitionController_.Reset();
2430     while (!pageUpdateTasks_.empty()) {
2431         pageUpdateTasks_.pop();
2432     }
2433     alignDeclarationNodeList_.clear();
2434     hoverNodes_.clear();
2435     renderFactory_.Reset();
2436     nodesToNotifyOnPreDraw_.clear();
2437     nodesNeedDrawOnPixelMap_.clear();
2438     layoutTransitionNodeSet_.clear();
2439     explicitAnimators_.clear();
2440     preTargetRenderNode_.Reset();
2441     sharedImageManager_.Reset();
2442     rectCallbackList_.clear();
2443     PipelineBase::Destroy();
2444     LOGI("PipelineContext::Destroy end.");
2445 }
2446 
SendCallbackMessageToFrontend(const std::string & callbackId,const std::string & data)2447 void PipelineContext::SendCallbackMessageToFrontend(const std::string& callbackId, const std::string& data)
2448 {
2449     auto frontend = weakFrontend_.Upgrade();
2450     if (!frontend) {
2451         LOGE("frontend is nullptr");
2452         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2453         return;
2454     }
2455     frontend->SendCallbackMessage(callbackId, data);
2456 }
2457 
SendEventToFrontend(const EventMarker & eventMarker)2458 void PipelineContext::SendEventToFrontend(const EventMarker& eventMarker)
2459 {
2460     auto frontend = weakFrontend_.Upgrade();
2461     if (!frontend) {
2462         LOGE("frontend is nullptr");
2463         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2464         return;
2465     }
2466     auto handler = frontend->GetEventHandler();
2467     if (!handler) {
2468         LOGE("fail to trigger async event due to event handler is nullptr");
2469         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2470         return;
2471     }
2472     handler->HandleAsyncEvent(eventMarker);
2473 }
2474 
SendEventToFrontend(const EventMarker & eventMarker,const std::string & param)2475 void PipelineContext::SendEventToFrontend(const EventMarker& eventMarker, const std::string& param)
2476 {
2477     auto frontend = weakFrontend_.Upgrade();
2478     if (!frontend) {
2479         LOGE("frontend is nullptr");
2480         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2481         return;
2482     }
2483     auto handler = frontend->GetEventHandler();
2484     if (!handler) {
2485         LOGE("fail to trigger async event due to event handler is nullptr");
2486         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2487         return;
2488     }
2489     handler->HandleAsyncEvent(eventMarker, param);
2490 }
2491 
AccessibilityRequestFocus(const ComposeId & id)2492 bool PipelineContext::AccessibilityRequestFocus(const ComposeId& id)
2493 {
2494     auto targetElement = GetComposedElementById(id);
2495     if (!targetElement) {
2496         LOGE("RequestFocusById targetElement is null.");
2497         EventReport::SendAccessibilityException(AccessibilityExcepType::GET_NODE_ERR);
2498         return false;
2499     }
2500     return RequestFocus(targetElement);
2501 }
2502 
RequestFocus(const RefPtr<Element> & targetElement)2503 bool PipelineContext::RequestFocus(const RefPtr<Element>& targetElement)
2504 {
2505     CHECK_RUN_ON(UI);
2506     if (!targetElement) {
2507         return false;
2508     }
2509     auto children = targetElement->GetChildren();
2510     for (const auto& childElement : children) {
2511         auto focusNode = AceType::DynamicCast<FocusNode>(childElement);
2512         if (focusNode) {
2513             if (focusNode->RequestFocusImmediately()) {
2514                 return true;
2515             } else {
2516                 continue;
2517             }
2518         }
2519         if (RequestFocus(childElement)) {
2520             return true;
2521         }
2522     }
2523     return false;
2524 }
2525 
RequestFocus(const std::string & targetNodeId,bool isSyncRequest)2526 bool PipelineContext::RequestFocus(const std::string& targetNodeId, bool isSyncRequest)
2527 {
2528     CHECK_NULL_RETURN(rootElement_, false);
2529     auto currentFocusChecked = rootElement_->RequestFocusImmediatelyById(targetNodeId);
2530     if (!isSubPipeline_ || currentFocusChecked) {
2531         LOGI("Request focus finish currentFocus is %{public}d", currentFocusChecked);
2532         return currentFocusChecked;
2533     }
2534     LOGI("Search focus in main pipeline");
2535     auto parentPipelineBase = parentPipeline_.Upgrade();
2536     CHECK_NULL_RETURN(parentPipelineBase, false);
2537     auto parentPipelineContext = AceType::DynamicCast<PipelineContext>(parentPipelineBase);
2538     CHECK_NULL_RETURN(parentPipelineContext, false);
2539     return parentPipelineContext->RequestFocus(targetNodeId);
2540 }
2541 
GetRenderFocusAnimation() const2542 RefPtr<RenderFocusAnimation> PipelineContext::GetRenderFocusAnimation() const
2543 {
2544     return focusAnimationManager_->GetRenderFocusAnimation();
2545 }
2546 
ShowShadow(const RRect & rrect,const Offset & offset) const2547 void PipelineContext::ShowShadow(const RRect& rrect, const Offset& offset) const
2548 {
2549     focusAnimationManager_->SetShadowProperties(rrect, offset);
2550 }
2551 
ShowShadow(const RRect & rrect,const Offset & offset,const Rect & clipRect) const2552 void PipelineContext::ShowShadow(const RRect& rrect, const Offset& offset, const Rect& clipRect) const
2553 {
2554     focusAnimationManager_->SetShadowProperties(rrect, offset, clipRect);
2555 }
2556 
PushShadow(const RefPtr<Element> & element) const2557 void PipelineContext::PushShadow(const RefPtr<Element>& element) const
2558 {
2559     focusAnimationManager_->PushShadow(element);
2560 }
2561 
PopShadow() const2562 void PipelineContext::PopShadow() const
2563 {
2564     focusAnimationManager_->PopShadow();
2565 }
2566 
CancelShadow() const2567 void PipelineContext::CancelShadow() const
2568 {
2569     focusAnimationManager_->CancelShadow();
2570 }
2571 
SetUseRootAnimation(bool useRoot)2572 void PipelineContext::SetUseRootAnimation(bool useRoot)
2573 {
2574     focusAnimationManager_->SetUseRoot(useRoot);
2575 }
2576 
2577 #ifndef WEARABLE_PRODUCT
SetMultimodalSubscriber(const RefPtr<MultimodalSubscriber> & multimodalSubscriber)2578 void PipelineContext::SetMultimodalSubscriber(const RefPtr<MultimodalSubscriber>& multimodalSubscriber)
2579 {
2580     multiModalManager_->SetMultimodalSubscriber(multimodalSubscriber);
2581 }
2582 
SetWindowOnShow()2583 void PipelineContext::SetWindowOnShow()
2584 {
2585     window_->OnShow();
2586     window_->RequestFrame();
2587 }
2588 
SetWindowOnHide()2589 void PipelineContext::SetWindowOnHide()
2590 {
2591     window_->RequestFrame();
2592     window_->OnHide();
2593 }
2594 
OnShow()2595 void PipelineContext::OnShow()
2596 {
2597     onShow_ = true;
2598     SetWindowOnShow();
2599     PerfMonitor::GetPerfMonitor()->SetAppForeground(true);
2600     auto multiModalScene = multiModalManager_->GetCurrentMultiModalScene();
2601     if (multiModalScene) {
2602         multiModalScene->Resume();
2603     }
2604     taskExecutor_->PostTask(
2605         [weak = AceType::WeakClaim(this)]() {
2606             auto context = weak.Upgrade();
2607             if (!context) {
2608                 return;
2609             }
2610 #ifdef ENABLE_ROSEN_BACKEND
2611             if (context->rsUIDirector_) {
2612                 context->rsUIDirector_->GoForeground();
2613             }
2614 #endif
2615             const auto& rootElement = context->rootElement_;
2616             if (!rootElement) {
2617                 LOGE("render element is null!");
2618                 return;
2619             }
2620             const auto& renderRoot = AceType::DynamicCast<RenderRoot>(rootElement->GetRenderNode());
2621             if (!renderRoot) {
2622                 LOGE("render root is null!");
2623                 return;
2624             }
2625             if ((context->windowModal_ == WindowModal::SEMI_MODAL) ||
2626                 (context->windowModal_ == WindowModal::DIALOG_MODAL)) {
2627                 renderRoot->SetDefaultBgColor();
2628             }
2629             renderRoot->NotifyOnShow();
2630         },
2631         TaskExecutor::TaskType::UI, "ArkUIRenderRootShow");
2632 }
2633 
OnHide()2634 void PipelineContext::OnHide()
2635 {
2636     onShow_ = false;
2637     SetWindowOnHide();
2638     PerfMonitor::GetPerfMonitor()->SetAppForeground(false);
2639     auto multiModalScene = multiModalManager_->GetCurrentMultiModalScene();
2640     if (multiModalScene) {
2641         multiModalScene->Hide();
2642     }
2643     taskExecutor_->PostTask(
2644         [weak = AceType::WeakClaim(this)]() {
2645             auto context = weak.Upgrade();
2646             if (!context) {
2647                 return;
2648             }
2649             if (context->IsSubPipeline()) {
2650                 context->FlushPipelineImmediately();
2651             }
2652 #ifdef ENABLE_ROSEN_BACKEND
2653             if (context->rsUIDirector_) {
2654                 context->rsUIDirector_->GoBackground();
2655                 context->rsUIDirector_->SendMessages();
2656             }
2657 #endif
2658             context->NotifyPopupDismiss();
2659             context->OnVirtualKeyboardAreaChange(Rect());
2660             const auto& rootElement = context->rootElement_;
2661             if (!rootElement) {
2662                 LOGE("render element is null!");
2663                 return;
2664             }
2665             const auto& renderRoot = AceType::DynamicCast<RenderRoot>(rootElement->GetRenderNode());
2666             if (!renderRoot) {
2667                 LOGE("render root is null!");
2668                 return;
2669             }
2670             renderRoot->NotifyOnHide();
2671         },
2672         TaskExecutor::TaskType::UI, "ArkUIRenderRootHide");
2673 }
2674 #endif
2675 
RefreshRootBgColor() const2676 void PipelineContext::RefreshRootBgColor() const
2677 {
2678     CHECK_RUN_ON(UI);
2679     if (!rootElement_) {
2680         return;
2681     }
2682     const auto& render = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2683     if (render) {
2684         render->SetDefaultBgColor(windowModal_ == WindowModal::CONTAINER_MODAL);
2685     }
2686 }
2687 
OnPageShow()2688 void PipelineContext::OnPageShow()
2689 {
2690     CHECK_RUN_ON(UI);
2691     if (onPageShowCallBack_) {
2692         onPageShowCallBack_();
2693     }
2694 }
2695 
SetTimeProvider(TimeProvider && timeProvider)2696 void PipelineContext::SetTimeProvider(TimeProvider&& timeProvider)
2697 {
2698     if (!timeProvider) {
2699         LOGE("Set time provider failed. provider is null.");
2700         return;
2701     }
2702     timeProvider_ = std::move(timeProvider);
2703 }
2704 
GetTimeFromExternalTimer()2705 uint64_t PipelineContext::GetTimeFromExternalTimer()
2706 {
2707     if (isFlushingAnimation_) {
2708         return flushAnimationTimestamp_;
2709     } else {
2710         if (!timeProvider_) {
2711             LOGE("No time provider has been set.");
2712             return 0;
2713         }
2714         return timeProvider_();
2715     }
2716 }
2717 
LoadSystemFont(const std::function<void ()> & onFondsLoaded)2718 void PipelineContext::LoadSystemFont(const std::function<void()>& onFondsLoaded)
2719 {
2720     GetTaskExecutor()->PostTask(
2721         [weak = WeakClaim(this), fontManager = fontManager_, onFondsLoaded]() {
2722             if (!fontManager) {
2723                 return;
2724             }
2725             fontManager->LoadSystemFont();
2726             auto context = weak.Upgrade();
2727             if (!context) {
2728                 return;
2729             }
2730             context->GetTaskExecutor()->PostTask(
2731                 [onFondsLoaded]() {
2732                     if (onFondsLoaded) {
2733                         onFondsLoaded();
2734                     }
2735                 },
2736                 TaskExecutor::TaskType::UI, "ArkUISystemFondsLoaded");
2737         },
2738         TaskExecutor::TaskType::IO, "ArkUILoadSystemFont");
2739 }
2740 
AddFontNode(const WeakPtr<RenderNode> & node)2741 void PipelineContext::AddFontNode(const WeakPtr<RenderNode>& node)
2742 {
2743     if (fontManager_) {
2744         fontManager_->AddFontNode(node);
2745     }
2746 }
2747 
RemoveFontNode(const WeakPtr<RenderNode> & node)2748 void PipelineContext::RemoveFontNode(const WeakPtr<RenderNode>& node)
2749 {
2750     if (fontManager_) {
2751         fontManager_->RemoveFontNode(node);
2752     }
2753 }
2754 
SetClickPosition(const Offset & position) const2755 void PipelineContext::SetClickPosition(const Offset& position) const
2756 {
2757     LOGI("SetClickPosition position:%{public}s rootOffset:%{public}s", position.ToString().c_str(),
2758         rootOffset_.ToString().c_str());
2759     if (textFieldManager_) {
2760         textFieldManager_->SetClickPosition(position - rootOffset_);
2761     }
2762 }
2763 
GetOverlayElement() const2764 const RefPtr<OverlayElement> PipelineContext::GetOverlayElement() const
2765 {
2766     if (!rootElement_) {
2767         LOGE("Root element is null!");
2768         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2769         return RefPtr<OverlayElement>();
2770     }
2771     auto overlay = AceType::DynamicCast<OverlayElement>(rootElement_->GetOverlayElement(windowModal_));
2772     if (!overlay) {
2773         LOGE("Get overlay element failed. overlay element is null!");
2774         return RefPtr<OverlayElement>();
2775     }
2776     return overlay;
2777 }
2778 
FlushBuildAndLayoutBeforeSurfaceReady()2779 void PipelineContext::FlushBuildAndLayoutBeforeSurfaceReady()
2780 {
2781     if (isSurfaceReady_) {
2782         return;
2783     }
2784     GetTaskExecutor()->PostTask(
2785         [weak = AceType::WeakClaim(this)]() {
2786             auto context = weak.Upgrade();
2787             if (!context || context->isSurfaceReady_) {
2788                 return;
2789             }
2790 
2791             context->FlushBuild();
2792             context->SetRootRect(context->width_, context->height_);
2793             context->FlushLayout();
2794         },
2795         TaskExecutor::TaskType::UI, "ArkUIFlushBuildAndLayout");
2796 }
2797 
RootLostFocus(BlurReason reason) const2798 void PipelineContext::RootLostFocus(BlurReason reason) const
2799 {
2800     if (rootElement_) {
2801         rootElement_->LostFocus(reason);
2802     }
2803 }
2804 
WindowFocus(bool isFocus)2805 void PipelineContext::WindowFocus(bool isFocus)
2806 {
2807     onFocus_ = isFocus;
2808     if (!isFocus) {
2809         RootLostFocus(BlurReason::WINDOW_BLUR);
2810         NotifyPopupDismiss();
2811         OnVirtualKeyboardAreaChange(Rect());
2812     }
2813     if (onFocus_ && onShow_) {
2814         FlushFocus();
2815     }
2816     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
2817         return;
2818     }
2819     if (!rootElement_) {
2820         LOGE("WindowFocus failed, rootElement_ is null.");
2821         return;
2822     }
2823     auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
2824     if (containerModal) {
2825         containerModal->WindowFocus(isFocus);
2826     }
2827 }
2828 
ContainerModalUnFocus()2829 void PipelineContext::ContainerModalUnFocus() {}
2830 
AddPageUpdateTask(std::function<void ()> && task,bool directExecute)2831 void PipelineContext::AddPageUpdateTask(std::function<void()>&& task, bool directExecute)
2832 {
2833     CHECK_RUN_ON(UI);
2834     pageUpdateTasks_.emplace(std::move(task));
2835     if (directExecute) {
2836         FlushPageUpdateTasks();
2837     } else {
2838         window_->RequestFrame();
2839     }
2840 #if defined(ENABLE_NATIVE_VIEW)
2841     if (frameCount_ == 1) {
2842         OnIdle(0);
2843         FlushPipelineImmediately();
2844     }
2845 #endif
2846 }
2847 
MovePage(const Offset & rootRect,double offsetHeight)2848 void PipelineContext::MovePage(const Offset& rootRect, double offsetHeight)
2849 {
2850     if (textFieldManager_ && GetLastPage()) {
2851         textFieldManager_->MovePage(GetLastPage()->GetPageId(), rootRect, offsetHeight);
2852     }
2853 }
2854 
GetDeactivateElement(int32_t componentId) const2855 RefPtr<Element> PipelineContext::GetDeactivateElement(int32_t componentId) const
2856 {
2857     CHECK_RUN_ON(UI);
2858     auto elementIter = deactivateElements_.find(componentId);
2859     if (elementIter != deactivateElements_.end()) {
2860         return elementIter->second;
2861     } else {
2862         return nullptr;
2863     }
2864 }
2865 
AddDeactivateElement(const int32_t id,const RefPtr<Element> & element)2866 void PipelineContext::AddDeactivateElement(const int32_t id, const RefPtr<Element>& element)
2867 {
2868     CHECK_RUN_ON(UI);
2869     deactivateElements_.emplace(id, element);
2870 }
2871 
ClearDeactivateElements()2872 void PipelineContext::ClearDeactivateElements()
2873 {
2874     CHECK_RUN_ON(UI);
2875     ACE_FUNCTION_TRACK();
2876     for (auto iter = deactivateElements_.begin(); iter != deactivateElements_.end();) {
2877         auto element = iter->second;
2878         RefPtr<RenderNode> render = element ? element->GetRenderNode() : nullptr;
2879         if (!render || !render->IsDisappearing()) {
2880             iter = deactivateElements_.erase(iter);
2881         } else {
2882             iter++;
2883         }
2884     }
2885 }
2886 
DumpAccessibility(const std::vector<std::string> & params) const2887 void PipelineContext::DumpAccessibility(const std::vector<std::string>& params) const
2888 {
2889     auto accessibilityManager = GetAccessibilityManager();
2890     if (!accessibilityManager) {
2891         return;
2892     }
2893     accessibilityManager->OnDumpInfo(params);
2894 }
2895 
UpdateWindowBlurRegion(int32_t id,RRect rRect,float progress,WindowBlurStyle style,const std::vector<RRect> & coords)2896 void PipelineContext::UpdateWindowBlurRegion(
2897     int32_t id, RRect rRect, float progress, WindowBlurStyle style, const std::vector<RRect>& coords)
2898 {
2899     CHECK_RUN_ON(UI);
2900     auto pos = windowBlurRegions_.find(id);
2901     if (pos != windowBlurRegions_.end()) {
2902         const auto& old = pos->second;
2903         if (NearEqual(progress, old.progress_) && rRect == old.innerRect_ && style == old.style_) {
2904             return;
2905         }
2906     }
2907     windowBlurRegions_[id] = { .progress_ = progress, .style_ = style, .innerRect_ = rRect, .coords_ = coords };
2908     needWindowBlurRegionRefresh_ = true;
2909 }
2910 
ClearWindowBlurRegion(int32_t id)2911 void PipelineContext::ClearWindowBlurRegion(int32_t id)
2912 {
2913     CHECK_RUN_ON(UI);
2914     auto pos = windowBlurRegions_.find(id);
2915     if (pos != windowBlurRegions_.end()) {
2916         windowBlurRegions_.erase(pos);
2917         needWindowBlurRegionRefresh_ = true;
2918     }
2919 }
2920 
InitDragListener()2921 void PipelineContext::InitDragListener()
2922 {
2923     if (!initDragEventListener_) {
2924         return;
2925     }
2926     initDragEventListener_();
2927 }
2928 
StartSystemDrag(const std::string & str,const RefPtr<PixelMap> & pixmap)2929 void PipelineContext::StartSystemDrag(const std::string& str, const RefPtr<PixelMap>& pixmap)
2930 {
2931     if (!dragEventHandler_) {
2932         return;
2933     }
2934     dragEventHandler_(str, pixmap);
2935 }
2936 
SetPreTargetRenderNode(const RefPtr<DragDropEvent> & preDragDropNode)2937 void PipelineContext::SetPreTargetRenderNode(const RefPtr<DragDropEvent>& preDragDropNode)
2938 {
2939     preTargetRenderNode_ = preDragDropNode;
2940 }
2941 
GetPreTargetRenderNode() const2942 const RefPtr<DragDropEvent>& PipelineContext::GetPreTargetRenderNode() const
2943 {
2944     return preTargetRenderNode_;
2945 }
2946 
SetInitRenderNode(const RefPtr<RenderNode> & initRenderNode)2947 void PipelineContext::SetInitRenderNode(const RefPtr<RenderNode>& initRenderNode)
2948 {
2949     initRenderNode_ = initRenderNode;
2950 }
2951 
GetInitRenderNode() const2952 const RefPtr<RenderNode>& PipelineContext::GetInitRenderNode() const
2953 {
2954     return initRenderNode_;
2955 }
2956 
ProcessDragEvent(const RefPtr<RenderNode> & renderNode,const RefPtr<DragEvent> & event,const Point & globalPoint)2957 void PipelineContext::ProcessDragEvent(
2958     const RefPtr<RenderNode>& renderNode, const RefPtr<DragEvent>& event, const Point& globalPoint)
2959 {
2960     auto targetDragDropNode =
2961         AceType::DynamicCast<DragDropEvent>(renderNode->FindDropChild(globalPoint, globalPoint - pageOffset_));
2962     auto initDragDropNode = AceType::DynamicCast<DragDropEvent>(GetInitRenderNode());
2963     auto extraParams = JsonUtil::Create(true);
2964     extraParams->Put("customDragInfo", customDragInfo_.c_str());
2965     extraParams->Put("selectedText", selectedText_.c_str());
2966     extraParams->Put("imageSrc", imageSrc_.c_str());
2967     auto info = GestureEvent();
2968     info.SetGlobalPoint(globalPoint);
2969     auto preTargetDragDropNode = GetPreTargetRenderNode();
2970     if (targetDragDropNode == preTargetDragDropNode) {
2971         if (targetDragDropNode && targetDragDropNode->GetOnDragMove()) {
2972             auto renderList = renderNode->FindChildNodeOfClass<V2::RenderList>(globalPoint, globalPoint);
2973             if (renderList) {
2974                 insertIndex_ = renderList->CalculateInsertIndex(renderList, info, selectedItemSize_);
2975             }
2976 
2977             if (insertIndex_ == RenderNode::DEFAULT_INDEX) {
2978                 (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
2979                 return;
2980             }
2981 
2982             if (targetDragDropNode != initDragDropNode) {
2983                 extraParams->Put("selectedIndex", -1);
2984             } else {
2985                 extraParams->Put("selectedIndex", selectedIndex_);
2986             }
2987 
2988             extraParams->Put("insertIndex", insertIndex_);
2989             (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
2990         }
2991     } else {
2992         if (preTargetDragDropNode && preTargetDragDropNode->GetOnDragLeave()) {
2993             (preTargetDragDropNode->GetOnDragLeave())(event, extraParams->ToString());
2994         }
2995 
2996         if (targetDragDropNode && targetDragDropNode->GetOnDragEnter()) {
2997             (targetDragDropNode->GetOnDragEnter())(event, extraParams->ToString());
2998         }
2999 
3000         SetPreTargetRenderNode(targetDragDropNode);
3001     }
3002 }
3003 
ProcessDragEventEnd(const RefPtr<RenderNode> & renderNode,const RefPtr<DragEvent> & event,const Point & globalPoint)3004 void PipelineContext::ProcessDragEventEnd(
3005     const RefPtr<RenderNode>& renderNode, const RefPtr<DragEvent>& event, const Point& globalPoint)
3006 {
3007     auto targetDragDropNode =
3008         AceType::DynamicCast<DragDropEvent>(renderNode->FindDropChild(globalPoint, globalPoint - pageOffset_));
3009     auto initDragDropNode = AceType::DynamicCast<DragDropEvent>(GetInitRenderNode());
3010     auto extraParams = JsonUtil::Create(true);
3011     extraParams->Put("customDragInfo", customDragInfo_.c_str());
3012     extraParams->Put("selectedText", selectedText_.c_str());
3013     extraParams->Put("imageSrc", imageSrc_.c_str());
3014     auto info = GestureEvent();
3015     info.SetGlobalPoint(globalPoint);
3016     auto preTargetDragDropNode = GetPreTargetRenderNode();
3017 
3018     auto textfield = renderNode->FindChildNodeOfClass<RenderTextField>(globalPoint, globalPoint);
3019     if (textfield) {
3020         auto value = textfield->GetEditingValue();
3021         value.Append(selectedText_);
3022         textfield->SetEditingValue(std::move(value));
3023     }
3024 
3025     if (targetDragDropNode && targetDragDropNode->GetOnDrop()) {
3026         auto renderList = renderNode->FindChildNodeOfClass<V2::RenderList>(globalPoint, globalPoint);
3027         if (renderList) {
3028             insertIndex_ = renderList->CalculateInsertIndex(renderList, info, selectedItemSize_);
3029         }
3030 
3031         if (insertIndex_ == RenderNode::DEFAULT_INDEX) {
3032             (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
3033             SetPreTargetRenderNode(nullptr);
3034             SetInitRenderNode(nullptr);
3035             return;
3036         }
3037 
3038         if (targetDragDropNode != initDragDropNode) {
3039             extraParams->Put("selectedIndex", -1);
3040         } else {
3041             extraParams->Put("selectedIndex", selectedIndex_);
3042         }
3043 
3044         extraParams->Put("insertIndex", insertIndex_);
3045         (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
3046     }
3047 
3048     if (initDragDropNode && initDragDropNode->GetOnDrop()) {
3049         (initDragDropNode->GetOnDrop())(event, extraParams->ToString());
3050     }
3051 
3052     SetPreTargetRenderNode(nullptr);
3053     SetInitRenderNode(nullptr);
3054 }
3055 
OnDragEvent(const PointerEvent & pointerEvent,DragEventAction action,const RefPtr<NG::FrameNode> & node)3056 void PipelineContext::OnDragEvent(const PointerEvent& pointerEvent, DragEventAction action,
3057     const RefPtr<NG::FrameNode>& node)
3058 {
3059     if (!clipboard_) {
3060         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(GetTaskExecutor());
3061     }
3062 
3063     if (!clipboardCallback_) {
3064         auto callback = [weakPipelineContext = WeakClaim(this)](const std::string& data) {
3065             auto pipelineContext = weakPipelineContext.Upgrade();
3066             if (pipelineContext) {
3067                 auto json = JsonUtil::ParseJsonString(data);
3068                 auto newData = JsonUtil::ParseJsonString(json->GetString("newData"));
3069                 pipelineContext->selectedItemSize_.SetWidth(newData->GetDouble("width"));
3070                 pipelineContext->selectedItemSize_.SetHeight(newData->GetDouble("height"));
3071                 pipelineContext->selectedIndex_ = newData->GetInt("selectedIndex");
3072                 pipelineContext->customDragInfo_ = newData->GetString("customDragInfo");
3073                 pipelineContext->selectedText_ = newData->GetString("selectedText");
3074                 pipelineContext->imageSrc_ = newData->GetString("imageSrc");
3075             }
3076         };
3077         clipboardCallback_ = callback;
3078     }
3079 
3080     if (clipboardCallback_) {
3081         clipboard_->GetData(clipboardCallback_);
3082     }
3083 
3084     auto renderNode = GetLastPageRender();
3085     if (!renderNode) {
3086         LOGE("PipelineContext::OnDragEvent renderNode is null.");
3087         return;
3088     }
3089 
3090     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
3091     event->SetX(ConvertPxToVp(Dimension(pointerEvent.x, DimensionUnit::PX)));
3092     event->SetY(ConvertPxToVp(Dimension(pointerEvent.y, DimensionUnit::PX)));
3093 
3094     Point globalPoint(pointerEvent.x, pointerEvent.y);
3095 
3096     if (action == DragEventAction::DRAG_EVENT_START) {
3097         pageOffset_ = GetPageRect().GetOffset();
3098     }
3099 
3100     event->SetPressedKeyCodes(pointerEvent.pressedKeyCodes_);
3101 
3102     if (action != DragEventAction::DRAG_EVENT_END) {
3103         ProcessDragEvent(renderNode, event, globalPoint);
3104     } else {
3105         ProcessDragEventEnd(renderNode, event, globalPoint);
3106     }
3107 }
3108 
FlushWindowBlur()3109 void PipelineContext::FlushWindowBlur()
3110 {
3111     CHECK_RUN_ON(UI);
3112     ACE_FUNCTION_TRACK();
3113 
3114     if (!updateWindowBlurRegionHandler_) {
3115         return;
3116     }
3117 
3118     if (IsJsPlugin()) {
3119         return;
3120     }
3121 
3122     if (IsJsCard()) {
3123         if (!needWindowBlurRegionRefresh_) {
3124             return;
3125         }
3126         std::vector<std::vector<float>> blurRectangles;
3127         if (!windowBlurRegions_.empty()) {
3128             blurRectangles.push_back(std::vector<float> { 1 });
3129         }
3130         updateWindowBlurRegionHandler_(blurRectangles);
3131         needWindowBlurRegionRefresh_ = false;
3132         return;
3133     }
3134     if (!rootElement_) {
3135         LOGE("root element is null");
3136         return;
3137     }
3138     auto renderNode = rootElement_->GetRenderNode();
3139     if (!renderNode) {
3140         LOGE("get renderNode failed");
3141         return;
3142     }
3143 
3144     if (!windowBlurRegions_.empty()) {
3145         renderNode->WindowBlurTest();
3146     }
3147 
3148     float scale = GetViewScale();
3149     if (needWindowBlurRegionRefresh_) {
3150         std::vector<std::vector<float>> blurRectangles;
3151         for (auto& region : windowBlurRegions_) {
3152             std::vector<float> rectArray;
3153             // progress
3154             rectArray.push_back(region.second.progress_);
3155             // style
3156             rectArray.push_back(static_cast<float>(region.second.style_));
3157             for (auto item : region.second.coords_) {
3158                 item.ApplyScaleAndRound(scale);
3159                 const Rect& rect = item.GetRect();
3160                 // rect
3161                 rectArray.push_back(static_cast<float>(rect.Left()));
3162                 rectArray.push_back(static_cast<float>(rect.Top()));
3163                 rectArray.push_back(static_cast<float>(rect.Right()));
3164                 rectArray.push_back(static_cast<float>(rect.Bottom()));
3165                 const Corner& radius = item.GetCorner();
3166                 // roundX roundY
3167                 rectArray.push_back(static_cast<float>(radius.topLeftRadius.GetX().Value()));
3168                 rectArray.push_back(static_cast<float>(radius.topLeftRadius.GetY().Value()));
3169             }
3170             blurRectangles.push_back(rectArray);
3171         }
3172         updateWindowBlurRegionHandler_(blurRectangles);
3173         needWindowBlurRegionRefresh_ = false;
3174     }
3175     if (updateWindowBlurDrawOpHandler_) {
3176         updateWindowBlurDrawOpHandler_();
3177     }
3178 }
3179 
MakeThreadStuck(const std::vector<std::string> & params) const3180 void PipelineContext::MakeThreadStuck(const std::vector<std::string>& params) const
3181 {
3182     int32_t time = StringUtils::StringToInt(params[2]);
3183     if (time < 0 || (params[1] != JS_THREAD_NAME && params[1] != UI_THREAD_NAME)) {
3184         DumpLog::GetInstance().Print("Params illegal, please check!");
3185         return;
3186     }
3187     DumpLog::GetInstance().Print(params[1] + " thread will stuck for " + params[2] + " seconds.");
3188     if (params[1] == JS_THREAD_NAME) {
3189         taskExecutor_->PostTask([time] { ThreadStuckTask(time); }, TaskExecutor::TaskType::JS, "ArkUIThreadStuck");
3190     } else {
3191         taskExecutor_->PostTask([time] { ThreadStuckTask(time); }, TaskExecutor::TaskType::UI, "ArkUIThreadStuck");
3192     }
3193 }
3194 
SetIsKeyEvent(bool isKeyEvent)3195 void PipelineContext::SetIsKeyEvent(bool isKeyEvent)
3196 {
3197     if (focusAnimationManager_) {
3198         isKeyEvent_ = isKeyEvent;
3199         focusAnimationManager_->SetIsKeyEvent(isKeyEvent_);
3200     }
3201 }
3202 
NavigatePage(uint8_t type,const PageTarget & target,const std::string & params)3203 void PipelineContext::NavigatePage(uint8_t type, const PageTarget& target, const std::string& params)
3204 {
3205     auto frontend = weakFrontend_.Upgrade();
3206     if (!frontend) {
3207         LOGE("frontend is nullptr");
3208         return;
3209     }
3210     frontend->NavigatePage(type, target, params);
3211 }
3212 
AddKeyFrame(float fraction,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback)3213 void PipelineContext::AddKeyFrame(
3214     float fraction, const RefPtr<Curve>& curve, const std::function<void()>& propertyCallback)
3215 {
3216     if (propertyCallback == nullptr) {
3217         LOGE("failed to add key frame, property callback is null!");
3218         return;
3219     }
3220 
3221     pendingImplicitLayout_.push(false);
3222     auto propertyChangeCallback = [weak = AceType::WeakClaim(this), callback = propertyCallback,
3223                                       id = Container::CurrentId()]() {
3224         ContainerScope scope(id);
3225         auto context = weak.Upgrade();
3226         if (context == nullptr) {
3227             LOGE("failed to add key frame, context is null!");
3228             return;
3229         }
3230 
3231         callback();
3232         if (context->pendingImplicitLayout_.top()) {
3233             context->FlushLayout();
3234         }
3235     };
3236     pendingImplicitLayout_.pop();
3237 
3238 #ifdef ENABLE_ROSEN_BACKEND
3239     RSNode::AddKeyFrame(fraction, NativeCurveHelper::ToNativeCurve(curve), propertyChangeCallback);
3240 #endif
3241 }
3242 
AddKeyFrame(float fraction,const std::function<void ()> & propertyCallback)3243 void PipelineContext::AddKeyFrame(float fraction, const std::function<void()>& propertyCallback)
3244 {
3245     if (propertyCallback == nullptr) {
3246         LOGE("failed to add key frame, property callback is null!");
3247         return;
3248     }
3249 
3250     pendingImplicitLayout_.push(false);
3251     auto propertyChangeCallback = [weak = AceType::WeakClaim(this), callback = propertyCallback,
3252                                       id = Container::CurrentId()]() {
3253         ContainerScope scope(id);
3254         auto context = weak.Upgrade();
3255         if (context == nullptr) {
3256             LOGE("failed to add key frame, context is null!");
3257             return;
3258         }
3259 
3260         callback();
3261         if (context->pendingImplicitLayout_.top()) {
3262             context->FlushLayout();
3263         }
3264     };
3265     pendingImplicitLayout_.pop();
3266 
3267 #ifdef ENABLE_ROSEN_BACKEND
3268     RSNode::AddKeyFrame(fraction, propertyChangeCallback);
3269 #endif
3270 }
3271 
SaveExplicitAnimationOption(const AnimationOption & option)3272 void PipelineContext::SaveExplicitAnimationOption(const AnimationOption& option)
3273 {
3274     explicitAnimationOption_ = option;
3275 }
3276 
CreateExplicitAnimator(const std::function<void ()> & onFinishEvent)3277 void PipelineContext::CreateExplicitAnimator(const std::function<void()>& onFinishEvent)
3278 {
3279     if (!onFinishEvent) {
3280         return;
3281     }
3282     auto animator = CREATE_ANIMATOR(AceType::WeakClaim(this));
3283     animator->AddStopListener([onFinishEvent, weakContext = AceType::WeakClaim(this), id = animator->GetId()] {
3284         auto context = weakContext.Upgrade();
3285         if (!context) {
3286             return;
3287         }
3288         context->PostAsyncEvent(onFinishEvent, "ArkUIAnimatorFinishEvent");
3289         context->explicitAnimators_.erase(id);
3290     });
3291     animator->SetDuration(explicitAnimationOption_.GetDuration());
3292     animator->SetStartDelay(explicitAnimationOption_.GetDelay());
3293     animator->SetIteration(explicitAnimationOption_.GetIteration());
3294     animator->SetTempo(explicitAnimationOption_.GetTempo());
3295     animator->SetAnimationDirection(explicitAnimationOption_.GetAnimationDirection());
3296     animator->SetFillMode(FillMode::FORWARDS);
3297     animator->Play();
3298     explicitAnimators_.emplace(animator->GetId(), animator);
3299 }
3300 
ClearExplicitAnimationOption()3301 void PipelineContext::ClearExplicitAnimationOption()
3302 {
3303     explicitAnimationOption_ = AnimationOption();
3304 }
3305 
GetExplicitAnimationOption() const3306 AnimationOption PipelineContext::GetExplicitAnimationOption() const
3307 {
3308     return explicitAnimationOption_;
3309 }
3310 
GetIsDeclarative() const3311 bool PipelineContext::GetIsDeclarative() const
3312 {
3313     RefPtr<Frontend> front = GetFrontend();
3314     if (front) {
3315         return (front->GetType() == FrontendType::DECLARATIVE_JS ||
3316                 front->GetType() == FrontendType::JS_PLUGIN ||
3317                 front->GetType() == FrontendType::DECLARATIVE_CJ);
3318     }
3319     return false;
3320 }
3321 
SetForbidPlatformQuit(bool forbidPlatformQuit)3322 void PipelineContext::SetForbidPlatformQuit(bool forbidPlatformQuit)
3323 {
3324     forbidPlatformQuit_ = forbidPlatformQuit;
3325     auto stageElement = GetStageElement();
3326     if (!stageElement) {
3327         LOGE("Stage is null.");
3328         return;
3329     }
3330     auto renderStage = AceType::DynamicCast<RenderStage>(stageElement->GetRenderNode());
3331     if (!renderStage) {
3332         LOGE("RenderStage is null.");
3333         return;
3334     }
3335     renderStage->SetForbidSwipeToRight(forbidPlatformQuit_);
3336 }
3337 
AddLayoutTransitionNode(const RefPtr<RenderNode> & node)3338 void PipelineContext::AddLayoutTransitionNode(const RefPtr<RenderNode>& node)
3339 {
3340     CHECK_RUN_ON(UI);
3341     layoutTransitionNodeSet_.insert(node);
3342 }
3343 
AddAlignDeclarationNode(const RefPtr<RenderNode> & node)3344 void PipelineContext::AddAlignDeclarationNode(const RefPtr<RenderNode>& node)
3345 {
3346     CHECK_RUN_ON(UI);
3347     alignDeclarationNodeList_.emplace_front(node);
3348 }
3349 
GetAlignDeclarationNodeList()3350 std::list<RefPtr<RenderNode>>& PipelineContext::GetAlignDeclarationNodeList()
3351 {
3352     CHECK_RUN_ON(UI);
3353     return alignDeclarationNodeList_;
3354 }
3355 
AddScreenOnEvent(std::function<void ()> && func)3356 void PipelineContext::AddScreenOnEvent(std::function<void()>&& func)
3357 {
3358     taskExecutor_->PostTask(
3359         [wp = WeakClaim(this), screenOnFunc = std::move(func)]() mutable {
3360             auto pipeline = wp.Upgrade();
3361             if (pipeline && pipeline->screenOnCallback_) {
3362                 pipeline->screenOnCallback_(std::move(screenOnFunc));
3363             }
3364         },
3365         TaskExecutor::TaskType::PLATFORM, "ArkUIScreenOnEvent");
3366 }
3367 
AddScreenOffEvent(std::function<void ()> && func)3368 void PipelineContext::AddScreenOffEvent(std::function<void()>&& func)
3369 {
3370     taskExecutor_->PostTask(
3371         [wp = WeakClaim(this), screenOffFunc = std::move(func)]() mutable {
3372             auto pipeline = wp.Upgrade();
3373             if (pipeline && pipeline->screenOffCallback_) {
3374                 pipeline->screenOffCallback_(std::move(screenOffFunc));
3375             }
3376         },
3377         TaskExecutor::TaskType::PLATFORM, "ArkUIScreenOffEvent");
3378 }
3379 
IsWindowInScreen()3380 bool PipelineContext::IsWindowInScreen()
3381 {
3382     if (queryIfWindowInScreenCallback_) {
3383         // We post an async task to do async query to avoid thread deadlock between UI thread and Platform thread
3384         taskExecutor_->PostTask(
3385             [wp = WeakClaim(this)] {
3386                 auto pipeline = wp.Upgrade();
3387                 if (!pipeline) {
3388                     return;
3389                 }
3390                 pipeline->queryIfWindowInScreenCallback_();
3391             },
3392             TaskExecutor::TaskType::PLATFORM, "ArkUIQueryIfWindowInScreen");
3393     }
3394     // Note that the result is not real-time result but the result from previous query
3395     return isWindowInScreen_;
3396 }
3397 
NotifyOnPreDraw()3398 void PipelineContext::NotifyOnPreDraw()
3399 {
3400     decltype(nodesToNotifyOnPreDraw_) nodesToNotifyOnPreDraw(std::move(nodesToNotifyOnPreDraw_));
3401     for (const auto& node : nodesToNotifyOnPreDraw) {
3402         node->OnPreDraw();
3403     }
3404 }
3405 
AddNodesToNotifyOnPreDraw(const RefPtr<RenderNode> & renderNode)3406 void PipelineContext::AddNodesToNotifyOnPreDraw(const RefPtr<RenderNode>& renderNode)
3407 {
3408     nodesToNotifyOnPreDraw_.emplace(renderNode);
3409 }
3410 
UpdateNodesNeedDrawOnPixelMap()3411 void PipelineContext::UpdateNodesNeedDrawOnPixelMap()
3412 {
3413     for (const auto& dirtyNode : dirtyRenderNodes_) {
3414         SearchNodesNeedDrawOnPixelMap(dirtyNode);
3415     }
3416     for (const auto& dirtyNode : dirtyRenderNodesInOverlay_) {
3417         SearchNodesNeedDrawOnPixelMap(dirtyNode);
3418     }
3419 }
3420 
SearchNodesNeedDrawOnPixelMap(const RefPtr<RenderNode> & renderNode)3421 void PipelineContext::SearchNodesNeedDrawOnPixelMap(const RefPtr<RenderNode>& renderNode)
3422 {
3423     auto parent = renderNode;
3424     while (parent) {
3425         auto box = AceType::DynamicCast<RenderBox>(parent);
3426         if (box && box->GetPixelMap()) {
3427             nodesNeedDrawOnPixelMap_.emplace(parent);
3428         }
3429         parent = parent->GetParent().Upgrade();
3430     }
3431 }
3432 
NotifyDrawOnPixelMap()3433 void PipelineContext::NotifyDrawOnPixelMap()
3434 {
3435     decltype(nodesNeedDrawOnPixelMap_) nodesNeedDrawOnPixelMap(std::move(nodesNeedDrawOnPixelMap_));
3436     for (const auto& node : nodesNeedDrawOnPixelMap) {
3437         auto box = AceType::DynamicCast<RenderBox>(node);
3438         if (box) {
3439             box->DrawOnPixelMap();
3440         }
3441     }
3442 }
3443 
PushVisibleCallback(NodeId id,double ratio,std::function<void (bool,double)> && func)3444 void PipelineContext::PushVisibleCallback(NodeId id, double ratio, std::function<void(bool, double)>&& func)
3445 {
3446     auto accessibilityManager = GetAccessibilityManager();
3447     if (!accessibilityManager) {
3448         return;
3449     }
3450     accessibilityManager->AddVisibleChangeNode(id, ratio, func);
3451 }
3452 
AddVisibleAreaChangeNode(const ComposeId & nodeId,double ratio,const VisibleRatioCallback & callback)3453 void PipelineContext::AddVisibleAreaChangeNode(
3454     const ComposeId& nodeId, double ratio, const VisibleRatioCallback& callback)
3455 {
3456     VisibleCallbackInfo info;
3457     info.callback = callback;
3458     info.visibleRatio = ratio;
3459     info.isCurrentVisible = false;
3460     auto iter = visibleAreaChangeNodes_.find(nodeId);
3461     if (iter != visibleAreaChangeNodes_.end()) {
3462         auto& callbackList = iter->second;
3463         callbackList.emplace_back(info);
3464     } else {
3465         std::list<VisibleCallbackInfo> callbackList;
3466         callbackList.emplace_back(info);
3467         visibleAreaChangeNodes_[nodeId] = callbackList;
3468     }
3469 }
3470 
RemoveVisibleChangeNode(NodeId id)3471 void PipelineContext::RemoveVisibleChangeNode(NodeId id)
3472 {
3473     auto accessibilityManager = GetAccessibilityManager();
3474     if (!accessibilityManager) {
3475         return;
3476     }
3477     accessibilityManager->RemoveVisibleChangeNode(id);
3478 }
3479 
IsVisibleChangeNodeExists(NodeId index) const3480 bool PipelineContext::IsVisibleChangeNodeExists(NodeId index) const
3481 {
3482     auto accessibilityManager = GetAccessibilityManager();
3483     if (!accessibilityManager) {
3484         return false;
3485     }
3486     return accessibilityManager->IsVisibleChangeNodeExists(index);
3487 }
3488 
SetRSUIDirector(std::shared_ptr<OHOS::Rosen::RSUIDirector> rsUIDirector)3489 void PipelineContext::SetRSUIDirector(std::shared_ptr<OHOS::Rosen::RSUIDirector> rsUIDirector)
3490 {
3491 #ifdef ENABLE_ROSEN_BACKEND
3492     rsUIDirector_ = rsUIDirector;
3493 #endif
3494 }
3495 
GetRSUIDirector()3496 std::shared_ptr<OHOS::Rosen::RSUIDirector> PipelineContext::GetRSUIDirector()
3497 {
3498 #ifdef ENABLE_ROSEN_BACKEND
3499     return rsUIDirector_;
3500 #else
3501     return nullptr;
3502 #endif
3503 }
3504 
StoreNode(int32_t restoreId,const WeakPtr<RenderElement> & node)3505 void PipelineContext::StoreNode(int32_t restoreId, const WeakPtr<RenderElement>& node)
3506 {
3507     auto ret = storeNode_.try_emplace(restoreId, node);
3508     if (!ret.second) {
3509         LOGW("store restore node fail, id = %{public}d", restoreId);
3510         storeNode_[restoreId] = node;
3511     }
3512 }
3513 
GetStoredNodeInfo()3514 std::unique_ptr<JsonValue> PipelineContext::GetStoredNodeInfo()
3515 {
3516     auto jsonNodeInfo = JsonUtil::Create(true);
3517     auto iter = storeNode_.begin();
3518     while (iter != storeNode_.end()) {
3519         auto RenderElement = (iter->second).Upgrade();
3520         if (RenderElement) {
3521             std::string info = RenderElement->ProvideRestoreInfo();
3522             if (!info.empty()) {
3523                 jsonNodeInfo->Put(std::to_string(iter->first).c_str(), info.c_str());
3524             }
3525         }
3526         ++iter;
3527     }
3528     return jsonNodeInfo;
3529 }
3530 
RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)3531 void PipelineContext::RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)
3532 {
3533     if (!nodeInfo->IsValid() || !nodeInfo->IsObject()) {
3534         LOGW("restore nodeInfo is invalid");
3535     }
3536     auto child = nodeInfo->GetChild();
3537     while (child->IsValid()) {
3538         auto key = child->GetKey();
3539         auto value = child->GetString();
3540         int vital = std::atoi(key.c_str());
3541         if (vital == 0) {
3542             LOGE("input %{public}s can not be converted to number.", key.c_str());
3543         }
3544         restoreNodeInfo_.try_emplace(vital, value);
3545         child = child->GetNext();
3546     }
3547 }
3548 
GetRestoreInfo(int32_t restoreId)3549 std::string PipelineContext::GetRestoreInfo(int32_t restoreId)
3550 {
3551     auto iter = restoreNodeInfo_.find(restoreId);
3552     if (iter != restoreNodeInfo_.end()) {
3553         std::string restoreNodeInfo = iter->second;
3554         restoreNodeInfo_.erase(iter);
3555         return restoreNodeInfo;
3556     }
3557     return "";
3558 }
3559 
SetSinglePageId(int32_t pageId)3560 void PipelineContext::SetSinglePageId(int32_t pageId)
3561 {
3562     auto stageElement = GetStageElement();
3563     if (!stageElement) {
3564         LOGE("Get stage element failed!");
3565         return;
3566     }
3567 
3568     stageElement->SetSinglePageId(pageId);
3569 }
3570 
SetAppTitle(const std::string & title)3571 void PipelineContext::SetAppTitle(const std::string& title)
3572 {
3573     CHECK_NULL_VOID(rootElement_);
3574     auto containerModalElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
3575     CHECK_NULL_VOID(containerModalElement);
3576     containerModalElement->SetAppTitle(title);
3577 }
3578 
SetAppIcon(const RefPtr<PixelMap> & icon)3579 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
3580 {
3581     CHECK_NULL_VOID(rootElement_);
3582     auto containerModalElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
3583     CHECK_NULL_VOID(containerModalElement);
3584     containerModalElement->SetAppIcon(icon);
3585 }
3586 
3587 } // namespace OHOS::Ace
3588