• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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/subwindow/subwindow_manager.h"
19 #include "core/components_ng/event/event_constants.h"
20 #include "core/event/key_event.h"
21 
22 #ifdef ENABLE_ROSEN_BACKEND
23 #include "render_service_client/core/transaction/rs_transaction.h"
24 #include "render_service_client/core/ui/rs_ui_director.h"
25 #include "render_service_client/core/ui/rs_ui_context.h"
26 #include "render_service_client/core/ui/rs_surface_node.h"
27 #endif
28 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
29 
30 #include "frameworks/core/components_ng/base/inspector.h"
31 #include "base/geometry/ng/offset_t.h"
32 #include "base/geometry/ng/rect_t.h"
33 #include "base/log/ace_performance_monitor.h"
34 #include "base/log/ace_trace.h"
35 #include "base/log/ace_tracker.h"
36 #include "base/log/dump_log.h"
37 #include "base/log/dump_recorder.h"
38 #include "base/log/event_report.h"
39 #include "base/memory/ace_type.h"
40 #include "base/mousestyle/mouse_style.h"
41 #include "base/perfmonitor/perf_monitor.h"
42 #include "base/ressched/ressched_report.h"
43 #include "base/thread/background_task_executor.h"
44 #include "base/utils/cpu_boost.h"
45 #include "core/common/ace_engine.h"
46 #include "core/common/font_manager.h"
47 #include "core/common/font_change_observer.h"
48 #include "core/common/ime/input_method_manager.h"
49 #include "core/common/layout_inspector.h"
50 #include "core/common/resource/resource_manager.h"
51 #include "core/common/resource/resource_parse_utils.h"
52 #include "core/common/stylus/stylus_detector_default.h"
53 #include "core/common/stylus/stylus_detector_mgr.h"
54 #include "core/common/text_field_manager.h"
55 #include "core/components_ng/base/node_render_status_monitor.h"
56 #include "core/components_ng/base/simplified_inspector.h"
57 #include "core/components_ng/base/ui_node_gc.h"
58 #include "core/components_ng/base/view_advanced_register.h"
59 #include "core/components_ng/pattern/container_modal/container_modal_view_factory.h"
60 #include "core/components_ng/pattern/container_modal/enhance/container_modal_pattern_enhance.h"
61 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
62 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
63 #include "core/components_ng/pattern/root/root_pattern.h"
64 #include "core/components_ng/pattern/text_field/text_field_manager.h"
65 #ifdef WINDOW_SCENE_SUPPORTED
66 #include "core/components_ng/pattern/window_scene/scene/window_scene_layout_manager.h"
67 #endif
68 #include "core/image/image_file_cache.h"
69 #include "core/pipeline/pipeline_context.h"
70 #ifdef COMPONENT_TEST_ENABLED
71 #include "component_test/pipeline_status.h"
72 #endif // COMPONENT_TEST_ENABLED
73 #include "interfaces/inner_api/ace_kit/src/view/ui_context_impl.h"
74 #include "interfaces/inner_api/ace_kit/include/ui/view/ai_caller_helper.h"
75 
76 namespace {
77 constexpr uint64_t ONE_MS_IN_NS = 1 * 1000 * 1000;
78 constexpr int32_t TIME_THRESHOLD = 2 * 1000000; // 3 millisecond
79 constexpr int32_t PLATFORM_VERSION_TEN = 10;
80 constexpr int32_t MILLISECONDS_TO_NANOSECONDS = 1000000; // Milliseconds to nanoseconds
81 constexpr int32_t VSYNC_PERIOD_COUNT = 5;
82 constexpr int32_t MIN_IDLE_TIME = 1000;
83 constexpr uint8_t SINGLECOLOR_UPDATE_ALPHA = 75;
84 constexpr int8_t RENDERING_SINGLE_COLOR = 1;
85 constexpr int32_t DELAY_TIME = 500;
86 constexpr int32_t PARAM_NUM = 2;
87 constexpr int64_t MAX_MISS_COUNT = 3;
88 constexpr int32_t MAX_FLUSH_COUNT = 2;
89 constexpr int32_t MAX_RECORD_SECOND = 15;
90 constexpr int32_t DEFAULT_RECORD_SECOND = 5;
91 constexpr int32_t SECOND_TO_MILLISEC = 1000;
92 constexpr int32_t USED_ID_FIND_FLAG = 3;
93 constexpr int32_t USED_JSON_PARAM = 4;
94 constexpr int32_t MAX_FRAME_COUNT_WITHOUT_JS_UNREGISTRATION = 100;
95 constexpr int32_t RATIO_OF_VSYNC_PERIOD = 2;
96 constexpr int32_t MAX_DVSYNC_TIME_USE_COUNT = 5;
97 #ifndef IS_RELEASE_VERSION
98 constexpr int32_t SINGLE_FRAME_TIME_MICROSEC = 16600;
99 #endif
100 constexpr char PID_FLAG[] = "pidflag";
101 } // namespace
102 
103 namespace OHOS::Ace::NG {
104 namespace {
105 constexpr Dimension CARET_AVOID_OFFSET = 24.0_vp;
106 
ShouldAddToHistory(std::vector<TouchEvent> & history,const TouchEvent & event,const TouchEvent & movePoint)107 void ShouldAddToHistory (
108     std::vector<TouchEvent>& history, const TouchEvent& event, const TouchEvent& movePoint)
109 {
110 #ifdef ARKUI_WEARABLE
111     if (event.x != movePoint.x || event.y != movePoint.y) {
112         history.emplace_back(movePoint);
113     }
114 #else
115     history.emplace_back(movePoint);
116 #endif
117 }
118 
GetDepthFromParams(const std::vector<std::string> & params)119 int32_t GetDepthFromParams(const std::vector<std::string>& params)
120 {
121     int32_t depth = 0;
122     std::string prefix = "dcDepth_";
123     for (const auto& param : params) {
124         if (param.find(prefix) == 0) {
125             std::string suffix = param.substr(prefix.length());
126             int32_t suffixInt = StringUtils::StringToInt(suffix);
127             if (suffixInt != 0) {
128                 depth = suffixInt;
129                 break;
130             }
131         }
132     }
133 
134     return depth;
135 }
136 
137 class TestAICaller : public AICallerHelper {
138 public:
139     TestAICaller() = default;
140     ~TestAICaller() override = default;
onAIFunctionCaller(const std::string & funcName,const std::string & params)141     bool onAIFunctionCaller(const std::string& funcName, const std::string& params) override
142     {
143         if (funcName.compare("Success") == 0) {
144             return true;
145         }
146         return false;
147     }
148 };
149 } // namespace
150 
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,RefPtr<PlatformResRegister> platformResRegister,const RefPtr<Frontend> & frontend,int32_t instanceId)151 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
152     RefPtr<AssetManager> assetManager, RefPtr<PlatformResRegister> platformResRegister,
153     const RefPtr<Frontend>& frontend, int32_t instanceId)
154     : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId, platformResRegister)
155 {
156     window_->OnHide();
157     if (navigationMgr_) {
158         navigationMgr_->SetPipelineContext(WeakClaim(this));
159     }
160     if (forceSplitMgr_) {
161         forceSplitMgr_->SetPipelineContext(WeakClaim(this));
162     }
163     if (avoidInfoMgr_) {
164         avoidInfoMgr_->SetPipelineContext(WeakClaim(this));
165         avoidInfoMgr_->SetInstanceId(instanceId);
166     }
167 #ifdef WINDOW_SCENE_SUPPORTED
168     if (uiExtensionManager_) {
169         uiExtensionManager_->SetPipelineContext(WeakClaim(this));
170         uiExtensionManager_->SetInstanceId(instanceId);
171     }
172 #endif
173 }
174 
PipelineContext(std::shared_ptr<Window> window,RefPtr<TaskExecutor> taskExecutor,RefPtr<AssetManager> assetManager,const RefPtr<Frontend> & frontend,int32_t instanceId)175 PipelineContext::PipelineContext(std::shared_ptr<Window> window, RefPtr<TaskExecutor> taskExecutor,
176     RefPtr<AssetManager> assetManager, const RefPtr<Frontend>& frontend, int32_t instanceId)
177     : PipelineBase(window, std::move(taskExecutor), std::move(assetManager), frontend, instanceId)
178 {
179     window_->OnHide();
180     if (navigationMgr_) {
181         navigationMgr_->SetPipelineContext(WeakClaim(this));
182     }
183     if (forceSplitMgr_) {
184         forceSplitMgr_->SetPipelineContext(WeakClaim(this));
185     }
186     if (avoidInfoMgr_) {
187         avoidInfoMgr_->SetPipelineContext(WeakClaim(this));
188         avoidInfoMgr_->SetInstanceId(instanceId);
189     }
190 #ifdef WINDOW_SCENE_SUPPORTED
191     if (uiExtensionManager_) {
192         uiExtensionManager_->SetPipelineContext(WeakClaim(this));
193         uiExtensionManager_->SetInstanceId(instanceId);
194     }
195 #endif
196 }
197 
PipelineContext()198 PipelineContext::PipelineContext()
199 {
200     if (navigationMgr_) {
201         navigationMgr_->SetPipelineContext(WeakClaim(this));
202     }
203     if (forceSplitMgr_) {
204         forceSplitMgr_->SetPipelineContext(WeakClaim(this));
205     }
206     if (avoidInfoMgr_) {
207         avoidInfoMgr_->SetPipelineContext(WeakClaim(this));
208     }
209 #ifdef WINDOW_SCENE_SUPPORTED
210     if (uiExtensionManager_) {
211         uiExtensionManager_->SetPipelineContext(WeakClaim(this));
212     }
213 #endif
214 }
215 
GetCurrentPageNameCallback()216 std::string PipelineContext::GetCurrentPageNameCallback()
217 {
218     CHECK_NULL_RETURN(stageManager_, "");
219     RefPtr<FrameNode> pageNode = stageManager_->GetLastPage();
220     CHECK_NULL_RETURN(pageNode, "");
221     auto pagePattern = pageNode->GetPattern<PagePattern>();
222     CHECK_NULL_RETURN(pagePattern, "");
223     CHECK_NULL_RETURN(pagePattern->GetPageInfo(), "");
224     int32_t pageId = pagePattern->GetPageInfo()->GetPageId();
225     RefPtr<NavigationGroupNode> navigationNode = nullptr;
226     CHECK_RUN_ON(UI);
227     auto it = pageToNavigationNodes_.find(pageId);
228     if (it == pageToNavigationNodes_.end() || it->second.empty()) {
229         return "";
230     }
231 
232     for (auto iter = it->second.begin(); iter != it->second.end() && !navigationNode; ++iter) {
233         navigationNode = AceType::DynamicCast<NavigationGroupNode>((*iter).Upgrade());
234     }
235 
236     CHECK_NULL_RETURN(navigationNode, "");
237     CHECK_NULL_RETURN(navigationNode->GetPattern(), "");
238     auto pattern = AceType::DynamicCast<NavigationPattern>(navigationNode->GetPattern());
239     CHECK_NULL_RETURN(pattern, "");
240     const auto& navDestinationNodes = pattern->GetAllNavDestinationNodes();
241     int32_t size = static_cast<int32_t>(navDestinationNodes.size());
242     if (size == 0) {
243         return "";
244     }
245     auto pageNameObj = navDestinationNodes.back();
246     std::string pageName = std::get<0>(pageNameObj);
247     return pageName;
248 }
249 
GetCurrentContext()250 RefPtr<PipelineContext> PipelineContext::GetCurrentContext()
251 {
252     auto currentContainer = Container::Current();
253     CHECK_NULL_RETURN(currentContainer, nullptr);
254     return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
255 }
256 
GetCurrentContextSafely()257 RefPtr<PipelineContext> PipelineContext::GetCurrentContextSafely()
258 {
259     auto currentContainer = Container::CurrentSafely();
260     CHECK_NULL_RETURN(currentContainer, nullptr);
261     return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
262 }
263 
GetCurrentContextSafelyWithCheck()264 RefPtr<PipelineContext> PipelineContext::GetCurrentContextSafelyWithCheck()
265 {
266     auto currentContainer = Container::CurrentSafelyWithCheck();
267     CHECK_NULL_RETURN(currentContainer, nullptr);
268     return DynamicCast<PipelineContext>(currentContainer->GetPipelineContext());
269 }
270 
GetCurrentContextPtrSafely()271 PipelineContext* PipelineContext::GetCurrentContextPtrSafely()
272 {
273     auto currentContainer = Container::CurrentSafely();
274     CHECK_NULL_RETURN(currentContainer, nullptr);
275     const auto& base = currentContainer->GetPipelineContext();
276     CHECK_NULL_RETURN(base, nullptr);
277     return DynamicCast<PipelineContext>(RawPtr(base));
278 }
279 
GetCurrentContextPtrSafelyWithCheck()280 PipelineContext* PipelineContext::GetCurrentContextPtrSafelyWithCheck()
281 {
282     auto currentContainer = Container::CurrentSafelyWithCheck();
283     CHECK_NULL_RETURN(currentContainer, nullptr);
284     const auto& base = currentContainer->GetPipelineContext();
285     CHECK_NULL_RETURN(base, nullptr);
286     return DynamicCast<PipelineContext>(RawPtr(base));
287 }
288 
GetMainPipelineContext()289 RefPtr<PipelineContext> PipelineContext::GetMainPipelineContext()
290 {
291     auto pipeline = PipelineBase::GetMainPipelineContext();
292     CHECK_NULL_RETURN(pipeline, nullptr);
293     return DynamicCast<PipelineContext>(pipeline);
294 }
295 
NeedSoftKeyboard()296 bool PipelineContext::NeedSoftKeyboard()
297 {
298     auto needSoftKeyboard = InputMethodManager::GetInstance()->NeedSoftKeyboard();
299     TAG_LOGI(AceLogTag::ACE_KEYBOARD, "window switch need keyboard %d", needSoftKeyboard);
300     return needSoftKeyboard;
301 }
302 
GetContextByContainerId(int32_t containerId)303 RefPtr<PipelineContext> PipelineContext::GetContextByContainerId(int32_t containerId)
304 {
305     auto preContainer = Container::GetContainer(containerId);
306     CHECK_NULL_RETURN(preContainer, nullptr);
307     return DynamicCast<PipelineContext>(preContainer->GetPipelineContext());
308 }
309 
GetCurrentRootWidth()310 float PipelineContext::GetCurrentRootWidth()
311 {
312     auto context = GetCurrentContext();
313     CHECK_NULL_RETURN(context, 0.0f);
314     return static_cast<float>(context->rootWidth_);
315 }
316 
GetCurrentRootHeight()317 float PipelineContext::GetCurrentRootHeight()
318 {
319     auto context = GetCurrentContext();
320     CHECK_NULL_RETURN(context, 0.0f);
321     return static_cast<float>(context->rootHeight_);
322 }
323 
AddDirtyPropertyNode(const RefPtr<FrameNode> & dirtyNode)324 void PipelineContext::AddDirtyPropertyNode(const RefPtr<FrameNode>& dirtyNode)
325 {
326     if (!CheckThreadSafe()) {
327         LOGW("AddDirtyPropertyNode doesn't run on UI thread!");
328     }
329     dirtyPropertyNodes_.emplace(dirtyNode);
330     hasIdleTasks_ = true;
331     RequestFrame();
332 }
333 
AddDirtyCustomNode(const RefPtr<UINode> & dirtyNode)334 void PipelineContext::AddDirtyCustomNode(const RefPtr<UINode>& dirtyNode)
335 {
336     CHECK_RUN_ON(UI);
337     if (!dirtyNode) {
338         LOGW("dirtyNode invalid");
339         return;
340     }
341     auto customNode = DynamicCast<CustomNode>(dirtyNode);
342     if (customNode && !dirtyNode->GetInspectorIdValue("").empty()) {
343         ACE_BUILD_TRACE_BEGIN("AddDirtyCustomNode[%s][self:%d][parent:%d][key:%s]",
344             customNode->GetJSViewName().c_str(),
345             dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0,
346             dirtyNode->GetInspectorIdValue("").c_str());
347         ACE_BUILD_TRACE_END()
348     } else if (customNode) {
349         ACE_BUILD_TRACE_BEGIN("AddDirtyCustomNode[%s][self:%d][parent:%d]",
350             customNode->GetJSViewName().c_str(),
351             dirtyNode->GetId(), dirtyNode->GetParent() ? dirtyNode->GetParent()->GetId() : 0);
352         ACE_BUILD_TRACE_END()
353     }
354     dirtyNodes_.emplace(dirtyNode);
355     hasIdleTasks_ = true;
356     RequestFrame();
357 }
358 
AddDirtyLayoutNode(const RefPtr<FrameNode> & dirty)359 void PipelineContext::AddDirtyLayoutNode(const RefPtr<FrameNode>& dirty)
360 {
361     CHECK_RUN_ON(UI);
362     CHECK_NULL_VOID(dirty);
363     if (IsDestroyed()) {
364         LOGW("Cannot add dirty layout node as the pipeline context is destroyed.");
365         return;
366     }
367     if (!dirty->GetInspectorIdValue("").empty()) {
368         ACE_BUILD_TRACE_BEGIN("AddDirtyLayoutNode[%s][self:%d][parent:%d][key:%s]",
369             dirty->GetTag().c_str(),
370             dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0,
371             dirty->GetInspectorIdValue("").c_str());
372         ACE_BUILD_TRACE_END()
373     } else {
374         ACE_BUILD_TRACE_BEGIN("AddDirtyLayoutNode[%s][self:%d][parent:%d]", dirty->GetTag().c_str(),
375             dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0);
376         ACE_BUILD_TRACE_END()
377     }
378     if (!dirty->IsOnMainTree() && predictNode_) {
379         predictNode_->AddPredictLayoutNode(dirty);
380         return;
381     }
382     taskScheduler_->AddDirtyLayoutNode(dirty);
383     ForceLayoutForImplicitAnimation();
384 #ifdef UICAST_COMPONENT_SUPPORTED
385     do {
386         auto container = Container::Current();
387         CHECK_NULL_BREAK(container);
388         auto distributedUI = container->GetDistributedUI();
389         CHECK_NULL_BREAK(distributedUI);
390         distributedUI->AddDirtyLayoutNode(dirty->GetId());
391     } while (false);
392 #endif
393     hasIdleTasks_ = true;
394     if (dirty->GetTag() == V2::ROOT_ETS_TAG && isFirstRootLayout_) {
395         isFirstRootLayout_ = false;
396         LOGI("Root node request first frame.");
397     }
398     RequestFrame();
399 }
400 
AddIgnoreLayoutSafeAreaBundle(IgnoreLayoutSafeAreaBundle && bundle)401 void PipelineContext::AddIgnoreLayoutSafeAreaBundle(IgnoreLayoutSafeAreaBundle&& bundle)
402 {
403     CHECK_RUN_ON(UI);
404     if (IsDestroyed()) {
405         LOGW("Cannot add ignoreSafeArea bundle as the pipeline context is destroyed.");
406         return;
407     }
408     if (SystemProperties::GetMeasureDebugTraceEnabled()) {
409         ACE_MEASURE_SCOPED_TRACE("PostponeBundleByIgnore postponedChildCount = %zu", bundle.first.size());
410     }
411     taskScheduler_->AddIgnoreLayoutSafeAreaBundle(std::move(bundle));
412 }
413 
AddLayoutNode(const RefPtr<FrameNode> & layoutNode)414 void PipelineContext::AddLayoutNode(const RefPtr<FrameNode>& layoutNode)
415 {
416     taskScheduler_->AddLayoutNode(layoutNode);
417 }
418 
AddDirtyRenderNode(const RefPtr<FrameNode> & dirty)419 void PipelineContext::AddDirtyRenderNode(const RefPtr<FrameNode>& dirty)
420 {
421     CHECK_RUN_ON(UI);
422     CHECK_NULL_VOID(dirty);
423     if (IsDestroyed()) {
424         LOGW("Cannot add dirty render node as the pipeline context is destroyed.");
425         return;
426     }
427     if (!dirty->GetInspectorIdValue("").empty()) {
428         ACE_BUILD_TRACE_BEGIN("AddDirtyRenderNode[%s][self:%d][parent:%d][key:%s]", dirty->GetTag().c_str(),
429             dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0,
430             dirty->GetInspectorIdValue("").c_str());
431         ACE_BUILD_TRACE_END()
432     } else {
433         ACE_BUILD_TRACE_BEGIN("AddDirtyRenderNode[%s][self:%d][parent:%d]", dirty->GetTag().c_str(),
434             dirty->GetId(), dirty->GetParent() ? dirty->GetParent()->GetId() : 0);
435         ACE_BUILD_TRACE_END()
436     }
437     taskScheduler_->AddDirtyRenderNode(dirty);
438     ForceRenderForImplicitAnimation();
439 #ifdef UICAST_COMPONENT_SUPPORTED
440     do {
441         auto container = Container::Current();
442         CHECK_NULL_BREAK(container);
443         auto distributedUI = container->GetDistributedUI();
444         CHECK_NULL_BREAK(distributedUI);
445         distributedUI->AddDirtyRenderNode(dirty->GetId());
446     } while (false);
447 #endif
448     hasIdleTasks_ = true;
449     RequestFrame();
450 }
451 
AddDirtyFreezeNode(FrameNode * node)452 void PipelineContext::AddDirtyFreezeNode(FrameNode* node)
453 {
454     dirtyFreezeNode_.emplace_back(WeakClaim(node));
455     hasIdleTasks_ = true;
456     RequestFrame();
457 }
458 
FlushFreezeNode()459 void PipelineContext::FlushFreezeNode()
460 {
461     std::set<RefPtr<FrameNode>, NodeCompare<RefPtr<FrameNode>>> dirtyFreezeNodeSet;
462     auto dirtyFreezeNodes = std::move(dirtyFreezeNode_);
463     dirtyFreezeNode_.clear();
464     for (auto&& weakNode : dirtyFreezeNodes) {
465         auto node = weakNode.Upgrade();
466         if (node) {
467             dirtyFreezeNodeSet.emplace(node);
468         }
469     }
470     //Process parentNode before childNode
471     for (auto&& node : dirtyFreezeNodeSet) {
472         node->ProcessFreezeNode();
473     }
474 }
475 
AddPendingDeleteCustomNode(const RefPtr<CustomNode> & node)476 void PipelineContext::AddPendingDeleteCustomNode(const RefPtr<CustomNode>& node)
477 {
478     pendingDeleteCustomNode_.push(node);
479     RequestFrame();
480 }
481 
FlushPendingDeleteCustomNode()482 void PipelineContext::FlushPendingDeleteCustomNode()
483 {
484     auto pendingStack = std::move(pendingDeleteCustomNode_);
485     while (!pendingStack.empty()) {
486         auto node = pendingStack.top();
487         pendingStack.pop();
488         if (AceType::InstanceOf<NG::CustomNode>(node)) {
489             auto customNode = AceType::DynamicCast<NG::CustomNode>(node);
490             if (!customNode->CheckFireOnAppear()) {
491                 customNode->FireOnAppear();
492                 customNode->FireDidBuild();
493             }
494             customNode->FireOnDisappear();
495             customNode->Reset();
496         }
497     }
498 }
499 
FlushDirtyPropertyNodes()500 void PipelineContext::FlushDirtyPropertyNodes()
501 {
502     // node api property diff before ets update.
503     if (!CheckThreadSafe()) {
504         LOGW("FlushDirtyNodeUpdate doesn't run on UI thread!");
505     }
506     decltype(dirtyPropertyNodes_) dirtyPropertyNodes(std::move(dirtyPropertyNodes_));
507     dirtyPropertyNodes_.clear();
508     for (const auto& node : dirtyPropertyNodes) {
509         node->ProcessPropertyDiff();
510     }
511 }
512 
FlushDirtyNodeUpdate()513 void PipelineContext::FlushDirtyNodeUpdate()
514 {
515 #ifndef IS_RELEASE_VERSION
516     int64_t startTime = GetCurrentTimestampMicroSecond();
517 #endif
518     CHECK_RUN_ON(UI);
519     ACE_FUNCTION_TRACE();
520     if (FrameReport::GetInstance().GetEnable()) {
521         FrameReport::GetInstance().BeginFlushBuild();
522     }
523 
524     // freeze node unlock before build begin.
525     FlushFreezeNode();
526 
527     FlushDirtyPropertyNodes();
528 
529     FlushPendingDeleteCustomNode();
530 
531     if (!ViewStackProcessor::GetInstance()->IsEmpty() && !dirtyNodes_.empty()) {
532         ACE_SCOPED_TRACE("Error update, node stack non-empty");
533         LOGW("stack is not empty when call FlushDirtyNodeUpdate, node may be mounted to incorrect pos!");
534     }
535     FlushDirtyNodeCpuBoostOperate(true);
536     // SomeTimes, customNode->Update may add some dirty custom nodes to dirtyNodes_,
537     // use maxFlushTimes to avoid dead cycle.
538     int maxFlushTimes = 3;
539     while (!dirtyNodes_.empty() && maxFlushTimes > 0) {
540         auto id = GetInstanceId();
541         ArkUIPerfMonitor::GetPerfMonitor(id)->RecordStateMgmtNode(dirtyNodes_.size());
542         decltype(dirtyNodes_) dirtyNodes(std::move(dirtyNodes_));
543         for (const auto& node : dirtyNodes) {
544             if (AceType::InstanceOf<NG::CustomNodeBase>(node)) {
545                 auto customNode = AceType::DynamicCast<NG::CustomNodeBase>(node);
546                 ACE_SCOPED_TRACE("CustomNodeUpdate name:%s,id:%d", customNode->GetJSViewName().c_str(), node->GetId());
547                 customNode->Update();
548             }
549         }
550         --maxFlushTimes;
551     }
552     FlushDirtyNodeCpuBoostOperate(false);
553 
554     FlushTSUpdates();
555 
556     if (FrameReport::GetInstance().GetEnable()) {
557         FrameReport::GetInstance().EndFlushBuild();
558     }
559 #ifndef IS_RELEASE_VERSION
560     int64_t duration = GetCurrentTimestampMicroSecond() - startTime;
561     if (duration > SINGLE_FRAME_TIME_MICROSEC) {
562         PerfMonitor::GetPerfMonitor()->SetSubHealthInfo("SUBHEALTH", "FlushDirtyNodeUpdate", duration);
563     }
564 #endif
565 }
566 
567 // Executes the callback function for typescript update, if set
FlushTSUpdates()568 void PipelineContext::FlushTSUpdates()
569 {
570     auto flushTSUpdateCb = flushTSUpdatesCb_;
571     if (flushTSUpdateCb) {
572         // Pass the current container id in the callback.
573         bool result = flushTSUpdateCb(GetInstanceId());
574         if (result) {
575             // There is more to update
576             RequestFrame();
577         }
578     }
579 }
580 
581 // Sets the callback for VSync updates and initiates a frame request
SetFlushTSUpdates(std::function<bool (int32_t)> && flushTSUpdates)582 void PipelineContext::SetFlushTSUpdates(std::function<bool(int32_t)>&& flushTSUpdates)
583 {
584     flushTSUpdatesCb_ = std::move(flushTSUpdates);
585     if (flushTSUpdatesCb_) {
586         RequestFrame();
587     }
588 }
589 
AddScheduleTask(const RefPtr<ScheduleTask> & task)590 uint32_t PipelineContext::AddScheduleTask(const RefPtr<ScheduleTask>& task)
591 {
592     CHECK_RUN_ON(UI);
593     scheduleTasks_.try_emplace(++nextScheduleTaskId_, task);
594     RequestFrame();
595     return nextScheduleTaskId_;
596 }
597 
RemoveScheduleTask(uint32_t id)598 void PipelineContext::RemoveScheduleTask(uint32_t id)
599 {
600     CHECK_RUN_ON(UI);
601     scheduleTasks_.erase(id);
602 }
603 
FlushOnceVsyncTask()604 void PipelineContext::FlushOnceVsyncTask()
605 {
606     if (onceVsyncListener_ != nullptr) {
607         onceVsyncListener_();
608         onceVsyncListener_ = nullptr;
609     }
610 }
611 
FlushDragEvents()612 void PipelineContext::FlushDragEvents()
613 {
614     auto manager = GetDragDropManager();
615     if (!manager) {
616         TAG_LOGE(AceLogTag::ACE_DRAG, "GetDragDrapManager error, manager is nullptr");
617         dragEvents_.clear();
618         return;
619     }
620     if (!manager->IsDragFwkShow()) {
621         manager->DoDragMoveAnimate(manager->GetDragAnimationPointerEvent());
622     }
623     decltype(dragEvents_) dragEvents(std::move(dragEvents_));
624     if (dragEvents.empty()) {
625         canUseLongPredictTask_ = true;
626         nodeToPointEvent_.clear();
627         return;
628     }
629     std::string extraInfo = manager->GetExtraInfo();
630     canUseLongPredictTask_ = false;
631     for (auto iter = dragEvents.begin(); iter != dragEvents.end(); ++iter) {
632         FlushDragEvents(manager, extraInfo, iter->first, iter->second);
633     }
634 }
635 
FlushDragEvents(const RefPtr<DragDropManager> & manager,const std::string & extraInfo,const RefPtr<FrameNode> & node,const std::list<DragPointerEvent> & pointEvent)636 void PipelineContext::FlushDragEvents(const RefPtr<DragDropManager>& manager,
637     const std::string& extraInfo,
638     const RefPtr<FrameNode>& node,
639     const std::list<DragPointerEvent>& pointEvent)
640 {
641     std::unordered_map<int, DragPointerEvent> idToPoints;
642     bool needInterpolation = true;
643     std::unordered_map<int32_t, DragPointerEvent> newIdPoints;
644     for (auto iter = pointEvent.rbegin(); iter != pointEvent.rend(); ++iter) {
645         idToPoints.emplace(iter->pointerId, *iter);
646         idToPoints[iter->pointerId].history.insert(idToPoints[iter->pointerId].history.begin(), *iter);
647         needInterpolation = iter->action != PointerAction::PULL_MOVE ? false : true;
648     }
649     if (!NeedTouchInterpolation()) {
650         needInterpolation = false;
651     }
652     if (needInterpolation) {
653         auto targetTimeStamp = resampleTimeStamp_;
654         for (const auto &idIter : idToPoints) {
655             auto stamp =
656                 std::chrono::duration_cast<std::chrono::nanoseconds>(idIter.second.time.time_since_epoch()).count();
657             if (targetTimeStamp > static_cast<uint64_t>(stamp)) {
658                 LOGI("Skip interpolation when there is no touch event after interpolation time point. "
659                         "(last stamp:%{public}" PRIu64 ", target stamp:%{public}" PRIu64 ")",
660                     static_cast<uint64_t>(stamp), targetTimeStamp);
661                 continue;
662             }
663             DragPointerEvent newPointerEvent = eventManager_->GetResamplePointerEvent(
664                 historyPointsEventById_[idIter.first], idIter.second.history, targetTimeStamp);
665             if (newPointerEvent.x != 0 && newPointerEvent.y != 0) {
666                 newIdPoints[idIter.first] = newPointerEvent;
667             }
668             historyPointsEventById_[idIter.first] = idIter.second.history;
669         }
670     }
671     FlushDragEvents(manager, newIdPoints, extraInfo, idToPoints, node);
672 }
673 
FlushDragEvents(const RefPtr<DragDropManager> & manager,const std::unordered_map<int32_t,DragPointerEvent> & newIdPoints,const std::string & extraInfo,const std::unordered_map<int,DragPointerEvent> & idToPoints,const RefPtr<FrameNode> & node)674 void PipelineContext::FlushDragEvents(const RefPtr<DragDropManager>& manager,
675     const std::unordered_map<int32_t, DragPointerEvent>& newIdPoints,
676     const std::string& extraInfo,
677     const std::unordered_map<int, DragPointerEvent>& idToPoints,
678     const RefPtr<FrameNode>& node)
679 {
680     std::map<WeakPtr<FrameNode>, std::vector<DragPointerEvent>> nodeToPointEvent;
681     std::list<DragPointerEvent> dragPoint;
682     for (const auto& iter : idToPoints) {
683         auto lastDispatchTime = eventManager_->GetLastDispatchTime();
684         lastDispatchTime[iter.first] = GetVsyncTime();
685         eventManager_->SetLastDispatchTime(std::move(lastDispatchTime));
686         auto it = newIdPoints.find(iter.first);
687         if (it != newIdPoints.end()) {
688             dragPoint.emplace_back(it->second);
689             nodeToPointEvent[node].emplace_back(it->second);
690         } else {
691             dragPoint.emplace_back(iter.second);
692             nodeToPointEvent[node].emplace_back(iter.second);
693         }
694     }
695     for (auto iter = dragPoint.rbegin(); iter != dragPoint.rend(); ++iter) {
696         manager->OnDragMove(*iter, extraInfo, node);
697     }
698     nodeToPointEvent_ = std::move(nodeToPointEvent);
699 }
700 
UpdateDVSyncTime(uint64_t nanoTimestamp,const std::string & abilityName,uint64_t vsyncPeriod)701 void PipelineContext::UpdateDVSyncTime(uint64_t nanoTimestamp, const std::string& abilityName, uint64_t vsyncPeriod)
702 {
703     if (nanoTimestamp < lastVSyncTime_) {
704         commandTimeUpdate_ = false;
705     }
706     if (commandTimeUpdate_) {
707         uint64_t now = static_cast<uint64_t>(GetSysTimestamp());
708         if (DVSyncChangeTime_ < now || dvsyncTimeUseCount_ >= MAX_DVSYNC_TIME_USE_COUNT) {
709             commandTimeUpdate_ = false;
710         }
711         if (commandTimeUpdate_) {
712             window_->RecordFrameTime(DVSyncChangeTime_, abilityName);
713             dvsyncTimeUseCount_++;
714             if (dvsyncTimeUpdate_) {
715                 window_->SetDVSyncUpdate(nanoTimestamp);
716                 dvsyncTimeUpdate_ = false;
717             }
718             DVSyncChangeTime_ += vsyncPeriod;
719         }
720     }
721 }
722 
FlushVsync(uint64_t nanoTimestamp,uint64_t frameCount)723 void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint64_t frameCount)
724 {
725     CHECK_RUN_ON(UI);
726     if (IsDestroyed()) {
727         LOGW("Cannot flush vsync as the pipeline context is destroyed.");
728         return;
729     }
730     SetVsyncTime(nanoTimestamp);
731     ACE_SCOPED_TRACE_COMMERCIAL("UIVsyncTask[timestamp:%" PRIu64 "][vsyncID:%" PRIu64 "][instanceID:%d]",
732         nanoTimestamp, frameCount, instanceId_);
733     window_->Lock();
734     static const std::string abilityName = AceApplicationInfo::GetInstance().GetProcessName().empty()
735                                                ? GetBundleName()
736                                                : AceApplicationInfo::GetInstance().GetProcessName();
737     window_->RecordFrameTime(nanoTimestamp, abilityName);
738     uint64_t vsyncPeriod = static_cast<uint64_t>(window_->GetVSyncPeriod());
739     uint64_t timeStamp = (nanoTimestamp > vsyncPeriod) ? (nanoTimestamp - vsyncPeriod + ONE_MS_IN_NS) : ONE_MS_IN_NS;
740     resampleTimeStamp_ = (timeStamp > compensationValue_) ? (timeStamp - compensationValue_) : 0;
741 #ifdef UICAST_COMPONENT_SUPPORTED
742     do {
743         auto container = Container::Current();
744         CHECK_NULL_BREAK(container);
745         auto distributedUI = container->GetDistributedUI();
746         CHECK_NULL_BREAK(distributedUI);
747         distributedUI->ApplyOneUpdate();
748     } while (false);
749 #endif
750     ProcessDelayTasks();
751     DispatchDisplaySync(nanoTimestamp);
752     FlushAnimation(nanoTimestamp);
753     FlushFrameCallback(nanoTimestamp, frameCount);
754     auto hasRunningAnimation = FlushModifierAnimation(nanoTimestamp);
755     FlushTouchEvents();
756     FlushDragEvents();
757     UpdateDVSyncTime(nanoTimestamp, abilityName, vsyncPeriod);
758     lastVSyncTime_ = nanoTimestamp;
759     FlushFrameCallbackFromCAPI(nanoTimestamp, frameCount);
760     FlushBuild();
761     if (isFormRender_ && drawDelegate_ && rootNode_) {
762         auto renderContext = AceType::DynamicCast<NG::RenderContext>(rootNode_->GetRenderContext());
763         drawDelegate_->DrawRSFrame(renderContext);
764         drawDelegate_ = nullptr;
765     }
766     if (!taskScheduler_->isEmpty()) {
767 #if !defined(PREVIEW)
768         LayoutInspector::SupportInspector();
769 #endif
770     }
771 
772     taskScheduler_->StartRecordFrameInfo(GetCurrentFrameInfo(recvTime_, nanoTimestamp));
773     taskScheduler_->FlushTask();
774     UIObserverHandler::GetInstance().HandleLayoutDoneCallBack();
775     if (nodeRenderStatusMonitor_) {
776         nodeRenderStatusMonitor_->WalkThroughAncestorForStateListener();
777     }
778     // flush correct rect again
779     taskScheduler_->FlushPersistAfterLayoutTask();
780     taskScheduler_->FinishRecordFrameInfo();
781     FlushNodeChangeFlag();
782     FlushAnimationClosure();
783     TryCallNextFrameLayoutCallback();
784 
785 #ifdef UICAST_COMPONENT_SUPPORTED
786     do {
787         auto container = Container::Current();
788         CHECK_NULL_BREAK(container);
789         auto distributedUI = container->GetDistributedUI();
790         CHECK_NULL_BREAK(distributedUI);
791         distributedUI->OnTreeUpdate();
792     } while (false);
793 #endif
794 
795     if (hasRunningAnimation || window_->HasUIRunningAnimation()) {
796         RequestFrame();
797     }
798     window_->FlushModifier();
799     FlushFrameRate();
800     FlushDragWindowVisibleCallback();
801     if (isFirstFlushMessages_) {
802         isFirstFlushMessages_ = false;
803         LOGI("ArkUi flush first frame messages.");
804     }
805     taskScheduler_->FlushAfterModifierTask();
806     // the application is in the background and the dark and light colors are switched.
807     if (!onShow_ && backgroundColorModeUpdated_) {
808         backgroundColorModeUpdated_ = false;
809         FlushMessages([window = window_]() {
810             if (window) {
811                 window->NotifySnapshotUpdate();
812             }
813         });
814     } else {
815         FlushMessages();
816     }
817     FlushWindowPatternInfo();
818     InspectDrew();
819     UIObserverHandler::GetInstance().HandleDrawCommandSendCallBack();
820     if (onShow_ && onFocus_ && isWindowHasFocused_) {
821         auto isDynamicRender = Container::Current() == nullptr ? false : Container::Current()->IsDynamicRender();
822         if ((!isFormRender_) || isDynamicRender) {
823             FlushFocusView();
824             FlushFocus();
825             FlushFocusScroll();
826         }
827     }
828     if (SystemProperties::GetContainerDeleteFlag()) {
829         if (isNeedCallbackAreaChange_) {
830             isNeedCallbackAreaChange_ = false;
831             RenderContext::SetNeedCallbackNodeChange(true);
832             HandleOnAreaChangeEvent(nanoTimestamp);
833             HandleVisibleAreaChangeEvent(nanoTimestamp);
834         }
835     } else {
836         HandleOnAreaChangeEvent(nanoTimestamp);
837         HandleVisibleAreaChangeEvent(nanoTimestamp);
838     }
839     UpdateFormLinkInfos();
840     FlushMouseEventInVsync();
841     eventManager_->FlushCursorStyleRequests();
842     if (isNeedFlushAnimationStartTime_) {
843         window_->FlushAnimationStartTime(animationTimeStamp_);
844         isNeedFlushAnimationStartTime_ = false;
845     }
846     needRenderNode_.clear();
847     taskScheduler_->FlushAfterRenderTask();
848     window_->FlushLayoutSize(width_, height_);
849     if (IsFocusWindowIdSetted()) {
850         FireAllUIExtensionEvents();
851     }
852     FireAccessibilityEvents();
853     // Keep the call sent at the end of the function
854     ResSchedReport::GetInstance().LoadPageEvent(ResDefine::LOAD_PAGE_COMPLETE_EVENT);
855     TriggerFrameDumpFuncIfExist();
856     window_->Unlock();
857 #ifdef COMPONENT_TEST_ENABLED
858     ComponentTest::UpdatePipelineStatus();
859 #endif // COMPONENT_TEST_ENABLED
860 }
861 
FlushMouseEventVoluntarily()862 void PipelineContext::FlushMouseEventVoluntarily()
863 {
864     if (!lastMouseEvent_ || lastMouseEvent_->action == MouseAction::WINDOW_LEAVE ||
865         windowSizeChangeReason_ == WindowSizeChangeReason::DRAG) {
866         return;
867     }
868     CHECK_RUN_ON(UI);
869     CHECK_NULL_VOID(rootNode_);
870     ACE_SCOPED_TRACE("FlushMouseEventVoluntarily x:%f y:%f", lastMouseEvent_->x, lastMouseEvent_->y);
871 
872     MouseEvent event;
873     if (isNeedFlushMouseEvent_ == MockFlushEventType::REJECT) {
874         event.mockFlushEvent = true;
875     }
876     event.x = lastMouseEvent_->x;
877     event.y = lastMouseEvent_->y;
878     event.time = lastMouseEvent_->time;
879     event.action = MouseAction::MOVE;
880     event.button = MouseButton::NONE_BUTTON;
881     event.sourceType = SourceType::MOUSE;
882     event.deviceId = lastMouseEvent_->deviceId;
883     event.sourceTool = SourceTool::MOUSE;
884     event.targetDisplayId = lastMouseEvent_->targetDisplayId;
885 
886     auto scaleEvent = event.CreateScaleEvent(viewScale_);
887     TouchRestrict touchRestrict { TouchRestrict::NONE };
888     touchRestrict.sourceType = event.sourceType;
889     touchRestrict.hitTestType = SourceType::MOUSE;
890     touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
891 
892     eventManager_->MouseTest(scaleEvent, rootNode_, touchRestrict);
893     eventManager_->DispatchMouseEventNG(scaleEvent);
894     eventManager_->DispatchMouseHoverEventNG(scaleEvent);
895     eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
896 }
897 
FlushWindowPatternInfo()898 void PipelineContext::FlushWindowPatternInfo()
899 {
900 #ifdef WINDOW_SCENE_SUPPORTED
901     int32_t id = -1;
902     if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
903         id = Container::CurrentId();
904     }
905     OTHER_DURATION(id);
906     auto container = Container::Current();
907     CHECK_NULL_VOID(container);
908     if (!container->IsSceneBoardWindow()) {
909         return;
910     }
911     auto screenNode = screenNode_.Upgrade();
912     if (!screenNode) {
913         return;
914     }
915     ACE_SCOPED_TRACE("FlushWindowPatternInfo");
916     auto instance = WindowSceneLayoutManager::GetInstance();
917     if (instance != nullptr) {
918         instance->FlushWindowPatternInfo(screenNode);
919     }
920 #endif
921 }
922 
InspectDrew()923 void PipelineContext::InspectDrew()
924 {
925     CHECK_RUN_ON(UI);
926     if (!needRenderNode_.empty()) {
927         auto needRenderNode = std::move(needRenderNode_);
928         for (auto&& nodeWeak : needRenderNode) {
929             auto node = nodeWeak.Upgrade();
930             if (!node) {
931                 return;
932             }
933             if (node->GetInspectorId().has_value()) {
934                 OnDrawCompleted(node->GetInspectorId()->c_str());
935             }
936             auto eventHub = node->GetOrCreateEventHub<NG::EventHub>();
937             CHECK_NULL_VOID(eventHub);
938             eventHub->FireDrawCompletedNDKCallback(this);
939         }
940     }
941     if (!needRenderForDrawChildrenNodes_.empty()) {
942         auto needRenderNodes = std::move(needRenderForDrawChildrenNodes_);
943         for (auto&& nodeWeak : needRenderNodes) {
944             auto node = nodeWeak.Upgrade();
945             if (node == nullptr) {
946                 continue;
947             }
948             if (node->GetInspectorId().has_value()) {
949                 OnDrawChildrenCompleted(node->GetInspectorId().value());
950             }
951         }
952         needRenderForDrawChildrenNodes_.clear();
953     }
954 }
955 
ProcessDelayTasks()956 void PipelineContext::ProcessDelayTasks()
957 {
958     if (delayedTasks_.empty()) {
959         return;
960     }
961     auto currentTimeStamp = GetSysTimestamp();
962     auto delayedTasks = std::move(delayedTasks_);
963     auto result = std::remove_if(delayedTasks.begin(), delayedTasks.end(), [this, currentTimeStamp](const auto& task) {
964         if (task.timeStamp + static_cast<int64_t>(task.time) * MILLISECONDS_TO_NANOSECONDS > currentTimeStamp) {
965             delayedTasks_.emplace_back(task);
966             return true;
967         }
968         return false;
969     });
970     delayedTasks.erase(result, delayedTasks.end());
971     std::for_each(delayedTasks.begin(), delayedTasks.end(), [this](auto& delayedTask) {
972         if (delayedTask.task) {
973             delayedTask.task();
974         }
975     });
976 }
977 
DispatchDisplaySync(uint64_t nanoTimestamp)978 void PipelineContext::DispatchDisplaySync(uint64_t nanoTimestamp)
979 {
980     int32_t currentId = -1;
981     if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
982         currentId = Container::CurrentId();
983     }
984     OTHER_DURATION(currentId);
985     CHECK_RUN_ON(UI);
986     ACE_FUNCTION_TRACE();
987 
988     const auto& displaySyncManager = GetOrCreateUIDisplaySyncManager();
989     if (!displaySyncManager) {
990         TAG_LOGE(AceLogTag::ACE_DISPLAY_SYNC, "[DispatchDisplaySync] displaySyncManager is nullptr.");
991         return;
992     }
993 
994     DisplaysyncCpuBoostOperate(true);
995     displaySyncManager->SetRefreshRateMode(window_->GetCurrentRefreshRateMode());
996     displaySyncManager->SetVsyncPeriod(window_->GetVSyncPeriod());
997 
998     if (FrameReport::GetInstance().GetEnable()) {
999         FrameReport::GetInstance().BeginFlushAnimation();
1000     }
1001 
1002     scheduleTasks_.clear();
1003     displaySyncManager->DispatchFunc(nanoTimestamp);
1004 
1005     if (FrameReport::GetInstance().GetEnable()) {
1006         FrameReport::GetInstance().EndFlushAnimation();
1007     }
1008 
1009     int32_t displaySyncRate = displaySyncManager->GetDisplaySyncRate();
1010     frameRateManager_->SetDisplaySyncRate(displaySyncRate);
1011     auto monitorVsyncRate = displaySyncManager->GetMonitorVsyncRate();
1012     auto id = GetInstanceId();
1013     ArkUIPerfMonitor::GetPerfMonitor(id)->RecordDisplaySyncRate(monitorVsyncRate);
1014     DisplaysyncCpuBoostOperate(false);
1015 }
1016 
FlushAnimation(uint64_t nanoTimestamp)1017 void PipelineContext::FlushAnimation(uint64_t nanoTimestamp)
1018 {
1019     int32_t id = -1;
1020     if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
1021         id = Container::CurrentId();
1022     }
1023     OTHER_DURATION(id);
1024     CHECK_RUN_ON(UI);
1025     ACE_FUNCTION_TRACE();
1026     if (scheduleTasks_.empty()) {
1027         return;
1028     }
1029 }
1030 
FlushModifier()1031 void PipelineContext::FlushModifier()
1032 {
1033     window_->FlushModifier();
1034 }
1035 
HandleSpecialContainerNode()1036 void PipelineContext::HandleSpecialContainerNode()
1037 {
1038     if (!SystemProperties::GetContainerDeleteFlag()) {
1039         return;
1040     }
1041 
1042     auto positionZSet = GetPositionZNodes();
1043     for (auto positionZNodeId : positionZSet) {
1044         auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(positionZNodeId));
1045         if (!frameNode) {
1046             continue;
1047         }
1048         auto parentNode = frameNode->GetParentFrameNode();
1049         if (!parentNode) {
1050             continue;
1051         }
1052         if (parentNode->GetRenderContext()) {
1053             parentNode->GetRenderContext()->SetDrawNode();
1054         }
1055         std::list<RefPtr<FrameNode>> childrenList;
1056         parentNode->GenerateOneDepthVisibleFrameWithTransition(childrenList);
1057         for (auto& node : childrenList) {
1058             if (node && node->GetRenderContext()) {
1059                 node->GetRenderContext()->SetDrawNode();
1060             }
1061         }
1062         auto overlayNode = parentNode->GetOverlayNode();
1063         if (overlayNode && overlayNode->GetRenderContext()) {
1064             overlayNode->GetRenderContext()->SetDrawNode();
1065         }
1066         auto accessibilityFocusPaintNode = parentNode->GetFocusPaintNode();
1067         if (accessibilityFocusPaintNode && accessibilityFocusPaintNode->GetRenderContext()) {
1068             accessibilityFocusPaintNode->GetRenderContext()->SetDrawNode();
1069         }
1070     }
1071     ClearPositionZNodes();
1072 }
1073 
UpdateOcclusionCullingStatus()1074 void PipelineContext::UpdateOcclusionCullingStatus()
1075 {
1076     for (auto &&[id, enable] : keyOcclusionNodes_) {
1077         auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(id));
1078         if (!frameNode) {
1079             continue;
1080         }
1081         frameNode->UpdateOcclusionCullingStatus(enable);
1082     }
1083     keyOcclusionNodes_.clear();
1084 }
1085 
FlushMessages(std::function<void ()> callback)1086 void PipelineContext::FlushMessages(std::function<void()> callback)
1087 {
1088     int32_t id = -1;
1089     if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
1090         id = Container::CurrentId();
1091     }
1092     OTHER_DURATION(id);
1093     ACE_FUNCTION_TRACE_COMMERCIAL();
1094     if (IsFreezeFlushMessage()) {
1095         SetIsFreezeFlushMessage(false);
1096         LOGI("Flush message is freezed.");
1097         return;
1098     }
1099     if (navigationMgr_) {
1100         navigationMgr_->CacheNavigationNodeAnimation();
1101     }
1102     if (!window_->GetIsRequestFrame()) {
1103         ACE_SCOPED_TRACE("smart gc end with no request frame(app_start or push_page)!");
1104         ResSchedReport::GetInstance().ResSchedDataReport("page_end_flush", {});
1105     }
1106     HandleSpecialContainerNode();
1107     UpdateOcclusionCullingStatus();
1108     window_->FlushTasks(callback);
1109 }
1110 
FlushUITasks(bool triggeredByImplicitAnimation)1111 void PipelineContext::FlushUITasks(bool triggeredByImplicitAnimation)
1112 {
1113     window_->Lock();
1114     if (!CheckThreadSafe()) {
1115         LOGW("FlushUITasks doesn't run on UI thread!");
1116     }
1117     decltype(dirtyPropertyNodes_) dirtyPropertyNodes(std::move(dirtyPropertyNodes_));
1118     dirtyPropertyNodes_.clear();
1119     for (const auto& dirtyNode : dirtyPropertyNodes) {
1120         dirtyNode->ProcessPropertyDiff();
1121     }
1122     taskScheduler_->FlushTaskWithCheck(triggeredByImplicitAnimation);
1123     if (AnimationUtils::IsImplicitAnimationOpen()) {
1124         FlushNodeChangeFlag();
1125     }
1126     window_->Unlock();
1127 }
1128 
FlushUITaskWithSingleDirtyNode(const RefPtr<FrameNode> & node)1129 void PipelineContext::FlushUITaskWithSingleDirtyNode(const RefPtr<FrameNode>& node)
1130 {
1131     CHECK_NULL_VOID(node);
1132     if (IsLayouting()) {
1133         taskScheduler_->AddSingleNodeToFlush(node);
1134         return;
1135     }
1136     auto layoutProperty = node->GetLayoutProperty();
1137     CHECK_NULL_VOID(layoutProperty);
1138     auto layoutConstraint = node->GetLayoutConstraint();
1139     auto originLayoutingFlag = IsLayouting();
1140     SetIsLayouting(true);
1141     if (layoutProperty->GetLayoutRect()) {
1142         node->SetActive(true, true);
1143         node->Measure(std::nullopt);
1144         node->Layout();
1145     } else {
1146         auto ancestorNodeOfFrame = node->GetAncestorNodeOfFrame(false);
1147         {
1148             ACE_SCOPED_TRACE("FlushUITaskWithSingleDirtyNodeMeasure[%s][self:%d][parent:%d][layoutConstraint:%s]"
1149                              "[pageId:%d][depth:%d]",
1150                 node->GetTag().c_str(), node->GetId(), ancestorNodeOfFrame ? ancestorNodeOfFrame->GetId() : 0,
1151                 layoutConstraint.ToString().c_str(), node->GetPageId(), node->GetDepth());
1152             node->Measure(layoutConstraint);
1153         }
1154         {
1155             ACE_SCOPED_TRACE("FlushUITaskWithSingleDirtyNodeLayout[%s][self:%d][parent:%d][pageId:%d][depth:%d]",
1156                 node->GetTag().c_str(), node->GetId(), ancestorNodeOfFrame ? ancestorNodeOfFrame->GetId() : 0,
1157                 node->GetPageId(), node->GetDepth());
1158             node->Layout();
1159         }
1160     }
1161     node->SetEscapeDelayForIgnore(false);
1162     SetIsLayouting(originLayoutingFlag);
1163 }
1164 
FlushAfterLayoutCallbackInImplicitAnimationTask()1165 void PipelineContext::FlushAfterLayoutCallbackInImplicitAnimationTask()
1166 {
1167     if (AnimationUtils::IsImplicitAnimationOpen()) {
1168         TAG_LOGD(AceLogTag::ACE_ANIMATION,
1169             "Can not flush implicit animation task after layout because implicit animation is open.");
1170         return;
1171     }
1172     window_->Lock();
1173     taskScheduler_->FlushAfterLayoutCallbackInImplicitAnimationTask();
1174     window_->Unlock();
1175 }
1176 
SetNeedRenderNode(const WeakPtr<FrameNode> & node)1177 void PipelineContext::SetNeedRenderNode(const WeakPtr<FrameNode>& node)
1178 {
1179     CHECK_RUN_ON(UI);
1180     needRenderNode_.insert(node);
1181 }
1182 
SetNeedRenderForDrawChildrenNode(const WeakPtr<NG::UINode> & node)1183 void PipelineContext::SetNeedRenderForDrawChildrenNode(const WeakPtr<NG::UINode>& node)
1184 {
1185     CHECK_NULL_VOID(node.Upgrade());
1186     needRenderForDrawChildrenNodes_.emplace(node);
1187 }
1188 
FlushFocus()1189 void PipelineContext::FlushFocus()
1190 {
1191     CHECK_RUN_ON(UI);
1192     ACE_FUNCTION_TRACK();
1193     ACE_FUNCTION_TRACE();
1194 
1195     FlushRequestFocus();
1196 
1197     auto focusNode = dirtyFocusNode_.Upgrade();
1198     if (!focusNode || focusNode->GetFocusType() != FocusType::NODE) {
1199         dirtyFocusNode_.Reset();
1200     } else {
1201         FlushFocusWithNode(focusNode, false);
1202         return;
1203     }
1204     auto focusScope = dirtyFocusScope_.Upgrade();
1205     if (!focusScope || focusScope->GetFocusType() != FocusType::SCOPE) {
1206         dirtyFocusScope_.Reset();
1207     } else {
1208         FlushFocusWithNode(focusScope, true);
1209         return;
1210     }
1211     GetOrCreateFocusManager()->WindowFocusMoveEnd();
1212 }
1213 
FlushFocusWithNode(RefPtr<FrameNode> focusNode,bool isScope)1214 void PipelineContext::FlushFocusWithNode(RefPtr<FrameNode> focusNode, bool isScope)
1215 {
1216     auto focusNodeHub = focusNode->GetFocusHub();
1217     if (focusNodeHub && !focusNodeHub->RequestFocusImmediately()) {
1218         auto unfocusableParentFocusNode = focusNodeHub->GetUnfocusableParentFocusNode().Upgrade();
1219         if (unfocusableParentFocusNode) {
1220             TAG_LOGD(AceLogTag::ACE_FOCUS,
1221                 "Request focus on %{public}s: %{public}s/%{public}d return false, unfocusable node: "
1222                 "%{public}s/%{public}d, focusable = %{public}d, shown = %{public}d, enabled = %{public}d",
1223                 isScope ? "scope" : "node", focusNode->GetTag().c_str(), focusNode->GetId(),
1224                 unfocusableParentFocusNode->GetFrameName().c_str(), unfocusableParentFocusNode->GetFrameId(),
1225                 unfocusableParentFocusNode->GetFocusable(), unfocusableParentFocusNode->IsShow(),
1226                 unfocusableParentFocusNode->IsEnabled());
1227             unfocusableParentFocusNode = nullptr;
1228         } else {
1229             TAG_LOGD(AceLogTag::ACE_FOCUS, "Request focus on %{public}s: %{public}s/%{public}d return false",
1230                 isScope ? "scope" : "node", focusNode->GetTag().c_str(), focusNode->GetId());
1231         }
1232     }
1233     dirtyFocusNode_.Reset();
1234     dirtyFocusScope_.Reset();
1235     dirtyRequestFocusNode_.Reset();
1236     GetOrCreateFocusManager()->WindowFocusMoveEnd();
1237 }
1238 
FlushRequestFocus()1239 void PipelineContext::FlushRequestFocus()
1240 {
1241     CHECK_RUN_ON(UI);
1242 
1243     auto requestFocusNode = dirtyRequestFocusNode_.Upgrade();
1244     if (!requestFocusNode) {
1245         dirtyRequestFocusNode_.Reset();
1246     } else {
1247         auto focusNodeHub = requestFocusNode->GetFocusHub();
1248         if (focusNodeHub && !focusNodeHub->RequestFocusImmediately()) {
1249             auto unfocusableParentFocusNode = focusNodeHub->GetUnfocusableParentFocusNode().Upgrade();
1250             if (unfocusableParentFocusNode) {
1251                 TAG_LOGI(AceLogTag::ACE_FOCUS,
1252                     "Request focus by id on node: %{public}s/%{public}d return false, unfocusable node: "
1253                     "%{public}s/%{public}d, focusable = %{public}d, shown = %{public}d, enabled = %{public}d",
1254                     requestFocusNode->GetTag().c_str(), requestFocusNode->GetId(),
1255                     unfocusableParentFocusNode->GetFrameName().c_str(), unfocusableParentFocusNode->GetFrameId(),
1256                     unfocusableParentFocusNode->GetFocusable(), unfocusableParentFocusNode->IsShow(),
1257                     unfocusableParentFocusNode->IsEnabled());
1258                 unfocusableParentFocusNode = nullptr;
1259             } else {
1260                 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus by id on node: %{public}s/%{public}d return false",
1261                     requestFocusNode->GetTag().c_str(), requestFocusNode->GetId());
1262             }
1263         }
1264         dirtyFocusNode_.Reset();
1265         dirtyFocusScope_.Reset();
1266         dirtyRequestFocusNode_.Reset();
1267         return;
1268     }
1269 }
1270 
FlushFocusView()1271 void PipelineContext::FlushFocusView()
1272 {
1273     CHECK_NULL_VOID(focusManager_);
1274     auto lastFocusView = (focusManager_->GetLastFocusView()).Upgrade();
1275     CHECK_NULL_VOID(lastFocusView);
1276     auto lastFocusViewHub = lastFocusView->GetFocusHub();
1277     CHECK_NULL_VOID(lastFocusViewHub);
1278     ACE_EVENT_SCOPED_TRACE("FlushFocusView:[%s][%d][enable:%d][show:%d]", lastFocusViewHub->GetFrameName().c_str(),
1279         lastFocusViewHub->GetFrameId(), lastFocusViewHub->IsEnabled(), lastFocusViewHub->IsShow());
1280     auto container = Container::Current();
1281     if (container && (container->IsUIExtensionWindow() || container->IsDynamicRender()) &&
1282         (!lastFocusView->IsRootScopeCurrentFocus())) {
1283         lastFocusView->SetIsViewRootScopeFocused(false);
1284     }
1285     if (lastFocusView && (!lastFocusView->IsRootScopeCurrentFocus() || !lastFocusView->GetIsViewHasFocused()) &&
1286         lastFocusViewHub->IsFocusableNode()) {
1287         lastFocusView->RequestDefaultFocus();
1288         focusManager_->SetFocusViewStackState(FocusViewStackState::IDLE);
1289     }
1290 }
1291 
FlushFocusScroll()1292 void PipelineContext::FlushFocusScroll()
1293 {
1294     CHECK_NULL_VOID(focusManager_);
1295     if (!focusManager_->GetNeedTriggerScroll()) {
1296         return;
1297     }
1298     auto lastFocusStateNode = focusManager_->GetLastFocusStateNode();
1299     CHECK_NULL_VOID(lastFocusStateNode);
1300     if (!lastFocusStateNode->TriggerFocusScroll()) {
1301         focusManager_->SetNeedTriggerScroll(false);
1302     }
1303 }
1304 
FlushPipelineImmediately()1305 void PipelineContext::FlushPipelineImmediately()
1306 {
1307     CHECK_RUN_ON(UI);
1308     ACE_SCOPED_TRACE("PipelineContext::FlushPipelineImmediately, isLayouting_ %d", taskScheduler_->IsLayouting());
1309     if (!taskScheduler_->IsLayouting()) {
1310         FlushPipelineWithoutAnimation();
1311         return;
1312     }
1313     auto task = [weak = WeakClaim(this)]() {
1314         auto pipeline = weak.Upgrade();
1315         CHECK_NULL_VOID(pipeline);
1316         pipeline->FlushPipelineWithoutAnimation();
1317     };
1318     AddAfterLayoutTask(task);
1319 }
1320 
RebuildFontNode()1321 void PipelineContext::RebuildFontNode()
1322 {
1323     if (fontManager_) {
1324         fontManager_->RebuildFontNodeNG();
1325     }
1326 }
1327 
FlushPipelineWithoutAnimation()1328 void PipelineContext::FlushPipelineWithoutAnimation()
1329 {
1330     ACE_FUNCTION_TRACE();
1331     window_->Lock();
1332     FlushBuild();
1333     FlushTouchEvents();
1334     taskScheduler_->FlushTask();
1335     FlushAnimationClosure();
1336     window_->FlushModifier();
1337     FlushMessages();
1338     FlushFocus();
1339     window_->Unlock();
1340 }
1341 
FlushFrameRate()1342 void PipelineContext::FlushFrameRate()
1343 {
1344     frameRateManager_->SetAnimateRate(window_->GetAnimateExpectedRate(), window_->HasFirstFrameAnimation());
1345     int32_t currAnimatorExpectedFrameRate = GetOrCreateUIDisplaySyncManager()->GetAnimatorRate();
1346     if (frameRateManager_->IsRateChanged() || currAnimatorExpectedFrameRate != lastAnimatorExpectedFrameRate_) {
1347         auto [rate, rateType] = frameRateManager_->GetExpectedRate();
1348         ACE_SCOPED_TRACE("FlushFrameRate Expected frameRate = %d frameRateType = %d "
1349             "currAnimatorExpectedFrameRate = %d, lastAnimatorExpectedFrameRate = %d",
1350             rate, rateType, currAnimatorExpectedFrameRate, lastAnimatorExpectedFrameRate_);
1351         TAG_LOGD(AceLogTag::ACE_DISPLAY_SYNC, "FlushFrameRate Expected frameRate = %{public}d "
1352             "frameRateType = %{public}d currAnimatorExpectedFrameRate = %{public}d, lastRate = %{public}d",
1353             rate, rateType, currAnimatorExpectedFrameRate, lastAnimatorExpectedFrameRate_);
1354         window_->FlushFrameRate(rate, currAnimatorExpectedFrameRate, rateType);
1355         frameRateManager_->SetIsRateChanged(false);
1356         lastAnimatorExpectedFrameRate_ = currAnimatorExpectedFrameRate;
1357     }
1358 }
1359 
FlushDragWindowVisibleCallback()1360 void PipelineContext::FlushDragWindowVisibleCallback()
1361 {
1362     if (dragWindowVisibleCallback_) {
1363         dragWindowVisibleCallback_();
1364         dragWindowVisibleCallback_ = nullptr;
1365     }
1366 }
1367 
FlushBuild()1368 void PipelineContext::FlushBuild()
1369 {
1370     if (vsyncListener_ != nullptr) {
1371         ACE_SCOPED_TRACE("arkoala build");
1372         vsyncListener_();
1373     }
1374     FlushOnceVsyncTask();
1375     isRebuildFinished_ = false;
1376     FlushDirtyNodeUpdate();
1377     isRebuildFinished_ = true;
1378     FlushBuildFinishCallbacks();
1379 }
1380 
SetVsyncListener(VsyncCallbackFun vsync)1381 void PipelineContext::SetVsyncListener(VsyncCallbackFun vsync)
1382 {
1383     vsyncListener_ = std::move(vsync);
1384 }
1385 
AddAnimationClosure(std::function<void ()> && animation)1386 void PipelineContext::AddAnimationClosure(std::function<void()>&& animation)
1387 {
1388     animationClosuresList_.emplace_back(std::move(animation));
1389 }
1390 
FlushAnimationClosure()1391 void PipelineContext::FlushAnimationClosure()
1392 {
1393     if (animationClosuresList_.empty()) {
1394         return;
1395     }
1396     window_->Lock();
1397     taskScheduler_->FlushTask();
1398 
1399     decltype(animationClosuresList_) temp(std::move(animationClosuresList_));
1400     for (const auto& animation : temp) {
1401         animation();
1402     }
1403     window_->Unlock();
1404 }
1405 
FlushBuildFinishCallbacks()1406 void PipelineContext::FlushBuildFinishCallbacks()
1407 {
1408     decltype(buildFinishCallbacks_) buildFinishCallbacks(std::move(buildFinishCallbacks_));
1409     for (const auto& func : buildFinishCallbacks) {
1410         if (func) {
1411             func();
1412         }
1413     }
1414 }
1415 
RegisterRootEvent()1416 void PipelineContext::RegisterRootEvent()
1417 {
1418     if (!IsFormRender()) {
1419         return;
1420     }
1421     auto accessibilityProperty = rootNode_->GetAccessibilityProperty<AccessibilityProperty>();
1422     if (accessibilityProperty != nullptr) {
1423         accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::NO_STR);
1424     }
1425 
1426     // To avoid conflicts between longPress and click events on the card,
1427     // use an empty longPress event placeholder in the EtsCard scenario
1428     auto hub = rootNode_->GetOrCreateGestureEventHub();
1429     CHECK_NULL_VOID(hub);
1430     auto event = [](const GestureEvent& info) mutable {};
1431     auto longPress = AceType::MakeRefPtr<NG::LongPressEvent>(std::move(event));
1432     hub->SetLongPressEvent(longPress, false, true);
1433 }
1434 
SetupRootElement()1435 void PipelineContext::SetupRootElement()
1436 {
1437     CHECK_RUN_ON(UI);
1438     auto rootPattern = ViewAdvancedRegister::GetInstance()->GeneratePattern(V2::ROOT_ETS_TAG);
1439     if (!rootPattern) {
1440         rootPattern = MakeRefPtr<RootPattern>();
1441     }
1442     rootNode_ = FrameNode::CreateFrameNodeWithTree(
1443         V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), rootPattern);
1444     rootNode_->SetHostRootId(GetInstanceId());
1445     rootNode_->SetHostPageId(-1);
1446     rootNode_->SetActive(true);
1447     RegisterRootEvent();
1448     CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
1449     MeasureProperty layoutConstraint;
1450     layoutConstraint.selfIdealSize = idealSize;
1451     layoutConstraint.maxSize = idealSize;
1452     rootNode_->UpdateLayoutConstraint(layoutConstraint);
1453     auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
1454     rootFocusHub->SetFocusType(FocusType::SCOPE);
1455     rootFocusHub->SetFocusable(true);
1456     window_->SetRootFrameNode(rootNode_);
1457     rootNode_->AttachToMainTree(false, this);
1458     auto stagePattern = ViewAdvancedRegister::GetInstance()->GeneratePattern(V2::STAGE_ETS_TAG);
1459     if (!stagePattern) {
1460         stagePattern = MakeRefPtr<StagePattern>();
1461     }
1462     auto stageNode = FrameNode::CreateFrameNode(
1463         V2::STAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), stagePattern);
1464     RefPtr<AppBarView> appBar = AceType::MakeRefPtr<AppBarView>();
1465     auto atomicService = installationFree_ ? appBar->Create(stageNode) : nullptr;
1466     auto container = Container::Current();
1467     if (container && installationFree_) {
1468         container->SetAppBar(appBar);
1469     }
1470     if (windowModal_ == WindowModal::CONTAINER_MODAL) {
1471         MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();
1472         rootNode_->AddChild(
1473             ContainerModalViewFactory::GetView(atomicService ? atomicService : stageNode, maximizeMode));
1474     } else {
1475         rootNode_->AddChild(atomicService ? atomicService : stageNode);
1476     }
1477 #ifdef ENABLE_ROSEN_BACKEND
1478     std::shared_ptr<Rosen::RSUIDirector> rsUIDirector;
1479     if (!IsJsCard() && !isFormRender_) {
1480         rsUIDirector = GetRSUIDirector();
1481         if (rsUIDirector) {
1482             RSTransactionBegin(rsUIDirector);
1483             rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1484             RSTransactionCommit(rsUIDirector);
1485         }
1486     }
1487 #endif
1488     accessibilityManagerNG_ = MakeRefPtr<AccessibilityManagerNG>();
1489     stageManager_ = ViewAdvancedRegister::GetInstance()->GenerateStageManager(stageNode);
1490     if (!stageManager_) {
1491         stageManager_ = MakeRefPtr<StageManager>(stageNode);
1492     }
1493     auto getPagePathCallback = [weakFrontend = weakFrontend_](const std::string& url) -> std::string {
1494         auto frontend = weakFrontend.Upgrade();
1495         CHECK_NULL_RETURN(frontend, "");
1496         return frontend->GetPagePathByUrl(url);
1497     };
1498     stageManager_->SetGetPagePathCallback(std::move(getPagePathCallback));
1499     auto frameNode = DynamicCast<FrameNode>(installationFree_ ? atomicService->GetParent() :
1500         stageNode->GetParent());
1501     overlayManager_ = MakeRefPtr<OverlayManager>(frameNode);
1502     fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
1503     selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
1504     fontManager_->AddFontObserver(selectOverlayManager_);
1505     if (!privacySensitiveManager_) {
1506         privacySensitiveManager_ = MakeRefPtr<PrivacySensitiveManager>();
1507     }
1508     postEventManager_ = MakeRefPtr<PostEventManager>();
1509     dragDropManager_ = MakeRefPtr<DragDropManager>();
1510     focusManager_ = GetOrCreateFocusManager();
1511     sharedTransitionManager_ = MakeRefPtr<SharedOverlayManager>(
1512         DynamicCast<FrameNode>(installationFree_ ? atomicService->GetParent() : stageNode->GetParent()));
1513 
1514     auto instanceId = container ? container->GetInstanceId() : Container::CurrentId();
1515     OnAreaChangedFunc onAreaChangedFunc = [weakOverlayManger = AceType::WeakClaim(AceType::RawPtr(overlayManager_)),
1516                                               instanceId](
1517                                               const RectF& /* oldRect */, const OffsetF& /* oldOrigin */,
1518                                               const RectF& /* rect */, const OffsetF& /* origin */) {
1519         TAG_LOGI(AceLogTag::ACE_OVERLAY, "start OnAreaChangedFunc");
1520         auto overlay = weakOverlayManger.Upgrade();
1521         CHECK_NULL_VOID(overlay);
1522         auto container = Container::GetContainer(instanceId);
1523         // In sceneBoard window, popup and menu need be cleared without animation.
1524         if (container && container->IsSceneBoardWindow()) {
1525             overlay->HideAllMenusWithoutAnimation();
1526             overlay->HideAllPopupsWithoutAnimation();
1527             SubwindowManager::GetInstance()->ClearAllMenuPopup(instanceId);
1528         } else {
1529             overlay->HideAllMenus();
1530             SubwindowManager::GetInstance()->HideMenuNG(false);
1531             overlay->HideCustomPopups();
1532         }
1533         SubwindowManager::GetInstance()->ClearToastInSubwindow();
1534         SubwindowManager::GetInstance()->ClearToastInSystemSubwindow();
1535         overlay->UpdateCustomKeyboardPosition();
1536     };
1537     rootNode_->SetOnAreaChangeCallback(std::move(onAreaChangedFunc));
1538     AddOnAreaChangeNode(rootNode_->GetId());
1539 }
1540 
SetOnWindowFocused(const std::function<void ()> & callback)1541 void PipelineContext::SetOnWindowFocused(const std::function<void()>& callback)
1542 {
1543     CHECK_NULL_VOID(taskExecutor_);
1544     taskExecutor_->PostTask([weak = WeakClaim(this), callback]() {
1545             auto pipeline = weak.Upgrade();
1546             CHECK_NULL_VOID(pipeline);
1547             pipeline->focusOnNodeCallback_ = callback;
1548         }, TaskExecutor::TaskType::UI, "ArkUISetOnWindowFocusedCallback");
1549 }
1550 
RSTransactionBegin(const std::shared_ptr<Rosen::RSUIDirector> & rsUIDirector)1551 void PipelineContext::RSTransactionBegin(const std::shared_ptr<Rosen::RSUIDirector>& rsUIDirector)
1552 {
1553 #ifdef ENABLE_ROSEN_BACKEND
1554     if (SystemProperties::GetMultiInstanceEnabled() && rsUIDirector) {
1555         auto surfaceNode = rsUIDirector->GetRSSurfaceNode();
1556         CHECK_NULL_VOID(surfaceNode);
1557         auto rsUIContext = surfaceNode->GetRSUIContext();
1558         CHECK_NULL_VOID(rsUIContext);
1559         auto rsTransaction = rsUIContext->GetRSTransaction();
1560         CHECK_NULL_VOID(rsTransaction);
1561         rsTransaction->Begin();
1562     }
1563 #endif
1564 }
1565 
RSTransactionCommit(const std::shared_ptr<Rosen::RSUIDirector> & rsUIDirector)1566 void PipelineContext::RSTransactionCommit(const std::shared_ptr<Rosen::RSUIDirector>& rsUIDirector)
1567 {
1568 #ifdef ENABLE_ROSEN_BACKEND
1569     if (SystemProperties::GetMultiInstanceEnabled() && rsUIDirector) {
1570         auto surfaceNode = rsUIDirector->GetRSSurfaceNode();
1571         CHECK_NULL_VOID(surfaceNode);
1572         auto rsUIContext = surfaceNode->GetRSUIContext();
1573         CHECK_NULL_VOID(rsUIContext);
1574         auto rsTransaction = rsUIContext->GetRSTransaction();
1575         CHECK_NULL_VOID(rsTransaction);
1576         rsTransaction->Commit();
1577     }
1578 #endif
1579 }
1580 
SetupSubRootElement()1581 void PipelineContext::SetupSubRootElement()
1582 {
1583     CHECK_RUN_ON(UI);
1584     appBgColor_ = Color::TRANSPARENT;
1585     auto rootPattern = ViewAdvancedRegister::GetInstance()->GeneratePattern(V2::ROOT_ETS_TAG);
1586     if (!rootPattern) {
1587         rootPattern = MakeRefPtr<RootPattern>();
1588     }
1589     rootNode_ = FrameNode::CreateFrameNodeWithTree(
1590         V2::ROOT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), rootPattern);
1591     rootNode_->SetHostRootId(GetInstanceId());
1592     rootNode_->SetHostPageId(-1);
1593     rootNode_->SetActive(true);
1594     CalcSize idealSize { CalcLength(rootWidth_), CalcLength(rootHeight_) };
1595     MeasureProperty layoutConstraint;
1596     layoutConstraint.selfIdealSize = idealSize;
1597     layoutConstraint.maxSize = idealSize;
1598     rootNode_->UpdateLayoutConstraint(layoutConstraint);
1599     auto rootFocusHub = rootNode_->GetOrCreateFocusHub();
1600     rootFocusHub->SetFocusType(FocusType::SCOPE);
1601     rootFocusHub->SetFocusable(true);
1602     window_->SetRootFrameNode(rootNode_);
1603     rootNode_->AttachToMainTree(false, this);
1604 
1605 #ifdef ENABLE_ROSEN_BACKEND
1606     std::shared_ptr<Rosen::RSUIDirector> rsUIDirector;
1607     if (!IsJsCard()) {
1608         rsUIDirector = GetRSUIDirector();
1609         if (rsUIDirector) {
1610             RSTransactionBegin(rsUIDirector);
1611             rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
1612             RSTransactionCommit(rsUIDirector);
1613         }
1614     }
1615 #endif
1616 #ifdef WINDOW_SCENE_SUPPORTED
1617     uiExtensionManager_ = MakeRefPtr<UIExtensionManager>();
1618 #endif
1619     accessibilityManagerNG_ = MakeRefPtr<AccessibilityManagerNG>();
1620     // the subwindow for overlay not need stage
1621     stageManager_ = ViewAdvancedRegister::GetInstance()->GenerateStageManager(nullptr);
1622     if (!stageManager_) {
1623         stageManager_ = MakeRefPtr<StageManager>(nullptr);
1624     }
1625     auto getPagePathCallback = [weakFrontend = weakFrontend_](const std::string& url) -> std::string {
1626         auto frontend = weakFrontend.Upgrade();
1627         CHECK_NULL_RETURN(frontend, "");
1628         return frontend->GetPagePathByUrl(url);
1629     };
1630     stageManager_->SetGetPagePathCallback(std::move(getPagePathCallback));
1631     overlayManager_ = MakeRefPtr<OverlayManager>(rootNode_);
1632     fullScreenManager_ = MakeRefPtr<FullScreenManager>(rootNode_);
1633     selectOverlayManager_ = MakeRefPtr<SelectOverlayManager>(rootNode_);
1634     fontManager_->AddFontObserver(selectOverlayManager_);
1635     dragDropManager_ = MakeRefPtr<DragDropManager>();
1636     focusManager_ = GetOrCreateFocusManager();
1637     postEventManager_ = MakeRefPtr<PostEventManager>();
1638 }
1639 
GetAccessibilityManagerNG()1640 RefPtr<AccessibilityManagerNG> PipelineContext::GetAccessibilityManagerNG()
1641 {
1642     return accessibilityManagerNG_;
1643 }
1644 
SendEventToAccessibilityWithNode(const AccessibilityEvent & accessibilityEvent,const RefPtr<FrameNode> & node)1645 void PipelineContext::SendEventToAccessibilityWithNode(
1646     const AccessibilityEvent& accessibilityEvent, const RefPtr<FrameNode>& node)
1647 {
1648     auto accessibilityManager = GetAccessibilityManager();
1649     if (!accessibilityManager || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1650         return;
1651     }
1652     accessibilityManager->SendEventToAccessibilityWithNode(accessibilityEvent, node, Claim(this));
1653 }
1654 
GetStageManager()1655 const RefPtr<StageManager>& PipelineContext::GetStageManager()
1656 {
1657     return stageManager_;
1658 }
1659 
GetDragDropManager()1660 const RefPtr<DragDropManager>& PipelineContext::GetDragDropManager()
1661 {
1662     return dragDropManager_;
1663 }
1664 
GetFocusManager() const1665 const RefPtr<FocusManager>& PipelineContext::GetFocusManager() const
1666 {
1667     return focusManager_;
1668 }
1669 
GetOrCreateFocusManager()1670 const RefPtr<FocusManager>& PipelineContext::GetOrCreateFocusManager()
1671 {
1672     if (!focusManager_) {
1673         focusManager_ = MakeRefPtr<FocusManager>(AceType::Claim(this));
1674         RegisterFocusCallback();
1675     }
1676     return focusManager_;
1677 }
1678 
GetSelectOverlayManager()1679 const RefPtr<SelectOverlayManager>& PipelineContext::GetSelectOverlayManager()
1680 {
1681     return selectOverlayManager_;
1682 }
1683 
GetOverlayManager()1684 const RefPtr<OverlayManager>& PipelineContext::GetOverlayManager()
1685 {
1686     return overlayManager_;
1687 }
1688 
GetFullScreenManager()1689 const RefPtr<FullScreenManager>& PipelineContext::GetFullScreenManager()
1690 {
1691     return fullScreenManager_;
1692 }
1693 
OnSurfaceChanged(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1694 void PipelineContext::OnSurfaceChanged(int32_t width, int32_t height, WindowSizeChangeReason type,
1695     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1696 {
1697     ACE_SCOPED_TRACE("PipelineContext::OnSurfaceChanged");
1698     CHECK_RUN_ON(UI);
1699     width_ = width;
1700     height_ = height;
1701     if (NearEqual(rootWidth_, width) && NearEqual(rootHeight_, height) &&
1702         type == WindowSizeChangeReason::CUSTOM_ANIMATION && !isDensityChanged_) {
1703         TryCallNextFrameLayoutCallback();
1704         return;
1705     }
1706     ExecuteSurfaceChangedCallbacks(width, height, type);
1707     auto callback = [weakFrontend = weakFrontend_, width, height]() {
1708         auto frontend = weakFrontend.Upgrade();
1709         if (frontend) {
1710             frontend->OnSurfaceChanged(width, height);
1711         }
1712     };
1713     auto container = Container::Current();
1714     if (!container) {
1715         return;
1716     }
1717     if (container->IsUseStageModel()) {
1718         callback();
1719         FlushBuild();
1720     } else {
1721         taskExecutor_->PostTask(callback, TaskExecutor::TaskType::JS, "ArkUISurfaceChanged");
1722     }
1723 
1724     FlushWindowSizeChangeCallback(width, height, type);
1725     UpdateHalfFoldHoverProperty(width, height);
1726     UpdateSizeChangeReason(type, rsTransaction);
1727 
1728 #ifdef ENABLE_ROSEN_BACKEND
1729     StartWindowSizeChangeAnimate(width, height, type, rsTransaction);
1730 #else
1731     SetRootRect(width, height, 0.0);
1732 #endif
1733 }
1734 
UpdateHalfFoldHoverProperty(int32_t windowWidth,int32_t windowHeight)1735 void PipelineContext::UpdateHalfFoldHoverProperty(int32_t windowWidth, int32_t windowHeight)
1736 {
1737     isHoverModeChanged_ = false;
1738     preIsHalfFoldHoverStatus_ = isHalfFoldHoverStatus_;
1739     UpdateHalfFoldHoverStatus(windowWidth, windowHeight);
1740     if (preIsHalfFoldHoverStatus_ != isHalfFoldHoverStatus_) {
1741         isHoverModeChanged_ = true;
1742     }
1743 }
1744 
OnLayoutCompleted(const std::string & componentId)1745 void PipelineContext::OnLayoutCompleted(const std::string& componentId)
1746 {
1747     CHECK_RUN_ON(UI);
1748     auto frontend = weakFrontend_.Upgrade();
1749     if (frontend) {
1750         frontend->OnLayoutCompleted(componentId);
1751     }
1752 }
1753 
OnDrawCompleted(const std::string & componentId)1754 void PipelineContext::OnDrawCompleted(const std::string& componentId)
1755 {
1756     CHECK_RUN_ON(UI);
1757     auto frontend = weakFrontend_.Upgrade();
1758     if (frontend) {
1759         frontend->OnDrawCompleted(componentId);
1760     }
1761 }
1762 
OnDrawChildrenCompleted(const std::string & componentId)1763 void PipelineContext::OnDrawChildrenCompleted(const std::string& componentId)
1764 {
1765     CHECK_RUN_ON(UI);
1766     auto frontend = weakFrontend_.Upgrade();
1767     if (frontend) {
1768         frontend->OnDrawChildrenCompleted(componentId);
1769     }
1770 }
1771 
ExecuteSurfaceChangedCallbacks(int32_t newWidth,int32_t newHeight,WindowSizeChangeReason type)1772 void PipelineContext::ExecuteSurfaceChangedCallbacks(int32_t newWidth, int32_t newHeight, WindowSizeChangeReason type)
1773 {
1774     SurfaceChangedCallbackMap callbackMap;
1775     std::swap(callbackMap, surfaceChangedCallbackMap_);
1776     for (auto&& [id, callback] : callbackMap) {
1777         if (callback) {
1778             callback(newWidth, newHeight, rootWidth_, rootHeight_, type);
1779         }
1780     }
1781     std::swap(callbackMap, surfaceChangedCallbackMap_);
1782 }
1783 
OnSurfacePositionChanged(int32_t posX,int32_t posY)1784 void PipelineContext::OnSurfacePositionChanged(int32_t posX, int32_t posY)
1785 {
1786     for (auto&& [id, callback] : surfacePositionChangedCallbackMap_) {
1787         if (callback) {
1788             callback(posX, posY);
1789         }
1790     }
1791 }
1792 
OnFoldStatusChange(FoldStatus foldStatus)1793 void PipelineContext::OnFoldStatusChange(FoldStatus foldStatus)
1794 {
1795     for (auto&& [id, callback] : foldStatusChangedCallbackMap_) {
1796         if (callback) {
1797             callback(foldStatus);
1798         }
1799     }
1800     StartFoldStatusDelayTask(foldStatus);
1801 }
1802 
OnFoldDisplayModeChange(FoldDisplayMode foldDisplayMode)1803 void PipelineContext::OnFoldDisplayModeChange(FoldDisplayMode foldDisplayMode)
1804 {
1805     for (auto&& [id, callback] : foldDisplayModeChangedCallbackMap_) {
1806         if (callback) {
1807             callback(foldDisplayMode);
1808         }
1809     }
1810 }
1811 
OnTransformHintChanged(uint32_t transform)1812 void PipelineContext::OnTransformHintChanged(uint32_t transform)
1813 {
1814     for (auto&& [id, callback] : transformHintChangedCallbackMap_) {
1815         if (callback) {
1816             callback(transform);
1817         }
1818     }
1819     transform_ = transform;
1820 }
1821 
StartWindowSizeChangeAnimate(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1822 void PipelineContext::StartWindowSizeChangeAnimate(int32_t width, int32_t height, WindowSizeChangeReason type,
1823     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1824 {
1825     static const bool IsWindowSizeAnimationEnabled = SystemProperties::IsWindowSizeAnimationEnabled();
1826     if (!IsWindowSizeAnimationEnabled) {
1827         SetRootRect(width, height, 0.0);
1828         return;
1829     }
1830     switch (type) {
1831         case WindowSizeChangeReason::FULL_TO_SPLIT:
1832         case WindowSizeChangeReason::FULL_TO_FLOATING: {
1833             StartFullToMultWindowAnimation(width, height, type, rsTransaction);
1834             break;
1835         }
1836         case WindowSizeChangeReason::RECOVER:
1837         case WindowSizeChangeReason::MAXIMIZE: {
1838             StartWindowMaximizeAnimation(width, height, rsTransaction);
1839             break;
1840         }
1841         case WindowSizeChangeReason::MAXIMIZE_TO_SPLIT:
1842         case WindowSizeChangeReason::SPLIT_TO_MAXIMIZE: {
1843             StartSplitWindowAnimation(width, height, type, rsTransaction);
1844             break;
1845         }
1846         case WindowSizeChangeReason::MAXIMIZE_IN_IMPLICT:
1847         case WindowSizeChangeReason::RECOVER_IN_IMPLICIT: {
1848             MaximizeInImplictAnimation(width, height, type, rsTransaction);
1849             break;
1850         }
1851         case WindowSizeChangeReason::ROTATION: {
1852             safeAreaManager_->UpdateKeyboardOffset(0.0);
1853             SetRootRect(width, height, 0.0);
1854             FlushUITasks();
1855             if (textFieldManager_) {
1856                 DynamicCast<TextFieldManagerNG>(textFieldManager_)->ScrollTextFieldToSafeArea();
1857             }
1858             FlushUITasks();
1859             if (!textFieldManager_) {
1860                 break;
1861             }
1862             PostKeyboardAvoidTask();
1863             break;
1864         }
1865         case WindowSizeChangeReason::RESIZE_WITH_ANIMATION: {
1866             SetRootRect(width, height, 0.0);
1867             FlushUITasks();
1868             break;
1869         }
1870         case WindowSizeChangeReason::DRAG_START:
1871         case WindowSizeChangeReason::DRAG:
1872         case WindowSizeChangeReason::DRAG_END:
1873         case WindowSizeChangeReason::RESIZE:
1874         case WindowSizeChangeReason::UNDEFINED:
1875         default: {
1876             SetRootRect(width, height, 0.0f);
1877         }
1878     }
1879 }
1880 
PostKeyboardAvoidTask()1881 void PipelineContext::PostKeyboardAvoidTask()
1882 {
1883     auto textFieldManager = DynamicCast<TextFieldManagerNG>(textFieldManager_);
1884     CHECK_NULL_VOID(textFieldManager);
1885     if (textFieldManager->UsingCustomKeyboardAvoid()) {
1886         taskExecutor_->PostTask(
1887             [weak = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
1888                 auto manager = weak.Upgrade();
1889                 CHECK_NULL_VOID(manager);
1890                 manager->TriggerCustomKeyboardAvoid();
1891             },
1892             TaskExecutor::TaskType::UI, "ArkUICustomKeyboardAvoid");
1893         return;
1894     }
1895     auto container = Container::Current();
1896     int32_t orientation = -1;
1897     if (container) {
1898         auto displayInfo = container->GetDisplayInfo();
1899         orientation = displayInfo ? (int32_t)displayInfo->GetRotation() : -1;
1900         if (textFieldManager->GetLaterAvoid() && textFieldManager->GetLaterOrientation() != orientation) {
1901             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "orientation not match, clear laterAvoid");
1902             textFieldManager->SetLaterAvoid(false);
1903             return;
1904         }
1905     }
1906     taskExecutor_->PostTask(
1907         [weakContext = WeakClaim(this), weakManager = WeakPtr<TextFieldManagerNG>(textFieldManager), orientation] {
1908             auto manager = weakManager.Upgrade();
1909             CHECK_NULL_VOID(manager);
1910             if (!manager->GetLaterAvoid()) {
1911                 manager->SetContextTriggerAvoidTaskOrientation(orientation);
1912                 return;
1913             }
1914             auto context = weakContext.Upgrade();
1915             CHECK_NULL_VOID(context);
1916             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "after rotation set root, trigger avoid now");
1917             auto keyboardRect = manager->GetLaterAvoidKeyboardRect();
1918             auto positionY = manager->GetLaterAvoidPositionY();
1919             auto height = manager->GetLaterAvoidHeight();
1920             context->OnVirtualKeyboardAreaChange(keyboardRect, positionY, height, nullptr, true);
1921             manager->SetLaterAvoid(false);
1922         },
1923         TaskExecutor::TaskType::UI, "ArkUIVirtualKeyboardAreaChange");
1924 }
1925 
StartWindowMaximizeAnimation(int32_t width,int32_t height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1926 void PipelineContext::StartWindowMaximizeAnimation(
1927     int32_t width, int32_t height, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1928 {
1929     TAG_LOGI(AceLogTag::ACE_ANIMATION,
1930         "Root node start RECOVER/MAXIMIZE animation, width = %{public}d, height = %{public}d", width, height);
1931 #ifdef ENABLE_ROSEN_BACKEND
1932     if (rsTransaction) {
1933         FlushMessages();
1934         rsTransaction->Begin();
1935     }
1936 #endif
1937     AnimationOption option;
1938     int32_t duration = 400;
1939     MaximizeMode maximizeMode = GetWindowManager()->GetWindowMaximizeMode();
1940     bool freeMultiWindowModeEnabled = GetWindowManager()->GetFreeMultiWindowModeEnabledState();
1941     if (maximizeMode == MaximizeMode::MODE_FULL_FILL || maximizeMode == MaximizeMode::MODE_AVOID_SYSTEM_BAR ||
1942         freeMultiWindowModeEnabled) {
1943         duration = 0;
1944     }
1945     option.SetDuration(duration);
1946     auto curve = Curves::EASE_OUT;
1947     option.SetCurve(curve);
1948     auto weak = WeakClaim(this);
1949     Animate(option, curve, [width, height, weak]() {
1950         auto pipeline = weak.Upgrade();
1951         CHECK_NULL_VOID(pipeline);
1952         pipeline->SetRootRect(width, height, 0.0);
1953         pipeline->FlushUITasks();
1954     });
1955 #ifdef ENABLE_ROSEN_BACKEND
1956     if (rsTransaction) {
1957         rsTransaction->Commit();
1958     }
1959 #endif
1960 }
1961 
StartFullToMultWindowAnimation(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1962 void PipelineContext::StartFullToMultWindowAnimation(int32_t width, int32_t height, WindowSizeChangeReason type,
1963     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1964 {
1965     TAG_LOGI(AceLogTag::ACE_ANIMATION,
1966         "Root node start multiple window animation, type = %{public}d, width = %{public}d, height = %{public}d", type,
1967         width, height);
1968 #ifdef ENABLE_ROSEN_BACKEND
1969     if (rsTransaction) {
1970         FlushMessages();
1971         rsTransaction->Begin();
1972     }
1973 #endif
1974     float response = 0.5f;
1975     float dampingFraction = 1.0f;
1976     AnimationOption option;
1977     if (type == WindowSizeChangeReason::FULL_TO_FLOATING) {
1978         response = 0.45f;
1979         dampingFraction = 0.75f;
1980     }
1981     auto springMotion = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingFraction, 0);
1982     option.SetCurve(springMotion);
1983     auto weak = WeakClaim(this);
1984     Animate(option, springMotion, [width, height, weak]() {
1985         auto pipeline = weak.Upgrade();
1986         CHECK_NULL_VOID(pipeline);
1987         pipeline->SetRootRect(width, height, 0.0);
1988         pipeline->FlushUITasks();
1989     });
1990 #ifdef ENABLE_ROSEN_BACKEND
1991     if (rsTransaction) {
1992         rsTransaction->Commit();
1993     }
1994 #endif
1995 }
1996 
StartSplitWindowAnimation(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)1997 void PipelineContext::StartSplitWindowAnimation(int32_t width, int32_t height, WindowSizeChangeReason type,
1998     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
1999 {
2000     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
2001         "Root node start split window animation, type = %{public}d, width = %{public}d, height = %{public}d", type,
2002         width, height);
2003 #ifdef ENABLE_ROSEN_BACKEND
2004     if (rsTransaction) {
2005         FlushMessages();
2006         rsTransaction->Begin();
2007     }
2008 #endif
2009     auto curve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 300.0f, 33.0f);
2010     AnimationOption option;
2011     option.SetCurve(curve);
2012     Animate(option, curve, [width, height, weak = WeakClaim(this)]() {
2013         auto pipeline = weak.Upgrade();
2014         CHECK_NULL_VOID(pipeline);
2015         pipeline->SetRootRect(width, height, 0.0);
2016         pipeline->FlushUITasks();
2017     });
2018 #ifdef ENABLE_ROSEN_BACKEND
2019     if (rsTransaction) {
2020         rsTransaction->Commit();
2021     }
2022 #endif
2023 }
2024 
MaximizeInImplictAnimation(int32_t width,int32_t height,WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2025 void PipelineContext::MaximizeInImplictAnimation(int32_t width, int32_t height, WindowSizeChangeReason type,
2026     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2027 {
2028     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
2029         "Maximize window in implict animation, type = %{public}d, width = %{public}d, height = %{public}d", type,
2030         width, height);
2031 #ifdef ENABLE_ROSEN_BACKEND
2032     if (rsTransaction) {
2033         FlushMessages();
2034         rsTransaction->Begin();
2035     }
2036 #endif
2037     auto curve = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 300.0f, 33.0f);
2038     AnimationOption option;
2039     option.SetCurve(curve);
2040     Animate(option, curve, [width, height, weak = WeakClaim(this)]() {
2041         auto pipeline = weak.Upgrade();
2042         CHECK_NULL_VOID(pipeline);
2043         pipeline->SetRootRect(width, height, 0.0);
2044         pipeline->FlushUITasks();
2045     });
2046 #ifdef ENABLE_ROSEN_BACKEND
2047     if (rsTransaction) {
2048         rsTransaction->Commit();
2049     }
2050 #endif
2051 }
2052 
SetRootRect(double width,double height,double offset)2053 void PipelineContext::SetRootRect(double width, double height, double offset)
2054 {
2055     CHECK_RUN_ON(UI);
2056     UpdateRootSizeAndScale(width, height);
2057     CHECK_NULL_VOID(rootNode_);
2058     ACE_SCOPED_TRACE("SetRootRect: origin:%s,set width:%f, height:%f, offset:%f",
2059         rootNode_->GetGeometryNode()->GetFrameRect().ToString().c_str(), width, height, offset);
2060     if (Container::CurrentId() < MIN_SUBCONTAINER_ID) {
2061         ScreenSystemManager::GetInstance().SetWindowInfo(rootWidth_, density_, dipScale_);
2062         ScreenSystemManager::GetInstance().OnSurfaceChanged(width);
2063     } else {
2064         ScreenSystemManager::GetInstance().SetWindowInfo(density_, dipScale_);
2065     }
2066     SizeF sizeF { static_cast<float>(width), static_cast<float>(height) };
2067     if (rootNode_->GetGeometryNode()->GetFrameSize() != sizeF || rootNode_->IsLayoutDirtyMarked()) {
2068         CalcSize idealSize { CalcLength(width), CalcLength(height) };
2069         MeasureProperty layoutConstraint;
2070         layoutConstraint.selfIdealSize = idealSize;
2071         layoutConstraint.maxSize = idealSize;
2072         rootNode_->UpdateLayoutConstraint(layoutConstraint);
2073         // reset parentLayoutConstraint to update itself when next measure task
2074         rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
2075         rootNode_->MarkDirtyNode();
2076     }
2077     if (rootNode_->GetGeometryNode()->GetFrameOffset().GetY() != offset) {
2078         OffsetF newOffset = rootNode_->GetGeometryNode()->GetFrameOffset();
2079         newOffset.SetY(static_cast<float>(offset));
2080         rootNode_->GetGeometryNode()->SetMarginFrameOffset(newOffset);
2081         auto rootContext = rootNode_->GetRenderContext();
2082         rootContext->SyncGeometryProperties(RawPtr(rootNode_->GetGeometryNode()));
2083         RequestFrame();
2084     }
2085     if (isDensityChanged_) {
2086         rootNode_->GetGeometryNode()->ResetParentLayoutConstraint();
2087         rootNode_->MarkForceMeasure();
2088         isDensityChanged_ = false;
2089     }
2090 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
2091     // For cross-platform build, flush tasks when first resize, speed up for fisrt frame.
2092     if (window_ && rootNode_->GetRenderContext() && !NearZero(width) && !NearZero(height)) {
2093         rootNode_->GetRenderContext()->SetBounds(0.0, 0.0, width, height);
2094         window_->FlushTasks();
2095         FlushVsync(GetTimeFromExternalTimer(), 0);
2096     }
2097 #endif
2098 }
2099 
UpdateSystemSafeArea(const SafeAreaInsets & systemSafeArea,bool checkSceneBoardWindow)2100 void PipelineContext::UpdateSystemSafeArea(const SafeAreaInsets& systemSafeArea, bool checkSceneBoardWindow)
2101 {
2102     if (checkSceneBoardWindow) {
2103         safeAreaManager_->UpdateScbSystemSafeArea(systemSafeArea);
2104         return;
2105     }
2106     CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
2107     if (safeAreaManager_->UpdateSystemSafeArea(systemSafeArea)) {
2108         AnimateOnSafeAreaUpdate();
2109     }
2110 }
2111 
UpdateCutoutSafeArea(const SafeAreaInsets & cutoutSafeArea,bool checkSceneBoardWindow)2112 void PipelineContext::UpdateCutoutSafeArea(const SafeAreaInsets& cutoutSafeArea, bool checkSceneBoardWindow)
2113 {
2114     if (checkSceneBoardWindow) {
2115         safeAreaManager_->UpdateScbCutoutSafeArea(cutoutSafeArea);
2116         return;
2117     }
2118     CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
2119     if (safeAreaManager_->UpdateCutoutSafeArea(cutoutSafeArea)) {
2120         AnimateOnSafeAreaUpdate();
2121     }
2122 }
2123 
UpdateNavSafeArea(const SafeAreaInsets & navSafeArea,bool checkSceneBoardWindow)2124 void PipelineContext::UpdateNavSafeArea(const SafeAreaInsets& navSafeArea, bool checkSceneBoardWindow)
2125 {
2126     if (checkSceneBoardWindow) {
2127         safeAreaManager_->UpdateScbNavSafeArea(navSafeArea);
2128         return;
2129     }
2130     CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
2131     if (safeAreaManager_->UpdateNavSafeArea(navSafeArea)) {
2132         AnimateOnSafeAreaUpdate();
2133     }
2134 }
2135 
UpdateSystemSafeAreaWithoutAnimation(const SafeAreaInsets & systemSafeArea,bool checkSceneBoardWindow)2136 void PipelineContext::UpdateSystemSafeAreaWithoutAnimation(const SafeAreaInsets& systemSafeArea,
2137     bool checkSceneBoardWindow)
2138 {
2139     if (checkSceneBoardWindow) {
2140         safeAreaManager_->UpdateScbSystemSafeArea(systemSafeArea);
2141         return;
2142     }
2143     CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
2144     if (safeAreaManager_->UpdateSystemSafeArea(systemSafeArea)) {
2145         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_AVOID_AREA);
2146     }
2147 }
2148 
UpdateCutoutSafeAreaWithoutAnimation(const SafeAreaInsets & cutoutSafeArea,bool checkSceneBoardWindow)2149 void PipelineContext::UpdateCutoutSafeAreaWithoutAnimation(const SafeAreaInsets& cutoutSafeArea,
2150     bool checkSceneBoardWindow)
2151 {
2152     if (checkSceneBoardWindow) {
2153         safeAreaManager_->UpdateScbCutoutSafeArea(cutoutSafeArea);
2154         return;
2155     }
2156     CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
2157     if (safeAreaManager_->UpdateCutoutSafeArea(cutoutSafeArea)) {
2158         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_AVOID_AREA);
2159     }
2160 }
2161 
UpdateNavSafeAreaWithoutAnimation(const SafeAreaInsets & navSafeArea,bool checkSceneBoardWindow)2162 void PipelineContext::UpdateNavSafeAreaWithoutAnimation(const SafeAreaInsets& navSafeArea,
2163     bool checkSceneBoardWindow)
2164 {
2165     if (checkSceneBoardWindow) {
2166         safeAreaManager_->UpdateScbNavSafeArea(navSafeArea);
2167         return;
2168     }
2169     CHECK_NULL_VOID(minPlatformVersion_ >= PLATFORM_VERSION_TEN);
2170     if (safeAreaManager_->UpdateNavSafeArea(navSafeArea)) {
2171         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_AVOID_AREA);
2172     }
2173 }
2174 
CheckAndUpdateKeyboardInset(float keyboardHeight)2175 void PipelineContext::CheckAndUpdateKeyboardInset(float keyboardHeight)
2176 {
2177     safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
2178 }
2179 
UpdateOriginAvoidArea(const Rosen::AvoidArea & avoidArea,uint32_t type)2180 void PipelineContext::UpdateOriginAvoidArea(const Rosen::AvoidArea& avoidArea, uint32_t type)
2181 {
2182 #ifdef WINDOW_SCENE_SUPPORTED
2183     CHECK_NULL_VOID(uiExtensionManager_);
2184     uiExtensionManager_->TransferOriginAvoidArea(avoidArea, type);
2185 #endif
2186 }
2187 
UpdateSizeChangeReason(WindowSizeChangeReason type,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2188 void PipelineContext::UpdateSizeChangeReason(
2189     WindowSizeChangeReason type, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2190 {
2191 #ifdef WINDOW_SCENE_SUPPORTED
2192     CHECK_NULL_VOID(uiExtensionManager_);
2193     uiExtensionManager_->NotifySizeChangeReason(type, rsTransaction);
2194 #endif
2195 }
2196 
SetEnableKeyBoardAvoidMode(KeyBoardAvoidMode value)2197 void PipelineContext::SetEnableKeyBoardAvoidMode(KeyBoardAvoidMode value)
2198 {
2199     if (safeAreaManager_->SetKeyBoardAvoidMode(value)) {
2200         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
2201         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "keyboardAvoid Mode update:%{public}d", value);
2202     }
2203 }
2204 
GetEnableKeyBoardAvoidMode()2205 KeyBoardAvoidMode PipelineContext::GetEnableKeyBoardAvoidMode()
2206 {
2207     return safeAreaManager_->GetKeyBoardAvoidMode();
2208 }
2209 
IsEnableKeyBoardAvoidMode()2210 bool PipelineContext::IsEnableKeyBoardAvoidMode()
2211 {
2212     return safeAreaManager_->KeyboardSafeAreaEnabled();
2213 }
2214 
SetIgnoreViewSafeArea(bool value)2215 void PipelineContext::SetIgnoreViewSafeArea(bool value)
2216 {
2217     if (safeAreaManager_->SetIgnoreSafeArea(value)) {
2218         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
2219     }
2220 }
2221 
SetIsLayoutFullScreen(bool value)2222 void PipelineContext::SetIsLayoutFullScreen(bool value)
2223 {
2224     if (safeAreaManager_->SetIsFullScreen(value)) {
2225         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
2226     }
2227 }
2228 
SetIsNeedAvoidWindow(bool value)2229 void PipelineContext::SetIsNeedAvoidWindow(bool value)
2230 {
2231     if (safeAreaManager_->SetIsNeedAvoidWindow(value)) {
2232         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
2233     }
2234 }
2235 
GetSafeArea() const2236 PipelineBase::SafeAreaInsets PipelineContext::GetSafeArea() const
2237 {
2238     return safeAreaManager_->GetSafeArea();
2239 }
2240 
GetSafeAreaWithoutProcess() const2241 PipelineBase::SafeAreaInsets PipelineContext::GetSafeAreaWithoutProcess() const
2242 {
2243     return safeAreaManager_->GetSafeAreaWithoutProcess();
2244 }
2245 
GetPageAvoidOffset()2246 float PipelineContext::GetPageAvoidOffset()
2247 {
2248     return safeAreaManager_->GetKeyboardOffset();
2249 }
2250 
CheckNeedAvoidInSubWindow()2251 bool PipelineContext::CheckNeedAvoidInSubWindow()
2252 {
2253     CHECK_NULL_RETURN(NearZero(GetPageAvoidOffset()), true);
2254     CHECK_NULL_RETURN(safeAreaManager_->KeyboardSafeAreaEnabled(), false);
2255     auto KeyboardInsetLength = safeAreaManager_->GetKeyboardInset().Length();
2256     return GreatNotEqual(KeyboardInsetLength, 0.0f);
2257 }
2258 
SyncSafeArea(SafeAreaSyncType syncType)2259 void PipelineContext::SyncSafeArea(SafeAreaSyncType syncType)
2260 {
2261     bool keyboardSafeArea =
2262         syncType == SafeAreaSyncType::SYNC_TYPE_KEYBOARD && !safeAreaManager_->KeyboardSafeAreaEnabled();
2263     CHECK_NULL_VOID(stageManager_);
2264     stageManager_->SyncPageSafeArea(keyboardSafeArea);
2265     SubwindowManager::GetInstance()->MarkDirtyDialogSafeArea();
2266     if (overlayManager_) {
2267         overlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
2268     }
2269     if (selectOverlayManager_) {
2270         selectOverlayManager_->MarkDirty(PROPERTY_UPDATE_MEASURE);
2271     }
2272     auto&& restoreNodes = safeAreaManager_->GetGeoRestoreNodes();
2273     for (auto&& wk : restoreNodes) {
2274         auto node = wk.Upgrade();
2275         if (node) {
2276             bool needMeasure = (syncType == SafeAreaSyncType::SYNC_TYPE_KEYBOARD && node->SelfExpansiveToKeyboard()) ||
2277                                (syncType == SafeAreaSyncType::SYNC_TYPE_AVOID_AREA ||
2278                                    syncType == SafeAreaSyncType::SYNC_TYPE_WINDOW_IGNORE);
2279             node->MarkDirtyNode(needMeasure ? PROPERTY_UPDATE_MEASURE : PROPERTY_UPDATE_LAYOUT);
2280         }
2281     }
2282 }
2283 
DetachNode(RefPtr<UINode> uiNode)2284 void PipelineContext::DetachNode(RefPtr<UINode> uiNode)
2285 {
2286     auto frameNode = DynamicCast<FrameNode>(uiNode);
2287     attachedNodeSet_.erase(WeakPtr(uiNode));
2288     CHECK_NULL_VOID(frameNode);
2289 
2290     RemoveStoredNode(frameNode->GetRestoreId());
2291     if (frameNode->IsPrivacySensitive()) {
2292         auto privacyManager = GetPrivacySensitiveManager();
2293         privacyManager->RemoveNode(AceType::WeakClaim(AceType::RawPtr(frameNode)));
2294     }
2295 
2296     if (!CheckThreadSafe()) {
2297         LOGW("DetachNode doesn't run on UI thread!");
2298     }
2299     dirtyPropertyNodes_.erase(frameNode);
2300     needRenderNode_.erase(WeakPtr<FrameNode>(frameNode));
2301 
2302     if (dirtyFocusNode_ == frameNode) {
2303         dirtyFocusNode_.Reset();
2304     }
2305 
2306     if (dirtyFocusScope_ == frameNode) {
2307         dirtyFocusScope_.Reset();
2308     }
2309 
2310     if (dirtyRequestFocusNode_ == frameNode) {
2311         dirtyRequestFocusNode_.Reset();
2312     }
2313 
2314     if (activeNode_ == frameNode) {
2315         activeNode_.Reset();
2316     }
2317 
2318     if (focusNode_ == frameNode) {
2319         focusNode_.Reset();
2320     }
2321 }
2322 
OnVirtualKeyboardHeightChange(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,const float safeHeight,const bool supportAvoidance,bool forceChange)2323 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight,
2324     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, const float safeHeight, const bool supportAvoidance,
2325     bool forceChange)
2326 {
2327     CHECK_RUN_ON(UI);
2328     // prevent repeated trigger with same keyboardHeight
2329     if (!forceChange && NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length())) {
2330         return;
2331     }
2332 
2333     ACE_FUNCTION_TRACE();
2334 #ifdef ENABLE_ROSEN_BACKEND
2335     if (rsTransaction) {
2336         FlushMessages();
2337         rsTransaction->Begin();
2338     }
2339 #endif
2340 
2341     if (supportAvoidance) {
2342         AvoidanceLogic(keyboardHeight, rsTransaction, safeHeight, supportAvoidance);
2343     } else {
2344         OriginalAvoidanceLogic(keyboardHeight, rsTransaction);
2345     }
2346 
2347 #ifdef ENABLE_ROSEN_BACKEND
2348     if (rsTransaction) {
2349         rsTransaction->Commit();
2350     }
2351 #endif
2352 }
2353 
AvoidanceLogic(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,float safeHeight,const bool supportAvoidance)2354 void PipelineContext::AvoidanceLogic(float keyboardHeight, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction,
2355     float safeHeight, const bool supportAvoidance)
2356 {
2357     auto func = [this, keyboardHeight, safeHeight]() mutable {
2358         safeAreaManager_->UpdateKeyboardSafeArea(static_cast<uint32_t>(keyboardHeight));
2359         keyboardHeight += safeAreaManager_->GetSafeHeight();
2360         float positionY = 0.0f;
2361         auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2362         float keyboardOffset = manager ? manager->GetClickPositionOffset() : safeAreaManager_->GetKeyboardOffset();
2363         if (manager) {
2364             positionY = manager->GetIfFocusTextFieldIsInline() ?
2365                 static_cast<float>(manager->GetClickPosition().GetY()) - keyboardOffset :
2366                 manager->GetFocusedNodeCaretRect().Top() - safeAreaManager_->GetKeyboardOffset();
2367         }
2368         auto bottomLen = safeAreaManager_->GetNavSafeArea().bottom_.IsValid() ?
2369             safeAreaManager_->GetNavSafeArea().bottom_.Length() : 0;
2370         if (manager->IsScrollableChild() && rootHeight_ - positionY - safeHeight - bottomLen < 0) {
2371             safeHeight = rootHeight_ - positionY - bottomLen;
2372         }
2373         if (NearZero(keyboardHeight) || LessOrEqual(positionY + safeHeight, rootHeight_ - keyboardHeight)) {
2374             safeAreaManager_->UpdateKeyboardOffset(0.0f);
2375         } else if (positionY + safeHeight > rootHeight_ - keyboardHeight) {
2376             safeAreaManager_->UpdateKeyboardOffset(-(positionY - rootHeight_ + keyboardHeight)- safeHeight);
2377         } else {
2378             safeAreaManager_->UpdateKeyboardOffset(0.0f);
2379         }
2380         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
2381         CHECK_NULL_VOID(manager);
2382         manager->AvoidKeyBoardInNavigation();
2383         // layout before scrolling textfield to safeArea, because of getting correct position
2384         FlushUITasks();
2385         bool scrollResult = manager->ScrollTextFieldToSafeArea();
2386         if (scrollResult) {
2387             FlushUITasks();
2388         }
2389         MarkDirtyOverlay();
2390         SubwindowManager::GetInstance()->FlushSubWindowUITasks(Container::CurrentId());
2391 
2392         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "AvoidanceLogic keyboardHeight: %{public}f, positionY: %{public}f, "
2393             "safeHeight: %{public}f, rootHeight_ %{public}f final calculate keyboard offset is %{public}f",
2394             keyboardHeight, positionY, safeHeight, rootHeight_, safeAreaManager_->GetKeyboardOffset());
2395     };
2396     FlushUITasks();
2397     DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
2398 }
2399 
OriginalAvoidanceLogic(float keyboardHeight,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction)2400 void PipelineContext::OriginalAvoidanceLogic(
2401     float keyboardHeight, const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
2402 {
2403     auto func = [this, keyboardHeight, id = instanceId_]() mutable {
2404         ContainerScope scope(id);
2405         safeAreaManager_->UpdateKeyboardSafeArea(static_cast<uint32_t>(keyboardHeight));
2406         if (keyboardHeight > 0) {
2407             // add height of navigation bar
2408             keyboardHeight += safeAreaManager_->GetSystemSafeArea().bottom_.Length();
2409         }
2410         auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2411         float positionY = manager ? static_cast<float>(manager->GetClickPosition().GetY()) : 0.0f;
2412         float height = manager ? manager->GetHeight() : 0.0f;
2413         SizeF rootSize { static_cast<float>(rootWidth_), static_cast<float>(rootHeight_) };
2414         float keyboardOffset = manager ? manager->GetClickPositionOffset() : safeAreaManager_->GetKeyboardOffset();
2415         float positionYWithOffset = positionY - keyboardOffset;
2416         float offsetFix = (rootSize.Height() - positionYWithOffset) > 100.0f
2417                               ? keyboardHeight - (rootSize.Height() - positionYWithOffset) / 2.0f
2418                               : keyboardHeight;
2419 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
2420         if (offsetFix > 0.0f && positionYWithOffset < offsetFix) {
2421             offsetFix = keyboardHeight - (rootSize.Height() - positionYWithOffset - height);
2422         }
2423 #endif
2424         if (NearZero(keyboardHeight)) {
2425             safeAreaManager_->UpdateKeyboardOffset(0.0f);
2426         } else if (LessOrEqual(rootSize.Height() - positionYWithOffset - height, height) &&
2427                    LessOrEqual(rootSize.Height() - positionYWithOffset, keyboardHeight)) {
2428             safeAreaManager_->UpdateKeyboardOffset(-keyboardHeight);
2429         } else if (positionYWithOffset + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
2430             safeAreaManager_->UpdateKeyboardOffset(-offsetFix);
2431         } else if ((positionYWithOffset + height > rootSize.Height() - keyboardHeight &&
2432                        positionYWithOffset < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
2433                    NearZero(rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
2434             safeAreaManager_->UpdateKeyboardOffset(-height - offsetFix / 2.0f);
2435         } else {
2436             safeAreaManager_->UpdateKeyboardOffset(0.0f);
2437         }
2438         SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
2439         CHECK_NULL_VOID(manager);
2440         manager->AvoidKeyBoardInNavigation();
2441         // layout before scrolling textfield to safeArea, because of getting correct position
2442         FlushUITasks();
2443         bool scrollResult = manager->ScrollTextFieldToSafeArea();
2444         if (scrollResult) {
2445             FlushUITasks();
2446         }
2447         MarkDirtyOverlay();
2448         SubwindowManager::GetInstance()->FlushSubWindowUITasks(Container::CurrentId());
2449     };
2450     FlushUITasks();
2451     DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
2452 }
2453 
OnVirtualKeyboardHeightChange(float keyboardHeight,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)2454 void PipelineContext::OnVirtualKeyboardHeightChange(float keyboardHeight, double positionY, double height,
2455     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
2456 {
2457     CHECK_RUN_ON(UI);
2458     // prevent repeated trigger with same keyboardHeight
2459     CHECK_NULL_VOID(safeAreaManager_);
2460     if (keyboardHeight >= rootHeight_) {
2461         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Keyboard higher than whole rootrect, no need to avoid");
2462         return;
2463     }
2464 
2465     if (UsingCaretAvoidMode()) {
2466         OnCaretPositionChangeOrKeyboardHeightChange(keyboardHeight,
2467             positionY, height, rsTransaction, forceChange);
2468         return;
2469     }
2470 
2471     auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2472     CHECK_NULL_VOID(manager);
2473     if (!forceChange && NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length()) &&
2474         prevKeyboardAvoidMode_ == safeAreaManager_->GetKeyBoardAvoidMode() && manager->PrevHasTextFieldPattern()) {
2475         safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
2476         TAG_LOGD(
2477             AceLogTag::ACE_KEYBOARD, "KeyboardHeight as same as last time, don't need to calculate keyboardOffset");
2478         return;
2479     }
2480 
2481     if (!forceChange && (NearEqual(keyboardHeight + 1, safeAreaManager_->GetKeyboardInset().Length()) ||
2482         NearEqual(keyboardHeight - 1, safeAreaManager_->GetKeyboardInset().Length())) &&
2483         prevKeyboardAvoidMode_ == safeAreaManager_->GetKeyBoardAvoidMode() && manager->PrevHasTextFieldPattern()) {
2484         TAG_LOGI(
2485             AceLogTag::ACE_KEYBOARD, "Ignore ileagal keyboard height change");
2486         return;
2487     }
2488 
2489     if (manager->UsingCustomKeyboardAvoid()) {
2490         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Using Custom Avoid Instead");
2491         return;
2492     }
2493 
2494     manager->UpdatePrevHasTextFieldPattern();
2495     prevKeyboardAvoidMode_ = safeAreaManager_->GetKeyBoardAvoidMode();
2496 
2497     ACE_FUNCTION_TRACE();
2498 #ifdef ENABLE_ROSEN_BACKEND
2499     if (rsTransaction) {
2500         FlushMessages();
2501         rsTransaction->Begin();
2502     }
2503 #endif
2504 
2505     auto weak = WeakClaim(this);
2506     auto func = [weak, keyboardHeight, positionY, height, manager]() mutable {
2507         auto context = weak.Upgrade();
2508         CHECK_NULL_VOID(context);
2509         context->SetIsLayouting(false);
2510         context->safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
2511         if (keyboardHeight > 0) {
2512             // add height of navigation bar
2513             keyboardHeight += context->safeAreaManager_->GetSystemSafeArea().bottom_.Length();
2514         }
2515 
2516         SizeF rootSize { static_cast<float>(context->rootWidth_), static_cast<float>(context->rootHeight_) };
2517 
2518         TAG_LOGI(AceLogTag::ACE_KEYBOARD,
2519             "origin positionY: %{public}f, height %{public}f", positionY, height);
2520 
2521         float keyboardOffset = manager ? manager->GetClickPositionOffset() :
2522             context->safeAreaManager_->GetKeyboardOffset();
2523         float currentPos = manager->GetClickPosition().GetY() - context->GetRootRect().GetOffset().GetY() -
2524             keyboardOffset;
2525 
2526         auto onFocusField = manager->GetOnFocusTextField().Upgrade();
2527         float adjust = 0.0f;
2528         if (onFocusField && onFocusField->GetHost() && onFocusField->GetHost()->GetGeometryNode()) {
2529             auto adjustRect = onFocusField->GetHost()->GetGeometryNode()->GetParentAdjust();
2530             adjust = adjustRect.Top();
2531         }
2532         currentPos += adjust;
2533 
2534         if (!onFocusField) {
2535             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "use origin arg from the window");
2536         } else if (manager->GetIfFocusTextFieldIsInline()) {
2537             manager->GetInlineTextFieldAvoidPositionYAndHeight(positionY, height);
2538             positionY -= keyboardOffset;
2539         } else if (!NearEqual(positionY, currentPos) && !context->IsEnableKeyBoardAvoidMode()) {
2540             positionY = currentPos;
2541             height = manager->GetHeight();
2542         }
2543 
2544         if (rootSize.Height() - positionY - height < 0) {
2545             height = rootSize.Height() - positionY;
2546         }
2547         auto lastKeyboardOffset = context->safeAreaManager_->GetKeyboardOffset();
2548         float newKeyboardOffset = context->CalcNewKeyboardOffset(keyboardHeight,
2549             positionY, height, rootSize, onFocusField && manager->GetIfFocusTextFieldIsInline());
2550         newKeyboardOffset = round(newKeyboardOffset);
2551         if (NearZero(keyboardHeight) || LessOrEqual(newKeyboardOffset, lastKeyboardOffset) ||
2552             manager->GetOnFocusTextFieldId() == manager->GetLastAvoidFieldId()) {
2553             context->safeAreaManager_->UpdateKeyboardOffset(newKeyboardOffset);
2554         } else {
2555             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Different field, Calculated offfset %{public}f is smaller than current"
2556                 "keyboardOffset, so keep current keyboardOffset", newKeyboardOffset);
2557         }
2558         manager->SetLastAvoidFieldId(manager->GetOnFocusTextFieldId());
2559 
2560         TAG_LOGI(AceLogTag::ACE_KEYBOARD,
2561             "keyboardHeight: %{public}f, positionY: %{public}f, textHeight: %{public}f, "
2562             "rootSize.Height() %{public}f adjust: %{public}f final calculate keyboard offset is %{public}f",
2563             keyboardHeight, positionY, height, rootSize.Height(), adjust,
2564             context->safeAreaManager_->GetKeyboardOffset());
2565         context->SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
2566         manager->AvoidKeyBoardInNavigation();
2567         // layout before scrolling textfield to safeArea, because of getting correct position
2568         context->FlushUITasks();
2569         bool scrollResult = manager->ScrollTextFieldToSafeArea();
2570         if (scrollResult) {
2571             context->FlushUITasks();
2572         }
2573         context->MarkDirtyOverlay();
2574         SubwindowManager::GetInstance()->FlushSubWindowUITasks(Container::CurrentId());
2575     };
2576     FlushUITasks();
2577     FlushDirtyPropertyNodesWhenExist();
2578     SetIsLayouting(true);
2579     DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
2580 
2581 #ifdef ENABLE_ROSEN_BACKEND
2582     if (rsTransaction) {
2583         rsTransaction->Commit();
2584     }
2585 #endif
2586 }
2587 
MarkDirtyOverlay()2588 void PipelineContext::MarkDirtyOverlay()
2589 {
2590     CHECK_NULL_VOID(rootNode_);
2591     auto childNodes = rootNode_->GetChildren();
2592     for (auto child: childNodes) {
2593         if (child && child->GetTag() == V2::POPUP_ETS_TAG) {
2594             child->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2595         }
2596     }
2597 }
2598 
FlushDirtyPropertyNodesWhenExist()2599 void PipelineContext::FlushDirtyPropertyNodesWhenExist()
2600 {
2601     if ((!IsDirtyLayoutNodesEmpty() || !dirtyPropertyNodes_.empty()) && !IsLayouting()) {
2602         FlushUITasks();
2603     }
2604 }
2605 
UsingCaretAvoidMode()2606 bool PipelineContext::UsingCaretAvoidMode()
2607 {
2608     CHECK_NULL_RETURN(safeAreaManager_, false);
2609     return safeAreaManager_->GetKeyBoardAvoidMode() == KeyBoardAvoidMode::OFFSET_WITH_CARET ||
2610         safeAreaManager_->GetKeyBoardAvoidMode() == KeyBoardAvoidMode::RESIZE_WITH_CARET;
2611 }
2612 
OnCaretPositionChangeOrKeyboardHeightChange(float keyboardHeight,double positionY,double height,const std::shared_ptr<Rosen::RSTransaction> & rsTransaction,bool forceChange)2613 void PipelineContext::OnCaretPositionChangeOrKeyboardHeightChange(
2614     float keyboardHeight, double positionY, double height,
2615     const std::shared_ptr<Rosen::RSTransaction>& rsTransaction, bool forceChange)
2616 {
2617     CHECK_RUN_ON(UI);
2618     CHECK_NULL_VOID(safeAreaManager_);
2619     auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2620     CHECK_NULL_VOID(manager);
2621     if (manager->UsingCustomKeyboardAvoid()) {
2622         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Using Custom Avoid Instead");
2623         return;
2624     }
2625     manager->UpdatePrevHasTextFieldPattern();
2626     prevKeyboardAvoidMode_ = safeAreaManager_->GetKeyBoardAvoidMode();
2627     ACE_FUNCTION_TRACE();
2628 #ifdef ENABLE_ROSEN_BACKEND
2629     if (rsTransaction) {
2630         FlushMessages();
2631         rsTransaction->Begin();
2632     }
2633 #endif
2634     bool keyboardHeightChanged = NearEqual(keyboardHeight, safeAreaManager_->GetKeyboardInset().Length());
2635     auto weak = WeakClaim(this);
2636     auto func = [weak, keyboardHeight, positionY, height, keyboardHeightChanged]() mutable {
2637         auto context = weak.Upgrade();
2638         CHECK_NULL_VOID(context);
2639         context->DoKeyboardAvoidFunc(keyboardHeight, positionY, height, keyboardHeightChanged);
2640         context->MarkDirtyOverlay();
2641         SubwindowManager::GetInstance()->FlushSubWindowUITasks(Container::CurrentId());
2642     };
2643     FlushUITasks();
2644     SetIsLayouting(true);
2645     DoKeyboardAvoidAnimate(keyboardAnimationConfig_, keyboardHeight, func);
2646 
2647 #ifdef ENABLE_ROSEN_BACKEND
2648     if (rsTransaction) {
2649         rsTransaction->Commit();
2650     }
2651 #endif
2652 }
2653 
DoKeyboardAvoidFunc(float keyboardHeight,double positionY,double height,bool keyboardHeightChanged)2654 void PipelineContext::DoKeyboardAvoidFunc(float keyboardHeight, double positionY, double height,
2655     bool keyboardHeightChanged)
2656 {
2657     CHECK_NULL_VOID(safeAreaManager_);
2658     auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2659     CHECK_NULL_VOID(manager);
2660     SetIsLayouting(false);
2661     safeAreaManager_->UpdateKeyboardSafeArea(keyboardHeight);
2662     if (keyboardHeight > 0) {
2663         // add height of navigation bar
2664         keyboardHeight += safeAreaManager_->GetSystemSafeArea().bottom_.Length();
2665     }
2666     SizeF rootSize { static_cast<float>(rootWidth_), static_cast<float>(rootHeight_) };
2667     TAG_LOGI(AceLogTag::ACE_KEYBOARD, "origin positionY: %{public}f, height %{public}f", positionY, height);
2668     float caretPos = manager->GetFocusedNodeCaretRect().Top() - GetRootRect().GetOffset().GetY() -
2669         GetSafeAreaManager()->GetKeyboardOffset(true);
2670     auto onFocusField = manager->GetOnFocusTextField().Upgrade();
2671     float adjust = 0.0f;
2672     if (onFocusField && onFocusField->GetHost() && onFocusField->GetHost()->GetGeometryNode()) {
2673         adjust = onFocusField->GetHost()->GetGeometryNode()->GetParentAdjust().Top();
2674         positionY = caretPos;
2675         height = manager->GetHeight();
2676     }
2677     positionY += adjust;
2678     if (rootSize.Height() - positionY - height < 0 && manager->IsScrollableChild()) {
2679         height = rootSize.Height() - positionY;
2680     }
2681     auto lastKeyboardOffset = safeAreaManager_->GetKeyboardOffset(true);
2682     auto newKeyboardOffset = CalcNewKeyboardOffset(keyboardHeight, positionY, height, rootSize);
2683     if (NearZero(keyboardHeight) || LessOrEqual(newKeyboardOffset, lastKeyboardOffset) ||
2684         (manager->GetOnFocusTextFieldId() == manager->GetLastAvoidFieldId() && !keyboardHeightChanged)) {
2685         safeAreaManager_->UpdateKeyboardOffset(newKeyboardOffset);
2686     } else {
2687         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "calc offset %{public}f is smaller, keep current", newKeyboardOffset);
2688         manager->SetLastAvoidFieldId(manager->GetOnFocusTextFieldId());
2689         return;
2690     }
2691     manager->SetLastAvoidFieldId(manager->GetOnFocusTextFieldId());
2692     TAG_LOGI(AceLogTag::ACE_KEYBOARD,
2693         "keyboardHeight: %{public}f, caretPos: %{public}f, caretHeight: %{public}f, "
2694         "rootSize.Height() %{public}f adjust: %{public}f lastOffset: %{public}f, "
2695         "final calculate keyboard offset is %{public}f",
2696         keyboardHeight, positionY, height, rootSize.Height(), adjust, lastKeyboardOffset,
2697         safeAreaManager_->GetKeyboardOffset());
2698     SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_KEYBOARD);
2699     manager->AvoidKeyBoardInNavigation();
2700     // layout before scrolling textfield to safeArea, because of getting correct position
2701     FlushUITasks();
2702     bool scrollResult = manager->ScrollTextFieldToSafeArea();
2703     if (scrollResult) {
2704         FlushUITasks();
2705     }
2706 }
2707 
CalcNewKeyboardOffset(float keyboardHeight,float positionY,float height,SizeF & rootSize,bool isInline)2708 float  PipelineContext::CalcNewKeyboardOffset(float keyboardHeight, float positionY,
2709     float height, SizeF& rootSize, bool isInline)
2710 {
2711     auto newKeyboardOffset = CalcAvoidOffset(keyboardHeight, positionY, height, rootSize);
2712     CHECK_NULL_RETURN(!isInline, newKeyboardOffset);
2713     CHECK_NULL_RETURN(safeAreaManager_, newKeyboardOffset);
2714     auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2715     CHECK_NULL_RETURN(manager, newKeyboardOffset);
2716     auto onFocusField = manager->GetOnFocusTextField().Upgrade();
2717     CHECK_NULL_RETURN(onFocusField, newKeyboardOffset);
2718     auto host = onFocusField->GetHost();
2719     CHECK_NULL_RETURN(host, newKeyboardOffset);
2720     auto geometryNode = host->GetGeometryNode();
2721     CHECK_NULL_RETURN(geometryNode, newKeyboardOffset);
2722     auto paintOffset = host->GetPaintRectOffset(false, true);
2723     auto frameSize = geometryNode->GetFrameSize();
2724     auto offset = CalcAvoidOffset(keyboardHeight, paintOffset.GetY() - safeAreaManager_->GetKeyboardOffset(true),
2725         frameSize.Height() + CARET_AVOID_OFFSET.ConvertToPx(), rootSize);
2726     return std::max(offset, newKeyboardOffset);
2727 }
2728 
CalcAvoidOffset(float keyboardHeight,float positionY,float height,SizeF rootSize)2729 float PipelineContext::CalcAvoidOffset(float keyboardHeight, float positionY,
2730     float height, SizeF rootSize)
2731 {
2732     float offsetFix = (rootSize.Height() - positionY - height) < keyboardHeight
2733         ? keyboardHeight - (rootSize.Height() - positionY - height)
2734         : keyboardHeight;
2735     if (NearZero(keyboardHeight)) {
2736         return 0.0f;
2737     }
2738     if (positionY + height > (rootSize.Height() - keyboardHeight) && offsetFix > 0.0f) {
2739         return -offsetFix;
2740     }
2741     if (LessOrEqual(rootSize.Height() - positionY - height, height) &&
2742         LessOrEqual(rootSize.Height() - positionY, keyboardHeight)) {
2743         return -keyboardHeight;
2744     }
2745     if ((positionY + height > rootSize.Height() - keyboardHeight &&
2746         positionY < rootSize.Height() - keyboardHeight && height < keyboardHeight / 2.0f) &&
2747         NearZero(rootNode_->GetGeometryNode()->GetFrameOffset().GetY())) {
2748         return -height - offsetFix / 2.0f;
2749     }
2750     return 0.0f;
2751 }
2752 
OnBackPressed()2753 bool PipelineContext::OnBackPressed()
2754 {
2755     CHECK_RUN_ON(PLATFORM);
2756     auto frontend = weakFrontend_.Upgrade();
2757     if (!frontend) {
2758         // return back.
2759         return false;
2760     }
2761 
2762     auto deviceType = SystemProperties::GetDeviceType();
2763     if ((deviceType == DeviceType::WEARABLE || deviceType == DeviceType::WATCH) && !enableSwipeBack_) {
2764         LOGW("disableSwipeBack set in wearable device, will NOT consume this back-press event");
2765         return true;
2766     }
2767 
2768     // If the tag of the last child of the rootnode is video, exit full screen.
2769     if (fullScreenManager_->OnBackPressed()) {
2770         LOGI("fullscreen component: video or web consumed backpressed event");
2771         return true;
2772     }
2773 
2774     // if has sharedTransition, back press will stop the sharedTransition
2775     if (sharedTransitionManager_ && sharedTransitionManager_->OnBackPressed()) {
2776         LOGI("sharedTransition consumed backpressed event");
2777         return true;
2778     }
2779 
2780     // if has popup, back press would hide popup and not trigger page back
2781     auto textfieldMgr = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2782     if (textfieldMgr) {
2783         auto lastRequestKeyboardNodeId = textfieldMgr->GetLastRequestKeyboardId();
2784         auto lastRequestKeyboardNode = DynamicCast<FrameNode>(
2785             ElementRegister::GetInstance()->GetUINodeById(lastRequestKeyboardNodeId));
2786         auto hasContainerModal = windowModal_ == WindowModal::CONTAINER_MODAL;
2787         if (lastRequestKeyboardNode && (lastRequestKeyboardNode->GetPageId() == -1 || (hasContainerModal &&
2788             lastRequestKeyboardNode->GetPageId() == 0)) && textfieldMgr->OnBackPressed()) {
2789             LOGI("textfield consumed backpressed event");
2790             return true;
2791         }
2792     }
2793     auto hasOverlay = false;
2794     taskExecutor_->PostSyncTask(
2795         [weakOverlay = AceType::WeakClaim(AceType::RawPtr(overlayManager_)),
2796             weakSelectOverlay = AceType::WeakClaim(AceType::RawPtr(selectOverlayManager_)), &hasOverlay]() {
2797             // Destroy behaviour of Select Overlay shouble be adjusted.
2798             auto overlay = weakOverlay.Upgrade();
2799             CHECK_NULL_VOID(overlay);
2800             auto selectOverlay = weakSelectOverlay.Upgrade();
2801             CHECK_NULL_VOID(selectOverlay);
2802             hasOverlay = selectOverlay->ResetSelectionAndDestroySelectOverlay(true);
2803             hasOverlay |= overlay->RemoveOverlay(true);
2804         },
2805         TaskExecutor::TaskType::UI, "ArkUIBackPressedRemoveOverlay");
2806     if (hasOverlay) {
2807         LOGI("Overlay consumed backpressed event");
2808         return true;
2809     }
2810 
2811     auto textfieldManager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
2812     if (textfieldManager && textfieldManager->OnBackPressed()) {
2813         LOGI("textfield consumed backpressed event");
2814         return true;
2815     }
2816 
2817     auto result = false;
2818     taskExecutor_->PostSyncTask(
2819         [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), stageManager = stageManager_, &result]() {
2820             auto frontend = weakFrontend.Upgrade();
2821             if (!frontend) {
2822                 result = false;
2823                 return;
2824             }
2825             auto context = weakPipelineContext.Upgrade();
2826             if (!context) {
2827                 result = false;
2828                 return;
2829             }
2830             CHECK_NULL_VOID(stageManager);
2831             auto lastPage = stageManager->GetLastPage();
2832             CHECK_NULL_VOID(lastPage);
2833             bool isEntry = false;
2834             auto pagePattern = lastPage->GetPattern<NG::PagePattern>();
2835             if (pagePattern) {
2836                 isEntry = pagePattern->IsNeedCallbackBackPressed();
2837             }
2838             auto navigationGroupNode =
2839                 AceType::DynamicCast<NavigationGroupNode>(context->FindNavigationNodeToHandleBack(lastPage, isEntry));
2840             if (navigationGroupNode) {
2841                 result = true;
2842             }
2843         },
2844         TaskExecutor::TaskType::UI, "ArkUIBackPressedFindNavigationGroup");
2845 
2846     if (result) {
2847         // user accept
2848         LOGI("Navigation consumed backpressed event");
2849         return true;
2850     }
2851 
2852     taskExecutor_->PostSyncTask(
2853         [weakFrontend = weakFrontend_, weakPipelineContext = WeakClaim(this), &result]() {
2854             auto frontend = weakFrontend.Upgrade();
2855             if (!frontend) {
2856                 result = false;
2857                 return;
2858             }
2859             result = frontend->OnBackPressed();
2860         },
2861         TaskExecutor::TaskType::JS, "ArkUIBackPressed");
2862 
2863     if (result) {
2864         // user accept
2865         LOGI("router consumed backpressed event");
2866         return true;
2867     }
2868 
2869     taskExecutor_->PostSyncTask(
2870         [weakPipelineContext = WeakClaim(this), &result]() {
2871             auto context = weakPipelineContext.Upgrade();
2872             CHECK_NULL_VOID(context);
2873             auto container = Container::Current();
2874             CHECK_NULL_VOID(container);
2875             auto appBar = container->GetAppBar();
2876             CHECK_NULL_VOID(appBar);
2877             auto atomicServicePattern = appBar->GetAtomicServicePattern();
2878             CHECK_NULL_VOID(atomicServicePattern);
2879             result = atomicServicePattern->OnBackPressedCallback();
2880         },
2881         TaskExecutor::TaskType::UI, "ArkUIBackPressedAppBar");
2882 
2883     if (result) {
2884         LOGI("appbar consumed backpressed event");
2885         return true;
2886     }
2887     return false;
2888 }
2889 
FindNavigationNodeToHandleBack(const RefPtr<UINode> & node,bool & isEntry)2890 RefPtr<FrameNode> PipelineContext::FindNavigationNodeToHandleBack(const RefPtr<UINode>& node, bool& isEntry)
2891 {
2892     CHECK_NULL_RETURN(node, nullptr);
2893     const auto& children = node->GetChildren();
2894     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
2895         auto& child = *iter;
2896         auto childNode = AceType::DynamicCast<FrameNode>(child);
2897         if (childNode && childNode->GetLayoutProperty()) {
2898             auto property = childNode->GetLayoutProperty();
2899             if (property->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE ||
2900                 !childNode->IsActive()) {
2901                 continue;
2902             }
2903         }
2904         if (childNode && childNode->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
2905             auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(childNode);
2906             auto topChild = navigationGroupNode->GetTopDestination();
2907             // find navigation from top destination
2908             auto targetNodeFromDestination = FindNavigationNodeToHandleBack(topChild, isEntry);
2909             if (targetNodeFromDestination) {
2910                 return targetNodeFromDestination;
2911             }
2912             if (isEntry) {
2913                 return nullptr;
2914             }
2915             targetNodeFromDestination = childNode;
2916             auto targetNavigation = AceType::DynamicCast<NavigationGroupNode>(targetNodeFromDestination);
2917             // check if the destination responds
2918             if (targetNavigation && targetNavigation->CheckCanHandleBack(isEntry)) {
2919                 return targetNavigation;
2920             }
2921             if (isEntry) {
2922                 return nullptr;
2923             }
2924             // if the destination does not responds, find navigation from navbar or homeDestination
2925             auto navBarOrHomeDestNode =
2926                 AceType::DynamicCast<NavDestinationNodeBase>(navigationGroupNode->GetNavBarOrHomeDestinationNode());
2927             auto navigationLayoutProperty = navigationGroupNode->GetLayoutProperty<NavigationLayoutProperty>();
2928             CHECK_NULL_RETURN(navigationLayoutProperty, nullptr);
2929             if (navigationLayoutProperty->GetHideNavBarValue(false)) {
2930                 return nullptr;
2931             }
2932             auto targetNodeFromNavbarOrHomeDest = FindNavigationNodeToHandleBack(navBarOrHomeDestNode, isEntry);
2933             if (targetNodeFromNavbarOrHomeDest) {
2934                 return targetNodeFromNavbarOrHomeDest;
2935             }
2936             return nullptr;
2937         }
2938         auto target = FindNavigationNodeToHandleBack(child, isEntry);
2939         if (target) {
2940             return target;
2941         }
2942         if (isEntry) {
2943             return nullptr;
2944         }
2945     }
2946     return nullptr;
2947 }
2948 
SetIsFocusActive(bool isFocusActive,FocusActiveReason reason,bool autoFocusInactive)2949 bool PipelineContext::SetIsFocusActive(bool isFocusActive, FocusActiveReason reason, bool autoFocusInactive)
2950 {
2951     auto focusManager = GetOrCreateFocusManager();
2952     CHECK_NULL_RETURN(focusManager, false);
2953     return focusManager->SetIsFocusActive(isFocusActive, reason, autoFocusInactive);
2954 }
2955 
OnTouchEvent(const TouchEvent & point,bool isSubPipe)2956 void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe)
2957 {
2958     OnTouchEvent(point, rootNode_, isSubPipe);
2959 }
2960 
OnMouseEvent(const MouseEvent & event)2961 void PipelineContext::OnMouseEvent(const MouseEvent& event)
2962 {
2963     OnMouseEvent(event, rootNode_);
2964 }
2965 
OnAxisEvent(const AxisEvent & event)2966 void PipelineContext::OnAxisEvent(const AxisEvent& event)
2967 {
2968     OnAxisEvent(event, rootNode_);
2969 }
2970 
OnTouchEvent(const TouchEvent & point,const RefPtr<FrameNode> & node,bool isSubPipe)2971 void PipelineContext::OnTouchEvent(
2972     const TouchEvent& point, const RefPtr<FrameNode>& node, bool isSubPipe)
2973 {
2974     CHECK_RUN_ON(UI);
2975 
2976     HandlePenHoverOut(point);
2977     if (CheckSourceTypeChange(point.sourceType)) {
2978         HandleTouchHoverOut(point);
2979     }
2980 
2981 #ifdef UICAST_COMPONENT_SUPPORTED
2982     do {
2983         auto container = Container::Current();
2984         CHECK_NULL_BREAK(container);
2985         auto distributedUI = container->GetDistributedUI();
2986         CHECK_NULL_BREAK(distributedUI);
2987         if (distributedUI->IsSinkMode()) {
2988             distributedUI->BypassEvent(point, isSubPipe);
2989             return;
2990         }
2991     } while (false);
2992 #endif
2993 
2994     auto formEventMgr = this->GetFormEventManager();
2995     SerializedGesture etsSerializedGesture;
2996     if (point.type != TouchType::DOWN && formEventMgr) {
2997         formEventMgr->HandleEtsCardTouchEvent(point, etsSerializedGesture);
2998     }
2999 
3000     if (point.type != TouchType::DOWN && !eventManager_->touchDelegatesMap_.empty()) {
3001         eventManager_->DelegateTouchEvent(point);
3002     }
3003     auto oriPoint = point;
3004     auto scalePoint = point.CreateScalePoint(GetViewScale());
3005     eventManager_->CheckDownEvent(scalePoint);
3006     ReportConfig config;
3007 #if !defined(MAC_PLATFORM) && !defined(IOS_PLATFORM) && defined(OHOS_PLATFORM)
3008     auto container = Container::GetContainer(instanceId_);
3009     if (container) {
3010         config.isReportTid = container->GetUIContentType() == UIContentType::DYNAMIC_COMPONENT;
3011     }
3012     if (config.isReportTid) {
3013         config.tid = static_cast<uint64_t>(pthread_self());
3014     }
3015 #endif
3016     ResSchedReport::GetInstance().OnTouchEvent(scalePoint, config);
3017 
3018     if (scalePoint.type != TouchType::MOVE && scalePoint.type != TouchType::PULL_MOVE &&
3019         scalePoint.type != TouchType::HOVER_MOVE) {
3020         eventManager_->GetEventTreeRecord(EventTreeType::TOUCH).AddTouchPoint(scalePoint);
3021 #ifdef IS_RELEASE_VERSION
3022             TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
3023                 "ITK Id:%{public}d, fId:%{public}d, T:%{public}d, I=%{public}d, "
3024                 "M=%{public}d",
3025                 scalePoint.touchEventId, scalePoint.id, (int)scalePoint.type, scalePoint.isInjected,
3026                 scalePoint.isPrivacyMode);
3027 #else
3028             TAG_LOGD(AceLogTag::ACE_INPUTKEYFLOW,
3029                 "ITK Id:%{public}d, fId:%{public}d, x=%{public}.3f, y=%{public}.3f T=%{public}d, "
3030                 "I=%{public}d",
3031                 scalePoint.touchEventId, scalePoint.id, scalePoint.x, scalePoint.y, (int)scalePoint.type,
3032                 scalePoint.isInjected);
3033 #endif
3034     }
3035 
3036     if (scalePoint.type == TouchType::MOVE) {
3037         for (auto listenerItem : listenerVector_) {
3038             if (listenerItem) {
3039                 listenerItem->OnTouchEvent();
3040             }
3041         }
3042     }
3043 
3044     eventManager_->SetInstanceId(GetInstanceId());
3045     if (scalePoint.type != TouchType::MOVE && historyPointsById_.find(scalePoint.id) != historyPointsById_.end()) {
3046         historyPointsById_.erase(scalePoint.id);
3047     }
3048     if (scalePoint.type == TouchType::DOWN) {
3049         DisableNotifyResponseRegionChanged();
3050         SetUiDvsyncSwitch(false);
3051         CompensateTouchMoveEventBeforeDown();
3052         // Set focus state inactive while touch down event received
3053         SetIsFocusActive(false, FocusActiveReason::POINTER_EVENT);
3054         TouchRestrict touchRestrict { TouchRestrict::NONE };
3055         touchRestrict.sourceType = point.sourceType;
3056         touchRestrict.touchEvent = point;
3057         touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
3058 
3059         eventManager_->TouchTest(scalePoint, node, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe);
3060         if (!touchRestrict.childTouchTestList.empty()) {
3061             scalePoint.childTouchTestList = touchRestrict.childTouchTestList;
3062         }
3063         auto touchTestResults = eventManager_->touchTestResults_;
3064         if (StylusDetectorMgr::GetInstance()->IsNeedInterceptedTouchEvent(
3065             scalePoint, eventManager_->touchTestResults_)) {
3066             eventManager_->ClearTouchTestTargetForPenStylus(scalePoint);
3067             return;
3068         }
3069 
3070         if (formEventMgr) {
3071             formEventMgr->HandleEtsCardTouchEvent(oriPoint, etsSerializedGesture);
3072         }
3073 
3074         if (!eventManager_->touchDelegatesMap_.empty()) {
3075             eventManager_->DelegateTouchEvent(point);
3076         }
3077         if (etsSerializedGesture.data.size() != 0) {
3078             GestureGroup rebirth(GestureMode::Exclusive);
3079             rebirth.Deserialize(etsSerializedGesture.data.data());
3080             auto recognizer = rebirth.CreateRecognizer();
3081             if (recognizer) {
3082                 recognizer->SetInnerFlag(true);
3083                 recognizer->BeginReferee(scalePoint.id, true);
3084                 std::list<RefPtr<NGGestureRecognizer>> combined;
3085                 combined.emplace_back(recognizer);
3086                 for (auto iter = touchTestResults[point.id].begin();
3087                     iter != touchTestResults[point.id].end(); iter++) {
3088                     auto outRecognizer = AceType::DynamicCast<NGGestureRecognizer>(*iter);
3089                     if (outRecognizer) {
3090                         combined.emplace_back(outRecognizer);
3091                         touchTestResults[point.id].erase(iter);
3092                         break;
3093                     }
3094                 }
3095                 auto exclusiveRecognizer = AceType::MakeRefPtr<ExclusiveRecognizer>(std::move(combined));
3096                 exclusiveRecognizer->AttachFrameNode(node);
3097                 exclusiveRecognizer->BeginReferee(scalePoint.id);
3098                 touchTestResults[point.id].emplace_back(exclusiveRecognizer);
3099                 eventManager_->touchTestResults_ = touchTestResults;
3100                 eventManager_->SetInnerFlag(true);
3101             }
3102         }
3103         if (IsFormRenderExceptDynamicComponent() && touchTestResults.find(point.id) != touchTestResults.end()) {
3104             for (const auto& touchResult : touchTestResults[point.id]) {
3105                 auto recognizer = AceType::DynamicCast<NG::RecognizerGroup>(touchResult);
3106                 if (recognizer) {
3107                     auto gesture = recognizer->CreateGestureFromRecognizer();
3108                     if (gesture) {
3109                         serializedGesture_.data = std::vector<char>(gesture->SizeofMe());
3110                         gesture->Serialize(serializedGesture_.data.data());
3111                     }
3112                     break;
3113                 }
3114             }
3115         }
3116         for (const auto& weakContext : touchPluginPipelineContext_) {
3117             auto pipelineContext = DynamicCast<OHOS::Ace::PipelineBase>(weakContext.Upgrade());
3118             if (!pipelineContext) {
3119                 continue;
3120             }
3121             auto pluginPoint =
3122                 point.UpdateScalePoint(viewScale_, static_cast<float>(pipelineContext->GetPluginEventOffset().GetX()),
3123                     static_cast<float>(pipelineContext->GetPluginEventOffset().GetY()), point.id);
3124             // eventManager_ instance Id may changed.
3125             pipelineContext->OnTouchEvent(pluginPoint, true);
3126         }
3127 
3128         // restore instance Id.
3129         eventManager_->SetInstanceId(GetInstanceId());
3130     }
3131     auto rootOffset = GetRootRect().GetOffset();
3132     eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, rootOffset);
3133 
3134     if (isSubPipe) {
3135         return;
3136     }
3137 
3138     // Currently, SetupRootElement is executed later than InitializeCallback in AceContainer.
3139     // We need to check whether accessibilityManagerNG_ is created.
3140     if (accessibilityManagerNG_ != nullptr) {
3141         accessibilityManagerNG_->HandleAccessibilityHoverEvent(node, scalePoint);
3142     }
3143 
3144     if (scalePoint.type == TouchType::MOVE) {
3145         if (isEventsPassThrough_ || point.passThrough) {
3146             scalePoint.isPassThroughMode = true;
3147             eventManager_->FlushTouchEventsEnd({ scalePoint });
3148             eventManager_->DispatchTouchEvent(scalePoint);
3149             hasIdleTasks_ = true;
3150             if (postEventManager_) {
3151                 postEventManager_->SetPassThroughResult(eventManager_->GetPassThroughResult());
3152             }
3153             return;
3154         }
3155         if (!eventManager_->GetInnerFlag() && formEventMgr) {
3156             auto mockPoint = point;
3157             mockPoint.type = TouchType::CANCEL;
3158             formEventMgr->HandleEtsCardTouchEvent(mockPoint, etsSerializedGesture);
3159             formEventMgr->RemoveEtsCardTouchEventCallback(mockPoint.id);
3160         }
3161         NotifyDragTouchEvent(scalePoint, node);
3162         touchEvents_.emplace_back(point);
3163         hasIdleTasks_ = true;
3164         RequestFrame();
3165         return;
3166     }
3167 
3168     if (scalePoint.type == TouchType::UP) {
3169         lastTouchTime_ = GetTimeFromExternalTimer();
3170         CompensateTouchMoveEvent(scalePoint);
3171         if (thpExtraMgr_ != nullptr) {
3172             const uint32_t delay = 800; // 800: ms
3173             taskExecutor_->RemoveTask(TaskExecutor::TaskType::UI, "NotifyResponseRegionChanged");
3174             auto task = [weak = WeakClaim(this)]() {
3175                 auto pipeline = weak.Upgrade();
3176                 CHECK_NULL_VOID(pipeline);
3177                 pipeline->NotifyResponseRegionChanged(pipeline->GetRootElement());
3178             };
3179             taskExecutor_->PostDelayedTask(task, TaskExecutor::TaskType::UI, delay, "NotifyResponseRegionChanged");
3180         }
3181     }
3182 
3183     eventManager_->DispatchTouchEvent(scalePoint);
3184 
3185     if ((scalePoint.type == TouchType::UP) || (scalePoint.type == TouchType::CANCEL)) {
3186         // need to reset touchPluginPipelineContext_ for next touch down event.
3187         touchPluginPipelineContext_.clear();
3188         if (formEventMgr) {
3189             formEventMgr->RemoveEtsCardTouchEventCallback(point.id);
3190         }
3191         if (!eventManager_->touchDelegatesMap_.empty()) {
3192             eventManager_->UnregisterTouchDelegate(point.id);
3193         }
3194         if (scalePoint.type == TouchType::CANCEL) {
3195             dragEvents_.clear();
3196         }
3197         NotifyDragTouchEvent(scalePoint, node);
3198     }
3199     if (scalePoint.type != TouchType::MOVE) {
3200         auto lastDispatchTime = eventManager_->GetLastDispatchTime();
3201         lastDispatchTime.erase(scalePoint.id);
3202         eventManager_->SetLastDispatchTime(std::move(lastDispatchTime));
3203         eventManager_->EraseFingerId(scalePoint.id);
3204     }
3205 
3206     hasIdleTasks_ = true;
3207     RequestFrame();
3208     if (postEventManager_) {
3209         postEventManager_->SetPassThroughResult(eventManager_->GetPassThroughResult());
3210     }
3211 }
3212 
CompensateTouchMoveEventBeforeDown()3213 void PipelineContext::CompensateTouchMoveEventBeforeDown()
3214 {
3215     if (touchEvents_.empty()) {
3216         return;
3217     }
3218     std::unordered_map<int32_t, TouchEvent> historyPointsById;
3219     for (auto iter = touchEvents_.rbegin(); iter != touchEvents_.rend(); ++iter) {
3220         auto scalePoint = (*iter).CreateScalePoint(GetViewScale());
3221         historyPointsById.emplace(scalePoint.id, scalePoint);
3222         historyPointsById[scalePoint.id].history.insert(historyPointsById[scalePoint.id].history.begin(), scalePoint);
3223     }
3224     for (const auto& item : historyPointsById) {
3225         eventManager_->DispatchTouchEvent(item.second);
3226     }
3227     touchEvents_.clear();
3228 }
3229 
CompensateTouchMoveEventFromUnhandledEvents(const TouchEvent & event)3230 bool PipelineContext::CompensateTouchMoveEventFromUnhandledEvents(const TouchEvent& event)
3231 {
3232     std::vector<TouchEvent> history;
3233     if (!touchEvents_.empty()) {
3234         for (auto iter = touchEvents_.begin(); iter != touchEvents_.end();) {
3235             auto movePoint = (*iter).CreateScalePoint(GetViewScale());
3236             if (event.id == movePoint.id) {
3237                 ShouldAddToHistory(history, event, movePoint);
3238                 iter = touchEvents_.erase(iter);
3239             } else {
3240                 auto& pointers = iter->pointers;
3241                 for (auto pointerIter = pointers.begin(); pointerIter != pointers.end();) {
3242                     if (pointerIter->id == event.id) {
3243                         pointerIter = pointers.erase(pointerIter);
3244                     } else {
3245                         ++pointerIter;
3246                     }
3247                 }
3248                 ++iter;
3249             }
3250         }
3251         if (!history.empty()) {
3252             TouchEvent lastMoveEvent(history.back());
3253             lastMoveEvent.history.swap(history);
3254             eventManager_->SetLastMoveBeforeUp(event.sourceType == SourceType::MOUSE);
3255             eventManager_->DispatchTouchEvent(lastMoveEvent);
3256             eventManager_->SetLastMoveBeforeUp(false);
3257         } else {
3258             TAG_LOGD(AceLogTag::ACE_INPUTTRACKING,
3259                 "Finger id: %{public}d, not found unhandled move event, compensate failed.", event.id);
3260         }
3261         return true;
3262     }
3263     return false;
3264 }
3265 
CompensateTouchMoveEvent(const TouchEvent & event)3266 void PipelineContext::CompensateTouchMoveEvent(const TouchEvent& event)
3267 {
3268     if (event.type != TouchType::UP) {
3269         // If not up, no need to compensate touch move event.
3270         return;
3271     }
3272     if (!CompensateTouchMoveEventFromUnhandledEvents(event)) {
3273         // Compensate touch move event with all touch move Event before up has been handled.
3274         auto lastEventIter = eventManager_->GetIdToTouchPoint().find(event.id);
3275         if (lastEventIter != eventManager_->GetIdToTouchPoint().end()) {
3276             auto iter = eventManager_->GetLastDispatchTime().find(lastEventIter->first);
3277             if (iter != eventManager_->GetLastDispatchTime().end()) {
3278                 ACE_SCOPED_TRACE("CompensateTouchMoveEvent last move event time: %s last dispatch time: %s",
3279                     std::to_string(static_cast<uint64_t>(lastEventIter->second.time.time_since_epoch().count()))
3280                         .c_str(),
3281                     std::to_string(iter->second).c_str());
3282                 if (static_cast<uint64_t>(lastEventIter->second.time.time_since_epoch().count()) > iter->second) {
3283                     eventManager_->SetLastMoveBeforeUp(event.sourceType == SourceType::MOUSE);
3284                     eventManager_->DispatchTouchEvent(lastEventIter->second);
3285                     eventManager_->SetLastMoveBeforeUp(false);
3286                 }
3287             }
3288         }
3289     }
3290 
3291     auto lastEventIter = eventManager_->GetIdToTouchPoint().find(event.id);
3292     if (lastEventIter != eventManager_->GetIdToTouchPoint().end()) {
3293         ACE_SCOPED_TRACE("Finger id: %d process last move event eventId: %d", lastEventIter->first,
3294             lastEventIter->second.touchEventId);
3295     }
3296 }
3297 
OnSurfaceDensityChanged(double density)3298 void PipelineContext::OnSurfaceDensityChanged(double density)
3299 {
3300     CHECK_RUN_ON(UI);
3301     if (!NearEqual(density, density_)) {
3302         isDensityChanged_ = true;
3303         isNeedReloadDensity_ = true;
3304     }
3305     density_ = density;
3306     if (!NearZero(viewScale_)) {
3307         dipScale_ = density_ / viewScale_;
3308     }
3309     if (isNeedReloadDensity_) {
3310         UIObserverHandler::GetInstance().NotifyDensityChange(density_);
3311         PipelineBase::OnSurfaceDensityChanged(density);
3312     }
3313 }
3314 
DumpPageViewData(const RefPtr<FrameNode> & node,RefPtr<ViewDataWrap> viewDataWrap,bool skipSubAutoFillContainer,bool needsRecordData)3315 bool PipelineContext::DumpPageViewData(const RefPtr<FrameNode>& node, RefPtr<ViewDataWrap> viewDataWrap,
3316     bool skipSubAutoFillContainer, bool needsRecordData)
3317 {
3318     CHECK_NULL_RETURN(viewDataWrap, false);
3319     CHECK_NULL_RETURN(rootNode_, false);
3320     auto rootRect = GetRootRect();
3321     rootRect.SetOffset(rootNode_->GetPositionToScreenWithTransform());
3322     viewDataWrap->SetPageRect(rootRect);
3323     RefPtr<FrameNode> pageNode = nullptr;
3324     RefPtr<FrameNode> dumpNode = nullptr;
3325     if (node == nullptr) {
3326         if (stageManager_) {
3327             pageNode = stageManager_->GetLastPage();
3328             dumpNode = pageNode;
3329         }
3330     } else {
3331         pageNode = node->GetPageNode();
3332         dumpNode = node;
3333     }
3334     CHECK_NULL_RETURN(dumpNode, false);
3335     dumpNode->DumpViewDataPageNodes(viewDataWrap, skipSubAutoFillContainer, needsRecordData);
3336     // The page path may not be obtained in the container, use the node tag as the page path.
3337     if (node) {
3338         const auto& nodeTag = node->GetTag();
3339         if (nodeTag == V2::DIALOG_ETS_TAG || nodeTag == V2::SHEET_PAGE_TAG ||
3340             nodeTag == V2::MODAL_PAGE_TAG || nodeTag == V2::POPUP_ETS_TAG) {
3341             viewDataWrap->SetPageUrl(nodeTag);
3342             return true;
3343         }
3344     }
3345     CHECK_NULL_RETURN(pageNode, false);
3346     auto pagePattern = pageNode->GetPattern<NG::PagePattern>();
3347     CHECK_NULL_RETURN(pagePattern, false);
3348     auto pageInfo = pagePattern->GetPageInfo();
3349     CHECK_NULL_RETURN(pageInfo, false);
3350     viewDataWrap->SetPageUrl(pageInfo->GetPageUrl());
3351     return true;
3352 }
3353 
CheckNeedAutoSave()3354 bool PipelineContext::CheckNeedAutoSave()
3355 {
3356     CHECK_NULL_RETURN(stageManager_, false);
3357     auto pageNode = stageManager_->GetLastPage();
3358     CHECK_NULL_RETURN(pageNode, false);
3359     return pageNode->NeedRequestAutoSave();
3360 }
3361 
CheckOverlayFocus()3362 bool PipelineContext::CheckOverlayFocus()
3363 {
3364     CHECK_NULL_RETURN(overlayManager_, false);
3365     auto overlayNode = overlayManager_->GetOverlayNode();
3366     CHECK_NULL_RETURN(overlayNode, false);
3367     return overlayNode->GetFocusHub() && overlayNode->GetFocusHub()->IsCurrentFocus();
3368 }
3369 
NotifyFillRequestSuccess(AceAutoFillType autoFillType,RefPtr<ViewDataWrap> viewDataWrap)3370 void PipelineContext::NotifyFillRequestSuccess(AceAutoFillType autoFillType, RefPtr<ViewDataWrap> viewDataWrap)
3371 {
3372     CHECK_NULL_VOID(viewDataWrap);
3373     auto pageNodeInfoWraps = viewDataWrap->GetPageNodeInfoWraps();
3374     for (const auto& item : pageNodeInfoWraps) {
3375         if (item == nullptr) {
3376             continue;
3377         }
3378         auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(item->GetId()));
3379         if (frameNode == nullptr) {
3380             TAG_LOGW(AceLogTag::ACE_AUTO_FILL, "frameNode is not found, id=%{public}d", item->GetId());
3381             continue;
3382         }
3383         frameNode->NotifyFillRequestSuccess(viewDataWrap, item, autoFillType);
3384     }
3385 }
3386 
NotifyFillRequestFailed(RefPtr<FrameNode> node,int32_t errCode,const std::string & fillContent,bool isPopup)3387 void PipelineContext::NotifyFillRequestFailed(RefPtr<FrameNode> node, int32_t errCode,
3388     const std::string& fillContent, bool isPopup)
3389 {
3390     CHECK_NULL_VOID(node);
3391     node->NotifyFillRequestFailed(errCode, fillContent, isPopup);
3392 }
3393 
DumpFocus(bool hasJson) const3394 void PipelineContext::DumpFocus(bool hasJson) const
3395 {
3396     auto rootFocusHub = rootNode_->GetFocusHub();
3397     CHECK_NULL_VOID(rootFocusHub);
3398     rootFocusHub->DumpFocusTree(0, hasJson);
3399     if (hasJson) {
3400         DumpLog::GetInstance().PrintEndDumpInfoNG();
3401     }
3402 }
3403 
DumpInspector(const std::vector<std::string> & params,bool hasJson) const3404 void PipelineContext::DumpInspector(const std::vector<std::string>& params, bool hasJson) const
3405 {
3406     auto accessibilityManager = GetAccessibilityManager();
3407     if (accessibilityManager) {
3408         accessibilityManager->OnDumpInfoNG(params, windowId_, hasJson);
3409         if (hasJson) {
3410             DumpLog::GetInstance().PrintEndDumpInfoNG();
3411         }
3412     }
3413 }
3414 
DumpData(const RefPtr<FrameNode> & node,const std::vector<std::string> & params,bool hasJson) const3415 void PipelineContext::DumpData(
3416     const RefPtr<FrameNode>& node, const std::vector<std::string>& params, bool hasJson) const
3417 {
3418     CHECK_NULL_VOID(node);
3419     int32_t depth = 0;
3420     if (IsDynamicRender()) {
3421         depth = GetDepthFromParams(params);
3422     }
3423     uint32_t used_id_flag = hasJson ? USED_JSON_PARAM : USED_ID_FIND_FLAG;
3424     auto paramSize = params.size();
3425     auto container = Container::GetContainer(instanceId_);
3426     if (container && (container->IsUIExtensionWindow() || container->IsFormRender())) {
3427         paramSize =
3428             static_cast<uint32_t>(std::distance(params.begin(), std::find(params.begin(), params.end(), PID_FLAG)));
3429     }
3430     if (paramSize < used_id_flag) {
3431         node->DumpTree(depth, hasJson);
3432         if (hasJson) {
3433             DumpLog::GetInstance().PrintEndDumpInfoNG(true);
3434         }
3435         DumpLog::GetInstance().OutPutBySize();
3436     }
3437     if (paramSize == used_id_flag && !node->DumpTreeById(depth, params[PARAM_NUM], hasJson)) {
3438         DumpLog::GetInstance().Print(
3439             "There is no id matching the ID in the parameter, please check whether the id is correct.");
3440     }
3441     if (paramSize > used_id_flag) {
3442         SimplifiedInspector::TestScrollToTarget(params, stageManager_->GetLastPage());
3443     }
3444 }
3445 
DumpElement(const std::vector<std::string> & params,bool hasJson) const3446 void PipelineContext::DumpElement(const std::vector<std::string>& params, bool hasJson) const
3447 {
3448     if (params.size() > 1 && params[1] == "-lastpage") {
3449         auto lastPage = stageManager_->GetLastPage();
3450         DumpData(lastPage, params, hasJson);
3451     } else {
3452         DumpData(rootNode_, params, hasJson);
3453     }
3454 }
3455 
DumpResLoadError() const3456 void PipelineContext::DumpResLoadError() const
3457 {
3458     ResourceManager::GetInstance().DumpResLoadError();
3459 }
3460 
OnDumpInfo(const std::vector<std::string> & params) const3461 bool PipelineContext::OnDumpInfo(const std::vector<std::string>& params) const
3462 {
3463     bool hasJson = params.back() == "-json";
3464     int32_t depth = 0;
3465     if (IsDynamicRender()) {
3466         depth = GetDepthFromParams(params);
3467     }
3468 
3469     if (window_) {
3470         DumpLog::GetInstance().Print(1, "LastRequestVsyncTime: " + std::to_string(window_->GetLastRequestVsyncTime()));
3471 #ifdef ENABLE_ROSEN_BACKEND
3472         auto rsUIDirector = window_->GetRSUIDirector();
3473         if (rsUIDirector) {
3474             DumpLog::GetInstance().Print(1, "transactionFlags: [" + std::to_string(getpid()) + "," +
3475                 std::to_string(rsUIDirector->GetIndex()) + "]");
3476         }
3477 #endif
3478     }
3479     DumpLog::GetInstance().Print(1, "last vsyncId: " + std::to_string(GetFrameCount()));
3480     DumpLog::GetInstance().Print(1, "finishCount:" + GetUnexecutedFinishCount());
3481     if (params[0] == "-element") {
3482         DumpElement(params, hasJson);
3483     } else if (params[0] == "-navigation") {
3484         auto navigationDumpMgr = GetNavigationManager();
3485         if (navigationDumpMgr) {
3486             navigationDumpMgr->OnDumpInfo();
3487         }
3488     } else if (params[0] == "-focus") {
3489         DumpFocus(hasJson);
3490     } else if (params[0] == "-focuswindowscene") {
3491         auto windowSceneNode = GetFocusedWindowSceneNode();
3492         auto windowSceneFocusHub = windowSceneNode ? windowSceneNode->GetFocusHub() : nullptr;
3493         if (windowSceneFocusHub) {
3494             windowSceneFocusHub->DumpFocusTree(0);
3495         }
3496     } else if (params[0] == "-focusmanager") {
3497         if (focusManager_) {
3498             focusManager_->DumpFocusManager();
3499         }
3500     } else if (params[0] == "-accessibility") {
3501         auto accessibilityManager = GetAccessibilityManager();
3502         if (accessibilityManager) {
3503             accessibilityManager->OnDumpInfoNG(params, windowId_);
3504         }
3505     } else if (params[0] == "-inspector") {
3506         DumpInspector(params, hasJson);
3507     } else if (params[0] == "-rotation" && params.size() >= 2) {
3508     } else if (params[0] == "-animationscale" && params.size() >= 2) {
3509     } else if (params[0] == "-velocityscale" && params.size() >= 2) {
3510     } else if (params[0] == "-scrollfriction" && params.size() >= 2) {
3511     } else if (params[0] == "-threadstuck" && params.size() >= 3) {
3512     } else if (params[0] == "-pipeline") {
3513         DumpPipelineInfo();
3514     } else if (params[0] == "-jsdump") {
3515         std::vector<std::string> jsParams;
3516         if (params.begin() != params.end()) {
3517             jsParams = std::vector<std::string>(params.begin() + 1, params.end());
3518         }
3519 
3520         auto stageNode = stageManager_->GetStageNode();
3521         CHECK_NULL_RETURN(stageNode, false);
3522         auto children = stageNode->GetChildren();
3523         for (const auto& pageNode : children) {
3524             auto frameNode = AceType::DynamicCast<FrameNode>(pageNode);
3525             CHECK_NULL_RETURN(frameNode, false);
3526             auto pagePattern = frameNode->GetPattern<PagePattern>();
3527             CHECK_NULL_RETURN(pagePattern, false);
3528             pagePattern->FireDumpListener(jsParams);
3529         }
3530     } else if (params[0] == "-event") {
3531         if (eventManager_) {
3532             eventManager_->DumpEventWithCount(params, EventTreeType::TOUCH, hasJson);
3533         }
3534         DumpUIExt();
3535     } else if (params[0] == "-postevent") {
3536         if (eventManager_) {
3537             eventManager_->DumpEvent(EventTreeType::POST_EVENT, hasJson);
3538         }
3539     } else if (params[0] == "-imagecache") {
3540         if (imageCache_) {
3541             imageCache_->DumpCacheInfo();
3542         }
3543         DumpUIExt();
3544     } else if (params[0] == "-imagefilecache") {
3545         ImageFileCache::GetInstance().DumpCacheInfo();
3546         DumpUIExt();
3547     } else if (params[0] == "-allelements") {
3548         AceEngine::Get().NotifyContainers([](const RefPtr<Container>& container) {
3549             auto pipeline = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
3550             auto rootNode = pipeline->GetRootElement();
3551             if (rootNode) {
3552                 DumpLog::GetInstance().Print(0, "ContainerId: " + std::to_string(Container::CurrentId()));
3553                 rootNode->DumpTree(0);
3554                 DumpLog::GetInstance().OutPutBySize();
3555             }
3556         });
3557     } else if (params[0] == "-default") {
3558         rootNode_->DumpTree(depth);
3559         DumpLog::GetInstance().OutPutDefault();
3560     } else if (params[0] == "-overlay") {
3561         if (overlayManager_) {
3562             overlayManager_->DumpOverlayInfo();
3563         }
3564     } else if (params[0] == "--stylus") {
3565         StylusDetectorDefault::GetInstance()->ExecuteCommand(params);
3566     } else if (params[0] == "-simplify") {
3567         LOGI("start collect simplify dump info");
3568         if (params.size() >= 3 && params[1] == "-compname") {
3569             rootNode_->DumpTreeByComponentName(params[2]);
3570         } else {
3571             rootNode_->DumpTree(0);
3572         }
3573         DumpLog::GetInstance().OutPutByCompress();
3574         LOGI("end collect simplify dump info");
3575     } else if (params[0] == "-resource") {
3576         DumpResLoadError();
3577     } else if (params[0] == "-start") {
3578         OnDumpRecorderStart(params);
3579     } else if (params[0] == "-end") {
3580         DumpRecorder::GetInstance().Stop();
3581     } else if (params[0] == "-injection" && params.size() > PARAM_NUM) {
3582 #ifndef IS_RELEASE_VERSION
3583         OnDumpInjection(params);
3584     } else if (params[0] == "-injectionkeycode" && params.size() > PARAM_NUM) {
3585         UiSessionManager::GetInstance()->SendCommand(params[1]);
3586 #endif
3587     } else if (params[0] == "-forcedark") {
3588         DumpForceColor(params);
3589     } else if (params[0] == "-bindaicaller" && params.size() >= PARAM_NUM) {
3590         OnDumpBindAICaller(params);
3591     } else if (params[0] == "-compname" && params.size() >= PARAM_NUM) {
3592         rootNode_->DumpTreeByComponentName(params[1]);
3593         DumpLog::GetInstance().OutPutDefault();
3594     }
3595     return true;
3596 }
3597 
OnDumpRecorderStart(const std::vector<std::string> & params) const3598 void PipelineContext::OnDumpRecorderStart(const std::vector<std::string>& params) const
3599 {
3600     int32_t recordTime = DEFAULT_RECORD_SECOND;
3601     if (static_cast<uint32_t>(sizeof(params)) <= 1) {
3602         return;
3603     }
3604     int32_t inputTime = StringUtils::StringToInt(params[1]);
3605     if (inputTime > 0) {
3606         recordTime = inputTime;
3607     }
3608     recordTime = std::min(recordTime, MAX_RECORD_SECOND);
3609     int64_t startTime = GetCurrentTimestamp();
3610     auto taskExecutor = GetTaskExecutor();
3611     std::function<bool()> dumpFunc = [startTime, recordTime, weakRoot = WeakClaim(RawPtr(rootNode_))]() {
3612         int64_t currentTime = GetCurrentTimestamp();
3613         if ((currentTime - startTime) >= recordTime * SECOND_TO_MILLISEC) {
3614             return false;
3615         }
3616         auto root = weakRoot.Upgrade();
3617         CHECK_NULL_RETURN(root, false);
3618         auto jsonRoot = JsonUtil::Create(true);
3619         root->DumpTreeJsonForDiff(jsonRoot);
3620         DumpRecorder::GetInstance().Record(currentTime, std::move(jsonRoot));
3621         return true;
3622     };
3623     DumpRecorder::GetInstance().Start(std::move(dumpFunc));
3624 }
3625 
TriggerFrameDumpFuncIfExist() const3626 void PipelineContext::TriggerFrameDumpFuncIfExist() const
3627 {
3628     auto frameDumpFunc = DumpRecorder::GetInstance().GetFrameDumpFunc();
3629     CHECK_NULL_VOID(frameDumpFunc);
3630     if (!frameDumpFunc()) {
3631         DumpRecorder::GetInstance().Stop();
3632     }
3633 }
3634 
DumpUIExt() const3635 void PipelineContext::DumpUIExt() const
3636 {
3637 #ifdef WINDOW_SCENE_SUPPORTED
3638     if (uiExtensionManager_) {
3639         uiExtensionManager_->DumpUIExt();
3640     }
3641 #endif
3642 }
3643 
GetCurrentFrameInfo(uint64_t recvTime,uint64_t timeStamp)3644 FrameInfo* PipelineContext::GetCurrentFrameInfo(uint64_t recvTime, uint64_t timeStamp)
3645 {
3646     if (SystemProperties::GetDumpFrameCount() == 0) {
3647         return nullptr;
3648     }
3649     if (dumpFrameInfos_.size() >= SystemProperties::GetDumpFrameCount()) {
3650         dumpFrameInfos_.pop_front();
3651     }
3652 
3653     dumpFrameInfos_.push_back({ .frameRecvTime_ = recvTime, .frameTimeStamp_ = timeStamp });
3654     return &dumpFrameInfos_.back();
3655 }
3656 
DumpPipelineInfo() const3657 void PipelineContext::DumpPipelineInfo() const
3658 {
3659     DumpLog::GetInstance().Print("PipelineInfo:");
3660     if (window_) {
3661         DumpLog::GetInstance().Print(1, "DisplayRefreshRate: " + std::to_string(window_->GetRefreshRate()));
3662         DumpLog::GetInstance().Print(1, "LastRequestVsyncTime: " + std::to_string(window_->GetLastRequestVsyncTime()));
3663         DumpLog::GetInstance().Print(1, "NowTime: " + std::to_string(GetSysTimestamp()));
3664     }
3665     if (!dumpFrameInfos_.empty()) {
3666         DumpLog::GetInstance().Print("==================================FrameTask==================================");
3667         for (const auto& info : dumpFrameInfos_) {
3668             DumpLog::GetInstance().Print("Task: " + info.GetTimeInfo());
3669             DumpLog::GetInstance().Print(1, "LayoutTask:");
3670             for (const auto& layout : info.layoutInfos_) {
3671                 DumpLog::GetInstance().Print(2, layout.ToString());
3672             }
3673             DumpLog::GetInstance().Print(1, "RenderTask:");
3674             for (const auto& layout : info.renderInfos_) {
3675                 DumpLog::GetInstance().Print(2, layout.ToString());
3676             }
3677             DumpLog::GetInstance().Print(
3678                 "==================================FrameTask==================================");
3679         }
3680     }
3681 }
3682 
CollectTouchEventsBeforeVsync(std::list<TouchEvent> & touchEvents)3683 void PipelineContext::CollectTouchEventsBeforeVsync(std::list<TouchEvent>& touchEvents)
3684 {
3685     auto targetTimeStamp = compensationValue_ > 0 ? GetVsyncTime() - compensationValue_ : GetVsyncTime();
3686     if (touchEvents_.size() >= 40) { // TP:140Hz, vsync:30Hz, Fingers:10
3687         TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
3688             "Too many touch events in current vsync.(vsync: %{public}" PRIu64 ", eventsCnt: %{public}u)",
3689             GetVsyncTime(), static_cast<uint32_t>(touchEvents_.size()));
3690     }
3691     for (auto iter = touchEvents_.begin(); iter != touchEvents_.end();) {
3692         auto timeStamp = std::chrono::duration_cast<std::chrono::nanoseconds>(iter->time.time_since_epoch()).count();
3693         if (targetTimeStamp < static_cast<uint64_t>(timeStamp)) {
3694             iter++;
3695             continue;
3696         }
3697         touchEvents.emplace_back(*iter);
3698         iter = touchEvents_.erase(iter);
3699     }
3700 }
3701 
FlushTouchEvents()3702 void PipelineContext::FlushTouchEvents()
3703 {
3704     CHECK_RUN_ON(UI);
3705     CHECK_NULL_VOID(rootNode_);
3706     {
3707         std::list<TouchEvent> touchEvents;
3708         CollectTouchEventsBeforeVsync(touchEvents);
3709         if (touchEvents.empty()) {
3710             canUseLongPredictTask_ = true;
3711             return;
3712         }
3713         canUseLongPredictTask_ = false;
3714         eventManager_->FlushTouchEventsBegin(touchEvents_);
3715         std::unordered_map<int, TouchEvent> idToTouchPoints;
3716         if (touchAccelarate_) {
3717             AccelerateConsumeTouchEvents(touchEvents, idToTouchPoints);
3718         } else {
3719             ConsumeTouchEvents(touchEvents, idToTouchPoints);
3720         }
3721         auto maxSize = touchEvents.size();
3722         for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter) {
3723             maxSize--;
3724             if (maxSize == 0) {
3725                 eventManager_->FlushTouchEventsEnd(touchEvents);
3726             }
3727             eventManager_->DispatchTouchEvent(*iter);
3728         }
3729         eventManager_->SetIdToTouchPoint(std::move(idToTouchPoints));
3730     }
3731 }
3732 
SetBackgroundColorModeUpdated(bool backgroundColorModeUpdated)3733 void PipelineContext::SetBackgroundColorModeUpdated(bool backgroundColorModeUpdated)
3734 {
3735     backgroundColorModeUpdated_ = backgroundColorModeUpdated;
3736 }
3737 
ConsumeTouchEventsInterpolation(const std::unordered_set<int32_t> & ids,const std::map<int32_t,int32_t> & timestampToIds,std::unordered_map<int32_t,TouchEvent> & newIdTouchPoints,const std::unordered_map<int,TouchEvent> & idToTouchPoints)3738 void PipelineContext::ConsumeTouchEventsInterpolation(
3739     const std::unordered_set<int32_t>& ids, const std::map<int32_t, int32_t>& timestampToIds,
3740     std::unordered_map<int32_t, TouchEvent>& newIdTouchPoints,
3741     const std::unordered_map<int, TouchEvent>& idToTouchPoints)
3742 {
3743     auto fakeIds = ids;
3744     auto targetTimeStamp = resampleTimeStamp_;
3745     for (auto it = timestampToIds.rbegin(); it != timestampToIds.rend(); ++it) {
3746         auto touchId = it->second;
3747         if (fakeIds.find(touchId) == fakeIds.end()) {
3748             continue;
3749         }
3750         const auto touchIter = idToTouchPoints.find(touchId);
3751         if (touchIter == idToTouchPoints.end()) {
3752             continue;
3753         }
3754         auto stamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
3755             touchIter->second.time.time_since_epoch()).count();
3756         if (targetTimeStamp > static_cast<uint64_t>(stamp)) {
3757             continue;
3758         }
3759         TouchEvent newTouchEvent;
3760         if (eventManager_->GetResampleTouchEvent(
3761             historyPointsById_[touchId], touchIter->second.history,
3762             targetTimeStamp, newTouchEvent)) {
3763             newIdTouchPoints[touchId] = newTouchEvent;
3764         }
3765         historyPointsById_[touchId] = touchIter->second.history;
3766         fakeIds.erase(touchId);
3767     }
3768 }
3769 
ConsumeTouchEvents(std::list<TouchEvent> & touchEvents,std::unordered_map<int,TouchEvent> & idToTouchPoints)3770 void PipelineContext::ConsumeTouchEvents(
3771     std::list<TouchEvent>& touchEvents, std::unordered_map<int, TouchEvent>& idToTouchPoints)
3772 {
3773     std::map<int32_t, int32_t> timestampToIds;
3774     std::unordered_set<int32_t> ids;
3775     bool needInterpolation = true;
3776     std::unordered_map<int32_t, TouchEvent> newIdTouchPoints;
3777 
3778     int32_t inputIndex = static_cast<int32_t>(touchEvents.size()) - 1;
3779     for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter, --inputIndex) {
3780         auto scalePoint = (*iter).CreateScalePoint(GetViewScale());
3781         idToTouchPoints.emplace(scalePoint.id, scalePoint);
3782         idToTouchPoints[scalePoint.id].history.insert(idToTouchPoints[scalePoint.id].history.begin(), scalePoint);
3783         needInterpolation = iter->type != TouchType::MOVE ? false : true;
3784         timestampToIds.emplace(inputIndex, scalePoint.id);
3785         ids.insert(scalePoint.id);
3786     }
3787 
3788     if (!NeedTouchInterpolation()) {
3789         needInterpolation = false;
3790     }
3791 
3792     if (needInterpolation) {
3793         ConsumeTouchEventsInterpolation(ids, timestampToIds, newIdTouchPoints, idToTouchPoints);
3794     }
3795 
3796     touchEvents.clear();
3797     auto lastDispatchTime = eventManager_->GetLastDispatchTime();
3798     for (auto iter = timestampToIds.rbegin(); iter != timestampToIds.rend(); ++iter) {
3799         auto touchId = iter->second;
3800         if (ids.find(touchId) == ids.end()) {
3801             continue;
3802         }
3803         lastDispatchTime[touchId] = GetVsyncTime() - compensationValue_;
3804         auto it = newIdTouchPoints.find(touchId);
3805         if (it != newIdTouchPoints.end()) {
3806             touchEvents.emplace_back(it->second);
3807         } else {
3808             touchEvents.emplace_back(idToTouchPoints[touchId]);
3809         }
3810         ids.erase(touchId);
3811     }
3812     eventManager_->SetLastDispatchTime(std::move(lastDispatchTime));
3813 }
3814 
GetResampleStamp() const3815 uint64_t PipelineContext::GetResampleStamp() const
3816 {
3817     constexpr uint64_t RESAMPLE_LANTENCY = 5 * ONE_MS_IN_NS;
3818     uint64_t vsyncTime = GetVsyncTime();
3819     return std::min(vsyncTime - RESAMPLE_LANTENCY, vsyncTime - compensationValue_);
3820 }
3821 
AccelerateConsumeTouchEvents(std::list<TouchEvent> & touchEvents,std::unordered_map<int,TouchEvent> & idToTouchPoints)3822 void PipelineContext::AccelerateConsumeTouchEvents(
3823     std::list<TouchEvent>& touchEvents, std::unordered_map<int, TouchEvent>& idToTouchPoints)
3824 {
3825     std::map<int32_t, int32_t> timestampToIds;
3826     std::unordered_set<int32_t> ids;
3827 
3828     int32_t inputIndex = static_cast<int32_t>(touchEvents.size()) - 1;
3829     // consume touchEvents and generate idToTouchPoints.
3830     for (auto iter = touchEvents.rbegin(); iter != touchEvents.rend(); ++iter, --inputIndex) {
3831         auto scalePoint = iter->CreateScalePoint(GetViewScale());
3832         idToTouchPoints.emplace(scalePoint.id, scalePoint);
3833         auto& history = idToTouchPoints[scalePoint.id].history;
3834         history.emplace(history.begin(), std::move(scalePoint));
3835         timestampToIds.emplace(inputIndex, scalePoint.id);
3836         ids.insert(scalePoint.id);
3837     }
3838 
3839     bool needInterpolation = (touchEvents.front().type == TouchType::MOVE) && NeedTouchInterpolation();
3840     auto& lastDispatchTime = eventManager_->GetLastDispatchTime();
3841     auto curVsyncArrivalTime = GetVsyncTime() - compensationValue_;
3842     touchEvents.clear();
3843 
3844     // resample and generate event to dispatch in touchEvents
3845     if (needInterpolation) {
3846         auto targetTimeStamp = GetResampleStamp();
3847         for (auto it = timestampToIds.rbegin(); it != timestampToIds.rend(); ++it) {
3848             auto touchId = it->second;
3849             if (ids.find(touchId) == ids.end()) {
3850                 continue;
3851             }
3852             TouchEvent newTouchEvent = idToTouchPoints[touchId];
3853             eventManager_->TryResampleTouchEvent(
3854                 historyPointsById_[touchId], idToTouchPoints[touchId].history, targetTimeStamp, newTouchEvent);
3855             lastDispatchTime[touchId] = curVsyncArrivalTime;
3856             touchEvents.emplace_back(std::move(newTouchEvent));
3857             ids.erase(touchId);
3858         }
3859     } else {
3860         for (auto it = timestampToIds.rbegin(); it != timestampToIds.rend(); ++it) {
3861             auto touchId = it->second;
3862             if (ids.find(touchId) == ids.end()) {
3863                 continue;
3864             }
3865             lastDispatchTime[touchId] = curVsyncArrivalTime;
3866             touchEvents.emplace_back(idToTouchPoints[touchId]);
3867             ids.erase(touchId);
3868         }
3869     }
3870 }
3871 
OnAccessibilityHoverEvent(const TouchEvent & point,const RefPtr<NG::FrameNode> & node)3872 void PipelineContext::OnAccessibilityHoverEvent(const TouchEvent& point, const RefPtr<NG::FrameNode>& node)
3873 {
3874     CHECK_RUN_ON(UI);
3875     auto scaleEvent = point.CreateScalePoint(viewScale_);
3876     if (scaleEvent.type != TouchType::HOVER_MOVE) {
3877 #ifdef IS_RELEASE_VERSION
3878         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
3879             "OnAccessibilityHoverEvent event id:%{public}d, fingerId:%{public}d,"
3880             "type=%{public}d, "
3881             "inject=%{public}d",
3882             scaleEvent.touchEventId, scaleEvent.id, (int)scaleEvent.type, scaleEvent.isInjected);
3883 #else
3884         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
3885             "OnAccessibilityHoverEvent event id:%{public}d, fingerId:%{public}d, x=%{public}f y=%{public}f "
3886             "type=%{public}d, "
3887             "inject=%{public}d",
3888             scaleEvent.touchEventId, scaleEvent.id, scaleEvent.x, scaleEvent.y, (int)scaleEvent.type,
3889             scaleEvent.isInjected);
3890 #endif
3891     }
3892     auto targerNode = node ? node : rootNode_;
3893     if (accessibilityManagerNG_ != nullptr) {
3894         accessibilityManagerNG_->HandleAccessibilityHoverEvent(targerNode, scaleEvent);
3895     }
3896     TouchRestrict touchRestrict { TouchRestrict::NONE };
3897     touchRestrict.sourceType = scaleEvent.sourceType;
3898     // use mouse to collect accessibility hover target
3899     touchRestrict.hitTestType = SourceType::MOUSE;
3900     touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
3901     touchRestrict.touchEvent.type = TouchType::HOVER_ENTER;
3902     eventManager_->AccessibilityHoverTest(scaleEvent, targerNode, touchRestrict);
3903     eventManager_->DispatchAccessibilityHoverEventNG(scaleEvent);
3904     RequestFrame();
3905 }
3906 
OnPenHoverEvent(const TouchEvent & point,const RefPtr<NG::FrameNode> & node)3907 void PipelineContext::OnPenHoverEvent(const TouchEvent& point, const RefPtr<NG::FrameNode>& node)
3908 {
3909     CHECK_RUN_ON(UI);
3910     auto scaleEvent = point.CreateScalePoint(viewScale_);
3911     if (scaleEvent.type != TouchType::MOVE) {
3912         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
3913             "OnPenHoverEvent event id:%{public}d, fingerId:%{public}d "
3914             "type=%{public}d, "
3915             "inject=%{public}d",
3916             scaleEvent.touchEventId, scaleEvent.id, (int)scaleEvent.type,
3917             scaleEvent.isInjected);
3918     }
3919 
3920     auto targerNode = node ? node : rootNode_;
3921     TouchRestrict touchRestrict { TouchRestrict::NONE };
3922     touchRestrict.sourceType = scaleEvent.sourceType;
3923     touchRestrict.touchEvent.sourceTool = scaleEvent.sourceTool;
3924     touchRestrict.touchEvent.type = scaleEvent.type;
3925     touchRestrict.touchEvent.force = scaleEvent.force;
3926 
3927     // use mouse to collect pen hover target
3928     touchRestrict.hitTestType = SourceType::MOUSE;
3929     touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN;
3930     eventManager_->PenHoverTest(scaleEvent, targerNode, touchRestrict);
3931     eventManager_->DispatchPenHoverEventNG(scaleEvent);
3932     eventManager_->DispatchPenHoverMoveEventNG(scaleEvent);
3933     RequestFrame();
3934 }
3935 
HandlePenHoverOut(const TouchEvent & point)3936 void PipelineContext::HandlePenHoverOut(const TouchEvent& point)
3937 {
3938     if (point.sourceTool != SourceTool::PEN || point.type != TouchType::DOWN || NearZero(point.force)) {
3939         return;
3940     }
3941 
3942     CHECK_RUN_ON(UI);
3943     auto oriPoint = point;
3944     oriPoint.type = TouchType::PROXIMITY_OUT;
3945 
3946     TouchTestResult testResult;
3947     eventManager_->UpdatePenHoverNode(oriPoint, testResult);
3948     eventManager_->DispatchPenHoverEventNG(oriPoint);
3949 }
3950 
UpdateLastMoveEvent(const MouseEvent & event)3951 void PipelineContext::UpdateLastMoveEvent(const MouseEvent& event)
3952 {
3953     if (!lastMouseEvent_) {
3954         lastMouseEvent_ = std::make_unique<MouseEvent>();
3955     }
3956     if (event.mockFlushEvent && event.action == MouseAction::WINDOW_LEAVE) {
3957         lastMouseEvent_->isMockWindowTransFlag = true;
3958     }
3959     lastMouseEvent_->x = event.x;
3960     lastMouseEvent_->y = event.y;
3961     lastMouseEvent_->button = event.button;
3962     lastMouseEvent_->action = event.action;
3963     lastMouseEvent_->sourceType = event.sourceType;
3964     lastMouseEvent_->time = event.time;
3965     lastMouseEvent_->touchEventId = event.touchEventId;
3966     lastMouseEvent_->mockFlushEvent = event.mockFlushEvent;
3967     lastMouseEvent_->pointerEvent = event.pointerEvent;
3968     lastMouseEvent_->deviceId = event.deviceId;
3969     lastMouseEvent_->sourceTool = event.sourceTool;
3970     lastMouseEvent_->targetDisplayId = event.targetDisplayId;
3971     lastSourceType_ = event.sourceType;
3972 }
3973 
OnMouseEvent(const MouseEvent & event,const RefPtr<FrameNode> & node)3974 void PipelineContext::OnMouseEvent(const MouseEvent& event, const RefPtr<FrameNode>& node)
3975 {
3976     CHECK_RUN_ON(UI);
3977     UpdateLastMoveEvent(event);
3978     lastMouseEvent_->node = node;
3979     if (event.action == MouseAction::PRESS || event.action == MouseAction::RELEASE) {
3980 #ifdef IS_RELEASE_VERSION
3981         TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
3982             "InputTracking id:%{public}d, mouseId:%{public}d, type=%{public}d, button=%{public}d, inject=%{public}d",
3983             event.touchEventId, event.id, (int)event.action, (int)event.button, event.isInjected);
3984 #else
3985         TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
3986             "InputTracking id:%{public}d, mouseId:%{public}d, x=%{public}.3f, y=%{public}.3f, z=%{public}.3f, "
3987             "type=%{public}d, button=%{public}d"
3988             "inject=%{public}d",
3989             event.touchEventId, event.id, event.x, event.y, event.z, (int)event.action, (int)event.button,
3990             event.isInjected);
3991 #endif
3992     }
3993 
3994     if (event.button == MouseButton::RIGHT_BUTTON && event.action == MouseAction::PRESS) {
3995         // Mouse right button press event set focus inactive here.
3996         // Mouse left button press event will set focus inactive in touch process.
3997         SetIsFocusActive(false, FocusActiveReason::POINTER_EVENT);
3998     }
3999 
4000     if (event.action == MouseAction::RELEASE || event.action == MouseAction::CANCEL ||
4001         event.action == MouseAction::WINDOW_LEAVE) {
4002         lastMouseTime_ = GetTimeFromExternalTimer();
4003         CompensateMouseMoveEvent(event, node);
4004     }
4005     NotifyDragMouseEvent(event);
4006     DispatchMouseToTouchEvent(event, node);
4007     if (event.action == MouseAction::MOVE) {
4008         if (event.passThrough) {
4009             DispatchMouseEvent(event, node);
4010             if (postEventManager_) {
4011                 postEventManager_->SetPassThroughResult(eventManager_->GetPassThroughResult());
4012             }
4013             return;
4014         }
4015         mouseEvents_[node].emplace_back(event);
4016         hasIdleTasks_ = true;
4017         RequestFrame();
4018         return;
4019     }
4020     DispatchMouseEvent(event, node);
4021     if (postEventManager_) {
4022         postEventManager_->SetPassThroughResult(eventManager_->GetPassThroughResult());
4023     }
4024 }
4025 
DispatchMouseToTouchEvent(const MouseEvent & event,const RefPtr<FrameNode> & node)4026 void PipelineContext::DispatchMouseToTouchEvent(const MouseEvent& event, const RefPtr<FrameNode>& node)
4027 {
4028     CHECK_NULL_VOID(node);
4029     if (((event.action == MouseAction::RELEASE || event.action == MouseAction::PRESS ||
4030             event.action == MouseAction::MOVE) &&
4031             (event.button == MouseButton::LEFT_BUTTON || event.pressedButtons == MOUSE_PRESS_LEFT)) ||
4032         event.action == MouseAction::CANCEL) {
4033         auto touchPoint = event.CreateTouchPoint();
4034         if (event.pullAction == MouseAction::PULL_MOVE) {
4035             touchPoint.pullType = TouchType::PULL_MOVE;
4036         }
4037         OnTouchEvent(touchPoint, node);
4038     } else {
4039         auto touchPoint = event.CreateTouchPoint();
4040         auto scalePoint = touchPoint.CreateScalePoint(GetViewScale());
4041         NG::OffsetF offset;
4042         auto geometryNode = node->GetGeometryNode();
4043         if (event.passThrough && geometryNode) {
4044             offset = geometryNode->GetFrameRect().GetOffset();
4045         } else {
4046             offset = GetRootRect().GetOffset();
4047         }
4048         eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, offset);
4049     }
4050 }
4051 
CompensateMouseMoveEvent(const MouseEvent & event,const RefPtr<FrameNode> & node)4052 void PipelineContext::CompensateMouseMoveEvent(const MouseEvent& event, const RefPtr<FrameNode>& node)
4053 {
4054     if (CompensateMouseMoveEventFromUnhandledEvents(event, node)) {
4055         return;
4056     }
4057     auto lastEventIter = nodeToMousePoints_.find(node);
4058     if (lastEventIter == nodeToMousePoints_.end() || lastEventIter->second.empty()) {
4059         return;
4060     }
4061     MouseEvent mouseEvent = lastEventIter->second.back();
4062     auto iter = eventManager_->GetLastDispatchTime().find(mouseEvent.id);
4063     if (iter != eventManager_->GetLastDispatchTime().end()) {
4064         if (static_cast<uint64_t>(mouseEvent.time.time_since_epoch().count()) > iter->second) {
4065             TouchRestrict touchRestrict { TouchRestrict::NONE };
4066             touchRestrict.sourceType = event.sourceType;
4067             touchRestrict.hitTestType = SourceType::MOUSE;
4068             touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
4069             eventManager_->MouseTest(mouseEvent, node, touchRestrict);
4070             eventManager_->DispatchMouseEventNG(mouseEvent);
4071             eventManager_->DispatchMouseHoverEventNG(mouseEvent);
4072             eventManager_->DispatchMouseHoverAnimationNG(mouseEvent);
4073         }
4074     }
4075 }
4076 
CompensateMouseMoveEventFromUnhandledEvents(const MouseEvent & event,const RefPtr<FrameNode> & node)4077 bool PipelineContext::CompensateMouseMoveEventFromUnhandledEvents(
4078     const MouseEvent& event, const RefPtr<FrameNode>& node)
4079 {
4080     if (mouseEvents_.empty()) {
4081         return false;
4082     }
4083 
4084     auto iter = mouseEvents_.find(node);
4085     if (iter == mouseEvents_.end()) {
4086         return false;
4087     }
4088     std::vector<MouseEvent> history;
4089     for (auto mouseIter = iter->second.begin(); mouseIter != iter->second.end();) {
4090         if (event.id == mouseIter->id) {
4091             history.emplace_back(*mouseIter);
4092             mouseIter = iter->second.erase(mouseIter);
4093         } else {
4094             mouseIter++;
4095         }
4096     }
4097     mouseEvents_.erase(iter);
4098 
4099     if (history.empty()) {
4100         return false;
4101     }
4102 
4103     MouseEvent lastMoveEvent(history.back());
4104     lastMoveEvent.history.swap(history);
4105     TouchRestrict touchRestrict { TouchRestrict::NONE };
4106     touchRestrict.sourceType = event.sourceType;
4107     touchRestrict.hitTestType = SourceType::MOUSE;
4108     touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
4109     eventManager_->MouseTest(lastMoveEvent, node, touchRestrict);
4110     eventManager_->DispatchMouseEventNG(lastMoveEvent);
4111     eventManager_->DispatchMouseHoverEventNG(lastMoveEvent);
4112     eventManager_->DispatchMouseHoverAnimationNG(lastMoveEvent);
4113     return true;
4114 }
4115 
DispatchMouseEvent(const MouseEvent & event,const RefPtr<FrameNode> & node)4116 void PipelineContext::DispatchMouseEvent(const MouseEvent& event, const RefPtr<FrameNode>& node)
4117 {
4118     CHECK_NULL_VOID(node);
4119     auto scaleEvent = event.CreateScaleEvent(viewScale_);
4120     if (scaleEvent.action != MouseAction::MOVE &&
4121         historyMousePointsById_.find(scaleEvent.id) != historyMousePointsById_.end()) {
4122         historyMousePointsById_.erase(scaleEvent.id);
4123     }
4124 
4125     TouchRestrict touchRestrict { TouchRestrict::NONE };
4126     touchRestrict.sourceType = event.sourceType;
4127     touchRestrict.hitTestType = SourceType::MOUSE;
4128     touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
4129     if (event.action != MouseAction::MOVE || event.passThrough) {
4130         eventManager_->MouseTest(scaleEvent, node, touchRestrict);
4131         eventManager_->DispatchMouseEventNG(scaleEvent);
4132         eventManager_->DispatchMouseHoverEventNG(scaleEvent);
4133         eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
4134     }
4135     accessibilityManagerNG_->HandleAccessibilityHoverEvent(node, scaleEvent);
4136     RequestFrame();
4137 }
4138 
FlushMouseEvent()4139 void PipelineContext::FlushMouseEvent()
4140 {
4141     if (!lastMouseEvent_ || lastMouseEvent_->action == MouseAction::WINDOW_LEAVE) {
4142         return;
4143     }
4144     MouseEvent event;
4145     event.x = lastMouseEvent_->x;
4146     event.y = lastMouseEvent_->y;
4147     event.time = lastMouseEvent_->time;
4148     event.action = MouseAction::MOVE;
4149     event.button = MouseButton::NONE_BUTTON;
4150     event.sourceType = SourceType::MOUSE;
4151     event.deviceId = lastMouseEvent_->deviceId;
4152     event.sourceTool = SourceTool::MOUSE;
4153 
4154     CHECK_RUN_ON(UI);
4155     CHECK_NULL_VOID(rootNode_);
4156     ACE_SCOPED_TRACE("FlushMouseEvent x:%f y:%f", lastMouseEvent_->x, lastMouseEvent_->y);
4157     auto scaleEvent = event.CreateScaleEvent(viewScale_);
4158     TouchRestrict touchRestrict { TouchRestrict::NONE };
4159     touchRestrict.sourceType = event.sourceType;
4160     touchRestrict.hitTestType = SourceType::MOUSE;
4161     touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
4162     OnFlushMouseEvent(touchRestrict);
4163 }
4164 
OnFlushMouseEvent(TouchRestrict & touchRestrict)4165 void PipelineContext::OnFlushMouseEvent(TouchRestrict& touchRestrict)
4166 {
4167     decltype(mouseEvents_) mouseEvents(std::move(mouseEvents_));
4168     if (mouseEvents.empty()) {
4169         canUseLongPredictTask_ = true;
4170         nodeToMousePoints_.clear();
4171         return;
4172     }
4173     canUseLongPredictTask_ = false;
4174     for (auto iter = mouseEvents.begin(); iter != mouseEvents.end(); ++iter) {
4175         OnFlushMouseEvent(iter->first, iter->second, touchRestrict);
4176     }
4177 }
4178 
OnFlushMouseEvent(const RefPtr<FrameNode> & node,const std::list<MouseEvent> & mouseEvents,TouchRestrict & touchRestrict)4179 void PipelineContext::OnFlushMouseEvent(
4180     const RefPtr<FrameNode> &node, const std::list<MouseEvent>& mouseEvents, TouchRestrict& touchRestrict)
4181 {
4182     if (mouseEvents.empty()) {
4183         canUseLongPredictTask_ = true;
4184         return ;
4185     }
4186     canUseLongPredictTask_ = false;
4187     std::unordered_map<int, MouseEvent> idToMousePoints;
4188     bool needInterpolation = true;
4189     std::unordered_map<int32_t, MouseEvent> newIdMousePoints;
4190     std::map<WeakPtr<FrameNode>, std::vector<MouseEvent>> nodeToMousePoints;
4191     for (auto iter = mouseEvents.rbegin(); iter != mouseEvents.rend(); ++iter) {
4192         auto scaleEvent = (*iter).CreateScaleEvent(GetViewScale());
4193         idToMousePoints.emplace(scaleEvent.id, scaleEvent);
4194         if (!iter->mockFlushEvent) {
4195             idToMousePoints[scaleEvent.id].history.insert(idToMousePoints[scaleEvent.id].history.begin(), scaleEvent);
4196         }
4197         nodeToMousePoints[node].emplace_back(idToMousePoints[scaleEvent.id]);
4198         needInterpolation = iter->action != MouseAction::MOVE ? false : true;
4199     }
4200     if (!NeedTouchInterpolation()) {
4201         needInterpolation = false;
4202     }
4203     if (needInterpolation) {
4204         auto targetTimeStamp = resampleTimeStamp_;
4205         for (const auto& idIter : idToMousePoints) {
4206             auto stamp =
4207                 std::chrono::duration_cast<std::chrono::nanoseconds>(idIter.second.time.time_since_epoch()).count();
4208             if (targetTimeStamp > static_cast<uint64_t>(stamp)) {
4209                 LOGI("there is no mouse event after interpolation time point. "
4210                     "(last stamp:%{public}" PRIu64 ", target stamp:%{public}" PRIu64 ")",
4211                     static_cast<uint64_t>(stamp), targetTimeStamp);
4212                 continue;
4213             }
4214             if (idIter.second.button == MouseButton::NONE_BUTTON) {
4215                 continue;
4216             }
4217             MouseEvent newMouseEvent = eventManager_->GetResampleMouseEvent(
4218                 historyMousePointsById_[idIter.first], idIter.second.history, targetTimeStamp);
4219             if (newMouseEvent.x != 0 && newMouseEvent.y != 0) {
4220                 newIdMousePoints[idIter.first] = newMouseEvent;
4221             }
4222             historyMousePointsById_[idIter.first] = idIter.second.history;
4223         }
4224     }
4225     nodeToMousePoints_ = std::move(nodeToMousePoints);
4226     DispatchMouseEvent(idToMousePoints, newIdMousePoints, mouseEvents, touchRestrict, node);
4227 }
4228 
DispatchMouseEvent(std::unordered_map<int,MouseEvent> & idToMousePoints,std::unordered_map<int32_t,MouseEvent> & newIdMousePoints,const std::list<MouseEvent> & mouseEvents,TouchRestrict & touchRestrict,const RefPtr<FrameNode> & node)4229 void PipelineContext::DispatchMouseEvent(
4230     std::unordered_map<int, MouseEvent>& idToMousePoints,
4231     std::unordered_map<int32_t, MouseEvent> &newIdMousePoints,
4232     const std::list<MouseEvent> &mouseEvents,
4233     TouchRestrict& touchRestrict,
4234     const RefPtr<FrameNode> &node)
4235 {
4236     std::list<MouseEvent> mousePoints;
4237     for (const auto& iter : idToMousePoints) {
4238         auto lastDispatchTime = eventManager_->GetLastDispatchTime();
4239         lastDispatchTime[iter.first] = GetVsyncTime();
4240         eventManager_->SetLastDispatchTime(std::move(lastDispatchTime));
4241         auto it = newIdMousePoints.find(iter.first);
4242         if (it != newIdMousePoints.end()) {
4243             mousePoints.emplace_back(it->second);
4244         } else {
4245             mousePoints.emplace_back(iter.second);
4246         }
4247     }
4248     for (auto iter = mousePoints.rbegin(); iter != mousePoints.rend(); ++iter) {
4249         auto scaleEvent = iter->CreateScaleEvent(viewScale_);
4250         eventManager_->MouseTest(scaleEvent, node, touchRestrict);
4251         eventManager_->DispatchMouseEventNG(scaleEvent);
4252         eventManager_->DispatchMouseHoverEventNG(scaleEvent);
4253         eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
4254     }
4255 }
4256 
ChangeMouseStyle(int32_t nodeId,MouseFormat format,int32_t windowId,bool isByPass,MouseStyleChangeReason reason)4257 bool PipelineContext::ChangeMouseStyle(int32_t nodeId, MouseFormat format, int32_t windowId, bool isByPass,
4258     MouseStyleChangeReason reason)
4259 {
4260     auto mouseStyleManager = eventManager_->GetMouseStyleManager();
4261     CHECK_NULL_RETURN(mouseStyleManager, false);
4262     if (!windowId) {
4263         windowId = static_cast<int32_t>(GetFocusWindowId());
4264     }
4265     mouseStyleManager->SetMouseFormat(windowId, nodeId, format, isByPass, reason);
4266     RequestFrame();
4267     return true;
4268 }
4269 
ReDispatch(KeyEvent & keyEvent)4270 void PipelineContext::ReDispatch(KeyEvent& keyEvent)
4271 {
4272     CHECK_NULL_VOID(eventManager_);
4273     TAG_LOGD(AceLogTag::ACE_WEB, "Web ReDispach key event: code:" SEC_PLD(%{public}d) "/action:%{public}d.",
4274         SEC_PARAM(keyEvent.code), keyEvent.action);
4275     eventManager_->ReDispatch(keyEvent);
4276 }
4277 
OnNonPointerEvent(const NonPointerEvent & event)4278 bool PipelineContext::OnNonPointerEvent(const NonPointerEvent& event)
4279 {
4280     return eventManager_->OnNonPointerEvent(event);
4281 }
4282 
RequestFocus(const std::string & targetNodeId,bool isSyncRequest)4283 bool PipelineContext::RequestFocus(const std::string& targetNodeId, bool isSyncRequest)
4284 {
4285     auto rootNode = GetFocusedWindowSceneNode();
4286     if (!rootNode) {
4287         rootNode = rootNode_;
4288     }
4289     CHECK_NULL_RETURN(rootNode, false);
4290     auto focusHub = rootNode->GetFocusHub();
4291     CHECK_NULL_RETURN(focusHub, false);
4292     auto currentFocusChecked = focusHub->RequestFocusImmediatelyById(targetNodeId, isSyncRequest);
4293     if (!isSubPipeline_ || currentFocusChecked) {
4294         return currentFocusChecked;
4295     }
4296     auto parentPipelineBase = parentPipeline_.Upgrade();
4297     CHECK_NULL_RETURN(parentPipelineBase, false);
4298     auto parentPipelineContext = AceType::DynamicCast<NG::PipelineContext>(parentPipelineBase);
4299     CHECK_NULL_RETURN(parentPipelineContext, false);
4300     return parentPipelineContext->RequestFocus(targetNodeId, isSyncRequest);
4301 }
4302 
AddDirtyFocus(const RefPtr<FrameNode> & node)4303 void PipelineContext::AddDirtyFocus(const RefPtr<FrameNode>& node)
4304 {
4305     CHECK_RUN_ON(UI);
4306     CHECK_NULL_VOID(node);
4307     if (node->GetFocusType() == FocusType::NODE) {
4308         dirtyFocusNode_ = WeakClaim(RawPtr(node));
4309     } else {
4310         dirtyFocusScope_ = WeakClaim(RawPtr(node));
4311     }
4312     RequestFrame();
4313 }
4314 
AddDirtyRequestFocus(const RefPtr<FrameNode> & node)4315 void PipelineContext::AddDirtyRequestFocus(const RefPtr<FrameNode>& node)
4316 {
4317     CHECK_RUN_ON(UI);
4318     CHECK_NULL_VOID(node);
4319     dirtyRequestFocusNode_ = WeakPtr<FrameNode>(node);
4320     RequestFrame();
4321 }
4322 
RootLostFocus(BlurReason reason) const4323 void PipelineContext::RootLostFocus(BlurReason reason) const
4324 {
4325     CHECK_NULL_VOID(rootNode_);
4326     auto focusHub = rootNode_->GetFocusHub();
4327     CHECK_NULL_VOID(focusHub);
4328     focusHub->LostFocus(reason);
4329     CHECK_NULL_VOID(overlayManager_);
4330     overlayManager_->HideAllMenus();
4331 }
4332 
ConvertAxisToMouse(const AxisEvent & event)4333 MouseEvent ConvertAxisToMouse(const AxisEvent& event)
4334 {
4335     MouseEvent result;
4336     result.x = event.x;
4337     result.y = event.y;
4338     result.globalDisplayX = event.globalDisplayX;
4339     result.globalDisplayY = event.globalDisplayY;
4340     result.action = MouseAction::MOVE;
4341     result.button = MouseButton::NONE_BUTTON;
4342     result.time = event.time;
4343     result.deviceId = event.deviceId;
4344     result.sourceType = event.sourceType;
4345     result.sourceTool = event.sourceTool;
4346     result.touchEventId = event.touchEventId;
4347     result.pointerEvent = event.pointerEvent;
4348     result.screenX = event.screenX;
4349     result.screenY = event.screenY;
4350     return result;
4351 }
4352 
OnAxisEvent(const AxisEvent & event,const RefPtr<FrameNode> & node)4353 void PipelineContext::OnAxisEvent(const AxisEvent& event, const RefPtr<FrameNode>& node)
4354 {
4355     if (!axisEventChecker_.IsAxisEventSequenceCorrect(event)) {
4356         TAG_LOGW(AceLogTag::ACE_INPUTKEYFLOW,
4357             "AxisEvent error occurred, the currentAction is %{public}d, the preAction is %{public}d", event.action,
4358             axisEventChecker_.GetPreAction());
4359     }
4360     auto scaleEvent = event.CreateScaleEvent(viewScale_);
4361     if (event.action == AxisAction::BEGIN || event.action == AxisAction::CANCEL || event.action == AxisAction::END) {
4362         eventManager_->GetEventTreeRecord(EventTreeType::TOUCH).AddAxis(scaleEvent);
4363     }
4364     auto formEventMgr = this->GetFormEventManager();
4365     SerializedGesture etsSerializedGesture;
4366     if (event.action != AxisAction::BEGIN && formEventMgr) {
4367         formEventMgr->HandleEtsCardAxisEvent(scaleEvent, etsSerializedGesture);
4368     }
4369 
4370     DispatchAxisEventToDragDropManager(event, node, etsSerializedGesture);
4371     // when api >= 15, do not block end and cancel action.
4372     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FIFTEEN)) {
4373         if (event.action != AxisAction::NONE) {
4374             eventManager_->AxisTest(scaleEvent, node);
4375             eventManager_->DispatchAxisEventNG(scaleEvent);
4376         }
4377     } else {
4378         if (event.action == AxisAction::BEGIN || event.action == AxisAction::UPDATE) {
4379             eventManager_->AxisTest(scaleEvent, node);
4380             eventManager_->DispatchAxisEventNG(scaleEvent);
4381         }
4382     }
4383     if (postEventManager_) {
4384         postEventManager_->SetPassThroughResult(eventManager_->GetPassThroughResult());
4385     }
4386     if (event.action == AxisAction::BEGIN && formEventMgr) {
4387         formEventMgr->HandleEtsCardAxisEvent(scaleEvent, etsSerializedGesture);
4388     }
4389     if (scaleEvent.action == AxisAction::BEGIN) {
4390         TAG_LOGD(AceLogTag::ACE_MOUSE, "Slide Axis Begin");
4391         ResSchedReport::GetInstance().OnAxisEvent(scaleEvent);
4392     } else if (scaleEvent.verticalAxis == 0 && scaleEvent.horizontalAxis == 0) {
4393         TAG_LOGD(AceLogTag::ACE_MOUSE, "Slide Axis End");
4394         ResSchedReport::GetInstance().ResSchedDataReport("axis_off");
4395     } else {
4396         TAG_LOGD(AceLogTag::ACE_MOUSE, "Slide Axis Update");
4397         ResSchedReport::GetInstance().OnAxisEvent(scaleEvent);
4398     }
4399     auto mouseEvent = ConvertAxisToMouse(event);
4400     OnMouseMoveEventForAxisEvent(mouseEvent, node);
4401     if (formEventMgr && ((scaleEvent.action == AxisAction::END) || (scaleEvent.action == AxisAction::CANCEL))) {
4402         formEventMgr->RemoveEtsCardAxisEventCallback(event.id);
4403         formEventMgr->RemoveEtsCardTouchEventCallback(event.id);
4404     }
4405 }
4406 
DispatchAxisEventToDragDropManager(const AxisEvent & event,const RefPtr<FrameNode> & node,SerializedGesture & etsSerializedGesture)4407 void PipelineContext::DispatchAxisEventToDragDropManager(const AxisEvent& event, const RefPtr<FrameNode>& node,
4408     SerializedGesture& etsSerializedGesture)
4409 {
4410     auto scaleEvent = event.CreateScaleEvent(viewScale_);
4411     auto dragManager = GetDragDropManager();
4412     if (dragManager && !dragManager->IsDragged()) {
4413         if (event.action == AxisAction::BEGIN) {
4414             isBeforeDragHandleAxis_ = true;
4415             TouchRestrict touchRestrict { TouchRestrict::NONE };
4416             touchRestrict.sourceType = event.sourceType;
4417             touchRestrict.hitTestType = SourceType::TOUCH;
4418             touchRestrict.inputEventType = InputEventType::AXIS;
4419             // If received rotate event, no need to touchtest.
4420             if (!event.isRotationEvent) {
4421                 eventManager_->TouchTest(scaleEvent, node, touchRestrict);
4422                 auto axisTouchTestResults_ = eventManager_->GetAxisTouchTestResults();
4423                 auto formEventMgr = this->GetFormEventManager();
4424                 if (formEventMgr) {
4425                     formEventMgr->HandleEtsCardTouchEvent(touchRestrict.touchEvent, etsSerializedGesture);
4426                 }
4427                 auto formGestureMgr =  this->GetFormGestureManager();
4428                 if (formGestureMgr) {
4429                     formGestureMgr->LinkGesture(event, this, node, axisTouchTestResults_,
4430                         etsSerializedGesture, eventManager_);
4431                 }
4432             }
4433         }
4434         eventManager_->DispatchTouchEvent(scaleEvent);
4435     } else if (isBeforeDragHandleAxis_ && (event.action == AxisAction::END || event.action == AxisAction::CANCEL)) {
4436         eventManager_->DispatchTouchEvent(scaleEvent);
4437         isBeforeDragHandleAxis_ = false;
4438     }
4439 }
4440 
OnMouseMoveEventForAxisEvent(const MouseEvent & event,const RefPtr<NG::FrameNode> & node)4441 void PipelineContext::OnMouseMoveEventForAxisEvent(const MouseEvent& event, const RefPtr<NG::FrameNode>& node)
4442 {
4443     if (event.action != MouseAction::MOVE || event.button != MouseButton::NONE_BUTTON) {
4444         return;
4445     }
4446     CHECK_RUN_ON(UI);
4447     UpdateLastMoveEvent(event);
4448     auto manager = GetDragDropManager();
4449     if (manager) {
4450         manager->SetIsDragCancel(false);
4451     } else {
4452         TAG_LOGW(AceLogTag::ACE_INPUTTRACKING, "InputTracking id:%{public}d, OnMouseEvent GetDragDropManager is null",
4453             event.touchEventId);
4454     }
4455     auto touchPoint = event.CreateTouchPoint();
4456     auto scalePoint = touchPoint.CreateScalePoint(GetViewScale());
4457     auto rootOffset = GetRootRect().GetOffset();
4458     eventManager_->HandleGlobalEventNG(scalePoint, selectOverlayManager_, rootOffset);
4459     CHECK_NULL_VOID(node);
4460     auto scaleEvent = event.CreateScaleEvent(viewScale_);
4461     TouchRestrict touchRestrict { TouchRestrict::NONE };
4462     touchRestrict.sourceType = event.sourceType;
4463     touchRestrict.hitTestType = SourceType::MOUSE;
4464     touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
4465     eventManager_->MouseTest(scaleEvent, node, touchRestrict);
4466     eventManager_->DispatchMouseEventNG(scaleEvent);
4467     eventManager_->DispatchMouseHoverEventNG(scaleEvent);
4468     eventManager_->DispatchMouseHoverAnimationNG(scaleEvent);
4469     accessibilityManagerNG_->HandleAccessibilityHoverEvent(node, scaleEvent);
4470     RequestFrame();
4471 }
4472 
HasDifferentDirectionGesture() const4473 bool PipelineContext::HasDifferentDirectionGesture() const
4474 {
4475     CHECK_NULL_RETURN(eventManager_, false);
4476     return eventManager_->HasDifferentDirectionGesture();
4477 }
4478 
AddVisibleAreaChangeNode(const int32_t nodeId)4479 void PipelineContext::AddVisibleAreaChangeNode(const int32_t nodeId)
4480 {
4481     onVisibleAreaChangeNodeIds_.emplace(nodeId);
4482     auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(nodeId));
4483     CHECK_NULL_VOID(frameNode);
4484     frameNode->ClearCachedIsFrameDisappear();
4485 }
4486 
AddVisibleAreaChangeNode(const RefPtr<FrameNode> & node,const std::vector<double> & ratios,const VisibleRatioCallback & callback,bool isUserCallback,bool isCalculateInnerClip)4487 void PipelineContext::AddVisibleAreaChangeNode(const RefPtr<FrameNode>& node,
4488     const std::vector<double>& ratios, const VisibleRatioCallback& callback, bool isUserCallback,
4489     bool isCalculateInnerClip)
4490 {
4491     CHECK_NULL_VOID(node);
4492     VisibleCallbackInfo addInfo;
4493     addInfo.callback = callback;
4494     addInfo.isCurrentVisible = false;
4495     onVisibleAreaChangeNodeIds_.emplace(node->GetId());
4496     node->ClearCachedIsFrameDisappear();
4497     if (isUserCallback) {
4498         node->SetVisibleAreaUserCallback(ratios, addInfo);
4499     } else {
4500         node->SetVisibleAreaInnerCallback(ratios, addInfo, isCalculateInnerClip);
4501     }
4502 }
4503 
RemoveVisibleAreaChangeNode(int32_t nodeId)4504 void PipelineContext::RemoveVisibleAreaChangeNode(int32_t nodeId)
4505 {
4506     auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(nodeId));
4507     if (frameNode) {
4508         frameNode->ClearCachedIsFrameDisappear();
4509     }
4510 
4511     onVisibleAreaChangeNodeIds_.erase(nodeId);
4512 }
4513 
HandleVisibleAreaChangeEvent(uint64_t nanoTimestamp)4514 void PipelineContext::HandleVisibleAreaChangeEvent(uint64_t nanoTimestamp)
4515 {
4516     if (onVisibleAreaChangeNodeIds_.empty()) {
4517         return;
4518     }
4519     auto nodes = FrameNode::GetNodesById(onVisibleAreaChangeNodeIds_);
4520     ACE_SCOPED_TRACE("HandleVisibleAreaChangeEvent_nodeCount:%d", static_cast<int32_t>(nodes.size()));
4521     for (auto&& frameNode : nodes) {
4522         frameNode->TriggerVisibleAreaChangeCallback(nanoTimestamp, false, isDisappearChangeNodeMinDepth_);
4523     }
4524 
4525     isDisappearChangeNodeMinDepth_ = 0;
4526 }
4527 
AddOnAreaChangeNode(int32_t nodeId)4528 void PipelineContext::AddOnAreaChangeNode(int32_t nodeId)
4529 {
4530     onAreaChangeNodeIds_.emplace(nodeId);
4531     isOnAreaChangeNodesCacheVaild_ = false;
4532     auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(nodeId));
4533     CHECK_NULL_VOID(frameNode);
4534     frameNode->ClearCachedGlobalOffset();
4535 }
4536 
RemoveOnAreaChangeNode(int32_t nodeId)4537 void PipelineContext::RemoveOnAreaChangeNode(int32_t nodeId)
4538 {
4539     auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(nodeId));
4540     if (frameNode) {
4541         frameNode->ClearCachedGlobalOffset();
4542     }
4543 
4544     onAreaChangeNodeIds_.erase(nodeId);
4545     isOnAreaChangeNodesCacheVaild_ = false;
4546 }
4547 
HasOnAreaChangeNode(int32_t nodeId)4548 bool PipelineContext::HasOnAreaChangeNode(int32_t nodeId)
4549 {
4550     return onAreaChangeNodeIds_.find(nodeId) != onAreaChangeNodeIds_.end();
4551 }
4552 
HandleOnAreaChangeEvent(uint64_t nanoTimestamp)4553 void PipelineContext::HandleOnAreaChangeEvent(uint64_t nanoTimestamp)
4554 {
4555     if (onAreaChangeNodeIds_.empty()) {
4556         return;
4557     }
4558     auto nodes = FrameNode::GetNodesById(onAreaChangeNodeIds_);
4559     ACE_SCOPED_TRACE("HandleOnAreaChangeEvent_nodeCount:%d", static_cast<int32_t>(nodes.size()));
4560     for (auto&& frameNode : nodes) {
4561         frameNode->TriggerOnAreaChangeCallback(nanoTimestamp, areaChangeNodeMinDepth_);
4562     }
4563 
4564     areaChangeNodeMinDepth_ = 0;
4565 }
4566 
UpdateFormLinkInfos()4567 void PipelineContext::UpdateFormLinkInfos()
4568 {
4569     if (formLinkInfoUpdateHandler_ && !formLinkInfoMap_.empty()) {
4570         std::vector<std::string> formLinkInfos;
4571         for (auto iter = formLinkInfoMap_.rbegin(); iter != formLinkInfoMap_.rend(); ++iter) {
4572             auto info = iter->second;
4573             formLinkInfos.push_back(info);
4574         }
4575         formLinkInfoUpdateHandler_(formLinkInfos);
4576     }
4577 }
4578 
OnShow()4579 void PipelineContext::OnShow()
4580 {
4581     CHECK_RUN_ON(UI);
4582     onShow_ = true;
4583     isNeedCallbackAreaChange_ = true;
4584     window_->OnShow();
4585     PerfMonitor::GetPerfMonitor()->SetAppForeground(true);
4586     RequestFrame();
4587     FlushWindowStateChangedCallback(true);
4588     AccessibilityEvent event;
4589     event.windowChangeTypes = WindowUpdateType::WINDOW_UPDATE_ACTIVE;
4590     event.type = AccessibilityEventType::PAGE_CHANGE;
4591     SendEventToAccessibility(event);
4592 }
4593 
OnHide()4594 void PipelineContext::OnHide()
4595 {
4596     CHECK_RUN_ON(UI);
4597     NotifyDragOnHide();
4598     onShow_ = false;
4599     isNeedCallbackAreaChange_ = true;
4600     window_->OnHide();
4601     PerfMonitor::GetPerfMonitor()->SetAppForeground(false);
4602     RequestFrame();
4603     OnVirtualKeyboardAreaChange(Rect());
4604     FlushWindowStateChangedCallback(false);
4605     AccessibilityEvent event;
4606     event.type = AccessibilityEventType::PAGE_CLOSE;
4607     SendEventToAccessibility(event);
4608     memoryMgr_->PostMemRecycleTask();
4609 }
4610 
WindowFocus(bool isFocus)4611 void PipelineContext::WindowFocus(bool isFocus)
4612 {
4613     CHECK_RUN_ON(UI);
4614     onFocus_ = isFocus;
4615     if (!isFocus) {
4616         TAG_LOGI(AceLogTag::ACE_FOCUS, "Window: %{public}d lost focus.", windowId_);
4617         RestoreDefault(0, MouseStyleChangeReason::WINDOW_LOST_FOCUS_RESET_MOUSESTYLE);
4618         RootLostFocus(BlurReason::WINDOW_BLUR);
4619         NotifyPopupDismiss();
4620     } else {
4621         TAG_LOGI(AceLogTag::ACE_FOCUS, "Window: %{public}d get focus.", windowId_);
4622 
4623         isWindowHasFocused_ = true;
4624         InputMethodManager::GetInstance()->SetWindowFocus(true);
4625     }
4626     GetOrCreateFocusManager()->WindowFocus(isFocus);
4627     FlushWindowFocusChangedCallback(isFocus);
4628 }
4629 
WindowActivate(bool isActive)4630 void PipelineContext::WindowActivate(bool isActive)
4631 {
4632     CHECK_RUN_ON(UI);
4633     onActive_ = isActive;
4634     FlushWindowActivateChangedCallback(isActive);
4635 }
4636 
ContainerModalUnFocus()4637 void PipelineContext::ContainerModalUnFocus()
4638 {
4639     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4640         return;
4641     }
4642     CHECK_NULL_VOID(rootNode_);
4643     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4644     CHECK_NULL_VOID(containerNode);
4645     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4646     CHECK_NULL_VOID(containerPattern);
4647     containerPattern->OnWindowForceUnfocused();
4648 }
4649 
ShowContainerTitle(bool isShow,bool hasDeco,bool needUpdate)4650 void PipelineContext::ShowContainerTitle(bool isShow, bool hasDeco, bool needUpdate)
4651 {
4652     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4653         return;
4654     }
4655     CHECK_NULL_VOID(rootNode_);
4656     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4657     CHECK_NULL_VOID(containerNode);
4658     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4659     CHECK_NULL_VOID(containerPattern);
4660     containerPattern->ShowTitle(isShow, hasDeco, needUpdate);
4661     isShowTitle_ = isShow && hasDeco;
4662     auto titleMgr = containerPattern->GetTitleManager();
4663     if (titleMgr) {
4664         if (isShowTitle_) {
4665             titleMgr->UpdateTargetNodesBarMargin();
4666         } else {
4667             titleMgr->ResetExpandStackNode();
4668         }
4669     }
4670 }
4671 
UpdateTitleInTargetPos(bool isShow,int32_t height)4672 void PipelineContext::UpdateTitleInTargetPos(bool isShow, int32_t height)
4673 {
4674     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4675         return;
4676     }
4677     CHECK_NULL_VOID(rootNode_);
4678     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4679     CHECK_NULL_VOID(containerNode);
4680     auto containerPattern = containerNode->GetPattern<ContainerModalPatternEnhance>();
4681     CHECK_NULL_VOID(containerPattern);
4682     containerPattern->UpdateTitleInTargetPos(isShow, height);
4683 }
4684 
4685 
SetContainerWindow(bool isShow,RRect & rRect)4686 void PipelineContext::SetContainerWindow(bool isShow, RRect& rRect)
4687 {
4688 #ifdef ENABLE_ROSEN_BACKEND
4689     if (!IsJsCard()) {
4690         auto window = GetWindow();
4691         if (window) {
4692             auto rect = rRect.GetRect();
4693             OHOS::Rosen::RectF rosenRectF = {rect.GetOffset().GetX(), rect.GetOffset().GetY(),
4694                 rect.Width(), rect.Height()};
4695             auto radiusValueX = rRect.GetCorner().topLeftRadius.GetX().Value();
4696             auto radiusValueY = rRect.GetCorner().topLeftRadius.GetY().Value();
4697 
4698             auto rosenRRect = OHOS::Rosen::RRect(rosenRectF, radiusValueX, radiusValueY);
4699             auto rsUIDirector = window->GetRSUIDirector();
4700             if (rsUIDirector) {
4701                 // set container window show state to render service
4702                 TAG_LOGD(AceLogTag::ACE_APPBAR, "SetContainerWindow: isShow=%{public}d; "
4703                     "x=%{public}f, y=%{public}f, width=%{public}f, hight=%{public}f, radiusValueX=%{public}f.",
4704                     isShow, rect.GetOffset().GetX(), rect.GetOffset().GetY(),
4705                     rect.Width(), rect.Height(), radiusValueX);
4706                 rsUIDirector->SetContainerWindow(isShow, rosenRRect);
4707             }
4708         }
4709     }
4710 #endif
4711 }
4712 
SetAppBgColor(const Color & color)4713 void PipelineContext::SetAppBgColor(const Color& color)
4714 {
4715     appBgColor_ = color;
4716 #ifdef ENABLE_ROSEN_BACKEND
4717     std::shared_ptr<Rosen::RSUIDirector> rsUIDirector;
4718     if (!IsJsCard()) {
4719         rsUIDirector = GetRSUIDirector();
4720         if (rsUIDirector) {
4721             RSTransactionBegin(rsUIDirector);
4722             rsUIDirector->SetAbilityBGAlpha(appBgColor_.GetAlpha());
4723             RSTransactionCommit(rsUIDirector);
4724         }
4725     }
4726 #endif
4727     CHECK_NULL_VOID(stageManager_);
4728     auto stage = stageManager_->GetStageNode();
4729     CHECK_NULL_VOID(stage);
4730     auto renderContext = stage->GetRenderContext();
4731     CHECK_NULL_VOID(renderContext);
4732     renderContext->UpdateBackgroundColor(color);
4733 }
4734 
SetAppTitle(const std::string & title)4735 void PipelineContext::SetAppTitle(const std::string& title)
4736 {
4737     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4738         return;
4739     }
4740     CHECK_NULL_VOID(rootNode_);
4741     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4742     CHECK_NULL_VOID(containerNode);
4743     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4744     CHECK_NULL_VOID(containerPattern);
4745     containerPattern->SetAppTitle(title);
4746 }
4747 
SetAppIcon(const RefPtr<PixelMap> & icon)4748 void PipelineContext::SetAppIcon(const RefPtr<PixelMap>& icon)
4749 {
4750     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
4751         return;
4752     }
4753     CHECK_NULL_VOID(rootNode_);
4754     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
4755     CHECK_NULL_VOID(containerNode);
4756     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
4757     CHECK_NULL_VOID(containerPattern);
4758     containerPattern->SetAppIcon(icon);
4759 }
4760 
FlushReload(const ConfigurationChange & configurationChange,bool fullUpdate)4761 void PipelineContext::FlushReload(const ConfigurationChange& configurationChange, bool fullUpdate)
4762 {
4763      auto changeTask = [weak = WeakClaim(this), configurationChange,
4764         weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager_)), fullUpdate]() {
4765         auto pipeline = weak.Upgrade();
4766         CHECK_NULL_VOID(pipeline);
4767         if (configurationChange.IsNeedUpdate() || configurationChange.iconUpdate) {
4768             auto rootNode = pipeline->GetRootElement();
4769             rootNode->UpdateConfigurationUpdate(configurationChange);
4770             auto overlay = weakOverlayManager.Upgrade();
4771             if (overlay) {
4772                 overlay->ReloadBuilderNodeConfig();
4773             }
4774         }
4775         if (fullUpdate && configurationChange.IsNeedUpdate()) {
4776             CHECK_NULL_VOID(pipeline->stageManager_);
4777             pipeline->SetIsReloading(true);
4778             pipeline->stageManager_->ReloadStage();
4779             pipeline->SetIsReloading(false);
4780             pipeline->FlushUITasks();
4781         }
4782     };
4783     if (!onShow_) {
4784         changeTask();
4785     } else {
4786         AnimationOption option;
4787         const int32_t duration = 400;
4788         option.SetDuration(duration);
4789         option.SetCurve(Curves::FRICTION);
4790         RecycleManager::Notify(configurationChange);
4791         AnimationUtils::Animate(
4792             option,
4793             changeTask,
4794             [weak = WeakClaim(this)]() {
4795                 auto pipeline = weak.Upgrade();
4796                 CHECK_NULL_VOID(pipeline);
4797                 pipeline->OnFlushReloadFinish();
4798             }, nullptr, Claim(this));
4799     }
4800     auto stage = stageManager_->GetStageNode();
4801     CHECK_NULL_VOID(stage);
4802     auto renderContext = stage->GetRenderContext();
4803     CHECK_NULL_VOID(renderContext);
4804     renderContext->UpdateWindowBlur();
4805 }
4806 
Destroy()4807 void PipelineContext::Destroy()
4808 {
4809     CHECK_RUN_ON(UI);
4810     SetDestroyed();
4811     rootNode_->DetachFromMainTree();
4812     std::set<WeakPtr<UINode>> nodeSet;
4813     std::swap(nodeSet, attachedNodeSet_);
4814     for (const auto& node : nodeSet) {
4815         auto illegalNode = node.Upgrade();
4816         if (illegalNode) {
4817             illegalNode->DetachFromMainTree();
4818         }
4819     }
4820     rootNode_->FireCustomDisappear();
4821     taskScheduler_->CleanUp();
4822     scheduleTasks_.clear();
4823     dirtyNodes_.clear();
4824     rootNode_.Reset();
4825     accessibilityManagerNG_.Reset();
4826     stageManager_.Reset();
4827     if (overlayManager_) {
4828         overlayManager_->ClearUIExtensionNode();
4829     }
4830     overlayManager_.Reset();
4831     sharedTransitionManager_.Reset();
4832     dragDropManager_.Reset();
4833     TAG_LOGI(AceLogTag::ACE_DRAG, "PipelineContext::Destroy Reset dragDropManager_");
4834     focusManager_.Reset();
4835     selectOverlayManager_.Reset();
4836     fullScreenManager_.Reset();
4837     memoryMgr_.Reset();
4838     nodeToMousePoints_.clear();
4839     nodeToPointEvent_.clear();
4840     touchEvents_.clear();
4841     mouseEvents_.clear();
4842     dragEvents_.clear();
4843     buildFinishCallbacks_.clear();
4844     onWindowStateChangedCallbacks_.clear();
4845     onWindowFocusChangedCallbacks_.clear();
4846     nodesToNotifyMemoryLevel_.clear();
4847     dirtyFocusNode_.Reset();
4848     dirtyFocusScope_.Reset();
4849     needRenderNode_.clear();
4850     dirtyRequestFocusNode_.Reset();
4851     auto formEventMgr = this->GetFormEventManager();
4852     if (formEventMgr) {
4853         formEventMgr->ClearEtsCardTouchEventCallback();
4854         formEventMgr->ClearEtsCardAxisEventCallback();
4855     }
4856 #ifdef WINDOW_SCENE_SUPPORTED
4857     uiExtensionManager_.Reset();
4858 #endif
4859     uiContextImpl_.Reset();
4860     PipelineBase::Destroy();
4861 }
4862 
AddBuildFinishCallBack(std::function<void ()> && callback)4863 void PipelineContext::AddBuildFinishCallBack(std::function<void()>&& callback)
4864 {
4865     buildFinishCallbacks_.emplace_back(std::move(callback));
4866 }
4867 
AddWindowStateChangedCallback(int32_t nodeId)4868 void PipelineContext::AddWindowStateChangedCallback(int32_t nodeId)
4869 {
4870     if (!CheckThreadSafe()) {
4871         LOGW("AddWindowStateChangedCallback doesn't run on UI thread!");
4872     }
4873     onWindowStateChangedCallbacks_.emplace(nodeId);
4874 }
4875 
RemoveWindowStateChangedCallback(int32_t nodeId)4876 void PipelineContext::RemoveWindowStateChangedCallback(int32_t nodeId)
4877 {
4878     if (!CheckThreadSafe()) {
4879         LOGW("RemoveWindowStateChangedCallback doesn't run on UI thread!");
4880     }
4881     onWindowStateChangedCallbacks_.erase(nodeId);
4882 }
4883 
FlushWindowStateChangedCallback(bool isShow)4884 void PipelineContext::FlushWindowStateChangedCallback(bool isShow)
4885 {
4886     if (!CheckThreadSafe()) {
4887         LOGW("FlushWindowStateChangedCallback doesn't run on UI thread!");
4888     }
4889     std::set<int32_t> onWindowStateChangedCallbacks;
4890     std::swap(onWindowStateChangedCallbacks, onWindowStateChangedCallbacks_);
4891     auto iter = onWindowStateChangedCallbacks.begin();
4892     while (iter != onWindowStateChangedCallbacks.end()) {
4893         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
4894         if (!node) {
4895             iter = onWindowStateChangedCallbacks.erase(iter);
4896         } else {
4897             if (isShow) {
4898                 node->OnWindowShow();
4899             } else {
4900                 node->OnWindowHide();
4901             }
4902             ++iter;
4903         }
4904     }
4905     std::swap(onWindowStateChangedCallbacks, onWindowStateChangedCallbacks_);
4906     HandleVisibleAreaChangeEvent(GetTimeFromExternalTimer());
4907     HandleSubwindow(isShow);
4908 }
4909 
AddWindowFocusChangedCallback(int32_t nodeId)4910 void PipelineContext::AddWindowFocusChangedCallback(int32_t nodeId)
4911 {
4912     onWindowFocusChangedCallbacks_.emplace(nodeId);
4913 }
4914 
RemoveWindowFocusChangedCallback(int32_t nodeId)4915 void PipelineContext::RemoveWindowFocusChangedCallback(int32_t nodeId)
4916 {
4917     onWindowFocusChangedCallbacks_.erase(nodeId);
4918 }
4919 
FlushWindowFocusChangedCallback(bool isFocus)4920 void PipelineContext::FlushWindowFocusChangedCallback(bool isFocus)
4921 {
4922     auto iter = onWindowFocusChangedCallbacks_.begin();
4923     while (iter != onWindowFocusChangedCallbacks_.end()) {
4924         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
4925         if (!node) {
4926             iter = onWindowFocusChangedCallbacks_.erase(iter);
4927         } else {
4928             if (isFocus) {
4929                 node->OnWindowFocused();
4930             } else {
4931                 node->OnWindowUnfocused();
4932             }
4933             ++iter;
4934         }
4935     }
4936 }
4937 
AddWindowActivateChangedCallback(int32_t nodeId)4938 void PipelineContext::AddWindowActivateChangedCallback(int32_t nodeId)
4939 {
4940     onWindowActivateChangedCallbacks_.emplace(nodeId);
4941 }
4942 
RemoveWindowActivateChangedCallback(int32_t nodeId)4943 void PipelineContext::RemoveWindowActivateChangedCallback(int32_t nodeId)
4944 {
4945     onWindowActivateChangedCallbacks_.erase(nodeId);
4946 }
4947 
FlushWindowActivateChangedCallback(bool isActivate)4948 void PipelineContext::FlushWindowActivateChangedCallback(bool isActivate)
4949 {
4950     auto iter = onWindowActivateChangedCallbacks_.begin();
4951     while (iter != onWindowActivateChangedCallbacks_.end()) {
4952         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
4953         if (!node) {
4954             iter = onWindowActivateChangedCallbacks_.erase(iter);
4955         } else {
4956             if (isActivate) {
4957                 node->OnWindowActivated();
4958             } else {
4959                 node->OnWindowDeactivated();
4960             }
4961             ++iter;
4962         }
4963     }
4964 }
4965 
AddWindowSizeChangeCallback(int32_t nodeId)4966 void PipelineContext::AddWindowSizeChangeCallback(int32_t nodeId)
4967 {
4968     onWindowSizeChangeCallbacks_.emplace_back(nodeId);
4969 }
4970 
RemoveWindowSizeChangeCallback(int32_t nodeId)4971 void PipelineContext::RemoveWindowSizeChangeCallback(int32_t nodeId)
4972 {
4973     onWindowSizeChangeCallbacks_.remove(nodeId);
4974 }
4975 
AddWindowSizeDragEndCallback(std::function<void ()> && callback)4976 void PipelineContext::AddWindowSizeDragEndCallback(std::function<void()>&& callback)
4977 {
4978     onWindowSizeDragEndCallbacks_.emplace_back(std::move(callback));
4979 }
4980 
SetIsWindowSizeDragging(bool isDragging)4981 void PipelineContext::SetIsWindowSizeDragging(bool isDragging)
4982 {
4983     isWindowSizeDragging_ = isDragging;
4984     if (!isDragging) {
4985         decltype(onWindowSizeDragEndCallbacks_) dragEndCallbacks(std::move(onWindowSizeDragEndCallbacks_));
4986         for (const auto& func : dragEndCallbacks) {
4987             if (func) {
4988                 func();
4989             }
4990         }
4991     }
4992 }
4993 
AddNavigationNode(int32_t pageId,WeakPtr<UINode> navigationNode)4994 void PipelineContext::AddNavigationNode(int32_t pageId, WeakPtr<UINode> navigationNode)
4995 {
4996     CHECK_RUN_ON(UI);
4997     pageToNavigationNodes_[pageId].push_back(navigationNode);
4998 }
4999 
RemoveNavigationNode(int32_t pageId,int32_t nodeId)5000 void PipelineContext::RemoveNavigationNode(int32_t pageId, int32_t nodeId)
5001 {
5002     CHECK_RUN_ON(UI);
5003     auto it = pageToNavigationNodes_.find(pageId);
5004     if (it != pageToNavigationNodes_.end() && !it->second.empty()) {
5005         for (auto iter = it->second.begin(); iter != it->second.end();) {
5006             auto navigationNode = AceType::DynamicCast<NavigationGroupNode>((*iter).Upgrade());
5007             if (navigationNode && navigationNode->GetId() == nodeId) {
5008                 iter = it->second.erase(iter);
5009             } else {
5010                 iter++;
5011             }
5012         }
5013     }
5014 }
5015 
FirePageChanged(int32_t pageId,bool isOnShow)5016 void PipelineContext::FirePageChanged(int32_t pageId, bool isOnShow)
5017 {
5018     CHECK_RUN_ON(UI);
5019     auto iter = pageToNavigationNodes_.find(pageId);
5020     if (iter == pageToNavigationNodes_.end()) {
5021         return;
5022     }
5023     for (auto navigationNode : iter->second) {
5024         NavigationPattern::FireNavigationChange(navigationNode.Upgrade(), isOnShow, true);
5025     }
5026 }
5027 
FlushWindowSizeChangeCallback(int32_t width,int32_t height,WindowSizeChangeReason type)5028 void PipelineContext::FlushWindowSizeChangeCallback(int32_t width, int32_t height, WindowSizeChangeReason type)
5029 {
5030     std::list<int32_t> callbacks;
5031     std::swap(callbacks, onWindowSizeChangeCallbacks_);
5032     auto iter = callbacks.begin();
5033     while (iter != callbacks.end()) {
5034         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
5035         if (!node) {
5036             iter = callbacks.erase(iter);
5037         } else {
5038             node->OnWindowSizeChanged(width, height, type);
5039             ++iter;
5040         }
5041     }
5042     std::swap(callbacks, onWindowSizeChangeCallbacks_);
5043 }
5044 
OnDragEvent(const DragPointerEvent & pointerEvent,DragEventAction action,const RefPtr<NG::FrameNode> & node)5045 void PipelineContext::OnDragEvent(const DragPointerEvent& pointerEvent, DragEventAction action,
5046     const RefPtr<NG::FrameNode>& node)
5047 {
5048     auto manager = GetDragDropManager();
5049     CHECK_NULL_VOID(manager);
5050     auto container = Container::Current();
5051     if (container && container->IsSceneBoardWindow()) {
5052         if (!manager->IsDragged() && manager->IsWindowConsumed()) {
5053             manager->SetIsWindowConsumed(false);
5054             return;
5055         }
5056     }
5057 
5058     if (action == DragEventAction::DRAG_EVENT_OUT || action == DragEventAction::DRAG_EVENT_END ||
5059         action == DragEventAction::DRAG_EVENT_PULL_THROW || action == DragEventAction::DRAG_EVENT_PULL_CANCEL) {
5060         if (!eventManager_->touchDelegatesMap_.empty()) {
5061             eventManager_->UnregisterTouchDelegate(pointerEvent.pointerId);
5062         }
5063         lastDragTime_ = GetTimeFromExternalTimer();
5064         CompensatePointerMoveEvent(pointerEvent, node);
5065         manager->HandleDragEvent(pointerEvent, action, node);
5066         return;
5067     }
5068     manager->HandleDragEvent(pointerEvent, action, node);
5069     if (action == DragEventAction::DRAG_EVENT_MOVE) {
5070         manager->SetDragAnimationPointerEvent(pointerEvent, node);
5071         dragEvents_[node].emplace_back(pointerEvent);
5072         RequestFrame();
5073     }
5074     if (action != DragEventAction::DRAG_EVENT_MOVE &&
5075         historyPointsEventById_.find(pointerEvent.pointerId) != historyPointsEventById_.end()) {
5076         historyPointsEventById_.erase(pointerEvent.pointerId);
5077     }
5078 }
5079 
NotifyDragTouchEvent(const TouchEvent & event,const RefPtr<NG::FrameNode> & node)5080 void PipelineContext::NotifyDragTouchEvent(const TouchEvent& event, const RefPtr<NG::FrameNode>& node)
5081 {
5082     auto manager = GetDragDropManager();
5083     CHECK_NULL_VOID(manager);
5084     manager->HandleTouchEvent(event, node);
5085 }
5086 
NotifyDragMouseEvent(const MouseEvent & event)5087 void PipelineContext::NotifyDragMouseEvent(const MouseEvent& event)
5088 {
5089     auto manager = GetDragDropManager();
5090     CHECK_NULL_VOID(manager);
5091     manager->HandleMouseEvent(event);
5092 }
5093 
NotifyDragOnHide()5094 void PipelineContext::NotifyDragOnHide()
5095 {
5096     auto manager = GetDragDropManager();
5097     CHECK_NULL_VOID(manager);
5098     manager->HandlePipelineOnHide();
5099     manager->OnDragAsyncEnd();
5100 }
5101 
CompensatePointerMoveEvent(const DragPointerEvent & event,const RefPtr<FrameNode> & node)5102 void PipelineContext::CompensatePointerMoveEvent(const DragPointerEvent& event, const RefPtr<FrameNode>& node)
5103 {
5104     auto manager = GetDragDropManager();
5105     std::string extraInfo = manager->GetExtraInfo();
5106     if (CompensatePointerMoveEventFromUnhandledEvents(event, node)) {
5107         return;
5108     }
5109     auto lastEventIter = nodeToPointEvent_.find(node);
5110     if (lastEventIter == nodeToPointEvent_.end() || lastEventIter->second.empty()) {
5111         return;
5112     }
5113     DragPointerEvent pointerEvent = lastEventIter->second.back();
5114     auto iter = eventManager_->GetLastDispatchTime().find(pointerEvent.pointerEventId);
5115     if (iter != eventManager_->GetLastDispatchTime().end()) {
5116         if (static_cast<uint64_t>(pointerEvent.time.time_since_epoch().count()) > iter->second) {
5117             manager->OnDragMove(pointerEvent, extraInfo, node);
5118         }
5119     }
5120 }
5121 
CompensatePointerMoveEventFromUnhandledEvents(const DragPointerEvent & event,const RefPtr<FrameNode> & node)5122 bool PipelineContext::CompensatePointerMoveEventFromUnhandledEvents(
5123     const DragPointerEvent& event, const RefPtr<FrameNode>& node)
5124 {
5125     auto manager = GetDragDropManager();
5126     std::string extraInfo = manager->GetExtraInfo();
5127     std::vector<DragPointerEvent> history;
5128     if (dragEvents_.empty()) {
5129         return false;
5130     }
5131 
5132     auto iter = dragEvents_.find(node);
5133     if (iter == dragEvents_.end()) {
5134         return false;
5135     }
5136     for (auto dragIter = iter->second.begin(); dragIter != iter->second.end();) {
5137         if (event.pointerEventId == dragIter->pointerEventId) {
5138             history.emplace_back(*dragIter);
5139             dragIter = iter->second.erase(dragIter);
5140         } else {
5141             dragIter++;
5142         }
5143     }
5144     dragEvents_.erase(iter);
5145 
5146     if (history.empty()) {
5147         return false;
5148     }
5149 
5150     auto lastePointerEvent(history.back());
5151     lastePointerEvent.history.swap(history);
5152     manager->OnDragMove(lastePointerEvent, extraInfo, node);
5153     return true;
5154 }
5155 
AddNodesToNotifyMemoryLevel(int32_t nodeId)5156 void PipelineContext::AddNodesToNotifyMemoryLevel(int32_t nodeId)
5157 {
5158     nodesToNotifyMemoryLevel_.emplace_back(nodeId);
5159 }
5160 
RemoveNodesToNotifyMemoryLevel(int32_t nodeId)5161 void PipelineContext::RemoveNodesToNotifyMemoryLevel(int32_t nodeId)
5162 {
5163     nodesToNotifyMemoryLevel_.remove(nodeId);
5164 }
5165 
NotifyMemoryLevel(int32_t level)5166 void PipelineContext::NotifyMemoryLevel(int32_t level)
5167 {
5168     auto iter = nodesToNotifyMemoryLevel_.begin();
5169     while (iter != nodesToNotifyMemoryLevel_.end()) {
5170         auto node = ElementRegister::GetInstance()->GetUINodeById(*iter);
5171         if (!node) {
5172             iter = nodesToNotifyMemoryLevel_.erase(iter);
5173         } else {
5174             node->OnNotifyMemoryLevel(level);
5175             ++iter;
5176         }
5177     }
5178     if (window_) {
5179         window_->FlushTasks();
5180     }
5181 }
AddPredictTask(PredictTask && task)5182 void PipelineContext::AddPredictTask(PredictTask&& task)
5183 {
5184     taskScheduler_->AddPredictTask(std::move(task));
5185     RequestFrame();
5186 }
5187 
AddFrameCallback(FrameCallbackFunc && frameCallbackFunc,IdleCallbackFunc && idleCallbackFunc,int64_t delayMillis)5188 void PipelineContext::AddFrameCallback(FrameCallbackFunc&& frameCallbackFunc, IdleCallbackFunc&& idleCallbackFunc,
5189     int64_t delayMillis)
5190 {
5191     if (delayMillis <= 0) {
5192         if (frameCallbackFunc != nullptr) {
5193             frameCallbackFuncs_.emplace_back(std::move(frameCallbackFunc));
5194         }
5195         if (idleCallbackFunc != nullptr) {
5196             idleCallbackFuncs_.emplace_back(std::move(idleCallbackFunc));
5197         }
5198         RequestFrame();
5199         return;
5200     }
5201     auto taskScheduler = GetTaskExecutor();
5202     CHECK_NULL_VOID(taskScheduler);
5203     if (frameCallbackFunc != nullptr) {
5204         taskScheduler->PostDelayedTask(
5205             [weak = WeakClaim(this), callbackFunc = std::move(frameCallbackFunc)]() -> void {
5206                 auto pipeline = weak.Upgrade();
5207                 CHECK_NULL_VOID(pipeline);
5208                 auto callback = const_cast<FrameCallbackFunc&>(callbackFunc);
5209                 pipeline->frameCallbackFuncs_.emplace_back(std::move(callback));
5210                 pipeline->RequestFrame();
5211             },
5212             TaskExecutor::TaskType::UI, delayMillis, "ArkUIPostFrameCallbackFuncDelayed");
5213     }
5214     if (idleCallbackFunc != nullptr) {
5215         taskScheduler->PostDelayedTask(
5216             [weak = WeakClaim(this), callbackFunc = std::move(idleCallbackFunc)]() -> void {
5217                 auto pipeline = weak.Upgrade();
5218                 CHECK_NULL_VOID(pipeline);
5219                 auto callback = const_cast<IdleCallbackFunc&>(callbackFunc);
5220                 pipeline->idleCallbackFuncs_.emplace_back(std::move(callback));
5221                 pipeline->RequestFrame();
5222             },
5223             TaskExecutor::TaskType::UI, delayMillis, "ArkUIPostIdleCallbackFuncDelayed");
5224     }
5225 }
5226 
AddCAPIFrameCallback(FrameCallbackFuncFromCAPI && frameCallbackFuncFromCAPI)5227 void PipelineContext::AddCAPIFrameCallback(FrameCallbackFuncFromCAPI&& frameCallbackFuncFromCAPI)
5228 {
5229     if (frameCallbackFuncFromCAPI != nullptr) {
5230         frameCallbackFuncsFromCAPI_.emplace_back(std::move(frameCallbackFuncFromCAPI));
5231     }
5232 }
5233 
TriggerIdleCallback(int64_t deadline)5234 void PipelineContext::TriggerIdleCallback(int64_t deadline)
5235 {
5236     if (idleCallbackFuncs_.empty()) {
5237         return;
5238     }
5239     int64_t currentTime = GetSysTimestamp();
5240     if (deadline - currentTime < MIN_IDLE_TIME) {
5241         RequestFrame();
5242         return;
5243     }
5244     decltype(idleCallbackFuncs_) tasks(std::move(idleCallbackFuncs_));
5245     for (const auto& IdleCallbackFunc : tasks) {
5246         IdleCallbackFunc(deadline - currentTime, GetFrameCount());
5247         currentTime = GetSysTimestamp();
5248     }
5249 }
5250 
OnIdle(int64_t deadline)5251 void PipelineContext::OnIdle(int64_t deadline)
5252 {
5253     int64_t currentTime = GetSysTimestamp();
5254     if (deadline == 0) {
5255         int64_t lastTaskEndTimestamp = window_->GetLastVsyncEndTimestamp();
5256         if (eventManager_) {
5257             lastTaskEndTimestamp = std::max(lastTaskEndTimestamp, eventManager_->GetLastTouchEventEndTimestamp());
5258         }
5259         if (lastTaskEndTimestamp > 0 && currentTime > lastTaskEndTimestamp
5260             && currentTime - lastTaskEndTimestamp > VSYNC_PERIOD_COUNT * window_->GetVSyncPeriod()) {
5261             auto frontend = weakFrontend_.Upgrade();
5262             if (frontend) {
5263                 frontend->NotifyUIIdle();
5264             }
5265         }
5266     }
5267     if (deadline == 0 || isWindowAnimation_) {
5268         canUseLongPredictTask_ = false;
5269         return;
5270     }
5271     if (canUseLongPredictTask_) {
5272         // check new incoming event after vsync.
5273         if (!touchEvents_.empty()) {
5274             canUseLongPredictTask_ = false;
5275         }
5276     }
5277     CHECK_RUN_ON(UI);
5278     ACE_SCOPED_TRACE_COMMERCIAL("OnIdle, targettime:%" PRId64 "", deadline);
5279     taskScheduler_->FlushPredictTask(deadline - TIME_THRESHOLD, canUseLongPredictTask_);
5280     canUseLongPredictTask_ = false;
5281     currentTime = GetSysTimestamp();
5282     if (currentTime < deadline) {
5283         ElementRegister::GetInstance()->CallJSCleanUpIdleTaskFunc(deadline - currentTime);
5284         frameCountForNotCallJSCleanUp_ = 0;
5285     } else {
5286         frameCountForNotCallJSCleanUp_++;
5287     }
5288 
5289     // Check if there is more than 100 frame which does not execute the CallJSCleanUpIdleTaskFunc
5290     // Force to invoke CallJSCleanUpIdleTaskFunc to make sure no OOM in JS side
5291     if (frameCountForNotCallJSCleanUp_ >= MAX_FRAME_COUNT_WITHOUT_JS_UNREGISTRATION) {
5292         // The longest execution time is half of vsync period
5293         ElementRegister::GetInstance()->CallJSCleanUpIdleTaskFunc(window_->GetVSyncPeriod() / RATIO_OF_VSYNC_PERIOD);
5294         frameCountForNotCallJSCleanUp_ = 0;
5295     }
5296 
5297     TriggerIdleCallback(deadline);
5298     UiNodeGc::ReleaseNodeRawMemory(deadline, taskExecutor_);
5299 }
5300 
Finish(bool) const5301 void PipelineContext::Finish(bool /* autoFinish */) const
5302 {
5303     CHECK_RUN_ON(UI);
5304     if (finishEventHandler_) {
5305         finishEventHandler_();
5306     }
5307 }
5308 
AddAfterLayoutTask(std::function<void ()> && task,bool isFlushInImplicitAnimationTask)5309 void PipelineContext::AddAfterLayoutTask(std::function<void()>&& task, bool isFlushInImplicitAnimationTask)
5310 {
5311     taskScheduler_->AddAfterLayoutTask(std::move(task), isFlushInImplicitAnimationTask);
5312 }
5313 
AddPersistAfterLayoutTask(std::function<void ()> && task)5314 void PipelineContext::AddPersistAfterLayoutTask(std::function<void()>&& task)
5315 {
5316     taskScheduler_->AddPersistAfterLayoutTask(std::move(task));
5317 }
5318 
AddAfterRenderTask(std::function<void ()> && task)5319 void PipelineContext::AddAfterRenderTask(std::function<void()>&& task)
5320 {
5321     taskScheduler_->AddAfterRenderTask(std::move(task));
5322 }
5323 
AddAfterModifierTask(std::function<void ()> && task)5324 void PipelineContext::AddAfterModifierTask(std::function<void()>&& task)
5325 {
5326     taskScheduler_->AddAfterModifierTask(std::move(task));
5327 }
5328 
AddSafeAreaPaddingProcessTask(FrameNode * node)5329 void PipelineContext::AddSafeAreaPaddingProcessTask(FrameNode* node)
5330 {
5331     taskScheduler_->AddSafeAreaPaddingProcessTask(node);
5332 }
5333 
RemoveSafeAreaPaddingProcessTask(FrameNode * node)5334 void PipelineContext::RemoveSafeAreaPaddingProcessTask(FrameNode* node)
5335 {
5336     taskScheduler_->RemoveSafeAreaPaddingProcessTask(node);
5337 }
5338 
FlushSafeAreaPaddingProcess()5339 void PipelineContext::FlushSafeAreaPaddingProcess()
5340 {
5341     taskScheduler_->FlushSafeAreaPaddingProcess();
5342 }
5343 
RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)5344 void PipelineContext::RestoreNodeInfo(std::unique_ptr<JsonValue> nodeInfo)
5345 {
5346     auto child = nodeInfo->GetChild();
5347     while (child->IsValid()) {
5348         auto key = child->GetKey();
5349         auto value = child->GetString();
5350         restoreNodeInfo_.try_emplace(StringUtils::StringToInt(key), value);
5351         child = child->GetNext();
5352     }
5353 }
5354 
GetStoredNodeInfo()5355 std::unique_ptr<JsonValue> PipelineContext::GetStoredNodeInfo()
5356 {
5357     auto jsonNodeInfo = JsonUtil::Create(true);
5358     auto iter = storeNode_.begin();
5359     while (iter != storeNode_.end()) {
5360         auto node = (iter->second).Upgrade();
5361         if (node) {
5362             std::string info = node->ProvideRestoreInfo();
5363             if (!info.empty()) {
5364                 jsonNodeInfo->Put(std::to_string(iter->first).c_str(), info.c_str());
5365             }
5366         }
5367         ++iter;
5368     }
5369     return jsonNodeInfo;
5370 }
5371 
StoreNode(int32_t restoreId,const WeakPtr<FrameNode> & node)5372 void PipelineContext::StoreNode(int32_t restoreId, const WeakPtr<FrameNode>& node)
5373 {
5374     auto ret = storeNode_.try_emplace(restoreId, node);
5375     if (!ret.second) {
5376         storeNode_[restoreId] = node;
5377     }
5378 }
5379 
GetRestoreInfo(int32_t restoreId,std::string & restoreInfo)5380 bool PipelineContext::GetRestoreInfo(int32_t restoreId, std::string& restoreInfo)
5381 {
5382     auto iter = restoreNodeInfo_.find(restoreId);
5383     if (iter != restoreNodeInfo_.end()) {
5384         restoreInfo = iter->second;
5385         restoreNodeInfo_.erase(iter);
5386         return true;
5387     }
5388     return false;
5389 }
5390 
SetContainerButtonHide(bool hideSplit,bool hideMaximize,bool hideMinimize,bool hideClose)5391 void PipelineContext::SetContainerButtonHide(bool hideSplit, bool hideMaximize, bool hideMinimize, bool hideClose)
5392 {
5393     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5394         LOGW("Set app icon failed, Window modal is not container.");
5395         return;
5396     }
5397     CHECK_NULL_VOID(rootNode_);
5398     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
5399     CHECK_NULL_VOID(containerNode);
5400     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5401     CHECK_NULL_VOID(containerPattern);
5402     containerPattern->SetContainerButtonHide(hideSplit, hideMaximize, hideMinimize, hideClose);
5403 }
5404 
EnableContainerModalGesture(bool isEnable)5405 void PipelineContext::EnableContainerModalGesture(bool isEnable)
5406 {
5407     CHECK_NULL_VOID(rootNode_);
5408     const auto &children = rootNode_->GetChildren();
5409     if (children.empty()) {
5410         LOGW("rootNode children list is empty.");
5411         return;
5412     }
5413     auto containerNode = AceType::DynamicCast<FrameNode>(children.front());
5414     if (!containerNode) {
5415         LOGW("container node is null when set event on gesture row");
5416         return;
5417     }
5418     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5419     CHECK_NULL_VOID(containerPattern);
5420     containerPattern->EnableContainerModalGesture(isEnable);
5421 }
5422 
GetContainerFloatingTitleVisible()5423 bool PipelineContext::GetContainerFloatingTitleVisible()
5424 {
5425     CHECK_NULL_RETURN(rootNode_, false);
5426     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
5427     CHECK_NULL_RETURN(containerNode, false);
5428     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5429     CHECK_NULL_RETURN(containerPattern, false);
5430     return containerPattern->GetFloatingTitleVisible();
5431 }
5432 
GetContainerCustomTitleVisible()5433 bool PipelineContext::GetContainerCustomTitleVisible()
5434 {
5435     CHECK_NULL_RETURN(rootNode_, false);
5436     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
5437     CHECK_NULL_RETURN(containerNode, false);
5438     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5439     CHECK_NULL_RETURN(containerPattern, false);
5440     return containerPattern->GetCustomTitleVisible();
5441 }
5442 
GetContainerControlButtonVisible()5443 bool PipelineContext::GetContainerControlButtonVisible()
5444 {
5445     CHECK_NULL_RETURN(rootNode_, false);
5446     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
5447     CHECK_NULL_RETURN(containerNode, false);
5448     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5449     CHECK_NULL_RETURN(containerPattern, false);
5450     return containerPattern->GetControlButtonVisible();
5451 }
5452 
SetWindowContainerColor(const Color & activeColor,const Color & inactiveColor)5453 void PipelineContext::SetWindowContainerColor(const Color& activeColor, const Color& inactiveColor)
5454 {
5455     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5456         LOGW("Set app icon failed, Window modal is not container.");
5457         return;
5458     }
5459     CHECK_NULL_VOID(rootNode_);
5460     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
5461     CHECK_NULL_VOID(containerNode);
5462     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5463     CHECK_NULL_VOID(containerPattern);
5464     containerPattern->SetWindowContainerColor(activeColor, inactiveColor);
5465 }
5466 
AddFontNodeNG(const WeakPtr<UINode> & node)5467 void PipelineContext::AddFontNodeNG(const WeakPtr<UINode>& node)
5468 {
5469     if (fontManager_) {
5470         fontManager_->AddFontNodeNG(node);
5471     }
5472 }
5473 
RemoveFontNodeNG(const WeakPtr<UINode> & node)5474 void PipelineContext::RemoveFontNodeNG(const WeakPtr<UINode>& node)
5475 {
5476     if (fontManager_) {
5477         fontManager_->RemoveFontNodeNG(node);
5478     }
5479 }
5480 
SetWindowSceneConsumed(bool isConsumed)5481 void PipelineContext::SetWindowSceneConsumed(bool isConsumed)
5482 {
5483     isWindowSceneConsumed_ = isConsumed;
5484 }
5485 
IsWindowSceneConsumed()5486 bool PipelineContext::IsWindowSceneConsumed()
5487 {
5488     return isWindowSceneConsumed_;
5489 }
5490 
SetCloseButtonStatus(bool isEnabled)5491 void PipelineContext::SetCloseButtonStatus(bool isEnabled)
5492 {
5493     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5494         return;
5495     }
5496     CHECK_NULL_VOID(rootNode_);
5497     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetChildren().front());
5498     CHECK_NULL_VOID(containerNode);
5499     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5500     CHECK_NULL_VOID(containerPattern);
5501     containerPattern->SetCloseButtonStatus(isEnabled);
5502 }
5503 
AnimateOnSafeAreaUpdate()5504 void PipelineContext::AnimateOnSafeAreaUpdate()
5505 {
5506     // complete other layout tasks before animation
5507     FlushUITasks();
5508     AnimationOption option;
5509     option.SetCurve(safeAreaManager_->GetSafeAreaCurve());
5510     AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
5511         auto self = weak.Upgrade();
5512         CHECK_NULL_VOID(self);
5513         self->SyncSafeArea(SafeAreaSyncType::SYNC_TYPE_AVOID_AREA);
5514         self->FlushUITasks();
5515     }, nullptr, nullptr, Claim(this));
5516 }
5517 
HandleSubwindow(bool isShow)5518 void PipelineContext::HandleSubwindow(bool isShow)
5519 {
5520     // When the main window is applied to the background,
5521     // there are sub windows that do not immediately hide, such as Toast floating window
5522     if (!isShow) {
5523         overlayManager_->ClearToastInSubwindow();
5524     }
5525 }
5526 
AddIsFocusActiveUpdateEvent(const RefPtr<FrameNode> & node,const std::function<void (bool)> & eventCallback)5527 void PipelineContext::AddIsFocusActiveUpdateEvent(
5528     const RefPtr<FrameNode>& node, const std::function<void(bool)>& eventCallback)
5529 {
5530     CHECK_NULL_VOID(node);
5531     auto focusManager = GetOrCreateFocusManager();
5532     CHECK_NULL_VOID(focusManager);
5533     focusManager->SetIsFocusActiveUpdateEvent(node->GetId(), eventCallback);
5534 }
5535 
RemoveIsFocusActiveUpdateEvent(const RefPtr<FrameNode> & node)5536 void PipelineContext::RemoveIsFocusActiveUpdateEvent(const RefPtr<FrameNode>& node)
5537 {
5538     CHECK_NULL_VOID(node);
5539     auto focusManager = GetOrCreateFocusManager();
5540     CHECK_NULL_VOID(focusManager);
5541     focusManager->RemoveIsFocusActiveUpdateEvent(node->GetId());
5542 }
5543 
GetNavigationController(const std::string & id)5544 std::shared_ptr<NavigationController> PipelineContext::GetNavigationController(const std::string& id)
5545 {
5546     std::lock_guard lock(navigationMutex_);
5547     auto iter = navigationNodes_.find(id);
5548     if (iter == navigationNodes_.end()) {
5549         return nullptr;
5550     }
5551 
5552     auto navigationGroupNode = iter->second.Upgrade();
5553     CHECK_NULL_RETURN(navigationGroupNode, nullptr);
5554 
5555     auto navigationPattern = navigationGroupNode->GetPattern<NavigationPattern>();
5556     CHECK_NULL_RETURN(navigationPattern, nullptr);
5557     return navigationPattern->GetNavigationController();
5558 }
5559 
AddOrReplaceNavigationNode(const std::string & id,const WeakPtr<FrameNode> & node)5560 void PipelineContext::AddOrReplaceNavigationNode(const std::string& id, const WeakPtr<FrameNode>& node)
5561 {
5562     std::lock_guard lock(navigationMutex_);
5563     auto frameNode = node.Upgrade();
5564     CHECK_NULL_VOID(frameNode);
5565     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(frameNode);
5566     CHECK_NULL_VOID(navigationGroupNode);
5567     auto oldId = navigationGroupNode->GetCurId();
5568     if (!oldId.empty() && navigationNodes_.find(oldId) != navigationNodes_.end()) {
5569         navigationNodes_.erase(oldId);
5570     }
5571 
5572     if (!id.empty()) {
5573         navigationNodes_[id] = node;
5574     }
5575 }
5576 
DeleteNavigationNode(const std::string & id)5577 void PipelineContext::DeleteNavigationNode(const std::string& id)
5578 {
5579     std::lock_guard lock(navigationMutex_);
5580     if (!id.empty() && navigationNodes_.find(id) != navigationNodes_.end()) {
5581         navigationNodes_.erase(id);
5582     }
5583 }
5584 
GetCurrentExtraInfo()5585 std::string PipelineContext::GetCurrentExtraInfo()
5586 {
5587     auto node = activeNode_.Upgrade();
5588     return node ? node->GetCurrentCustomNodeInfo() : std::string();
5589 }
5590 
SetCursor(int32_t cursorValue)5591 void PipelineContext::SetCursor(int32_t cursorValue)
5592 {
5593     if (cursorValue >= 0 && cursorValue <= static_cast<int32_t>(MouseFormat::RUNNING)) {
5594         auto mouseFormat = static_cast<MouseFormat>(cursorValue);
5595         auto mouseStyleManager = eventManager_->GetMouseStyleManager();
5596         CHECK_NULL_VOID(mouseStyleManager);
5597         mouseStyleManager->SetUserSetCursor(true);
5598         ChangeMouseStyle(-1, mouseFormat, GetFocusWindowId(),
5599             false, MouseStyleChangeReason::USER_SET_MOUSESTYLE);
5600     }
5601 }
5602 
RestoreDefault(int32_t windowId,MouseStyleChangeReason reason)5603 void PipelineContext::RestoreDefault(int32_t windowId, MouseStyleChangeReason reason)
5604 {
5605     ChangeMouseStyle(-1, MouseFormat::DEFAULT, windowId > 0 ? windowId : GetFocusWindowId(),
5606         false, reason);
5607     auto mouseStyleManager = eventManager_->GetMouseStyleManager();
5608     CHECK_NULL_VOID(mouseStyleManager);
5609     mouseStyleManager->SetUserSetCursor(false);
5610     eventManager_->FlushCursorStyleRequests();
5611 }
5612 
FlushAnimationDirtysWhenExist(const AnimationOption & option)5613 void PipelineContext::FlushAnimationDirtysWhenExist(const AnimationOption& option)
5614 {
5615     int32_t flushCount = 0;
5616     bool isDirtyLayoutNodesEmpty = IsDirtyLayoutNodesEmpty();
5617     while (!isDirtyLayoutNodesEmpty && !IsLayouting() && !isReloading_) {
5618         if (flushCount >= MAX_FLUSH_COUNT || option.GetIteration() != ANIMATION_REPEAT_INFINITE) {
5619             TAG_LOGW(AceLogTag::ACE_ANIMATION, "animation: option:%{public}s, isDirtyLayoutNodesEmpty:%{public}d",
5620                 option.ToString().c_str(), isDirtyLayoutNodesEmpty);
5621             break;
5622         }
5623         FlushUITasks(true);
5624         isDirtyLayoutNodesEmpty = IsDirtyLayoutNodesEmpty();
5625         flushCount++;
5626     }
5627 }
5628 
OpenFrontendAnimation(const AnimationOption & option,const RefPtr<Curve> & curve,const std::function<void ()> & finishCallback)5629 void PipelineContext::OpenFrontendAnimation(
5630     const AnimationOption& option, const RefPtr<Curve>& curve, const std::function<void()>& finishCallback)
5631 {
5632     // push false to show we already open a animation closure.
5633     pendingFrontendAnimation_.push(false);
5634 
5635     // flush ui tasks before open animation closure.
5636     if (!isReloading_ && !IsLayouting()) {
5637         FlushUITasks();
5638     }
5639     auto wrapFinishCallback = GetWrappedAnimationCallback(option, finishCallback);
5640     if (IsFormRenderExceptDynamicComponent()) {
5641         SetIsFormAnimation(true);
5642         if (!IsFormAnimationFinishCallback()) {
5643             SetFormAnimationStartTime(GetMicroTickCount());
5644         }
5645     }
5646     FlushAnimationDirtysWhenExist(option);
5647     AnimationUtils::OpenImplicitAnimation(option, curve, wrapFinishCallback, Claim(this));
5648 }
5649 
CloseFrontendAnimation()5650 void PipelineContext::CloseFrontendAnimation()
5651 {
5652     if (pendingFrontendAnimation_.empty()) {
5653         return;
5654     }
5655 
5656     if (pendingFrontendAnimation_.top()) {
5657         if (!isReloading_ && !IsLayouting()) {
5658             FlushUITasks();
5659         } else if (IsLayouting()) {
5660             TAG_LOGW(AceLogTag::ACE_ANIMATION,
5661                 "IsLayouting, CloseFrontendAnimation has tasks not flushed, maybe some layout animation not generated");
5662         }
5663     }
5664     if (!pendingFrontendAnimation_.empty()) {
5665         pendingFrontendAnimation_.pop();
5666     }
5667     AnimationUtils::CloseImplicitAnimation(Claim(this));
5668 }
5669 
IsDragging() const5670 bool PipelineContext::IsDragging() const
5671 {
5672     if (!dragDropManager_) {
5673         return false;
5674     }
5675     bool isDragging = dragDropManager_->IsDragging();
5676     isDragging = (isDragging || dragDropManager_->IsMSDPDragging());
5677     return isDragging;
5678 }
5679 
SetIsDragging(bool isDragging)5680 void PipelineContext::SetIsDragging(bool isDragging)
5681 {
5682     if (!eventManager_) {
5683         return;
5684     }
5685     eventManager_->SetIsDragging(isDragging);
5686 }
5687 
ResetDragging()5688 void PipelineContext::ResetDragging()
5689 {
5690     CHECK_NULL_VOID(dragDropManager_);
5691     dragDropManager_->ResetDragging();
5692 }
5693 
SetContainerModalTitleVisible(bool customTitleSettedShow,bool floatingTitleSettedShow)5694 void PipelineContext::SetContainerModalTitleVisible(bool customTitleSettedShow, bool floatingTitleSettedShow)
5695 {
5696     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5697         return;
5698     }
5699     CHECK_NULL_VOID(rootNode_);
5700     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
5701     CHECK_NULL_VOID(containerNode);
5702     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5703     CHECK_NULL_VOID(containerPattern);
5704     containerPattern->SetContainerModalTitleVisible(customTitleSettedShow, floatingTitleSettedShow);
5705     customTitleSettedShow_ = customTitleSettedShow;
5706 }
5707 
SetContainerModalTitleHeight(int32_t height)5708 void PipelineContext::SetContainerModalTitleHeight(int32_t height)
5709 {
5710     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5711         return;
5712     }
5713     CHECK_NULL_VOID(rootNode_);
5714     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
5715     CHECK_NULL_VOID(containerNode);
5716     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5717     CHECK_NULL_VOID(containerPattern);
5718     containerPattern->SetContainerModalTitleHeight(height);
5719 }
5720 
GetContainerModalTitleHeight()5721 int32_t PipelineContext::GetContainerModalTitleHeight()
5722 {
5723     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5724         return -1;
5725     }
5726     CHECK_NULL_RETURN(rootNode_, -1);
5727     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
5728     CHECK_NULL_RETURN(containerNode, -1);
5729     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5730     CHECK_NULL_RETURN(containerPattern, -1);
5731     return containerPattern->GetContainerModalTitleHeight();
5732 }
5733 
GetContainerModalNode()5734 RefPtr<FrameNode> PipelineContext::GetContainerModalNode()
5735 {
5736     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5737         return nullptr;
5738     }
5739     CHECK_NULL_RETURN(rootNode_, nullptr);
5740     return AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
5741 }
5742 
DoKeyboardAvoidAnimate(const KeyboardAnimationConfig & keyboardAnimationConfig,float keyboardHeight,const std::function<void ()> & func)5743 void PipelineContext::DoKeyboardAvoidAnimate(const KeyboardAnimationConfig& keyboardAnimationConfig,
5744     float keyboardHeight, const std::function<void()>& func)
5745 {
5746     if (isDoKeyboardAvoidAnimate_) {
5747         AnimationOption option = AnimationUtil::CreateKeyboardAnimationOption(keyboardAnimationConfig, keyboardHeight);
5748         Animate(option, option.GetCurve(), func, [weak = WeakClaim(this)]() {
5749             auto pipeline = weak.Upgrade();
5750             CHECK_NULL_VOID(pipeline);
5751             CHECK_NULL_VOID(pipeline->textFieldManager_);
5752             auto textFieldManagerNg = DynamicCast<TextFieldManagerNG>(pipeline->textFieldManager_);
5753             CHECK_NULL_VOID(textFieldManagerNg);
5754             textFieldManagerNg->OnAfterAvoidKeyboard(false);
5755         });
5756     } else {
5757         func();
5758     }
5759 }
5760 
GetCustomTitleHeight()5761 Dimension PipelineContext::GetCustomTitleHeight()
5762 {
5763     auto containerModal = GetContainerModalNode();
5764     CHECK_NULL_RETURN(containerModal, Dimension());
5765     return containerModal->GetPattern<ContainerModalPattern>()->GetCustomTitleHeight();
5766 }
5767 
GetContainerModalButtonsRect(RectF & containerModal,RectF & buttons)5768 bool PipelineContext::GetContainerModalButtonsRect(RectF& containerModal, RectF& buttons)
5769 {
5770     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5771         return false;
5772     }
5773     CHECK_NULL_RETURN(rootNode_, false);
5774     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
5775     CHECK_NULL_RETURN(containerNode, false);
5776     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5777     CHECK_NULL_RETURN(containerPattern, false);
5778     return containerPattern->GetContainerModalButtonsRect(containerModal, buttons);
5779 }
5780 
SubscribeContainerModalButtonsRectChange(std::function<void (RectF & containerModal,RectF & buttons)> && callback)5781 void PipelineContext::SubscribeContainerModalButtonsRectChange(
5782     std::function<void(RectF& containerModal, RectF& buttons)>&& callback)
5783 {
5784     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5785         return;
5786     }
5787     CHECK_NULL_VOID(rootNode_);
5788     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
5789     CHECK_NULL_VOID(containerNode);
5790     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5791     CHECK_NULL_VOID(containerPattern);
5792     containerPattern->SubscribeContainerModalButtonsRectChange(std::move(callback));
5793 }
5794 
GetWindowPaintRectWithoutMeasureAndLayout(RectInt & rect)5795 void PipelineContext::GetWindowPaintRectWithoutMeasureAndLayout(RectInt& rect)
5796 {
5797     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5798         return;
5799     }
5800     CHECK_NULL_VOID(rootNode_);
5801     auto containerNode = AceType::DynamicCast<FrameNode>(rootNode_->GetFirstChild());
5802     CHECK_NULL_VOID(containerNode);
5803     auto containerPattern = containerNode->GetPattern<ContainerModalPattern>();
5804     CHECK_NULL_VOID(containerPattern);
5805     containerPattern->GetWindowPaintRectWithoutMeasureAndLayout(rect);
5806 }
5807 
GetPostEventManager()5808 const RefPtr<PostEventManager>& PipelineContext::GetPostEventManager()
5809 {
5810     return postEventManager_;
5811 }
5812 
GetSerializedGesture() const5813 const SerializedGesture& PipelineContext::GetSerializedGesture() const
5814 {
5815     return serializedGesture_;
5816 }
5817 
PrintVsyncInfoIfNeed() const5818 bool PipelineContext::PrintVsyncInfoIfNeed() const
5819 {
5820     if (dumpFrameInfos_.empty()) {
5821         return false;
5822     }
5823     auto lastFrameInfo = dumpFrameInfos_.back();
5824     const uint64_t timeout = 1000000000; // unit is ns, 1s
5825     if (lastFrameInfo.frameRecvTime_ < window_->GetLastRequestVsyncTime() &&
5826         static_cast<uint64_t>(GetSysTimestamp()) - window_->GetLastRequestVsyncTime() >= timeout) {
5827         LOGW("lastRequestVsyncTime is %{public}" PRIu64 ", now time is %{public}" PRId64
5828              ", timeout, window foreground:%{public}d, lastReceiveVsync info:%{public}s",
5829             window_->GetLastRequestVsyncTime(), GetSysTimestamp(), onShow_, lastFrameInfo.GetTimeInfo().c_str());
5830         return true;
5831     }
5832     return false;
5833 }
5834 
StopWindowAnimation()5835 void PipelineContext::StopWindowAnimation()
5836 {
5837     isWindowAnimation_ = false;
5838     if (taskScheduler_ && !taskScheduler_->IsPredictTaskEmpty()) {
5839         RequestFrame();
5840     }
5841     OnRotationAnimationEnd();
5842 }
5843 
AddSyncGeometryNodeTask(std::function<void ()> && task)5844 void PipelineContext::AddSyncGeometryNodeTask(std::function<void()>&& task)
5845 {
5846     taskScheduler_->AddSyncGeometryNodeTask(std::move(task));
5847 }
5848 
FlushSyncGeometryNodeTasks()5849 void PipelineContext::FlushSyncGeometryNodeTasks()
5850 {
5851     taskScheduler_->FlushSyncGeometryNodeTasks();
5852 }
5853 
SetUIExtensionImeShow(bool imeShow)5854 void PipelineContext::SetUIExtensionImeShow(bool imeShow)
5855 {
5856     textFieldManager_->SetUIExtensionImeShow(imeShow);
5857 }
5858 
SetOverlayNodePositions(std::vector<Ace::RectF> rects)5859 void PipelineContext::SetOverlayNodePositions(std::vector<Ace::RectF> rects)
5860 {
5861     overlayNodePositions_ = rects;
5862 }
5863 
SetCallBackNode(const WeakPtr<NG::FrameNode> & node)5864 void PipelineContext::SetCallBackNode(const WeakPtr<NG::FrameNode>& node)
5865 {
5866     auto frameNode = node.Upgrade();
5867     CHECK_NULL_VOID(frameNode);
5868     auto pipelineContext = frameNode->GetContext();
5869     CHECK_NULL_VOID(pipelineContext);
5870     pipelineContext->UpdateCurrentActiveNode(node);
5871 }
5872 
GetOverlayNodePositions()5873 std::vector<Ace::RectF> PipelineContext::GetOverlayNodePositions()
5874 {
5875     return overlayNodePositions_;
5876 }
5877 
RegisterOverlayNodePositionsUpdateCallback(const std::function<void (std::vector<Ace::RectF>)> && callback)5878 void PipelineContext::RegisterOverlayNodePositionsUpdateCallback(
5879     const std::function<void(std::vector<Ace::RectF>)>&& callback)
5880 {
5881     overlayNodePositionUpdateCallback_ = std::move(callback);
5882 }
5883 
TriggerOverlayNodePositionsUpdateCallback(std::vector<Ace::RectF> rects)5884 void PipelineContext::TriggerOverlayNodePositionsUpdateCallback(std::vector<Ace::RectF> rects)
5885 {
5886     if (overlayNodePositionUpdateCallback_) {
5887         overlayNodePositionUpdateCallback_(rects);
5888     }
5889 }
5890 
CheckNeedUpdateBackgroundColor(Color & color)5891 void PipelineContext::CheckNeedUpdateBackgroundColor(Color& color)
5892 {
5893     if (!isFormRender_ || (renderingMode_ != RENDERING_SINGLE_COLOR)) {
5894         return;
5895     }
5896     Color replaceColor = color.ChangeAlpha(SINGLECOLOR_UPDATE_ALPHA);
5897     color = replaceColor;
5898 }
5899 
CheckNeedDisableUpdateBackgroundImage()5900 bool PipelineContext::CheckNeedDisableUpdateBackgroundImage()
5901 {
5902     if (!isFormRender_ || (renderingMode_ != RENDERING_SINGLE_COLOR && !enableBlurBackground_)) {
5903         return false;
5904     }
5905     return true;
5906 }
5907 
GetColorMode() const5908 ColorMode PipelineContext::GetColorMode() const
5909 {
5910     auto container = Container::GetContainer(instanceId_);
5911     CHECK_NULL_RETURN(container, ColorMode::LIGHT);
5912     return container->GetColorMode();
5913 }
5914 
ChangeDarkModeBrightness()5915 void PipelineContext::ChangeDarkModeBrightness()
5916 {
5917     auto windowManager = GetWindowManager();
5918     CHECK_NULL_VOID(windowManager);
5919     auto mode = windowManager->GetWindowMode();
5920     auto container = Container::CurrentSafely();
5921     CHECK_NULL_VOID(container);
5922     auto percent = SystemProperties::GetDarkModeBrightnessPercent();
5923     auto stage = stageManager_->GetStageNode();
5924     CHECK_NULL_VOID(stage);
5925     auto renderContext = stage->GetRenderContext();
5926     CHECK_NULL_VOID(renderContext);
5927     CalcDimension dimension;
5928     dimension.SetValue(1);
5929     if (container->GetColorMode() == ColorMode::DARK && appBgColor_.ColorToString().compare("#FF000000") == 0 &&
5930         mode != WindowMode::WINDOW_MODE_FULLSCREEN && !container->IsUIExtensionWindow() &&
5931         !container->IsDynamicRender() && !container->IsFormRender() && !IsJsCard()) {
5932         if (!onFocus_ && mode == WindowMode::WINDOW_MODE_FLOATING) {
5933             dimension.SetValue(1 + percent.second);
5934         } else {
5935             dimension.SetValue(1 + percent.first);
5936         }
5937     }
5938     renderContext->UpdateFrontBrightness(dimension);
5939 }
5940 
IsContainerModalVisible() const5941 bool PipelineContext::IsContainerModalVisible() const
5942 {
5943     if (windowModal_ != WindowModal::CONTAINER_MODAL) {
5944         return false;
5945     }
5946     auto windowManager = GetWindowManager();
5947     bool isFloatingWindow = windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
5948     return isShowTitle_ && isFloatingWindow && customTitleSettedShow_;
5949 }
5950 
PreLayout(uint64_t nanoTimestamp,uint32_t frameCount)5951 void PipelineContext::PreLayout(uint64_t nanoTimestamp, uint32_t frameCount)
5952 {
5953     FlushVsync(nanoTimestamp, frameCount);
5954 }
5955 
CheckAndLogLastReceivedTouchEventInfo(int32_t eventId,TouchType type)5956 void PipelineContext::CheckAndLogLastReceivedTouchEventInfo(int32_t eventId, TouchType type)
5957 {
5958     eventManager_->CheckAndLogLastReceivedTouchEventInfo(eventId, type);
5959 }
5960 
CheckAndLogLastConsumedTouchEventInfo(int32_t eventId,TouchType type)5961 void PipelineContext::CheckAndLogLastConsumedTouchEventInfo(int32_t eventId, TouchType type)
5962 {
5963     eventManager_->CheckAndLogLastConsumedTouchEventInfo(eventId, type);
5964 }
5965 
CheckAndLogLastReceivedMouseEventInfo(int32_t eventId,MouseAction action)5966 void PipelineContext::CheckAndLogLastReceivedMouseEventInfo(int32_t eventId, MouseAction action)
5967 {
5968     eventManager_->CheckAndLogLastReceivedMouseEventInfo(eventId, action);
5969 }
5970 
CheckAndLogLastConsumedMouseEventInfo(int32_t eventId,MouseAction action)5971 void PipelineContext::CheckAndLogLastConsumedMouseEventInfo(int32_t eventId, MouseAction action)
5972 {
5973     eventManager_->CheckAndLogLastConsumedMouseEventInfo(eventId, action);
5974 }
5975 
CheckAndLogLastReceivedAxisEventInfo(int32_t eventId,AxisAction action)5976 void PipelineContext::CheckAndLogLastReceivedAxisEventInfo(int32_t eventId, AxisAction action)
5977 {
5978     eventManager_->CheckAndLogLastReceivedAxisEventInfo(eventId, action);
5979 }
5980 
CheckAndLogLastConsumedAxisEventInfo(int32_t eventId,AxisAction action)5981 void PipelineContext::CheckAndLogLastConsumedAxisEventInfo(int32_t eventId, AxisAction action)
5982 {
5983     eventManager_->CheckAndLogLastConsumedAxisEventInfo(eventId, action);
5984 }
5985 
FlushFrameCallback(uint64_t nanoTimestamp,uint64_t frameCount)5986 void PipelineContext::FlushFrameCallback(uint64_t nanoTimestamp, uint64_t frameCount)
5987 {
5988     // UINT64_MAX means recover vsync, just request frame.
5989     if (frameCount == UINT64_MAX) {
5990         RequestFrame();
5991         return;
5992     }
5993     if (!frameCallbackFuncs_.empty()) {
5994         decltype(frameCallbackFuncs_) tasks;
5995         std::swap(tasks, frameCallbackFuncs_);
5996         for (const auto& frameCallbackFunc : tasks) {
5997             frameCallbackFunc(nanoTimestamp);
5998         }
5999     }
6000 }
6001 
FlushFrameCallbackFromCAPI(uint64_t nanoTimestamp,uint64_t frameCount)6002 void PipelineContext::FlushFrameCallbackFromCAPI(uint64_t nanoTimestamp, uint64_t frameCount)
6003 {
6004     // UINT64_MAX means recover vsync, just request frame.
6005     if (frameCount == UINT64_MAX) {
6006         RequestFrame();
6007         return;
6008     }
6009     if (!frameCallbackFuncsFromCAPI_.empty()) {
6010         decltype(frameCallbackFuncsFromCAPI_) tasks;
6011         std::swap(tasks, frameCallbackFuncsFromCAPI_);
6012         for (const auto& frameCallbackFuncFromCAPI : tasks) {
6013             frameCallbackFuncFromCAPI(nanoTimestamp, static_cast<uint32_t>(frameCount));
6014         }
6015     }
6016 }
6017 
RegisterTouchEventListener(const std::shared_ptr<ITouchEventCallback> & listener)6018 void PipelineContext::RegisterTouchEventListener(const std::shared_ptr<ITouchEventCallback>& listener)
6019 {
6020     if (!listener) {
6021         return;
6022     }
6023     listenerVector_.emplace_back(listener);
6024 }
6025 
UnregisterTouchEventListener(const WeakPtr<NG::Pattern> & pattern)6026 void PipelineContext::UnregisterTouchEventListener(const WeakPtr<NG::Pattern>& pattern)
6027 {
6028     for (auto iter = listenerVector_.begin(); iter != listenerVector_.end();) {
6029         auto patternPtr = (*iter)->GetPatternFromListener();
6030         if (patternPtr.Invalid() || patternPtr == pattern) {
6031             iter = listenerVector_.erase(iter);
6032         } else {
6033             iter++;
6034         }
6035     }
6036 }
6037 
RegisterFocusCallback()6038 void PipelineContext::RegisterFocusCallback()
6039 {
6040     focusManager_->AddFocusChangeCallback([](const WeakPtr<FocusHub>& last, const RefPtr<FocusHub>& current,
6041         FocusReason focusReason) {
6042         CHECK_NULL_VOID(current);
6043         auto node = current->GetFrameNode();
6044         CHECK_NULL_VOID(node);
6045         InputMethodManager::GetInstance()->OnFocusNodeChange(node, focusReason);
6046     });
6047 }
6048 
GetInspectorTree(bool onlyNeedVisible)6049 void PipelineContext::GetInspectorTree(bool onlyNeedVisible)
6050 {
6051     if (onlyNeedVisible) {
6052         auto root = JsonUtil::CreateSharedPtrJson(true);
6053         RefPtr<NG::FrameNode> topNavNode;
6054         uiTranslateManager_->FindTopNavDestination(rootNode_, topNavNode);
6055         if (topNavNode != nullptr) {
6056             topNavNode->DumpSimplifyTree(0, root);
6057         } else {
6058             rootNode_->DumpSimplifyTree(0, root);
6059         }
6060         auto cb = [root]() {
6061             auto json = root->ToString();
6062             json.erase(std::remove(json.begin(), json.end(), ' '), json.end());
6063             auto res = JsonUtil::Create(true);
6064             res->Put("0", json.c_str());
6065             UiSessionManager::GetInstance()->ReportInspectorTreeValue(res->ToString());
6066         };
6067         taskExecutor_->PostTask(cb, TaskExecutor::TaskType::BACKGROUND, "ArkUIGetInspectorTree");
6068     } else {
6069         bool needThrow = false;
6070         NG::InspectorFilter filter;
6071         filter.AddFilterAttr("content");
6072         auto nodeInfos = NG::Inspector::GetInspector(false, filter, needThrow);
6073         UiSessionManager::GetInstance()->AddValueForTree(0, nodeInfos);
6074         rootNode_->GetInspectorValue();
6075     }
6076 }
6077 
AddFrameNodeChangeListener(const WeakPtr<FrameNode> & node)6078 void PipelineContext::AddFrameNodeChangeListener(const WeakPtr<FrameNode>& node)
6079 {
6080     CHECK_NULL_VOID(node.Upgrade());
6081     if (std::find(changeInfoListeners_.begin(), changeInfoListeners_.end(), node) == changeInfoListeners_.end()) {
6082         changeInfoListeners_.push_back(node);
6083     }
6084 }
6085 
RemoveFrameNodeChangeListener(int32_t nodeId)6086 void PipelineContext::RemoveFrameNodeChangeListener(int32_t nodeId)
6087 {
6088     if (changeInfoListeners_.empty()) {
6089         return;
6090     }
6091     changeInfoListeners_.remove_if([nodeId](const WeakPtr<FrameNode>& node) {
6092         return !node.Upgrade() || nodeId == node.Upgrade()->GetId();
6093     });
6094 }
6095 
AddChangedFrameNode(const WeakPtr<FrameNode> & node)6096 bool PipelineContext::AddChangedFrameNode(const WeakPtr<FrameNode>& node)
6097 {
6098     CHECK_NULL_RETURN(node.Upgrade(), false);
6099     if (changeInfoListeners_.empty()) {
6100         return false;
6101     }
6102     if (std::find(changedNodes_.begin(), changedNodes_.end(), node) == changedNodes_.end()) {
6103         changedNodes_.push_back(node);
6104     }
6105     return true;
6106 }
6107 
RemoveChangedFrameNode(int32_t nodeId)6108 void PipelineContext::RemoveChangedFrameNode(int32_t nodeId)
6109 {
6110     if (changedNodes_.empty()) {
6111         return;
6112     }
6113     changedNodes_.remove_if([nodeId](const WeakPtr<FrameNode>& node) {
6114         return !node.Upgrade() || nodeId == node.Upgrade()->GetId();
6115     });
6116 }
6117 
FlushNodeChangeFlag()6118 void PipelineContext::FlushNodeChangeFlag()
6119 {
6120     ACE_FUNCTION_TRACE();
6121     if (!changeInfoListeners_.empty()) {
6122         for (const auto& it : changeInfoListeners_) {
6123             auto listener = it.Upgrade();
6124             if (listener) {
6125                 listener->ProcessFrameNodeChangeFlag();
6126             }
6127         }
6128     }
6129     CleanNodeChangeFlag();
6130 }
6131 
CleanNodeChangeFlag()6132 void PipelineContext::CleanNodeChangeFlag()
6133 {
6134     auto cleanNodes = std::move(changedNodes_);
6135     for (const auto& it : cleanNodes) {
6136         auto changeNode = it.Upgrade();
6137         if (changeNode) {
6138             changeNode->ClearChangeInfoFlag();
6139         }
6140     }
6141 }
6142 
NotifyAllWebPattern(bool isRegister)6143 void PipelineContext::NotifyAllWebPattern(bool isRegister)
6144 {
6145     rootNode_->NotifyWebPattern(isRegister);
6146 }
6147 
NotifyColorModeChange(uint32_t colorMode)6148 void PipelineContext::NotifyColorModeChange(uint32_t colorMode)
6149 {
6150     AnimationOption option;
6151     const int32_t duration = 400;
6152     option.SetDuration(duration);
6153     option.SetCurve(Curves::FRICTION);
6154     AnimationUtils::Animate(
6155         option,
6156         [weakPipelineContext = WeakClaim(this), weak = WeakPtr<FrameNode>(rootNode_),
6157             colorMode, rootColorMode = GetColorMode(), instanceId = instanceId_]() {
6158             auto pipeline = weakPipelineContext.Upgrade();
6159             CHECK_NULL_VOID(pipeline);
6160             auto rootNode = weak.Upgrade();
6161             CHECK_NULL_VOID(rootNode);
6162             ContainerScope scope(instanceId);
6163             ResourceParseUtils::SetIsReloading(true);
6164             pipeline->SetIsReloading(true);
6165             rootNode->SetDarkMode(rootColorMode == ColorMode::DARK);
6166             rootNode->NotifyColorModeChange(colorMode);
6167             pipeline->SetIsReloading(false);
6168             ResourceParseUtils::SetIsReloading(false);
6169             pipeline->FlushUITasks();
6170         },
6171         [weak = WeakClaim(this), instanceId = instanceId_]() {
6172             auto pipeline = weak.Upgrade();
6173             CHECK_NULL_VOID(pipeline);
6174             ContainerScope scope(instanceId);
6175             pipeline->OnFlushReloadFinish();
6176         }, nullptr, Claim(this));
6177     CHECK_NULL_VOID(stageManager_);
6178     auto stage = stageManager_->GetStageNode();
6179     CHECK_NULL_VOID(stage);
6180     auto renderContext = stage->GetRenderContext();
6181     CHECK_NULL_VOID(renderContext);
6182     renderContext->UpdateWindowBlur();
6183 }
6184 
UpdateHalfFoldHoverStatus(int32_t windowWidth,int32_t windowHeight)6185 void PipelineContext::UpdateHalfFoldHoverStatus(int32_t windowWidth, int32_t windowHeight)
6186 {
6187     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
6188         isHalfFoldHoverStatus_ = false;
6189         return;
6190     }
6191     auto container = Container::Current();
6192     CHECK_NULL_VOID(container);
6193     bool isFoldable = container->IsFoldable();
6194     if (!isFoldable && !SystemProperties::IsSmallFoldProduct()) {
6195         isHalfFoldHoverStatus_ = false;
6196         return;
6197     }
6198     auto displayInfo = container->GetDisplayInfo();
6199     CHECK_NULL_VOID(displayInfo);
6200     auto windowManager = GetWindowManager();
6201     auto windowMode = windowManager->GetWindowMode();
6202     auto isHalfFolded = displayInfo->GetFoldStatus() == FoldStatus::HALF_FOLD;
6203     auto displayWidth = displayInfo->GetWidth();
6204     auto displayHeight = displayInfo->GetHeight();
6205     auto isFullScreen = windowMode == WindowMode::WINDOW_MODE_FULLSCREEN ||
6206         (NearEqual(displayWidth, windowWidth) && NearEqual(displayHeight, windowHeight));
6207     if (!isFullScreen || !isHalfFolded) {
6208         isHalfFoldHoverStatus_ = false;
6209         return;
6210     }
6211     auto rotation = displayInfo->GetRotation();
6212     if (SystemProperties::IsSmallFoldProduct()) {
6213         isHalfFoldHoverStatus_ = rotation == Rotation::ROTATION_0 || rotation == Rotation::ROTATION_180;
6214     } else {
6215         isHalfFoldHoverStatus_ = rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270;
6216     }
6217 }
6218 
OnHalfFoldHoverChangedCallback()6219 void PipelineContext::OnHalfFoldHoverChangedCallback()
6220 {
6221     auto tempHalfFoldHoverChangedCallbackMap = halfFoldHoverChangedCallbackMap_;
6222     for (auto&& [id, callback] : tempHalfFoldHoverChangedCallbackMap) {
6223         if (callback) {
6224             callback(isHalfFoldHoverStatus_);
6225         }
6226     }
6227 }
6228 
OnRawKeyboardChangedCallback()6229 void PipelineContext::OnRawKeyboardChangedCallback()
6230 {
6231     auto tempRawKeyboardChangedCallbackMap = rawKeyboardChangedCallbackMap_;
6232     for (auto&& [id, callback] : tempRawKeyboardChangedCallbackMap) {
6233         if (callback) {
6234             callback();
6235         }
6236     }
6237 }
6238 
StartFoldStatusDelayTask(FoldStatus foldStatus)6239 void PipelineContext::StartFoldStatusDelayTask(FoldStatus foldStatus)
6240 {
6241     if (foldStatusDelayTask_) {
6242         foldStatusDelayTask_.Cancel();
6243     }
6244     foldStatusDelayTask_.Reset([weak = WeakClaim(this)]() {
6245         auto context = weak.Upgrade();
6246         CHECK_NULL_VOID(context);
6247         context->UpdateHalfFoldHoverProperty(context->GetRootWidth(), context->GetRootHeight());
6248         context->OnHalfFoldHoverChangedCallback();
6249     });
6250     taskExecutor_->PostDelayedTask(
6251         foldStatusDelayTask_, TaskExecutor::TaskType::UI, DELAY_TIME, "ArkUIHalfFoldHoverStatusChange");
6252 }
6253 
GetResponseRegion(const RefPtr<FrameNode> & rootNode)6254 std::string PipelineContext::GetResponseRegion(const RefPtr<FrameNode>& rootNode)
6255 {
6256     CHECK_NULL_RETURN(rootNode, "");
6257     std::vector<RectF> responseRegionList;
6258     auto window = GetCurrentWindowRect();
6259     RectF windowRect{window.Left(), window.Top(), window.Width(), window.Height()};
6260     rootNode->GetResponseRegionListByTraversal(responseRegionList, windowRect);
6261     std::string responseRegionStrOrigin;
6262     std::string responseRegionStrFilter;
6263     for (const auto& rect : responseRegionList) {
6264         int32_t left = static_cast<int32_t>(rect.Left());
6265         int32_t top = static_cast<int32_t>(rect.Top());
6266         int32_t width = static_cast<int32_t>(rect.Width());
6267         int32_t height = static_cast<int32_t>(rect.Height());
6268         int32_t right = static_cast<int32_t>(rect.Right());
6269         int32_t bottom = static_cast<int32_t>(rect.Bottom());
6270         std::string rectStr = std::to_string(left) + "," +
6271                               std::to_string(top) + "," +
6272                               std::to_string(right) + "," +
6273                               std::to_string(bottom);
6274 
6275         responseRegionStrOrigin += rectStr + "#";
6276         if (thpExtraMgr_ && width <= thpExtraMgr_->GetWidth() && height <= thpExtraMgr_->GetHeight()) {
6277             responseRegionStrFilter += rectStr + "#";
6278         }
6279     }
6280     if (!responseRegionStrFilter.empty()) {
6281         responseRegionStrFilter.pop_back();
6282     }
6283     LOGD("THP_UpdateViewsLocation origin responseRegion = %{public}s", responseRegionStrOrigin.c_str());
6284     return responseRegionStrFilter;
6285 }
6286 
NotifyResponseRegionChanged(const RefPtr<FrameNode> & rootNode)6287 void PipelineContext::NotifyResponseRegionChanged(const RefPtr<FrameNode>& rootNode)
6288 {
6289     ACE_FUNCTION_TRACE();
6290     if (!thpExtraMgr_) {
6291         return;
6292     }
6293     std::string responseRegion = GetResponseRegion(rootNode);
6294     std::string parameters = "thp#Location#" + responseRegion;
6295     LOGD("THP_UpdateViewsLocation responseRegion = %{public}s", parameters.c_str());
6296     auto task = [weak = WeakClaim(this), parameters]() {
6297         ACE_SCOPED_TRACE("ThpExtraRunCommand");
6298         auto pipeline = weak.Upgrade();
6299         CHECK_NULL_VOID(pipeline);
6300         CHECK_NULL_VOID(pipeline->thpExtraMgr_);
6301         pipeline->thpExtraMgr_->ThpExtraRunCommand("THP_UpdateViewsLocation", parameters.c_str());
6302     };
6303     BackgroundTaskExecutor::GetInstance().PostTask(task);
6304 }
6305 
DisableNotifyResponseRegionChanged()6306 void PipelineContext::DisableNotifyResponseRegionChanged()
6307 {
6308     CHECK_NULL_VOID(taskExecutor_);
6309     taskExecutor_->RemoveTask(TaskExecutor::TaskType::UI, "NotifyResponseRegionChanged");
6310 }
6311 
6312 #if defined(SUPPORT_TOUCH_TARGET_TEST)
6313 
OnTouchTargetHitTest(const TouchEvent & point,bool isSubPipe,const std::string & target)6314 bool PipelineContext::OnTouchTargetHitTest(const TouchEvent& point, bool isSubPipe, const std::string& target)
6315 {
6316     auto scalePoint = point.CreateScalePoint(GetViewScale());
6317     if (scalePoint.type == TouchType::DOWN) {
6318         TouchRestrict touchRestrict { TouchRestrict::NONE };
6319         touchRestrict.sourceType = point.sourceType;
6320         touchRestrict.touchEvent = point;
6321         bool isTouchTarget = eventManager_->TouchTargetHitTest(
6322             scalePoint, rootNode_, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe, target);
6323         return isTouchTarget;
6324     }
6325     return false;
6326 }
6327 #endif
6328 
CatchInteractiveAnimations(const std::function<void ()> & animationCallback)6329 bool PipelineContext::CatchInteractiveAnimations(const std::function<void()>& animationCallback)
6330 {
6331     CHECK_NULL_RETURN(navigationMgr_, false);
6332     if (navigationMgr_->IsInteractive()) {
6333         return navigationMgr_->AddInteractiveAnimation(animationCallback);
6334     }
6335     return false;
6336 }
6337 
CheckThreadSafe()6338 bool PipelineContext::CheckThreadSafe()
6339 {
6340     CHECK_NULL_RETURN(taskExecutor_, true);
6341     if (!isFormRender_ && !taskExecutor_->WillRunOnCurrentThread(TaskExecutor::TaskType::UI)) {
6342         LogBacktrace();
6343         return false;
6344     }
6345     return true;
6346 }
6347 
AdjustVsyncTimeStamp(uint64_t nanoTimestamp)6348 uint64_t PipelineContext::AdjustVsyncTimeStamp(uint64_t nanoTimestamp)
6349 {
6350     auto period = window_->GetVSyncPeriod();
6351     static constexpr int64_t LARGE_TIME = INT64_MAX >> 2;
6352     if (static_cast<int64_t>(nanoTimestamp) > LARGE_TIME || period > LARGE_TIME) {
6353         TAG_LOGW(AceLogTag::ACE_ANIMATION, "time is too huge, nanoTime:%{public}" PRIu64 ", period:%{public}" PRId64,
6354             nanoTimestamp, period);
6355     }
6356     if (period > 0 && recvTime_ > static_cast<int64_t>(nanoTimestamp) + MAX_MISS_COUNT * period) {
6357         return static_cast<uint64_t>(recvTime_ - ((recvTime_ - static_cast<int64_t>(nanoTimestamp)) % period));
6358     }
6359     return nanoTimestamp;
6360 }
6361 
FlushModifierAnimation(uint64_t nanoTimestamp)6362 bool PipelineContext::FlushModifierAnimation(uint64_t nanoTimestamp)
6363 {
6364     auto animationTimeStamp = AdjustVsyncTimeStamp(nanoTimestamp);
6365     if (animationTimeStamp < animationTimeStamp_) {
6366         ACE_SCOPED_TRACE("skip ModifierAnimation");
6367         TAG_LOGW(AceLogTag::ACE_ANIMATION,
6368             "Time decreases, skip ModifierAnimation, lastTime:%{public}" PRIu64 ", nowTime:%{public}" PRIu64,
6369             animationTimeStamp_, animationTimeStamp);
6370         return true;
6371     }
6372     animationTimeStamp_ = animationTimeStamp;
6373     return window_->FlushAnimation(animationTimeStamp);
6374 }
6375 
RegisterAttachedNode(UINode * uiNode)6376 void PipelineContext::RegisterAttachedNode(UINode* uiNode)
6377 {
6378     attachedNodeSet_.emplace(WeakClaim(uiNode));
6379 }
6380 
RemoveAttachedNode(UINode * uiNode)6381 void PipelineContext::RemoveAttachedNode(UINode* uiNode)
6382 {
6383     attachedNodeSet_.erase(WeakClaim(uiNode));
6384 }
6385 
ScopedLayout(PipelineContext * pipeline)6386 ScopedLayout::ScopedLayout(PipelineContext* pipeline)
6387 {
6388     if (!pipeline) {
6389         return;
6390     }
6391     // save flag before measure
6392     pipeline_ = pipeline;
6393     isLayouting_ = pipeline_->IsLayouting();
6394     pipeline_->SetIsLayouting(true);
6395 }
6396 
~ScopedLayout()6397 ScopedLayout::~ScopedLayout()
6398 {
6399     if (!pipeline_) {
6400         return;
6401     }
6402     // set layout flag back
6403     pipeline_->SetIsLayouting(isLayouting_);
6404 }
6405 
GetBundleName()6406 std::string PipelineContext::GetBundleName()
6407 {
6408     auto container = Container::GetContainer(instanceId_);
6409     CHECK_NULL_RETURN(container, "");
6410     return container->GetBundleName();
6411 }
6412 
GetModuleName()6413 std::string PipelineContext::GetModuleName()
6414 {
6415     auto container = Container::GetContainer(instanceId_);
6416     CHECK_NULL_RETURN(container, "");
6417     return container->GetModuleName();
6418 }
6419 
SetHostParentOffsetToWindow(const Offset & offset)6420 void PipelineContext::SetHostParentOffsetToWindow(const Offset& offset)
6421 {
6422     lastHostParentOffsetToWindow_ = offset;
6423     CHECK_NULL_VOID(rootNode_);
6424     auto renderContext = rootNode_->GetRenderContext();
6425     CHECK_NULL_VOID(renderContext);
6426     renderContext->RequestNextFrame();
6427 }
6428 
GetUIContext()6429 RefPtr<Kit::UIContext> PipelineContext::GetUIContext()
6430 {
6431     if (uiContextImpl_) {
6432         return uiContextImpl_;
6433     }
6434     uiContextImpl_ = AceType::MakeRefPtr<Kit::UIContextImpl>(this);
6435     return uiContextImpl_;
6436 }
6437 
GetAllPixelMap()6438 void PipelineContext::GetAllPixelMap()
6439 {
6440     CHECK_NULL_VOID(stageManager_);
6441     auto pageNode = stageManager_->GetLastPage();
6442     CHECK_NULL_VOID(pageNode);
6443     CHECK_NULL_VOID(uiTranslateManager_);
6444     uiTranslateManager_->GetAllPixelMap(pageNode);
6445 }
6446 
SetDisplayWindowRectInfo(const Rect & displayWindowRectInfo)6447 void PipelineContext::SetDisplayWindowRectInfo(const Rect& displayWindowRectInfo)
6448 {
6449     auto offSetPosX_ = displayWindowRectInfo_.Left() - displayWindowRectInfo.Left();
6450     auto offSetPosY_ = displayWindowRectInfo_.Top() - displayWindowRectInfo.Top();
6451     if (!NearZero(offSetPosX_) || !NearZero(offSetPosY_)) {
6452         if (lastMouseEvent_) {
6453             lastMouseEvent_->x += offSetPosX_;
6454             lastMouseEvent_->y += offSetPosY_;
6455         }
6456     }
6457     displayWindowRectInfo_ = displayWindowRectInfo;
6458 }
6459 
SetIsTransFlag(bool result)6460 void PipelineContext::SetIsTransFlag(bool result)
6461 {
6462     if (isTransFlag_ != result) {
6463         isTransFlag_ = result;
6464     }
6465 }
6466 
FlushMouseEventForHover()6467 void PipelineContext::FlushMouseEventForHover()
6468 {
6469     if (!isTransFlag_ || !lastMouseEvent_ || lastMouseEvent_->sourceType != SourceType::MOUSE ||
6470         lastMouseEvent_->action == MouseAction::PRESS || lastSourceType_ == SourceType::TOUCH ||
6471         lastMouseEvent_->button != MouseButton::NONE_BUTTON) {
6472         return;
6473     }
6474     if (lastMouseEvent_->action == MouseAction::WINDOW_LEAVE) {
6475         return;
6476     }
6477     CHECK_NULL_VOID(rootNode_);
6478     if (lastMouseEvent_->isMockWindowTransFlag || windowSizeChangeReason_ == WindowSizeChangeReason::DRAG) {
6479         return;
6480     }
6481     CHECK_RUN_ON(UI);
6482     auto container = Container::Current();
6483     CHECK_NULL_VOID(container);
6484     ACE_SCOPED_TRACE("FlushMouseEventForHover x:%f y:%f", lastMouseEvent_->x, lastMouseEvent_->y);
6485     MouseEvent event;
6486     event.x = lastMouseEvent_->x;
6487     event.y = lastMouseEvent_->y;
6488     event.screenX = lastMouseEvent_->screenX;
6489     event.screenY = lastMouseEvent_->screenY;
6490     event.button = lastMouseEvent_->button;
6491     event.deviceId = lastMouseEvent_->deviceId;
6492     event.sourceTool = lastMouseEvent_->sourceTool;
6493     event.sourceType = lastMouseEvent_->sourceType;
6494     if (lastMouseEvent_->action == MouseAction::WINDOW_ENTER) {
6495         event.action = MouseAction::MOVE;
6496     } else {
6497         event.action = lastMouseEvent_->action;
6498     }
6499     event.time = lastMouseEvent_->time;
6500     event.touchEventId = lastMouseEvent_->touchEventId;
6501     event.mockFlushEvent = true;
6502     event.pointerEvent = lastMouseEvent_->pointerEvent;
6503     event.targetDisplayId = lastMouseEvent_->targetDisplayId;
6504     TAG_LOGD(AceLogTag::ACE_MOUSE,
6505         "the mock mouse event action: %{public}d x: %{public}f y: %{public}f", event.action, event.x, event.y);
6506     TouchRestrict touchRestrict { TouchRestrict::NONE };
6507     touchRestrict.sourceType = event.sourceType;
6508     touchRestrict.hitTestType = SourceType::MOUSE;
6509     touchRestrict.inputEventType = InputEventType::MOUSE_BUTTON;
6510     if (container->IsSceneBoardWindow()) {
6511         eventManager_->MouseTest(event, lastMouseEvent_->node.Upgrade(), touchRestrict);
6512     } else {
6513         eventManager_->MouseTest(event, rootNode_, touchRestrict);
6514     }
6515     eventManager_->DispatchMouseHoverEventNG(event);
6516     eventManager_->DispatchMouseHoverAnimationNG(event, true);
6517 }
6518 
HandleTouchHoverOut(const TouchEvent & point)6519 void PipelineContext::HandleTouchHoverOut(const TouchEvent& point)
6520 {
6521     if (point.sourceTool != SourceTool::FINGER || NearZero(point.force)) {
6522         return;
6523     }
6524     CHECK_RUN_ON(UI);
6525     eventManager_->CleanHoverStatusForDragBegin();
6526 }
6527 
FlushMouseEventInVsync()6528 void PipelineContext::FlushMouseEventInVsync()
6529 {
6530     auto mouseEventSize = mouseEvents_.size();
6531     if (!mouseEvents_.empty()) {
6532         FlushMouseEvent();
6533         isNeedFlushMouseEvent_ = MockFlushEventType::NONE;
6534         mouseEvents_.clear();
6535     } else if (isNeedFlushMouseEvent_ == MockFlushEventType::REJECT ||
6536                isNeedFlushMouseEvent_ == MockFlushEventType::EXECUTE) {
6537         FlushMouseEventVoluntarily();
6538         isNeedFlushMouseEvent_ = MockFlushEventType::NONE;
6539     }
6540     if (lastMouseEvent_ && isTransFlag_ && (mouseEventSize == 0 || lastMouseEvent_->mockFlushEvent)) {
6541         FlushMouseEventForHover();
6542     }
6543     isTransFlag_ = false;
6544     windowSizeChangeReason_ = WindowSizeChangeReason::UNDEFINED;
6545 }
6546 
SetWindowSizeChangeReason(WindowSizeChangeReason reason)6547 void PipelineContext::SetWindowSizeChangeReason(WindowSizeChangeReason reason)
6548 {
6549     windowSizeChangeReason_ = reason;
6550 }
6551 
OnDumpInjection(const std::vector<std::string> & params) const6552 void PipelineContext::OnDumpInjection(const std::vector<std::string>& params) const
6553 {
6554     int32_t nodeId = StringUtils::StringToInt(params[PARAM_NUM], -1);
6555     if (nodeId < 0) {
6556         return;
6557     }
6558     auto frameNode = DynamicCast<FrameNode>(ElementRegister::GetInstance()->GetUINodeById(nodeId));
6559     CHECK_NULL_VOID(frameNode);
6560     frameNode->OnRecvCommand(params[1]);
6561 }
6562 
OnRotationAnimationEnd()6563 void PipelineContext::OnRotationAnimationEnd()
6564 {
6565     for (auto&& [id, callback] : rotationEndCallbackMap_) {
6566         if (callback) {
6567             callback();
6568         }
6569     }
6570 }
6571 
GetRSUIDirector()6572 std::shared_ptr<Rosen::RSUIDirector> PipelineContext::GetRSUIDirector()
6573 {
6574 #ifdef ENABLE_ROSEN_BACKEND
6575     auto window = GetWindow();
6576     if (window) {
6577         return window->GetRSUIDirector();
6578     }
6579 #endif
6580     return nullptr;
6581 }
6582 
GetNodeRenderStatusMonitor()6583 const RefPtr<NodeRenderStatusMonitor>& PipelineContext::GetNodeRenderStatusMonitor()
6584 {
6585     if (!nodeRenderStatusMonitor_) {
6586         nodeRenderStatusMonitor_ = AceType::MakeRefPtr<NodeRenderStatusMonitor>();
6587     }
6588     return nodeRenderStatusMonitor_;
6589 }
6590 
RegisterArkUIObjectLifecycleCallback(Kit::ArkUIObjectLifecycleCallback && callback)6591 void PipelineContext::RegisterArkUIObjectLifecycleCallback(Kit::ArkUIObjectLifecycleCallback&& callback)
6592 {
6593     LOGI("register arkui object lifecycle callback.");
6594     objectLifecycleCallback_ = std::move(callback);
6595 }
6596 
UnregisterArkUIObjectLifecycleCallback()6597 void PipelineContext::UnregisterArkUIObjectLifecycleCallback()
6598 {
6599     LOGI("unregister arkui object lifecycle callback.");
6600     objectLifecycleCallback_ = nullptr;
6601 }
6602 
FireArkUIObjectLifecycleCallback(void * data)6603 void PipelineContext::FireArkUIObjectLifecycleCallback(void* data)
6604 {
6605     CHECK_NULL_VOID(objectLifecycleCallback_);
6606     objectLifecycleCallback_(data);
6607 }
6608 
DumpForceColor(const std::vector<std::string> & params) const6609 void PipelineContext::DumpForceColor(const std::vector<std::string>& params) const
6610 {
6611     if (params.size() <= PARAM_NUM) {
6612         return;
6613     }
6614     int32_t nodeId = StringUtils::StringToInt(params[1], -1);
6615     if (nodeId < 0) {
6616         return;
6617     }
6618     Color color = Color::FromString(params[2]); // Index 2 represents the third parameter
6619     auto invertColor = ColorInverter::GetInstance().Invert(
6620         color, PipelineContext::GetCurrentContext(), params[2]); // Index 2 represents the third parameter
6621     DumpLog::GetInstance().Print(1, "InvertColor: [" + invertColor.ToString() + "]");
6622 }
6623 
CheckSourceTypeChange(SourceType currentSourceType)6624 bool PipelineContext::CheckSourceTypeChange(SourceType currentSourceType)
6625 {
6626     bool ret = false;
6627     if (currentSourceType != lastSourceType_) {
6628         ret = true;
6629         lastSourceType_ = currentSourceType;
6630     }
6631     return ret;
6632 }
6633 
ExeAppAIFunctionCallback(const std::string & funcName,const std::string & params)6634 uint32_t PipelineContext::ExeAppAIFunctionCallback(const std::string& funcName, const std::string& params)
6635 {
6636     static constexpr uint32_t AI_CALL_NODE_INVALID = 3;
6637     RefPtr<NG::FrameNode> topNavNode;
6638     CHECK_NULL_RETURN(rootNode_, AI_CALL_NODE_INVALID);
6639     rootNode_->FindTopNavDestination(topNavNode);
6640     CHECK_NULL_RETURN(topNavNode, AI_CALL_NODE_INVALID);
6641     return topNavNode->CallAIFunction(funcName, params);
6642 }
6643 
OnDumpBindAICaller(const std::vector<std::string> & params) const6644 void PipelineContext::OnDumpBindAICaller(const std::vector<std::string>& params) const
6645 {
6646     RefPtr<NG::FrameNode> topNavNode;
6647     CHECK_NULL_VOID(rootNode_);
6648     rootNode_->FindTopNavDestination(topNavNode);
6649     CHECK_NULL_VOID(topNavNode);
6650     if (params.size() > 1) {
6651         if (params[1] == "-bind") {
6652             auto myAICaller = std::make_shared<TestAICaller>();
6653             topNavNode->SetAICallerHelper(myAICaller);
6654         } else if (params[1] == "-unbind") {
6655             topNavNode->SetAICallerHelper(nullptr);
6656         }
6657     }
6658 }
6659 
6660 } // namespace OHOS::Ace::NG
6661