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