• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/pipeline/pipeline_context.h"
17 #include <cstdlib>
18 #include "base/utils/utils.h"
19 
20 #ifdef ENABLE_ROSEN_BACKEND
21 #include "render_service_base/include/platform/common/rs_system_properties.h"
22 #include "render_service_client/core/ui/rs_node.h"
23 #include "render_service_client/core/ui/rs_surface_node.h"
24 #include "render_service_client/core/ui/rs_ui_director.h"
25 #include "render_service_client/core/transaction/rs_transaction.h"
26 
27 #include "core/animation/native_curve_helper.h"
28 #endif
29 
30 #include "base/log/ace_tracker.h"
31 #include "base/log/dump_log.h"
32 #include "base/log/event_report.h"
33 #include "base/ressched/ressched_report.h"
34 #include "core/animation/card_transition_controller.h"
35 #include "core/animation/shared_transition_controller.h"
36 #include "core/common/font_manager.h"
37 #include "core/common/layout_inspector.h"
38 #include "core/common/text_field_manager.h"
39 #include "core/components/container_modal/container_modal_element.h"
40 #include "core/components/dialog/dialog_component.h"
41 #include "core/components/dialog_modal/dialog_modal_component.h"
42 #include "core/components/dialog_modal/dialog_modal_element.h"
43 #include "core/components/focus_animation/render_focus_animation.h"
44 #include "core/components/overlay/overlay_component.h"
45 #include "core/components/root/render_root.h"
46 #include "core/components/root/root_component.h"
47 #include "core/components/root/root_element.h"
48 #include "core/components/select_popup/select_popup_component.h"
49 #include "core/components/semi_modal/semi_modal_component.h"
50 #include "core/components/semi_modal/semi_modal_element.h"
51 #include "core/components/semi_modal/semi_modal_theme.h"
52 #include "core/components/stage/stage_component.h"
53 #include "core/components/theme/app_theme.h"
54 #include "core/components_v2/inspector/shape_composed_element.h"
55 #include "core/components_v2/list/render_list.h"
56 #include "core/pipeline/base/factories/flutter_render_factory.h"
57 
58 namespace OHOS::Ace {
59 namespace {
60 
61 constexpr int64_t SEC_TO_NANOSEC = 1000000000;
62 constexpr char JS_THREAD_NAME[] = "JS";
63 constexpr char UI_THREAD_NAME[] = "UI";
64 constexpr uint32_t DEFAULT_MODAL_COLOR = 0x00000000;
65 constexpr float ZOOM_DISTANCE_DEFAULT = 50.0;
66 constexpr float ZOOM_DISTANCE_MOVE_PER_WHEEL = 5.0;
67 constexpr int32_t FLUSH_RELOAD_TRANSITION_DURATION_MS = 400;
68 
__anon0fa1b4e10202() 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 
OnNonPointerEvent(const NonPointerEvent & nonPointerEvent)1639 bool PipelineContext::OnNonPointerEvent(const NonPointerEvent& nonPointerEvent)
1640 {
1641     CHECK_RUN_ON(UI);
1642     if (nonPointerEvent.eventType != UIInputEventType::KEY) {
1643         return false;
1644     }
1645     const auto& event = static_cast<const KeyEvent&>(nonPointerEvent);
1646     if (!rootElement_) {
1647         LOGE("the root element is nullptr");
1648         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
1649         return false;
1650     }
1651     rootElement_->HandleSpecifiedKey(event);
1652 
1653     SetShortcutKey(event);
1654 
1655     pressedKeyCodes = event.pressedCodes;
1656     isKeyCtrlPressed_ = !pressedKeyCodes.empty() && (pressedKeyCodes.back() == KeyCode::KEY_CTRL_LEFT ||
1657                                                         pressedKeyCodes.back() == KeyCode::KEY_CTRL_RIGHT);
1658     if ((event.code == KeyCode::KEY_CTRL_LEFT || event.code == KeyCode::KEY_CTRL_RIGHT) &&
1659         event.action == KeyAction::UP) {
1660         if (isOnScrollZoomEvent_) {
1661             zoomEventA_.type = TouchType::UP;
1662             zoomEventB_.type = TouchType::UP;
1663             LOGI("Send TouchEventA(%{public}f, %{public}f, %{public}zu)", zoomEventA_.x, zoomEventA_.y,
1664                 zoomEventA_.type);
1665             OnTouchEvent(zoomEventA_);
1666             LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y,
1667                 zoomEventB_.type);
1668             OnTouchEvent(zoomEventB_);
1669             isOnScrollZoomEvent_ = false;
1670         }
1671     }
1672 
1673     if (event.code == KeyCode::KEY_TAB && event.action == KeyAction::DOWN && !isTabKeyPressed_) {
1674         isTabKeyPressed_ = true;
1675     }
1676     CHECK_NULL_RETURN(rootElement_, false);
1677     auto lastPage = GetLastPage();
1678     bool isHandleByTabIndex = false;
1679     if (lastPage) {
1680         isHandleByTabIndex = rootElement_->HandleFocusByTabIndex(event, lastPage);
1681     } else {
1682         isHandleByTabIndex = rootElement_->HandleFocusByTabIndex(event, rootElement_);
1683     }
1684     if (isHandleByTabIndex) {
1685         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "Tab index focus system handled this event");
1686         return true;
1687     }
1688     if (rootElement_->HandleKeyEvent(event)) {
1689         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "Default focus system handled this event");
1690         return true;
1691     }
1692     return false;
1693 }
1694 
RequestDefaultFocus()1695 bool PipelineContext::RequestDefaultFocus()
1696 {
1697     RefPtr<FocusNode> defaultFocusNode;
1698     std::string mainNodeName;
1699     auto curPageElement = GetLastPage();
1700     if (curPageElement) {
1701         if (curPageElement->IsDefaultHasFocused()) {
1702             return false;
1703         }
1704         curPageElement->SetIsDefaultHasFocused(true);
1705         defaultFocusNode = curPageElement->GetChildDefaultFocusNode();
1706         mainNodeName = std::string(AceType::TypeName(curPageElement));
1707     } else if (rootElement_) {
1708         if (rootElement_->IsDefaultHasFocused()) {
1709             return false;
1710         }
1711         rootElement_->SetIsDefaultHasFocused(true);
1712         defaultFocusNode = rootElement_->GetChildDefaultFocusNode();
1713         mainNodeName = std::string(AceType::TypeName(rootElement_));
1714     } else {
1715         LOGE("RequestDefaultFocus: rootElement or pageElement is nullptr!");
1716         return false;
1717     }
1718     if (!defaultFocusNode) {
1719         return false;
1720     }
1721     if (!defaultFocusNode->IsFocusableWholePath()) {
1722         return false;
1723     }
1724     return defaultFocusNode->RequestFocusImmediately();
1725 }
1726 
SetShortcutKey(const KeyEvent & event)1727 void PipelineContext::SetShortcutKey(const KeyEvent& event)
1728 {
1729     if (event.action == KeyAction::DOWN) {
1730         auto codeValue = static_cast<int32_t>(event.code);
1731         if (codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_LEFT) ||
1732             codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_RIGHT)) {
1733             MarkIsShiftDown(true);
1734         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_LEFT) ||
1735                    codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_RIGHT)) {
1736             MarkIsCtrlDown(true);
1737         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_A)) {
1738             MarkIsKeyboardA(true);
1739             if (subscribeCtrlA_) {
1740                 subscribeCtrlA_();
1741             }
1742         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_C)) {
1743             if (textOverlayManager_) {
1744                 textOverlayManager_->HandleCtrlC();
1745             }
1746         }
1747     } else if (event.action == KeyAction::UP) {
1748         auto codeValue = static_cast<int32_t>(event.code);
1749         if (codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_LEFT) ||
1750             codeValue == static_cast<int32_t>(KeyCode::KEY_SHIFT_RIGHT)) {
1751             MarkIsShiftDown(false);
1752         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_LEFT) ||
1753                    codeValue == static_cast<int32_t>(KeyCode::KEY_CTRL_RIGHT)) {
1754             MarkIsCtrlDown(false);
1755         } else if (codeValue == static_cast<int32_t>(KeyCode::KEY_A)) {
1756             MarkIsKeyboardA(false);
1757         }
1758     }
1759 }
1760 
OnMouseEvent(const MouseEvent & event)1761 void PipelineContext::OnMouseEvent(const MouseEvent& event)
1762 {
1763     CHECK_RUN_ON(UI);
1764 
1765     if ((event.action == MouseAction::RELEASE || event.action == MouseAction::PRESS ||
1766             event.action == MouseAction::MOVE) &&
1767         (event.button == MouseButton::LEFT_BUTTON || event.pressedButtons == MOUSE_PRESS_LEFT)) {
1768         auto touchPoint = event.CreateTouchPoint();
1769         OnTouchEvent(touchPoint);
1770     }
1771 
1772     CHECK_NULL_VOID(rootElement_);
1773     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1774     if (event.action == MouseAction::PRESS && event.button != MouseButton::LEFT_BUTTON) {
1775         eventManager_->HandleOutOfRectCallback(
1776             { scaleEvent.x, scaleEvent.y, scaleEvent.sourceType }, rectCallbackList_);
1777     }
1778     eventManager_->MouseTest(scaleEvent, rootElement_->GetRenderNode());
1779     eventManager_->DispatchMouseEvent(scaleEvent);
1780     eventManager_->DispatchMouseHoverAnimation(scaleEvent);
1781     eventManager_->DispatchMouseHoverEvent(scaleEvent);
1782 #ifdef ENABLE_ROSEN_BACKEND
1783     std::chrono::high_resolution_clock::duration epoch_time = event.time.time_since_epoch();
1784     auto eventTimestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch_time);
1785     if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_) {
1786         std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
1787                                       ? AceApplicationInfo::GetInstance().GetPackageName()
1788                                       : AceApplicationInfo::GetInstance().GetProcessName();
1789         rsUIDirector_->SetTimeStamp(eventTimestamp.count(), abilityName);
1790     }
1791 #endif
1792     FlushMessages();
1793 }
1794 
CreateTouchEventOnZoom(const AxisEvent & event)1795 void PipelineContext::CreateTouchEventOnZoom(const AxisEvent& event)
1796 {
1797     zoomEventA_.id = 0;
1798     zoomEventB_.id = 1;
1799     zoomEventA_.type = zoomEventB_.type = TouchType::UNKNOWN;
1800     zoomEventA_.time = zoomEventB_.time = event.time;
1801     zoomEventA_.deviceId = zoomEventB_.deviceId = event.deviceId;
1802     zoomEventA_.sourceType = zoomEventB_.sourceType = SourceType::MOUSE;
1803     if (!isOnScrollZoomEvent_) {
1804         zoomEventA_.x = zoomEventA_.screenX = event.x - ZOOM_DISTANCE_DEFAULT;
1805         zoomEventA_.y = zoomEventA_.screenY = event.y;
1806         zoomEventA_.type = TouchType::DOWN;
1807         zoomEventB_.x = zoomEventB_.screenX = event.x + ZOOM_DISTANCE_DEFAULT;
1808         zoomEventB_.y = zoomEventB_.screenY = event.y;
1809         zoomEventB_.type = TouchType::DOWN;
1810         LOGI("Send TouchEventA(%{public}f, %{public}f, %{public}zu)", zoomEventA_.x, zoomEventA_.y, zoomEventA_.type);
1811         OnTouchEvent(zoomEventA_);
1812         LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y, zoomEventB_.type);
1813         OnTouchEvent(zoomEventB_);
1814         isOnScrollZoomEvent_ = true;
1815     }
1816     if (LessOrEqual(event.verticalAxis, 0.0)) {
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, zoomEventA_.type);
1820         OnTouchEvent(zoomEventA_);
1821         zoomEventB_.x = zoomEventB_.screenX += ZOOM_DISTANCE_MOVE_PER_WHEEL;
1822         zoomEventB_.type = TouchType::MOVE;
1823         LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y, zoomEventB_.type);
1824         OnTouchEvent(zoomEventB_);
1825     } else {
1826         if (!NearEqual(zoomEventA_.x, event.x)) {
1827             zoomEventA_.x = zoomEventA_.screenX += ZOOM_DISTANCE_MOVE_PER_WHEEL;
1828             zoomEventA_.type = TouchType::MOVE;
1829             LOGI("Send TouchEventA(%{public}f, %{public}f, %{public}zu)", zoomEventA_.x, zoomEventA_.y,
1830                 zoomEventA_.type);
1831             OnTouchEvent(zoomEventA_);
1832         }
1833         if (!NearEqual(zoomEventB_.x, event.x)) {
1834             zoomEventB_.x = zoomEventB_.screenX -= ZOOM_DISTANCE_MOVE_PER_WHEEL;
1835             zoomEventB_.type = TouchType::MOVE;
1836             LOGI("Send TouchEventB(%{public}f, %{public}f, %{public}zu)", zoomEventB_.x, zoomEventB_.y,
1837                 zoomEventB_.type);
1838             OnTouchEvent(zoomEventB_);
1839         }
1840     }
1841 }
1842 
ConvertAxisToMouse(const AxisEvent & event)1843 MouseEvent ConvertAxisToMouse(const AxisEvent& event)
1844 {
1845     MouseEvent result;
1846     result.x = event.x;
1847     result.y = event.y;
1848     result.action = MouseAction::MOVE;
1849     result.button = MouseButton::NONE_BUTTON;
1850     result.time = event.time;
1851     result.deviceId = event.deviceId;
1852     result.sourceType = event.sourceType;
1853     return result;
1854 }
1855 
OnAxisEvent(const AxisEvent & event)1856 void PipelineContext::OnAxisEvent(const AxisEvent& event)
1857 {
1858     if (isKeyCtrlPressed_ && !NearZero(event.verticalAxis) &&
1859         (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE)) {
1860         CreateTouchEventOnZoom(event);
1861         return;
1862     }
1863 
1864     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1865 
1866     if (event.action == AxisAction::BEGIN) {
1867         TouchRestrict touchRestrict { TouchRestrict::NONE };
1868         eventManager_->TouchTest(scaleEvent, rootElement_->GetRenderNode(), touchRestrict);
1869     }
1870     eventManager_->DispatchTouchEvent(scaleEvent);
1871 
1872     if (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE) {
1873         eventManager_->AxisTest(scaleEvent, rootElement_->GetRenderNode());
1874         eventManager_->DispatchAxisEvent(scaleEvent);
1875     }
1876 
1877     auto mouseEvent = ConvertAxisToMouse(event);
1878     OnMouseEvent(mouseEvent);
1879 }
1880 
AddToHoverList(const RefPtr<RenderNode> & node)1881 void PipelineContext::AddToHoverList(const RefPtr<RenderNode>& node)
1882 {
1883     CHECK_RUN_ON(UI);
1884     int32_t nodeId = node->GetAccessibilityNodeId();
1885     if (nodeId == 0) {
1886         return;
1887     }
1888     if (nodeId != hoverNodeId_) {
1889         // Hover node changed to the next id.
1890         hoverNodes_.clear();
1891         hoverNodes_.emplace_back(node);
1892         hoverNodeId_ = nodeId;
1893     } else {
1894         // Hover node add to current hover list.
1895         hoverNodes_.emplace_back(node);
1896     }
1897 }
1898 
OnRotationEvent(const RotationEvent & event) const1899 bool PipelineContext::OnRotationEvent(const RotationEvent& event) const
1900 {
1901     CHECK_RUN_ON(UI);
1902     if (!rootElement_) {
1903         LOGE("the root element is nullptr");
1904         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
1905         return false;
1906     }
1907 
1908     RefPtr<StackElement> stackElement = GetLastStack();
1909     if (!stackElement) {
1910         LOGE("the stack element is nullptr");
1911         return false;
1912     }
1913     RefPtr<RenderNode> stackRenderNode = stackElement->GetRenderNode();
1914     if (!stackRenderNode) {
1915         LOGE("the stack render node is nullptr");
1916         return false;
1917     }
1918 
1919     return eventManager_->DispatchRotationEvent(event, stackRenderNode, requestedRenderNode_.Upgrade());
1920 }
1921 
SetCardViewPosition(int id,float offsetX,float offsetY)1922 void PipelineContext::SetCardViewPosition(int id, float offsetX, float offsetY)
1923 {
1924     auto accessibilityManager = GetAccessibilityManager();
1925     if (!accessibilityManager) {
1926         return;
1927     }
1928     accessibilityManager->SetCardViewPosition(id, offsetX, offsetY);
1929 }
1930 
SetCardViewAccessibilityParams(const std::string & key,bool focus)1931 void PipelineContext::SetCardViewAccessibilityParams(const std::string& key, bool focus)
1932 {
1933     auto accessibilityManager = GetAccessibilityManager();
1934     if (!accessibilityManager) {
1935         return;
1936     }
1937     accessibilityManager->SetCardViewParams(key, focus);
1938 }
1939 
FlushVsync(uint64_t nanoTimestamp,uint32_t frameCount)1940 void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount)
1941 {
1942     CHECK_RUN_ON(UI);
1943     ACE_FUNCTION_TRACK();
1944 #if defined(ENABLE_NATIVE_VIEW)
1945     if (frameCount_ < 2) {
1946         frameCount_++;
1947     }
1948 #endif
1949 #ifdef ENABLE_ROSEN_BACKEND
1950     if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_) {
1951         std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
1952                                       ? AceApplicationInfo::GetInstance().GetPackageName()
1953                                       : AceApplicationInfo::GetInstance().GetProcessName();
1954         rsUIDirector_->SetTimeStamp(nanoTimestamp, abilityName);
1955     }
1956 #endif
1957     if (isSurfaceReady_) {
1958         FlushTouchEvents();
1959         FlushAnimation(GetTimeFromExternalTimer());
1960         FlushPipelineWithoutAnimation();
1961         FlushAnimationTasks();
1962         window_->FlushLayoutSize(width_, height_);
1963         hasIdleTasks_ = false;
1964     } else {
1965         LOGW("the surface is not ready, waiting");
1966     }
1967     if (isMoving_) {
1968         window_->RequestFrame();
1969         MarkForcedRefresh();
1970         isMoving_ = false;
1971     }
1972 }
1973 
OnIdle(int64_t deadline)1974 void PipelineContext::OnIdle(int64_t deadline)
1975 {
1976     CHECK_RUN_ON(UI);
1977     ACE_FUNCTION_TRACE();
1978     auto front = GetFrontend();
1979     if (front && GetIsDeclarative()) {
1980         if (deadline != 0) {
1981             FlushPredictLayout(deadline);
1982         }
1983         return;
1984     }
1985     FlushPredictLayout(deadline);
1986     if (hasIdleTasks_) {
1987         FlushPipelineImmediately();
1988         window_->RequestFrame();
1989         MarkForcedRefresh();
1990         hasIdleTasks_ = false;
1991     }
1992     FlushPageUpdateTasks();
1993 }
1994 
OnVirtualKeyboardHeightChange(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance,bool forceChange)1995 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight,
1996     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, const bool supportAvoidance,
1997     bool forceChange)
1998 {
1999     CHECK_RUN_ON(UI);
2000     ACE_FUNCTION_TRACE();
2001 #ifdef ENABLE_ROSEN_BACKEND
2002     if (rsTransaction) {
2003         FlushMessages();
2004         rsTransaction->Begin();
2005     }
2006 #endif
2007 
2008     auto func = [this, keyboardHeight]() {
2009         double positionY = 0;
2010         if (textFieldManager_) {
2011             positionY = textFieldManager_->GetClickPosition().GetY();
2012         }
2013         auto newKeyboardHeight = keyboardHeight / viewScale_;
2014         auto height = height_ / viewScale_;
2015         double offsetFix =
2016             (height - positionY) > 100.0 ? newKeyboardHeight - (height - positionY) / 2.0 : newKeyboardHeight;
2017         LOGI("OnVirtualKeyboardAreaChange positionY:%{public}f safeArea:%{public}f offsetFix:%{public}f", positionY,
2018             (height - newKeyboardHeight), offsetFix);
2019         if (NearZero(newKeyboardHeight)) {
2020             if (textFieldManager_ && AceType::InstanceOf<TextFieldManager>(textFieldManager_)) {
2021                 auto textFieldManager = AceType::DynamicCast<TextFieldManager>(textFieldManager_);
2022                 if (textFieldManager->ResetSlidingPanelParentHeight()) {
2023                     return;
2024                 }
2025             }
2026             SetRootSizeWithWidthHeight(width_, height_, 0);
2027             rootOffset_.SetY(0.0);
2028         } else if (positionY > (height - newKeyboardHeight) && offsetFix > 0.0) {
2029             if (textFieldManager_ && AceType::InstanceOf<TextFieldManager>(textFieldManager_)) {
2030                 auto textFieldManager = AceType::DynamicCast<TextFieldManager>(textFieldManager_);
2031                 if (textFieldManager->UpdatePanelForVirtualKeyboard(-offsetFix, height)) {
2032                     return;
2033                 }
2034             }
2035             SetRootSizeWithWidthHeight(width_, height_, -offsetFix);
2036             rootOffset_.SetY(-offsetFix);
2037         }
2038     };
2039 
2040     AnimationOption option = AnimationUtil::CreateKeyboardAnimationOption(keyboardAnimationConfig_, keyboardHeight);
2041     Animate(option, option.GetCurve(), func);
2042 
2043 #ifdef ENABLE_ROSEN_BACKEND
2044     if (rsTransaction) {
2045         rsTransaction->Commit();
2046     }
2047 #endif
2048 }
2049 
FlushPipelineImmediately()2050 void PipelineContext::FlushPipelineImmediately()
2051 {
2052     CHECK_RUN_ON(UI);
2053     ACE_FUNCTION_TRACE();
2054     if (isSurfaceReady_) {
2055         FlushPipelineWithoutAnimation();
2056     } else {
2057         LOGW("the surface is not ready, waiting");
2058     }
2059 }
2060 
WindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2061 void PipelineContext::WindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type,
2062     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2063 {
2064     static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
2065     if (!rootElement_ || !rootElement_->GetRenderNode() || !IsWindowSizeAnimationEnabled) {
2066         LOGE("RootNodeAnimation: no root element found, no animation configured");
2067         SetRootSizeWithWidthHeight(width, height);
2068         return;
2069     }
2070     auto rootNode = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2071     switch (type) {
2072         case WindowSizeChangeReason::RECOVER:
2073         case WindowSizeChangeReason::MAXIMIZE: {
2074             AnimationOption option;
2075             constexpr int32_t duration = 400;
2076             option.SetDuration(duration);
2077             auto curve = MakeRefPtr<DecelerationCurve>();
2078             option.SetCurve(curve);
2079             Animate(option, curve, [width, height, this]() {
2080                 SetRootSizeWithWidthHeight(width, height);
2081                 FlushLayout();
2082             });
2083             break;
2084         }
2085         case WindowSizeChangeReason::ROTATION: {
2086             SetRootSizeWithWidthHeight(width, height);
2087             FlushLayout();
2088             break;
2089         }
2090         case WindowSizeChangeReason::DRAG_START:
2091         case WindowSizeChangeReason::DRAG:
2092         case WindowSizeChangeReason::DRAG_END:
2093         case WindowSizeChangeReason::RESIZE:
2094         case WindowSizeChangeReason::UNDEFINED:
2095         default: {
2096             SetRootSizeWithWidthHeight(width, height);
2097         }
2098     }
2099 }
2100 
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2101 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type,
2102     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2103 {
2104     CHECK_RUN_ON(UI);
2105     if (width_ == width && height_ == height && type == WindowSizeChangeReason::CUSTOM_ANIMATION) {
2106         TryCallNextFrameLayoutCallback();
2107         return;
2108     }
2109     // Refresh the screen when developers customize the resolution and screen density on the PC preview.
2110 #if !defined(PREVIEW)
2111     if (width_ == width && height_ == height && isSurfaceReady_ && !isDensityUpdate_) {
2112         return;
2113     }
2114 #endif
2115 
2116     for (auto&& [id, callback] : surfaceChangedCallbackMap_) {
2117         if (callback) {
2118             callback(width, height, width_, height_, type);
2119         }
2120     }
2121 
2122     width_ = width;
2123     height_ = height;
2124 
2125     ACE_SCOPED_TRACE("OnSurfaceChanged(%d, %d)", width, height);
2126     LOGI("Surface size changed, [%{public}d * %{public}d]", width, height);
2127     if (!NearZero(rootHeight_)) {
2128         double newRootHeight = height / viewScale_;
2129         double newRootWidth = width / viewScale_;
2130         double offsetHeight = rootHeight_ - newRootHeight;
2131         if (textFieldManager_ && GetLastPage()) {
2132             textFieldManager_->MovePage(GetLastPage()->GetPageId(), { newRootWidth, newRootHeight }, offsetHeight);
2133         }
2134     }
2135 
2136     taskExecutor_->PostTask(
2137         [weakFrontend = weakFrontend_, width, height]() {
2138             auto frontend = weakFrontend.Upgrade();
2139             if (frontend) {
2140                 frontend->OnSurfaceChanged(width, height);
2141             }
2142         },
2143         TaskExecutor::TaskType::JS, "ArkUISurfaceChanged");
2144 
2145     // init transition clip size when surface changed.
2146     const auto& pageElement = GetLastPage();
2147     if (pageElement) {
2148         const auto& transitionElement = AceType::DynamicCast<PageTransitionElement>(pageElement->GetFirstChild());
2149         if (transitionElement) {
2150             transitionElement->InitTransitionClip();
2151         }
2152     }
2153 #ifdef ENABLE_ROSEN_BACKEND
2154     WindowSizeChangeAnimate(width, height, type, rsTransaction);
2155 #else
2156     SetRootSizeWithWidthHeight(width, height);
2157 #endif
2158     if (isSurfaceReady_) {
2159         return;
2160     }
2161     isSurfaceReady_ = true;
2162     FlushPipelineWithoutAnimation();
2163     MarkForcedRefresh();
2164 #ifndef WEARABLE_PRODUCT
2165     multiModalManager_->OpenChannel(Claim(this));
2166 #endif
2167 }
2168 
OnSurfacePositionChanged(int32_t posX,int32_t posY)2169 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
2170 {
2171     for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
2172         if (callback) {
2173             callback(posX, posY);
2174         }
2175     }
2176 }
2177 
OnSurfaceDensityChanged(double density)2178 void PipelineContext::OnSurfaceDensityChanged(double density)
2179 {
2180     CHECK_RUN_ON(UI);
2181     ACE_SCOPED_TRACE("OnSurfaceDensityChanged(%lf)", density);
2182     isDensityUpdate_ = density != density_;
2183     density_ = density;
2184     if (!NearZero(viewScale_)) {
2185         dipScale_ = density_ / viewScale_;
2186     }
2187     if (isDensityUpdate_) {
2188         PipelineBase::OnSurfaceDensityChanged(density);
2189     }
2190 }
2191 
OnSystemBarHeightChanged(double statusBar,double navigationBar)2192 void PipelineContext::OnSystemBarHeightChanged(double statusBar, double navigationBar)
2193 {
2194     CHECK_RUN_ON(UI);
2195     ACE_SCOPED_TRACE("OnSystemBarHeightChanged(%lf, %lf)", statusBar, navigationBar);
2196     double statusBarHeight = 0.0;
2197     double navigationBarHeight = 0.0;
2198     if (!NearZero(viewScale_) && !NearZero(dipScale_)) {
2199         statusBarHeight = statusBar / viewScale_ / dipScale_;
2200         navigationBarHeight = navigationBar / viewScale_ / dipScale_;
2201     }
2202 
2203     if ((!NearEqual(statusBarHeight, statusBarHeight_)) || (!NearEqual(navigationBarHeight, navigationBarHeight_))) {
2204         statusBarHeight_ = statusBarHeight;
2205         navigationBarHeight_ = navigationBarHeight;
2206         if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
2207             auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2208             if (semiModal) {
2209                 semiModal->UpdateSystemBarHeight(statusBarHeight_, navigationBarHeight_);
2210             }
2211         } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
2212             auto dialogModal = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
2213             if (dialogModal) {
2214                 dialogModal->UpdateSystemBarHeight(statusBarHeight_, navigationBarHeight_);
2215             }
2216         } else {
2217             // Normal modal, do nothing.
2218         }
2219     }
2220 }
2221 
OnSurfaceDestroyed()2222 void PipelineContext::OnSurfaceDestroyed()
2223 {
2224     CHECK_RUN_ON(UI);
2225     ACE_SCOPED_TRACE("OnSurfaceDestroyed");
2226     isSurfaceReady_ = false;
2227 }
2228 
SetRootSizeWithWidthHeight(int32_t width,int32_t height,int32_t offset)2229 void PipelineContext::SetRootSizeWithWidthHeight(int32_t width, int32_t height, int32_t offset)
2230 {
2231     CHECK_RUN_ON(UI);
2232     UpdateRootSizeAndScale(width, height);
2233     CHECK_NULL_VOID(rootElement_);
2234     const Rect paintRect(0.0, 0.0, rootWidth_, rootHeight_);
2235     auto rootNode = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2236     if (!rootNode) {
2237         return;
2238     }
2239     auto stack = GetStageElement()->GetElementParent().Upgrade();
2240     if (stack) {
2241         auto renderStack = AceType::DynamicCast<RenderStack>(stack->GetRenderNode());
2242         if (renderStack) {
2243             renderStack->SetTop(Dimension(offset));
2244         }
2245     }
2246     if (!NearEqual(viewScale_, rootNode->GetScale()) || paintRect != rootNode->GetPaintRect() || isDensityUpdate_) {
2247         if (!NearEqual(viewScale_, rootNode->GetScale())) {
2248             rootNode->SetReset(true);
2249         }
2250         rootNode->SetPaintRect(paintRect);
2251         rootNode->SetScale(viewScale_);
2252         rootNode->MarkNeedLayout();
2253         rootNode->MarkNeedRender();
2254         focusAnimationManager_->SetAvailableRect(paintRect);
2255     }
2256     if (IsJsPlugin() || IsJsCard()) {
2257         return;
2258     }
2259     ScreenSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
2260     ScreenSystemManager::GetInstance().OnSurfaceChanged(width);
2261 }
2262 
SetAppBgColor(const Color & color)2263 void PipelineContext::SetAppBgColor(const Color& color)
2264 {
2265     LOGI("Set bgColor %{public}u", color.GetValue());
2266     appBgColor_ = color;
2267 #ifdef ENABLE_ROSEN_BACKEND
2268     if (rsUIDirector_) {
2269         rsUIDirector_->SetAbilityBGAlpha(appBgColor_.GetAlpha());
2270     }
2271 #endif
2272     if (!themeManager_) {
2273         LOGW("themeManager_ is nullptr!");
2274         return;
2275     }
2276     auto appTheme = themeManager_->GetTheme<AppTheme>();
2277     if (!appTheme) {
2278         LOGW("appTheme is nullptr!");
2279         return;
2280     }
2281     appTheme->SetBackgroundColor(appBgColor_);
2282     if (!rootElement_) {
2283         LOGW("rootElement_ is nullptr!");
2284         return;
2285     }
2286     auto renderRoot = DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2287     if (!renderRoot) {
2288         LOGW("renderRoot is nullptr!");
2289         return;
2290     }
2291     if (windowModal_ == WindowModal::CONTAINER_MODAL) {
2292         auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
2293         if (containerModal) {
2294             containerModal->SetAppBgColor(appBgColor_);
2295             renderRoot->SetBgColor(Color::TRANSPARENT);
2296             return;
2297         }
2298     }
2299     renderRoot->SetBgColor(appBgColor_);
2300 }
2301 
Finish(bool autoFinish) const2302 void PipelineContext::Finish(bool autoFinish) const
2303 {
2304     CHECK_RUN_ON(UI);
2305     if (autoFinish && rootElement_ && onShow_) {
2306         if (windowModal_ == WindowModal::SEMI_MODAL || windowModal_ == WindowModal::SEMI_MODAL_FULL_SCREEN) {
2307             auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2308             if (!semiModal) {
2309                 LOGE("SemiModal animate to exit app failed. semi modal is null");
2310                 return;
2311             }
2312             semiModal->AnimateToExitApp();
2313             return;
2314         } else if (windowModal_ == WindowModal::DIALOG_MODAL) {
2315             // dialog modal use translucent theme and will do exit animation by ACE itself.
2316             auto dialogModal = AceType::DynamicCast<DialogModalElement>(rootElement_->GetFirstChild());
2317             if (!dialogModal) {
2318                 LOGE("DialogModal animate to exit app failed. dialog modal is null");
2319                 return;
2320             }
2321             dialogModal->AnimateToExitApp();
2322             return;
2323         } else {
2324             // normal force finish.
2325             Finish(false);
2326         }
2327     } else {
2328         if (finishEventHandler_) {
2329             finishEventHandler_();
2330         } else {
2331             LOGE("fail to finish current context due to handler is nullptr");
2332         }
2333     }
2334 }
2335 
RequestFullWindow(int32_t duration)2336 void PipelineContext::RequestFullWindow(int32_t duration)
2337 {
2338     CHECK_RUN_ON(UI);
2339     if (!rootElement_) {
2340         LOGE("Root element is null!");
2341         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2342         return;
2343     }
2344     auto semiModal = AceType::DynamicCast<SemiModalElement>(rootElement_->GetFirstChild());
2345     if (!semiModal) {
2346         LOGI("Get semiModal element failed. SemiModal element is null!");
2347         return;
2348     }
2349     if (semiModal->IsFullWindow()) {
2350         LOGI("Already in full window, skip it.");
2351         return;
2352     }
2353     isFullWindow_ = true;
2354     // when semi modal animating, no more full window request can be handled, so mark it as full window.
2355     semiModal->SetFullWindow(true);
2356     semiModal->AnimateToFullWindow(duration);
2357     NotifyStatusBarBgColor(semiModal->GetBackgroundColor());
2358     auto page = GetLastStack();
2359     if (!page) {
2360         return;
2361     }
2362     auto renderPage = AceType::DynamicCast<RenderStack>(page->GetRenderNode());
2363     if (!renderPage) {
2364         return;
2365     }
2366     // Change to full window, change page stack layout strategy.
2367     renderPage->SetStackFit(StackFit::INHERIT);
2368     renderPage->SetMainStackSize(MainStackSize::MAX);
2369     renderPage->MarkNeedLayout();
2370 }
2371 
ShowFocusAnimation(const RRect & rrect,const Color & color,const Offset & offset,bool isIndented) const2372 void PipelineContext::ShowFocusAnimation(
2373     const RRect& rrect, const Color& color, const Offset& offset, bool isIndented) const
2374 {
2375     focusAnimationManager_->SetFocusAnimationProperties(rrect, color, offset, isIndented);
2376 }
2377 
ShowFocusAnimation(const RRect & rrect,const Color & color,const Offset & offset,const Rect & clipRect) const2378 void PipelineContext::ShowFocusAnimation(
2379     const RRect& rrect, const Color& color, const Offset& offset, const Rect& clipRect) const
2380 {
2381     focusAnimationManager_->SetFocusAnimationProperties(rrect, color, offset, clipRect);
2382 }
2383 
AddDirtyFocus(const RefPtr<FocusNode> & node)2384 void PipelineContext::AddDirtyFocus(const RefPtr<FocusNode>& node)
2385 {
2386     CHECK_RUN_ON(UI);
2387     if (!node) {
2388         LOGW("node is null.");
2389         return;
2390     }
2391     if (node->IsChild()) {
2392         dirtyFocusNode_ = WeakClaim(RawPtr(node));
2393     } else {
2394         dirtyFocusScope_ = WeakClaim(RawPtr(node));
2395     }
2396     window_->RequestFrame();
2397 }
2398 
CancelFocusAnimation() const2399 void PipelineContext::CancelFocusAnimation() const
2400 {
2401     focusAnimationManager_->CancelFocusAnimation();
2402 }
2403 
PopFocusAnimation() const2404 void PipelineContext::PopFocusAnimation() const
2405 {
2406     focusAnimationManager_->PopFocusAnimationElement();
2407 }
2408 
PopRootFocusAnimation() const2409 void PipelineContext::PopRootFocusAnimation() const
2410 {
2411     focusAnimationManager_->PopRootFocusAnimationElement();
2412 }
2413 
PushFocusAnimation(const RefPtr<Element> & element) const2414 void PipelineContext::PushFocusAnimation(const RefPtr<Element>& element) const
2415 {
2416     focusAnimationManager_->PushFocusAnimationElement(element);
2417 }
2418 
Destroy()2419 void PipelineContext::Destroy()
2420 {
2421     CHECK_RUN_ON(UI);
2422     LOGI("PipelineContext::Destroy begin.");
2423     rootElement_.Reset();
2424     composedElementMap_.clear();
2425     dirtyElements_.clear();
2426     deactivateElements_.clear();
2427     dirtyRenderNodes_.clear();
2428     dirtyRenderNodesInOverlay_.clear();
2429     dirtyLayoutNodes_.clear();
2430     predictLayoutNodes_.clear();
2431     geometryChangedNodes_.clear();
2432     needPaintFinishNodes_.clear();
2433     dirtyFocusNode_.Reset();
2434     dirtyFocusScope_.Reset();
2435     postFlushListeners_.clear();
2436     postAnimationFlushListeners_.clear();
2437     preFlushListeners_.clear();
2438     sharedTransitionController_.Reset();
2439     cardTransitionController_.Reset();
2440     while (!pageUpdateTasks_.empty()) {
2441         pageUpdateTasks_.pop();
2442     }
2443     alignDeclarationNodeList_.clear();
2444     hoverNodes_.clear();
2445     renderFactory_.Reset();
2446     nodesToNotifyOnPreDraw_.clear();
2447     nodesNeedDrawOnPixelMap_.clear();
2448     layoutTransitionNodeSet_.clear();
2449     explicitAnimators_.clear();
2450     preTargetRenderNode_.Reset();
2451     sharedImageManager_.Reset();
2452     rectCallbackList_.clear();
2453     PipelineBase::Destroy();
2454     LOGI("PipelineContext::Destroy end.");
2455 }
2456 
SendCallbackMessageToFrontend(const std::string & callbackId,const std::string & data)2457 void PipelineContext::SendCallbackMessageToFrontend(const std::string& callbackId, const std::string& data)
2458 {
2459     auto frontend = weakFrontend_.Upgrade();
2460     if (!frontend) {
2461         LOGE("frontend is nullptr");
2462         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2463         return;
2464     }
2465     frontend->SendCallbackMessage(callbackId, data);
2466 }
2467 
SendEventToFrontend(const EventMarker & eventMarker)2468 void PipelineContext::SendEventToFrontend(const EventMarker& eventMarker)
2469 {
2470     auto frontend = weakFrontend_.Upgrade();
2471     if (!frontend) {
2472         LOGE("frontend is nullptr");
2473         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2474         return;
2475     }
2476     auto handler = frontend->GetEventHandler();
2477     if (!handler) {
2478         LOGE("fail to trigger async event due to event handler is nullptr");
2479         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2480         return;
2481     }
2482     handler->HandleAsyncEvent(eventMarker);
2483 }
2484 
SendEventToFrontend(const EventMarker & eventMarker,const std::string & param)2485 void PipelineContext::SendEventToFrontend(const EventMarker& eventMarker, const std::string& param)
2486 {
2487     auto frontend = weakFrontend_.Upgrade();
2488     if (!frontend) {
2489         LOGE("frontend is nullptr");
2490         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2491         return;
2492     }
2493     auto handler = frontend->GetEventHandler();
2494     if (!handler) {
2495         LOGE("fail to trigger async event due to event handler is nullptr");
2496         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2497         return;
2498     }
2499     handler->HandleAsyncEvent(eventMarker, param);
2500 }
2501 
AccessibilityRequestFocus(const ComposeId & id)2502 bool PipelineContext::AccessibilityRequestFocus(const ComposeId& id)
2503 {
2504     auto targetElement = GetComposedElementById(id);
2505     if (!targetElement) {
2506         LOGE("RequestFocusById targetElement is null.");
2507         EventReport::SendAccessibilityException(AccessibilityExcepType::GET_NODE_ERR);
2508         return false;
2509     }
2510     return RequestFocus(targetElement);
2511 }
2512 
RequestFocus(const RefPtr<Element> & targetElement)2513 bool PipelineContext::RequestFocus(const RefPtr<Element>& targetElement)
2514 {
2515     CHECK_RUN_ON(UI);
2516     if (!targetElement) {
2517         return false;
2518     }
2519     auto children = targetElement->GetChildren();
2520     for (const auto& childElement : children) {
2521         auto focusNode = AceType::DynamicCast<FocusNode>(childElement);
2522         if (focusNode) {
2523             if (focusNode->RequestFocusImmediately()) {
2524                 return true;
2525             } else {
2526                 continue;
2527             }
2528         }
2529         if (RequestFocus(childElement)) {
2530             return true;
2531         }
2532     }
2533     return false;
2534 }
2535 
RequestFocus(const std::string & targetNodeId,bool isSyncRequest)2536 bool PipelineContext::RequestFocus(const std::string& targetNodeId, bool isSyncRequest)
2537 {
2538     CHECK_NULL_RETURN(rootElement_, false);
2539     auto currentFocusChecked = rootElement_->RequestFocusImmediatelyById(targetNodeId);
2540     if (!isSubPipeline_ || currentFocusChecked) {
2541         LOGI("Request focus finish currentFocus is %{public}d", currentFocusChecked);
2542         return currentFocusChecked;
2543     }
2544     LOGI("Search focus in main pipeline");
2545     auto parentPipelineBase = parentPipeline_.Upgrade();
2546     CHECK_NULL_RETURN(parentPipelineBase, false);
2547     auto parentPipelineContext = AceType::DynamicCast<PipelineContext>(parentPipelineBase);
2548     CHECK_NULL_RETURN(parentPipelineContext, false);
2549     return parentPipelineContext->RequestFocus(targetNodeId);
2550 }
2551 
GetRenderFocusAnimation() const2552 RefPtr<RenderFocusAnimation> PipelineContext::GetRenderFocusAnimation() const
2553 {
2554     return focusAnimationManager_->GetRenderFocusAnimation();
2555 }
2556 
ShowShadow(const RRect & rrect,const Offset & offset) const2557 void PipelineContext::ShowShadow(const RRect& rrect, const Offset& offset) const
2558 {
2559     focusAnimationManager_->SetShadowProperties(rrect, offset);
2560 }
2561 
ShowShadow(const RRect & rrect,const Offset & offset,const Rect & clipRect) const2562 void PipelineContext::ShowShadow(const RRect& rrect, const Offset& offset, const Rect& clipRect) const
2563 {
2564     focusAnimationManager_->SetShadowProperties(rrect, offset, clipRect);
2565 }
2566 
PushShadow(const RefPtr<Element> & element) const2567 void PipelineContext::PushShadow(const RefPtr<Element>& element) const
2568 {
2569     focusAnimationManager_->PushShadow(element);
2570 }
2571 
PopShadow() const2572 void PipelineContext::PopShadow() const
2573 {
2574     focusAnimationManager_->PopShadow();
2575 }
2576 
CancelShadow() const2577 void PipelineContext::CancelShadow() const
2578 {
2579     focusAnimationManager_->CancelShadow();
2580 }
2581 
SetUseRootAnimation(bool useRoot)2582 void PipelineContext::SetUseRootAnimation(bool useRoot)
2583 {
2584     focusAnimationManager_->SetUseRoot(useRoot);
2585 }
2586 
2587 #ifndef WEARABLE_PRODUCT
SetMultimodalSubscriber(const RefPtr<MultimodalSubscriber> & multimodalSubscriber)2588 void PipelineContext::SetMultimodalSubscriber(const RefPtr<MultimodalSubscriber>& multimodalSubscriber)
2589 {
2590     multiModalManager_->SetMultimodalSubscriber(multimodalSubscriber);
2591 }
2592 
SetWindowOnShow()2593 void PipelineContext::SetWindowOnShow()
2594 {
2595     window_->OnShow();
2596     window_->RequestFrame();
2597 }
2598 
SetWindowOnHide()2599 void PipelineContext::SetWindowOnHide()
2600 {
2601     window_->RequestFrame();
2602     window_->OnHide();
2603 }
2604 
OnShow()2605 void PipelineContext::OnShow()
2606 {
2607     onShow_ = true;
2608     SetWindowOnShow();
2609     PerfMonitor::GetPerfMonitor()->SetAppForeground(true);
2610     auto multiModalScene = multiModalManager_->GetCurrentMultiModalScene();
2611     if (multiModalScene) {
2612         multiModalScene->Resume();
2613     }
2614     taskExecutor_->PostTask(
2615         [weak = AceType::WeakClaim(this)]() {
2616             auto context = weak.Upgrade();
2617             if (!context) {
2618                 return;
2619             }
2620 #ifdef ENABLE_ROSEN_BACKEND
2621             if (context->rsUIDirector_) {
2622                 context->rsUIDirector_->GoForeground();
2623             }
2624 #endif
2625             const auto& rootElement = context->rootElement_;
2626             if (!rootElement) {
2627                 LOGE("render element is null!");
2628                 return;
2629             }
2630             const auto& renderRoot = AceType::DynamicCast<RenderRoot>(rootElement->GetRenderNode());
2631             if (!renderRoot) {
2632                 LOGE("render root is null!");
2633                 return;
2634             }
2635             if ((context->windowModal_ == WindowModal::SEMI_MODAL) ||
2636                 (context->windowModal_ == WindowModal::DIALOG_MODAL)) {
2637                 renderRoot->SetDefaultBgColor();
2638             }
2639             renderRoot->NotifyOnShow();
2640         },
2641         TaskExecutor::TaskType::UI, "ArkUIRenderRootShow");
2642 }
2643 
OnHide()2644 void PipelineContext::OnHide()
2645 {
2646     onShow_ = false;
2647     SetWindowOnHide();
2648     PerfMonitor::GetPerfMonitor()->SetAppForeground(false);
2649     auto multiModalScene = multiModalManager_->GetCurrentMultiModalScene();
2650     if (multiModalScene) {
2651         multiModalScene->Hide();
2652     }
2653     taskExecutor_->PostTask(
2654         [weak = AceType::WeakClaim(this)]() {
2655             auto context = weak.Upgrade();
2656             if (!context) {
2657                 return;
2658             }
2659             if (context->IsSubPipeline()) {
2660                 context->FlushPipelineImmediately();
2661             }
2662 #ifdef ENABLE_ROSEN_BACKEND
2663             if (context->rsUIDirector_) {
2664                 context->rsUIDirector_->GoBackground();
2665                 context->rsUIDirector_->SendMessages();
2666             }
2667 #endif
2668             context->NotifyPopupDismiss();
2669             context->OnVirtualKeyboardAreaChange(Rect());
2670             const auto& rootElement = context->rootElement_;
2671             if (!rootElement) {
2672                 LOGE("render element is null!");
2673                 return;
2674             }
2675             const auto& renderRoot = AceType::DynamicCast<RenderRoot>(rootElement->GetRenderNode());
2676             if (!renderRoot) {
2677                 LOGE("render root is null!");
2678                 return;
2679             }
2680             renderRoot->NotifyOnHide();
2681         },
2682         TaskExecutor::TaskType::UI, "ArkUIRenderRootHide");
2683 }
2684 #endif
2685 
RefreshRootBgColor() const2686 void PipelineContext::RefreshRootBgColor() const
2687 {
2688     CHECK_RUN_ON(UI);
2689     if (!rootElement_) {
2690         return;
2691     }
2692     const auto& render = AceType::DynamicCast<RenderRoot>(rootElement_->GetRenderNode());
2693     if (render) {
2694         render->SetDefaultBgColor(windowModal_ == WindowModal::CONTAINER_MODAL);
2695     }
2696 }
2697 
OnPageShow()2698 void PipelineContext::OnPageShow()
2699 {
2700     CHECK_RUN_ON(UI);
2701     if (onPageShowCallBack_) {
2702         onPageShowCallBack_();
2703     }
2704 }
2705 
SetTimeProvider(TimeProvider && timeProvider)2706 void PipelineContext::SetTimeProvider(TimeProvider&& timeProvider)
2707 {
2708     if (!timeProvider) {
2709         LOGE("Set time provider failed. provider is null.");
2710         return;
2711     }
2712     timeProvider_ = std::move(timeProvider);
2713 }
2714 
GetTimeFromExternalTimer()2715 uint64_t PipelineContext::GetTimeFromExternalTimer()
2716 {
2717     if (isFlushingAnimation_) {
2718         return flushAnimationTimestamp_;
2719     } else {
2720         if (!timeProvider_) {
2721             LOGE("No time provider has been set.");
2722             return 0;
2723         }
2724         return timeProvider_();
2725     }
2726 }
2727 
LoadSystemFont(const std::function<void ()> & onFondsLoaded)2728 void PipelineContext::LoadSystemFont(const std::function<void()>& onFondsLoaded)
2729 {
2730     GetTaskExecutor()->PostTask(
2731         [weak = WeakClaim(this), fontManager = fontManager_, onFondsLoaded]() {
2732             if (!fontManager) {
2733                 return;
2734             }
2735             fontManager->LoadSystemFont();
2736             auto context = weak.Upgrade();
2737             if (!context) {
2738                 return;
2739             }
2740             context->GetTaskExecutor()->PostTask(
2741                 [onFondsLoaded]() {
2742                     if (onFondsLoaded) {
2743                         onFondsLoaded();
2744                     }
2745                 },
2746                 TaskExecutor::TaskType::UI, "ArkUISystemFondsLoaded");
2747         },
2748         TaskExecutor::TaskType::IO, "ArkUILoadSystemFont");
2749 }
2750 
AddFontNode(const WeakPtr<RenderNode> & node)2751 void PipelineContext::AddFontNode(const WeakPtr<RenderNode>& node)
2752 {
2753     if (fontManager_) {
2754         fontManager_->AddFontNode(node);
2755     }
2756 }
2757 
RemoveFontNode(const WeakPtr<RenderNode> & node)2758 void PipelineContext::RemoveFontNode(const WeakPtr<RenderNode>& node)
2759 {
2760     if (fontManager_) {
2761         fontManager_->RemoveFontNode(node);
2762     }
2763 }
2764 
SetClickPosition(const Offset & position) const2765 void PipelineContext::SetClickPosition(const Offset& position) const
2766 {
2767     LOGI("SetClickPosition position:%{public}s rootOffset:%{public}s", position.ToString().c_str(),
2768         rootOffset_.ToString().c_str());
2769     if (textFieldManager_) {
2770         textFieldManager_->SetClickPosition(position - rootOffset_);
2771     }
2772 }
2773 
GetOverlayElement() const2774 const RefPtr<OverlayElement> PipelineContext::GetOverlayElement() const
2775 {
2776     if (!rootElement_) {
2777         LOGE("Root element is null!");
2778         EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR);
2779         return RefPtr<OverlayElement>();
2780     }
2781     auto overlay = AceType::DynamicCast<OverlayElement>(rootElement_->GetOverlayElement(windowModal_));
2782     if (!overlay) {
2783         LOGE("Get overlay element failed. overlay element is null!");
2784         return RefPtr<OverlayElement>();
2785     }
2786     return overlay;
2787 }
2788 
FlushBuildAndLayoutBeforeSurfaceReady()2789 void PipelineContext::FlushBuildAndLayoutBeforeSurfaceReady()
2790 {
2791     if (isSurfaceReady_) {
2792         return;
2793     }
2794     GetTaskExecutor()->PostTask(
2795         [weak = AceType::WeakClaim(this)]() {
2796             auto context = weak.Upgrade();
2797             if (!context || context->isSurfaceReady_) {
2798                 return;
2799             }
2800 
2801             context->FlushBuild();
2802             context->SetRootRect(context->width_, context->height_);
2803             context->FlushLayout();
2804         },
2805         TaskExecutor::TaskType::UI, "ArkUIFlushBuildAndLayout");
2806 }
2807 
RootLostFocus(BlurReason reason) const2808 void PipelineContext::RootLostFocus(BlurReason reason) const
2809 {
2810     if (rootElement_) {
2811         rootElement_->LostFocus(reason);
2812     }
2813 }
2814 
WindowFocus(bool isFocus)2815 void PipelineContext::WindowFocus(bool isFocus)
2816 {
2817     onFocus_ = isFocus;
2818     if (!isFocus) {
2819         RootLostFocus(BlurReason::WINDOW_BLUR);
2820         NotifyPopupDismiss();
2821         OnVirtualKeyboardAreaChange(Rect());
2822     }
2823     if (onFocus_ && onShow_) {
2824         FlushFocus();
2825     }
2826     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
2827         return;
2828     }
2829     if (!rootElement_) {
2830         LOGE("WindowFocus failed, rootElement_ is null.");
2831         return;
2832     }
2833     auto containerModal = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
2834     if (containerModal) {
2835         containerModal->WindowFocus(isFocus);
2836     }
2837 }
2838 
ContainerModalUnFocus()2839 void PipelineContext::ContainerModalUnFocus() {}
2840 
AddPageUpdateTask(std::function<void ()> && task,bool directExecute)2841 void PipelineContext::AddPageUpdateTask(std::function<void()>&& task, bool directExecute)
2842 {
2843     CHECK_RUN_ON(UI);
2844     pageUpdateTasks_.emplace(std::move(task));
2845     if (directExecute) {
2846         FlushPageUpdateTasks();
2847     } else {
2848         window_->RequestFrame();
2849     }
2850 #if defined(ENABLE_NATIVE_VIEW)
2851     if (frameCount_ == 1) {
2852         OnIdle(0);
2853         FlushPipelineImmediately();
2854     }
2855 #endif
2856 }
2857 
MovePage(const Offset & rootRect,double offsetHeight)2858 void PipelineContext::MovePage(const Offset& rootRect, double offsetHeight)
2859 {
2860     if (textFieldManager_ && GetLastPage()) {
2861         textFieldManager_->MovePage(GetLastPage()->GetPageId(), rootRect, offsetHeight);
2862     }
2863 }
2864 
GetDeactivateElement(int32_t componentId) const2865 RefPtr<Element> PipelineContext::GetDeactivateElement(int32_t componentId) const
2866 {
2867     CHECK_RUN_ON(UI);
2868     auto elementIter = deactivateElements_.find(componentId);
2869     if (elementIter != deactivateElements_.end()) {
2870         return elementIter->second;
2871     } else {
2872         return nullptr;
2873     }
2874 }
2875 
AddDeactivateElement(const int32_t id,const RefPtr<Element> & element)2876 void PipelineContext::AddDeactivateElement(const int32_t id, const RefPtr<Element>& element)
2877 {
2878     CHECK_RUN_ON(UI);
2879     deactivateElements_.emplace(id, element);
2880 }
2881 
ClearDeactivateElements()2882 void PipelineContext::ClearDeactivateElements()
2883 {
2884     CHECK_RUN_ON(UI);
2885     ACE_FUNCTION_TRACK();
2886     for (auto iter = deactivateElements_.begin(); iter != deactivateElements_.end();) {
2887         auto element = iter->second;
2888         RefPtr<RenderNode> render = element ? element->GetRenderNode() : nullptr;
2889         if (!render || !render->IsDisappearing()) {
2890             iter = deactivateElements_.erase(iter);
2891         } else {
2892             iter++;
2893         }
2894     }
2895 }
2896 
DumpAccessibility(const std::vector<std::string> & params) const2897 void PipelineContext::DumpAccessibility(const std::vector<std::string>& params) const
2898 {
2899     auto accessibilityManager = GetAccessibilityManager();
2900     if (!accessibilityManager) {
2901         return;
2902     }
2903     accessibilityManager->OnDumpInfo(params);
2904 }
2905 
UpdateWindowBlurRegion(int32_t id,RRect rRect,float progress,WindowBlurStyle style,const std::vector<RRect> & coords)2906 void PipelineContext::UpdateWindowBlurRegion(
2907     int32_t id, RRect rRect, float progress, WindowBlurStyle style, const std::vector<RRect>& coords)
2908 {
2909     CHECK_RUN_ON(UI);
2910     auto pos = windowBlurRegions_.find(id);
2911     if (pos != windowBlurRegions_.end()) {
2912         const auto& old = pos->second;
2913         if (NearEqual(progress, old.progress_) && rRect == old.innerRect_ && style == old.style_) {
2914             return;
2915         }
2916     }
2917     windowBlurRegions_[id] = { .progress_ = progress, .style_ = style, .innerRect_ = rRect, .coords_ = coords };
2918     needWindowBlurRegionRefresh_ = true;
2919 }
2920 
ClearWindowBlurRegion(int32_t id)2921 void PipelineContext::ClearWindowBlurRegion(int32_t id)
2922 {
2923     CHECK_RUN_ON(UI);
2924     auto pos = windowBlurRegions_.find(id);
2925     if (pos != windowBlurRegions_.end()) {
2926         windowBlurRegions_.erase(pos);
2927         needWindowBlurRegionRefresh_ = true;
2928     }
2929 }
2930 
InitDragListener()2931 void PipelineContext::InitDragListener()
2932 {
2933     if (!initDragEventListener_) {
2934         return;
2935     }
2936     initDragEventListener_();
2937 }
2938 
StartSystemDrag(const std::string & str,const RefPtr<PixelMap> & pixmap)2939 void PipelineContext::StartSystemDrag(const std::string& str, const RefPtr<PixelMap>& pixmap)
2940 {
2941     if (!dragEventHandler_) {
2942         return;
2943     }
2944     dragEventHandler_(str, pixmap);
2945 }
2946 
SetPreTargetRenderNode(const RefPtr<DragDropEvent> & preDragDropNode)2947 void PipelineContext::SetPreTargetRenderNode(const RefPtr<DragDropEvent>& preDragDropNode)
2948 {
2949     preTargetRenderNode_ = preDragDropNode;
2950 }
2951 
GetPreTargetRenderNode() const2952 const RefPtr<DragDropEvent>& PipelineContext::GetPreTargetRenderNode() const
2953 {
2954     return preTargetRenderNode_;
2955 }
2956 
SetInitRenderNode(const RefPtr<RenderNode> & initRenderNode)2957 void PipelineContext::SetInitRenderNode(const RefPtr<RenderNode>& initRenderNode)
2958 {
2959     initRenderNode_ = initRenderNode;
2960 }
2961 
GetInitRenderNode() const2962 const RefPtr<RenderNode>& PipelineContext::GetInitRenderNode() const
2963 {
2964     return initRenderNode_;
2965 }
2966 
ProcessDragEvent(const RefPtr<RenderNode> & renderNode,const RefPtr<DragEvent> & event,const Point & globalPoint)2967 void PipelineContext::ProcessDragEvent(
2968     const RefPtr<RenderNode>& renderNode, const RefPtr<DragEvent>& event, const Point& globalPoint)
2969 {
2970     auto targetDragDropNode =
2971         AceType::DynamicCast<DragDropEvent>(renderNode->FindDropChild(globalPoint, globalPoint - pageOffset_));
2972     auto initDragDropNode = AceType::DynamicCast<DragDropEvent>(GetInitRenderNode());
2973     auto extraParams = JsonUtil::Create(true);
2974     extraParams->Put("customDragInfo", customDragInfo_.c_str());
2975     extraParams->Put("selectedText", selectedText_.c_str());
2976     extraParams->Put("imageSrc", imageSrc_.c_str());
2977     auto info = GestureEvent();
2978     info.SetGlobalPoint(globalPoint);
2979     auto preTargetDragDropNode = GetPreTargetRenderNode();
2980     if (targetDragDropNode == preTargetDragDropNode) {
2981         if (targetDragDropNode && targetDragDropNode->GetOnDragMove()) {
2982             auto renderList = renderNode->FindChildNodeOfClass<V2::RenderList>(globalPoint, globalPoint);
2983             if (renderList) {
2984                 insertIndex_ = renderList->CalculateInsertIndex(renderList, info, selectedItemSize_);
2985             }
2986 
2987             if (insertIndex_ == static_cast<int32_t>(RenderNode::DEFAULT_INDEX)) {
2988                 (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
2989                 return;
2990             }
2991 
2992             if (targetDragDropNode != initDragDropNode) {
2993                 extraParams->Put("selectedIndex", -1);
2994             } else {
2995                 extraParams->Put("selectedIndex", selectedIndex_);
2996             }
2997 
2998             extraParams->Put("insertIndex", insertIndex_);
2999             (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
3000         }
3001     } else {
3002         if (preTargetDragDropNode && preTargetDragDropNode->GetOnDragLeave()) {
3003             (preTargetDragDropNode->GetOnDragLeave())(event, extraParams->ToString());
3004         }
3005 
3006         if (targetDragDropNode && targetDragDropNode->GetOnDragEnter()) {
3007             (targetDragDropNode->GetOnDragEnter())(event, extraParams->ToString());
3008         }
3009 
3010         SetPreTargetRenderNode(targetDragDropNode);
3011     }
3012 }
3013 
ProcessDragEventEnd(const RefPtr<RenderNode> & renderNode,const RefPtr<DragEvent> & event,const Point & globalPoint)3014 void PipelineContext::ProcessDragEventEnd(
3015     const RefPtr<RenderNode>& renderNode, const RefPtr<DragEvent>& event, const Point& globalPoint)
3016 {
3017     auto targetDragDropNode =
3018         AceType::DynamicCast<DragDropEvent>(renderNode->FindDropChild(globalPoint, globalPoint - pageOffset_));
3019     auto initDragDropNode = AceType::DynamicCast<DragDropEvent>(GetInitRenderNode());
3020     auto extraParams = JsonUtil::Create(true);
3021     extraParams->Put("customDragInfo", customDragInfo_.c_str());
3022     extraParams->Put("selectedText", selectedText_.c_str());
3023     extraParams->Put("imageSrc", imageSrc_.c_str());
3024     auto info = GestureEvent();
3025     info.SetGlobalPoint(globalPoint);
3026     auto preTargetDragDropNode = GetPreTargetRenderNode();
3027 
3028     auto textfield = renderNode->FindChildNodeOfClass<RenderTextField>(globalPoint, globalPoint);
3029     if (textfield) {
3030         auto value = textfield->GetEditingValue();
3031         value.Append(selectedText_);
3032         textfield->SetEditingValue(std::move(value));
3033     }
3034 
3035     if (targetDragDropNode && targetDragDropNode->GetOnDrop()) {
3036         auto renderList = renderNode->FindChildNodeOfClass<V2::RenderList>(globalPoint, globalPoint);
3037         if (renderList) {
3038             insertIndex_ = renderList->CalculateInsertIndex(renderList, info, selectedItemSize_);
3039         }
3040 
3041         if (insertIndex_ == static_cast<int32_t>(RenderNode::DEFAULT_INDEX)) {
3042             (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
3043             SetPreTargetRenderNode(nullptr);
3044             SetInitRenderNode(nullptr);
3045             return;
3046         }
3047 
3048         if (targetDragDropNode != initDragDropNode) {
3049             extraParams->Put("selectedIndex", -1);
3050         } else {
3051             extraParams->Put("selectedIndex", selectedIndex_);
3052         }
3053 
3054         extraParams->Put("insertIndex", insertIndex_);
3055         (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
3056     }
3057 
3058     if (initDragDropNode && initDragDropNode->GetOnDrop()) {
3059         (initDragDropNode->GetOnDrop())(event, extraParams->ToString());
3060     }
3061 
3062     SetPreTargetRenderNode(nullptr);
3063     SetInitRenderNode(nullptr);
3064 }
3065 
OnDragEvent(const DragPointerEvent & pointerEvent,DragEventAction action,const RefPtr<NG::FrameNode> & node)3066 void PipelineContext::OnDragEvent(const DragPointerEvent& pointerEvent, DragEventAction action,
3067     const RefPtr<NG::FrameNode>& node)
3068 {
3069     if (!clipboard_) {
3070         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(GetTaskExecutor());
3071     }
3072 
3073     if (!clipboardCallback_) {
3074         auto callback = [weakPipelineContext = WeakClaim(this)](const std::string& data) {
3075             auto pipelineContext = weakPipelineContext.Upgrade();
3076             if (pipelineContext) {
3077                 auto json = JsonUtil::ParseJsonString(data);
3078                 auto newData = JsonUtil::ParseJsonString(json->GetString("newData"));
3079                 pipelineContext->selectedItemSize_.SetWidth(newData->GetDouble("width"));
3080                 pipelineContext->selectedItemSize_.SetHeight(newData->GetDouble("height"));
3081                 pipelineContext->selectedIndex_ = newData->GetInt("selectedIndex");
3082                 pipelineContext->customDragInfo_ = newData->GetString("customDragInfo");
3083                 pipelineContext->selectedText_ = newData->GetString("selectedText");
3084                 pipelineContext->imageSrc_ = newData->GetString("imageSrc");
3085             }
3086         };
3087         clipboardCallback_ = callback;
3088     }
3089 
3090     if (clipboardCallback_) {
3091         clipboard_->GetData(clipboardCallback_);
3092     }
3093 
3094     auto renderNode = GetLastPageRender();
3095     if (!renderNode) {
3096         LOGE("PipelineContext::OnDragEvent renderNode is null.");
3097         return;
3098     }
3099 
3100     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
3101     event->SetX(ConvertPxToVp(Dimension(pointerEvent.x, DimensionUnit::PX)));
3102     event->SetY(ConvertPxToVp(Dimension(pointerEvent.y, DimensionUnit::PX)));
3103 
3104     Point globalPoint(pointerEvent.x, pointerEvent.y);
3105 
3106     if (action == DragEventAction::DRAG_EVENT_START) {
3107         pageOffset_ = GetPageRect().GetOffset();
3108     }
3109 
3110     event->SetPressedKeyCodes(pointerEvent.pressedKeyCodes_);
3111 
3112     if (action != DragEventAction::DRAG_EVENT_END) {
3113         ProcessDragEvent(renderNode, event, globalPoint);
3114     } else {
3115         ProcessDragEventEnd(renderNode, event, globalPoint);
3116     }
3117 }
3118 
FlushWindowBlur()3119 void PipelineContext::FlushWindowBlur()
3120 {
3121     CHECK_RUN_ON(UI);
3122     ACE_FUNCTION_TRACK();
3123 
3124     if (!updateWindowBlurRegionHandler_) {
3125         return;
3126     }
3127 
3128     if (IsJsPlugin()) {
3129         return;
3130     }
3131 
3132     if (IsJsCard()) {
3133         if (!needWindowBlurRegionRefresh_) {
3134             return;
3135         }
3136         std::vector<std::vector<float>> blurRectangles;
3137         if (!windowBlurRegions_.empty()) {
3138             blurRectangles.push_back(std::vector<float> { 1 });
3139         }
3140         updateWindowBlurRegionHandler_(blurRectangles);
3141         needWindowBlurRegionRefresh_ = false;
3142         return;
3143     }
3144     if (!rootElement_) {
3145         LOGE("root element is null");
3146         return;
3147     }
3148     auto renderNode = rootElement_->GetRenderNode();
3149     if (!renderNode) {
3150         LOGE("get renderNode failed");
3151         return;
3152     }
3153 
3154     if (!windowBlurRegions_.empty()) {
3155         renderNode->WindowBlurTest();
3156     }
3157 
3158     float scale = GetViewScale();
3159     if (needWindowBlurRegionRefresh_) {
3160         std::vector<std::vector<float>> blurRectangles;
3161         for (auto& region : windowBlurRegions_) {
3162             std::vector<float> rectArray;
3163             // progress
3164             rectArray.push_back(region.second.progress_);
3165             // style
3166             rectArray.push_back(static_cast<float>(region.second.style_));
3167             for (auto item : region.second.coords_) {
3168                 item.ApplyScaleAndRound(scale);
3169                 const Rect& rect = item.GetRect();
3170                 // rect
3171                 rectArray.push_back(static_cast<float>(rect.Left()));
3172                 rectArray.push_back(static_cast<float>(rect.Top()));
3173                 rectArray.push_back(static_cast<float>(rect.Right()));
3174                 rectArray.push_back(static_cast<float>(rect.Bottom()));
3175                 const Corner& radius = item.GetCorner();
3176                 // roundX roundY
3177                 rectArray.push_back(static_cast<float>(radius.topLeftRadius.GetX().Value()));
3178                 rectArray.push_back(static_cast<float>(radius.topLeftRadius.GetY().Value()));
3179             }
3180             blurRectangles.push_back(rectArray);
3181         }
3182         updateWindowBlurRegionHandler_(blurRectangles);
3183         needWindowBlurRegionRefresh_ = false;
3184     }
3185     if (updateWindowBlurDrawOpHandler_) {
3186         updateWindowBlurDrawOpHandler_();
3187     }
3188 }
3189 
MakeThreadStuck(const std::vector<std::string> & params) const3190 void PipelineContext::MakeThreadStuck(const std::vector<std::string>& params) const
3191 {
3192     int32_t time = StringUtils::StringToInt(params[2]);
3193     if (time < 0 || (params[1] != JS_THREAD_NAME && params[1] != UI_THREAD_NAME)) {
3194         DumpLog::GetInstance().Print("Params illegal, please check!");
3195         return;
3196     }
3197     DumpLog::GetInstance().Print(params[1] + " thread will stuck for " + params[2] + " seconds.");
3198     if (params[1] == JS_THREAD_NAME) {
3199         taskExecutor_->PostTask([time] { ThreadStuckTask(time); }, TaskExecutor::TaskType::JS, "ArkUIThreadStuck");
3200     } else {
3201         taskExecutor_->PostTask([time] { ThreadStuckTask(time); }, TaskExecutor::TaskType::UI, "ArkUIThreadStuck");
3202     }
3203 }
3204 
SetIsKeyEvent(bool isKeyEvent)3205 void PipelineContext::SetIsKeyEvent(bool isKeyEvent)
3206 {
3207     if (focusAnimationManager_) {
3208         isKeyEvent_ = isKeyEvent;
3209         focusAnimationManager_->SetIsKeyEvent(isKeyEvent_);
3210     }
3211 }
3212 
NavigatePage(uint8_t type,const PageTarget & target,const std::string & params)3213 void PipelineContext::NavigatePage(uint8_t type, const PageTarget& target, const std::string& params)
3214 {
3215     auto frontend = weakFrontend_.Upgrade();
3216     if (!frontend) {
3217         LOGE("frontend is nullptr");
3218         return;
3219     }
3220     frontend->NavigatePage(type, target, params);
3221 }
3222 
AddKeyFrame(float fraction,const RefPtr<Curve> & curve,const std::function<void ()> & propertyCallback)3223 void PipelineContext::AddKeyFrame(
3224     float fraction, const RefPtr<Curve>& curve, const std::function<void()>& propertyCallback)
3225 {
3226     if (propertyCallback == nullptr) {
3227         LOGE("failed to add key frame, property callback is null!");
3228         return;
3229     }
3230 
3231     pendingImplicitLayout_.push(false);
3232     auto propertyChangeCallback = [weak = AceType::WeakClaim(this), callback = propertyCallback,
3233                                       id = Container::CurrentId()]() {
3234         ContainerScope scope(id);
3235         auto context = weak.Upgrade();
3236         if (context == nullptr) {
3237             LOGE("failed to add key frame, context is null!");
3238             return;
3239         }
3240 
3241         callback();
3242         if (context->pendingImplicitLayout_.top()) {
3243             context->FlushLayout();
3244         }
3245     };
3246     pendingImplicitLayout_.pop();
3247 
3248 #ifdef ENABLE_ROSEN_BACKEND
3249     RSNode::AddKeyFrame(fraction, NativeCurveHelper::ToNativeCurve(curve), propertyChangeCallback);
3250 #endif
3251 }
3252 
AddKeyFrame(float fraction,const std::function<void ()> & propertyCallback)3253 void PipelineContext::AddKeyFrame(float fraction, const std::function<void()>& propertyCallback)
3254 {
3255     if (propertyCallback == nullptr) {
3256         LOGE("failed to add key frame, property callback is null!");
3257         return;
3258     }
3259 
3260     pendingImplicitLayout_.push(false);
3261     auto propertyChangeCallback = [weak = AceType::WeakClaim(this), callback = propertyCallback,
3262                                       id = Container::CurrentId()]() {
3263         ContainerScope scope(id);
3264         auto context = weak.Upgrade();
3265         if (context == nullptr) {
3266             LOGE("failed to add key frame, context is null!");
3267             return;
3268         }
3269 
3270         callback();
3271         if (context->pendingImplicitLayout_.top()) {
3272             context->FlushLayout();
3273         }
3274     };
3275     pendingImplicitLayout_.pop();
3276 
3277 #ifdef ENABLE_ROSEN_BACKEND
3278     RSNode::AddKeyFrame(fraction, propertyChangeCallback);
3279 #endif
3280 }
3281 
SaveExplicitAnimationOption(const AnimationOption & option)3282 void PipelineContext::SaveExplicitAnimationOption(const AnimationOption& option)
3283 {
3284     explicitAnimationOption_ = option;
3285 }
3286 
CreateExplicitAnimator(const std::function<void ()> & onFinishEvent)3287 void PipelineContext::CreateExplicitAnimator(const std::function<void()>& onFinishEvent)
3288 {
3289     if (!onFinishEvent) {
3290         return;
3291     }
3292     auto animator = CREATE_ANIMATOR(AceType::WeakClaim(this));
3293     animator->AddStopListener([onFinishEvent, weakContext = AceType::WeakClaim(this), id = animator->GetId()] {
3294         auto context = weakContext.Upgrade();
3295         if (!context) {
3296             return;
3297         }
3298         context->PostAsyncEvent(onFinishEvent, "ArkUIAnimatorFinishEvent");
3299         context->explicitAnimators_.erase(id);
3300     });
3301     animator->SetDuration(explicitAnimationOption_.GetDuration());
3302     animator->SetStartDelay(explicitAnimationOption_.GetDelay());
3303     animator->SetIteration(explicitAnimationOption_.GetIteration());
3304     animator->SetTempo(explicitAnimationOption_.GetTempo());
3305     animator->SetAnimationDirection(explicitAnimationOption_.GetAnimationDirection());
3306     animator->SetFillMode(FillMode::FORWARDS);
3307     animator->Play();
3308     explicitAnimators_.emplace(animator->GetId(), animator);
3309 }
3310 
ClearExplicitAnimationOption()3311 void PipelineContext::ClearExplicitAnimationOption()
3312 {
3313     explicitAnimationOption_ = AnimationOption();
3314 }
3315 
GetExplicitAnimationOption() const3316 AnimationOption PipelineContext::GetExplicitAnimationOption() const
3317 {
3318     return explicitAnimationOption_;
3319 }
3320 
GetIsDeclarative() const3321 bool PipelineContext::GetIsDeclarative() const
3322 {
3323     RefPtr<Frontend> front = GetFrontend();
3324     if (front) {
3325         return (front->GetType() == FrontendType::DECLARATIVE_JS ||
3326                 front->GetType() == FrontendType::JS_PLUGIN ||
3327                 front->GetType() == FrontendType::DECLARATIVE_CJ);
3328     }
3329     return false;
3330 }
3331 
SetForbidPlatformQuit(bool forbidPlatformQuit)3332 void PipelineContext::SetForbidPlatformQuit(bool forbidPlatformQuit)
3333 {
3334     forbidPlatformQuit_ = forbidPlatformQuit;
3335     auto stageElement = GetStageElement();
3336     if (!stageElement) {
3337         LOGE("Stage is null.");
3338         return;
3339     }
3340     auto renderStage = AceType::DynamicCast<RenderStage>(stageElement->GetRenderNode());
3341     if (!renderStage) {
3342         LOGE("RenderStage is null.");
3343         return;
3344     }
3345     renderStage->SetForbidSwipeToRight(forbidPlatformQuit_);
3346 }
3347 
AddLayoutTransitionNode(const RefPtr<RenderNode> & node)3348 void PipelineContext::AddLayoutTransitionNode(const RefPtr<RenderNode>& node)
3349 {
3350     CHECK_RUN_ON(UI);
3351     layoutTransitionNodeSet_.insert(node);
3352 }
3353 
AddAlignDeclarationNode(const RefPtr<RenderNode> & node)3354 void PipelineContext::AddAlignDeclarationNode(const RefPtr<RenderNode>& node)
3355 {
3356     CHECK_RUN_ON(UI);
3357     alignDeclarationNodeList_.emplace_front(node);
3358 }
3359 
GetAlignDeclarationNodeList()3360 std::list<RefPtr<RenderNode>>& PipelineContext::GetAlignDeclarationNodeList()
3361 {
3362     CHECK_RUN_ON(UI);
3363     return alignDeclarationNodeList_;
3364 }
3365 
AddScreenOnEvent(std::function<void ()> && func)3366 void PipelineContext::AddScreenOnEvent(std::function<void()>&& func)
3367 {
3368     taskExecutor_->PostTask(
3369         [wp = WeakClaim(this), screenOnFunc = std::move(func)]() mutable {
3370             auto pipeline = wp.Upgrade();
3371             if (pipeline && pipeline->screenOnCallback_) {
3372                 pipeline->screenOnCallback_(std::move(screenOnFunc));
3373             }
3374         },
3375         TaskExecutor::TaskType::PLATFORM, "ArkUIScreenOnEvent");
3376 }
3377 
AddScreenOffEvent(std::function<void ()> && func)3378 void PipelineContext::AddScreenOffEvent(std::function<void()>&& func)
3379 {
3380     taskExecutor_->PostTask(
3381         [wp = WeakClaim(this), screenOffFunc = std::move(func)]() mutable {
3382             auto pipeline = wp.Upgrade();
3383             if (pipeline && pipeline->screenOffCallback_) {
3384                 pipeline->screenOffCallback_(std::move(screenOffFunc));
3385             }
3386         },
3387         TaskExecutor::TaskType::PLATFORM, "ArkUIScreenOffEvent");
3388 }
3389 
IsWindowInScreen()3390 bool PipelineContext::IsWindowInScreen()
3391 {
3392     if (queryIfWindowInScreenCallback_) {
3393         // We post an async task to do async query to avoid thread deadlock between UI thread and Platform thread
3394         taskExecutor_->PostTask(
3395             [wp = WeakClaim(this)] {
3396                 auto pipeline = wp.Upgrade();
3397                 if (!pipeline) {
3398                     return;
3399                 }
3400                 pipeline->queryIfWindowInScreenCallback_();
3401             },
3402             TaskExecutor::TaskType::PLATFORM, "ArkUIQueryIfWindowInScreen");
3403     }
3404     // Note that the result is not real-time result but the result from previous query
3405     return isWindowInScreen_;
3406 }
3407 
NotifyOnPreDraw()3408 void PipelineContext::NotifyOnPreDraw()
3409 {
3410     decltype(nodesToNotifyOnPreDraw_) nodesToNotifyOnPreDraw(std::move(nodesToNotifyOnPreDraw_));
3411     for (const auto& node : nodesToNotifyOnPreDraw) {
3412         node->OnPreDraw();
3413     }
3414 }
3415 
AddNodesToNotifyOnPreDraw(const RefPtr<RenderNode> & renderNode)3416 void PipelineContext::AddNodesToNotifyOnPreDraw(const RefPtr<RenderNode>& renderNode)
3417 {
3418     nodesToNotifyOnPreDraw_.emplace(renderNode);
3419 }
3420 
UpdateNodesNeedDrawOnPixelMap()3421 void PipelineContext::UpdateNodesNeedDrawOnPixelMap()
3422 {
3423     for (const auto& dirtyNode : dirtyRenderNodes_) {
3424         SearchNodesNeedDrawOnPixelMap(dirtyNode);
3425     }
3426     for (const auto& dirtyNode : dirtyRenderNodesInOverlay_) {
3427         SearchNodesNeedDrawOnPixelMap(dirtyNode);
3428     }
3429 }
3430 
SearchNodesNeedDrawOnPixelMap(const RefPtr<RenderNode> & renderNode)3431 void PipelineContext::SearchNodesNeedDrawOnPixelMap(const RefPtr<RenderNode>& renderNode)
3432 {
3433     auto parent = renderNode;
3434     while (parent) {
3435         auto box = AceType::DynamicCast<RenderBox>(parent);
3436         if (box && box->GetPixelMap()) {
3437             nodesNeedDrawOnPixelMap_.emplace(parent);
3438         }
3439         parent = parent->GetParent().Upgrade();
3440     }
3441 }
3442 
NotifyDrawOnPixelMap()3443 void PipelineContext::NotifyDrawOnPixelMap()
3444 {
3445     decltype(nodesNeedDrawOnPixelMap_) nodesNeedDrawOnPixelMap(std::move(nodesNeedDrawOnPixelMap_));
3446     for (const auto& node : nodesNeedDrawOnPixelMap) {
3447         auto box = AceType::DynamicCast<RenderBox>(node);
3448         if (box) {
3449             box->DrawOnPixelMap();
3450         }
3451     }
3452 }
3453 
PushVisibleCallback(NodeId id,double ratio,std::function<void (bool,double)> && func)3454 void PipelineContext::PushVisibleCallback(NodeId id, double ratio, std::function<void(bool, double)>&& func)
3455 {
3456     auto accessibilityManager = GetAccessibilityManager();
3457     if (!accessibilityManager) {
3458         return;
3459     }
3460     accessibilityManager->AddVisibleChangeNode(id, ratio, func);
3461 }
3462 
AddVisibleAreaChangeNode(const ComposeId & nodeId,double ratio,const VisibleRatioCallback & callback)3463 void PipelineContext::AddVisibleAreaChangeNode(
3464     const ComposeId& nodeId, double ratio, const VisibleRatioCallback& callback)
3465 {
3466     VisibleCallbackInfo info;
3467     info.callback = callback;
3468     info.visibleRatio = ratio;
3469     info.isCurrentVisible = false;
3470     auto iter = visibleAreaChangeNodes_.find(nodeId);
3471     if (iter != visibleAreaChangeNodes_.end()) {
3472         auto& callbackList = iter->second;
3473         callbackList.emplace_back(info);
3474     } else {
3475         std::list<VisibleCallbackInfo> callbackList;
3476         callbackList.emplace_back(info);
3477         visibleAreaChangeNodes_[nodeId] = callbackList;
3478     }
3479 }
3480 
RemoveVisibleChangeNode(NodeId id)3481 void PipelineContext::RemoveVisibleChangeNode(NodeId id)
3482 {
3483     auto accessibilityManager = GetAccessibilityManager();
3484     if (!accessibilityManager) {
3485         return;
3486     }
3487     accessibilityManager->RemoveVisibleChangeNode(id);
3488 }
3489 
IsVisibleChangeNodeExists(NodeId index) const3490 bool PipelineContext::IsVisibleChangeNodeExists(NodeId index) const
3491 {
3492     auto accessibilityManager = GetAccessibilityManager();
3493     if (!accessibilityManager) {
3494         return false;
3495     }
3496     return accessibilityManager->IsVisibleChangeNodeExists(index);
3497 }
3498 
SetRSUIDirector(std::shared_ptr<OHOS::Rosen::RSUIDirector> rsUIDirector)3499 void PipelineContext::SetRSUIDirector(std::shared_ptr<OHOS::Rosen::RSUIDirector> rsUIDirector)
3500 {
3501 #ifdef ENABLE_ROSEN_BACKEND
3502     rsUIDirector_ = rsUIDirector;
3503 #endif
3504 }
3505 
GetRSUIDirector()3506 std::shared_ptr<OHOS::Rosen::RSUIDirector> PipelineContext::GetRSUIDirector()
3507 {
3508 #ifdef ENABLE_ROSEN_BACKEND
3509     return rsUIDirector_;
3510 #else
3511     return nullptr;
3512 #endif
3513 }
3514 
StoreNode(int32_t restoreId,const WeakPtr<RenderElement> & node)3515 void PipelineContext::StoreNode(int32_t restoreId, const WeakPtr<RenderElement>& node)
3516 {
3517     auto ret = storeNode_.try_emplace(restoreId, node);
3518     if (!ret.second) {
3519         LOGW("store restore node fail, id = %{public}d", restoreId);
3520         storeNode_[restoreId] = node;
3521     }
3522 }
3523 
GetStoredNodeInfo()3524 std::unique_ptr<JsonValue> PipelineContext::GetStoredNodeInfo()
3525 {
3526     auto jsonNodeInfo = JsonUtil::Create(true);
3527     auto iter = storeNode_.begin();
3528     while (iter != storeNode_.end()) {
3529         auto RenderElement = (iter->second).Upgrade();
3530         if (RenderElement) {
3531             std::string info = RenderElement->ProvideRestoreInfo();
3532             if (!info.empty()) {
3533                 jsonNodeInfo->Put(std::to_string(iter->first).c_str(), info.c_str());
3534             }
3535         }
3536         ++iter;
3537     }
3538     return jsonNodeInfo;
3539 }
3540 
RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)3541 void PipelineContext::RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)
3542 {
3543     if (!nodeInfo->IsValid() || !nodeInfo->IsObject()) {
3544         LOGW("restore nodeInfo is invalid");
3545     }
3546     auto child = nodeInfo->GetChild();
3547     while (child->IsValid()) {
3548         auto key = child->GetKey();
3549         auto value = child->GetString();
3550         int vital = std::atoi(key.c_str());
3551         if (vital == 0) {
3552             LOGE("input %{public}s can not be converted to number.", key.c_str());
3553         }
3554         restoreNodeInfo_.try_emplace(vital, value);
3555         child = child->GetNext();
3556     }
3557 }
3558 
GetRestoreInfo(int32_t restoreId)3559 std::string PipelineContext::GetRestoreInfo(int32_t restoreId)
3560 {
3561     auto iter = restoreNodeInfo_.find(restoreId);
3562     if (iter != restoreNodeInfo_.end()) {
3563         std::string restoreNodeInfo = iter->second;
3564         restoreNodeInfo_.erase(iter);
3565         return restoreNodeInfo;
3566     }
3567     return "";
3568 }
3569 
SetSinglePageId(int32_t pageId)3570 void PipelineContext::SetSinglePageId(int32_t pageId)
3571 {
3572     auto stageElement = GetStageElement();
3573     if (!stageElement) {
3574         LOGE("Get stage element failed!");
3575         return;
3576     }
3577 
3578     stageElement->SetSinglePageId(pageId);
3579 }
3580 
SetAppTitle(const std::string & title)3581 void PipelineContext::SetAppTitle(const std::string& title)
3582 {
3583     CHECK_NULL_VOID(rootElement_);
3584     auto containerModalElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
3585     CHECK_NULL_VOID(containerModalElement);
3586     containerModalElement->SetAppTitle(title);
3587 }
3588 
SetAppIcon(const RefPtr<PixelMap> & icon)3589 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
3590 {
3591     CHECK_NULL_VOID(rootElement_);
3592     auto containerModalElement = AceType::DynamicCast<ContainerModalElement>(rootElement_->GetFirstChild());
3593     CHECK_NULL_VOID(containerModalElement);
3594     containerModalElement->SetAppIcon(icon);
3595 }
3596 
3597 } // namespace OHOS::Ace
3598