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