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