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