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