• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "base/memory/ace_type.h"
19 #include "core/components_ng/base/ui_node.h"
20 #include "core/components_ng/pattern/image/image_layout_property.h"
21 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
22 #include "core/components_ng/pattern/navigation/title_bar_node.h"
23 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
24 
25 #ifdef ENABLE_ROSEN_BACKEND
26 #include "render_service_client/core/ui/rs_ui_director.h"
27 
28 #include "core/components_ng/render/adapter/rosen_window.h"
29 #endif
30 
31 #include <algorithm>
32 #include <cinttypes>
33 #include <cstdint>
34 #include <memory>
35 
36 #include "base/geometry/ng/offset_t.h"
37 #include "base/log/ace_trace.h"
38 #include "base/log/ace_tracker.h"
39 #include "base/log/event_report.h"
40 #include "base/log/frame_report.h"
41 #include "base/memory/referenced.h"
42 #include "base/thread/task_executor.h"
43 #include "base/utils/utils.h"
44 #include "core/animation/scheduler.h"
45 #include "core/common/ace_application_info.h"
46 #include "core/common/container.h"
47 #include "core/common/layout_inspector.h"
48 #include "core/common/text_field_manager.h"
49 #include "core/common/thread_checker.h"
50 #include "core/common/window.h"
51 #include "core/components/common/layout/grid_system_manager.h"
52 #include "core/components_ng/base/frame_node.h"
53 #include "core/components_ng/pattern/app_bar/app_bar_view.h"
54 #include "core/components_ng/pattern/container_modal/container_modal_pattern.h"
55 #include "core/components_ng/pattern/container_modal/container_modal_view.h"
56 #include "core/components_ng/pattern/custom/custom_node_base.h"
57 #include "core/components_ng/pattern/overlay/overlay_manager.h"
58 #include "core/components_ng/pattern/root/root_pattern.h"
59 #include "core/components_ng/pattern/stage/stage_pattern.h"
60 #include "core/components_ng/pattern/text_field/text_field_manager.h"
61 #include "core/components_ng/property/calc_length.h"
62 #include "core/components_v2/inspector/inspector_constants.h"
63 #include "core/event/ace_events.h"
64 #include "core/event/touch_event.h"
65 #include "core/pipeline/base/element_register.h"
66 #include "core/pipeline/pipeline_context.h"
67 #include "core/pipeline_ng/ui_task_scheduler.h"
68 
69 namespace {
70 constexpr int32_t TIME_THRESHOLD = 2 * 1000000; // 3 millisecond
71 } // namespace
72 
73 namespace OHOS::Ace::NG {
74 
PipelineContext(std::unique_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,RefPtr<PlatformResRegister> platformResRegister,const RefPtr<Frontend> & frontend,int32_t instanceId)75 PipelineContext::PipelineContext(std::unique_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
76     RefPtr<AssetManager> assetManager, RefPtr<PlatformResRegister> platformResRegister,
77     const RefPtr<Frontend>& frontend, int32_t instanceId)
78     : PipelineBase(std::move(window), std::move(taskExecutor), std::move(assetManager), frontend, instanceId)
79 {
80     window_->OnHide();
81 }
82 
PipelineContext(std::unique_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend,int32_t instanceId)83 PipelineContext::PipelineContext(std::unique_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
84     RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend, int32_t instanceId)
85     : PipelineBase(std::move(window), std::move(taskExecutor), std::move(assetManager), frontend, instanceId)
86 {
87     window_->OnHide();
88 }
89 
GetCurrentContext()90 RefPtr<PipelineContext> PipelineContext::GetCurrentContext()
91 {
92     auto currentContainer = Container::Current();
93     CHECK_NULL_RETURN(currentContainer, nullptr);
94     return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
95 }
96 
GetCurrentRootWidth()97 float PipelineContext::GetCurrentRootWidth()
98 {
99     auto context = GetCurrentContext();
100     CHECK_NULL_RETURN(context, 0.0f);
101     return static_cast<float>(context->rootWidth_);
102 }
103 
GetCurrentRootHeight()104 float PipelineContext::GetCurrentRootHeight()
105 {
106     auto context = GetCurrentContext();
107     CHECK_NULL_RETURN(context, 0.0f);
108     return static_cast<float>(context->rootHeight_);
109 }
110 
AddDirtyCustomNode(const RefPtr<UINode> & dirtyNode)111 void PipelineContext::AddDirtyCustomNode(const RefPtr<UINode>& dirtyNode)
112 {
113     CHECK_RUN_ON(UI);
114     CHECK_NULL_VOID(dirtyNode);
115     dirtyNodes_.emplace(dirtyNode);
116     hasIdleTasks_ = true;
117     window_->RequestFrame();
118 }
119 
AddDirtyLayoutNode(const RefPtr<FrameNode> & dirty)120 void PipelineContext::AddDirtyLayoutNode(const RefPtr<FrameNode>& dirty)
121 {
122     CHECK_RUN_ON(UI);
123     CHECK_NULL_VOID(dirty);
124     taskScheduler_.AddDirtyLayoutNode(dirty);
125     ForceLayoutForImplicitAnimation();
126     hasIdleTasks_ = true;
127     window_->RequestFrame();
128 }
129 
AddDirtyRenderNode(const RefPtr<FrameNode> & dirty)130 void PipelineContext::AddDirtyRenderNode(const RefPtr<FrameNode>& dirty)
131 {
132     CHECK_RUN_ON(UI);
133     CHECK_NULL_VOID(dirty);
134     taskScheduler_.AddDirtyRenderNode(dirty);
135     hasIdleTasks_ = true;
136     window_->RequestFrame();
137 }
138 
FlushDirtyNodeUpdate()139 void PipelineContext::FlushDirtyNodeUpdate()
140 {
141     CHECK_RUN_ON(UI);
142     ACE_FUNCTION_TRACE();
143     if (FrameReport::GetInstance().GetEnable()) {
144         FrameReport::GetInstance().BeginFlushBuild();
145     }
146 
147     // SomeTimes, customNode->Update may add some dirty custom nodes to dirtyNodes_,
148     // use maxFlushTimes to avoid dead cycle.
149     int maxFlushTimes = 3;
150     while (!dirtyNodes_.empty() && maxFlushTimes > 0) {
151         decltype(dirtyNodes_) dirtyNodes(std::move(dirtyNodes_));
152         for (const auto& node : dirtyNodes) {
153             if (AceType::InstanceOf<NG::CustomNodeBase>(node)) {
154                 auto customNode = AceType::DynamicCast<NG::CustomNodeBase>(node);
155                 customNode->Update();
156             }
157         }
158         --maxFlushTimes;
159     }
160     if (!dirtyNodes_.empty()) {
161         LOGW("FlushDirtyNodeUpdate 3 times, still has dirty nodes");
162     }
163 
164     if (FrameReport::GetInstance().GetEnable()) {
165         FrameReport::GetInstance().EndFlushBuild();
166     }
167 }
168 
AddScheduleTask(const RefPtr<ScheduleTask> & task)169 uint32_t PipelineContext::AddScheduleTask(const RefPtr<ScheduleTask>& task)
170 {
171     CHECK_RUN_ON(UI);
172     scheduleTasks_.try_emplace(++nextScheduleTaskId_, task);
173     window_->RequestFrame();
174     return nextScheduleTaskId_;
175 }
176 
FlushVsync(uint64_t nanoTimestamp,uint32_t frameCount)177 void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount)
178 {
179     CHECK_RUN_ON(UI);
180     ACE_FUNCTION_TRACE();
181     static const std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
182                                                ? AceApplicationInfo::GetInstance().GetPackageName()
183                                                : AceApplicationInfo::GetInstance().GetProcessName();
184     window_->RecordFrameTime(nanoTimestamp, abilityName);
185     FlushAnimation(GetTimeFromExternalTimer());
186     FlushBuild();
187     if (isFormRender_ && drawDelegate_) {
188         auto renderContext = AceType::DynamicCast<NG::RenderContext>(rootNode_->GetRenderContext());
189         drawDelegate_->DrawRSFrame(renderContext);
190         drawDelegate_ = nullptr;
191     }
192     FlushTouchEvents();
193     if (!taskScheduler_.isEmpty()) {
194 #if !defined(PREVIEW)
195         LayoutInspector::SupportInspector();
196 #endif
197     }
198     taskScheduler_.FlushTask();
199     TryCallNextFrameLayoutCallback();
200     auto hasAninmation = window_->FlushCustomAnimation(nanoTimestamp);
201     if (hasAninmation) {
202         RequestFrame();
203     }
204     FlushMessages();
205     if (!isFormRender_ && onShow_ && onFocus_) {
206         FlushFocus();
207     }
208     HandleOnAreaChangeEvent();
209     HandleVisibleAreaChangeEvent();
210 }
211 
FlushAnimation(uint64_t nanoTimestamp)212 void PipelineContext::FlushAnimation(uint64_t nanoTimestamp)
213 {
214     CHECK_RUN_ON(UI);
215     ACE_FUNCTION_TRACE();
216     if (scheduleTasks_.empty()) {
217         return;
218     }
219 
220     if (FrameReport::GetInstance().GetEnable()) {
221         FrameReport::GetInstance().BeginFlushAnimation();
222     }
223 
224     decltype(scheduleTasks_) temp(std::move(scheduleTasks_));
225     for (const auto& [id, weakTask] : temp) {
226         auto task = weakTask.Upgrade();
227         if (task) {
228             task->OnFrame(nanoTimestamp);
229         }
230     }
231 
232     if (FrameReport::GetInstance().GetEnable()) {
233         FrameReport::GetInstance().EndFlushAnimation();
234     }
235 }
236 
FlushMessages()237 void PipelineContext::FlushMessages()
238 {
239     ACE_FUNCTION_TRACE();
240     window_->FlushTasks();
241 }
242 
FlushFocus()243 void PipelineContext::FlushFocus()
244 {
245     CHECK_RUN_ON(UI);
246     ACE_FUNCTION_TRACK();
247     ACE_FUNCTION_TRACE();
248     auto focusNode = dirtyFocusNode_.Upgrade();
249     if (!focusNode || focusNode->GetFocusType() != FocusType::NODE) {
250         dirtyFocusNode_.Reset();
251     } else {
252         auto focusNodeHub = focusNode->GetFocusHub();
253         if (focusNodeHub) {
254             focusNodeHub->RequestFocusImmediately();
255         }
256         dirtyFocusNode_.Reset();
257         dirtyFocusScope_.Reset();
258         return;
259     }
260     auto focusScope = dirtyFocusScope_.Upgrade();
261     if (!focusScope || focusScope->GetFocusType() != FocusType::SCOPE) {
262         dirtyFocusScope_.Reset();
263     } else {
264         auto focusScopeHub = focusScope->GetFocusHub();
265         if (focusScopeHub) {
266             focusScopeHub->RequestFocusImmediately();
267         }
268         dirtyFocusNode_.Reset();
269         dirtyFocusScope_.Reset();
270         return;
271     }
272     if (!RequestDefaultFocus()) {
273         if (rootNode_ && rootNode_->GetFocusHub() && !rootNode_->GetFocusHub()->IsCurrentFocus()) {
274             rootNode_->GetFocusHub()->RequestFocusImmediately();
275         }
276     }
277 }
278 
FlushPipelineImmediately()279 void PipelineContext::FlushPipelineImmediately()
280 {
281     CHECK_RUN_ON(UI);
282     ACE_FUNCTION_TRACE();
283     FlushPipelineWithoutAnimation();
284 }
285 
FlushPipelineWithoutAnimation()286 void PipelineContext::FlushPipelineWithoutAnimation()
287 {
288     FlushBuild();
289     FlushTouchEvents();
290     taskScheduler_.FlushTask();
291     FlushMessages();
292     FlushFocus();
293 }
294 
FlushBuild()295 void PipelineContext::FlushBuild()
296 {
297     isRebuildFinished_ = false;
298     FlushDirtyNodeUpdate();
299     isRebuildFinished_ = true;
300     FlushBuildFinishCallbacks();
301 }
302 
FlushBuildFinishCallbacks()303 void PipelineContext::FlushBuildFinishCallbacks()
304 {
305     decltype(buildFinishCallbacks_) buildFinishCallbacks(std::move(buildFinishCallbacks_));
306     for (const auto& func : buildFinishCallbacks) {
307         if (func) {
308             func();
309         }
310     }
311 }
312 
RegisterRootEvent()313 void PipelineContext::RegisterRootEvent()
314 {
315     if (!IsFormRender()) {
316         return;
317     }
318 
319     // To avoid conflicts between longPress and click events on the card,
320     // use an empty longPress event placeholder in the EtsCard scenario
321     auto hub = rootNode_->GetOrCreateGestureEventHub();
322     CHECK_NULL_VOID(hub);
323     auto event = [](const GestureEvent& info) mutable {
324         LOGD("Not Support LongPress");
325     };
326     auto longPress = AceType::MakeRefPtr<NG::LongPressEvent>(std::move(event));
327     hub->SetLongPressEvent(longPress, false, true);
328 }
329 
SetupRootElement()330 void PipelineContext::SetupRootElement()
331 {
332     CHECK_RUN_ON(UI);
333     rootNode_ = FrameNode::CreateFrameNodeWithTree(
334         V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
335     rootNode_->SetHostRootId(GetInstanceId());
336     rootNode_->SetHostPageId(-1);
337     RegisterRootEvent();
338     CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
339     MeasureProperty layoutConstraint;
340     layoutConstraint.selfIdealSize = idealSize;
341     layoutConstraint.maxSize = idealSize;
342     rootNode_->UpdateLayoutConstraint(layoutConstraint);
343     auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
344     rootFocusHub->SetFocusType(FocusType::SCOPE);
345     rootFocusHub->SetFocusable(true);
346     window_->SetRootFrameNode(rootNode_);
347     rootNode_->AttachToMainTree();
348 
349     auto stageNode = FrameNode::CreateFrameNode(
350         V2::STAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<StagePattern>());
351     auto appBarNode = installationFree_ ? AppBarView::Create(stageNode) : nullptr;
352     if (windowModal_ == WindowModal::CONTAINER_MODAL) {
353         rootNode_->AddChild(ContainerModalView::Create(appBarNode ? appBarNode : stageNode));
354     } else {
355         rootNode_->AddChild(appBarNode ? appBarNode : stageNode);
356     }
357 #ifdef ENABLE_ROSEN_BACKEND
358     if (!IsJsCard() && !isFormRender_) {
359         auto rsWindow = static_cast<RosenWindow*>(GetWindow());
360         if (rsWindow) {
361             auto rsUIDirector = rsWindow->GetRsUIDirector();
362             if (rsUIDirector) {
363                 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
364             }
365         }
366     }
367 #endif
368     stageManager_ = MakeRefPtr<StageManager>(stageNode);
369     overlayManager_ = MakeRefPtr<OverlayManager>(
370         DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
371     fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
372     selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
373     dragDropManager_ = MakeRefPtr<DragDropManager>();
374     sharedTransitionManager_ = MakeRefPtr<SharedOverlayManager>(
375         DynamicCast<FrameNode>(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent()));
376 
377     OnAreaChangedFunc onAreaChangedFunc = [weakOverlayManger = AceType::WeakClaim(AceType::RawPtr(overlayManager_))](
378                                               const RectF& /* oldRect */, const OffsetF& /* oldOrigin */,
379                                               const RectF& /* rect */, const OffsetF& /* origin */) {
380         auto overlay = weakOverlayManger.Upgrade();
381         CHECK_NULL_VOID(overlay);
382         overlay->HideAllMenus();
383         overlay->HideAllPopups();
384     };
385     rootNode_->SetOnAreaChangeCallback(std::move(onAreaChangedFunc));
386     AddOnAreaChangeNode(rootNode_->GetId());
387 
388     LOGI("SetupRootElement success!");
389 }
390 
SetupSubRootElement()391 void PipelineContext::SetupSubRootElement()
392 {
393     CHECK_RUN_ON(UI);
394     appBgColor_ = Color::TRANSPARENT;
395     rootNode_ = FrameNode::CreateFrameNodeWithTree(
396         V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), MakeRefPtr<RootPattern>());
397     rootNode_->SetHostRootId(GetInstanceId());
398     rootNode_->SetHostPageId(-1);
399     CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
400     MeasureProperty layoutConstraint;
401     layoutConstraint.selfIdealSize = idealSize;
402     layoutConstraint.maxSize = idealSize;
403     rootNode_->UpdateLayoutConstraint(layoutConstraint);
404     auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
405     rootFocusHub->SetFocusType(FocusType::SCOPE);
406     rootFocusHub->SetFocusable(true);
407     window_->SetRootFrameNode(rootNode_);
408     rootNode_->AttachToMainTree();
409 
410 #ifdef ENABLE_ROSEN_BACKEND
411     if (!IsJsCard()) {
412         auto rsWindow = static_cast<RosenWindow*>(GetWindow());
413         if (rsWindow) {
414             auto rsUIDirector = rsWindow->GetRsUIDirector();
415             if (rsUIDirector) {
416                 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
417             }
418         }
419     }
420 #endif
421     // the subwindow for overlay not need stage
422     stageManager_ = MakeRefPtr<StageManager>(nullptr);
423     overlayManager_ = MakeRefPtr<OverlayManager>(rootNode_);
424     fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
425     selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
426     dragDropManager_ = MakeRefPtr<DragDropManager>();
427 }
428 
GetStageManager()429 const RefPtr<StageManager>& PipelineContext::GetStageManager()
430 {
431     return stageManager_;
432 }
433 
GetDragDropManager()434 const RefPtr<DragDropManager>& PipelineContext::GetDragDropManager()
435 {
436     return dragDropManager_;
437 }
438 
GetSelectOverlayManager()439 const RefPtr<SelectOverlayManager>& PipelineContext::GetSelectOverlayManager()
440 {
441     return selectOverlayManager_;
442 }
443 
GetOverlayManager()444 const RefPtr<OverlayManager>& PipelineContext::GetOverlayManager()
445 {
446     return overlayManager_;
447 }
448 
GetFullScreenManager()449 const RefPtr<FullScreenManager>& PipelineContext::GetFullScreenManager()
450 {
451     return fullScreenManager_;
452 }
453 
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type)454 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
455 {
456     CHECK_RUN_ON(UI);
457     LOGD("PipelineContext: OnSurfaceChanged start.");
458     if (NearEqual(rootWidth_, width) && NearEqual(rootHeight_, height) &&
459         type == WindowSizeChangeReason::CUSTOM_ANIMATION) {
460         TryCallNextFrameLayoutCallback();
461         return;
462     }
463     ExecuteSurfaceChangedCallbacks(width, height);
464     // TODO: add adjust for textFieldManager when ime is show.
465     taskExecutor_->PostTask(
466         [weakFrontend = weakFrontend_, width, height]() {
467             auto frontend = weakFrontend.Upgrade();
468             if (frontend) {
469                 frontend->OnSurfaceChanged(width, height);
470             }
471         },
472         TaskExecutor::TaskType::JS);
473 
474 #ifdef ENABLE_ROSEN_BACKEND
475     StartWindowSizeChangeAnimate(width, height, type);
476 #else
477     SetRootRect(width, height, 0.0);
478 #endif
479 }
480 
ExecuteSurfaceChangedCallbacks(int32_t newWidth,int32_t newHeight)481 void PipelineContext::ExecuteSurfaceChangedCallbacks(int32_t newWidth, int32_t newHeight)
482 {
483     for (auto&& [id, callback] : surfaceChangedCallbackMap_) {
484         if (callback) {
485             callback(newWidth, newHeight, rootWidth_, rootHeight_);
486         }
487     }
488 }
489 
OnSurfacePositionChanged(int32_t posX,int32_t posY)490 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
491 {
492     for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
493         if (callback) {
494             callback(posX, posY);
495         }
496     }
497 }
498 
StartWindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type)499 void PipelineContext::StartWindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type)
500 {
501     static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
502     if (!IsWindowSizeAnimationEnabled) {
503         LOGE("no animation configured");
504         SetRootRect(width, height, 0.0);
505         return;
506     }
507     switch (type) {
508         case WindowSizeChangeReason::RECOVER:
509         case WindowSizeChangeReason::MAXIMIZE: {
510             LOGI("PipelineContext::Root node RECOVER/MAXIMIZE animation, width = %{public}d, height = %{public}d",
511                 width, height);
512             AnimationOption option;
513             constexpr int32_t duration = 400;
514             option.SetDuration(duration);
515             auto curve = MakeRefPtr<DecelerationCurve>();
516             option.SetCurve(curve);
517             auto weak = WeakClaim(this);
518             Animate(option, curve, [width, height, weak]() {
519                 auto pipeline = weak.Upgrade();
520                 CHECK_NULL_VOID(pipeline);
521                 pipeline->SetRootRect(width, height, 0.0);
522                 pipeline->FlushUITasks();
523             });
524             break;
525         }
526         case WindowSizeChangeReason::ROTATION: {
527             LOGI("PipelineContext::Root node ROTATION animation, width = %{public}d, height = %{public}d", width,
528                 height);
529             AnimationOption option;
530             constexpr int32_t duration = 600;
531             option.SetDuration(duration);
532             auto curve = MakeRefPtr<CubicCurve>(0.2, 0.0, 0.2, 1.0); // animation curve: cubic [0.2, 0.0, 0.2, 1.0]
533             option.SetCurve(curve);
534             auto weak = WeakClaim(this);
535             Animate(
536                 option, curve,
537                 [width, height, weak]() {
538                     auto pipeline = weak.Upgrade();
539                     CHECK_NULL_VOID(pipeline);
540                     pipeline->SetRootRect(width, height, 0.0);
541                     pipeline->FlushUITasks();
542                 },
543                 [weak]() {
544                     auto pipeline = weak.Upgrade();
545                     CHECK_NULL_VOID(pipeline);
546                     pipeline->rotationAnimationCount_--;
547                     if (pipeline->rotationAnimationCount_ < 0) {
548                         LOGE("PipelineContext::Root node ROTATION animation callback"
549                              "rotationAnimationCount Invalid %{public}d",
550                             pipeline->rotationAnimationCount_);
551                     }
552                     if (pipeline->rotationAnimationCount_ == 0) {
553                         pipeline->window_->SetDrawTextAsBitmap(false);
554                     }
555                 });
556             rotationAnimationCount_++;
557             window_->SetDrawTextAsBitmap(true);
558             break;
559         }
560         case WindowSizeChangeReason::DRAG_START:
561         case WindowSizeChangeReason::DRAG:
562         case WindowSizeChangeReason::DRAG_END:
563         case WindowSizeChangeReason::RESIZE:
564         case WindowSizeChangeReason::UNDEFINED:
565         default: {
566             LOGD("PipelineContext::RootNodeAnimation : unsupported type, no animation added");
567             SetRootRect(width, height, 0.0f);
568         }
569     }
570 }
571 
SetRootRect(double width,double height,double offset)572 void PipelineContext::SetRootRect(double width, double height, double offset)
573 {
574     LOGI("SetRootRect width %{public}f, height %{public}f, %{public}f", width, height, offset);
575     CHECK_RUN_ON(UI);
576     UpdateRootSizeAndScale(width, height);
577     CHECK_NULL_VOID(rootNode_);
578     GridSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
579     GridSystemManager::GetInstance().OnSurfaceChanged(width);
580     SizeF sizeF { static_cast<float>(width), static_cast<float>(height) };
581     if (rootNode_->GetGeometryNode()->GetFrameSize() != sizeF || rootNode_->IsLayoutDirtyMarked()) {
582         CalcSize idealSize { CalcLength(width), CalcLength(height) };
583         MeasureProperty layoutConstraint;
584         layoutConstraint.selfIdealSize = idealSize;
585         layoutConstraint.maxSize = idealSize;
586         rootNode_->UpdateLayoutConstraint(layoutConstraint);
587         // reset parentLayoutConstraint to update itself when next measure task
588         rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
589         rootNode_->MarkDirtyNode();
590     }
591     if (rootNode_->GetGeometryNode()->GetFrameOffset().GetY() != offset) {
592         OffsetF newOffset = rootNode_->GetGeometryNode()->GetFrameOffset();
593         newOffset.SetY(static_cast<float>(offset));
594         rootNode_->GetGeometryNode()->SetMarginFrameOffset(newOffset);
595         auto rootContext = rootNode_->GetRenderContext();
596         rootContext->SyncGeometryProperties(RawPtr(rootNode_->GetGeometryNode()));
597         RequestFrame();
598     }
599 }
600 
OnVirtualKeyboardHeightChange(float keyboardHeight)601 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight)
602 {
603     CHECK_RUN_ON(UI);
604     float positionY = 0;
605     auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
606     float height = 0.0f;
607     if (manager) {
608         height = manager->GetHeight();
609         positionY = static_cast<float>(manager->GetClickPosition().GetY());
610     }
611     SizeF rootSize { static_cast<float>(rootWidth_), static_cast<float>(rootHeight_) };
612     float offsetFix = (rootSize.Height() - positionY) > 100.0 ? keyboardHeight - (rootSize.Height() - positionY) / 2.0
613                                                               : keyboardHeight;
614     LOGI("OnVirtualKeyboardAreaChange positionY:%{public}f safeArea:%{public}f offsetFix:%{public}f, "
615          "keyboardHeight %{public}f",
616         positionY, (rootSize.Height() - keyboardHeight), offsetFix, keyboardHeight);
617     if (NearZero(keyboardHeight)) {
618         SetRootRect(rootSize.Width(), rootSize.Height(), 0);
619     } else if (positionY > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0) {
620         SetRootRect(rootSize.Width(), rootSize.Height(), -offsetFix);
621     } else if ((positionY + height > rootSize.Height() - keyboardHeight &&
622                    positionY < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
623                NearZero(rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
624         SetRootRect(rootSize.Width(), rootSize.Height(), -height - offsetFix / 2.0f);
625     }
626 }
627 
OnBackPressed()628 bool PipelineContext::OnBackPressed()
629 {
630     LOGD("OnBackPressed");
631     CHECK_RUN_ON(PLATFORM);
632     auto frontend = weakFrontend_.Upgrade();
633     if (!frontend) {
634         // return back.
635         return false;
636     }
637 
638     // If the tag of the last child of the rootnode is video, exit full screen.
639     if (fullScreenManager_->OnBackPressed()) {
640         LOGI("Exit full screen: back press accepted");
641         return true;
642     }
643 
644     // if has sharedTransition, back press will stop the sharedTransition
645     if (sharedTransitionManager_->OnBackPressed()) {
646         LOGI("sharedTransition stop: back press accepted");
647         return true;
648     }
649 
650     // if has popup, back press would hide popup and not trigger page back
651     auto hasOverlay = false;
652     taskExecutor_->PostSyncTask(
653         [weakOverlay = AceType::WeakClaim(AceType::RawPtr(overlayManager_)), &hasOverlay]() {
654             auto overlay = weakOverlay.Upgrade();
655             CHECK_NULL_VOID_NOLOG(overlay);
656             hasOverlay = overlay->RemoveOverlay();
657         },
658         TaskExecutor::TaskType::UI);
659     if (hasOverlay) {
660         LOGI("popup hidden: back press accepted");
661         return true;
662     }
663 
664     auto result = false;
665     taskExecutor_->PostSyncTask(
666         [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), &result]() {
667             auto frontend = weakFrontend.Upgrade();
668             if (!frontend) {
669                 LOGW("frontend is nullptr");
670                 result = false;
671                 return;
672             }
673             auto context = weakPipelineContext.Upgrade();
674             if (!context) {
675                 LOGW("pipelineContext is nullptr");
676                 result = false;
677                 return;
678             }
679             if (context->GetNavDestinationBackButtonNode()) {
680                 auto navDestinationNode =
681                     AceType::DynamicCast<NavDestinationGroupNode>(context->GetNavDestinationBackButtonNode());
682                 if (navDestinationNode->GetNavDestinationBackButtonEvent()) {
683                     GestureEvent gestureEvent;
684                     navDestinationNode->GetNavDestinationBackButtonEvent()(gestureEvent);
685                     result = true;
686                 }
687             }
688         },
689         TaskExecutor::TaskType::UI);
690 
691     if (result) {
692         // user accept
693         LOGI("CallRouterBackToPopPage(): frontend accept");
694         return true;
695     }
696 
697     taskExecutor_->PostSyncTask(
698         [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), &result]() {
699             auto frontend = weakFrontend.Upgrade();
700             if (!frontend) {
701                 LOGW("frontend is nullptr");
702                 result = false;
703                 return;
704             }
705             result = frontend->OnBackPressed();
706         },
707         TaskExecutor::TaskType::JS);
708 
709     if (result) {
710         // user accept
711         LOGI("CallRouterBackToPopPage(): frontend accept");
712         return true;
713     }
714     LOGI("CallRouterBackToPopPage(): return platform consumed");
715     return false;
716 }
717 
GetNavDestinationBackButtonNode()718 RefPtr<FrameNode> PipelineContext::GetNavDestinationBackButtonNode()
719 {
720     auto lastPage = stageManager_->GetLastPage();
721     CHECK_NULL_RETURN(lastPage, nullptr);
722     auto navigationNode = lastPage->FindChildNodeOfClass<NavigationGroupNode>();
723     CHECK_NULL_RETURN(navigationNode, nullptr);
724     auto navigationContentNode = navigationNode->GetContentNode();
725     CHECK_NULL_RETURN(navigationContentNode, nullptr);
726     auto navDestinationNode = navigationContentNode->FindChildNodeOfClass<NavDestinationGroupNode>();
727     CHECK_NULL_RETURN(navDestinationNode, nullptr);
728     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationNode->GetTitleBarNode());
729     CHECK_NULL_RETURN(titleBarNode, nullptr);
730     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
731     CHECK_NULL_RETURN(backButtonNode, nullptr);
732     auto backButtonLayoutProperty = backButtonNode->GetLayoutProperty<ImageLayoutProperty>();
733     if (!backButtonLayoutProperty->HasVisibility()) {
734         return nullptr;
735     }
736 
737     if (backButtonLayoutProperty->GetVisibilityValue() != VisibleType::VISIBLE) {
738         return nullptr;
739     }
740     return navDestinationNode;
741 }
742 
OnTouchEvent(const TouchEvent & point,bool isSubPipe)743 void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe)
744 {
745     CHECK_RUN_ON(UI);
746     HandleEtsCardTouchEvent(point);
747     auto scalePoint = point.CreateScalePoint(GetViewScale());
748     LOGD("AceTouchEvent: x = %{public}f, y = %{public}f, type = %{public}zu", scalePoint.x, scalePoint.y,
749         scalePoint.type);
750     eventManager_->SetInstanceId(GetInstanceId());
751     if (scalePoint.type == TouchType::DOWN) {
752         isNeedShowFocus_ = false;
753         CHECK_NULL_VOID_NOLOG(rootNode_);
754         auto rootFocusHub = rootNode_->GetFocusHub();
755         if (rootFocusHub) {
756             rootFocusHub->ClearAllFocusState();
757         }
758 
759         LOGD("receive touch down event, first use touch test to collect touch event target");
760         TouchRestrict touchRestrict { TouchRestrict::NONE };
761         touchRestrict.sourceType = point.sourceType;
762         touchRestrict.touchEvent = point;
763         eventManager_->TouchTest(scalePoint, rootNode_, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe);
764 
765         for (const auto& weakContext : touchPluginPipelineContext_) {
766             auto pipelineContext = DynamicCast<OHOS::Ace::PipelineBase>(weakContext.Upgrade());
767             if (!pipelineContext) {
768                 continue;
769             }
770             auto pluginPoint =
771                 point.UpdateScalePoint(viewScale_, static_cast<float>(pipelineContext->GetPluginEventOffset().GetX()),
772                     static_cast<float>(pipelineContext->GetPluginEventOffset().GetY()), point.id);
773             // eventManager_ instance Id may changed.
774             pipelineContext->OnTouchEvent(pluginPoint, true);
775         }
776 
777         // restore instance Id.
778         eventManager_->SetInstanceId(GetInstanceId());
779     }
780     if (isSubPipe) {
781         return;
782     }
783 
784     if (scalePoint.type == TouchType::MOVE) {
785         touchEvents_.emplace_back(point);
786         hasIdleTasks_ = true;
787         window_->RequestFrame();
788         return;
789     }
790 
791     std::optional<TouchEvent> lastMoveEvent;
792     if (scalePoint.type == TouchType::UP && !touchEvents_.empty()) {
793         for (auto iter = touchEvents_.begin(); iter != touchEvents_.end(); ++iter) {
794             auto movePoint = (*iter).CreateScalePoint(GetViewScale());
795             if (scalePoint.id == movePoint.id) {
796                 lastMoveEvent = movePoint;
797                 touchEvents_.erase(iter++);
798             }
799         }
800         if (lastMoveEvent.has_value()) {
801             eventManager_->DispatchTouchEvent(lastMoveEvent.value());
802         }
803     }
804 
805     eventManager_->DispatchTouchEvent(scalePoint);
806 
807     if ((scalePoint.type == TouchType::UP) || (scalePoint.type == TouchType::CANCEL)) {
808         // need to reset touchPluginPipelineContext_ for next touch down event.
809         touchPluginPipelineContext_.clear();
810         RemoveEtsCardTouchEventCallback(point.id);
811     }
812 
813     hasIdleTasks_ = true;
814     window_->RequestFrame();
815 }
816 
OnSurfaceDensityChanged(double density)817 void PipelineContext::OnSurfaceDensityChanged(double density)
818 {
819     CHECK_RUN_ON(UI);
820     LOGI("OnSurfaceDensityChanged density_(%{public}lf)", density_);
821     LOGI("OnSurfaceDensityChanged dipScale_(%{public}lf)", dipScale_);
822     density_ = density;
823     if (!NearZero(viewScale_)) {
824         LOGI("OnSurfaceDensityChanged viewScale_(%{public}lf)", viewScale_);
825         dipScale_ = density_ / viewScale_;
826     }
827 }
828 
OnDumpInfo(const std::vector<std::string> & params) const829 bool PipelineContext::OnDumpInfo(const std::vector<std::string>& params) const
830 {
831     ACE_DCHECK(!params.empty());
832 
833     if (params[0] == "-element") {
834         if (params.size() > 1 && params[1] == "-lastpage") {
835             auto lastPage = stageManager_->GetLastPage();
836             if (lastPage) {
837                 lastPage->DumpTree(0);
838             }
839         } else {
840             rootNode_->DumpTree(0);
841         }
842     } else if (params[0] == "-render") {
843     } else if (params[0] == "-focus") {
844         if (rootNode_->GetFocusHub()) {
845             rootNode_->GetFocusHub()->DumpFocusTree(0);
846         }
847     } else if (params[0] == "-layer") {
848     } else if (params[0] == "-frontend") {
849 #ifndef WEARABLE_PRODUCT
850     } else if (params[0] == "-multimodal") {
851 #endif
852     } else if (params[0] == "-accessibility" || params[0] == "-inspector") {
853         auto accessibilityManager = GetAccessibilityManager();
854         if (accessibilityManager) {
855             accessibilityManager->OnDumpInfo(params);
856         }
857     } else if (params[0] == "-rotation" && params.size() >= 2) {
858     } else if (params[0] == "-animationscale" && params.size() >= 2) {
859     } else if (params[0] == "-velocityscale" && params.size() >= 2) {
860     } else if (params[0] == "-scrollfriction" && params.size() >= 2) {
861     } else if (params[0] == "-threadstuck" && params.size() >= 3) {
862     } else {
863         return false;
864     }
865     return true;
866 }
867 
FlushTouchEvents()868 void PipelineContext::FlushTouchEvents()
869 {
870     CHECK_RUN_ON(UI);
871     CHECK_NULL_VOID(rootNode_);
872     {
873         eventManager_->FlushTouchEventsBegin(touchEvents_);
874         std::unordered_set<int32_t> moveEventIds;
875         decltype(touchEvents_) touchEvents(std::move(touchEvents_));
876         if (touchEvents.empty()) {
877             return;
878         }
879         std::list<TouchEvent> touchPoints;
880         for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter) {
881             auto scalePoint = (*iter).CreateScalePoint(GetViewScale());
882             auto result = moveEventIds.emplace(scalePoint.id);
883             if (result.second) {
884                 touchPoints.emplace_front(scalePoint);
885             }
886         }
887         auto maxSize = touchPoints.size();
888         for (auto iter = touchPoints.rbegin(); iter != touchPoints.rend(); ++iter) {
889             maxSize--;
890             if (maxSize == 0) {
891                 eventManager_->FlushTouchEventsEnd(touchPoints);
892             }
893             eventManager_->DispatchTouchEvent(*iter);
894         }
895     }
896 }
897 
OnMouseEvent(const MouseEvent & event)898 void PipelineContext::OnMouseEvent(const MouseEvent& event)
899 {
900     CHECK_RUN_ON(UI);
901 
902     if ((event.action == MouseAction::RELEASE || event.action == MouseAction::PRESS ||
903             event.action == MouseAction::MOVE) &&
904         (event.button == MouseButton::LEFT_BUTTON || event.pressedButtons == MOUSE_PRESS_LEFT)) {
905         auto touchPoint = event.CreateTouchPoint();
906         OnTouchEvent(touchPoint);
907     }
908 
909     CHECK_NULL_VOID(rootNode_);
910     auto scaleEvent = event.CreateScaleEvent(viewScale_);
911     LOGD(
912         "MouseEvent (x,y): (%{public}f,%{public}f), button: %{public}d, action: %{public}d, pressedButtons: %{public}d",
913         scaleEvent.x, scaleEvent.y, scaleEvent.button, scaleEvent.action, scaleEvent.pressedButtons);
914     TouchRestrict touchRestrict { TouchRestrict::NONE };
915     touchRestrict.sourceType = event.sourceType;
916     touchRestrict.hitTestType = SourceType::MOUSE;
917     eventManager_->MouseTest(scaleEvent, rootNode_, touchRestrict);
918     eventManager_->DispatchMouseEventNG(scaleEvent);
919     eventManager_->DispatchMouseHoverEventNG(scaleEvent);
920     eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
921     window_->RequestFrame();
922 }
923 
ChangeMouseStyle(int32_t nodeId,MouseFormat format)924 bool PipelineContext::ChangeMouseStyle(int32_t nodeId, MouseFormat format)
925 {
926     if (mouseStyleNodeId_ != nodeId) {
927         return false;
928     }
929     auto mouseStyle = MouseStyle::CreateMouseStyle();
930     return mouseStyle->ChangePointerStyle(GetWindowId(), format);
931 }
932 
OnKeyEvent(const KeyEvent & event)933 bool PipelineContext::OnKeyEvent(const KeyEvent& event)
934 {
935     eventManager_->SetPressedKeyCodes(event.pressedCodes);
936     // Need update while key tab pressed
937     if (!isNeedShowFocus_ && event.action == KeyAction::DOWN &&
938         (event.IsKey({ KeyCode::KEY_TAB }) || event.IsDirectionalKey())) {
939         isNeedShowFocus_ = true;
940         auto rootFocusHub = rootNode_->GetFocusHub();
941         if (rootFocusHub) {
942             rootFocusHub->PaintAllFocusState();
943         }
944         return true;
945     }
946     auto lastPage = stageManager_->GetLastPage();
947     auto mainNode = lastPage ? lastPage : rootNode_;
948     CHECK_NULL_RETURN(mainNode, false);
949     if (!eventManager_->DispatchTabIndexEventNG(event, rootNode_, mainNode)) {
950         return eventManager_->DispatchKeyEventNG(event, rootNode_);
951     }
952     return true;
953 }
954 
RequestDefaultFocus()955 bool PipelineContext::RequestDefaultFocus()
956 {
957     CHECK_NULL_RETURN(stageManager_, false);
958     auto lastPage = stageManager_->GetLastPage();
959     auto mainNode = lastPage ? lastPage : rootNode_;
960     CHECK_NULL_RETURN(mainNode, false);
961     auto mainFocusHub = mainNode->GetFocusHub();
962     CHECK_NULL_RETURN(mainFocusHub, false);
963     if (mainFocusHub->IsDefaultHasFocused()) {
964         LOGD("RequestDefaultFocus: %{public}s/%{public}d 's default focus node has be focused.",
965             mainNode->GetTag().c_str(), mainNode->GetId());
966         return false;
967     }
968     auto defaultFocusNode = mainFocusHub->GetChildFocusNodeByType();
969     if (!defaultFocusNode) {
970         LOGD("RequestDefaultFocus: %{public}s/%{public}d do not has default focus node.", mainNode->GetTag().c_str(),
971             mainNode->GetId());
972         return false;
973     }
974     if (!defaultFocusNode->IsFocusableWholePath()) {
975         LOGD("RequestDefaultFocus: %{public}s/%{public}d 's default focus node is not focusable.",
976             mainNode->GetTag().c_str(), mainNode->GetId());
977         return false;
978     }
979     mainFocusHub->SetIsDefaultHasFocused(true);
980     LOGD("Focus: request default focus node %{public}s", defaultFocusNode->GetFrameName().c_str());
981     return defaultFocusNode->RequestFocusImmediately();
982 }
983 
RequestFocus(const std::string & targetNodeId)984 bool PipelineContext::RequestFocus(const std::string& targetNodeId)
985 {
986     CHECK_NULL_RETURN(rootNode_, false);
987     auto focusHub = rootNode_->GetFocusHub();
988     CHECK_NULL_RETURN(focusHub, false);
989     auto currentFocusChecked = focusHub->RequestFocusImmediatelyById(targetNodeId);
990     if (!isSubPipeline_ || currentFocusChecked) {
991         LOGI("Request focus in current pipeline return is %{public}d", currentFocusChecked);
992         return currentFocusChecked;
993     }
994     LOGI("Request focus in parent pipeline");
995     auto parentPipelineBase = parentPipeline_.Upgrade();
996     CHECK_NULL_RETURN(parentPipelineBase, false);
997     auto parentPipelineContext = AceType::DynamicCast<NG::PipelineContext>(parentPipelineBase);
998     CHECK_NULL_RETURN(parentPipelineContext, false);
999     return parentPipelineContext->RequestFocus(targetNodeId);
1000 }
1001 
AddDirtyFocus(const RefPtr<FrameNode> & node)1002 void PipelineContext::AddDirtyFocus(const RefPtr<FrameNode>& node)
1003 {
1004     CHECK_RUN_ON(UI);
1005     CHECK_NULL_VOID(node);
1006     if (node->GetFocusType() == FocusType::NODE) {
1007         dirtyFocusNode_ = WeakClaim(RawPtr(node));
1008     } else {
1009         dirtyFocusScope_ = WeakClaim(RawPtr(node));
1010     }
1011     window_->RequestFrame();
1012 }
1013 
RootLostFocus(BlurReason reason) const1014 void PipelineContext::RootLostFocus(BlurReason reason) const
1015 {
1016     CHECK_NULL_VOID(rootNode_);
1017     auto focusHub = rootNode_->GetFocusHub();
1018     CHECK_NULL_VOID(focusHub);
1019     focusHub->LostFocus(reason);
1020     CHECK_NULL_VOID(overlayManager_);
1021     overlayManager_->HideAllMenus();
1022     overlayManager_->HideAllPopups();
1023 }
1024 
ConvertAxisToMouse(const AxisEvent & event)1025 MouseEvent ConvertAxisToMouse(const AxisEvent& event)
1026 {
1027     MouseEvent result;
1028     result.x = event.x;
1029     result.y = event.y;
1030     result.action = MouseAction::MOVE;
1031     result.button = MouseButton::NONE_BUTTON;
1032     result.time = event.time;
1033     result.deviceId = event.deviceId;
1034     result.sourceType = event.sourceType;
1035     return result;
1036 }
1037 
OnAxisEvent(const AxisEvent & event)1038 void PipelineContext::OnAxisEvent(const AxisEvent& event)
1039 {
1040     auto scaleEvent = event.CreateScaleEvent(viewScale_);
1041     LOGD("AxisEvent (x,y): (%{public}f,%{public}f), action: %{public}d, horizontalAxis: %{public}f, verticalAxis: "
1042          "%{public}f, pinchAxisScale: %{public}f",
1043         scaleEvent.x, scaleEvent.y, scaleEvent.action, scaleEvent.horizontalAxis, scaleEvent.verticalAxis,
1044         scaleEvent.pinchAxisScale);
1045 
1046     if (event.action == AxisAction::BEGIN) {
1047         TouchRestrict touchRestrict { TouchRestrict::NONE };
1048         touchRestrict.sourceType = event.sourceType;
1049         touchRestrict.hitTestType = SourceType::TOUCH;
1050         eventManager_->TouchTest(scaleEvent, rootNode_, touchRestrict);
1051     }
1052     eventManager_->DispatchTouchEvent(scaleEvent);
1053 
1054     if (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE) {
1055         eventManager_->AxisTest(scaleEvent, rootNode_);
1056         eventManager_->DispatchAxisEvent(scaleEvent);
1057     }
1058 
1059     auto mouseEvent = ConvertAxisToMouse(event);
1060     OnMouseEvent(mouseEvent);
1061 }
1062 
AddVisibleAreaChangeNode(const RefPtr<FrameNode> & node,double ratio,const VisibleRatioCallback & callback)1063 void PipelineContext::AddVisibleAreaChangeNode(
1064     const RefPtr<FrameNode>& node, double ratio, const VisibleRatioCallback& callback)
1065 {
1066     CHECK_NULL_VOID(node);
1067     VisibleCallbackInfo info;
1068     info.callback = callback;
1069     info.visibleRatio = ratio;
1070     info.isCurrentVisible = false;
1071     auto iter = visibleAreaChangeNodes_.find(node->GetId());
1072     if (iter != visibleAreaChangeNodes_.end()) {
1073         auto& callbackList = iter->second;
1074         callbackList.emplace_back(info);
1075     } else {
1076         std::list<VisibleCallbackInfo> callbackList;
1077         callbackList.emplace_back(info);
1078         visibleAreaChangeNodes_[node->GetId()] = callbackList;
1079     }
1080 }
1081 
RemoveVisibleAreaChangeNode(int32_t nodeId)1082 void PipelineContext::RemoveVisibleAreaChangeNode(int32_t nodeId)
1083 {
1084     visibleAreaChangeNodes_.erase(nodeId);
1085 }
1086 
HandleVisibleAreaChangeEvent()1087 void PipelineContext::HandleVisibleAreaChangeEvent()
1088 {
1089     if (visibleAreaChangeNodes_.empty()) {
1090         return;
1091     }
1092     for (auto& visibleChangeNode : visibleAreaChangeNodes_) {
1093         auto uiNode = ElementRegister::GetInstance()->GetUINodeById(visibleChangeNode.first);
1094         if (!uiNode) {
1095             continue;
1096         }
1097         auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
1098         if (!frameNode) {
1099             continue;
1100         }
1101         frameNode->TriggerVisibleAreaChangeCallback(visibleChangeNode.second);
1102     }
1103 }
1104 
AddOnAreaChangeNode(int32_t nodeId)1105 void PipelineContext::AddOnAreaChangeNode(int32_t nodeId)
1106 {
1107     onAreaChangeNodeIds_.emplace(nodeId);
1108 }
1109 
RemoveOnAreaChangeNode(int32_t nodeId)1110 void PipelineContext::RemoveOnAreaChangeNode(int32_t nodeId)
1111 {
1112     onAreaChangeNodeIds_.erase(nodeId);
1113 }
1114 
HandleOnAreaChangeEvent()1115 void PipelineContext::HandleOnAreaChangeEvent()
1116 {
1117     if (onAreaChangeNodeIds_.empty()) {
1118         return;
1119     }
1120     for (const auto& nodeId : onAreaChangeNodeIds_) {
1121         auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
1122         if (!uiNode) {
1123             continue;
1124         }
1125         auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
1126         if (!frameNode) {
1127             continue;
1128         }
1129         frameNode->TriggerOnAreaChangeCallback();
1130     }
1131 }
1132 
OnShow()1133 void PipelineContext::OnShow()
1134 {
1135     CHECK_RUN_ON(UI);
1136     onShow_ = true;
1137     window_->OnShow();
1138     window_->RequestFrame();
1139     FlushWindowStateChangedCallback(true);
1140 }
1141 
OnHide()1142 void PipelineContext::OnHide()
1143 {
1144     CHECK_RUN_ON(UI);
1145     onShow_ = false;
1146     window_->RequestFrame();
1147     window_->OnHide();
1148     OnVirtualKeyboardAreaChange(Rect());
1149     FlushWindowStateChangedCallback(false);
1150 }
1151 
WindowFocus(bool isFocus)1152 void PipelineContext::WindowFocus(bool isFocus)
1153 {
1154     CHECK_RUN_ON(UI);
1155     onFocus_ = isFocus;
1156     if (!isFocus) {
1157         LOGD("WindowFocus: isFocus_ is %{public}d. Lost all focus.", onFocus_);
1158         RootLostFocus(BlurReason::WINDOW_BLUR);
1159         NotifyPopupDismiss();
1160         OnVirtualKeyboardAreaChange(Rect());
1161     }
1162     if (onFocus_ && onShow_) {
1163         LOGD("WindowFocus: onFocus_ and onShow_ are both true. Do FlushFocus().");
1164         FlushFocus();
1165     } else {
1166         LOGD("WindowFocus: onFocus_ is %{public}d, onShow_ is %{public}d.", onFocus_, onShow_);
1167     }
1168     FlushWindowFocusChangedCallback(isFocus);
1169 }
1170 
ShowContainerTitle(bool isShow)1171 void PipelineContext::ShowContainerTitle(bool isShow)
1172 {
1173     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
1174         LOGW("ShowContainerTitle failed, Window modal is not container.");
1175         return;
1176     }
1177     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
1178     CHECK_NULL_VOID(containerNode);
1179     containerNode->GetPattern<ContainerModalPattern>()->ShowTitle(isShow);
1180 }
1181 
SetContainerWindow(bool isShow)1182 void PipelineContext::SetContainerWindow(bool isShow)
1183 {
1184 #ifdef ENABLE_ROSEN_BACKEND
1185     if (!IsJsCard()) {
1186         auto rsWindow = static_cast<RosenWindow*>(GetWindow());
1187         if (rsWindow) {
1188             auto rsUIDirector = rsWindow->GetRsUIDirector();
1189             if (rsUIDirector) {
1190                 rsUIDirector->SetContainerWindow(isShow, density_); // set container window show state to render service
1191             }
1192         }
1193     }
1194 #endif
1195 }
1196 
SetAppBgColor(const Color & color)1197 void PipelineContext::SetAppBgColor(const Color& color)
1198 {
1199     appBgColor_ = color;
1200 #ifdef ENABLE_ROSEN_BACKEND
1201     if (!IsJsCard()) {
1202         auto rsWindow = static_cast<RosenWindow*>(GetWindow());
1203         if (rsWindow) {
1204             auto rsUIDirector = rsWindow->GetRsUIDirector();
1205             if (rsUIDirector) {
1206                 rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1207             }
1208         }
1209     }
1210 #endif
1211     CHECK_NULL_VOID(rootNode_);
1212     auto rootPattern = rootNode_->GetPattern<RootPattern>();
1213     CHECK_NULL_VOID(rootPattern);
1214     rootPattern->SetAppBgColor(appBgColor_, windowModal_ == WindowModal::CONTAINER_MODAL);
1215 }
1216 
SetAppTitle(const std::string & title)1217 void PipelineContext::SetAppTitle(const std::string& title)
1218 {
1219     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
1220         LOGW("SetAppTitle failed, Window modal is not container.");
1221         return;
1222     }
1223     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
1224     CHECK_NULL_VOID(containerNode);
1225     containerNode->GetPattern<ContainerModalPattern>()->SetAppTitle(title);
1226 }
1227 
SetAppIcon(const RefPtr<PixelMap> & icon)1228 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
1229 {
1230     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
1231         LOGW("SetAppIcon failed, Window modal is not container.");
1232         return;
1233     }
1234     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
1235     CHECK_NULL_VOID(containerNode);
1236     containerNode->GetPattern<ContainerModalPattern>()->SetAppIcon(icon);
1237 }
1238 
FlushReload()1239 void PipelineContext::FlushReload()
1240 {
1241     LOGI("PipelineContext::FlushReload.");
1242     AnimationOption option;
1243     const int32_t duration = 400;
1244     option.SetDuration(duration);
1245     option.SetCurve(Curves::FRICTION);
1246     AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
1247         auto pipeline = weak.Upgrade();
1248         CHECK_NULL_VOID(pipeline);
1249         pipeline->stageManager_->ReloadStage();
1250         pipeline->FlushUITasks();
1251     });
1252 }
1253 
Destroy()1254 void PipelineContext::Destroy()
1255 {
1256     CHECK_RUN_ON(UI);
1257     LOGI("PipelineContext::Destroy begin.");
1258     taskScheduler_.CleanUp();
1259     scheduleTasks_.clear();
1260     dirtyNodes_.clear();
1261     rootNode_.Reset();
1262     stageManager_.Reset();
1263     overlayManager_.Reset();
1264     sharedTransitionManager_.Reset();
1265     dragDropManager_.Reset();
1266     selectOverlayManager_.Reset();
1267     fullScreenManager_.Reset();
1268     touchEvents_.clear();
1269     buildFinishCallbacks_.clear();
1270     onWindowStateChangedCallbacks_.clear();
1271     onWindowFocusChangedCallbacks_.clear();
1272     nodesToNotifyMemoryLevel_.clear();
1273     dirtyFocusNode_.Reset();
1274     dirtyFocusScope_.Reset();
1275     PipelineBase::Destroy();
1276     LOGI("PipelineContext::Destroy end.");
1277 }
1278 
AddBuildFinishCallBack(std::function<void ()> && callback)1279 void PipelineContext::AddBuildFinishCallBack(std::function<void()>&& callback)
1280 {
1281     buildFinishCallbacks_.emplace_back(std::move(callback));
1282 }
1283 
AddWindowStateChangedCallback(int32_t nodeId)1284 void PipelineContext::AddWindowStateChangedCallback(int32_t nodeId)
1285 {
1286     onWindowStateChangedCallbacks_.emplace_back(nodeId);
1287 }
1288 
RemoveWindowStateChangedCallback(int32_t nodeId)1289 void PipelineContext::RemoveWindowStateChangedCallback(int32_t nodeId)
1290 {
1291     onWindowStateChangedCallbacks_.remove(nodeId);
1292 }
1293 
FlushWindowStateChangedCallback(bool isShow)1294 void PipelineContext::FlushWindowStateChangedCallback(bool isShow)
1295 {
1296     auto iter = onWindowStateChangedCallbacks_.begin();
1297     while (iter != onWindowStateChangedCallbacks_.end()) {
1298         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
1299         if (!node) {
1300             iter = onWindowStateChangedCallbacks_.erase(iter);
1301         } else {
1302             if (isShow) {
1303                 node->OnWindowShow();
1304             } else {
1305                 node->OnWindowHide();
1306             }
1307             ++iter;
1308         }
1309     }
1310 }
1311 
AddWindowFocusChangedCallback(int32_t nodeId)1312 void PipelineContext::AddWindowFocusChangedCallback(int32_t nodeId)
1313 {
1314     onWindowFocusChangedCallbacks_.emplace_back(nodeId);
1315 }
1316 
RemoveWindowFocusChangedCallback(int32_t nodeId)1317 void PipelineContext::RemoveWindowFocusChangedCallback(int32_t nodeId)
1318 {
1319     onWindowFocusChangedCallbacks_.remove(nodeId);
1320 }
1321 
FlushWindowFocusChangedCallback(bool isFocus)1322 void PipelineContext::FlushWindowFocusChangedCallback(bool isFocus)
1323 {
1324     auto iter = onWindowFocusChangedCallbacks_.begin();
1325     while (iter != onWindowFocusChangedCallbacks_.end()) {
1326         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
1327         if (!node) {
1328             iter = onWindowFocusChangedCallbacks_.erase(iter);
1329         } else {
1330             if (isFocus) {
1331                 node->OnWindowFocused();
1332             } else {
1333                 node->OnWindowUnfocused();
1334             }
1335             ++iter;
1336         }
1337     }
1338 }
1339 
OnDragEvent(int32_t x,int32_t y,DragEventAction action)1340 void PipelineContext::OnDragEvent(int32_t x, int32_t y, DragEventAction action)
1341 {
1342     auto manager = GetDragDropManager();
1343     CHECK_NULL_VOID(manager);
1344     if (manager->IsDragged()) {
1345         LOGI("current context is the source of drag");
1346         return;
1347     }
1348 
1349     std::string extraInfo;
1350     manager->GetExtraInfoFromClipboard(extraInfo);
1351 
1352     if (action == DragEventAction::DRAG_EVENT_END) {
1353         manager->OnDragEnd(static_cast<float>(x), static_cast<float>(y), extraInfo);
1354         manager->RestoreClipboardData();
1355         return;
1356     }
1357 
1358     manager->OnDragMove(static_cast<float>(x), static_cast<float>(y), extraInfo);
1359 }
1360 
AddNodesToNotifyMemoryLevel(int32_t nodeId)1361 void PipelineContext::AddNodesToNotifyMemoryLevel(int32_t nodeId)
1362 {
1363     nodesToNotifyMemoryLevel_.emplace_back(nodeId);
1364 }
1365 
RemoveNodesToNotifyMemoryLevel(int32_t nodeId)1366 void PipelineContext::RemoveNodesToNotifyMemoryLevel(int32_t nodeId)
1367 {
1368     nodesToNotifyMemoryLevel_.remove(nodeId);
1369 }
1370 
NotifyMemoryLevel(int32_t level)1371 void PipelineContext::NotifyMemoryLevel(int32_t level)
1372 {
1373     LOGI("PipelineContext: NotifyMemoryLevel called");
1374     auto iter = nodesToNotifyMemoryLevel_.begin();
1375     while (iter != nodesToNotifyMemoryLevel_.end()) {
1376         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
1377         if (!node) {
1378             iter = nodesToNotifyMemoryLevel_.erase(iter);
1379         } else {
1380             node->OnNotifyMemoryLevel(level);
1381         }
1382         ++iter;
1383     }
1384 }
AddPredictTask(PredictTask && task)1385 void PipelineContext::AddPredictTask(PredictTask&& task)
1386 {
1387     taskScheduler_.AddPredictTask(std::move(task));
1388     window_->RequestFrame();
1389 }
1390 
OnIdle(int64_t deadline)1391 void PipelineContext::OnIdle(int64_t deadline)
1392 {
1393     if (deadline == 0) {
1394         return;
1395     }
1396     CHECK_RUN_ON(UI);
1397     ACE_SCOPED_TRACE("OnIdle, targettime:%" PRId64 "", deadline);
1398     taskScheduler_.FlushPredictTask(deadline - TIME_THRESHOLD);
1399 }
1400 
Finish(bool) const1401 void PipelineContext::Finish(bool /*autoFinish*/) const
1402 {
1403     CHECK_RUN_ON(UI);
1404     if (finishEventHandler_) {
1405         LOGI("call finishEventHandler");
1406         finishEventHandler_();
1407     } else {
1408         LOGE("fail to finish current context due to handler is nullptr");
1409     }
1410 }
1411 
AddAfterLayoutTask(std::function<void ()> && task)1412 void PipelineContext::AddAfterLayoutTask(std::function<void()>&& task)
1413 {
1414     taskScheduler_.AddAfterLayoutTask(std::move(task));
1415 }
1416 
1417 } // namespace OHOS::Ace::NG
1418