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