• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_ng/pipeline_context.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 #include <cstdint>
21 #include <memory>
22 
23 #ifdef ENABLE_ROSEN_BACKEND
24 #include "render_service_client/core/transaction/rs_transaction.h"
25 #include "render_service_client/core/ui/rs_ui_director.h"
26 
27 #endif
28 
29 #include "base/geometry/ng/offset_t.h"
30 #include "base/geometry/ng/rect_t.h"
31 #include "base/log/ace_trace.h"
32 #include "base/log/ace_tracker.h"
33 #include "base/log/dump_log.h"
34 #include "base/log/event_report.h"
35 #include "base/memory/ace_type.h"
36 #include "base/memory/referenced.h"
37 #include "base/ressched/ressched_report.h"
38 #include "base/thread/task_executor.h"
39 #include "base/utils/time_util.h"
40 #include "base/utils/utils.h"
41 #include "core/animation/scheduler.h"
42 #include "core/common/ace_application_info.h"
43 #include "core/common/container.h"
44 #include "core/common/font_manager.h"
45 #include "core/common/layout_inspector.h"
46 #include "core/common/text_field_manager.h"
47 #include "core/common/thread_checker.h"
48 #include "core/common/window.h"
49 #include "core/components/common/layout/screen_system_manager.h"
50 #include "core/components_ng/base/frame_node.h"
51 #include "core/components_ng/base/ui_node.h"
52 #include "core/components_ng/pattern/app_bar/app_bar_view.h"
53 #include "core/components_ng/pattern/container_modal/container_modal_pattern.h"
54 #include "core/components_ng/pattern/container_modal/container_modal_view.h"
55 #include "core/components_ng/pattern/container_modal/container_modal_view_factory.h"
56 #include "core/components_ng/pattern/custom/custom_node_base.h"
57 #include "core/components_ng/pattern/image/image_layout_property.h"
58 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
59 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
60 #include "core/components_ng/pattern/navigation/title_bar_node.h"
61 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
62 #include "core/components_ng/pattern/overlay/overlay_manager.h"
63 #include "core/components_ng/pattern/root/root_pattern.h"
64 #include "core/components_ng/pattern/stage/stage_pattern.h"
65 #include "core/components_ng/pattern/text_field/text_field_manager.h"
66 #include "core/components_ng/property/calc_length.h"
67 #include "core/components_ng/property/measure_property.h"
68 #include "core/components_ng/property/safe_area_insets.h"
69 #include "core/components_v2/inspector/inspector_constants.h"
70 #include "core/event/ace_events.h"
71 #include "core/event/touch_event.h"
72 #include "core/pipeline/base/element_register.h"
73 #include "core/pipeline/pipeline_context.h"
74 #include "core/pipeline_ng/ui_task_scheduler.h"
75 
76 namespace {
77 constexpr int32_t TIME_THRESHOLD = 2 * 1000000; // 3 millisecond
78 constexpr int32_t PLATFORM_VERSION_TEN = 10;
79 constexpr int32_t MILLISECONDS_TO_NANOSECONDS = 1000000; // Milliseconds to nanoseconds
80 } // namespace
81 
82 namespace OHOS::Ace::NG {
83 
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,RefPtr<PlatformResRegister> platformResRegister,const RefPtr<Frontend> & frontend,int32_t instanceId)84 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
85     RefPtr<AssetManager> assetManager, RefPtr<PlatformResRegister> platformResRegister,
86     const RefPtr<Frontend>& frontend, int32_t instanceId)
87     : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId, platformResRegister)
88 {
89     window_->OnHide();
90 }
91 
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend,int32_t instanceId)92 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
93     RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend, int32_t instanceId)
94     : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId)
95 {
96     window_->OnHide();
97 }
98 
GetCurrentContext()99 RefPtr<PipelineContext> PipelineContext::GetCurrentContext()
100 {
101     auto currentContainer = Container::Current();
102     CHECK_NULL_RETURN(currentContainer, nullptr);
103     return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
104 }
105 
GetCurrentRootWidth()106 float PipelineContext::GetCurrentRootWidth()
107 {
108     auto context = GetCurrentContext();
109     CHECK_NULL_RETURN(context, 0.0f);
110     return static_cast<float>(context->rootWidth_);
111 }
112 
GetCurrentRootHeight()113 float PipelineContext::GetCurrentRootHeight()
114 {
115     auto context = GetCurrentContext();
116     CHECK_NULL_RETURN(context, 0.0f);
117     return static_cast<float>(context->rootHeight_);
118 }
119 
AddDirtyCustomNode(const RefPtr<UINode> & dirtyNode)120 void PipelineContext::AddDirtyCustomNode(const RefPtr<UINode>& dirtyNode)
121 {
122     CHECK_RUN_ON(UI);
123     CHECK_NULL_VOID(dirtyNode);
124     dirtyNodes_.emplace(dirtyNode);
125     hasIdleTasks_ = true;
126     RequestFrame();
127 }
128 
AddDirtyLayoutNode(const RefPtr<FrameNode> & dirty)129 void PipelineContext::AddDirtyLayoutNode(const RefPtr<FrameNode>& dirty)
130 {
131     CHECK_RUN_ON(UI);
132     CHECK_NULL_VOID(dirty);
133     taskScheduler_->AddDirtyLayoutNode(dirty);
134     ForceLayoutForImplicitAnimation();
135 #ifdef UICAST_COMPONENT_SUPPORTED
136     do {
137         auto container = Container::Current();
138         CHECK_NULL_BREAK(container);
139         auto distributedUI = container->GetDistributedUI();
140         CHECK_NULL_BREAK(distributedUI);
141         distributedUI->AddDirtyLayoutNode(dirty->GetId());
142     } while (false);
143 #endif
144     hasIdleTasks_ = true;
145     RequestFrame();
146 }
147 
AddDirtyRenderNode(const RefPtr<FrameNode> & dirty)148 void PipelineContext::AddDirtyRenderNode(const RefPtr<FrameNode>& dirty)
149 {
150     CHECK_RUN_ON(UI);
151     CHECK_NULL_VOID(dirty);
152     taskScheduler_->AddDirtyRenderNode(dirty);
153     ForceRenderForImplicitAnimation();
154 #ifdef UICAST_COMPONENT_SUPPORTED
155     do {
156         auto container = Container::Current();
157         CHECK_NULL_BREAK(container);
158         auto distributedUI = container->GetDistributedUI();
159         CHECK_NULL_BREAK(distributedUI);
160         distributedUI->AddDirtyRenderNode(dirty->GetId());
161     } while (false);
162 #endif
163     hasIdleTasks_ = true;
164     RequestFrame();
165 }
166 
FlushDirtyNodeUpdate()167 void PipelineContext::FlushDirtyNodeUpdate()
168 {
169     CHECK_RUN_ON(UI);
170     ACE_FUNCTION_TRACE();
171     if (FrameReport::GetInstance().GetEnable()) {
172         FrameReport::GetInstance().BeginFlushBuild();
173     }
174 
175     // SomeTimes, customNode->Update may add some dirty custom nodes to dirtyNodes_,
176     // use maxFlushTimes to avoid dead cycle.
177     int maxFlushTimes = 3;
178     while (!dirtyNodes_.empty() && maxFlushTimes > 0) {
179         decltype(dirtyNodes_) dirtyNodes(std::move(dirtyNodes_));
180         for (const auto& node : dirtyNodes) {
181             if (AceType::InstanceOf<NG::CustomNodeBase>(node)) {
182                 auto customNode = AceType::DynamicCast<NG::CustomNodeBase>(node);
183                 ACE_SCOPED_TRACE("CustomNodeUpdate %s", customNode->GetJSViewName().c_str());
184                 customNode->Update();
185             }
186         }
187         --maxFlushTimes;
188     }
189     if (!dirtyNodes_.empty()) {
190         LOGW("FlushDirtyNodeUpdate 3 times, still has dirty nodes");
191     }
192 
193     if (FrameReport::GetInstance().GetEnable()) {
194         FrameReport::GetInstance().EndFlushBuild();
195     }
196 }
197 
AddScheduleTask(const RefPtr<ScheduleTask> & task)198 uint32_t PipelineContext::AddScheduleTask(const RefPtr<ScheduleTask>& task)
199 {
200     CHECK_RUN_ON(UI);
201     scheduleTasks_.try_emplace(++nextScheduleTaskId_, task);
202     RequestFrame();
203     return nextScheduleTaskId_;
204 }
205 
RemoveScheduleTask(uint32_t id)206 void PipelineContext::RemoveScheduleTask(uint32_t id)
207 {
208     CHECK_RUN_ON(UI);
209     scheduleTasks_.erase(id);
210 }
211 
FlushVsync(uint64_t nanoTimestamp,uint32_t frameCount)212 void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount)
213 {
214     CHECK_RUN_ON(UI);
215     ACE_FUNCTION_TRACE();
216     auto recvTime = GetSysTimestamp();
217     static const std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
218                                                ? AceApplicationInfo::GetInstance().GetPackageName()
219                                                : AceApplicationInfo::GetInstance().GetProcessName();
220     window_->RecordFrameTime(nanoTimestamp, abilityName);
221     FlushFrameTrace();
222 #ifdef UICAST_COMPONENT_SUPPORTED
223     do {
224         auto container = Container::Current();
225         CHECK_NULL_BREAK(container);
226         auto distributedUI = container->GetDistributedUI();
227         CHECK_NULL_BREAK(distributedUI);
228         distributedUI->ApplyOneUpdate();
229     } while (false);
230 #endif
231     ProcessDelayTasks();
232     FlushAnimation(GetTimeFromExternalTimer());
233     FlushTouchEvents();
234     FlushBuild();
235     if (isFormRender_ && drawDelegate_ && rootNode_) {
236         auto renderContext = AceType::DynamicCast<NG::RenderContext>(rootNode_->GetRenderContext());
237         drawDelegate_->DrawRSFrame(renderContext);
238         drawDelegate_ = nullptr;
239     }
240     if (!taskScheduler_->isEmpty()) {
241 #if !defined(PREVIEW)
242         LayoutInspector::SupportInspector();
243 #endif
244     }
245 
246     taskScheduler_->StartRecordFrameInfo(GetCurrentFrameInfo(recvTime, nanoTimestamp));
247     taskScheduler_->FlushTask();
248     taskScheduler_->FinishRecordFrameInfo();
249     FlushAnimationClosure();
250     TryCallNextFrameLayoutCallback();
251 
252 #ifdef UICAST_COMPONENT_SUPPORTED
253     do {
254         auto container = Container::Current();
255         CHECK_NULL_BREAK(container);
256         auto distributedUI = container->GetDistributedUI();
257         CHECK_NULL_BREAK(distributedUI);
258         distributedUI->OnTreeUpdate();
259     } while (false);
260 #endif
261 
262     bool hasAnimation = window_->FlushCustomAnimation(nanoTimestamp);
263     if (hasAnimation) {
264         RequestFrame();
265     }
266     if (dragCleanTask_) {
267         dragCleanTask_();
268         dragCleanTask_ = nullptr;
269     }
270     FlushMessages();
271     InspectDrew();
272     if (!isFormRender_ && onShow_ && onFocus_) {
273         FlushFocus();
274     }
275     HandleOnAreaChangeEvent();
276     HandleVisibleAreaChangeEvent();
277     if (isNeedFlushMouseEvent_) {
278         FlushMouseEvent();
279         isNeedFlushMouseEvent_ = false;
280     }
281     needRenderNode_.clear();
282     taskScheduler_->FlushAfterRenderTask();
283     // Keep the call sent at the end of the function
284     if (FrameReport::GetInstance().GetEnable()) {
285         FrameReport::GetInstance().FlushEnd();
286     }
287     ResSchedReport::GetInstance().LoadPageEvent(ResDefine::LOAD_PAGE_COMPLETE_EVENT);
288 }
289 
InspectDrew()290 void PipelineContext::InspectDrew()
291 {
292     CHECK_RUN_ON(UI);
293     if (!needRenderNode_.empty()) {
294         auto needRenderNode = std::move(needRenderNode_);
295         for (auto&& node : needRenderNode) {
296             if (node) {
297                 OnDrawCompleted(node->GetInspectorId()->c_str());
298             }
299         }
300     }
301 }
302 
ProcessDelayTasks()303 void PipelineContext::ProcessDelayTasks()
304 {
305     if (delayedTasks_.empty()) {
306         return;
307     }
308     auto currentTimeStamp = GetSysTimestamp();
309     auto delayedTasks = std::move(delayedTasks_);
310     auto result = std::remove_if(delayedTasks.begin(), delayedTasks.end(), [this, currentTimeStamp](const auto& task) {
311         if (task.timeStamp + static_cast<int64_t>(task.time) * MILLISECONDS_TO_NANOSECONDS > currentTimeStamp) {
312             delayedTasks_.emplace_back(task);
313             return true;
314         }
315         return false;
316     });
317     delayedTasks.erase(result, delayedTasks.end());
318     std::for_each(delayedTasks.begin(), delayedTasks.end(), [this](auto& delayedTask) {
319         if (delayedTask.task) {
320             delayedTask.task();
321         }
322     });
323 }
324 
FlushFrameTrace()325 void PipelineContext::FlushFrameTrace()
326 {
327     if (FrameReport::GetInstance().GetEnable()) {
328         FrameReport::GetInstance().FlushBegin();
329     }
330 }
331 
FlushAnimation(uint64_t nanoTimestamp)332 void PipelineContext::FlushAnimation(uint64_t nanoTimestamp)
333 {
334     CHECK_RUN_ON(UI);
335     ACE_FUNCTION_TRACE();
336     if (scheduleTasks_.empty()) {
337         return;
338     }
339 
340     if (FrameReport::GetInstance().GetEnable()) {
341         FrameReport::GetInstance().BeginFlushAnimation();
342     }
343 
344     decltype(scheduleTasks_) temp(std::move(scheduleTasks_));
345     for (const auto& [id, weakTask] : temp) {
346         auto task = weakTask.Upgrade();
347         if (task) {
348             task->OnFrame(nanoTimestamp);
349         }
350     }
351 
352     if (FrameReport::GetInstance().GetEnable()) {
353         FrameReport::GetInstance().EndFlushAnimation();
354     }
355 }
356 
FlushMessages()357 void PipelineContext::FlushMessages()
358 {
359     ACE_FUNCTION_TRACE();
360     window_->FlushTasks();
361 }
362 
SetNeedRenderNode(const RefPtr<FrameNode> & node)363 void PipelineContext::SetNeedRenderNode(const RefPtr<FrameNode>& node)
364 {
365     CHECK_RUN_ON(UI);
366     needRenderNode_.insert(node);
367 }
368 
NotifyConfigurationChange(const OnConfigurationChange & configurationChange)369 void PipelineContext::NotifyConfigurationChange(const OnConfigurationChange& configurationChange)
370 {
371     LOGI("NotifyConfigurationChange");
372     auto rootNode = GetRootElement();
373     rootNode->UpdateConfigurationUpdate(configurationChange);
374     PipelineBase::NotifyConfigurationChange(configurationChange);
375 }
376 
FlushFocus()377 void PipelineContext::FlushFocus()
378 {
379     CHECK_RUN_ON(UI);
380     ACE_FUNCTION_TRACK();
381     ACE_FUNCTION_TRACE();
382 
383     auto defaultFocusNode = dirtyDefaultFocusNode_.Upgrade();
384     if (!defaultFocusNode) {
385         dirtyDefaultFocusNode_.Reset();
386     } else {
387         auto focusNodeHub = defaultFocusNode->GetFocusHub();
388         if (focusNodeHub) {
389             auto defaultFocusNode = focusNodeHub->GetChildFocusNodeByType();
390             if (defaultFocusNode && defaultFocusNode->IsFocusableWholePath()) {
391                 defaultFocusNode->RequestFocusImmediately();
392             } else {
393                 focusNodeHub->RequestFocusImmediately();
394             }
395         }
396         dirtyFocusNode_.Reset();
397         dirtyFocusScope_.Reset();
398         dirtyDefaultFocusNode_.Reset();
399         return;
400     }
401 
402     auto focusNode = dirtyFocusNode_.Upgrade();
403     if (!focusNode || focusNode->GetFocusType() != FocusType::NODE) {
404         dirtyFocusNode_.Reset();
405     } else {
406         auto focusNodeHub = focusNode->GetFocusHub();
407         if (focusNodeHub) {
408             focusNodeHub->RequestFocusImmediately();
409         }
410         dirtyFocusNode_.Reset();
411         dirtyFocusScope_.Reset();
412         dirtyDefaultFocusNode_.Reset();
413         return;
414     }
415     auto focusScope = dirtyFocusScope_.Upgrade();
416     if (!focusScope || focusScope->GetFocusType() != FocusType::SCOPE) {
417         dirtyFocusScope_.Reset();
418     } else {
419         auto focusScopeHub = focusScope->GetFocusHub();
420         if (focusScopeHub) {
421             focusScopeHub->RequestFocusImmediately();
422         }
423         dirtyFocusNode_.Reset();
424         dirtyFocusScope_.Reset();
425         dirtyDefaultFocusNode_.Reset();
426         return;
427     }
428     if (isRootFocusNeedUpdate_ && rootNode_ && rootNode_->GetFocusHub()) {
429         auto rootFocusHub = rootNode_->GetFocusHub();
430         if (!rootFocusHub->IsCurrentFocus()) {
431             rootFocusHub->RequestFocusImmediately();
432         } else if (!rootFocusHub->IsCurrentFocusWholePath()) {
433             rootFocusHub->LostFocus();
434             rootFocusHub->RequestFocusImmediately();
435         }
436         isRootFocusNeedUpdate_ = false;
437     }
438 }
439 
FlushPipelineImmediately()440 void PipelineContext::FlushPipelineImmediately()
441 {
442     CHECK_RUN_ON(UI);
443     ACE_FUNCTION_TRACE();
444     FlushPipelineWithoutAnimation();
445 }
446 
FlushPipelineWithoutAnimation()447 void PipelineContext::FlushPipelineWithoutAnimation()
448 {
449     ACE_FUNCTION_TRACE();
450     FlushBuild();
451     FlushTouchEvents();
452     taskScheduler_->FlushTask();
453     FlushAnimationClosure();
454     FlushMessages();
455     FlushFocus();
456 }
457 
FlushBuild()458 void PipelineContext::FlushBuild()
459 {
460     isRebuildFinished_ = false;
461     FlushDirtyNodeUpdate();
462     isRebuildFinished_ = true;
463     FlushBuildFinishCallbacks();
464 }
465 
AddAnimationClosure(std::function<void ()> && animation)466 void PipelineContext::AddAnimationClosure(std::function<void()>&& animation)
467 {
468     animationClosuresList_.emplace_back(std::move(animation));
469 }
470 
FlushAnimationClosure()471 void PipelineContext::FlushAnimationClosure()
472 {
473     if (animationClosuresList_.empty()) {
474         return;
475     }
476     taskScheduler_->FlushTask();
477 
478     decltype(animationClosuresList_) temp(std::move(animationClosuresList_));
479     auto scheduler = std::move(taskScheduler_);
480     taskScheduler_ = std::make_unique<UITaskScheduler>();
481     for (const auto& animation : temp) {
482         animation();
483         taskScheduler_->CleanUp();
484     }
485     taskScheduler_ = std::move(scheduler);
486 }
487 
FlushBuildFinishCallbacks()488 void PipelineContext::FlushBuildFinishCallbacks()
489 {
490     decltype(buildFinishCallbacks_) buildFinishCallbacks(std::move(buildFinishCallbacks_));
491     for (const auto& func : buildFinishCallbacks) {
492         if (func) {
493             func();
494         }
495     }
496 }
497 
RegisterRootEvent()498 void PipelineContext::RegisterRootEvent()
499 {
500     if (!IsFormRender()) {
501         return;
502     }
503 
504     // To avoid conflicts between longPress and click events on the card,
505     // use an empty longPress event placeholder in the EtsCard scenario
506     auto hub = rootNode_->GetOrCreateGestureEventHub();
507     CHECK_NULL_VOID(hub);
508     auto event = [](const GestureEvent& info) mutable { LOGD("Not Support LongPress"); };
509     auto longPress = AceType::MakeRefPtr<NG::LongPressEvent>(std::move(event));
510     hub->SetLongPressEvent(longPress, false, true);
511 }
512 
SetupRootElement()513 void PipelineContext::SetupRootElement()
514 {
515     CHECK_RUN_ON(UI);
516     rootNode_ = FrameNode::CreateFrameNodeWithTree(
517         V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
518     rootNode_->SetHostRootId(GetInstanceId());
519     rootNode_->SetHostPageId(-1);
520     rootNode_->SetActive(true);
521     RegisterRootEvent();
522     CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
523     MeasureProperty layoutConstraint;
524     layoutConstraint.selfIdealSize = idealSize;
525     layoutConstraint.maxSize = idealSize;
526     rootNode_->UpdateLayoutConstraint(layoutConstraint);
527     auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
528     rootFocusHub->SetFocusType(FocusType::SCOPE);
529     rootFocusHub->SetFocusable(true);
530     window_->SetRootFrameNode(rootNode_);
531     rootNode_->AttachToMainTree();
532 
533     auto stageNode = FrameNode::CreateFrameNode(
534         V2::STAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<StagePattern>());
535     auto atomicService = installationFree_ ? AppBarView::Create(stageNode) : nullptr;
536     if (windowModal_ == WindowModal::CONTAINER_MODAL) {
537         MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();
538         rootNode_->AddChild(
539             ContainerModalViewFactory::GetView(atomicService ? atomicService : stageNode, maximizeMode));
540     } else {
541         rootNode_->AddChild(atomicService ? atomicService : stageNode);
542     }
543 #ifdef ENABLE_ROSEN_BACKEND
544     if (!IsJsCard() && !isFormRender_) {
545         auto window = GetWindow();
546         if (window) {
547             auto rsUIDirector = window->GetRSUIDirector();
548             if (rsUIDirector) {
549                 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
550             }
551         }
552     }
553 #endif
554     stageManager_ = MakeRefPtr<StageManager>(stageNode);
555     overlayManager_ = MakeRefPtr<OverlayManager>(
556         DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
557     fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
558     selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
559     dragDropManager_ = MakeRefPtr<DragDropManager>();
560     sharedTransitionManager_ = MakeRefPtr<SharedOverlayManager>(
561         DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
562 
563     OnAreaChangedFunc onAreaChangedFunc = [weakOverlayManger = AceType::WeakClaim(AceType::RawPtr(overlayManager_))](
564                                               const RectF& /* oldRect */, const OffsetF& /* oldOrigin */,
565                                               const RectF& /* rect */, const OffsetF& /* origin */) {
566         auto overlay = weakOverlayManger.Upgrade();
567         CHECK_NULL_VOID(overlay);
568         overlay->HideAllMenus();
569         overlay->HideCustomPopups();
570     };
571     rootNode_->SetOnAreaChangeCallback(std::move(onAreaChangedFunc));
572     AddOnAreaChangeNode(rootNode_->GetId());
573 
574     LOGI("SetupRootElement success!");
575 }
576 
SetupSubRootElement()577 void PipelineContext::SetupSubRootElement()
578 {
579     CHECK_RUN_ON(UI);
580     appBgColor_ = Color::TRANSPARENT;
581     rootNode_ = FrameNode::CreateFrameNodeWithTree(
582         V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
583     rootNode_->SetHostRootId(GetInstanceId());
584     rootNode_->SetHostPageId(-1);
585     rootNode_->SetActive(true);
586     CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
587     MeasureProperty layoutConstraint;
588     layoutConstraint.selfIdealSize = idealSize;
589     layoutConstraint.maxSize = idealSize;
590     rootNode_->UpdateLayoutConstraint(layoutConstraint);
591     auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
592     rootFocusHub->SetFocusType(FocusType::SCOPE);
593     rootFocusHub->SetFocusable(true);
594     window_->SetRootFrameNode(rootNode_);
595     rootNode_->AttachToMainTree();
596 
597 #ifdef ENABLE_ROSEN_BACKEND
598     if (!IsJsCard()) {
599         auto window = GetWindow();
600         if (window) {
601             auto rsUIDirector = window->GetRSUIDirector();
602             if (rsUIDirector) {
603                 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
604             }
605         }
606     }
607 #endif
608     // the subwindow for overlay not need stage
609     stageManager_ = MakeRefPtr<StageManager>(nullptr);
610     overlayManager_ = MakeRefPtr<OverlayManager>(rootNode_);
611     fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
612     selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
613     dragDropManager_ = MakeRefPtr<DragDropManager>();
614 }
615 
GetStageManager()616 const RefPtr<StageManager>& PipelineContext::GetStageManager()
617 {
618     return stageManager_;
619 }
620 
GetDragDropManager()621 const RefPtr<DragDropManager>& PipelineContext::GetDragDropManager()
622 {
623     return dragDropManager_;
624 }
625 
GetSelectOverlayManager()626 const RefPtr<SelectOverlayManager>& PipelineContext::GetSelectOverlayManager()
627 {
628     return selectOverlayManager_;
629 }
630 
GetOverlayManager()631 const RefPtr<OverlayManager>& PipelineContext::GetOverlayManager()
632 {
633     return overlayManager_;
634 }
635 
GetFullScreenManager()636 const RefPtr<FullScreenManager>& PipelineContext::GetFullScreenManager()
637 {
638     return fullScreenManager_;
639 }
640 
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)641 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type,
642     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
643 {
644     CHECK_RUN_ON(UI);
645     LOGD("PipelineContext: OnSurfaceChanged start.");
646     if (NearEqual(rootWidth_, width) && NearEqual(rootHeight_, height) &&
647         type == WindowSizeChangeReason::CUSTOM_ANIMATION) {
648         TryCallNextFrameLayoutCallback();
649         return;
650     }
651     ExecuteSurfaceChangedCallbacks(width, height, type);
652     // TODO: add adjust for textFieldManager when ime is show.
653     auto callback = [weakFrontend = weakFrontend_, width, height]() {
654         auto frontend = weakFrontend.Upgrade();
655         if (frontend) {
656             frontend->OnSurfaceChanged(width, height);
657         }
658     };
659     auto container = Container::Current();
660     if (!container) {
661         return;
662     }
663     if (container->IsUseStageModel()) {
664         callback();
665         FlushBuild();
666     } else {
667         taskExecutor_->PostTask(callback, TaskExecutor::TaskType::JS);
668     }
669 
670     FlushWindowSizeChangeCallback(width, height, type);
671 
672 #ifdef ENABLE_ROSEN_BACKEND
673     StartWindowSizeChangeAnimate(width, height, type, rsTransaction);
674 #else
675     SetRootRect(width, height, 0.0);
676 #endif
677 }
678 
OnLayoutCompleted(const std::string & componentId)679 void PipelineContext::OnLayoutCompleted(const std::string& componentId)
680 {
681     CHECK_RUN_ON(UI);
682     auto frontend = weakFrontend_.Upgrade();
683     if (frontend) {
684         frontend->OnLayoutCompleted(componentId);
685     }
686 }
687 
OnDrawCompleted(const std::string & componentId)688 void PipelineContext::OnDrawCompleted(const std::string& componentId)
689 {
690     CHECK_RUN_ON(UI);
691     auto frontend = weakFrontend_.Upgrade();
692     if (frontend) {
693         frontend->OnDrawCompleted(componentId);
694     }
695 }
696 
ExecuteSurfaceChangedCallbacks(int32_t newWidth,int32_t newHeight,WindowSizeChangeReason type)697 void PipelineContext::ExecuteSurfaceChangedCallbacks(int32_t newWidth, int32_t newHeight, WindowSizeChangeReason type)
698 {
699     for (auto&& [id, callback] : surfaceChangedCallbackMap_) {
700         if (callback) {
701             callback(newWidth, newHeight, rootWidth_, rootHeight_, type);
702         }
703     }
704 }
705 
OnSurfacePositionChanged(int32_t posX,int32_t posY)706 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
707 {
708     for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
709         if (callback) {
710             callback(posX, posY);
711         }
712     }
713 }
714 
StartWindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)715 void PipelineContext::StartWindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type,
716     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
717 {
718     static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
719     if (!IsWindowSizeAnimationEnabled) {
720         LOGE("no animation configured");
721         SetRootRect(width, height, 0.0);
722         return;
723     }
724     switch (type) {
725         case WindowSizeChangeReason::RECOVER:
726         case WindowSizeChangeReason::MAXIMIZE: {
727             LOGI("PipelineContext::Root node RECOVER/MAXIMIZE animation, width = %{public}d, height = %{public}d",
728                 width, height);
729             AnimationOption option;
730             constexpr int32_t duration = 400;
731             option.SetDuration(duration);
732             auto curve = MakeRefPtr<DecelerationCurve>();
733             option.SetCurve(curve);
734             auto weak = WeakClaim(this);
735             Animate(option, curve, [width, height, weak]() {
736                 auto pipeline = weak.Upgrade();
737                 CHECK_NULL_VOID(pipeline);
738                 pipeline->SetRootRect(width, height, 0.0);
739                 pipeline->FlushUITasks();
740             });
741             break;
742         }
743         case WindowSizeChangeReason::ROTATION: {
744             SetRootRect(width, height, 0.0);
745             FlushUITasks();
746             if (textFieldManager_) {
747                 DynamicCast<TextFieldManagerNG>(textFieldManager_)->ScrollTextFieldToSafeArea();
748             }
749             FlushUITasks();
750             break;
751         }
752         case WindowSizeChangeReason::DRAG_START:
753         case WindowSizeChangeReason::DRAG:
754         case WindowSizeChangeReason::DRAG_END:
755         case WindowSizeChangeReason::RESIZE:
756         case WindowSizeChangeReason::UNDEFINED:
757         default: {
758             LOGD("PipelineContext::RootNodeAnimation : unsupported type, no animation added");
759             SetRootRect(width, height, 0.0f);
760         }
761     }
762 }
763 
SetRootRect(double width,double height,double offset)764 void PipelineContext::SetRootRect(double width, double height, double offset)
765 {
766     LOGI("SetRootRect width %{public}f, height %{public}f, %{public}f", width, height, offset);
767     CHECK_RUN_ON(UI);
768     UpdateRootSizeAndScale(width, height);
769     CHECK_NULL_VOID(rootNode_);
770     ScreenSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
771     ScreenSystemManager::GetInstance().OnSurfaceChanged(width);
772     SizeF sizeF { static_cast<float>(width), static_cast<float>(height) };
773     if (rootNode_->GetGeometryNode()->GetFrameSize() != sizeF || rootNode_->IsLayoutDirtyMarked()) {
774         CalcSize idealSize { CalcLength(width), CalcLength(height) };
775         MeasureProperty layoutConstraint;
776         layoutConstraint.selfIdealSize = idealSize;
777         layoutConstraint.maxSize = idealSize;
778         rootNode_->UpdateLayoutConstraint(layoutConstraint);
779         // reset parentLayoutConstraint to update itself when next measure task
780         rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
781         rootNode_->MarkDirtyNode();
782     }
783     if (rootNode_->GetGeometryNode()->GetFrameOffset().GetY() != offset) {
784         OffsetF newOffset = rootNode_->GetGeometryNode()->GetFrameOffset();
785         newOffset.SetY(static_cast<float>(offset));
786         rootNode_->GetGeometryNode()->SetMarginFrameOffset(newOffset);
787         auto rootContext = rootNode_->GetRenderContext();
788         rootContext->SyncGeometryProperties(RawPtr(rootNode_->GetGeometryNode()));
789         RequestFrame();
790     }
791 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
792     // For cross-platform build, flush tasks when first resize, speed up for fisrt frame.
793     if (window_ && rootNode_->GetRenderContext() && !NearZero(width) && !NearZero(height)) {
794         rootNode_->GetRenderContext()->SetBounds(0.0, 0.0, width, height);
795         window_->FlushTasks();
796         FlushVsync(GetTimeFromExternalTimer(), 0);
797     }
798 #endif
799 }
800 
UpdateSystemSafeArea(const SafeAreaInsets & systemSafeArea)801 void PipelineContext::UpdateSystemSafeArea(const SafeAreaInsets& systemSafeArea)
802 {
803     CHECK_NULL_VOID_NOLOG(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
804     AnimationOption option;
805     CHECK_NULL_VOID_NOLOG(safeAreaManager_);
806     option.SetCurve(safeAreaManager_->GetSafeAreaCurve());
807     AnimationUtils::Animate(option, [weak = WeakClaim(this), systemSafeArea]() {
808         auto pipeline = weak.Upgrade();
809         CHECK_NULL_VOID_NOLOG(pipeline);
810         auto safeAreaManager = pipeline->GetSafeAreaManager();
811         CHECK_NULL_VOID_NOLOG(safeAreaManager);
812         if (safeAreaManager->UpdateSystemSafeArea(systemSafeArea)) {
813             pipeline->SyncSafeArea();
814             pipeline->FlushUITasks();
815         }
816     });
817 }
818 
UpdateCutoutSafeArea(const SafeAreaInsets & cutoutSafeArea)819 void PipelineContext::UpdateCutoutSafeArea(const SafeAreaInsets& cutoutSafeArea)
820 {
821     CHECK_NULL_VOID_NOLOG(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
822     AnimationOption option;
823     CHECK_NULL_VOID_NOLOG(safeAreaManager_);
824     option.SetCurve(safeAreaManager_->GetSafeAreaCurve());
825     AnimationUtils::Animate(option, [weak = WeakClaim(this), cutoutSafeArea]() {
826         auto pipeline = weak.Upgrade();
827         CHECK_NULL_VOID_NOLOG(pipeline);
828         auto safeAreaManager = pipeline->GetSafeAreaManager();
829         CHECK_NULL_VOID_NOLOG(safeAreaManager);
830         if (safeAreaManager->UpdateCutoutSafeArea(cutoutSafeArea)) {
831             pipeline->SyncSafeArea();
832             pipeline->FlushUITasks();
833         }
834     });
835 }
836 
SetIgnoreViewSafeArea(bool value)837 void PipelineContext::SetIgnoreViewSafeArea(bool value)
838 {
839     if (safeAreaManager_->SetIgnoreSafeArea(value)) {
840         SyncSafeArea();
841     }
842 }
843 
SetIsLayoutFullScreen(bool value)844 void PipelineContext::SetIsLayoutFullScreen(bool value)
845 {
846     if (safeAreaManager_->SetIsFullScreen(value)) {
847         SyncSafeArea();
848     }
849 }
850 
GetSafeArea() const851 PipelineBase::SafeAreaInsets PipelineContext::GetSafeArea() const
852 {
853     return safeAreaManager_->GetSafeArea();
854 }
855 
SyncSafeArea(bool onKeyboard)856 void PipelineContext::SyncSafeArea(bool onKeyboard)
857 {
858     CHECK_NULL_VOID_NOLOG(rootNode_);
859     rootNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
860     CHECK_NULL_VOID_NOLOG(stageManager_);
861     auto page = stageManager_->GetLastPage();
862     if (page) {
863         page->MarkDirtyNode(onKeyboard ? PROPERTY_UPDATE_LAYOUT : PROPERTY_UPDATE_MEASURE);
864     }
865     if (overlayManager_) {
866         overlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
867     }
868     if (selectOverlayManager_) {
869         selectOverlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
870     }
871     auto&& restoreNodes = safeAreaManager_->GetGeoRestoreNodes();
872     for (auto&& wk : restoreNodes) {
873         auto node = wk.Upgrade();
874         if (node) {
875             node->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
876         }
877     }
878 }
879 
OnVirtualKeyboardHeightChange(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)880 void PipelineContext::OnVirtualKeyboardHeightChange(
881     float keyboardHeight, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
882 {
883     CHECK_RUN_ON(UI);
884     // prevent repeated trigger with same keyboardHeight
885     if (keyboardHeight == safeAreaManager_->GetKeyboardInset().Length()) {
886         return;
887     }
888 
889     ACE_FUNCTION_TRACE();
890 #ifdef ENABLE_ROSEN_BACKEND
891     if (rsTransaction) {
892         FlushMessages();
893         rsTransaction->Begin();
894     }
895 #endif
896     safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
897     if (keyboardHeight > 0) {
898         // add height of navigation bar
899         keyboardHeight += safeAreaManager_->GetSystemSafeArea().bottom_.Length();
900     }
901     auto func = [this, keyboardHeight]() {
902         float positionY = 0.0f;
903         auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
904         float height = 0.0f;
905         if (manager) {
906             height = manager->GetHeight();
907             positionY = static_cast<float>(manager->GetClickPosition().GetY());
908         }
909         SizeF rootSize { static_cast<float>(rootWidth_), static_cast<float>(rootHeight_) };
910         float keyboardOffset = safeAreaManager_->GetKeyboardOffset();
911         float positionYWithOffset = positionY - keyboardOffset;
912         float offsetFix = (rootSize.Height() - positionYWithOffset) > 100.0f
913                               ? keyboardHeight - (rootSize.Height() - positionYWithOffset) / 2.0f
914                               : keyboardHeight;
915 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
916         if (offsetFix > 0.0f && positionYWithOffset < offsetFix) {
917             offsetFix = keyboardHeight - (rootSize.Height() - positionYWithOffset - height);
918         }
919 #endif
920         LOGI("OnVirtualKeyboardAreaChange positionY:%{public}f safeArea:%{public}f offsetFix:%{public}f, "
921              "keyboardHeight %{public}f",
922             positionY, (rootSize.Height() - keyboardHeight), offsetFix, keyboardHeight);
923         if (NearZero(keyboardHeight)) {
924             safeAreaManager_->UpdateKeyboardOffset(0.0f);
925         } else if (LessOrEqual(rootSize.Height() - positionYWithOffset - height, height) &&
926                    LessOrEqual(rootSize.Height() - positionYWithOffset, keyboardHeight)) {
927             safeAreaManager_->UpdateKeyboardOffset(-keyboardHeight);
928         } else if (positionYWithOffset + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
929             safeAreaManager_->UpdateKeyboardOffset(-offsetFix);
930         } else if ((positionYWithOffset + height > rootSize.Height() - keyboardHeight &&
931                        positionYWithOffset < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
932                    NearZero(rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
933             safeAreaManager_->UpdateKeyboardOffset(-height - offsetFix / 2.0f);
934         } else {
935             safeAreaManager_->UpdateKeyboardOffset(0.0f);
936         }
937         SyncSafeArea(true);
938         // layout immediately
939         FlushUITasks();
940 
941         CHECK_NULL_VOID_NOLOG(manager);
942         manager->ScrollTextFieldToSafeArea();
943         FlushUITasks();
944     };
945 
946     AnimationOption option = AnimationUtil::CreateKeyboardAnimationOption(keyboardAnimationConfig_, keyboardHeight);
947     Animate(option, option.GetCurve(), func);
948 
949 #ifdef ENABLE_ROSEN_BACKEND
950     if (rsTransaction) {
951         rsTransaction->Commit();
952     }
953 #endif
954 }
955 
OnBackPressed()956 bool PipelineContext::OnBackPressed()
957 {
958     LOGD("OnBackPressed");
959     CHECK_RUN_ON(PLATFORM);
960     auto frontend = weakFrontend_.Upgrade();
961     if (!frontend) {
962         // return back.
963         return false;
964     }
965 
966     // If the tag of the last child of the rootnode is video, exit full screen.
967     if (fullScreenManager_->OnBackPressed()) {
968         LOGI("Exit full screen: back press accepted");
969         return true;
970     }
971 
972     // if has sharedTransition, back press will stop the sharedTransition
973     if (sharedTransitionManager_->OnBackPressed()) {
974         LOGI("sharedTransition stop: back press accepted");
975         return true;
976     }
977 
978     auto textfieldManager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
979     if (textfieldManager && textfieldManager->OnBackPressed()) {
980         return true;
981     }
982 
983     // if has popup, back press would hide popup and not trigger page back
984     auto hasOverlay = false;
985     taskExecutor_->PostSyncTask(
986         [weakOverlay = AceType::WeakClaim(AceType::RawPtr(overlayManager_)),
987             weakSelectOverlay = AceType::WeakClaim(AceType::RawPtr(selectOverlayManager_)), &hasOverlay]() {
988             // Destroy behaviour of Select Overlay shouble be adjusted.
989             auto overlay = weakOverlay.Upgrade();
990             CHECK_NULL_VOID_NOLOG(overlay);
991             auto selectOverlay = weakSelectOverlay.Upgrade();
992             CHECK_NULL_VOID_NOLOG(selectOverlay);
993             selectOverlay->DestroySelectOverlay();
994             hasOverlay = overlay->RemoveOverlay(true);
995         },
996         TaskExecutor::TaskType::UI);
997     if (hasOverlay) {
998         LOGI("popup hidden: back press accepted");
999         return true;
1000     }
1001 
1002     auto result = false;
1003     taskExecutor_->PostSyncTask(
1004         [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), stageManager = stageManager_, &result]() {
1005             auto frontend = weakFrontend.Upgrade();
1006             if (!frontend) {
1007                 LOGW("frontend is nullptr");
1008                 result = false;
1009                 return;
1010             }
1011             auto context = weakPipelineContext.Upgrade();
1012             if (!context) {
1013                 LOGW("pipelineContext is nullptr");
1014                 result = false;
1015                 return;
1016             }
1017             CHECK_NULL_VOID(stageManager);
1018             auto lastPage = stageManager->GetLastPage();
1019             CHECK_NULL_VOID(lastPage);
1020             auto navigationGroupNode =
1021                 AceType::DynamicCast<NavigationGroupNode>(context->FindNavigationNodeToHandleBack(lastPage));
1022             if (navigationGroupNode) {
1023                 result = true;
1024             }
1025         },
1026         TaskExecutor::TaskType::UI);
1027 
1028     if (result) {
1029         // user accept
1030         LOGI("CallRouterBackToPopPage(): navDestination accept");
1031         return true;
1032     }
1033 
1034     taskExecutor_->PostSyncTask(
1035         [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), &result]() {
1036             auto frontend = weakFrontend.Upgrade();
1037             if (!frontend) {
1038                 LOGW("frontend is nullptr");
1039                 result = false;
1040                 return;
1041             }
1042             result = frontend->OnBackPressed();
1043         },
1044         TaskExecutor::TaskType::JS);
1045 
1046     if (result) {
1047         // user accept
1048         LOGI("CallRouterBackToPopPage(): frontend accept");
1049         return true;
1050     }
1051     LOGI("CallRouterBackToPopPage(): return platform consumed");
1052     return false;
1053 }
1054 
FindNavigationNodeToHandleBack(const RefPtr<UINode> & node)1055 RefPtr<FrameNode> PipelineContext::FindNavigationNodeToHandleBack(const RefPtr<UINode>& node)
1056 {
1057     const auto& children = node->GetChildren();
1058     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1059         auto& child = *iter;
1060 
1061         auto target = FindNavigationNodeToHandleBack(child);
1062         if (target) {
1063             return target;
1064         }
1065     }
1066     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(node);
1067     if (navigationGroupNode && navigationGroupNode->CheckCanHandleBack()) {
1068         return navigationGroupNode;
1069     }
1070     return nullptr;
1071 }
1072 
SetIsFocusActive(bool isFocusActive)1073 bool PipelineContext::SetIsFocusActive(bool isFocusActive)
1074 {
1075     if (isFocusActive_ == isFocusActive) {
1076         return false;
1077     }
1078     isFocusActive_ = isFocusActive;
1079     CHECK_NULL_RETURN_NOLOG(rootNode_, false);
1080     auto rootFocusHub = rootNode_->GetFocusHub();
1081     CHECK_NULL_RETURN_NOLOG(rootFocusHub, false);
1082     if (isFocusActive_) {
1083         return rootFocusHub->PaintAllFocusState();
1084     }
1085     rootFocusHub->ClearAllFocusState();
1086     return true;
1087 }
1088 
OnTouchEvent(const TouchEvent & point,bool isSubPipe)1089 void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe)
1090 {
1091     CHECK_RUN_ON(UI);
1092 
1093 #ifdef UICAST_COMPONENT_SUPPORTED
1094     do {
1095         auto container = Container::Current();
1096         CHECK_NULL_BREAK(container);
1097         auto distributedUI = container->GetDistributedUI();
1098         CHECK_NULL_BREAK(distributedUI);
1099         if (distributedUI->IsSinkMode()) {
1100             distributedUI->BypassEvent(point, isSubPipe);
1101             return;
1102         }
1103     } while (false);
1104 #endif
1105 
1106     HandleEtsCardTouchEvent(point);
1107 
1108     auto scalePoint = point.CreateScalePoint(GetViewScale());
1109     LOGD("AceTouchEvent: x = %{public}f, y = %{public}f, type = %{public}zu", scalePoint.x, scalePoint.y,
1110         scalePoint.type);
1111     eventManager_->SetInstanceId(GetInstanceId());
1112     if (scalePoint.type == TouchType::DOWN) {
1113         // Set focus state inactive while touch down event received
1114         SetIsFocusActive(false);
1115         LOGD("receive touch down event, first use touch test to collect touch event target");
1116         TouchRestrict touchRestrict { TouchRestrict::NONE };
1117         touchRestrict.sourceType = point.sourceType;
1118         touchRestrict.touchEvent = point;
1119         eventManager_->TouchTest(scalePoint, rootNode_, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe);
1120         for (const auto& weakContext : touchPluginPipelineContext_) {
1121             auto pipelineContext = DynamicCast<OHOS::Ace::PipelineBase>(weakContext.Upgrade());
1122             if (!pipelineContext) {
1123                 continue;
1124             }
1125             auto pluginPoint =
1126                 point.UpdateScalePoint(viewScale_, static_cast<float>(pipelineContext->GetPluginEventOffset().GetX()),
1127                     static_cast<float>(pipelineContext->GetPluginEventOffset().GetY()), point.id);
1128             // eventManager_ instance Id may changed.
1129             pipelineContext->OnTouchEvent(pluginPoint, true);
1130         }
1131 
1132         // restore instance Id.
1133         eventManager_->SetInstanceId(GetInstanceId());
1134     }
1135 
1136     auto rootOffset = GetRootRect().GetOffset();
1137     eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, rootOffset);
1138 
1139     if (isSubPipe) {
1140         return;
1141     }
1142 
1143     if (scalePoint.type == TouchType::MOVE) {
1144         touchEvents_.emplace_back(point);
1145         auto container = Container::Current();
1146         if (container && container->IsScenceBoardWindow() && IsWindowSceneConsumed()) {
1147             FlushTouchEvents();
1148             return;
1149         } else {
1150             hasIdleTasks_ = true;
1151             RequestFrame();
1152             return;
1153         }
1154     }
1155 
1156     if (scalePoint.type == TouchType::UP) {
1157         lastTouchTime_ = GetTimeFromExternalTimer();
1158     }
1159 
1160     std::optional<TouchEvent> lastMoveEvent;
1161     if (scalePoint.type == TouchType::UP && !touchEvents_.empty()) {
1162         for (auto iter = touchEvents_.begin(); iter != touchEvents_.end(); ++iter) {
1163             auto movePoint = (*iter).CreateScalePoint(GetViewScale());
1164             if (scalePoint.id == movePoint.id) {
1165                 lastMoveEvent = movePoint;
1166                 touchEvents_.erase(iter++);
1167             }
1168         }
1169         if (lastMoveEvent.has_value()) {
1170             eventManager_->DispatchTouchEvent(lastMoveEvent.value());
1171         }
1172     }
1173 
1174     eventManager_->DispatchTouchEvent(scalePoint);
1175 
1176     if ((scalePoint.type == TouchType::UP) || (scalePoint.type == TouchType::CANCEL)) {
1177         // need to reset touchPluginPipelineContext_ for next touch down event.
1178         touchPluginPipelineContext_.clear();
1179         RemoveEtsCardTouchEventCallback(point.id);
1180     }
1181 
1182     hasIdleTasks_ = true;
1183     RequestFrame();
1184 }
1185 
OnSurfaceDensityChanged(double density)1186 void PipelineContext::OnSurfaceDensityChanged(double density)
1187 {
1188     CHECK_RUN_ON(UI);
1189     LOGD("density_(%{public}lf), dipScale_(%{public}lf)", density_, dipScale_);
1190     density_ = density;
1191     if (!NearZero(viewScale_)) {
1192         LOGD("viewScale_(%{public}lf)", viewScale_);
1193         dipScale_ = density_ / viewScale_;
1194     }
1195 }
1196 
OnDumpInfo(const std::vector<std::string> & params) const1197 bool PipelineContext::OnDumpInfo(const std::vector<std::string>& params) const
1198 {
1199     ACE_DCHECK(!params.empty());
1200 
1201     if (params[0] == "-element") {
1202         if (params.size() > 1 && params[1] == "-lastpage") {
1203             auto lastPage = stageManager_->GetLastPage();
1204             if (lastPage) {
1205                 lastPage->DumpTree(0);
1206             }
1207         } else {
1208             rootNode_->DumpTree(0);
1209         }
1210     } else if (params[0] == "-render") {
1211     } else if (params[0] == "-focus") {
1212         if (rootNode_->GetFocusHub()) {
1213             rootNode_->GetFocusHub()->DumpFocusTree(0);
1214         }
1215     } else if (params[0] == "-layer") {
1216     } else if (params[0] == "-frontend") {
1217 #ifndef WEARABLE_PRODUCT
1218     } else if (params[0] == "-multimodal") {
1219 #endif
1220     } else if (params[0] == "-accessibility" || params[0] == "-inspector") {
1221         auto accessibilityManager = GetAccessibilityManager();
1222         if (accessibilityManager) {
1223             accessibilityManager->OnDumpInfo(params);
1224         }
1225     } else if (params[0] == "-rotation" && params.size() >= 2) {
1226     } else if (params[0] == "-animationscale" && params.size() >= 2) {
1227     } else if (params[0] == "-velocityscale" && params.size() >= 2) {
1228     } else if (params[0] == "-scrollfriction" && params.size() >= 2) {
1229     } else if (params[0] == "-threadstuck" && params.size() >= 3) {
1230     } else if (params[0] == "-pipeline") {
1231         DumpPipelineInfo();
1232     } else {
1233         return false;
1234     }
1235 
1236     return true;
1237 }
1238 
GetCurrentFrameInfo(uint64_t recvTime,uint64_t timeStamp)1239 FrameInfo* PipelineContext::GetCurrentFrameInfo(uint64_t recvTime, uint64_t timeStamp)
1240 {
1241     if (SystemProperties::GetDumpFrameCount() == 0) {
1242         return nullptr;
1243     }
1244     if (dumpFrameInfos_.size() >= SystemProperties::GetDumpFrameCount()) {
1245         dumpFrameInfos_.pop_front();
1246     }
1247 
1248     dumpFrameInfos_.push_back({ .frameRecvTime_ = recvTime, .frameTimeStamp_ = timeStamp });
1249     return &dumpFrameInfos_.back();
1250 }
1251 
DumpPipelineInfo() const1252 void PipelineContext::DumpPipelineInfo() const
1253 {
1254     DumpLog::GetInstance().Print("PipelineInfo:");
1255     if (window_) {
1256         DumpLog::GetInstance().Print(1, "DisplayRefreshRate: " + std::to_string(window_->GetRefreshRate()));
1257         DumpLog::GetInstance().Print(1, "LastRequestVsyncTime: " + std::to_string(window_->GetLastRequestVsyncTime()));
1258     }
1259     if (!dumpFrameInfos_.empty()) {
1260         DumpLog::GetInstance().Print("==================================FrameTask==================================");
1261         for (const auto& info : dumpFrameInfos_) {
1262             DumpLog::GetInstance().Print("Task: " + info.GetTimeInfo());
1263             DumpLog::GetInstance().Print(1, "LayoutTask:");
1264             for (const auto& layout : info.layoutInfos_) {
1265                 DumpLog::GetInstance().Print(2, layout.ToString());
1266             }
1267             DumpLog::GetInstance().Print(1, "RenderTask:");
1268             for (const auto& layout : info.renderInfos_) {
1269                 DumpLog::GetInstance().Print(2, layout.ToString());
1270             }
1271             DumpLog::GetInstance().Print(
1272                 "==================================FrameTask==================================");
1273         }
1274     }
1275 }
1276 
FlushTouchEvents()1277 void PipelineContext::FlushTouchEvents()
1278 {
1279     CHECK_RUN_ON(UI);
1280     CHECK_NULL_VOID(rootNode_);
1281     {
1282         std::unordered_set<int32_t> moveEventIds;
1283         decltype(touchEvents_) touchEvents(std::move(touchEvents_));
1284         if (touchEvents.empty()) {
1285             canUseLongPredictTask_ = true;
1286             return;
1287         }
1288         canUseLongPredictTask_ = false;
1289         eventManager_->FlushTouchEventsBegin(touchEvents_);
1290         std::unordered_map<int, TouchEvent> idToTouchPoints;
1291         for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter) {
1292             auto scalePoint = (*iter).CreateScalePoint(GetViewScale());
1293             idToTouchPoints.emplace(scalePoint.id, scalePoint);
1294             idToTouchPoints[scalePoint.id].history.insert(idToTouchPoints[scalePoint.id].history.begin(), scalePoint);
1295         }
1296         std::list<TouchEvent> touchPoints;
1297         for (auto& [_, item] : idToTouchPoints) {
1298             touchPoints.emplace_back(std::move(item));
1299         }
1300         auto maxSize = touchPoints.size();
1301         for (auto iter = touchPoints.rbegin(); iter != touchPoints.rend(); ++iter) {
1302             maxSize--;
1303             if (maxSize == 0) {
1304                 eventManager_->FlushTouchEventsEnd(touchPoints);
1305             }
1306             eventManager_->DispatchTouchEvent(*iter);
1307         }
1308     }
1309 }
1310 
OnMouseEvent(const MouseEvent & event)1311 void PipelineContext::OnMouseEvent(const MouseEvent& event)
1312 {
1313     CHECK_RUN_ON(UI);
1314     if (!lastMouseEvent_) {
1315         lastMouseEvent_ = std::make_unique<MouseEvent>();
1316     }
1317     lastMouseEvent_->x = event.x;
1318     lastMouseEvent_->y = event.y;
1319     lastMouseEvent_->button = event.button;
1320     lastMouseEvent_->action = event.action;
1321     lastMouseEvent_->sourceType = event.sourceType;
1322     lastMouseEvent_->time = event.time;
1323 
1324     if (event.button == MouseButton::RIGHT_BUTTON && event.action == MouseAction::PRESS) {
1325         // Mouse right button press event set focus inactive here.
1326         // Mouse left button press event will set focus inactive in touch process.
1327         SetIsFocusActive(false);
1328     }
1329     auto container = Container::Current();
1330     if (((event.action == MouseAction::RELEASE || event.action == MouseAction::PRESS ||
1331              event.action == MouseAction::MOVE) &&
1332             (event.button == MouseButton::LEFT_BUTTON || event.pressedButtons == MOUSE_PRESS_LEFT)) ||
1333         (container && container->IsScenceBoardWindow() &&
1334             (event.pullAction == MouseAction::PULL_MOVE || event.pullAction == MouseAction::PULL_UP))) {
1335         auto touchPoint = event.CreateTouchPoint();
1336         OnTouchEvent(touchPoint);
1337     }
1338 
1339     CHECK_NULL_VOID(rootNode_);
1340     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1341     LOGD(
1342         "MouseEvent (x,y): (%{public}f,%{public}f), button: %{public}d, action: %{public}d, pressedButtons: %{public}d",
1343         scaleEvent.x, scaleEvent.y, scaleEvent.button, scaleEvent.action, scaleEvent.pressedButtons);
1344     TouchRestrict touchRestrict { TouchRestrict::NONE };
1345     touchRestrict.sourceType = event.sourceType;
1346     touchRestrict.hitTestType = SourceType::MOUSE;
1347     eventManager_->MouseTest(scaleEvent, rootNode_, touchRestrict);
1348     eventManager_->DispatchMouseEventNG(scaleEvent);
1349     eventManager_->DispatchMouseHoverEventNG(scaleEvent);
1350     eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
1351     RequestFrame();
1352 }
1353 
FlushMouseEvent()1354 void PipelineContext::FlushMouseEvent()
1355 {
1356     if (!lastMouseEvent_ || lastMouseEvent_->action == MouseAction::WINDOW_LEAVE) {
1357         return;
1358     }
1359     MouseEvent event;
1360     event.x = lastMouseEvent_->x;
1361     event.y = lastMouseEvent_->y;
1362     event.time = lastMouseEvent_->time;
1363     event.action = MouseAction::MOVE;
1364     event.button = MouseButton::NONE_BUTTON;
1365     event.sourceType = SourceType::MOUSE;
1366 
1367     CHECK_RUN_ON(UI);
1368     CHECK_NULL_VOID(rootNode_);
1369     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1370     TouchRestrict touchRestrict { TouchRestrict::NONE };
1371     touchRestrict.sourceType = event.sourceType;
1372     touchRestrict.hitTestType = SourceType::MOUSE;
1373     eventManager_->MouseTest(scaleEvent, rootNode_, touchRestrict);
1374     eventManager_->DispatchMouseEventNG(scaleEvent);
1375     eventManager_->DispatchMouseHoverEventNG(scaleEvent);
1376     eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
1377 }
1378 
ChangeMouseStyle(int32_t nodeId,MouseFormat format)1379 bool PipelineContext::ChangeMouseStyle(int32_t nodeId, MouseFormat format)
1380 {
1381     if (!onFocus_) {
1382         LOGD("ChangeMouseStyle failed because the window is not on focus.");
1383         return false;
1384     }
1385     if (mouseStyleNodeId_ != nodeId) {
1386         return false;
1387     }
1388     auto mouseStyle = MouseStyle::CreateMouseStyle();
1389     CHECK_NULL_RETURN(mouseStyle, false);
1390     LOGD("ChangeMouseStyle to %{public}d on Frame %{public}d", format, nodeId);
1391     return mouseStyle->ChangePointerStyle(GetWindowId(), format);
1392 }
1393 
OnKeyEvent(const KeyEvent & event)1394 bool PipelineContext::OnKeyEvent(const KeyEvent& event)
1395 {
1396     eventManager_->SetPressedKeyCodes(event.pressedCodes);
1397     CHECK_NULL_RETURN(eventManager_, false);
1398     if (event.action == KeyAction::DOWN) {
1399         eventManager_->DispatchKeyboardShortcut(event);
1400     }
1401     if (event.code == KeyCode::KEY_ESCAPE) {
1402         auto manager = GetDragDropManager();
1403         if (manager) {
1404             manager->SetIsDragCancel(true);
1405             manager->OnDragEnd({ 0.0f, 0.0f }, "");
1406         }
1407     }
1408     // TAB key set focus state from inactive to active.
1409     // If return success. This tab key will just trigger onKeyEvent process.
1410     isTabJustTriggerOnKeyEvent_ =
1411         (event.action == KeyAction::DOWN && event.IsKey({ KeyCode::KEY_TAB }) && SetIsFocusActive(true));
1412     auto lastPage = stageManager_ ? stageManager_->GetLastPage() : nullptr;
1413     auto mainNode = lastPage ? lastPage : rootNode_;
1414     CHECK_NULL_RETURN(mainNode, false);
1415     if (!eventManager_->DispatchTabIndexEventNG(event, rootNode_, mainNode)) {
1416         auto result = eventManager_->DispatchKeyEventNG(event, rootNode_);
1417         if (!result && event.code == KeyCode::KEY_ESCAPE && event.action == KeyAction::DOWN) {
1418             CHECK_NULL_RETURN(overlayManager_, false);
1419             auto currentContainer = Container::Current();
1420             if (currentContainer->IsSubContainer() || currentContainer->IsDialogContainer()) {
1421                 return overlayManager_->RemoveOverlayInSubwindow();
1422             } else {
1423                 return overlayManager_->RemoveOverlay(false);
1424             }
1425         } else {
1426             return result;
1427         }
1428     }
1429     return true;
1430 }
1431 
RequestDefaultFocus()1432 bool PipelineContext::RequestDefaultFocus()
1433 {
1434     CHECK_NULL_RETURN(stageManager_, false);
1435     auto lastPage = stageManager_->GetLastPage();
1436     auto mainNode = lastPage ? lastPage : rootNode_;
1437     CHECK_NULL_RETURN(mainNode, false);
1438     auto mainFocusHub = mainNode->GetFocusHub();
1439     CHECK_NULL_RETURN(mainFocusHub, false);
1440     if (mainFocusHub->IsDefaultHasFocused()) {
1441         LOGD("MainNode: %{public}s/%{public}d 's default focus node has be focused.", mainNode->GetTag().c_str(),
1442             mainNode->GetId());
1443         return false;
1444     }
1445     auto defaultFocusNodeWeak = mainFocusHub->GetDefaultFocusNode();
1446     auto defaultFocusNode = defaultFocusNodeWeak.Upgrade();
1447     if (!defaultFocusNode) {
1448         return false;
1449     }
1450     if (!defaultFocusNode->IsFocusableWholePath()) {
1451         LOGD("MainNode: %{public}s/%{public}d 's default focus node is not focusable.", mainNode->GetTag().c_str(),
1452             mainNode->GetId());
1453         return false;
1454     }
1455     mainFocusHub->SetIsDefaultHasFocused(true);
1456     LOGD("MainNode: %{public}s/%{public}d request default focus node: %{public}s/%{public}d",
1457         mainNode->GetTag().c_str(), mainNode->GetId(), defaultFocusNode->GetFrameName().c_str(),
1458         defaultFocusNode->GetFrameId());
1459     return defaultFocusNode->RequestFocusImmediately();
1460 }
1461 
RequestFocus(const std::string & targetNodeId)1462 bool PipelineContext::RequestFocus(const std::string& targetNodeId)
1463 {
1464     CHECK_NULL_RETURN(rootNode_, false);
1465     auto focusHub = rootNode_->GetFocusHub();
1466     CHECK_NULL_RETURN(focusHub, false);
1467     auto currentFocusChecked = focusHub->RequestFocusImmediatelyById(targetNodeId);
1468     if (!isSubPipeline_ || currentFocusChecked) {
1469         LOGI("Request focus in current pipeline return is %{public}d", currentFocusChecked);
1470         return currentFocusChecked;
1471     }
1472     LOGI("Request focus in parent pipeline");
1473     auto parentPipelineBase = parentPipeline_.Upgrade();
1474     CHECK_NULL_RETURN(parentPipelineBase, false);
1475     auto parentPipelineContext = AceType::DynamicCast<NG::PipelineContext>(parentPipelineBase);
1476     CHECK_NULL_RETURN(parentPipelineContext, false);
1477     return parentPipelineContext->RequestFocus(targetNodeId);
1478 }
1479 
AddDirtyFocus(const RefPtr<FrameNode> & node)1480 void PipelineContext::AddDirtyFocus(const RefPtr<FrameNode>& node)
1481 {
1482     CHECK_RUN_ON(UI);
1483     CHECK_NULL_VOID(node);
1484     if (node->GetFocusType() == FocusType::NODE) {
1485         dirtyFocusNode_ = WeakClaim(RawPtr(node));
1486     } else {
1487         dirtyFocusScope_ = WeakClaim(RawPtr(node));
1488     }
1489     RequestFrame();
1490 }
1491 
AddDirtyDefaultFocus(const RefPtr<FrameNode> & node)1492 void PipelineContext::AddDirtyDefaultFocus(const RefPtr<FrameNode>& node)
1493 {
1494     CHECK_RUN_ON(UI);
1495     CHECK_NULL_VOID(node);
1496     dirtyDefaultFocusNode_ = WeakPtr<FrameNode>(node);
1497     RequestFrame();
1498 }
1499 
RootLostFocus(BlurReason reason) const1500 void PipelineContext::RootLostFocus(BlurReason reason) const
1501 {
1502     CHECK_NULL_VOID(rootNode_);
1503     auto focusHub = rootNode_->GetFocusHub();
1504     CHECK_NULL_VOID(focusHub);
1505     focusHub->LostFocus(reason);
1506     CHECK_NULL_VOID(overlayManager_);
1507     overlayManager_->HideAllMenus();
1508     overlayManager_->HideCustomPopups();
1509 }
1510 
ConvertAxisToMouse(const AxisEvent & event)1511 MouseEvent ConvertAxisToMouse(const AxisEvent& event)
1512 {
1513     MouseEvent result;
1514     result.x = event.x;
1515     result.y = event.y;
1516     result.action = MouseAction::MOVE;
1517     result.button = MouseButton::NONE_BUTTON;
1518     result.time = event.time;
1519     result.deviceId = event.deviceId;
1520     result.sourceType = event.sourceType;
1521     result.pointerEvent = event.pointerEvent;
1522     return result;
1523 }
1524 
OnAxisEvent(const AxisEvent & event)1525 void PipelineContext::OnAxisEvent(const AxisEvent& event)
1526 {
1527     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1528     LOGD("AxisEvent (x,y): (%{public}f,%{public}f), action: %{public}d, horizontalAxis: %{public}f, verticalAxis: "
1529          "%{public}f, pinchAxisScale: %{public}f",
1530         scaleEvent.x, scaleEvent.y, scaleEvent.action, scaleEvent.horizontalAxis, scaleEvent.verticalAxis,
1531         scaleEvent.pinchAxisScale);
1532 
1533     auto dragManager = GetDragDropManager();
1534     if (dragManager && !dragManager->IsDragged()) {
1535         if (event.action == AxisAction::BEGIN) {
1536             TouchRestrict touchRestrict { TouchRestrict::NONE };
1537             touchRestrict.sourceType = event.sourceType;
1538             touchRestrict.hitTestType = SourceType::TOUCH;
1539             eventManager_->TouchTest(scaleEvent, rootNode_, touchRestrict);
1540         }
1541         eventManager_->DispatchTouchEvent(scaleEvent);
1542     }
1543 
1544     if (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE) {
1545         eventManager_->AxisTest(scaleEvent, rootNode_);
1546         eventManager_->DispatchAxisEventNG(scaleEvent);
1547     }
1548 
1549     auto mouseEvent = ConvertAxisToMouse(event);
1550     OnMouseEvent(mouseEvent);
1551 }
1552 
AddVisibleAreaChangeNode(const RefPtr<FrameNode> & node,double ratio,const VisibleRatioCallback & callback,bool isUserCallback)1553 void PipelineContext::AddVisibleAreaChangeNode(
1554     const RefPtr<FrameNode>& node, double ratio, const VisibleRatioCallback& callback, bool isUserCallback)
1555 {
1556     CHECK_NULL_VOID(node);
1557     VisibleCallbackInfo addInfo;
1558     addInfo.callback = callback;
1559     addInfo.isCurrentVisible = false;
1560     onVisibleAreaChangeNodeIds_.emplace(node->GetId());
1561     if (isUserCallback) {
1562         node->AddVisibleAreaUserCallback(ratio, addInfo);
1563     } else {
1564         node->AddVisibleAreaInnerCallback(ratio, addInfo);
1565     }
1566 }
1567 
RemoveVisibleAreaChangeNode(int32_t nodeId)1568 void PipelineContext::RemoveVisibleAreaChangeNode(int32_t nodeId)
1569 {
1570     onVisibleAreaChangeNodeIds_.erase(nodeId);
1571 }
1572 
HandleVisibleAreaChangeEvent()1573 void PipelineContext::HandleVisibleAreaChangeEvent()
1574 {
1575     ACE_FUNCTION_TRACE();
1576     if (onVisibleAreaChangeNodeIds_.empty()) {
1577         return;
1578     }
1579     auto nodes = FrameNode::GetNodesById(onVisibleAreaChangeNodeIds_);
1580     for (auto&& frameNode : nodes) {
1581         frameNode->TriggerVisibleAreaChangeCallback();
1582     }
1583 }
1584 
AddOnAreaChangeNode(int32_t nodeId)1585 void PipelineContext::AddOnAreaChangeNode(int32_t nodeId)
1586 {
1587     onAreaChangeNodeIds_.emplace(nodeId);
1588 }
1589 
RemoveOnAreaChangeNode(int32_t nodeId)1590 void PipelineContext::RemoveOnAreaChangeNode(int32_t nodeId)
1591 {
1592     onAreaChangeNodeIds_.erase(nodeId);
1593 }
1594 
HandleOnAreaChangeEvent()1595 void PipelineContext::HandleOnAreaChangeEvent()
1596 {
1597     ACE_FUNCTION_TRACE();
1598     if (onAreaChangeNodeIds_.empty()) {
1599         return;
1600     }
1601     auto nodes = FrameNode::GetNodesById(onAreaChangeNodeIds_);
1602     for (auto&& frameNode : nodes) {
1603         frameNode->TriggerOnAreaChangeCallback();
1604     }
1605     UpdateFormLinkInfos();
1606 }
1607 
UpdateFormLinkInfos()1608 void PipelineContext::UpdateFormLinkInfos()
1609 {
1610     if (formLinkInfoUpdateHandler_ && !formLinkInfoMap_.empty()) {
1611         LOGI("formLinkInfoUpdateHandler called");
1612         std::vector<std::string> formLinkInfos;
1613         for (auto iter = formLinkInfoMap_.rbegin(); iter != formLinkInfoMap_.rend(); ++iter) {
1614             auto info = iter->second;
1615             formLinkInfos.push_back(info);
1616         }
1617         formLinkInfoUpdateHandler_(formLinkInfos);
1618     }
1619 }
1620 
OnShow()1621 void PipelineContext::OnShow()
1622 {
1623     CHECK_RUN_ON(UI);
1624     onShow_ = true;
1625     window_->OnShow();
1626     RequestFrame();
1627     FlushWindowStateChangedCallback(true);
1628     AccessibilityEvent event;
1629     event.windowChangeTypes = WindowUpdateType::WINDOW_UPDATE_ACTIVE;
1630     event.type = AccessibilityEventType::PAGE_CHANGE;
1631     SendEventToAccessibility(event);
1632 }
1633 
OnHide()1634 void PipelineContext::OnHide()
1635 {
1636     CHECK_RUN_ON(UI);
1637     onShow_ = false;
1638     window_->OnHide();
1639     RequestFrame();
1640     OnVirtualKeyboardAreaChange(Rect());
1641     FlushWindowStateChangedCallback(false);
1642     AccessibilityEvent event;
1643     event.type = AccessibilityEventType::PAGE_CHANGE;
1644     SendEventToAccessibility(event);
1645 }
1646 
WindowFocus(bool isFocus)1647 void PipelineContext::WindowFocus(bool isFocus)
1648 {
1649     CHECK_RUN_ON(UI);
1650     onFocus_ = isFocus;
1651     if (!isFocus) {
1652         LOGI("WindowFocus: window - %{public}d on blur.", windowId_);
1653         auto mouseStyle = MouseStyle::CreateMouseStyle();
1654         if (mouseStyle) {
1655             mouseStyle->ChangePointerStyle(static_cast<int32_t>(GetWindowId()), MouseFormat::DEFAULT);
1656         }
1657         RootLostFocus(BlurReason::WINDOW_BLUR);
1658         NotifyPopupDismiss();
1659         OnVirtualKeyboardAreaChange(Rect());
1660     } else {
1661         LOGI("WindowFocus: window - %{public}d on focus.", windowId_);
1662         isRootFocusNeedUpdate_ = true;
1663         FlushFocus();
1664     }
1665     FlushWindowFocusChangedCallback(isFocus);
1666 }
1667 
ShowContainerTitle(bool isShow,bool hasDeco)1668 void PipelineContext::ShowContainerTitle(bool isShow, bool hasDeco)
1669 {
1670     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
1671         LOGW("ShowContainerTitle failed, Window modal is not container.");
1672         return;
1673     }
1674     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
1675     CHECK_NULL_VOID(containerNode);
1676     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
1677     CHECK_NULL_VOID(containerPattern);
1678     containerPattern->ShowTitle(isShow, hasDeco);
1679 }
1680 
SetContainerWindow(bool isShow)1681 void PipelineContext::SetContainerWindow(bool isShow)
1682 {
1683 #ifdef ENABLE_ROSEN_BACKEND
1684     if (!IsJsCard()) {
1685         auto window = GetWindow();
1686         if (window) {
1687             auto rsUIDirector = window->GetRSUIDirector();
1688             if (rsUIDirector) {
1689                 // set container window show state to render service
1690                 rsUIDirector->SetContainerWindow(isShow, density_);
1691             }
1692         }
1693     }
1694 #endif
1695 }
1696 
SetAppBgColor(const Color & color)1697 void PipelineContext::SetAppBgColor(const Color& color)
1698 {
1699     appBgColor_ = color;
1700 #ifdef ENABLE_ROSEN_BACKEND
1701     if (!IsJsCard()) {
1702         auto window = GetWindow();
1703         if (window) {
1704             auto rsUIDirector = window->GetRSUIDirector();
1705             if (rsUIDirector) {
1706                 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1707             }
1708         }
1709     }
1710 #endif
1711     CHECK_NULL_VOID(rootNode_);
1712     auto rootPattern = rootNode_->GetPattern<RootPattern>();
1713     CHECK_NULL_VOID(rootPattern);
1714     rootPattern->SetAppBgColor(appBgColor_, windowModal_ == WindowModal::CONTAINER_MODAL);
1715 }
1716 
SetAppTitle(const std::string & title)1717 void PipelineContext::SetAppTitle(const std::string& title)
1718 {
1719     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
1720         LOGW("SetAppTitle failed, Window modal is not container.");
1721         return;
1722     }
1723     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
1724     CHECK_NULL_VOID(containerNode);
1725     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
1726     CHECK_NULL_VOID(containerPattern);
1727     containerPattern->SetAppTitle(title);
1728 }
1729 
SetAppIcon(const RefPtr<PixelMap> & icon)1730 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
1731 {
1732     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
1733         LOGW("SetAppIcon failed, Window modal is not container.");
1734         return;
1735     }
1736     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
1737     CHECK_NULL_VOID(containerNode);
1738     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
1739     CHECK_NULL_VOID(containerPattern);
1740     containerPattern->SetAppIcon(icon);
1741 }
1742 
FlushReload()1743 void PipelineContext::FlushReload()
1744 {
1745     LOGI("PipelineContext::FlushReload.");
1746     AnimationOption option;
1747     const int32_t duration = 400;
1748     option.SetDuration(duration);
1749     option.SetCurve(Curves::FRICTION);
1750     AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
1751         auto pipeline = weak.Upgrade();
1752         CHECK_NULL_VOID(pipeline);
1753         CHECK_NULL_VOID(pipeline->stageManager_);
1754         pipeline->SetIsReloading(true);
1755         pipeline->stageManager_->ReloadStage();
1756         pipeline->SetIsReloading(false);
1757         pipeline->FlushUITasks();
1758     });
1759 }
1760 
Destroy()1761 void PipelineContext::Destroy()
1762 {
1763     CHECK_RUN_ON(UI);
1764     LOGI("PipelineContext::Destroy begin.");
1765     taskScheduler_->CleanUp();
1766     scheduleTasks_.clear();
1767     dirtyNodes_.clear();
1768     rootNode_.Reset();
1769     stageManager_.Reset();
1770     overlayManager_.Reset();
1771     sharedTransitionManager_.Reset();
1772     dragDropManager_.Reset();
1773     selectOverlayManager_.Reset();
1774     fullScreenManager_.Reset();
1775     touchEvents_.clear();
1776     buildFinishCallbacks_.clear();
1777     onWindowStateChangedCallbacks_.clear();
1778     onWindowFocusChangedCallbacks_.clear();
1779     nodesToNotifyMemoryLevel_.clear();
1780     dirtyFocusNode_.Reset();
1781     dirtyFocusScope_.Reset();
1782     needRenderNode_.clear();
1783     dirtyDefaultFocusNode_.Reset();
1784     PipelineBase::Destroy();
1785     LOGI("PipelineContext::Destroy end.");
1786 }
1787 
AddBuildFinishCallBack(std::function<void ()> && callback)1788 void PipelineContext::AddBuildFinishCallBack(std::function<void()>&& callback)
1789 {
1790     buildFinishCallbacks_.emplace_back(std::move(callback));
1791 }
1792 
AddWindowStateChangedCallback(int32_t nodeId)1793 void PipelineContext::AddWindowStateChangedCallback(int32_t nodeId)
1794 {
1795     onWindowStateChangedCallbacks_.emplace(nodeId);
1796 }
1797 
RemoveWindowStateChangedCallback(int32_t nodeId)1798 void PipelineContext::RemoveWindowStateChangedCallback(int32_t nodeId)
1799 {
1800     onWindowStateChangedCallbacks_.erase(nodeId);
1801 }
1802 
FlushWindowStateChangedCallback(bool isShow)1803 void PipelineContext::FlushWindowStateChangedCallback(bool isShow)
1804 {
1805     auto iter = onWindowStateChangedCallbacks_.begin();
1806     while (iter != onWindowStateChangedCallbacks_.end()) {
1807         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
1808         if (!node) {
1809             iter = onWindowStateChangedCallbacks_.erase(iter);
1810         } else {
1811             if (isShow) {
1812                 node->OnWindowShow();
1813             } else {
1814                 node->OnWindowHide();
1815             }
1816             ++iter;
1817         }
1818     }
1819     HandleVisibleAreaChangeEvent();
1820 }
1821 
AddWindowFocusChangedCallback(int32_t nodeId)1822 void PipelineContext::AddWindowFocusChangedCallback(int32_t nodeId)
1823 {
1824     onWindowFocusChangedCallbacks_.emplace_back(nodeId);
1825 }
1826 
RemoveWindowFocusChangedCallback(int32_t nodeId)1827 void PipelineContext::RemoveWindowFocusChangedCallback(int32_t nodeId)
1828 {
1829     onWindowFocusChangedCallbacks_.remove(nodeId);
1830 }
1831 
FlushWindowFocusChangedCallback(bool isFocus)1832 void PipelineContext::FlushWindowFocusChangedCallback(bool isFocus)
1833 {
1834     auto iter = onWindowFocusChangedCallbacks_.begin();
1835     while (iter != onWindowFocusChangedCallbacks_.end()) {
1836         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
1837         if (!node) {
1838             iter = onWindowFocusChangedCallbacks_.erase(iter);
1839         } else {
1840             if (isFocus) {
1841                 node->OnWindowFocused();
1842             } else {
1843                 node->OnWindowUnfocused();
1844             }
1845             ++iter;
1846         }
1847     }
1848 }
1849 
AddWindowSizeChangeCallback(int32_t nodeId)1850 void PipelineContext::AddWindowSizeChangeCallback(int32_t nodeId)
1851 {
1852     onWindowSizeChangeCallbacks_.emplace_back(nodeId);
1853 }
1854 
RemoveWindowSizeChangeCallback(int32_t nodeId)1855 void PipelineContext::RemoveWindowSizeChangeCallback(int32_t nodeId)
1856 {
1857     onWindowSizeChangeCallbacks_.remove(nodeId);
1858 }
1859 
FlushWindowSizeChangeCallback(int32_t width,int32_t height,WindowSizeChangeReason type)1860 void PipelineContext::FlushWindowSizeChangeCallback(int32_t width, int32_t height, WindowSizeChangeReason type)
1861 {
1862     auto iter = onWindowSizeChangeCallbacks_.begin();
1863     while (iter != onWindowSizeChangeCallbacks_.end()) {
1864         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
1865         if (!node) {
1866             iter = onWindowSizeChangeCallbacks_.erase(iter);
1867         } else {
1868             node->OnWindowSizeChanged(width, height, type);
1869             ++iter;
1870         }
1871     }
1872 }
1873 
OnDragEvent(int32_t x,int32_t y,DragEventAction action)1874 void PipelineContext::OnDragEvent(int32_t x, int32_t y, DragEventAction action)
1875 {
1876     auto manager = GetDragDropManager();
1877     CHECK_NULL_VOID(manager);
1878 #ifdef ENABLE_DRAG_FRAMEWORK
1879     auto container = Container::Current();
1880     if (container && container->IsScenceBoardWindow()) {
1881         if (!manager->IsDragged() && manager->IsWindowConsumed()) {
1882             manager->SetIsWindowConsumed(false);
1883             LOGD("The event does not need to be handled");
1884             return;
1885         }
1886     }
1887     if (action == DragEventAction::DRAG_EVENT_OUT) {
1888         manager->ClearSummary();
1889         manager->ClearExtraInfo();
1890     }
1891 #endif // ENABLE_DRAG_FRAMEWORK
1892 
1893     std::string extraInfo;
1894 
1895 #ifdef ENABLE_DRAG_FRAMEWORK
1896     if (action == DragEventAction::DRAG_EVENT_START) {
1897         manager->RequireSummary();
1898         manager->GetExtraInfoFromClipboard(extraInfo);
1899         manager->SetExtraInfo(extraInfo);
1900     }
1901 #else
1902     manager->GetExtraInfoFromClipboard(extraInfo);
1903 #endif // ENABLE_DRAG_FRAMEWORK
1904     if (action == DragEventAction::DRAG_EVENT_END) {
1905 #ifdef ENABLE_DRAG_FRAMEWORK
1906         manager->GetExtraInfoFromClipboard(extraInfo);
1907         manager->SetExtraInfo(extraInfo);
1908 #endif // ENABLE_DRAG_FRAMEWORK
1909         manager->OnDragEnd(Point(x, y, x, y), extraInfo);
1910         manager->RestoreClipboardData();
1911         return;
1912     }
1913     manager->OnDragMove(Point(x, y, x, y), extraInfo);
1914 }
1915 
AddNodesToNotifyMemoryLevel(int32_t nodeId)1916 void PipelineContext::AddNodesToNotifyMemoryLevel(int32_t nodeId)
1917 {
1918     nodesToNotifyMemoryLevel_.emplace_back(nodeId);
1919 }
1920 
RemoveNodesToNotifyMemoryLevel(int32_t nodeId)1921 void PipelineContext::RemoveNodesToNotifyMemoryLevel(int32_t nodeId)
1922 {
1923     nodesToNotifyMemoryLevel_.remove(nodeId);
1924 }
1925 
NotifyMemoryLevel(int32_t level)1926 void PipelineContext::NotifyMemoryLevel(int32_t level)
1927 {
1928     LOGI("PipelineContext: NotifyMemoryLevel called");
1929     auto iter = nodesToNotifyMemoryLevel_.begin();
1930     while (iter != nodesToNotifyMemoryLevel_.end()) {
1931         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
1932         if (!node) {
1933             iter = nodesToNotifyMemoryLevel_.erase(iter);
1934         } else {
1935             node->OnNotifyMemoryLevel(level);
1936             ++iter;
1937         }
1938     }
1939 }
AddPredictTask(PredictTask && task)1940 void PipelineContext::AddPredictTask(PredictTask&& task)
1941 {
1942     taskScheduler_->AddPredictTask(std::move(task));
1943     RequestFrame();
1944 }
1945 
OnIdle(int64_t deadline)1946 void PipelineContext::OnIdle(int64_t deadline)
1947 {
1948     if (deadline == 0) {
1949         canUseLongPredictTask_ = false;
1950         return;
1951     }
1952     if (canUseLongPredictTask_) {
1953         // check new incoming event after vsync.
1954         if (!touchEvents_.empty()) {
1955             canUseLongPredictTask_ = false;
1956         }
1957     }
1958     CHECK_RUN_ON(UI);
1959     ACE_SCOPED_TRACE("OnIdle, targettime:%" PRId64 "", deadline);
1960     taskScheduler_->FlushPredictTask(deadline - TIME_THRESHOLD, canUseLongPredictTask_);
1961     canUseLongPredictTask_ = false;
1962     if (GetSysTimestamp() < deadline) {
1963         ElementRegister::GetInstance()->CallJSCleanUpIdleTaskFunc();
1964     }
1965 }
1966 
Finish(bool) const1967 void PipelineContext::Finish(bool /*autoFinish*/) const
1968 {
1969     CHECK_RUN_ON(UI);
1970     if (finishEventHandler_) {
1971         LOGI("call finishEventHandler");
1972         finishEventHandler_();
1973     } else {
1974         LOGE("fail to finish current context due to handler is nullptr");
1975     }
1976 }
1977 
AddAfterLayoutTask(std::function<void ()> && task)1978 void PipelineContext::AddAfterLayoutTask(std::function<void()>&& task)
1979 {
1980     taskScheduler_->AddAfterLayoutTask(std::move(task));
1981 }
1982 
AddAfterRenderTask(std::function<void ()> && task)1983 void PipelineContext::AddAfterRenderTask(std::function<void()>&& task)
1984 {
1985     taskScheduler_->AddAfterRenderTask(std::move(task));
1986 }
1987 
RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)1988 void PipelineContext::RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)
1989 {
1990     if (!nodeInfo->IsObject()) {
1991         LOGW("restore nodeInfo is invalid");
1992     }
1993     auto child = nodeInfo->GetChild();
1994     while (child->IsValid()) {
1995         auto key = child->GetKey();
1996         auto value = child->GetString();
1997         restoreNodeInfo_.try_emplace(StringUtils::StringToInt(key), value);
1998         child = child->GetNext();
1999     }
2000 }
2001 
GetStoredNodeInfo()2002 std::unique_ptr<JsonValue> PipelineContext::GetStoredNodeInfo()
2003 {
2004     auto jsonNodeInfo = JsonUtil::Create(false);
2005     auto iter = storeNode_.begin();
2006     while (iter != storeNode_.end()) {
2007         auto node = (iter->second).Upgrade();
2008         if (node) {
2009             std::string info = node->ProvideRestoreInfo();
2010             if (!info.empty()) {
2011                 jsonNodeInfo->Put(std::to_string(iter->first).c_str(), info.c_str());
2012             }
2013         }
2014         ++iter;
2015     }
2016     return jsonNodeInfo;
2017 }
2018 
StoreNode(int32_t restoreId,const WeakPtr<FrameNode> & node)2019 void PipelineContext::StoreNode(int32_t restoreId, const WeakPtr<FrameNode>& node)
2020 {
2021     auto ret = storeNode_.try_emplace(restoreId, node);
2022     if (!ret.second) {
2023         LOGW("update restore node, id = %{public}d", restoreId);
2024         storeNode_[restoreId] = node;
2025     }
2026 }
2027 
GetRestoreInfo(int32_t restoreId,std::string & restoreInfo)2028 bool PipelineContext::GetRestoreInfo(int32_t restoreId, std::string& restoreInfo)
2029 {
2030     auto iter = restoreNodeInfo_.find(restoreId);
2031     if (iter != restoreNodeInfo_.end()) {
2032         restoreInfo = iter->second;
2033         restoreNodeInfo_.erase(iter);
2034         return true;
2035     }
2036     return false;
2037 }
2038 
SetContainerButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize)2039 void PipelineContext::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize)
2040 {
2041     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
2042         LOGW("SetAppIcon failed, Window modal is not container.");
2043         return;
2044     }
2045     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
2046     CHECK_NULL_VOID(containerNode);
2047     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
2048     CHECK_NULL_VOID(containerPattern);
2049     containerPattern->SetContainerButtonHide(hideSplit, hideMaximize, hideMinimize);
2050 }
2051 
AddFontNodeNG(const WeakPtr<UINode> & node)2052 void PipelineContext::AddFontNodeNG(const WeakPtr<UINode>& node)
2053 {
2054     if (fontManager_) {
2055         fontManager_->AddFontNodeNG(node);
2056     }
2057 }
2058 
RemoveFontNodeNG(const WeakPtr<UINode> & node)2059 void PipelineContext::RemoveFontNodeNG(const WeakPtr<UINode>& node)
2060 {
2061     if (fontManager_) {
2062         fontManager_->RemoveFontNodeNG(node);
2063     }
2064 }
2065 
SetWindowSceneConsumed(bool isConsumed)2066 void PipelineContext::SetWindowSceneConsumed(bool isConsumed)
2067 {
2068     isWindowSceneConsumed_ = isConsumed;
2069 }
2070 
IsWindowSceneConsumed()2071 bool PipelineContext::IsWindowSceneConsumed()
2072 {
2073     return isWindowSceneConsumed_;
2074 }
2075 
SetCloseButtonStatus(bool isEnabled)2076 void PipelineContext::SetCloseButtonStatus(bool isEnabled)
2077 {
2078     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
2079         return;
2080     }
2081     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
2082     CHECK_NULL_VOID(containerNode);
2083     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
2084     CHECK_NULL_VOID(containerPattern);
2085     containerPattern->SetCloseButtonStatus(isEnabled);
2086 }
2087 } // namespace OHOS::Ace::NG
2088