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