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