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