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