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