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