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