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